1
0
mirror of https://github.com/binary-kitchen/doorlockd synced 2024-12-23 02:34:27 +01:00
doorlockd-mirror/avr-code/main.c

189 lines
2.9 KiB
C
Raw Normal View History

2015-05-14 22:03:00 +02:00
/* 2015, Ralf Ramsauer
* ralf@binary-kitchen.de
*/
2015-09-16 22:58:00 +02:00
#include <stdbool.h>
2015-05-14 22:03:00 +02:00
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
2015-09-16 22:58:00 +02:00
#include "io.h"
#include "uart.h"
2015-05-14 22:03:00 +02:00
#include "../doorcmds.h"
2015-09-16 22:58:00 +02:00
static volatile enum {LOCKED, UNLOCKED} state = LOCKED;
static volatile bool schnapper = false;
2015-05-14 22:03:00 +02:00
static inline void timer_init(void)
{
// Config the timer
// The 16bit Timer1 is used for resetting the lock state,
// if the UART stops receiving the unlock command
TIMSK |= (1<<TOIE1);
TIFR |= (1<<TOV1);
TCCR1A = 0;
TCCR1B = (1<<CS12);
}
2015-09-16 22:58:00 +02:00
static inline void reset_timeout(void)
2015-05-14 22:03:00 +02:00
{
2015-09-16 22:58:00 +02:00
TCNT1 = 0;
2015-05-20 22:42:20 +02:00
}
static inline void extint_init(void)
{
// Configure external interrupts
// External interrupts are used for Button Unlock an Lock
MCUCR = (1<<ISC11)|(1<<ISC01);
GIMSK |= (1<<INT0)|(1<<INT1);
}
2015-09-16 22:58:00 +02:00
void uart_handler(const unsigned char c)
2015-05-20 22:42:20 +02:00
{
2015-09-16 22:58:00 +02:00
char retval = c;
switch ((char)c) {
case DOOR_CMD_UNLOCK:
2015-09-16 22:58:00 +02:00
state = UNLOCKED;
reset_timeout();
break;
case DOOR_CMD_LOCK:
2015-09-16 22:58:00 +02:00
state = LOCKED;
break;
case DOOR_CMD_PING:
2015-09-16 22:58:00 +02:00
break;
case DOOR_CMD_SCHNAPER:
2015-09-16 22:58:00 +02:00
if (state == UNLOCKED)
schnapper = true;
else
retval = '?';
break;
case DOOR_CMD_STATUS:
2015-09-16 22:58:00 +02:00
retval = (state == LOCKED) ? 'l' : 'u';
break;
default:
retval = '?';
break;
}
uart_putc(retval);
2015-05-14 22:03:00 +02:00
}
// Timeroverflow interrupts occurs each 1.137 seconds
// UART receive interrupts is used to prevent timer overflows
2015-09-16 22:58:00 +02:00
ISR(TIMER1_OVF_vect)
2015-05-14 22:03:00 +02:00
{
2015-09-16 22:58:00 +02:00
state = LOCKED;
2015-05-14 22:03:00 +02:00
}
// Button Lock
2015-09-16 22:58:00 +02:00
ISR(INT0_vect)
2015-05-14 22:03:00 +02:00
{
2015-09-16 22:58:00 +02:00
cli();
// This code is used to prevent spurious interrupts
_delay_ms(50);
if (!is_button_lock())
goto out;
uart_putc(DOOR_BUTTON_LOCK);
2015-09-16 22:58:00 +02:00
state = LOCKED;
out:
sei();
2015-05-14 22:03:00 +02:00
}
// Button Unlock
2015-09-16 22:58:00 +02:00
ISR(INT1_vect)
2015-05-14 22:03:00 +02:00
{
2015-09-16 22:58:00 +02:00
cli();
// This code is used to prevent spurious interrupts
_delay_ms(50);
if (!is_button_unlock())
goto out;
uart_putc(DOOR_BUTTON_UNLOCK);
2015-09-16 22:58:00 +02:00
bolzen_off();
schnapper_on();
_delay_ms(3000);
schnapper_off();
out:
sei();
2015-05-14 22:03:00 +02:00
}
2015-09-16 22:58:00 +02:00
int main(void)
{
// Disable all interrupts
2015-09-16 22:58:00 +02:00
cli();
// Init IO
2015-09-16 22:58:00 +02:00
io_init();
// Wait a bit to settle down
_delay_ms(1000);
// Init Uart
2015-09-16 22:58:00 +02:00
uart_init();
uart_set_recv_handler(uart_handler);
// Init Timer
timer_init();
reset_timeout();
2015-09-16 22:58:00 +02:00
// Init external interrupts
extint_init();
2015-09-16 22:58:00 +02:00
// Enable all interrupts
2015-09-16 22:58:00 +02:00
sei();
for(;;) {
if (state == LOCKED) {
bolzen_on();
status_off();
2015-09-16 22:58:00 +02:00
schnapper = false;
// Check if someone used the emergency unlock
2015-09-16 22:58:00 +02:00
if (is_emergency_unlock()) {
// If so, wait 200ms and double check
2015-09-16 22:58:00 +02:00
_delay_ms(200);
if (is_emergency_unlock()) {
uart_putc(DOOR_EMERGENCY_UNLOCK);
2015-09-16 22:58:00 +02:00
cli();
bolzen_off();
schnapper_on();
_delay_ms(3000);
schnapper_off();
bolzen_on();
sei();
}
}
} else if (state == UNLOCKED) {
bolzen_off();
status_on();
2015-09-16 22:58:00 +02:00
if (schnapper == true) {
schnapper = false;
schnapper_on();
_delay_ms(2000);
schnapper_off();
}
}
}
return 0;
2015-05-14 22:03:00 +02:00
}