/*****************************************************
Chip type           : ATmega8L
Program type        : Application
Clock frequency     : 4,000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 256
*****************************************************/

#include <mega8.h>

// Standard Input/Output functions
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <delay.h>
#include <twi.h>
#include <ctype.h>

// Declare your global variables here

        
unsigned char k[21], i, j=0, output1, output2, D, b2a, U_vstup[4], not_number;
float U_vst, meas_konst;
/*********** Nastaveni ref. napeti na PCF8591 !!!!Dulezite z hlediska spravneho nastaveni/mereni napeti!!!! ***********/
float Uref = 4.734;
/**********************************************************************************************************************/
/*
příkazy:
OUT 16x >> OUT 1001010100010101
INx     >> IN1 nebo IN2
DA      >> DA 4,56
ADx     >> AD 1 nebo 2,3,4
*/

/********** Chybove hlaseni ************/
void UN_COM(void)
{
printf("UNKNOWN COMMAND \n\r");
}

void ERR(void)
{
printf("ERROR \n\r");
}
/***************************************/

void bin2ascii_underfce(unsigned char b2a)    //podfunkce funkce bin2ascii
{
b2a = b2a | 48;
putchar(b2a);        
}

void bin2ascii(void)          //fce pro prevod binarniho cisla do ascii soustavy (potreba pro funkci IN)
        {
        b2a=0;
                
        b2a=TWDR&128;
        b2a=b2a>>7;            
        bin2ascii_underfce(b2a);
                
        b2a=TWDR&64;
        b2a=b2a>>6;            
        bin2ascii_underfce(b2a);
                
        b2a=TWDR&32;
        b2a=b2a>>5;            
        bin2ascii_underfce(b2a);
                
        b2a=TWDR&16;
        b2a=b2a>>4;            
        bin2ascii_underfce(b2a);
                
        b2a=TWDR&8;
        b2a=b2a>>3;            
        bin2ascii_underfce(b2a);
                
        b2a=TWDR&4;
        b2a=b2a>>2;            
        bin2ascii_underfce(b2a);
                
        b2a=TWDR&2;
        b2a=b2a>>1;            
        bin2ascii_underfce(b2a);
                
        b2a=TWDR&1;
        bin2ascii_underfce(b2a);
        
        printf("\n\r");
        }


/*********Hlavni funkce pro komunikaci AVR-I2C**********/


void OUT_fce(unsigned char output1, unsigned char output2)
        {
        /****expander*****/
        //0111000x = adresa PCF8574A expander1 vystupni kanal
        //0111001x = adresa PCF8574A expander2 vystupni kanal
               
        i2c_startni(0x70);  // 01110000 "zapisovaci" adresa expanderu 1
        i2c_zapis(output1);
        i2c_stopni();
        delay_us(10);
        i2c_startni(0x72);  // 01110010 "zapisovaci" adresa expanderu 2 
        i2c_zapis(output2);
        i2c_stopni();
        
        delay_us(10);
               
        }

void IN_fce(void)
        {
        unsigned char addr;
        
        if (k[3] == 49) addr = 0x71;   // 01110001 "cteci" adresa expanderu 1 vstupni kanal
        else addr=0x73;  // 01110011 "cteci" adresa expanderu 2 vstupni kanal
        i2c_startni(addr);  
        i2c_readNak();
        i2c_stopni();
        
        bin2ascii();
        //return TWDR;
        }

      
void DA_fce(unsigned char D)
        {
          
        i2c_startni(0x90);  // 10010000 "zapisovaci" adresa prevodniku
        i2c_zapis(0x44);    // 01000100 control byte
        i2c_zapis(D);
        i2c_stopni();
        
        delay_us(10);
        
        }

void measure( void)   //vstupni rozsah mereno napeti 
        {
        unsigned char meas;
        printf("Zadejte vstupni rozsah mereni: 1 - 300V, 2 - 100V, 3 - 50V, 4 - 5V\n\r");
        meas = getchar();
        putchar(meas);
        
        if ( meas <= 48 || meas >=53) ERR();
                else
                {
                meas=(meas & 7)-1;          //prevod z ascii do bin
                i2c_startni(0x70); //zapisovaci adresa expanderu na prepinani rozsahu
                i2c_zapis(meas);
                i2c_stopni();
        
                if (meas==0) meas_konst=62.5;           //nasobici konstanta pro rozsah 300V
                else if (meas==1) meas_konst=20.41;      //                              100V
                else if (meas==2) meas_konst=10;      //                              50V
                else if (meas==3) meas_konst=1;       //                              5V
                else ERR();
        
                printf("\n\r");
                }
        }        
        
unsigned char AD_fce(void)
        {
        unsigned char cont_ADC;
               
        /*
        AD channel number - urcuje control byte D0 a D1 bity
        cont0_ADC = 0x00000100b; // ch 0
        cont1_ADC = 0x00000101b; // ch 1
        cont2_ADC = 0x00000110b; // ch 2
        cont3_ADC = 0x00000111b; // ch 3
        */
        
        if ( k[3] == 48) cont_ADC = 0x04;
        else if ( k[3] == 49) cont_ADC = 0x05;
        else if ( k[3] == 50) cont_ADC = 0x06;
        else if ( k[3] == 51) cont_ADC = 0x07;
        else ERR();
        if(k[3] >= 48 && k[3] <=51)
                {
                i2c_startni(0x90);      // 10010000 "zapisovaci" adresa prevodniku
                i2c_zapis(cont_ADC);        // control byte
                i2c_stopni();
                delay_us(1);
                i2c_startni(0x91);      // 10010001 "cteci" adresa prevodniku
                i2c_readNak();
                i2c_stopni();
                
                U_vst = TWDR*(Uref/256)*meas_konst;                
                PORTB=TWDR;
                }
        else U_vst=0;
        
        return U_vst;
        }

void backspace( void)
{
putchar(32);
putchar(8);
j--;
}        
                                
void main(void)
{
// USART initialization
UCSRA=0x00;
UCSRB=0x18;     // USART Receiver: On , USART Transmitter: On
UCSRC=0x86;     // Communication Parameters: 8 Data, 1 Stop, No Parity , USART Mode: Asynchronous     
UBRRH=0x00;     // USART Baud Rate: 9600
UBRRL=0x19;     // USART Baud Rate: 9600                                

// Analog Comparator: Off
ACSR=0x80;

// 2 Wire Bus initialization
TWSR=0x00;
TWBR=0x18;      // Bit Rate: 62,500 kHz
TWAR=0x00;
TWCR=0x44;      // Generate Acknowledge Pulse: On

DDRB=0xff;

while (1)
      {
      
      k[j]=getchar();
      putchar( k[j]);
      
      if (k[j] == 13)  //pokud enter
        {
        /*
        for ( i=0; i< strlen (k); i++)  //tento cyklus jednoduse prepise prikaz
                {
                putchar(k[i]);
                }
        */        
        printf("\n\r");

        if ((k[0] == 111 || k[0] == 79) && (k[1] == 117 || k[1] == 85) && (k[2] == 116 || k[2] == 84))          // pokud out/OUT
                {
                output1 = 0;
                not_number=0;
                        for ( i=4; i<19; i++)
                                if ( k[i]<=47 || k[i]>=50) not_number++;   //overeni zda parametr obsahuje pouze 1 nebo 0
                        if (not_number > 0) ERR();        
                        else 
                        {
                        output1 = ((k[11]&1)<<7) + ((k[10]&1)<<6) + ((k[9]&1)<<5) + ((k[8]&1)<<4) + ((k[7]&1)<<3) + ((k[6]&1)<<2) + ((k[5]&1)<<1) + (k[4]&1);
                
                        PORTB=output1;
                
                        OUT_fce(output1, 0);
                        };
                }
        else if ((k[0] == 73 || k[0] == 105 ) && (k[1] == 78 || k[1] == 110  ) && (k[2] == 49 || k[2] == 50))      // pokud in1/IN1
                {
                if (k[3] == 49 || k[3] == 50) IN_fce();
                else UN_COM();
                
                }
        /*
        else if ((k[0] == 73 || k[0] == 105 ) && (k[1] == 78 || k[1] == 110  ) && (k[2] == 50))      // pokud in2/IN2
                {
                IN2_fce();
                bin2ascii();
                }
        */
        else if ((k[0] == 68 || k[0] == 100 ) && (k[1] == 65 || k[1] == 97))               // pokud da/DA
                {
                float A_out = (k[3]&15) + ((k[5]&15)*0.1) + ((k[6]&15)*0.01);    //prevede cisla z pole na jedno cislo
                if (k[3]<48 && k[3]>57 && k[5]<48 && k[5]>57 && k[6]<48 && k[6]>57) ERR();      //overeni zda parametr obsahuje pouze cisla
                else if (A_out<=Uref) 
                        {
                        D = (A_out*(256/Uref));                              //vypocita dec. hodnotu podle vzorce: D = A_out*256/Uref
                        DA_fce(D);
                        }
                        
                     else ERR();
                }
                                  
        else if ((k[0] == 65 || k[0] == 97) && (k[1] == 68 || k[1] == 100))           //pokud ad/AD 
                {
                measure();
                AD_fce();       
                AD_fce();
                
                if ( U_vst >= 100) U_vst = U_vst/100;
                if ( U_vst >= 10) U_vst = U_vst/10;
                //printf("Napeti: ");
                for ( i = 0; i < 4; i++)        // cyklus pro rozdeleni float na jednotliva cisla
                        {
                        U_vstup[i] = (unsigned char)U_vst;
                        if ( U_vstup[i] > U_vst) U_vstup[i] -= 1;
                        
                        U_vst -= U_vstup[i];
                        U_vst *= 10;
                        
                        U_vstup[i] = U_vstup[i] | 48;
                        if ( i==1 && meas_konst==1) 
                                {
                                printf(",");
                                putchar( U_vstup[i]);
                                }
                        else if ( i==2 && (meas_konst==10 || meas_konst==20.41 ))
                                {
                                printf(",");
                                putchar( U_vstup[i]);
                                }
                        else if ( i==3 && meas_konst==62.5 )
                                {
                                printf(",");
                                putchar( U_vstup[i]);
                                }
                        else putchar( U_vstup[i]);
                        };
                
                printf(" V \n\r");
                /*
                for ( i = 0; i < 4; i++)          // konverze do ascii + vypis na seriovou linku
                        {
                        U_vstup[i] = U_vstup[i] | 48;
                        if ( i==1) 
                                {
                                printf(",");
                                putchar( U_vstup[i]);
                                }
                        
                        else putchar( U_vstup[i]);
                        
                        };
                
                */
                
                }
        else UN_COM();
        
        j = -1;
        
        }
      
      if ( j == 22) ERR();
      else 
        {
        if ( k[j] == 8)   //pokud backspace
                {
                backspace();
                } 
        else j++; //if ( j == 22) ERR();
           //else j++;
        }
	};
}
