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

204 lines
3.0 KiB
C
Raw Normal View History

/*
* 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
*/
#include "uart.h"
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>
#define RED 0x1
#define GREEN 0x2
#define YELLOW 0x4
2015-05-14 22:03:00 +02:00
#define SET_CONDITIONAL(predicate, port, pin) \
if ((predicate)) \
port |= (1 << pin); \
else \
port &= ~(1 << pin);
/* can either be red, green, or yellow */
static unsigned char state;
2015-05-14 22:03:00 +02:00
static inline void set_schnapper(bool state)
{
SET_CONDITIONAL(state, PORTB, PB0);
}
static inline void set_bolzen(bool state)
2015-05-14 22:03:00 +02:00
{
SET_CONDITIONAL(state, PORTB, PB1);
2015-05-20 22:42:20 +02:00
}
static inline void reset_timeout(void)
{
TCNT1 = 0;
}
static void set_leds(void)
2015-05-20 22:42:20 +02:00
{
static unsigned int counter = 0;
bool pwm_cycle = ++counter % 20;
2015-09-16 22:58:00 +02:00
if (pwm_cycle) {
PORTD &= ~((1 << PD5) | (1 << PD6));
PORTB &= ~(1 << PB4);
}
2015-09-16 22:58:00 +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
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
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
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
}
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
{
reset_timeout();
update_state(RED);
2015-05-14 22:03:00 +02:00
}
static inline void timer_init(void)
2015-05-14 22:03:00 +02:00
{
TIMSK |= (1 << TOIE1);
TIFR |= (1 << TOV1);
TCCR1A = 0;
TCCR1B = (1 << CS12);
2015-05-14 22:03:00 +02:00
}
static inline void setup_ports(void)
2015-05-14 22:03:00 +02:00
{
PORTB = 0;
DDRB = (1 << PB4) | (1 << PB1) | (1 << PB0);
2015-09-16 22:58:00 +02:00
PORTD = 0;
DDRD = (1 << PD5) | (1 << PD6);
}
2015-09-16 22:58:00 +02:00
static unsigned char get_keys(void)
{
unsigned char ret = 0;
2015-09-16 22:58:00 +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
return ret;
2015-05-14 22:03:00 +02:00
}
2015-09-16 22:58:00 +02:00
int main(void)
{
unsigned char i;
2015-09-16 22:58:00 +02:00
setup_ports();
timer_init();
2015-09-16 22:58:00 +02:00
uart_init();
update_state(RED);
reset_timeout();
2015-09-16 22:58:00 +02:00
sei();
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
}
while (get_keys())
reset_timeout();
set_leds();
2015-09-16 22:58:00 +02:00
}
2015-05-14 22:03:00 +02:00
}