peer2peer.c

Back to Peer-to-peer sample application.

00001 
00017 /******************************************************************************
00018                     Includes section
00019 ******************************************************************************/
00020 #include <types.h>
00021 #include <configServer.h>
00022 #include <appTimer.h>
00023 #include <zdo.h>
00024 #include <peer2peer.h>
00025 #include <serialInterface.h>
00026 
00027 /******************************************************************************
00028                     Define(s) section
00029 ******************************************************************************/
00030 
00031 /******************************************************************************
00032                     Variables section
00033 ******************************************************************************/
00034 // Network related variables
00035 static uint16_t nwkAddr;                        // Own NWK address
00036 static AppMessageBuffer_t appMessageBuffer;     // Application message buffer
00037 static uint8_t messageIdTx = 0;                 // Application transmitted message ID
00038 static uint8_t messageIdRx = 0;                 // Application received message ID
00039 static bool messageIdRxValid = false;           // Application received message ID valid flag
00040 static uint8_t actualDataLength = 0;            // Actual data length to be transmitted via network   
00041 
00042 // Temporary data received via network buffer
00043 static uint8_t tmpDataBuffer[APP_TMP_DATA_BUFFER_SIZE];
00044 static uint8_t tmpDataBufferActualLength = 0;   
00045 
00046 // UART related variables
00047 static HAL_UartDescriptor_t appUartDescriptor;          // UART descriptor (required by stack)
00048 static bool uartTxBusyFlag = false;                     // UART transmission transaction status
00049 static uint8_t uartTxBuffer[APP_UART_TX_BUFFER_SIZE];   // UART Tx buffer
00050 static uint8_t uartRxBuffer[APP_UART_RX_BUFFER_SIZE];   // UART Rx buffer
00051 static uint8_t uartRxPending = 0;
00052 
00053 static AppState_t appState = APP_INITIAL_STATE;  // application state
00054 static AppDataTransmission_t appDataTransmissionState = APP_DATA_TRANSMISSION_IDLE_STATE; //application data transmission feature state
00055 static ZDO_StartNetworkReq_t networkParams; // request params for ZDO_StartNetworkReq
00056 static APS_DataReq_t apsDataReq;
00057 
00058 // endpoint parameters
00059 static SimpleDescriptor_t simpleDescriptor = { APP_ENDPOINT, APP_PROFILE_ID, 1, 1, 0, 0 , NULL, 0, NULL };
00060 static APS_RegisterEndpointReq_t endpointParams;
00061 
00062 // Timer indicating starting network during network joining.
00063 // Also used as delay timer between APS_DataConf and APS_DataReq.
00064 static HAL_AppTimer_t delayTimer;
00065 
00066 /***********************************************************************************
00067                     Static functions declarations section
00068 ***********************************************************************************/
00069 static void APS_DataIndication(APS_DataInd_t* dataInd);
00070 static void APS_DataConf(APS_DataConf_t* confInfo);
00071 static void ZDO_StartNetworkConf(ZDO_StartNetworkConf_t* confirmInfo);
00072 static void initNetwork(void);
00073 static void startNetwork(void);
00074 static void networkSendData(bool newTransmission);
00075 static void startBlinkTimer(void);
00076 static void initSerialInterface(void);
00077 static void sendDataToUart(uint8_t*, uint8_t);
00078 static void startingNetworkTimerFired(void);
00079 static void delayTimerFired(void);
00080 static void uartBytesReceived(uint8_t readBytesLen);
00081 static void uartWriteConf(void);
00082 static void buttonReleased(uint8_t buttons);
00083 
00084 /***********************************************************************************
00085                     Implementation section
00086 ***********************************************************************************/
00087 /**************************************************************************/
00093 void APL_TaskHandler(void)
00094 {
00095   switch (appState)
00096   { 
00097     case APP_INITIAL_STATE:                 // Node has initial state
00098       initSerialInterface();                // Open UART
00099       appOpenButtons(NULL, buttonReleased); // Open buttons
00100       appOpenLeds();                        // Enable LEDs   
00101       initNetwork();
00102       SYS_PostTask(APL_TASK_ID);            // Execute next step
00103       break;
00104 
00105     case APP_NETWORK_JOINING_STATE:
00106       startBlinkTimer();
00107       startNetwork();
00108       break;
00109 
00110     case APP_NETWORK_JOINED_STATE:
00111     default:
00112       break;
00113   }
00114 }
00115 
00116 /**************************************************************************/
00122 static void initNetwork(void)
00123 {
00124   DeviceType_t  deviceType  = DEVICE_TYPE_ROUTER;
00125   ExtAddr_t     extAddr     = APP_COORD_UID;
00126 
00127 #ifndef _SLIDERS_
00128   // NWK preconfigured address reading for Config Server
00129   CS_ReadParameter(CS_NWK_ADDR_ID, &nwkAddr);
00130 #else  //#ifndef _SLIDERS_
00131   // NWK address reading from sliders 
00132   nwkAddr = BSP_ReadSliders();
00133   // Set the NWK address value to Config Server
00134   CS_WriteParameter(CS_NWK_ADDR_ID, &nwkAddr);
00135 #endif //#ifndef _SLIDERS_
00136 
00137   //NWK address value check
00138   if (APP_MAX_NWK_ADDR < nwkAddr)
00139   {
00140     appState = APP_ERROR_STATE;
00141   }
00142   else
00143   {
00144     // Node role detection. If nwkAddr == 0 then node is coordinator. 
00145     // In othe case the node role is router.
00146     if (0 == nwkAddr)   
00147     {
00148       deviceType = DEVICE_TYPE_COORDINATOR;
00149       // Set the extended address value to Config Server for coordinator only
00150       CS_WriteParameter(CS_UID_ID, &extAddr);
00151     }
00152     // Set the deviceType value to Config Server
00153     CS_WriteParameter(CS_DEVICE_TYPE_ID, &deviceType);
00154 
00155     // Application state changing
00156     appState = APP_NETWORK_JOINING_STATE;
00157   }
00158 }
00159 
00160 /**************************************************************************/
00166 void ZDO_StartNetworkConf(ZDO_StartNetworkConf_t* confirmInfo)
00167 {
00168   if (confirmInfo->status == ZDO_SUCCESS_STATUS)
00169   {
00170     appState = APP_NETWORK_JOINED_STATE;
00171     actualDataLength = 0;
00172     messageIdRxValid = false;
00173     uartRxPending = 0;
00174 
00175     // Stop the blink timer
00176     HAL_StopAppTimer(&delayTimer);
00177     appOnLed(APP_NETWORK_STATUS_LED);
00178 
00179 #if APP_DATA_TRANSMISSION_DELAY
00180     // Setup timer to be used as delay timer between APS_DataConf and APS_DataReq.
00181     delayTimer.interval = APP_DATA_TRANSMISSION_DELAY;
00182     delayTimer.mode     = TIMER_ONE_SHOT_MODE;
00183     delayTimer.callback = delayTimerFired;
00184 #endif
00185 
00186     // Set application endpoint properties
00187     endpointParams.simpleDescriptor = &simpleDescriptor;
00188     endpointParams.APS_DataInd = APS_DataIndication;
00189     // Register endpoint
00190     APS_RegisterEndpointReq(&endpointParams);
00191   }
00192   else
00193   {
00194     SYS_PostTask(APL_TASK_ID);
00195   }
00196 }
00197 
00198 /**************************************************************************/
00204 static void startNetwork(void)
00205 {
00206   networkParams.ZDO_StartNetworkConf = ZDO_StartNetworkConf;
00207   // start network
00208   ZDO_StartNetworkReq(&networkParams);   
00209 }
00210 
00211 /**************************************************************************/
00217 static void startBlinkTimer(void)
00218 {
00219   delayTimer.interval = APP_JOINING_INDICATION_PERIOD;
00220   delayTimer.mode     = TIMER_REPEAT_MODE;
00221   delayTimer.callback = startingNetworkTimerFired;
00222   HAL_StartAppTimer(&delayTimer);
00223 }
00224 
00225 /**************************************************************************/
00231 static void startingNetworkTimerFired(void)
00232 {
00233   appToggleLed(APP_NETWORK_STATUS_LED);
00234 }
00235 
00236 /**************************************************************************/
00242 void ZDO_MgmtNwkUpdateNotf(ZDO_MgmtNwkUpdateNotf_t *nwkParams)
00243 {
00244   switch (nwkParams->status)
00245   {
00246     case ZDO_NETWORK_STARTED_STATUS:
00247       break;
00248 
00249     case ZDO_NETWORK_LOST_STATUS:
00250 //    case ZDO_REJOIN_STARTED_STATUS:
00251       {
00252         APS_UnregisterEndpointReq_t unregEndpoint;  
00253         if (APP_NETWORK_JOINED_STATE == appState)
00254         {
00255           unregEndpoint.endpoint = endpointParams.simpleDescriptor->endpoint;
00256           APS_UnregisterEndpointReq(&unregEndpoint);    
00257         }
00258         appOffLed(APP_NETWORK_STATUS_LED);
00259   
00260         // try to rejoin the network
00261         appState = APP_NETWORK_JOINING_STATE;
00262         SYS_PostTask(APL_TASK_ID);
00263         break;  
00264       }        
00265 
00266     case ZDO_NWK_UPDATE_STATUS:
00267       break;
00268 
00269     default:
00270       break;
00271   }
00272 }
00273 
00274 /**************************************************************************/
00280 void ZDO_WakeUpInd(void)
00281 {
00282 }
00283 
00284 /**************************************************************************/
00290 void ZDO_SleepInd(void)
00291 {
00292 }
00293 
00294 /**************************************************************************/
00301 static void networkSendData(bool newTransmission)
00302 {
00303   if (APP_DATA_TRANSMISSION_IDLE_STATE == appDataTransmissionState)
00304   {
00305     appDataTransmissionState = APP_DATA_TRANSMISSION_BUSY_STATE;
00306     // indicate we're sending
00307     appOnLed(APP_SENDING_STATUS_LED);
00308 
00309     if (newTransmission)
00310     {
00311       // The new applicatiom message will be sent
00312       // messageId value 
00313       appMessageBuffer.message.messageId = messageIdTx++;
00314       // APS Data Request preparing
00315       apsDataReq.dstAddrMode = APS_SHORT_ADDRESS;               // Short addressing mode 
00316       // Destination address
00317       apsDataReq.dstAddress.shortAddress = (nwkAddr & 0xfffe) | ((~nwkAddr) & 0x01);
00318       apsDataReq.profileId = simpleDescriptor.AppProfileId;     // Profile ID
00319       apsDataReq.dstEndpoint = simpleDescriptor.endpoint;       // Desctination endpoint
00320       apsDataReq.clusterId = APP_CLUSTER_ID;                    // Desctination cluster ID
00321       apsDataReq.srcEndpoint = simpleDescriptor.endpoint;       // Source endpoint
00322       apsDataReq.asdu = (uint8_t*) &appMessageBuffer.message;   // application message pointer
00323       // actual application message length
00324       apsDataReq.asduLength = actualDataLength + sizeof(appMessageBuffer.message.messageId);
00325       apsDataReq.txOptions.acknowledgedTransmission = 1;        // Acknowledged transmission enabled
00326       apsDataReq.radius = 0;                                    // Default radius
00327       apsDataReq.APS_DataConf = APS_DataConf;                   // Confirm handler
00328     }
00329 
00330     // send data request
00331     APS_DataReq(&apsDataReq);
00332   }
00333 }
00334 
00335 /**************************************************************************/
00341 void APS_DataConf(APS_DataConf_t* confInfo)
00342 {
00343   appOffLed(APP_SENDING_STATUS_LED);
00344 
00345   if (APS_SUCCESS_STATUS == confInfo->status) // data delivered
00346   {
00347 #if APP_DATA_TRANSMISSION_DELAY
00348     // Start delay timer. This timer is used to prevent collisions in duplex mode.
00349     HAL_StartAppTimer(&delayTimer);
00350 #else
00351     // No delay needed.
00352     delayTimerFired();
00353 #endif
00354   }
00355   else  // data not delivered, resend
00356   {
00357     appDataTransmissionState = APP_DATA_TRANSMISSION_IDLE_STATE;
00358     networkSendData(false); // Current application message retransmission
00359   }
00360 }
00361 
00362 /**************************************************************************/
00368 static void delayTimerFired(void)
00369 {
00370   appDataTransmissionState = APP_DATA_TRANSMISSION_IDLE_STATE;
00371 
00372   appOffLed(APP_SENDING_STATUS_LED);
00373 
00374   if (uartRxPending > 0)
00375     uartBytesReceived(uartRxPending);
00376 }
00377                 
00378 /**************************************************************************/
00384 void APS_DataIndication(APS_DataInd_t* indData)
00385 {
00386   AppMessage_t *appMessage = (AppMessage_t *) indData->asdu;
00387 
00388   // Data received indication
00389   appOnLed(APP_RECEIVING_STATUS_LED);
00390 
00391   if ((false == messageIdRxValid) ||
00392       (messageIdRx != appMessage->messageId))
00393   {
00394     messageIdRxValid = true;
00395     messageIdRx = appMessage->messageId;
00396     // write received data to UART
00397     sendDataToUart(appMessage->data, indData->asduLength - 1);
00398   }
00399   appOffLed(APP_RECEIVING_STATUS_LED);
00400 }
00401 
00402 /**************************************************************************/
00408 static void initSerialInterface(void)
00409 {
00410   uartTxBusyFlag = false;
00411   
00412   appUartDescriptor.tty             = UART_CHANNEL;
00413   appUartDescriptor.mode            = ASYNC;
00414   appUartDescriptor.baudrate        = UART_BAUDRATE_38400;
00415   appUartDescriptor.dataLength      = UART_DATA8;
00416   appUartDescriptor.parity          = UART_PARITY_NONE;
00417   appUartDescriptor.stopbits        = UART_STOPBIT_1;
00418   appUartDescriptor.rxBuffer        = uartRxBuffer;
00419   appUartDescriptor.rxBufferLength  = sizeof(uartRxBuffer);
00420   appUartDescriptor.txBuffer        = NULL; // use callback mode
00421   appUartDescriptor.txBufferLength  = 0;
00422   appUartDescriptor.rxCallback      = uartBytesReceived;
00423   appUartDescriptor.txCallback      = uartWriteConf;
00424   appUartDescriptor.flowControl     = UART_FLOW_CONTROL_HARDWARE;
00425   OPEN_UART(&appUartDescriptor);
00426 }
00427 
00428 /**************************************************************************/
00435 static void sendDataToUart(uint8_t* data, uint8_t length)
00436 {
00437   if (APP_TMP_DATA_BUFFER_SIZE > tmpDataBufferActualLength + length)
00438   {
00439     memcpy(&tmpDataBuffer[tmpDataBufferActualLength], data, length);
00440     tmpDataBufferActualLength += length;
00441     // If there are no space in tmp Buffer for future messages receive
00442   }
00443    
00444   if (false == uartTxBusyFlag)
00445   {
00446     uartWriteConf();
00447   }
00448   
00449   // If there are no space in tmp Buffer for future messages receive
00450   if (APP_TMP_DATA_BUFFER_SIZE < tmpDataBufferActualLength + APP_MAX_DATA_SIZE) 
00451   {
00452     APS_StopEndpointIndication(APP_ENDPOINT); // Disable APS Data Indications
00453   }
00454 }
00455 
00456 /**************************************************************************/
00462 static void uartWriteConf(void)
00463 {
00464   int bytesWritten;
00465 
00466   if (0 < tmpDataBufferActualLength)  // data waiting to be written to UART
00467   {
00468     memcpy(uartTxBuffer, tmpDataBuffer, tmpDataBufferActualLength);
00469     bytesWritten = WRITE_UART(&appUartDescriptor, uartTxBuffer, tmpDataBufferActualLength);
00470     if (0 < bytesWritten)
00471     {
00472       tmpDataBufferActualLength -= bytesWritten;
00473       uartTxBusyFlag = true;
00474     }
00475   }
00476   else
00477   {
00478     uartTxBusyFlag = false;
00479     APS_ResumeEndpointIndication(APP_ENDPOINT); // Enable APS Data Indications
00480   }
00481 }
00482 
00483 /**************************************************************************/
00489 static void uartBytesReceived(uint8_t bytesToRead)
00490 {
00491   if (APP_NETWORK_JOINED_STATE == appState)
00492   {
00493     uartRxPending = bytesToRead;
00494 
00495     if (APP_DATA_TRANSMISSION_IDLE_STATE == appDataTransmissionState)
00496     {
00497       if (APP_MAX_DATA_SIZE < bytesToRead)
00498         bytesToRead = APP_MAX_DATA_SIZE;
00499 
00500       // Read data from UART 
00501       actualDataLength = (uint8_t) READ_UART(&appUartDescriptor, appMessageBuffer.message.data, bytesToRead);
00502 
00503       networkSendData(true);
00504 
00505       uartRxPending -= bytesToRead;
00506     }
00507   }
00508 }
00509 
00510 /**************************************************************************/
00516 static void buttonReleased(uint8_t aButton)
00517 {
00518   switch (aButton)
00519   {
00520     case BSP_KEY0:  // SW1 pressed
00521       if ((APP_NETWORK_JOINED_STATE == appState) &&
00522           (APP_DATA_TRANSMISSION_IDLE_STATE == appDataTransmissionState))
00523       {
00524         // Fill the buffer with some data and send it
00525         memset(&appMessageBuffer.message.data, 0xdd, APP_MAX_DATA_SIZE); 
00526         actualDataLength = APP_MAX_DATA_SIZE;
00527         networkSendData(true);
00528         break;
00529       }
00530       
00531     default:
00532       break;
00533   }
00534 }
00535 
00536 // eof peer2Peer.c

Generated on Tue Feb 17 16:44:56 2009 for BitCloud Stack Documentation by  doxygen 1.5.1-p1