1
0
mirror of https://github.com/binary-kitchen/doorlockd synced 2024-12-22 10:24:26 +01:00

Added new AVR software

This commit is contained in:
Ralf Ramsauer 2015-09-16 22:58:00 +02:00
parent 6b8e45ef42
commit 07cddb29f8
5 changed files with 916 additions and 727 deletions

View File

@ -79,7 +79,7 @@ OBJDIR = obj
# List C source files here. (C dependencies are automatically generated.)
SRC = main.c
SRC = main.c uart.c
# List C++ source files here. (C dependencies are automatically generated.)
@ -268,7 +268,7 @@ AVRDUDE_PROGRAMMER = avr910
AVRDUDE_PORT = /dev/ttyUSB0 # programmer connected to serial device
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
# Uncomment the following if you want avrdude's erase cycle counter.

106
avr-code/io.h Normal file
View File

@ -0,0 +1,106 @@
#ifndef IO_H
#define IO_H
#include <stdbool.h>
#include <avr/io.h>
/*
* Macros
*/
#define PIN(x) (*(&x - 2)) // Address Of Data Direction Register Of Port x
#define DDR(x) (*(&x - 1)) // Address Of Input Register Of Port x
/*
* Outputs
*/
#define PORT_BOLZEN PORTB
#define PIN_BOLZEN PB0
#define PORT_SCHNAPPER PORTB
#define PIN_SCHNAPPER PB1
#define PORT_STATUS PORTB
#define PIN_STATUS PB2
/*
* Inputs
*/
#define PORT_BUTTON_LOCK PORTD
#define PIN_BUTTON_LOCK PD2
#define PORT_BUTTON_UNLOCK PORTD
#define PIN_BUTTON_UNLOCK PD3
#define PORT_EMERGENCY_UNLOCK PORTD
#define PIN_EMERGENCY_UNLOCK PD4
static inline bool is_emergency_unlock(void)
{
return !(PIN(PORT_EMERGENCY_UNLOCK) & (1<<PIN_EMERGENCY_UNLOCK));
}
static inline bool is_button_unlock(void)
{
return !(PIN(PORT_BUTTON_UNLOCK) & (1<<PIN_BUTTON_UNLOCK));
}
static inline bool is_button_lock(void)
{
return !(PIN(PORT_BUTTON_LOCK) & (1<<PIN_BUTTON_LOCK));
}
static inline void schnapper_off(void)
{
PORT_SCHNAPPER &= ~(1<<PIN_SCHNAPPER);
}
static inline void schnapper_on(void)
{
PORT_SCHNAPPER |= (1<<PIN_SCHNAPPER);
}
static inline void bolzen_off(void)
{
PORT_BOLZEN &= ~(1<<PIN_BOLZEN);
}
static inline void bolzen_on(void)
{
PORT_BOLZEN |= (1<<PIN_BOLZEN);
}
static inline void status_off(void)
{
PORT_STATUS &= ~(1<<PIN_STATUS);
}
static inline void status_on(void)
{
PORT_STATUS |= (1<<PIN_STATUS);
}
static inline void io_init(void)
{
// Set output directions
DDR(PORT_SCHNAPPER) |= (1<<PIN_SCHNAPPER);
schnapper_off();
DDR(PORT_SCHNAPPER) |= (1<<PIN_BOLZEN);
bolzen_off();
DDR(PORT_STATUS) |= (1<<PIN_STATUS);
status_off();
// Set input directions and activate pull-ups
DDR(PORT_BUTTON_UNLOCK) &= ~(1<<PIN_BUTTON_UNLOCK);
PORT_BUTTON_UNLOCK |= (1<<PIN_BUTTON_UNLOCK);
DDR(PORT_BUTTON_LOCK) &= ~(1<<PIN_BUTTON_LOCK);
PORT_BUTTON_LOCK |= (1<<PIN_BUTTON_LOCK);
DDR(PORT_EMERGENCY_UNLOCK) &= ~(1<<PIN_EMERGENCY_UNLOCK);
PORT_EMERGENCY_UNLOCK |= (1<<PIN_EMERGENCY_UNLOCK);
}
#endif

View File

@ -2,141 +2,158 @@
* ralf@binary-kitchen.de
*/
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <string.h>
#define GREEN_ON (PORTB &= ~(1<<PB1))
#define GREEN_OFF (PORTB |= (1<<PB1))
#include "io.h"
#include "uart.h"
#define RED_ON (PORTB &= ~(1<<PB0))
#define RED_OFF (PORTB |= (1<<PB0))
static volatile enum {LOCKED, UNLOCKED} state = LOCKED;
static volatile bool schnapper = false;
#define DOORLIGHT_ON (PORTD |= (1<<PD6))
#define DOORLIGHT_OFF (PORTD &= ~(1<<PD6))
#define OPEN_BOLZEN (PORTD &= ~(1<<PD4))
#define CLOSE_BOLZEN (PORTD |= (1<<PD4))
#define OPEN_SCHNAPPER (PORTD |= (1<<PD5))
#define CLOSE_SCHNAPPER (PORTD &= ~(1<<PD5))
#define IS_RESCUE (!(PIND & (1<<PD3)))
#define IS_SWITCH (!(PIND & (1<<PD2)))
static uint8_t open = 0;
static uint8_t klacker = 0;
void open_door()
static inline void reset_timeout(void)
{
RED_OFF;
GREEN_ON;
OPEN_BOLZEN;
DOORLIGHT_ON;
}
void close_door()
{
RED_ON;
GREEN_OFF;
DOORLIGHT_OFF;
CLOSE_SCHNAPPER;
CLOSE_BOLZEN;
}
void schnapper(unsigned int i)
{
OPEN_SCHNAPPER;
while (i--) {
_delay_ms(1000);
}
CLOSE_SCHNAPPER;
_delay_ms(100);
}
ISR(USI_OVERFLOW_vect)
{
// Clear interrupt flag
USISR |= (1<<USIOIF);
// Reset counter
TCNT1 = 0;
open = 1;
}
uint8_t in = USIDR;
// Depending on the clock, a klacker either can be 10101010 or 01010101
if (in == 0x55 || in == 0xAA)
void uart_handler(const unsigned char c)
{
klacker = 1;
}
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);
}
// Alle 1.137 Sekunden
ISR(TIMER1_OVF_vect)
{
open = 0;
state = LOCKED;
}
int main(void) {
// disable all interrupts
// Notzu
ISR(INT0_vect)
{
cli();
// PD4-6 as Output
DDRD = (1<<PD5)|(1<<PD4)|(1<<PD6);
// PD2,3 Pullup
PORTD |= (1<<PD2)|(1<<PD3);
// This code is used to prevent spurious interrupts
_delay_ms(50);
if (!is_button_lock())
goto out;
// PB0-1 as Output
DDRB = (1<<PB0)|(1<<PB1);
// PB5,7 Pullup
PORTB |= (1<<PB7)|(1<<PB5);
uart_putc('L');
state = LOCKED;
// first action: close door
close_door();
out:
sei();
}
// Configure USI
USICR = (1<<USICS1) | (1<<USIOIE) | (1<<USIWM0);
// Notauf
ISR(INT1_vect)
{
cli();
// Configure Timer
// 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();
}
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);
TCNT1 = 0;
TCCR1A = 0;
TCCR1B = (1<<CS01)|(1<<CS00);
TCCR1B = (1<<CS12);
// wait a bit to settle down
_delay_ms(1000);
TCNT1 = 0;
// falling edge
MCUCR = (1<<ISC11)|(1<<ISC01);
GIMSK |= (1<<INT0)|(1<<INT1);
// enable interrupts
sei();
for(;;) {
if (open == 0) {
close_door();
} else if (open == 1) {
open_door();
if (klacker == 1)
{
schnapper(3);
klacker = 0;
}
}
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();
if (IS_RESCUE) {
cli();
open_door();
schnapper(3);
sei();
} else if (IS_SWITCH && open == 0) {
_delay_ms(300);
if(IS_SWITCH && open == 0) {
cli();
open_door();
schnapper(5);
sei();
}
}
_delay_ms(50);
} else if (state == UNLOCKED) {
bolzen_off();
if (schnapper == true) {
schnapper = false;
schnapper_on();
_delay_ms(2000);
schnapper_off();
}
}
}
return 0;

53
avr-code/uart.c Normal file
View File

@ -0,0 +1,53 @@
#include <stddef.h>
#include <avr/interrupt.h>
#include <avr/io.h>
#include "uart.h"
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
#error Choose another crystal. Baud error too high.
#endif
static void (*recv_handler)(unsigned char c) = NULL;
ISR(USART_RX_vect)
{
cli();
if(recv_handler)
recv_handler(UDR);
sei();
}
void uart_init()
{
// Enable receive and transmit
UCSRB = (1<<RXEN)|(1<<TXEN)|(1<<RXCIE);
// Asynchronous mode, 8N1
UCSRC = (1<<UCSZ1)|(1<<UCSZ0);
UBRRH = UBRR_VAL >> 8;
UBRRL = UBRR_VAL & 0xFF;
}
void uart_set_recv_handler(void (*handler)(unsigned char c))
{
recv_handler = handler;
}
void uart_putc(const char c)
{
while ( !(UCSRA & (1<<UDRE)) );
UDR = (const unsigned char)c;
}
void uart_puts(const char* str)
{
do {
uart_putc(*str);
} while(*++str);
}

13
avr-code/uart.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef UART_H
#define UART_H
#define BAUD 9600UL
void uart_set_recv_handler(void (*handler)(unsigned char c));
void uart_init(void);
void uart_putc(const char c);
void uart_puts(const char* str);
#endif