summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile45
-rw-r--r--main.c166
2 files changed, 211 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0b9e15c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,45 @@
+MCU ?= attiny2313
+AVRDUDE_PROGRAMMER ?= usbasp
+
+AVRCC ?= avr-gcc
+AVRFLASH ?= avrdude
+AVRNM ?= avr-nm
+AVROBJCOPY ?= avr-objcopy
+AVROBJDUMP ?= avr-objdump
+
+CFLAGS += -mmcu=attiny2313 -DF_CPU=20000000UL
+#CFLAGS += -gdwarf-2 -fverbose-asm -save-temps
+CFLAGS += -I. -std=gnu99 -O2 -Wall -Wextra -pedantic
+CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -fwhole-program -flto -mstrict-X
+
+AVRFLAGS += -U lfuse:w:0xe4:m -U hfuse:w:0xdf:m -U efuse:w:0xff:m
+AVRFLAGS += -U flash:w:main.hex
+# AVRFLAGS += -U eeprom:w:main.eep
+
+%.hex: %.elf
+ ${AVROBJCOPY} -O ihex -R .eeprom $< $@
+
+%.eep: %.elf
+ ${AVROBJCOPY} -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+ --change-section-lma .eeprom=0 -O ihex $< $@
+
+main.elf: main.c
+ ${AVRCC} ${CFLAGS} -o $@ ${@:.elf=.c} -Wl,-Map=main.map,--cref
+ avr-size -d $@
+
+program: main.hex main.eep
+ ${AVRFLASH} -p ${MCU} -c ${AVRDUDE_PROGRAMMER} ${AVRFLAGS}
+
+secsize: main.elf
+ ${AVROBJDUMP} -hw -j.text -j.bss -j.data main.elf
+
+funsize: main.elf
+ ${AVRNM} --print-size --size-sort main.elf
+
+.PHONY: program secsize funsize
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
+build elf hex eep lss sym coff extcoff \
+clean clean_list program debug gdb-config
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..e20b45f
--- /dev/null
+++ b/main.c
@@ -0,0 +1,166 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdlib.h>
+
+/*
+ * Onewire iButton / SmartButton slave.
+ * Has the 64bit ID set below
+ * (corresponds to <https://wiki.chaosdorf.de/images/f/fc/Smartbutton.jpg>).
+ *
+ * Only supports non-overdrive READ ROM. Does not hold any data.
+ *
+ * Tested and working with a DS2482. Should mostly adhere to the standard,
+ * but nothing is guaranteed.
+ *
+ * Any unexpected input (SKIP ROM, overdriv, ...) may cause a hangup requiring
+ * an AVR reset.
+ */
+
+#define ADDR1 0xC4
+#define ADDR2 0x00
+#define ADDR3 0x00
+#define ADDR4 0x09
+#define ADDR5 0x7d
+#define ADDR6 0x79
+#define ADDR7 0x04
+#define ADDR8 0x01
+
+// HCNT: r30 (ZL), r31 (ZH)
+// LCNT: r28 (YL), r29 (YH)
+
+#define LCNTH GPIOR2
+#define LCNTL GPIOR1
+#define HCNTL GPIOR0
+
+#define CNT USIDR
+#define LASTCMD OCR0B
+#define BUF OCR0A
+#define POS OCR1A
+#define APOS OCR1B
+#define BYTE EEDR
+
+int main (void)
+{
+ /* watchdog reset after ~4 seconds */
+ MCUSR &= ~_BV(WDRF);
+ WDTCSR = _BV(WDCE) | _BV(WDE);
+ WDTCSR = _BV(WDE) | _BV(WDP3);
+
+ MCUCR = _BV(ISC10);
+ GIMSK = _BV(INT1);
+
+ ACSR |= _BV(ACD);
+
+ POS = 0;
+ APOS = 0;
+ DDRD = 0;
+ PORTD = 0;
+
+ sei();
+
+ asm volatile ("ldi r28, 0");
+ asm volatile ("ldi r29, 0");
+ asm volatile ("ldi r30, 0");
+ asm volatile ("ldi r31, 0");
+
+ // 1us
+ while (1) { // 1c
+ asm volatile ("inc r30"); // 1c
+ asm volatile ("adiw r28, 1"); // 2c
+ asm volatile ("wdr"); // 1c
+ }
+
+ return 0;
+}
+
+ISR(INT1_vect)
+{
+ if (PIND & _BV(PD3)) {
+
+ asm("out 0x15, r29"); // LCNTH
+ asm("out 0x14, r28"); // LCNTL
+ asm("out 0x13, r30"); // HCNTL
+
+ // > 256us - reset
+ if (LCNTH > 0) {
+ DDRD = _BV(PD3);
+ // 120us
+ for (CNT = 0; CNT < 120; CNT++) {
+ asm volatile ("wdr");
+ }
+ DDRD = 0;
+ asm volatile ("wdr");
+ EIFR |= _BV(INTF1);
+ }
+ // ~60us - write 0
+ else if (LCNTL > 6) {
+ if (!LASTCMD)
+ POS++;
+ }
+ // < ~15us - write 1 OR read
+ else {
+ if (!LASTCMD) {
+ BUF |= _BV(POS);
+ POS++;
+ }
+ }
+ if (!LASTCMD && (POS == 7)) {
+ LASTCMD = BUF;
+ POS = 1;
+ APOS = 0;
+ BYTE = ~ADDR8;
+ MCUCR = _BV(ISC11);
+ EIFR |= _BV(INTF1);
+ }
+
+
+ asm volatile ("ldi r30, 1"); // HCNTL = 1
+ }
+ else {
+ if (LASTCMD == 0x33) {
+
+ if (BYTE & POS) {
+
+ DDRD = _BV(PD3);
+ // 15us
+ for (CNT = 0; CNT < 18; CNT++) {
+ asm volatile ("wdr");
+ }
+ DDRD = 0;
+ asm volatile ("wdr");
+ EIFR |= _BV(INTF1);
+ }
+ if (POS != 0x80) {
+ POS <<= 1;
+ }
+ else {
+ APOS++;
+ POS = 1;
+ if (APOS == 1)
+ BYTE = ~ADDR7;
+ else if (APOS == 2)
+ BYTE = ~ADDR6;
+ else if (APOS == 3)
+ BYTE = ~ADDR5;
+ else if (APOS == 4)
+ BYTE = ~ADDR4;
+ else if (APOS == 5)
+ BYTE = ~ADDR3;
+ else if (APOS == 6)
+ BYTE = ~ADDR2;
+ else if (APOS == 7)
+ BYTE = ~ADDR1;
+
+ else if (APOS == 8) {
+ LASTCMD = 0;
+ MCUCR = _BV(ISC10);
+ POS = 0;
+ }
+ }
+ }
+ asm volatile ("ldi r29, 0"); // LCNTH = 0
+ asm volatile ("ldi r28, 1"); // LCNTL = 1
+
+ }
+
+}