/*****************************************************
This program was produced by the
CodeWizardAVR V1.25.9 Standard
Automatic Program Generator
© Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project :
Version :
Date    : 29.10.2010
Author  : F4CG
Company : F4CG
Comments:


Chip type           : ATmega8
Program type        : Application
Clock frequency     : 8,000000 MHz
Memory model        : Small
External SRAM size  : 0
Data Stack size     : 256
*****************************************************/

#include <mega8.h>
 #include <lcd.h>
#include <delay.h>

// Alphanumeric LCD Module functions
#asm
   .equ __lcd_port=0x12 ;PORTD
#endasm
#define COUNT 8
#define urov_pomex 4

eeprom unsigned int set_u=0;
eeprom unsigned int set_i=0;
eeprom unsigned int set_u1=0;
eeprom unsigned int set_u2=0;
eeprom unsigned int set_u3=0;
eeprom unsigned int e_err_set=0;
eeprom unsigned char out_on=0;
eeprom unsigned char gist_on=0;
int pwm_val_a=0,pwm_val_b=0,time_out=0,i=0;
unsigned char set_mode=0,EncState=0,cod_button=0,mode_Display=0, e=0, out=0,m=0,p=0,g=0,fg=1;
unsigned char Dig[7];
  int I_ust=0,I_izm=0,U=0,star_adc_data_U=0, err=0,err_temp=0;
char Counter=0,k=1;

//Функция  антидребезга
  unsigned char incod(void)
  {
  unsigned char cod0=0;
  unsigned char k,cod1;

   for(k=0;k<200;k++)
      {
       cod1=PINB&0xF8;
        if (cod0!=cod1)
         {
           k=0;
           cod0=cod1;
         }
       }
       return cod1;
   };

    void PrepareData(   int adc_result)      // Ф-ция для разложения числа
{
unsigned  int Num1=0,Num2=0, Num3=0,Num4=0;

  #asm("wdr")
     if (adc_result<0)
      {
        adc_result=0;
          };

 while (adc_result >= 1000) //тысяча
  {
  adc_result -= 1000;
  Num1++;
  }

  while (adc_result >= 100) //сотня
  {
  adc_result -= 100;
  Num2++;
  }
   while (adc_result >= 10) //десятки
  {
  adc_result -= 10;
  Num3++;
  }

  Num4 = adc_result; //остаток
  Dig[0] = Num1+0x30;
  Dig[1] = Num2+0x30;
  Dig[3] = Num3+0x30;
  Dig[4] = Num4+0x30;
   #asm("wdr")
}

void Display(void)   // Ф-ция  отображения
{
  int i;
   #asm("wdr")
  if ((Dig[0]-0x30)<=0)
  {
    Dig[0]=0x20;
          };
   //lcd_puts(&Dig[0]);
  for(i=0; i<6; i++)
  {
    lcd_putchar(Dig[i]);
  }
}



#define ADC_VREF_TYPE 0xC0

// Read the AD conversion result
  int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}


// Timer 0 overflow interrupt service routine  отображение информации
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
  #asm("wdr")
  TCNT0=0x7F;
  time_out+=1;

if (Counter++ >=COUNT)
  {

    Counter = 0;
    switch (mode_Display)
     {
    case 0:
           {

    lcd_gotoxy(1,0);
    //напряжение
    U=U>>3;
     if(g)
     {
       if(fg)
        {
    if (star_adc_data_U!=U)
         {
            if((U>star_adc_data_U-urov_pomex)&&(U<star_adc_data_U+urov_pomex))
              {U=star_adc_data_U;}
             else
               {
                 star_adc_data_U=U;
                };
           };
         };
      };




    PrepareData(U);   //

     Dig[2] = '.';
     Dig[5] = 'V';
     Display();
    lcd_putsf(", ");

    //ток измеренный


    PrepareData((I_izm>>3)-err);   //

     Dig[2] = '.';
     Dig[5] = 'A';
    Display();

    lcd_gotoxy(1,1);

    //ток установленный
    lcd_putsf("Set I=  ");

    PrepareData((I_ust>>3)-err);
     Dig[2] = '.';
     Dig[5] = 'A';
    Display();

    if (I_izm>=I_ust)
    { PORTB.0=1;
    lcd_gotoxy(0xF,1);
      lcd_putchar(0xDA);

    }
    else
    {
      lcd_putchar(' ');
      PORTB.0=0;
    };

    if (set_mode==1)
       { lcd_gotoxy(0,0);
        lcd_putchar('>');
         lcd_gotoxy(0,1);
          lcd_putchar(0x20);
           };

           if (set_mode==2)
       { lcd_gotoxy(0,1);
        lcd_putchar('>');
         lcd_gotoxy(0,0);
          lcd_putchar(0x20);
           };



             if (set_mode==0)
       { lcd_gotoxy(0,1);
        lcd_putchar(0x20);
         lcd_gotoxy(0,0);
          lcd_putchar(0x20);
           };
           break;
           }
    case 1:
           {
             lcd_gotoxy(0,0);
             lcd_putsf("    saving      ");
             lcd_gotoxy(0,1);
             lcd_putsf("   complete     ");
           break;
           }
     case 2:
           {
             lcd_clear();
             lcd_gotoxy(0,0);
             lcd_putsf("    OUT ON      ");
           break;
              }
      case 3:
           {
             lcd_clear();
             lcd_gotoxy(0,0);
             lcd_putsf("    OUT OFF      ");
           break;
              }
       case 4:
           {
             lcd_clear();
             lcd_gotoxy(0,0);
             lcd_putsf("  FILTER ON     ");
           break;
              }
        case 5:
           {
             lcd_clear();
             lcd_gotoxy(0,0);
             lcd_putsf("  FILTER OFF      ");
           break;
              }
    };
    U = 0;
    I_izm = 0;
    I_ust = 0;
  }
  else
  {

    U+=read_adc(2)*4;
    I_izm+=read_adc(0);
    I_ust += read_adc(1);
  }





// Place your code here

}

void EncoderScan(void) // Функция опроса энкодера
{
unsigned char New=0;
static unsigned char val_bi=0, val_bd=0, val_ai=0, val_ad=0  ;
New = incod();    // Берем текущее значение
            // И сравниваем со старым

// Смотря в какую сторону оно поменялось -- увеличиваем
// Или уменьшаем соответствующий параметр

  if (set_mode==1)
   {

        switch(EncState)
    {
    case 184:
        {
        if(New == 248) val_bi++;
        if(New == 56) val_bd++;
        break;
        }

    case 56:
        {
        if(New == 184) val_bi++;
        if(New == 120) val_bd++;
        break;
        }
    case 120:
        {
        if(New == 56) val_bi++;
        if(New == 248) val_bd++;
        break;
        }
    case 248:
        {
        if(New == 120) val_bi++;
        if(New == 184) val_bd++;
        break;
        }
    };
                     if (val_bi>=4)           // на 1 изменение положения  4 импульса
                     {


                        if (++pwm_val_b>=1023) {pwm_val_b=1023;  };

                       OCR1B=pwm_val_b;
                         val_bi=0;
                          time_out=0;

                              }
                         else
                          {
                             if (val_bd>=4)
                                {
                                    if (--pwm_val_b<=0) {pwm_val_b=0;};
                                    OCR1B=pwm_val_b;
                                   time_out=0;
                                   val_bd=0;
                                    };
                             };






    }
else
 {
   if (set_mode==2)
   {

     switch(EncState)
    {
    case 184:
        {
        if(New == 248) val_ai++;
        if(New == 56)  val_ad++;
        break;
        }
    case 56:
        {
        if(New == 184) val_ai++;
        if(New == 120)val_ad++;
        break;
        }
    case 120:
        {
        if(New == 56) val_ai++;
        if(New == 248) val_ad++;
        break;
        }
    case 248:
        {
        if(New == 120) val_ai++;
        if(New == 184) val_ad++;
        break;
        }
    }
     if (val_ai>=4)
                     {


                        if (++pwm_val_a>=1023) {pwm_val_a=1023;  };

                       OCR1A=pwm_val_a;
                         val_ai=0;
                          time_out=0;

                              }
                         else
                          {
                             if (val_ad>=4)
                                {
                                    if (--pwm_val_a<=0) {pwm_val_a=0;};
                                    OCR1A=pwm_val_a;
                                   time_out=0;
                                   val_ad=0;
                                    };
                             };

    };
    };

EncState = New;        // Записываем новое значение
                // Предыдущего состояния

 };
// Declare your global variables here

void main(void)
{
// Declare your local variables here
//OSCCAL=0x9F;
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=Out Func1=Out Func0=Out
// State7=P State6=P State5=P State4=P State3=P State2=0 State1=0 State0=0
PORTB=0xF8;
DDRB=0x07;

// Port C initialization
// Func6=In Func5=Out Func4=Out Func3=In Func2=In Func1=In Func0=In
// State6=T State5=0 State4=0 State3=P State2=T State1=T State0=T
PORTC=0x08;
DDRC=0x30;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=in Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=P State2=0 State1=0 State0=0
PORTD=0x08;
DDRD=0xF7;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 7,813 kHz
TCCR0=0x05;
TCNT0=0x7F;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: Ph. correct PWM top=03FFh
// OC1A output: Non-Inv.
// OC1B output: Non-Inv.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0xA3;
TCCR1B=0x01;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x01;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;

// ADC initialization
// ADC Clock frequency: 1000,000 kHz
// ADC Voltage Reference: Int., cap. on AREF
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x83;

// LCD module initialization
lcd_init(16);

// Watchdog Timer initialization
// Watchdog Timer Prescaler: OSC/2048k
#pragma optsize-
WDTCR=0x1F;
WDTCR=0x0F;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
 pwm_val_a=set_i;
  pwm_val_b=set_u;
  OCR1A=pwm_val_a;
  OCR1B=pwm_val_b;
  err=e_err_set;
  p= out_on;
   lcd_clear();
     i=0;
 lcd_gotoxy(0,0);
 lcd_putsf("scheme, firmware");
 lcd_gotoxy(4,1);
 lcd_putsf(" SONATA");
  while (i<10) {i+=1;
  delay_ms(5);};
 i=0;
 lcd_clear();
 lcd_gotoxy(2,0);
lcd_putsf("power supply");
 lcd_gotoxy(4,1);
 lcd_putsf(" ver 2.0");
  while (i<5) {i+=1;
  delay_ms(5);};
  i=0;


// Global enable interrupts
#asm("sei")
PORTC.4=1;
if(p){ PORTC.5=1;out=1;};
g=gist_on;
while (1)
      {
       if(PIND.3==0)
        {
        time_out=0;
            while (PIND.3==0)
             {
                 #asm("wdr")
                 if(time_out>50)
                    {
                      p^=1;
                       out_on=p;
                   m=1;

                                  if (p)
                           {
                              mode_Display=2;

                                       }
                               else
                                   {
                        mode_Display=3;

                     };
                           while(PIND.3==0){  #asm("wdr")};

                        };
           mode_Display=0;
                   };
            if(!m)
            {
             out^=1;
           PORTC.5=out;};
           m=0;
            };

       if (PINC.3==0)
       {
       k=0;
       time_out=0;
        set_mode+=1;
        if(!fg){star_adc_data_U=0;};
        fg=(set_mode==1)?0:1;
         if (set_mode>2)
          {
                  set_mode=0;
                    k=1;
                    set_i=pwm_val_a;
                    set_u=pwm_val_b;
                      };
         while (PINC.3==0) {    };
          };
            if  (PINB.3==0&PINB.4==0)
              {
                 time_out=0;
                  while (PINB.3==0&PINB.4==0)
                   {if (time_out>100)
                       { TIMSK=0x00;
                           err=0;
                           err_temp=0;
                           lcd_gotoxy(0,0);
                           lcd_putsf("  DEFINE ERROR  ");
                           lcd_gotoxy(0,1);
                           lcd_putsf("    COMPLETE    ");
                       while (PINB.3==0||PINB.4==0) { time_out=0;#asm("wdr")};
                         for( e=0; e<4; e++)
                         {
                            err_temp= read_adc(0);
                            if(err_temp>err){err=err_temp;};

                             };
                             e_err_set=err;
                       mode_Display=0;
                       TIMSK=0x01;
                        };

                      };
                      };

                     if(PINB.4==0&PINB.5==0)
                        {
                          g^=1;
                          gist_on=g;
                              if(g)
                                {
                                  mode_Display=4;
                                  star_adc_data_U=0;
                                  }
                                else
                                    {
                                      mode_Display=5;
                                       };
                             while(PINB.4==0&PINB.5==0) {  #asm("wdr") };
                                 mode_Display=0;
                         };

     if (k<1)
     { EncoderScan();
        if (time_out>200)
        { set_mode=0;
          k=1;
          if(!fg){fg=1;star_adc_data_U=0;};
        set_i=pwm_val_a;
         set_u=pwm_val_b;
                    };

        if (PINB.3==0||PINB.4==0||PINB.5==0)
        {
           cod_button=(incod()&0x38);



          // time_out=0;
               if (cod_button==0x30)
                {
                   time_out=0;
                  while (PINB.3==0)
                   {if (time_out>100)
                       {set_u1=pwm_val_b;
                       mode_Display=1;

                        };

                      };
                      mode_Display=0;
                      OCR1B=set_u1;
                      pwm_val_b=set_u1;

                  }
        else  {
                 if (cod_button==0x28)
                {
                 time_out=0;
                  while (PINB.4==0)
                   {if (time_out>100) {set_u2=pwm_val_b;mode_Display=1; };

                      };
                      mode_Display=0;
                      OCR1B=set_u2;
                      pwm_val_b=set_u2;

                  }
               else  {
                       if (cod_button==0x18)
                {
                   time_out=0;
                  while (PINB.5==0)
                   {if (time_out>100) {set_u3=pwm_val_b;mode_Display=1; };

                      };
                      mode_Display=0;
                      OCR1B=pwm_val_b=set_u3;

                  }

                      };



               };







            };
        };


      // Place your code here




      };

}
