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.

RTOS/LAUNCHXL-CC1350: Abnormal consumption on CC1350

Part Number: LAUNCHXL-CC1350
Other Parts Discussed in Thread: CC1350,

Tool/software: TI-RTOS

Hi everybody,

we're testing consumption on LAUNCHXL-CC1350, in the configuration without jumpers so we have only the consumption of CC1350, of the Flash Chip and of a Magnetic Chip on SPI.

if we use rfWsnDmNode_CC1350_LAUNCHXL_TI example we can get even 50uA, but with our firmware we never go under 1.6mA.

Here there is a version of our firmware with minimal functions and the problem remains.

Have you got any ideas?

Thanks.

Regards.

#include <stdlib.h> /* atoi */
#include <string.h> /* memcpy */

#include <ti/sysbios/BIOS.h>

#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Task.h>
#include <xdc/runtime/Error.h>

#include <inc/hw_ccfg.h>
#include <inc/hw_ccfg_simple_struct.h>

#include "at/AtProcess.h"
#include "at/AtControl.h"
#include "at/platform/inc/AtTerm.h"
#include "at/platform/tirtos/DbgPrint.h"
#include "at/AtParams.h"

#include "easylink/EasyLink.h"

#include "Board.h"

#include <ti/drivers/PIN.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/UART.h>

#include <driverlib/sys_ctrl.h>
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/knl/Event.h>

#include <ti/drivers/Power.h>
#include <ti/drivers/power/PowerCC26XX.h>
#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>
#include <driverlib/trng.h>
#include "seb/SEB.h"

#define NODE_TASK_STACK_SIZE 1024
#define NODE_TASK_PRIORITY   3
#define NODE_EVENT_ALL                  0xFFFFFFFF
#define NODE_EVENT_NEW_BLE_MSG    (uint32_t)(1 << 0)

#define RADIO_EVENT_ALL                 0xFFFFFFFF
#define RADIO_EVENT_SEND_ADC_DATA       (uint32_t)(1 << 0)
#define RADIO_EVENT_DATA_ACK_RECEIVED   (uint32_t)(1 << 1)
#define RADIO_EVENT_ACK_TIMEOUT         (uint32_t)(1 << 2)
#define RADIO_EVENT_SEND_FAIL           (uint32_t)(1 << 3)

#define NODERADIO_MAX_RETRIES 2
#define NORERADIO_ACK_TIMEOUT_TIME_MS (160)

#define NODE_0M_TXPOWER    -10

static Clock_Params clkParams;
static Clock_Struct clk0Struct;

typedef enum
{
	RxStatus_Stop        = 0,
	RxStatus_Wait        = 1,
	RxStatus_Success     = 2,
	RxStatus_Timeout     = 3
} RxStatusn;

typedef enum
{
	Err_PinOpen			= 1,
	Err_PinCb			= 2,
	Err_FlashInfo		= 3,
	Err_FlashRead		= 4,
	Err_FlashWrite		= 5,
	Err_NoHMC5993		= 6,
	Err_HMCSetup	    = 7,
	Err_Radio			= 8,
	Err_UART			= 9,
	Err_Checkdata		= 10,
	Err_Generic			= 11
} BigErrors;

typedef enum
{
	SPI_Closed			= 0,		
	SPI_HMC5993			= 1,		
	SPI_Flash		    = 2			
} SPI_port;

/****************************
 * defines di programma		*
 ****************************/
#define	OK		0
#define	ERRORE	1

#define	BIT7	0x80
#define	BIT6	0x40
#define	BIT5	0x20
#define	BIT4	0x10
#define	BIT3	0x08
#define	BIT2	0x04
#define	BIT1	0x02
#define	BIT0	0x01

#define SRETRY_EMB	10

/************************
 * Semaphores variables *
 ************************/
static Semaphore_Handle sema1;
static Semaphore_Params semParams;
static Semaphore_Struct sem1Struct;

static SPI_Params spiparams;
static SPI_Handle spihandle;
static SPI_Transaction spiTransaction;

static int SPI_Port;

static Char txbuf[256];
static Char rxbuf[256];

/****************
 * Uart RS232	*
 ****************/
static UART_Params uartParams;
static UART_Handle uart;


EasyLink_TxPacket txPacket;

static int RxStatus;

static uint8_t BLE_request = 0;

/************************************************
 * Application LED pin configuration table:		*
 ************************************************/
PIN_Handle pinHandle;
PIN_State pinState;
PIN_Config pinTable[] = {
	Board_GLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
	Board_RLED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_DIO1_RFSW | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_DIO30_SWPWR | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

PIN_State buttonPinState;
PIN_Handle buttonPinHandle;
PIN_Config buttonPinTable[] = {
    Board_BUTTON0  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    Board_BUTTON1  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    PIN_TERMINATE
};

/***** Defines *****/
#define SensorTaskStackSize       2048

#define SensorTaskStackSize1       2048

#define SensorTaskPriority        2

static Task_Params SensorTaskParams;
Task_Struct SensorpTask;
static uint8_t SensorTaskStack[SensorTaskStackSize];

static Task_Params SensorTaskParams1;
Task_Struct SensorpTask1;
static uint8_t SensorTaskStack1[SensorTaskStackSize1];

typedef struct Sensor_configuration
{
	uint32_t NumStallo;
	uint32_t gwd;
	uint32_t DataCal;
	uint32_t SogliaLo;
	uint32_t SogliaHi;
	uint32_t Nresets;
	short sdv[3];
	uint8_t Gain;
} Sensor_configuration;

static Sensor_configuration CNF;

static short Status = 0;

static short C_retry;
static short C_kalive;
static short C_misura;

static short Retries;
static short S_retry;
static bool ret;

static uint8_t TxBuffer[40];	

#define Wait 0

static uint16_t nodeAddress16;

/* proprietary advertisement packet */
static uint8_t localNameAdvertisement[] = {
        0x02, //Length of this Data section
        0x01, //<<Flags>>
        0x02, //LE General Discoverable Mode
        0x11, //Length of this Data section (era 0x18)
        0x09, //<<Complete local name>>
        '1', '2', '3', '4', '5', '6', '7', '8', '9', 'O', '1',
        '2', '3', '4', '5', '6'
        };

/* proprietary advertisement packet */
static uint8_t propAdvertisement[] = {
        0x02, //Length of this section
        0x01, //<<Flags>>
        0x02, //LE General Discoverable Mode
        0x06, //Length of this section
        0xff, //<<Manufacturer Specific Data>>
        0x0d,
        0x00,
        0x03,
        0x00,
        0x00}; //BTN state

SimpleBeacon_Frame propAdvFrame;
SimpleBeacon_Frame localNameAdvFrame;

static uint8_t bleMacAddr[6];

/***** Prototypes *****/
static void sendBleAdvertisement();

#define EDELAY	20000

static void ShowError(int n)
{
	int x;

	if (n == 0) n=1;

	while (1) {
		PIN_setOutputValue(pinHandle, Board_GLED,true);
	    Task_sleep(EDELAY);
		for (x=0; x<n; x++) {
			PIN_setOutputValue(pinHandle, Board_RLED,true);
		    Task_sleep(EDELAY);
			PIN_setOutputValue(pinHandle, Board_RLED,false);
		    Task_sleep(EDELAY);
		}
		PIN_setOutputValue(pinHandle, Board_GLED,false);
	    Task_sleep(EDELAY*6);
	}
}

int SPI_to_Flash(void)
{
	if (SPI_Port != SPI_Flash) {
		if (SPI_Port == SPI_HMC5993) {
			SPI_close(spihandle);
			SPI_Port = SPI_Closed;
		}
		spihandle = SPI_open(Board_SPI1, &spiparams);
		if (!spihandle) return ERRORE;
		SPI_Port = SPI_Flash;
	}
	return OK;
}

int SPI_to_Sensor(void)
{
	if (SPI_Port != SPI_HMC5993) {
		if (SPI_Port == SPI_Flash) {
			SPI_close(spihandle);
			SPI_Port = SPI_Closed;
		}
		spihandle = SPI_open(Board_SPI0, &spiparams);
		if (!spihandle) return ERRORE;
		SPI_Port = SPI_HMC5993;
	}
	return OK;
}

int FlashInfotest(void)
{
	if (SPI_to_Flash() != OK) return ERRORE;

	Task_sleep(100);

	txbuf[0] = 0x9f;											//get Identification
	txbuf[1] = 0;
	txbuf[2] = 0;
	txbuf[3] = 0;
	spiTransaction.count = 4;									//1 byte TX, 3 byte RX
	spiTransaction.txBuf = &txbuf;
	spiTransaction.rxBuf = &rxbuf;
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;

	if ((rxbuf[1]!=0xC2)||(rxbuf[2]!=0x28)||(rxbuf[3]!=0x14)) return ERRORE;

	return OK;
}

int LeggiConfigurazione(void)
{
	int x;
	uint8_t CRC;

	bool FlashOK = false;

	if (SPI_to_Flash() != OK) return ERRORE;

	Task_sleep(100);

	txbuf[0] = 0x03;											//read

	txbuf[1] = 0x00;											//addr msb
	txbuf[2] = 0x00;											//addr
	txbuf[3] = 0x00;											//addr lsb (24 bit)

	spiTransaction.count = 4+4+sizeof(CNF);
	Task_sleep(1000);
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (ret) {
		if ((rxbuf[4]==0x12)&&(rxbuf[5]==0x34)&&(rxbuf[6]==sizeof(CNF))) {
			CRC=0;
			for (x=0;x<sizeof(CNF);x++) CRC^= rxbuf[8+x];
			if (CRC == rxbuf[7]) FlashOK=true;
		}
		if (FlashOK) {
			memcpy(&CNF, &rxbuf[8], sizeof(CNF));
		}
	}
	return OK;
}

int ReadFlashStatus(void)
{
	Task_sleep(100);

	txbuf[0] = 0x05;
	spiTransaction.count = 2;									//1 byte TX, 1 byte RX
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;

	return OK;
}

int ScriviConfigurazione(void)
{
	int x;
	uint8_t CRC;

	if (SPI_to_Flash() != OK) return ERRORE;

	Task_sleep(100);

	do 	{
		Task_sleep(100);
		txbuf[0] = 0x06;
		spiTransaction.count = 1;
		ret = SPI_transfer(spihandle, &spiTransaction);
		if (!ret) return 1;
		if (ReadFlashStatus() != 0) return ERRORE;
	} while ((rxbuf[1] & 0x02) == 0);

	/*********************
	 * sector erase	(4K) *
	 *********************/
	Task_sleep(100);

	txbuf[0] = 0x20;											//read
	txbuf[1] = 0;												//block address
	txbuf[2] = 0;
	txbuf[3] = 0;
	spiTransaction.count = 4;									//1 byte TX, 3 byte address
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;

	do 	{
		Task_sleep(1000);
		if (ReadFlashStatus() != 0) return ERRORE;
	} while ((rxbuf[1] & 0x01) == 0x01);

	do 	{

		Task_sleep(100);

		txbuf[0] = 0x06;
		spiTransaction.count = 1;
		ret = SPI_transfer(spihandle, &spiTransaction);
		if (!ret) return 2;
		if (ReadFlashStatus() != 0) return ERRORE;

	} while ((rxbuf[1] & 0x02) == 0);

	Task_sleep(100);

	txbuf[0] = 0x02;
	txbuf[1] = 0x00;
	txbuf[2] = 0x00;
	txbuf[3] = 0x00;


	txbuf[4] = 0x12;
	txbuf[5] = 0x34;
	txbuf[6] = sizeof(CNF);

	memcpy(&txbuf[8], &CNF, sizeof(CNF));

	CRC=0;
	for (x=0;x<sizeof(CNF);x++) CRC^= txbuf[8+x];
	txbuf[7] = CRC;

	spiTransaction.count = 4 + 4 + sizeof(CNF);
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;

	do 	{
		Task_sleep(1000);
		if (ReadFlashStatus() != 0) return ERRORE;
	} while ((rxbuf[1] & 0x01) == 0x01);


	Task_sleep(100);

	txbuf[0] = 0x03;
	txbuf[1] = 0x00;
	txbuf[2] = 0x00;
	txbuf[3] = 0x00;
	spiTransaction.count = 4 + sizeof(CNF);
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;

	return memcmp(&txbuf[4], &CNF, sizeof(CNF));

}

static int HMC5983test(void)
{
	if (SPI_to_Sensor() != OK) return ERRORE;

	Task_sleep(100);

	txbuf[0] = BIT7+BIT6+10;
	txbuf[1] = 0;
	txbuf[2] = 0;
	txbuf[3] = 0;
	spiTransaction.count = 4;
	spiTransaction.txBuf = &txbuf;
	spiTransaction.rxBuf = &rxbuf;
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;

	if ((rxbuf[1]!=0x48)||(rxbuf[2]!=0x34)||(rxbuf[3]!=0x33)) return ERRORE;

	return OK;
}

static int HMC5983Setup(void)
{
	if (SPI_to_Sensor() != OK) return ERRORE;

	Task_sleep(100);

	txbuf[0] = BIT6+0;
	txbuf[1] = 0x90;
	txbuf[2] = CNF.Gain <<5;
	spiTransaction.count = 3;
	spiTransaction.txBuf = &txbuf;
	spiTransaction.rxBuf = &rxbuf;
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;

	txbuf[0] = BIT7+0;
	spiTransaction.count = 2;
	spiTransaction.txBuf = &txbuf;
	spiTransaction.rxBuf = &rxbuf;
	ret = SPI_transfer(spihandle, &spiTransaction);
	if (!ret) return ERRORE;
	if (rxbuf[1] != 0x90) return ERRORE;

	return OK;
}

static void DebugSys(UArg arg0, UArg arg1)
{
	uint8_t b;

    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudRate = 9600;
    uartParams.readMode = UART_MODE_BLOCKING;
    uartParams.readTimeout = UART_WAIT_FOREVER;

    uart = UART_open(Board_UART0, &uartParams);
    if (uart == NULL) ShowError(Err_UART);

	while (1)
	{
        UART_read(uart, &b, 1);
	}

}

static void cb (EasyLink_RxPacket * rxPacket, EasyLink_Status status)
{
	if (status != EasyLink_Status_Success) return;
	if (RxStatus != RxStatus_Wait) return;
	PIN_setOutputValue(pinHandle, Board_GLED,true);
	RxStatus = RxStatus_Success;
    Semaphore_post(sema1);
}

void TimerTick(UArg arg0)
{
	CNF.gwd++;
	if (Status != Wait) C_retry++;
	C_kalive++;
	C_misura++;
    Semaphore_post(sema1);
}

void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId) {
	CPUdelay(8000*50);
    if (!PIN_getInputValue(pinId)) {
        switch (pinId) {
            case Board_BUTTON0:
                break;
            case Board_BUTTON1:
                break;
            default:
                break;
        }
    }
}

static int SendRadioCommand(void)
{
	uint8_t *b = &TxBuffer[0];

    int i;

    C_kalive = 0;
    C_retry = 0;

	PIN_setOutputValue(pinHandle, Board_RLED, true);

	*b++ = 0x80;

	i = b -	&TxBuffer[0];

	TxBuffer[5]=(uint8_t)((i-6)+(Retries << 5));

	memcpy(txPacket.dstAddr, AtParams_txAddr, AtParams_addrSize);

    txPacket.absTime = 0;
    txPacket.len = i;
    memcpy(txPacket.payload, TxBuffer, i);

    AtParams_easyLinkStatus = EasyLink_transmit(&txPacket);

	PIN_setOutputValue(pinHandle, Board_RLED,false);

	if (AtParams_easyLinkStatus != EasyLink_Status_Success) return 1;

	return 0;
}

static void AttendiRicezione(void)
{
	int t;

	EasyLink_Status n;

	RxStatus = RxStatus_Wait;
	Semaphore_reset(sema1, 0);

    n = EasyLink_receiveAsync(&cb, 0);
    if (n != EasyLink_Status_Success) return;

    for (t=0;t <5;t++ )  {
    	Semaphore_pend(sema1, BIOS_WAIT_FOREVER);
    	if (RxStatus == RxStatus_Success) {
    		PIN_setOutputValue(pinHandle, Board_GLED,false);
    		return;
    	}
    }

    n = EasyLink_abort();

}

static void SensorMain(UArg arg0, UArg arg1)
{

	S_retry  = SRETRY_EMB;

    pinHandle = PIN_open(&pinState, pinTable);

    /********************
     * Open Button pins *
     ********************/
    buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable);
    if (!buttonPinHandle) ShowError(Err_PinOpen);

    /********************************
     * Setup callback for 2 buttons *
     ********************************/
    if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFxn) != 0) ShowError(Err_PinCb);

    PIN_setOutputValue(pinHandle, Board_DIO30_SWPWR, 1);

	SPI_Params_init(&spiparams);
	spiparams.bitRate  = 200000;
	spiparams.frameFormat = SPI_POL1_PHA1;
	SPI_Port = SPI_Closed;

	if (FlashInfotest() != OK) ShowError(Err_FlashInfo);

	if (LeggiConfigurazione() != OK) ShowError(Err_FlashRead);

	CNF.Gain = 1;

	if (HMC5983test() != 0) ShowError(Err_NoHMC5993);

	if (HMC5983Setup() != 0) ShowError(Err_HMCSetup);

	Task_sleep(1000);

    Semaphore_Params_init(&semParams);
    Semaphore_construct(&sem1Struct, 0, &semParams);
    sema1 = Semaphore_handle(&sem1Struct);

    RxStatus = RxStatus_Stop;

    Clock_Params_init(&clkParams);
    clkParams.period = 90000;
    clkParams.startFlag = TRUE;
    Clock_construct(&clk0Struct, (Clock_FuncPtr)TimerTick, 90000, &clkParams);


    EasyLink_setCtrl(EasyLink_Ctrl_MultiClient_Mode, 1);
    EasyLink_Status n = EasyLink_init(EasyLink_Phy_625bpsLrm);

    if (n != EasyLink_Status_Success) ShowError(Err_Radio);

    /* initialise the Simple Beacon module called directly for Prop Adv
     * Set multiclient mode to true
     */
    SimpleBeacon_init(true);

    SimpleBeacon_getIeeeAddr(bleMacAddr);

    propAdvFrame.deviceAddress = bleMacAddr;
    propAdvFrame.length = sizeof(propAdvertisement);
    propAdvFrame.pAdvData = propAdvertisement;

    if (CNF.NumStallo <255) nodeAddress16 = (uint16_t)(CNF.NumStallo);
    else nodeAddress16 = 255;
    localNameAdvertisement[20] = (nodeAddress16)%10 + 0x30;
    localNameAdvertisement[19] = ((nodeAddress16)%100)/10 + 0x30;
    localNameAdvertisement[18] = (nodeAddress16)/100 + 0x30;

    localNameAdvFrame.deviceAddress = bleMacAddr;
    localNameAdvFrame.length = sizeof(localNameAdvertisement);
    localNameAdvFrame.pAdvData = localNameAdvertisement;

    AtParams_rxTimeout = 100;

    Task_sleep(1000);

    while (1)
    {

    	Semaphore_reset(sema1, 0);

    	Semaphore_pend(sema1, BIOS_WAIT_FOREVER);

    	if (BLE_request){
    		BLE_request = 0;
    		sendBleAdvertisement();
    	}

		if (C_retry < S_retry) continue;

		SendRadioCommand();

		AttendiRicezione();

    }
}

static void sendBleAdvertisement()
{
    uint8_t txCnt, chan;

    //Swtich RF switch to 2.4G antenna
    PIN_setOutputValue(pinHandle, Board_DIO1_RFSW, 0);

    for (txCnt = 0; txCnt < SimpleBeacon_AdvertisementTimes; txCnt++)
    {
        for (chan = 37; chan < 40; chan++)
        {
                //set BTN value in Prop advertisement
                propAdvertisement[9] = 0x01;
                //advertisement advertise local name
                SimpleBeacon_sendFrame(localNameAdvFrame,  1, (uint64_t) 1<<chan);
                //advertisement advertise button value
                SimpleBeacon_sendFrame(propAdvFrame, 1, (uint64_t) 1<<chan);
        }
        //sleep on all but last advertisement
        if(txCnt+1 < SimpleBeacon_AdvertisementTimes)
        {
            Task_sleep(SimpleBeacon_AdvertisementIntervals[txCnt]);
        }
    }

    //Swtich RF switch to Sub1G antenna
    PIN_setOutputValue(pinHandle, Board_DIO1_RFSW, 1);

}

/****************************
 *  ======== main ========  *
 ****************************/
int main(void)
{
    Board_initGeneral();
    Power_enablePolicy();

    Board_initSPI();
    Board_initUART();

    Task_Params_init(&SensorTaskParams);
    SensorTaskParams.stackSize = SensorTaskStackSize;
    SensorTaskParams.priority = SensorTaskPriority;
    SensorTaskParams.stack = &SensorTaskStack;
    SensorTaskParams.arg0 = (UInt) 1000000;
    Task_construct(&SensorpTask, SensorMain, &SensorTaskParams, NULL);

    Task_Params_init(&SensorTaskParams1);
    SensorTaskParams1.stackSize = SensorTaskStackSize1;
    SensorTaskParams1.priority = SensorTaskPriority;
    SensorTaskParams1.stack = &SensorTaskStack1;
    SensorTaskParams1.arg0 = (UInt) 1000000;
    Task_construct(&SensorpTask1, DebugSys, &SensorTaskParams1, NULL);

    System_flush();

    BIOS_start();

    return (0);
}

  • Hi Matteo,

    A couple of questions...
    - Are you using the Simplelink CC1350 SDK ? If so, which version ?
    - Did you modify the rfWsnDmNode example to create your custom firmware ? If so, can you post the original example along with the modified one (I suppose you already shared the modified example's source file?) so we can diff them ? Please share the board files too in case they have changed.

    I noticed that you use Task_sleep() in the shared source file. I wanted to point out that on CC26xx, 1 clock tick is 10us and not 1ms (TI-RTOS tick length is 1ms on most other devices). In case you were assuming a tick length of 1ms, the sleep period may be much shorter than you anticipated. This can reduce idle time and hence affect the power savings.

    Best,
    Ashish
  • Hi Ashish,

    here the configuration of the project, on CCS 6.1.3.00034.

    We have created this firmware from a copy of rfWsnDmNode project, board file is the same.

    Here the original files of the example; if I use them, I get the right comsumption (about 50ua).

    /*
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <ti/drivers/UART.h>
    #include <ti/drivers/SPI.h>
    
    /* Board Header files */
    #include "Board.h"
    
    #include "DmNodeRadioTask.h"
    #include "DmNodeTask.h"
    
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        /* Call board init functions. */
        Board_initGeneral();
    
        /* Initialise the UART and SPI for the display driver. */
        Board_initUART();
        Board_initSPI();
    
        /* Initialize sensor node tasks */
        NodeRadioTask_init();
        NodeTask_init();
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    
    /*
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /***** Includes *****/
    #include <DmNodeRadioTask.h>
    #include <DmNodeTask.h>
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    #include <string.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Clock.h>
    
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    #include <ti/mw/display/Display.h>
    #include <ti/mw/display/DisplayExt.h>
    
    /* Board Header files */
    #include "Board.h"
    
    #include "SceAdc.h"
    
    #ifdef USE_BIM
    #include "bim/BimFactoryReset.h"
    #endif
    
    
    /***** Defines *****/
    #define NODE_TASK_STACK_SIZE 1024
    #define NODE_TASK_PRIORITY   3
    
    #define NODE_EVENT_ALL                  0xFFFFFFFF
    #define NODE_EVENT_NEW_ADC_VALUE    (uint32_t)(1 << 0)
    #define NODE_EVENT_UPDATE_LCD       (uint32_t)(1 << 1)
    
    #ifdef USE_BIM
    #define NODE_EVENT_FACTORY_RESET    (uint32_t)(1 << 2)
    #endif
    
    /* A change mask of 0xFF0 means that changes in the lower 4 bits does not trigger a wakeup. */
    #define NODE_ADCTASK_CHANGE_MASK                    0xFF0
    
    /* Minimum slow Report interval is 50s (in units of samplingTime)*/
    #define NODE_ADCTASK_REPORTINTERVAL_SLOW                50
    /* Minimum fast Report interval is 1s (in units of samplingTime) for 30s*/
    #define NODE_ADCTASK_REPORTINTERVAL_FAST                1
    #define NODE_ADCTASK_REPORTINTERVAL_FAST_DURIATION_MS   30000
    
    #ifdef USE_BIM
    /* BLE Load button check timers - check button ever 100ms for 5s*/
    #define NODE_BLE_BOOTLODER_BUTTON_CHECK_TIMER_MS    100
    #define NODE_BLE_BOOTLODER_BUTTON_CHECK_DURATION_S  6
    #endif
    
    
    /***** Variable declarations *****/
    static Task_Params nodeTaskParams;
    Task_Struct nodeTask;    /* not static so you can see in ROV */
    static uint8_t nodeTaskStack[NODE_TASK_STACK_SIZE];
    Event_Struct nodeEvent;  /* not static so you can see in ROV */
    static Event_Handle nodeEventHandle;
    static uint16_t latestAdcValue;
    
    /* Clock for the fast report timeout */
    Clock_Struct fastReportTimeoutClock;     /* not static so you can see in ROV */
    static Clock_Handle fastReportTimeoutClockHandle;
    
    #ifdef USE_BIM
    /* Clock for the fast report timeout */
    Clock_Struct bleBootloadBtnCheckClock;     /* not static so you can see in ROV */
    static Clock_Handle bleBootloadBtnCheckClockHandle;
    #endif
    
    /* Pin driver handle */
    static PIN_Handle buttonPinHandle;
    PIN_Handle ledPinHandle;
    
    /* Global memory storage for a PIN_Config table */
    static PIN_State buttonPinState;
    static PIN_State ledPinState;
    
    /* Display driver handles */
    static Display_Handle hDisplayLcd;
    static Display_Handle hDisplaySerial;
    
    static Node_AdertiserType advertisementType = Node_AdertiserMsUrl;
    
    /* Enable the 3.3V power domain used by the LCD */
    PIN_Config pinTable[] = {
        NODE_SUB1_ACTIVITY_LED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        NODE_BLE_ACTIVITY_LED | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_DIO1_RFSW | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_DIO30_SWPWR | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    /*
     * Application button pin configuration table:
     *   - Buttons interrupts are configured to trigger on falling edge.
     */
    PIN_Config buttonPinTable[] = {
        Board_BUTTON0  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        Board_BUTTON1  | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        PIN_TERMINATE
    };
    
    static uint8_t nodeAddress = 0;
    
    /***** Prototypes *****/
    static void nodeTaskFunction(UArg arg0, UArg arg1);
    static void updateLcd(void);
    void fastReportTimeoutCallback(UArg arg0);
    void adcCallback(uint16_t adcValue);
    void buttonCallback(PIN_Handle handle, PIN_Id pinId);
    
    #ifdef USE_BIM
    void bleBtnCheckTimerCallback(UArg arg0);
    #endif
    
    /***** Function definitions *****/
    void NodeTask_init(void)
    {
    
        /* Create event used internally for state changes */
        Event_Params eventParam;
        Event_Params_init(&eventParam);
        Event_construct(&nodeEvent, &eventParam);
        nodeEventHandle = Event_handle(&nodeEvent);
    
        /* Create clock object which is used for fast report timeout */
        Clock_Params clkParams;
        clkParams.period = 0;
        clkParams.startFlag = FALSE;
        Clock_construct(&fastReportTimeoutClock, fastReportTimeoutCallback, 1, &clkParams);
        fastReportTimeoutClockHandle = Clock_handle(&fastReportTimeoutClock);
    
    #ifdef USE_BIM
        /* Create clock object which is used for ble bootload button check */
        Clock_construct(&bleBootloadBtnCheckClock, bleBtnCheckTimerCallback, 1, &clkParams);
        bleBootloadBtnCheckClockHandle = Clock_handle(&bleBootloadBtnCheckClock);
    #endif
    
        /* Create the node task */
        Task_Params_init(&nodeTaskParams);
        nodeTaskParams.stackSize = NODE_TASK_STACK_SIZE;
        nodeTaskParams.priority = NODE_TASK_PRIORITY;
        nodeTaskParams.stack = &nodeTaskStack;
        Task_construct(&nodeTask, nodeTaskFunction, &nodeTaskParams, NULL);
    }
    
    static void nodeTaskFunction(UArg arg0, UArg arg1)
    {
        /* Initialize display and try to open both UART and LCD types of display. */
        Display_Params params;
        Display_Params_init(&params);
        params.lineClearMode = DISPLAY_CLEAR_BOTH;
    
        /* Open both an available LCD display and an UART display.
         * Whether the open call is successful depends on what is present in the
         * Display_config[] array of the board file.
         *
         * Note that for SensorTag evaluation boards combined with the SHARP96x96
         * Watch DevPack, there is a pin conflict with UART such that one must be
         * excluded, and UART is preferred by default. To display on the Watch
         * DevPack, add the precompiler define BOARD_DISPLAY_EXCLUDE_UART.
         */
        hDisplayLcd = Display_open(Display_Type_LCD, &params);
        hDisplaySerial = Display_open(Display_Type_UART, &params);
    
        /* Check if the selected Display type was found and successfully opened */
        if (hDisplaySerial)
        {
            Display_print0(hDisplaySerial, 0, 0, "Waiting for SCE ADC reading...");
        }
    
        /* Check if the selected Display type was found and successfully opened */
        if (hDisplayLcd)
        {
            Display_print0(hDisplayLcd, 0, 0, "Waiting for ADC...");
        }
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, pinTable);
        if (!ledPinHandle)
        {
            System_abort("Error initializing board 3.3V domain pins\n");
        }
    
        /* Start the SCE ADC task with 1s sample period and reacting to change in ADC value. */
        SceAdc_init(0x00010000, NODE_ADCTASK_REPORTINTERVAL_FAST, NODE_ADCTASK_CHANGE_MASK);
        SceAdc_registerAdcCallback(adcCallback);
        SceAdc_start();
    
        /* setup timeout for fast report timeout */
        Clock_setTimeout(fastReportTimeoutClockHandle,
                NODE_ADCTASK_REPORTINTERVAL_FAST_DURIATION_MS * 1000 / Clock_tickPeriod);
    
        /* start fast report and timeout */
        Clock_start(fastReportTimeoutClockHandle);
    
    #ifdef USE_BIM
        /* setup timer for ble bootload button check */
        Clock_setTimeout(bleBootloadBtnCheckClockHandle,
                NODE_BLE_BOOTLODER_BUTTON_CHECK_TIMER_MS * 1000 / Clock_tickPeriod);
    #endif
    
        buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable);
        if (!buttonPinHandle)
        {
            System_abort("Error initializing button pins\n");
        }
    
        /* Setup callback for button pins */
        if (PIN_registerIntCb(buttonPinHandle, &buttonCallback) != 0)
        {
            System_abort("Error registering button callback function");
        }
    
        //Enable power to RF switch to 2.4G antenna
        PIN_setOutputValue(ledPinHandle, Board_DIO30_SWPWR, 1);
    
        while (1)
        {
            /* Wait for event */
            uint32_t events = Event_pend(nodeEventHandle, 0, NODE_EVENT_ALL, BIOS_WAIT_FOREVER);
    
            /* If new ADC value, send this data */
            if (events & NODE_EVENT_NEW_ADC_VALUE) {
                /* Toggle activity LED */
                PIN_setOutputValue(ledPinHandle, NODE_SUB1_ACTIVITY_LED,!PIN_getOutputValue(NODE_SUB1_ACTIVITY_LED));
    
                /* Send ADC value to concentrator */
                NodeRadioTask_sendAdcData(latestAdcValue);
    
                /* update display */
                updateLcd();
            }
            /* If new ADC value, send this data */
            if (events & NODE_EVENT_UPDATE_LCD) {
                /* update display */
                updateLcd();
            }
    #ifdef USE_BIM
            if (events & NODE_EVENT_FACTORY_RESET) {
    
                Display_control(hDisplayLcd, DISPLAY_CMD_TRANSPORT_CLOSE, NULL);
    
                BimFactoryReset_applyFactoryImage();
    
                /* BIM Factory Reset failed, reenable the LCD */
                Display_control(hDisplayLcd, DISPLAY_CMD_TRANSPORT_OPEN, NULL);
    
                /* Re-enable interrupts to detect button release. */
                PIN_setConfig(buttonPinHandle, PIN_BM_IRQ, Board_BUTTON0 | PIN_IRQ_NEGEDGE);
                PIN_setConfig(buttonPinHandle, PIN_BM_IRQ, Board_BUTTON1 | PIN_IRQ_NEGEDGE);
            }
    #endif
        }
    
    }
    
    static void updateLcd(void)
    {
        char advMode[16] = {0};
    
        /* get node address if not already done */
        if (nodeAddress == 0)
        {
            nodeAddress = nodeRadioTask_getNodeAddr();
        }
    
        /* print to LCD */
        Display_clear(hDisplayLcd);
        Display_print1(hDisplayLcd, 0, 0, "NodeID: 0x%02x", nodeAddress);
        Display_print1(hDisplayLcd, 1, 0, "ADC: %04d", latestAdcValue);
    
        /* print to UART clear screen, put cuser to beggining of terminal and print the header */
        Display_print1(hDisplaySerial, 0, 0, "\033[2J \033[0;0HNode ID: 0x%02x", nodeAddress);
        Display_print1(hDisplaySerial, 0, 0, "Node ADC Reading: %04d", latestAdcValue);
    
        if (advertisementType == Node_AdertiserMsUrl)
        {
             strncpy(advMode, "BLE MS + URL", 12);
        }
        else if (advertisementType == Node_AdertiserMs)
        {
             strncpy(advMode, "BLE MS", 6);
        }
        else if (advertisementType == Node_AdertiserUrl)
        {
             strncpy(advMode, "Eddystone URL", 13);
        }
        else if (advertisementType == Node_AdertiserUid)
        {
             strncpy(advMode, "Eddystone UID", 13);
        }
        else
        {
             strncpy(advMode, "None", 4);
        }
    
        /* print to LCD */
        Display_print0(hDisplayLcd, 2, 0, "Adv Mode:");
        Display_print1(hDisplayLcd, 3, 0, "%s", advMode);
        /* print to UART */
        Display_print1(hDisplaySerial, 0, 0, "Advertiser Mode: %s", advMode);
    }
    
    
    void adcCallback(uint16_t adcValue)
    {
        /* Save latest value */
        latestAdcValue = adcValue;
    
        /* Post event */
        Event_post(nodeEventHandle, NODE_EVENT_NEW_ADC_VALUE);
    }
    
    /*
     *  ======== buttonCallback ========
     *  Pin interrupt Callback function board buttons configured in the pinTable.
     */
    void buttonCallback(PIN_Handle handle, PIN_Id pinId)
    {
        /* Debounce logic, only toggle if the button is still pushed (low) */
        CPUdelay(8000*50);
    
    
        if ((PIN_getInputValue(Board_BUTTON0) == 0) & (PIN_getInputValue(Board_BUTTON1) == 0)) {
    #ifdef USE_BIM
            //stop button interupts while checking ble bootload button hold
            PIN_setConfig(buttonPinHandle, PIN_BM_IRQ, Board_BUTTON0 | PIN_IRQ_DIS);
            PIN_setConfig(buttonPinHandle, PIN_BM_IRQ, Board_BUTTON1 | PIN_IRQ_DIS);
            //start BLE bootloader timer to check pins
            Clock_start(bleBootloadBtnCheckClockHandle);
    #endif
        }
        else if (PIN_getInputValue(Board_BUTTON0) == 0)
        {
            //start fast report and timeout
            SceAdc_setReportInterval(NODE_ADCTASK_REPORTINTERVAL_FAST, NODE_ADCTASK_CHANGE_MASK);
            Clock_start(fastReportTimeoutClockHandle);
        }
        else if (PIN_getInputValue(Board_BUTTON1) == 0)
        {
            //cycle between url, uid and none
            advertisementType++;
            if (advertisementType == Node_AdertiserTypeEnd)
            {
                advertisementType = Node_AdertiserNone;
            }
    
            /* update display */
            Event_post(nodeEventHandle, NODE_EVENT_UPDATE_LCD);
    
            //Set advertiement type
            nodeRadioTask_setAdvertiserType(advertisementType);
    
            //start fast report and timeout
            SceAdc_setReportInterval(NODE_ADCTASK_REPORTINTERVAL_FAST, NODE_ADCTASK_CHANGE_MASK);
            Clock_start(fastReportTimeoutClockHandle);
        }
    }
    
    void fastReportTimeoutCallback(UArg arg0)
    {
        //stop fast report
        SceAdc_setReportInterval(NODE_ADCTASK_REPORTINTERVAL_SLOW, NODE_ADCTASK_CHANGE_MASK);
    }
    
    #ifdef USE_BIM
    void bleBtnCheckTimerCallback(UArg arg0)
    {
        static uint32_t btnHoldCnt = 0;
    
        if ((PIN_getInputValue(Board_BUTTON0) == 0) & (PIN_getInputValue(Board_BUTTON1) == 0))
        {
            if ( (++btnHoldCnt * NODE_BLE_BOOTLODER_BUTTON_CHECK_TIMER_MS) >
                (NODE_BLE_BOOTLODER_BUTTON_CHECK_DURATION_S*1000))
            {
                Event_post(nodeEventHandle, NODE_EVENT_FACTORY_RESET);
                btnHoldCnt = 0;
            }
            else
            {
                Clock_start(bleBootloadBtnCheckClockHandle);
            }
        }
        else
        {
            btnHoldCnt = 0;
            /* Re-enable interrupts to detect button release. */
            PIN_setConfig(buttonPinHandle, PIN_BM_IRQ, Board_BUTTON0 | PIN_IRQ_NEGEDGE);
            PIN_setConfig(buttonPinHandle, PIN_BM_IRQ, Board_BUTTON1 | PIN_IRQ_NEGEDGE);
        }
    }
    #endif //USE_BIM
    
    /*
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /***** Includes *****/
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    #include <ti/sysbios/knl/Event.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    
    /* Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    
    /* Board Header files */
    #include "Board.h"
    
    #include <stdlib.h>
    #include <driverlib/trng.h>
    #include <driverlib/aon_batmon.h>
    #include <DmNodeRadioTask.h>
    
    #include "easylink/EasyLink.h"
    #include "RadioProtocol.h"
    #include "seb/SEB.h"
    
    
    /***** Defines *****/
    #define NODERADIO_TASK_STACK_SIZE 1024
    #define NODERADIO_TASK_PRIORITY   3
    
    #define RADIO_EVENT_ALL                 0xFFFFFFFF
    #define RADIO_EVENT_SEND_ADC_DATA       (uint32_t)(1 << 0)
    #define RADIO_EVENT_DATA_ACK_RECEIVED   (uint32_t)(1 << 1)
    #define RADIO_EVENT_ACK_TIMEOUT         (uint32_t)(1 << 2)
    #define RADIO_EVENT_SEND_FAIL           (uint32_t)(1 << 3)
    
    #define NODERADIO_MAX_RETRIES 2
    #define NORERADIO_ACK_TIMEOUT_TIME_MS (160)
    
    #define NODE_0M_TXPOWER    -10
    
    /***** Type declarations *****/
    struct RadioOperation {
        EasyLink_TxPacket easyLinkTxPacket;
        uint8_t retriesDone;
        uint8_t maxNumberOfRetries;
        uint32_t ackTimeoutMs;
        enum NodeRadioOperationStatus result;
    };
    
    
    /***** Variable declarations *****/
    static Task_Params nodeRadioTaskParams;
    Task_Struct nodeRadioTask;        /* not static so you can see in ROV */
    static uint8_t nodeRadioTaskStack[NODERADIO_TASK_STACK_SIZE];
    Semaphore_Struct radioAccessSem;  /* not static so you can see in ROV */
    static Semaphore_Handle radioAccessSemHandle;
    Event_Struct radioOperationEvent; /* not static so you can see in ROV */
    static Event_Handle radioOperationEventHandle;
    Semaphore_Struct radioResultSem;  /* not static so you can see in ROV */
    static Semaphore_Handle radioResultSemHandle;
    static struct RadioOperation currentRadioOperation;
    static uint16_t adcData;
    static uint8_t nodeAddress = 0;
    static struct DualModeSensorPacket dmSensorPacket;
    static Node_AdertiserType advertiserType = Node_AdertiserMsUrl;
    
    /* The Eddystone UID spec advices to use the first 10 bytes of the sha-1 hash
     * of an owned domain or subdonmian. The subdomain of
     * www.ti.com/.../CC1350 = 792f082074ebc132032cad5fdaada66154e14e98 */
    static uint8_t uidNameSpace[10] = {0x79, 0x2f, 0x08, 0x20, 0x74, 0xeb, 0xc1,
                                       0x32, 0x03, 0x2c};
    
    /* previous Tick count used to calculate uptime for the TLM beacon */
    static uint32_t prevTicks;
    
    /* uid Instance should be set to 6 LSB's of IEEE addr */
    static uint8_t uidInstanceId[6];
    
    /* propreitory advertisement packet */
    static uint8_t localNameAdvertisement[] = {
            0x02, //Length of this Data section
            0x01, //<<Flags>>
            0x02, //LE General Discoverable Mode
            0x18, //Length of this Data section
            0x09, //<<Complete local name>>
            'C', 'C', '1', '3', '5', '0', ' ',
            'L', 'a', 'u', 'n', 'c', 'h',
            'p', 'a', 'd', ' ', '-', ' ', '0', 'x', '0', '0'
            };
    
    /* propreitory advertisement packet */
    static uint8_t propAdvertisement[] = {
            0x02, //Length of this section
            0x01, //<<Flags>>
            0x02, //LE General Discoverable Mode
            0x06, //Length of this section
            0xff, //<<Manufacturer Specific Data>>
            0x0d,
            0x00,
            0x03,
            0x00,
            0x00}; //BTN state
    
    SimpleBeacon_Frame propAdvFrame;
    SimpleBeacon_Frame localNameAdvFrame;
    
    static uint8_t bleMacAddr[6];
    
    /* Pin driver handle */
    extern PIN_Handle ledPinHandle;
    
    /***** Prototypes *****/
    static void nodeRadioTaskFunction(UArg arg0, UArg arg1);
    static void returnRadioOperationStatus(enum NodeRadioOperationStatus status);
    static void sendDmPacket(struct DualModeSensorPacket sensorPacket, uint8_t maxNumberOfRetries, uint32_t ackTimeoutMs);
    static void resendPacket();
    static void rxDoneCallback(EasyLink_RxPacket * rxPacket, EasyLink_Status status);
    static void sendBleAdvertisement(struct DualModeSensorPacket sensorPacket);
    
    /***** Function definitions *****/
    void NodeRadioTask_init(void) {
    
        /* Create semaphore used for exclusive radio access */
        Semaphore_Params semParam;
        Semaphore_Params_init(&semParam);
        Semaphore_construct(&radioAccessSem, 1, &semParam);
        radioAccessSemHandle = Semaphore_handle(&radioAccessSem);
    
        /* Create semaphore used for callers to wait for result */
        Semaphore_construct(&radioResultSem, 0, &semParam);
        radioResultSemHandle = Semaphore_handle(&radioResultSem);
    
        /* Create event used internally for state changes */
        Event_Params eventParam;
        Event_Params_init(&eventParam);
        Event_construct(&radioOperationEvent, &eventParam);
        radioOperationEventHandle = Event_handle(&radioOperationEvent);
    
        /* Create the radio protocol task */
        Task_Params_init(&nodeRadioTaskParams);
        nodeRadioTaskParams.stackSize = NODERADIO_TASK_STACK_SIZE;
        nodeRadioTaskParams.priority = NODERADIO_TASK_PRIORITY;
        nodeRadioTaskParams.stack = &nodeRadioTaskStack;
        Task_construct(&nodeRadioTask, nodeRadioTaskFunction, &nodeRadioTaskParams, NULL);
    }
    
    void nodeRadioTask_setAdvertiserType(Node_AdertiserType type) {
        advertiserType = type;
    }
    
    uint8_t nodeRadioTask_getNodeAddr(void) {
        return nodeAddress;
    }
    
    static void nodeRadioTaskFunction(UArg arg0, UArg arg1)
    {
        /* Set mulitclient mode for EasyLink */
        EasyLink_setCtrl(EasyLink_Ctrl_MultiClient_Mode, 1);
    
        /* Initialize EasyLink */
        if (EasyLink_init(RADIO_EASYLINK_MODULATION) != EasyLink_Status_Success)
        {
            System_abort("EasyLink_init failed");
        }
    
        /* Set frequency */
        if (EasyLink_setFrequency(RADIO_FREQUENCY) != EasyLink_Status_Success)
        {
            System_abort("EasyLink_setFrequency failed");
        }
    
        /* Use the True Random Number Generator to generate sensor node address randomly */;
        Power_setDependency(PowerCC26XX_PERIPH_TRNG);
        TRNGEnable();
        /* Do not accept the same address as the concentrator, in that case get a new random value */
        do
        {
            while (!(TRNGStatusGet() & TRNG_NUMBER_READY))
            {
                //wiat for randum number generator
            }
            nodeAddress = (uint8_t)TRNGNumberGet(TRNG_LOW_WORD);
        } while (nodeAddress == RADIO_CONCENTRATOR_ADDRESS);
        TRNGDisable();
        Power_releaseDependency(PowerCC26XX_PERIPH_TRNG);
    
        /* Set the filter to the generated random address */
        if (EasyLink_enableRxAddrFilter(&nodeAddress, 1, 1) != EasyLink_Status_Success)
        {
            System_abort("EasyLink_enableRxAddrFilter failed");
        }
    
        /* Setup ADC sensor packet */
        dmSensorPacket.header.sourceAddress = nodeAddress;
        dmSensorPacket.header.packetType = RADIO_PACKET_TYPE_DM_SENSOR_PACKET;
    
        /* initialise the Simple Beacon module called dirrectly for Prop Adv
         * Set multiclient mode to true
         */
        SimpleBeacon_init(true);
    
        /* initialise the Simple Eddystone Beacon module
         * Set multiclient mode to true
         */
        SEB_init(true);
    
        SEB_initUrl("www.ti.com/.../cc1350", NODE_0M_TXPOWER);
    
        SimpleBeacon_getIeeeAddr(bleMacAddr);
    
        propAdvFrame.deviceAddress = bleMacAddr;
        propAdvFrame.length = sizeof(propAdvertisement);
        propAdvFrame.pAdvData = propAdvertisement;
    
        //convert nodeAddress to Ascii hex
        localNameAdvertisement[27] = ((nodeAddress & 0x0F) < 0xa) ?
                (nodeAddress & 0x0F) + 0x30:
                (nodeAddress & 0x0F) - 0xa + 0x41;
        localNameAdvertisement[26] = (((nodeAddress & 0xF0) >> 4) < 0xa) ?
                ((nodeAddress & 0xF0) >> 4) + 0x30:
                ((nodeAddress & 0xF0) >> 4) - 0xa + 0x41;
        localNameAdvFrame.deviceAddress = bleMacAddr;
        localNameAdvFrame.length = sizeof(localNameAdvertisement);
        localNameAdvFrame.pAdvData = localNameAdvertisement;
    
        /* Initialise previous Tick count used to calculate uptime for the TLM beacon */
        prevTicks = Clock_getTicks();
    
        /* Enter main task loop */
        while (1)
        {
            /* Wait for an event */
            uint32_t events = Event_pend(radioOperationEventHandle, 0, RADIO_EVENT_ALL, BIOS_WAIT_FOREVER);
    
            /* If we should send ADC data */
            if (events & RADIO_EVENT_SEND_ADC_DATA)
            {
                uint32_t currentTicks;
    
                currentTicks = Clock_getTicks();
                //check for wrap around
                if (currentTicks > prevTicks)
                {
                    //calculate time since last reading in 0.1s units
                    dmSensorPacket.time100MiliSec += ((currentTicks - prevTicks) * Clock_tickPeriod) / 100000;
                }
                else
                {
                    //calculate time since last reading in 0.1s units
                    dmSensorPacket.time100MiliSec += ((prevTicks - currentTicks) * Clock_tickPeriod) / 100000;
                }
                prevTicks = currentTicks;
    
                dmSensorPacket.batt = AONBatMonBatteryVoltageGet();
                dmSensorPacket.adcValue = adcData;
                dmSensorPacket.button = !PIN_getInputValue(Board_BUTTON0);
    
                if (advertiserType != Node_AdertiserNone)
                {
                    sendBleAdvertisement(dmSensorPacket);
                }
    
                sendDmPacket(dmSensorPacket, NODERADIO_MAX_RETRIES, NORERADIO_ACK_TIMEOUT_TIME_MS);
            }
    
            /* If we get an ACK from the concentrator */
            if (events & RADIO_EVENT_DATA_ACK_RECEIVED)
            {
                returnRadioOperationStatus(NodeRadioStatus_Success);
            }
    
            /* If we get an ACK timeout */
            if (events & RADIO_EVENT_ACK_TIMEOUT)
            {
    
                /* If we haven't resent it the maximum number of times yet, then resend packet */
                if (currentRadioOperation.retriesDone < currentRadioOperation.maxNumberOfRetries)
                {
                    resendPacket();
                }
                else
                {
                    /* Else return send fail */
                    Event_post(radioOperationEventHandle, RADIO_EVENT_SEND_FAIL);
                }
            }
    
            /* If send fail */
            if (events & RADIO_EVENT_SEND_FAIL)
            {
                returnRadioOperationStatus(NodeRadioStatus_Failed);
            }
    
        }
    }
    
    enum NodeRadioOperationStatus NodeRadioTask_sendAdcData(uint16_t data)
    {
        enum NodeRadioOperationStatus status;
    
        /* Get radio access sempahore */
        Semaphore_pend(radioAccessSemHandle, BIOS_WAIT_FOREVER);
    
        /* Save data to send */
        adcData = data;
    
        /* Raise RADIO_EVENT_SEND_ADC_DATA event */
        Event_post(radioOperationEventHandle, RADIO_EVENT_SEND_ADC_DATA);
    
        /* Wait for result */
        Semaphore_pend(radioResultSemHandle, BIOS_WAIT_FOREVER);
    
        /* Get result */
        status = currentRadioOperation.result;
    
        /* Return radio access semaphore */
        Semaphore_post(radioAccessSemHandle);
    
        return status;
    }
    
    static void returnRadioOperationStatus(enum NodeRadioOperationStatus result)
    {
        /* Save result */
        currentRadioOperation.result = result;
    
        /* Post result semaphore */
        Semaphore_post(radioResultSemHandle);
    }
    
    static void sendDmPacket(struct DualModeSensorPacket sensorPacket, uint8_t maxNumberOfRetries, uint32_t ackTimeoutMs)
    {
        /* Set destination address in EasyLink API */
        currentRadioOperation.easyLinkTxPacket.dstAddr[0] = RADIO_CONCENTRATOR_ADDRESS;
    
        /* Copy ADC packet to payload
         * Note that the EasyLink API will implcitily both add the length byte and the destination address byte. */
        memcpy(currentRadioOperation.easyLinkTxPacket.payload, ((uint8_t*)&dmSensorPacket), sizeof(struct DualModeSensorPacket));
        currentRadioOperation.easyLinkTxPacket.len = sizeof(struct DualModeSensorPacket);
    
        /* Setup retries */
        currentRadioOperation.maxNumberOfRetries = maxNumberOfRetries;
        currentRadioOperation.ackTimeoutMs = ackTimeoutMs;
        currentRadioOperation.retriesDone = 0;
        EasyLink_setCtrl(EasyLink_Ctrl_AsyncRx_TimeOut, EasyLink_ms_To_RadioTime(ackTimeoutMs));
    
        /* Send packet  */
        if (EasyLink_transmit(&currentRadioOperation.easyLinkTxPacket) != EasyLink_Status_Success)
        {
            System_abort("EasyLink_transmit failed");
        }
    
        /* Enter RX */
        if (EasyLink_receiveAsync(rxDoneCallback, 0) != EasyLink_Status_Success)
        {
            System_abort("EasyLink_receiveAsync failed");
        }
    }
    
    static void resendPacket()
    {
        /* Send packet  */
        if (EasyLink_transmit(&currentRadioOperation.easyLinkTxPacket) != EasyLink_Status_Success)
        {
            System_abort("EasyLink_transmit failed");
        }
    
        /* Enter RX and wait for ACK with timeout */
        if (EasyLink_receiveAsync(rxDoneCallback, 0) != EasyLink_Status_Success)
        {
            System_abort("EasyLink_receiveAsync failed");
        }
    
        /* Increase retries by one */
        currentRadioOperation.retriesDone++;
    }
    
    static void sendBleAdvertisement(struct DualModeSensorPacket sensorPacket)
    {
        uint8_t txCnt, chan;
    
        //Swtich RF switch to 2.4G antenna
        PIN_setOutputValue(ledPinHandle, Board_DIO1_RFSW, 0);
    
        //Prepare TLM frame interleaved with URL and UID
        if ((advertiserType == Node_AdertiserUrl) ||
            (advertiserType == Node_AdertiserMsUrl))
        {
            SEB_initTLM(sensorPacket.batt, sensorPacket.adcValue, sensorPacket.time100MiliSec);
        }
    
        if (advertiserType == Node_AdertiserUid)
        {
            //Prepare TLM frame interleaved with URL and UID
            SEB_initTLM(sensorPacket.batt, sensorPacket.adcValue, sensorPacket.time100MiliSec);
    
            //Set uid intance for the eddystone UID frame
            uidInstanceId[0] = sensorPacket.header.sourceAddress;
            SEB_initUID(uidNameSpace, uidInstanceId, NODE_0M_TXPOWER);
        }
    
        for (txCnt = 0; txCnt < SimpleBeacon_AdvertisementTimes; txCnt++)
        {
            for (chan = 37; chan < 40; chan++)
            {
                if ((advertiserType == Node_AdertiserMs) ||
                    (advertiserType == Node_AdertiserMsUrl))
                {
                    //set BTN value in Prop advertisement
                    propAdvertisement[9] = !PIN_getInputValue(Board_BUTTON0);
    
                    //advertisement advertise local name
                    SimpleBeacon_sendFrame(localNameAdvFrame,  1, (uint64_t) 1<<chan);
                    //advertisement advertise button value
                    SimpleBeacon_sendFrame(propAdvFrame, 1, (uint64_t) 1<<chan);
                }
                if ((advertiserType == Node_AdertiserUrl) ||
                    (advertiserType == Node_AdertiserMsUrl))
                {
                    SEB_sendFrame(SEB_FrameType_Url, bleMacAddr, 1, (uint64_t) 1<<chan);
                    SEB_sendFrame(SEB_FrameType_Tlm, bleMacAddr, 1, (uint64_t) 1<<chan);
                }
                if (advertiserType == Node_AdertiserUid)
                {
                    SEB_sendFrame(SEB_FrameType_Uuid, bleMacAddr, 1, (uint64_t) 1<<chan);
                    SEB_sendFrame(SEB_FrameType_Tlm, bleMacAddr, 1, (uint64_t) 1<<chan);
                }
            }
            //sleep on all but last advertisement
            if(txCnt+1 < SimpleBeacon_AdvertisementTimes)
            {
                Task_sleep(SimpleBeacon_AdvertisementIntervals[txCnt]);
            }
        }
    
        //Swtich RF switch to Sub1G antenna
        PIN_setOutputValue(ledPinHandle, Board_DIO1_RFSW, 1);
    
        /* Toggle activity LED */
        PIN_setOutputValue(ledPinHandle, NODE_BLE_ACTIVITY_LED,!PIN_getOutputValue(NODE_BLE_ACTIVITY_LED));
    }
    
    static void rxDoneCallback(EasyLink_RxPacket * rxPacket, EasyLink_Status status)
    {
        struct PacketHeader* packetHeader;
    
        /* If this callback is called because of a packet received */
        if (status == EasyLink_Status_Success)
        {
            /* Check the payload header */
            packetHeader = (struct PacketHeader*)rxPacket->payload;
    
            /* Check if this is an ACK packet */
            if (packetHeader->packetType == RADIO_PACKET_TYPE_ACK_PACKET)
            {
                /* Signal ACK packet received */
                Event_post(radioOperationEventHandle, RADIO_EVENT_DATA_ACK_RECEIVED);
            }
        }
        /* did the Rx timeout */
        else if(status == EasyLink_Status_Rx_Timeout)
        {
            /* Post a RADIO_EVENT_ACK_TIMEOUT event */
            Event_post(radioOperationEventHandle, RADIO_EVENT_ACK_TIMEOUT);
        }
        else
        {
            /* Rx Error, treat as a Timeout and Post a RADIO_EVENT_ACK_TIMEOUT
               event */
            Event_post(radioOperationEventHandle, RADIO_EVENT_ACK_TIMEOUT);
        }
    
    }
    

  • I dont see the configuration and <board>.c files. Can you try posting again ?

    Thanks,
    Ashish
  • I'm trying to rebuild all the project on new CCS7, with simplelink_cc13x0_sdk_1_00_00_13 and both SPI and UART totally closed when I need lob consumption. I'll update you about the results of the test.