// カラー表示発表会用タイマー(Fck=14.32MHz) // 4/14.32 * 228 * 249 * 63 =0.999s...1000秒に1秒程度進む // 2007.6.11 koyama@cc.hirosaki-u.ac.jp #include #include #include #include #include #define Fck 14.32 #define VS 156 #define HS 10 #define SYN 0x04 #define BLK 0x05 #define GRY 0x06 #define WHT 0x07 #define SCl 0x04 #define SCh 0x06 #define YEl 0x06 #define YEh 0x07 #define CYl 0x05 #define CYh 0x07 #define GRl 0x05 #define GRh 0x07 #define MAl 0x05 #define MAh 0x07 #define REl 0x05 #define REh 0x07 #define BLl 0x05 #define BLh 0x06 #define nop() asm volatile("nop"::) #define sc(a,b) {PORTB=a;PORTB=a; PORTB=b;PORTB=b;} #define sc8(a,b) {sc(a,b);sc(a,b);sc(a,b);sc(a,b);sc(a,b);sc(a,b);sc(a,b);sc(a,b);} //#define pxl(x,r1,r2) asm volatile("rol %0\n\t" \ // "out 0x18,%1\n\t"\ // "brcc L_%=\n\t" \ // "out 0x18,%2\n\t"\ // "L_%=:" \ // : \ // : "a" (x), "a" (r1), "a" (r2) ) #define pxl(x,r1,r2) asm volatile("rol %0\n\t" \ "out 0x18,%1\n\t"\ "brcc L1_%=\n\t" \ "out 0x18,%2\n\t"\ "L1_%=: nop\n\t" \ "out 0x18,%1\n\t"\ "brcc L2_%=\n\t" \ "out 0x18,%2\n\t"\ "L2_%=:" \ : \ : "a" (x), "r" (r1), "r" (r2) ) #define pxl8(x) {pxl(x,blk,wht);pxl(x,blk,wht);pxl(x,blk,wht);pxl(x,blk,wht);pxl(x,blk,wht);pxl(x,blk,wht);pxl(x,blk,wht);pxl(x,blk,wht);} #define SCREEN_W 64 #define SCREEN_H 24 #define LINEtop 40 #define LINEdup 8 #define LINEext0 (LINEtop+FONT_H*LINEdup) #define LINEext (LINEtop+SCREEN_H*LINEdup) #define FONT_W 16 #define FONT_H 16 #define T_10 51 #define T_7 42 #define T_1 6 uint8_t vram[SCREEN_W/8*SCREEN_H]; // SCREEN_W×SCREEN_Hドットvram uint8_t BZtimer=0; // ブザー音長用カウンタ(正の間ブザーが鳴る) uint8_t bz=0xff; // 64us×35毎にbit2を反転 uint8_t S=0; // スイッチ操作に伴う状態 uint8_t SWcntr=0; // スイッチがOFFで0、ONでカウントアップ uint8_t ss=0, mm=0; // 現在の秒と分の値 uint8_t mm1, mm2, mm3; // 1鈴 2鈴 3鈴の値(分) #include "vlibnum.c" // 4×6と16×16の数字フォント void Strans(){ // スイッチ操作による状態遷移 DDRB=0x03; PORTB|=0x04; if(bit_is_clear(PINB,2)){ if(SWcntr<255) SWcntr++;} // SWon else SWcntr=0; DDRB=0x07; if(S==0 && SWcntr>0){ S=1; BZtimer=T_1;} // ブッ else if(S==1){ if(SWcntr==0) S=2; else if(SWcntr>T_10){ S=4; mm=0;BZtimer=T_1;} // ブッ(1秒後) }else if(S==2 && SWcntr>0){ S=3; BZtimer=T_1;} else if(S==3){ if(SWcntr==0) S=0; else if(SWcntr>T_10){ S=4; mm=0;BZtimer=T_1;} // ブッ(1秒後) }else if(S==4){ ss=0; if(SWcntr==0){ S=0; mm=0; } // リセット else if(SWcntr>T_10*2){ S=5; mm=1;BZtimer=T_1;} // ブッ(2秒後) }else if(S==5){ if(SWcntr==0){ S=6; mm1=mm2=mm3=1;} else if(SWcntr>T_10*3){ S=8; mm=2;BZtimer=T_1;} // ブッ(3秒後) }else if(S==8){ if(SWcntr==0){ S=9; mm2=mm3=mm1;} else if(SWcntr>T_10*4){ S=11; mm=3;BZtimer=T_1;} // ブッ(4秒後) }else if(S==11){ if(SWcntr==0){ S=12; mm3=mm2; } else if(SWcntr>=T_10*5){S=14; mm=0;BZtimer=T_1;} // ブッ(5秒後) }else if(S==6 && SWcntr>0){ S=7; BZtimer=T_1;} // mm1設定モード else if(S==9 && SWcntr>0){ S=10; BZtimer=T_1;} // mm2設定モード else if(S==12 && SWcntr>0){ S=13; BZtimer=T_1;} // mm3設定モード else if(S==7){ //mm1カウントアップ if(SWcntr==0){ S=6; if(mm1<60) mm2=mm3=++mm1;} else if(SWcntr>T_10){ S=14; BZtimer=T_1;} // ブッ }else if(S==10){ //mm2カウントアップ if(SWcntr==0){ S=9; if(mm2<60) mm3=++mm2; } else if(SWcntr>T_10){ S=14; BZtimer=T_1;} // ブッ }else if(S==13){ //mm3カウントアップ if(SWcntr==0){ S=12; if(mm3<60) ++mm3; } else if(SWcntr>T_10){ S=14; BZtimer=T_1;} // ブッ }else if(S==14 && SWcntr==0){ S=0; ss=mm=0; eeprom_busy_wait(); eeprom_write_byte((uint8_t *)0,mm1); eeprom_busy_wait(); eeprom_write_byte((uint8_t *)1,mm2); eeprom_busy_wait(); eeprom_write_byte((uint8_t *)2,mm3); } } ISR(TIM1_COMPA_vect){} // 63.687us int main (void){ uint8_t blk, wht, b0,b1,b2,b3,b4,b5,b6, i; uint8_t line=0; // 走査線カウンタで63.687us毎にカウントアップ uint8_t BZcntr=0; // ブザー音用カウンタで63.687us毎にカウントアップ uint8_t *p; // vram[]のポインタ uint8_t sscntr=0; // 1秒作成用カウンタ PORTB=0x04; DDRB=0x07; // xxxxxooo OCR1A=OCR1C=227; // CTC on OCR1C=228(4/14.32*228=63.687us) TCCR1=0x83; // CK/4 eeprom_busy_wait(); mm1=eeprom_read_byte((uint8_t *)0); eeprom_busy_wait(); mm2=eeprom_read_byte((uint8_t *)1); eeprom_busy_wait(); mm3=eeprom_read_byte((uint8_t *)2); TIMSK=(1<=LINEtop && line=mm3&&sscntr>T_7&&S==2||mm/10==0) Vputc(8,0,' '); else Vputc(8,0,'0'+mm/10); // mmの表示 }else if(line==LINEext+2){ if(mm>=mm3&&sscntr>T_7&&S==2) Vputc(24,0,' '); else Vputc(24,0,'0'+mm%10); }else if(line==LINEext+3) Vputc4x6(40,8,'0'+ss/10);// ssの表示 else if(line==LINEext+4) Vputc4x6(44,8,'0'+ss%10); else if(line==LINEext+5){ if(mm1/10==0) Vputc4x6(32,18,' '); // mm1の表示 else Vputc4x6(32,18,'0'+mm1/10); }else if(line==LINEext+6) Vputc4x6(36,18,'0'+mm1%10); else if(line==LINEext+7){ if(mm2==mm1||mm2/10==0) Vputc4x6(44,18,' '); // mm2の表示 else Vputc4x6(44,18,'0'+mm2/10); }else if(line==LINEext+8){ if(mm2==mm1) Vputc4x6(48,18,' '); else Vputc4x6(48,18,'0'+mm2%10); }else if(line==LINEext+9){ if(mm3==mm2||mm3/10==0) Vputc4x6(56,18,' '); // mm3の表示 else Vputc4x6(56,18,'0'+mm3/10); }else if(line==LINEext+10){ if(mm3==mm2) Vputc4x6(60,18,' '); else Vputc4x6(60,18,'0'+mm3%10); }else if(line==LINEext+11&&S==2&&(++sscntr==63)){// 15.86*63=0.999s sscntr=0; if(++ss>=60){ ss=0; ++mm;} if(mm==mm1&&ss==0||mm1!=mm2&&mm==mm2&&ss<=1||mm2!=mm3&&mm==mm3&&ss<=2) BZtimer=T_7; }else if(line==LINEext+12 && BZtimer>0) BZtimer--; } bz=0xff; if(BZtimer && ++BZcntr&0x20) bz=0xfb; // 63.687 * 64=4.076ms(481.7Hz) if(line==249) line=0; // 4/14.32 * 228 * 249 * 63 =0.999s } }