// タイムエイド tiny2313 CLK:4MHz...3V 15mA #include #include #include #include #include #define TIMEOUT 10 #define STOP 0 // S #define ALARM 8 // S(8〜1) #define RUN (ALARM+1) // S #define RUNp (ALARM+2) // S(プロテクトモード) #define T100ms 26 // sel: 0(入力) 1(M10) 2(M1) 3(B0-7) 4(B8-15)5(B16-19) // b6 o o o o o o ... g // b5 r i i i i o(1) // b4 r i i i o(1) i // b3 r(S10) i i o(1) i i // b2 r(STRT) r r r r r // b1 r(M10) o(1) i i i i // b0 r(M1) i o(1) i i i prog_uint8_t DD[]={ 0x40, 0x42, 0x41, 0x48, 0x50, 0x60}; prog_uint8_t PD[]={ 0x7f, 0x06, 0x05, 0x0c, 0x14, 0x24}; uint8_t LEDbuf[]={ 0xf7, 0x00, 0x00, 0xf7, 0xf7, 0xf7}; prog_uint8_t LEDseg[]={ //fedg.cba fedg.cba 0b00010000, 0b11110001, // 0, 1 0b10000100, 0b11000000, // 2, 3 0b01100001, 0b01000010, // 4, 5 0b00000010, 0b01110000, // 6, 7 0b00000000, 0b01000000};// 8, 9 prog_uint8_t BAR[]={ //5436.210 5436.210 0b11110111, 0b11110110, // 0, 1 0b11110100, 0b11110000, // 2, 3 0b11010000, 0b10010000, // 4, 5 0b00010000 }; // 6 uint8_t i, bar=0, sel=0, cntr=0, cntr8=0; uint8_t MM=0, mm=0, SS=0, ss=0; // 分秒 uint8_t S=STOP; // 動作状態 uint8_t be; // BlinkEnable //uint8_t ve, vib; // VibrationEnable, Vibration on/off uint8_t STARTsw=0, M10sw=0, M1sw=0, S10sw=0; uint8_t BZcntr=0; // BZcntr>0の時ブザー音 uint8_t SSdisp=0; // 1の時秒表示 uint8_t SLPcntr=TIMEOUT; // SleepCounter uint16_t SWcntr=0; // SW長押し判定カウンタ uint8_t STARTsw_on(){return (STARTsw>0);} uint8_t M10sw_on(){ return (M10sw>0); } uint8_t M1sw_on(){ return (M1sw>0); } uint8_t S10sw_on(){ return (S10sw>0); } void tone(uint8_t length){ TCCR1A=0xb2; // COM1A:10..加算一致で0, 減算一致で1, 00..使用せず // TCCR1A=(ve?0x32:0xb2); // COM1B:11..加算一致で1, 減算一致で0 BZcntr=length; } void LEDset(){ LEDbuf[1]=pgm_read_byte(&LEDseg[(SSdisp?ss:(ss>0?mm+1:mm))/10]);// D10 LEDbuf[2]=pgm_read_byte(&LEDseg[(SSdisp?ss:(ss>0?mm+1:mm))%10]);// D1 bar=(uint16_t)20-10*((MM-mm)*60+SS-ss)/((MM*60+SS)/2); // if(mm>=50) bar=(uint16_t)20-10*((MM-mm)*60+SS-ss)/((MM*60+SS)/2); // else bar=(uint16_t)20-20*((MM-mm)*60+SS-ss)/(MM*60+SS); //bar:0〜20 if(be==1 && bar>0 && (cntr&0x80)!=0) bar--; // 長押しパワーオンでBLINK if(bar>=14){ LEDbuf[3]=LEDbuf[4]=0x00; LEDbuf[5]=pgm_read_byte(&BAR[bar-14]); }else if(bar>=7){ LEDbuf[3]=0x00; LEDbuf[4]=pgm_read_byte(&BAR[bar-7]); LEDbuf[5]=0xf7; }else{ LEDbuf[3]=pgm_read_byte(&BAR[bar]); LEDbuf[4]=LEDbuf[5]=0xf7; } } SIGNAL(SIG_TIMER0_COMPA){ // 0.5ms int uint8_t x=LEDbuf[sel]; // PORTB=0xe7 | vib; PORTB=0xe7; DDRD=pgm_read_byte(&DD[sel]); PORTD=(pgm_read_byte(&PD[sel])|((x<<2)&0x40)); // PORTB=(x&0xe7) | vib; PORTB=x&0xe7; if((--cntr8 & 0x07)==0){ // 0.5*8=4ms if(SWcntr>0) SWcntr--; // スイッチ長押しカウンタ if(++cntr==250){ // 4ms*250=1s cntr=0; if(S>=RUN){ // RUN, RUNp if(ss>0 && --ss==0 && mm==0) S=ALARM; else if(ss==0 && mm>0){ ss=59; if(--mm==0) SSdisp=1; } }else if(S==STOP && SLPcntr>0) SLPcntr--; }else if(S>0 && S<=ALARM){ // 1〜ALARM(8回) if(cntr==1||cntr==41||cntr==81||cntr==121) tone(T100ms);//ピピピピ if(cntr==121) S--; // vib=((cntr<121)?0x08:0x00); // vibrator on/off } if(BZcntr>0 && --BZcntr==0) TCCR1A=0x02; // ブザー停止 } if(sel==0){ if(bit_is_clear(PIND,2)) STARTsw=20; else if(STARTsw>0) STARTsw--; if(bit_is_clear(PIND,1)) M10sw=20; else if(M10sw>0) M10sw--; if(bit_is_clear(PIND,0)) M1sw=20; else if(M1sw>0) M1sw--; if(bit_is_clear(PIND,3)) S10sw=20; else if(S10sw>0) S10sw--; } LEDset(); sel++; if(S>=RUN){ // RUN, RUNp if(sel>=6)sel=0;// 0(入力)→1(M10)→2(M1)→3(B0-7)→4(B8-15)→5(B16-19) }else{ // STOP, ALARM if(sel>=3)sel=0;// 0(入力)→1(M10)→2(M1) } if(STARTsw>0) STARTsw--; } SIGNAL(SIG_INTERRUPT0){} // External Interrupt Request 0 int main(void){ TCCR0A=2; TCCR0B=2; OCR0A=249; // Timer0: CTC, CK/8...500kHz // PORTB=0xef; DDRB=0xe7; ve=((PINB&0x08)?0:1);// VibrationEnable PORTB=0xe7; DDRB=0xff; TCCR1A=0x02; TCCR1B=0x11; // WGM:1010(PhaseCorrectPWM ICR1), CK/1 ICR1=476; OCR1A=OCR1B=238; TIMSK=_BV(OCIE0A); sei(); for(;;){ if(STARTsw_on()){ // スタートSWが押されたら if(S==STOP && (ss>0||mm>0)){ // STOPで設定あれば for(SWcntr=250*3;STARTsw_on()&&SWcntr>0;); if(SWcntr==0){ // 3秒以上長押しなら tone(T100ms); // ピッ! while(STARTsw_on()); // 開放を待って S=RUNp; // RUNp }else S=RUN; // 短押しならRUN sel=0; cntr=0; }else{ // RUN, RUNp, ALARMならば for(SWcntr=250*3;STARTsw_on()&&SWcntr>0;); if(SWcntr==0){ // 3秒以上長押しなら tone(T100ms); // ピッ! while(STARTsw_on()); // 開放を待って S=STOP; // vib=0x00; // vibrator off }else if(S<=RUN){ S=STOP; // 短押しならRUN,ALARM→STOP // vib=0x00; } } SLPcntr=TIMEOUT; }else if(S10sw_on()){ // S10swが押されたら while(S10sw_on()); // 開放を待つ if(S==STOP){ // 時間設定はSTOP状態で SS=ss=(SSdisp?(ss+10)-ss%10:10); MM=mm=0; if(ss>=100) SS=(ss-=100); SSdisp=1; } SLPcntr=TIMEOUT; }else if(M1sw_on()){ // M1swが押されたら while(M1sw_on()); // 開放を待つ if(S==STOP){ // 時間設定はSTOP状態で SSdisp=0; SS=ss=0; if(mm==99) MM=mm=0; else MM=++mm; } SLPcntr=TIMEOUT; }else if(M10sw_on()){ // M10swが押されたら while(M10sw_on()); // 開放を待つ if(S==STOP){ // 時間設定はSTOP状態で SSdisp=0; SS=ss=0; if(mm==99) MM=mm=0; else if(mm>=90) MM=mm=99; else MM=(mm+=10); } SLPcntr=TIMEOUT; }else if(SLPcntr==0){ // SLEEPモードへ TIMSK=0x00; PORTB=0x00; DDRB=0x00; PORTD=0x04; DDRD=0x00; GIMSK=_BV(INT0); // enable Ext SW set_sleep_mode(_BV(SM0)); sleep_mode(); // PowerDown mode GIMSK=0; PORTB=0xe7; DDRB=0xff; // WakeUp SS=ss=MM=mm=SSdisp=0; SLPcntr=TIMEOUT; TIMSK=_BV(OCIE0A); while(!STARTsw_on()); // スタートSWが押されるのを待つ for(SWcntr=250;STARTsw_on()&&SWcntr>0;); // 開放を待つ if(SWcntr==0){ // 1秒以上長押しなら be=1; // BlinkEnable tone(T100ms); // ピッ! while(STARTsw_on()); // 開放を待って }else be=0; } } }