/*Программа для счетчика оборотов намоточного станка энкодер из компьютерной мыши
для корректировки кол-ва оборотов изменять переменную "К" 
автор: 
микроконтроллер ATTINY2313
тактовая частота 1МГц, fuse по умолчанию
26 октября 2014 года*/

#include <tiny2313a.h>
#include <delay.h>
#include <stdio.h> 
/*переменные для работы с динамической индикации*/
int number = 0;
int number1 = 0;
int number2 = 0;
int i=0;

/*переменные для подсчета импульсов энкодера и приращения их в кол-во витков*/
int impulsp,impulsl, vitok=0;

/*переменные для обработки энкодера*/
int NewState,OldState,upState,downState;
int k=6; //переменная для перевода кол-ва импульсов энкодера в обороты станка

int flag=0; //переменная задержки перед записью в eeprom
eeprom int vitok_eep; //переменная хранящая в eeprom последнее значение показаний счетчика

// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{       
        PORTD=0b00000000;
        NewState=PINA & 0x03;    
        flag++;
/*обработка динамической индикации*/        
        if(i==0)
        {
           number=number1;
           PORTD.5=1;
           i++; 
        }
        else
        {
           number=number2;
           PORTD.6=1;
           i=0;
        }              
            
        switch(number) 
        {  
         case 0:{PORTB=0b00111111; break;}
         case 1:{PORTB=0b00000110; break;}
         case 2:{PORTB=0b01011011; break;}
         case 3:{PORTB=0b01001111; break;}
         case 4:{PORTB=0b01100110; break;}
         case 5:{PORTB=0b01101101; break;}
         case 6:{PORTB=0b01111101; break;}
         case 7:{PORTB=0b00000111; break;}
         case 8:{PORTB=0b01111111; break;}
         case 9:{PORTB=0b01101111; break;}   
        } 
        
/*обработка энкодера*/         
        if(NewState!=OldState)
         {
          switch(OldState)
           {
            case 2:
             {
              if(NewState==3) upState++;
              if(NewState==0) downState++;
              break;
             }
            case 0:
             {
              if(NewState==2) upState++;
              if(NewState==1) downState++;
              break;
             }
            case 1:
             {
              if(NewState==0) upState++;
              if(NewState==3) downState++;
              break;
             }
            case 3:
             {
              if(NewState==1) upState++;
              if(NewState==2) downState++;
              break;
             }     
           }
                   
OldState=NewState;
          }
 TCNT1H=0x00;
 TCNT1L=0x00;
 
}
/*основная функция*/  
void main(void)
{
PORTB=0xFF;
DDRB=0xFF;

PORTD=0b01100000;
DDRD=0b01100000;

PORTA=0b00000111;
DDRA=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 1000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x03;
OCR1AL=0xE8;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x10;
vitok=vitok_eep; //выводим последние показания счетчика записанные в eeprom
// Global enable interrupts
#asm("sei")

/*рабочий цикл*/
while (1)
      {   
          if(upState >= 4) //если вращаем энкодер вправо,  
           {
            impulsp++;    // начинаем отсчитывать импульсы
            upState=0;
           }
          if(impulsp >= k) // если насчитали 6 и более импульсов 
           {  
            vitok++;      //  увеличиваем число на индикаторе на 1
            impulsp=0;
           }
          if(vitok >99)  // если на индикаторе 99 и более, 
           {
            vitok=0;     // обнуляем показания
           }     
          if(downState >= 4) // /если вращаем энкодер влево,
           {
            impulsl++;      // начинаем отсчитывать импульсы
            downState=0;
           }
           if(impulsl >= k)  // если насчитали 6 и более импульсов
           { 
            vitok--;        //  уменьшаем число на индикаторе на 1
            impulsl=0;
           }
           if(vitok < 0)   // если на индикаторе 0 и менее,
           {
            vitok=99;      // устанавливаем значение 99
           } 
/*выводим на индикаторы количество оборотов(витков)*/                
          number1=vitok%10; //выводим единицы 
          number2=vitok/10; //выводим десятки

/*принудительное обнуление счетчика*/          
           if(PIND.4==0) // если пин 2 порта С притянут к нулю (к общему проводу) 
           {
            delay_ms(50); //рабочая задержка (антидребезг контактов)
            vitok=0;     // и сбрасываем показания счетчика на 0
           }
/*запись показаний счетчика в eeprom, что бы постоянно не писать все значения подряд
пишем только в случае если показания на счетчике не меняются около 1 сек.*/           
          if(flag>=1000) //ждем примерно 1 сек., если показания не поменялись  
           {
            vitok_eep=vitok; //записываем последнее значения счетчика в eeprom
           }                
      };
}