Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
LsrModule.cpp
00001 /** 00002 * @file LsrModule.cpp 00003 * @author LS Research LLC 00004 * @version 1.0 00005 * 00006 * @section LICENSE 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License as 00010 * published by the Free Software Foundation; either version 2 of 00011 * the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, but 00014 * WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * General Public License for more details at 00017 * http://www.gnu.org/copyleft/gpl.html 00018 * 00019 * @section DESCRIPTION 00020 * 00021 * Implementation of contents in LsrModule.h. 00022 */ 00023 00024 /** 00025 * Modified by Mark Harris at SAIT.ca 00026 * Improved functionality for mbed 00027 */ 00028 00029 #include "LsrModule.h " 00030 #include "mbed.h" 00031 00032 /** 00033 * C function pointer typedef. 00034 * 00035 */ 00036 typedef void (*ptrRxMsgCallback)(void); 00037 00038 /** 00039 * Table used for subscribing callback functions for 00040 * received UART messages. 00041 */ 00042 ptrRxMsgCallback ptrRxMsgCallbackTable[69]; 00043 00044 00045 /** 00046 * This table contains the min and max length for each message type. The first array index 00047 * is the message type and the second index is the min value (0) or max value (1). 00048 */ 00049 const uint8_t cau8RxMsgLengthAndTypeTable[69][2] = { 00050 {12, 39}, // 0x81 - Query Firmware Version Response 00051 {0, 0}, // 0x82 - Invalid message type 00052 {0, 0}, // 0x83 - Invalid message type 00053 {0, 0}, // 0x84 - Invalid message type 00054 {0, 0}, // 0x85 - Invalid message type 00055 {0, 0}, // 0x86 - Invalid message type 00056 {0, 0}, // 0x87 - Invalid message type 00057 {0, 0}, // 0x88 - Invalid message type 00058 {0, 0}, // 0x89 - Invalid message type 00059 {0, 0}, // 0x8A - Invalid message type 00060 {0, 0}, // 0x8B - Invalid message type 00061 {5, 5}, // 0x8C - Set Security Transmit Frame Counter Ack 00062 {11, 11}, // 0x8D - Query Security Transmit Frame Counter Response 00063 {0, 0}, // 0x8E - Invalid message type 00064 {0, 0}, // 0x8F - Invalid message type 00065 {5, 5}, // 0x90 - Set Basic RF Settings Ack 00066 {39, 39}, // 0x91 - Query Basic RF Settings Response 00067 {5, 5}, // 0x92 - Save Settings to NV Memory Ack 00068 {5, 5}, // 0x93 - Reset Request Ack 00069 {9, 9}, // 0x94 - Query Supply Voltage Response 00070 {21, 21}, // 0x95 - Query Statistics Response 00071 {5, 5}, // 0x96 - Clear Statistics Ack 00072 {0, 0}, // 0x97 - Invalid message type 00073 {5, 5}, // 0x98 - Set Host Data Rate Ack 00074 {0, 0}, // 0x99 - Invalid message type 00075 {0, 0}, // 0x9A - Invalid message type 00076 {0, 0}, // 0x9B - Invalid message type 00077 {0, 0}, // 0x9C - Invalid message type 00078 {0, 0}, // 0x9D - Invalid message type 00079 {0, 0}, // 0x9E - Invalid message type 00080 {0, 0}, // 0x9F - Invalid message type 00081 {7, 7}, // 0xA0 - Send Simple Short Address RF Data Packet Ack 00082 {17, 115}, // 0xA1 - Received Simple Short Address RF Data Packet 00083 {7, 7}, // 0xA2 - Send Advanced Short Address RF Data Packet Ack 00084 {21, 119}, // 0xA3 - Received Advanced Short Address RF Data Packet 00085 {7, 7}, // 0xA4 - Send Simple Long Address RF Data Packet Ack 00086 {29, 127}, // 0xA5 - Received Simple Long Address RF Data Packet 00087 {7, 7}, // 0xA6 - Send Advanced Long Address RF Data Packet Ack 00088 {33, 131}, // 0xA7 - Received Advanced Long Address RF Data Packet 00089 {0, 0}, // 0xA8 - Invalid message type 00090 {0, 0}, // 0xA9 - Invalid message type 00091 {0, 0}, // 0xAA - Invalid message type 00092 {0, 0}, // 0xAB - Invalid message type 00093 {0, 0}, // 0xAC - Invalid message type 00094 {0, 0}, // 0xAD - Invalid message type 00095 {13, 131}, // 0xAE - Received Promiscuous Mode Packet 00096 {0, 0}, // 0xAF - Invalid message type 00097 {0, 0}, // 0xB0 - Invalid message type 00098 {0, 0}, // 0xB1 - Invalid message type 00099 {0, 0}, // 0xB2 - Invalid message type 00100 {0, 0}, // 0xB3 - Invalid message type 00101 {0, 0}, // 0xB4 - Invalid message type 00102 {0, 0}, // 0xB5 - Invalid message type 00103 {0, 0}, // 0xB6 - Invalid message type 00104 {0, 0}, // 0xB7 - Invalid message type 00105 {0, 0}, // 0xB8 - Invalid message type 00106 {0, 0}, // 0xB9 - Invalid message type 00107 {0, 0}, // 0xBA - Invalid message type 00108 {0, 0}, // 0xBB - Invalid message type 00109 {0, 0}, // 0xBC - Invalid message type 00110 {0, 0}, // 0xBD - Invalid message type 00111 {0, 0}, // 0xBE - Invalid message type 00112 {0, 0}, // 0xBF - Invalid message type 00113 {0, 0}, // 0xC0 - Invalid message type 00114 {0, 0}, // 0xC1 - Invalid message type 00115 {0, 0}, // 0xC2 - Invalid message type 00116 {0 ,0}, // 0xC3 - Invalid message type 00117 {5, 5}, // 0xC4 - Channel Energy Scan Ack 00118 {23, 23} // 0xC5 - Channel Energy Scan Results 00119 }; 00120 00121 /** 00122 * Construnctor. 00123 * 00124 * Example: 00125 * 00126 * LsrModule(false, 19200); 00127 * 00128 */ 00129 LsrModule::LsrModule(PinName tx, PinName rx, int baudRate) : Serial(tx, rx) 00130 { 00131 baud(baudRate); 00132 00133 ptrHostState = &LsrModule::HostRxWaitForMsgStartByteState; 00134 00135 //attach(this, &LsrModule::RunHostRxStateMachine); 00136 } /*** End LsrModule ***/ 00137 00138 00139 /** 00140 * Destructor. Called automatically, de-allocates resources. 00141 * 00142 */ 00143 LsrModule::~LsrModule(void) 00144 { 00145 pu8RxBuffer = NULL; 00146 ptrHostState = NULL; 00147 ptrHostProcessCallbackState = NULL; 00148 00149 for (u8ForLoopCounter = 0; u8ForLoopCounter < sizeof(ptrRxMsgCallbackTable); u8ForLoopCounter++) 00150 { 00151 ptrRxMsgCallbackTable[u8ForLoopCounter] = NULL; 00152 } 00153 } /*** End ~LsrModule ***/ 00154 00155 00156 /** 00157 * Creates a callback for specific received UART message. Call this function from your main application in 00158 * this manner: "SubscribeRxMsgCallback(0xA1, &simpleShortAddrCallback)", where simpleShortAddrCallback is 00159 * defined like this: void simpleShortAddrCallback(void) in your main application. 00160 * IMPORTANT: All user defined callback methods must return void and take no parameters (void). 00161 * 00162 * @return True: Subscribed callback. False: Did not subscribe callback. 00163 * 00164 */ 00165 bool LsrModule::SubscribeRxMsgCallback(uint8_t u8RxMsgType ///< The received message for which you want the callback to execute. 00166 , void (*callback)(void) ///< C function pointer to the specified callback function. 00167 ) 00168 { 00169 if ((u8RxMsgType > LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE) && (u8RxMsgType < LSR_MODULE_MAX_SERIAL_RX_MSG_TYPE)) 00170 { 00171 ptrRxMsgCallbackTable[u8RxMsgType- LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE] = callback; 00172 return true; 00173 } 00174 00175 return false; 00176 } /*** End SubscribeRxMsgCallback ***/ 00177 00178 00179 /** 00180 * Removes a callback for specific received UART message. See SubscribeRxMsgCallback's description for 00181 * more information. 00182 * 00183 * @return True: Unsubscribed callback. False: Did not unsubscribed callback. 00184 * 00185 */ 00186 bool LsrModule::UnsubscribeRxMsgCallback(uint8_t u8RxMsgType ///< The received message for which you want the callback to be removed. 00187 ) 00188 { 00189 if ((u8RxMsgType > LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE) && (u8RxMsgType < LSR_MODULE_MAX_SERIAL_RX_MSG_TYPE)) 00190 { 00191 ptrRxMsgCallbackTable[u8RxMsgType - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE] = NULL; 00192 return true; 00193 } 00194 00195 return false; 00196 } /*** End UnsubscribeRxMsgCallback ***/ 00197 00198 00199 /** 00200 * Executes host RX state machine. This function must be executed continually from the loop function in your main 00201 * application. 00202 * 00203 */ 00204 void LsrModule::RunHostRxStateMachine(void) 00205 { 00206 (this->*ptrHostState)(); 00207 } /*** End RunHostRxStateMachine ***/ 00208 00209 00210 /** 00211 * Flushes appropriate serial port. 00212 * 00213 */ 00214 void LsrModule::SerialFlush(void) 00215 { 00216 // Serial.flush(); 00217 // i think this is meant to clean out the rx buffer 00218 /*** End SerialFlush ***/ 00219 } 00220 00221 /** 00222 * Adds header to the UART transmit buffer. 00223 * 00224 */ 00225 void LsrModule::AddSerialMsgHeader(uint8_t u8MsgType, uint8_t u8MsgLength) 00226 { 00227 SerialFlush(); 00228 u8UartTxBufferIndex = LSR_MODULE_MSG_START_BYTE_INDEX; 00229 au8UartTxBuffer[u8UartTxBufferIndex++] = LSR_MODULE_SERIAL_MSG_START_BYTE; 00230 au8UartTxBuffer[u8UartTxBufferIndex++] = u8MsgLength; 00231 au8UartTxBuffer[u8UartTxBufferIndex++] = u8MsgType; 00232 u8TxMsgChecksum = (LSR_MODULE_SERIAL_MSG_START_BYTE + u8MsgLength + u8MsgType); 00233 } /*** End LsrModuleAddSerialMsgHeader ***/ 00234 00235 00236 /** 00237 * Adds data bytes to the UART transmit buffer. 00238 * 00239 */ 00240 void LsrModule::AddSerialByteToMsgBuffer(uint8_t u8Data ///< The data to add. 00241 ) 00242 { 00243 au8UartTxBuffer[u8UartTxBufferIndex++] = u8Data; 00244 u8TxMsgChecksum += u8Data; 00245 } /*** End LsrModuleAddSerialByteToMsgBuffer ***/ 00246 00247 00248 /** 00249 * Adds message trailer to the UART transmit buffer. 00250 * 00251 */ 00252 void LsrModule::AddSerialMsgTrailer(void) 00253 { 00254 au8UartTxBuffer[u8UartTxBufferIndex++] = u8TxMsgChecksum; 00255 au8UartTxBuffer[u8UartTxBufferIndex] = LSR_MODULE_SERIAL_MSG_END_BYTE; 00256 WriteSerialMsg(); 00257 } /*** End AddSerialMsgTrailer ***/ 00258 00259 00260 /** 00261 * Writes the UART transmit buffer using the appropriate serial port. 00262 * 00263 */ 00264 void LsrModule::WriteSerialMsg(void) 00265 { 00266 //write (const uint8_t *buffer, int length, const event_callback_t &callback, int event=SERIAL_EVENT_TX_COMPLETE) 00267 write(au8UartTxBuffer, au8UartTxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX]); 00268 00269 } /*** End WriteSerialMsg ***/ 00270 00271 00272 /** 00273 * Sends message type 0x01 (Query Version) to the module via UART communication. This will spark 00274 * a response message from the module to the Arduino of type 0x81. Subscribing to 0x81 in 00275 * your main application will allow you to parse the response data. See the description for 00276 * SubscribeRxMsgCallback for more information. 00277 * 00278 */ 00279 void LsrModule::QueryVersionMsg(void) 00280 { 00281 AddSerialMsgHeader(LSR_MODULE_QUERY_VERSION_MSG_TYPE, 5); 00282 AddSerialMsgTrailer(); 00283 } /*** End QueryVersionMsg ***/ 00284 00285 00286 /** 00287 * Sends message type 0x0C (Sets Security Transmit Frame Counter) to the module via UART communication. 00288 * This frame counter is used with RF messages transmitted with security to ensure sequential freshness. 00289 * This sets the starting frame count and is automatically incremented on every secured packet sent. 00290 * This will spark an ACK message from the module to the Arduino of type 0x8C. Subscribing to 0x8C in 00291 * your main application will allow you to parse the response data. See the description for 00292 * SubscribeRxMsgCallback for more information. 00293 * 00294 * Example: 00295 * 00296 * uint32_t u32FrameCounter = 0xAEDFEDFA; 00297 * SetSecurityTransmitFrameCounterMsg(&u32FrameCounter); 00298 * 00299 */ 00300 void LsrModule::SetSecurityTransmitFrameCounterMsg(uint32_t* pu32FrameCounter ///< Pointer to 4 byte frame counter (LSB to MSB). 00301 ) 00302 { 00303 DWordu_t dwuFrameCounter; 00304 00305 dwuFrameCounter.u32 = *pu32FrameCounter; 00306 00307 AddSerialMsgHeader(LSR_MODULE_SET_SECURITY_TX_FRAME_COUNTER_MSG_TYPE, 11); 00308 AddSerialByteToMsgBuffer(dwuFrameCounter.dws.lb); 00309 AddSerialByteToMsgBuffer(dwuFrameCounter.dws.mlb); 00310 AddSerialByteToMsgBuffer(dwuFrameCounter.dws.mhb); 00311 AddSerialByteToMsgBuffer(dwuFrameCounter.dws.hb); 00312 AddSerialByteToMsgBuffer(0x00); // Add filler byte. 00313 AddSerialByteToMsgBuffer(0x00); // Add filler byte. 00314 AddSerialMsgTrailer(); 00315 } /*** End SetSecurityTransmitFrameCounterMsg ***/ 00316 00317 00318 /** 00319 * Sends message type 0x0D (Query Security Transmit Frame Counter) to the module via UART communication. This 00320 * will spark a response message from the module to the Arduino of type 0x8D. Subscribing to 0x8D in your main 00321 * application will allow you to parse the response data. See the description for SubscribeRxMsgCallback 00322 * for more information. 00323 * 00324 */ 00325 void LsrModule::QuerySecurityTransmitFrameCounterMsg(void) 00326 { 00327 AddSerialMsgHeader(LSR_MODULE_QUERY_SECURITY_TX_FRAME_COUNTER_MSG_TYPE, 5); 00328 AddSerialMsgTrailer(); 00329 } /*** End QuerySecurityTransmitFrameCounterMsg ***/ 00330 00331 00332 /** 00333 * Sends message type 0x10 (Set Basic RF Settings) to the module via UART communication. 00334 * This will spark an ACK message from the module to the Arduino of type 0x90. Subscribing to 0x90 in 00335 * your main application will allow you to parse the response data. See the description for 00336 * SubscribeRxMsgCallback for more information. 00337 * 00338 */ 00339 void LsrModule::SetBasicRfSettingsMsg(uint16_t u16PanId ///< Personal Area Network (PAN) ID assigned to module. 00340 , uint16_t u16AddrShort ///< 2 byte short address assigned to module. 00341 , uint8_t* pu8AddrLong ///< Pointer to 8 byte long address assigned to module. Do not assign a zero, even if using short addressing. 00342 , uint8_t u8RfChannel ///< RF channel assigned to module. 00343 , uint8_t u8TxPowerLevel ///< Transmit power assigned to module. 00344 , uint8_t u8ReceiverConfig ///< 1 byte bitmask of receiver options. 00345 , uint8_t* pu8SecurityKey ///< Pointer to 32 byte security key assigned to module. 00346 ) 00347 { 00348 Wordu_t wuPanId; 00349 Wordu_t wuShortAddr; 00350 00351 wuPanId.u16 = u16PanId; 00352 wuShortAddr.u16 = u16AddrShort; 00353 00354 if ((u8RfChannel >= LSR_MODULE_RF_CHANNEL_MIN) && (u8RfChannel <= LSR_MODULE_RF_CHANNEL_MAX) && 00355 (u8TxPowerLevel <= LSR_MODULE_TX_POWER_LEVEL_MAX) && 00356 (u8ReceiverConfig <= LSR_MODULE_RX_CONFIG_MAX)) 00357 { 00358 AddSerialMsgHeader(LSR_MODULE_SET_BASIC_RF_SETTINGS_MSG_TYPE, 39); 00359 AddSerialByteToMsgBuffer(wuPanId.ws.lb); 00360 AddSerialByteToMsgBuffer(wuPanId.ws.hb); 00361 AddSerialByteToMsgBuffer(wuShortAddr.ws.lb); 00362 AddSerialByteToMsgBuffer(wuShortAddr.ws.hb); 00363 00364 for (u8ForLoopCounter = 0; u8ForLoopCounter < 8; u8ForLoopCounter++) 00365 { 00366 AddSerialByteToMsgBuffer(*pu8AddrLong); 00367 pu8AddrLong++; 00368 } 00369 00370 AddSerialByteToMsgBuffer(u8RfChannel); 00371 AddSerialByteToMsgBuffer(u8TxPowerLevel); 00372 AddSerialByteToMsgBuffer(u8ReceiverConfig); 00373 00374 AddSerialByteToMsgBuffer(0x00); // Add filler byte. 00375 AddSerialByteToMsgBuffer(0x00); // Add filler byte. 00376 AddSerialByteToMsgBuffer(0x00); // Add filler byte. 00377 00378 for (u8ForLoopCounter = 0; u8ForLoopCounter < 16; u8ForLoopCounter++) 00379 { 00380 AddSerialByteToMsgBuffer(*pu8SecurityKey); 00381 pu8SecurityKey++; 00382 } 00383 00384 AddSerialMsgTrailer(); 00385 } 00386 } /*** End SetBasicRfSettingsMsg ***/ 00387 00388 00389 /** 00390 * Sends message type 0x11 (Query Basic RF Settings) to the module via UART communication. This will spark 00391 * a response message from the module to the Arduino of type 0x91. Subscribing to 0x91 in your main 00392 * application will allow you to parse the response data. See the description for SubscribeRxMsgCallback 00393 * for more information. 00394 * 00395 */ 00396 void LsrModule::QueryBasicRfSettingsMsg(void) 00397 { 00398 AddSerialMsgHeader(LSR_MODULE_QUERY_BASIC_RF_SETTINGS_MSG_TYPE, 5); 00399 AddSerialMsgTrailer(); 00400 } /*** End QueryBasicRfSettingsMsg ***/ 00401 00402 00403 /** 00404 * Sends message type 0x12 (Save Settings to non-volatile Memory) to the module via UART communication. Calling 00405 * this command will make your module retain all basic configuration settings on boot up. This will spark an ACK 00406 * message from the module to the Arduino of type 0x92. Subscribing to 0x92 in your main application will allow 00407 * you to parse the response data. See the description for SubscribeRxMsgCallback for more information. 00408 * 00409 */ 00410 void LsrModule::SaveSettingsToNVMemoryMsg(void) 00411 { 00412 AddSerialMsgHeader(LSR_MODULE_SAVE_SETTINGS_TO_NV_MEMORY_MSG_TYPE, 5); 00413 AddSerialMsgTrailer(); 00414 } /*** End SaveSettingsToNVMemoryMsg ***/ 00415 00416 00417 /** 00418 * Sends message type 0x13 (Reset Request) to the module via UART communication. This will make your module perform 00419 * a restart. This will spark an ACK message from the module to the Arduino of type 0x93. Subscribing to 0x93 in 00420 * your main application will allow you to parse the response data. See the description for SubscribeRxMsgCallback 00421 * for more information. 00422 * 00423 */ 00424 void LsrModule::ResetRequestMsg(void) 00425 { 00426 AddSerialMsgHeader(LSR_MODULE_RESET_REQUEST_MSG_TYPE, 5); 00427 AddSerialMsgTrailer(); 00428 } /*** End ResetRequestMsg ***/ 00429 00430 00431 /** 00432 * Sends message type 0x14 (Query Supply Voltage) to the module via UART communication. This will spark a 00433 * response message from the module to the Arduino of type 0x94. Subscribing to 0x94 in your main application 00434 * will allow you to parse the response data. See the description for SubscribeRxMsgCallback for more information. 00435 * 00436 */ 00437 void LsrModule::QuerySupplyVoltageMsg(void) 00438 { 00439 AddSerialMsgHeader(LSR_MODULE_QUERY_SUPPLY_VOLTAGE_MSG_TYPE, 5); 00440 AddSerialMsgTrailer(); 00441 } /*** End QuerySupplyVoltageMsg ***/ 00442 00443 00444 /** 00445 * Sends message type 0x15 (Query Statistics) to the module via UART communication. Statistics include packets sent, 00446 * acks received, packets received and broadcast packets received. This will spark a response message from the module 00447 * to the Arduino of type 0x95. Subscribing to 0x94 in your main application will allow you to parse the response 00448 * data. See the description for SubscribeRxMsgCallback for more information. 00449 * 00450 */ 00451 void LsrModule::QueryStatisticsMsg(void) 00452 { 00453 AddSerialMsgHeader(LSR_MODULE_QUERY_STATISTICS_MSG_TYPE, 5); 00454 AddSerialMsgTrailer(); 00455 } /*** End QueryStatisticsMsg ***/ 00456 00457 00458 /** 00459 * Sends message type 0x16 (Clear Statistics) to the module via UART communication. This will spark an ACK message 00460 * from the module to the Arduino of type 0x96. Subscribing to 0x96 in your main application will allow you to 00461 * Parse the response data. See the description for SubscribeRxMsgCallback for more information. 00462 * 00463 */ 00464 void LsrModule::ClearStatisticsMsg(void) 00465 { 00466 AddSerialMsgHeader(LSR_MODULE_CLEAR_STATISTICS_MSG_TYPE, 5); 00467 AddSerialMsgTrailer(); 00468 } /*** End ClearStatisticsMsg ***/ 00469 00470 00471 /** 00472 * Sends message type 0x18 (Set Host Data Rate) to the module via UART communication. This will spark an ACK message 00473 * from the module to the Arduino of type 0x98. Subscribing to 0x98 in your main application will allow you to parse 00474 * the response data. See the description for SubscribeRxMsgCallback for more information. 00475 * 00476 */ 00477 void LsrModule::SetHostDataRateMsg(uint8_t u8HostDataRate ///< Data rate for module to use when communicating via UART: 00478 ///< 0 = 1,200 bits/s 00479 ///< 1 = 2,400 bits/s 00480 ///< 2 = 4,800 bits/s 00481 ///< 3 = 9,600 bits/s 00482 ///< 4 = 19,200 bits/s 00483 ///< 5 = 38,400 bits/s 00484 ///< 6 = 57,600 bits/s 00485 ///< 7 = 115,200 bits/s 00486 ) 00487 { 00488 if (u8HostDataRate <= LSR_MODULE_HOST_DATA_RATE_MAX) 00489 { 00490 AddSerialMsgHeader(LSR_MODULE_SET_HOST_DATA_RATE_MSG_TYPE, 6); 00491 AddSerialByteToMsgBuffer(u8HostDataRate); 00492 AddSerialMsgTrailer(); 00493 00494 // 2.4 ms for the data rate change packet to be transmitted. 00495 wait_ms(3); 00496 00497 switch (u8HostDataRate) 00498 { 00499 case LSR_MODULE_HOST_DATA_RATE_1200: 00500 baud(1200); 00501 break; 00502 case LSR_MODULE_HOST_DATA_RATE_2400: 00503 baud(2400); 00504 break; 00505 case LSR_MODULE_HOST_DATA_RATE_4800: 00506 baud(4800); 00507 break; 00508 case LSR_MODULE_HOST_DATA_RATE_9600: 00509 baud(9600); 00510 break; 00511 case LSR_MODULE_HOST_DATA_RATE_19200: 00512 baud(19200); 00513 break; 00514 case LSR_MODULE_HOST_DATA_RATE_38400: 00515 baud(38400); 00516 break; 00517 case LSR_MODULE_HOST_DATA_RATE_57600: 00518 baud(57600); 00519 break; 00520 case LSR_MODULE_HOST_DATA_RATE_115200: 00521 baud(115200); 00522 break; 00523 case LSR_MODULE_HOST_DATA_RATE_230400: 00524 baud(230400); 00525 break; 00526 case LSR_MODULE_HOST_DATA_RATE_460800: 00527 baud(460800); 00528 break; 00529 case LSR_MODULE_HOST_DATA_RATE_921600: 00530 baud(921600); 00531 break; 00532 } 00533 } 00534 } /*** End SetHostDataRateMsg ***/ 00535 00536 00537 /** 00538 * Sends message type 0x19 (Set RF Data Rate) to the module via UART communication. This will spark an ACK message 00539 * from the module to the Arduino of type 0x98. Subscribing to 0x98 in your main application will allow you to parse 00540 * the response data. See the description for SubscribeRxMsgCallback for more information. 00541 * 00542 */ 00543 void LsrModule::SetRfDataRateMsg(uint8_t u8RfDataRate ///< Data rate for module to use when communicating via radio: 00544 ///< 0 = 1,200 bits/s 00545 ///< 1 = 2,400 bits/s 00546 ///< 2 = 4,800 bits/s 00547 ///< 3 = 9,600 bits/s 00548 ///< 4 = 19,200 bits/s 00549 ///< 5 = 38,400 bits/s 00550 ///< 6 = 57,600 bits/s 00551 ///< 7 = 115,200 bits/s 00552 ) 00553 { 00554 if (u8RfDataRate <= LSR_MODULE_RF_DATA_RATE_MAX) 00555 { 00556 AddSerialMsgHeader(LSR_MODULE_SET_RF_DATA_RATE_MSG_TYPE, 6); 00557 AddSerialByteToMsgBuffer(u8RfDataRate); 00558 AddSerialMsgTrailer(); 00559 } 00560 } /*** End SetRfDataRateMsg ***/ 00561 00562 /** 00563 * Sends message type 0x20 (Send Simple Short Address RF Data Packet) to the module via UART communication. 00564 * This will spark an ACK message from the module to the Arduino of type 0xA0. Subscribing to 0xA0 in 00565 * your main application will allow you to parse the response data. See the description for SubscribeRxMsgCallback 00566 * for more information. 00567 * 00568 * Example: 00569 * 00570 * uint8_t u8Data[5] = {4, 7, 3, 5, 8}; 00571 * uint8_t u8PacketID; 00572 * 00573 * SendSimpleShortAddrRfDataPacketMsg(&u8Data, sizeof(u8Data, 213, 0, packetID++); 00574 * 00575 */ 00576 void LsrModule::SendSimpleShortAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent. 00577 , uint8_t u8DataLength ///< Length of data being sent. 00578 , uint16_t u16DestAddress ///< 2 byte destination address. 00579 , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options. 00580 , uint8_t u8PacketId ///< ID assigned to packet. 00581 ) 00582 { 00583 if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) && 00584 ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_SIMPLE_SHORT_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) || 00585 (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_SIMPLE_SHORT_RF_DATA_LENGTH)))) 00586 { 00587 AddSerialMsgHeader(LSR_MODULE_SEND_SIMPLE_SHORT_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 9)); 00588 00589 AddSerialByteToMsgBuffer(u8TxOptions); 00590 AddSerialByteToMsgBuffer(u16DestAddress % 256); 00591 AddSerialByteToMsgBuffer(u16DestAddress >> 8); 00592 AddSerialByteToMsgBuffer(u8PacketId); 00593 00594 while (u8DataLength != 0) 00595 { 00596 AddSerialByteToMsgBuffer(*pu8Data); 00597 pu8Data++; 00598 u8DataLength--; 00599 } 00600 00601 AddSerialMsgTrailer(); 00602 } 00603 } /*** End SendSimpleShortAddrRfDataPacketMsg ***/ 00604 00605 00606 /** 00607 * Sends message type 0x22 (Send Advanced Short Address RF Data Packet) to the module via UART communication. 00608 * This will spark an ACK message from the module to the Arduino of type 0xA2. Subscribing to 0xA2 in 00609 * your main application will allow you to parse the response data. See the description for SubscribeRxMsgCallback 00610 * for more information. 00611 * 00612 * Example: 00613 * 00614 * uint8_t u8Data[5] = {4, 7, 3, 5, 8}; 00615 * uint8_t u8PacketID; 00616 * 00617 * SendAdvancedShortAddrRfDataPacketMsg(&u8Data, sizeof(u8Data, 1111, 213, 0, packetID++); 00618 * 00619 */ 00620 void LsrModule::SendAdvancedShortAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent. 00621 , uint8_t u8DataLength ///< Length of data being sent. 00622 , uint16_t u16DestPanId ///< 2 byte Personal Area Network (PAN) ID. 00623 , uint16_t u16DestAddress ///< 2 byte destination address. 00624 , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options. 00625 , uint8_t u8PacketId ///< ID assigned to packet. 00626 ) 00627 { 00628 if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) && 00629 ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_ADVANCED_SHORT_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) || 00630 (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_ADVANCED_SHORT_RF_DATA_LENGTH)))) 00631 { 00632 AddSerialMsgHeader(LSR_MODULE_SEND_ADVANCED_SHORT_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 11)); 00633 00634 AddSerialByteToMsgBuffer(u8TxOptions); 00635 AddSerialByteToMsgBuffer(u16DestPanId % 256); 00636 AddSerialByteToMsgBuffer(u16DestPanId >> 8); 00637 AddSerialByteToMsgBuffer(u16DestAddress % 256); 00638 AddSerialByteToMsgBuffer(u16DestAddress >> 8); 00639 AddSerialByteToMsgBuffer(u8PacketId); 00640 00641 while (u8DataLength != 0) 00642 { 00643 AddSerialByteToMsgBuffer(*pu8Data); 00644 pu8Data++; 00645 u8DataLength--; 00646 } 00647 00648 AddSerialMsgTrailer(); 00649 } 00650 } /*** End SendAdvancedShortAddrRfDataPacketMsg ***/ 00651 00652 00653 /** 00654 * Sends message type 0x24 (Send Simple Long Address RF Data Packet) to the module via UART communication. 00655 * This will spark an ACK message from the module to the Arduino of type 0xA4. Subscribing to 0xA4 in 00656 * your main application will allow you to parse the response data. See the description for SubscribeRxMsgCallback 00657 * for more information. 00658 * 00659 * Example: 00660 * 00661 * uint8_t u8Data[5] = {4, 7, 3, 5, 8}; 00662 * uint8_t u8DestAddress[8] = {2, 3, 6, 5, 2, 3, 6, 5}; 00663 * uint8_t u8PacketID; 00664 * 00665 * SendSimpleLongAddrRfDataPacketMsg(&u8Data, sizeof(u8Data), &u8DestAddress, 0, packetID++); 00666 * 00667 */ 00668 void LsrModule::SendSimpleLongAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent. 00669 , uint8_t u8DataLength ///< Length of data being sent. 00670 , uint8_t* pu8DestAddress ///< Pointer to 8 byte destination address. 00671 , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options. 00672 , uint8_t u8PacketId ///< ID assigned to packet. 00673 ) 00674 { 00675 if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) && 00676 ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_SIMPLE_LONG_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) || 00677 (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_SIMPLE_LONG_RF_DATA_LENGTH)))) 00678 { 00679 AddSerialMsgHeader(LSR_MODULE_SEND_SIMPLE_LONG_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 15)); 00680 00681 AddSerialByteToMsgBuffer(u8TxOptions); 00682 00683 for (u8ForLoopCounter = 0; u8ForLoopCounter < 8; u8ForLoopCounter++) 00684 { 00685 AddSerialByteToMsgBuffer(*pu8DestAddress); 00686 pu8DestAddress++; 00687 } 00688 00689 AddSerialByteToMsgBuffer(u8PacketId); 00690 00691 while (u8DataLength != 0) 00692 { 00693 AddSerialByteToMsgBuffer(*pu8Data); 00694 pu8Data++; 00695 u8DataLength--; 00696 } 00697 00698 AddSerialMsgTrailer(); 00699 } 00700 } /*** End SendSimpleLongAddrRfDataPacketMsg ***/ 00701 00702 00703 /** 00704 * Sends message type 0x26 (Send Advanced Long Address RF Data Packet) to the module via UART communication. 00705 * This will spark an ACK message from the module to the Arduino of type 0xA6. Subscribing to 0xA6 in 00706 * your main application will allow you to parse the response data. See the description for SubscribeRxMsgCallback 00707 * for more information. 00708 * 00709 * Example: 00710 * 00711 * uint8_t u8Data[5] = {4, 7, 3, 5, 8}; 00712 * uint8_t u8DestAddress[8] = {2, 3, 6, 5, 2, 3, 6, 5}; 00713 * uint8_t u8PacketID; 00714 * 00715 * SendAdvancedLongAddrRfDataPacketMsg(&u8Data, sizeof(u8Data), 1111, &u8DestAddress, 0, packetID++); 00716 * 00717 */ 00718 void LsrModule::SendAdvancedLongAddrRfDataPacketMsg(uint8_t* pu8Data ///< Pointer to data being sent. 00719 , uint8_t u8DataLength ///< Length of data being sent. 00720 , uint16_t u16DestPanId ///< 2 byte Personal Area Network (PAN) ID. 00721 , uint8_t* pu8DestAddress ///< Pointer to 8 byte destination address. 00722 , uint8_t u8TxOptions ///< 1 byte bit mask of transmit options. 00723 , uint8_t u8PacketId ///< ID assigned to packet. 00724 ) 00725 { 00726 if ((u8TxOptions <= LSR_MODULE_TX_OPTIONS_MAX) && 00727 ((((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) != 0) && (u8DataLength <= (LSR_MODULE_ADVANCED_LONG_RF_DATA_LENGTH - LSR_MODULE_SECURITY_OVERHEAD))) || 00728 (((u8TxOptions & LSR_MODULE_TX_OPTIONS_USE_SECURITY_BITMASK) == 0) && (u8DataLength <= LSR_MODULE_ADVANCED_LONG_RF_DATA_LENGTH)))) 00729 { 00730 AddSerialMsgHeader(LSR_MODULE_SEND_ADVANCED_LONG_RF_DATA_PACKET_MSG_TYPE, (u8DataLength + 17)); 00731 00732 AddSerialByteToMsgBuffer(u8TxOptions); 00733 AddSerialByteToMsgBuffer(u16DestPanId % 256); 00734 AddSerialByteToMsgBuffer(u16DestPanId >> 8); 00735 00736 for (u8ForLoopCounter = 0; u8ForLoopCounter < 8; u8ForLoopCounter++) 00737 { 00738 AddSerialByteToMsgBuffer(*pu8DestAddress); 00739 pu8DestAddress++; 00740 } 00741 00742 AddSerialByteToMsgBuffer(u8PacketId); 00743 00744 while (u8DataLength != 0) 00745 { 00746 AddSerialByteToMsgBuffer(*pu8Data); 00747 pu8Data++; 00748 u8DataLength--; 00749 } 00750 00751 AddSerialMsgTrailer(); 00752 } 00753 } /*** End SendAdvancedLongAddrRfDataPacketMsg ***/ 00754 00755 00756 /** 00757 * Sends message type 0x44 (Channel Energy Scan) to the module via UART communication. This will spark a response message from the module 00758 * to the host of type 0xC5. Subscribing to 0xC5 in your main application will allow you to parse the response 00759 * data. See the description for SubscribeRxMsgCallback for more information. 00760 * 00761 * Example (Channel 5 for SiFLEX02, Channel 15 for ProFLEX01): 00762 * 00763 * ChannelEnergyScanMsg(11110111, 7); 00764 * 00765 */ 00766 void LsrModule::ChannelEnergyScanMsg(uint16_t u16ChannelMask ///< Two byte bitmask (LSB to MSB) of the RF channels to perfom an enrgy scan on. 00767 , uint8_t u8ScanDuration ///< Duration to scan for: 00768 ///< 0 = 61.4 mSec 00769 ///< 1 = 92.2 mSec 00770 ///< 2 = 154 mSec 00771 ///< 3 = 276 mSec 00772 ///< 4 = 522 mSec 00773 ///< 5 = 1.01 Sec 00774 ///< 6 = 2.00 Sec 00775 ///< 7 = 3.96 Sec 00776 ///< 8 = 7.90 Sec 00777 ///< 9 = 15.8 Sec 00778 ///< 10 = 31.5 Sec 00779 ///< 11 = 62.9 Sec 00780 ///< 12 = 126 Sec 00781 ///< 13 = 252 Sec 00782 ///< 14 = 503 Sec 00783 00784 ) 00785 { 00786 Wordu_t wuChannelMask; 00787 00788 wuChannelMask.u16 = u16ChannelMask; 00789 00790 if (u8ScanDuration <= LSR_MODULE_SCAN_DURATION_MAX) 00791 { 00792 AddSerialMsgHeader(LSR_MODULE_CHANNEL_ENERGY_SCAN_MSG_TYPE, 8); 00793 AddSerialByteToMsgBuffer(wuChannelMask.ws.lb); 00794 AddSerialByteToMsgBuffer(wuChannelMask.ws.hb); 00795 AddSerialByteToMsgBuffer(u8ScanDuration); 00796 AddSerialMsgTrailer(); 00797 } 00798 } /*** End ChannelEnergyScanMsg ***/ 00799 00800 /** 00801 * Sends message type 0x51 (Query Host Interface Configuration) to the module via UART communication. This will spark a 00802 * response message from the module to the host of type 0xD1. Subscribing to 0xD1 in your main application 00803 * will allow you to parse the response data. See the description for SubscribeRxMsgCallback for more information. 00804 * 00805 */ 00806 void LsrModule::QueryHostInterfaceConfiguration(void) 00807 { 00808 AddSerialMsgHeader(LSR_MODULE_QUERY_HOST_INTERFACE_CONFIGURATION, 5); 00809 AddSerialMsgTrailer(); 00810 } /*** End QuerySupplyVoltageMsg ***/ 00811 00812 00813 00814 /** 00815 * Verifies msg type and length. 00816 * @return True: Valid msg length and type. False: Invalid msg length or type. 00817 * 00818 */ 00819 bool LsrModule::ValidMsgLengthAndType(uint8_t u8MsgType ///< Received UART message type. 00820 , uint8_t u8MsgLength ///< Received UART message length. 00821 ) 00822 { 00823 if ((u8MsgLength >= cau8RxMsgLengthAndTypeTable[u8MsgType - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE][0]) && 00824 (u8MsgLength <= cau8RxMsgLengthAndTypeTable[u8MsgType - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE][1])) 00825 { 00826 return true; 00827 } 00828 return false; 00829 } /*** End ValidMsgLengthAndType ***/ 00830 00831 00832 /** 00833 * Verifies message checksum. 00834 * @return True: Valid checksum. False: Invalid checksum. 00835 * 00836 */ 00837 bool LsrModule::ValidRxChecksum(uint8_t* pu8MsgBuffer ///< Pointer to received UART buffer. 00838 , uint8_t u8MsgLength ///< Received UART message length. 00839 ) 00840 { 00841 uint8_t u8Checksum = 0; 00842 00843 for (u8ForLoopCounter = 0; u8ForLoopCounter < (u8MsgLength - 2); u8ForLoopCounter++) 00844 { 00845 u8Checksum += au8UartRxBuffer[u8ForLoopCounter]; 00846 } 00847 00848 if (au8UartRxBuffer[u8MsgLength-2] == u8Checksum) 00849 { 00850 return true; 00851 } 00852 00853 return false; 00854 } /*** End ValidRxChecksum ***/ 00855 00856 00857 /** 00858 * Calls appropriate callback function for received message. 00859 * 00860 */ 00861 void LsrModule::HostProcessCallbackMsgStart(uint8_t* pu8MsgBuffer ///< Pointer to received message. 00862 , uint8_t u8Length ///< Length of received message. 00863 ) 00864 { 00865 if ((ptrRxMsgCallbackTable[(*(pu8MsgBuffer + LSR_MODULE_MSG_TYPE_BYTE_INDEX)) - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE]) != NULL) 00866 { 00867 ptrRxMsgCallbackTable[(*(pu8MsgBuffer + LSR_MODULE_MSG_TYPE_BYTE_INDEX)) - LSR_MODULE_MIN_SERIAL_RX_MSG_TYPE](); 00868 } 00869 } /*** End HostProcessCallbackMsgStart ***/ 00870 00871 00872 /** 00873 * Determines if appropriate serial port is available. 00874 * @return True: Serial is available. False: Serial is unavailable. 00875 * 00876 */ 00877 bool LsrModule::SerialAvailable(void) 00878 { 00879 if (readable()) 00880 { 00881 return true; 00882 } 00883 00884 return false; 00885 } /*** End SerialAvailable ***/ 00886 00887 00888 /** 00889 * Reads appropriate serial port. 00890 * @return Byte read. 00891 * 00892 */ 00893 uint8_t LsrModule::SerialRead(void) 00894 { 00895 return getc(); 00896 00897 } /*** End SerialRead ***/ 00898 00899 00900 /** 00901 * Refreshes and restarts Rx state machine. 00902 * 00903 */ 00904 void LsrModule::SerialRxCleanupRestart(void) 00905 { 00906 SerialFlush(); 00907 u8UartRxBufferIndex = LSR_MODULE_MSG_START_BYTE_INDEX; 00908 ptrHostState = &LsrModule::HostRxWaitForMsgStartByteState; 00909 } /*** End SerialRxCleanupRestart ***/ 00910 00911 00912 /** 00913 * Waits for data packet start byte. 00914 * 00915 */ 00916 void LsrModule::HostRxWaitForMsgStartByteState(void) 00917 { 00918 while (readable() && (SerialRead() == LSR_MODULE_SERIAL_MSG_START_BYTE)) 00919 { 00920 au8UartRxBuffer[u8UartRxBufferIndex++] = LSR_MODULE_SERIAL_MSG_START_BYTE; 00921 ptrHostState = &LsrModule::HostRxGetMsgLengthState; 00922 } 00923 } /*** End HostRxWaitForMsgStartByteState ***/ 00924 00925 00926 /** 00927 * Gets data packet length byte. 00928 * 00929 */ 00930 void LsrModule::HostRxGetMsgLengthState(void) 00931 { 00932 while (readable()) 00933 { 00934 u8RxReadByte = SerialRead(); 00935 00936 if ((u8RxReadByte >= LSR_MODULE_MIN_SERIAL_RX_MSG_LENGTH) && 00937 (u8RxReadByte <= LSR_MODULE_MAX_SERIAL_RX_MSG_LENGTH)) 00938 { 00939 au8UartRxBuffer[u8UartRxBufferIndex++] = u8RxReadByte; 00940 ptrHostState = &LsrModule::HostRxGetMsgTypeState; 00941 } 00942 else 00943 { 00944 ptrHostState = &LsrModule::SerialRxCleanupRestart; 00945 } 00946 } 00947 } /*** End HostRxGetMsgLengthState ***/ 00948 00949 00950 /** 00951 * Gets data packet type byte. 00952 * 00953 */ 00954 void LsrModule::HostRxGetMsgTypeState(void) 00955 { 00956 while (readable()) 00957 { 00958 00959 u8RxReadByte = SerialRead(); 00960 00961 if (ValidMsgLengthAndType(u8RxReadByte, au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX])) 00962 { 00963 au8UartRxBuffer[u8UartRxBufferIndex++] = u8RxReadByte; 00964 ptrHostState = &LsrModule::HostRxWaitToGetRestOfMsgState; 00965 } 00966 else 00967 { 00968 ptrHostState = &LsrModule::SerialRxCleanupRestart; 00969 } 00970 } 00971 } /*** End HostRxGetMsgTypeState ***/ 00972 00973 00974 /** 00975 * Grabs rest of data packet bytes. 00976 * 00977 */ 00978 void LsrModule::HostRxWaitToGetRestOfMsgState(void) 00979 { 00980 while (readable()) 00981 { 00982 u8RxReadByte = SerialRead(); 00983 au8UartRxBuffer[u8UartRxBufferIndex++] = u8RxReadByte; 00984 00985 if (u8UartRxBufferIndex > LSR_MODULE_MAX_SERIAL_RX_MSG_LENGTH) 00986 { 00987 ptrHostState = &LsrModule::SerialRxCleanupRestart; 00988 } 00989 else if ((u8RxReadByte == LSR_MODULE_SERIAL_MSG_END_BYTE) && (u8UartRxBufferIndex == au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX])) 00990 { 00991 ptrHostState = &LsrModule::HostRxValidateMsgState; 00992 } 00993 } 00994 } /*** End HostRxWaitToGetRestOfMsgState ***/ 00995 00996 00997 /** 00998 * Validates received message. 00999 * 01000 */ 01001 void LsrModule::HostRxValidateMsgState(void) 01002 { 01003 01004 if (ValidRxChecksum(au8UartRxBuffer, au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX])) // Is checksum good? 01005 { 01006 ptrHostState = &LsrModule::HostRxGoodMsgState; // Good checksum - next state 01007 } 01008 else 01009 { 01010 ptrHostState = &LsrModule::SerialRxCleanupRestart; // Bad checksum - restart 01011 } 01012 } /*** End HostRxValidateMsgState ***/ 01013 01014 01015 /** 01016 * Calls appropriate received UART message callback and starts state machine over. 01017 * 01018 */ 01019 void LsrModule::HostRxGoodMsgState(void) 01020 { 01021 pu8RxBuffer = au8UartRxBuffer; 01022 u8RxMsgLength = au8UartRxBuffer[LSR_MODULE_MSG_LENGTH_BYTE_INDEX]; 01023 HostProcessCallbackMsgStart(au8UartRxBuffer, u8RxMsgLength); 01024 ptrHostState = &LsrModule::SerialRxCleanupRestart; // Start new RX sequence 01025 } /*** End HostRxGoodMsgState ***/
Generated on Tue Jul 12 2022 21:29:55 by
1.7.2