//  ATtiny13A

#include <avr/EEPROM.h>
#define EEPROM_LEN 32        // ������� ������������ ������ � ������ (��� ���������)
#define STORE_LEN EEPROM_LEN
uint16_t EEMEM store_debugged[STORE_LEN];
volatile uint16_t i_eeprom = 0x04; // ��������� ����� ������ �����

#define F_CPU 9600000
#include <avr/interrupt.h>
#include <avr/io.h>
#include <util/atomic.h>

#define MAX_PULSE_WIDTH 1500 // ������������ ���������� ����� �������� ��������� (� ����� �������)
#define MAX_PULS_AMO 10      // ����. ����� �������������� ���������; ������������ ������ ������� - 40 ���� (������� - ������� �����)

volatile unsigned long dt[MAX_PULS_AMO] = {0}; // ��������� ����� ����� ������� ��� ������� ������
volatile uint8_t front_number = 0;       // ����� ���������� ������������� ������
volatile unsigned long timer_ticks = 0;  // ������� � ���������� �������


ISR(TIM0_OVF_vect)  // ~~27 mcs
{
  timer_ticks++;
}


uint8_t get_front_number(void)
{
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
    return front_number;
  }
}

unsigned long get_timer_ticks(void)
{
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
    return timer_ticks;
  }
}

void front_number_zero()
{
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
  {
    front_number = 0;
  }
}


ISR(INT0_vect){
  if(front_number >= MAX_PULS_AMO) return;
  dt[front_number] = get_timer_ticks();
  front_number++;
}


void setup()
{
  // ��������� �����
  DDRB  = 0xFF;
  PORTB = 0x00;
  // �� ����
  DDRB  &= ~(1 << DDB1);
  // ��������
  PORTB |=  (1 << PB1);

  // ��������� �������� ����������
  MCUCR &= ~((1 << ISC01) | (1 << ISC00));
  // ������������ INT0 (PB1) �� ������������ ������
  MCUCR |= (1 << ISC01) | (1 << ISC00);
  // ��������� ������� ���������� INT0
  GIMSK = (1 << INT0);
  
  // ��������� �������
  TCCR0B |= (1 << CS00); // ������������ 1
  TCCR0A |= (1 << WGM00) | (1 << WGM01);
  TIMSK0 |= 2;
  TCNT0 = 0;
  sei();
}


unsigned long millis()  // �� core13 (v.022)
{
  unsigned long x;
  
  asm("cli");
  #if F_CPU == 1000000
  x = get_timer_ticks() / 4;
  #elif F_CPU == 9600000
  x = get_timer_ticks() / 37;
  #endif
  asm("sei");
  
  return x;
}


void _delay_ms(unsigned ms) // ~~
{
  unsigned long ms_0 = millis();
  while((millis() - ms_0) < ms);
}


int main(void)
{
  setup();

  while (1)
  {
    uint8_t pulse_amo = get_front_number(); // ����� ����������� ��������� (��������� ����� ������� ��������� 4 �����)
    if(pulse_amo > 1) // ��������� ������ ������ �������� (����� ������� �������)
    {
      if((get_timer_ticks() - dt[pulse_amo - 1]) >= MAX_PULSE_WIDTH) // ����� ���������� ������ ������ ���������� �������
      {
        uint16_t hash = 0;
        
        for (uint8_t i = 0; i < pulse_amo - 1; i++) 
        {
          if (dt[i+1] <= dt[i]) 
            continue;  // ���� ����� ����������

          uint16_t ticks_tween_fronts  = (uint16_t)(dt[i+1] - dt[i]); // ���������� ����� ��������
          
          hash += (1 << i) * ticks_tween_fronts / 50;
        }

        // ������� ��� ������ 
        PORTB ^= (1 << PB2); _delay_ms(500); PORTB ^= (1 << PB2);
          
        eeprom_write_word (&store_debugged[i_eeprom++], hash); // �������� ���
        
        front_number_zero();
      }
      continue;
    }
  }
}