added devel folder..
This commit is contained in:
@@ -13,5 +13,3 @@
|
||||
*.so
|
||||
*.out
|
||||
*.hex
|
||||
|
||||
devel/
|
||||
|
||||
@@ -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
|
||||
Symlink
+1
@@ -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
|
||||
Symlink
+1
@@ -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
|
||||
Symlink
+1
@@ -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
|
||||
Symlink
+1
@@ -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)
|
||||
Symlink
+1
@@ -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)
|
||||
}
|
||||
|
||||
Symlink
+1
@@ -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
|
||||
Symlink
+1
@@ -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
|
||||
Executable
BIN
Binary file not shown.
Symlink
+1
@@ -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
|
||||
Executable
BIN
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
|
||||
Executable
BIN
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);
|
||||
Symlink
+1
@@ -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
|
||||
Symlink
+1
@@ -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
|
||||
Executable
BIN
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
|
||||
Executable
BIN
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);
|
||||
+1112
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);
|
||||
|
||||
Symlink
+1
@@ -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"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user