//---------------------------------------------------------------------------- // HACIR 19950907 CHG // Phillips RC5 receiver/transmitter // Measures temperature // // von Carsten Groen [cgroen@image.dk] im Maerz 1998 bekommen // // HACBUS: // Device type: 0x03 ; HACIR type // Address : 0x01..0x0F ; Address 1..15 // Commands : 0x00 ; Poll // Resp: 0x80 XX XX YY YY ; Last RC5 code (Address,Code) and current temperature // ; Address=0xFF, Code=0xFF if no new code since last poll) // ; Address=0xFF, Code=RC5Code if trying to repeat without allowed // : 0x01 xx ; Allow/Dont allow* repeat of Up/Down buttons // Resp: 0x81 // : 0x02 xx xx ; Send RC5 code (address, code) // Resp: 0x82 ; NOT IMPLEMENTED (WILL NEVER BE, NO SPACE !!) //---------------------------------------------------------------------------- #include #include #include "..\HACNET\HACNET.H" //---------------------------------------------------------------------------- // Constants... //---------------------------------------------------------------------------- #define TRUE 1 #define FALSE 0 #define MyDeviceType 0x03 #define RxSize 3+3 // Maximum size of RxBuffer //---------------------------------------------------------------------------- // I/O definitions... //---------------------------------------------------------------------------- #define IRDet P33 // IR detector, only referenced in RC5RX.A51 file #define IREmit P34 // Not implemented #define DS1820 P37 // Temperature sensor //---------------------------------------------------------------------------- // Variables... //---------------------------------------------------------------------------- unsigned char RC5RxAddress, RC5RxCommand; // Last command received on RC5 bit RC5Avail=FALSE; // And if the data are new... unsigned char RxBuffer[RxSize]; // RxBuffer extern bit RxAvail; // Message available in RX Buffer extern bit Resend; // Resend last response unsigned char Repeating; //---------------------------------------------------------------------------- // wait for a specific time in 10 mSec // Based on a 11.059 MHz crystal //---------------------------------------------------------------------------- void Delay(unsigned char t) { unsigned int i; if (t==0) return; while (t--) for(i=0;i<774; i++); } //лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл // DS1820 Helper routines. 19950926 CHG // DS1820 is assumed to be external supplied with Vcc // Global constants/variables that must be declared: // #define DS1820 Pxx // DQ of DS1820 // //лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл //---------------------------------------------------------------------------- // DS1820 Initialize // Returns: 0 if DS1820 is present // 1 if no DS1820 is present //---------------------------------------------------------------------------- unsigned char InitDS1820(void) { unsigned char i, Temp; // Reset DS1820... DS1820=0; // Keep low signal for at least 480 uSec for (i=0; i<200; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) DS1820=1; // Wait minimum 60 uSec before presence check... for (i=0; i<30; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) // Check if DS1820 present... Temp=DS1820; // Wait minimum 300 uSec for (i=0; i<100; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) // return if DS1820 present... return Temp; } //---------------------------------------------------------------------------- // Write a bit to DS1820 //---------------------------------------------------------------------------- void DS1820WBit(bit Data) { unsigned char i; // Initiate write slot DS1820=0; // Let DS1820 see it... for (i=0; i<4; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) DS1820=Data; // Put out the bit // Wait 60 uSec for (i=0; i<20; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) DS1820=1; } //---------------------------------------------------------------------------- // Read a bit from DS1820 //---------------------------------------------------------------------------- bit DS1820RBit(void) { unsigned char i; bit Temp; // Initiate read slot DS1820=0; // Let DS1820 see it... for (i=0; i<1; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) DS1820=1; // Let data settle... for (i=0; i<1; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) // Read the bit... Temp=DS1820; // Let the read slot time out... for (i=0; i<20; i++); // 3 cycles per iteration (3.26 uSec @ 11.0592 MHz) // return the state of the bit... return Temp; } //---------------------------------------------------------------------------- // Write a byte to DS1820 //---------------------------------------------------------------------------- void DS1820WByte(unsigned char Data) { unsigned char i; unsigned char Temp; Temp=Data; for (i=0; i<8; i++) { DS1820WBit(Temp &0x01); // Send out bit Temp >>=1; // Advance to next bit } } //---------------------------------------------------------------------------- // Read a byte from DS1820 //---------------------------------------------------------------------------- unsigned char DS1820RByte(void) { unsigned char i; unsigned char Temp=0; for (i=0; i<8; i++) { Temp >>=1; // Advance to next bit if (DS1820RBit()) Temp |= 0x80; // It's a '1' else Temp &= 0x7F; // It's a '0' } return Temp; } //---------------------------------------------------------------------------- // Read temperature // Returns temperature in 0.5 deg resolution. // (ie. 24.5 deg => 245) //---------------------------------------------------------------------------- unsigned int DS1820ReadTemp(void) { unsigned int j,i; static bit TempConverting=FALSE; // DS1820 in the process of // converting a temperature reading static unsigned int LastTemp=0xFFFF;// Last temp reading // If not allready converting, go start one... if (TempConverting==FALSE) { EA=0; // Disable interrupts InitDS1820(); // Reset DS1820 DS1820WByte(0xCC); // Skip ROM command DS1820WByte(0x44); // Convert temperature command EA=1; // Enable interrupts TempConverting=TRUE; // If allready converting, check if done } else { if (DS1820RByte()==0xFF) { // if done converting EA=0; // Disable interrupts InitDS1820(); // Reset DS1820 DS1820WByte(0xCC); // Skip ROM command DS1820WByte(0xBE); // Read scratchpad registers j=DS1820RByte(); // Read LSB of temperature in scratchpad j+=DS1820RByte() << 8; // -//- MSB -------------//------------- i=((j>>1)*10)+((j & 0x0001) * 5); InitDS1820(); // Reset DS1820 EA=1; // Enable interrupts TempConverting=FALSE; // Ready for next convert command LastTemp=i; } } return LastTemp; } //лллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллллл //---------------------------------------------------------------------------- // Startbit detected on IRDet input... // // Timing of RC5: // In this example, a Address of 0 and and COmmand of 60 is assumed (TV/VIDEO button) // Note: Timing show below is at the output pin of the SHARP IR detector, which is // inverted compared to RC5 timing. // The RC5 protocol is BiPhase coded, ie we will always have an transition of the dataline. // (Used because of noise immunity) // // ФФП // A logic '1': Г // РФ // // кФ // A logic '0': Г // ФФй // // // Г889Г + + + + + + + + + + + + + + + + + + + + + + + + // ГuS Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г Г // ФФТФП кФП к#ПГ ГкФПГкФПГкФПГкФПГкФТФПГкФПГкФПГкФПГ ГкФПГкФТФФ // Г * Г Г Г ГГ ГГ ГГГ ГГГ ГГГ ГГГ Г ГГГ ГГГ ГГГ ГГ ГГ ГГГ Г // Г РФД РФД РФТФй УФй УФй УФй УФй Г РФД РФД РФД РФТФй УФй Г // ГSt ГSt ГCtlГS4 ГS3 ГS2 ГS1 ГS0 ГC5 ГC5 ГC3 ГC2 ГC1 ГC0 Г // // // The plus, '+' is where we will get an Timer interrupt. // // The '*' is the falling edge of the startbit, which will give an external // interrupt on INT1*. // // When this external interrupt is occuring, we will set the Timer period to // 1.778 mSec * 1.5 889/4 uSec, total 3111 uSec, and disable any further external // interrupt until we have sampled all the bits. // // After this timeout, we will be in the middle of the first half part of the first bit, // the Ctl bit (Marked with a #). // // The data are sampled and hereafter, the Timer interrupt is occuring once every // 444 uSec's. // // We will also detect Phase errors. (Same signal level in two consecutive samples) // //---------------------------------------------------------------------------- void Int1(void) interrupt 2 using 2 { // $$$ //ES=FALSE; // ES: Disable serial port int EX1=FALSE; // Avoid another INT1* until we are completely finished... TH0=0xF4; // Timeout value for 3100 uSec. TL0=0xD4; TR0=TRUE; // Start timer 0 } //---------------------------------------------------------------------------- // Timer 0 interrupt. //---------------------------------------------------------------------------- void Timer0(void) interrupt 1 using 2 { static unsigned char RC5BitCnt=0; // Counts number of bits received static unsigned int RC5Data; // Contains the 12 bits we receive static bit OldValue; static bit PhaseError; // Biphase error detacted in RC5 frame static bit ControlBit; // Control bit in RC5 frame P35=!P35; // Load Timer again... TH0=0xFC; // Timeout value for 862 uSec. TL0=0xE0; // if (RC5BitCnt==0) { RC5Data=0; OldValue=IRDet; PhaseError=FALSE; } // if not beyond last bit, go sample it if (RC5BitCnt<24) { // Check if uneven number, ie 1,3,5 etc (Second half of bit) // It's in this half we decide if it's a '1' or a '0' if (RC5BitCnt & 0x01) { // Check for Biphase errors... if (OldValue!=IRDet) { RC5Data <<= 1; // Advance to next bit; // Because we sample in second half, we have to invert level if (IRDet) // Stick it in... RC5Data &= 0xFFFE; else RC5Data |= 0x0001; // Biphase error } else PhaseError=TRUE; } RC5BitCnt++; // Remember signal level for Phase detect next bit OldValue=IRDet; // if beyond the last bit, we are finished } else { // All bits sampled, tell the world... TR0=FALSE; // Stop timer 0 RC5BitCnt=0; // Prepare for next time if (!PhaseError && !RC5Avail) { // Repating if new controlbit equals the old one... Repeating=ControlBit==((RC5Data & 0x0800)==0x0800); // Remeber this new controlbit... ControlBit=((RC5Data & 0x0800)==0x0800); RC5RxAddress=(unsigned char)((RC5Data & 0x07C0)>>6); RC5RxCommand=(unsigned char)(RC5Data & 0x003F); RC5Avail=TRUE; // Tell world we have a complete RC5 code... } PhaseError=FALSE; IE1=0; // Clear any pending int's EX1=TRUE; // Prepare for another startbit... // $$$ // ES=TRUE; // ES: Enable serial port int } } //---------------------------------------------------------------------------- // Main part //---------------------------------------------------------------------------- void main() { unsigned int LastTemp=0xFEDE; // Last complete temperature unsigned int NewTemp =0x0ABE; // Newly read temperature unsigned char Rsp[5]; // Buffer for responses bit RC5RepeatAllowed; // If repeat is allowed unsigned char MyAddress; // My assigned address on the Dip switches. //---------------------------------------------------------------------------- // Initalize HACNET Driver //---------------------------------------------------------------------------- MyAddress=InitHACNET(MyDeviceType, RxSize); //--------------------------------- // Initialize outputs... //--------------------------------- IREmit=0; //------------------------------ // Configure onchip resources... //------------------------------ Delay(150); // $$$ PX1 = 1; // External interrupt 0 high priority IT1 = 1; // External interrupt 1 Edge sensitive EX1 = 1; // External interrupt 1 enable ET0 = 1; // Enable Timer 0 interrupts // $$$ PT0 = 1; // Timer 0 high priority TMOD |= 0x01;// TMOD: timer 0, mode 1, 16 timer EA=1; // Global int enable //--------------------------- // Check if DS1820 present... //--------------------------- // if (InitDS1820()==0) // if (MyAddress==0) HacTransmit("DS1820 Present\n\r",16); // else // if (MyAddress==0) HacTransmit("DS1820 NOT Present\n\r",20); // Service the DS1820... NewTemp=DS1820ReadTemp(); //---------------------------------------------------------------------------- // Forever //---------------------------------------------------------------------------- while(1) { //---------------------------------------------------------------------------- // Diagnostic mode, Address is 0x00 // Read all inputs and reflect their state on the outputs... //---------------------------------------------------------------------------- if (MyAddress==0) { //---------------------------------------------------------------------------- // Normal mode //---------------------------------------------------------------------------- } else { // Check if we have to resend last response... if (Resend) { Resend=FALSE; // Delay(200); HacTransmit(Rsp, 0xFF); } // If anything to us from HACCON... if (RxAvail) { // Delay(200); switch (RxBuffer[0]) { // Poll request... case 0: Rsp[0]=0x80; // Response code Rsp[1]=0xFF; Rsp[2]=0xFF; // If any new RC5 codes since last request... if (RC5Avail) { // If this is a repeating code... if (Repeating) { // If it was Up or DOWN button pressed... if (RC5RxCommand==16 || RC5RxCommand==17) { // And they are allowed to repeat... if (RC5RepeatAllowed) { Rsp[1]=RC5RxAddress; // Send Address Rsp[2]=RC5RxCommand; // Send Command // Else if they were not allowed to repeat, clear it... } else RC5Avail=FALSE; // Not UP or DOWN pressed, clear it... } else RC5Avail=FALSE; // Not repeating, just send code... } else { Rsp[1]=RC5RxAddress; // Send Address Rsp[2]=RC5RxCommand; // Send Command } } Rsp[4]=(unsigned char)(NewTemp >> 8); Rsp[3]=(unsigned char)NewTemp; if (RC5Avail || (NewTemp!=LastTemp)) { HacTransmit(Rsp, 5); LastTemp=NewTemp; } else HacTransmit(Rsp, 1); RC5Avail=FALSE; // Service the DS1820... NewTemp=DS1820ReadTemp(); break; // Allow/Dont allow repeat of Up/Down buttons case 1 : RC5RepeatAllowed=(RxBuffer[1]==1); Rsp[0]=0x81; // Response code HacTransmit(Rsp, 1); // Empty response break; // Send RC5 command (Not implemented) case 2 : Rsp[0]=0x82; // Response code HacTransmit(Rsp, 1); // Empty response break; } RxAvail=0; } } } } /* // Return last received RC5 command case 0: Rsp[0]=0x80; // Response code // If any new RC5 codes since last request... if (RC5Avail) { if ((RC5RxCommand==16 || RC5RxCommand==17) && (Repeating && !RC5RepeatAllowed)) { Rsp[1]=0xFF; // Error, repeating Up or Down Rsp[2]=RC5RxCommand; } else { Rsp[1]=RC5RxAddress; // Send Address Rsp[2]=RC5RxCommand; // Send Command } } else { Rsp[1]=0xFF; Rsp[2]=0xFF; } Rsp[4]=(unsigned char)(NewTemp >> 8); Rsp[3]=(unsigned char)NewTemp; if (RC5Avail || (NewTemp!=LastTemp)) { HacTransmit(Rsp, 5); LastTemp=NewTemp; } else HacTransmit(Rsp, 1); RC5Avail=FALSE; // Service the DS1820... NewTemp=DS1820ReadTemp(); break; */