/*  Filename     SLAB51.C
    Description  SLAB-51 QC Program v4.3 ???
    Hardware     SLAB-51  
    Chip         89V51RD2BN Xtal 11.0592 MHz (Speed x1)
    Compiler     Keil PK51 v7.10
    Engineer	 Kriangsak B.	
    Company      Sila Research Co.,Ltd. 
*/

#include <reg52.h>
#include <absacc.h>
#include <assert.h>
#include <ctype.h>
#include <intrins.h>
#include <math.h>
#include <setjmp.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define  MAXBUF         40        // maximun for combuf (not include ':' & 0xd)
#define  SHTOUT         40000     // sht15 timeout

/********** I/O PORT **********/

sfr      AUXR 			= 0x8e;   // 89C51RD2 auxr sfr

sbit     P00 			= P0^0;    
sbit     P01 			= P0^1;
sbit     P02 			= P0^2;
sbit     P03 			= P0^3;
sbit     P04 			= P0^4;
sbit     P05 			= P0^5;
sbit     P06 			= P0^6;
sbit     P07 			= P0^7;

sbit     P10 			= P1^0;    
sbit     P11 			= P1^1;
sbit     P12 			= P1^2;
sbit     P13 			= P1^3;
sbit     P14 			= P1^4;
sbit     P15 			= P1^5;
sbit     P16 			= P1^6;
sbit     P17 			= P1^7;

sbit     P20 			= P2^0;    
sbit     P21 			= P2^1;
sbit     P22 			= P2^2;
sbit     P23 			= P2^3;
sbit     P24 			= P2^4;
sbit     P25 			= P2^5;
sbit     P26 			= P2^6;
sbit     P27 			= P2^7;

sbit     P30 			= P3^0;
sbit     P31 			= P3^1;
sbit     P32 			= P3^2;
sbit     P33 			= P3^3;
sbit     P34 			= P3^4;
sbit     P35 		    = P3^5;
sbit     P36 		    = P3^6;
sbit     P37            = P3^7;

sbit     IRSCL          = P1^5;             // ds1307
sbit     IRSDA          = P1^6;                    
sbit     IPSCL          = P1^5;             // 24lc04     
sbit     IPSDA          = P1^6;

#define  LCDPORT        0xc000              // lcd port (memory map)
#define  PSEGM          XBYTE[0xd000]       // 8255 on board
#define  PKEYI          XBYTE[0xd001]  
#define  PDIGT          XBYTE[0xd002]  
#define  PCONT          XBYTE[0xd003]  

#define  USRA   		XBYTE [0xE000]      // 8255 user 
#define  USRB   		XBYTE [0xE001]
#define  USRC   		XBYTE [0xE002]
#define  USRP   		XBYTE [0xE003]

/********** I/O PORT (V-C52) **********/

sbit     P8255A0        = P2^0;             // 8255 
sbit     P8255A1        = P2^1;
sbit     P8255S1        = P2^2;
sbit     P8255S2        = P2^3;
sbit     LCDRS          = P2^4;             // lcd i/o 
sbit     LCDRW          = P2^5;
sbit     LCDEN          = P2^6;
sbit     SOUNDB         = P3^5;

/********** I/O PORT (EXPANSION) **********/

sbit     MXCLK          = P3^2;             // max7219 (p3)
sbit     MXLDB          = P3^3; 
sbit     MXDAT          = P3^5;
sbit     MXCLK2         = P1^0;             // max7219 (p1)
sbit     MXLDB2         = P1^1;
sbit     MXDAT2         = P1^4;

sbit     CARDDA 		= P3^2;             // magnetic (p3)
sbit 	 CARDCK 		= P3^3;
sbit 	 CARDCP 		= P3^5;
sbit     CARDDA2 		= P1^0;             // magnetic (p1)
sbit 	 CARDCK2 		= P1^1;
sbit 	 CARDCP2 		= P1^4;

sbit     DPCLK          = P3^2;             // 6b595 (p3)  
sbit     DPSTR          = P3^3;                 
sbit     DPDAT          = P3^5;                
sbit     DPCLK2         = P1^0;             // 6b595 (p1)  
sbit     DPSTR2         = P1^1;                 
sbit     DPDAT2         = P1^4;                

sbit     DAT            = P3^2;             // sht15 (p3)
sbit     SCK            = P3^3;
sbit     DAT2           = P1^0;             // sht15 (p1)
sbit     SCK2           = P1^1;

sbit     XXSCL			= P3^3;             // I2C (p3)
sbit     XXSDA			= P3^5;          
sbit     XXSCL2			= P1^1;             // I2C (p1)
sbit     XXSDA2			= P1^4;          

sbit     LCDCLK         = P3^2;             // tlcd (p3)
sbit     LCDLD			= P3^3;
sbit     LCDDIN         = P3^5;
sbit     LCDCLK2        = P1^0;             // tlcd (p1)
sbit     LCDLD2			= P1^1;
sbit     LCDDIN2        = P1^4;

/********** INT-RAM WORKING AREA **********/

unsigned char           DISBUF[16] _at_ 0x08;    // display buffer
unsigned char           TIMBUF[8] _at_ 0x18;  	 // ds1307 (8 byte) = ss,mm,hh,ww,dd,mm,yy,cc 
                                                 // m48t0x (7 byte) = ss,mm,hh,ww,dd,mm,yy
unsigned int            SPEEDM;             	 // baud-rate memory
unsigned char           COMINX;             	 // COMBUF index

unsigned char           COMCNT;              	 // COMBUF counter
unsigned char           STRBUF[4+1];        	 // string buffer 
unsigned int            HEX;                	 // hex buffer
unsigned char           LCDNUM;	            	 // lcd number 0=082 1=161 2=162 3=164 4=202 5=204
unsigned char           MAXCOL;		        	 // max column
unsigned char           MAXROW;             	 // max row
unsigned char           ROW;                	 // lcd current-row
unsigned char           COL;                	 // lcd current-column
unsigned char           MXINT;              	 // max7219 intensity
unsigned char           MXDIG;              	 // max7219 digit
unsigned char           B5DIG;              	 // 6b595 digit (p3)
unsigned char           B5DIG2;             	 // 6b595 digit (p1)

         bit            TXOK;               	 // tx flag
         bit            RXOK;               	 // rx command ready flag
         bit            SCOMF;              	 // start command flag
		 bit            ACOMF;              	 // ascii command flag
         bit            KEYFAG;             	 // key flag (scan)
		 bit            CURF;               	 // cursor flag
		 bit            BACKLF;                  // backlight flag

unsigned char bdata     BITMAP;

sbit                    B0 = BITMAP^0;
sbit                    B1 = BITMAP^1;
sbit                    B2 = BITMAP^2;
sbit                    B3 = BITMAP^3;
sbit                    B4 = BITMAP^4;
sbit                    B5 = BITMAP^5;
sbit                    B6 = BITMAP^6;
sbit                    B7 = BITMAP^7;

unsigned char idata     COMBUF[MAXBUF+1];   	 // communication buffer

unsigned char xdata     LCDBUF[80];         	 // lcd buffer
unsigned char xdata     MAGBUF[40];         	 // magnetic buffer
unsigned char xdata     MAGOUT[40];         	 // magnetic buffer

/********** BASIC FUNCTION **********/

void setextram (void) {      // set ext-ram (89v51rd2)    
	unsigned char a;   
    a = AUXR;                          
    a = a | 0x02;
    AUXR = a;
}

void setintram (void) {      // set int-ram (89v51rd2)   
	unsigned char a;   
    a = AUXR;                          
    a = a & 0xfd;
    AUXR = a;
}

void dmsec (unsigned int count) {           // mSec Delay
    unsigned int i;                         // for Keil CA51 (Speed x1)
    while (count) {
        i = 115; while (i>0) i--;
        count--;
    }
}

unsigned char atohr (unsigned char a) {          // change ascii to hex (R)
    if ((a>='a' && a<='f') || (a>='A' && a<='F')) {
		return ((a + 9) & 0xf);
	}
    else return (a & 0xf);
}

unsigned char atohl (unsigned char a) {          // change ascii to hex (L)
    a = atohr (a);
    a = a << 4;
    return (a);
}

unsigned char autobaud (void) {   // auto RS232 baud-rate (speed x1)
    unsigned char x;              // for clock 11.0592 Mhz
    unsigned int speed;           // start by SPACE character or ':'
                                  // auto 1200,2400,4800,9600,19200,38400
    while (1) {
        TMOD = 0x10;              // timer-1 mode-1 16 bit counter
        TH1  = 0x00;
        TL1  = 0x00;
        TR1  = 0;
        while (RXD);              // wait for first start bit
        TR1  = 1;                 // start count
        while (~RXD);
        TR1  = 0;                 // stop count
        speed = TH1;
        speed <<= 8;
        speed |= TL1;             // speed = raw data
        dmsec (100);

        x = ' ';                            // check SPACE
        if (speed>4580 && speed<4620) {
            SPEEDM = 1200;
            return (x); 
        }
        else if (speed>2280 && speed<2320) {
            SPEEDM = 2400;
            return (x); 
        }
        else if (speed>1130 && speed<1170) {
            SPEEDM = 4800;
            return (x); 
        }
        else if (speed>556&& speed<596) {
            SPEEDM = 9600;
            return (x); 
        }
        else if (speed>268 && speed<308) {
            SPEEDM = 19200;
            return (x); 
        }

        x = ':';                            // check ':'
        if (speed>1514 && speed<1554) {
            SPEEDM = 1200;
            return (x); 
        }
        else if (speed>748 && speed<788) {
            SPEEDM = 2400;
            return (x); 
        }
        else if (speed>364 && speed<404) {
            SPEEDM = 4800;
            return (x); 
        }
        else if (speed>172 && speed<212) {
            SPEEDM = 9600;
            return (x); 
        }
        else if (speed>76 & speed<116) {
            SPEEDM = 19200;
            return (x); 
        }
        dmsec (100);
    }
}

void setbaud (void) {             // set RS232 baud rate (speed x1)
    SCON = 0x52;                  // for clock 11.0592 Mhz
    TMOD = 0x20;
    switch (SPEEDM) {
        case  1200: TH1 = 0xe8; break;
        case  2400: TH1 = 0xf4; break;
        case  4800: TH1 = 0xfa; break;
        case  9600: TH1 = 0xfd; break;
        case 19200: TH1 = 0xfd; PCON |= 0x80; break;
    }
    TR1 = 1;
}

void sendon (void) {         // rs485 send on
    dmsec (5);
    T0 = 1;    
}

void sendoff (void) {        // rs485 send off (ascii command mode only)
    while (!TXOK);
    _nop_ ();
    _nop_ ();
    T0 = 0;
}

unsigned int chks (void) {
    unsigned int c,addr;
    bit countflag;
    countflag = 0;
    c = 0;
    for (addr=0x4fff;addr>0;addr--) {       // find checksum (auto 20K)

        if (countflag==0 && CBYTE[addr]!=0xff) countflag = 1;
        if (countflag) c = c + CBYTE[addr];
    }
    c = c + CBYTE[0];
    return (c);
}

void lcdwi (unsigned char com) {       // LCD write instruction
    XBYTE[LCDPORT] = com;  
    while (XBYTE[LCDPORT+1] & 0x80);
}

void lcdwd (unsigned char dat) {       // LCD write data
    XBYTE[LCDPORT+2] = dat;
    while (XBYTE[LCDPORT+1] & 0x80);
}

void lcdset (void) {                   // LCD start process 
    unsigned char i;
    for (i=0;i<=3;i++) {    
        lcdwi (0x38);                  // function set 
    }
    lcdwi (0x0c);                      // display on (cursor off)
}

void lcdclear (void) {                 // clear LCD & LCDBUF 
    unsigned char i;
    lcdwi (0x01);
    for (i=0;i<=79;i++) 
        LCDBUF[i] = ' ';
}

void lcdout (void) {                   // load LCDBUF to LCD 
    unsigned char j;
    if (LCDNUM==1) {                   // lcd 161 model
        lcdwi (0x80);                  // line-1 (L) 
        for (j=1;j<=8;j++)
            lcdwd (LCDBUF[j-1]);
        lcdwi (0xc0);                  // line-1 (R)
        for (j=1;j<=8;j++)
            lcdwd (LCDBUF[j-1+8]);
    }
    else if (LCDNUM==5) {              // lcd 204 model
        lcdwi (0x80);                  // line-1
        for (j=1;j<=20;j++)
            lcdwd (LCDBUF[j-1]);
        lcdwi (0xc0);                  // line-2
        for (j=1;j<=20;j++)
            lcdwd (LCDBUF[j-1+20]);
        lcdwi (0x94);                  // line-3
        for (j=1;j<=20;j++)
            lcdwd (LCDBUF[j-1+40]);
        lcdwi (0xd4);                  // line-4
        for (j=1;j<=20;j++)
            lcdwd (LCDBUF[j-1+60]);
    }
    else {
        lcdwi (0x80);                  // line-1 
        for (j=1;j<=MAXCOL;j++)                          
            lcdwd (LCDBUF[j-1]);
        if (MAXROW==1) return;
        lcdwi (0xc0);                  // line-2 
        for (j=1;j<=MAXCOL;j++)
            lcdwd (LCDBUF[j-1+20]);
        if (MAXROW==2) return;
        lcdwi (0x90);                  // line-3 
        for (j=1;j<=MAXCOL;j++)
            lcdwd (LCDBUF[j-1+40]);
        if (MAXROW==3) return;
        lcdwi (0xd0);                  // line-4 
        for (j=1;j<=MAXCOL;j++)
            lcdwd (LCDBUF[j-1+60]);
    }
}

void lcdcur (void) {                   // set cursor at ROW,COL
    unsigned char c;
    if (LCDNUM==1) {                   // lcd 161 model
        c = COL;
        if (c<8)       {c = c | 0x80; lcdwi (c); lcdwi (0x0e);}
        else if (c<16) {c = (c - 8) | 0xc0; lcdwi (c); lcdwi (0x0e);}
    }
    else if (LCDNUM==5) {              // lcd 204 model
        if (ROW==0) c = 0x80;
        else if (ROW==1) c = 0xc0;
        else if (ROW==2) c = 0x94;
        else if (ROW==3) c = 0xd4;
        if (COL<MAXCOL) {lcdwi (c + COL); lcdwi (0x0e);}
    }
    else {                             // lcd xxx model
        if (ROW==0) c = 0x80;
        else if (ROW==1) c = 0xc0;
        else if (ROW==2) c = 0x90;
        else if (ROW==3) c = 0xd0;
        if (COL<MAXCOL) {lcdwi (c + COL); lcdwi (0x0e);}
    }
}

void plcdwi (unsigned char com) {      // LCD write instruction
    LCDRS = 0; LCDRW = 0; LCDEN = 1;
    P0 = com;
    LCDEN = 0; LCDEN = 1;
    dmsec(1);
}

void plcdwd (unsigned char dat) {      // LCD write data
    LCDRS = 1; LCDRW = 0; LCDEN = 1;
    P0 = dat;
    LCDEN = 0; LCDEN = 1;
    dmsec(1);
}

void plcdset (void) {                  // LCD start process 
    unsigned char i;
    for (i=0;i<=3;i++) {    
        plcdwi (0x38);                 // function set 
    }
    plcdwi (0x0c);                     // display on 
}

void plcdclear (void) {                // clear LCD & LCDBUF 
    unsigned char i;
    plcdwi (0x01);
    for(i=0;i<=39;i++) {
        LCDBUF[i]=' ';
	}
}

void plcdout (void) {                  // load LCDBUF to LCD 
    unsigned char i,j;
    i = 0;
    plcdwi (0x80);                      // line-1 
    for (j=1;j<=20;j++) {
        plcdwd (LCDBUF[i++]);
	}
    plcdwi (0xc0);                      // line-2 
    for (j=1;j<=20;j++) {
        plcdwd (LCDBUF[i++]);
	}
}

void sound (unsigned char freq,int time) {       // Sound Generate
    unsigned char i;
    while (time>0) {
        PDIGT = PDIGT & 0xbf;                    // out signal low 
        for (i=1;i<=freq;i++)
            time--;
        PDIGT = PDIGT | 0x40;                    // out signal high
        for (i=1;i<=freq;i++)
            time--;
    }
}

void psound (unsigned char freq,int time) {      // Sound Generate (i/o)
    unsigned char i;
    while (time>0) {
        SOUNDB = 0;                              // out signal low 
        for (i=1;i<=freq;i++)
            time--;
        SOUNDB = 1;                              // out signal high
        for (i=1;i<=freq;i++)
            time--;
    }
}

unsigned char code KEYTAB[] = {0xe0,0xe1,0xe2,0xe3,
                               0xe4,0xe5,0xe6,0xe7,
                               0xd0,0xd1,0xd2,0xd3,
                               0xd4,0xd5,0xd6,0xd7,  
                               0xb0,0xb1,0xb2,0xb3,
                               0xb4,0xb5,0xb6,0xb7,
                               0x70,0x71,0x72,0x73,
                               0x74,0x75,0x76,0x77};
                               // 32 key table

unsigned char scan (void) {            // scan display & get key
    unsigned char i,j,x;
    bit f;
    f = 0;
    for (i=0;i<=7;i++) {
        x = PDIGT;                     // out digit
        x = (x & 0xf0) | i;
        PDIGT = x;
        PSEGM = DISBUF[i];             // out segment
        dmsec (1);
        PSEGM = 0;
        x = PKEYI & 0x0f;              // check key
        if (x!=0x0f) {
            f = 1;
            if (!KEYFAG) {             // new press
                x = (x << 4) | i;
                for (j=0;j<=31;j++) {
                    if (x==KEYTAB[j]) {
                        sound (20,2000);
                        KEYFAG = 1;
                        return (j);
                    }
                } 
            }
        }
    }
    if (!f) KEYFAG = 0;                // No any key press , clear KEYFAG (release)
    return (0xff);                     // one loop scan
}

void disclear (void) {                 // clear DISBUF
    unsigned char i;
    for (i=0;i<=15;i++) {
        DISBUF[i] = 0;
    }
}

void disload (unsigned char x) {       // load DISBUF from x
    unsigned char i;
    for (i=0;i<=7;i++) {
        DISBUF[i] = x;
    }
}

unsigned char code SEGTAB[16] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,
                                 0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
                                 // standard segment code

unsigned char htosx (unsigned char hex) {        // change hex to segment
    return (SEGTAB[hex]);
}

unsigned char code SEGTABM[16] = {0x7E,0x30,0x6D,0x79,0x33,0x5B,0x5F,0x70,
                                  0x7F,0x7B,0x77,0x1F,0x4E,0x3D,0x4F,0x47};
                                  // max7219 segment code

unsigned char htosm (unsigned char hex) {        // change hex to segment
    return (SEGTABM[hex]);
}

void ipdel (void) {                    // I2C delay 
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
    _nop_ ();
}

void irchigh (void) {                  // I2C clock high for ds1307 
    IRSCL = 1;
    ipdel ();
}

void irclow (void) {                   // I2C clock low for ds1307 
    IRSCL = 0;
    ipdel ();
}

void irstart (void) {                  // start condition for ds1307 
    IRSDA = 1;
    IRSCL = 1;
    IRSDA = 0;
    ipdel ();
    IRSCL = 0;
    IRSDA = 1;
}

void irstop (void) {                   // stop condition for ds1307 
    IRSDA = 0;
    IRSCL = 1;
    ipdel ();
    IRSDA = 1;
}

bit irwrbyte (unsigned dat) {          // write one byte for ds1307
    unsigned char i;                   // return 0 = ok 
    bit outbit;                        // return 1 = error 
    for (i=1;i<=8;i++) {
        outbit = dat & 0x80;
        IRSDA = outbit;
        dat = dat << 1;
        irchigh ();
        irclow ();
    }
    IRSDA = 1;
    irchigh ();
    outbit = IRSDA;
    irclow ();
    return (outbit);
}

unsigned char irrdbyte () {       // read one byte for ds1307 (last byte) 
    unsigned char i,dat;          // return 0xff = error 
    bit inbit;
    dat = 0;
    for (i=1;i<=8;i++) {
        irchigh ();
        inbit = IRSDA;
        dat = dat << 1;
        dat = dat | inbit;
        irclow ();
    }
    IRSDA = 1;
    irchigh ();
    inbit = IRSDA;
    irclow ();
    if (~inbit) dat = 0xff;
    return (dat);
}

unsigned char irrdbytez () {      // read one byte ack=0 for DS1307 
    unsigned char i,dat;         
    bit inbit;
    dat = 0;
    for (i=1;i<=8;i++) {
        irchigh ();
        inbit = IRSDA;
        dat = dat << 1;
        dat = dat | inbit;
        irclow ();
    }
    IRSDA = 0;
    irchigh ();
    irclow ();
    IRSDA = 1;
    return (dat);
}

void rtset (void) {                    // set RTC status bit 
    TIMBUF[0] = TIMBUF[0] & 0x7f;      // clear CH (clock halt) 
    TIMBUF[2] = TIMBUF[2] & 0xbf;      // set 24 hour 
    TIMBUF[7] = TIMBUF[7] & 0xec;      // b7=out b4=sqwe b1,b0=rs 
}

void rtwr (void) {                     // ds1307 rtc write 
    unsigned char i;                   
    irstart ();
    irwrbyte (0xd0);                   // address & r/w bit 
    irwrbyte (0x00);                   // start register addr=0 
    for (i=0;i<=7;i++) 
        irwrbyte (TIMBUF[i]);
    irstop ();
}

void rtrd (void) {                     // ds1307 rtc read 
    unsigned char i,dat;               
    irstart ();
    irwrbyte (0xd0);                   // address & r/w bit 
    irwrbyte (0x00);                   // start register addr=0 
    irstop ();
    ipdel ();

    irstart ();
    irwrbyte (0xd1);                   // address & r/w bit 
    for (i=0;i<=6;i++) {
        dat = irrdbytez ();
        TIMBUF[i] = dat;
    }
    dat = irrdbyte ();                 // last byte 
    TIMBUF[7] = dat;                   // if TIMBUF[7]=0xff error
    irstop ();
}

void ipchigh (void) {                  // I2C clock high 
    IPSCL = 1;
    ipdel ();
}

void ipclow (void) {                   // I2C clock low 
    IPSCL = 0;
    ipdel ();
}

void ipstart (void) {                  // start condition 
    IPSDA = 1;
    IPSCL = 1;
    IPSDA = 0;
    ipdel ();
    IPSCL = 0;
    IPSDA = 1;
}
                                        
void ipstop (void) {                   // stop condition 
    IPSDA = 0;
    IPSCL = 1;
    ipdel ();
    IPSDA = 1;
}

bit ipwrbyte (unsigned dat) {          // write one byte 
    unsigned char i;                   // return 0 = ok 
    bit outbit;                        // return 1 = error 
    for (i=1;i<=8;i++) {
        outbit = dat & 0x80;
        IPSDA = outbit;
        dat = dat << 1;
        ipchigh ();
        ipclow ();
    }
    IPSDA = 1;
    ipchigh ();
    outbit = IPSDA;
    ipclow ();
    return (outbit);
}

unsigned char iprdbyte () {            // read one byte 
    unsigned char i,dat;               // return 0xff = error 
    bit inbit;
    dat = 0;
    for (i=1;i<=8;i++) {
        ipchigh ();
        inbit = IPSDA;
        dat = dat << 1;
        dat = dat | inbit;
        ipclow ();
    }
    IPSDA = 1;
    ipchigh ();
    inbit = IPSDA;
    ipclow ();
    if (~inbit) dat = 0xff;
    return (dat);
}

void ipwrep (unsigned char addr,dat) {      // write 24lc04 (p0) eeprom 
    ipstart ();
    ipwrbyte (0xa0);                        // chip address 
    ipwrbyte (addr);                        // word address 
    ipwrbyte (dat);                         // data 
    ipstop ();
    dmsec (5);
}

unsigned char iprdep (unsigned char addr) {      // read 24lc04 (p0) eeprom 
    unsigned char dat;                           // return 0xff = error 
    ipstart ();                                  // **** set control ****
    ipwrbyte (0xa0);                             // chip address write 
    ipwrbyte (addr);                             // word address 
    ipstop ();
    dmsec (1);

    ipstart ();                                  // **** read ****
    ipwrbyte (0xa1);                             // chip address read 
    dat = iprdbyte (); 
    ipstop ();
    dmsec (1);
    return (dat);
}

unsigned char           TIMBUF[8] _at_ 0x18;  	 // ds1307 (8 byte) = ss,mm,hh,ww,dd,mm,yy,cc 
                                                 // m48t0x (7 byte) = ss,mm,hh,ww,dd,mm,yy

void m48write (unsigned int addr) {    // m48t0x write rtc
    unsigned char x;
    x = XBYTE[addr] | 0x80;            // set w bit
    XBYTE[addr] = x;
    XBYTE[addr+1] = TIMBUF[0] & 0x7f;  // second
    XBYTE[addr+2] = TIMBUF[1] & 0x7f;  // minute
    XBYTE[addr+3] = TIMBUF[2] & 0x3f;  // hour
    XBYTE[addr+4] = TIMBUF[3] & 0x07;  // week
    XBYTE[addr+5] = TIMBUF[4] & 0x3f;  // date
    XBYTE[addr+6] = TIMBUF[5] & 0x1f;  // month
    XBYTE[addr+7] = TIMBUF[6];         // year
    x = XBYTE[addr] & 0x7f;            // clr w bit
    XBYTE[addr] = x;
}

void m48read (unsigned int addr) {     // m48t0x read rtc
    unsigned char x;
    x = XBYTE[addr] | 0x40;            // set r bit
    XBYTE[addr] = x;
    TIMBUF[0] = XBYTE[addr+1];
    TIMBUF[1] = XBYTE[addr+2];
    TIMBUF[2] = XBYTE[addr+3];
    TIMBUF[3] = XBYTE[addr+4];
    TIMBUF[4] = XBYTE[addr+5];
    TIMBUF[5] = XBYTE[addr+6];
    TIMBUF[6] = XBYTE[addr+7];
    x = XBYTE[addr] & 0xbf;            // clr r bit
    XBYTE[addr] = x;
}

void p8255wr (unsigned char a,d) {               // 8255/port write 
    switch (a) {
        case 0: P8255A1 = 0; P8255A0 = 0; break;
        case 1: P8255A1 = 0; P8255A0 = 1; break;
        case 2: P8255A1 = 1; P8255A0 = 0; break;
        case 3: P8255A1 = 1; P8255A0 = 1; break;
    }    
    P0 = d;
    WR = 0;
    WR = 1;        
}

/*
unsigned char p8255rd (unsigned char a) {        // 8255/port read 
	unsigned char d;
    switch (a) {
        case 0: P8255A1 = 0; P8255A0 = 0; break;
        case 1: P8255A1 = 0; P8255A0 = 1; break;
        case 2: P8255A1 = 1; P8255A0 = 0; break;
        case 3: P8255A1 = 1; P8255A0 = 1; break;
    }    
	P0 = 0xff;
    RD = 0;
	d = P0;
    RD = 1;
    return (d);        
}
*/

// ********** 3B port I2C **********

void xxchigh (void) {                  // I2C clock high 
    XXSCL = 1;
    ipdel ();
}

void xxclow (void) {                   // I2C clock low 
    XXSCL = 0;
    ipdel ();
}

void xxstart (void) {                  // start condition 
    XXSDA = 1;
    XXSCL = 1;
    XXSDA = 0;
    ipdel ();
    XXSCL = 0;
    XXSDA = 1;
}
                                        
void xxstop (void) {                   // stop condition 
    XXSDA = 0;
    XXSCL = 1;
    ipdel ();
    XXSDA = 1;
}

bit xxwrbyte (unsigned dat) {          // write one byte 
    unsigned char i;                   // return 0 = ok 
    bit outbit;                        // return 1 = error 
    for (i=1;i<=8;i++) {
        outbit = dat & 0x80;
        XXSDA = outbit;
        dat = dat << 1;
        xxchigh ();
        xxclow ();
    }
    XXSDA = 1;
    xxchigh ();
    outbit = XXSDA;
    xxclow ();
    return (outbit);
}

unsigned char xxrdbyte () {            // read one byte 
    unsigned char i,dat;               // return 0xff = error 
    bit inbit;
    dat = 0;
    for (i=1;i<=8;i++) {
        xxchigh ();
        inbit = XXSDA;
        dat = dat << 1;
        dat = dat | inbit;
        xxclow ();
    }
    XXSDA = 1;
    xxchigh ();
    inbit = XXSDA;
    xxclow ();
    if (~inbit) dat = 0xff;
    return (dat);
}

void xxwr (unsigned char addr,dat) {        // write port (pcf8574a)
    xxstart ();
    addr = ((addr << 1) & 0x0e) | 0x70;
    xxwrbyte (addr);
    xxwrbyte (dat);
    xxstop ();
}

unsigned char xxrd (unsigned char addr) {   // read port 
    unsigned char dat;                      // return 0xff = error 
    xxstart ();
    addr = ((addr << 1) & 0x0e) | 0x71;
    xxwrbyte (addr);
    dat = xxrdbyte (); 
    xxstop ();
    return (dat);
}

void xxchigh2 (void) {                 // I2C clock high 
    XXSCL2 = 1;
    ipdel ();
}

void xxclow2 (void) {                  // I2C clock low 
    XXSCL2 = 0;
    ipdel ();
}

void xxstart2 (void) {                 // start condition 
    XXSDA2 = 1;
    XXSCL2 = 1;
    XXSDA2 = 0;
    ipdel ();
    XXSCL2 = 0;
    XXSDA2 = 1;
}
                                        
void xxstop2 (void) {                  // stop condition 
    XXSDA2 = 0;
    XXSCL2 = 1;
    ipdel ();
    XXSDA2 = 1;
}

bit xxwrbyte2 (unsigned dat) {         // write one byte 
    unsigned char i;                   // return 0 = ok 
    bit outbit;                        // return 1 = error 
    for (i=1;i<=8;i++) {
        outbit = dat & 0x80;
        XXSDA2 = outbit;
        dat = dat << 1;
        xxchigh2 ();
        xxclow2 ();
    }
    XXSDA2 = 1;
    xxchigh2 ();
    outbit = XXSDA2;
    xxclow2 ();
    return (outbit);
}

unsigned char xxrdbyte2 () {           // read one byte 
    unsigned char i,dat;               // return 0xff = error 
    bit inbit;
    dat = 0;
    for (i=1;i<=8;i++) {
        xxchigh2 ();
        inbit = XXSDA2;
        dat = dat << 1;
        dat = dat | inbit;
        xxclow2 ();
    }
    XXSDA2 = 1;
    xxchigh2 ();
    inbit = XXSDA2;
    xxclow2 ();
    if (~inbit) dat = 0xff;
    return (dat);
}

void xxwr2 (unsigned char addr,dat) {       // write port (pcf8574a)
    xxstart2 ();
    addr = ((addr << 1) & 0x0e) | 0x70;
    xxwrbyte2 (addr);
    xxwrbyte2 (dat);
    xxstop2 ();
}

unsigned char xxrd2 (unsigned char addr) {  // read port 
    unsigned char dat;                      // return 0xff = error 
    xxstart2 ();
    addr = ((addr << 1) & 0x0e) | 0x71;
    xxwrbyte2 (addr);
    dat = xxrdbyte2 (); 
    xxstop2 ();
    return (dat);
}

// ********** 3B port max7219 **********

void mxbyte (unsigned char add,dat) {
    unsigned char i;
    for (i=1;i<=8;i++) {               // 8 bit address
        MXDAT = add & 0x80;
        add = add << 1;
        MXCLK = 1;
        MXCLK = 0;
    }
    for (i=1;i<=8;i++) {               // 8 bit data
        MXDAT = dat & 0x80;
        dat = dat << 1;
        MXCLK = 1;
        MXCLK = 0;
    }
    MXLDB = 1;                         // load clock
    MXLDB = 0;
}

void mxset (void) {                    // max7219 setup
    MXCLK = 0;
    MXLDB = 0;
    mxbyte (0x0f,0);                   // display - normal
    mxbyte (0x0c,1);                   // shutdown - normal
    mxbyte (0x09,0);                   // decode - no decode
    mxbyte (0x0a,MXINT);               // intensity
    mxbyte (0x0b,MXDIG);               // scan limit - 4 digit
}

void mxload (void) {                   // max7219 load to display
    mxset ();
    mxbyte (1,DISBUF[0]);
    mxbyte (2,DISBUF[1]);
    mxbyte (3,DISBUF[2]);
    mxbyte (4,DISBUF[3]);
    mxbyte (5,DISBUF[4]);
    mxbyte (6,DISBUF[5]);
    mxbyte (7,DISBUF[6]);
    mxbyte (8,DISBUF[7]);
}

void mxbyte2 (unsigned char add,dat) {
    unsigned char i;
    for (i=1;i<=8;i++) {               // 8 bit address
        MXDAT2 = add & 0x80;
        add = add << 1;
        MXCLK2 = 1;
        MXCLK2 = 0;
    }
    for (i=1;i<=8;i++) {               // 8 bit data
        MXDAT2 = dat & 0x80;
        dat = dat << 1;
        MXCLK2 = 1;
        MXCLK2 = 0;
    }
    MXLDB2 = 1;                        // load clock
    MXLDB2 = 0;
}

void mxset2 (void) {                   // max7219 setup
    MXCLK2 = 0;
    MXLDB2 = 0;
    mxbyte2 (0x0f,0);                  // display - normal
    mxbyte2 (0x0c,1);                  // shutdown - normal
    mxbyte2 (0x09,0);                  // decode - no decode
    mxbyte2 (0x0a,MXINT);              // intensity
    mxbyte2 (0x0b,MXDIG);              // scan limit - 4 digit
}

void mxload2 (void) {                  // max7219 load to display
    mxset2 ();
    mxbyte2 (1,DISBUF[0]);
    mxbyte2 (2,DISBUF[1]);
    mxbyte2 (3,DISBUF[2]);
    mxbyte2 (4,DISBUF[3]);
    mxbyte2 (5,DISBUF[4]);
    mxbyte2 (6,DISBUF[5]);
    mxbyte2 (7,DISBUF[6]);
    mxbyte2 (8,DISBUF[7]);
}

// ********** 3B port magnetic **********

void magclear (void) {                 // magnetic clear buffer
    unsigned char i;
    for (i=0;i<=39;i++) {
        MAGBUF[i] = 0;
        MAGOUT[i] = 0;
    }
}

void magread (void) {    		       // magnetic read raw data	
    unsigned char a,i,j;               // to MAGBUF
    bit dat,first;
    while (CARDCP);                    // wait for CP=0
    a = 0;
    i = 0;
    j = 0;
    first = 1;
    while (!CARDCP) {
        while (CARDCK) {               // wait for CK=0
            if (CARDCP) return; 
        }
        _nop_ ();
        _nop_ ();
        dat = CARDDA;
        if (first) {
            if (!dat) first = 0;       // don't care first bit = 1 
        }
        if (~first) {
            a = a >> 1;
            if (dat) a = a | 0x80;
            i++;
            if (i==5) {
                a = a >> 3;
                a = ~a & 0x1f;
                MAGBUF[j] = a;
                j++;
                i = 0;
            }
        }
        while (!CARDCK);               // wait for CK=1
    }
}

void magread2 (void) {    		       // magnetic read raw data	
    unsigned char a,i,j;               // to MAGBUF
    bit dat,first;
    while (CARDCP2);                   // wait for CP=0
    a = 0;
    i = 0;
    j = 0;
    first = 1;
    while (!CARDCP2) {
        while (CARDCK2) {              // wait for CK=0
            if (CARDCP2) return; 
        }
        _nop_ ();
        _nop_ ();
        dat = CARDDA2;
        if (first) {
            if (!dat) first = 0;       // don't care first bit = 1 
        }
        if (~first) {
            a = a >> 1;
            if (dat) a = a | 0x80;
            i++;
            if (i==5) {
                a = a >> 3;
                a = ~a & 0x1f;
                MAGBUF[j] = a;
                j++;
                i = 0;
            }
        }
        while (!CARDCK2);              // wait for CK=1
    }
}

bit magchk (void) {                    // magnetic check parity 
    unsigned char a,b,i,j;             // and change to ascii (to MAGOUT)
    bit flag;
    for (i=0;i<=39;i++) {
        a = MAGBUF[i];
        if (a==0) break;
        b = 0;
        for (j=0;j<=4;j++) {
            flag = a & 1;
            a = a >> 1;
            if (flag) b++;
        } 
        if ((b % 2)==0) return (1);
        a = MAGBUF[i] & 0xf; 
        if (a>=0xa) a = (a - 9) | 0x40; else a = a | 0x30;
        MAGOUT[i] = a;
    }
    if (MAGOUT[0]!='B') return (1);
    else return (0);
}

void magreverse (void) {                                   // magnetic reverse data
    unsigned char a,b,i,j,p,x,y;
    bit dat,skip;
    for (i=0;i<=39;i++) MAGOUT[i] = 0;                     // clear MAGOUT   
    i = 40; p = 0; x = 0; y = 0; skip = 1;
    while (i>0) {
        i--;
        a = MAGBUF[i]; 
        if (skip && a==0);                                 // nothing
        else {
            a = a << 3;
            for (j=1;j<=5;j++) {
                b = a & 0x80; a = a << 1;
                if (b==0x80) dat = 1; else dat = 0;
                if (skip && dat==1) skip = 0;              // find first bit = 1
                if (!skip) {                               // reverse data
                    if (dat) p = p | 0x80; else p = p & 0x7f;
                    p = p >> 1; y++;
                    if (y==5) {
                        MAGOUT[x++] = p >> 2; 
                        p = 0; y = 0; 
                    }
                }
            }
        }                                            
    }
    if (y>0) {						                       // check end data				
        while (y!=5) { p = p >> 1; y++; }
        MAGOUT[x] = p >> 2;
    }
    for (i=0;i<=39;i++) MAGBUF[i] = MAGOUT[i];             // move to MAGBUF 
}

// ********** 3B port 6B595 **********

void outdpf (void) {                       // out to 7-segment display (3B Port)
    unsigned char a,i,j;          	  
    DPCLK = 0;
    DPSTR = 0;
    for (i=0;i<=B5DIG;i++) {               // digits  
        a = DISBUF[i];
    	for (j=0;j<=7;j++) {
            DPDAT = a & 0x80;
            a = a << 1;
            DPCLK = 1;
            _nop_ ();
            _nop_ ();
            DPCLK = 0;
            _nop_ ();
            _nop_ ();
    	}       
    }
    DPSTR = 1;
    _nop_ ();
    _nop_ ();
    DPSTR = 0;
    _nop_ ();
    _nop_ ();
}

void outdpf2 (void) {                      // out to 7-segment display (3B Port)
    unsigned char a,i,j;          	  
    DPCLK2 = 0;
    DPSTR2 = 0;
    for (i=0;i<=B5DIG2;i++) {              // digits  
        a = DISBUF[i];
    	for (j=0;j<=7;j++) {
            DPDAT2 = a & 0x80;
            a = a << 1;
            DPCLK2 = 1;
            _nop_ ();
            _nop_ ();
            DPCLK2 = 0;
            _nop_ ();
            _nop_ ();
    	}       
    }
    DPSTR2 = 1;
    _nop_ ();
    _nop_ ();
    DPSTR2 = 0;
    _nop_ ();
    _nop_ ();
}

// ********** 3B port sht15 **********

void sht11_delay (void) {
    _nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
    _nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
    _nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
    _nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
	_nop_ ();
}

unsigned char sht11_wb (unsigned char value) { 
	unsigned char i,error = 0;  
  	for (i=0x80;i>0;i/=2) {            // shift bit for masking
        if (i & value) DAT = 1;        // masking value with i , write to I2C-BUS
    	else DAT = 0;                        
    	SCK = 1;                       // clk for I2C-BUS
        sht11_delay ();
    	SCK = 0;
  	}
  	DAT = 1;                           // release DATA-line
  	SCK = 1;                           // clk #9 for ack 
    sht11_delay ();
  	error = DAT;                       // check ack (DATA will be pulled down by SHT11)
  	SCK = 0;        
  	return (error);                    // error=1 in case of no acknowledge
}

unsigned char sht11_rd (unsigned char ack) { 
 	unsigned char i,val = 0;
 	DAT = 1;                           // release DATA-line 
  	for (i=0x80;i>0;i/=2) {            // shift bit for masking
   		SCK = 1;                       // clk for I2C-BUS
        sht11_delay ();
    	if (DAT) val = (val | i);      // read bit  
    	SCK = 0; 
  	}
  	DAT = ack;                         // in case of "ack==1" pull down DATA-Line
  	SCK = 1;                           // clk #9 for ack
    sht11_delay ();
  	SCK = 0;						    
  	DAT = 1;                           // release DATA-line
  	return (val);
}

void sht11_start (void) { 
   	DAT = 1; SCK = 0;                  // Initial state
    sht11_delay ();
   	SCK = 1;       
    sht11_delay ();
   	DAT = 0;            
    sht11_delay ();
   	SCK = 0;       
    sht11_delay ();
   	SCK = 1;       
    sht11_delay ();
   	DAT = 1;            
    sht11_delay ();
   	SCK = 0;       
    sht11_delay ();
}

void sht11_reset (void) {  
	unsigned char i; 
  	DAT = 1; SCK = 0;                  // Initial state
    sht11_delay ();
  	for (i=0;i<=9;i++){                // 9 SCK cycles
		SCK = 1;
        sht11_delay ();
    	SCK = 0;
        sht11_delay ();
  	}
    sht11_start ();
}

float sht11_temp (void) {
	unsigned char error = 0;  
	unsigned int i,temp;
	float ftemp;
  	sht11_start ();                    // start
    error += sht11_wb (0x03);		   // measure 
  	DAT = 1;
  	for (i=0;i<SHTOUT;i++){ 
  		if (DAT==0) break;	           // wait until sensor has finished the measurement
  	}
    if (DAT) error += 1;               // or timeout (~2 sec.) is reached

    if (error>0) ftemp = 0;
	else {
        temp = sht11_rd (1);           // read the first byte (MSB)
		temp <<= 8;
		temp |= sht11_rd (1);          // read the second byte (LSB)
	  	sht11_rd (0);                  // read checksum
		ftemp = temp * 0.01 - 40;	   // calculate
	} 
  	return (ftemp);
}

float sht11_humi (float ftemp) {
	unsigned char error = 0;  
	unsigned int i,humi;
	float fh_lin,fh_true;

	const float C1 = -4.0;			   // for 12 Bit
  	const float C2 = 0.0405;		   // for 12 Bit
  	const float C3 = -0.0000028;	   // for 12 Bit
  	const float T1 = 0.01;			   // for 14 Bit
  	const float T2 = 0.00008;		   // for 14 Bit	
	
	sht11_start ();                    // start
    error += sht11_wb (0x05);		   // measure 
  	DAT = 1;
  	for (i=0;i<SHTOUT;i++){ 
		if (DAT==0) break;	           // wait until sensor has finished the measurement
  	}
    if (DAT) error += 1;               // or timeout (~2 sec.) is reached

    if (error>0) fh_true = 0;
	else {
        humi = sht11_rd (1);           // read the first byte (MSB)
		humi <<= 8;
		humi |= sht11_rd (1);          // read the second byte (LSB)
	  	sht11_rd (0);                  // read checksum

    	fh_lin = (C3 * humi * humi) + (C2 * humi) + C1;         // linear humidity 
     	fh_true = (ftemp - 25) * (T1 + T2 * humi) + fh_lin;     // true humidity
        if (fh_true>100) fh_true = 100;
        else if (fh_true<0.1) fh_true = 0.1;
	} 
  	return (fh_true);
}

unsigned char sht11_wb2 (unsigned char value) { 
	unsigned char i,error = 0;  
  	for (i=0x80;i>0;i/=2) {            // shift bit for masking
        if (i & value) DAT2 = 1;       // masking value with i , write to I2C-BUS
    	else DAT2 = 0;                        
    	SCK2 = 1;                      // clk for I2C-BUS
        sht11_delay ();
    	SCK2 = 0;
  	}
  	DAT2 = 1;                          // release DATA-line
  	SCK2 = 1;                          // clk #9 for ack 
    sht11_delay ();
  	error = DAT2;                      // check ack (DATA will be pulled down by SHT11)
  	SCK2 = 0;        
  	return (error);                    // error=1 in case of no acknowledge
}

unsigned char sht11_rd2 (unsigned char ack) { 
 	unsigned char i,val = 0;
 	DAT2 = 1;                          // release DATA-line 
  	for (i=0x80;i>0;i/=2) {            // shift bit for masking
   		SCK2 = 1;                      // clk for I2C-BUS
        sht11_delay ();
    	if (DAT2) val = (val | i);     // read bit  
    	SCK2 = 0; 
  	}
  	DAT2 = ack;                        // in case of "ack==1" pull down DATA-Line
  	SCK2 = 1;                          // clk #9 for ack
    sht11_delay ();
  	SCK2 = 0;						    
  	DAT2 = 1;                          // release DATA-line
  	return (val);
}

void sht11_start2 (void) { 
   	DAT2 = 1; SCK2 = 0;                // Initial state
    sht11_delay ();
   	SCK2 = 1;       
    sht11_delay ();
   	DAT2 = 0;            
    sht11_delay ();
   	SCK2 = 0;       
    sht11_delay ();
   	SCK2 = 1;       
    sht11_delay ();
   	DAT2 = 1;            
    sht11_delay ();
   	SCK2 = 0;       
    sht11_delay ();
}

void sht11_reset2 (void) {  
	unsigned char i; 
  	DAT2 = 1; SCK2 = 0;                // Initial state
    sht11_delay ();
  	for (i=0;i<=9;i++){                // 9 SCK cycles
		SCK2 = 1;
        sht11_delay ();
    	SCK2 = 0;
        sht11_delay ();
  	}
    sht11_start2 ();
}

float sht11_temp2 (void) {
	unsigned char error = 0;  
	unsigned int i,temp;
	float ftemp;
  	sht11_start2 ();                   // start
    error += sht11_wb2 (0x03);		   // measure 
  	DAT2 = 1;
  	for (i=0;i<SHTOUT;i++){ 
  		if (DAT2==0) break;	           // wait until sensor has finished the measurement
  	}
    if (DAT2) error += 1;              // or timeout (~2 sec.) is reached

    if (error>0) ftemp = 0;
	else {
        temp = sht11_rd2 (1);          // read the first byte (MSB)
		temp <<= 8;
		temp |= sht11_rd2 (1);         // read the second byte (LSB)
	  	sht11_rd2 (0);                 // read checksum
		ftemp = temp * 0.01 - 40;	   // calculate
	} 
  	return (ftemp);
}

float sht11_humi2 (float ftemp) {
	unsigned char error = 0;  
	unsigned int i,humi;
	float fh_lin,fh_true;

	const float C1 = -4.0;			   // for 12 Bit
  	const float C2 = 0.0405;		   // for 12 Bit
  	const float C3 = -0.0000028;	   // for 12 Bit
  	const float T1 = 0.01;			   // for 14 Bit
  	const float T2 = 0.00008;		   // for 14 Bit	
	
	sht11_start2 ();                   // start
    error += sht11_wb2 (0x05);		   // measure 
  	DAT2 = 1;
  	for (i=0;i<SHTOUT;i++){ 
		if (DAT2==0) break;	           // wait until sensor has finished the measurement
  	}
    if (DAT2) error += 1;              // or timeout (~2 sec.) is reached

    if (error>0) fh_true = 0;
	else {
        humi = sht11_rd2 (1);          // read the first byte (MSB)
		humi <<= 8;
		humi |= sht11_rd2 (1);         // read the second byte (LSB)
	  	sht11_rd2 (0);                 // read checksum

    	fh_lin = (C3 * humi * humi) + (C2 * humi) + C1;         // linear humidity 
     	fh_true = (ftemp - 25) * (T1 + T2 * humi) + fh_lin;     // true humidity
        if (fh_true>100) fh_true = 100;
        else if (fh_true<0.1) fh_true = 0.1;
	} 
  	return (fh_true);
}

// ********** 3B port tlcd (3B) **********

void tlcdbyte (char x) {                              // send byte to TLCD-xxx (3B port - 3)
    char i;
    unsigned int c;
    LCDCLK = 1;
    LCDLD = 1;
    for (i=0;i<=7;i++) {
        if (x & 0x80) LCDDIN = 1; else LCDDIN = 0;
        c = 2; while (c>0) c--;                       // approx 10 uS
        LCDCLK = 0;
        c = 2; while (c>0) c--;                       // approx 10 uS
        LCDCLK = 1;
        x = x << 1;
    }
    LCDLD = 0;
    c = 2; while (c>0) c--;
    LCDLD = 1;
    c = 20; while (c>0) c--;                          // approx 100 uS
}

void tlcdbyte2 (char x) {                             // send byte to TLCD-xxx (3B port - 1)
    char i;
    unsigned int c;
    LCDCLK2 = 1;
    LCDLD2 = 1;
    for (i=0;i<=7;i++) {
        if (x & 0x80) LCDDIN2 = 1; else LCDDIN2 = 0;
        c = 2; while (c>0) c--;                       // approx 10 uS
        LCDCLK2 = 0;
        c = 2; while (c>0) c--;                       // approx 10 uS
        LCDCLK2 = 1;
        x = x << 1;
    }
    LCDLD2 = 0;
    c = 2; while (c>0) c--;
    LCDLD2 = 1;
    c = 20; while (c>0) c--;                          // approx 100 uS
}

/********** TEST MAIN **********/

void test1b (void) {
    unsigned char a;
    printf ("\n\nTesting 1B Port (P34,P17) ...");
    printf ("\nType any keys to exit");
    a = 0;
    while (!RI) {
        BITMAP = a;
        P34 = B0;
        P17 = B1;
        dmsec (200);
        a++;
    }
    getkey ();
    P34 = 1;
    P17 = 1;
}

void test3b (void) {
    unsigned char a;
    printf ("\n\nTesting 3B Port (P32,P33,P35,P10,P11,P14) ...");
    printf ("\nType any keys to exit");
    a = 0;
    while (!RI) {
        BITMAP = a;
        P32 = B0;
        P33 = B1;
        P35 = B2;
        P10 = B3;
        P11 = B4;
        P14 = B5;
        dmsec (50);
        a++;
    }
    getkey ();
    P32 = 1;
    P33 = 1;
    P35 = 1;
    P10 = 1;
    P11 = 1;
    P14 = 1;
}

void test3bx (void) {
    unsigned char a;
    printf ("\n\nTesting I/O Port (P12,P13,P17) ...");
    printf ("\nType any keys to exit");
    a = 0;
    while (!RI) {
        BITMAP = a;
        P12 = B3;
        P13 = B4;
        P17 = B5;
        dmsec (50);
        a++;
    }
    getkey ();
    P12 = 1;
    P13 = 1;
    P17 = 1;
}

void test12b (void) {
    unsigned char a,i,j,k;
    printf ("\n\nTesting 12B Port (P1,P32,P33,P34,P35) ...");
    for (k=1;k<=3;k++) {
        j = 0xfe;
        for (i=1;i<=8;i++) {
            a = (j >> 2) | 0xc3;
            P1 = j;
            P3 = a;
            dmsec (400);
            j = (j << 1) | 1;
        }
    }
    for (i=1;i<=3;i++) {
        j = 0x55;
        a = (j >> 2 ) | 0xc3;
        P1 = j;
        P3 = a;
        dmsec (600);
        j = 0xaa;
        a = (j >> 2 ) | 0xc3;
        P1 = j;
        P3 = a;
        dmsec (600);
    }
    P1 = 0xff;
    P3 = 0xff;
}

void test24bs (unsigned int add) {
    unsigned char i,j,k;
    XBYTE[add+3] = 0x80;
    for (k=1;k<=3;k++) {
        j = 1;
        for (i=1;i<=8;i++) {
            XBYTE[add] = j; 
            XBYTE[add+1] = j; 
            XBYTE[add+2] = j; 
            dmsec (400);
            j = j << 1;
        }
    }
    for (i=1;i<=3;i++) {
        j = 0x55;
        XBYTE[add] = j; 
        XBYTE[add+1] = j; 
        XBYTE[add+2] = j; 
        dmsec (600);
        j = 0xaa;
        XBYTE[add] = j; 
        XBYTE[add+1] = j; 
        XBYTE[add+2] = j; 
        dmsec (600);
    }
    j = 0;
    XBYTE[add] = j; 
    XBYTE[add+1] = j; 
    XBYTE[add+2] = j; 
}

void test24b (void) {
    printf ("\n\nTesting 24B Port [8255/E000-E003H] ...");
	test24bs (0xe000);  
}

void testlcd (void) {
    unsigned char a,i;
    printf ("\n\nTesting LCD Port with LCD20x2 (Backlight-PC4) ...");
    LCDNUM = 4;
    MAXROW = 2; 
    MAXCOL = 20;
    lcdset ();
    lcdclear ();
    dmsec (1000);
    PDIGT = PDIGT & 0xef;                        // backlight on 
    for (a='0';a<='9';a++) {
        for (i=0;i<=79;i++) LCDBUF[i] = a;
        lcdout ();
        dmsec (400);
    }
    for (i=0;i<=79;i++) LCDBUF[i] = 0xff;
    lcdout ();
    for (i=0;i<=3;i++) {                         // backlight flash
        PDIGT = PDIGT & 0xef;
        dmsec (200);
        PDIGT = PDIGT | 0x10;                 
        dmsec (200);
    }
}

void testscan (void) {
    unsigned char a;
    printf ("\n\nTesting 4x8K,8x8D Port & Speaker (8255) ...");
    printf ("\nType any keys to exit");
    disclear ();
    disload (0x40);
    while (!RI) {
        a = scan (); 
        if (a!=0xff) {
            DISBUF[0] = htosx ((a & 0xf0) >> 4); 
            DISBUF[1] = htosx (a & 0x0f);
            DISBUF[2] = DISBUF[0];
            DISBUF[4] = DISBUF[0];
            DISBUF[6] = DISBUF[0];
            DISBUF[3] = DISBUF[1];
            DISBUF[5] = DISBUF[1];
            DISBUF[7] = DISBUF[1];
        }    
    }
    getkey ();
}

void testdip (void) {
    unsigned char a,b,x,i;
    printf ("\n\nTesting INT0,INT1 Key & Dip-Switch ...");
    printf ("\nType any keys to exit");
    b = 0xff;
    while (!RI) {
        a = (PKEYI & 0xf0) >> 2;
        if (INT0==1) a |= 0x1; 
        if (INT1==1) a |= 0x2;
        if (a!=b) {
            printf ("\nINT0,INT,Dip1-4 = ");
            x = a;
            for (i=0;i<=5;i++) {
                if ((x & 0x1)==0) printf ("0"); else printf ("1");
                x >>= 1;
            }
            b = a;
        }
    }
    getkey ();
}

void testrtc (void) {
    unsigned char x;
    printf ("\n\nTesting RTC DS1307 ...");
    printf ("\nType (S) to set time at 23:59:55 28/02/04");
    printf ("\nor any keys to Continue Display :");
    x = getkey ();
    if (x=='S' || x=='s') {
        TIMBUF[4] = 0x28;
        TIMBUF[5] = 0x02;
        TIMBUF[6] = 0x04;
        TIMBUF[3] = 0x01;
        TIMBUF[2] = 0x23;
        TIMBUF[1] = 0x59;
        TIMBUF[0] = 0x55;
        rtset ();
        rtwr ();
		dmsec (200);
    }
    printf ("\nType any keys to exit");
    x = 0xff;
    while (!RI) {
        dmsec (100);
        rtrd ();
        if (TIMBUF[0]!=x) {
            printf ("\ntime %02bx:%02bx:%02bx  date %02bx/%02bx/%02bx",
            TIMBUF[2],TIMBUF[1],TIMBUF[0],TIMBUF[4],TIMBUF[5],TIMBUF[6]);
            x = TIMBUF[0];
        }
    }
    getkey ();
}

void test24lc04 (void) {
    bit err;
    printf ("\n\nTesting EEprom 24LC04 ... ");
    ipwrep (0,0xaa);
    ipwrep (1,0x55);
    err = 0;
    if (iprdep (0)!=0xaa) err = 1;
    if (iprdep (1)!=0x55) err = 1;
    if (err) printf ("Error !");
    else printf ("OK");
    printf ("\nType any keys ");
    getkey ();
}

void testram (unsigned int start,end) {
    unsigned int run,block;
    unsigned char a,b;
    bit err;
    printf ("Testing RAM %04X-%04XH ...\n",start,end);
	setextram ();
    run = start;                            // write memory 
    a = 0x11;
    while (run<=end) {
        XBYTE[run] = a;
        a++;
        if (a==0x9a) a = 0x11;
        run++;
    }
    run = start;                            // read & check 
    block = run;
    a = 0x11;
    err = 0;
    while (run<=end) {
        b = XBYTE[run];
        if (b!=a) err = 1;
        XBYTE[run] = 0;                     // clear ram
        a++;
        if (a==0x9a) {
            a = 0x11;
            if (err) printf ("%04X    ",block);
            else printf ("%04X=OK ",block);
            err = 0;
            block = run;
        }
        run++;
    }
	setintram ();
    printf ("\nType any keys ");
    getkey ();
}

void testram8 (void) {                      // test 8k ram 
	printf ("\n\n");
	testram (0,0x1fff);
}

void testram32 (void) {                     // test 32k ram 
	printf ("\n\n");
	testram (0,0x7fff);
}

void testram128 (void) {                    // test 128k ram (4 blank)
    P16 = 0; 
	P15 = 0;
    printf ("\n\nBlank-0\n");
	testram (0,0x7fff);     
    P16 = 0; 
	P15 = 1;
    printf ("\n\nBlank-1\n");
	testram (0,0x7fff);     
    P16 = 1; 
	P15 = 0;
    printf ("\n\nBlank-2\n");
	testram (0,0x7fff);     
    P16 = 1; 
	P15 = 1;
    printf ("\n\nBlank-3\n");
	testram (0,0x7fff);     
}

void testram8p (void) {                     // test 8k ram (8000)
	printf ("\n\n");
	testram (0x8000,0x9fff);
}

void test8255s (void) {
    unsigned char i,j,k;
    p8255wr (3,0x80);
    for (k=1;k<=3;k++) {
        j = 1;
        for (i=1;i<=8;i++) {
            p8255wr (0,j);
            p8255wr (1,j);
            p8255wr (2,j);
            dmsec (400);
            j = j << 1;
        }
    }
    for (i=1;i<=3;i++) {
        j = 0x55;
		p8255wr (0,j);
		p8255wr (1,j);
		p8255wr (2,j);
        dmsec (600);
        j = 0xaa;
		p8255wr (0,j);
		p8255wr (1,j);
		p8255wr (2,j);
        dmsec (600);
    }
    j = 0;
	p8255wr (0,j);
	p8255wr (1,j);
	p8255wr (2,j);
}

void test8255cs1 (void) {
    printf ("\n\nTesting 24B Port [I/O-8255-CS1] ...");
    P8255S1 = 0;
	test8255s ();  
	P8255S1 = 1;
}

void test8255cs2 (void) {
    printf ("\n\nTesting 24B Port [I/O-8255-CS2] ...");
    P8255S2 = 0;
	test8255s ();  
	P8255S2 = 1;
}

void testlcd27 (void) {
    unsigned char a,i;
    printf ("\n\nTesting LCD Port with LCD20x2 (Backlight-P27) ...");
    plcdset ();
    plcdclear ();
    dmsec (1000);
	P27 = 0;			                         // backlight on 
    for (a='0';a<='9';a++) {
        for (i=0;i<=79;i++) LCDBUF[i] = a;
        plcdout ();
        dmsec (400);
    }
    for (i=0;i<=79;i++) LCDBUF[i] = 0xff;
    plcdout ();
    for (i=0;i<=3;i++) {                         // backlight flash
        P27 = 0;
        dmsec (200);
        P27 = 1;
        dmsec (200);
    }
}

void testkeysp (void) {
    unsigned char a,b,x,i;
    printf ("\n\nTesting INT0,INT1 Key & Speaker (P35) ...");
    printf ("\nType any keys to exit");
    b = 0xff;
    while (!RI) {
		a = 0; 
        if (INT0==1) a |= 0x1; 
        if (INT1==1) a |= 0x2;
        if (a!=b) {
            printf ("\nINT0,INT = ");
            x = a;
            for (i=0;i<=1;i++) {
                if ((x & 0x1)==0) printf ("0"); else printf ("1");
                x >>= 1;
            }
            b = a;
			psound (20,10000);
        }
    }
    getkey ();
}

/********** TEST SUB-MENU **********/

void testlcdx (void) {                 // test lcd 
    unsigned char a,i;
    printf ("\n\nWorking ...");
    switch (LCDNUM) {
        case 0: MAXROW = 2; MAXCOL = 8; break; 
        case 1: MAXROW = 1; MAXCOL = 16; break; 
        case 2: MAXROW = 2; MAXCOL = 16; break; 
        case 3: MAXROW = 4; MAXCOL = 16; break; 
        case 4: MAXROW = 2; MAXCOL = 20; break; 
        case 5: MAXROW = 4; MAXCOL = 20; break; 
    }

    lcdset ();
    lcdclear ();
    dmsec (1000);
    for (a='0';a<='9';a++) {
        for (i=0;i<=79;i++) LCDBUF[i] = a;
        lcdout ();
        dmsec (400);
    }
    for (i=0;i<=79;i++) LCDBUF[i] = 0xff;
    lcdout ();
    dmsec (1000);
    a = 'A';
    for (i=0;i<=19;i++) {LCDBUF[i] = a; a++;}
    a = 'a';
    for (i=20;i<=39;i++) {LCDBUF[i] = a; a++;}
    a = 'A';
    for (i=40;i<=59;i++) {LCDBUF[i] = a; a++;}
    a = 'a';
    for (i=60;i<=79;i++) {LCDBUF[i] = a; a++;}
    lcdout ();
}                 

void backonoff (void) {                     // backlight on/off
    BACKLF = ~BACKLF;
    if (BACKLF) {                           // on
        printf ("\n\nBacklight = ON");
        PDIGT = PDIGT & 0xef;
    }
    else {                                  // off 
        printf ("\n\nBacklight = OFF");
        PDIGT = PDIGT | 0x10;                 
    }
}

void testex24b (void) {
    unsigned char x,m;
    USRP = 0x80;              
    m = 0;
    printf ("\n\nTest EX-Series (24B Port,PA0-PA3 or PA4-PA7) ...");
    printf ("\nType 0-7 to work ");
    while (1) {
        x = getkey ();
		switch (x) {
			case '0': if (m & 0x01) m &= 0xfe; else m |= 0x01; USRA = m; break;
			case '1': if (m & 0x02) m &= 0xfd; else m |= 0x02; USRA = m; break;
			case '2': if (m & 0x04) m &= 0xfb; else m |= 0x04; USRA = m; break;
			case '3': if (m & 0x08) m &= 0xf7; else m |= 0x08; USRA = m; break;
			case '4': if (m & 0x10) m &= 0xef; else m |= 0x10; USRA = m; break;
			case '5': if (m & 0x20) m &= 0xdf; else m |= 0x20; USRA = m; break;
			case '6': if (m & 0x40) m &= 0xbf; else m |= 0x40; USRA = m; break;
			case '7': if (m & 0x80) m &= 0x7f; else m |= 0x80; USRA = m; break;
			default: return;
        }
    }
}

void testex12b (void) {
    unsigned char x;
    P1 = 0xff;
    printf ("\n\nTest EX-Series (12B Port,P10-P13 or P14-P17) ...");
    printf ("\nType 0-7 to work ");
    while (1) {
        x = getkey ();
		switch (x) {
			case '0': P10 = ~P10; break;
			case '1': P11 = ~P11; break;
			case '2': P12 = ~P12; break;
			case '3': P13 = ~P13; break;
			case '4': P14 = ~P14; break;
			case '5': P15 = ~P15; break;
			case '6': P16 = ~P16; break;
			case '7': P17 = ~P17; break;
			default: return;
        }
    }
}

void testex3b (void) {
    unsigned char x;
    printf ("\n\nTest EX-Series (3B Port[P10,P11,P13] & Set Address A0-A2=0) ...");
    printf ("\nType 0-7 to work ");
    BITMAP = 0xff;
    xxwr2 (0,BITMAP);
    while (1) {
        x = getkey ();
		switch (x) {
			case '0': B0 = ~B0; xxwr2 (0,BITMAP); break;
			case '1': B1 = ~B1; xxwr2 (0,BITMAP); break;
			case '2': B2 = ~B2; xxwr2 (0,BITMAP); break;
			case '3': B3 = ~B3; xxwr2 (0,BITMAP); break;
			case '4': B4 = ~B4; xxwr2 (0,BITMAP); break;
			case '5': B5 = ~B5; xxwr2 (0,BITMAP); break;
			case '6': B6 = ~B6; xxwr2 (0,BITMAP); break;
			case '7': B7 = ~B7; xxwr2 (0,BITMAP); break;
			default: return;
        }
    }
}

void testdp595 (void) {
    unsigned char i,j,k,x;
    printf ("\n\nTest DP-Series (3B Port[P10,P11,P13],6B595,8 Digits) ...");
    printf ("\nWorking ");
    B5DIG2 = 7;
    disclear ();
    outdpf2 (); 
    for (i=0;i<=2;i++) {			             // loop-shift
   	    x = 1;
       	for (j=0;j<=7;j++) {         	         // shift segment
            for (k=0;k<=7;k++) DISBUF[k] = x;
	    	outdpf2 ();
       	    dmsec (500);  
			x <<= 1;
	    }			
   	}
    disclear ();
	outdpf2 ();
	dmsec (500);
   	for (i=0;i<=2;i++) {			             // loop-flash
	    DISBUF[0] = htosx (0);
       	DISBUF[1] = htosx (1);
        DISBUF[2] = htosx (2);
   	    DISBUF[3] = htosx (3);
       	DISBUF[4] = htosx (4);
        DISBUF[5] = htosx (5);
   	    DISBUF[6] = htosx (6);
       	DISBUF[7] = htosx (7);
    	outdpf2 ();
		dmsec (1500);
   	    disclear ();
    	outdpf2 ();
		dmsec (500);
	}			
    DPCLK2 = 1;					                 // clear port 
    DPSTR2 = 1;
    DPDAT2 = 1;
}

void test7219 (void) {
    unsigned char i,j,k,x;
    printf ("\n\nTest DP-Series (3B Port[P10,P11,P13],max7219,8 Digits) ...");
    printf ("\nWorking ");
	disclear ();
    MXINT = 0xf;
    MXDIG = 0x7;
	mxset2 ();
	mxload2 ();
    for (i=0;i<=2;i++) {			             // loop-shift
   	    x = 1;
       	for (j=0;j<=7;j++) {         	         // shift segment
            for (k=0;k<=7;k++) DISBUF[k] = x;
			mxload2 ();
       	    dmsec (500);  
			x <<= 1;
	    }			
   	}
    disclear ();
	mxload2 ();
	dmsec (500);
   	for (i=0;i<=2;i++) {			             // loop-flash
	    DISBUF[0] = htosm (0);
       	DISBUF[1] = htosm (1);
        DISBUF[2] = htosm (2);
   	    DISBUF[3] = htosm (3);
       	DISBUF[4] = htosm (4);
        DISBUF[5] = htosm (5);
   	    DISBUF[6] = htosm (6);
       	DISBUF[7] = htosm (7);
		mxload2 ();
		dmsec (1500);
   	    disclear ();
    	mxload2 ();
		dmsec (500);
	}			
    MXCLK2 = 1;					                 // clear port 
    MXLDB2 = 1;
    MXDAT2 = 1;
}

void testdk (void) {
    unsigned char a; 
    printf ("\n\nTesting DP,DK-Series (Scan 8x8D,4x8K Port) ...");
    printf ("\nType any keys to exit");
    disclear ();
    disload (0x40);
    while (!RI) {
        a = scan (); 
        if (a!=0xff) {
            DISBUF[0] = htosx ((a & 0xf0) >> 4); 
            DISBUF[1] = htosx (a & 0x0f);
            DISBUF[2] = DISBUF[0];
            DISBUF[4] = DISBUF[0];
            DISBUF[6] = DISBUF[0];
            DISBUF[3] = DISBUF[1];
            DISBUF[5] = DISBUF[1];
            DISBUF[7] = DISBUF[1];
        }    
    }
    getkey ();
}

void testtlcd (void) {
    unsigned char a; 
    printf ("\n\nTesting RS232 to 3B Port Serial (TLCD) ...");
    printf ("\nType Ctrl-C to exit ");
    while (1) {
        a = getkey (); 
		if (a==0x03) return;
		tlcdbyte2 (a);
    }
}

void testmag (void) {
    unsigned char i;
	bit er;
    printf ("\n\nTest Magnetic,Proximity (3B Port[P10,P11,P13]) ...\n");
	magclear ();
   	magread2 ();    
	er = magchk ();
    if (er) {
		magreverse ();
		er = magchk ();
	}
	if (er) printf ("Error !");
	else {
	    for (i=0;i<=39;i++) {
    	    if (MAGOUT[i]==0) break;
        	printf ("%c",MAGOUT[i]);
	    }
	}
}

void testsht15 (void) {           // sht15
    float ft,fh;
    printf ("\n\nTest SHT15 Temp & Humidity (3B Port[P10,P11,P13]) ...");
    printf ("\nType any keys to exit");
    while (!RI) {
	   	sht11_reset2 ();                  
		ft = sht11_temp2 ();    
	    fh = sht11_humi2 (ft);
	    printf ("\nT%05.1f H%04.1f",ft,fh);
		dmsec (1000);
	}
    getkey ();
}

void testm48 (void) {
    unsigned char x;
    unsigned int addr;
    printf ("\n\nSelect 1=M48T08 2=M48T35 >");
    x = getchar ();
	if (x=='1') addr = 0x1ff8; else addr = 0x7ff8;
    printf ("\nTesting RTC M48Txx (On DMEM 0000H Socket)...");
    printf ("\nType (S) to set time at 23:59:55 28/02/04");
    printf ("\nor any keys to Continue Display :");
    x = getkey ();
    if (x=='S' || x=='s') {
        TIMBUF[4] = 0x28;
        TIMBUF[5] = 0x02;
        TIMBUF[6] = 0x04;
        TIMBUF[3] = 0x01;
        TIMBUF[2] = 0x23;
        TIMBUF[1] = 0x59;
        TIMBUF[0] = 0x55;
        m48write (addr);
		dmsec (200);
    }
    printf ("\nType any keys to exit");
    x = 0xff;
    while (!RI) {
        dmsec (100);
		m48read (addr);
        if (TIMBUF[0]!=x) {
            printf ("\ntime %02bx:%02bx:%02bx  date %02bx/%02bx/%02bx",
            TIMBUF[2],TIMBUF[1],TIMBUF[0],TIMBUF[4],TIMBUF[5],TIMBUF[6]);
            x = TIMBUF[0];
        }
    }
    getkey ();
}

/********** INTERRUPT FUNCTION **********/

void input (unsigned char a) {              // input to COMBUF
    unsigned char i;                   
    if (a==':') {                           // start 
        COMINX = 0;  
        SCOMF = 1;
        for (i=0;i<=MAXBUF;i++) COMBUF[i] = 0;
    }

    else {
        if (SCOMF) {
            if (a==0x0d || a==0xff) {       // end
                COMBUF[COMINX] = a;
                SCOMF = 0;  
                RXOK = 1;
            }    
            else if (a<0x20) return;        // nothing
            else if (COMINX<MAXBUF) {
                COMBUF[COMINX] = a;         // command
                COMINX++;
            }
        }
    }
}

void serial (void) interrupt 4 {            // serial interrupt 
    unsigned char a;                        // receive binary command
    if (TI) {                               // TXD
        TI = 0;
        TXOK = 1;
        return;
    }

    a = SBUF;                               // RXD
    RI = 0;
    input (a);
}

                                            // modify function for printf		
char putchar (char x) {                     // send one byte  
    if (ACOMF) {
	    while (!TXOK);
    	TXOK = 0;
	    SBUF = x;
    }
	else {
        if (x=='\n') {
		    while (!TI);
		    TI = 0;
		    SBUF = 0x0d;                    
		}
	    while (!TI);
    	TI = 0;
	    SBUF = x;
	}
    return (x);
}

/********** COM FUNCTION (SUB) **********/

void pokr (void) {                // print OK\r
    printf ("OK\r");
}

void pok (void) {                 // print OK
    printf ("OK");
}

void perr (void) {                // print ER\r
    printf ("ER\r");
}

void per (void) {                 // print ER
	printf ("ER");
}

/*
bit tohex (void) {                // change ascii to hex (COMBUF)
    unsigned char i;              // 0=no 1=yes
    HEX = 0;
	i = 0;
   	while (1) {
	    if (COMBUF[COMCNT]==',') {
		    COMCNT++;
		    if (i==0) return (0);
			else if (i>4) return (0);
			else return (1);
		}
        if (COMBUF[COMCNT]==0xd) {
		    if (i==0) return (0);
			else if (i>4) return (0);
			else return (1);
		}
        HEX = (HEX << 4) | atohr (COMBUF[COMCNT++]);
		i++;
    }
}
*/

void pbit (bit a) {                              // print bit
    if (a) printf ("1"); else printf ("0");
}

void pbyte (unsigned char a) {                   // print byte
    printf ("%02bX",a);
}

/********** COM FUNCTION (BASIC) **********/

void comp (void) {			      // port (bit)
    unsigned char x,y;
	bit f;
	x = COMBUF[1];                // port bit-address 
	y = COMBUF[2];
	if (x==0xd || y==0xd) {perr (); return;}
	x = atohl (x) | atohr (y);
    y = COMBUF[3];                // option data 
    if (y==0xd) f = 0;
	else if (COMBUF[4]!=0xd) {perr (); return;}
    else {
		f = 1;
	    if (y=='0') y = 0; else if (y=='1') y = 1;
 		else {perr (); return;}
    } 

   	switch (x) {
		case 0x00: if (f) {P00 = y; pok (); break;} else {pbit (P00); break;}
		case 0x01: if (f) {P01 = y; pok (); break;} else {pbit (P01); break;}
		case 0x02: if (f) {P02 = y; pok (); break;} else {pbit (P02); break;}
		case 0x03: if (f) {P03 = y; pok (); break;} else {pbit (P03); break;}
		case 0x04: if (f) {P04 = y; pok (); break;} else {pbit (P04); break;}
		case 0x05: if (f) {P05 = y; pok (); break;} else {pbit (P05); break;}
		case 0x06: if (f) {P06 = y; pok (); break;} else {pbit (P06); break;}
		case 0x07: if (f) {P07 = y; pok (); break;} else {pbit (P07); break;}

		case 0x10: if (f) {P10 = y; pok (); break;} else {pbit (P10); break;}
		case 0x11: if (f) {P11 = y; pok (); break;} else {pbit (P11); break;}
		case 0x12: if (f) {P12 = y; pok (); break;} else {pbit (P12); break;}
		case 0x13: if (f) {P13 = y; pok (); break;} else {pbit (P13); break;}
		case 0x14: if (f) {P14 = y; pok (); break;} else {pbit (P14); break;}
		case 0x15: if (f) {P15 = y; pok (); break;} else {pbit (P15); break;}
		case 0x16: if (f) {P16 = y; pok (); break;} else {pbit (P16); break;}
		case 0x17: if (f) {P17 = y; pok (); break;} else {pbit (P17); break;}

		case 0x20: if (f) {P20 = y; pok (); break;} else {pbit (P20); break;}
		case 0x21: if (f) {P21 = y; pok (); break;} else {pbit (P21); break;}
		case 0x22: if (f) {P22 = y; pok (); break;} else {pbit (P22); break;}
		case 0x23: if (f) {P23 = y; pok (); break;} else {pbit (P23); break;}
		case 0x24: if (f) {P24 = y; pok (); break;} else {pbit (P24); break;}
		case 0x25: if (f) {P25 = y; pok (); break;} else {pbit (P25); break;}
		case 0x26: if (f) {P26 = y; pok (); break;} else {pbit (P26); break;}
		case 0x27: if (f) {P27 = y; pok (); break;} else {pbit (P27); break;}

		case 0x30: if (f) {P30 = y; pok (); break;} else {pbit (P30); break;}
		case 0x31: if (f) {P31 = y; pok (); break;} else {pbit (P31); break;}
		case 0x32: if (f) {P32 = y; pok (); break;} else {pbit (P32); break;}
		case 0x33: if (f) {P33 = y; pok (); break;} else {pbit (P33); break;}
		case 0x34: if (f) {P34 = y; pok (); break;} else {pbit (P34); break;}
		case 0x35: if (f) {P35 = y; pok (); break;} else {pbit (P35); break;}
		case 0x36: if (f) {P36 = y; pok (); break;} else {pbit (P36); break;}
		case 0x37: if (f) {P37 = y; pok (); break;} else {pbit (P37); break;}
		default: per ();
	}
	printf ("\r");
}

void comr (void) {			      // port (byte)
    unsigned char x,y,z;
	bit f;
	z = COMBUF[1];                // port address
	x = COMBUF[2];                // option data
	y = COMBUF[3];
	if (x==0xd) f = 0; 
	else if (y==0xd) {perr (); return;}
	else if (COMBUF[4]!=0xd) {perr (); return;}
	else {
		f = 1;
		x = atohl (x) | atohr (y);
	}
   	switch (z) {
		case '0': if (f) {P0 = x; pok (); break;} else {pbyte (P0); break;}
		case '1': if (f) {P1 = x; pok (); break;} else {pbyte (P1); break;}
		case '2': if (f) {P2 = x; pok (); break;} else {pbyte (P2); break;}
		case '3': if (f) {P3 = x; pok (); break;} else {pbyte (P3); break;}
		default: per ();
	}
	printf ("\r");
}

void comx (void) {                // data memory
    unsigned int addr;
    unsigned char x,y;
	bit f;
	x = COMBUF[1];                // address 
	y = COMBUF[2];
	if (x==0xd || y==0xd) {perr (); return;}
	addr = atohl (x) | atohr (y);
	x = COMBUF[3];               
	y = COMBUF[4];
	if (x==0xd || y==0xd) {perr (); return;}
	addr = (addr << 8) | atohl (x) | atohr (y);

	x = COMBUF[5];                // option data
	y = COMBUF[6];
	if (x==0xd) f = 0; 
	else if (y==0xd) {perr (); return;}
	else if (COMBUF[7]!=0xd) {perr (); return;}
	else {
		f = 1;
		x = atohl (x) | atohr (y);
	}

	if (f) {XBYTE[addr] = x; pok ();}
	else pbyte (XBYTE[addr]);
	printf ("\r");
}

void comls (void) {                    // LCD set

    if (COMBUF[2]==0xd) {perr (); return;}
    LCDNUM = atohr (COMBUF[2]);
    switch (LCDNUM) {
        case 0: MAXROW = 2; MAXCOL = 8; break; 
        case 1: MAXROW = 1; MAXCOL = 16; break; 
        case 2: MAXROW = 2; MAXCOL = 16; break; 
        case 3: MAXROW = 4; MAXCOL = 16; break; 
        case 4: MAXROW = 2; MAXCOL = 20; break; 
        case 5: MAXROW = 4; MAXCOL = 20; break; 
		default: perr (); return;
    }
    lcdset ();
    lcdclear ();
	COL = 0;
	ROW = 0;
	CURF = 0;
	pokr ();
}

void comlp (void) {                    // LCD position 

    if (COMBUF[2]==0xd || COMBUF[3]==0xd || COMBUF[4]==0xd || COMBUF[5]==0xd) {perr (); return;}
    STRBUF[0] = COMBUF[2];
	STRBUF[1] = COMBUF[3];
	STRBUF[2] = 0;
    COL = atoi (STRBUF);
	if (COL>19) {perr (); return;}
    ROW = atohr (COMBUF[4]);
	if (ROW>3) {perr (); return;}

    if (COMBUF[5]=='0') {              // cursor off   
	    CURF = 0;
		lcdwi (0x0c);  
	}
	else if (COMBUF[5]=='1') {         // cursor on 
	    CURF = 1;
	    lcdcur ();                      
	}
	else {perr (); return;}
	pokr ();
}

void comlt (void) {                    // LCD text
    unsigned char i,x;
	i = 2;
    while (1) {
	    x = COMBUF[i++];
	    if (x==0xd) break;
        else if (COL<MAXCOL) { 
            LCDBUF[(ROW * 20)+COL] = x;
            COL++;
		}
    }
	lcdout ();
	if (CURF) lcdcur ();               // cursor on
	pokr ();
}

void comlb (void) {                                   // LCD backlight on/off
    if (COMBUF[2]=='0') PDIGT = PDIGT | 0x10;         // backlight off         
	else if (COMBUF[2]=='1') PDIGT = PDIGT & 0xef;    // backlight on 
	else {perr (); return;}
	pokr ();
}

void coml (void) {                     // LCD command 
    switch (toupper (COMBUF[1])) {
        case 'S': comls (); break;
		case 'P': comlp (); break;
		case 'T': comlt (); break;
		case 'B': comlb (); break;
	}
}

void comsn (unsigned char p) {    // number
	unsigned char i,j,x;
	disclear ();
	i = 3;
	j = 0;
    while (1) {
		x = COMBUF[i++];
		if (x==0xd) break;
	    else if (x=='-') DISBUF[j] = 0x40;
		else if (x==' ') DISBUF[j] = 0;
		else if (x=='.') {if (j>0) j--; DISBUF[j] = DISBUF[j] | 0x80;}
		else DISBUF[j] = htosx (atohr (x));
		j++;
	}
	if (p=='0') while ((x = scan ())==0xff);
	else x = scan ();
	if (x==0xff) x = 99;
	printf ("%02bd\r",x);
}

void comsh (unsigned char p) {    // segment
	unsigned char i,j,x,y;
	disclear ();
	i = 3;
	j = 0;
    while (1) {
		x = COMBUF[i++]; 
		y = COMBUF[i++];
		if (x==0xd || y==0xd) break;
		DISBUF[j++] = atohl (x) | atohr (y);
	}
	if (p=='0') while ((x = scan ())==0xff);
	else x = scan ();
	if (x==0xff) x = 99;
	printf ("%02bd\r",x);
}

void coms (void) {                     // scan 8x8d 4x8k
    unsigned char p;
	p = toupper (COMBUF[1]);
	if (p=='0' || p=='1') {
		switch (toupper (COMBUF[2])) {
			case 'N': comsn (p); break;
			case 'H': comsh (p); break;
		}
	}
	else perr (); 
}

void comb (void) {                     // beep 
    unsigned char f;
	int l;
    STRBUF[0] = COMBUF[1];
	STRBUF[1] = COMBUF[2];
	STRBUF[2] = 0;
    f = atoi (STRBUF) * 2;
	STRBUF[0] = COMBUF[3];
	STRBUF[1] = COMBUF[4];
	l = atoi (STRBUF) * 300;
	if (f==0 || l==0) perr ();
	else {
		sound (f,l);
		pokr ();
	}
}

void comw (void) {                     // dip-switch
    unsigned char a,i;
    a = (PKEYI & 0xf0);
    for (i=0;i<=3;i++) {
        if ((a & 0x10)==0x00) printf ("1"); else printf ("0");
        a >>= 1;
    }
	printf ("\r");
}

void comt (void) {                                         // time  
	if (COMBUF[1]==0xd) {                                  // show  
        rtrd ();
		printf ("%02bx%02bx%02bx\r",TIMBUF[2],TIMBUF[1],TIMBUF[0]);
	}
	else {                                                      // set
	    TIMBUF[2] = atohl (COMBUF[1]) | atohr (COMBUF[2]);      // hh
	    TIMBUF[1] = atohl (COMBUF[3]) | atohr (COMBUF[4]);      // mm
    	TIMBUF[0] = atohl (COMBUF[5]) | atohr (COMBUF[6]);      // ss
		rtset ();
		rtwr ();
		pokr ();
	}
}

void comd (void) {                                         // date
	if (COMBUF[1]==0xd) {                                  // show  
		rtrd ();
		printf ("%02bx%02bx%02bx\r",TIMBUF[4],TIMBUF[5],TIMBUF[6]);
	}
	else {                                                      // set
	    TIMBUF[4] = atohl (COMBUF[1]) | atohr (COMBUF[2]);      // dd
    	TIMBUF[5] = atohl (COMBUF[3]) | atohr (COMBUF[4]);      // mm
	    TIMBUF[6] = atohl (COMBUF[5]) | atohr (COMBUF[6]);      // yy
		rtset ();
		rtwr ();
    	pokr ();
	}
}

void come (void) {			      // eeprom 24lcxx
    unsigned char x,y,a;
	bit f;
	x = COMBUF[1];                // port bit-address 
	y = COMBUF[2];
	if (x==0xd || y==0xd) {perr (); return;}
	a = atohl (x) | atohr (y);
    x = COMBUF[3];                // option data 
    y = COMBUF[4];
	if (x==0xd || y==0xd) f = 0;
	else if (COMBUF[5]!=0xd) {perr (); return;}
    else {
		f = 1;
		x = atohl (x) | atohr (y);
    } 

    if (f) {                      // write  
		ipwrep (a,x);
		pokr ();
	}
	else {                        // read
		x = iprdep (a);
		printf ("%02bX\r",x);
	}
}

/********** COM FUNCTION (SPECIAL) **********/

void com0 (void) {		          // check
    printf ("SLAB-51 v4.3\r");    // ???
}

void com1s (unsigned char p) {    // setup
	MXINT = atohr (COMBUF[3]);
	MXDIG = atohr (COMBUF[4]);
	if (p=='3') mxset (); else mxset2 ();
	pokr ();
}

void com1n (unsigned char p) {    // number
	unsigned char i,j,x;
	disclear ();
	i = 3;
	j = 0;
    while (1) {
		x = COMBUF[i++];
		if (x==0xd) break;
	    else if (x=='-') DISBUF[j] = 0x01;
		else if (x==' ') DISBUF[j] = 0;
		else if (x=='.') {if (j>0) j--; DISBUF[j] = DISBUF[j] | 0x80;}
		else DISBUF[j] = htosm (atohr (x));
		j++;
	}
	if (p=='3') mxload (); else mxload2 ();
	pokr ();
}

void com1h (unsigned char p) {    // segment
	unsigned char i,j,x,y;
	disclear ();
	i = 3;
	j = 0;
    while (1) {
		x = COMBUF[i++]; 
		y = COMBUF[i++];
		if (x==0xd || y==0xd) break;
		DISBUF[j++] = atohl (x) | atohr (y);
	}
	if (p=='3') mxload (); else mxload2 ();
	pokr ();
}

void com1 (void) {                // max7219  
    unsigned char p;
	p = toupper (COMBUF[1]);
	if (p=='1' || p=='3') {
		switch (toupper (COMBUF[2])) {
			case 'S': com1s (p); break;
			case 'N': com1n (p); break;
			case 'H': com1h (p); break;
		}
	}
	else perr (); 
}

void com2s (unsigned char p) {    // setup
	if (p=='3') B5DIG = atohr (COMBUF[3]);
	else B5DIG2 = atohr (COMBUF[3]);
	pokr ();
}

void com2n (unsigned char p) {    // number
	unsigned char i,j,x;
	disclear ();
	i = 3;
	j = 0;
    while (1) {
		x = COMBUF[i++];
		if (x==0xd) break;
	    else if (x=='-') DISBUF[j] = 0x40;
		else if (x==' ') DISBUF[j] = 0;
		else if (x=='.') {if (j>0) j--; DISBUF[j] = DISBUF[j] | 0x80;}
		else DISBUF[j] = htosx (atohr (x));
		j++;
	}
	if (p=='3') outdpf (); else outdpf2 ();
	pokr ();
}

void com2h (unsigned char p) {    // segment
	unsigned char i,j,x,y;
	disclear ();
	i = 3;
	j = 0;
    while (1) {
		x = COMBUF[i++]; 
		y = COMBUF[i++];
		if (x==0xd || y==0xd) break;
		DISBUF[j++] = atohl (x) | atohr (y);
	}
	if (p=='3') outdpf (); else outdpf2 ();
	pokr ();
}

void com2 (void) {                // 6b595  
    unsigned char p;
	p = toupper (COMBUF[1]);
	if (p=='1' || p=='3') {
		switch (toupper (COMBUF[2])) {
			case 'S': com2s (p); break;
			case 'N': com2n (p); break;
			case 'H': com2h (p); break;
		}
	}
	else perr (); 
}

void com3 (void) {                // magnetic
    unsigned char i,p;
    bit er;
	magclear ();
	p = toupper (COMBUF[1]);
	if (p=='3') {                 // read port-3 
		magread ();    
	}
	else if (p=='1') {            // read port-1
    	magread2 ();    
	}
	else {perr (); return;}
	er = magchk ();
    if (er) {
		magreverse ();
		er = magchk ();
	}

	if (er) perr ();              // show data
	else {
	    for (i=0;i<=39;i++) {
    	    if (MAGOUT[i]==0) break;
        	printf ("%c",MAGOUT[i]);
	    }
		printf ("\r");
	}
}

void com4 (void) {                // sht15
    float ft,fh;
	unsigned char p;
	p = toupper (COMBUF[1]);
	if (p=='3') {                 // read port-3 
	   	sht11_reset ();                  
		ft = sht11_temp ();    
	    fh = sht11_humi (ft);
	}
	else if (p=='1') {            // read port-1
	   	sht11_reset2 ();                  
		ft = sht11_temp2 ();    
	    fh = sht11_humi2 (ft);
	}
	else {perr (); return;}
    printf ("T%05.1f H%04.1f\r",ft,fh);
}

void com5 (void) {                // pcf8574a
    unsigned char addr,dat,x,y,p;
	bit f;
    p = COMBUF[1];
	if (p=='1' || p=='3'); else {perr (); return;}

	x = COMBUF[2];                // address 
	y = COMBUF[3];
	if (x==0xd || y==0xd) {perr (); return;}
	addr = atohl (x) | atohr (y);

	x = COMBUF[4];                // option data
	y = COMBUF[5];
	if (x==0xd) f = 0; 
	else if (y==0xd) {perr (); return;}
	else if (COMBUF[6]!=0xd) {perr (); return;}
	else {
		f = 1;
		dat = atohl (x) | atohr (y);
	}

	if (f) {                                // write port   
	    if (p=='1') xxwr2 (addr,dat);
		else xxwr (addr,dat); 
		pok ();
	}
	else {									// read port   
		if (p=='1') pbyte (xxrd2 (addr));
		else pbyte (xxrd (addr));
	}
	printf ("\r");
}

void com6 (void) {                // tlcd (3B port)
	unsigned char p,i,x;
	p = toupper (COMBUF[1]);
	if (p=='3') {                 // port-3
        tlcdbyte (':');           // auto-add first colon 
		i = 2;
        while (1) {
			x = COMBUF[i];
			if (x==0xd) {tlcdbyte (0xd); pokr (); return;}
			else {
				tlcdbyte (x);
				i++;
			}
		}       
	}
	else if (p=='1') {            // port-1
        tlcdbyte2 (':');           // auto-add first colon 
		i = 2;
        while (1) {
			x = COMBUF[i];
			if (x==0xd) {tlcdbyte2 (0xd); pokr (); return;}
			else {
				tlcdbyte2 (x);
				i++;
			}
		}       
	}
	else {perr (); return;}
}

/********** MAIN FUNCTION **********/

void com485 (void) {
    unsigned char i;
    PCONT = 0x82;                 // 8255 control code (slab-51)
    PDIGT = PDIGT | 0x50;         // sound=1 backlight=1
    ACOMF = 1;                    // ascii command flag 

    ES = 1;                       // enable serial interrupt
    EA = 1;
    COMINX = 0;                   // start first command 
    SCOMF = 1;
    for (i=0;i<=MAXBUF;i++) COMBUF[i] = 0;
    while (1) {
        if (RXOK) {
            RXOK = 0;  
			sendon ();
            switch (toupper (COMBUF[0])) {
				case 'P': comp (); break;
				case 'R': comr (); break;
				case 'X': comx (); break;
				case 'L': coml (); break;
				case 'S': coms (); break;
				case 'B': comb (); break;
				case 'W': comw (); break;
				case 'T': comt (); break;
				case 'D': comd (); break;
				case 'E': come (); break;
                case '0': com0 (); break;
				case '1': com1 (); break;
				case '2': com2 (); break;
				case '3': com3 (); break;
				case '4': com4 (); break;
				case '5': com5 (); break;
				case '6': com6 (); break;
            }
			sendoff ();
        }
    }
}

void start (void) {                    // start process 
    unsigned char i,a;
    unsigned int c;
    TI = 1;                            // auto baud-rate
    T0 = 0;                            // first rs485 off 
    a = autobaud ();
    setbaud ();
    if (a==':') com485 ();

    PCONT = 0x82;                      // 8255 control code (slab-51)
    PDIGT = PDIGT | 0x50;              // sound=1 backlight=1
    ACOMF = 0;

    sendon ();
    c = chks ();
    for (i=1;i<=22;i++) printf ("\n");
    printf ("SLAB-51 QC Program v4.3 (89V51RD2BN)\n"); // ???
    printf ("Checksum=%04X Speed=%u\n",c,SPEEDM);
    printf ("2006 Sila Research Co.,Ltd.");
    printf ("\nType any keys ...");
    getkey ();
}

void menuex (void) {
    unsigned char a,i;
    bit f;
    a = 0;
    f = 1;
    while (1) {
        if (f) {
            printf ("\n\n");                              
            printf ("   #### Test Expansion Board #### \n");
            printf ("1. EX-Series (24B Port,Active High) \n");
            printf ("2. EX-Series (12B Port,Active Low) \n");
            printf ("3. EX-Series (3B Port,Active Low,I2C) \n"); 
            printf ("4. DP-Series (3B Port,6B595) \n");
            printf ("5. DP-Series (3B Port,Max7219) \n");
            printf ("6. DP,DK-Series (Scan 8x8D,4x8K Port) \n");
            printf ("7. RS232 to 3B Port Serial (TLCD) \n"); 
			printf ("Q. Quit \n");
            printf ("   Select :");
        }
        f = 0;
        if (a!=0) {i = a; a = 0;} else i = toupper (getkey ());
        switch (i) {
			case '1': f = 1; testex24b (); break;
			case '2': f = 1; testex12b (); break;
			case '3': f = 1; testex3b (); break;
			case '4': f = 1; testdp595 (); break;
			case '5': f = 1; test7219 (); break;
			case '6': f = 1; testdk (); break;
			case '7': f = 1; testtlcd (); break;
			case 'Q': return;
			default: printf ("\a");
		}
    }
}

void menulcd (void) {
    unsigned char a,i;
    bit f;
    a = 0;
    f = 1;
    while (1) {
        if (f) {
            printf ("\n\n");                              
            printf ("   #### Test LCD Module #### \n");
            printf ("1. DMC082 \n");
            printf ("2. DMC161 \n");
            printf ("3. DMC162 \n"); 
            printf ("4. DMC164 \n");
            printf ("5. DMC202 \n");
            printf ("6. DMC204 \n");
            printf ("7. Backlight On/Off \n");
			printf ("Q. Quit \n");
            printf ("   Select :");
        }
        f = 0;
        if (a!=0) {i = a; a = 0;} else i = toupper (getkey ());
        switch (i) {
            case '1': f = 1; LCDNUM = 0; testlcdx (); break; 
            case '2': f = 1; LCDNUM = 1; testlcdx (); break; 
            case '3': f = 1; LCDNUM = 2; testlcdx (); break; 
            case '4': f = 1; LCDNUM = 3; testlcdx (); break; 
            case '5': f = 1; LCDNUM = 4; testlcdx (); break; 
            case '6': f = 1; LCDNUM = 5; testlcdx (); break; 
            case '7': f = 1; backonoff (); break; 
			case 'Q': return;
			default: printf ("\a");
		}
    }
}

void menuac (void) {
    unsigned char a,i;
    bit f;
    a = 0;
    f = 1;
    while (1) {
        if (f) {
            printf ("\n\n");                              
            printf ("   #### Test Accessory & Component #### \n");
            printf ("1. Magnetic,Proximity \n");
            printf ("2. SHT15 Temp & Humidity \n");
			printf ("3. RTC M48T08,M48T35 \n");
			printf ("Q. Quit \n");
            printf ("   Select :");
        }
        f = 0;
        if (a!=0) {i = a; a = 0;} else i = toupper (getkey ());
        switch (i) {
			case '1': f = 1; testmag (); break;
			case '2': f = 1; testsht15 (); break;
			case '3': f = 1; testm48 (); break;
			case 'Q': return;
			default: printf ("\a");
		}
    }
}

void main (void) {
    unsigned char a,i;
    bit f;
    a = 0;
    start ();
    f = 1;
    while (1) {
        if (f) {
            printf ("\n\n");                              
            printf ("   #### SLAB-51 v4.3 Menu ####       SLAB-51 V-C5155 V-C52 \n"); // ???
            printf ("                                       v4.0    v5.0   v3.0 \n");    
            printf ("1. 1B Port (P34,P17) .................. X \n");
            printf ("2. 3B Port (P32,P33,P35,P10,P11,P14) .. X ..... X .... X \n");
            printf ("3. I/O Port (P12,P13,P17) ..................... X .... X \n"); 
            printf ("4. 12B Port (P1,P32,P33,P34,P35) ...... X ..... X .... X \n");
            printf ("5. 24B Port (E000-8255) ............... X ..... X \n");
            printf ("6. LCD Port (C000-Backlight-PC4) ...... X \n");
            printf ("7. 4x8K,8x8D Port & Speaker (8255) .... X \n");
            printf ("8. INT0,INT1 Key & Dip-Switch ......... X \n");
			printf ("9. RTC DS1307 ......................... X ............ X \n");
            printf ("A. EEprom 24LC04 ...................... X ............ X \n");
			printf ("B. Ram 0000-1FFFH (8K) ................ X ..... X \n");
			printf ("C. Ram 0000-7FFFH (32K) ............... X ..... X \n");
			printf ("D. Ram 0000-7FFFH (128K) 32x4 Blank ........... X \n");
			printf ("E. Ram 8000-9FFFH (8K) ................ X ..... X \n");
			printf ("F. 24B Port (I/O-8255-CS1) ........................... X \n");
			printf ("G. 24B Port (I/O-8255-CS2) ........................... X \n");
			printf ("H. LCD Port (I/O-Backlight-P27) ...................... X \n");
			printf ("I. INT0,INT1 Key & Speaker (P35) ..................... X \n");
			printf ("X. Test Expansion Board \n");
			printf ("Y. Test LCD Module \n");
			printf ("Z. Test Accessory & Component \n");
            printf ("   Select :");
        }
        f = 0;
        if (a!=0) {i = a; a = 0;} else i = toupper (getkey ());
        switch (i) {
			case '1': f = 1; test1b (); break;
			case '2': f = 1; test3b (); break;
			case '3': f = 1; test3bx (); break;
            case '4': f = 1; test12b (); break;
			case '5': f = 1; test24b (); break;
			case '6': f = 1; testlcd (); break;
			case '7': f = 1; testscan (); break;
			case '8': f = 1; testdip (); break;
			case '9': f = 1; testrtc (); break;
			case 'A': f = 1; test24lc04 (); break;
			case 'B': f = 1; testram8 (); break;
			case 'C': f = 1; testram32 (); break;
			case 'D': f = 1; testram128 (); break;	
			case 'E': f = 1; testram8p (); break;
			case 'F': f = 1; test8255cs1 (); break;
			case 'G': f = 1; test8255cs2 (); break;
			case 'H': f = 1; testlcd27 (); break;
			case 'I': f = 1; testkeysp (); break;
			case 'X': f = 1; menuex (); break;
			case 'Y': f = 1; menulcd (); break;
			case 'Z': f = 1; menuac (); break;
			default: printf ("\a");
		}
    }
}



