/*
   mini4.c
   Firmware for MiniLogger V3.0
   89C51RD2+ICL7109+128kB SRAM+RTC+LCD+GPIO

   Copyright (C) 2003
   WICHIT SIRICHOTE, 29 June 2003
   Department of Applied Physics
   Faculty of Science
   King Mongkut's Institute of Technology Ladkrabang, Bangkok 10250 THAILAND

   June 7, 2004 found bug on compare time, DS1307 uses BCD for time updating
                but compare function uses binary number, need to fix it!

   June 16, 2004 fixed AUTO mode!

   Nov 6, 2004 save and restore flag1 

*/

#include <8051io.h>
#include <8051reg.h> 
#include <8051int.h>
#include <8051bit.h>   // require preprocessor -P when compiling

#include "c:\mc\tiny\minilcd.c"

#define word unsigned int
#define byte unsigned char
#define beginsysdata 0
#define beginrecord 100
#define begincrc 1000
#define status 0
/* system status eg., main/battery power, door open/close , digital input, analog input */
#define name 2

#define adc 0x08   // ICL7109 12-bit ADC
#define gpio1 0x0c // 8-bit output port
#define gpio2 0x0e // 8-bit input port
#define lcd 0x0a // LCD

// flag1 bit usages

#define keypressed 0x01

//extern register char cputick;
register unsigned char sec100,sec,sec5,min,hour,day,month,year,flag1,ACCU,temp,led;
register unsigned char i,command,counter3;
register unsigned char BUFFER[30],mode,key;

register char n,page,channel,POL,OV;

register int temp3, temp4,k;

register int buffer[4];

register unsigned char tbuffer[8];

extern register char lastread // flag for last byte to be read

char title[] = "\n\nMiniLOGGER V3.0 (? help)";
char prompt[] = "\n>>";
char menu[] = "\n\nHELP MENU\
                \n/ print analog reading\
                \nt TIME set\
                \nd DATE set\
                \nc Clock display\
                \ns set START/STOP recording time\
                \ni sampling Interval\
                \n= display setting parameters\
                \nr number of record\
                \nb terminal connection\
                \nn New record\
                \na ALL read: sample real-time and data\
                \nx Read All: sample and data\
                \nu About MiniLOGGER V3.0\
                \n? help";

char _about[] = "\nMiniLOGGER was desinged by Wichit SIRICHOTE 28 June 2003\
                 \nApplied Physics Dept. KMITL\
                 \nfirmware updated: 25 June 2004\
                 \nURL: www.kmitl.ac.th/~kswichit email: kswichit@kmitl.ac.th";


char _terminal[] = "\n 1    2    3    4    5    6    7    8    9   10  11  12\
                    \nIN1+ IN1- IN2+ IN2- IN3+ IN3- IN4+ IN4- -5V +5V  0V  +V";

register unsigned int blink_every;
register unsigned int count,number_of_record,counter1,counter2,interval,temp16,j;

register unsigned char pointer[3]; // 24 bit long number for external RAM pointer
register unsigned char temp1[3], temp2[3]; // temp1 and temp2 are used for 24-bit storage
extern register char Longreg[];

register unsigned char channel_display;



/*-------------------- constant definition -------------------------*/
#define XOFF 0x13 // transmission flow control
#define XON 0x11
#define adj 2
#define LED P1.7
#define trigger P3.5
#define standby_blink 100
#define recording_blink 300
#define base 100  // start address for NVRAM storage
#define max_record 5000 //limit maximum record for 256kB SRAM (5000*50)

/*-------- address for setting parameters saved in NVSRAM 256 bytes page 0--*/
#define start_hour 0
#define start_min 1
#define stop_hour 2
#define stop_min 3
#define interval_saved 4 // 4-5 (16-bit)
#define record_saved 6 // 6-7 (16-bit) 
#define description 8 // 8-58 (max description string 50 characters)
#define mode_saved 60  // mode 1 manual, -1 auto
#define save_flag1 61 // for flag1 saving 

main()
{
  asm" MOV $8E,#3"; // normal access to external memory, emits ALE when access ram

  IE = 0x81; // enable external interrupt0
  TCON |= 0x01; // edge trigger
  channel = 0;
  channel_display = 0;

  xpoke(gpio1,0,channel); // select mux channel 0

  flag1 = 0;
  interval = 6000; // 60000 ms = 1 min
  blink_every = standby_blink;
  longset(pointer,100);  /* initialize pointer to 100 */

  reload_setting();   // reload previous recording setting

  InitLcd();
  Puts("MiniLOGG");
  goto_xy(0,1);
  Puts("ER V3.0");

  delay(1000);

  key = 0xbf;
  flag1 |= 0x02;
  execute_key();  // emulate key S5 was pressed

  serinit(9600);
  putstr(title);
  sendprompt();

//  clr_screen();

  while(1)
  {
    tick_wait();
/*------------- the following tasks execute every 10ms ------*/
//    cputick = 0;
    cpubeat();
    getcommand();
    printtime();
    settime();
    setdate();
    set_interval();
    dec_counter2();
    start_record();
    save_record();
    print_number_of_record();
    set_start_stop();
    new_record();
    show_setting();
    print_menu();
    clock();
    read_all();
    xread_all();
    manual_start_stop();
    about();
    get_key();
    key_released();
    execute_key();
    terminal_signal();
    prompting();
    print_adc();
    print_no_record();


    }
/************************************************************/
}

INTERRUPT(_IE0_) service_adc()
{
 //  P1 &= ~0x40; // hold ADC

 //  asm" MOV $8F,#0"; // x1 mode

     temp3 = xpeek(adc,2);  // get low byte
     temp4 = xpeek(adc,1); // get high byte

 //  asm" MOV $8F,#1"; // x2 mode

 //    printf("\r %02x %02x",temp1,temp2);

     POL = temp4&0x10;
     OV = temp4&0x20;

     temp4 &= 0x0f;
     temp4 <<= 8;
     temp3 |= temp4;

     if(!POL)
     temp3*=-1;
     if(OV)
     temp3 = 9999;
     buffer[channel] = temp3;

     channel++;
     channel &=3;
     xpoke(gpio1,0,channel); // select next channel
     delay(1); // wait for mux settled
   //  P1 |= 0x40; // run ADC after mux settled for next channel scanning

     if(channel ==0)
     {
     P1 &= ~0x40; //stop ADC
     flag1 |= 0x80;  // set ADC result bit
   //  printf(" %d %d %d %d",buffer[0],buffer[1],buffer[2],buffer[3]);

     }
}


terminal_signal()
{
        if(command == 'b')
        {
         putstr(_terminal);
         sendprompt();
        }
}


setpage(char x)    // emit A16,A17,A18,A19 to P1.0-P1.3
{
     temp = x;
     asm{
     MOV A,temp
     MOV C,ACC.0
     MOV P1.0,C
     MOV C,ACC.1
     MOV P1.1,C
     MOV C,ACC.2
     MOV P1.2,C
     MOV C,ACC.3
     MOV P1.3,C
     }
}

xpeek(char x,int y)   // read byte with page, address
{
     setpage(x);
     return peek(y);
}

xpoke(char x,int y,char z) // write byte with page,address,data
{
     setpage(x);
     poke(y,z);
}

output_1Hz()
{
        send_start();
        send_byte(0xd0);
        send_byte(0x07);  // pointed to address 7
        send_byte(0x90);  // enable 1Hz output
        send_stop();
}

readRTC()
{
       send_start();
       send_byte(0xD0);
       send_byte(0x00);
       send_stop();

       send_start();
       send_byte(0xD1);

       lastread = 0;
       for(i=0; i<6 ; i++)
         tbuffer[i] = read_byte();
         lastread = 1;
         tbuffer[i] = read_byte();
         send_stop();

// printf("\n %02x-%02x-%02x %02x:%02x:%02x",tbuffer[4],tbuffer[5],tbuffer[6],tbuffer[2],tbuffer[1],tbuffer[0]);

}

initRTC()
{
       send_start();
       send_byte(0xD0);
       send_byte(0x00);
       send_byte(0x00);
       send_byte(0x30);
       send_byte(0x12);
       send_byte(0x03);
       send_byte(0x25);
       send_byte(0x07);
       send_byte(0x00);
       send_stop();
}

send_time()
{
   readRTC();
}

about()
{
        if(command == 'u')
        {
         putstr(_about);
         sendprompt();
         }
}

settime()
{
    if (command == 't')
    {
    putstr("\nenter current time HH:MM:SS >");
    hour = getbyte();
    putch(':');
    min = getbyte();
    putch(':');
    sec = getbyte();

    send_start();
    send_byte(0xD0);
    send_byte(0x00);
    send_byte(sec);
    send_byte(min);
    send_byte(hour);
    send_stop();
    sendprompt();
    }
}


int getnum()

{
    char s[6];      /* five characters plus terminator */
    char c;
    int i;
    for (i = 0; (c = putch(getch())) != 13; i++)
        s[i] = c;
        s[i] = '\0';
        if (i==0)
        return (-1);
        else
        return (_atoi(s));

}

getbyte()
{
    char s[3];      /* two characters plus terminator */
    int i;
    for (i = 0; i < 2; i++)   /* read two characters then return value */
      s[i] = putch(getch());  // echo to terminal
      s[i] = '\0';
      return(((s[0]-0x30)<<4)|(s[1]-0x30)); // return BCD
   //  return (_atoi(s));                   // return binary
}

char getbyte_dec()
{
    char s[3];      /* two characters plus terminator */
    int i;
    for (i = 0; i < 2; i++)   /* read two characters then return value */
      s[i] = putch(getch());  // echo to terminal
      s[i] = '\0';
   //   return(((s[0]-0x30)<<4)|(s[1]-0x30)); // return BCD
     return (_atoi(s));                   // return binary
}

set_interval()
{
    if(command == 'i'){
     putstr("\n interval 1-600 sec > ");
     setpage(0);
     pokew(interval_saved,(getnum()*100)); // convert to *10 ms 
     interval = peekw(interval_saved);
     counter2 = interval; // load interval to counter2
     sendprompt();
                       }
}


dec_counter2()
{
   if (flag1&0x08){
    counter2--;
    if(counter2 <= 0){
      counter2 = interval;
      flag1 |= 0x04;
                           }
                     }
}

start_record(){

    unsigned char temp;

    counter3--;
    if ( counter3 <= 0){
     counter3 = 100;  // run this task every 1 second
     readRTC();

     temp = tbuffer[2]>>4;  // convert BCD to binary for hour
     temp *=10;
     tbuffer[2] = temp+(tbuffer[2]&0xf);

     temp = tbuffer[1]>>4;  // convert BCD to binary for min
     temp *=10;
     tbuffer[1] = temp+(tbuffer[1]&0xf);

     setpage(0);


  // printf("\n%d:%d==%d:%d",tbuffer[2],tbuffer[1],peek(start_hour),peek(start_min));

 if((tbuffer[2] == peek(start_hour)) && (tbuffer[1]== peek(start_min)))
        {flag1 |= 0x08; // start dec counter2
        blink_every = recording_blink;
        poke(save_flag1,flag1); // save start flag has been set
        }
 if ((tbuffer[2] == peek(stop_hour)) && (tbuffer[1] == peek(stop_min)))
        {flag1 &= ~0x08; //  disable running dec_counter2
        blink_every = standby_blink;
        }
                        }
}


setdate()

{
    if (command == 'd')
    {
    putstr("\nenter current date DD-MM-YR >");
    day = getbyte();
    putch('-');
    month = getbyte();
    putch('-');
    year = getbyte();

    send_start();
    send_byte(0xD0);
    send_byte(0x04);
    send_byte(day);
    send_byte(month);
    send_byte(year);
    send_stop();
    sendprompt();

    }
}


prompting()
 
{
    if (command == 13)
       {
        putstr(title);
        sendprompt();
       }
}

printtime()
{
      if (command == '/')
      {
      readRTC();
   printf("\n%02x-%02x-%02x ",tbuffer[4],tbuffer[5],tbuffer[6]);
   printf("%02x:%02x:%02x ",tbuffer[2],tbuffer[1],tbuffer[0]);
      read_ICL7109();
 printf(" %d %d %d %d",buffer[0],buffer[1],buffer[2],buffer[3]);
      sendprompt();
      }
}

getcommand()
{

    if (SCON&0x01)
        command = putch(getch());
    else command = -1;             /* no cammand has entered */
}

sendprompt()
{
    putstr(prompt);
}


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


cpubeat()
{
    beat5sec();
    livecpu();

}

beat5sec()  /* clear P3.4 every 500 tocks */

{
       counter1++;
        if (counter1 > blink_every )
        {
           counter1 = 0;
           flag1 |= 0x40; /* set bit 6 of flag1 to signal livecpu task */
           clrbit(LED)  //asm " CLR P3.4";
           led = 5;      /* 5*10ms = 50ms LED on */
        }

}

livecpu()

{
    if (flag1&0x40)
      {
        led--;
        if (led == 0)
           {
           setbit(LED)  //asm " SETB P3.4";
           flag1 &= ~0x40;
           }
    }
}


read_ICL7109() /* read analog from ICL7109, save in BUFFER */
{
 //   clrbit(LED) // while reading ADC turns LED on

    P1 |= 0x40; // start ADC

    while((flag1&0x80)==0)
    ;
    flag1 &= ~0x80; // clear flag1
//    setbit(LED)
// printf(" %d %d %d %d",buffer[0],buffer[1],buffer[2],buffer[3]);
}


tick_wait()
{
    asm {
    JNB TCON.5,*      /* wait for timer0 overflow */
    CLR TCON.5
    ORL TH0,#$DC     /* reload $DC00, i.e., for 10ms overflow */
    }
}

int get_address()  /* return address pointer */ 
{
    int i;
    i = pointer[1];
    i <<= 8;
    return(i|pointer[0]);
}

inc_pointer()
{
   asm{
    MOV   A,#1
    ADD   A,pointer
    MOV   pointer,A
    CLR   A
    ADDC  A,pointer+1
    MOV   pointer+1,A
    CLR   A
    ADDC  A,pointer+2
    MOV   pointer+2,A
      }
}
   

int set_RAM_address() /* increment next address SRAM */
{
    inc_pointer();
    setpage(pointer[2]);
    return(get_address());
}

int iset_RAM_address() /* increment next address word based */
{
    inc_pointer();
    inc_pointer();
    setpage(pointer[2]);
    return(get_address());
}

char convert_hi_nibble(unsigned char c)
{
    return((c>>=4)+0x30);
}

char convert_lo_nibble(char c)
{
   return((c&0x0f)+0x30);
}

// format raw data saved in external ram
// number day month year hr min sec adc0 adc1 adc2 adc3 *
// number = 16-bit
// adc0-adc3 = 16-bit
// 17 bytes each record

save_record()
{
     if(flag1&0x04)
     {
        read_ICL7109();
        readRTC();
        pokew(iset_RAM_address(),number_of_record);
        // save date & time
        poke(set_RAM_address(),tbuffer[4]);  // save day
        poke(set_RAM_address(),tbuffer[5]);  // save month
        poke(set_RAM_address(),tbuffer[6]);  // save year

        poke(set_RAM_address(),tbuffer[2]);  // save hr
        poke(set_RAM_address(),tbuffer[1]);  // save min
        poke(set_RAM_address(),tbuffer[0]);  // save sec

     // now save the buffer read from ICL7109

        pokew(iset_RAM_address(),buffer[0]);
        pokew(iset_RAM_address(),buffer[1]);
        pokew(iset_RAM_address(),buffer[2]);
        pokew(iset_RAM_address(),buffer[3]);

        flag1 &= ~0x04;
        ++number_of_record;
        max_limit(); // check maximum for 5000 records
        setpage(0);
        pokew(record_saved,number_of_record); // save available records
    //    printf("%u",number_of_record);
      }
}

max_limit(){   // disable recording mode if number of record > max_record
        if(number_of_record > max_record)
          {flag1 &= ~0x08; //  disable running dec_counter2
           blink_every = standby_blink;
           poke(mode_saved,-1); // change to auto mode indicating maximum limited
          }
}

print_number_of_record()
{
     if (command == 'r')
     {
       printf("\n%u records available",number_of_record);
       sendprompt();
      }
}
/*
get_record()      // test reading until found record terminator
{
    char i;
    if (command == 'g')
    {
    putch('\n');
    j = 101;
    for (j = 101; j< 101+(number_of_record*46); j = j+46)
    {
    for ( i = 0; i <46; i++)
     {
     if(peek(i+j) != 0)
         putch(peek(i+j));
         else putch('\n');
     }
     }
     sendprompt();
    }
}

*/


get_key()
{
    if((xpeek(gpio2,0) != 0xff)&& ((flag1&keypressed)==0))
         {
         flag1 |= keypressed;  // enter only after key was pressed
         key = xpeek(gpio2,0);
     //    printf("%x", key);
         }
        else  key = -1;
}


key_released()
{
        if(xpeek(gpio2,0) == 0xff) flag1 &= ~keypressed;
}

execute_key()
{
       if(key != -1)
       {
       switch (key)
       {
        case 0x7f: channel_display++;
        break;
        case 0xbf:
          flag1^=0x02;
          flag1 &= ~0x10; // show unit
          clr_screen();
          goto_xy(0,1);
          Puts("x0.1mV ");
        if(flag1&0x02)
         {
          putch_lcd('*');
         }
        else
        {
        clr_screen();
        show_mode_on_lcd();
        goto_xy(0,0);
        Puts("Record= ");
        flag1 |= 0x10; // show number of record on LCD
        }
        break;
        case 0xdf: break;
        case 0xef: break;
        }
       }
}

set_start_stop()
{
        if (command == 's'){
        setpage(0);
        printf("\nSTART %02d:%02d >",peek(start_hour),peek(start_min));
        poke(start_hour,getbyte_dec()); // save new start time
        putch(':');
        poke(start_min,getbyte_dec());
        printf("\nSTOP  %02d:%02d >",peek(stop_hour),peek(stop_min));
        poke(stop_hour,getbyte_dec());
        putch(':');
        poke(stop_min,getbyte_dec());
        printf("\n %02d:%02d %02d:%02d",peek(start_hour),peek(start_min),peek(stop_hour),peek(stop_min));
        swapping_mode();
        show_mode_on_lcd();
        sendprompt();
                             }
}

swapping_mode()   // enable/disable manual check
{
        if (peek(start_hour) == 99)
            poke(mode_saved,1); // manual mode
            else (poke(mode_saved,-1)); // automatic mode
}

show_setting(){

      if (command == '='){
      setpage(0);
      printf("\n START %02d:%02d",peek(start_hour),peek(start_min));
      printf("\n STOP  %02d:%02d",peek(stop_hour),peek(stop_min));
      printf("\n SAMPLING INTERVAL(sec) = %u",peekw(interval_saved)/100);
      if (peek(mode_saved) == 1)
      printf("\n MANUAL");
      else (printf("\n AUTO"));
      sendprompt();
      }
}

reload_setting(){
     setpage(0);

     flag1 = peek(save_flag1); // restore flag1

     interval = peekw(interval_saved);
     counter2 = interval;
     number_of_record= peekw(record_saved);
     longset(temp2,46);     // temp2 = 46
     longset(temp1,number_of_record);  // temp1 = number of record
     longmul(temp1,temp2);  // Longreg = temp1*temp2
     longset(temp1,base);   // temp1 = base = 100
     longadd(Longreg,temp1);  // Longreg = Longreg + temp1
     longcpy(pointer,Longreg); // restore pointer
}


new_record()
{
     if (command == 'n')
     {
     putstr("\n New record?(Y/N)");
     if (getch() == 'y')
        { flag1 &= ~0x08;  // reset start bit enable
          number_of_record = 0;
          setpage(0);
          pokew(record_saved,0); // reset number of record to 0
     //     printf("%d",peekw(record_saved));
          longset(pointer,base);
          enter_description();
         }
         sendprompt();
     }
}

print_menu(){
        if (command == '?'){
        putstr(menu);
        sendprompt();
        }
}

clock(){
        if (command == 'c'){
   readRTC();
   printf("\n%02x-%02x-%02x ",tbuffer[4],tbuffer[5],tbuffer[6]);
   printf("%02x:%02x:%02x ",tbuffer[2],tbuffer[1],tbuffer[0]);
        sendprompt();
        }
}

read_all()  // read all record from 100 to current pointer
{
        if (command == 'a'){

        send_description();
        longset(temp1,1);        // decrement pointer
        longsub(pointer,temp1);  
        longcpy(temp1,pointer);  // copy end address to temp1
        longset(pointer,100);  // point to start of NVRAM

      //  while (longcmp(temp1,pointer) > 0)
       for(j=0; j<number_of_record; j++)
           {
        send(0x0d);
        send(0x0a);
        peekw(iset_RAM_address());

 // printf(" %d",peekw(iset_RAM_address()));

  printf(" %d",j);

  printf(" %02x-%02x-%02x",peek(set_RAM_address()),peek(set_RAM_address()),peek(set_RAM_address()));
  printf(" %02x:%02x:%02x",peek(set_RAM_address()),peek(set_RAM_address()),peek(set_RAM_address()));
  printf(" %d", peekw(iset_RAM_address()));
  printf(" %d", peekw(iset_RAM_address()));
  printf(" %d", peekw(iset_RAM_address()));
  printf(" %d", peekw(iset_RAM_address()));
               see_XOFF();
             }      
         sendprompt();
                           }
}

xread_all()  // read all record from 100 to current pointer
{
        if (command == 'x'){

        send_description();
        longset(temp1,1);        // decrement pointer
        longsub(pointer,temp1);  
        longcpy(temp1,pointer);  // copy end address to temp1
        longset(pointer,100);  // point to start of NVRAM

      //  while (longcmp(temp1,pointer) > 0)
       for(j=0; j<number_of_record; j++)
           {
        send(0x0d);
        send(0x0a);
        peekw(iset_RAM_address());

 // printf(" %d",peekw(iset_RAM_address()));

  printf(" %d",j);

  // dummy peak for date and time
  peek(set_RAM_address());
  peek(set_RAM_address());
  peek(set_RAM_address());
  peek(set_RAM_address());
  peek(set_RAM_address());
  peek(set_RAM_address());

  printf(" %d", peekw(iset_RAM_address()));
  printf(" %d", peekw(iset_RAM_address()));
  printf(" %d", peekw(iset_RAM_address()));
  printf(" %d", peekw(iset_RAM_address()));
               see_XOFF();
             }      
         sendprompt();
                           }
}

/*

send_formatted_record()
{
  send(0x0d);
  send(0x0a);
  printf("%c%c/%c%c/%c%c",BUFFER[0],BUFFER[1],BUFFER[2],BUFFER[3],BUFFER[4],BUFFER[5]);    
  printf(",%c%c:%c%c:%c%c",BUFFER[6],BUFFER[7],BUFFER[8],BUFFER[9],BUFFER[10],BUFFER[11]);
  for(j = 0; j< 24; j+=3)  // skip BUFFER[12] = *
  printf(",%c%c%c",BUFFER[13+j],BUFFER[14+j],BUFFER[15+j]);
  printf(",%c%c%c%c%c%c",BUFFER[37],BUFFER[38],BUFFER[39],BUFFER[40],BUFFER[41],BUFFER[42]);
}
*/

see_XOFF()
{
      char c;
        if ( chkchr() == XOFF)
           { 
             while( c != XON)
             c = chkchr();
            }
}

send(char a)    // Dave's putch() automatically send 0x0d after 0x0a
{
        temp = a;
        asm{
        JNB  SCON.1,*
        CLR  SCON.1      
        MOV  A,temp
        MOV  SBUF,A      
            }
}

enter_description()
{
        putstr("\n<-- Enter description text (max 30 characters)-->\n");
        _getstr(BUFFER,30);  // get string max 30 characters
        setpage(0);
        for (j = 0; BUFFER[j] != '\0'; j++)  // save to NVRAM
           poke((description+j),BUFFER[j]);
        poke((description+j),'\0');  // put line terminator
       // sendprompt();
}

send_description()
{
        char c;
        send(0x0d);
        send(0x0a);
        setpage(0);
        for (j = 0; (c = peek(description+j)) != '\0'; j++)
          putch(c);
}

manual_start_stop(){
        setpage(0);
     if (peek(mode_saved)==1){

        if((P3&0x08) == 0)
        {flag1 |= 0x08; // start dec counter2
        blink_every = recording_blink;
        }
        else
        {flag1 &= ~0x08; //  disable running dec_counter2
        blink_every = standby_blink;
        }
                                }
}

show_mode_on_lcd()
{
        setpage(0);
     if (peek(mode_saved)==1)
     {
        goto_xy(7,1);
        putch_lcd('M');
     }
     else
     {
        goto_xy(7,1);
        putch_lcd('A');
     }
}      

print_adc()
{
       if(flag1&0x02)
       {
        read_ICL7109();
        goto_xy(0,0);
        channel_display &= 0x03; // only 0-3 can be used

        putch_lcd(channel_display+49); // show channel 1 to 4 instead
        putch_lcd(' ');
        print_4digit(buffer[channel_display]);
        }
}


print_no_record()
{
        if(flag1&0x10)  // print number of record on lcd
        {
        goto_xy(0,1);
        print_4digit(number_of_record);
        }
}
