1 /*
  2     projekt:        numitron_clock.c
  3     datum:          30.05.2013
  4     autor:          KOSTKA Filip
  5                     SENFLUK Petr
  6
  7     *****************************
  8     Numitronove hodiny s Atmega32
  9     *****************************
 10
 11     obsluha:        pin PD5 - PWM
 12                     pin PB2 - zhaveni
 13                 
 14     zobrazovace:    SEG1 - PD7
 15                     SEG2 - PD6
 16                     SEG3 - PB3
 17                     SEG4 - PD4
 18                     SEG5 - PB0
 19                     SEG6 - PB1
 20     
 21     segmenty: PAx
 22        _____
 23       |  1  |
 24     3 |_____| 0
 25       |  2  |
 26     4 |_____| 7 # 6
 27          5
 28
 29 */

 30
 31 #define F_CPU 14745600
 32
 33 #include <avr/io.h>
 34 #include <avr/interrupt.h>
 35
 36     //definice znakove sady
 37     const char dNULL = 0b00000000;
 38     const char dDASH = 0b00000100;
 39     const char dTOP = 0b00000010;
 40     const char dBOTTOM = 0b00100000;
 41     
 42     const char d0 = 0b10111011;
 43     const char d1 = 0b10000001;
 44     const char d2 = 0b00110111;
 45     const char d3 = 0b10100111;
 46     const char d4 = 0b10001101;
 47     const char d5 = 0b10101110;
 48     const char d6 = 0b10111110;
 49     const char d7 = 0b10000011;
 50     const char d8 = 0b10111111;
 51     const char d9 = 0b10101111;
 52     
 53     const char dA = 0b10011111;
 54     const char db = 0b10111100;
 55     const char dE = 0b00111110;
 56     const char dJ = 0b10100001;
 57     const char dS = 0b10101110;
 58     const char dY = 0b10001101;
 59
 60     const char menu_top = 6;
 61     const char brigh_top = 3;
 62
 63     //stavove promenne
 64     char time_update, set_update, brigh_update = 1;
 65     char menu_state = 0, mpx_state = 1, brigh_state = 3;
 66     char hr = 0char min = 0char sec = 0;
 67     char digit_1, digit_2, digit_3, digit_4, digit_5, digit_6;
 68     char time_cnt;
 69
 70 //tlacitko MENU
 71 ISR(INT0_vect ){
 72     if(menu_state == menu_top)
 73         menu_state = 0;
 74     else
 75         menu_state += 1;
 76 }
 77
 78 //tlacitko SET
 79 ISR(INT1_vect ){
 80     set_update = 1;
 81 }
 82
 83 //citac OC0 - multiplex
 84 ISR(TIMER0_OVF_vect ){
 85     //frekvence spousteni 900Hz
 86     if(mpx_state == 6)
 87         mpx_state = 1;
 88     else
 89         mpx_state += 1;
 90 }
 91
 92 //citac OC2 - casomira
 93 ISR(TIMER2_OVF_vect ){
 94     //frekvecne spousteni 225Hz
 95     if(time_cnt == 225){
 96         time_cnt = 0;
 97         time_update = 1;
 98     }
 99     else
100         time_cnt += 1;
101 }
102
103 char num_to_digit(short num){
104     switch(num){
105         case 0 : return d0; 
106         case 1 : return d1;
107         case 2 : return d2;
108         case 3 : return d3;
109         case 4 : return d4;
110         case 5 : return d5;
111         case 6 : return d6;
112         case 7 : return d7;
113         case 8 : return d8;
114         case 9 : return d9;
115     }
116     return dDASH;    //pro pripad spatneho vstupniho parametru
117 }
118
119 //inicializace casu
120 void time_init(){
121     if(sec < 59)
122         sec += 1;
123     else{
124         sec = 0;
125         if(min < 59)
126             min += 1;
127         else{
128             min = 0;
129             if(hr < 23)
130                 hr += 1;
131             else
132                 hr = 0;
133         }//min
134     }//sec
135     time_update = 0;
136 }
137
138 //inicializace pri stisknuti tlacitka SET
139 void set_init(){
140     switch(menu_state){
141         case 0 : ; break;    //rezerva (datum / sleep mode ...)
142         case 1 : if(hr == 23)
143                      hr = 0;
144                  else
145                      hr += 1break;
146         case 2 : if(min == 59)
147                      min = 0;
148                  else
149                      min += 1break;
150         case 3 : if(brigh_state == brigh_top)
151                      brigh_state = 0;
152                  else
153                      brigh_state += 1;
154                  brigh_update = 1break;
155     }//switch
156     set_update = 0;
157 }
158
159 //menu_state = 0 - IDLE
160 void menu_0(){
161     digit_1 = num_to_digit(hr / 10);
162     digit_2 = num_to_digit(hr % 10) | 0b01000000;
163     digit_3 = num_to_digit(min / 10);
164     digit_4 = num_to_digit(min % 10) | 0b01000000;
165     digit_5 = num_to_digit(sec / 10);
166     digit_6 = num_to_digit(sec % 10) | 0b01000000;
167 }
168
169 //menu_state = 1 - NASTAVENI HODIN
170 void menu_1(){
171     digit_1 = num_to_digit(hr / 10);
172     digit_2 = num_to_digit(hr % 10) | 0b01000000;
173     digit_3 = dDASH;
174     digit_4 = dDASH;
175     digit_5 = dDASH;
176     digit_6 = dDASH;
177 }
178
179 //menu_state = 2 - NASTAVENI MINUT
180 void menu_2(){
181     digit_1 = dDASH;
182     digit_2 = dDASH;
183     digit_3 = num_to_digit(min / 10);
184     digit_4 = num_to_digit(min % 10) | 0b01000000;
185     digit_5 = dDASH;
186     digit_6 = dDASH;
187 }
188
189 //menu_state = 3 - NASTAVENI JASU
190 void menu_3(){
191     digit_1 = dJ;
192     digit_2 = dA;
193     digit_3 = dS;
194     digit_4 = dNULL;
195     switch(brigh_state){
196         case 0 : digit_5 = d0;
197                  digit_6 = d0; break;
198         case 1 : digit_5 = d0;
199                  digit_6 = d1; break;
200         case 2 : digit_5 = d1;
201                  digit_6 = d0; break;
202         case 3 : digit_5 = d1;
203                  digit_6 = d1; break;
204     }//switch
205 }
206
207 //menu_state = 4 - BEZICI TEXT
208 void menu_4(){
209     switch(sec % 6){
210         case 0 : digit_1 = dDASH;
211                  digit_2 = dDASH;
212                  digit_3 = dDASH;
213                  digit_4 = db;
214                  digit_5 = dY;
215                  digit_6 = dE; break;
216         case 1 : digit_1 = dDASH;
217                  digit_2 = dDASH;
218                  digit_3 = db;
219                  digit_4 = dY;
220                  digit_5 = dE;
221                  digit_6 = dDASH; break;
222         case 2 : digit_1 = dDASH;
223                  digit_2 = db;
224                  digit_3 = dY;
225                  digit_4 = dE;
226                  digit_5 = dDASH;
227                  digit_6 = dDASH; break;
228         case 3 : digit_1 = db;
229                  digit_2 = dY;
230                  digit_3 = dE;
231                  digit_4 = dDASH;
232                  digit_5 = dDASH;
233                  digit_6 = dDASH; break;
234         case 4 : digit_1 = dY;
235                  digit_2 = dE;
236                  digit_3 = dDASH;
237                  digit_4 = dDASH;
238                  digit_5 = dDASH;
239                  digit_6 = db; break;
240         case 5 : digit_1 = dE;
241                  digit_2 = dDASH;
242                  digit_3 = dDASH;
243                  digit_4 = dDASH;
244                  digit_5 = db;
245                  digit_6 = dY; break;
246     }//switch
247 }
248
249 //menu_state = 5 - VLNKY
250 void menu_5(){
251     switch((time_cnt / 15) % 4){
252         case 0 : digit_1 = dBOTTOM;
253                  digit_2 = dDASH;
254                  digit_3 = dTOP;
255                  digit_4 = dDASH;
256                  digit_5 = dBOTTOM;
257                  digit_6 = dDASH; break;
258         case 1 : digit_1 = dDASH;
259                  digit_2 = dTOP;
260                  digit_3 = dDASH;
261                  digit_4 = dBOTTOM;
262                  digit_5 = dDASH;
263                  digit_6 = dTOP; break;
264         case 2 : digit_1 = dTOP;
265                  digit_2 = dDASH;
266                  digit_3 = dBOTTOM;
267                  digit_4 = dDASH;
268                  digit_5 = dTOP;
269                  digit_6 = dDASH; break;
270         case 3 : digit_1 = dDASH;
271                  digit_2 = dBOTTOM;
272                  digit_3 = dDASH;
273                  digit_4 = dTOP;
274                  digit_5 = dDASH;
275                  digit_6 = dBOTTOM; break;
276     }//switch
277 }
278
279 //menu_state = 6 - BINARNI SEKUNDOVKA
280 void menu_6(){
281     char temp = sec;
282     digit_6 = num_to_digit(temp % 2);
283     temp  /= 2;
284     digit_5 = num_to_digit(temp % 2);
285     temp  /= 2;
286     digit_4 = num_to_digit(temp % 2);
287     temp  /= 2;
288     digit_3 = num_to_digit(temp % 2);
289     temp  /= 2;
290     digit_2 = num_to_digit(temp % 2);
291     temp  /= 2;
292     digit_1 = num_to_digit(temp % 2);
293     temp  /= 2;
294 }
295
296 int main(void ){
297     
298     //globalni preruseni
299     sei();
300     
301     //preruseni pro tlacitka
302     GICR |= (1 << INT1)|(1 << INT0);    //external interrupt
303     MCUCR |= (1 << ISC01)|(1 << ISC11);    //falling edge
304     
305     //preruseni citace OC0 - multiplex
306     TIMSK |= (1 << TOIE0);
307     
308     //preruseni citace OC2 - casomira
309     TIMSK |= (1 << TOIE2);
310     
311     //nastaveni citace 0C0 - multiplex
312     TCCR0 |= (1 << CS00)|(1 << CS01);    //prescaler 64
313
314     //nastaveni citace OC1A - PWM
315     TCCR1A |= (1 << COM1A1);            //set at bottom, clear on match
316     TCCR1A |= (1 << WGM10);                //fast PWM 8-bit
317     TCCR1B |= (1 << WGM12);
318     TCCR1B |= (1 << CS10);                //no prescaler
319     
320     //nastaveni citace 0C2 - casomira
321     TCCR2 |= (1 << CS22)|(1 << CS21);    //prescaler 256
322     
323     //inicializece portu - celkem 16 vystupnich pinu
324     DDRA = 0b11111111;
325     DDRB = 0b00001111;
326     DDRC = 0b00000000;
327     DDRD = 0b11110000;
328     
329     //zhaveni (PB2), pull-up na INT0 (PD2), INT2 (PD3) a PWM (PD5)
330     PORTB = 0b00000100;
331     PORTD = 0b00101100;
332     
333     while(1){
334         //...externi aktualizace - tlacitko SET
335         if (set_update == 1){
336             set_init();
337         }
338
339         //...nastaveni PWM
340         if(brigh_update == 1){
341             switch(brigh_state){
342                 case 0 : OCR1AL = 102break;    //...2/5 Ucc
343                 case 1 : OCR1AL = 154break;    //...3/5 Ucc
344                 case 2 : OCR1AL = 205break;    //...4/5 Ucc
345                 case 3 : OCR1AL = 255break;    //...Ucc
346             }//switch
347             brigh_update = 0;
348         }
349
350         //...interni aktualizace - cas
351         if (time_update == 1){
352             time_init();
353         }
354         
355         //...sestaveni displeje
356         switch(menu_state){
357             case 0 : menu_0(); break;    //IDLE
358             case 1 : menu_1(); break;    //NASTAVENI HODIN
359             case 2 : menu_2(); break;    //NASTAVENI MINUT
360             case 3 : menu_3(); break;    //NASTAVENI JASU
361             case 4 : menu_4(); break;    //BEZICI TEXT - ukazka
362             case 5 : menu_5(); break;    //VLNY - ukazka
363             case 6 : menu_6(); break;    //BINARNI SEKUNDOVKA - ukazka
364         }//switch
365
366         //...multiplex
367         switch(mpx_state){
368             case 1: PORTB &= ~0b00000010;    //vypnuti katody 6. zobrazovace
369                     PORTD |= 0b10000000;    //zapnuti katody 1. zobrazovace
370                     PORTA = digit_1; break;    //odeslani znaku
371             case 2: PORTD &= ~0b10000000;    //...
372                     PORTD |= 0b01000000;
373                     PORTA = digit_2; break;
374             case 3: PORTD &= ~0b01000000;
375                     PORTB |= 0b00001000;
376                     PORTA = digit_3; break;
377             case 4: PORTB &= ~0b00001000;
378                     PORTD |= 0b00010000;
379                     PORTA = digit_4; break;
380             case 5: PORTD &= ~0b00010000;
381                     PORTB |= 0b00000001;
382                     PORTA = digit_5; break;
383             case 6: PORTB &= ~0b00000001;
384                     PORTB |= 0b00000010;
385                     PORTA = digit_6; break;
386         }
387     }//while
388
389 }//main
390