// 白黒オーバレイ電光掲示板(16×16×5文字, ATtiny85, Fck=20MHz) // 2007.7.6 koyama@cc.hirosaki-u.ac.jp #include #include #include #include #define T1000 61 #define Fck 20 #define VS 218 #define HS 16 #define SYN 0x00 #define BLK 0x01 #define GRY 0x02 #define WHT 0x03 #define SCREEN_W 80 #define SCREEN_H 16 #define LINEtop 168 #define LINEdup 4 #define LINEext (LINEtop+SCREEN_H*LINEdup) #define FONT_W 8 #define FONT_H 16 #define nop() asm volatile("nop"::) #include "font.c" // 8x16および16×16のフォント #define pxl(x) {if(x){PORTB=WHT;nop();nop();nop();nop();}else{PORTB=BLK;nop();nop();nop();nop();nop();}} #define pxl8(x) {pxl(x&0x80); pxl(x&0x40); pxl(x&0x20); pxl(x&0x10); pxl(x&0x08); pxl(x&0x04); pxl(x&0x02); pxl(x&0x01);} prog_uint8_t *q; // mesのポインタ uint8_t swcntr=0; // SWのチャタリング防止カウンタ uint8_t overlay; // overlay=0...SGEN , 1...Overlay uint8_t mmode=NMES+1; // 表示モード(初めは連続表示モード) uint8_t imes=0; // 表示中のメッセージ番号 uint8_t mescnt; // mes表示回数 // (SCREEN_W+8)×SCREEN_Hドットvramとポインタ(ただしTV表示はSCREEN_W×SCREEN_H) uint8_t vram[(SCREEN_W/8+2)*SCREEN_H]; // (SCREEN_W+16)×SCREEN_Hドット uint8_t pcntr=0; // ポーズカウンタ uint8_t dcntr=0; // ドットカウンタ void setc(){ // 次の文字のフォントをvramにセット uint8_t i,j,c; uint16_t v; c=pgm_read_byte(q++); // cはmesの次の文字コード if(c==255){ // 文字列の終わり if(pgm_read_byte(&patt[imes])&1!=0) pcntr=T1000; // 行末でポーズ if(NMES>1 && mmode==NMES+1){// 2以上の連続表示モードならimesを更新 if(++imes==NMES){ imes=0; if(pcntr==0) mescnt++; // mes表示回数更新 } }else if(pcntr==0) mescnt++; // mes表示回数更新 q=(prog_uint8_t *)mes[imes]; c=pgm_read_byte(q++); } i=SCREEN_W/8; if(c<0x80){ // 8x16ドットフォント dcntr=8; for(j=0;j>8; vram[i+1]=v&0xff; } } } ISR(TIM1_COMPA_vect){ if(swcntr==0 && overlay){//SWoffでOverlayで0.1秒間Csyncが無ければSGENにする overlay=0; OCR1A=OCR1C=64*Fck/8-1; TCCR1=0x84; // 159(64us), CK/8 } } ISR(INT0_vect){TCNT1=0;} // Csyncで検出用タイマーをリセット int main (void){ uint8_t b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10, i,j,k; uint8_t line=0; // 走査線カウンタで64us毎にカウントアップ uint8_t fcntr=0; // フレームカウンタ uint8_t S=0; // スイッチ操作に伴う状態 uint8_t *p; // vram[]のポインタ PORTB=0x00; DDRB=0x03; // xxxxxioo DDRB=0x00/0x03 TCCR0B=0x02; // CK/8...TCNT0==80〜160(64us) // overlay=0; OCR1A=OCR1C=64*Fck/8-1; TCCR1=0x84; // 159(64us), CK/8 overlay=1; OCR1A=OCR1C=122; TCCR1=0x8f; // 16384/Fck*122=0.1秒 q=(prog_uint8_t *)mes[imes]; TIMSK=(1<0 && --swcntr==0){ // SWを離して16.3ms後 for(i=0;i<(SCREEN_W/8+2)*SCREEN_H;i++) vram[i]=0;// vramクリヤ if(++mmode>NMES+1 || NMES==1 && mmode==2) imes=mmode=0;// mes[0]の単一表示 else if(mmode==NMES){ // 表示オフ while(PINB&0x04); // SWonを待つ swcntr=255; imes=0; // wakeup後はmes[0]から連続表示 }else if(mmode==NMES+1) imes=0; // mes[0]からの連続表示 else imes=mmode; // mes[mmode]の単一表示 q=(prog_uint8_t *)mes[imes]; mescnt=0; } PORTB&=0xfb; for(i=0;i<6;i++) nop(); // pull up off if(overlay) GIMSK=(1<=LINEtop && line0){ nop();nop();nop();nop();nop();nop();} else if(fcntr&1){ nop();nop();nop();} // スムーズスクロール else{ nop();nop();nop();nop();nop();nop();nop();nop();} PORTB=BLK; // ****ここから表示**** b0=*p; b1=*(p+1);b2=*(p+2);b3=*(p+3);b4=*(p+4); b5=*(p+5); b6=*(p+6);b7=*(p+7);b8=*(p+8);b9=*(p+9); pxl8(b0);pxl8(b1);pxl8(b2);pxl8(b3);pxl8(b4); pxl8(b5);pxl8(b6);pxl8(b7);pxl8(b8);pxl8(b9); PORTB=BLK; // ****ここまで表示**** if(line%LINEdup==LINEdup-1) p+=(SCREEN_W/8+2); // ライン重複 }else if(line==LINEext) p=vram; else if(line>LINEext && line<=LINEext+SCREEN_H && pcntr==0 && dcntr>0 && fcntr&1){ b0=*p; b1=*(p+1);b2=*(p+2);b3=*(p+3);b4=*(p+4); b5=*(p+5); b6=*(p+6);b7=*(p+7);b8=*(p+8);b9=*(p+9); b10=*(p+10);i=*(p+11); b0<<=1; if(b1&0x80) *p++=b0|1; else *p++=b0;// vramスクロール b1<<=1; if(b2&0x80) *p++=b1|1; else *p++=b1; b2<<=1; if(b3&0x80) *p++=b2|1; else *p++=b2; b3<<=1; if(b4&0x80) *p++=b3|1; else *p++=b3; b4<<=1; if(b5&0x80) *p++=b4|1; else *p++=b4; b5<<=1; if(b6&0x80) *p++=b5|1; else *p++=b5; b6<<=1; if(b7&0x80) *p++=b6|1; else *p++=b6; b7<<=1; if(b8&0x80) *p++=b7|1; else *p++=b7; b8<<=1; if(b9&0x80) *p++=b8|1; else *p++=b8; b9<<=1; if(b10&0x80)*p++=b9|1; else *p++=b9; b10<<=1;if(i&0x80) *p++=b10|1; else *p++=b10; *p++=(i<<1); }else if(line==LINEext+SCREEN_H+1 && pcntr==0){ if(dcntr>0 && fcntr&1) dcntr--; if(dcntr==0) setc(); }else if(line==LINEext+SCREEN_H+2){ fcntr++; if(pcntr>0 && --pcntr==0){ for(i=k=0;i