1: #include 2: #include 3: 4: static const code unsigned char digits[10] = 5: { 6: 0x5F, /* 0 */ 7: 0x06, 8: 0x3B, 9: 0x2F, /* 3 */ 10: 0x66, 11: 0x6D, 12: 0x7D, 13: 0x07, /* 7 */ 14: 0x7F, 15: 0x6F, 16: }; 17: static const code unsigned char wave[] = 18: { 19: 1,1,0,1,1,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1 20: }; 21: 22: #define TOUT 0x10 // watchdog timeout bit in STATUS 23: #define XTAL 4000000 // crystal freq 24: #define PRE 4 // prescaler value 25: #define INTVL 1000u // 1000uS (1mS) per loop 26: 27: #define DIVIDE (XTAL/PRE/INTVL/4) // division ratio - must be < 256 28: #define SECS(x) ((x)*1000000/INTVL/21) // convert secs to outer loop count 29: 30: #define DEBOUNCE 10 // debounce 10mS 31: #define COUNT 40 // this many debounce intervals to do something 32: #define CYCLES sizeof(wave) // this many cycles per "tick" 33: #define PWRDOWN 30 // power down time 34: 35: persistent static unsigned char rate; // current rate 36: static bit btn_1, btn_2; // push buttons 37: static bit spkr; // speaker bit 38: static bit counting; // we are counting up or down 39: static bit fast; // we are counting fast! 40: static bit display; // display on 41: 42: main() 43: { 44: unsigned char digcnt, // digit counter 45: segcnt, // segment counter 46: debounce, // debounce timer 47: button, // button press timer 48: cntcnt, // counter timer for speed up 49: beep_cnt, // beep timer 50: curval; // current value 51: 52: unsigned int tick_cnt, // delay timer 53: powerdown, // powerdown timer 54: tock_cnt; // tick-tock reload value 55: 56: OPTION = 1; 57: PORT_A = 0x0F; // set all bits high 58: TRIS_A = ~0x0F; // bits 0-3 are output 59: PORT_B = 0x80; // set bits low 60: TRIS_B = ~0x7F; // bits 0-6 are output 61: PORT_A &= ~3; // enable both buttons 62: btn_1 = 0; 63: btn_2 = 0; 64: if((STATUS & TOUT)) { // power on-reset? 65: rate = 60; // initialize rate 66: beep_cnt = CYCLES; 67: display = 1; 68: powerdown = SECS(PWRDOWN); 69: } else { // watchdog reset 70: if(PORT_B & 0x80) { // no buttons pressed - back to sleep 71: TRIS_A = 0xFF; // hi-Z all pins 72: TRIS_B = 0xFF; 73: OPTION = 0xB; // WDT prescaled by 8 - about 150 ms 74: asm(" sleep"); 75: } 76: display = 1; 77: powerdown = SECS(PWRDOWN); 78: } 79: spkr = 0; 80: debounce = 0; 81: button = 0; 82: counting = 0; 83: tock_cnt = (unsigned)(60*1000000/INTVL)/rate; 84: tick_cnt = tock_cnt; 85: for(;;) { 86: if(powerdown) 87: if(--powerdown == 0) { 88: display = 0; 89: if(!spkr) { 90: TRIS_A = 0xFF; // hi-Z all pins 91: TRIS_B = 0xFF; 92: OPTION = 0xB; // WDT prescaled by 8 - about 150 ms 93: asm(" sleep"); 94: } 95: } 96: curval = rate; 97: digcnt = 0; 98: do { 99: segcnt = 1; // least sig. segment 100: do { 101: asm(" clrwdt"); 102: while((RTCC & 0x80) == 0) // sync with RTCC 103: continue; 104: if(beep_cnt && wave[--beep_cnt]) 105: PORT_A ^= 0x8; // toggle speaker bit 106: while(RTCC & 0x80) 107: continue; 108: RTCC = -DIVIDE; // reprogram RTCC 109: if(--tick_cnt == 0) { 110: tick_cnt = tock_cnt; 111: if(spkr) 112: beep_cnt = CYCLES; 113: } 114: if(beep_cnt && wave[--beep_cnt]) 115: PORT_A ^= 0x8; // toggle speaker bit 116: PORT_A |= 0x7; // all digits off 117: PORT_A &= ~(1 << digcnt); // enable one digit 118: PORT_B = 0x80; // all segments off 119: if(display) 120: PORT_B |= segcnt & digits[curval % 10]; // convert digit to seg pattern 121: segcnt <<= 1; 122: if(digcnt == 0 && !btn_2) { // scan button 1 123: if((PORT_B & 0x80) == 0) { 124: if(!btn_1) { 125: debounce = 0; 126: button = 0; 127: cntcnt = 0; 128: fast = 0; 129: } 130: btn_1 = 1; 131: if(++debounce == DEBOUNCE) { 132: debounce = 0; 133: button++; 134: } 135: display = 1; 136: powerdown = SECS(PWRDOWN); 137: } else { 138: if(!counting && btn_1 && button > 1 && button < COUNT/3) 139: spkr = 0; 140: btn_1 = 0; 141: button = 0; 142: } 143: } else if(digcnt == 1 && !btn_1) { // scan button 2 144: if((PORT_B & 0x80) == 0) { 145: if(!btn_2) { 146: debounce = 0; 147: button = 0; 148: cntcnt = 0; 149: fast = 0; 150: } 151: btn_2 = 1; 152: if(++debounce == DEBOUNCE) { 153: debounce = 0; 154: button++; 155: } 156: display = 1; 157: powerdown = SECS(PWRDOWN); 158: } else { 159: if(!counting && btn_2 && button > 1 && button < COUNT/3) 160: spkr = 1; 161: btn_2 = 0; 162: button = 0; 163: } 164: } 165: if(button >= COUNT/3) { 166: if(fast) { 167: if(btn_1) 168: rate -= 10; 169: else 170: rate += 10; 171: } else { 172: if(btn_1) 173: rate--; 174: else 175: rate++; 176: if(++cntcnt == 5) 177: fast = 1; 178: } 179: if(rate < 10) 180: rate = 10; 181: if(rate > 200) 182: rate = 200; 183: counting = 1; 184: button = 0; 185: } 186: } while(!(segcnt & 0x80)); 187: if(counting && !btn_1 && !btn_2) { 188: tock_cnt = (unsigned)(60*1000000/INTVL)/rate; 189: counting = 0; 190: } 191: curval /= 10; 192: } while(++digcnt != 3); 193: } 194: }