/* **************************************************** */
/* Intel 80C552 - system IMM552                         */
/* Definicny subor (adresy, spec.registre a biy         */
/* **************************************************** */

#define TRUE    1
#define FALSE   0
#define CTRL    0x12
#define DATA    0x1A
#define WDINT   0                  /* interval WD 1.57s */


#define DISP ((char *)0x28200L)[0] /* adresa displeja   */
#define RWM  ((char *)0x22000L)    /* adresa RAM-ky     */
#define RTC  ((char *)0x24000L)    /* adresa RT Clock   */

                          /* definicie pre 8255     */
#define XBYTE ((char *)0x20000L)
#define CW55    0x90     /* PA-vstup, PB,PC-vystup */
#define PA55    0xF800
#define PB55    0xF801
#define PC55    0xF802
#define CR55    0xF803   /* Riadiaci register      */

#if !defined reg552.h
/* adresy registrov specialnych funkcii                 */
sfr B    = 0xF0;
sfr P1   = 0x90;
sfr P3   = 0xB0;
sfr P4   = 0xC0;
sfr P5   = 0xC4;
sfr T3   = 0xFF;
sfr PCON = 0x87;
sfr ADCH = 0xC6;
sfr ADCON= 0xC5;
#endif


/* **************************************************** */
/* Riadiace signaly displeja                            */
/*     P1.7 je RS  (Register Select) 0=registre, 1=RAMka */
/*             R/W (Read/Write) je trvale 0             */
/*                  t.j. neda sa citat BUSY flag!       */
/*             E (Enable) je aktivovane adresou 8200H   */
/* **************************************************** */
sbit D_RS = P1^7;

/* **************************************************** */
/* Reset WD timera, volat v riadiacom algoritme         */
/* **************************************************** */
void wd(void)
    { PCON|=0x10; T3=WDINT; }

/* **************************************************** */
/*                                                      */
/* wait(n)                                              */
/*                                                      */
/* Oneskorenie n*100us                                  */
/*         (plati pre krystal 4 alebo 11.0592MHz)       */
/* **************************************************** */
void wait(n)
  unsigned char n;
  { unsigned char i,ii;
    for(ii=0;ii<n;ii++)
        for(i=0;i<24;i++);
  }

/* **************************************************** */
/* Funkcie pre obsluhu displeja a zobrazovanie          */
/* **************************************************** */

/* **************************************************** */
/*                                                      */
/* Disp_send(Byte,Reg);                                 */
/*                                                      */
/* posle na displej byte "a_" a nastavi signaly "b_"    */
/* **************************************************** */
void Disp_send(char a_,char b_)
{
 XBYTE[PB55]=a_;          /* prepisane z Basic-u  */
 wait(1);
 XBYTE[PC55]=b_;
 wait(1);
 XBYTE[PC55]=0;
 wait(1);
}


/* **************************************************** */
/*                                                      */
/* Disp_ini8()                                          */
/*                                                      */
/* Inicializacia displeja 8-bitovo                      */
/* P1.7  = Register Select                              */
/* **************************************************** */
void Disp_ini8(void)
  {
    XBYTE[CR55]=CW55;     // inicializuj 8255

    Disp_send(0x00,0x00); //Reset
    wait(150);            // po zapnuti cakaj 15ms
    Disp_send(0x30,0x12); // 0 0 1 1  x x x x
    wait(46);             // cakaj 4.6ms
    Disp_send(0x30,0x12); // a posli znova  0011 xxxx
    wait(1);              // cakaj 0.1ms
    Disp_send(0x30,0x12); // a posli znova  0011 xxxx
    wait(1);
    Disp_send(0x38,0x12);
                  // 0 0 1 1  1 0 x x
                  //       |  | |_ F=0:  font 7x5
                  //       |  |___ N=1:  dva riadky
                  //       |______ DL=1: 8 bitov
    wait(1);
    Disp_send(0x08,0x12);
                  // 0 0 0 0  1 0 0 0
                  // display OFF
    wait(1);
    Disp_send(0x01,0x12);
                  // 0 0 0 0  0 0 0 1
                  // clear & cursor home
    wait(17);
    Disp_send(0x06,0x12);
                  // 0 0 0 0  0 1 1 0
                  //              |__ I/D: 1=Increment 0=Decrement
                  // set shift mode
  }

/* **************************************************** */
/*                                                      */
/* Disp_clr();                                          */
/*                                                      */
/* zmaze displej, kurzor vrati na zaciatok 1. riadku    */
/* **************************************************** */
#define Disp_clr(); { Disp_send(0x01,0x12); wait(17); }

/* **************************************************** */
/*                                                      */
/* Disp_on();                                           */
/*                                                      */
/* zapni displej a kurzor, vypni blikanie kurzora       */
/* DISP = 0 0 0 0 1 D C B                               */
/*        B: 1=ON 0=OFF (Blinkng cursor)                */
/*        C: 1=ON 0=OFF (Cursor On/Off )                */
/*        D: 1=ON 0=OFF (Display On/Off)                */
/* **************************************************** */
#define Disp_on();  Disp_send(0x0C,0x12);




/* **************************************************** */
/*                                                      */
/* Disp_text(text,row,pos)                              */
/*                                                      */
/* zobraz na displeji "text" v riadku "row" (1/2)       */
/* pozicii "pos" (0-F)                                  */
/* **************************************************** */
void Disp_text(text,row,pos)
char text[];
unsigned char row,pos;
{
 unsigned char i;
 Disp_send(0x40*(row-1)+pos+0x80,0x12);  // pozicia na displeji

 i=0;
 while (text[i]!='\0')
     Disp_send(text[i++],0x1A);

}

/* **************************************************** */
/*                                                      */
/* Disp_int(numb,row,pos)                               */
/*                                                      */
/* vypis cisla "numb" (0-99999) na displej              */
/* do riadku "row" a od pozicie "pos" vlavo             */
/*  - nevyznamne nuly sa nepotlacaju                    */
/* **************************************************** */
void Disp_int(numb,row,pos)
unsigned int numb;
unsigned char row, pos;
{
         unsigned int tmp,exp;
          Disp_send(0x40*(row-1)+pos+0x80,CTRL);  //pozicia na displeji
           for(exp=10000;exp>=1;exp=exp/10)
            { tmp = numb/exp;
                   Disp_send(tmp+'0',DATA);       // zapis vyssi rad
                      numb -= tmp*exp;
                }
        }




/* **************************************************** */
/*                                                      */
/* Disp_char(byte,row,pos)                              */
/*                                                      */
/* zobraz na displeji "byte" v riadku "row" (1/2)       */
/* pozicii "pos" (0-F)                                  */
/* **************************************************** */
void Disp_char(byte,row,pos)
unsigned char byte,row,pos;
{
 unsigned char tmp;
 Disp_send(0x40*(row-1)+pos+0x80,0x12);  // pozicia na displeji
 tmp = byte>>4;
 tmp = (tmp<10 ? tmp+'0' :  tmp+'7');
 Disp_send(tmp,0x1A);
 tmp = byte&0x0F;
 tmp = (tmp<10 ? tmp+'0' :  tmp+'7');
 Disp_send(tmp,0x1A);
}


/* **************************************************** */
/*                                                      */
/* Kb_read()                                            */
/*                                                      */
/* precita hodnotu z klavesnice 0: nic, 1-16: klavesa   */
/* 255: error  -  prepisane z Basic-u                   */
/* ak je stlacena viac ako jedna, vrati len najnizsiu   */
/* **************************************************** */
char Kb_read(void)
{
  unsigned char a,b,c,i;
    XBYTE[0xF802] = 0xF1;   // odpoji displej
    a=c=0;
    do {
      for(b=1,i=0;i<a;i++,b*=2);
      XBYTE[0xF801] = b;
      b = XBYTE[0xF800];
      if ((c!=0)&&(b!=0)) c=255;
      else switch (b) {
           case 0:   break;
           case 1:   c=13+a;
                     break;
           case 2:   c=9+a;
                     break;
           case 4:   c=5+a;
                     break;
           case 8:   c=1+a;
                     break;
           default:  c=255; };
     a++;
    } while (!((c==255) || (a>3)));
   return (c);
}

/* ******************************************************* */
/*                                                         */
/* AD_measure(channel)                                     */
/*                                                         */
/* Get A/D "channel" measured value                        */
/* ******************************************************* */

unsigned int AD_measure (unsigned char channel)
   {
    unsigned int tmp;
    ADCON = 0x00;         /* triggering SW, do not convert */
    ADCON|= channel;      /* select A/D channel            */
    ADCON |= 0x08;        /* and start measurement         */
    wait(1);

    while (ADCON&0x08);   /* wait until measurement ready  */
    ADCON &= 0xef;        /* clear interrupt flag          */

    return ( ADCH*4 + ((ADCON >>6)&0x03) );
    }

/* Nasledovnu konstrukciu             */
/* sbit AD_BUSY  = ADCON^4;           */
/* nemozme pouzit, pretoze ADCON      */
/* nie je bitovo adresovatelny    !!! */

void Disp_c(byte,row,pos)
unsigned char byte,row,pos;
{
 Disp_send(0x40*(row-1)+pos+0x80,0x12);  // pozicia na displeji
 Disp_send(byte,0x1A);
}