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
|
|
|
|
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
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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 'u':
|
|
|
|
state = UNLOCKED;
|
|
|
|
reset_timeout();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'l':
|
|
|
|
state = LOCKED;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'p':
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
if (state == UNLOCKED)
|
|
|
|
schnapper = true;
|
|
|
|
else
|
|
|
|
retval = '?';
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i':
|
|
|
|
retval = (state == LOCKED) ? 'l' : 'u';
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
retval = '?';
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
uart_putc(retval);
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|
|
|
|
|
2015-09-16 22:58:00 +02:00
|
|
|
// Alle 1.137 Sekunden
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2015-09-16 22:58:00 +02:00
|
|
|
// Notzu
|
|
|
|
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('L');
|
|
|
|
state = LOCKED;
|
|
|
|
|
|
|
|
out:
|
|
|
|
sei();
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|
|
|
|
|
2015-09-16 22:58:00 +02:00
|
|
|
// Notauf
|
|
|
|
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('U');
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
cli();
|
|
|
|
io_init();
|
|
|
|
|
|
|
|
// Wait a bit to settle down
|
|
|
|
_delay_ms(1000);
|
|
|
|
uart_init();
|
|
|
|
uart_set_recv_handler(uart_handler);
|
|
|
|
|
|
|
|
// Timer config
|
|
|
|
TIMSK |= (1<<TOIE1);
|
|
|
|
TIFR |= (1<<TOV1);
|
|
|
|
TCCR1A = 0;
|
|
|
|
TCCR1B = (1<<CS12);
|
|
|
|
|
|
|
|
TCNT1 = 0;
|
|
|
|
|
|
|
|
// falling edge
|
|
|
|
MCUCR = (1<<ISC11)|(1<<ISC01);
|
|
|
|
GIMSK |= (1<<INT0)|(1<<INT1);
|
|
|
|
|
|
|
|
sei();
|
|
|
|
|
|
|
|
for(;;) {
|
|
|
|
if (state == LOCKED) {
|
|
|
|
bolzen_on();
|
|
|
|
schnapper = false;
|
|
|
|
if (is_emergency_unlock()) {
|
|
|
|
_delay_ms(200);
|
|
|
|
if (is_emergency_unlock()) {
|
|
|
|
uart_putc('N');
|
|
|
|
cli();
|
|
|
|
|
|
|
|
bolzen_off();
|
|
|
|
schnapper_on();
|
|
|
|
|
|
|
|
_delay_ms(3000);
|
|
|
|
|
|
|
|
schnapper_off();
|
|
|
|
bolzen_on();
|
|
|
|
|
|
|
|
sei();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (state == UNLOCKED) {
|
|
|
|
bolzen_off();
|
|
|
|
if (schnapper == true) {
|
|
|
|
schnapper = false;
|
|
|
|
schnapper_on();
|
|
|
|
_delay_ms(2000);
|
|
|
|
schnapper_off();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|