/* source code for a simple binary clock, targeted to the AVR attiny2313. * Copyright (c) 2007, Patrick Tait * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of secondpagemedia.com nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Patrick Tait ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL Patrick Tait BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE */ #define DEBOUNCE_K 4 /*^ Debounce coefficient, this * wait time == debounce time ^*/ #define WAIT_TIME 3 /*^ Time to wait between polling ^*/ #define SECONDPRESS_K 40 /*Second press coefficent. This * Wait time == time until repeats begin*/ #define REPEAT_K 15 /*^Key repeat coefficient. This * wait time == time between repetes*/ int main(void); void Cascade(unsigned int *Seconds, unsigned int *Minutes, unsigned int *Hours); #include /* Defines pins, ports, etc to make programs easier to read */ #define F_CPU 1000000UL/*for the timer*/ #include /*_delay_ms stuff*/ /* * Pins: * PB0-5: ground for LED matrix * PD[01]: debug blinkers. 0 is every second, 1 is every pulse * PD[234]: Vcc for matrix * PD5: 60hz clock * PD6: Input for the buttons. H++, M++ and ajudt brightness */ int main(){ unsigned int State= 0; /* Holds the previous state of the * trigger pulse, 0 for low, 1 for * high */ unsigned int MS = 0; /* Milliseconds/trigger pulses */ unsigned int Seconds = 0; /* Next 3 vars hold the time */ unsigned int Minutes = 0; unsigned int Hours = 0; unsigned int String = 0; /*0-2, for lighting individual strings*/ unsigned int HoursPressed = 0, MinutesPressed = 0, BrightnessPressed = 0; unsigned int Brightness = 0; /*^Controls the brightness level. From 0 (Brightest) to * WAIT_TIME - 1 (Darkest), works by turning the lights on for * WAIT_TIME - Brightness, and then off for Brightness*/ /*Set up the ports*/ DDRB = _BV(PD0) + _BV(PD1) + _BV(PD2) + _BV(PD3) + _BV(PD4) + _BV(PD5); /*^ enables output on pins 0-5 on port D ^*/ DDRD = ~(_BV(PD5) + _BV(PD6));/* Enable input on 5&6 of port D, * output elsewhere*/ PORTD = _BV(PD6); /*Pullup on PD6, no pullup on PD5, outputs low*/ PORTB |= _BV(PD0) + _BV(PD1) + _BV(PD2) + _BV(PD3) + _BV(PD4) + _BV(PD5);/*all high, therefore all off*/ while(1){ /*This segment checks to see if the clock signal (halfwave from * the power line) is high, if so it increments the clock*/ if(PIND & _BV(PD5)) /*PD5 is on*/ { PORTD |= _BV(PD1); if(State == 0)/*It wasn't on before*/ { MS++;/*1/60 of a second*/ if(MS == 60) { MS = 0; Seconds++; Cascade(&Seconds, &Minutes, &Hours); } } State = 1; } else/*PD0 is low*/ { PORTD &= ~_BV(PD1); State = 0; } /*This segment flips on the sets of LEDs for the seconds, * minutes, and hours, it also controls the inputs. * PB0-5 are set to low for on, PD 2(s) 3(m) and 4(h) are set to * high to activate the respective string. * Switches are debounced for DEBOUNCE_K * WAIT_TIME, after * SECONDPRESS_K*WAIT_TIME and every REPEAT_K another keypress * is recorded */ /* turns off both sides of the matrix */ switch(String){ case 0: /*Hours*/ PORTD |= _BV(PD4);/*Pin four high*/ PORTB &= ~Hours; String = 1; if(!(PIND & _BV(PD6))){ /*Button is pressed*/ HoursPressed++; if(HoursPressed == DEBOUNCE_K){ Hours++; Cascade(&Seconds, &Minutes, &Hours); } else if(HoursPressed == SECONDPRESS_K){ Hours++; Cascade(&Seconds, &Minutes, &Hours); } else if(HoursPressed > SECONDPRESS_K && !(HoursPressed % REPEAT_K)){ /*^every multiple of REPEAT_K*/ Hours++; Cascade(&Seconds, &Minutes, &Hours); } } else{ HoursPressed = 0; } break; case 1: /*minutes*/ PORTD |= _BV(PD3);/*Pin three high*/ PORTB &= ~Minutes;/*display minutes*/ String = 2; if(!(PIND & _BV(PD6))){ /*Button is pressed*/ MinutesPressed++; if(MinutesPressed == DEBOUNCE_K){ Minutes++; Cascade(&Seconds, &Minutes, &Hours); } else if(MinutesPressed == SECONDPRESS_K){ Minutes++; Cascade(&Seconds, &Minutes, &Hours); } else if(MinutesPressed > SECONDPRESS_K && !(MinutesPressed % REPEAT_K)){ /*^every multiple of REPEAT_K*/ Minutes++; Cascade(&Seconds, &Minutes, &Hours); } } else{ MinutesPressed = 0; } break; case 2: /*seconds*/ PORTD |= _BV(PD2);/*Pin two high*/ PORTB &= ~Seconds;/*display seconds*/ String = 0; /*Code for brightness button*/ /*nonfunctional, due to deadlines*/ if(!(PIND & _BV(PD6))){ /*Button is pressed*/ BrightnessPressed++; if(BrightnessPressed == DEBOUNCE_K){ Brightness++; PIND = _BV(PD0);/*toggle pin 0*/ if(Brightness == WAIT_TIME){ Brightness = 0; } } } else{ BrightnessPressed = 0; } break; } /*keep it on for this long*/ _delay_ms(WAIT_TIME - Brightness); /*Turn it off for this long*/ PORTD &= ~(_BV(PD2) + _BV(PD3) + _BV(PD4)); PORTB |= _BV(PD0) + _BV(PD1) + _BV(PD2) + _BV(PD3) + _BV(PD4) + _BV(PD5);/*all high, therefore all off*/ _delay_ms(Brightness); } return(0); } /*Rolls over the clock times*/ void Cascade(unsigned int *Seconds, unsigned int *Minutes, unsigned int *Hours){ if(*Seconds >= 60) { *Seconds = 0; *Minutes += 1; } if(*Minutes >= 60) { *Seconds = 0; *Minutes = 0; *Hours += 1; } if(*Hours >= 24) { *Seconds = 0; *Minutes = 0; *Hours = 0; } }