// 2010.2.14 ATmega328P 学会用TVタイマー(Fck=14.32MHz) // 4/14.32 * 228 * 249 * 63 =0.999s...1000秒に1秒程度進む #include #include #include #include #include #define Fck 14.32 #define VS 156 #define HS 10 #define SYN 0x00 #define BLK 0x01 #define GRY 0x02 #define WHT 0x03 #define SCl 0x00 #define SCh 0x02 #define YEl 0x02 #define YEh 0x03 #define CYl 0x01 #define CYh 0x03 #define GRl 0x01 #define GRh 0x03 #define MAl 0x01 #define MAh 0x03 #define REl 0x01 #define REh 0x03 #define BLl 0x01 #define BLh 0x02 #define nop() asm volatile("nop"::) #define sc(a,b) {PORTC=a;PORTC=a; PORTC=b;PORTC=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 0x08,%1\n\t"\ "brcc L1_%=\n\t" \ "out 0x08,%2\n\t"\ "L1_%=: nop\n\t" \ "out 0x08,%1\n\t"\ "brcc L2_%=\n\t" \ "out 0x08,%2\n\t"\ "L2_%=: nop\n\t" \ "out 0x08,%1\n\t"\ "brcc L3_%=\n\t" \ "out 0x08,%2\n\t"\ "L3_%=:" \ : \ : "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 48 #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 S=0; // スイッチ操作に伴う状態 uint8_t ss=0, mm=0, ss0, mm0; // 現在の秒と分の値 uint8_t UP=0; // アップカウントモード uint8_t mm1,mm2,mm3, MM1,MM2,MM3;// 1鈴 2鈴 3鈴の値(分) uint8_t MM1sw=0,MM2sw=0,MM3sw=0,SRTsw=0;// スイッチがOFFで0、ONでカウントアップ #include "vlibnum.c" // 4×6と16×16の数字フォント void Strans1(){ // 16.384ms スイッチ操作による状態遷移 if((PIND&0x07)==0){ // 3つのSW同時押し if(S!=8){ S=8; UP=(UP?0:1); eeprom_busy_wait(); eeprom_write_byte((uint8_t *)0,UP); } }else{ if(bit_is_clear(PIND,0)){ if(MM1sw<255) MM1sw++; }else MM1sw=0; if(bit_is_clear(PIND,1)){ if(MM2sw<255) MM2sw++; }else MM2sw=0; if(bit_is_clear(PIND,2)){ if(MM3sw<255) MM3sw++; }else MM3sw=0; if(bit_is_clear(PIND,3)){ if(SRTsw<255) SRTsw++; }else SRTsw=0; if(S==0){ if(SRTsw>0){ S=1; BZtimer=T_1;} // ブッ else if(MM1sw>0 && mm==0 && ss==0) S=5; else if(MM2sw>0 && mm==0 && ss==0) S=6; else if(MM3sw>0 && mm==0 && ss==0) S=7; }else if(S==1){ if(SRTsw==0) S=2; // スタート! else if(SRTsw>T_10){ S=4; mm=ss=0;BZtimer=T_1;}// リセット! }else if(S==2 && SRTsw>0){ S=3; BZtimer=T_1;} else if(S==3){ if(SRTsw==0) S=0; // ストップ! else if(SRTsw>T_10){ S=4; mm=ss=0;BZtimer=T_1;}// リセット! }else if(S==4 && SRTsw==0 && MM1sw==0 && MM2sw==0 && MM3sw==0) S=0; } } void Strans2(){ // 16.384ms プリセット操作による状態遷移 if(S==5){ // mm1カウントアップ if(MM1sw==0){ S=0; if(mm1<99) mm2=mm3=++mm1;} else if(MM1sw>T_10){S=4; mm2=mm3=mm1=0;} // 長押し }else if(S==6){ // mm2カウントアップ if(MM2sw==0){ S=0; if(mm2<99) mm3=++mm2;} else if(MM2sw>T_10){S=4; mm3=mm2=mm1;} // 長押し }else if(S==7){ // mm3カウントアップ if(MM3sw==0){ S=0; if(mm3<99) ++mm3;} else if(MM3sw>T_10){S=4; mm3=mm2;} // 長押し }else if(S==8){ if((PIND&0x07)==7) S=0; // 3つのSW解除 } } ISR(TIMER0_COMPA_vect){} // 63.687us int main (void){ uint8_t b0,b1,b2,b3,b4,b5, i, blk, wht; uint8_t line=0; // 走査線カウンタで63.687us毎にカウントアップ uint8_t BZcntr=0; // ブザー音用カウンタで63.687us毎にカウントアップ uint8_t *p; // vram[]のポインタ uint8_t sscntr=0; // 1秒作成用カウンタ PORTB=0x00; DDRB=0x02; // xxxxxxox...Audio Bzz PORTC=0x00; DDRC=0x03; // xxxxxxoo...Video DAC PORTD=0x0f; DDRD=0x00; // xxxxrrrr...SW TCCR0A=0x02;TCCR0B=0x02;OCR0A=113; // CTC, CK/8, 8/14.32*(113+1)=63.687us TCCR1A=0x00;TCCR1B=0x09;OCR1A=16272;// CTC, CK/1, Fck*1000000/440/2-1 eeprom_busy_wait(); UP =eeprom_read_byte((uint8_t *)0); eeprom_busy_wait(); mm1=MM1=eeprom_read_byte((uint8_t *)1); eeprom_busy_wait(); mm2=MM2=eeprom_read_byte((uint8_t *)2); eeprom_busy_wait(); mm3=MM3=eeprom_read_byte((uint8_t *)3); TIMSK0=(1<=LINEtop && line=mm3?mm-mm3:(ss?mm3-mm-1:mm3-mm))); if(mm1>0&&mm>=mm3&&sscntr>T_7&&S==2||mm0/10==0) Vputc(8,0,' '); else Vputc(8,0,'0'+mm0/10); // 3鈴オーバーで点滅 }else if(line==LINEext+4){ if(mm1>0&&mm>=mm3&&sscntr>T_7&&S==2) Vputc(24,0,' '); else Vputc(24,0,'0'+mm0%10); }else if(line==LINEext+5){ // ssの表示 ss0=(UP||mm>=mm3?ss:(ss?60-ss:0)); Vputc4x6(40,8,'0'+ss0/10); }else if(line==LINEext+6){ Vputc4x6(44,8,'0'+ss0%10); }else if(line==LINEext+7){ // 1鈴設定値mm1の表示 mm0=(UP?mm1:mm3); if(mm0/10==0) Vputc4x6(16,18,' '); else Vputc4x6(16,18,'0'+mm0/10); }else if(line==LINEext+8){ if(mm0==0) Vputc4x6(20,18,' '); else Vputc4x6(20,18,'0'+mm0%10); }else if(line==LINEext+9){ // 2鈴設定値mm2の表示 mm0=(UP?mm2:mm3-mm1); if(mm2==mm1||mm0/10==0) Vputc4x6(28,18,' '); else Vputc4x6(28,18,'0'+mm0/10); }else if(line==LINEext+10){ if(mm2==mm1) Vputc4x6(32,18,' '); else Vputc4x6(32,18,'0'+mm0%10); }else if(line==LINEext+11){ // 3鈴設定値mm3の表示 mm0=(UP?mm3:mm3-mm2); if(mm3==mm2||mm0/10==0) Vputc4x6(40,18,' '); else Vputc4x6(40,18,'0'+mm0/10); }else if(line==LINEext+12){ if(mm3==mm2) Vputc4x6(44,18,' '); else Vputc4x6(44,18,'0'+mm0%10); }else if(line==LINEext+13&&S==2&&(++sscntr==63)){// 15.86*63=0.999s sscntr=0; if(++ss>=60){ ss=0; if(++mm>=100) mm=0;} if(mm==mm1&&ss==0||mm1!=mm2&&mm==mm2&&ss<=1||mm2!=mm3&&mm==mm3&&ss<=2) BZtimer=T_7; }else if(line==LINEext+14 && BZtimer>0) BZtimer--; } TCCR1A=(BZtimer>0?0x40:0x00); // Bzz on(toggle)/off if(line==249) line=0; // 4/14.32 * 228 * 249 * 63 =0.999s } }