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