/**** IR Mrakomer 4 ****/
#define VERSION "4.0"
#define ID "$Id: irmrak3.c 1215 2008-08-08 12:25:25Z kakl $"
#include "irmrak4.h"

#define  DOME        PIN_B4   // Dome controll port
#define  SA          0x00     // Slave Address (0 for single slave / 0x5A<<1 default)
#define  RAM_Access  0x00     // RAM access command
#define  RAM_Tobj1   0x07     // To1 address in the eeprom
#define  RAM_Tamb    0x06     // Ta address in the eeprom
#define  HEATING     PIN_B3   // Heating for defrosting
#define  MAXHEAT     10       // Number of cycles for heating
#define  MAXOPEN     10       // Number of cycles for dome open

#bit CREN = 0x18.4      // USART registers
#bit SPEN = 0x18.7
#bit OERR = 0x18.1
#bit FERR = 0x18.2

char  VER[4]=VERSION;
char  REV[50]=ID;

int8  heat;
int8  open;


unsigned char PEC_calculation(unsigned char pec[]) // CRC calculation
{
   unsigned char   crc[6];
   unsigned char   BitPosition=47;
   unsigned char   shift;
   unsigned char   i;
   unsigned char   j;
   unsigned char   temp;

   do
   {
      crc[5]=0;            /* Load CRC value 0x000000000107 */
      crc[4]=0;
      crc[3]=0;
      crc[2]=0;
      crc[1]=0x01;
      crc[0]=0x07;
      BitPosition=47;         /* Set maximum bit position at 47 */
      shift=0;

      //Find first 1 in the transmited message
      i=5;               /* Set highest index */
      j=0;
      while((pec[i]&(0x80>>j))==0 && i>0)
      {
         BitPosition--;
         if(j<7)
         {
            j++;
         }
         else
         {
            j=0x00;
            i--;
         }
      }/*End of while */

      shift=BitPosition-8;   /*Get shift value for crc value*/


      //Shift crc value
      while(shift)
      {
         for(i=5; i<0xFF; i--)
         {
            if((crc[i-1]&0x80) && (i>0))
            {
               temp=1;
            }
            else
            {
               temp=0;
            }
            crc[i]<<=1;
            crc[i]+=temp;
         }/*End of for*/
         shift--;
      }/*End of while*/

      //Exclusive OR between pec and crc
      for(i=0; i<=5; i++)
      {
         pec[i] ^=crc[i];
      }/*End of for*/
   } while(BitPosition>8);/*End of do-while*/

   return pec[0];
}/*End of PEC_calculation*/


int16 ReadTemp(int8 addr, int8 select)    // Read sensor RAM
{
   unsigned char arr[6];         // Buffer for the sent bytes
   int8 crc;                     // Readed CRC
   int16 temp;                   // Readed temperature

   disable_interrupts(GLOBAL);
   i2c_stop();
   i2c_start();
   i2c_write(addr);
   i2c_write(RAM_Access|select);  // Select the teperature sensor in device
   i2c_start();
   i2c_write(addr);
   arr[2]=i2c_read(1);        // lo
   arr[1]=i2c_read(1);        // hi
   temp=MAKE16(arr[1],arr[2]);
   crc=i2c_read(0);           //crc
   i2c_stop();
   enable_interrupts(GLOBAL);

   arr[5]=addr;
   arr[4]=RAM_Access|select;
   arr[3]=addr;
   arr[0]=0;
   if (crc != PEC_calculation(arr)) temp=0; // Calculate and check CRC

   return temp;
}

void delay(int16 cycles)
{
   int16 i;
   
   if (open>0)
      for(i=0; i<cycles; i++) {output_toggle(DOME); delay_us(100);}
      else
      for(i=0; i<cycles; i++) {output_low(DOME); delay_us(100);}      

      restart_wdt();
}

void main()
{
   unsigned int16 n, temp, tempa;
   signed int16 ta, to;

   output_low(HEATING);                 // Heating off
   setup_wdt(WDT_2304MS);               // Setup Watch Dog
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
//   setup_oscillator(OSC_4MHZ|OSC_INTRC,+2); // Pokud je nutna kalibrace RCosc
   setup_oscillator(OSC_4MHZ|OSC_INTRC);

   delay_ms(1000);
   restart_wdt();
   printf("\n\r* Mrakomer %s (C) 2007 KAKL *\n\r",VER);   // Welcome message
   printf("* %s *\n\r",REV);
   printf("<#seq.> <ambient temp.> <space temp.> <status>\n\r\n\r");
   tempa=ReadTemp(SA, RAM_Tamb);       // Dummy read
   temp=ReadTemp(SA, RAM_Tobj1);

   n=0;
   heat=0;
   open=0;

//   enable_interrupts(GLOBAL);
//   enable_interrupts(INT_RDA);

   restart_wdt();

   while(TRUE)
   {
      while(kbhit()) getc();        // Flush USART buffer
      CREN=0; CREN=1;               // Reinitialise USART

      do 
      {
         delay(10000);
         if (heat>0)
            {
               output_high(HEATING);
               heat--;          
            }
            else
            {
               output_low(HEATING);
            }

         if (open>0) open--;
      } while (!kbhit());

      {
         char ch;
               
         ch=getc();
         
         switch (ch)
         {
            case 'h':
               heat=MAXHEAT;           // Needs heating
               break;
      
            case 'c':
               heat=0;                 // Needs colder
               break;
      
            case 'o':
               open=MAXOPEN;           // Open the dome
               break;
      
            case 'l':
               open=0;                 // Lock the dome
               break;
         }
      }

      n++;        // Increment the number of measurement

      tempa=ReadTemp(SA, RAM_Tamb);       // Read temperatures from sensor
      temp=ReadTemp(SA, RAM_Tobj1);

      ta=tempa*2-27315;    // °K -> °C
      to=temp*2-27315;

      { // printf
         char output[30];
         int8 j;
               
         sprintf(output,"#%Lu %Ld %Ld %u %u\n\r\0", n, ta, to, heat, open);
   
         j=0;
         while(output[j]!=0)
         {
            delay(50);
            putc(output[j++]);
            output_toggle(DOME);
         }
      }
   }
}