#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define AVG_TIME 50
#define THS_TIME 45
#define SD_SEG_A _BV(0)
#define SD_SEG_B _BV(1)
#define SD_SEG_C _BV(2)
#define SD_SEG_D _BV(3)
#define SD_SEG_E _BV(4)
#define SD_SEG_F _BV(5)
#define SD_SEG_G _BV(6)
#define SD_LED_RED SD_SEG_A
#define SD_LED_YLW SD_SEG_C
#define LD_SEL_LED _BV(0)
#define LD_SEL_1 _BV(1)
#define LD_SEL_2 _BV(2)
#define LD_SEL_3 _BV(3)
#define LD_SEL_4 _BV(4)
#define GET_SEL (PINC & 0x1f)
#define SD_SYM_NONE (0)
#define SD_SYM_0 (SD_SEG_A | SD_SEG_B | SD_SEG_C | SD_SEG_D | SD_SEG_E | SD_SEG_F)
#define SD_SYM_1 (SD_SEG_B | SD_SEG_C)
#define SD_SYM_2 (SD_SEG_A | SD_SEG_B | SD_SEG_D | SD_SEG_E | SD_SEG_G)
#define SD_SYM_3 (SD_SEG_A | SD_SEG_B | SD_SEG_C | SD_SEG_D | SD_SEG_G)
#define SD_SYM_4 (SD_SEG_B | SD_SEG_C | SD_SEG_F | SD_SEG_G)
#define SD_SYM_5 (SD_SEG_A | SD_SEG_C | SD_SEG_D | SD_SEG_F | SD_SEG_G)
#define SD_SYM_6 (SD_SEG_A | SD_SEG_C | SD_SEG_D | SD_SEG_E | SD_SEG_F | SD_SEG_G)
#define SD_SYM_7 (SD_SEG_A | SD_SEG_B | SD_SEG_C)
#define SD_SYM_8 (SD_SEG_A | SD_SEG_B | SD_SEG_C | SD_SEG_D | SD_SEG_E | SD_SEG_F | SD_SEG_G)
#define SD_SYM_9 (SD_SEG_A | SD_SEG_B | SD_SEG_C | SD_SEG_D | SD_SEG_F | SD_SEG_G)
#define SD_SYM_E (SD_SEG_A | SD_SEG_D | SD_SEG_E | SD_SEG_F | SD_SEG_G)
#define SD_SYM_P (SD_SEG_A | SD_SEG_B | SD_SEG_E | SD_SEG_F | SD_SEG_G)
#define SD_SYM_T (SD_SEG_D | SD_SEG_E | SD_SEG_F | SD_SEG_G)
#define GET_SYM (~PIND & 0x7f)
#define BROKEN_SEG (SD_SEG_D)
static uint8_t sd_symbols[] = {
SD_SYM_NONE,
SD_SYM_0, SD_SYM_1, SD_SYM_2, SD_SYM_3, SD_SYM_4,
SD_SYM_5, SD_SYM_6, SD_SYM_7, SD_SYM_8, SD_SYM_9,
SD_SYM_E, SD_SYM_P, SD_SYM_T
};
volatile static uint8_t sel, symbol;
volatile static short fb0, fb1, fb2, fb3, fb4;
ISR(PCINT1_vect) {
sel = GET_SEL;
symbol = GET_SYM;
if (((sel & LD_SEL_LED) && fb0) ||
((sel & LD_SEL_1) && fb1) ||
((sel & LD_SEL_2) && fb2) ||
((sel & LD_SEL_3) && fb3) ||
((sel & LD_SEL_4) && fb4)){
PORTD &= ~BROKEN_SEG;
}
else {
PORTD |= BROKEN_SEG;
}
}
int main(void)
{
int cur_time;
int led_on_time;
uint8_t last_symbol_1, last_symbol_2, last_symbol_3, last_symbol_4;
int i;
DDRC = 0;
DDRD = BROKEN_SEG;
PCICR |= _BV(PCIE1);
PCMSK1 |= _BV(PCINT8) | _BV(PCINT9) | _BV(PCINT10) | _BV(PCINT11) | _BV(PCINT12);
cur_time = 0;
led_on_time = 0;
last_symbol_1 = last_symbol_2 = last_symbol_3 = last_symbol_4 = 0;
fb0 = fb1 = fb2 = fb3 = fb4 = 0;
while(1) {
sei();
while (sel == 0) {}
cli();
if (sel & (LD_SEL_1 | LD_SEL_2 | LD_SEL_3 | LD_SEL_4)) {
for (i = 0; i < 14; i++) {
uint8_t sd_symbol = sd_symbols[i];
if ((symbol & ~BROKEN_SEG) == (sd_symbol & ~BROKEN_SEG)) {
short val;
if (sd_symbol & BROKEN_SEG) {
val = 1;
} else {
val = 0;
}
if (sel & LD_SEL_1) {
last_symbol_1 = sd_symbol;
fb1 = val;
} else if (sel & LD_SEL_2) {
last_symbol_2 = sd_symbol;
fb2 = val;
} else if (sel & LD_SEL_3) {
last_symbol_3 = sd_symbol;
fb3 = val;
} else if (sel & LD_SEL_4) {
last_symbol_4 = sd_symbol;
fb4 = val;
}
if ((last_symbol_1 == SD_SYM_P) &&(last_symbol_2 == SD_SYM_8) &&
(last_symbol_3 == SD_SYM_5) && (last_symbol_4 == SD_SYM_5)) {
fb2 = 0;
}
else if ((last_symbol_1 == SD_SYM_E) &&(last_symbol_2 == SD_SYM_8) &&
(last_symbol_3 == SD_SYM_1) && (last_symbol_4 == SD_SYM_1)) {
fb1 = 0;
fb2 = 0;
fb4 = 1;
}
break;
}
}
}
else if (sel & LD_SEL_LED) {
if (cur_time++ > AVG_TIME) {
if (led_on_time < THS_TIME) {
fb0 = 0;
} else {
fb0 = 1;
}
cur_time = 0;
led_on_time = 0;
} else {
if ((symbol & (SD_LED_RED | SD_LED_YLW)) == 0) {
led_on_time++;
}
}
}
sel = 0;
}
return 0;
}