/* * Copyright (c) 2015-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. */ /* * ======== empty.c ======== */ /* XDCtools Header files */ #include #include #include /* BIOS Header files */ #include #include #include /* TI-RTOS Header files */ #include #include /* Board Header files */ #include "Board.h" #include "RFQueue.h" #include "smartrf_settings/smartrf_settings.h" #define TX_TASKSTACKSIZE 1024 #define TX_TASK_PRIORITY 3 #define RX_TASK_PRIORITY 2 /* TX Configuration */ #define PAYLOAD_LENGTH 30 #define PACKET_INTERVAL (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */ #define NUM_APPENDED_BYTES 2 /* The Data Entries data field will contain: * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1) * Max 30 payload bytes * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */ #define NUM_DATA_ENTRIES 2 /* NOTE: Only two data entries supported at the moment */ /***** Prototypes *****/ static void txTaskFunction(UArg arg0, UArg arg1); void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId); void TxTask_init(PIN_Handle inPinHandle); static void callbackRx(RF_Handle h, RF_CmdHandle ch, RF_EventMask e); //static void rxTaskFunction(UArg arg0, UArg arg1); static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES, PAYLOAD_LENGTH, NUM_APPENDED_BYTES)]; /* Receive dataQueue for RF Core to fill in data */ static dataQueue_t dataQueue; static rfc_dataEntryGeneral_t* currentDataEntry; static uint8_t packetLength; static uint8_t* packetDataPointer; static uint8_t boardLED1 = 0; static uint32_t currVal = 0; static Task_Params txTaskParams; Task_Struct task0Struct; static Char task0Stack[TX_TASKSTACKSIZE]; static RF_Object rfObject; static RF_Handle rfHandle; int32_t packVal = 0; uint32_t time; static uint8_t packet[PAYLOAD_LENGTH+1]; static uint16_t seqNumber; /* Pin driver handle */ static PIN_Handle ledPinHandle; static PIN_Handle buttonPinHandle; /* Global memory storage for a PIN_Config table */ static PIN_State buttonPinState; static PIN_State ledPinState; /* TX Semaphore */ static Semaphore_Struct txSemaphore; static Semaphore_Handle txSemaphoreHandle; /* * Application LED pin configuration table: * - All LEDs board LEDs are off. */ PIN_Config ledPinTable[] = { Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, Board_LED1 | 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 }; /* * ======== buttonCallbackFxn ======== * Pin interrupt Callback function board buttons configured in the pinTable. */ void buttonCallbackFxn(PIN_Handle handle, PIN_Id pinId) { /* Debounce logic, only toggle if the button is still pushed (low) */ CPUdelay(8000*50); if (!PIN_getInputValue(pinId)) { /* Toggle LED based on the button pressed */ switch(pinId) { case Board_BUTTON0: packVal = 123; currVal = PIN_getOutputValue(Board_LED0); PIN_setOutputValue(ledPinHandle, Board_LED0, !currVal); break; case Board_BUTTON1: packVal = 321; currVal = PIN_getOutputValue(Board_LED1); PIN_setOutputValue(ledPinHandle, Board_LED1, !currVal); boardLED1 = 1; break; default: /* Do nothing */ PIN_setOutputValue(ledPinHandle, Board_LED0, 1); PIN_setOutputValue(ledPinHandle, Board_LED1, 1); break; } } /* Post TX semaphore to TX task */ Semaphore_post(txSemaphoreHandle); } /* Receive Callback Function */ void callbackRx(RF_Handle h, RF_CmdHandle ch, RF_EventMask e) { if (e & RF_EventRxEntryDone) { do { /* Get current unhandled data entry */ currentDataEntry = RFQueue_getDataEntry(); /* Handle the packet data, located at ¤tDataEntry->data: * - Length is the first byte with the current configuration * - Data starts from the second byte */ packetLength = *(uint8_t*)(¤tDataEntry->data); packetDataPointer = (uint8_t*)(¤tDataEntry->data + 1); /* Copy the payload + the status byte to the packet variable */ memcpy(packet, packetDataPointer, (packetLength + 1)); if((*(packet+2)) == (uint8_t)123) { /* Toggle pin to indicate RX */ PIN_setOutputValue(ledPinHandle, Board_LED0,!PIN_getOutputValue(Board_LED0)); } else if((*(packet+2)) == (uint8_t)321) { boardLED1 = 0; PIN_setOutputValue(ledPinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1)); txTaskParams.priority = TX_TASK_PRIORITY; //RF_cmdNop.pNextOp = (rfc_radioOp_t*)&RF_cmdPropTx; RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0); } else { PIN_setOutputValue(ledPinHandle, Board_LED0,!PIN_getOutputValue(Board_LED0)); PIN_setOutputValue(ledPinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1)); } }while(RFQueue_nextEntry() == DATA_ENTRY_FINISHED); } } /***** Function definitions *****/ void TxTask_init(PIN_Handle inPinHandle) { //pinHandle = inPinHandle; /* Initialize TX semaphore */ Semaphore_construct(&txSemaphore, 0, NULL); txSemaphoreHandle = Semaphore_handle(&txSemaphore); Task_Params_init(&txTaskParams); txTaskParams.stackSize = TX_TASKSTACKSIZE; txTaskParams.priority = TX_TASK_PRIORITY; txTaskParams.stack = &task0Stack; txTaskParams.arg0 = (UInt)1000000; Task_construct(&task0Struct,txTaskFunction,&txTaskParams, NULL); } /* * ======== txTaskFunction ======== * Transmit the data over RF radio. * Blink LED when data is transmitted. */ static void txTaskFunction(UArg arg0, UArg arg1) { uint32_t time; /* Setup callback for button pins */ if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFxn) != 0) { System_abort("Error registering button callback function"); } RF_Params rfParams; RF_Params_init(&rfParams); RF_cmdPropTx.pktLen = PAYLOAD_LENGTH; RF_cmdPropTx.pPkt = packet; RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME; RF_cmdPropTx.startTrigger.pastTrig = 1; RF_cmdPropTx.startTime = 0; if( RFQueue_defineQueue(&dataQueue, rxDataEntryBuffer, sizeof(rxDataEntryBuffer), NUM_DATA_ENTRIES, PAYLOAD_LENGTH + NUM_APPENDED_BYTES)) { /* Failed to allocate space for all data entries */ while(1); } /* Modify CMD_PROP_RX command for application needs */ RF_cmdPropRx.pQueue = &dataQueue; /* Set the Data Entity queue for received data */ RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1; /* Discard ignored packets from Rx queue */ RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1; /* Discard packets with CRC error from Rx queue */ RF_cmdPropRx.maxPktLen = PAYLOAD_LENGTH; /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */ RF_cmdPropRx.pktConf.bRepeatOk = 1; RF_cmdPropRx.pktConf.bRepeatNok = 1; /* Request access to the radio */ rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams); /* Set the frequency */ RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0); /* Get current time */ time = RF_getCurrentTime(); while(1) { /* Wait for a button press */ Semaphore_pend(txSemaphoreHandle, BIOS_WAIT_FOREVER); /* Create packet with incrementing sequence number and random payload */ packet[0] = (uint8_t)(seqNumber >> 8); packet[1] = (uint8_t)(seqNumber++); uint8_t i; for (i = 2; i < PAYLOAD_LENGTH; i++) { //packet[i] = rand(); packet[i] = packVal; } /* Set absolute TX time to utilize automatic power management */ time += PACKET_INTERVAL; RF_cmdPropTx.startTime = time; /* Send packet */ RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0); if (!(result & RF_EventLastCmdDone)) { /* Error */ while(1); } while((currVal != PIN_getOutputValue(Board_LED1))&&(boardLED1 == 1)) { /* Enter RX mode and stay forever in RX */ txTaskParams.priority = RX_TASK_PRIORITY; RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callbackRx, IRQ_RX_ENTRY_DONE); while(1); //RF_pendCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callbackRx, IRQ_RX_ENTRY_DONE); } } } /* * ======== main ======== */ int main(void) { //Task_Params taskParams; /* Call board init functions */ Board_initGeneral(); /* Open LED pins */ ledPinHandle = PIN_open(&ledPinState, ledPinTable); if(!ledPinHandle) { System_abort("Error initializing board LED pins\n"); } buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable); if(!buttonPinHandle) { System_abort("Error initializing button pins\n"); } /* Initialize task */ TxTask_init(ledPinHandle); /* Start BIOS */ BIOS_start(); return (0); }