// 信号機 tiny2313 CLK:8MHz #include #include // │⊃ H ⊂│ 車A B 歩 // ○├───┐ │○ 0:0 OffOff HOff // ───┴UUU┘ ├┬─── 1:12秒 BlueRed HRed(Wait) // A B⊂│ 2:4秒 YellowRed HRed(Wait) // ⊂│ 3:1秒 RedRed HRed(Wait) // ┌┐ ⊂│ 4:6秒 RedBlue HBlue // │⊃B └┘ 5:5秒 RedBlue HOff/HBlue // │⊃ 6:1秒 RedBlue HRed // │⊃ A 7:4秒 RedYellow HRed // ──┴┤ ┌∩∩∩┬──── 8:1秒 RedRed HRed // ○│ └───┤○ // #define F_CPU 8000000 #define F_Bzz 500 #define OffOff 0x10 #define BlueRed 0x91 #define YellowRed 0x51 #define RedRed 0x31 #define RedBlue 0x34 #define RedYellow 0x32 #define HOff 0x0f #define HBlue 0x4f #define HRedWait 0x3f #define HRed 0x1f #define T100ms 13 uint8_t i, cntr=0, cntr4=0, t=0; uint8_t Auto=0; S=0; // 動作状態 uint8_t C[]={ // 自動車信号AB OffOff,BlueRed,YellowRed,RedRed,RedBlue,RedBlue,RedBlue,RedYellow,RedRed}; uint8_t H[]={ // 歩行者信号 HOff, HRed, HRed, HRed, HBlue, HBlue, HRed, HRed, HRed}; uint8_t T[]={ // 停留時間 0, 12, 4, 1, 6, 5, 1, 4, 1}; uint8_t MODEsw=0, Hsw=0; uint8_t BZcntr=0; // BZcntr>0の時ブザー音 uint8_t SWcntr=0; // SW長押し判定カウンタ uint8_t MODEsw_on(){return (MODEsw>0);} uint8_t Hsw_on(){ return (Hsw>0); } void tone(uint8_t length){ TCCR1A=0xc2; // COM1A:11..加算一致で1, 減算一致で0 BZcntr=length; } SIGNAL(SIG_TIMER0_COMPA){ // 2ms int if((--cntr4 & 0x03)==0){ // 2*4=8ms if(SWcntr>0) SWcntr--; // スイッチ長押しカウンタ if(++cntr==125){ // 8ms*125=1s cntr=0; if(Auto>0 && t>0 && --t==0){ // タイムアウトで次の状態へ if(++S>8){ S=1; if(Auto==2) Auto=0; } // 歩待機を解除 PORTB=C[S]; PORTD=((Auto==2&&S<=3)?HRedWait:H[S]); t=T[S]; } } if(S==1 && Auto==0 && t==0 && Hsw_on()){ PORTD=HRedWait; t=T[S]; } else if(S==5) PORTD=(cntr<63?HBlue:HOff); // 歩青点滅 if(BZcntr>0 && --BZcntr==0) TCCR1A=0x02; // ブザー停止 } if(bit_is_clear(PIND,0)) MODEsw=40; else if(MODEsw>0) MODEsw--; if(bit_is_clear(PIND,1)) Hsw=40; else if(Hsw>0) Hsw--; } int main(void){ // A B PORTB=C[S]; DDRB=0xef; // BYR-TBYR PORTD=H[S]; DDRD=0x70; // -BWR--HM t=0; TCCR0A=2; TCCR0B=3; OCR0A=249; // Timer0: CTC, CK/64...8us×250=2ms TCCR1A=0x02;TCCR1B=0x12; // WGM:1010(PhaseCorrectPWM ICR1), CK/8 ICR1=F_CPU/8/F_Bzz/2; OCR1A=F_CPU/8/F_Bzz/4;// 500Hz TIMSK=_BV(OCIE0A); sei(); for(;;){ if(MODEsw_on()){ // モードSWが押されたら tone(T100ms); if(Auto>0){ // 自動または歩ならば Auto=0; // 手動へ PORTB=C[S]; PORTD=H[S]; t=0; while(MODEsw_on()); // 開放を待って }else{ // 手動ならば for(SWcntr=125;MODEsw_on()&&SWcntr>0;); if(SWcntr==0){ // 1秒以上長押しなら Auto=1; // 自動へ t=T[S]; tone(T100ms); while(MODEsw_on()); // 開放を待って }else{ if(++S>8) S=1; // 短押しなら次の状態へ PORTB=C[S]; PORTD=H[S]; t=0; } cntr=0; } }else if(Auto==0&&S==1&&Hsw_on()){ // 手動でSが1で歩行者swが押されたら Auto=2; // 歩待機へ PORTD=HRedWait; t=T[S]; // 「おまちください」 while(Hsw_on()); // 開放を待つ } } }