1 // ********************************************************************* 2 // Custom DPA Handler code example - Standard Sensors - Template * 3 // ********************************************************************* 4 // Copyright (c) IQRF Tech s.r.o. 5 // 6 // File: $RCSfile: 1402_Sensor-Template.c,v $ 7 // Version: $Revision: 1.31 $ 8 // Date: $Date: 2020/03/20 13:25:58 $ 9 // 10 // Revision history: 11 // 2020/01/09 Release for DPA 4.12 12 // 2018/10/25 Release for DPA 3.03 13 // 2017/11/16 Release for DPA 3.02 14 // 2017/08/14 Release for DPA 3.01 15 // 16 // ********************************************************************* 17 18 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 19 // IQRF Standards documentation https://www.iqrfalliance.org/iqrf-interoperability/ 20 21 // This example implements 6 sensors according to the IQRF Sensors standard. The example does not implement writing data to the sensors. 22 23 // Default IQRF include (modify the path according to your setup) 24 #include "IQRF.h" 25 26 // Uncomment to implement Custom DPA Handler for Coordinator 27 //#define COORDINATOR_CUSTOM_HANDLER 28 29 // Default DPA header (modify the path according to your setup) 30 #include "DPA.h" 31 // Default Custom DPA Handler header (modify the path according to your setup) 32 #include "DPAcustomHandler.h" 33 // IQRF standards header (modify the path according to your setup) 34 #include "IQRFstandard.h" 35 #include "IQRF_HWPID.h" 36 37 //############################################################################################ 38 39 // Number of implemented sensors 40 #define SENSORS_COUNT 7 41 42 // Variables to store sensor value at Get?_????() methods. 43 uns16 sensorValue @ param3; 44 uns16 sensorValueHighWord @ param4; 45 46 // Reads sensor value to the sensorValue variable and to responseFRCvalue(2B,4B) variable(s) based on FRC command @ _PCMD 47 // Returns TRUE if the FRC is prepared 48 bit Get0_Temperature(); 49 bit Get1_CO2(); 50 bit Get2_VOC(); 51 bit Get3_Humidity(); 52 bit Get4_Binary7(); 53 bit Get5_DataBlock(); 54 bit Get6_Binary30(); 55 56 // Stores sensor value byte(s) to the FSR1[+1...], in case of PCMD_STD_SENSORS_READ_TYPES_AND_VALUES sensor type is stored before value byte(s) 57 void StoreValue( uns8 sensorType ); 58 59 // FRC parameter 60 uns8 sensorIndexAndData; 61 62 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 63 //############################################################################################ 64 bit CustomDpaHandler() 65 //############################################################################################ 66 { 67 // This forces CC5X to wisely use MOVLB instructions (doc says: The 'default' bank is used by the compiler for loops and labels when the algorithm gives up finding the optimal choice) 68 #pragma updateBank default = UserBank_01 69 70 // Handler presence mark 71 clrwdt(); 72 73 // Sleeping parameters, valid when Time != 0 74 static TPerOSSleep_Request PerOSSleep_Request; 75 76 // Detect DPA event to handle 77 switch ( GetDpaEvent() ) 78 { 79 // ------------------------------------------------- 80 case DpaEvent_Interrupt: 81 // Do an extra quick background interrupt work 82 // ! The time spent handling this event is critical.If there is no interrupt to handle return immediately otherwise keep the code as fast as possible. 83 // ! Make sure the event is the 1st case in the main switch statement at the handler routine.This ensures that the event is handled as the 1st one. 84 // ! It is desirable that this event is handled with immediate return even if it is not used by the custom handler because the Interrupt event is raised on every MCU interrupt and the “empty” return handler ensures the shortest possible interrupt routine response time. 85 // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy. 86 // ! Make sure race condition does not occur when accessing those variables at other places. 87 // ! Make sure( inspect.lst file generated by C compiler ) compiler does not create any hidden temporary local variable( occurs when using division, multiplication or bit shifts ) at the event handler code.The name of such variable is usually Cnumbercnt. 88 // ! Do not call any OS functions except setINDFx(). 89 // ! Do not use any OS variables especially for writing access. 90 // ! All above rules apply also to any other function being called from the event handler code, although calling any function from Interrupt event is not recommended because of additional MCU stack usage. 91 return Carry; 92 93 // ------------------------------------------------- 94 case DpaEvent_Idle: 95 // Do a quick background work when RF packet is not received 96 97 // Should go to sleep? 98 if ( PerOSSleep_Request.Time != 0 ) 99 { 100 // Copy sleep parameters to the DPA request 101 _DpaMessage.PerOSSleep_Request.Time = PerOSSleep_Request.Time; 102 _DpaMessage.PerOSSleep_Request.Control = PerOSSleep_Request.Control; 103 // Switch off sleeping time=flag 104 PerOSSleep_Request.Time = 0; 105 // Finalize OS Sleep DPA Request 106 _DpaDataLength = sizeof( _DpaMessage.PerOSSleep_Request ); 107 _PNUM = PNUM_OS; 108 _PCMD = CMD_OS_SLEEP; 109 // Perform local DPA Request to go to sleep 110 DpaApiLocalRequest(); 111 } 112 break; 113 114 // ------------------------------------------------- 115 case DpaEvent_DpaRequest: 116 // Called to interpret DPA request for peripherals 117 // ------------------------------------------------- 118 // Peripheral enumeration 119 if ( IsDpaEnumPeripheralsRequest() ) 120 { 121 // We implement 1 standard peripheral 122 _DpaMessage.EnumPeripheralsAnswer.UserPerNr = 1; 123 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_STD_SENSORS ); 124 // ToDo: use actual IQRF Alliance allocated HWPID and current version of this handler 125 _DpaMessage.EnumPeripheralsAnswer.HWPID = HWPID_IQRF_TECH__DEMO_SENSOR_TEMPLATE; 126 _DpaMessage.EnumPeripheralsAnswer.HWPIDver = 0x0002; 127 128 DpaHandleReturnTRUE: 129 return TRUE; 130 } 131 // ------------------------------------------------- 132 // Get information about peripheral 133 else if ( IsDpaPeripheralInfoRequest() ) 134 { 135 if ( _PNUM == PNUM_STD_SENSORS ) 136 { 137 _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_STD_SENSORS; 138 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE; 139 // Set standard version 140 _DpaMessage.PeripheralInfoAnswer.Par1 = STD_SENSORS_VERSION; 141 goto DpaHandleReturnTRUE; 142 } 143 144 break; 145 } 146 // ------------------------------------------------- 147 else 148 { 149 // Handle peripheral command 150 151 // Supported peripheral number? 152 if ( _PNUM == PNUM_STD_SENSORS ) 153 { 154 // Supported commands? 155 switch ( _PCMD ) 156 { 157 // Invalid command 158 default: 159 // Return error 160 DpaApiReturnPeripheralError( ERROR_PCMD ); 161 162 // Sensor enumeration 163 case PCMD_STD_ENUMERATE: 164 if ( _DpaDataLength != 0 ) 165 goto _ERROR_DATA_LEN; 166 167 // Then just enumerate their types 168 _DpaMessage.Response.PData[0] = STD_SENSOR_TYPE_TEMPERATURE; 169 _DpaMessage.Response.PData[1] = STD_SENSOR_TYPE_CO2; 170 _DpaMessage.Response.PData[2] = STD_SENSOR_TYPE_VOC; 171 _DpaMessage.Response.PData[3] = STD_SENSOR_TYPE_HUMIDITY; 172 _DpaMessage.Response.PData[4] = STD_SENSOR_TYPE_BINARYDATA7; 173 _DpaMessage.Response.PData[5] = STD_SENSOR_TYPE_DATA_BLOCK; 174 _DpaMessage.Response.PData[6] = STD_SENSOR_TYPE_BINARYDATA30; 175 W = SENSORS_COUNT; 176 goto _W2_DpaDataLength; 177 178 // Supported commands. They are handled the same way except one "if" at StoreValue() method 179 case PCMD_STD_SENSORS_READ_VALUES: 180 case PCMD_STD_SENSORS_READ_TYPES_AND_VALUES: 181 { 182 // No sensor bitmap specified? W = _DpaDataLength. Note: W is used to avoid MOVLB at next if 183 W = _DpaDataLength; 184 if ( W == 0 ) // Note: must not modify W 185 { 186 // Actually clears the bitmap 187 #if &_DpaMessage.Request.PData[0] != &bufferRF[0] 188 #error 189 #endif 190 clearBufferRF(); 191 // Simulate 1st only sensor in the bitmap (states of the other unimplemented sensors do not care) 192 _DpaMessage.Request.PData[0].0 = 1; 193 // Bitmap is 32 bits long = 4 194 _DpaDataLength = W = 4; 195 } 196 197 // Invalid bitmap (data) length (W = _DpaDataLength)? 198 if ( W != 4 ) 199 { 200 _ERROR_DATA_LEN: 201 // Return error 202 DpaApiReturnPeripheralError( ERROR_DATA_LEN ); 203 } 204 205 // Now read the sensors 206 207 // Prepare pointer (minus 1, see below) to store sensor (types and) values to 208 // Note: 5 sensors at this example cannot return more than DPA_MAX_DATA_LENGTH bytes of data, so it does not have to be checked... 209 // ... If it would be the case, then ERROR_FAIL must be returned 210 FSR1 = &_DpaMessage.Response.PData[-1]; 211 212 // Store bitmap of sensors to get values from 213 uns8 sensorsBitmap = FSR1[1]; 214 215 // 1st sensor (index 0) selected? 216 if ( sensorsBitmap.0 ) 217 { 218 Get0_Temperature(); 219 StoreValue( STD_SENSOR_TYPE_TEMPERATURE ); 220 } 221 222 // 2nd sensor (index 1) selected? 223 if ( sensorsBitmap.1 ) 224 { 225 Get1_CO2(); 226 StoreValue( STD_SENSOR_TYPE_CO2 ); 227 } 228 229 // 3rd sensor (index 2) selected? 230 if ( sensorsBitmap.2 ) 231 { 232 Get2_VOC(); 233 StoreValue( STD_SENSOR_TYPE_VOC ); 234 } 235 236 // 4th sensor (index 3) selected? 237 if ( sensorsBitmap.3 ) 238 { 239 Get3_Humidity(); 240 StoreValue( STD_SENSOR_TYPE_HUMIDITY ); 241 } 242 243 // 5th sensor (index 4) selected? 244 if ( sensorsBitmap.4 ) 245 { 246 Get4_Binary7(); 247 StoreValue( STD_SENSOR_TYPE_BINARYDATA7 ); 248 } 249 250 // 6th sensor (index 5) selected? 251 if ( sensorsBitmap.5 ) 252 { 253 Get5_DataBlock(); 254 StoreValue( STD_SENSOR_TYPE_DATA_BLOCK ); 255 } 256 257 // 6th sensor (index 5) selected? 258 if ( sensorsBitmap.6 ) 259 { 260 Get6_Binary30(); 261 StoreValue( STD_SENSOR_TYPE_BINARYDATA30 ); 262 } 263 264 // Compute returned data bytes count 265 W = FSR1L - ( (uns16)&_DpaMessage.Response.PData[0] & 0xFF ) + 1; 266 // Optimization: return W long block of bytes at response 267 _W2_DpaDataLength: 268 _DpaDataLength = W; 269 goto DpaHandleReturnTRUE; 270 } 271 } 272 } 273 274 break; 275 } 276 277 // ------------------------------------------------- 278 case DpaEvent_Init: 279 // Do a one time initialization before main loop starts 280 281 // Setup all free GPIOs as inputs (used at Binary7 simulation) 282 TRISA |= 0b0010.0001; 283 TRISC |= 0b1111.1100; 284 TRISB |= 0b0001.0000; 285 286 break; 287 288 // ------------------------------------------------- 289 case DpaEvent_FrcValue: 290 // Called to get FRC value 291 292 // FSR1 for optimization purposes (avoid MOVLB) will be used to point to DataOutBeforeResponseFRC[0...] 293 FSR1 = &DataOutBeforeResponseFRC[0]; 294 // Check for correct FRC user data 295 if ( *FSR1++ /*DataOutBeforeResponseFRC[0]*/ == PNUM_STD_SENSORS ) 296 { 297 // Data and index 298 sensorIndexAndData = FSR1[1]; /*DataOutBeforeResponseFRC[2]*/ 299 // Actually used sensor index 300 uns8 sensorIndex = FSR1[1] /*DataOutBeforeResponseFRC[2]*/ & 0x1f; 301 // Test sensor type 302 switch ( *FSR1++ /*DataOutBeforeResponseFRC[1]*/ ) 303 { 304 default: 305 goto DpaHandleReturnFALSE; 306 307 // No type specified, use specified index value 308 case 0x00: 309 goto _KeepSensorIndex; 310 311 // For other types make the index value based on the requested index value and sensor type 312 case STD_SENSOR_TYPE_TEMPERATURE: 313 if ( sensorIndex > 0 ) 314 goto DpaHandleReturnFALSE; 315 W = 0; 316 break; 317 318 case STD_SENSOR_TYPE_CO2: 319 if ( sensorIndex > 0 ) 320 goto DpaHandleReturnFALSE; 321 W = 1; 322 break; 323 324 case STD_SENSOR_TYPE_VOC: 325 if ( sensorIndex > 0 ) 326 goto DpaHandleReturnFALSE; 327 W = 2; 328 break; 329 330 case STD_SENSOR_TYPE_HUMIDITY: 331 if ( sensorIndex > 0 ) 332 goto DpaHandleReturnFALSE; 333 W = 3; 334 break; 335 336 case STD_SENSOR_TYPE_BINARYDATA7: 337 if ( sensorIndex > 0 ) 338 goto DpaHandleReturnFALSE; 339 W = 4; 340 break; 341 342 case STD_SENSOR_TYPE_BINARYDATA30: 343 if ( sensorIndex > 0 ) 344 goto DpaHandleReturnFALSE; 345 W = 6; 346 break; 347 } 348 349 // New sensor index based on type and requested index 350 sensorIndex = W; 351 _KeepSensorIndex: 352 353 // Test for supported FRC commands 354 switch ( _PCMD ) 355 { 356 default: 357 goto DpaHandleReturnFALSE; 358 359 case FRC_STD_SENSORS_BIT: 360 case FRC_STD_SENSORS_1B: 361 case FRC_STD_SENSORS_2B: 362 case FRC_STD_SENSORS_4B: 363 switch ( sensorIndex ) 364 { 365 default: 366 goto DpaHandleReturnFALSE; 367 368 case 0: 369 Carry = Get0_Temperature(); 370 break; 371 372 case 1: 373 Carry = Get1_CO2(); 374 break; 375 376 case 2: 377 Carry = Get2_VOC(); 378 break; 379 380 case 3: 381 Carry = Get3_Humidity(); 382 break; 383 384 case 4: 385 Carry = Get4_Binary7(); 386 break; 387 388 case 6: 389 Carry = Get6_Binary30(); 390 break; 391 } 392 393 // This type of FRC is not valid for the specified sensor 394 if ( !Carry ) 395 goto DpaHandleReturnFALSE; 396 397 break; 398 } 399 400 // Some sensor was measured by FRC, check if there is a sleep request 401 FSR1++; 402 if ( INDF1.0 ) // Note: same as DataOutBeforeResponseFRC[3].0 403 { 404 // Remember sleep parameters to go to sleep at the Idle event later 405 PerOSSleep_Request.Time.low8 = FSR1[4 - 3]; // Note: same as DataOutBeforeResponseFRC[4]; 406 PerOSSleep_Request.Time.high8 = FSR1[5 - 3]; // Note: same as DataOutBeforeResponseFRC[5]; 407 PerOSSleep_Request.Control = FSR1[6 - 3]; // Note: same as DataOutBeforeResponseFRC[6]; 408 } 409 } 410 411 break; 412 413 // ------------------------------------------------- 414 case DpaEvent_FrcResponseTime: 415 // Called to get FRC response time 416 417 // In this example the FRC commands are fast 418 switch ( DataOutBeforeResponseFRC[0] ) 419 { 420 case FRC_STD_SENSORS_BIT: 421 case FRC_STD_SENSORS_1B: 422 case FRC_STD_SENSORS_2B: 423 case FRC_STD_SENSORS_4B: 424 responseFRCvalue = _FRC_RESPONSE_TIME_40_MS; 425 break; 426 } 427 break; 428 } 429 DpaHandleReturnFALSE: 430 return FALSE; 431 } 432 433 //############################################################################################ 434 // Increases FSR1 and then stores the byte 435 void setPlusPlusINDF1( uns8 data @ W ) 436 //############################################################################################ 437 { 438 FSR1++; // Note: must not modify W 439 setINDF1( data ); 440 } 441 442 //############################################################################################ 443 // Stores measured sensor value byte(s) and optionally sensor type to the FSR[+1...] 444 void StoreValue( uns8 sensorType ) 445 //############################################################################################ 446 { 447 // Is the sensor type to be stored too? 448 if ( _PCMD == PCMD_STD_SENSORS_READ_TYPES_AND_VALUES ) 449 setPlusPlusINDF1( sensorType ); 450 451 // Store lower value byte (or length in case of multiple bytes) 452 setPlusPlusINDF1( sensorValue.low8 ); 453 454 // 2 bytes? 455 if ( sensorType.7 == 0 ) 456 { 457 // Store higher value byte 458 setPlusPlusINDF1( sensorValue.high8 ); 459 return; 460 } 461 462 // 4 bytes? 463 if ( ( sensorType & 0b1110.0000 ) == 0b1010.0000 ) 464 { 465 setPlusPlusINDF1( sensorValue.high8 ); 466 setPlusPlusINDF1( sensorValueHighWord.low8 ); 467 setPlusPlusINDF1( sensorValueHighWord.high8 ); 468 return; 469 } 470 471 // Multiple bytes? 472 if ( ( sensorType & 0b1100.0000 ) == 0b1100.0000 ) 473 { 474 // Data is expected at bufferINFO, length at sensorValue.low8 475 setFSR0( _FSR_INFO ); 476 do 477 { 478 // Store all data 479 setPlusPlusINDF1( *FSR0++ ); 480 } while ( --sensorValue.low8 != 0 ); 481 return; 482 } 483 } 484 485 //############################################################################################ 486 bit setFRCerror() 487 //############################################################################################ 488 { 489 #ifndef __CC5XFREE__ 490 responseFRCvalue4B = 2; 491 #else 492 responseFRCvalue4B.low16 = 2; 493 responseFRCvalue4B.high16 = 0; 494 #endif 495 return TRUE; 496 } 497 498 //############################################################################################ 499 // Sensor index 0: measure temperature using the TR sensor 500 bit Get0_Temperature() 501 //############################################################################################ 502 { 503 // Make sure FSR1 is not modified 504 505 // Measure temperature using TR sensor 506 bit sensorError = FALSE; 507 // When error, then adjust the standard error values 508 if ( getTemperature() == -128 ) 509 { 510 sensorError = TRUE; 511 STD_SENSOR_TYPE_TEMPERATURE_SET_ERROR( param3 ); 512 } 513 514 // Return sensor value 515 sensorValue = param3; 516 517 // Test for supported FRC commands 518 switch ( _PCMD ) 519 { 520 default: 521 return FALSE; 522 523 case FRC_STD_SENSORS_1B: 524 // Return sensor FRC value 1B 525 // Check for out of limits 526 if ( sensorError || (int16)sensorValue > (int16)( 105.5 * 16 ) || (int16)sensorValue < ( (int16)-20 * 16 ) ) 527 return setFRCerror(); 528 529 // Convert to the "F = ( T + 22 ) * 2 " from 1/16 resolution 530 responseFRCvalue2B = sensorValue + 4; // Note: do rounding when /8 531 responseFRCvalue2B /= 8; 532 responseFRCvalue += 44; 533 break; 534 535 case FRC_STD_SENSORS_2B: 536 // Return sensor FRC value 2B 537 if ( sensorError ) 538 return setFRCerror(); 539 540 responseFRCvalue2B = sensorValue ^ 0x8000; 541 break; 542 } 543 544 return TRUE; 545 } 546 547 //############################################################################################ 548 // Sensor index 1: simulate measuring CO2 549 bit Get1_CO2() 550 //############################################################################################ 551 { 552 // Make sure FSR1 is not modified 553 554 bit sensorError = FALSE; 555 // Fake CO2 return value 556 sensorValue = 0x0987; 557 // When error, return standard (FRC) error value(s) 558 if ( STD_SENSOR_TYPE_CO2_IS_ERROR( sensorValue ) ) 559 sensorError = TRUE; 560 561 // Test for supported FRC commands 562 switch ( _PCMD ) 563 { 564 default: 565 return FALSE; 566 567 case FRC_STD_SENSORS_1B: 568 // Return sensor FRC value 1B 569 // Check for out of limits 570 if ( sensorError || sensorValue > 4016 ) 571 return setFRCerror(); 572 573 responseFRCvalue = sensorValue / 16 + 4; 574 break; 575 576 case FRC_STD_SENSORS_2B: 577 // Return sensor FRC value 2B 578 if ( sensorError ) 579 return setFRCerror(); 580 581 responseFRCvalue2B = sensorValue + 4; 582 break; 583 } 584 585 return TRUE; 586 } 587 588 //############################################################################################ 589 // Sensor index 2: simulate measuring VOC 590 bit Get2_VOC() 591 //############################################################################################ 592 { 593 // Make sure FSR1 is not modified 594 595 bit sensorError = FALSE; 596 // Fake VOC return value 597 sensorValue = 0x0123; 598 // When error, return standard (FRC) error value(s) 599 if ( STD_SENSOR_TYPE_VOC_IS_ERROR( sensorValue ) ) 600 sensorError = TRUE; 601 602 // Test for supported FRC commands 603 switch ( _PCMD ) 604 { 605 default: 606 return FALSE; 607 608 case FRC_STD_SENSORS_1B: 609 // Return sensor FRC value 1B 610 // Check for out of limits 611 if ( sensorError || sensorValue > 4016 ) 612 return setFRCerror(); 613 614 responseFRCvalue = sensorValue / 16 + 4; 615 break; 616 617 case FRC_STD_SENSORS_2B: 618 // Return sensor FRC value 2B 619 if ( sensorError ) 620 return setFRCerror(); 621 622 responseFRCvalue2B = sensorValue + 4; 623 break; 624 } 625 626 return TRUE; 627 } 628 629 //############################################################################################ 630 // Sensor index 3: simulate measuring humidity 631 bit Get3_Humidity() 632 //############################################################################################ 633 { 634 // Make sure FSR1 is not modified 635 636 // Fake humidity return value 637 sensorValue.low8 = lastRSSI & 0x7F; 638 639 // Test for supported FRC commands 640 switch ( _PCMD ) 641 { 642 default: 643 return FALSE; 644 645 case FRC_STD_SENSORS_1B: 646 // Return sensor FRC value 1B 647 if ( STD_SENSOR_TYPE_HUMIDITY_IS_ERROR( sensorValue.low8 ) ) 648 return setFRCerror(); 649 650 responseFRCvalue = sensorValue.low8 + 4; 651 break; 652 } 653 return TRUE; 654 } 655 656 //############################################################################################ 657 // Sensor index 4: simulate binary data 658 bit Get4_Binary7() 659 //############################################################################################ 660 { 661 // Make sure FSR1 is not modified 662 663 bit sensorError = FALSE; 664 // Fake humidity return value 665 sensorValue.low8 = 0; 666 667 // Get bits from the available user GPIO inputs (DDC-IO-01 can be used for the simulation) 668 if ( PORTA.0 ) // SIM C1 669 sensorValue.0 = 1; 670 if ( PORTC.2 ) // SIM C2 671 sensorValue.1 = 1; 672 if ( PORTA.5 ) // SIM C5 673 sensorValue.2 = 1; 674 if ( PORTC.3 ) // SIM C6 675 sensorValue.3 = 1; 676 if ( PORTC.4 ) // SIM C7 677 sensorValue.4 = 1; 678 if ( PORTC.5 ) // SIM C8 679 sensorValue.5 = 1; 680 681 // When error, return standard (FRC) error value(s) 682 if ( STD_SENSOR_TYPE_BINARYDATA7_IS_ERROR( sensorValue.low8 ) ) 683 sensorError = TRUE; 684 685 // Test for supported FRC commands 686 switch ( _PCMD ) 687 { 688 default: 689 return FALSE; 690 691 case FRC_STD_SENSORS_BIT: 692 // If there is a sensor error, 2-bit FRC cannot indicate it, it returns [01] 693 if ( !sensorError ) 694 { 695 // Number of shifts to get the bit out of the return value 696 uns8 bitLoop = ( INDF1 >> 5 ) + 1; 697 // Value to get the bit from 698 W = sensorValue.low8; 699 do 700 { 701 // Get the bit to Carry 702 W = rr( W ); 703 // Next bit 704 } while ( --bitLoop != 0 ); // Note: must not modify W and Carry 705 // Current (prepared by DPA) FRC value is [01], change it to [11] (means bit is set) 706 responseFRCvalue.1 = 1; // Note: must not modify Carry 707 // Is bit set? 708 if ( !Carry ) 709 // Bit is NOT set, return [10] 710 responseFRCvalue.0 = 0; 711 } 712 break; 713 714 case FRC_STD_SENSORS_1B: 715 // Return sensor FRC value 1B 716 if ( sensorError ) 717 return setFRCerror(); 718 719 responseFRCvalue = sensorValue.low8 + 4; 720 break; 721 } 722 return TRUE; 723 } 724 725 //############################################################################################ 726 // Sensor index 5: simulate data block 727 bit Get5_DataBlock() 728 //############################################################################################ 729 { 730 // Make sure FSR1 is not modified 731 uns16 saveFSR1 = FSR1; 732 733 // Get data to bufferINFO 734 moduleInfo(); 735 // Return length 736 sensorValue.low8 = sizeof( TModuleInfo ); 737 738 FSR1 = saveFSR1; 739 return FALSE; 740 } 741 742 //############################################################################################ 743 // Sensor index 6: simulate 30 bit data 744 bit Get6_Binary30() 745 //############################################################################################ 746 { 747 // Make sure FSR1 is not modified 748 uns16 saveFSR1 = FSR1; 749 moduleInfo(); 750 responseFRCvalue4B.low8 = sensorValue.low8 = ModuleInfo.MID[0]; 751 responseFRCvalue4B.midL8 = sensorValue.high8 = ModuleInfo.MID[1]; 752 responseFRCvalue4B.midH8 = sensorValueHighWord.low8 = ModuleInfo.MID[2]; 753 responseFRCvalue4B.high8 = sensorValueHighWord.high8 = ModuleInfo.MID[3]; 754 FSR1 = saveFSR1; 755 756 // Test for supported FRC commands 757 switch ( _PCMD ) 758 { 759 default: 760 // Return back default FRC value 761 setFRCerror(); 762 responseFRCvalue--; 763 return FALSE; 764 765 case FRC_STD_SENSORS_2B: 766 if ( ( sensorIndexAndData & 0b10.0000 ) != 0 ) 767 #ifndef __CC5XFREE__ 768 responseFRCvalue4B >>= 15; 769 #else 770 { 771 // Carry = responseFRCvalue4B.15 772 W = rl( responseFRCvalue4B.midH8 ); 773 responseFRCvalue4B.midL8 = rl( responseFRCvalue4B.midL8 ); 774 responseFRCvalue4B.low8 = rl( responseFRCvalue4B.low8 ); 775 responseFRCvalue4B.low16 = responseFRCvalue4B.high16; 776 } 777 #endif 778 779 responseFRCvalue2B.15 = 0; 780 // Note: fall through does the same as "responseFRCvalue2B += 4;" 781 782 case FRC_STD_SENSORS_4B: 783 #ifndef __CC5XFREE__ 784 responseFRCvalue4B += 4; 785 #else 786 W = 4; 787 responseFRCvalue4B.low8 += W; 788 W = 0; 789 responseFRCvalue4B.midL8 = addWFC( responseFRCvalue4B.midL8 ); 790 responseFRCvalue4B.midH8 = addWFC( responseFRCvalue4B.midH8 ); 791 responseFRCvalue4B.high8 = addWFC( responseFRCvalue4B.high8 ); 792 #endif 793 break; 794 } 795 return TRUE; 796 } 797 //############################################################################################ 798 799 // Default Custom DPA Handler header; 2nd include to implement Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 800 #include "DPAcustomHandler.h" 801 //############################################################################################