1 // *********************************************************************************************************** 2 // Custom DPA Handler code example - Standard Sensors - DDC-SE-01 - LP version * 3 // *********************************************************************************************************** 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: 4C02_DDC-SE_LP.c,v $ 7 // Version: $Revision: 1.18 $ 8 // Date: $Date: 2021/08/18 20:43:06 $ 9 // 10 // Revision history: 11 // 2021/08/18 Release for DPA 4.16 12 // 2020/01/02 Release for DPA 4.11 13 // 2019/03/07 Release for DPA 4.01 14 // 15 // ********************************************************************* 16 17 // MCR-BuildStdHandler 18 #message '+CC5X -bu' 19 20 #define _HWPID_ HWPID_IQRF_TECH__DEMO_DDC_SE01_LP 21 #define _HWPIDver_ 0x0000 22 23 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 24 // IQRF Standards documentation https://doc.iqrf.org/ 25 26 // This example implements 3 sensors according to the IQRF Sensors standard 27 // Index 0 i.e. 1st sensor is either Dallas 18B20 or MCP9802 temperature sensor at DDC-SE-01 board according to the HW jumper position and symbol DALLASnotMCP. 28 // Index 1 i.e. 2nd sensor is light intensity indicator at DDC-SE-01 board (value range is 0[max light]-127[max dark]). 29 // Index 2 i.e. 3rd sensor is potentiometer value at DDC-SE-01 board (value range is 0[left stop]-127[right stop]). 30 31 // This example must be compiled without a "-bu" compiler switch in order to fit into available Flash memory 32 33 // Default IQRF include (modify the path according to your setup) 34 #include "IQRF.h" 35 36 // We can save more instructions if needed by the symbol below 37 // #define PARAM_CHECK_LEVEL 1 38 39 // Default DPA header (modify the path according to your setup) 40 #include "DPA.h" 41 // Default Custom DPA Handler header (modify the path according to your setup) 42 #include "DPAcustomHandler.h" 43 // IQRF standards header (modify the path according to your setup) 44 #include "IQRFstandard.h" 45 #include "IQRF_HWPID.h" 46 47 // If defined then the handler is compiled for Dallas otherwise for MCP9802 48 #define DALLASnotMCP 49 50 //############################################################################################ 51 52 // Define useful macro that saves some code but not preset at DPA < 3.01 53 #if DPA_VERSION_MASTER < 0x0301 54 // Optimized macro for both testing enumeration peripherals ELSE peripherals information. See examples 55 #define IfDpaEnumPeripherals_Else_PeripheralInfo_Else_PeripheralRequestNoSize() if ( _PCMD == CMD_GET_PER_INFO ) if ( _PNUM == PNUM_ENUMERATION ) 56 57 #if PARAM_CHECK_LEVEL >= 2 58 #define IfDpaEnumPeripherals_Else_PeripheralInfo_Else_PeripheralRequest() if ( _DpaDataLength == 0 && _PCMD == CMD_GET_PER_INFO ) if ( _PNUM == PNUM_ENUMERATION ) 59 #else 60 #define IfDpaEnumPeripherals_Else_PeripheralInfo_Else_PeripheralRequest() IfDpaEnumPeripherals_Else_PeripheralInfo_Else_PeripheralRequestNoSize() 61 #endif 62 #endif 63 64 //############################################################################################ 65 66 // Number of implemented sensors 67 #define SENSORS_COUNT 3 68 69 // Variable to store sensor value at Get?_????() methods. This example implements sensors returning maximum 2 bytes of data. 70 uns16 sensorValue @ param3; 71 72 // Reads sensor value to the sensorValue variable and to responseFRCvalue(2B) variable 73 bit Get0_Temperature(); 74 bit Get1_BinaryData_Light(); 75 bit Get2_BinaryData_Potentiometer(); 76 77 // 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) 78 void StoreValue( uns8 sensorType ); 79 80 #ifdef DALLASnotMCP 81 // Sensor connected to PORT C.3 (compatible with DDC-SE-01) 82 #define OneWire_TRIS TRISC.3 83 #define OneWire_IO_IN PORTC.3 84 #define OneWire_IO_OUT LATC.3 85 86 // ms per ticks 87 #define TICKS_LEN 10 88 89 // Writes sensor configuration (resolution) 90 bit Ds18B20WriteConfig( uns8 value ); 91 92 // Resets OneWire 93 bit OneWireReset(); 94 // Reads OneWire byte 95 uns8 OneWireReadByte(); 96 // Writes OneWire byte 97 void OneWireWriteByte( uns8 byte ); 98 99 // DS18B20 commands 100 #define CMD_READROM 0x33 101 #define CMD_CONVERTTEMP 0x44 102 #define CMD_CPYSCRATCHPAD 0x48 103 #define CMD_WSCRATCHPAD 0x4e 104 #define CMD_MATCHROM 0x55 105 #define CMD_RPWRSUPPLY 0xb4 106 #define CMD_RECEEPROM 0xb8 107 #define CMD_RSCRATCHPAD 0xbe 108 #define CMD_SKIPROM 0xcc 109 #define CMD_ALARMSEARCH 0xec 110 #define CMD_SEARCHROM 0xf0 111 112 // Final DS18B20 temperature value read by state machine 113 uns16 temperature; 114 115 #else // DALLASnotMCP 116 117 // I2C SCL frequency [Hz] 118 #define I2Cfrequency 50000 119 120 // MCP9802 address 121 #define I2C_ADR 0b10010110 122 // Power pin 123 #define PWR_SENSOR_TRIS TRISC.7 124 #define PWR_SENSOR_IO LATC.7 125 126 #endif 127 128 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 129 //############################################################################################ 130 bit CustomDpaHandler() 131 //############################################################################################ 132 { 133 // 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) 134 #pragma updateBank default = UserBank_01 135 136 #ifdef DALLASnotMCP 137 // Finite machine states 138 typedef enum 139 { 140 S_ResetConvertT = 0, 141 S_SkipRomConvertT, 142 S_CmdConvertT, 143 144 S_WaitConvertT, 145 146 S_ResetReadTemp, 147 S_SkipRomReadTemp, 148 S_CmdReadTemp, 149 S_Byte1ReadTemp, 150 S_Byte2ReadTemp 151 } TState; 152 #endif 153 154 // Handler presence mark 155 clrwdt(); 156 157 // Sleeping parameters, valid when Time != 0 158 static TPerOSSleep_Request PerOSSleep_Request; 159 160 #ifdef DALLASnotMCP 161 // Finite machine state 162 static uns8 state; // = S_ResetConvertT = 0 163 // Pre-read lower temperature byte 164 static uns8 temperatureByteLow; 165 // Conversion timeout counter 166 static uns16 timeoutStart; 167 #endif 168 169 // Detect DPA event to handle 170 switch ( GetDpaEvent() ) 171 { 172 // ------------------------------------------------- 173 case DpaEvent_Interrupt: 174 // Do an extra quick background interrupt work 175 176 return Carry; 177 178 // ------------------------------------------------- 179 case DpaEvent_Idle: 180 // Do a quick background work when RF packet is not received 181 182 // Should go to sleep? 183 if ( PerOSSleep_Request.Time != 0 ) 184 { 185 // Copy sleep parameters to the DPA request 186 _DpaMessage.PerOSSleep_Request.Time = PerOSSleep_Request.Time; 187 _DpaMessage.PerOSSleep_Request.Control = PerOSSleep_Request.Control; 188 // Finalize OS Sleep DPA Request 189 _DpaDataLength = sizeof( _DpaMessage.PerOSSleep_Request ); 190 _PNUM = PNUM_OS; 191 _PCMD = CMD_OS_SLEEP; 192 #ifndef DALLASnotMCP 193 // I2C down 194 _DpaApiI2Cshutdown(); 195 #endif 196 // Perform local DPA Request to go to sleep 197 DpaApiLocalRequest(); 198 #ifndef DALLASnotMCP 199 // I2C up 200 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 201 #endif 202 // Switch off sleeping time=flag 203 PerOSSleep_Request.Time = 0; 204 } 205 206 #ifdef DALLASnotMCP 207 // Run finite state machine to read temperature from DS18B20 at background so the temperature value is immediately ready for FRC 208 209 // Make sure 1Wire data pin at LATX.y is low as it might be set by another PORTX.? pin manipulation 210 OneWire_IO_OUT = 0; 211 212 skip( state ); 213 #pragma computedGoto 1 214 goto _S_ResetConvertT; 215 goto _S_SkipRomConvertT; 216 goto _S_CmdConvertT; 217 goto _S_WaitConvertT; 218 goto _S_ResetReadTemp; 219 goto _S_SkipRomReadTemp; 220 goto _S_CmdReadTemp; 221 goto _S_Byte1ReadTemp; 222 goto _S_Byte2ReadTemp; 223 #pragma computedGoto 0 224 ; 225 // -------------- 226 _S_Byte2ReadTemp: 227 temperature.high8 = OneWireReadByte(); 228 temperature.low8 = temperatureByteLow; 229 230 ResetMachine: 231 state = S_ResetConvertT; 232 goto ExitMachine; 233 234 // -------------- 235 _S_ResetConvertT: 236 _S_ResetReadTemp: 237 if ( !OneWireReset() ) 238 { 239 _S_Error_Reset: 240 STD_SENSOR_TYPE_TEMPERATURE_SET_ERROR( temperature ); 241 goto ResetMachine; 242 } 243 goto NextState; 244 245 // -------------- 246 _S_SkipRomConvertT: 247 _S_SkipRomReadTemp: 248 // OneWire: Skip ROM 249 OneWireWriteByte( CMD_SKIPROM ); 250 goto NextState; 251 252 // -------------- 253 _S_CmdConvertT: 254 // OneWire: Convert temperature 255 OneWireWriteByte( CMD_CONVERTTEMP ); 256 // Start timeout for approx 750 ms (the longest conversion time) 257 captureTicks(); 258 // Remember start time 259 timeoutStart = param3; 260 goto NextState; 261 262 // -------------- 263 _S_WaitConvertT: 264 // Measured? 265 if ( OneWireReadByte() == 0xff ) 266 goto NextState; 267 268 // Timeout? 269 captureTicks(); 270 param3 -= timeoutStart; 271 // Yes! 272 if ( param3 > ( 2 + 750 / TICKS_LEN ) ) 273 goto _S_Error_Reset; 274 275 goto ExitMachine; 276 277 // -------------- 278 _S_CmdReadTemp: 279 // OneWire: Read scratchpad 280 OneWireWriteByte( CMD_RSCRATCHPAD ); 281 goto NextState; 282 283 // -------------- 284 _S_Byte1ReadTemp: 285 temperatureByteLow = OneWireReadByte(); 286 goto NextState; 287 288 // -------------- 289 NextState: 290 ++state; 291 292 ExitMachine: 293 #endif 294 break; 295 296 // ------------------------------------------------- 297 case DpaEvent_Init: 298 // Do a one time initialization before main loop starts 299 300 // Initialize ticks 301 startCapture(); 302 303 // Initialize sensors 304 // C5 (AN4) as input 305 moduleInfo(); 306 // Connected TR pins? 307 if ( !bufferINFO[5].7 ) 308 { 309 TRISC.6 = 1; 310 TRISB.4 = 1; 311 } 312 TRISA.5 = 1; 313 314 // C1 (AN0) as input 315 TRISA.0 = 1; 316 317 #ifdef DALLASnotMCP 318 // Setup DS18B20 for 9bit precision, conversion takes 94ms (see datasheet) 319 Ds18B20WriteConfig( 0b0.00.00000 ); 320 #else 321 // Expect MCP9802 is enabled 322 I2Ctimeout = 0xFF; 323 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 324 #endif 325 break; 326 327 // ------------------------------------------------- 328 case DpaEvent_AfterSleep: 329 // Called after woken up after sleep 330 #ifndef DALLASnotMCP 331 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 332 #endif 333 334 break; 335 336 // ------------------------------------------------- 337 case DpaEvent_BeforeSleep: 338 // Called before going to sleep 339 #ifndef DALLASnotMCP 340 _DpaApiI2Cshutdown(); 341 #endif 342 break; 343 344 // ------------------------------------------------- 345 case DpaEvent_DpaRequest: 346 // Called to interpret DPA request for peripherals 347 // ------------------------------------------------- 348 // Peripheral enumeration 349 IfDpaEnumPeripherals_Else_PeripheralInfo_Else_PeripheralRequest() 350 { 351 // We implement 2 standard peripherals 352 _DpaMessage.EnumPeripheralsAnswer.UserPerNr = 1; 353 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_STD_SENSORS ); 354 _DpaMessage.EnumPeripheralsAnswer.HWPID |= _HWPID_; 355 _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= _HWPIDver_; 356 357 DpaHandleReturnTRUE: 358 return TRUE; 359 } 360 // ------------------------------------------------- 361 // Get information about peripherals 362 else 363 { 364 switch ( _DpaMessage.PeripheralInfoAnswer.PerT = _PNUM ) 365 { 366 case PNUM_STD_SENSORS: 367 // Set standard version 368 _DpaMessage.PeripheralInfoAnswer.Par1 = STD_SENSORS_VERSION; 369 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE; 370 goto DpaHandleReturnTRUE; 371 } 372 373 break; 374 } 375 376 { 377 // ------------------------------------------------- 378 // Handle peripheral command 379 380 // Supported peripheral number? 381 switch ( _PNUM ) 382 { 383 case PNUM_STD_SENSORS: 384 { 385 // Supported commands? 386 switch ( _PCMD ) 387 { 388 // Invalid command 389 default: 390 { 391 // Return error 392 _ERROR_PCMD: 393 W = ERROR_PCMD; 394 _ERROR_W: 395 DpaApiReturnPeripheralError( W ); 396 } 397 398 // Sensor enumeration 399 case PCMD_STD_ENUMERATE: 400 if ( _DpaDataLength != 0 ) 401 { 402 _ERROR_DATA_LEN: 403 W = ERROR_DATA_LEN; 404 goto _ERROR_W; 405 } 406 407 _DpaMessage.Response.PData[0] = STD_SENSOR_TYPE_TEMPERATURE; 408 _DpaMessage.Response.PData[1] = STD_SENSOR_TYPE_BINARYDATA7; 409 _DpaMessage.Response.PData[2] = STD_SENSOR_TYPE_BINARYDATA7; 410 W = SENSORS_COUNT; 411 goto _W2_DpaDataLength; 412 413 // Supported commands. They are handled the same way except one "if" at StoreValue() method 414 case PCMD_STD_SENSORS_READ_VALUES: 415 case PCMD_STD_SENSORS_READ_TYPES_AND_VALUES: 416 { 417 // No sensor bitmap specified? W = _DpaDataLength. Note: W is used to avoid MOVLB at next if 418 W = _DpaDataLength; 419 if ( W == 0 ) // Note: must not modify W 420 { 421 // Actually clears the bitmap 422 #if &_DpaMessageIqrfStd.PerStdSensorRead_Request.Bitmap[0] != &bufferRF[0] 423 #error Cannot use clearBufferRF for clearing bitmap 424 #endif 425 clearBufferRF(); 426 // Simulate 1st only sensor in the bitmap (states of the other unimplemented sensors do not care) 427 _DpaMessageIqrfStd.PerStdSensorRead_Request.Bitmap[0].0 = 1; 428 // Bitmap is 32 bits long 429 _DpaDataLength = W = sizeof( _DpaMessageIqrfStd.PerStdSensorRead_Request.Bitmap ); 430 } 431 432 // Invalid bitmap (data) length (W = _DpaDataLength)? 433 if ( W != sizeof( _DpaMessageIqrfStd.PerStdSensorRead_Request.Bitmap ) ) 434 goto _ERROR_DATA_LEN; 435 436 // Now read the sensors 437 438 // Prepare pointer (minus 1, see below) to store sensor (types and) values to 439 // Note: 3 sensors at this example cannot return more than DPA_MAX_DATA_LENGTH bytes of data, so it does not have to be checked... 440 // ... If it would be the case, then ERROR_FAIL must be returned 441 FSR1 = &_DpaMessage.Response.PData[-1]; 442 443 // Store bitmap of sensors to get values from 444 uns8 sensorsBitmap = FSR1[1 + offsetof( TPerStdSensorRead_Request, Bitmap )]; 445 446 // 1st sensor (index 0) selected? 447 if ( sensorsBitmap.0 ) 448 { 449 Get0_Temperature(); 450 StoreValue( STD_SENSOR_TYPE_TEMPERATURE ); 451 } 452 453 // 2nd sensor (index 1) selected? 454 if ( sensorsBitmap.1 ) 455 { 456 Get1_BinaryData_Light(); 457 StoreValue( STD_SENSOR_TYPE_BINARYDATA7 ); 458 } 459 460 // 3rd sensor (index 2) selected? 461 if ( sensorsBitmap.2 ) 462 { 463 Get2_BinaryData_Potentiometer(); 464 StoreValue( STD_SENSOR_TYPE_BINARYDATA7 ); 465 } 466 467 // Compute returned data bytes count 468 W = FSR1L - ( (uns16)&_DpaMessageIqrfStd & 0xFF ) + 1; 469 // Optimization: return W long block of bytes at response 470 _W2_DpaDataLength: 471 _DpaDataLength = W; 472 goto DpaHandleReturnTRUE; 473 } 474 } 475 } 476 } 477 478 break; 479 } 480 481 // ------------------------------------------------- 482 case DpaEvent_FrcValue: 483 // Called to get FRC value 484 485 // FSR1 for optimization purposes (avoid MOVLB) will be used to point to DataOutBeforeResponseFRC[0...] 486 FSR1 = (uns16)&PerStdSensorFrc; 487 #if offsetof( TPerStdSensorFrc, Header ) != 0 || offsetof( TPerStdSensorFrc, SensorType ) != 1 || offsetof( TPerStdSensorFrc, Options ) != 3 488 #error Cannot optimize 489 #endif 490 // Check for correct FRC user data 491 if ( *FSR1++ /* PerStdSensorFrc.Header */ == PNUM_STD_SENSORS ) 492 { 493 // Actually used sensor index 494 uns8 sensorIndex = FSR1[offsetof( TPerStdSensorFrc, SensorIndex ) - 1] & 0x1f; 495 // Test sensor type 496 switch ( *FSR1++ /* PerStdSensorFrc.SensorType */ ) 497 { 498 default: 499 goto DpaHandleReturnFALSE; 500 501 // No type specified, use specified index value 502 case 0x00: 503 goto _KeepSensorIndex; 504 505 // For other types make the index value based on the requested index value and sensor type 506 case STD_SENSOR_TYPE_TEMPERATURE: 507 if ( sensorIndex > 0 ) 508 goto DpaHandleReturnFALSE; 509 W = 0 + sensorIndex; 510 break; 511 512 case STD_SENSOR_TYPE_BINARYDATA7: 513 if ( sensorIndex > 1 ) 514 goto DpaHandleReturnFALSE; 515 W = 1 + sensorIndex; 516 break; 517 } 518 519 // New sensor index based on type and requested index 520 sensorIndex = W; 521 _KeepSensorIndex: 522 523 // Test for supported FRC commands 524 switch ( _PCMD ) 525 { 526 default: 527 goto DpaHandleReturnFALSE; 528 529 case FRC_STD_SENSORS_BIT: 530 case FRC_STD_SENSORS_1B: 531 case FRC_STD_SENSORS_2B: 532 switch ( sensorIndex ) 533 { 534 default: 535 goto DpaHandleReturnFALSE; 536 537 case 0: 538 Carry = Get0_Temperature(); 539 break; 540 541 case 1: 542 Carry = Get1_BinaryData_Light(); 543 break; 544 545 case 2: 546 Carry = Get2_BinaryData_Potentiometer(); 547 break; 548 } 549 550 // This type of FRC is not valid for the specified sensor 551 if ( !Carry ) 552 goto DpaHandleReturnFALSE; 553 554 break; 555 } 556 557 // Some sensor was measured by FRC, check if there is a sleep request 558 FSR1++; 559 if ( INDF1.0 ) // Note: same as PerStdSensorFrc.Options.0 560 { 561 // Remember sleep parameters to go to sleep at the Idle event later 562 PerOSSleep_Request.Time.low8 = FSR1[offsetof( TPerOSSleep_Request, Time ) + 0 + offsetof( TPerStdSensorFrc, SleepParameters ) - 3]; 563 PerOSSleep_Request.Time.high8 = FSR1[offsetof( TPerOSSleep_Request, Time ) + 1 + offsetof( TPerStdSensorFrc, SleepParameters ) - 3]; 564 PerOSSleep_Request.Control = FSR1[offsetof( TPerOSSleep_Request, Control ) + offsetof( TPerStdSensorFrc, SleepParameters ) - 3]; 565 } 566 } 567 568 break; 569 570 // ------------------------------------------------- 571 case DpaEvent_FrcResponseTime: 572 // Called to get FRC response time 573 574 // In this example the FRC commands are fast 575 switch ( DataOutBeforeResponseFRC[0] ) 576 { 577 case FRC_STD_SENSORS_BIT: 578 case FRC_STD_SENSORS_1B: 579 case FRC_STD_SENSORS_2B: 580 responseFRCvalue = _FRC_RESPONSE_TIME_40_MS; 581 break; 582 } 583 break; 584 } 585 DpaHandleReturnFALSE: 586 return FALSE; 587 } 588 589 //############################################################################################ 590 bit returnTRUE() 591 //############################################################################################ 592 { 593 return TRUE; 594 } 595 596 //############################################################################################ 597 bit returnFALSE() 598 //############################################################################################ 599 { 600 return FALSE; 601 } 602 603 //############################################################################################ 604 // Increases FSR1 and then stores the byte 605 void setPlusPlusINDF1( uns8 data @ W ) 606 //############################################################################################ 607 { 608 FSR1++; // Note: must not modify W 609 setINDF1( data ); 610 } 611 612 //############################################################################################ 613 // Stores measured sensor value byte(s) and optionally sensor type to the FSR[+1...] 614 void StoreValue( uns8 sensorType ) 615 //############################################################################################ 616 { 617 // Is the sensor type to be stored too? 618 if ( _PCMD == PCMD_STD_SENSORS_READ_TYPES_AND_VALUES ) 619 setPlusPlusINDF1( sensorType ); 620 621 // Store lower value byte 622 setPlusPlusINDF1( sensorValue.low8 ); 623 624 // No more value bytes to store? 625 if ( sensorType.7 != 0 ) 626 return; 627 628 // Store higher value byte 629 setPlusPlusINDF1( sensorValue.high8 ); 630 631 // Note: this example implements sensors returning only 1 or 2 bytes of data. If another data widths are returned, then it must be implemented explicitly. 632 } 633 634 //############################################################################################ 635 bit setFRCerror() 636 //############################################################################################ 637 { 638 responseFRCvalue2B = FRC_STD_FRC_ERROR_VALUE; 639 return returnTRUE(); 640 } 641 642 //############################################################################################ 643 bit sensorError; 644 bit AdjustFrcTemperature() 645 //############################################################################################ 646 { 647 // Test for supported FRC commands 648 switch ( _PCMD ) 649 { 650 default: 651 return returnFALSE(); 652 653 case FRC_STD_SENSORS_1B: 654 // Return sensor FRC value 1B 655 // Check for out of limits 656 if ( sensorError || (int16)sensorValue > (int16)( 105.5 * 16 ) || (int16)sensorValue < ( (int16)-20 * 16 ) ) 657 return setFRCerror(); 658 659 // Convert to the "F = ( T + 22 ) * 2 " from 1/16 resolution 660 responseFRCvalue2B = sensorValue + 4; // Note: do rounding when /8 661 responseFRCvalue2B /= 8; 662 responseFRCvalue += 44; 663 break; 664 665 case FRC_STD_SENSORS_2B: 666 // Return sensor FRC value 2B 667 if ( sensorError ) 668 return setFRCerror(); 669 670 responseFRCvalue2B = sensorValue ^ 0x8000; 671 break; 672 } 673 674 return returnTRUE(); 675 } 676 677 //############################################################################################ 678 // Sensor index 1: measure temperature using one of the DDC-SE-01 sensors 679 bit Get0_Temperature() 680 //############################################################################################ 681 { 682 // Make sure FSR1 is not modified 683 684 // Measure temperature using DDC-SE-01 sensors 685 // Read temperature and check for an error 686 687 // Reads temperature from an enabled sensor 688 #ifdef DALLASnotMCP 689 sensorError = FALSE; 690 // Temperature is ready at the background 691 sensorValue = temperature; 692 // When error, return standard (FRC) error value(s) 693 if ( STD_SENSOR_TYPE_TEMPERATURE_IS_ERROR( sensorValue ) ) 694 sensorError = TRUE; 695 #else 696 sensorError = TRUE; 697 // Temperature value must be read from I2C sensor 698 STD_SENSOR_TYPE_TEMPERATURE_SET_ERROR( sensorValue ); 699 // MCP9802 address 700 _DpaApiI2Cstart( I2C_ADR ); 701 if ( !I2CwasTimeout ) 702 { 703 // pointer: 1 = configuration register 704 _DpaApiI2Cwrite( 0x01 ); 705 // configuration: 9-bit ADC 706 _DpaApiI2CwriteAndStop( 0x00 ); 707 708 // MCP9802 address 709 _DpaApiI2Cstart( I2C_ADR ); 710 // pointer: 0 = temperature 711 _DpaApiI2CwriteAndStop( 0 ); 712 713 // MCP9802 address + read 714 _DpaApiI2Cstart( I2C_ADR | 1 ); 715 // store the result 716 sensorValue.high8 = _DpaApiI2Cread( TRUE ); 717 sensorValue.low8 = _DpaApiI2Cread( FALSE ); 718 _DpaApiI2Cstop(); 719 720 sensorValue += 0x10 / 2; 721 sensorValue /= 0x10; 722 723 sensorError = FALSE; 724 } 725 #endif 726 727 // FrcValues 728 return AdjustFrcTemperature(); 729 } 730 731 //############################################################################################ 732 // Sensor index 1: returns light intensity indicator value using DDC-SE-01 733 bit Get_BinaryData_Final( uns8 _ADCON0 @ W ) 734 //############################################################################################ 735 { 736 ADCON0 = _ADCON0; 737 // Read ADC 738 739 // ADC result - left justified, Fosc/8 740 ADCON1 = 0b0001.0000; 741 // Do a smallest delay for ADC ACQUISITION TIME 742 waitMS( 1 ); 743 // start ADC 744 GO = 1; 745 // wait for ADC finish 746 while ( GO ); 747 // Get ADC value 748 sensorValue.low8 = ADRESH / 2; 749 750 // Return sensor FRC value 751 752 // Test for supported FRC commands 753 switch ( _PCMD ) 754 { 755 default: 756 return returnFALSE(); 757 758 case FRC_STD_SENSORS_BIT: 759 // If there is a sensor error, 2-bit FRC cannot indicate it, it returns [01] 760 761 // Number of shifts to get the bit out of the return value 762 uns8 bitLoop = ( INDF1 >> 5 ) + 1; 763 // Value to get the bit from 764 W = sensorValue.low8; 765 do 766 { 767 // Get the bit to Carry 768 W = rr( W ); 769 // Next bit 770 } while ( --bitLoop != 0 ); // Note: must not modify W and Carry 771 // Current (prepared by DPA) FRC value is [01], change it to [11] (means bit is set) 772 responseFRCvalue.1 = 1; // Note: must not modify Carry 773 // Is bit set? 774 if ( !Carry ) 775 // Bit is NOT set, return [10] 776 responseFRCvalue.0 = 0; 777 break; 778 779 case FRC_STD_SENSORS_1B: 780 responseFRCvalue = sensorValue.low8 + 4; 781 break; 782 } 783 784 return returnTRUE(); 785 } 786 787 //############################################################################################ 788 // Sensor index 1: returns light intensity indicator value using DDC-SE-01 789 bit Get1_BinaryData_Light() 790 //############################################################################################ 791 { 792 // Make sure FSR1 is not modified 793 794 // ADC initialization (for more info see PIC datasheet) pin C1 (AN0) as analog input 795 ANSELA.0 = 1; 796 // ADC setting (AN0 channel) 797 return Get_BinaryData_Final( 0b0.00000.01 ); 798 } 799 800 //############################################################################################ 801 // Sensor index 2: returns potentiometer value using DDC-SE-01 802 bit Get2_BinaryData_Potentiometer() 803 //############################################################################################ 804 { 805 // Make sure FSR1 is not modified 806 807 // ADC initialization (for more info see PIC datasheet) pin C5 (AN4) as analog input 808 ANSELA.5 = 1; 809 // ADC setting (AN4 channel) 810 return Get_BinaryData_Final( 0b0.00100.01 ); 811 } 812 813 #ifdef DALLASnotMCP 814 //############################################################################################ 815 // OneWire and Dallas 18B20 routines 816 //############################################################################################ 817 818 //############################################################################################ 819 void Delay5us( uns8 val @ W ) // Absolutely precise timing but val != 0 820 //############################################################################################ 821 { 822 // 16 MHz 823 // + 0.75us ( W=val, Call ) 824 for ( ;; ) 825 { // loop time 826 nop2(); // 0.50us 827 nop2(); // 1.00us 828 nop2(); // 1.50us 829 nop2(); // 2.00us 830 nop2(); // 2.50us 831 nop2(); // 3.00us 832 nop(); // 3.25us 833 if ( --val == 0 ) // + 0.75us (W--, BTFS ) 834 return; // + 0.25us 835 nop2(); // 4.50us 836 } // 5.00us (Goto) 837 } 838 //############################################################################################ 839 840 #define OneWireData0() { OneWire_TRIS = 0; } // 0.5us @ 16MHz 841 #define OneWireData1() { OneWire_TRIS = 1; } // 0.5us @ 16MHz 842 843 //############################################################################################ 844 void OneWireWriteByte( uns8 byte ) 845 //############################################################################################ 846 { 847 uns8 bitLoop = 8; 848 do 849 { 850 // Next sequence is time precision critical 851 GIE = FALSE; 852 853 OneWireData0(); 854 nop2(); // 1 us [0.5 us] 855 nop2(); // [1.0 us] 856 if ( byte.0 ) // 2.5 us [1.75us] 857 OneWireData1(); 858 859 // End of time precision critical sequence 860 GIE = TRUE; 861 862 // 60us minimum in total, does not have to be precise 863 Delay5us( ( 60 - 3 ) / 5 + 1 ); 864 865 OneWireData1(); 866 867 byte >>= 1; 868 } while ( --bitLoop != 0 ); 869 } 870 871 //############################################################################################ 872 uns8 OneWireReadByte() 873 //############################################################################################ 874 { 875 uns8 result; 876 uns8 bitLoop = 8; 877 do 878 { 879 // Next sequence is time precision critical 880 GIE = FALSE; 881 882 OneWireData0(); 883 nop2(); // 1 us [0.5 us] 884 #if F_OSC == 16000000 885 nop2(); // [1.0 us] 886 #endif 887 OneWireData1(); // 2 us [1.5 us] 888 Delay5us( 15 / 5 ); // 17 us [16.5 us] 889 890 Carry = 0; // 17.5 us [16.75 us] 891 if ( OneWire_IO_IN ) // 18.5 us [ 17.25 us] (condition must not modify Carry) 892 Carry = 1; 893 894 // End of time precision critical sequence 895 GIE = TRUE; // must not modify Carry 896 result = rr( result ); 897 898 // 60us minimum in total, does not have to be precise 899 Delay5us( ( 60 - 20 ) / 5 + 1 ); 900 } while ( --bitLoop != 0 ); 901 902 return result; 903 } 904 905 //############################################################################################ 906 bit OneWireReset() 907 //############################################################################################ 908 { 909 // Setting the pin once to low is enough 910 OneWire_IO_OUT = 0; 911 // Reset pulse 912 OneWireData0(); 913 Delay5us( 500 / 5 ); 914 // Reset pulse end 915 OneWireData1(); 916 // Next sequence is time precision critical 917 GIE = FALSE; 918 // Wait for presence pulse 919 Delay5us( 70 / 5 ); 920 // End of time precision critical sequence 921 GIE = TRUE; 922 // Presence pulse? 923 if ( OneWire_IO_IN ) 924 { 925 // No presence, finish initialization sequence 926 Delay5us( ( 500 - 70 ) / 5 ); 927 return returnFALSE(); 928 } 929 else 930 { 931 // Presence OK, finish initialization sequence 932 Delay5us( ( 500 - 70 ) / 5 ); 933 return returnTRUE(); 934 } 935 } 936 937 //############################################################################################ 938 void OneWireCmd( uns8 cmd ) 939 //############################################################################################ 940 { 941 // OneWire: Skip ROM 942 OneWireWriteByte( CMD_SKIPROM ); 943 // OneWire: Send command 944 OneWireWriteByte( cmd ); 945 } 946 947 //############################################################################################ 948 bit Ds18B20WriteConfig( uns8 value ) 949 //############################################################################################ 950 { 951 if ( OneWireReset() ) 952 { 953 // Write Scratchpad 954 OneWireCmd( CMD_WSCRATCHPAD ); 955 956 // Write TL = ? (we dot not care the value) 957 OneWireWriteByte( W ); 958 // Write TH = ? (we dot not care the value) 959 OneWireWriteByte( W ); 960 // Write Config byte 961 OneWireWriteByte( value ); 962 963 if ( OneWireReset() ) 964 { 965 // Copy Scratchpad 966 OneWireCmd( CMD_CPYSCRATCHPAD ); 967 return returnTRUE(); 968 } 969 } 970 return returnFALSE(); 971 } 972 973 #endif // DALLASnotMCP 974 975 //############################################################################################ 976 // 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) 977 #include "DPAcustomHandler.h" 978 //############################################################################################