diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4c7662d --- /dev/null +++ b/Makefile @@ -0,0 +1,63 @@ +MCU_TARGET = atmega328p +MCU_FREQ = 16000000UL +MCU_TTY = /dev/ttyUSB0 +MCU_TTY_BAUD = 57600 +MCU_PROGRAMMER = arduino + +PRG = main +OBJ = main.o uart.o + +OPTIMIZE = -O2 +DEFS = -DF_CPU=$(MCU_FREQ) -DBAUDRATE=$(MCU_TTY_BAUD) +LIBS = +# You should not have to change anything below here. +CC = avr-gcc +# Override is only needed by avr-lib build system. +override CFLAGS = -g --std=c99 -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) +override LDFLAGS = -Wl,-Map,$(PRG).map +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump + +all: $(PRG).elf $(PRG).asm + +$(PRG).elf: $(OBJ) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) + +# dependencies: + +clean: + rm -rf *.o $(PRG).elf *.eps *.png *.pdf *.bak *.asm *.hex + rm -rf *.lst *.map $(EXTRA_CLEAN_FILES) + +lst: $(PRG).lst + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +# Rules for building the .text rom images +text: hex bin srec + +hex: $(PRG).hex + +bin: $(PRG).bin + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ + +# to get the final asm code + +%.asm: %.elf + $(OBJDUMP) -z -j .text -m avr5 -d $< > $@ + +reset: + avrdude -v -p$(MCU_TARGET) -c$(MCU_PROGRAMMER) -P$(MCU_TTY) -b$(MCU_TTY_BAUD) + +flash: $(PRG).hex + avrdude -v -p$(MCU_TARGET) -c$(MCU_PROGRAMMER) -P$(MCU_TTY) -b$(MCU_TTY_BAUD) -u -U flash:w:$(PRG).hex + +screen: + screen $(MCU_TTY) $(MCU_TTY_BAUD) + diff --git a/main.c b/main.c new file mode 100644 index 0000000..6720334 --- /dev/null +++ b/main.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include "uart.h" + +/* Button matrix between PB3-PB4, PC0-PC3 + * PC0-PC3 are inputs, default pull-up + * PB3-PB4 are pulled to ground (alternating) while the above are read + */ + +void print_nibble(uint8_t nibble) { + nibble += 0x30; + if (nibble > 0x39) nibble += 7; + uart_putc(nibble); +} + +void print_int8hex(uint8_t val) { + print_nibble(val >> 4); + print_nibble(val & 0x0F); +} + +uint8_t getButtonState() { + uint8_t val = 0; + + // Pull upper button line (PB4) down + PORTB |= (1 << PB3); + PORTB &= ~(1 << PB4); + _delay_ms(1); + val = ((~PINC) << 4); + + // Pull lower button line (PB3) down + PORTB &= ~(1 << PB3); + PORTB |= (1 << PB4); + _delay_ms(1); + val |= (~PINC) & 0x0F; + + return val; +} + +uint8_t getrelay(uint8_t n) { + uint8_t v = 0; + switch(n) { + case 0: v = (PIND >> PD2); break; + case 1: v = (PIND >> PD3); break; + case 2: v = (PIND >> PD4); break; + case 3: v = (PIND >> PD5); break; + case 4: v = (PIND >> PD6); break; + case 5: v = (PIND >> PD7); break; + case 6: v = (PINB >> PB0); break; + case 7: v = (PINB >> PB1); break; + } + return(~v & 1); +} + +void setrelay(uint8_t n, uint8_t s) { + if (s) { + switch(n) { + case 0: PORTD &= ~(1 << PD2); break; + case 1: PORTD &= ~(1 << PD3); break; + case 2: PORTD &= ~(1 << PD4); break; + case 3: PORTD &= ~(1 << PD5); break; + case 4: PORTD &= ~(1 << PD6); break; + case 5: PORTD &= ~(1 << PD7); break; + case 6: PORTB &= ~(1 << PB0); break; + case 7: PORTB &= ~(1 << PB1); break; + } + } else { + switch(n) { + case 0: PORTD |= (1 << PD2); break; + case 1: PORTD |= (1 << PD3); break; + case 2: PORTD |= (1 << PD4); break; + case 3: PORTD |= (1 << PD5); break; + case 4: PORTD |= (1 << PD6); break; + case 5: PORTD |= (1 << PD7); break; + case 6: PORTB |= (1 << PB0); break; + case 7: PORTB |= (1 << PB1); break; + } + } +} + +int main() { + DDRC &= ~(0b1111); // This sets PC0 to PC3 to input + PORTC |= 0b1111; // This makes dito pull-up per default + + DDRB |= (1 << PB3) | (1 << PB4); // Keybad rows + + DDRD |= 0b11111100; // PD2 to PD7 for relay + DDRB |= 0b00000011; // PB0 and PB1 for relay + + // Same with PORT, so relays stay off + PORTD |= 0b11111100; + PORTB |= 0b00000011; + + sei(); + uint8_t c,p,d,i; + p = 0; + + while (1) { + c = getButtonState(); + d = c ^ p; + p = c; + for (i = 0; i<8; i++) { + if (d & c & 0x80) { + setrelay(i, 1 - getrelay(i)); + print_nibble(i); + uart_putc('\r'); + uart_putc('\n'); + } + d = d << 1; + c = c << 1; + } + }; +} diff --git a/uart.c b/uart.c new file mode 100644 index 0000000..ddf511d --- /dev/null +++ b/uart.c @@ -0,0 +1,82 @@ +#include +#include +#include + +#include "uart.h" + +#define UART_BUFSIZE 64 + +typedef volatile struct { + char data[UART_BUFSIZE]; + uint8_t r; + uint8_t w; +} buf; + +buf __attribute__ ((section (".noinit"))) uart_rxbuf; +buf __attribute__ ((section (".noinit"))) uart_txbuf; + +#define BAUD_PRESCALE (((F_CPU/(BAUDRATE*8UL)))-1) + +void __attribute__ ((naked)) __attribute__ ((section (".init5"))) uart_init() { + uart_rxbuf.r = 0; + uart_rxbuf.w = 0; + + uart_txbuf.r = 0; + uart_txbuf.w = 0; + + UCSR0A = (1< + +uint8_t uart_getc(); +uint8_t uart_putc(unsigned char c);