Initial commit
This commit is contained in:
commit
698c35b23c
2 changed files with 217 additions and 0 deletions
26
Makefile
Normal file
26
Makefile
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
# Makefile to build light_ws2812 library examples
|
||||
# This is not a very good example of a makefile - the dependencies do not work, therefore everything is rebuilt every time.
|
||||
|
||||
# Change these parameters for your device
|
||||
|
||||
F_CPU = 16000000
|
||||
DEVICE = atmega168
|
||||
|
||||
CFLAGS = -g2 -mmcu=$(DEVICE) -DF_CPU=$(F_CPU)
|
||||
CFLAGS+= -Os -ffunction-sections -fdata-sections -fpack-struct -fno-move-loop-invariants -fno-tree-scev-cprop -fno-inline-small-functions
|
||||
CFLAGS+= -Wall -Wno-pointer-to-int-cast
|
||||
#CFLAGS+= -Wa,-ahls=$<.lst
|
||||
|
||||
LDFLAGS = -Wl,--relax,--section-start=.text=0,-Map=main.map
|
||||
|
||||
main.elf: main.c
|
||||
avr-gcc $(CFLAGS) -o $@ $^
|
||||
avr-size $@
|
||||
|
||||
.PHONY: program
|
||||
program: main.elf
|
||||
avrdude -c arduino -P /dev/serial/by-id/usb-1a86_USB2.0-Serial-if00-port0 -b 19200 -p atmega168 -U flash:w:$<
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f main.elf
|
||||
191
main.c
Normal file
191
main.c
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
|
||||
#include <util/delay.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <string.h>
|
||||
|
||||
#define HZ 3906UL
|
||||
#define TIMEOUT_SEC 5
|
||||
#define MIN_PULSE_WIDTH_MS 50
|
||||
#define RING_DURATION_SEC 20
|
||||
#define OPEN_DURATION_SEC 3
|
||||
|
||||
#define PRESSED_MIN_MS 250
|
||||
#define RELEASED_MIN_MS 250
|
||||
|
||||
uint8_t global_thursday_mode = 0;
|
||||
|
||||
void tx_str(const char * PROGMEM s) {
|
||||
uint8_t c;
|
||||
while ((c = pgm_read_byte(s++))) {
|
||||
while (!(UCSR0A & (1<<UDRE0))) ;
|
||||
UDR0 = c;
|
||||
}
|
||||
}
|
||||
|
||||
void tx_help(void) {
|
||||
tx_str(PSTR("Klingeldings v0.23\r\n"));
|
||||
tx_str(PSTR("Questions? ask <jaseg@jaseg.net>\r\n"));
|
||||
tx_str(PSTR("Echo is disabled.\r\n\r\n"));
|
||||
tx_str(PSTR("Notifications are sent on their own line using the format \"CODE Human-readable explanation\\r\\n\".\r\n"));
|
||||
tx_str(PSTR("The notifications types are (the following occurences have been nerfed using backspaces):\r\n"));
|
||||
tx_str(PSTR(" T \bHUA Thursday mode auto open\r\n"));
|
||||
tx_str(PSTR(" R \bING Ringing\r\n"));
|
||||
tx_str(PSTR(" C \bODE Code access granted\r\n"));
|
||||
tx_str(PSTR(" T \bHU1 Thursday mode set to on\r\n"));
|
||||
tx_str(PSTR(" T \bHU0 Thursday mode set to off\r\n"));
|
||||
tx_str(PSTR(" B \bOOT Device booted.\r\n\r\n"));
|
||||
tx_str(PSTR(" O \bPEN Manual open\r\n"));
|
||||
tx_str(PSTR("Commands must be sent on their own line. Available commands:\r\n"));
|
||||
tx_str(PSTR(" open - Opens the door\r\n"));
|
||||
tx_str(PSTR(" thursday on - Mutes the ringer and turns on auto opening \r\n"));
|
||||
tx_str(PSTR(" thursday off - Unmutes the ringer and turns off auto opening\r\n\r\n"));
|
||||
}
|
||||
|
||||
void open(void) {
|
||||
PORTC |= 0x02; /* Opener relay */
|
||||
/* wait and blink for a few seconds */
|
||||
for (uint8_t i=0; i<4*OPEN_DURATION_SEC; i++) {
|
||||
PORTB ^= 0x20; /* LED */
|
||||
_delay_ms(250);
|
||||
}
|
||||
PORTC &= ~0x02; /* Opener relay */
|
||||
}
|
||||
|
||||
uint8_t handle_open_button(void) {
|
||||
if (PINC&0x20)
|
||||
return 0;
|
||||
tx_str(PSTR("OPEN Manual open\r\n"));
|
||||
open();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ring(void) {
|
||||
if (global_thursday_mode) {
|
||||
tx_str(PSTR("THUA Thursday mode auto open\r\n"));
|
||||
open();
|
||||
} else {
|
||||
tx_str(PSTR("RING Ringing\r\n"));
|
||||
PORTB |= 0x20;
|
||||
PORTC |= 0x04;
|
||||
for (uint16_t i=0; i<RING_DURATION_SEC*100 && !handle_open_button(); i++)
|
||||
_delay_ms(10);
|
||||
PORTB &= ~0x20;
|
||||
PORTC &= ~0x04;
|
||||
}
|
||||
}
|
||||
|
||||
void code(void) {
|
||||
tx_str(PSTR("CODE Code access granted\r\n"));
|
||||
open();
|
||||
}
|
||||
|
||||
void set_thursday_mode(uint8_t mode) {
|
||||
global_thursday_mode = mode;
|
||||
|
||||
tx_str(mode ? PSTR("THU1 Thursday mode set to on\r\n") : PSTR("THU0 Thursday mode set to off\r\n"));
|
||||
|
||||
if (mode)
|
||||
PORTC |= 0x10;
|
||||
else
|
||||
PORTC &= ~0x10;
|
||||
}
|
||||
|
||||
ISR (USART_RX_vect) {
|
||||
static uint8_t idx = 0;
|
||||
static char rxbuf[16];
|
||||
char ch = UDR0;
|
||||
|
||||
if (idx < sizeof(rxbuf)/sizeof(rxbuf[0]))
|
||||
rxbuf[idx++] = ch;
|
||||
else
|
||||
idx = 255;
|
||||
|
||||
if (ch == '\r' || ch == '\n') {
|
||||
idx = 0;
|
||||
if (!strcmp("open\r", rxbuf))
|
||||
open();
|
||||
else if (!strcmp("help\r", rxbuf))
|
||||
tx_help();
|
||||
else if (!strcmp("thursday on\r", rxbuf))
|
||||
set_thursday_mode(1);
|
||||
else if (!strcmp("thursday off\r", rxbuf))
|
||||
set_thursday_mode(0);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
/* IO map:
|
||||
* A0/PC0 IN ringer relay
|
||||
* A1/PC1 OUT opener relay
|
||||
* A2/PC2 OUT ringer signal
|
||||
* A3/PC3 IN thursday mode toggle
|
||||
* A4/PC4 OUT thursday mode signal
|
||||
*/
|
||||
/* use 115200Bd */
|
||||
UBRR0H = 0;
|
||||
UBRR0L = 16;
|
||||
UCSR0A = (1<<U2X0);
|
||||
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
|
||||
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
|
||||
DDRD |= 0x02; /* TX */
|
||||
|
||||
TCCR1B = 0x05; /* prescaler=1024 -> 3906.25Hz */
|
||||
|
||||
PORTC |= 0x01; /* Ringer relay input */
|
||||
DDRC |= 0x02; /* Opener relay output */
|
||||
DDRC |= 0x04; /* Doorbell button output */
|
||||
PORTC |= 0x08; /* Thursday mode toggle */
|
||||
DDRC |= 0x10; /* Thursday mode signal */
|
||||
PORTC |= 0x20; /* Opener button */
|
||||
DDRB |= 0x20; /* Status LED */
|
||||
|
||||
sei();
|
||||
_delay_ms(500);
|
||||
tx_help();
|
||||
tx_str(PSTR("BOOT Device booted.\r\n"));
|
||||
|
||||
uint16_t pattern[7];
|
||||
uint8_t pidx = 0;
|
||||
uint8_t thursday_toggle_timeout = 0;
|
||||
uint8_t codefail = 0;
|
||||
for (;;) {
|
||||
handle_open_button();
|
||||
if (!(PINC&0x08) && !thursday_toggle_timeout) { /* Thursday button */
|
||||
set_thursday_mode(!global_thursday_mode);
|
||||
thursday_toggle_timeout = 1;
|
||||
TCNT1 = 0;
|
||||
}
|
||||
if (TCNT1 > TIMEOUT_SEC*HZ) { /* Doorbell button timeout */
|
||||
if (pidx != 0 || codefail)
|
||||
ring();
|
||||
pidx = 0;
|
||||
codefail = 0;
|
||||
thursday_toggle_timeout = 0;
|
||||
TCNT1 = 0;
|
||||
} else {
|
||||
uint8_t st = PINC&1;
|
||||
if (st == (pidx&1)) {
|
||||
uint16_t val = TCNT1;
|
||||
if (val > HZ/1000*MIN_PULSE_WIDTH_MS) {
|
||||
pattern[pidx++] = val;
|
||||
TCNT1 = 0;
|
||||
if (pidx == sizeof(pattern)/sizeof(pattern[0])-1) {
|
||||
pidx = 0;
|
||||
if(( PRESSED_MIN_MS*HZ/1000 <= pattern[1])
|
||||
&& (RELEASED_MIN_MS*HZ/1000 <= pattern[2])
|
||||
&& ( PRESSED_MIN_MS*HZ/1000 <= pattern[3])
|
||||
&& (RELEASED_MIN_MS*HZ/1000 <= pattern[4])
|
||||
&& ( PRESSED_MIN_MS*HZ/1000 <= pattern[5])
|
||||
&& (RELEASED_MIN_MS*HZ/1000 <= pattern[6]))
|
||||
codefail = (code(), 0);
|
||||
else
|
||||
codefail = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in a new issue