#include #include /* * Doll house security system for the PIC 16C84 */ #define TOUT 0x10 // watchdog timeout bit in STATUS #define XTAL 2000000 // oscillator freq - about 2MHz (RC) #define PRE 4 // prescaler value #define RATE 2000 // 500uS per loop #define TICKS 50 // 50Hz tick timer #define GRACE 5 // 5 secs to open door after pressing bell #define PWROFF 120 // power off after this time of no activity #define DIVIDE (XTAL/PRE/RATE/4) // division ratio - must be < 256 typedef unsigned char uchar; /* * Pin assignments * * Port B * 0 Front door reed switch * 1 Interior light touch sensor * 2 Interior light control (0 = on) * 3 Speaker * 4 Party lights 1 (0 = on) * 5 Party lights 2 * 6 Party lights 3 * 7 Front door pushbutton * * Port A is not used */ #define PORTBIT(adr, bit) ((unsigned)(&adr)*8+(bit)) static bit reed @ PORTBIT(PORTB, 0); static bit touch @ PORTBIT(PORTB, 1); static bit light @ PORTBIT(PORTB, 2); static bit spkr @ PORTBIT(PORTB, 3); static bit part0 @ PORTBIT(PORTB, 4); static bit part1 @ PORTBIT(PORTB, 5); static bit part2 @ PORTBIT(PORTB, 6); static bit bell @ PORTBIT(PORTB, 7); static bit RTIF @ PORTBIT(INTCON, 2); static bit alarm; // alarm has been triggered static bit open; // door already open static bit partying; // lights-a-flashin' static uchar grace; // period to open door static uchar ticktimer; // tick timer static uchar sectimer; // seconds timer static uchar altimer; // alarm timer static uchar partytimer; static uchar flashtimer; // flash timer static uchar powerdowntimer; #define IOBITS_B 0x83 // I/O bits specification static unsigned char spkrcnt; // speaker counter /* * The interrupt routine - the only interrupt source is the timer * so we can assume it caused the interrupt */ void interrupt timer(void) { RTIF = 0; TMR0 = -DIVIDE; if(bell == 0) { powerdowntimer = 0; if(alarm) { alarm = 0; part0 = 1; part2 = 1; } grace = GRACE; ++spkrcnt; spkrcnt &= 7; if(((spkrcnt+1) & spkrcnt) == 0) if(spkr) spkr = 0; else spkr = 1; } else partytimer = 0; if(alarm) { if(powerdowntimer >= 30) { alarm = 0; part0 = 1; part2 = 1; } else { ++altimer; if(altimer & 0x80 || altimer & 1) if(spkr) spkr = 0; else spkr = 1; if(altimer & 0x80) { part0 = 1; part2 = 0; } else { part0 = 0; part2 = 1; } } } if(reed) { if(!open && !grace) { powerdowntimer = 0; alarm = 1; } open = 1; grace = 0; } else open = 0; if(++ticktimer == RATE/TICKS) { ticktimer = 0; if(++sectimer == TICKS) { powerdowntimer++; sectimer = 0; if(++partytimer == 2) { if(partying) { partying = 0; part0 = 1; part1 = 1; part2 = 1; } else { partying = 1; part0 = 0; part1 = 1; part2 = 1; } } if(grace) --grace; } if(partying && ++flashtimer == TICKS/4) { flashtimer = 0; if(part0 == 0) { part0 = 1; part1 = 0; } else if(part1 == 0) { part1 = 1; part2 = 0; } else { part0 = 0; part1 = 1; part2 = 1; } } } } main() { for(;;) { OPTION = 1; TRISB = IOBITS_B; TRISA = 0x00; // all bits outputs - lower current drain PORTA = 0xFF; PORTB = 0xF7; // set bits high if(!(PORTB & 0x80)) powerdowntimer = 0; INTCON = 0xA0; // enable rtcc interrupt for(;;) { asm("clrwdt"); if(powerdowntimer >= PWROFF) { INTCON = 0; PORTB = 0x74; TRISB = 0x0; // all bits output - lower current drain OPTION = 0x8D; // WDT prescaled by 64 - about 1200 ms asm(" sleep"); break; } } } }