123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595 |
- /**************************************************************************************************
- Filename: SerialApp.c
- Revised: $Date: 2009-03-29 10:51:47 -0700 (Sun, 29 Mar 2009) $
- Revision: $Revision: 19585 $
- Description - Serial Transfer Application (no Profile).
- Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.
- IMPORTANT: Your use of this Software is limited to those specific rights
- granted under the terms of a software license agreement between the user
- who downloaded the software, his/her employer (which must be your employer)
- and Texas Instruments Incorporated (the "License"). You may not use this
- Software unless you agree to abide by the terms of the License. The License
- limits your use, and you acknowledge, that the Software may not be modified,
- copied or distributed unless embedded on a Texas Instruments microcontroller
- or used solely and exclusively in conjunction with a Texas Instruments radio
- frequency transceiver, which is integrated into your product. Other than for
- the foregoing purpose, you may not use, reproduce, copy, prepare derivative
- works of, modify, distribute, perform, display or sell this Software and/or
- its documentation for any purpose.
- YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
- PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
- INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
- NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
- TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
- NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
- LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
- INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
- OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
- OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
- (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
- Should you have any questions regarding your right to use this Software,
- contact Texas Instruments Incorporated at www.TI.com.
- **************************************************************************************************/
- /*********************************************************************
- This sample application is basically a cable replacement
- and it should be customized for your application. A PC
- (or other device) sends data via the serial port to this
- application's device. This device transmits the message
- to another device with the same application running. The
- other device receives the over-the-air message and sends
- it to a PC (or other device) connected to its serial port.
-
- This application doesn't have a profile, so it handles everything directly.
- Key control:
- SW1:
- SW2: initiates end device binding
- SW3:
- SW4: initiates a match description request
- *********************************************************************/
- /*********************************************************************
- * INCLUDES
- */
- #include "AF.h"
- #include "OnBoard.h"
- #include "OSAL_Tasks.h"
- #include "SerialApp.h"
- #include "ZDApp.h"
- #include "ZDObject.h"
- #include "ZDProfile.h"
- #include "hal_drivers.h"
- #include "hal_key.h"
- #if defined ( LCD_SUPPORTED )
- #include "hal_lcd.h"
- #endif
- #include "hal_led.h"
- #include "hal_uart.h"
- /*********************************************************************
- * MACROS
- */
- /*********************************************************************
- * CONSTANTS
- */
- #if !defined( SERIAL_APP_PORT )
- #define SERIAL_APP_PORT 0
- #endif
- #if !defined( SERIAL_APP_BAUD )
- #define SERIAL_APP_BAUD HAL_UART_BR_38400
- //#define SERIAL_APP_BAUD HAL_UART_BR_115200
- #endif
- // When the Rx buf space is less than this threshold, invoke the Rx callback.
- #if !defined( SERIAL_APP_THRESH )
- #define SERIAL_APP_THRESH 64
- #endif
- #if !defined( SERIAL_APP_RX_SZ )
- #define SERIAL_APP_RX_SZ 128
- #endif
- #if !defined( SERIAL_APP_TX_SZ )
- #define SERIAL_APP_TX_SZ 128
- #endif
- // Millisecs of idle time after a byte is received before invoking Rx callback.
- #if !defined( SERIAL_APP_IDLE )
- #define SERIAL_APP_IDLE 6
- #endif
- // Loopback Rx bytes to Tx for throughput testing.
- #if !defined( SERIAL_APP_LOOPBACK )
- #define SERIAL_APP_LOOPBACK FALSE
- #endif
- // This is the max byte count per OTA message.
- #if !defined( SERIAL_APP_TX_MAX )
- #define SERIAL_APP_TX_MAX 80
- #endif
- #define SERIAL_APP_RSP_CNT 4
- // This list should be filled with Application specific Cluster IDs.
- const cId_t SerialApp_ClusterList[SERIALAPP_MAX_CLUSTERS] =
- {
- SERIALAPP_CLUSTERID1,
- SERIALAPP_CLUSTERID2
- };
- const SimpleDescriptionFormat_t SerialApp_SimpleDesc =
- {
- SERIALAPP_ENDPOINT, // int Endpoint;
- SERIALAPP_PROFID, // uint16 AppProfId[2];
- SERIALAPP_DEVICEID, // uint16 AppDeviceId[2];
- SERIALAPP_DEVICE_VERSION, // int AppDevVer:4;
- SERIALAPP_FLAGS, // int AppFlags:4;
- SERIALAPP_MAX_CLUSTERS, // byte AppNumInClusters;
- (cId_t *)SerialApp_ClusterList, // byte *pAppInClusterList;
- SERIALAPP_MAX_CLUSTERS, // byte AppNumOutClusters;
- (cId_t *)SerialApp_ClusterList // byte *pAppOutClusterList;
- };
- const endPointDesc_t SerialApp_epDesc =
- {
- SERIALAPP_ENDPOINT,
- &SerialApp_TaskID,
- (SimpleDescriptionFormat_t *)&SerialApp_SimpleDesc,
- noLatencyReqs
- };
- /*********************************************************************
- * TYPEDEFS
- */
- /*********************************************************************
- * GLOBAL VARIABLES
- */
- uint8 SerialApp_TaskID; // Task ID for internal task/event processing.
- /*********************************************************************
- * EXTERNAL VARIABLES
- */
- /*********************************************************************
- * EXTERNAL FUNCTIONS
- */
- /*********************************************************************
- * LOCAL VARIABLES
- */
- static uint8 SerialApp_MsgID;
- static afAddrType_t SerialApp_TxAddr;
- static uint8 SerialApp_TxSeq;
- static uint8 SerialApp_TxBuf[SERIAL_APP_TX_MAX+1];
- static uint8 SerialApp_TxLen;
- static afAddrType_t SerialApp_RxAddr;
- static uint8 SerialApp_RxSeq;
- static uint8 SerialApp_RspBuf[SERIAL_APP_RSP_CNT];
- /*********************************************************************
- * LOCAL FUNCTIONS
- */
- static void SerialApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg );
- static void SerialApp_HandleKeys( uint8 shift, uint8 keys );
- static void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt );
- static void SerialApp_Send(void);
- static void SerialApp_Resp(void);
- static void SerialApp_CallBack(uint8 port, uint8 event);
- /*********************************************************************
- * @fn SerialApp_Init
- *
- * @brief This is called during OSAL tasks' initialization.
- *
- * @param task_id - the Task ID assigned by OSAL.
- *
- * @return none
- */
- void SerialApp_Init( uint8 task_id )
- {
- halUARTCfg_t uartConfig;
- SerialApp_TaskID = task_id;
- SerialApp_RxSeq = 0xC3;
- afRegister( (endPointDesc_t *)&SerialApp_epDesc );
- RegisterForKeys( task_id );
- uartConfig.configured = TRUE; // 2x30 don't care - see uart driver.
- uartConfig.baudRate = SERIAL_APP_BAUD;
- uartConfig.flowControl = TRUE;
- uartConfig.flowControlThreshold = SERIAL_APP_THRESH; // 2x30 don't care - see uart driver.
- uartConfig.rx.maxBufSize = SERIAL_APP_RX_SZ; // 2x30 don't care - see uart driver.
- uartConfig.tx.maxBufSize = SERIAL_APP_TX_SZ; // 2x30 don't care - see uart driver.
- uartConfig.idleTimeout = SERIAL_APP_IDLE; // 2x30 don't care - see uart driver.
- uartConfig.intEnable = TRUE; // 2x30 don't care - see uart driver.
- uartConfig.callBackFunc = SerialApp_CallBack;
- HalUARTOpen (SERIAL_APP_PORT, &uartConfig);
- #if defined ( LCD_SUPPORTED )
- HalLcdWriteString( "SerialApp", HAL_LCD_LINE_2 );
- #endif
-
- ZDO_RegisterForZDOMsg( SerialApp_TaskID, End_Device_Bind_rsp );
- ZDO_RegisterForZDOMsg( SerialApp_TaskID, Match_Desc_rsp );
- }
- /*********************************************************************
- * @fn SerialApp_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 SerialApp_ProcessEvent( uint8 task_id, UINT16 events )
- {
- (void)task_id; // Intentionally unreferenced parameter
-
- if ( events & SYS_EVENT_MSG )
- {
- afIncomingMSGPacket_t *MSGpkt;
- while ( (MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SerialApp_TaskID )) )
- {
- switch ( MSGpkt->hdr.event )
- {
- case ZDO_CB_MSG:
- SerialApp_ProcessZDOMsgs( (zdoIncomingMsg_t *)MSGpkt );
- break;
-
- case KEY_CHANGE:
- SerialApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t *)MSGpkt)->keys );
- break;
- case AF_INCOMING_MSG_CMD:
- SerialApp_ProcessMSGCmd( MSGpkt );
- break;
- default:
- break;
- }
- osal_msg_deallocate( (uint8 *)MSGpkt );
- }
- return ( events ^ SYS_EVENT_MSG );
- }
- if ( events & SERIALAPP_SEND_EVT )
- {
- SerialApp_Send();
- return ( events ^ SERIALAPP_SEND_EVT );
- }
- if ( events & SERIALAPP_RESP_EVT )
- {
- SerialApp_Resp();
- return ( events ^ SERIALAPP_RESP_EVT );
- }
- return ( 0 ); // Discard unknown events.
- }
- /*********************************************************************
- * @fn SerialApp_ProcessZDOMsgs()
- *
- * @brief Process response messages
- *
- * @param none
- *
- * @return none
- */
- static void SerialApp_ProcessZDOMsgs( zdoIncomingMsg_t *inMsg )
- {
- switch ( inMsg->clusterID )
- {
- case End_Device_Bind_rsp:
- if ( ZDO_ParseBindRsp( inMsg ) == ZSuccess )
- {
- // Light LED
- HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
- }
- #if defined(BLINK_LEDS)
- else
- {
- // Flash LED to show failure
- HalLedSet ( HAL_LED_4, HAL_LED_MODE_FLASH );
- }
- #endif
- break;
-
- case Match_Desc_rsp:
- {
- ZDO_ActiveEndpointRsp_t *pRsp = ZDO_ParseEPListRsp( inMsg );
- if ( pRsp )
- {
- if ( pRsp->status == ZSuccess && pRsp->cnt )
- {
- SerialApp_TxAddr.addrMode = (afAddrMode_t)Addr16Bit;
- SerialApp_TxAddr.addr.shortAddr = pRsp->nwkAddr;
- // Take the first endpoint, Can be changed to search through endpoints
- SerialApp_TxAddr.endPoint = pRsp->epList[0];
-
- // Light LED
- HalLedSet( HAL_LED_4, HAL_LED_MODE_ON );
- }
- osal_mem_free( pRsp );
- }
- }
- break;
- }
- }
- /*********************************************************************
- * @fn SerialApp_HandleKeys
- *
- * @brief Handles all key events for this device.
- *
- * @param shift - true if in shift/alt.
- * @param keys - bit field for key events.
- *
- * @return none
- */
- void SerialApp_HandleKeys( uint8 shift, uint8 keys )
- {
- zAddrType_t txAddr;
-
- if ( shift )
- {
- if ( keys & HAL_KEY_SW_1 )
- {
- }
- if ( keys & HAL_KEY_SW_2 )
- {
- }
- if ( keys & HAL_KEY_SW_3 )
- {
- }
- if ( keys & HAL_KEY_SW_4 )
- {
- }
- }
- else
- {
- if ( keys & HAL_KEY_SW_1 )
- {
- }
- if ( keys & HAL_KEY_SW_2 )
- {
- HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
-
- // Initiate an End Device Bind Request for the mandatory endpoint
- txAddr.addrMode = Addr16Bit;
- txAddr.addr.shortAddr = 0x0000; // Coordinator
- ZDP_EndDeviceBindReq( &txAddr, NLME_GetShortAddr(),
- SerialApp_epDesc.endPoint,
- SERIALAPP_PROFID,
- SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
- SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
- FALSE );
- }
- if ( keys & HAL_KEY_SW_3 )
- {
- }
- if ( keys & HAL_KEY_SW_4 )
- {
- HalLedSet ( HAL_LED_4, HAL_LED_MODE_OFF );
-
- // Initiate a Match Description Request (Service Discovery)
- txAddr.addrMode = AddrBroadcast;
- txAddr.addr.shortAddr = NWK_BROADCAST_SHORTADDR;
- ZDP_MatchDescReq( &txAddr, NWK_BROADCAST_SHORTADDR,
- SERIALAPP_PROFID,
- SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
- SERIALAPP_MAX_CLUSTERS, (cId_t *)SerialApp_ClusterList,
- FALSE );
- }
- }
- }
- /*********************************************************************
- * @fn SerialApp_ProcessMSGCmd
- *
- * @brief Data message processor callback. This function processes
- * any incoming data - probably from other devices. Based
- * on the cluster ID, perform the intended action.
- *
- * @param pkt - pointer to the incoming message packet
- *
- * @return TRUE if the 'pkt' parameter is being used and will be freed later,
- * FALSE otherwise.
- */
- void SerialApp_ProcessMSGCmd( afIncomingMSGPacket_t *pkt )
- {
- uint8 stat;
- uint8 seqnb;
- uint8 delay;
- switch ( pkt->clusterId )
- {
- // A message with a serial data block to be transmitted on the serial port.
- case SERIALAPP_CLUSTERID1:
- // Store the address for sending and retrying.
- osal_memcpy(&SerialApp_RxAddr, &(pkt->srcAddr), sizeof( afAddrType_t ));
- seqnb = pkt->cmd.Data[0];
- // Keep message if not a repeat packet
- if ( (seqnb > SerialApp_RxSeq) || // Normal
- ((seqnb < 0x80 ) && ( SerialApp_RxSeq > 0x80)) ) // Wrap-around
- {
- // Transmit the data on the serial port.
- if ( HalUARTWrite( SERIAL_APP_PORT, pkt->cmd.Data+1, (pkt->cmd.DataLength-1) ) )
- {
- // Save for next incoming message
- SerialApp_RxSeq = seqnb;
- stat = OTA_SUCCESS;
- }
- else
- {
- stat = OTA_SER_BUSY;
- }
- }
- else
- {
- stat = OTA_DUP_MSG;
- }
- // Select approproiate OTA flow-control delay.
- delay = (stat == OTA_SER_BUSY) ? SERIALAPP_NAK_DELAY : SERIALAPP_ACK_DELAY;
- // Build & send OTA response message.
- SerialApp_RspBuf[0] = stat;
- SerialApp_RspBuf[1] = seqnb;
- SerialApp_RspBuf[2] = LO_UINT16( delay );
- SerialApp_RspBuf[3] = HI_UINT16( delay );
- osal_set_event( SerialApp_TaskID, SERIALAPP_RESP_EVT );
- osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_RESP_EVT);
- break;
- // A response to a received serial data block.
- case SERIALAPP_CLUSTERID2:
- if ((pkt->cmd.Data[1] == SerialApp_TxSeq) &&
- ((pkt->cmd.Data[0] == OTA_SUCCESS) || (pkt->cmd.Data[0] == OTA_DUP_MSG)))
- {
- SerialApp_TxLen = 0;
- osal_stop_timerEx(SerialApp_TaskID, SERIALAPP_SEND_EVT);
- }
- else
- {
- // Re-start timeout according to delay sent from other device.
- delay = BUILD_UINT16( pkt->cmd.Data[2], pkt->cmd.Data[3] );
- osal_start_timerEx( SerialApp_TaskID, SERIALAPP_SEND_EVT, delay );
- }
- break;
- default:
- break;
- }
- }
- /*********************************************************************
- * @fn SerialApp_Send
- *
- * @brief Send data OTA.
- *
- * @param none
- *
- * @return none
- */
- static void SerialApp_Send(void)
- {
- #if SERIAL_APP_LOOPBACK
- if (SerialApp_TxLen < SERIAL_APP_TX_MAX)
- {
- SerialApp_TxLen += HalUARTRead(SERIAL_APP_PORT, SerialApp_TxBuf+SerialApp_TxLen+1,
- SERIAL_APP_TX_MAX-SerialApp_TxLen);
- }
- if (SerialApp_TxLen)
- {
- (void)SerialApp_TxAddr;
- if (HalUARTWrite(SERIAL_APP_PORT, SerialApp_TxBuf+1, SerialApp_TxLen))
- {
- SerialApp_TxLen = 0;
- }
- else
- {
- osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
- }
- }
- #else
- if (!SerialApp_TxLen &&
- (SerialApp_TxLen = HalUARTRead(SERIAL_APP_PORT, SerialApp_TxBuf+1, SERIAL_APP_TX_MAX)))
- {
- // Pre-pend sequence number to the Tx message.
- SerialApp_TxBuf[0] = ++SerialApp_TxSeq;
- }
- if (SerialApp_TxLen)
- {
- if (afStatus_SUCCESS != AF_DataRequest(&SerialApp_TxAddr,
- (endPointDesc_t *)&SerialApp_epDesc,
- SERIALAPP_CLUSTERID1,
- SerialApp_TxLen+1, SerialApp_TxBuf,
- &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS))
- {
- osal_set_event(SerialApp_TaskID, SERIALAPP_SEND_EVT);
- }
- }
- #endif
- }
- /*********************************************************************
- * @fn SerialApp_Resp
- *
- * @brief Send data OTA.
- *
- * @param none
- *
- * @return none
- */
- static void SerialApp_Resp(void)
- {
- if (afStatus_SUCCESS != AF_DataRequest(&SerialApp_RxAddr,
- (endPointDesc_t *)&SerialApp_epDesc,
- SERIALAPP_CLUSTERID2,
- SERIAL_APP_RSP_CNT, SerialApp_RspBuf,
- &SerialApp_MsgID, 0, AF_DEFAULT_RADIUS))
- {
- osal_set_event(SerialApp_TaskID, SERIALAPP_RESP_EVT);
- }
- }
- /*********************************************************************
- * @fn SerialApp_CallBack
- *
- * @brief Send data OTA.
- *
- * @param port - UART port.
- * @param event - the UART port event flag.
- *
- * @return none
- */
- static void SerialApp_CallBack(uint8 port, uint8 event)
- {
- (void)port;
- if ((event & (HAL_UART_RX_FULL | HAL_UART_RX_ABOUT_FULL | HAL_UART_RX_TIMEOUT)) &&
- #if SERIAL_APP_LOOPBACK
- (SerialApp_TxLen < SERIAL_APP_TX_MAX))
- #else
- !SerialApp_TxLen)
- #endif
- {
- SerialApp_Send();
- }
- }
- /*********************************************************************
- *********************************************************************/
|