// ATtiny13A #include #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 #include #include #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; } } }