/* DIY Annoy-a-tron source code * (c) 2007 Jurre "Kipmans" Hanema, * Idea (c) ThinkGeek * * Released under "THE BEER-WARE LICENSE" (Revision 42): * wrote this file. As long as you retain this notice you can * do whatever you want with this stuff. If we meet some day, and you think this * stuff is worth it, you can buy me a beer in return. */ #define F_CPU 4000000 /* 4 MHz crystal */ #include #include #include #include #define SIX_MINUTES 360000 /* ms */ #define TWO_MINUTES 120000 /* ms */ #define STATE_WAITING 1 #define STATE_BEEP2K 2 #define STATE_BEEP10K 3 #define MODE_2K 1 #define MODE_10K 2 #define MODE_ALT 3 #define set_output_high(port, bit) (port |= _BV(bit)) #define set_output_low(port, bit) (port &= ~_BV(bit)) volatile unsigned long int n_millisecs; volatile unsigned long int ms_busy; volatile unsigned char isr_calls; volatile unsigned char n_halfperiods; volatile unsigned char state; volatile unsigned char mode; volatile unsigned char high; volatile unsigned char tmp; ISR(TIMER0_OVF0_vect) { // Called every 0,05 ms isr_calls++; if(state == STATE_WAITING && isr_calls >= 20) { ms_busy++; if(ms_busy >= n_millisecs) { if(mode == MODE_2K) state = STATE_BEEP2K; else if(mode == MODE_10K) state = STATE_BEEP10K; else { tmp = rand() / (RAND_MAX / 10 + 1); if(tmp >= 5) state = STATE_BEEP2K; else state = STATE_BEEP10K; } ms_busy = 0; } isr_calls = 0; } if((state == STATE_BEEP2K && isr_calls >= 5) || (state == STATE_BEEP10K && isr_calls >= 1)) { if(high) { set_output_low(PORTD, PD2); set_output_high(PORTD, PD3); high = 0; } else { set_output_high(PORTD, PD2); set_output_low(PORTD, PD3); high = 1; } n_halfperiods++; if((state == STATE_BEEP2K && n_halfperiods >= 4) || (state == STATE_BEEP10K && n_halfperiods >= 20)) { ms_busy++; if(ms_busy >= 1000) { state = STATE_WAITING; set_output_low(PORTD, PD2); set_output_low(PORTD, PD3); ms_busy = 0; n_millisecs = random() / (RANDOM_MAX / SIX_MINUTES + 1) + TWO_MINUTES; } n_halfperiods = 0; } isr_calls = 0; } TCNT0 = 230; } int main() { unsigned char garbage; cli(); isr_calls = 0; state = STATE_WAITING; mode = MODE_2K; DDRD = _BV(PD2) | _BV(PD3); PORTD |= _BV(PD0) | _BV(PD1) | _BV(PD4) | _BV(PD5) | _BV(PD6); PORTB |= _BV(PB0) | _BV(PB1) | _BV(PB2) | _BV(PB3) | _BV(PB4) | _BV(PB5) | _BV(PB6) | _BV(PB7); set_output_low(PORTD, PD2); TIMSK = _BV(TOIE0); TCCR0 = _BV(CS01); TCNT0 = 230; srandom(garbage); n_millisecs = random() / (RANDOM_MAX / SIX_MINUTES + 1) + TWO_MINUTES; sei(); while(1) { if(bit_is_clear(PIND, PD0)) mode = MODE_2K; else if(bit_is_clear(PIND, PD1)) mode = MODE_10K; else mode = MODE_ALT; } return 0; }