1 // ********************************************************************* 2 // Custom DPA Handler code example - DDC-SE-01 and/or DDC-RE-01 * 3 // ********************************************************************* 4 // Copyright (c) MICRORISC s.r.o. 5 // 6 // File: $RCSfile: CustomDpaHandler-DDC-Core.c,v $ 7 // Version: $Revision: 1.33 $ 8 // Date: $Date: 2022/02/25 09:41:25 $ 9 // 10 // Revision history: 11 // 2022/02/24 Release for DPA 4.17 12 // 2021/08/20 Release for DPA 4.16 13 // 2020/01/02 Release for DPA 4.11 14 // 2017/03/13 Release for DPA 3.00 15 // 2016/12/22 Release for DPA 2.28 16 // 17 // ********************************************************************* 18 19 // Online DPA documentation https://doc.iqrf.org/DpaTechGuide/ 20 21 /* This example implements HWP for DDC-SE-01 and/or DDC-RE-01 22 23 DDC-SE-01: HWPID=0x001F 24 DDC-RE-01: HWPID=0x002F 25 DDC-SE-01 & DDC-RE-01: HWPID=0x003F 26 27 ! Make sure embedded UART DPA peripheral is not enabled to avoid a collision of peripherals 28 29 ----------- DDC-SE-01 30 Request: PNUM = 0x20, PCMD = 0x31 31 Response: 32 PData[0]=Temperature at [C] 33 PData[1]=Photoresistor value 0x00-0xFF 34 PData[2]=Potentiometer value 0x00-0xFF 35 returns ERROR_FAIL when error reading temperature 36 37 FRC=0xC0, returns temperature at C, 127 for 0 C, 0x80 for error reading temperature 38 FRC=0xC1, returns photoresistor value, returns 1 instead of 0 39 FRC=0xC2, returns potentiometer value, returns 1 instead of 0 40 41 ----------- DDC-RE-01 42 Request: PNUM = 0x20, PCMD = 0x32 43 PData[0]=Relay1Ctrl 44 PData[1]=Relay2Ctrl 45 46 Response: 47 PData[0]=Relay1State 48 PData[1]=Relay2State 49 50 RelayCtrl: 0=Switch the Relay off, 1=Switch the Relay on, Other=Do not control the Relay 51 RelayState: 0=Relay was off, 1=Relay was on 52 */ 53 54 // ********************************************************************* 55 56 // Default IQRF include (modify the path according to your setup) 57 #include "IQRF.h" 58 59 // Default DPA header (modify the path according to your setup) 60 #include "DPA.h" 61 // Default Custom DPA Handler header (modify the path according to your setup) 62 #include "DPAcustomHandler.h" 63 64 #if defined( DDC_SE_01 ) && defined( DDC_RE_01 ) 65 #define ThisHWPID 0x003F 66 #elif defined( DDC_SE_01 ) 67 #define ThisHWPID 0x001F 68 #elif defined( DDC_RE_01 ) 69 #define ThisHWPID 0x002F 70 #else 71 #error Symbol(s) DDC_SE_01 and/or DDC_RE_01 must be defined 72 #endif 73 74 //############################################################################################ 75 76 #if defined( DDC_SE_01 ) 77 78 // Special temperature value to indicate a sensor error 79 #define ERROR_TEMPERATURE 0xF800 80 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 // Writes sensor configuration (resolution) 87 bit Ds18B20WriteConfig( uns8 value ); 88 89 // Resets OneWire 90 bit OneWireReset(); 91 // Reads OneWire byte 92 uns8 OneWireReadByte(); 93 // Writes OneWire byte 94 void OneWireWriteByte( uns8 byte ); 95 96 // DS18B20 commands 97 #define CMD_READROM 0x33 98 #define CMD_CONVERTTEMP 0x44 99 #define CMD_CPYSCRATCHPAD 0x48 100 #define CMD_WSCRATCHPAD 0x4e 101 #define CMD_MATCHROM 0x55 102 #define CMD_RPWRSUPPLY 0xb4 103 #define CMD_RECEEPROM 0xb8 104 #define CMD_RSCRATCHPAD 0xbe 105 #define CMD_SKIPROM 0xcc 106 #define CMD_ALARMSEARCH 0xec 107 #define CMD_SEARCHROM 0xf0 108 109 // I2C SCL frequency [Hz] 110 #define I2Cfrequency 50000 111 112 // MCP9802 address 113 #define I2C_ADR 0b1001.0110 114 115 // Sensors read routines 116 uns16 GetTemperature(); 117 uns8 ReadAdcPhotoresistor(); 118 uns8 ReadAdcPotentiometer(); 119 120 // TRUE if DS18B20 is enabled, FALSE in case of MCP9802 121 bit isDS18B20; 122 // Final DS18B20 temperature value 123 uns16 temperature; 124 125 #endif 126 127 #if defined( DDC_RE_01 ) 128 129 // C.5 = C8 = Relay#1 130 #define RELAY1_LAT LATC.5 131 #define RELAY1_TRIS TRISC.5 132 133 // C.2 = C2 = Relay#2 134 #define RELAY2_LAT LATC.2 135 #define RELAY2_TRIS TRISC.2 136 137 #endif 138 139 // Must be the 1st defined function in the source code in order to be placed at the correct FLASH location! 140 //############################################################################################ 141 bit CustomDpaHandler() 142 //############################################################################################ 143 { 144 #if defined( DDC_SE_01 ) 145 // Finite machine states 146 typedef enum 147 { 148 S_ResetConvertT = 0, 149 S_SkipRomConvertT, 150 S_CmdConvertT, 151 152 S_WaitConvertT, 153 154 S_ResetReadTemp, 155 S_SkipRomReadTemp, 156 S_CmdReadTemp, 157 S_Byte1ReadTemp, 158 S_Byte2ReadTemp 159 } TState; 160 161 #endif 162 163 // Handler presence mark 164 clrwdt(); 165 166 #if defined( DDC_SE_01 ) 167 // Finite machine state 168 static uns8 state; // = S_ResetConvertT = 0 169 // Pre-read lower temperature byte 170 static uns8 temperatureByteLow; 171 // Conversion timeout counter 172 static uns8 timeout; 173 #endif 174 175 // Detect DPA event to handle 176 switch ( GetDpaEvent() ) 177 { 178 // ------------------------------------------------- 179 case DpaEvent_Interrupt: 180 // Do an extra quick background interrupt work 181 // ! 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. 182 // ! 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. 183 // ! 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. 184 // ! Only global variables or local ones marked by static keyword can be used to allow reentrancy. 185 // ! Make sure race condition does not occur when accessing those variables at other places. 186 // ! 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. 187 // ! Do not call any OS functions except setINDFx(). 188 // ! Do not use any OS variables especially for writing access. 189 // ! 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. 190 191 #if defined( DDC_SE_01 ) 192 #define TICKS_LEN 10 193 194 // If TMR6 interrupt occurred 195 if ( TMR6IF ) 196 { 197 // Unmask interrupt 198 TMR6IF = 0; 199 // Decrement count 200 if ( timeout != 0 ) 201 timeout--; 202 } 203 #endif 204 return Carry; 205 206 #if defined( DDC_SE_01 ) 207 // ------------------------------------------------- 208 case DpaEvent_Idle: 209 // Do a quick background work when RF packet is not received 210 211 // Run finite state machine to read temperature from DS18B20 at background so the temperature value is immediately ready for FRC 212 if ( !isDS18B20 ) 213 break; 214 215 // Make sure 1Wire data pin at LATX.y is low as it might be set by another PORTX.? pin manipulation 216 OneWire_IO_OUT = 0; 217 218 skip( state ); 219 #pragma computedGoto 1 220 goto _S_ResetConvertT; 221 goto _S_SkipRomConvertT; 222 goto _S_CmdConvertT; 223 goto _S_WaitConvertT; 224 goto _S_ResetReadTemp; 225 goto _S_SkipRomReadTemp; 226 goto _S_CmdReadTemp; 227 goto _S_Byte1ReadTemp; 228 goto _S_Byte2ReadTemp; 229 #pragma computedGoto 0 230 ; 231 // -------------- 232 _S_Byte2ReadTemp: 233 temperature.high8 = OneWireReadByte(); 234 temperature.low8 = temperatureByteLow; 235 236 ResetMachine: 237 state = S_ResetConvertT; 238 goto ExitMachine; 239 240 // -------------- 241 _S_ResetConvertT: 242 _S_ResetReadTemp: 243 if ( !OneWireReset() ) 244 { 245 _S_Error_Reset: 246 temperature = ERROR_TEMPERATURE; 247 goto ResetMachine; 248 } 249 goto NextState; 250 251 // -------------- 252 _S_SkipRomConvertT: 253 _S_SkipRomReadTemp: 254 // OneWire: Skip ROM 255 OneWireWriteByte( CMD_SKIPROM ); 256 goto NextState; 257 258 // -------------- 259 _S_CmdConvertT: 260 // OneWire: Convert temperature 261 OneWireWriteByte( CMD_CONVERTTEMP ); 262 // Setup timeout for approx 750 ms (the longest conversion time) 263 timeout = 2 + 750 / TICKS_LEN; 264 goto NextState; 265 266 // -------------- 267 _S_WaitConvertT: 268 if ( OneWireReadByte() == 0xff ) 269 goto NextState; 270 271 // Timeout? 272 if ( timeout == 0 ) 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 break; 294 295 // ------------------------------------------------- 296 case DpaEvent_FrcValue: 297 // Called to get FRC value 298 299 // Which FRC command? 300 switch ( _PCMD ) 301 { 302 case FRC_USER_BYTE_FROM + 0: 303 // Returns temperature 304 uns16 curTemperature = GetTemperature(); 305 if ( curTemperature == ERROR_TEMPERATURE ) 306 responseFRCvalue = 0x80; 307 else 308 { 309 responseFRCvalue = curTemperature.low8; 310 if ( responseFRCvalue == 0 ) 311 responseFRCvalue = 127; 312 } 313 break; 314 315 case FRC_USER_BYTE_FROM + 1: 316 // Returns photoresistor value 317 responseFRCvalue = ReadAdcPhotoresistor(); 318 _Zero2One: 319 if ( responseFRCvalue == 0 ) 320 responseFRCvalue |= 1; 321 break; 322 323 case FRC_USER_BYTE_FROM + 2: 324 // Returns potentiometer value 325 responseFRCvalue = ReadAdcPotentiometer(); 326 goto _Zero2One; 327 } 328 break; 329 330 // ------------------------------------------------- 331 case DpaEvent_FrcResponseTime: 332 // Called to get FRC response time 333 334 if ( DataOutBeforeResponseFRC[0] >= ( FRC_USER_BYTE_FROM + 0 ) && DataOutBeforeResponseFRC[0] <= ( FRC_USER_BYTE_FROM + 2 ) ) 335 responseFRCvalue = _FRC_RESPONSE_TIME_40_MS; 336 break; 337 #endif 338 339 // ------------------------------------------------- 340 case DpaEvent_DpaRequest: 341 { 342 // Called to interpret DPA request for peripherals 343 // ------------------------------------------------- 344 // Peripheral enumeration 345 if ( IsDpaEnumPeripheralsRequest() ) 346 { 347 // We implement 1 user peripheral 348 _DpaMessage.EnumPeripheralsAnswer.UserPerNr |= 1; 349 #ifdef FlagUserPer // Get ready for upcoming DPA 3.00 350 FlagUserPer( _DpaMessage.EnumPeripheralsAnswer.UserPer, PNUM_USER + 0 ); 351 #endif 352 _DpaMessage.EnumPeripheralsAnswer.HWPID |= ThisHWPID; 353 _DpaMessage.EnumPeripheralsAnswer.HWPIDver |= 0x0000; 354 355 DpaHandleReturnTRUE: 356 return TRUE; 357 } 358 // ------------------------------------------------- 359 // Get information about peripheral 360 else if ( IsDpaPeripheralInfoRequest() ) 361 { 362 if ( _PNUM == PNUM_USER + 0 ) 363 { 364 _DpaMessage.PeripheralInfoAnswer.PerT = PERIPHERAL_TYPE_USER_AREA; 365 #if !defined( DDC_RE_01 ) 366 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ; 367 #else 368 _DpaMessage.PeripheralInfoAnswer.PerTE = PERIPHERAL_TYPE_EXTENDED_READ_WRITE; 369 #endif 370 goto DpaHandleReturnTRUE; 371 } 372 373 break; 374 } 375 // ------------------------------------------------- 376 else 377 { 378 // Handle peripheral command 379 if ( _PNUM == PNUM_USER + 0 ) 380 { 381 switch ( _PCMD ) 382 { 383 #if defined( DDC_SE_01 ) 384 case 0x31: 385 // Read sensors 386 if ( _DpaDataLength != 0 ) 387 { 388 W = ERROR_DATA_LEN; 389 goto _ERROR_W; 390 } 391 392 // Read temperature and check for an error 393 uns16 temperature = GetTemperature(); 394 if ( temperature == ERROR_TEMPERATURE ) 395 { 396 W = ERROR_FAIL; 397 goto _ERROR_W; 398 } 399 400 _DpaMessage.Response.PData[0] = temperature.low8; 401 402 // Read other sensors 403 _DpaMessage.Response.PData[1] = ReadAdcPhotoresistor(); 404 _DpaMessage.Response.PData[2] = ReadAdcPotentiometer(); 405 406 // Return 3 bytes 407 _DpaDataLength = 3; 408 goto DpaHandleReturnTRUE; 409 #endif 410 411 #if defined( DDC_RE_01 ) 412 case 0x32: 413 // Control and return state of relays 414 if ( _DpaDataLength != 2 ) 415 { 416 W = ERROR_DATA_LEN; 417 goto _ERROR_W; 418 } 419 420 // Relay #1 421 // Get 422 userReg0 = 0; 423 if ( RELAY1_LAT ) 424 userReg0.0 = 1; 425 426 // Set 427 switch ( _DpaMessage.Request.PData[0] ) 428 { 429 case 0: 430 RELAY1_LAT = 0; 431 break; 432 case 1: 433 RELAY1_LAT = 1; 434 break; 435 } 436 _DpaMessage.Response.PData[0] = userReg0; 437 438 // Relay #2 439 // Get 440 userReg0 = 0; 441 if ( RELAY2_LAT ) 442 userReg0.0 = 1; 443 444 // Set 445 switch ( _DpaMessage.Request.PData[1] ) 446 { 447 case 0: 448 RELAY2_LAT = 0; 449 break; 450 case 1: 451 RELAY2_LAT = 1; 452 break; 453 } 454 _DpaMessage.Response.PData[1] = userReg0; 455 // Receives and returns 2 bytes 456 goto DpaHandleReturnTRUE; 457 #endif 458 459 // Invalid command 460 default: 461 W = ERROR_PCMD; 462 _ERROR_W: 463 DpaApiReturnPeripheralError( W ); 464 } 465 } 466 } 467 468 break; 469 } 470 471 // ------------------------------------------------- 472 case DpaEvent_Init: 473 // Do a one time initialization before main loop starts 474 475 #if defined( DDC_SE_01 ) 476 // Initialize sensors 477 478 // C5 as input 479 moduleInfo(); 480 // Connected TR pins? 481 if ( !bufferINFO[5].7 ) 482 { 483 TRISC.6 = 1; 484 TRISB.4 = 1; 485 } 486 // C5 as input 487 TRISA.5 = 1; 488 // C1 as input 489 TRISA.0 = 1; 490 491 // Setup TMR6 to generate ticks on the background (ticks every 10ms) 492 _PR6 = 250 - 1; 493 // Prescaler 16, Postscaler 10, 16 * 10 * 250 = 40000 = 4MHz * 10ms 494 #if defined( TR7xG ) 495 TMR6MD = 0; 496 T6CON = 0b1.100.1001; 497 // Timer2/4/6 Clock Select bits = FOSC/4 498 T6CLKCON |= 0b0000.0001; 499 #else 500 T6CON = 0b0.1001.1.10; 501 #endif 502 503 TMR6IE = TRUE; 504 505 // Setup DS18B20 for 9bit precision, conversion takes 94ms (see datasheet) 506 if ( Ds18B20WriteConfig( 0b0.00.00000 ) ) 507 // DS18B20 is enabled 508 isDS18B20 = TRUE; 509 else 510 { 511 // Expect MCP9802 is enabled 512 I2Ctimeout = 0xFF; 513 514 #if defined( TR7xG ) 515 // Do PPS for I2C 516 unlockPPS(); 517 SSP1CLKPPS = 0x13; // RC3 518 SSP1DATPPS = 0x14; // RC4 519 RC3PPS = 0x14; // SCK1/SCL1 520 RC4PPS = 0x15; // SD01/SDA1 521 lockPPS(); 522 #endif 523 524 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 525 } 526 #endif 527 528 #if defined( DDC_RE_01 ) 529 // Initialize relays 530 RELAY1_LAT = 0; 531 RELAY2_LAT = 0; 532 RELAY1_TRIS = 0; 533 RELAY2_TRIS = 0; 534 535 #endif 536 break; 537 538 #if defined( DDC_SE_01 ) 539 // ------------------------------------------------- 540 case DpaEvent_AfterSleep: 541 // Called after woken up after sleep 542 if ( !isDS18B20 ) 543 _DpaApiI2Cinit( I2CcomputeFrequency( I2Cfrequency ) ); 544 545 // Called on wake-up from sleep 546 TMR6IE = TRUE; 547 _TMR6ON = TRUE; 548 break; 549 550 // ------------------------------------------------- 551 case DpaEvent_BeforeSleep: 552 // Called before going to sleep 553 if ( !isDS18B20 ) 554 _DpaApiI2Cshutdown(); 555 556 // ------------------------------------------------- 557 case DpaEvent_DisableInterrupts: 558 // Called when device needs all hardware interrupts to be disabled (before Reset, Restart, LoadCode, Remove bond, and Run RFPGM) 559 // Must not use TMR6 any more 560 _TMR6ON = FALSE; 561 TMR6IE = FALSE; 562 break; 563 #endif 564 } 565 return FALSE; 566 } 567 568 //############################################################################################ 569 #if defined( DDC_SE_01 ) 570 571 //############################################################################################ 572 // OneWire and Dallas 18B20 routines 573 //############################################################################################ 574 575 //############################################################################################ 576 void Delay5us( uns8 val @ W ) // Absolutely precise timing but val != 0 577 //############################################################################################ 578 { 579 // 16 MHz 580 // + 0.75us ( W=val, Call ) 581 for ( ;; ) 582 { // loop time 583 nop2(); // 0.50us 584 nop2(); // 1.00us 585 nop2(); // 1.50us 586 nop2(); // 2.00us 587 nop2(); // 2.50us 588 nop2(); // 3.00us 589 nop(); // 3.25us 590 if ( --val == 0 ) // + 0.75us (W--, BTFS ) 591 return; // + 0.25us 592 nop2(); // 4.50us 593 } // 5.00us (Goto) 594 } 595 //############################################################################################ 596 597 #define OneWireData0() { OneWire_TRIS = 0; } // 0.5us @ 16MHz 598 #define OneWireData1() { OneWire_TRIS = 1; } // 0.5us @ 16MHz 599 600 //############################################################################################ 601 void OneWireWriteByte( uns8 byte ) 602 //############################################################################################ 603 { 604 uns8 bitLoop = 8; 605 do 606 { 607 // Next sequence is time precision critical 608 GIE = FALSE; 609 610 OneWireData0(); 611 nop2(); // 1 us [0.5 us] 612 nop2(); // [1.0 us] 613 if ( byte.0 ) // 2.5 us [1.75us] 614 OneWireData1(); 615 616 // End of time precision critical sequence 617 GIE = TRUE; 618 619 // 60us minimum in total, does not have to be precise 620 Delay5us( ( 60 - 3 ) / 5 + 1 ); 621 622 OneWireData1(); 623 624 byte >>= 1; 625 } while ( --bitLoop != 0 ); 626 } 627 628 //############################################################################################ 629 uns8 OneWireReadByte() 630 //############################################################################################ 631 { 632 uns8 result; 633 uns8 bitLoop = 8; 634 do 635 { 636 // Next sequence is time precision critical 637 GIE = FALSE; 638 639 OneWireData0(); 640 nop2(); // 1 us [0.5 us] 641 #if F_OSC == 16000000 642 nop2(); // [1.0 us] 643 #endif 644 OneWireData1(); // 2 us [1.5 us] 645 Delay5us( 15 / 5 ); // 17 us [16.5 us] 646 647 Carry = 0; // 17.5 us [16.75 us] 648 if ( OneWire_IO_IN ) // 18.5 us [ 17.25 us] (condition must not modify Carry) 649 Carry = 1; 650 651 // End of time precision critical sequence 652 GIE = TRUE; // must not modify Carry 653 result = rr( result ); 654 655 // 60us minimum in total, does not have to be precise 656 Delay5us( ( 60 - 20 ) / 5 + 1 ); 657 } while ( --bitLoop != 0 ); 658 659 return result; 660 } 661 662 //############################################################################################ 663 bit OneWireReset() 664 //############################################################################################ 665 { 666 // Setting the pin once to low is enough 667 OneWire_IO_OUT = 0; 668 // Reset pulse 669 OneWireData0(); 670 Delay5us( 500 / 5 ); 671 // Reset pulse end 672 OneWireData1(); 673 // Next sequence is time precision critical 674 GIE = FALSE; 675 // Wait for presence pulse 676 Delay5us( 70 / 5 ); 677 // End of time precision critical sequence 678 GIE = TRUE; 679 // Presence pulse? 680 if ( OneWire_IO_IN ) 681 { 682 // No presence, finish initialization sequence 683 Delay5us( ( 500 - 70 ) / 5 ); 684 return FALSE; 685 } 686 else 687 { 688 // Presence OK, finish initialization sequence 689 Delay5us( ( 500 - 70 ) / 5 ); 690 return TRUE; 691 } 692 } 693 694 //############################################################################################ 695 void OneWireCmd( uns8 cmd ) 696 //############################################################################################ 697 { 698 // OneWire: Skip ROM 699 OneWireWriteByte( CMD_SKIPROM ); 700 // OneWire: Send command 701 OneWireWriteByte( cmd ); 702 } 703 704 //############################################################################################ 705 bit Ds18B20WriteConfig( uns8 value ) 706 //############################################################################################ 707 { 708 if ( OneWireReset() ) 709 { 710 // Write Scratchpad 711 OneWireCmd( CMD_WSCRATCHPAD ); 712 713 // Write TL = ? (we dot not care the value) 714 OneWireWriteByte( W ); 715 // Write TH = ? (we dot not care the value) 716 OneWireWriteByte( W ); 717 // Write Config byte 718 OneWireWriteByte( value ); 719 720 if ( OneWireReset() ) 721 { 722 // Copy Scratchpad 723 OneWireCmd( CMD_CPYSCRATCHPAD ); 724 return TRUE; 725 } 726 } 727 return FALSE; 728 } 729 730 //############################################################################################ 731 uns16 MCP9802GetTemp() 732 //############################################################################################ 733 { 734 // MCP9802 address 735 _DpaApiI2Cstart( I2C_ADR ); 736 if ( I2CwasTimeout ) 737 return ERROR_TEMPERATURE; 738 739 // pointer: 1 = configuration register 740 _DpaApiI2Cwrite( 0x01 ); 741 // configuration: 9-bit ADC 742 _DpaApiI2CwriteAndStop( 0x00 ); 743 744 // MCP9802 address 745 _DpaApiI2Cstart( I2C_ADR ); 746 // pointer: 0 = temperature 747 _DpaApiI2CwriteAndStop( 0 ); 748 749 // MCP9802 address + read 750 _DpaApiI2Cstart( I2C_ADR | 1 ); 751 uns16 temperature; 752 // store the result 753 temperature.high8 = _DpaApiI2Cread( TRUE ); 754 temperature.low8 = _DpaApiI2Cread( FALSE ); 755 _DpaApiI2Cstop(); 756 return temperature; 757 } 758 759 //############################################################################################ 760 uns16 GetTemperature() 761 //############################################################################################ 762 { 763 // Reads temperature from an enabled sensor 764 uns16 temperatureResult; 765 766 if ( isDS18B20 ) 767 { 768 // Temperature is ready at the background 769 temperatureResult = temperature; 770 if ( temperatureResult != ERROR_TEMPERATURE ) 771 { 772 temperatureResult += 0x08; 773 temperatureResult /= 0x10; 774 } 775 } 776 else 777 { 778 // Temperature value must be read from I2C sensor 779 temperatureResult = MCP9802GetTemp(); 780 if ( temperatureResult != ERROR_TEMPERATURE ) 781 { 782 temperatureResult += 0x80; 783 temperatureResult /= 0x100; 784 } 785 } 786 787 return temperatureResult; 788 } 789 790 #if defined( TR7xG ) 791 //############################################################################################ 792 // Might not be needed if ADC registers are kept default 793 void resetADCregs() 794 //############################################################################################ 795 { 796 // Start reseting ADC registers from ADCON0 to ADPCH 797 FSR0 = &ADCON0; 798 do 799 { 800 setINDF0( 0 ); 801 FSR0++; 802 // Stop reseting at 1st GPR register, ADPCH is the last implemented register before GPR 803 } while ( !FSR0L.5 ); 804 } 805 #endif 806 807 //############################################################################################ 808 uns8 ReadAdc() 809 //############################################################################################ 810 { 811 #if defined( TR7xG ) 812 // ADC is enabled, ADGO is cleared upon completion, Clock supplied according to ADCLK register, left-justified 813 ADCON0 = 0b1000.0000; 814 // ADC Conversion Clock = FOSC/8 815 ADCLK = 8 / 2 - 1; 816 #else 817 // ADC result - left justified, Fosc/8 818 ADCON1 = 0b0001.0000; 819 #endif 820 821 // Short delay to stabilize 822 updateCRC16( W ); 823 824 // start ADC 825 _GO = 1; 826 // wait for ADC finish 827 while ( _GO ); 828 return ADRESH; 829 } 830 831 //############################################################################################ 832 uns8 ReadAdcPhotoresistor() 833 //############################################################################################ 834 { 835 #if defined( TR7xG ) 836 // Enable ADC 837 ADCMD = 0; 838 // Resets all ADC registers 839 // VREF- is connected to AVSS, VREF+ is connected to VDD 840 resetADCregs(); 841 // ADC Positive Input Channel = ANA0 842 setADPCH( 0x00 ); 843 #else 844 // ADC setting (AN0 channel) 845 ADCON0 = 0b0.00000.01; 846 #endif 847 // ADC initialization (for more info see PIC datasheet) pin C1 (AN0-D/ANA0-G) as analog input 848 ANSELA.0 = 1; 849 return ReadAdc(); 850 } 851 852 //############################################################################################ 853 uns8 ReadAdcPotentiometer() 854 //############################################################################################ 855 { 856 #if defined( TR7xG ) 857 // Enable ADC 858 ADCMD = 0; 859 // Resets all ADC registers 860 // VREF- is connected to AVSS, VREF+ is connected to VDD 861 resetADCregs(); 862 // ADC Positive Input Channel = ANA5 863 setADPCH( 0x05 ); 864 #else 865 // ADC setting (AN4 channel) 866 ADCON0 = 0b0.00100.01; 867 #endif 868 // ADC initialization (for more info see PIC datasheet) pin C5 (AN4-D/ANA5-G) as analog input 869 ANSELA.5 = 1; 870 return ReadAdc(); 871 } 872 //############################################################################################ 873 #endif 874 //############################################################################################ 875 // Default Custom DPA Handler header; 2nd include implementing a Code bumper to detect too long code of the Custom DPA Handler (modify the path according to your setup) 876 #include "DPAcustomHandler.h" 877 //############################################################################################