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