/*  Filename     D20SQC.C v1.2
    Description  DIP 20 Pin Super QC
    Hardware     Any Embedded Board (DIP 20)
    Compiler     Keil CA51 v5.0
    Engineer     Kriangsak B.
    Company      Sila Research Co.,Ltd. */

#include <reg51.h>
#include <absacc.h>
#include <ctype.h>
#include <intrins.h>
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

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

sbit    IPSDA  = P1^0;            // ds1307,24lcxx,max7300 
sbit    IPSCL  = P1^1;            
sbit    IRSDA  = P1^0;
sbit    IRSCL  = P1^1;

sbit    RELAY  = P1^2;            // Relay Bit 
sbit    KEY1   = P1^3;            // Key-1 
sbit    KEY2   = P1^4;            // Key-2 

sbit    INPUT1 = P3^2;            // IN-1 int0 
sbit    INPUT2 = P3^3;            // IN-2 int1 
sbit    D485   = P3^4;            // rs485
sbit    SOUNDB = P3^5;            // Sound Bit 
sbit    BIT1   = P3^7;            // 1B Port 

sbit    RELAY1 = P1^2;            // V-C2051M V2.0
sbit    RELAY2 = P1^3;
sbit    RELAY3 = P1^4;

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

unsigned char data TIMBUF[8];     // ss,mm,hh,ww,dd,mm,yy,cc 

/********** FUNCTION **********/

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

void sound (unsigned char freq,int time) {
    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--;
    }
}

void beeph(void) {sound(15,10000);}

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

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 (void) {        // 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);
}

void ip73conf (unsigned char addr,com,dat) {     // max7300 config port 
    addr = ((addr << 1) & 0x1e) | 0x80;
    ipstart ();                                  
    ipwrbyte (addr);
    ipwrbyte (com);
    ipwrbyte (dat);
    ipstop ();
}

void ip73setout (unsigned char addr) {           // max7300 set all 20B output
    ip73conf (addr,0x04,0x00);			 // shutdown 
    ip73conf (addr,0x06,0x00);			 // all clear (masked off)
    ip73conf (addr,0x09,0x55);                   // set p4-p7 output (no pin)
    ip73conf (addr,0x0a,0x55);                   // set p8-p11 output (no pin)
    ip73conf (addr,0x0b,0x55);                   // set p12-p15 output 
    ip73conf (addr,0x0c,0x55);                   // set p16-p19 output 
    ip73conf (addr,0x0d,0x55);                   // set p20-p23 output 
    ip73conf (addr,0x0e,0x55);                   // set p24-p27 output 
    ip73conf (addr,0x0f,0x55);                   // set p28-p31 output 
    ip73conf (addr,0x04,0x01);                   // normal
}

/*
void ip73setin (unsigned char addr) {            // max7300 set all 20B input
    ip73conf (addr,0x04,0x00);			 // shutdown 
    ip73conf (addr,0x06,0x00);			 // all clear (masked off)
    ip73conf (addr,0x09,0x55);                   // set p4-p7 output (no pin)
    ip73conf (addr,0x0a,0x55);                   // set p8-p11 output (no pin)
    ip73conf (addr,0x0b,0xff);                   // set p12-p15 input 
    ip73conf (addr,0x0c,0xff);                   // set p16-p19 innut 
    ip73conf (addr,0x0d,0xff);                   // set p20-p23 input 
    ip73conf (addr,0x0e,0xff);                   // set p24-p27 input 
    ip73conf (addr,0x0f,0xff);                   // set p28-p31 input 
    ip73conf (addr,0x04,0x01);                   // normal
}
*/

void ip73wra (unsigned char addr,dat) {          // max7300 write port A (p12-p19)
    addr = ((addr << 1) & 0x1e) | 0x80;
    ipstart ();                                  
    ipwrbyte (addr);
    ipwrbyte (0x4c);
    ipwrbyte (dat);
    ipstop ();
}

void ip73wrb (unsigned char addr,dat) {          // max7300 write port B (p20-p27)
    addr = ((addr << 1) & 0x1e) | 0x80;
    ipstart ();                                  
    ipwrbyte (addr);
    ipwrbyte (0x54);
    ipwrbyte (dat);
    ipstop ();
}

void ip73wrc (unsigned char addr,dat) {          // max7300 write port C (p28-p31)
    addr = ((addr << 1) & 0x1e) | 0x80;
    ipstart ();                                  
    ipwrbyte (addr);
    ipwrbyte (0x5c);
    ipwrbyte (dat & 0xf);
    ipstop ();
}

/*
unsigned char ip73rda (unsigned char addr) {     // max7300 read port A (p12-p19)
    unsigned char a,dat;
    a = ((addr << 1) & 0x1e) | 0x80;
    ipstart ();                                  
    ipwrbyte (a);
    ipwrbyte (0x4c);
    ipstop ();

    a = ((addr << 1) & 0x1e) | 0x81;
    ipstart ();                                  
    ipwrbyte (a);
    dat = iprdbyte ();
    ipstop ();
    return (dat);
}

unsigned char ip73rdb (unsigned char addr) {     // max7300 read port B (p20-p27)
    unsigned char a,dat;
    a = ((addr << 1) & 0x1e) | 0x80;
    ipstart ();                                  
    ipwrbyte (a);
    ipwrbyte (0x54);
    ipstop ();

    a = ((addr << 1) & 0x1e) | 0x81;
    ipstart ();                                  
    ipwrbyte (a);
    dat = iprdbyte ();
    ipstop ();
    return (dat);
}

unsigned char ip73rdc (unsigned char addr) {     // max7300 read port C (p28-p31)
    unsigned char a,dat;
    a = ((addr << 1) & 0x1e) | 0x80;
    ipstart ();                                  
    ipwrbyte (a);
    ipwrbyte (0x5c);
    ipstop ();

    a = ((addr << 1) & 0x1e) | 0x81;
    ipstart ();                                  
    ipwrbyte (a);
    dat = iprdbyte ();
    ipstop ();
    return (dat);
}
*/

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 anykey (void) {
    printf ("Type any keys to exit\n");
}

void testing (void) {
    printf ("Testing ");
}

unsigned int autobaud (void) {    // auto RS232 baud-rate 
    unsigned int speed;           // start by SPACE character 
                                  // auto 1200,2400,4800,9600,19200 
    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 
    SCON = 0x52;                  // set RS232 parameter 
    TMOD = 0x20;
    if (speed>3400) {
        speed = 1200;
        TH1 = 0xe8;
    }
    else if (speed>1700) {
        speed = 2400;
        TH1 = 0xf4;
    }
    else if (speed>860) {
        speed = 4800;
        TH1 = 0xfa;
    }
    else if (speed>430) {
        speed = 9600;
        TH1 = 0xfd;
    }
    else {
        speed = 19200;
        TH1 = 0xfd;
        PCON |= 0x80;
    }
    TR1 = 1;
    return (speed);
}

void start (void) {               // start process 
    unsigned char i;
    unsigned int speed;
    speed = autobaud ();
    for (i=1;i<=20;i++)
        printf ("\n");
    printf ("2004 Sila Research Co.,Ltd.\n");
    printf ("D20SQC Super QC Program v1.2\n");
    printf ("Speed = %d\n",speed);
}

unsigned char menu (void) {       // main menu 
    unsigned char i;
    beeph ();
    while (1) {
        printf ("\nMain Menu ...\n\n");
        printf ("---- V-C4051M ----\n");
        printf ("1. 20B Port\n");
        printf ("2. 3B Port\n");
        printf ("3. 1B & 485-LED Port\n");
        printf ("4. Opto-Input\n");
        printf ("5. Sound & Relay\n");
        printf ("6. On-Board Keys\n");
        printf ("7. RTC DS1307\n");
        printf ("8. EEprom 24LC04\n");
//        printf ("---- V-C2051 ----\n");
//        printf ("A. Test P1\n");
//        printf ("B. Test P3\n");
        printf ("---- V-C2051M ----\n");
        printf ("C. Relay & Sound\n");
        printf ("D. 3B Port\n");
        printf ("E. 1B & 485-LED Port\n");
        printf ("F. PCB 10,11,32,33\n");
        printf ("\nSelect :");
        i = toupper (getchar ());
        if (i>='1' && i<='8') break;
        if (i>='C' && i<='F') break;
    }
    printf ("\n\n");
    return (i);
}

void menu1 (void) {                    
    unsigned char i,j,k;
    testing ();
    printf ("20B port (MAX7300) with EX-LED ...");
    ip73setout (0);		
    for (k=1;k<=3;k++) {
        j = 1;
        for (i=1;i<=8;i++) {
            ip73wra (0,j); 
            ip73wrb (0,j); 
            ip73wrc (0,j); 
            dmsec (400);
            j = j << 1;
        }
    }
    for (i=1;i<=3;i++) {
        j = 0x55;
        ip73wra (0,j); 
        ip73wrb (0,j); 
        ip73wrc (0,j); 
        dmsec (600);
        j = 0xaa;
        ip73wra (0,j); 
        ip73wrb (0,j); 
        ip73wrc (0,j); 
        dmsec (600);
    }
    j = 0;
    ip73wra (0,j); 
    ip73wrb (0,j); 
    ip73wrc (0,j); 
}

void menu2 (void) {
    unsigned char i,j;
    testing ();
    printf ("3B Port with LP ...\n");
    anykey ();
    while (~RI) {
        for (i=0;i<=7;i++) {
            j = i << 5;
            P1 = j | 0x1f;
            dmsec (200);
            if (RI) break;
        }
    }
    P1 = P1 | 0xe0;
    getchar ();
}

void menu3 (void) {
    testing ();
    printf ("1B Port & 485-LED with LP ...\n");
    anykey ();
    while (~RI) {
        D485 = 0;
        BIT1 = 0;
        dmsec (200);
        if (RI) break;
        D485 = 1; 
        BIT1 = 1;
        dmsec (200);
        if (RI) break;
    }
    D485 = 1;
    BIT1 = 1;
    getchar ();
}

void menu4 (void) {
    testing ();
    printf ("Opto-Input ...\n");
    printf ("IN-1 ");
    while (INPUT1);
    printf ("OK\n");
    printf ("IN-2 ");
    while (INPUT2);
    printf ("OK\n");
    printf ("Type any keys\n");
    getchar ();
}

void menu5 (void) {
    testing ();
    printf ("Sound & Relay ...\n");
    anykey ();
    while (~RI) {
        RELAY = 0;
        sound (40,5000);
        dmsec (800);
        if (RI) break;
        RELAY = 1;
        sound (70,8000);
        dmsec (800);
        if (RI) break;
    }
    RELAY = 1;
    getchar ();
}

void menu6 (void) {
    testing ();
    printf ("On-Board Keys ...\n");
    printf ("SW-1 ");
    while (KEY1);
    printf ("OK\n");
    printf ("SW-2 ");
    while (KEY2);
    printf ("OK\n");
    printf ("Type any keys\n");
    getchar ();
}

void menu7 (void) {
    unsigned char x;
    testing ();
    printf ("RTC DS1307 ...\n");
    TIMBUF[0] = 0x55;                       // second       
    TIMBUF[1] = 0x59;                       // minute 
    TIMBUF[2] = 0x23;                       // hour 
    TIMBUF[4] = 0x28;                       // date 
    TIMBUF[5] = 0x02;                       // month 
    TIMBUF[6] = 0x04;                       // year 
    rtset ();
    rtwr ();
    while (TIMBUF[0]!=0x05) {
        dmsec (100);
        rtrd ();
        if (TIMBUF[0]!=x) {
            printf ("time %02bx:%02bx:%02bx  date %02bx/%02bx/%02bx\n",
            TIMBUF[2],TIMBUF[1],TIMBUF[0],TIMBUF[4],TIMBUF[5],TIMBUF[6]);
            x = TIMBUF[0];
        }
    }
}

void menu8 (void) {
    bit err;
    testing ();
    printf ("EEprom 24LC04 ...\n");
    ipwrep (0,0xaa);
    ipwrep (1,0x55);
    err = 0;
    if (iprdep (0)!=0xaa) err = 1;
    if (iprdep (1)!=0x55) err = 1;
    if (err) printf ("Error !\n");
    else printf ("OK\n");
    printf ("Type any key ");
    getchar ();
}

/*
void menua (void) {
    unsigned char x;
    printf ("Testing P1 with LP ...\n");
    anykey ();
    x = 0;
    while (~RI) {
        P1 = x++;
        dmsec (10);
    }
    getchar ();
}

void menub (void) {
    unsigned char x;
    printf ("Testing P3 with LP ...\n");
    anykey ();
    x = 0;
    while (~RI) {
        P3 = x++ | 0x03;
        dmsec (10);
    }
    getchar ();
}
*/

void menuc (void) {
    testing ();
    printf ("Relay ...\n");
    anykey ();
    while (~RI) {
        RELAY1 = 0;
        sound (70,8000);
        dmsec (800);
        if (RI) break;
        RELAY1 = 1;
        dmsec (800);
        if (RI) break;

        RELAY2 = 0;
        sound (60,8000);
        dmsec (800);
        if (RI) break;
        RELAY2 = 1;
        dmsec (800);
        if (RI) break;

        RELAY3 = 0;
        sound (50,8000);
        dmsec (800);
        if (RI) break;
        RELAY3 = 1;
        dmsec (800);
        if (RI) break;
    }
    RELAY1 = 1;
    RELAY2 = 1;
    RELAY3 = 1;
    getchar ();
}

sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P32 = P3^2;
sbit P33 = P3^3;

void menuf (void) {
    unsigned char x;
    testing ();
    printf ("PCB 10,11,32,33 with LP ...\n");
    anykey ();
    x = 0;
    while (~RI) {
        if (x & 0x1) P10 = 1; else P10 = 0;
        if (x & 0x2) P11 = 1; else P11 = 0;
        if (x & 0x4) P32 = 1; else P32 = 0;
        if (x & 0x8) P33 = 1; else P33 = 0;
        x++;
        dmsec (10);
    }
    getchar ();
}

/********** MAIN **********/

void main (void) {
    unsigned char i;
    start ();
    while (1) {
        i = menu ();
        switch (i) {
            case '1': menu1 (); break;
            case '2': menu2 (); break;
            case '3': menu3 (); break;
            case '4': menu4 (); break;
            case '5': menu5 (); break;
            case '6': menu6 (); break;
            case '7': menu7 (); break;
            case '8': menu8 (); break;
//            case 'A': menua (); break;
//            case 'B': menub (); break;           
            case 'C': menuc (); break;           
            case 'D': menu2 (); break;           
            case 'E': menu3 (); break;    
            case 'F': menuf (); break;          
        }
    }
}


