/* ATtiny13 1.2MHz */ #define F_CPU 1200000L #include #include #include #include #define ADDRESS_1 8 #define ADDRESS_2 16 #define SWITCH_DDR DDRB #define SWITCH_PULL_UP PORTB #define SWITCH_PORT_IN PINB #define SWITCH_0_PIN PB4 #define SWITCH_1_PIN PB3 #define SYNC_DDR DDRB #define SYNC_PORT_IN PINB #define SYNC_0_PIN PB0 #define SYNC_1_PIN PB1 #define LED_DDR DDRB #define LED_PORT_OUT PORTB #define LED_PIN PB2 #define SET_BIT(byte, bit) ((byte) |= (1UL << (bit))) #define CLEAR_BIT(byte,bit) ((byte) &= ~(1UL << (bit))) #define IS_SET(byte,bit) (((byte) & (1UL << (bit))) >> (bit)) #define IS_PRESSED(byte,bit) (!(((byte) & (1UL << (bit))) >> (bit))) volatile uint8_t frequency, mode, frequency_old, mode_old, sequence=0, duration, duty, c, d, timer_overflow_count=0, timer_overflow_target=6; ISR(TIM0_OVF_vect) { if(++timer_overflow_count > timer_overflow_target) { // check if any button is pressed timer_overflow_target=6; // by default every 82ms /* If SWITCH_1 is pressed, change device's frequency */ if (IS_PRESSED(SWITCH_PORT_IN,SWITCH_1_PIN)) { frequency ++; timer_overflow_target=12; // wait 164ms after a button is pressed } if (frequency > 4) { frequency = 0; } /* If SWITCH_0 is pressed, change device's duty cycle */ if (IS_PRESSED(SWITCH_PORT_IN,SWITCH_0_PIN)) { mode++; timer_overflow_target=12; // wait 164ms after a button is pressed } if (mode > 4) { mode = 0; } /* If two buttons are pressed at the same time, reset to default settings */ if((IS_PRESSED(SWITCH_PORT_IN,SWITCH_1_PIN)) && (IS_PRESSED(SWITCH_PORT_IN,SWITCH_0_PIN))) { frequency=4; mode=2; eeprom_update_byte((uint8_t*)ADDRESS_1, frequency); // update EEPROM with defaults eeprom_update_byte((uint8_t*)ADDRESS_2, mode); CLEAR_BIT(LED_PORT_OUT,LED_PIN); // and make LEDs go dark _delay_ms(1000); // for one second } timer_overflow_count = 0; } } void advance_sequence(void) { // this function drives LEDs switch(sequence) { case 0: /* light LEDs only when eye is occluded and mode is not 0*/ if(((IS_SET(SYNC_PORT_IN,SYNC_0_PIN)) || (IS_SET(SYNC_PORT_IN,SYNC_1_PIN))) && mode) { SET_BIT(LED_PORT_OUT,LED_PIN); } break; case 1: CLEAR_BIT(LED_PORT_OUT,LED_PIN); break; break; } sequence++; if(sequence>1) sequence=0; } int main(void) { uint8_t i; uint16_t delay; CLEAR_BIT(SWITCH_DDR,SWITCH_0_PIN); // set switches pins as inputs, pulled-up by internal resistors CLEAR_BIT(SWITCH_DDR,SWITCH_1_PIN); SET_BIT(SWITCH_PULL_UP,SWITCH_0_PIN); SET_BIT(SWITCH_PULL_UP,SWITCH_1_PIN); CLEAR_BIT(SYNC_DDR,SYNC_0_PIN); // set SYNC pins as inputs CLEAR_BIT(SYNC_DDR,SYNC_1_PIN); SET_BIT(LED_DDR,LED_PIN); // set LEDs pin as output frequency = eeprom_read_byte((uint8_t*)ADDRESS_1); // read previous state of device mode = eeprom_read_byte((uint8_t*)ADDRESS_2); if (frequency > 4) { frequency = 4; } // if EEPROM stored settings outside of range, set defaults if (mode > 4) { mode = 2; } SET_BIT(TCCR0B,CS01); // prescale timer to 1/64th the clock rate SET_BIT(TCCR0B,CS00); SET_BIT(TIMSK0,TOIE0); // enable timer overflow interrupt sei(); while (1) { switch(frequency) { // calculate how much time every main while loop execution will take case 0: duration=40; break; case 1: duration=20; break; case 2: duration=13; break; case 3: duration=10; break; case 4: duration=1; break; } d = d + duration; if(d > 100) { // Check approximately every 100 ms. // duration is in 0.1 ms, in one cycle of main while loop duration is executed 10 // times (in this particular device 4 times), hence 10 "milliseconds" in 100 ms if((frequency == frequency_old) && (mode == mode_old)) c++; // check if settings are permanent else c= 0; if(c==100) { // after approximately 10 seconds of settings being permanent eeprom_update_byte((uint8_t*)ADDRESS_1, frequency); //start updating EEPROM with stable setting eeprom_update_byte((uint8_t*)ADDRESS_2, mode); c = 0; } frequency_old = frequency; mode_old = mode; d = 0; } duty = mode; switch(frequency) { // determines how much time each fourth of main while loop cycle will take case 0: delay=3000; break; case 1: delay=1500; break; case 2: delay=1000; break; case 3: delay=750; break; case 4: delay=75; break; } /* Puts 4 blocks of _delay_loop_2 to properly */ /* control LEDs duty cycle. First blocks set */ /* LED_PIN to 1, next blocks set LED_PIN to 0. */ /* Each execution of _delay_loop_2 takes four */ /* clock cycles. */ /* -------------------------------------------- */ advance_sequence(); for(i = 0; i < (duty); i++) _delay_loop_2(delay); advance_sequence(); for(i = 0; i < (4-duty); i++) _delay_loop_2(delay); /* -------------------------------------------- */ } }