/*
   thermo.c is a source program for interfacing 89C4051 with CA3162 10-bit
   ADC and 16x1 line LCD display. LM35 is used to be temperature sensor, 10ms
   cputick generates 100 ms timebase. LCD display shows time in sec unit
   and temperature in Celcius. FIR filters do filtering raw data producing
   0.1 C reading.
   Copyright (C) 1998 W.SIRICHOTE
*/

#include c:\mc51\8051io.h
#include c:\mc51\8051reg.h


extern register char cputick;  /* cputick increments by 1 every 10 ms */
unsigned register int count,i,adc,min,max;
unsigned register char sec100,sec10,ACC,initcount,flag;
unsigned register int msd,nsd,lsd;
unsigned register int xin[10];


main()
{
  TMOD = 0x21;   /* set timer0 to 16-bit counter */
  serinit(9600);
  cputick = 0;
  i = 0;
  count=0;
  sec100=0;
  sec10=0;
  flag = 0;
  initcount=0;
  asm "E EQU $B5";   /* bit define for P3.5 and P3.4 */
  asm "RS EQU $B4";
  asm " CLR E";
  asm " CLR RS";
  P1 = 0;
  delay(5);
  i_LCD();
  puttitle();
  delay(5000);  /* show quantities to be measured */
  flag |= 0x04;
  puttime();
  xin[0]=10000;  /* show invalid display by putting out-of-range xin value */
  flag |= 0x02;
  puttemp();
  TCON = 0x59;
  while(1)     /* run continuously */
  {
   do
    {
       ;       /* put tasks require 51's speed here */
    }
    while ( cputick < 10);    /* 10 * 10 ms = 100 ms */
    cputick = 0;

/*   ____---____________________---___________________---________
         |<------- 100 ms ----->|
     _______----___________________----__________________----____
            time ~20 ms

*/
    /* put tasks requires 100 ms tick here */

    asm " setb $b0";
    time();         /* update time base */
    putxin();       /* put converted digital data to 10-word buffer */
    puttemp();      /* put temperature reading to LCD */
    puttime();      /* put second counter to LCD */
    asm " clr $b0";

     }
}

time()

/* flag
   %00000001 set bit0 every 100 ms
   %00000010 set bit1 after first 10-samples
   %00000100 set bit2 every 1 s

*/

{
   sec100++;
   if (sec100 >= 1)       /* 1 * 100 ms = 100 ms */
      {sec100 = 0;
        sec10++;
        initcount++;
        flag |= 0x01;    /* set bit 0 in flag */

        if (initcount >= 10)
            {initcount = 10;
            flag |= 0x02;
            }
        if (sec10 >= 10)
        { sec10 = 0;
            count++;   /* increment count every 1 sec */
            flag |= 0x04;
          /*  sendreading();  */
            }
       }
}

pause(j)
int j;
{
   int i;
   for (i = 0; i < j; i++)
   ;
}

LCDWI(A)     /* write instruction to LCD */
char A;

{
     ACC = A; /* use ACC for interfacing to Assembly */
     asm {
        MOV A,ACC
        CLR RS
        CLR E
        MOV P1,A
        SETB E
        NOP
        CLR  E
        SWAP A
        MOV  P1,A
        SETB E
        NOP
        CLR  E
    }
    pause(1);

}

LCDWD(A)
char A;

{
     ACC = A; /* use ACC for interfacing to Assembly */
     asm {
        MOV A,ACC
        SETB RS   /* write data */
        CLR E
        MOV P1,A   /* check for p1.0-p1.4 */
        SETB E
        NOP
        CLR  E
        SWAP A
        MOV  P1,A
        SETB E
        NOP
        CLR  E
    }
     pause(1);
}


i_LCD()    /* initialize LCD in accordance with Hitachi 44780 4-bit */
{
    P1 = 0x30;
    pulseE();
    delay(10);
    pulseE();
    delay(1);
    pulseE();
    delay(1);
    P1 = 0x20;
    pulseE();
    pulseE();
    pulseE();
    LCDWI(0x28);   /* function set 4-bit bus, 1/16 line, 5*7 dots */
    LCDWI(0x0c);   /* display on/off on display,off cursor, no blink */
    LCDWI(0x06);   /* entry mode DDRAM address + */
    LCDWI(1);      /* clear display */
    delay(5);
}

pulseE()
{
    asm{
        SETB E
        NOP
        CLR E
    }
}


puttime()
{
    int temp;
    char zero;
    if ((flag & 0x04) == 4)
    { flag &= ~0x04;
    zero = 0;
    LCDWI(0x80);     /* leftmost digit */
    if (count/10000 != 0)
        {
        LCDWD(count/10000+48);
        zero = 1;
        }
        else LCDWD(' ');
     temp = count%10000;

    if ((zero == 0) && (temp/1000 == 0))
        LCDWD(' ');
        else {
            LCDWD(temp/1000+48);
            zero = 1;
        }
    temp = temp%1000;
    if ((zero == 0) && (temp/100 == 0))
        LCDWD(' ');
        else {
            LCDWD(temp/100+48);
            zero = 1;
        }
    temp = temp%100;
    if ((zero == 0) && (temp/10 == 0))
        LCDWD(' ');
        else LCDWD(temp/10+48);
    temp = temp%10;
    LCDWD(temp+48);
    LCDWD(' ');
    LCDWD('s');
    LCDWD(' ');
    }
}
/*
puttime()
{
    int temp;
    char zero;
    zero = 0;
    LCDWI(0x80);     /* leftmost digit */
    LCDWD(' ');
    LCDWD(count/10000+48);
    temp = count%10000;
    LCDWD(temp/1000+48);
    temp = temp%1000;
    LCDWD(temp/100+48);
    temp = temp%100;
    LCDWD(temp/10+48);
    temp = temp%10;
    LCDWD(temp+48);
    LCDWD(' ');
    LCDWD('s');

}

*/

time1ms()    /* 1 ms delay with XTAL 11.0592MHz */
{
    int i;
    for (i = 0; i < 8 ; i++)
    ;
}

delay(n)      /* do nothing n*1ms */
int n;
{
    int i;
    for (i=0; i< n ; i++)
    time1ms();

}

int readtemp()
{
    P1 = 0xff;       /* make P1.0 to P1.3 to be input port */
    asm " SETB $B7";
    asm " JNB $B7,*";
    asm " JB $B7,*";
    delay(1);
    msd = (P1 & 0x0f);
    delay(2);
    P1 = 0xff;
    lsd = P1 & 0x0f;
    delay(2);
    P1 = 0xff;
    nsd = (P1 & 0x0f);
    return(msd*100+nsd*10+lsd);

}

putxin()    /* put raw data to FIFO buffer */

{   if ((flag & 0x01) ==1)
    {flag &= 0xfe;
    xin[9]=xin[8];
    xin[8]=xin[7];
    xin[7]=xin[6];
    xin[6]=xin[5];
    xin[5]=xin[4];
    xin[4]=xin[3];
    xin[3]=xin[2];
    xin[2]=xin[1];
    xin[1]=xin[0];
    xin[0]=readtemp();
    }
}

int average()

{

return((xin[0]+xin[1]+xin[2]+xin[3]+xin[4]+xin[5]+xin[6]+xin[7]+xin[8]+xin[9])/10);

}

puttemp()

{
    int temp,t;
    if((flag & 0x02)== 2)
    { flag &= ~0x02;

    LCDWI(0xc0);
    LCDWD(' ');
    temp=average();
    adc=temp;
    if (temp < min)
       min = temp;
       if (temp > max)
        max = temp;

    if ( (temp < 999) && (temp > 0)) /* limit measuring range to 0-100 c */
    {
    t = temp/100;
    if(t != 0)
        LCDWD(t+48);
    else LCDWD(' ');
    temp = temp%100;
    LCDWD(temp/10+48);
    LCDWD('.');
    LCDWD(temp%10+48);
    }
    else
    {
        LCDWD('-');
        LCDWD('-');
        LCDWD('-');
        LCDWD('-');
    }
    LCDWD(0xdf);   /* i.e., 'C */
    LCDWD('C');
    LCDWD(' ');
    }
}

puttitle()

{
    LCDWI(0x80);
    LCDWD('D');
    LCDWD('i');
    LCDWD('g');
    LCDWD('i');
    LCDWD('T');
    LCDWD('h');
    LCDWD('e');
    LCDWD('r');
    LCDWI(0xc0);
    LCDWD('m');
    LCDWD('0');
    LCDWD('-');
    LCDWD('1');
    LCDWD('0');
    LCDWD('0');
    LCDWD(0xdf);
    LCDWD('C');

}
