This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Suspected Timer issue with ADC value transmission

Other Parts Discussed in Thread: CC2531, CC2530

I have a potentially very simple problem that I am overlooking the solution to. I could not find a clear document about the timer settings. 

I have a smartRF05 with a cc2530 that is transmitting to a cc2531 dongle that is then read by matlab to plot the data. I have it working great with 3 channels and almost with 4. 

Desired functionality: Connect to serial port with matlab, read n data points, break them into a matrix based on the set number of adc channels, and plot. This works great with 3 channels, but when I set 4 adc input pins I get odd behavior.

The input data swaps places at random intervals. So instead of 3 channels running high, and one running low (the proper values), it will swap channels after a few reads. 

I want the cc2530 to send a stream of data that looks like this [127 127 127 28 127 127 127 28 ...] and this works fine for a few hundred samples, then it will swap and I will receive [127 127 28 127 127 127 28 127 ...] and then swap places to another pattern again. 

I know the matlab code is not an issue since it works fine when I set 3 input adc channels. 

CODE: I have a file in my zstack app where I initialize the ADC functionality. I think the issue is somehow related to the timer settings but I do not see why. In settings.cfg I have DAUDIO and DMICS set. 

The only changes I made to this file are

1) #define ADC_N 0x08 //P0_3->P18_11

2) APCFG = 0x00 | micCfg; // micCfg is set to channel 1, 3, 5, 7 (I added channel 7 for the fourth pin, set based on compile flag)

3) ADCCON2 = HAL_ADC_REF_125V | HAL_ADC_DEC_064 | 0x07; (increased the channel input to 7 from 5)

#ifdef AUDIO

#include "RoachZStack_ADC.h"
#include "hal_adc.h"
#include "hal_lcd.h"
#include "hal_led.h"
#include "hal_dma.h"
#include "hal_sleep.h"
#include "ZConfig.h"
#include "OSAL.h"

adcMsg_t* pBufferReading = NULL;
adcMsg_t* pBufferDone = NULL;
adcMsg_t* pBufferNext = NULL;

// Task ID not initialized
#define NO_TASK_ID 0xFF

#define ADC_R 0x10 //P0_4->P18_13
#define ADC_L 0x02 //P0_1->P18_7
#define ADC_C 0x20 //P0_5->P18_15
#define ADC_N 0x00 // p0.0 -> p12// 0x08 //P0_3->P18_11 in user guide // add pin P0_3 -- less noise


#define HAL_ADC_EOC 0x80 /* End of Conversion bit */
#define HAL_ADC_START 0x40 /* Starts Conversion */

#define HAL_ADC_STSEL_EXT 0x00 /* External Trigger */
#define HAL_ADC_STSEL_FULL 0x10 /* Full Speed, No Trigger */
#define HAL_ADC_STSEL_T1C0 0x20 /* Timer1, Channel 0 Compare Event Trigger */
#define HAL_ADC_STSEL_ST 0x30 /* ADCCON1.ST =1 Trigger */

#define HAL_ADC_RAND_NORM 0x00 /* Normal Operation */
#define HAL_ADC_RAND_LFSR 0x04 /* Clock LFSR */
#define HAL_ADC_RAND_SEED 0x08 /* Seed Modulator */
#define HAL_ADC_RAND_STOP 0x0c /* Stop Random Generator */
#define HAL_ADC_RAND_BITS 0x0c /* Bits [3:2] */

#define HAL_ADC_DEC_064 0x00 /* Decimate by 64 : 8-bit resolution */
#define HAL_ADC_DEC_128 0x10 /* Decimate by 128 : 10-bit resolution */
#define HAL_ADC_DEC_256 0x20 /* Decimate by 256 : 12-bit resolution */
#define HAL_ADC_DEC_512 0x30 /* Decimate by 512 : 14-bit resolution */
#define HAL_ADC_DEC_BITS 0x30 /* Bits [5:4] */

#define HAL_ADC_STSEL HAL_ADC_STSEL_ST
#define HAL_ADC_RAND_GEN HAL_ADC_RAND_STOP
#define HAL_ADC_REF_VOLT HAL_ADC_REF_125V
#define HAL_ADC_DEC_RATE HAL_ADC_DEC_064
#define HAL_ADC_SCHN HAL_ADC_CHN_VDD3
#define HAL_ADC_ECHN HAL_ADC_CHN_GND


// Registered keys task ID, initialized to NOT USED.
extern volatile uint8 allocCount;
static uint8 registeredADCTaskID = NO_TASK_ID;
uint8 RoachZStack_ADC_TaskID; // Task ID for internal task/event processing.

uint16 data = 0;

uint16 overflow = 0;

#ifndef ZDO_COORDINATOR
HAL_ISR_FUNCTION( DMA_ISR, DMA_VECTOR )
{

T1CTL = 0x00 | 0x0C | 0x00;
//HAL_ENTER_ISR();

DMAIF = 0;

if (pBufferDone != NULL)
{
osal_msg_deallocate((uint8*)pBufferDone);
overflow++;
}
pBufferDone = pBufferReading;
pBufferReading = pBufferNext;
pBufferNext = NULL;
if (pBufferReading != NULL)
{
HAL_DMA_SET_DEST(HAL_DMA_GET_DESC1234(1), pBufferReading->buffer);
HAL_DMA_ARM_CH(1);
T1CTL = 0x00 | 0x0C | 0x02;
}

osal_set_event(RoachZStack_ADC_TaskID, RZS_ADC_READ );

CLEAR_SLEEP_MODE();
//HAL_EXIT_ISR();
}
#endif
/*********************************************************************
* @fn RoachZStack_Init
*
* @brief This is called during OSAL tasks' initialization.
*
* @param task_id - the Task ID assigned by OSAL.
*
* @return none
*/
void RoachZStack_ADC_Init( uint8 task_id )
{
#ifndef ZDO_COORDINATOR
PERCFG |= 0x40;
RoachZStack_ADC_TaskID = task_id;
uint8 micCfg = 1 << HAL_ADC_CHANNEL_1;

if (MICS > 1){
micCfg |= 1 << HAL_ADC_CHANNEL_3;
}

if (MICS > 2){
micCfg |= 1 << HAL_ADC_CHANNEL_5;
}

if (MICS > 3) {
micCfg |= 1 << HAL_ADC_CHANNEL_7;
}

APCFG = 0x00 | micCfg; // analog periferal config
// ADC control settings
ADCCON1 = HAL_ADC_STSEL_T1C0 | 0x03; // 0x03 reserved // timer1, channel 0 compare event
//HAL_ADC_REF_AVDD or HAL_ADC_REF_125V
ADCCON2 = HAL_ADC_REF_125V | HAL_ADC_DEC_064 | 0x07; //stop at channel 5
//P2INP |= 0x20;
T1CTL = 0x00 | 0x0C | 0x02; // timer 1 control

uint16 counter = 200;//125;

T1CC0H = counter >> 8; // timer 1 channel 0, capture and compare, high byte
T1CC0L = (uint8)counter; // low byte
// no rf, no interrupt, set->clear, compare, no capture
T1CCTL0 = 0x00 | 0x00 | 0x18 | 0x04 | 0x00; // 5C;
DMAIE = 1;

HalDmaInit();
HAL_DMA_SET_SOURCE(HAL_DMA_GET_DESC1234(1), &X_ADCH);
HAL_DMA_SET_VLEN(HAL_DMA_GET_DESC1234(1), HAL_DMA_VLEN_USE_LEN);
HAL_DMA_SET_LEN(HAL_DMA_GET_DESC1234(1), sizeof(pBufferReading->buffer));
HAL_DMA_SET_WORD_SIZE(HAL_DMA_GET_DESC1234(1), HAL_DMA_WORDSIZE_BYTE);
HAL_DMA_SET_TRIG_MODE(HAL_DMA_GET_DESC1234(1), HAL_DMA_TMODE_SINGLE);
HAL_DMA_SET_TRIG_SRC(HAL_DMA_GET_DESC1234(1), HAL_DMA_TRIG_ADC_CHALL);
HAL_DMA_SET_SRC_INC(HAL_DMA_GET_DESC1234(1), HAL_DMA_SRCINC_0);
HAL_DMA_SET_DST_INC(HAL_DMA_GET_DESC1234(1), HAL_DMA_DSTINC_1);
HAL_DMA_SET_IRQ(HAL_DMA_GET_DESC1234(1), HAL_DMA_IRQMASK_ENABLE);
HAL_DMA_SET_PRIORITY(HAL_DMA_GET_DESC1234(1), HAL_DMA_PRI_GUARANTEED);

#endif
}

/*********************************************************************
* ADC Register function
*
* The adc handler is setup to send all adc changes to
* one task (if a task is registered).
*
*********************************************************************/
uint8 RegisterForADC( uint8 task_id )
{
// Allow only the first task
if ( registeredADCTaskID == NO_TASK_ID )
{
registeredADCTaskID = task_id;
osal_set_event(RoachZStack_ADC_TaskID, RZS_ADC_READ );
return ( true );
}
else
return ( false );
}


/*********************************************************************
* @fn RoachZStack_ProcessEvent
*
* @brief Generic Application Task event processor.
*
* @param task_id - The OSAL assigned task ID.
* @param events - Bit map of events to process.
*
* @return Event flags of all unprocessed events.
*/
UINT16 RoachZStack_ADC( uint8 task_id, UINT16 events )
{

if (events & RZS_ADC_READ)
{
if (registeredADCTaskID == NO_TASK_ID)
{
osal_start_timerEx( RoachZStack_ADC_TaskID, RZS_ADC_READ, 2);
return events ^ RZS_ADC_READ;
}

halIntState_t intState;
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.

if (pBufferDone != NULL)
{
// Send the address to the task
pBufferDone->hdr.event = RZS_ADC_VALUE;
for (int i = 0; i < (sizeof(pBufferDone->buffer)/sizeof(*(pBufferDone->buffer))); i++)
{
if (pBufferDone->buffer[i] > 127)
{
pBufferDone->buffer[i] = 0;
}
}
osal_msg_send( registeredADCTaskID, (uint8 *)pBufferDone );
pBufferDone = NULL;
}

if (pBufferNext == NULL)
{
pBufferNext = (adcMsg_t*) osal_msg_allocate( sizeof(adcMsg_t) );
allocCount++;
if (pBufferNext != NULL)
{
pBufferNext->size = 0;
}
else
{
HalLedSet(HAL_LED_2, HAL_LED_MODE_TOGGLE);
}
}
if (pBufferReading == NULL)
{
pBufferReading = pBufferNext;
pBufferNext = (adcMsg_t*) osal_msg_allocate( sizeof(adcMsg_t) );
if (pBufferReading != NULL)
{
HAL_DMA_SET_DEST(HAL_DMA_GET_DESC1234(1), pBufferReading->buffer);
HAL_DMA_ARM_CH(1);
T1CTL = 0x00 | 0x0C | 0x02;
}
}

HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.

return events ^ RZS_ADC_READ;
}
return 0;
}

#endif