2018-09-01 23:07:13 +02:00
|
|
|
/*
|
|
|
|
* doorlock-avr, AVR code of Binary Kitchen's doorlock
|
|
|
|
*
|
|
|
|
* Copyright (c) Binary Kitchen, 2018
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Ralf Ramsauer <ralf@binary-kitchen.de>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
|
|
* the COPYING file in the top-level directory.
|
2015-05-14 22:03:00 +02:00
|
|
|
*/
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
#include "uart.h"
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +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>
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
#define RED 0x1
|
|
|
|
#define GREEN 0x2
|
|
|
|
#define YELLOW 0x4
|
2015-05-14 22:03:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
#define SET_CONDITIONAL(predicate, port, pin) \
|
|
|
|
if ((predicate)) \
|
|
|
|
port |= (1 << pin); \
|
|
|
|
else \
|
|
|
|
port &= ~(1 << pin);
|
2015-09-17 14:59:03 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
/* can either be red, green, or yellow */
|
|
|
|
static unsigned char state;
|
2015-05-14 22:03:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static inline void set_schnapper(bool state)
|
2015-09-17 15:05:32 +02:00
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
SET_CONDITIONAL(state, PORTB, PB0);
|
2015-09-17 15:05:32 +02:00
|
|
|
}
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static inline void set_bolzen(bool state)
|
2015-05-14 22:03:00 +02:00
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
SET_CONDITIONAL(state, PORTB, PB1);
|
2015-05-20 22:42:20 +02:00
|
|
|
}
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static inline void reset_timeout(void)
|
2015-09-17 15:05:32 +02:00
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
TCNT1 = 0;
|
2015-09-17 15:05:32 +02:00
|
|
|
}
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static void set_leds(void)
|
2015-05-20 22:42:20 +02:00
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
static unsigned int counter = 0;
|
|
|
|
bool pwm_cycle = ++counter % 20;
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
if (pwm_cycle) {
|
|
|
|
PORTD &= ~((1 << PD5) | (1 << PD6));
|
|
|
|
PORTB &= ~(1 << PB4);
|
|
|
|
}
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
switch (state) {
|
|
|
|
case RED:
|
|
|
|
PORTD |= (1 << PD5);
|
|
|
|
break;
|
|
|
|
case YELLOW:
|
|
|
|
PORTD |= (1 << PD6);
|
|
|
|
break;
|
|
|
|
case GREEN:
|
|
|
|
PORTB |= (1 << PB4);
|
|
|
|
break;
|
|
|
|
}
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
if (pwm_cycle)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case RED:
|
|
|
|
PORTD ^= (1 << PD6);
|
|
|
|
PORTB ^= (1 << PB4);
|
|
|
|
break;
|
|
|
|
case YELLOW:
|
|
|
|
PORTD ^= (1 << PD5);
|
|
|
|
PORTB ^= (1 << PB4);
|
|
|
|
break;
|
|
|
|
case GREEN:
|
|
|
|
PORTD ^= (1 << PD5);
|
|
|
|
PORTD ^= (1 << PD6);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static void update_state(unsigned char new_state)
|
|
|
|
{
|
|
|
|
reset_timeout();
|
|
|
|
|
|
|
|
if (new_state == state)
|
|
|
|
return;
|
|
|
|
|
|
|
|
state = new_state;
|
|
|
|
switch (state) {
|
|
|
|
case RED:
|
|
|
|
set_bolzen(false);
|
|
|
|
set_schnapper(false);
|
|
|
|
uart_putc('r');
|
|
|
|
break;
|
|
|
|
case YELLOW:
|
|
|
|
set_bolzen(true);
|
|
|
|
set_schnapper(false);
|
|
|
|
uart_putc('y');
|
|
|
|
break;
|
|
|
|
case GREEN:
|
|
|
|
set_bolzen(true);
|
|
|
|
set_schnapper(true);
|
|
|
|
uart_putc('g');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
ISR(USART_RX_vect)
|
|
|
|
{
|
|
|
|
unsigned char c = UDR;
|
|
|
|
bool respond = true;
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case 'r':
|
|
|
|
update_state(RED);
|
|
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
update_state(YELLOW);
|
|
|
|
break;
|
|
|
|
case 'g':
|
|
|
|
update_state(GREEN);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
respond = false;
|
|
|
|
break;
|
2015-09-16 22:58:00 +02:00
|
|
|
}
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
if (respond)
|
|
|
|
uart_putc(c);
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|
|
|
|
|
2015-09-16 22:58:00 +02:00
|
|
|
ISR(TIMER1_OVF_vect)
|
2015-05-14 22:03:00 +02:00
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
reset_timeout();
|
|
|
|
update_state(RED);
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static inline void timer_init(void)
|
2015-05-14 22:03:00 +02:00
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
TIMSK |= (1 << TOIE1);
|
|
|
|
TIFR |= (1 << TOV1);
|
|
|
|
TCCR1A = 0;
|
|
|
|
TCCR1B = (1 << CS12);
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static inline void setup_ports(void)
|
2015-05-14 22:03:00 +02:00
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
PORTB = 0;
|
|
|
|
DDRB = (1 << PB4) | (1 << PB1) | (1 << PB0);
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
PORTD = 0;
|
|
|
|
DDRD = (1 << PD5) | (1 << PD6);
|
|
|
|
}
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
static unsigned char get_keys(void)
|
|
|
|
{
|
|
|
|
unsigned char ret = 0;
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
if (!(PIND & (1 << PD2))) ret |= RED;
|
|
|
|
if (!(PIND & (1 << PD3))) ret |= YELLOW;
|
|
|
|
if (!(PIND & (1 << PD4))) ret |= GREEN;
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
return ret;
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|
|
|
|
|
2015-09-16 22:58:00 +02:00
|
|
|
int main(void)
|
|
|
|
{
|
2018-09-01 23:07:13 +02:00
|
|
|
unsigned char i;
|
2015-09-16 22:58:00 +02:00
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
setup_ports();
|
|
|
|
timer_init();
|
2015-09-16 22:58:00 +02:00
|
|
|
uart_init();
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
update_state(RED);
|
2015-09-17 15:02:34 +02:00
|
|
|
reset_timeout();
|
2015-09-16 22:58:00 +02:00
|
|
|
|
|
|
|
sei();
|
|
|
|
|
2018-09-01 23:07:13 +02:00
|
|
|
for (;;) {
|
|
|
|
i = get_keys();
|
|
|
|
if (i & GREEN) {
|
|
|
|
uart_putc('G');
|
|
|
|
update_state(GREEN);
|
|
|
|
} else if (i & YELLOW) {
|
|
|
|
uart_putc('Y');
|
|
|
|
update_state(YELLOW);
|
|
|
|
} else if (i & RED) {
|
|
|
|
uart_putc('R');
|
|
|
|
update_state(RED);
|
2015-09-16 22:58:00 +02:00
|
|
|
}
|
2018-09-01 23:07:13 +02:00
|
|
|
while (get_keys())
|
|
|
|
reset_timeout();
|
|
|
|
set_leds();
|
2015-09-16 22:58:00 +02:00
|
|
|
}
|
2015-05-14 22:03:00 +02:00
|
|
|
}
|