Add basic button functionality and uart code
This commit is contained in:
parent
94a88ce80d
commit
ed6e98095d
63
Makefile
Normal file
63
Makefile
Normal file
@ -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)
|
||||||
|
|
114
main.c
Normal file
114
main.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
82
uart.c
Normal file
82
uart.c
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <util/atomic.h>
|
||||||
|
|
||||||
|
#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<<U2X0);
|
||||||
|
UCSR0B = (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
|
||||||
|
UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); // 8N1
|
||||||
|
UBRR0 = BAUD_PRESCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __attribute__ ((naked)) __attribute__ ((section (".fini5"))) uart_deinit() {
|
||||||
|
while ((UCSR0B & (1 << UDRIE0))) {};
|
||||||
|
while (!(UCSR0A & (1 << TXC0))) {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// RX Facilities
|
||||||
|
ISR(USART_RX_vect) {
|
||||||
|
uint8_t c = UDR0;
|
||||||
|
|
||||||
|
if (((uart_rxbuf.w - uart_rxbuf.r) & (UART_BUFSIZE - 1)) == 1) return;
|
||||||
|
uart_rxbuf.data[uart_rxbuf.w++] = c;
|
||||||
|
uart_rxbuf.w = uart_rxbuf.w & (UART_BUFSIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t uart_getc() {
|
||||||
|
uint8_t c;
|
||||||
|
while (uart_rxbuf.w == uart_rxbuf.r) {};
|
||||||
|
|
||||||
|
// Disable interrupt to avoid race condition
|
||||||
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
c = uart_rxbuf.data[uart_rxbuf.r++];
|
||||||
|
uart_rxbuf.r = uart_rxbuf.r & (UART_BUFSIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TX Facilities
|
||||||
|
ISR(USART_UDRE_vect) {
|
||||||
|
if ((uart_txbuf.w != uart_txbuf.r) && (UCSR0B & (1<<TXEN0))) {
|
||||||
|
UDR0 = uart_txbuf.data[uart_txbuf.r++];
|
||||||
|
uart_txbuf.r = uart_txbuf.r & (UART_BUFSIZE - 1);
|
||||||
|
} else {
|
||||||
|
UCSR0B &= ~(1<<UDRIE0); // UDRE off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t uart_putc(unsigned char c) {
|
||||||
|
while (((uart_txbuf.r - uart_txbuf.w) & (UART_BUFSIZE - 1)) == 1) {};
|
||||||
|
|
||||||
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
uart_txbuf.data[uart_txbuf.w++] = c;
|
||||||
|
uart_txbuf.w = uart_txbuf.w & (UART_BUFSIZE - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
UCSR0B |= (1<<UDRIE0); // UDRE on
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user