1 // ********************************************************************* 2 // Sketch to cooperate with CustomDpaHandler-Bridge-UART.c * 3 // ********************************************************************* 4 // Copyright (c) IQRF Tech s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-Bridge-UART.ino,v $ 7 // Version: $Revision: 1.7 $ 8 // Date: $Date: 2021/02/22 17:55:18 $ 9 // 10 // Revision history: 11 // 2019/03/01 Release for DPA 4.01 12 // 2018/10/25 Release for DPA 3.03 13 // 14 // ********************************************************************* 15 16 // Please see CustomDpaHandler-Bridge-UART.c for implementation details. 17 18 // This Sketch implements one standard IQRF sensor 19 // Type of the sensor is Binary7 20 21 // Include IQRF DPA headers 22 #include "DPA.h" 23 #include "IQRFstandard.h" 24 #include "IQRF_HWPID.h" 25 26 //############################################################################################ 27 void setup() 28 //############################################################################################ 29 { 30 // Setup UART to connect to IQRF TR module 31 Serial.begin( 115200 ); 32 } 33 34 //############################################################################################ 35 // Returns sensor value 36 byte GetSensor0Value() 37 //############################################################################################ 38 { 39 // Remap values from Alcohol Gas Sensor MQ-3 connected to the analog input 0 40 return map( analogRead( 0 ), 500, 1023, 0, 127 ); 41 } 42 43 //############################################################################################ 44 45 // HDLC byte stuffing bytes 46 // Flag Sequence 47 #define HDLC_FRM_FLAG_SEQUENCE 0x7e 48 // Asynchronous Control Escape 49 #define HDLC_FRM_CONTROL_ESCAPE 0x7d 50 // Asynchronous transparency modifier 51 #define HDLC_FRM_ESCAPE_BIT 0x20 52 53 // Flag to DpaEvent_DpaRequest event value to indicate return TRUE not FALSE 54 #define EVENT_RETURN_TRUE 0x80 55 // Flag to DpaEvent_DpaRequest event value to report error, error value is the 1st data byte 56 #define EVENT_RESPONSE_ERROR 0x40 57 58 // Received data from IQRF 59 byte RxBuffer[2 * sizeof( byte ) + sizeof( TDpaIFaceHeader ) + sizeof( TDpaMessage )]; 60 61 // Data from IQRF length limits 62 #define MIN_RX_PACKET_DATA_LENGTH 2 63 #define MAX_RX_PACKET_DATA_LENGTH sizeof( RxBuffer ) 64 65 //############################################################################################ 66 // Sends one byte to IQRF 67 void TxByte( byte data ) 68 //############################################################################################ 69 { 70 Serial.write( data ); 71 } 72 73 //############################################################################################ 74 // Sends one HDLC byte to IQRF 75 void TxHdlcByte( byte data ) 76 //############################################################################################ 77 { 78 switch ( data ) 79 { 80 default: 81 TxByte( data ); 82 return; 83 84 case HDLC_FRM_FLAG_SEQUENCE: 85 case HDLC_FRM_CONTROL_ESCAPE: 86 { 87 TxByte( HDLC_FRM_CONTROL_ESCAPE ); 88 TxByte( data ^ HDLC_FRM_ESCAPE_BIT ); 89 return; 90 } 91 } 92 } 93 94 //############################################################################################ 95 // Returns FRC value back to IQRF 96 void ResponseFRCvalue( unsigned long frcValue ) 97 //############################################################################################ 98 { 99 // Start packet 100 TxByte( HDLC_FRM_FLAG_SEQUENCE ); 101 // Send event value 102 TxHdlcByte( DpaEvent_FrcValue ); 103 // Send FRC value up to 4 bytes 104 TxHdlcByte( frcValue & 0xFF ); 105 TxHdlcByte( ( frcValue >> 8 ) & 0xFF ); 106 TxHdlcByte( ( frcValue >> 16 ) & 0xFF ); 107 TxHdlcByte( ( frcValue >> 24 ) & 0xFF ); 108 // Stop packet 109 TxByte( HDLC_FRM_FLAG_SEQUENCE ); 110 } 111 112 //############################################################################################ 113 // Return DPA response back to IQRF 114 void ResponseCommand( byte returnFlags, byte _DpaDataLength, byte dataLength, byte *pData ) 115 //############################################################################################ 116 { 117 // Start packet 118 TxByte( HDLC_FRM_FLAG_SEQUENCE ); 119 // Send event value 120 TxHdlcByte( DpaEvent_DpaRequest | returnFlags ); 121 // Send DPA variable data length (must not equal to the actual data length sent) 122 TxHdlcByte( _DpaDataLength ); 123 // Send DPA response data 124 for ( ; dataLength != 0; dataLength-- ) 125 TxHdlcByte( *pData++ ); 126 // Stop packet 127 TxByte( HDLC_FRM_FLAG_SEQUENCE ); 128 } 129 130 //############################################################################################ 131 // Packet from Custom DPA Handler was received 132 void CustomDpaHandler( byte dataLength ) 133 //############################################################################################ 134 { 135 // Which Custom DPA Handler event to handle? 136 switch ( RxBuffer[0] ) 137 { 138 // Prepare DPA response to DPA request 139 case DpaEvent_DpaRequest: 140 if ( dataLength >= ( 2 * sizeof( byte ) + sizeof( TDpaIFaceHeader ) ) ) 141 { 142 // Fake important DPA variables for the DPA Request/Response so the Custom DPA handler code will can be written almost same way on both platforms 143 #define _DpaDataLength (RxBuffer[1]) 144 #define _NADR (RxBuffer[2]) 145 #define _NADRhigh (RxBuffer[3]) 146 #define _PNUM (RxBuffer[4]) 147 #define _PCMD (RxBuffer[5]) 148 #define _HWPIDlow (RxBuffer[6]) 149 #define _HWPIDhigh (RxBuffer[7]) 150 #define _DpaMessage (*((TDpaMessage*)(RxBuffer+8))) 151 152 // Fake Custom DPA Handler macro to return DPA error (this macro does not do return the same way the DPA original macro) 153 #define DpaApiReturnPeripheralError(error) do { \ 154 _DpaMessage.ErrorAnswer.ErrN = error; \ 155 returnDataLength = _DpaDataLength = sizeof( _DpaMessage.ErrorAnswer.ErrN ); \ 156 returnFlags = EVENT_RESPONSE_ERROR | EVENT_RETURN_TRUE; \ 157 } while( 0 ) 158 159 // Value or error flag to return from Custom DPA handler 160 byte returnFlags = 0; 161 // Length data to return (may not equal to _DpaDataLength) 162 byte returnDataLength = 0; 163 // Device enumeration? 164 if ( IsDpaEnumPeripheralsRequest() ) 165 { 166 // We implement 1 user peripheral 167 _DpaMessage.EnumPeripheralsAnswer.UserPerNr = 1; 168 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_STD_SENSORS ); 169 _DpaMessage.EnumPeripheralsAnswer.HWPID = 0x123F; 170 _DpaMessage.EnumPeripheralsAnswer.HWPIDver = 0xABCD; 171 172 // Return the enumeration structure but do not modify _DpaDataLength 173 returnDataLength = sizeof( _DpaMessage.EnumPeripheralsAnswer ); 174 // Return TRUE 175 returnFlags = EVENT_RETURN_TRUE; 176 } 177 // Get information about peripherals? 178 else if ( IsDpaPeripheralInfoRequest() ) 179 { 180 if ( _PNUM == PNUM_STD_SENSORS ) 181 { 182 _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_STD_SENSORS; 183 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE; 184 // Set standard version 185 _DpaMessage.PeripheralInfoAnswer.Par1 = STD_SENSORS_VERSION; 186 187 // Return the information structure but do not modify _DpaDataLength 188 returnDataLength = sizeof( _DpaMessage.PeripheralInfoAnswer ); 189 // Return TRUE 190 returnFlags = EVENT_RETURN_TRUE; 191 } 192 } 193 else 194 { 195 // Handle peripheral command 196 197 // Supported peripheral number? 198 if ( _PNUM == PNUM_STD_SENSORS ) 199 { 200 // Supported commands? 201 switch ( _PCMD ) 202 { 203 // Invalid command 204 default: 205 // Return error 206 DpaApiReturnPeripheralError( ERROR_PCMD ); 207 break; 208 209 // Sensor enumeration 210 case PCMD_STD_ENUMERATE: 211 // Check data request length 212 if ( _DpaDataLength != 0 ) 213 { 214 DpaApiReturnPeripheralError( ERROR_DATA_LEN ); 215 break; 216 } 217 218 // 1st byte is sensor type 219 _DpaMessage.Response.PData[0] = STD_SENSOR_TYPE_BINARYDATA7; 220 221 // Return just one sensor type 222 returnDataLength = _DpaDataLength = sizeof( _DpaMessage.Response.PData[0] ); 223 // Return TRUE 224 returnFlags = EVENT_RETURN_TRUE; 225 break; 226 227 // Supported commands. They are handled almost the same way 228 case PCMD_STD_SENSORS_READ_VALUES: 229 case PCMD_STD_SENSORS_READ_TYPES_AND_VALUES: 230 { 231 // No sensor bitmap specified? 232 if ( _DpaDataLength == 0 ) 233 { 234 // Bitmap is 32 bits long = 4 235 _DpaDataLength = 4; 236 // Simulate 1st sensor in the bitmap (states of the other unimplemented sensors do not care) 237 _DpaMessage.Request.PData[0] |= 0x01; // Note: must not modify W 238 } 239 // Valid bitmap length? 240 else if ( _DpaDataLength != 4 ) 241 { 242 // Return error 243 DpaApiReturnPeripheralError( ERROR_DATA_LEN ); 244 break; 245 } 246 247 // Pointer to the response data 248 byte *pResponseData = _DpaMessage.Response.PData; 249 // Is my only sensor selected? 250 if ( ( _DpaMessage.Request.PData[0] & 0x01 ) != 0 ) 251 { 252 // Return also sensor type? 253 if ( _PCMD == PCMD_STD_SENSORS_READ_TYPES_AND_VALUES ) 254 *pResponseData++ = STD_SENSOR_TYPE_BINARYDATA7; 255 256 // Return sensor data 257 *pResponseData++ = GetSensor0Value(); 258 } 259 260 // Returned data length 261 returnDataLength = _DpaDataLength = ( pResponseData - _DpaMessage.Response.PData ); 262 // Return TRUE 263 returnFlags = EVENT_RETURN_TRUE; 264 break; 265 } 266 } 267 } 268 } 269 270 // Return DPA response 271 ResponseCommand( returnFlags, _DpaDataLength, returnDataLength, (byte*)&_DpaMessage ); 272 } 273 break; 274 275 // Return FRC Value 276 case DpaEvent_FrcValue: 277 // Check for the minimum length (FRC command and at least 2 bytes of data) 278 if ( dataLength >= ( 2 + 1 + 2 ) ) 279 { 280 // Fake important DPA variables for the DPA FRC handling 281 #define FrcCommand (RxBuffer[1]) 282 #define DataOutBeforeResponseFRC ((byte*)( &RxBuffer[2] )) 283 284 // Check the correct FRC request 285 if ( DataOutBeforeResponseFRC[0] == PNUM_STD_SENSORS && 286 ( DataOutBeforeResponseFRC[1] == 0x00 || DataOutBeforeResponseFRC[1] == STD_SENSOR_TYPE_BINARYDATA7 ) && 287 ( DataOutBeforeResponseFRC[2] & 0x1f ) == 0 ) 288 { 289 // Which FRC command to handle? 290 switch ( FrcCommand ) 291 { 292 case FRC_STD_SENSORS_1B: 293 ResponseFRCvalue( GetSensor0Value() + 4 ); 294 break; 295 296 case FRC_STD_SENSORS_BIT: 297 ResponseFRCvalue( ( GetSensor0Value() & ( 0x01 << ( DataOutBeforeResponseFRC[2] >> 5 ) ) ) != 0 ? 0x03 : 0x01 ); 298 break; 299 } 300 } 301 } 302 break; 303 } 304 } 305 306 //############################################################################################ 307 void loop() 308 //############################################################################################ 309 { 310 // Byte received from the IQRF? 311 while ( Serial.available() ) 312 { 313 // HDLC machine states 314 typedef enum { RXstateWaitHead, RXstatePacket, RXstateEscape } TState; 315 316 // HDLC state 317 static byte state = RXstateWaitHead; 318 // Length of the already received data 319 static byte rxLength; 320 // Pointer to the received data 321 static byte *pRxBuffer; 322 323 // Read the byte from IQRF 324 byte oneByte = Serial.read(); 325 switch ( state ) 326 { 327 // Waiting for the HDLC header 328 case RXstateWaitHead: 329 { 330 if ( oneByte == HDLC_FRM_FLAG_SEQUENCE ) 331 { 332 _SetRXstatePacket: 333 rxLength = 0; 334 pRxBuffer = RxBuffer; 335 state = RXstatePacket; 336 } 337 break; 338 } 339 340 // Handling packet data byte 341 case RXstatePacket: 342 { 343 switch ( oneByte ) 344 { 345 case HDLC_FRM_CONTROL_ESCAPE: 346 // RXstateEscape 347 state++; 348 goto _ExitMachine; 349 350 case HDLC_FRM_FLAG_SEQUENCE: 351 { 352 if ( rxLength >= MIN_RX_PACKET_DATA_LENGTH ) 353 // Packet received, handle it 354 CustomDpaHandler( rxLength ); 355 356 goto _SetRXstatePacket; 357 } 358 } 359 360 _StoreByte: 361 if ( rxLength == ( MAX_RX_PACKET_DATA_LENGTH + 2 ) ) 362 goto _SetRXstateWaitHead; 363 364 *pRxBuffer++ = oneByte; 365 rxLength++; 366 367 _ExitMachine: 368 break; 369 } 370 371 // Handle escaped byte 372 case RXstateEscape: 373 { 374 switch ( oneByte ) 375 { 376 case HDLC_FRM_FLAG_SEQUENCE: 377 goto _SetRXstatePacket; 378 379 case HDLC_FRM_CONTROL_ESCAPE: 380 _SetRXstateWaitHead: 381 state = RXstateWaitHead; 382 break; 383 384 default: 385 // RXstatePacket 386 state--; 387 oneByte ^= HDLC_FRM_ESCAPE_BIT; 388 goto _StoreByte; 389 } 390 break; 391 } 392 } 393 } 394 } 395 396 //############################################################################################