diff options
-rw-r--r-- | Makefile | 45 | ||||
-rw-r--r-- | main.c | 166 |
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 @@ -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 + + } + +} |