aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <code@jaseg.net>2016-05-04 14:07:15 +0200
committerjaseg <code@jaseg.net>2016-05-05 18:31:10 +0200
commit698c35b23c7f3f43e47479ff158e71c7c331f918 (patch)
tree4f9574fba9412a936de6deb12c1f0f80339ef05f
downloadcccb-klingel-698c35b23c7f3f43e47479ff158e71c7c331f918.tar.gz
cccb-klingel-698c35b23c7f3f43e47479ff158e71c7c331f918.tar.bz2
cccb-klingel-698c35b23c7f3f43e47479ff158e71c7c331f918.zip
Initial commit
-rw-r--r--Makefile26
-rw-r--r--main.c191
2 files changed, 217 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..6bcec57
--- /dev/null
+++ b/Makefile
@@ -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
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..37451c6
--- /dev/null
+++ b/main.c
@@ -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;
+ }
+ }
+ }
+ }
+ }
+}
+