http://www.instructables.com/id/Led-Ladder-Game-Attiny85/ #define F_CPU 1000000 // ----------------------------------------------------------------------------------- #include #include #include // ----------------------------------------------------------------------------------- #define LED(n) DDRB = 0; PORTB = led[n][0]; DDRB = led[n][1]; _delay_us(1500); // ----------------------------------------------------------------------------------- const unsigned char led[12][2] = { {8, 8 | 4}, {8, 8 | 1}, {8, 8 | 2}, {1, 1 | 4}, {1, 1 | 8}, {1, 1 | 2}, {2, 2 | 4}, {2, 2 | 1}, {2, 2 | 8}, {4, 4 | 8}, {4, 4 | 2}, {4, 4 | 1}, }; // ----------------------------------------------------------------------------------- const int onTimes[12] = {0x80, 0x78, 0x70, 0x68, 0x60, 0x58, 0x50, 0x48, 0x40, 0x30, 0x20, 0x10}; // ----------------------------------------------------------------------------------- volatile unsigned char pressed = false; volatile unsigned char onTime = onTimes[0]; volatile unsigned char value = 0; volatile unsigned char ledOn; // ----------------------------------------------------------------------------------- int main(void) { cli(); // globally disable pullups, we need this for our charlie plexing to work MCUCR |= (1 << PUD); // set timer1's frequency TCCR1 |= (1 << CS13) | (1 << CS12) | (1 << CS10); // have timer1 fire our interupt when it overflows TIMSK |= (1 << TOIE1); // set the timer to 0 TCNT1 = 0; sei(); // main loop while (1) { ledOn = (TCNT1 < onTime); if (value) { // turn the last rung of the ladder LED(value - 1); } else { DDRB = 0; // we are in the starting position, turn all LEDs off } if (ledOn && !pressed) { // this is the flashing LED LED(value); } if (!(PINB & (1 << PINB4))) // if the button is down { if (!ledOn) // we pressed/held the button when the LED was off! { // flash the current LED 5 times LED(value); _delay_ms(100); DDRB = 0; _delay_ms(100); LED(value); _delay_ms(100); DDRB = 0; _delay_ms(100); LED(value); _delay_ms(100); DDRB = 0; _delay_ms(100); LED(value); _delay_ms(100); DDRB = 0; _delay_ms(100); LED(value); _delay_ms(100); DDRB = 0; _delay_ms(100); // slide down the ladder while (--value != 0xFF) { LED(value); _delay_ms(50); } // reset all of our values so the user can start again pressed = false; value = 0; onTime = onTimes[0]; TCNT1 = 0; } else if (!pressed) // check this is the first time we have found the button was pressed this loop { pressed = true; // signal to stop us climbing any further until the next timer loop value++; // step up _delay_ms(50); DDRB = 0; _delay_ms(50); // quick flash if (value == 12) { // if we reached the end TCNT1 = 0; // reset the timer and ... while(1) { // show a continue sliding up for the wining animation!! LED((TCNT1 / 4) % 12); } } } } } } // ----------------------------------------------------------------------------------- ISR(TIM1_OVF_vect) { // each time we reach the TOP of our counter we reset our pressed state pressed = false; // and update the flashing interval onTime = onTimes[value]; } // -----------------------------------------------------------------------------------