/* xtimer1.c 2-channel timer and Clock Timer1 Timer2 HOUR MIN __ __ __ __ __ __ __ __ |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| 0-99min 0-99min 0-23 0-59 key1 Key2 Key3 Key4 The xtimer1.c is firmware for xtimer board. The timer has beend developed for my wife kitchen. The first version used MAX7219 for LED driver. This version uses cheap CMOS shift regsiter, 4094 driving the LED The hardware schematic and details can get from http://www.kmitl.ac.th/~kswichit/xtimer/new_xtimer1.html Copyright(c) 2006 Wichit Sirichote kswichit@kmitl.ac.th This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. */ #include char cputick; char command; char timer1,timer2,timer3,timer4,timer5,load_timer5,load_timer6,timer6; unsigned int timer1_clk,timer2_clk,timer3_clk,timer4_clk; unsigned char timer7; unsigned char blink1,blink2,blink3,blink4,one_sec; unsigned char index1,index2,index3,index4,index5,index6; unsigned char flag1,flag2,key,ACCU,temp,buzzer1,buzzer2; unsigned char i,column,buffer[8],t[5]; char delay,count1; unsigned char sec100,sec,min,hour; unsigned int count; unsigned char code busy_pattern[4]= {1,20,0,100}; // on 20ticks, off 100ticks unsigned char code busy_pattern2[4]= {1,20,0,20}; // on 20ticks, off 20ticks unsigned int Time,temp16; //int PGM; /* signed PGM 0-499 */ char code preset_timer1[] = {-1,0,3,5,10,15,20,25,30,0}; char code preset_timer2[] = {-1,0,3,5,10,15,20,25,30,0}; char code preset_timer3[] = {-1,0,1,2,3,5,8,9,10,11,12,13,14,0}; char code preset_timer4[] = {-1,0,3,5,10,15,20,25,30,0}; sbit CLK = P1^7; sbit DIN = P1^6; sbit strobe = P1^5; sbit output1 = P1^1; sbit output2 = P1^2; sbit output3 = P1^3; sbit output4 = P1^4; sbit buzzer = P3^0; sbit xbuzzer = P3^1; sbit key1 = P3^2; sbit key2 = P3^3; sbit key3 = P3^4; sbit key4 = P3^5; #define on 0 #define off 1 /* mask byte of flag1 for bit testing */ #define mode 0x40 /* swap number entry mode */ #define disabling_key 0x80 /* disable consecutive key pressing */ // prototype declaration void blink_timer1(); void blink_timer2(); void blink_timer3(); void blink_timer4(); char code convert[10] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; // LED pattern for 0 1 2 3 4 5 6 7 8 9 void clock() /* update real-time clock */ { sec100++; if (sec100 >= 100) /* 100 * 10 ms = 1 s */ {sec100 = 0; sec++; if (sec >= 60) {sec = 0; min++; if (min >= 60) {min = 0; hour++; if (hour >= 24) {hour = 0; } } } } } // write 64-bit data to 4094 x 8, COMS shift regsiter // The output of each register was tied to common chathod 7-segment LED // data was shifted with rising edge, 0-to-1 CLK signal // all bits are sent to the output with 1-to-0 STROBE signal void write_led() { char i,j; for(j=0; j<8; j++) { for(i=0;i<8; i++) { if(buffer[j]&0x80) DIN = 1; // set bit data line else DIN=0; // clear bit data line CLK= 1; // make clock high buffer[j] <<=1; // shift 1 bit left CLK = 0; // make clock low } } strobe = 1; // make strobe high ; strobe = 0; // then low } void blink() { if(flag1&0x02) blink_timer1(); if(flag1&0x08) blink_timer2(); blink_timer3(); if(flag1&0x20) blink_timer4(); } offmsd() // turn msd off { if (buffer[3] == 0x3f) buffer[3] = 0x00; if (buffer[5] == 0x3f) buffer[5] = 0x00; if (buffer[7] == 0x3f) buffer[7] = 0x00; } void moveTimetoBuffer() /* convert 8-bit binary to 7-segment 8-digit */ { if(timer1 != -1) { buffer[7] = convert[timer1/10]; buffer[6] = convert[timer1%10]; if(flag2&0x01) buffer[6] |= 0x80; else buffer[6] &= ~0x80; } else { buffer[7]=buffer[6]= 0x40; } if(timer2 != -1) { buffer[5] = convert[timer2/10]; buffer[4] = convert[timer2%10]; if(flag2&0x02) buffer[4] |= 0x80; else buffer[4] &= ~0x80; } else { buffer[5]=buffer[4]= 0x40; } buffer[3] = convert[hour/10]; buffer[2] = convert[hour%10]; if(flag2&0x04) buffer[2] |= 0x80; else buffer[2] &= ~0x80; buffer[1] = convert[min/10]; buffer[0] = convert[min%10]; offmsd(); // turn off msd, e.g. 09 to 9, say } updatedisplay() { moveTimetoBuffer(); blink(); write_led(); } // timer functions run every one second void run_timer1(void) { if(timer1 != -1) { if(timer1 != 0) { timer7 = 0; // reset timeout buzzer1 = 0; flag1 |= 0x02; output1=1; if(++timer1_clk >= 60) // timer1 is one min based! { timer1_clk = 0; timer1--; } } else // timer1 == 0 then fire output { output1=0; // fire output1 buzzer1 = 1; flag1 &= ~0x02; flag2 &= ~0x01; } } else { flag1 &= ~0x02; // no blink when timer1 == -1 flag2 &= ~0x01; buzzer1 = 0; } } void run_timer2() { if(timer2 != -1) { if(timer2 != 0) { timer7 = 0; buzzer2 = 0; flag1 |= 0x08; output2=1; if(++timer2_clk >= 60) //timer2 is one min based! { timer2_clk = 0; timer2--; } } else // timer2 == 0 then fire output { output2=0; // fire output1 // putch('2'); buzzer2 = 1; flag1 &= ~0x08; flag2 &= ~0x02; } } else { flag1 &= ~0x08; // no blink when timer1 == -1 flag2 &= ~0x02; buzzer2 = 0; } } run_timer() { if(++one_sec>=100) { one_sec = 0; run_timer1(); run_timer2(); } } // reload preset time value from preset array for each key pressed void set_timer() { if((flag1&1) == 0) // enter only when keys have been released { if(!key4) // if key 1 has been pressed { flag1 |= 1; if(index1>=10) index1 =0; timer1= preset_timer1[index1++]; } if(!key3) { flag1 |= 1; if(index2>=10) index2 =0; timer2= preset_timer2[index2++]; } if(!key2) { flag1 |= 1; if(++hour >=24) {hour = 0; sec =0; sec100 =0; } } if(!key1) { flag1 |= 1; if(++min >=60) { min =0; sec=0; sec100 = 0; } } } } void key_release() { if((P3&0x3c) == 0x3c) flag1 &= ~1; } void blink_timer1() { ++blink1; if(blink1 >= 20) flag2 &= ~0x01; if( blink1 >= 100) { flag2 |= 0x01; blink1 = 0; } } void blink_timer2() { ++blink2; if(blink2 >= 50) flag2 &= ~0x02; if( blink2 >= 100) { flag2 |= 0x02; blink2 = 0; } } void blink_timer3() { ++blink3; if(blink3 >= 50) flag2 &= ~0x04; if( blink3 >= 100) { flag2 |= 0x04; blink3 = 0; } } void blink_timer4() { ++blink4; if(blink4 >= 50) flag2 &= ~0x08; if( blink4 >= 100) // <-- change for minute based blinking! { flag2 |= 0x08; blink4 = 0; } } void enable_buzzer(char i){ if (i) buzzer=0; else buzzer=1; } void enable_buzzer2(char i){ if (i) xbuzzer=0; else xbuzzer=1; } void counting_down2(char j){ timer5--; if (timer5 == 0){ index5+=2; if (index5 >= j) index5 = 0; load_timer5 = 0; } } void counting_down3(char j){ timer6--; if (timer6 == 0){ index6+=2; if (index6 >= j) index6 = 0; load_timer6 = 0; } } void ring1() { if (buzzer1){ if(load_timer5 == 0){ enable_buzzer(busy_pattern[index5]); // on or off bit timer5 = busy_pattern[index5+1]; // get duration load_timer5 = 1; // one time only } counting_down2(4); } else buzzer=1; } void ring2() { if (buzzer2){ if(load_timer6 == 0){ enable_buzzer2(busy_pattern2[index6]); timer6 = busy_pattern2[index6+1]; load_timer6 = 1; } counting_down3(4); } else xbuzzer=1; } // enter timer interrupt every 10ms void timer_isr(void) interrupt 1 using 1 { TH0 |= 0xb1; // reload value with 8MHz Xtal TL0 |= 0xe0; cputick++; clock(); // update realtime clock set_timer(); run_timer(); key_release(); updatedisplay(); ring1(); ring2(); } main() { flag1 = flag2 = 0; P1 = P3 = 0xFF; TMOD = 0x01; // timer0 mode 1 EA = ET0 = TR0 = 1; // enable timer0 interrupt, start timer timer1= timer2=timer3=timer4 =-1; timer1_clk=timer2_clk=timer3_clk=timer4_clk=0; index1=index2=index3=index4=index5=index6=0; load_timer5 = load_timer6=0; buzzer1=buzzer2=0; timer7 = 0; for(;;) ; }