2 * The Sphinx -- A Device for Asking Riddles at the Entrance to the Garage
4 * (c) 2017--2019 Martin Mares <mj@ucw.cz>
8 * Pin assignment (component side view; "*" marks inverted signals)
10 * +-------------------+
12 * button* | PB3 PB2=SCK | signal "closed" from drive*
13 * output to drive | PB4 PB1=MISO | corridor LED
14 * | GND PB0=MOSI | diagnostic LED*
15 * +-------------------+
17 * Note that MISO, MOSI, and SCK are used for programming, so our signals
18 * are connected via jumpers, which must be kept open during programming.
20 * Connections to door control unit:
26 * Connections to EP 161 module:
32 #define F_CPU 1200000UL
34 #include <avr/interrupt.h>
36 #include <avr/sleep.h>
37 #include <util/delay.h>
42 #define B(x) (1U<<(x))
44 static void sleep(uint16_t millisec)
52 static byte out_pulse;
53 #define OUT_PULSE_WIDTH 100
55 #define DEBOUNCE_THRESHOLD 3
57 static u16 press_timer;
58 #define LONG_PRESS 150
59 static u16 unlock_timer;
60 #define UNLOCK_SECONDS 30
61 static byte blink_timer;
65 // Generate output pulse
71 // Debounce the button
80 if (debounce < DEBOUNCE_THRESHOLD)
86 // PB2 is 0 if the door is fully closed,
87 // we need to set door_open if it is at least partially open.
92 unlock_timer = UNLOCK_SECONDS * 60;
105 unlock_timer = UNLOCK_SECONDS * 100;
106 } else if (door_open) {
107 if (!(blink_timer & 63))
110 if (!(blink_timer & 15))
120 if (press_timer < LONG_PRESS) {
122 if (press_timer == LONG_PRESS)
123 unlock_timer = UNLOCK_SECONDS * 100;
133 // PB0: output for diagnostic LED
136 // PB1: output for corridor LED
140 // PB2: signal "door closed" from the drive, needs pull up
143 // PB3: button input, needs pull up
146 // PB4: output to control the gate
150 for (byte i=0; i<5; i++) {
173 // Set up timer interrupt
174 TCCR0A = 0x02; // No OC pins, clear on compare
175 TCCR0B = 0x05; // Run at CLK_IO / 1024
176 OCR0A = 11; // Approximately once in 10ms
177 TIMSK0 = B(OCIE0A); // Interrupt on compare
180 // Sleep well, my little sphinx
182 set_sleep_mode(SLEEP_MODE_IDLE);