parent
f928a4ff8c
commit
033273b9d1
@ -0,0 +1,5 @@ |
|||||||
|
**Files in this folder are experimental, work-in-progress projects.** |
||||||
|
|
||||||
|
Do not expect them to work. |
||||||
|
|
||||||
|
For finished stuff, look into the /projects folder. |
@ -0,0 +1,147 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
|
||||||
|
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c iopins.c stream.c adc.c dht11.c sonar.c onewire.c
|
||||||
|
#Files that need config file:
|
||||||
|
# EXTRA_SOURCE_FILES += lcd.c
|
||||||
|
# EXTRA_SOURCE_FILES += color.c wsrgb.c
|
||||||
|
# EXTRA_SOURCE_FILES += debouce.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
fser: all flash ser |
||||||
|
|
||||||
|
ser: |
||||||
|
gtkterm -p /dev/ttyUSB0
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,35 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "lib/iopins.h" |
||||||
|
#include "lib/uart.h" |
||||||
|
#include "lib/stream.h" |
||||||
|
#include "lib/dht11.h" |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
uart_init(9600); |
||||||
|
uart_puts_P(PSTR("*** DHT11 test ***\r\n")); |
||||||
|
|
||||||
|
while(1) |
||||||
|
{ |
||||||
|
dht11_result_t result; |
||||||
|
|
||||||
|
if (dht11_read(2, &result)) { |
||||||
|
// Temperature
|
||||||
|
put_i8(uart, result.temp); |
||||||
|
uart_puts_P(PSTR(" °C, ")); |
||||||
|
// Humidity
|
||||||
|
put_i8(uart, result.rh); |
||||||
|
uart_puts_P(PSTR(" %r.H\r\n")); |
||||||
|
} else { |
||||||
|
uart_puts_P(PSTR("Read error!\r\n")); |
||||||
|
} |
||||||
|
|
||||||
|
_delay_ms(500); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,137 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c uart_ansi.c iopins.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
Binary file not shown.
@ -0,0 +1,276 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#include "calc.h" |
||||||
|
#include "iopins.h" |
||||||
|
|
||||||
|
|
||||||
|
void set_dir_n(const uint8_t pin, const uint8_t d) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: set_dir(0, d); return; |
||||||
|
case 1: set_dir(1, d); return; |
||||||
|
case 2: set_dir(2, d); return; |
||||||
|
case 3: set_dir(3, d); return; |
||||||
|
case 4: set_dir(4, d); return; |
||||||
|
case 5: set_dir(5, d); return; |
||||||
|
case 6: set_dir(6, d); return; |
||||||
|
case 7: set_dir(7, d); return; |
||||||
|
case 8: set_dir(8, d); return; |
||||||
|
case 9: set_dir(9, d); return; |
||||||
|
case 10: set_dir(10, d); return; |
||||||
|
case 11: set_dir(11, d); return; |
||||||
|
case 12: set_dir(12, d); return; |
||||||
|
case 13: set_dir(13, d); return; |
||||||
|
case 14: set_dir(14, d); return; |
||||||
|
case 15: set_dir(15, d); return; |
||||||
|
case 16: set_dir(16, d); return; |
||||||
|
case 17: set_dir(17, d); return; |
||||||
|
case 18: set_dir(18, d); return; |
||||||
|
case 19: set_dir(19, d); return; |
||||||
|
case 20: set_dir(20, d); return; |
||||||
|
case 21: set_dir(21, d); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void as_input_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: as_input(0); return; |
||||||
|
case 1: as_input(1); return; |
||||||
|
case 2: as_input(2); return; |
||||||
|
case 3: as_input(3); return; |
||||||
|
case 4: as_input(4); return; |
||||||
|
case 5: as_input(5); return; |
||||||
|
case 6: as_input(6); return; |
||||||
|
case 7: as_input(7); return; |
||||||
|
case 8: as_input(8); return; |
||||||
|
case 9: as_input(9); return; |
||||||
|
case 10: as_input(10); return; |
||||||
|
case 11: as_input(11); return; |
||||||
|
case 12: as_input(12); return; |
||||||
|
case 13: as_input(13); return; |
||||||
|
case 14: as_input(14); return; |
||||||
|
case 15: as_input(15); return; |
||||||
|
case 16: as_input(16); return; |
||||||
|
case 17: as_input(17); return; |
||||||
|
case 18: as_input(18); return; |
||||||
|
case 19: as_input(19); return; |
||||||
|
case 20: as_input(20); return; |
||||||
|
case 21: as_input(21); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void as_input_pu_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: as_input_pu(0); return; |
||||||
|
case 1: as_input_pu(1); return; |
||||||
|
case 2: as_input_pu(2); return; |
||||||
|
case 3: as_input_pu(3); return; |
||||||
|
case 4: as_input_pu(4); return; |
||||||
|
case 5: as_input_pu(5); return; |
||||||
|
case 6: as_input_pu(6); return; |
||||||
|
case 7: as_input_pu(7); return; |
||||||
|
case 8: as_input_pu(8); return; |
||||||
|
case 9: as_input_pu(9); return; |
||||||
|
case 10: as_input_pu(10); return; |
||||||
|
case 11: as_input_pu(11); return; |
||||||
|
case 12: as_input_pu(12); return; |
||||||
|
case 13: as_input_pu(13); return; |
||||||
|
case 14: as_input_pu(14); return; |
||||||
|
case 15: as_input_pu(15); return; |
||||||
|
case 16: as_input_pu(16); return; |
||||||
|
case 17: as_input_pu(17); return; |
||||||
|
case 18: as_input_pu(18); return; |
||||||
|
case 19: as_input_pu(19); return; |
||||||
|
case 20: as_input_pu(20); return; |
||||||
|
case 21: as_input_pu(21); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void as_output_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: as_output(0); return; |
||||||
|
case 1: as_output(1); return; |
||||||
|
case 2: as_output(2); return; |
||||||
|
case 3: as_output(3); return; |
||||||
|
case 4: as_output(4); return; |
||||||
|
case 5: as_output(5); return; |
||||||
|
case 6: as_output(6); return; |
||||||
|
case 7: as_output(7); return; |
||||||
|
case 8: as_output(8); return; |
||||||
|
case 9: as_output(9); return; |
||||||
|
case 10: as_output(10); return; |
||||||
|
case 11: as_output(11); return; |
||||||
|
case 12: as_output(12); return; |
||||||
|
case 13: as_output(13); return; |
||||||
|
case 14: as_output(14); return; |
||||||
|
case 15: as_output(15); return; |
||||||
|
case 16: as_output(16); return; |
||||||
|
case 17: as_output(17); return; |
||||||
|
case 18: as_output(18); return; |
||||||
|
case 19: as_output(19); return; |
||||||
|
case 20: as_output(20); return; |
||||||
|
case 21: as_output(21); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void set_pin_n(const uint8_t pin, const uint8_t v) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: set_pin(0, v); return; |
||||||
|
case 1: set_pin(1, v); return; |
||||||
|
case 2: set_pin(2, v); return; |
||||||
|
case 3: set_pin(3, v); return; |
||||||
|
case 4: set_pin(4, v); return; |
||||||
|
case 5: set_pin(5, v); return; |
||||||
|
case 6: set_pin(6, v); return; |
||||||
|
case 7: set_pin(7, v); return; |
||||||
|
case 8: set_pin(8, v); return; |
||||||
|
case 9: set_pin(9, v); return; |
||||||
|
case 10: set_pin(10, v); return; |
||||||
|
case 11: set_pin(11, v); return; |
||||||
|
case 12: set_pin(12, v); return; |
||||||
|
case 13: set_pin(13, v); return; |
||||||
|
case 14: set_pin(14, v); return; |
||||||
|
case 15: set_pin(15, v); return; |
||||||
|
case 16: set_pin(16, v); return; |
||||||
|
case 17: set_pin(17, v); return; |
||||||
|
case 18: set_pin(18, v); return; |
||||||
|
case 19: set_pin(19, v); return; |
||||||
|
case 20: set_pin(20, v); return; |
||||||
|
case 21: set_pin(21, v); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void set_low_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: set_low(0); return; |
||||||
|
case 1: set_low(1); return; |
||||||
|
case 2: set_low(2); return; |
||||||
|
case 3: set_low(3); return; |
||||||
|
case 4: set_low(4); return; |
||||||
|
case 5: set_low(5); return; |
||||||
|
case 6: set_low(6); return; |
||||||
|
case 7: set_low(7); return; |
||||||
|
case 8: set_low(8); return; |
||||||
|
case 9: set_low(9); return; |
||||||
|
case 10: set_low(10); return; |
||||||
|
case 11: set_low(11); return; |
||||||
|
case 12: set_low(12); return; |
||||||
|
case 13: set_low(13); return; |
||||||
|
case 14: set_low(14); return; |
||||||
|
case 15: set_low(15); return; |
||||||
|
case 16: set_low(16); return; |
||||||
|
case 17: set_low(17); return; |
||||||
|
case 18: set_low(18); return; |
||||||
|
case 19: set_low(19); return; |
||||||
|
case 20: set_low(20); return; |
||||||
|
case 21: set_low(21); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void set_high_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: set_high(0); return; |
||||||
|
case 1: set_high(1); return; |
||||||
|
case 2: set_high(2); return; |
||||||
|
case 3: set_high(3); return; |
||||||
|
case 4: set_high(4); return; |
||||||
|
case 5: set_high(5); return; |
||||||
|
case 6: set_high(6); return; |
||||||
|
case 7: set_high(7); return; |
||||||
|
case 8: set_high(8); return; |
||||||
|
case 9: set_high(9); return; |
||||||
|
case 10: set_high(10); return; |
||||||
|
case 11: set_high(11); return; |
||||||
|
case 12: set_high(12); return; |
||||||
|
case 13: set_high(13); return; |
||||||
|
case 14: set_high(14); return; |
||||||
|
case 15: set_high(15); return; |
||||||
|
case 16: set_high(16); return; |
||||||
|
case 17: set_high(17); return; |
||||||
|
case 18: set_high(18); return; |
||||||
|
case 19: set_high(19); return; |
||||||
|
case 20: set_high(20); return; |
||||||
|
case 21: set_high(21); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void toggle_pin_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: toggle_pin(0); return; |
||||||
|
case 1: toggle_pin(1); return; |
||||||
|
case 2: toggle_pin(2); return; |
||||||
|
case 3: toggle_pin(3); return; |
||||||
|
case 4: toggle_pin(4); return; |
||||||
|
case 5: toggle_pin(5); return; |
||||||
|
case 6: toggle_pin(6); return; |
||||||
|
case 7: toggle_pin(7); return; |
||||||
|
case 8: toggle_pin(8); return; |
||||||
|
case 9: toggle_pin(9); return; |
||||||
|
case 10: toggle_pin(10); return; |
||||||
|
case 11: toggle_pin(11); return; |
||||||
|
case 12: toggle_pin(12); return; |
||||||
|
case 13: toggle_pin(13); return; |
||||||
|
case 14: toggle_pin(14); return; |
||||||
|
case 15: toggle_pin(15); return; |
||||||
|
case 16: toggle_pin(16); return; |
||||||
|
case 17: toggle_pin(17); return; |
||||||
|
case 18: toggle_pin(18); return; |
||||||
|
case 19: toggle_pin(19); return; |
||||||
|
case 20: toggle_pin(20); return; |
||||||
|
case 21: toggle_pin(21); return; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool get_pin_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
switch(pin) { |
||||||
|
case 0: return get_pin(0); |
||||||
|
case 1: return get_pin(1); |
||||||
|
case 2: return get_pin(2); |
||||||
|
case 3: return get_pin(3); |
||||||
|
case 4: return get_pin(4); |
||||||
|
case 5: return get_pin(5); |
||||||
|
case 6: return get_pin(6); |
||||||
|
case 7: return get_pin(7); |
||||||
|
case 8: return get_pin(8); |
||||||
|
case 9: return get_pin(9); |
||||||
|
case 10: return get_pin(10); |
||||||
|
case 11: return get_pin(11); |
||||||
|
case 12: return get_pin(12); |
||||||
|
case 13: return get_pin(13); |
||||||
|
case 14: return get_pin(14); |
||||||
|
case 15: return get_pin(15); |
||||||
|
case 16: return get_pin(16); |
||||||
|
case 17: return get_pin(17); |
||||||
|
case 18: return get_pin(18); |
||||||
|
case 19: return get_pin(19); |
||||||
|
case 20: return get_pin(20); |
||||||
|
case 21: return get_pin(21); |
||||||
|
} |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool is_low_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
return !get_pin_n(pin); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool is_high_n(const uint8_t pin) |
||||||
|
{ |
||||||
|
return get_pin_n(pin); |
||||||
|
} |
@ -0,0 +1,190 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <avr/io.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#include "calc.h" |
||||||
|
|
||||||
|
/** Pin numbering reference */ |
||||||
|
#define D0 0 |
||||||
|
#define D1 1 |
||||||
|
#define D2 2 |
||||||
|
#define D3 3 |
||||||
|
#define D4 4 |
||||||
|
#define D5 5 |
||||||
|
#define D6 6 |
||||||
|
#define D7 7 |
||||||
|
#define D8 8 |
||||||
|
#define D9 9 |
||||||
|
#define D10 10 |
||||||
|
#define D11 11 |
||||||
|
#define D12 12 |
||||||
|
#define D13 13 |
||||||
|
#define D14 14 |
||||||
|
#define D15 15 |
||||||
|
#define D16 16 |
||||||
|
#define D17 17 |
||||||
|
#define D18 18 |
||||||
|
#define D19 19 |
||||||
|
#define D20 20 |
||||||
|
#define D21 21 |
||||||
|
#define A0 14 |
||||||
|
#define A1 15 |
||||||
|
#define A2 16 |
||||||
|
#define A3 17 |
||||||
|
#define A4 18 |
||||||
|
#define A5 19 |
||||||
|
#define A6 20 |
||||||
|
#define A7 21 |
||||||
|
|
||||||
|
|
||||||
|
/** Set pin direction */ |
||||||
|
#define set_dir(pin, d) set_bit(_DDR_##pin, _PN_##pin, d) |
||||||
|
void set_dir_n(const uint8_t pin, const uint8_t d); |
||||||
|
|
||||||
|
|
||||||
|
/** Configure pin as input */ |
||||||
|
#define as_input(pin) cbi(_DDR_##pin, _PN_##pin) |
||||||
|
void as_input_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** Configure pin as input, with pull-up enabled */ |
||||||
|
#define as_input_pu(pin) { as_input(pin); set_high(pin); } |
||||||
|
void as_input_pu_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** Configure pin as output */ |
||||||
|
#define as_output(pin) sbi(_DDR_##pin, _PN_##pin) |
||||||
|
void as_output_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** Write value to a pin */ |
||||||
|
#define set_pin(pin, v) set_bit(_PORT_##pin, _PN_##pin, v) |
||||||
|
void set_pin_n(const uint8_t pin, const uint8_t v); |
||||||
|
|
||||||
|
|
||||||
|
/** Write 0 to a pin */ |
||||||
|
#define set_low(pin) cbi(_PORT_##pin, _PN_##pin) |
||||||
|
void set_low_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** Write 1 to a pin */ |
||||||
|
#define set_high(pin) sbi(_PORT_##pin, _PN_##pin) |
||||||
|
void set_high_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** Toggle a pin state */ |
||||||
|
#define toggle_pin(pin) sbi(_PIN_##pin, _PN_##pin) |
||||||
|
void toggle_pin_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** Read a pin value */ |
||||||
|
#define get_pin(pin) get_bit(_PIN_##pin, _PN_##pin) |
||||||
|
bool get_pin_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** CHeck if pin is low */ |
||||||
|
#define is_low(pin) (get_pin(pin) == 0) |
||||||
|
bool is_low_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
/** CHeck if pin is high */ |
||||||
|
#define is_high(pin) (get_pin(pin) != 0) |
||||||
|
bool is_high_n(const uint8_t pin); |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Helper macros
|
||||||
|
|
||||||
|
#define _PORT_0 PORTD |
||||||
|
#define _PORT_1 PORTD |
||||||
|
#define _PORT_2 PORTD |
||||||
|
#define _PORT_3 PORTD |
||||||
|
#define _PORT_4 PORTD |
||||||
|
#define _PORT_5 PORTD |
||||||
|
#define _PORT_6 PORTD |
||||||
|
#define _PORT_7 PORTD |
||||||
|
#define _PORT_8 PORTB |
||||||
|
#define _PORT_9 PORTB |
||||||
|
#define _PORT_10 PORTB |
||||||
|
#define _PORT_11 PORTB |
||||||
|
#define _PORT_12 PORTB |
||||||
|
#define _PORT_13 PORTB |
||||||
|
#define _PORT_14 PORTC |
||||||
|
#define _PORT_15 PORTC |
||||||
|
#define _PORT_16 PORTC |
||||||
|
#define _PORT_17 PORTC |
||||||
|
#define _PORT_18 PORTC |
||||||
|
#define _PORT_19 PORTC |
||||||
|
#define _PORT_20 PORTC |
||||||
|
#define _PORT_21 PORTC |
||||||
|
|
||||||
|
#define _PIN_0 PIND |
||||||
|
#define _PIN_1 PIND |
||||||
|
#define _PIN_2 PIND |
||||||
|
#define _PIN_3 PIND |
||||||
|
#define _PIN_4 PIND |
||||||
|
#define _PIN_5 PIND |
||||||
|
#define _PIN_6 PIND |
||||||
|
#define _PIN_7 PIND |
||||||
|
#define _PIN_8 PINB |
||||||
|
#define _PIN_9 PINB |
||||||
|
#define _PIN_10 PINB |
||||||
|
#define _PIN_11 PINB |
||||||
|
#define _PIN_12 PINB |
||||||
|
#define _PIN_13 PINB |
||||||
|
#define _PIN_14 PINC |
||||||
|
#define _PIN_15 PINC |
||||||
|
#define _PIN_16 PINC |
||||||
|
#define _PIN_17 PINC |
||||||
|
#define _PIN_18 PINC |
||||||
|
#define _PIN_19 PINC |
||||||
|
#define _PIN_20 PINC |
||||||
|
#define _PIN_21 PINC |
||||||
|
|
||||||
|
#define _DDR_0 DDRD |
||||||
|
#define _DDR_1 DDRD |
||||||
|
#define _DDR_2 DDRD |
||||||
|
#define _DDR_3 DDRD |
||||||
|
#define _DDR_4 DDRD |
||||||
|
#define _DDR_5 DDRD |
||||||
|
#define _DDR_6 DDRD |
||||||
|
#define _DDR_7 DDRD |
||||||
|
#define _DDR_8 DDRB |
||||||
|
#define _DDR_9 DDRB |
||||||
|
#define _DDR_10 DDRB |
||||||
|
#define _DDR_11 DDRB |
||||||
|
#define _DDR_12 DDRB |
||||||
|
#define _DDR_13 DDRB |
||||||
|
#define _DDR_14 DDRC |
||||||
|
#define _DDR_15 DDRC |
||||||
|
#define _DDR_16 DDRC |
||||||
|
#define _DDR_17 DDRC |
||||||
|
#define _DDR_18 DDRC |
||||||
|
#define _DDR_19 DDRC |
||||||
|
#define _DDR_20 DDRC |
||||||
|
#define _DDR_21 DDRC |
||||||
|
|
||||||
|
#define _PN_0 0 |
||||||
|
#define _PN_1 1 |
||||||
|
#define _PN_2 2 |
||||||
|
#define _PN_3 3 |
||||||
|
#define _PN_4 4 |
||||||
|
#define _PN_5 5 |
||||||
|
#define _PN_6 6 |
||||||
|
#define _PN_7 7 |
||||||
|
#define _PN_8 0 |
||||||
|
#define _PN_9 1 |
||||||
|
#define _PN_10 2 |
||||||
|
#define _PN_11 3 |
||||||
|
#define _PN_12 4 |
||||||
|
#define _PN_13 5 |
||||||
|
#define _PN_14 0 |
||||||
|
#define _PN_15 1 |
||||||
|
#define _PN_16 2 |
||||||
|
#define _PN_17 3 |
||||||
|
#define _PN_18 4 |
||||||
|
#define _PN_19 5 |
||||||
|
#define _PN_20 6 |
||||||
|
#define _PN_21 7 |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,27 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "lib/iopins.h" |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
for (int i = 2; i <= 5; i++) { |
||||||
|
as_output_n(i); |
||||||
|
} |
||||||
|
|
||||||
|
as_input_pu(12); |
||||||
|
|
||||||
|
while(1) { |
||||||
|
for (int i = 2; i <= 5; i++) { |
||||||
|
if (is_low(12)) { |
||||||
|
set_high_n(i); |
||||||
|
_delay_ms(100); |
||||||
|
set_low_n(i); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,167 @@ |
|||||||
|
|
||||||
|
MCU = atmega328p
|
||||||
|
|
||||||
|
F_CPU = 16000000
|
||||||
|
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
MAIN = main.c
|
||||||
|
|
||||||
|
## If you've split your program into multiple files,
|
||||||
|
## include the additional .c source (in same directory) here
|
||||||
|
## (and include the .h files in your foo.c)
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
## Here you can link to one more directory (and multiple .c files)
|
||||||
|
# EXTRA_SOURCE_DIR = ../AVR-Programming-Library/
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
EXTRA_SOURCE_FILES = debounce.c lcd.c adc.c
|
||||||
|
|
||||||
|
EXTRA_CFLAGS =
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Programmer Defaults ##########
|
||||||
|
########## Set up once, then forget about it ##########
|
||||||
|
########## (Can override. See bottom of file.) ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
#19200
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Makefile Magic! ##########
|
||||||
|
########## Summary: ##########
|
||||||
|
########## We want a .hex file ##########
|
||||||
|
########## Compile source files into .elf ##########
|
||||||
|
########## Convert .elf file into .hex ##########
|
||||||
|
########## You shouldn't need to edit below. ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## Compilation options, type man avr-gcc if you're curious.
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
CFLAGS += $(EXTRA_CFLAGS)
|
||||||
|
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
# CFLAGS += -lm
|
||||||
|
## CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
## CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
|
||||||
|
## Lump target and extra source files together
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
## List of all header files
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
|
||||||
|
## For every .c file, compile an .o object file
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
## Generic Makefile targets. (Only .hex file is necessary)
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
# Optionally create listing file from .elf
|
||||||
|
# This creates approximate assembly-language equivalent of your code.
|
||||||
|
# Useful for debugging time-sensitive bits,
|
||||||
|
# or making sure the compiler does what you want.
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
|
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Optionally show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
squeaky_clean: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Programmer-specific details ##########
|
||||||
|
########## Flashing code to AVR using avrdude ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flash_eeprom: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
terminal: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
|
||||||
|
flash_arduino: PROGRAMMER_TYPE = arduino |
||||||
|
flash_arduino: PROGRAMMER_ARGS = |
||||||
|
flash_arduino: flash |
||||||
|
|
||||||
|
flash_dragon_isp: PROGRAMMER_TYPE = dragon_isp |
||||||
|
flash_dragon_isp: PROGRAMMER_ARGS = |
||||||
|
flash_dragon_isp: flash |
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Fuse settings and suitable defaults ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
## Generic
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
## Called with no extra definitions, sets to defaults
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1,10 @@ |
|||||||
|
Snake for HD44780 |
||||||
|
================= |
||||||
|
|
||||||
|
This is a Snake game (known from old Nokia phones) played on a character display with HD44780. |
||||||
|
|
||||||
|
Program tested on Arduino Pro Mini (flashed with avrdude using the Makefile). |
||||||
|
|
||||||
|
**Connections** are `#define`d in `main.c`, board size and snake speed can also be adjusted. No external parts except the display and buttons required. |
||||||
|
|
||||||
|
Best works with a gamepad, but any buttons will work. |
@ -0,0 +1,5 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
// Config file for debouncer
|
||||||
|
#define DEBO_CHANNELS 6 |
||||||
|
#define DEBO_TICKS 1 |
@ -0,0 +1,13 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
// Config file for LCD.
|
||||||
|
|
||||||
|
#include "lib/arduino_pins.h" |
||||||
|
|
||||||
|
#define LCD_RS D2 |
||||||
|
#define LCD_RW D3 |
||||||
|
#define LCD_E D4 |
||||||
|
#define LCD_D4 D5 |
||||||
|
#define LCD_D5 D6 |
||||||
|
#define LCD_D6 D7 |
||||||
|
#define LCD_D7 D8 |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,429 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include "lib/meta.h" |
||||||
|
#include "lib/arduino_pins.h" |
||||||
|
#include "lib/calc.h" |
||||||
|
#include "lib/adc.h" |
||||||
|
#include "lib/lcd.h" |
||||||
|
#include "lib/debounce.h" |
||||||
|
|
||||||
|
// Buttons (to ground)
|
||||||
|
#define BTN_LEFT A0 |
||||||
|
#define BTN_RIGHT A1 |
||||||
|
#define BTN_UP A2 |
||||||
|
#define BTN_DOWN A3 |
||||||
|
#define BTN_PAUSE A4 |
||||||
|
#define BTN_RESTART A5 |
||||||
|
|
||||||
|
// Debouncer channels for buttons
|
||||||
|
// (Must be added in this order to debouncer)
|
||||||
|
#define D_LEFT 0 |
||||||
|
#define D_RIGHT 1 |
||||||
|
#define D_UP 2 |
||||||
|
#define D_DOWN 3 |
||||||
|
#define D_PAUSE 4 |
||||||
|
#define D_RESTART 5 |
||||||
|
|
||||||
|
// Board size (!!! rows = 2x number of display lines, max 2*4 = 8 !!!)
|
||||||
|
#define ROWS 8 |
||||||
|
#define COLS 20 |
||||||
|
|
||||||
|
// Delay between snake steps, in 10 ms
|
||||||
|
#define STEP_DELAY 24 |
||||||
|
|
||||||
|
// proto
|
||||||
|
void update(); |
||||||
|
void init_cgram(); |
||||||
|
void init_gameboard(); |
||||||
|
|
||||||
|
void init() |
||||||
|
{ |
||||||
|
// Randomize RNG
|
||||||
|
adc_init(); |
||||||
|
srand(adc_read_word(3)); |
||||||
|
|
||||||
|
// Init LCD
|
||||||
|
lcd_init(); |
||||||
|
init_cgram(); // load default glyphs
|
||||||
|
|
||||||
|
// Init game board.
|
||||||
|
init_gameboard(); |
||||||
|
|
||||||
|
// gamepad buttons
|
||||||
|
as_input_pu(BTN_LEFT); |
||||||
|
as_input_pu(BTN_RIGHT); |
||||||
|
as_input_pu(BTN_UP); |
||||||
|
as_input_pu(BTN_DOWN); |
||||||
|
as_input_pu(BTN_PAUSE); |
||||||
|
as_input_pu(BTN_RESTART); |
||||||
|
|
||||||
|
// add buttons to debouncer
|
||||||
|
debo_add_rev(BTN_LEFT); |
||||||
|
debo_add_rev(BTN_RIGHT); |
||||||
|
debo_add_rev(BTN_UP); |
||||||
|
debo_add_rev(BTN_DOWN); |
||||||
|
debo_add_rev(BTN_PAUSE); |
||||||
|
debo_add_rev(BTN_RESTART); |
||||||
|
|
||||||
|
// setup timer
|
||||||
|
TCCR0A = _BV(WGM01); // CTC
|
||||||
|
TCCR0B = _BV(CS02) | _BV(CS00); // prescaler 1024
|
||||||
|
OCR0A = 156; // interrupt every 10 ms
|
||||||
|
sbi(TIMSK0, OCIE0A); |
||||||
|
sei(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** timer 0 interrupt vector */ |
||||||
|
ISR(TIMER0_COMPA_vect) |
||||||
|
{ |
||||||
|
debo_tick(); // poll debouncer
|
||||||
|
update(); // update and display
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// sub-glyphs
|
||||||
|
#define _HEAD_ 15, 21, 21, 30 |
||||||
|
#define _BODY_ 15, 31, 31, 30 |
||||||
|
#define _FOOD_ 10, 21, 17, 14 |
||||||
|
//14, 17, 17, 14
|
||||||
|
#define _NONE_ 0, 0, 0, 0 |
||||||
|
|
||||||
|
// complete glyphs for loading into memory
|
||||||
|
|
||||||
|
// Only one food & one head glyph have to be loaded at a time.
|
||||||
|
|
||||||
|
// Body - Body
|
||||||
|
const uint8_t SYMBOL_BB[] PROGMEM = {_BODY_, _BODY_}; |
||||||
|
|
||||||
|
// Body - None
|
||||||
|
const uint8_t SYMBOL_BX[] PROGMEM = {_BODY_, _NONE_}; |
||||||
|
const uint8_t SYMBOL_XB[] PROGMEM = {_NONE_, _BODY_}; |
||||||
|
|
||||||
|
// Head - None
|
||||||
|
const uint8_t SYMBOL_HX[] PROGMEM = {_HEAD_, _NONE_}; |
||||||
|
const uint8_t SYMBOL_XH[] PROGMEM = {_NONE_, _HEAD_}; |
||||||
|
|
||||||
|
// Body - Head
|
||||||
|
const uint8_t SYMBOL_BH[] PROGMEM = {_BODY_, _HEAD_}; |
||||||
|
const uint8_t SYMBOL_HB[] PROGMEM = {_HEAD_, _BODY_}; |
||||||
|
|
||||||
|
// Head - Food
|
||||||
|
const uint8_t SYMBOL_HF[] PROGMEM = {_HEAD_, _FOOD_}; |
||||||
|
const uint8_t SYMBOL_FH[] PROGMEM = {_FOOD_, _HEAD_}; |
||||||
|
|
||||||
|
// Food - None
|
||||||
|
const uint8_t SYMBOL_FX[] PROGMEM = {_FOOD_, _NONE_}; |
||||||
|
const uint8_t SYMBOL_XF[] PROGMEM = {_NONE_, _FOOD_}; |
||||||
|
|
||||||
|
// Body - Food
|
||||||
|
const uint8_t SYMBOL_BF[] PROGMEM = {_BODY_, _FOOD_}; |
||||||
|
const uint8_t SYMBOL_FB[] PROGMEM = {_FOOD_, _BODY_}; |
||||||
|
|
||||||
|
|
||||||
|
// board block (snake, food...)
|
||||||
|
typedef enum { |
||||||
|
bEMPTY = 0x00, |
||||||
|
bHEAD = 0x01, |
||||||
|
bFOOD = 0x02, |
||||||
|
bBODY_LEFT = 0x80, |
||||||
|
bBODY_RIGHT = 0x81, |
||||||
|
bBODY_UP = 0x82, |
||||||
|
bBODY_DOWN = 0x83, |
||||||
|
} block_t; |
||||||
|
|
||||||
|
// Snake direction
|
||||||
|
typedef enum { |
||||||
|
dLEFT = 0x00, |
||||||
|
dRIGHT = 0x01, |
||||||
|
dUP = 0x02, |
||||||
|
dDOWN = 0x03, |
||||||
|
} dir_t; |
||||||
|
|
||||||
|
// Coordinate on board
|
||||||
|
typedef struct { |
||||||
|
int8_t x; |
||||||
|
int8_t y; |
||||||
|
} coord_t; |
||||||
|
|
||||||
|
#define is_body(blk) (((blk) & 0x80) != 0) |
||||||
|
#define mk_body_dir(dir) (0x80 + (dir)) |
||||||
|
|
||||||
|
// compare two coords
|
||||||
|
#define coord_eq(a, b) (((a).x == (b).x) && ((a).y == (b).y)) |
||||||
|
|
||||||
|
|
||||||
|
bool crashed; |
||||||
|
uint8_t snake_len; |
||||||
|
|
||||||
|
// y, x indexing
|
||||||
|
block_t board[ROWS][COLS]; |
||||||
|
|
||||||
|
coord_t head_pos; |
||||||
|
coord_t tail_pos; |
||||||
|
dir_t head_dir; |
||||||
|
|
||||||
|
const uint8_t CODE_BB = 0; |
||||||
|
const uint8_t CODE_BX = 1; |
||||||
|
const uint8_t CODE_XB = 2; |
||||||
|
const uint8_t CODE_H = 3; // glyph with head, dynamic
|
||||||
|
const uint8_t CODE_F = 4; // glyph with food, dynamic
|
||||||
|
const uint8_t CODE_XX = 32; // space
|
||||||
|
|
||||||
|
|
||||||
|
// Set a block in board
|
||||||
|
#define set_block_xy(x, y, block) do { board[y][x] = (block); } while(0) |
||||||
|
#define get_block_xy(x, y) board[y][x] |
||||||
|
#define get_block(pos) get_block_xy((pos).x, (pos).y) |
||||||
|
#define set_block(pos, block) set_block_xy((pos).x, (pos).y, (block)) |
||||||
|
|
||||||
|
|
||||||
|
void init_cgram() |
||||||
|
{ |
||||||
|
// those will be always the same
|
||||||
|
lcd_glyph_P(CODE_BB, SYMBOL_BB); |
||||||
|
lcd_glyph_P(CODE_BX, SYMBOL_BX); |
||||||
|
lcd_glyph_P(CODE_XB, SYMBOL_XB); |
||||||
|
lcd_glyph_P(5, SYMBOL_XF); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void place_food() |
||||||
|
{ |
||||||
|
while(1) { |
||||||
|
const uint8_t xx = rand() % COLS; |
||||||
|
const uint8_t yy = rand() % ROWS; |
||||||
|
|
||||||
|
if (get_block_xy(xx, yy) == bEMPTY) { |
||||||
|
set_block_xy(xx, yy, bFOOD); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void init_gameboard() |
||||||
|
{ |
||||||
|
//erase the board
|
||||||
|
for (uint8_t x = 0; x < COLS; x++) { |
||||||
|
for (uint8_t y = 0; y < ROWS; y++) { |
||||||
|
set_block_xy(x, y, bEMPTY); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
lcd_clear(); |
||||||
|
|
||||||
|
tail_pos = (coord_t) {.x = 0, .y = 0}; |
||||||
|
|
||||||
|
set_block_xy(0, 0, bBODY_RIGHT); |
||||||
|
set_block_xy(1, 0, bBODY_RIGHT); |
||||||
|
set_block_xy(2, 0, bBODY_RIGHT); |
||||||
|
set_block_xy(3, 0, bHEAD); |
||||||
|
|
||||||
|
head_pos = (coord_t) {.x = 3, .y = 0}; |
||||||
|
|
||||||
|
snake_len = 4; // includes head
|
||||||
|
|
||||||
|
head_dir = dRIGHT; |
||||||
|
crashed = false; |
||||||
|
|
||||||
|
place_food(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
uint8_t presc = 0; |
||||||
|
|
||||||
|
bool restart_held; |
||||||
|
bool pause_held; |
||||||
|
bool paused; |
||||||
|
void update() |
||||||
|
{ |
||||||
|
if (debo_get_pin(D_RESTART)) { |
||||||
|
|
||||||
|
if (!restart_held) { |
||||||
|
// restart
|
||||||
|
init_gameboard(); |
||||||
|
presc = 0; |
||||||
|
restart_held = true; |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
restart_held = false; |
||||||
|
} |
||||||
|
|
||||||
|
if (debo_get_pin(D_PAUSE)) { |
||||||
|
|
||||||
|
if (!pause_held) { |
||||||
|
paused ^= true; |
||||||
|
pause_held = true; |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
pause_held = false; |
||||||
|
} |
||||||
|
|
||||||
|
if(!crashed && !paused) { |
||||||
|
|
||||||
|
// resolve movement direction
|
||||||
|
if (debo_get_pin(D_LEFT)) |
||||||
|
head_dir = dLEFT; |
||||||
|
else if (debo_get_pin(D_RIGHT)) |
||||||
|
head_dir = dRIGHT; |
||||||
|
else if (debo_get_pin(D_UP)) |
||||||
|
head_dir = dUP; |
||||||
|
else if (debo_get_pin(D_DOWN)) |
||||||
|
head_dir = dDOWN; |
||||||
|
|
||||||
|
// time's up for a move
|
||||||
|
if (presc++ == STEP_DELAY) { |
||||||
|
presc = 0; |
||||||
|
|
||||||
|
// move snake
|
||||||
|
const coord_t oldpos = head_pos; |
||||||
|
|
||||||
|
switch (head_dir) { |
||||||
|
case dLEFT: head_pos.x--; break; |
||||||
|
case dRIGHT: head_pos.x++; break; |
||||||
|
case dUP: head_pos.y--; break; |
||||||
|
case dDOWN: head_pos.y++; break; |
||||||
|
} |
||||||
|
|
||||||
|
bool do_move = false; |
||||||
|
bool do_grow = false; |
||||||
|
|
||||||
|
if (head_pos.x < 0 || head_pos.x >= COLS || head_pos.y < 0 || head_pos.y >= ROWS) { |
||||||
|
// ouch, a wall!
|
||||||
|
crashed = true; |
||||||
|
} else { |
||||||
|
// check if tile occupied or not
|
||||||
|
if (coord_eq(head_pos, tail_pos)) { |
||||||
|
// head moved in previous tail, that's OK.
|
||||||
|
do_move = true; |
||||||
|
} else { |
||||||
|
// moved to other tile than tail
|
||||||
|
switch (get_block(head_pos)) { |
||||||
|
|
||||||
|
case bFOOD: |
||||||
|
do_grow = true; // fall through
|
||||||
|
case bEMPTY: |
||||||
|
do_move = true; |
||||||
|
break; |
||||||
|
|
||||||
|
default: // includes all BODY_xxx
|
||||||
|
crashed = true; // snake crashed into some block
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (do_move) { |
||||||
|
// Move tail
|
||||||
|
if (do_grow) { |
||||||
|
// let tail as is
|
||||||
|
snake_len++; // grow the counter
|
||||||
|
} else { |
||||||
|
// tail dir
|
||||||
|
dir_t td = get_block(tail_pos) & 0xF; |
||||||
|
|
||||||
|
// clean tail
|
||||||
|
set_block(tail_pos, bEMPTY); |
||||||
|
|
||||||
|
// move tail based on old direction of tail block
|
||||||
|
switch (td) { |
||||||
|
case dLEFT: tail_pos.x--; break; |
||||||
|
case dRIGHT: tail_pos.x++; break; |
||||||
|
case dUP: tail_pos.y--; break; |
||||||
|
case dDOWN: tail_pos.y++; break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Move head
|
||||||
|
set_block(head_pos, bHEAD); // place head in new pos
|
||||||
|
set_block(oldpos, mk_body_dir(head_dir)); // directional body in old head pos
|
||||||
|
|
||||||
|
if (do_grow) { |
||||||
|
// food eaten, place new
|
||||||
|
place_food(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} // end !crashed
|
||||||
|
|
||||||
|
|
||||||
|
// Render the board
|
||||||
|
for (uint8_t r = 0; r < ROWS / 2; r++) { |
||||||
|
lcd_xy(0, r); |
||||||
|
for (uint8_t c = 0; c < COLS; c++) { |
||||||
|
const block_t t1 = get_block_xy(c, r * 2); |
||||||
|
const block_t t2 = get_block_xy(c, (r * 2) + 1); |
||||||
|
|
||||||
|
uint8_t code = '!'; // ! marks fail
|
||||||
|
|
||||||
|
if ((t1 == bEMPTY) && (t2 == bEMPTY)) { |
||||||
|
code = CODE_XX; |
||||||
|
if (crashed) code = '*'; |
||||||
|
} else if (is_body(t1) && is_body(t2)) |
||||||
|
code = CODE_BB; |
||||||
|
else if (is_body(t1) && (t2 == bEMPTY)) |
||||||
|
code = CODE_BX; |
||||||
|
else if (t1 == bEMPTY && is_body(t2)) |
||||||
|
code = CODE_XB; |
||||||
|
else if ((t1 == bFOOD) || (t2 == bFOOD)) { |
||||||
|
// one is food
|
||||||
|
|
||||||
|
code = CODE_F; |
||||||
|
|
||||||
|
if (t1 == bFOOD) { |
||||||
|
if (t2 == bEMPTY) |
||||||
|
lcd_glyph_P(code, SYMBOL_FX); |
||||||
|
else if (t2 == bHEAD) |
||||||
|
lcd_glyph_P(code, SYMBOL_FH); |
||||||
|
else if (is_body(t2)) |
||||||
|
lcd_glyph_P(code, SYMBOL_FB); |
||||||
|
} else { // t2 is food
|
||||||
|
if (t1 == bEMPTY) |
||||||
|
lcd_glyph_P(code, SYMBOL_XF); |
||||||
|
else if (t1 == bHEAD) |
||||||
|
lcd_glyph_P(code, SYMBOL_HF); |
||||||
|
else if (is_body(t1)) |
||||||
|
lcd_glyph_P(code, SYMBOL_BF); |
||||||
|
} |
||||||
|
lcd_xy(c,r); |
||||||
|
|
||||||
|
} else if ((t1 == bHEAD )|| (t2 == bHEAD)) { |
||||||
|
// one is head
|
||||||
|
|
||||||
|
code = CODE_H; |
||||||
|
|
||||||
|
if (t1 == bHEAD) { |
||||||
|
if (t2 == bEMPTY) |
||||||
|
lcd_glyph_P(code, SYMBOL_HX); |
||||||
|
else if (is_body(t2)) |
||||||
|
lcd_glyph_P(code, SYMBOL_HB); |
||||||
|
} else { // t2 is head
|
||||||
|
if (t1 == bEMPTY) |
||||||
|
lcd_glyph_P(code, SYMBOL_XH); |
||||||
|
else if (is_body(t1)) |
||||||
|
lcd_glyph_P(code, SYMBOL_BH); |
||||||
|
} |
||||||
|
|
||||||
|
lcd_xy(c,r); |
||||||
|
} |
||||||
|
|
||||||
|
lcd_putc(code); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
init(); |
||||||
|
|
||||||
|
while(1); // timer does everything
|
||||||
|
} |
@ -0,0 +1,141 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c iopins.c stream.c onewire.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
fser: all flash ser |
||||||
|
|
||||||
|
ser: |
||||||
|
gtkterm -p /dev/ttyUSB0
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,38 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "lib/iopins.h" |
||||||
|
#include "lib/uart.h" |
||||||
|
#include "lib/stream.h" |
||||||
|
#include "lib/onewire.h" |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
uart_init(9600); |
||||||
|
uart_puts_P(PSTR("*** OneWire test ***\r\n")); |
||||||
|
|
||||||
|
while(1) |
||||||
|
{ |
||||||
|
_delay_ms(100); |
||||||
|
|
||||||
|
if (ds1820_single_measure(2)) |
||||||
|
{ |
||||||
|
int16_t temp = ds1820_read_temp_c(2); |
||||||
|
|
||||||
|
if (temp == TEMP_ERROR) { |
||||||
|
// Checksum mismatch
|
||||||
|
uart_puts_P(PSTR("Corrupt data!\r\n")); |
||||||
|
} else { |
||||||
|
put_i16f(uart, temp, 1); |
||||||
|
uart_puts_P(PSTR(" °C\r\n")); |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
uart_puts_P(PSTR("Device not connected!\r\n")); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,170 @@ |
|||||||
|
|
||||||
|
MCU = atmega328p
|
||||||
|
|
||||||
|
F_CPU = 16000000
|
||||||
|
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
MAIN = main.c
|
||||||
|
|
||||||
|
## If you've split your program into multiple files,
|
||||||
|
## include the additional .c source (in same directory) here
|
||||||
|
## (and include the .h files in your foo.c)
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
## Here you can link to one more directory (and multiple .c files)
|
||||||
|
# EXTRA_SOURCE_DIR = ../AVR-Programming-Library/
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
EXTRA_SOURCE_FILES = adc.c hsl.c
|
||||||
|
|
||||||
|
EXTRA_FLAGS =
|
||||||
|
#-DHSL_LINEAR=1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Programmer Defaults ##########
|
||||||
|
########## Set up once, then forget about it ##########
|
||||||
|
########## (Can override. See bottom of file.) ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
#19200
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Makefile Magic! ##########
|
||||||
|
########## Summary: ##########
|
||||||
|
########## We want a .hex file ##########
|
||||||
|
########## Compile source files into .elf ##########
|
||||||
|
########## Convert .elf file into .hex ##########
|
||||||
|
########## You shouldn't need to edit below. ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## Compilation options, type man avr-gcc if you're curious.
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -pedantic -Wfatal-errors
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
CFLAGS += $(EXTRA_FLAGS)
|
||||||
|
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
# CFLAGS += -lm
|
||||||
|
## CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
## CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
|
||||||
|
## Lump target and extra source files together
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
## List of all header files
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
|
||||||
|
## For every .c file, compile an .o object file
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
## Generic Makefile targets. (Only .hex file is necessary)
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
# Optionally create listing file from .elf
|
||||||
|
# This creates approximate assembly-language equivalent of your code.
|
||||||
|
# Useful for debugging time-sensitive bits,
|
||||||
|
# or making sure the compiler does what you want.
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
|
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Optionally show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
squeaky_clean: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Programmer-specific details ##########
|
||||||
|
########## Flashing code to AVR using avrdude ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flash_eeprom: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
terminal: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
|
||||||
|
flash_arduino: PROGRAMMER_TYPE = arduino |
||||||
|
flash_arduino: PROGRAMMER_ARGS = |
||||||
|
flash_arduino: flash |
||||||
|
|
||||||
|
flash_dragon_isp: PROGRAMMER_TYPE = dragon_isp |
||||||
|
flash_dragon_isp: PROGRAMMER_ARGS = |
||||||
|
flash_dragon_isp: flash |
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Fuse settings and suitable defaults ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
## Generic
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
## Called with no extra definitions, sets to defaults
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1,11 @@ |
|||||||
|
Random color flasher, with fading. |
||||||
|
|
||||||
|
Color is atm restricted to hues of blue-cyan. |
||||||
|
|
||||||
|
Works with a 4x4 zigzag screen |
||||||
|
|
||||||
|
0->1->2->3 |
||||||
|
7<-6<-5<-4 |
||||||
|
8->... |
||||||
|
|
||||||
|
(But will work with any screen since there's no pattern to be preserved) |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,69 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include "lib/meta.h" |
||||||
|
#include "lib/arduino_pins.h" |
||||||
|
#include "lib/calc.h" |
||||||
|
|
||||||
|
#include "lib/colors.h" |
||||||
|
#include "lib/hsl.h" |
||||||
|
#include "lib/adc.h" |
||||||
|
|
||||||
|
#define WS_T_1H 650 |
||||||
|
#define WS_T_1L 200 |
||||||
|
#define WS_T_0H 120 |
||||||
|
#define WS_T_0L 650 |
||||||
|
|
||||||
|
#include "lib/ws_rgb.h" |
||||||
|
|
||||||
|
#define WS1 D2 |
||||||
|
|
||||||
|
void SECTION(".init8") init() |
||||||
|
{ |
||||||
|
adc_init(); |
||||||
|
srand(adc_read_word(0)); |
||||||
|
|
||||||
|
as_output(WS1); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
#define WIDTH 4 |
||||||
|
#define HEIGHT 4 |
||||||
|
#define SIZE (WIDTH*HEIGHT) |
||||||
|
hsl_t board[SIZE]; |
||||||
|
xrgb_t screen[SIZE]; |
||||||
|
|
||||||
|
for (uint8_t i = 0; i < SIZE; i++) { |
||||||
|
board[i] = (hsl_t) {.h=0, .s=255, .l=0}; |
||||||
|
screen[i] = (xrgb_t) {.r=0, .g=0, .b=0}; |
||||||
|
} |
||||||
|
|
||||||
|
while(1) { |
||||||
|
for(uint8_t i = 0; i < SIZE; i++) { |
||||||
|
if (board[i].l > 0) { |
||||||
|
board[i].l--; |
||||||
|
} |
||||||
|
|
||||||
|
screen[i] = hsl2xrgb(board[i]); |
||||||
|
} |
||||||
|
|
||||||
|
if (rand() % 4 == 0) { |
||||||
|
uint8_t i = rand() % SIZE; |
||||||
|
|
||||||
|
if (board[i].l == 0) { |
||||||
|
board[i].h = 125 + rand() % 57; |
||||||
|
board[i].s = 200 + rand() % 56; |
||||||
|
board[i].l = 150 + rand() % 106; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
//ws_send_xrgb_array_zigzag_linear(WS1, screen, 4, 4);
|
||||||
|
ws_send_xrgb_array_zigzag_linear(WS1, screen, 4, 4); |
||||||
|
_delay_ms(10); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,147 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
|
||||||
|
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c iopins.c stream.c adc.c dht11.c sonar.c onewire.c
|
||||||
|
#Files that need config file:
|
||||||
|
# EXTRA_SOURCE_FILES += lcd.c
|
||||||
|
# EXTRA_SOURCE_FILES += color.c wsrgb.c
|
||||||
|
# EXTRA_SOURCE_FILES += debouce.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
fser: all flash ser |
||||||
|
|
||||||
|
ser: |
||||||
|
gtkterm -p /dev/ttyUSB0
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1,191 @@ |
|||||||
|
# This file was generated by an application wizard of Qt Creator. |
||||||
|
# The code below handles deployment to Android and Maemo, aswell as copying |
||||||
|
# of the application data to shadow build directories on desktop. |
||||||
|
# It is recommended not to modify this file, since newer versions of Qt Creator |
||||||
|
# may offer an updated version of it. |
||||||
|
|
||||||
|
defineTest(qtcAddDeployment) { |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
greaterThan(QT_MAJOR_VERSION, 4) { |
||||||
|
itemsources = $${item}.files |
||||||
|
} else { |
||||||
|
itemsources = $${item}.sources |
||||||
|
} |
||||||
|
$$itemsources = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath= $$eval($${deploymentfolder}.target) |
||||||
|
export($$itemsources) |
||||||
|
export($$itempath) |
||||||
|
DEPLOYMENT += $$item |
||||||
|
} |
||||||
|
|
||||||
|
MAINPROFILEPWD = $$PWD |
||||||
|
|
||||||
|
android-no-sdk { |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
itemfiles = $${item}.files |
||||||
|
$$itemfiles = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath = /data/user/qt/$$eval($${deploymentfolder}.target) |
||||||
|
export($$itemfiles) |
||||||
|
export($$itempath) |
||||||
|
INSTALLS += $$item |
||||||
|
} |
||||||
|
|
||||||
|
target.path = /data/user/qt |
||||||
|
|
||||||
|
export(target.path) |
||||||
|
INSTALLS += target |
||||||
|
} else:android { |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
itemfiles = $${item}.files |
||||||
|
$$itemfiles = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath = /assets/$$eval($${deploymentfolder}.target) |
||||||
|
export($$itemfiles) |
||||||
|
export($$itempath) |
||||||
|
INSTALLS += $$item |
||||||
|
} |
||||||
|
|
||||||
|
x86 { |
||||||
|
target.path = /libs/x86 |
||||||
|
} else: armeabi-v7a { |
||||||
|
target.path = /libs/armeabi-v7a |
||||||
|
} else { |
||||||
|
target.path = /libs/armeabi |
||||||
|
} |
||||||
|
|
||||||
|
export(target.path) |
||||||
|
INSTALLS += target |
||||||
|
} else:win32 { |
||||||
|
copyCommand = |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) |
||||||
|
source = $$replace(source, /, \\) |
||||||
|
sourcePathSegments = $$split(source, \\) |
||||||
|
target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments) |
||||||
|
target = $$replace(target, /, \\) |
||||||
|
target ~= s,\\\\\\.?\\\\,\\, |
||||||
|
!isEqual(source,$$target) { |
||||||
|
!isEmpty(copyCommand):copyCommand += && |
||||||
|
isEqual(QMAKE_DIR_SEP, \\) { |
||||||
|
copyCommand += $(COPY_DIR) \"$$source\" \"$$target\" |
||||||
|
} else { |
||||||
|
source = $$replace(source, \\\\, /) |
||||||
|
target = $$OUT_PWD/$$eval($${deploymentfolder}.target) |
||||||
|
target = $$replace(target, \\\\, /) |
||||||
|
copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(copyCommand) { |
||||||
|
copyCommand = @echo Copying application data... && $$copyCommand |
||||||
|
copydeploymentfolders.commands = $$copyCommand |
||||||
|
first.depends = $(first) copydeploymentfolders |
||||||
|
export(first.depends) |
||||||
|
export(copydeploymentfolders.commands) |
||||||
|
QMAKE_EXTRA_TARGETS += first copydeploymentfolders |
||||||
|
} |
||||||
|
} else:ios { |
||||||
|
copyCommand = |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) |
||||||
|
source = $$replace(source, \\\\, /) |
||||||
|
target = $CODESIGNING_FOLDER_PATH/$$eval($${deploymentfolder}.target) |
||||||
|
target = $$replace(target, \\\\, /) |
||||||
|
sourcePathSegments = $$split(source, /) |
||||||
|
targetFullPath = $$target/$$last(sourcePathSegments) |
||||||
|
targetFullPath ~= s,/\\.?/,/, |
||||||
|
!isEqual(source,$$targetFullPath) { |
||||||
|
!isEmpty(copyCommand):copyCommand += && |
||||||
|
copyCommand += mkdir -p \"$$target\" |
||||||
|
copyCommand += && cp -r \"$$source\" \"$$target\" |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(copyCommand) { |
||||||
|
copyCommand = echo Copying application data... && $$copyCommand |
||||||
|
!isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";" |
||||||
|
QMAKE_POST_LINK += "$$copyCommand" |
||||||
|
export(QMAKE_POST_LINK) |
||||||
|
} |
||||||
|
} else:unix { |
||||||
|
maemo5 { |
||||||
|
desktopfile.files = $${TARGET}.desktop |
||||||
|
desktopfile.path = /usr/share/applications/hildon |
||||||
|
icon.files = $${TARGET}64.png |
||||||
|
icon.path = /usr/share/icons/hicolor/64x64/apps |
||||||
|
} else:!isEmpty(MEEGO_VERSION_MAJOR) { |
||||||
|
desktopfile.files = $${TARGET}_harmattan.desktop |
||||||
|
desktopfile.path = /usr/share/applications |
||||||
|
icon.files = $${TARGET}80.png |
||||||
|
icon.path = /usr/share/icons/hicolor/80x80/apps |
||||||
|
} else { # Assumed to be a Desktop Unix |
||||||
|
copyCommand = |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) |
||||||
|
source = $$replace(source, \\\\, /) |
||||||
|
macx { |
||||||
|
target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target) |
||||||
|
} else { |
||||||
|
target = $$OUT_PWD/$$eval($${deploymentfolder}.target) |
||||||
|
} |
||||||
|
target = $$replace(target, \\\\, /) |
||||||
|
sourcePathSegments = $$split(source, /) |
||||||
|
targetFullPath = $$target/$$last(sourcePathSegments) |
||||||
|
targetFullPath ~= s,/\\.?/,/, |
||||||
|
!isEqual(source,$$targetFullPath) { |
||||||
|
!isEmpty(copyCommand):copyCommand += && |
||||||
|
copyCommand += $(MKDIR) \"$$target\" |
||||||
|
copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\" |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(copyCommand) { |
||||||
|
copyCommand = @echo Copying application data... && $$copyCommand |
||||||
|
copydeploymentfolders.commands = $$copyCommand |
||||||
|
first.depends = $(first) copydeploymentfolders |
||||||
|
export(first.depends) |
||||||
|
export(copydeploymentfolders.commands) |
||||||
|
QMAKE_EXTRA_TARGETS += first copydeploymentfolders |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(target.path) { |
||||||
|
installPrefix = $${target.path} |
||||||
|
} else { |
||||||
|
installPrefix = /opt/$${TARGET} |
||||||
|
} |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
itemfiles = $${item}.files |
||||||
|
$$itemfiles = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target) |
||||||
|
export($$itemfiles) |
||||||
|
export($$itempath) |
||||||
|
INSTALLS += $$item |
||||||
|
} |
||||||
|
|
||||||
|
!isEmpty(desktopfile.path) { |
||||||
|
export(icon.files) |
||||||
|
export(icon.path) |
||||||
|
export(desktopfile.files) |
||||||
|
export(desktopfile.path) |
||||||
|
INSTALLS += icon desktopfile |
||||||
|
} |
||||||
|
|
||||||
|
isEmpty(target.path) { |
||||||
|
target.path = $${installPrefix}/bin |
||||||
|
export(target.path) |
||||||
|
} |
||||||
|
INSTALLS += target |
||||||
|
} |
||||||
|
|
||||||
|
export (ICON) |
||||||
|
export (INSTALLS) |
||||||
|
export (DEPLOYMENT) |
||||||
|
export (LIBS) |
||||||
|
export (QMAKE_EXTRA_TARGETS) |
||||||
|
} |
||||||
|
|
@ -0,0 +1,57 @@ |
|||||||
|
#include "main.h" |
||||||
|
#include "sd.h" |
||||||
|
#include "spi.h" |
||||||
|
|
||||||
|
static uint8_t sd_buffer[512]; |
||||||
|
static sd_context_t sdc; |
||||||
|
|
||||||
|
void main(void) |
||||||
|
{ |
||||||
|
int j, ok; |
||||||
|
ok = 0; |
||||||
|
|
||||||
|
/* Stop the watchdog timer */ |
||||||
|
WDTCTL = WDTPW | WDTHOLD; |
||||||
|
|
||||||
|
/* Set some reasonable values for the timeouts.
|
||||||
|
*/ |
||||||
|
sdc.timeout_write = PERIPH_CLOCKRATE / 8; |
||||||
|
sdc.timeout_read = PERIPH_CLOCKRATE / 20; |
||||||
|
|
||||||
|
sdc.busyflag = 0; |
||||||
|
for (j = 0; j < SD_INIT_TRY && ok != 1; j++) |
||||||
|
{ |
||||||
|
ok = do_sd_initialize(&sdc); |
||||||
|
} |
||||||
|
|
||||||
|
/* Read in the first block on the SD Card */ |
||||||
|
if (ok == 1) |
||||||
|
{ |
||||||
|
sd_read_block(&sdc, 0, sd_buffer); |
||||||
|
sd_wait_notbusy(&sdc); |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait forever */ |
||||||
|
while (1) { } |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int do_sd_initialize(sd_context_t *sdc) |
||||||
|
{ |
||||||
|
/* Initialize the SPI controller */ |
||||||
|
spi_initialize(); |
||||||
|
|
||||||
|
/* Start out with a slow SPI clock, 400kHz, as required
|
||||||
|
by the SD spec |
||||||
|
(for MMC compatibility). */ |
||||||
|
spi_set_divisor(PERIPH_CLOCKRATE / 400000); |
||||||
|
|
||||||
|
/* Initialization OK? */ |
||||||
|
if (sd_initialize(sdc) != 1) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* Set the maximum SPI clock rate possible */ |
||||||
|
spi_set_divisor(2); |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
#ifndef MAIN_H |
||||||
|
#define MAIN_H |
||||||
|
|
||||||
|
#include "sdcomm_spi.h" |
||||||
|
|
||||||
|
/* Peripheral clock rate, in Hz, used for timing. */ |
||||||
|
#define PERIPH_CLOCKRATE 8000000 |
||||||
|
int do_sd_initialize(sd_context_t *sdc); |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,467 @@ |
|||||||
|
#include "main.h" |
||||||
|
#include "sd.h" |
||||||
|
#include "sdcomm_spi.h" |
||||||
|
#include "spi.h" |
||||||
|
|
||||||
|
static uint8_t response[5]; |
||||||
|
static uint8_t argument[4]; |
||||||
|
|
||||||
|
int sd_card_present() |
||||||
|
{ |
||||||
|
return (!(P3IN & 0x01)); |
||||||
|
} |
||||||
|
|
||||||
|
/* This function initializes the SD card. It returns 1 if
|
||||||
|
initialization was successful, 0 otherwise. |
||||||
|
|
||||||
|
sd_context_t *sdc -- pointer to a data structure containing |
||||||
|
information about the card. For now, the |
||||||
|
timeouts MUST be specified in advance. This |
||||||
|
function does not yet calculate them from the |
||||||
|
card data. |
||||||
|
*/ |
||||||
|
|
||||||
|
int sd_initialize(sd_context_t *sdc) |
||||||
|
{ |
||||||
|
char i, j; |
||||||
|
/* SPI SD initialization sequence:
|
||||||
|
* CMD0 |
||||||
|
* CMD55 |
||||||
|
* ACMD41 |
||||||
|
* CMD58 |
||||||
|
* (Note there is no CMD2 or CMD3 in SPI mode. These |
||||||
|
* instructions are devoted to addressing on the SD bus.) |
||||||
|
* |
||||||
|
* SD memory card SD initialization sequence: |
||||||
|
* CMD0 |
||||||
|
* CMD55 |
||||||
|
* ACMD41 |
||||||
|
* CMD2 |
||||||
|
* CMD3 |
||||||
|
*/ |
||||||
|
sdc->busyflag = 0; |
||||||
|
for (i = 0; i < 4; i++) |
||||||
|
argument[i] = 0; |
||||||
|
|
||||||
|
/* Delay for at least 74 clock cycles. This means to actually
|
||||||
|
* *clock* out at least 74 clock cycles with no data present on |
||||||
|
* the clock. In SPI mode, send at least 10 idle bytes (0xFF). */ |
||||||
|
|
||||||
|
spi_cs_assert(); |
||||||
|
sd_delay(100); |
||||||
|
spi_cs_deassert(); |
||||||
|
sd_delay(2); |
||||||
|
|
||||||
|
/* Put the card in the idle state */ |
||||||
|
if (sd_send_command(sdc, CMD0, CMD0_R, response, argument) == 0) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* Now wait until the card goes idle. Retry at most SD_IDLE_WAIT_MAX
|
||||||
|
times */ |
||||||
|
|
||||||
|
j = 0; |
||||||
|
do |
||||||
|
{ |
||||||
|
j++; |
||||||
|
/* Flag the next command as an application-specific command */ |
||||||
|
if (sd_send_command(sdc, CMD55, CMD55_R, response, argument) == 1) |
||||||
|
{ |
||||||
|
/* Tell the card to send its OCR */ |
||||||
|
sd_send_command(sdc, ACMD41, ACMD41_R, response, argument); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
/* No response, bail early */ |
||||||
|
j = SD_IDLE_WAIT_MAX; |
||||||
|
} |
||||||
|
} |
||||||
|
while ((response[0] & MSK_IDLE) == MSK_IDLE && j < SD_IDLE_WAIT_MAX); |
||||||
|
|
||||||
|
/* As long as we didn’t hit the timeout, assume we’re OK. */ |
||||||
|
if (j >= SD_IDLE_WAIT_MAX) |
||||||
|
return 0; |
||||||
|
|
||||||
|
if (sd_send_command(sdc, CMD58, CMD58_R, response, argument) == 0) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* At a very minimum, we must allow 3.3V. */ |
||||||
|
if ((response[2] & MSK_OCR_33) != MSK_OCR_33) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* Set the block length */ |
||||||
|
if (sd_set_blocklen(sdc, SD_BLOCKSIZE) != 1) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* If we got this far, initialization was OK.
|
||||||
|
*/ |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
This function reads a single block from the SD card at block |
||||||
|
blockaddr. The buffer must be preallocated. Returns 1 if the |
||||||
|
command was successful, zero otherwise. |
||||||
|
|
||||||
|
This is an ASYNCHRONOUS call. |
||||||
|
|
||||||
|
The transfer will not be complete when the function returns. |
||||||
|
If you want to explicitly wait until any pending transfers are |
||||||
|
finished, use the command sd_wait_notbusy(sdc). |
||||||
|
|
||||||
|
sd_context_t *sdc |
||||||
|
-- a pointer to an sd device context structure, |
||||||
|
populated by the function sd_initialize() |
||||||
|
|
||||||
|
u32 blockaddr |
||||||
|
-- The block address to read from the card. |
||||||
|
This is a block address, not a linear address. |
||||||
|
|
||||||
|
uint8_t *data |
||||||
|
-- The data, a pointer to an array of uint8_ts. |
||||||
|
*/ |
||||||
|
|
||||||
|
int sd_read_block(sd_context_t *sdc, uint32_t blockaddr, |
||||||
|
uint8_t *data) |
||||||
|
{ |
||||||
|
unsigned long int i = 0; |
||||||
|
uint8_t tmp; |
||||||
|
uint8_t blank = 0xFF; |
||||||
|
|
||||||
|
/* Adjust the block address to a linear address */ |
||||||
|
blockaddr <<= SD_BLOCKSIZE_NBITS; |
||||||
|
|
||||||
|
/* Wait until any old transfers are finished */ |
||||||
|
sd_wait_notbusy(sdc); |
||||||
|
|
||||||
|
/* Pack the address */ |
||||||
|
sd_packarg(argument, blockaddr); |
||||||
|
|
||||||
|
/* Need to add size checking */ |
||||||
|
if (sd_send_command(sdc, CMD17, CMD17_R, response, argument) == 0) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* Check for an error, like a misaligned read */ |
||||||
|
if (response[0] != 0) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* Re-assert CS to continue the transfer */ |
||||||
|
spi_cs_assert(); |
||||||
|
|
||||||
|
/* Wait for the token */ |
||||||
|
i = 0; |
||||||
|
do |
||||||
|
{ |
||||||
|
tmp = spi_rcv_byte(); |
||||||
|
i++; |
||||||
|
} |
||||||
|
while ((tmp == 0xFF) && i < sdc->timeout_read); |
||||||
|
|
||||||
|
if ((tmp & MSK_TOK_DATAERROR) == 0) |
||||||
|
{ |
||||||
|
/* Clock out a byte before returning */ |
||||||
|
spi_send_byte(0xFF); |
||||||
|
|
||||||
|
/* The card returned an error response. Bail and return 0 */ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
/* Prime the interrupt flags so things happen in the correct order. */ |
||||||
|
IFG1 &= ~URXIFG0; |
||||||
|
IFG1 &= ~UTXIFG0; |
||||||
|
|
||||||
|
/* Get the block */ |
||||||
|
/* Source DMA address: receive register. */ |
||||||
|
DMA0SA = U0RXBUF_; |
||||||
|
|
||||||
|
/* Destination DMA address: the user data buffer. */ |
||||||
|
DMA0DA = (unsigned short) data; |
||||||
|
|
||||||
|
/* The size of the block to be transferred */ |
||||||
|
DMA0SZ = SD_BLOCKSIZE; |
||||||
|
|
||||||
|
/* Configure the DMA transfer*/ |
||||||
|
DMA0CTL = |
||||||
|
DMADT_0 | /* Single transfer mode */ |
||||||
|
DMASBDB | /* Byte mode */ |
||||||
|
DMAEN | /* Enable DMA */ |
||||||
|
DMADSTINCR1 | DMADSTINCR0; /* Increment the destination address */ |
||||||
|
|
||||||
|
/* We depend on the DMA priorities here. Both triggers occur at
|
||||||
|
the same time, since the source is identical. DMA0 is handled |
||||||
|
first, and retrieves the byte. DMA1 is triggered next, and |
||||||
|
sends the next byte. */ |
||||||
|
|
||||||
|
/* Source DMA address: constant 0xFF (don’t increment)*/ |
||||||
|
DMA1SA = (unsigned short) ␣ |
||||||
|
|
||||||
|
/* Destination DMA address: the transmit buffer. */ |
||||||
|
DMA1DA = U0TXBUF_; |
||||||
|
|
||||||
|
/* Increment the destination address */ |
||||||
|
/* The size of the block to be transferred */ |
||||||
|
DMA1SZ = SD_BLOCKSIZE - 1; |
||||||
|
|
||||||
|
/* Configure the DMA transfer*/ |
||||||
|
DMA1CTL = |
||||||
|
DMADT_0 | /* Single transfer mode */ |
||||||
|
DMASBDB | /* Byte mode */ |
||||||
|
DMAEN; /* Enable DMA */ |
||||||
|
|
||||||
|
/* DMA trigger is UART receive for both DMA0 and DMA1 */ |
||||||
|
DMACTL0 = DMA0TSEL_3 | DMA1TSEL_3; |
||||||
|
|
||||||
|
/* Kick off the transfer by sending the first byte */ |
||||||
|
U0TXBUF = 0xFF; |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function writes a single block to the SD card at block |
||||||
|
blockaddr. Returns 1 if the command was successful, zero |
||||||
|
otherwise. |
||||||
|
|
||||||
|
This is an ASYNCHRONOUS call. The transfer will not be complete |
||||||
|
when the function returns. If you want to explicitly wait until |
||||||
|
any pending transfers are finished, use the command |
||||||
|
sd_wait_notbusy(sdc). |
||||||
|
|
||||||
|
sd_context_t *sdc |
||||||
|
-- a pointer to an sd device context structure, |
||||||
|
populated by the function sd_initialize() |
||||||
|
|
||||||
|
u32 blockaddr |
||||||
|
-- The block address to read from the card. |
||||||
|
This is a block address, not a linear address. |
||||||
|
|
||||||
|
uint8_t *data |
||||||
|
-- The data, a pointer to an array of unsigned |
||||||
|
chars. |
||||||
|
*/ |
||||||
|
int sd_write_block(sd_context_t *sdc, uint32_t blockaddr, |
||||||
|
uint8_t *data) |
||||||
|
{ |
||||||
|
/* Adjust the block address to a linear address */ |
||||||
|
blockaddr <<= SD_BLOCKSIZE_NBITS; |
||||||
|
|
||||||
|
/* Wait until any old transfers are finished */ |
||||||
|
sd_wait_notbusy(sdc); |
||||||
|
|
||||||
|
/* Pack the address */ |
||||||
|
sd_packarg(argument, blockaddr); |
||||||
|
|
||||||
|
if (sd_send_command(sdc, CMD24, CMD24_R, response, argument) == 0) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* Check for an error, like a misaligned write */ |
||||||
|
if (response[0] != 0) |
||||||
|
return 0; |
||||||
|
|
||||||
|
/* Re-assert CS to continue the transfer */ |
||||||
|
spi_cs_assert(); |
||||||
|
|
||||||
|
/* The write command needs an additional 8 clock cycles before
|
||||||
|
* the block write is started. */ |
||||||
|
spi_rcv_byte(); |
||||||
|
|
||||||
|
/* Clear any pending flags */ |
||||||
|
IFG1 &= ~(URXIFG0 | UTXIFG0); |
||||||
|
|
||||||
|
/* Get the block */ |
||||||
|
/* Source DMA address: the data buffer. */ |
||||||
|
DMA0SA = (unsigned short)data; |
||||||
|
|
||||||
|
/* Destination DMA address: the UART send register. */ |
||||||
|
DMA0DA = U0TXBUF_; |
||||||
|
|
||||||
|
/* The size of the block to be transferred */ |
||||||
|
DMA0SZ = SD_BLOCKSIZE; |
||||||
|
|
||||||
|
/* Configure the DMA transfer*/ |
||||||
|
DMA0CTL = |
||||||
|
DMADT_0 | /* Single transfer mode */ |
||||||
|
DMASBDB | /* Byte mode */ |
||||||
|
DMAEN | /* Enable DMA */ |
||||||
|
DMASRCINCR1 | DMASRCINCR0; /* Increment the source address */ |
||||||
|
|
||||||
|
/* DMA trigger is UART send */ |
||||||
|
DMACTL0 = DMA0TSEL_3; |
||||||
|
|
||||||
|
/* Kick off the transfer by sending the first byte, the "start block"
|
||||||
|
* token */ |
||||||
|
U0TXBUF = SD_TOK_WRITE_STARTBLOCK; |
||||||
|
|
||||||
|
/* Signal that the card may be busy, so any subsequent commands
|
||||||
|
should wait for the busy signalling to end (indicated by a |
||||||
|
nonzero response). */ |
||||||
|
sdc->busyflag = 1; |
||||||
|
|
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
/*
|
||||||
|
This function synchronously waits until any pending block transfers |
||||||
|
are finished. If your program needs to ensure a block has finished |
||||||
|
transferring, call this function. |
||||||
|
|
||||||
|
Note that sd_read_block() and sd_write_block() already call this |
||||||
|
function internally before attempting a new transfer, so there are |
||||||
|
only two times when a user would need to use this function. |
||||||
|
|
||||||
|
1) When the processor will be shutting down. All pending |
||||||
|
writes should be finished first. |
||||||
|
|
||||||
|
2) When the user needs the results of an sd_read_block() call |
||||||
|
right away. |
||||||
|
*/ |
||||||
|
void sd_wait_notbusy(sd_context_t *sdc) |
||||||
|
{ |
||||||
|
/* Just twiddle our thumbs until the transfer’s done */ |
||||||
|
while ((DMA0CTL & DMAEN) != 0) { } |
||||||
|
|
||||||
|
/* Reset the DMA controller */ |
||||||
|
DMACTL0 = 0; |
||||||
|
|
||||||
|
/* Ignore the checksum */ |
||||||
|
sd_delay(4); |
||||||
|
|
||||||
|
/* Check for the busy flag (set on a write block) */ |
||||||
|
if (sdc->busyflag == 1) |
||||||
|
{ |
||||||
|
while (spi_rcv_byte() != 0xFF); |
||||||
|
} |
||||||
|
|
||||||
|
sdc->busyflag = 0; |
||||||
|
|
||||||
|
/* Deassert CS */ |
||||||
|
spi_cs_deassert(); |
||||||
|
|
||||||
|
/* Send some extra clocks so the card can resynchronize on the next
|
||||||
|
transfer */ |
||||||
|
|
||||||
|
sd_delay(2); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void sd_packarg(uint8_t *argument, uint32_t value) |
||||||
|
{ |
||||||
|
argument[3] = (uint8_t)(value >> 24); |
||||||
|
argument[2] = (uint8_t)(value >> 16); |
||||||
|
argument[1] = (uint8_t)(value >> 8); |
||||||
|
argument[0] = (uint8_t)(value); |
||||||
|
} |
||||||
|
|
||||||
|
int sd_send_command(sd_context_t *sdc, |
||||||
|
uint8_t cmd, uint8_t response_type, |
||||||
|
uint8_t *response, uint8_t *argument) |
||||||
|
{ |
||||||
|
int i; |
||||||
|
char response_length; |
||||||
|
uint8_t tmp; |
||||||
|
spi_cs_assert(); |
||||||
|
|
||||||
|
/* All data is sent MSB first, and MSb first */ |
||||||
|
/* Send the header/command */ |
||||||
|
/* Format:
|
||||||
|
cmd[7:6] : 01 |
||||||
|
cmd[5:0] : command */ |
||||||
|
spi_send_byte((cmd & 0x3F) | 0x40); |
||||||
|
for (i = 3; i >= 0; i--) |
||||||
|
{ |
||||||
|
spi_send_byte(argument[i]); |
||||||
|
} |
||||||
|
|
||||||
|
/* This is the CRC. It only matters what we put here for the first
|
||||||
|
command. Otherwise, the CRC is ignored for SPI mode unless we |
||||||
|
enable CRC checking. */ |
||||||
|
spi_send_byte(0x95); |
||||||
|
|
||||||
|
response_length = 0; |
||||||
|
switch (response_type) |
||||||
|
{ |
||||||
|
case R1: |
||||||
|
case R1B: |
||||||
|
response_length = 1; |
||||||
|
break; |
||||||
|
case R2: |
||||||
|
response_length = 2; |
||||||
|
break; |
||||||
|
case R3: |
||||||
|
response_length = 5; |
||||||
|
break; |
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
/* Wait for a response. A response can be recognized by the
|
||||||
|
start bit (a zero) */ |
||||||
|
i = 0; |
||||||
|
do |
||||||
|
{ |
||||||
|
tmp = spi_rcv_byte(); |
||||||
|
i++; |
||||||
|
} |
||||||
|
while (((tmp & 0x80) != 0) && i < SD_CMD_TIMEOUT); |
||||||
|
|
||||||
|
/* Just bail if we never got a response */ |
||||||
|
if (i >= SD_CMD_TIMEOUT) |
||||||
|
{ |
||||||
|
spi_cs_deassert(); |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
for (i = response_length - 1; i >= 0; i--) |
||||||
|
{ |
||||||
|
response[i] = tmp; |
||||||
|
/* This handles the trailing-byte requirement. */ |
||||||
|
tmp = spi_rcv_byte(); |
||||||
|
} |
||||||
|
|
||||||
|
/* If the response is a "busy" type (R1B), then there’s some
|
||||||
|
* special handling that needs to be done. The card will |
||||||
|
* output a continuous stream of zeros, so the end of the BUSY |
||||||
|
* state is signaled by any nonzero response. The bus idles |
||||||
|
* high. |
||||||
|
*/ |
||||||
|
i = 0; |
||||||
|
if (response_type == R1B) |
||||||
|
{ |
||||||
|
do |
||||||
|
{ |
||||||
|
i++; |
||||||
|
tmp = spi_rcv_byte(); |
||||||
|
} |
||||||
|
/* This should never time out, unless SDI is grounded.
|
||||||
|
* Don’t bother forcing a timeout condition here. */ |
||||||
|
while (tmp != 0xFF); |
||||||
|
|
||||||
|
spi_send_byte(0xFF); |
||||||
|
} |
||||||
|
|
||||||
|
spi_cs_deassert(); |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
void sd_delay(char number) |
||||||
|
{ |
||||||
|
char i; |
||||||
|
|
||||||
|
/* Null for now */ |
||||||
|
for (i = 0; i < number; i++) |
||||||
|
{ |
||||||
|
/* Clock out an idle byte (0xFF) */ |
||||||
|
spi_send_byte(0xFF); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/* Set the block length for all future block transactions */ |
||||||
|
/* Returns 1 if the function was successful */ |
||||||
|
int sd_set_blocklen(sd_context_t *sdc, uint32_t length) |
||||||
|
{ |
||||||
|
/* Pack the block length */ |
||||||
|
sd_packarg(argument, length); |
||||||
|
|
||||||
|
return (sd_send_command(sdc, CMD16, CMD16_R, response, argument)); |
||||||
|
} |
||||||
|
|
@ -0,0 +1,25 @@ |
|||||||
|
#ifndef SD_H |
||||||
|
#define SD_H |
||||||
|
|
||||||
|
#include "sdcomm_spi.h" |
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
#define SD_BLOCKSIZE 512 |
||||||
|
#define SD_BLOCKSIZE_NBITS 9 |
||||||
|
|
||||||
|
/* User functions */ |
||||||
|
int sd_card_present(); |
||||||
|
int sd_initialize(sd_context_t *sdc); |
||||||
|
int sd_read_block(sd_context_t *sdc, uint32_t blockaddr, uint8_t *data); |
||||||
|
int sd_write_block(sd_context_t *sdc, uint32_t blockaddr, uint8_t *data); |
||||||
|
void sd_wait_notbusy(sd_context_t *sdc); |
||||||
|
|
||||||
|
/* Internal functions, used for SD card communications. */ |
||||||
|
void sd_packarg(uint8_t *argument, uint32_t value); |
||||||
|
int sd_set_blocklen(sd_context_t *sdc, uint32_t length); |
||||||
|
int sd_send_command(sd_context_t *sdc, |
||||||
|
uint8_t cmd, uint8_t response_type, |
||||||
|
uint8_t *response, uint8_t *argument); |
||||||
|
void sd_delay(char number); |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,25 @@ |
|||||||
|
TEMPLATE = app |
||||||
|
CONFIG += console |
||||||
|
CONFIG -= app_bundle |
||||||
|
CONFIG -= qt |
||||||
|
|
||||||
|
INCLUDEPATH += /usr/avr/include |
||||||
|
|
||||||
|
include(deployment.pri) |
||||||
|
qtcAddDeployment() |
||||||
|
|
||||||
|
DISTFILES += \ |
||||||
|
Makefile \ |
||||||
|
style.astylerc |
||||||
|
|
||||||
|
HEADERS += \ |
||||||
|
main.h \ |
||||||
|
sd.h \ |
||||||
|
sdcomm_spi.h \ |
||||||
|
spi.h |
||||||
|
|
||||||
|
SOURCES += \ |
||||||
|
main.c \ |
||||||
|
sd.c \ |
||||||
|
spi.c |
||||||
|
|
@ -0,0 +1,250 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE QtCreatorProject> |
||||||
|
<!-- Written by QtCreator 3.4.1, 2015-06-09T22:29:35. --> |
||||||
|
<qtcreator> |
||||||
|
<data> |
||||||
|
<variable>EnvironmentId</variable> |
||||||
|
<value type="QByteArray">{dfe3cb4a-0f3e-4da9-9c52-5d2c464adafb}</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.ActiveTarget</variable> |
||||||
|
<value type="int">0</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.EditorSettings</variable> |
||||||
|
<valuemap type="QVariantMap"> |
||||||
|
<value type="bool" key="EditorConfiguration.AutoIndent">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value> |
||||||
|
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value> |
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0"> |
||||||
|
<value type="QString" key="language">Cpp</value> |
||||||
|
<valuemap type="QVariantMap" key="value"> |
||||||
|
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value> |
||||||
|
</valuemap> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="EditorConfiguration.CodeStyle.Count">1</value> |
||||||
|
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value> |
||||||
|
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value> |
||||||
|
<value type="int" key="EditorConfiguration.IndentSize">4</value> |
||||||
|
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value> |
||||||
|
<value type="int" key="EditorConfiguration.MarginColumn">80</value> |
||||||
|
<value type="bool" key="EditorConfiguration.MouseHiding">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value> |
||||||
|
<value type="int" key="EditorConfiguration.PaddingMode">1</value> |
||||||
|
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.ShowMargin">false</value> |
||||||
|
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value> |
||||||
|
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value> |
||||||
|
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value> |
||||||
|
<value type="int" key="EditorConfiguration.TabSize">8</value> |
||||||
|
<value type="bool" key="EditorConfiguration.UseGlobal">true</value> |
||||||
|
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value> |
||||||
|
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value> |
||||||
|
</valuemap> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable> |
||||||
|
<valuemap type="QVariantMap"> |
||||||
|
<valuemap type="QVariantMap" key="ClangProjectSettings"> |
||||||
|
<value type="QString" key="CustomPchFile"></value> |
||||||
|
<value type="int" key="PchUsage">1</value> |
||||||
|
</valuemap> |
||||||
|
</valuemap> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.Target.0</variable> |
||||||
|
<valuemap type="QVariantMap"> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{ee748544-c6c0-4f44-9cef-fbb65dc2525a}</value> |
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value> |
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> |
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> |
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ondra/git/avr-projects/devel/sdcard/</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> |
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value> |
||||||
|
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1"> |
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ondra/git/avr-projects/devel/sdcard/build-sdcard-Desktop-Release</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value> |
||||||
|
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> |
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value> |
||||||
|
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProcessStep.Arguments">flash</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProcessStep.Command">make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProcessStep.WorkingDirectory">%{buildDir}</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Custom Process Step</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.ProcessStep</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0"> |
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value> |
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> |
||||||
|
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments">-p /dev/ttyUSB0</value> |
||||||
|
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">gtkterm</value> |
||||||
|
<value type="bool" key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal">false</value> |
||||||
|
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">%{buildDir}</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run gtkterm</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value> |
||||||
|
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1"> |
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value> |
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">sd_bad</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/ondra/git/avr-projects/devel/sd_bad/sd_bad.pro</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">sd_bad.pro</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">true</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value> |
||||||
|
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value> |
||||||
|
</valuemap> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.TargetCount</variable> |
||||||
|
<value type="int">1</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.Updater.FileVersion</variable> |
||||||
|
<value type="int">18</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>Version</variable> |
||||||
|
<value type="int">18</value> |
||||||
|
</data> |
||||||
|
</qtcreator> |
@ -0,0 +1,152 @@ |
|||||||
|
#ifndef SDCOMM_SPI_H |
||||||
|
#define SDCOMM_SPI_H |
||||||
|
|
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
unsigned long int timeout_write; |
||||||
|
unsigned long int timeout_read; |
||||||
|
char busyflag; |
||||||
|
} sd_context_t; |
||||||
|
|
||||||
|
#define R1 1 |
||||||
|
#define R1B 2 |
||||||
|
#define R2 3 |
||||||
|
#define R3 4 |
||||||
|
|
||||||
|
#define MSK_IDLE 0x01 |
||||||
|
#define MSK_ERASE_RST 0x02 |
||||||
|
#define MSK_ILL_CMD 0x04 |
||||||
|
#define MSK_CRC_ERR 0x08 |
||||||
|
#define MSK_ERASE_SEQ_ERR 0x10 |
||||||
|
#define MSK_ADDR_ERR 0x20 |
||||||
|
#define MSK_PARAM_ERR 0x40 |
||||||
|
#define SD_TOK_READ_STARTBLOCK 0xFE |
||||||
|
#define SD_TOK_WRITE_STARTBLOCK 0xFE |
||||||
|
#define SD_TOK_READ_STARTBLOCK_M 0xFE |
||||||
|
#define SD_TOK_WRITE_STARTBLOCK_M 0xFC |
||||||
|
#define SD_TOK_STOP_MULTI 0xFD |
||||||
|
|
||||||
|
/* Error token is 111XXXXX */ |
||||||
|
#define MSK_TOK_DATAERROR 0xE0 |
||||||
|
|
||||||
|
/* Bit fields */ |
||||||
|
#define MSK_TOK_ERROR 0x01 |
||||||
|
#define MSK_TOK_CC_ERROR 0x02 |
||||||
|
#define MSK_TOK_ECC_FAILED 0x04 |
||||||
|
#define MSK_TOK_CC_OUTOFRANGE 0x08 |
||||||
|
#define MSK_TOK_CC_LOCKED 0x10 |
||||||
|
|
||||||
|
/* Mask off the bits in the OCR corresponding to voltage range 3.2V to
|
||||||
|
* 3.4V, OCR bits 20 and 21 */ |
||||||
|
#define MSK_OCR_33 0xC0 |
||||||
|
|
||||||
|
/* Number of times to retry the probe cycle during initialization */ |
||||||
|
#define SD_INIT_TRY 50 |
||||||
|
/* Number of tries to wait for the card to go idle during initialization */ |
||||||
|
#define SD_IDLE_WAIT_MAX 100 |
||||||
|
/* Hardcoded timeout for commands. 8 words, or 64 clocks. Do 10
|
||||||
|
* words instead */ |
||||||
|
#define SD_CMD_TIMEOUT 100 |
||||||
|
|
||||||
|
/******************************** Basic command set **************************/ |
||||||
|
/* Reset cards to idle state */ |
||||||
|
#define CMD0 0 |
||||||
|
#define CMD0_R R1 |
||||||
|
/* Read the OCR (MMC mode, do not use for SD cards) */ |
||||||
|
#define CMD1 1 |
||||||
|
#define CMD1_R R1 |
||||||
|
/* Card sends the CSD */ |
||||||
|
#define CMD9 9 |
||||||
|
#define CMD9_R R1 |
||||||
|
/* Card sends CID */ |
||||||
|
#define CMD10 10 |
||||||
|
#define CMD10_R R1 |
||||||
|
/* Stop a multiple block (stream) read/write operation */ |
||||||
|
#define CMD12 12 |
||||||
|
#define CMD12_R R1B |
||||||
|
/* Get the addressed card’s status register */ |
||||||
|
#define CMD13 13 |
||||||
|
#define CMD13_R R2 |
||||||
|
|
||||||
|
/***************************** Block read commands **************************/ |
||||||
|
/* Set the block length */ |
||||||
|
#define CMD16 16 |
||||||
|
#define CMD16_R R1 |
||||||
|
/* Read a single block */ |
||||||
|
#define CMD17 17 |
||||||
|
#define CMD17_R R1 |
||||||
|
/* Read multiple blocks until a CMD12 */ |
||||||
|
#define CMD18 18 |
||||||
|
#define CMD18_R R1 |
||||||
|
|
||||||
|
/***************************** Block write commands *************************/ |
||||||
|
/* Write a block of the size selected with CMD16 */ |
||||||
|
#define CMD24 24 |
||||||
|
#define CMD24_R R1 |
||||||
|
/* Multiple block write until a CMD12 */ |
||||||
|
#define CMD25 25 |
||||||
|
#define CMD25_R R1 |
||||||
|
/* Program the programmable bits of the CSD */ |
||||||
|
#define CMD27 27 |
||||||
|
#define CMD27_R R1 |
||||||
|
|
||||||
|
/***************************** Write protection *****************************/ |
||||||
|
/* Set the write protection bit of the addressed group */ |
||||||
|
#define CMD28 28 |
||||||
|
#define CMD28_R R1B |
||||||
|
/* Clear the write protection bit of the addressed group */ |
||||||
|
#define CMD29 29 |
||||||
|
#define CMD29_R R1B |
||||||
|
/* Ask the card for the status of the write protection bits */ |
||||||
|
#define CMD30 30 |
||||||
|
#define CMD30_R R1 |
||||||
|
|
||||||
|
/***************************** Erase commands *******************************/ |
||||||
|
/* Set the address of the first write block to be erased */ |
||||||
|
#define CMD32 32 |
||||||
|
#define CMD32_R R1 |
||||||
|
/* Set the address of the last write block to be erased */ |
||||||
|
#define CMD33 33 |
||||||
|
#define CMD33_R R1 |
||||||
|
/* Erase the selected write blocks */ |
||||||
|
#define CMD38 38 |
||||||
|
#define CMD38_R R1B |
||||||
|
|
||||||
|
/***************************** Lock Card commands ***************************/ |
||||||
|
/* Commands from 42 to 54, not defined here */ |
||||||
|
/***************************** Application-specific commands ****************/ |
||||||
|
/* Flag that the next command is application-specific */ |
||||||
|
#define CMD55 55 |
||||||
|
#define CMD55_R R1 |
||||||
|
/* General purpose I/O for application-specific commands */ |
||||||
|
#define CMD56 56 |
||||||
|
#define CMD56_R R1 |
||||||
|
/* Read the OCR (SPI mode only) */ |
||||||
|
#define CMD58 58 |
||||||
|
#define CMD58_R R3 |
||||||
|
/* Turn CRC on or off */ |
||||||
|
#define CMD59 59 |
||||||
|
#define CMD59_R R1 |
||||||
|
|
||||||
|
/***************************** Application-specific commands ***************/ |
||||||
|
/* Get the SD card’s status */ |
||||||
|
#define ACMD13 13 |
||||||
|
#define ACMD13_R R2 |
||||||
|
/* Get the number of written write blocks (Minus errors ) */ |
||||||
|
#define ACMD22 22 |
||||||
|
#define ACMD22_R R1 |
||||||
|
/* Set the number of write blocks to be pre-erased before writing */ |
||||||
|
#define ACMD23 23 |
||||||
|
#define ACMD23_R R1 |
||||||
|
/* Get the card’s OCR (SD mode) */ |
||||||
|
#define ACMD41 41 |
||||||
|
#define ACMD41_R R1 |
||||||
|
/* Connect or disconnect the 50kOhm internal pull-up on CD/DAT[3] */ |
||||||
|
#define ACMD42 42 |
||||||
|
#define ACMD42_R R1 |
||||||
|
/* Get the SD configuration register */ |
||||||
|
#define ACMD51 42 |
||||||
|
#define ACMD51_R R1 |
||||||
|
|
||||||
|
#endif |
||||||
|
|
@ -0,0 +1,88 @@ |
|||||||
|
#include "main.h" |
||||||
|
#include "spi.h" |
||||||
|
|
||||||
|
/* Initialize and enable the SPI module */ |
||||||
|
void spi_initialize() |
||||||
|
{ |
||||||
|
P3SEL = 0x00E; // Setup P3 for SPI mode
|
||||||
|
P3OUT |= 0x010; // Setup P3.4 as the SS signal, active low. So, initialize it high.
|
||||||
|
P3DIR |= 0x010; // Set up P3.4 as an output
|
||||||
|
|
||||||
|
U0CTL = (CHAR | SYNC | MM | SWRST); // 8-bit, SPI, Master
|
||||||
|
U0TCTL = (SSEL1 | STC | CKPH); // Normal polarity, 3-wire
|
||||||
|
U0BR0 = 0x002; // SPICLK = SMCLK/2 (2=Minimum divisor)
|
||||||
|
U0BR1 = 0x000; |
||||||
|
U0MCTL = 0x000; |
||||||
|
ME1 |= USPIE0; // Module enable
|
||||||
|
U0CTL &= ~SWRST; // SPI enable
|
||||||
|
} |
||||||
|
|
||||||
|
/* Set the baud-rate divisor. The correct value is computed by dividing
|
||||||
|
the clock rate by the desired baud rate. The minimum divisor allowed |
||||||
|
is 2. */ |
||||||
|
|
||||||
|
void spi_set_divisor(unsigned int divisor) |
||||||
|
{ |
||||||
|
U0CTL |= SWRST; // Temporarily disable the SPI module
|
||||||
|
U0BR1 = divisor >> 8; |
||||||
|
U0BR0 = divisor; |
||||||
|
U0CTL &= ~SWRST; // Re-enable SPI
|
||||||
|
} |
||||||
|
|
||||||
|
/* Assert the CS signal, active low (CS=0) */ |
||||||
|
void spi_cs_assert() |
||||||
|
{ |
||||||
|
// Pin 3.4, Pin 32
|
||||||
|
P3OUT &= ~0x010; |
||||||
|
} |
||||||
|
|
||||||
|
/* Deassert the CS signal (CS=1) */ |
||||||
|
void spi_cs_deassert() |
||||||
|
{ |
||||||
|
// Pin 3.4, Pin 32
|
||||||
|
P3OUT |= 0x010; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* Send a single byte over the SPI port */ |
||||||
|
void spi_send_byte(uint8_t input) |
||||||
|
{ |
||||||
|
IFG1 &= ~URXIFG0; |
||||||
|
/* Send the byte */ |
||||||
|
TXBUF0 = input; |
||||||
|
/* Wait for the byte to be sent */ |
||||||
|
while ((IFG1 & URXIFG0) == 0) { } |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* Receive a byte. Output an 0xFF (the bus idles high) to receive the byte */ |
||||||
|
uint8_t spi_rcv_byte() |
||||||
|
{ |
||||||
|
uint8_t tmp; |
||||||
|
IFG1 &= ~URXIFG0; |
||||||
|
/* Send the byte */ |
||||||
|
TXBUF0 = 0xFF; |
||||||
|
/* Wait for the byte to be received */ |
||||||
|
while ((IFG1 & URXIFG0) == 0) { } |
||||||
|
tmp = U0RXBUF; |
||||||
|
return (tmp); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/* Disable the SPI module. This function assumes the module had
|
||||||
|
* already been initialized. */ |
||||||
|
void spi_disable() |
||||||
|
{ |
||||||
|
/* Put the SPI module in reset mode */ |
||||||
|
U0CTL |= SWRST; |
||||||
|
/* Disable the USART module */ |
||||||
|
ME1 &= ~USPIE0; |
||||||
|
} |
||||||
|
|
||||||
|
void spi_enable() |
||||||
|
{ |
||||||
|
/* Enable the USART module */ |
||||||
|
ME1 |= USPIE0; |
||||||
|
/* Take the SPI module out of reset mode */ |
||||||
|
U0CTL &= ~SWRST; |
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
#ifndef SPI_H |
||||||
|
#define SPI_H |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
void spi_initialize(); |
||||||
|
void spi_set_divisor(unsigned int divisor); |
||||||
|
void spi_cs_assert(); |
||||||
|
void spi_cs_deassert(); |
||||||
|
void spi_send_byte(uint8_t input); |
||||||
|
uint8_t spi_rcv_byte(); |
||||||
|
void spi_enable(); |
||||||
|
void spi_disable(); |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,13 @@ |
|||||||
|
style=allman |
||||||
|
indent=tab |
||||||
|
max-instatement-indent=60 |
||||||
|
|
||||||
|
convert-tabs |
||||||
|
|
||||||
|
indent-switches |
||||||
|
|
||||||
|
pad-oper |
||||||
|
unpad-paren |
||||||
|
pad-header |
||||||
|
|
||||||
|
verbose |
@ -0,0 +1,147 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
|
||||||
|
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c iopins.c stream.c adc.c dht11.c sonar.c onewire.c spi.c sd.c fat16.c
|
||||||
|
#Files that need config file:
|
||||||
|
# EXTRA_SOURCE_FILES += lcd.c
|
||||||
|
# EXTRA_SOURCE_FILES += color.c wsrgb.c
|
||||||
|
# EXTRA_SOURCE_FILES += debouce.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
fser: all flash ser |
||||||
|
|
||||||
|
ser: |
||||||
|
gtkterm -p /dev/ttyUSB0
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1,191 @@ |
|||||||
|
# This file was generated by an application wizard of Qt Creator. |
||||||
|
# The code below handles deployment to Android and Maemo, aswell as copying |
||||||
|
# of the application data to shadow build directories on desktop. |
||||||
|
# It is recommended not to modify this file, since newer versions of Qt Creator |
||||||
|
# may offer an updated version of it. |
||||||
|
|
||||||
|
defineTest(qtcAddDeployment) { |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
greaterThan(QT_MAJOR_VERSION, 4) { |
||||||
|
itemsources = $${item}.files |
||||||
|
} else { |
||||||
|
itemsources = $${item}.sources |
||||||
|
} |
||||||
|
$$itemsources = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath= $$eval($${deploymentfolder}.target) |
||||||
|
export($$itemsources) |
||||||
|
export($$itempath) |
||||||
|
DEPLOYMENT += $$item |
||||||
|
} |
||||||
|
|
||||||
|
MAINPROFILEPWD = $$PWD |
||||||
|
|
||||||
|
android-no-sdk { |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
itemfiles = $${item}.files |
||||||
|
$$itemfiles = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath = /data/user/qt/$$eval($${deploymentfolder}.target) |
||||||
|
export($$itemfiles) |
||||||
|
export($$itempath) |
||||||
|
INSTALLS += $$item |
||||||
|
} |
||||||
|
|
||||||
|
target.path = /data/user/qt |
||||||
|
|
||||||
|
export(target.path) |
||||||
|
INSTALLS += target |
||||||
|
} else:android { |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
itemfiles = $${item}.files |
||||||
|
$$itemfiles = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath = /assets/$$eval($${deploymentfolder}.target) |
||||||
|
export($$itemfiles) |
||||||
|
export($$itempath) |
||||||
|
INSTALLS += $$item |
||||||
|
} |
||||||
|
|
||||||
|
x86 { |
||||||
|
target.path = /libs/x86 |
||||||
|
} else: armeabi-v7a { |
||||||
|
target.path = /libs/armeabi-v7a |
||||||
|
} else { |
||||||
|
target.path = /libs/armeabi |
||||||
|
} |
||||||
|
|
||||||
|
export(target.path) |
||||||
|
INSTALLS += target |
||||||
|
} else:win32 { |
||||||
|
copyCommand = |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) |
||||||
|
source = $$replace(source, /, \\) |
||||||
|
sourcePathSegments = $$split(source, \\) |
||||||
|
target = $$OUT_PWD/$$eval($${deploymentfolder}.target)/$$last(sourcePathSegments) |
||||||
|
target = $$replace(target, /, \\) |
||||||
|
target ~= s,\\\\\\.?\\\\,\\, |
||||||
|
!isEqual(source,$$target) { |
||||||
|
!isEmpty(copyCommand):copyCommand += && |
||||||
|
isEqual(QMAKE_DIR_SEP, \\) { |
||||||
|
copyCommand += $(COPY_DIR) \"$$source\" \"$$target\" |
||||||
|
} else { |
||||||
|
source = $$replace(source, \\\\, /) |
||||||
|
target = $$OUT_PWD/$$eval($${deploymentfolder}.target) |
||||||
|
target = $$replace(target, \\\\, /) |
||||||
|
copyCommand += test -d \"$$target\" || mkdir -p \"$$target\" && cp -r \"$$source\" \"$$target\" |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(copyCommand) { |
||||||
|
copyCommand = @echo Copying application data... && $$copyCommand |
||||||
|
copydeploymentfolders.commands = $$copyCommand |
||||||
|
first.depends = $(first) copydeploymentfolders |
||||||
|
export(first.depends) |
||||||
|
export(copydeploymentfolders.commands) |
||||||
|
QMAKE_EXTRA_TARGETS += first copydeploymentfolders |
||||||
|
} |
||||||
|
} else:ios { |
||||||
|
copyCommand = |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) |
||||||
|
source = $$replace(source, \\\\, /) |
||||||
|
target = $CODESIGNING_FOLDER_PATH/$$eval($${deploymentfolder}.target) |
||||||
|
target = $$replace(target, \\\\, /) |
||||||
|
sourcePathSegments = $$split(source, /) |
||||||
|
targetFullPath = $$target/$$last(sourcePathSegments) |
||||||
|
targetFullPath ~= s,/\\.?/,/, |
||||||
|
!isEqual(source,$$targetFullPath) { |
||||||
|
!isEmpty(copyCommand):copyCommand += && |
||||||
|
copyCommand += mkdir -p \"$$target\" |
||||||
|
copyCommand += && cp -r \"$$source\" \"$$target\" |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(copyCommand) { |
||||||
|
copyCommand = echo Copying application data... && $$copyCommand |
||||||
|
!isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK += ";" |
||||||
|
QMAKE_POST_LINK += "$$copyCommand" |
||||||
|
export(QMAKE_POST_LINK) |
||||||
|
} |
||||||
|
} else:unix { |
||||||
|
maemo5 { |
||||||
|
desktopfile.files = $${TARGET}.desktop |
||||||
|
desktopfile.path = /usr/share/applications/hildon |
||||||
|
icon.files = $${TARGET}64.png |
||||||
|
icon.path = /usr/share/icons/hicolor/64x64/apps |
||||||
|
} else:!isEmpty(MEEGO_VERSION_MAJOR) { |
||||||
|
desktopfile.files = $${TARGET}_harmattan.desktop |
||||||
|
desktopfile.path = /usr/share/applications |
||||||
|
icon.files = $${TARGET}80.png |
||||||
|
icon.path = /usr/share/icons/hicolor/80x80/apps |
||||||
|
} else { # Assumed to be a Desktop Unix |
||||||
|
copyCommand = |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
source = $$MAINPROFILEPWD/$$eval($${deploymentfolder}.source) |
||||||
|
source = $$replace(source, \\\\, /) |
||||||
|
macx { |
||||||
|
target = $$OUT_PWD/$${TARGET}.app/Contents/Resources/$$eval($${deploymentfolder}.target) |
||||||
|
} else { |
||||||
|
target = $$OUT_PWD/$$eval($${deploymentfolder}.target) |
||||||
|
} |
||||||
|
target = $$replace(target, \\\\, /) |
||||||
|
sourcePathSegments = $$split(source, /) |
||||||
|
targetFullPath = $$target/$$last(sourcePathSegments) |
||||||
|
targetFullPath ~= s,/\\.?/,/, |
||||||
|
!isEqual(source,$$targetFullPath) { |
||||||
|
!isEmpty(copyCommand):copyCommand += && |
||||||
|
copyCommand += $(MKDIR) \"$$target\" |
||||||
|
copyCommand += && $(COPY_DIR) \"$$source\" \"$$target\" |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(copyCommand) { |
||||||
|
copyCommand = @echo Copying application data... && $$copyCommand |
||||||
|
copydeploymentfolders.commands = $$copyCommand |
||||||
|
first.depends = $(first) copydeploymentfolders |
||||||
|
export(first.depends) |
||||||
|
export(copydeploymentfolders.commands) |
||||||
|
QMAKE_EXTRA_TARGETS += first copydeploymentfolders |
||||||
|
} |
||||||
|
} |
||||||
|
!isEmpty(target.path) { |
||||||
|
installPrefix = $${target.path} |
||||||
|
} else { |
||||||
|
installPrefix = /opt/$${TARGET} |
||||||
|
} |
||||||
|
for(deploymentfolder, DEPLOYMENTFOLDERS) { |
||||||
|
item = item$${deploymentfolder} |
||||||
|
itemfiles = $${item}.files |
||||||
|
$$itemfiles = $$eval($${deploymentfolder}.source) |
||||||
|
itempath = $${item}.path |
||||||
|
$$itempath = $${installPrefix}/$$eval($${deploymentfolder}.target) |
||||||
|
export($$itemfiles) |
||||||
|
export($$itempath) |
||||||
|
INSTALLS += $$item |
||||||
|
} |
||||||
|
|
||||||
|
!isEmpty(desktopfile.path) { |
||||||
|
export(icon.files) |
||||||
|
export(icon.path) |
||||||
|
export(desktopfile.files) |
||||||
|
export(desktopfile.path) |
||||||
|
INSTALLS += icon desktopfile |
||||||
|
} |
||||||
|
|
||||||
|
isEmpty(target.path) { |
||||||
|
target.path = $${installPrefix}/bin |
||||||
|
export(target.path) |
||||||
|
} |
||||||
|
INSTALLS += target |
||||||
|
} |
||||||
|
|
||||||
|
export (ICON) |
||||||
|
export (INSTALLS) |
||||||
|
export (DEPLOYMENT) |
||||||
|
export (LIBS) |
||||||
|
export (QMAKE_EXTRA_TARGETS) |
||||||
|
} |
||||||
|
|
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,64 @@ |
|||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <util/delay.h> |
||||||
|
|
||||||
|
#include "lib/uart.h" |
||||||
|
#include "lib/stream.h" |
||||||
|
#include "lib/sd.h" |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
uart_init(9600); |
||||||
|
uart_puts_P(PSTR("*** SD CARD SPI TEST ***\r\n")); |
||||||
|
|
||||||
|
if (!sd_init()) |
||||||
|
{ |
||||||
|
put_str_P(uart, PSTR("Failed to init.")); |
||||||
|
while (1); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
uint8_t text[512]; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
put_str_P(uart, PSTR("\r\nReading...\r\n")); |
||||||
|
if (sd_read(0, 0, text, 0, 512)) |
||||||
|
{ |
||||||
|
put_bytes(uart, text, 512); |
||||||
|
put_nl(uart); |
||||||
|
put_nl(uart); |
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 60; i++) |
||||||
|
{ |
||||||
|
text[i] = ('A' + i); |
||||||
|
} |
||||||
|
|
||||||
|
put_str_P(uart, PSTR("\r\nWriting...\r\n")); |
||||||
|
sd_write(1, text); |
||||||
|
put_str_P(uart, PSTR("\r\nWrite done.\r\n")); |
||||||
|
|
||||||
|
for (uint16_t i = 0; i < 512; i++) |
||||||
|
{ |
||||||
|
text[i] = 0; |
||||||
|
} |
||||||
|
|
||||||
|
if (sd_read(1, 0, text, 0, 512)) |
||||||
|
{ |
||||||
|
put_str_P(uart, PSTR("\r\nWritten, result: \r\n")); |
||||||
|
put_bytes(uart, text, 512); |
||||||
|
put_nl(uart); |
||||||
|
put_nl(uart); |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
put_str_P(uart, PSTR("\r\nRead failed.\r\n")); |
||||||
|
} |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
put_str_P(uart, PSTR("Failed to read.")); |
||||||
|
while (1); |
||||||
|
} |
||||||
|
|
||||||
|
while (1); |
||||||
|
} |
@ -0,0 +1,56 @@ |
|||||||
|
TEMPLATE = app |
||||||
|
CONFIG += console |
||||||
|
CONFIG -= app_bundle |
||||||
|
CONFIG -= qt |
||||||
|
|
||||||
|
INCLUDEPATH += /usr/avr/include |
||||||
|
|
||||||
|
SOURCES += main.c \ |
||||||
|
lib/adc.c \ |
||||||
|
lib/color.c \ |
||||||
|
lib/debounce.c \ |
||||||
|
lib/dht11.c \ |
||||||
|
lib/iopins.c \ |
||||||
|
lib/lcd.c \ |
||||||
|
lib/onewire.c \ |
||||||
|
lib/sonar.c \ |
||||||
|
lib/stream.c \ |
||||||
|
lib/uart.c \ |
||||||
|
lib/wsrgb.c \ |
||||||
|
sd/main.c \ |
||||||
|
sd/sd.c \ |
||||||
|
sd/spi.c \ |
||||||
|
lib/fat16.c \ |
||||||
|
lib/sd.c \ |
||||||
|
lib/spi.c |
||||||
|
|
||||||
|
include(deployment.pri) |
||||||
|
qtcAddDeployment() |
||||||
|
|
||||||
|
HEADERS += \ |
||||||
|
lib/adc.h \ |
||||||
|
lib/calc.h \ |
||||||
|
lib/color.h \ |
||||||
|
lib/debounce.h \ |
||||||
|
lib/dht11.h \ |
||||||
|
lib/iopins.h \ |
||||||
|
lib/lcd.h \ |
||||||
|
lib/nsdelay.h \ |
||||||
|
lib/onewire.h \ |
||||||
|
lib/sonar.h \ |
||||||
|
lib/stream.h \ |
||||||
|
lib/uart.h \ |
||||||
|
lib/wsrgb.h \ |
||||||
|
sd/main.h \ |
||||||
|
sd/sd.h \ |
||||||
|
sd/sdcomm_spi.h \ |
||||||
|
sd/spi.h \ |
||||||
|
lib/fat16.h \ |
||||||
|
lib/fat16_internal.h \ |
||||||
|
lib/spi.h \ |
||||||
|
lib/sd.h |
||||||
|
|
||||||
|
DISTFILES += \ |
||||||
|
Makefile \ |
||||||
|
style.astylerc |
||||||
|
|
@ -0,0 +1,250 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<!DOCTYPE QtCreatorProject> |
||||||
|
<!-- Written by QtCreator 3.4.1, 2015-06-10T00:54:58. --> |
||||||
|
<qtcreator> |
||||||
|
<data> |
||||||
|
<variable>EnvironmentId</variable> |
||||||
|
<value type="QByteArray">{dfe3cb4a-0f3e-4da9-9c52-5d2c464adafb}</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.ActiveTarget</variable> |
||||||
|
<value type="int">0</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.EditorSettings</variable> |
||||||
|
<valuemap type="QVariantMap"> |
||||||
|
<value type="bool" key="EditorConfiguration.AutoIndent">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value> |
||||||
|
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value> |
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0"> |
||||||
|
<value type="QString" key="language">Cpp</value> |
||||||
|
<valuemap type="QVariantMap" key="value"> |
||||||
|
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value> |
||||||
|
</valuemap> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="EditorConfiguration.CodeStyle.Count">1</value> |
||||||
|
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value> |
||||||
|
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value> |
||||||
|
<value type="int" key="EditorConfiguration.IndentSize">4</value> |
||||||
|
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value> |
||||||
|
<value type="int" key="EditorConfiguration.MarginColumn">80</value> |
||||||
|
<value type="bool" key="EditorConfiguration.MouseHiding">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value> |
||||||
|
<value type="int" key="EditorConfiguration.PaddingMode">1</value> |
||||||
|
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.ShowMargin">false</value> |
||||||
|
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value> |
||||||
|
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value> |
||||||
|
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value> |
||||||
|
<value type="int" key="EditorConfiguration.TabSize">8</value> |
||||||
|
<value type="bool" key="EditorConfiguration.UseGlobal">true</value> |
||||||
|
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value> |
||||||
|
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value> |
||||||
|
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value> |
||||||
|
</valuemap> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable> |
||||||
|
<valuemap type="QVariantMap"> |
||||||
|
<valuemap type="QVariantMap" key="ClangProjectSettings"> |
||||||
|
<value type="QString" key="CustomPchFile"></value> |
||||||
|
<value type="int" key="PchUsage">1</value> |
||||||
|
</valuemap> |
||||||
|
</valuemap> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.Target.0</variable> |
||||||
|
<valuemap type="QVariantMap"> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{ee748544-c6c0-4f44-9cef-fbb65dc2525a}</value> |
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value> |
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value> |
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">1</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0"> |
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ondra/git/avr-projects/devel/sdcard/</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">-B</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> |
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value> |
||||||
|
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1"> |
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/ondra/git/avr-projects/devel/sdcard/build-sdcard-Desktop-Release</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value> |
||||||
|
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value> |
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value> |
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"> |
||||||
|
<value type="QString">-w</value> |
||||||
|
<value type="QString">-r</value> |
||||||
|
</valuelist> |
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value> |
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value> |
||||||
|
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0"> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0"> |
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProcessStep.Arguments">flash -B</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProcessStep.Command">make</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProcessStep.WorkingDirectory">%{buildDir}</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Custom Process Step</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.ProcessStep</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy locally</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0"> |
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value> |
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">sdcard</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">sdcard2</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/home/ondra/git/avr-projects/devel/sdcard/sdcard.pro</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">sdcard.pro</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value> |
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">true</value> |
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value> |
||||||
|
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> |
||||||
|
</valuemap> |
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.1"> |
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value> |
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/> |
||||||
|
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Arguments">-p /dev/ttyUSB0</value> |
||||||
|
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.Executable">gtkterm</value> |
||||||
|
<value type="bool" key="ProjectExplorer.CustomExecutableRunConfiguration.UseTerminal">false</value> |
||||||
|
<value type="QString" key="ProjectExplorer.CustomExecutableRunConfiguration.WorkingDirectory">%{buildDir}</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Run gtkterm</value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value> |
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value> |
||||||
|
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value> |
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value> |
||||||
|
</valuemap> |
||||||
|
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">2</value> |
||||||
|
</valuemap> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.TargetCount</variable> |
||||||
|
<value type="int">1</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>ProjectExplorer.Project.Updater.FileVersion</variable> |
||||||
|
<value type="int">18</value> |
||||||
|
</data> |
||||||
|
<data> |
||||||
|
<variable>Version</variable> |
||||||
|
<value type="int">18</value> |
||||||
|
</data> |
||||||
|
</qtcreator> |
@ -0,0 +1,13 @@ |
|||||||
|
style=allman |
||||||
|
indent=tab |
||||||
|
max-instatement-indent=60 |
||||||
|
|
||||||
|
convert-tabs |
||||||
|
|
||||||
|
indent-switches |
||||||
|
|
||||||
|
pad-oper |
||||||
|
unpad-paren |
||||||
|
pad-header |
||||||
|
|
||||||
|
verbose |
@ -0,0 +1,166 @@ |
|||||||
|
|
||||||
|
MCU = atmega328p
|
||||||
|
|
||||||
|
F_CPU = 16000000
|
||||||
|
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
MAIN = main.c
|
||||||
|
|
||||||
|
## If you've split your program into multiple files,
|
||||||
|
## include the additional .c source (in same directory) here
|
||||||
|
## (and include the .h files in your foo.c)
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
## Here you can link to one more directory (and multiple .c files)
|
||||||
|
# EXTRA_SOURCE_DIR = ../AVR-Programming-Library/
|
||||||
|
EXTRA_SOURCE_DIR =
|
||||||
|
EXTRA_SOURCE_FILES =
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Programmer Defaults ##########
|
||||||
|
########## Set up once, then forget about it ##########
|
||||||
|
########## (Can override. See bottom of file.) ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
#19200
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Makefile Magic! ##########
|
||||||
|
########## Summary: ##########
|
||||||
|
########## We want a .hex file ##########
|
||||||
|
########## Compile source files into .elf ##########
|
||||||
|
########## Convert .elf file into .hex ##########
|
||||||
|
########## You shouldn't need to edit below. ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = sudo avrdude
|
||||||
|
|
||||||
|
## Compilation options, type man avr-gcc if you're curious.
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
# CFLAGS += -lm
|
||||||
|
## CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
## CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
|
||||||
|
## Lump target and extra source files together
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
## List of all header files
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
|
||||||
|
## For every .c file, compile an .o object file
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
## Generic Makefile targets. (Only .hex file is necessary)
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
# Optionally create listing file from .elf
|
||||||
|
# This creates approximate assembly-language equivalent of your code.
|
||||||
|
# Useful for debugging time-sensitive bits,
|
||||||
|
# or making sure the compiler does what you want.
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
|
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Optionally show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
squeaky_clean: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Programmer-specific details ##########
|
||||||
|
########## Flashing code to AVR using avrdude ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flash_eeprom: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
terminal: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
|
||||||
|
flash_arduino: PROGRAMMER_TYPE = arduino |
||||||
|
flash_arduino: PROGRAMMER_ARGS = |
||||||
|
flash_arduino: flash |
||||||
|
|
||||||
|
flash_dragon_isp: PROGRAMMER_TYPE = dragon_isp |
||||||
|
flash_dragon_isp: PROGRAMMER_ARGS = |
||||||
|
flash_dragon_isp: flash |
||||||
|
|
||||||
|
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
########## Fuse settings and suitable defaults ##########
|
||||||
|
##########------------------------------------------------------##########
|
||||||
|
|
||||||
|
## Generic
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
## Called with no extra definitions, sets to defaults
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1,351 @@ |
|||||||
|
; Zapojeni (Připojen DMC-50399 v 4-bitovem modu): |
||||||
|
; +------u------+ |
||||||
|
; Vcc -> reset --+ /RST Vcc +-- napajeni +5V |
||||||
|
; --+ PD0 PB7 +-- RS (0=instr W, BF+addr R; 1=data W/R) |
||||||
|
; --+ PD1 PB6 +-- R/W (1=read,0=write) |
||||||
|
; --+ PA1 PB5 +-- E (clock, active falling edge) |
||||||
|
; --+ PA0 PB4 +-- |
||||||
|
; --+ PD2 PB3 +-- DATA 7 |
||||||
|
; --+ PD3 PB2 +-- DATA 6 |
||||||
|
; --+ PD4 PB1 +-- DATA 5 |
||||||
|
; --+ PD5 PB0 +-- DATA 4 |
||||||
|
; GND --+ GND PD6 +-- |
||||||
|
; +-------------+ |
||||||
|
|
||||||
|
;DMC-50399: |
||||||
|
; 1 - GND |
||||||
|
; 2 - +5V |
||||||
|
; 3 - 0V (lcd driver) |
||||||
|
; 4 - RS |
||||||
|
; 5 - R/W |
||||||
|
; 6 - E |
||||||
|
; 7 - DATA 0 |
||||||
|
; 8 - DATA 1 |
||||||
|
;... |
||||||
|
;14 - DATA 7 |
||||||
|
|
||||||
|
.device attiny2313 |
||||||
|
;běží na 4MHz, ckdiv8=1 (vypnuto) |
||||||
|
;250x16=1ms=1000us |
||||||
|
|
||||||
|
;LFUSE: 0xE2 -U lfuse:w:0xE2:m |
||||||
|
;HFUSE: 0xDF -U hfuse:w:0xDF:m |
||||||
|
|
||||||
|
|
||||||
|
;K O N S T A N T Y + P R E Z D I V K Y P O R T U A P I N U |
||||||
|
.equ LCDPORT = PORTB |
||||||
|
.equ LCDPIN = PINB |
||||||
|
.equ LCDDDR = DDRB |
||||||
|
|
||||||
|
.equ RS = 7 |
||||||
|
.equ RW = 6 |
||||||
|
.equ E = 5 |
||||||
|
|
||||||
|
.equ LCD_CLEAR = 0b00000001 |
||||||
|
.equ LCD_HOME = 0b00000010 |
||||||
|
|
||||||
|
.equ LCD_MODE_INC_NOSHIFT = 0b00000110 |
||||||
|
.equ LCD_MODE_INC_SHIFT = 0b00000111 |
||||||
|
.equ LCD_MODE_DEC_NOSHIFT = 0b00000100 |
||||||
|
.equ LCD_MODE_DEC_SHIFT = 0b00000101 |
||||||
|
|
||||||
|
.equ LCD_DISPLAY_DISABLED = 0b00001000 |
||||||
|
.equ LCD_DISPLAY_NOCURSOR = 0b00001100 |
||||||
|
.equ LCD_DISPLAY_CURSOR = 0b00001110 |
||||||
|
.equ LCD_DISPLAY_ALTER = 0b00001101 |
||||||
|
.equ LCD_DISPLAY_CURSOR_ALTER = 0b00001111 |
||||||
|
|
||||||
|
.equ LCD_CURSOR_LEFT = 0b00010000 |
||||||
|
.equ LCD_CURSOR_RIGHT = 0b00010100 |
||||||
|
.equ LCD_SHIFT_LEFT = 0b00011000 |
||||||
|
.equ LCD_SHIFT_RIGHT = 0b00011100 |
||||||
|
|
||||||
|
|
||||||
|
;5x7 font, 1-line |
||||||
|
.equ LCD_MODE_4BIT_1LINE = 0b00100000 |
||||||
|
;.equ LCD_MODE_8BIT_1LINE = 0b00110000 |
||||||
|
;5x7 font, 2-line |
||||||
|
.equ LCD_MODE_4BIT_2LINE = 0b00101000 |
||||||
|
;.equ LCD_MODE_8BIT_2LINE = 0b00111000 |
||||||
|
|
||||||
|
.equ ROW1_ADDR = 0x00 |
||||||
|
.equ ROW2_ADDR = 0x40 |
||||||
|
.equ ROW3_ADDR = 0x14 |
||||||
|
.equ ROW4_ADDR = 0x54 |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;aliases |
||||||
|
.def ZH = r31 |
||||||
|
.def ZL = r30 |
||||||
|
.def YH = r29 |
||||||
|
.def YL = r28 |
||||||
|
.def XH = r27 |
||||||
|
.def XL = r26 |
||||||
|
|
||||||
|
; Z A C A T E K P R O G R A M U |
||||||
|
;vektory preruseni |
||||||
|
.org 0x0000 ;RESET |
||||||
|
rjmp RESET ;skok na start po resetu |
||||||
|
|
||||||
|
.org 0x0013 |
||||||
|
|
||||||
|
;nastaveni po resetu |
||||||
|
.DB "HD44780 INTERFACE" ;(nazev programu) |
||||||
|
RESET: |
||||||
|
ldi r16,low(RAMEND) ;nastavi stack pointer |
||||||
|
out SPL,r16 |
||||||
|
cli ;zakazat vsechna preruseni |
||||||
|
|
||||||
|
; Nastaveni portu |
||||||
|
;PORTB = LCDPORT |
||||||
|
ldi r16,0b11111111 ;smer portu B |
||||||
|
out LCDDDR,r16 |
||||||
|
ldi r16,0b00000000 ;vypnout B |
||||||
|
out LCDPORT,r16 |
||||||
|
|
||||||
|
sei ;Global Interrupt Enable |
||||||
|
|
||||||
|
; == display init == |
||||||
|
rcall LCD_INIT |
||||||
|
|
||||||
|
ldi r17,LCD_MODE_INC_NOSHIFT |
||||||
|
rcall TX_INSTR |
||||||
|
|
||||||
|
ldi r17,LCD_DISPLAY_NOCURSOR |
||||||
|
rcall TX_INSTR |
||||||
|
|
||||||
|
; == load user-defined characters to CGRAM == (default, array label named MYCHARS, end-mark=0xFE) |
||||||
|
ldi r17,0 |
||||||
|
rcall CGRAM_SET_ADDR |
||||||
|
|
||||||
|
ldi ZH,high(MYCHARS*2) |
||||||
|
ldi ZL,low(MYCHARS*2) |
||||||
|
CGRAM_loop: |
||||||
|
lpm r17,Z+ |
||||||
|
cpi r17,0xFE |
||||||
|
breq CGRAM_loop_end |
||||||
|
rcall TX_DATA |
||||||
|
rjmp CGRAM_loop |
||||||
|
CGRAM_loop_end: |
||||||
|
|
||||||
|
|
||||||
|
; == pgm body == |
||||||
|
|
||||||
|
;load text to DDRAM |
||||||
|
ldi r17,ROW1_ADDR |
||||||
|
rcall DDRAM_SET_ADDR |
||||||
|
|
||||||
|
ldi ZH,high(MYTEXT1*2) |
||||||
|
ldi ZL,low(MYTEXT1*2) |
||||||
|
DDRAM_loop: |
||||||
|
lpm r17,Z+ |
||||||
|
cpi r17,0xFE |
||||||
|
breq DDRAM_loop_end |
||||||
|
rcall TX_DATA |
||||||
|
rjmp DDRAM_loop |
||||||
|
DDRAM_loop_end: |
||||||
|
|
||||||
|
;load text to DDRAM |
||||||
|
ldi r17,ROW2_ADDR |
||||||
|
rcall DDRAM_SET_ADDR |
||||||
|
|
||||||
|
ldi ZH,high(MYTEXT2*2) |
||||||
|
ldi ZL,low(MYTEXT2*2) |
||||||
|
DDRAM2_loop: |
||||||
|
lpm r17,Z+ |
||||||
|
cpi r17,0xFE |
||||||
|
breq DDRAM2_loop_end |
||||||
|
rcall TX_DATA |
||||||
|
rjmp DDRAM2_loop |
||||||
|
DDRAM2_loop_end: |
||||||
|
|
||||||
|
;direct write to X,Y - example |
||||||
|
ldi r16,3 ;Y, zacina 0 a roste smerem dolu |
||||||
|
ldi r17,5 ;X, zacina nulou a roste smerem doprava |
||||||
|
rcall LCD_CURSOR_XY |
||||||
|
ldi r17,"%" |
||||||
|
rcall TX_DATA |
||||||
|
ldi r17,"%" |
||||||
|
rcall TX_DATA |
||||||
|
ldi r17,"%" |
||||||
|
rcall TX_DATA |
||||||
|
;infinite loop |
||||||
|
loop: rjmp loop |
||||||
|
|
||||||
|
|
||||||
|
MYTEXT1: |
||||||
|
.DB 0,0,0," POKUSNY TEXT ",0,0,0,0xFE |
||||||
|
MYTEXT2: |
||||||
|
.DB "Opravdu pekny text!",0xFE |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; == USER-DEFINED CHARS == |
||||||
|
MYCHARS: |
||||||
|
; 5x8, first 3 bits are not used |
||||||
|
;end of mychars |
||||||
|
.DB 0xe,0x1f,0x15,0x1f,0x1f,0x1f,0x15 ;smajlik |
||||||
|
|
||||||
|
;konec |
||||||
|
.DB 0xFE |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
;r16=Y |
||||||
|
;r17=X |
||||||
|
LCD_CURSOR_XY: |
||||||
|
cpi r16,0 |
||||||
|
brne test1 |
||||||
|
fail: ldi r16,ROW1_ADDR |
||||||
|
rjmp addrdone |
||||||
|
test1: |
||||||
|
cpi r16,1 |
||||||
|
brne test2 |
||||||
|
ldi r16,ROW2_ADDR |
||||||
|
rjmp addrdone |
||||||
|
test2: |
||||||
|
cpi r16,2 |
||||||
|
brne test3 |
||||||
|
ldi r16,ROW3_ADDR |
||||||
|
rjmp addrdone |
||||||
|
test3: |
||||||
|
cpi r16,3 |
||||||
|
brne fail |
||||||
|
ldi r16,ROW4_ADDR |
||||||
|
addrdone: |
||||||
|
add r17,r16 |
||||||
|
rcall DDRAM_SET_ADDR |
||||||
|
ret |
||||||
|
|
||||||
|
;r16=počet ms (cca) |
||||||
|
delay: |
||||||
|
push r17 ;2 |
||||||
|
push r18 ;2 |
||||||
|
d1: |
||||||
|
ldi r17,250 ;1 |
||||||
|
d2: |
||||||
|
ldi r18,14 ;1 |
||||||
|
d3: |
||||||
|
dec r18 ;1 |
||||||
|
nop |
||||||
|
brne d3 ;2 (1 |
||||||
|
dec r17 ; +1) |
||||||
|
brne d2 ;2 (1 |
||||||
|
dec r16 ; +1) |
||||||
|
brne d1 ;2 (1) |
||||||
|
|
||||||
|
pop r18 ;2 |
||||||
|
pop r17 ;2 |
||||||
|
ret |
||||||
|
|
||||||
|
|
||||||
|
LCD_INIT: |
||||||
|
ldi r16,16 |
||||||
|
rcall delay |
||||||
|
ldi r16,0b00000010 ;4bit |
||||||
|
out PORTB,r16 |
||||||
|
rcall LCD_CLK |
||||||
|
ldi r16,5 |
||||||
|
rcall delay |
||||||
|
ldi r17,LCD_MODE_4BIT_2LINE ;set 4-bit mode |
||||||
|
rcall TX_INSTR |
||||||
|
ret |
||||||
|
|
||||||
|
;r17 |
||||||
|
TX_INSTR: |
||||||
|
swap r17 ;send high nibble |
||||||
|
mov r16,r17 |
||||||
|
andi r16,0b00001111 |
||||||
|
out LCDPORT,r16 |
||||||
|
rcall LCD_CLK |
||||||
|
|
||||||
|
swap r17 ;send low nibble |
||||||
|
mov r16,r17 |
||||||
|
andi r16,0b00001111 |
||||||
|
out LCDPORT,r16 |
||||||
|
rcall LCD_CLK |
||||||
|
|
||||||
|
ret |
||||||
|
|
||||||
|
;r17 |
||||||
|
TX_DATA: |
||||||
|
swap r17 ;send high nibble |
||||||
|
mov r16,r17 |
||||||
|
andi r16,0b00001111 |
||||||
|
sbr r16,(1<<RS) |
||||||
|
out LCDPORT,r16 |
||||||
|
rcall LCD_CLK |
||||||
|
|
||||||
|
swap r17 ;send low nibble |
||||||
|
mov r16,r17 |
||||||
|
andi r16,0b00001111 |
||||||
|
sbr r16,(1<<RS) |
||||||
|
out LCDPORT,r16 |
||||||
|
rcall LCD_CLK |
||||||
|
|
||||||
|
ret |
||||||
|
|
||||||
|
;r17 disabled to reduce code size |
||||||
|
;RX_DATA: |
||||||
|
; ;input |
||||||
|
; ldi r16,0b11110000 ;LCDPORT dirrection (RS RW E n.c.) output, (D7 D6 D5 D4) input |
||||||
|
; out LCDDDR,r16 |
||||||
|
; ldi r16,0b00001111 ;pullups to data pins enabled |
||||||
|
; out LCDPORT,r16 |
||||||
|
; |
||||||
|
; clr r17 |
||||||
|
; ldi r16,(1<<RW)|(1<<RS) |
||||||
|
; out LCDPORT,r16 ;set LCD to read mode, for data |
||||||
|
; |
||||||
|
; rcall LCD_CLK ;receive high nibble |
||||||
|
; in r16,LCDPIN |
||||||
|
; andi r16,0b00001111 |
||||||
|
; or r17,r16 |
||||||
|
; swap r17 ;store high nibble |
||||||
|
; |
||||||
|
; rcall LCD_CLK ;receive low nibble |
||||||
|
; in r16,LCDPIN |
||||||
|
; andi r16,0b00001111 |
||||||
|
; or r17,r16 ;store low nibble |
||||||
|
; |
||||||
|
; ;output |
||||||
|
; ldi r16,0b11111111 ;LCDPORT as output (RS RW E n.c. D7 D6 D5 D4) |
||||||
|
; out LCDDDR,r16 |
||||||
|
; ldi r16,0b00000000 ;LCDPORT off |
||||||
|
; out LCDPORT,r16 |
||||||
|
; |
||||||
|
; ;r17=received value (D7 D6 D5 D4 D3 D2 D1 D0) |
||||||
|
; ret |
||||||
|
|
||||||
|
LCD_CLK: |
||||||
|
sbi LCDPORT,E ;EXECUTE on |
||||||
|
nop |
||||||
|
nop |
||||||
|
nop |
||||||
|
cbi LCDPORT,E ;EXECUTE off |
||||||
|
ldi r16,150 ;pause: 100 for 4MHZ |
||||||
|
clkw: |
||||||
|
dec r16 |
||||||
|
brne clkw |
||||||
|
ret |
||||||
|
|
||||||
|
;r17 |
||||||
|
;7 bitu (1.radek zacina 00,druhej 40) |
||||||
|
DDRAM_SET_ADDR: |
||||||
|
clr r16 |
||||||
|
sbr r16,0b10000000 |
||||||
|
or r17,r16 |
||||||
|
rcall TX_INSTR |
||||||
|
ret |
||||||
|
|
||||||
|
;r17 |
||||||
|
;6 bitu (5,4,3 = znak, 2,1,0 = radek - shora) |
||||||
|
CGRAM_SET_ADDR: |
||||||
|
clr r16 |
||||||
|
sbr r16,0b01000000 |
||||||
|
or r17,r16 |
||||||
|
rcall TX_INSTR |
||||||
|
ret |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,426 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include "lib/meta.h" |
||||||
|
#include "lib/arduino_pins.h" |
||||||
|
#include "lib/calc.h" |
||||||
|
#include "lib/adc.h" |
||||||
|
|
||||||
|
#define LCD_PIN_RS D10 |
||||||
|
#define LCD_PIN_RW D11 |
||||||
|
#define LCD_PIN_E D12 |
||||||
|
#define LCD_PIN_D4 D13 |
||||||
|
#define LCD_PIN_D5 D14 |
||||||
|
#define LCD_PIN_D6 D15 |
||||||
|
#define LCD_PIN_D7 D16 |
||||||
|
// D17 = A3 = source of entropy for random.
|
||||||
|
|
||||||
|
#include "lib/lcd.h" |
||||||
|
|
||||||
|
|
||||||
|
// Buttons (to ground)
|
||||||
|
#define BTN_LEFT D2 |
||||||
|
#define BTN_RIGHT D3 |
||||||
|
#define BTN_UP D4 |
||||||
|
#define BTN_DOWN D5 |
||||||
|
#define BTN_SELECT D6 |
||||||
|
#define BTN_RESTART D7 |
||||||
|
|
||||||
|
// Debouncer channels for buttons
|
||||||
|
// (Must be added in this order to debouncer)
|
||||||
|
#define D_LEFT 0 |
||||||
|
#define D_RIGHT 1 |
||||||
|
#define D_UP 2 |
||||||
|
#define D_DOWN 3 |
||||||
|
#define D_SELECT 4 |
||||||
|
#define D_RESTART 5 |
||||||
|
|
||||||
|
#define DEBO_CHANNELS 6 |
||||||
|
#define DEBO_TICKS 1 // in 0.01s
|
||||||
|
|
||||||
|
#include "lib/debounce.h" |
||||||
|
|
||||||
|
// Board size (!!! rows = 2x number of display lines, max 2*4 = 8 !!!)
|
||||||
|
#define ROWS 4 |
||||||
|
#define COLS 20 |
||||||
|
|
||||||
|
// Delay between snake steps, in 10 ms
|
||||||
|
#define STEP_DELAY 24 |
||||||
|
|
||||||
|
// proto
|
||||||
|
void update(); |
||||||
|
void init_cgram(); |
||||||
|
void init_gameboard(); |
||||||
|
|
||||||
|
void SECTION(".init8") init() |
||||||
|
{ |
||||||
|
// Randomize RNG
|
||||||
|
adc_init(); |
||||||
|
srand(adc_read_word(3)); |
||||||
|
|
||||||
|
// Init LCD
|
||||||
|
lcd_init(); |
||||||
|
init_cgram(); // load default glyphs
|
||||||
|
|
||||||
|
// Init game board.
|
||||||
|
init_gameboard(); |
||||||
|
|
||||||
|
// gamepad buttons
|
||||||
|
as_input_pu(BTN_LEFT); |
||||||
|
as_input_pu(BTN_RIGHT); |
||||||
|
as_input_pu(BTN_UP); |
||||||
|
as_input_pu(BTN_DOWN); |
||||||
|
as_input_pu(BTN_SELECT); |
||||||
|
as_input_pu(BTN_RESTART); |
||||||
|
|
||||||
|
// add buttons to debouncer
|
||||||
|
debo_add_rev(BTN_LEFT); |
||||||
|
debo_add_rev(BTN_RIGHT); |
||||||
|
debo_add_rev(BTN_UP); |
||||||
|
debo_add_rev(BTN_DOWN); |
||||||
|
debo_add_rev(BTN_SELECT); |
||||||
|
debo_add_rev(BTN_RESTART); |
||||||
|
|
||||||
|
// setup timer
|
||||||
|
TCCR0A = _BV(WGM01); // CTC
|
||||||
|
TCCR0B = _BV(CS02) | _BV(CS00); // prescaler 1024
|
||||||
|
OCR0A = 156; // interrupt every 10 ms
|
||||||
|
sbi(TIMSK0, OCIE0A); |
||||||
|
sei(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** timer 0 interrupt vector */ |
||||||
|
ISR(TIMER0_COMPA_vect) |
||||||
|
{ |
||||||
|
debo_tick(); // poll debouncer
|
||||||
|
update(); // update and display
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// sub-glyphs
|
||||||
|
#define _HEAD_ 15, 21, 21, 30 |
||||||
|
#define _BODY_ 15, 31, 31, 30 |
||||||
|
#define _FOOD_ 10, 21, 17, 14 |
||||||
|
//14, 17, 17, 14
|
||||||
|
#define _NONE_ 0, 0, 0, 0 |
||||||
|
|
||||||
|
// complete glyphs for loading into memory
|
||||||
|
|
||||||
|
// Only one food & one head glyph have to be loaded at a time.
|
||||||
|
|
||||||
|
// Body - Body
|
||||||
|
const uint8_t SYMBOL_BB[] PROGMEM = {_BODY_, _BODY_}; |
||||||
|
|
||||||
|
// Body - None
|
||||||
|
const uint8_t SYMBOL_BX[] PROGMEM = {_BODY_, _NONE_}; |
||||||
|
const uint8_t SYMBOL_XB[] PROGMEM = {_NONE_, _BODY_}; |
||||||
|
|
||||||
|
// Head - None
|
||||||
|
const uint8_t SYMBOL_HX[] PROGMEM = {_HEAD_, _NONE_}; |
||||||
|
const uint8_t SYMBOL_XH[] PROGMEM = {_NONE_, _HEAD_}; |
||||||
|
|
||||||
|
// Body - Head
|
||||||
|
const uint8_t SYMBOL_BH[] PROGMEM = {_BODY_, _HEAD_}; |
||||||
|
const uint8_t SYMBOL_HB[] PROGMEM = {_HEAD_, _BODY_}; |
||||||
|
|
||||||
|
// Head - Food
|
||||||
|
const uint8_t SYMBOL_HF[] PROGMEM = {_HEAD_, _FOOD_}; |
||||||
|
const uint8_t SYMBOL_FH[] PROGMEM = {_FOOD_, _HEAD_}; |
||||||
|
|
||||||
|
// Food - None
|
||||||
|
const uint8_t SYMBOL_FX[] PROGMEM = {_FOOD_, _NONE_}; |
||||||
|
const uint8_t SYMBOL_XF[] PROGMEM = {_NONE_, _FOOD_}; |
||||||
|
|
||||||
|
// Body - Food
|
||||||
|
const uint8_t SYMBOL_BF[] PROGMEM = {_BODY_, _FOOD_}; |
||||||
|
const uint8_t SYMBOL_FB[] PROGMEM = {_FOOD_, _BODY_}; |
||||||
|
|
||||||
|
|
||||||
|
// board block (snake, food...)
|
||||||
|
typedef enum { |
||||||
|
bEMPTY = 0x00, |
||||||
|
bHEAD = 0x01, |
||||||
|
bFOOD = 0x02, |
||||||
|
bBODY_LEFT = 0x80, |
||||||
|
bBODY_RIGHT = 0x81, |
||||||
|
bBODY_UP = 0x82, |
||||||
|
bBODY_DOWN = 0x83, |
||||||
|
} block_t; |
||||||
|
|
||||||
|
// Snake direction
|
||||||
|
typedef enum { |
||||||
|
dLEFT = 0x00, |
||||||
|
dRIGHT = 0x01, |
||||||
|
dUP = 0x02, |
||||||
|
dDOWN = 0x03, |
||||||
|
} dir_t; |
||||||
|
|
||||||
|
// Coordinate on board
|
||||||
|
typedef struct { |
||||||
|
int8_t x; |
||||||
|
int8_t y; |
||||||
|
} coord_t; |
||||||
|
|
||||||
|
#define is_body(blk) (((blk) & 0x80) != 0) |
||||||
|
#define mk_body_dir(dir) (0x80 + (dir)) |
||||||
|
|
||||||
|
// compare two coords
|
||||||
|
#define coord_eq(a, b) (((a).x == (b).x) && ((a).y == (b).y)) |
||||||
|
|
||||||
|
|
||||||
|
bool crashed; |
||||||
|
uint8_t snake_len; |
||||||
|
|
||||||
|
// y, x indexing
|
||||||
|
block_t board[ROWS][COLS]; |
||||||
|
|
||||||
|
coord_t head_pos; |
||||||
|
coord_t tail_pos; |
||||||
|
dir_t head_dir; |
||||||
|
|
||||||
|
const uint8_t CODE_BB = 0; |
||||||
|
const uint8_t CODE_BX = 1; |
||||||
|
const uint8_t CODE_XB = 2; |
||||||
|
const uint8_t CODE_H = 3; // glyph with head, dynamic
|
||||||
|
const uint8_t CODE_F = 4; // glyph with food, dynamic
|
||||||
|
const uint8_t CODE_XX = 32; // space
|
||||||
|
|
||||||
|
|
||||||
|
// Set a block in board
|
||||||
|
#define set_block_xy(x, y, block) do { board[y][x] = (block); } while(0) |
||||||
|
#define get_block_xy(x, y) board[y][x] |
||||||
|
#define get_block(pos) get_block_xy((pos).x, (pos).y) |
||||||
|
#define set_block(pos, block) set_block_xy((pos).x, (pos).y, (block)) |
||||||
|
|
||||||
|
|
||||||
|
void init_cgram() |
||||||
|
{ |
||||||
|
// those will be always the same
|
||||||
|
lcd_define_glyph_pgm(CODE_BB, SYMBOL_BB); |
||||||
|
lcd_define_glyph_pgm(CODE_BX, SYMBOL_BX); |
||||||
|
lcd_define_glyph_pgm(CODE_XB, SYMBOL_XB); |
||||||
|
lcd_define_glyph_pgm(5, SYMBOL_XF); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void place_food() |
||||||
|
{ |
||||||
|
while(1) { |
||||||
|
const uint8_t xx = rand() % COLS; |
||||||
|
const uint8_t yy = rand() % ROWS; |
||||||
|
|
||||||
|
if (get_block_xy(xx, yy) == bEMPTY) { |
||||||
|
set_block_xy(xx, yy, bFOOD); |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void init_gameboard() |
||||||
|
{ |
||||||
|
//erase the board
|
||||||
|
for (uint8_t x = 0; x < COLS; x++) { |
||||||
|
for (uint8_t y = 0; y < ROWS; y++) { |
||||||
|
set_block_xy(x, y, bEMPTY); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
lcd_clear(); |
||||||
|
|
||||||
|
tail_pos = (coord_t) {.x = 0, .y = 0}; |
||||||
|
|
||||||
|
set_block_xy(0, 0, bBODY_RIGHT); |
||||||
|
set_block_xy(1, 0, bBODY_RIGHT); |
||||||
|
set_block_xy(2, 0, bBODY_RIGHT); |
||||||
|
set_block_xy(3, 0, bHEAD); |
||||||
|
|
||||||
|
head_pos = (coord_t) {.x = 3, .y = 0}; |
||||||
|
|
||||||
|
snake_len = 4; // includes head
|
||||||
|
|
||||||
|
head_dir = dRIGHT; |
||||||
|
crashed = false; |
||||||
|
|
||||||
|
place_food(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
uint8_t presc = 0; |
||||||
|
|
||||||
|
bool restart_held; |
||||||
|
void update() |
||||||
|
{ |
||||||
|
if (debo_get_pin(D_RESTART)) { |
||||||
|
|
||||||
|
if (!restart_held) { |
||||||
|
// restart
|
||||||
|
init_gameboard(); |
||||||
|
presc = 0; |
||||||
|
restart_held = true; |
||||||
|
} |
||||||
|
|
||||||
|
} else { |
||||||
|
restart_held = false; |
||||||
|
} |
||||||
|
|
||||||
|
if(!crashed) { |
||||||
|
|
||||||
|
// resolve movement direction
|
||||||
|
if (debo_get_pin(D_LEFT)) |
||||||
|
head_dir = dLEFT; |
||||||
|
else if (debo_get_pin(D_RIGHT)) |
||||||
|
head_dir = dRIGHT; |
||||||
|
else if (debo_get_pin(D_UP)) |
||||||
|
head_dir = dUP; |
||||||
|
else if (debo_get_pin(D_DOWN)) |
||||||
|
head_dir = dDOWN; |
||||||
|
|
||||||
|
// time's up for a move
|
||||||
|
if (presc++ == STEP_DELAY) { |
||||||
|
presc = 0; |
||||||
|
|
||||||
|
// move snake
|
||||||
|
const coord_t oldpos = head_pos; |
||||||
|
|
||||||
|
switch (head_dir) { |
||||||
|
case dLEFT: head_pos.x--; break; |
||||||
|
case dRIGHT: head_pos.x++; break; |
||||||
|
case dUP: head_pos.y--; break; |
||||||
|
case dDOWN: head_pos.y++; break; |
||||||
|
} |
||||||
|
|
||||||
|
bool do_move = false; |
||||||
|
bool do_grow = false; |
||||||
|
|
||||||
|
if (head_pos.x < 0 || head_pos.x >= COLS || head_pos.y < 0 || head_pos.y >= ROWS) { |
||||||
|
// ouch, a wall!
|
||||||
|
crashed = true; |
||||||
|
} else { |
||||||
|
// check if tile occupied or not
|
||||||
|
if (coord_eq(head_pos, tail_pos)) { |
||||||
|
// head moved in previous tail, that's OK.
|
||||||
|
do_move = true; |
||||||
|
} else { |
||||||
|
// moved to other tile than tail
|
||||||
|
switch (get_block(head_pos)) { |
||||||
|
|
||||||
|
case bFOOD: |
||||||
|
do_grow = true; // fall through
|
||||||
|
case bEMPTY: |
||||||
|
do_move = true; |
||||||
|
break; |
||||||
|
|
||||||
|
default: // includes all BODY_xxx
|
||||||
|
crashed = true; // snake crashed into some block
|
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (do_move) { |
||||||
|
// Move tail
|
||||||
|
if (do_grow) { |
||||||
|
// let tail as is
|
||||||
|
snake_len++; // grow the counter
|
||||||
|
} else { |
||||||
|
// tail dir
|
||||||
|
dir_t td = get_block(tail_pos) & 0xF; |
||||||
|
|
||||||
|
// clean tail
|
||||||
|
set_block(tail_pos, bEMPTY); |
||||||
|
|
||||||
|
// move tail based on old direction of tail block
|
||||||
|
switch (td) { |
||||||
|
case dLEFT: tail_pos.x--; break; |
||||||
|
case dRIGHT: tail_pos.x++; break; |
||||||
|
case dUP: tail_pos.y--; break; |
||||||
|
case dDOWN: tail_pos.y++; break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Move head
|
||||||
|
set_block(head_pos, bHEAD); // place head in new pos
|
||||||
|
set_block(oldpos, mk_body_dir(head_dir)); // directional body in old head pos
|
||||||
|
|
||||||
|
if (do_grow) { |
||||||
|
// food eaten, place new
|
||||||
|
place_food(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} // end !crashed
|
||||||
|
|
||||||
|
|
||||||
|
// Render the board
|
||||||
|
for (uint8_t r = 0; r < ROWS / 2; r++) { |
||||||
|
lcd_xy(0, r); |
||||||
|
for (uint8_t c = 0; c < COLS; c++) { |
||||||
|
const block_t t1 = get_block_xy(c, r * 2); |
||||||
|
const block_t t2 = get_block_xy(c, (r * 2) + 1); |
||||||
|
|
||||||
|
uint8_t code = '!'; // ! marks fail
|
||||||
|
|
||||||
|
if ((t1 == bEMPTY) && (t2 == bEMPTY)) { |
||||||
|
code = CODE_XX; |
||||||
|
if (crashed) code = '*'; |
||||||
|
} else if (is_body(t1) && is_body(t2)) |
||||||
|
code = CODE_BB; |
||||||
|
else if (is_body(t1) && (t2 == bEMPTY)) |
||||||
|
code = CODE_BX; |
||||||
|
else if (t1 == bEMPTY && is_body(t2)) |
||||||
|
code = CODE_XB; |
||||||
|
else if ((t1 == bFOOD) || (t2 == bFOOD)) { |
||||||
|
// one is food
|
||||||
|
|
||||||
|
code = CODE_F; |
||||||
|
|
||||||
|
if (t1 == bFOOD) { |
||||||
|
if (t2 == bEMPTY) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_FX); |
||||||
|
else if (t2 == bHEAD) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_FH); |
||||||
|
else if (is_body(t2)) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_FB); |
||||||
|
} else { // t2 is food
|
||||||
|
if (t1 == bEMPTY) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_XF); |
||||||
|
else if (t1 == bHEAD) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_HF); |
||||||
|
else if (is_body(t1)) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_BF); |
||||||
|
} |
||||||
|
lcd_xy(c,r); |
||||||
|
|
||||||
|
} else if ((t1 == bHEAD )|| (t2 == bHEAD)) { |
||||||
|
// one is head
|
||||||
|
|
||||||
|
code = CODE_H; |
||||||
|
|
||||||
|
if (t1 == bHEAD) { |
||||||
|
if (t2 == bEMPTY) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_HX); |
||||||
|
else if (is_body(t2)) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_HB); |
||||||
|
} else { // t2 is head
|
||||||
|
if (t1 == bEMPTY) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_XH); |
||||||
|
else if (is_body(t1)) |
||||||
|
lcd_define_glyph_pgm(code, SYMBOL_BH); |
||||||
|
} |
||||||
|
|
||||||
|
lcd_xy(c,r); |
||||||
|
} |
||||||
|
|
||||||
|
lcd_char(code); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void main() { while(1); } // timer does everything
|
@ -0,0 +1,147 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c iopins.c color.c wsrgb.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
fser: all flash ser |
||||||
|
|
||||||
|
ser: |
||||||
|
gtkterm -p /dev/ttyUSB0
|
||||||
|
|
||||||
|
cl: |
||||||
|
./client /dev/ttyUSB0 9600
|
||||||
|
|
||||||
|
fcl: all flash |
||||||
|
./client /dev/ttyUSB0 9600
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
Binary file not shown.
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,32 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "lib/iopins.h" |
||||||
|
#include "lib/wsrgb.h" |
||||||
|
#include "lib/uart.h" |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
ws_init(); |
||||||
|
|
||||||
|
xrgb_t c[3]; |
||||||
|
c[0] = xrgb(255, 0, 255); |
||||||
|
c[1] = xrgb(0, 255, 255); |
||||||
|
c[2] = xrgb(255, 255, 0); |
||||||
|
|
||||||
|
while(1) { |
||||||
|
ws_send_xrgb_array(c, 3); |
||||||
|
|
||||||
|
ws_show(); |
||||||
|
|
||||||
|
c[0].r++; |
||||||
|
c[1].b++; |
||||||
|
c[2].g++; |
||||||
|
|
||||||
|
_delay_ms(10); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
#define WS_T_1H 700 |
||||||
|
#define WS_T_1L 150 |
||||||
|
#define WS_T_0H 150 |
||||||
|
#define WS_T_0L 700 |
||||||
|
#define WS_T_LATCH 7000 |
||||||
|
|
||||||
|
#define WS_PIN 2 |
@ -0,0 +1,147 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c uart_ansi.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
fser: all flash serial |
||||||
|
|
||||||
|
ser: |
||||||
|
gtkterm -p /dev/ttyUSB0
|
||||||
|
|
||||||
|
cl: |
||||||
|
./client /dev/ttyUSB0 9600
|
||||||
|
|
||||||
|
fcl: all flash |
||||||
|
./client /dev/ttyUSB0 9600
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
Binary file not shown.
@ -0,0 +1,7 @@ |
|||||||
|
all: client |
||||||
|
|
||||||
|
client: main.c |
||||||
|
gcc -std=gnu99 main.c serial.c -o client
|
||||||
|
|
||||||
|
run: client |
||||||
|
./client /dev/ttyUSB0 9600
|
Binary file not shown.
@ -0,0 +1,37 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
#include "serial.h" |
||||||
|
|
||||||
|
int main(int argc, char const *argv[]) |
||||||
|
{ |
||||||
|
if (argc < 2) { fprintf(stderr, "Missing parameter <device>\n"); return 1; } |
||||||
|
|
||||||
|
int baud = 9600; |
||||||
|
if (argc == 3) sscanf(argv[2], "%d", &baud); |
||||||
|
|
||||||
|
int fd = serial_open(argv[1], baud); |
||||||
|
|
||||||
|
// Wait for the Arduino to start
|
||||||
|
usleep(1500000); |
||||||
|
|
||||||
|
// Redirecting stdin/stdout to arduino
|
||||||
|
while(1) { |
||||||
|
char buf[1]; |
||||||
|
if (fread(buf, 1, 1, stdin) > 0) { |
||||||
|
serial_write(fd, buf[0]); |
||||||
|
fflush(stdout); |
||||||
|
} |
||||||
|
|
||||||
|
char c; |
||||||
|
c = serial_read(fd, 10); |
||||||
|
if (c > 0) { |
||||||
|
putchar(c); |
||||||
|
fflush(stdout); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,89 @@ |
|||||||
|
#define _POSIX_SOURCE |
||||||
|
#define _GNU_SOURCE |
||||||
|
|
||||||
|
#include <sys/types.h> |
||||||
|
#include <sys/stat.h> |
||||||
|
#include <sys/ioctl.h> |
||||||
|
#include <fcntl.h> |
||||||
|
#include <termios.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <string.h> |
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
#include "serial.h" |
||||||
|
|
||||||
|
|
||||||
|
/** Open a serial port */ |
||||||
|
int serial_open(const char* port, const unsigned int baud) |
||||||
|
{ |
||||||
|
int fd = open(port, O_RDWR | O_NONBLOCK); |
||||||
|
|
||||||
|
struct termios tio; |
||||||
|
memset(&tio, 0, sizeof(tio)); |
||||||
|
|
||||||
|
speed_t bd = baud; |
||||||
|
switch(bd) { |
||||||
|
case 1200: bd = B1200; break; |
||||||
|
case 1800: bd = B1800; break; |
||||||
|
case 2400: bd = B2400; break; |
||||||
|
case 4800: bd = B4800; break; |
||||||
|
case 9600: bd = B9600; break; |
||||||
|
case 19200: bd = B19200; break; |
||||||
|
case 38400: bd = B38400; break; |
||||||
|
} |
||||||
|
|
||||||
|
tio.c_cflag = bd | CS8 | CLOCAL | CREAD | CRTSCTS; |
||||||
|
tio.c_iflag = IGNPAR; |
||||||
|
|
||||||
|
tcflush(fd, TCIFLUSH); |
||||||
|
tcsetattr(fd, TCSANOW, &tio); |
||||||
|
return fd; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Close a serial port */ |
||||||
|
int serial_close(int fd) |
||||||
|
{ |
||||||
|
return close(fd); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a byte. Returns false on failure */ |
||||||
|
int serial_write(int fd, uint8_t b) |
||||||
|
{ |
||||||
|
return write(fd, &b, 1); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int serial_puts(int fd, const char* str) |
||||||
|
{ |
||||||
|
int len = strlen(str); |
||||||
|
return write(fd, str, len); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
uint8_t serial_read(int fd, int timeout) |
||||||
|
{ |
||||||
|
uint8_t b[1]; |
||||||
|
do { |
||||||
|
int n = read(fd, b, 1); |
||||||
|
if (n == -1) return -1; |
||||||
|
if (n == 0) { |
||||||
|
usleep(1 * 1000); // wait 1 ms
|
||||||
|
timeout--; |
||||||
|
continue; |
||||||
|
} |
||||||
|
return b[0]; |
||||||
|
} while(timeout > 0); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int serial_flush(int fd) |
||||||
|
{ |
||||||
|
sleep(2); |
||||||
|
return tcflush(fd, TCIOFLUSH); |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
|
||||||
|
/** Open a serial port */ |
||||||
|
int serial_open(const char* port, const unsigned int baud); |
||||||
|
|
||||||
|
|
||||||
|
/** Close a serial port */ |
||||||
|
int serial_close(int fd); |
||||||
|
|
||||||
|
|
||||||
|
/** Write a byte. Returns false on failure */ |
||||||
|
int serial_write(int fd, uint8_t b); |
||||||
|
|
||||||
|
|
||||||
|
/** Send a string */ |
||||||
|
int serial_puts(int fd, const char* str); |
||||||
|
|
||||||
|
|
||||||
|
/** Read a byte */ |
||||||
|
uint8_t serial_read(int fd, int timeout); |
||||||
|
|
||||||
|
|
||||||
|
/** Flush */ |
||||||
|
int serial_flush(int fd); |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,25 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include "lib/uart.h" |
||||||
|
|
||||||
|
ISR(USART_RX_vect) |
||||||
|
{ |
||||||
|
uint8_t x = uart_rx(); |
||||||
|
uart_tx(x); |
||||||
|
} |
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
uart_init(9600); |
||||||
|
uart_isr_rx(1); |
||||||
|
sei(); |
||||||
|
while(1) { |
||||||
|
//uart_puts_P(PSTR("TEST"));
|
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
|
||||||
|
Es [ ? |
||||||
|
left 27 91 68 |
||||||
|
right 27 91 67 |
||||||
|
up 27 91 65 |
||||||
|
down 27 91 66 |
||||||
|
|
||||||
|
Es [ ? ~ |
||||||
|
insert 27 91 50 126 |
||||||
|
delete 27 91 51 126 |
||||||
|
pgup 27 91 53 126 |
||||||
|
pgdn 27 91 54 126 |
||||||
|
|
||||||
|
Es O ? |
||||||
|
f1 27 79 80 |
||||||
|
f2 27 79 81 |
||||||
|
f3 27 79 82 |
||||||
|
f4 27 79 83 |
||||||
|
home 27 79 72 |
||||||
|
end 27 79 70 |
||||||
|
|
||||||
|
back 8 |
||||||
|
tab 9 |
||||||
|
enter 13 |
||||||
|
esc 27 |
@ -0,0 +1,137 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE =
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES = uart.c uart_ansi.c sonar.c
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
@ -0,0 +1,13 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
// Pin config file for LCD.
|
||||||
|
|
||||||
|
#include "lib/arduino_pins.h" |
||||||
|
|
||||||
|
#define LCD_RS D2 |
||||||
|
#define LCD_RW D3 |
||||||
|
#define LCD_E D4 |
||||||
|
#define LCD_D4 D5 |
||||||
|
#define LCD_D5 D6 |
||||||
|
#define LCD_D6 D7 |
||||||
|
#define LCD_D7 D8 |
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,91 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
|
||||||
|
#include "lib/calc.h" |
||||||
|
#include "lib/uart.h" |
||||||
|
#include "lib/uart_ansi.h" |
||||||
|
#include "lib/pins.h" |
||||||
|
#include "lib/arduino_pins.h" |
||||||
|
#include "lib/sonar.h" |
||||||
|
|
||||||
|
ISR(PCINT0_vect) |
||||||
|
{ |
||||||
|
if (sonar_handle_pci()) return; |
||||||
|
} |
||||||
|
|
||||||
|
// All PCINT vectors must call sonar_handle_pci
|
||||||
|
// This way, they are linked to PCINT0
|
||||||
|
// so we can avoid code duplication
|
||||||
|
ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect)); |
||||||
|
ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect)); |
||||||
|
|
||||||
|
|
||||||
|
// Timer overflow - if sonar has a timeout -> 0xFFFF in result.
|
||||||
|
ISR(TIMER1_OVF_vect) |
||||||
|
{ |
||||||
|
if (sonar_handle_t1ovf()) return; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
uart_init(9600); |
||||||
|
vt_init(); |
||||||
|
|
||||||
|
sonar_t so; |
||||||
|
sonar_t so2; |
||||||
|
|
||||||
|
sonar_init(&so, A0, A1); |
||||||
|
sonar_init(&so2, A2, A3); |
||||||
|
|
||||||
|
sei(); |
||||||
|
|
||||||
|
// end
|
||||||
|
int16_t res; |
||||||
|
while(1) { |
||||||
|
vt_clear(); |
||||||
|
vt_home(); |
||||||
|
uart_puts_pgm(PSTR("SONAR\r\n===================")); |
||||||
|
|
||||||
|
// first
|
||||||
|
vt_goto(99, 99); // move cursor away
|
||||||
|
sonar_start(&so); |
||||||
|
while(sonar_busy()); |
||||||
|
res = sonar_result(); |
||||||
|
|
||||||
|
// print value
|
||||||
|
vt_goto(0, 2); |
||||||
|
uart_puts_pgm(PSTR("A: ")); |
||||||
|
|
||||||
|
if (res < 0) { |
||||||
|
uart_puts_pgm(PSTR("No Obstacle")); |
||||||
|
} else { |
||||||
|
uart_puti(res, 1); |
||||||
|
uart_puts_pgm(PSTR(" cm")); |
||||||
|
} |
||||||
|
|
||||||
|
// second
|
||||||
|
vt_goto(99, 99); // move cursor away
|
||||||
|
sonar_start(&so2); |
||||||
|
while(sonar_busy()); |
||||||
|
res = sonar_result(); |
||||||
|
|
||||||
|
// print value
|
||||||
|
vt_goto(0, 3); |
||||||
|
uart_puts_pgm(PSTR("B: ")); |
||||||
|
|
||||||
|
if (res < 0) { |
||||||
|
uart_puts_pgm(PSTR("No Obstacle")); |
||||||
|
} else { |
||||||
|
uart_puti(res, 1); |
||||||
|
uart_puts_pgm(PSTR(" cm")); |
||||||
|
} |
||||||
|
|
||||||
|
vt_goto(99, 99); // move cursor away
|
||||||
|
_delay_ms(200); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,147 @@ |
|||||||
|
## === CPU settings ===
|
||||||
|
# CPU type
|
||||||
|
MCU = atmega328p
|
||||||
|
# CPU frequency
|
||||||
|
F_CPU = 16000000
|
||||||
|
# Fuses
|
||||||
|
LFUSE = 0xFF
|
||||||
|
HFUSE = 0xDE
|
||||||
|
EFUSE = 0x05
|
||||||
|
|
||||||
|
|
||||||
|
## === Source files ===
|
||||||
|
# Main C file
|
||||||
|
MAIN = main.c
|
||||||
|
# Extra C files in this folder
|
||||||
|
LOCAL_SOURCE = fat16.c
|
||||||
|
|
||||||
|
# Library directory (with C files)
|
||||||
|
EXTRA_SOURCE_DIR = lib/
|
||||||
|
# C files in the library directory
|
||||||
|
EXTRA_SOURCE_FILES =
|
||||||
|
|
||||||
|
|
||||||
|
## === Programmer ===
|
||||||
|
PROGRAMMER_TYPE = arduino
|
||||||
|
PROGRAMMER_ARGS = -b 57600 -P /dev/ttyUSB0
|
||||||
|
|
||||||
|
|
||||||
|
## === C flags ===
|
||||||
|
|
||||||
|
CFLAGS = -std=gnu99 -mmcu=$(MCU) -DF_CPU=$(F_CPU)UL -I. -I$(EXTRA_SOURCE_DIR)
|
||||||
|
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||||
|
CFLAGS += -Wall -Wno-main -Wno-strict-prototypes -Wno-comment
|
||||||
|
CFLAGS += -g2 -Wextra -Wfatal-errors -Wno-unused-but-set-variable
|
||||||
|
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections -Wl,--relax
|
||||||
|
# CFLAGS += -lm ## Math
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
|
||||||
|
# CFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
|
||||||
|
CFLAGS_BUILD = $(CFLAGS) -Os
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
## Defined programs / locations
|
||||||
|
CC = avr-gcc
|
||||||
|
OBJCOPY = avr-objcopy
|
||||||
|
OBJDUMP = avr-objdump
|
||||||
|
AVRSIZE = avr-size
|
||||||
|
AVRDUDE = avrdude
|
||||||
|
|
||||||
|
## === File lists ===
|
||||||
|
TARGET = $(strip $(basename $(MAIN)))
|
||||||
|
SRC1 = $(TARGET).c
|
||||||
|
SRC = $(SRC1)
|
||||||
|
EXTRA_SOURCE = $(addprefix $(EXTRA_SOURCE_DIR), $(EXTRA_SOURCE_FILES))
|
||||||
|
SRC += $(EXTRA_SOURCE)
|
||||||
|
SRC += $(LOCAL_SOURCE)
|
||||||
|
|
||||||
|
HEADERS = $(SRC:.c=.h)
|
||||||
|
OBJ = $(SRC:.c=.o)
|
||||||
|
|
||||||
|
|
||||||
|
## === File generation ===
|
||||||
|
all: $(TARGET).hex size |
||||||
|
pre: $(TARGET).pre |
||||||
|
|
||||||
|
%.hex: %.elf |
||||||
|
$(OBJCOPY) -R .eeprom -O ihex $< $@
|
||||||
|
|
||||||
|
%.elf: $(SRC) |
||||||
|
$(CC) $(CFLAGS_BUILD) $(SRC) --output $@
|
||||||
|
|
||||||
|
%.pre: $(SRC1) |
||||||
|
$(CC) $(CFLAGS) -E $(SRC1) --output $@
|
||||||
|
|
||||||
|
%.eeprom: %.elf |
||||||
|
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
|
||||||
|
|
||||||
|
%.lst: %.elf |
||||||
|
$(OBJDUMP) -S $< > $@
|
||||||
|
|
||||||
|
# Show debug info
|
||||||
|
debug: |
||||||
|
@echo
|
||||||
|
@echo "Source files:" $(SRC)
|
||||||
|
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
|
||||||
|
@echo
|
||||||
|
|
||||||
|
|
||||||
|
# Disassemble the ELF
|
||||||
|
disassemble: $(TARGET).lst |
||||||
|
dis: disassemble |
||||||
|
lst: disassemble |
||||||
|
|
||||||
|
# Make eeprom file
|
||||||
|
eeprom: $(TARGET).eeprom |
||||||
|
|
||||||
|
# Show how big the resulting program is
|
||||||
|
size: $(TARGET).elf |
||||||
|
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
|
||||||
|
|
||||||
|
# Clean all produced trash
|
||||||
|
clean: |
||||||
|
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
|
||||||
|
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
|
||||||
|
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
|
||||||
|
$(TARGET).eeprom
|
||||||
|
|
||||||
|
# Clean all trash
|
||||||
|
purge: |
||||||
|
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~
|
||||||
|
|
||||||
|
|
||||||
|
## === avrdude ===
|
||||||
|
|
||||||
|
flash: $(TARGET).hex |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
|
||||||
|
|
||||||
|
flashe: $(TARGET).eeprom |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
|
||||||
|
|
||||||
|
shell: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
|
||||||
|
|
||||||
|
fser: all flash serial |
||||||
|
|
||||||
|
ser: |
||||||
|
gtkterm -p /dev/ttyUSB0
|
||||||
|
|
||||||
|
cl: |
||||||
|
./client /dev/ttyUSB0 9600
|
||||||
|
|
||||||
|
fcl: all flash |
||||||
|
./client /dev/ttyUSB0 9600
|
||||||
|
|
||||||
|
# === fuses ===
|
||||||
|
|
||||||
|
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
|
||||||
|
|
||||||
|
fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
|
||||||
|
$(PROGRAMMER_ARGS) $(FUSE_STRING)
|
||||||
|
show_fuses: |
||||||
|
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
|
||||||
|
|
||||||
|
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m |
||||||
|
set_default_fuses: fuses |
Binary file not shown.
@ -0,0 +1,7 @@ |
|||||||
|
all: client |
||||||
|
|
||||||
|
client: main.c |
||||||
|
gcc -std=gnu99 main.c serial.c -o client
|
||||||
|
|
||||||
|
run: client |
||||||
|
./client /dev/ttyUSB0 9600
|
Binary file not shown.
@ -0,0 +1,37 @@ |
|||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
#include "serial.h" |
||||||
|
|
||||||
|
int main(int argc, char const *argv[]) |
||||||
|
{ |
||||||
|
if (argc < 2) { fprintf(stderr, "Missing parameter <device>\n"); return 1; } |
||||||
|
|
||||||
|
int baud = 9600; |
||||||
|
if (argc == 3) sscanf(argv[2], "%d", &baud); |
||||||
|
|
||||||
|
int fd = serial_open(argv[1], baud); |
||||||
|
|
||||||
|
// Wait for the Arduino to start
|
||||||
|
usleep(1500000); |
||||||
|
|
||||||
|
// Redirecting stdin/stdout to arduino
|
||||||
|
while(1) { |
||||||
|
char buf[1]; |
||||||
|
if (fread(buf, 1, 1, stdin) > 0) { |
||||||
|
serial_write(fd, buf[0]); |
||||||
|
fflush(stdout); |
||||||
|
} |
||||||
|
|
||||||
|
char c; |
||||||
|
c = serial_read(fd, 10); |
||||||
|
if (c > 0) { |
||||||
|
putchar(c); |
||||||
|
fflush(stdout); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -0,0 +1,89 @@ |
|||||||
|
#define _POSIX_SOURCE |
||||||
|
#define _GNU_SOURCE |
||||||
|
|
||||||
|
#include <sys/types.h> |
||||||
|
#include <sys/stat.h> |
||||||
|
#include <sys/ioctl.h> |
||||||
|
#include <fcntl.h> |
||||||
|
#include <termios.h> |
||||||
|
#include <stdio.h> |
||||||
|
#include <stdlib.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <string.h> |
||||||
|
#include <unistd.h> |
||||||
|
|
||||||
|
#include "serial.h" |
||||||
|
|
||||||
|
|
||||||
|
/** Open a serial port */ |
||||||
|
int serial_open(const char* port, const unsigned int baud) |
||||||
|
{ |
||||||
|
int fd = open(port, O_RDWR | O_NONBLOCK); |
||||||
|
|
||||||
|
struct termios tio; |
||||||
|
memset(&tio, 0, sizeof(tio)); |
||||||
|
|
||||||
|
speed_t bd = baud; |
||||||
|
switch(bd) { |
||||||
|
case 1200: bd = B1200; break; |
||||||
|
case 1800: bd = B1800; break; |
||||||
|
case 2400: bd = B2400; break; |
||||||
|
case 4800: bd = B4800; break; |
||||||
|
case 9600: bd = B9600; break; |
||||||
|
case 19200: bd = B19200; break; |
||||||
|
case 38400: bd = B38400; break; |
||||||
|
} |
||||||
|
|
||||||
|
tio.c_cflag = bd | CS8 | CLOCAL | CREAD | CRTSCTS; |
||||||
|
tio.c_iflag = IGNPAR; |
||||||
|
|
||||||
|
tcflush(fd, TCIFLUSH); |
||||||
|
tcsetattr(fd, TCSANOW, &tio); |
||||||
|
return fd; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Close a serial port */ |
||||||
|
int serial_close(int fd) |
||||||
|
{ |
||||||
|
return close(fd); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** Write a byte. Returns false on failure */ |
||||||
|
int serial_write(int fd, uint8_t b) |
||||||
|
{ |
||||||
|
return write(fd, &b, 1); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int serial_puts(int fd, const char* str) |
||||||
|
{ |
||||||
|
int len = strlen(str); |
||||||
|
return write(fd, str, len); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
uint8_t serial_read(int fd, int timeout) |
||||||
|
{ |
||||||
|
uint8_t b[1]; |
||||||
|
do { |
||||||
|
int n = read(fd, b, 1); |
||||||
|
if (n == -1) return -1; |
||||||
|
if (n == 0) { |
||||||
|
usleep(1 * 1000); // wait 1 ms
|
||||||
|
timeout--; |
||||||
|
continue; |
||||||
|
} |
||||||
|
return b[0]; |
||||||
|
} while(timeout > 0); |
||||||
|
return -1; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int serial_flush(int fd) |
||||||
|
{ |
||||||
|
sleep(2); |
||||||
|
return tcflush(fd, TCIOFLUSH); |
||||||
|
} |
@ -0,0 +1,27 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
#include <stdint.h> |
||||||
|
|
||||||
|
|
||||||
|
/** Open a serial port */ |
||||||
|
int serial_open(const char* port, const unsigned int baud); |
||||||
|
|
||||||
|
|
||||||
|
/** Close a serial port */ |
||||||
|
int serial_close(int fd); |
||||||
|
|
||||||
|
|
||||||
|
/** Write a byte. Returns false on failure */ |
||||||
|
int serial_write(int fd, uint8_t b); |
||||||
|
|
||||||
|
|
||||||
|
/** Send a string */ |
||||||
|
int serial_puts(int fd, const char* str); |
||||||
|
|
||||||
|
|
||||||
|
/** Read a byte */ |
||||||
|
uint8_t serial_read(int fd, int timeout); |
||||||
|
|
||||||
|
|
||||||
|
/** Flush */ |
||||||
|
int serial_flush(int fd); |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,260 @@ |
|||||||
|
#pragma once |
||||||
|
|
||||||
|
/** Abstract block device interface */ |
||||||
|
typedef struct |
||||||
|
{ |
||||||
|
// Sequential read
|
||||||
|
void (*load)(void* dest, const uint16_t len); |
||||||
|
// Sequential write
|
||||||
|
void (*store)(const void* src, const uint16_t len); |
||||||
|
// Sequential byte write
|
||||||
|
void (*write)(const uint8_t b); |
||||||
|
// Sequential byte read
|
||||||
|
uint8_t (*read)(void); |
||||||
|
// Absolute seek
|
||||||
|
void (*seek)(const uint32_t); |
||||||
|
// Relative seek
|
||||||
|
void (*rseek)(const int16_t); |
||||||
|
} BLOCKDEV; |
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------
|
||||||
|
|
||||||
|
/** file types (values don't matter) */ |
||||||
|
typedef enum |
||||||
|
{ |
||||||
|
FT_NONE = '-', |
||||||
|
FT_DELETED = 'x', |
||||||
|
FT_SUBDIR = 'D', |
||||||
|
FT_PARENT = 'P', |
||||||
|
FT_LABEL = 'L', |
||||||
|
FT_LFN = '~', |
||||||
|
FT_INVALID = 'i', // not recognized weird file
|
||||||
|
FT_SELF = '.', |
||||||
|
FT_FILE = 'F' |
||||||
|
} FAT16_FT; |
||||||
|
|
||||||
|
|
||||||
|
// File Attributes (bit flags)
|
||||||
|
#define FA_READONLY 0x01 // read only file
|
||||||
|
#define FA_HIDDEN 0x02 // hidden file
|
||||||
|
#define FA_SYSTEM 0x04 // system file
|
||||||
|
#define FA_LABEL 0x08 // volume label entry, found only in root directory.
|
||||||
|
#define FA_DIR 0x10 // subdirectory
|
||||||
|
#define FA_ARCHIVE 0x20 // archive flag
|
||||||
|
|
||||||
|
|
||||||
|
/** Boot Sector structure - INTERNAL! */ |
||||||
|
typedef struct __attribute__((packed)) |
||||||
|
{ |
||||||
|
|
||||||
|
// Fields loaded directly from disk:
|
||||||
|
|
||||||
|
// 13 bytes skipped
|
||||||
|
uint8_t sectors_per_cluster; |
||||||
|
uint16_t reserved_sectors; |
||||||
|
uint8_t num_fats; |
||||||
|
uint16_t root_entries; |
||||||
|
// 3 bytes skipped
|
||||||
|
uint16_t fat_size_sectors; |
||||||
|
// 8 bytes skipped
|
||||||
|
uint32_t total_sectors; // if "short size sectors" is used, it's copied here too
|
||||||
|
// 7 bytes skipped
|
||||||
|
char volume_label[11]; // space padded, no terminator
|
||||||
|
|
||||||
|
// Added fields:
|
||||||
|
|
||||||
|
uint32_t bytes_per_cluster; |
||||||
|
|
||||||
|
} |
||||||
|
Fat16BootSector; |
||||||
|
|
||||||
|
|
||||||
|
/** FAT filesystem handle - private fields! */ |
||||||
|
typedef struct __attribute__((packed)) |
||||||
|
{ |
||||||
|
// Backing block device
|
||||||
|
const BLOCKDEV* dev; |
||||||
|
|
||||||
|
// Root directory sector start
|
||||||
|
uint32_t rd_addr; |
||||||
|
|
||||||
|
// Start of first cluster (number "2")
|
||||||
|
uint32_t data_addr; |
||||||
|
|
||||||
|
// Start of fat table
|
||||||
|
uint32_t fat_addr; |
||||||
|
|
||||||
|
// Boot sector data struct
|
||||||
|
Fat16BootSector bs; |
||||||
|
} |
||||||
|
FAT16; |
||||||
|
|
||||||
|
|
||||||
|
/** File handle struct */ |
||||||
|
typedef struct __attribute__((packed)) |
||||||
|
{ |
||||||
|
// Fields loaded directly from disk:
|
||||||
|
|
||||||
|
uint8_t name[11]; // Starting 0x05 converted to 0xE5, other "magic chars" left intact
|
||||||
|
uint8_t attribs; // composed of FA_* constants
|
||||||
|
// 14 bytes skipped
|
||||||
|
uint16_t clu_start; |
||||||
|
uint32_t size; |
||||||
|
|
||||||
|
// Added fields:
|
||||||
|
|
||||||
|
FAT16_FT type; |
||||||
|
|
||||||
|
// --- Private fields ---
|
||||||
|
|
||||||
|
// Cursor
|
||||||
|
uint32_t cur_abs; // absolute position in device
|
||||||
|
uint32_t cur_rel; // relative position in file
|
||||||
|
uint16_t cur_clu; // cluster where the cursor is
|
||||||
|
uint16_t cur_ofs; // offset within the active cluster
|
||||||
|
|
||||||
|
// File position in the directory
|
||||||
|
uint16_t clu; // first cluster of directory
|
||||||
|
uint16_t num; // fiel entry number
|
||||||
|
|
||||||
|
// pointer to FAT
|
||||||
|
const FAT16* fat; |
||||||
|
} |
||||||
|
FAT16_FILE; |
||||||
|
|
||||||
|
|
||||||
|
/** Initialize a filesystem */ |
||||||
|
void fat16_init(const BLOCKDEV* dev, FAT16* fat); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open the first file of the root directory. |
||||||
|
* The file may be invalid (eg. a volume label, deleted etc), |
||||||
|
* or blank (type FT_NONE) if the filesystem is empty. |
||||||
|
* |
||||||
|
* Either way, the prev and next functions will work as expected. |
||||||
|
*/ |
||||||
|
void fat16_root(const FAT16* fat, FAT16_FILE* file); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the disk label. |
||||||
|
*/ |
||||||
|
char* fat16_disk_label(const FAT16* fat, char* label_out); |
||||||
|
|
||||||
|
|
||||||
|
// ----------- FILE I/O -------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move file cursor to a position relative to file start |
||||||
|
* Returns false on I/O error (bad file, out of range...) |
||||||
|
*/ |
||||||
|
bool fat16_fseek(FAT16_FILE* file, uint32_t addr); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read bytes from file into memory |
||||||
|
* Returns false on I/O error (bad file, out of range...) |
||||||
|
*/ |
||||||
|
bool fat16_fread(FAT16_FILE* file, void* target, uint32_t len); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write into file at a "seek" position. |
||||||
|
* "seek" cursor must be within (0..filesize) |
||||||
|
*/ |
||||||
|
bool fat16_fwrite(FAT16_FILE* file, void* source, uint32_t len); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new file in given folder |
||||||
|
* |
||||||
|
* file ... open directory; new file is opened into this handle. |
||||||
|
* name ... name of the new file, including extension |
||||||
|
*/ |
||||||
|
bool fat16_mkfile(FAT16_FILE* file, const char* name); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sub-directory of given name. |
||||||
|
* Directory is allocated and populated with entries "." and ".." |
||||||
|
*/ |
||||||
|
bool fat16_mkdir(FAT16_FILE* file, const char* name); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write new file size (also to the disk). |
||||||
|
* Allocates / frees needed clusters, does not erase them. |
||||||
|
*/ |
||||||
|
void fat16_resize(FAT16_FILE* file, uint32_t size); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a file entry and free clusters. |
||||||
|
* Does NOT work on folders. |
||||||
|
*/ |
||||||
|
bool fat16_rmfile(FAT16_FILE* file); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete an empty directory. |
||||||
|
* Calling with non-subfolder entry or non-empty directory will cause error. |
||||||
|
*/ |
||||||
|
bool fat16_rmdir(FAT16_FILE* file); |
||||||
|
|
||||||
|
// --------- NAVIGATION ------------
|
||||||
|
|
||||||
|
|
||||||
|
/** Go to previous file in the directory (false = no prev file) */ |
||||||
|
bool fat16_prev(FAT16_FILE* file); |
||||||
|
|
||||||
|
|
||||||
|
/** Go to next file in directory (false = no next file) */ |
||||||
|
bool fat16_next(FAT16_FILE* file); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a subdirectory denoted by the file. |
||||||
|
* Provided handle changes to first entry of the directory. |
||||||
|
*/ |
||||||
|
bool fat16_opendir(FAT16_FILE* file); |
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a parent directory. Fails in root. |
||||||
|
*/ |
||||||
|
bool fat16_parent(FAT16_FILE* file); |
||||||
|
|
||||||
|
|
||||||
|
/** Rewind to first file in directory */ |
||||||
|
void fat16_first(FAT16_FILE* file); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a file with given "display name" in this directory. |
||||||
|
* If file is found, "dir" will contain it's handle. |
||||||
|
* Either way, "dir" gets modified and you may need to rewind it afterwards. |
||||||
|
*/ |
||||||
|
bool fat16_find(FAT16_FILE* dir, const char* name); |
||||||
|
|
||||||
|
|
||||||
|
// -------- FILE INSPECTION -----------
|
||||||
|
|
||||||
|
/** Check if file is a valid entry, or long-name/label/deleted */ |
||||||
|
bool fat16_is_file_valid(const FAT16_FILE* file); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve a file name, trim spaces and add null terminator. |
||||||
|
* Returns the passed char*, or NULL on error. |
||||||
|
*/ |
||||||
|
char* fat16_dispname(const FAT16_FILE* file, char* disp_out); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert filename to zero-padded fixed length one |
||||||
|
* Returns the passed char*. |
||||||
|
*/ |
||||||
|
char* fat16_rawname(const char* disp_in, char* raw_out); |
||||||
|
|
@ -0,0 +1 @@ |
|||||||
|
/home/ondra/git/avr-lib/lib |
@ -0,0 +1,103 @@ |
|||||||
|
#include <avr/io.h> |
||||||
|
#include <util/delay.h> |
||||||
|
#include <avr/pgmspace.h> |
||||||
|
#include <avr/interrupt.h> |
||||||
|
#include <stdbool.h> |
||||||
|
#include <stdint.h> |
||||||
|
#include <stdlib.h> |
||||||
|
|
||||||
|
#include "fat16.h" |
||||||
|
|
||||||
|
BLOCKDEV test; |
||||||
|
|
||||||
|
void test_seek(const uint32_t pos) |
||||||
|
{ |
||||||
|
asm volatile (""); |
||||||
|
} |
||||||
|
|
||||||
|
void test_rseek(const int16_t pos) |
||||||
|
{ |
||||||
|
asm volatile (""); |
||||||
|
} |
||||||
|
|
||||||
|
void test_load(void* dest, const uint16_t len) |
||||||
|
{ |
||||||
|
asm volatile (""); |
||||||
|
} |
||||||
|
|
||||||
|
void test_store(const void* source, const uint16_t len) |
||||||
|
{ |
||||||
|
asm volatile (""); |
||||||
|
} |
||||||
|
|
||||||
|
void test_write(const uint8_t b) |
||||||
|
{ |
||||||
|
asm volatile (""); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t test_read() |
||||||
|
{ |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
void test_open() |
||||||
|
{ |
||||||
|
test.read = &test_read; |
||||||
|
test.write = &test_write; |
||||||
|
|
||||||
|
test.load = &test_load; |
||||||
|
test.store = &test_store; |
||||||
|
|
||||||
|
test.seek = &test_seek; |
||||||
|
test.rseek = &test_rseek; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void main() |
||||||
|
{ |
||||||
|
test_open(); |
||||||
|
|
||||||
|
// Initialize the FS
|
||||||
|
FAT16 fat; |
||||||
|
fat16_init(&test, &fat); |
||||||
|
|
||||||
|
FAT16_FILE file; |
||||||
|
fat16_root(&fat, &file); |
||||||
|
|
||||||
|
char str[10]; |
||||||
|
|
||||||
|
fat16_disk_label(&fat, str); |
||||||
|
|
||||||
|
|
||||||
|
// ----------- FILE I/O -------------
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move file cursor to a position relative to file start |
||||||
|
* Returns false on I/O error (bad file, out of range...) |
||||||
|
*/ |
||||||
|
fat16_fseek(&file, 1234); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read bytes from file into memory |
||||||
|
* Returns false on I/O error (bad file, out of range...) |
||||||
|
*/ |
||||||
|
fat16_fread(&file, str, 10); |
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write into file at a "seek" position. |
||||||
|
* "seek" cursor must be within (0..filesize) |
||||||
|
*/ |
||||||
|
fat16_fwrite(&file, str, 10); |
||||||
|
|
||||||
|
|
||||||
|
/** Go to next file in directory (false = no next file) */ |
||||||
|
fat16_next(&file); |
||||||
|
|
||||||
|
|
||||||
|
while(1) { |
||||||
|
//uart_puts_P(PSTR("TEST"));
|
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue