From 4813472a201f06b1f7db6b75ea07e751ca3a95a1 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Sun, 12 Mar 2017 12:36:46 +0100 Subject: [PATCH] The Sphinx v0.9 --- sphinx/sphinx.c | 110 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 99 insertions(+), 11 deletions(-) diff --git a/sphinx/sphinx.c b/sphinx/sphinx.c index 7355d0b..5f3e3f2 100644 --- a/sphinx/sphinx.c +++ b/sphinx/sphinx.c @@ -1,5 +1,5 @@ /* - * Asking Riddles at the Entrance to Garage + * The Sphinx -- A Device for Asking Riddles at the Entrance to the Garage * * (c) 2017 Martin Mares */ @@ -9,19 +9,24 @@ * * +-------------------+ * | RESET* VCC | - * button | PB3 SCK | + * button* | PB3 SCK | * output | PB4 MISO | * | GND PB0=MOSI | diagnostic LED* * +-------------------+ + * + * Note that MOSI is used for programming, so the LED is connected + * via jumper, which must be open during programming. */ #define F_CPU 1200000UL +#include #include #include #include typedef uint8_t byte; +typedef uint16_t u16; #define B(x) (1U<<(x)) @@ -33,32 +38,115 @@ static void sleep(uint16_t millisec) } } +static byte out_pulse; +#define OUT_PULSE_WIDTH 100 +static byte debounce; +#define DEBOUNCE_THRESHOLD 3 +static byte pressed; +static u16 press_timer; +#define LONG_PRESS 500 +static byte second_timer; +static byte unlocked; +#define UNLOCK_SECONDS 20 + +ISR(TIM0_COMPA_vect) +{ + if (out_pulse) { + if (!--out_pulse) + PORTB &= ~B(PB4); + } + + if (!second_timer) { + second_timer = 100; + if (unlocked) + unlocked--; + } + second_timer--; + + if (PINB & B(PB3)) { + // Switch open + if (debounce) + debounce--; + else + pressed = 0; + } else { + // Switch closed + if (debounce < DEBOUNCE_THRESHOLD) + debounce++; + else + pressed = 1; + } + + if (unlocked) { + if (!(second_timer & 7)) + PORTB ^= B(PB0); + if (pressed) { + if (out_pulse < 2) + out_pulse = 2; + PORTB |= B(PB4); + unlocked = UNLOCK_SECONDS; + } + } else { + if (!pressed) { + PORTB |= B(PB0); + press_timer = 0; + } else { + PORTB &= ~B(PB0); + if (press_timer < LONG_PRESS) { + press_timer++; + if (press_timer == LONG_PRESS) { + out_pulse = OUT_PULSE_WIDTH; + PORTB |= B(PB4); + unlocked = UNLOCK_SECONDS; + } + } + } + } +} + int main(void) { - DDRB |= B(PB0); // PB0: output - DDRB |= B(PB4); // PB4: output - PORTB &= ~B(PB3); // PB3: input, no pullup + // PB0: output for diagnostic LED + DDRB |= B(PB0); + + // PB3: button input, needs pull up + PORTB |= B(PB3); + + // PB4: output to control the gate + PORTB &= ~B(PB4); + DDRB |= B(PB4); for (byte i=0; i<5; i++) { PORTB &= ~B(PB0); - sleep(100); + sleep(50); PORTB |= B(PB0); - sleep(100); + sleep(50); } +#if 0 + // Copy mode for (;;) { sleep(10); if (PINB & B(PB3)) { - PORTB &= ~B(PB0); - PORTB |= B(PB4); - } else { PORTB |= B(PB0); PORTB &= ~B(PB4); + } else { + PORTB &= ~B(PB0); + PORTB |= B(PB4); } } +#endif + + // Set up timer interrupt + TCCR0A = 0x02; // No OC pins, clear on compare + TCCR0B = 0x05; // Run at CLK_IO / 1024 + OCR0A = 11; // Approximately once in 10ms + TIMSK0 = B(OCIE0A); // Interrupt on compare + sei(); + // Sleep well, my little sphinx for (;;) { - set_sleep_mode(SLEEP_MODE_PWR_DOWN); + set_sleep_mode(SLEEP_MODE_IDLE); sleep_mode(); } } -- 2.39.2