//----------------------------------------------------------------------------
// HACIR                                                      19950907 CHG
// Phillips RC5 receiver/transmitter And DS1820 interface
// Measures temperature
//
// 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 <reg2051.h>
#include <stdio.h>
#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;
*/
