Compare commits
43 Commits
Author | SHA1 | Date |
---|---|---|
Christian Kroll | 4642f779f9 | |
Christian Kroll | c9ffc868dc | |
Christian Kroll | fa3c01d0c2 | |
Christian Kroll | 47d9b5e548 | |
Christian Kroll | 850e92f766 | |
Christian Kroll | edda250312 | |
Christian Kroll | 496f6a9ced | |
Christian Kroll | 45ba07b9d7 | |
Christian Kroll | 877bebd41a | |
Christian Kroll | 43f4fc9b2c | |
Christian Kroll | 656ec1c5c3 | |
Christian Kroll | 1e99121751 | |
Christian Kroll | ecec6bae36 | |
Christian Kroll | f48994b222 | |
Christian Kroll | 0d69c2d209 | |
Christian Kroll | 469ac61fa5 | |
Christian Kroll | 5ca1b807f4 | |
Christian Kroll | bf6b2d95dd | |
Christian Kroll | d5d58f8c0d | |
Christian Kroll | 7d0022a22d | |
Christian Kroll | 967ab9a05e | |
Christian Kroll | 126c1d0c44 | |
Christian Kroll | 09d7d80674 | |
Christian Kroll | 82c44aec65 | |
Christian Kroll | 937d9da592 | |
Christian Kroll | 09ce8f22b3 | |
Christian Kroll | b9471a6637 | |
Christian Kroll | cc060261d4 | |
Christian Kroll | 5ad9905dee | |
Christian Kroll | bec7a9edff | |
Christian Kroll | 7937f86137 | |
Christian Kroll | 6c1b652d46 | |
Christian Kroll | a53a78ea3b | |
Christian Kroll | fca9b8f07a | |
Christian Kroll | c6fde40211 | |
Stefan Kinzel | 6057b6e3e8 | |
Stefan Kinzel | 95bd1ba238 | |
Stefan Kinzel | b435b52217 | |
Christian Kroll | 306ad40288 | |
Stefan Kinzel | da9d0adc57 | |
Christian Kroll | 1dff4f3885 | |
Christian Kroll | 3a5052900d | |
Christian Kroll | 2919187ae1 |
16
config.in
16
config.in
|
@ -8,17 +8,21 @@ comment "General Setup"
|
|||
choice 'Target MCU' \
|
||||
"ATmega8 atmega8 \
|
||||
ATmega16 atmega16 \
|
||||
ATmega164 atmega164 \
|
||||
ATmega164P atmega164p \
|
||||
ATmega168 atmega168 \
|
||||
ATmega168P atmega168p \
|
||||
ATmega32 atmega32 \
|
||||
ATmega324 atmega324 \
|
||||
ATmega324P atmega324p \
|
||||
ATmega32U4 atmega32u4 \
|
||||
ATmega328 atmega328 \
|
||||
ATmega328p atmega328p \
|
||||
ATmega328P atmega328p \
|
||||
ATmega644 atmega644 \
|
||||
ATmega644p atmega644p \
|
||||
ATmega644P atmega644p \
|
||||
ATmega1280 atmega1280 \
|
||||
ATmega1284 atmega1284 \
|
||||
ATmega1284p atmega1284p \
|
||||
ATmega1284P atmega1284p \
|
||||
ATmega2560 atmega2560 \
|
||||
ATmega8515 atmega8515" \
|
||||
'ATmega32' MCU
|
||||
|
@ -62,9 +66,13 @@ source src/can/config.in
|
|||
###############################################################################
|
||||
|
||||
|
||||
### UART Menu #################################################################
|
||||
source src/uart/config.in
|
||||
###############################################################################
|
||||
|
||||
|
||||
### Borg Menu #################################################################
|
||||
dep_bool "Menu Support" MENU_SUPPORT $JOYSTICK_SUPPORT
|
||||
depends on JOYSTICK_SUPPORT
|
||||
###############################################################################
|
||||
|
||||
|
||||
|
|
21
defaults.mk
21
defaults.mk
|
@ -75,6 +75,20 @@ else
|
|||
endif
|
||||
endif
|
||||
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm
|
||||
else
|
||||
ifeq ($(OSTYPE),OpenBSD)
|
||||
CFLAGS_SIM = -g -I/usr/local/include -I/usr/X11R6/include -Wall -pedantic -std=c99 -O0
|
||||
CFLAGS_SIM += -D_XOPEN_SOURCE=600
|
||||
ifeq ($(MACHINE),amd64)
|
||||
LDFLAGS_SIM = -L/usr/local/lib -L/usr/X11R6/lib -T ld_scripts/elf_x86_64_obsd.xd
|
||||
else
|
||||
ifeq ($(MACHINE),i386)
|
||||
LDFLAGS_SIM = -L/usr/local/lib -L/usr/X11R6/lib -T ld_scripts/elf_i386_obsd.xd
|
||||
else
|
||||
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
|
||||
endif
|
||||
endif
|
||||
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm
|
||||
else
|
||||
ifeq ($(OSTYPE),Linux)
|
||||
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_XOPEN_SOURCE=600
|
||||
|
@ -99,6 +113,8 @@ Currently supported platforms:$(n) \
|
|||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
##############################################################################
|
||||
# the default target
|
||||
$(TARGET):
|
||||
|
@ -116,8 +132,8 @@ $(MAKETOPDIR)/config.mk:
|
|||
@echo "#" >>$@
|
||||
@echo "# Other flags you might want to tune: CPPFLAGS, LDFLAGS ..." >>$@
|
||||
@echo "Created default config.mk, tune your settings there!"
|
||||
-include $(MAKETOPDIR)/config.mk
|
||||
|
||||
-include $(MAKETOPDIR)/config.mk
|
||||
|
||||
##############################################################################
|
||||
# configure load address for bootloader, if enabled
|
||||
|
@ -125,9 +141,7 @@ $(MAKETOPDIR)/config.mk:
|
|||
ifneq ($(MAKECMDGOALS),clean)
|
||||
ifneq ($(MAKECMDGOALS),mrproper)
|
||||
ifneq ($(MAKECMDGOALS),menuconfig)
|
||||
|
||||
include $(MAKETOPDIR)/.config
|
||||
|
||||
CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU)
|
||||
|
||||
# flags for the linker, choose appropriate linker script
|
||||
|
@ -140,7 +154,6 @@ else
|
|||
LDFLAGS += -T ld_scripts/avr5.x -Wl,-Map,image.map -mmcu=$(MCU)
|
||||
endif
|
||||
endif
|
||||
|
||||
endif # MAKECMDGOALS!=menuconfig
|
||||
endif # MAKECMDGOALS!=mrproper
|
||||
endif # MAKECMDGOALS!=clean
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
/* Script for ld -pie: link position independent executable */
|
||||
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
|
||||
"elf32-i386")
|
||||
OUTPUT_ARCH(i386)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR("/usr/lib");
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = 0 + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
|
||||
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
|
||||
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init :
|
||||
{
|
||||
KEEP (*(.init))
|
||||
} =0x90909090
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
} =0x90909090
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(.fini))
|
||||
} =0x90909090
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
. = ALIGN(0x20000000) + 0x0 ;
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = ALIGN (0x1000) - ((0x1000 - .) & (0x1000 - 1)); . = DATA_SEGMENT_ALIGN (0x1000, 0x1000);
|
||||
/* Ensure the __preinit_array_start label is properly aligned. We
|
||||
could instead move the label definition inside the section, but
|
||||
the linker would then create the section even if it turns out to
|
||||
be empty, which isn't pretty. */
|
||||
. = ALIGN(32 / 8);
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
.preinit_array : { *(.preinit_array) }
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
PROVIDE (__init_array_start = .);
|
||||
.init_array : { *(.init_array) }
|
||||
PROVIDE (__init_array_end = .);
|
||||
PROVIDE (__fini_array_start = .);
|
||||
.fini_array : { *(.fini_array) }
|
||||
PROVIDE (__fini_array_end = .);
|
||||
PROVIDE (__openbsd_randomdata_start = .);
|
||||
.openbsd.randomdata :
|
||||
{
|
||||
*(.openbsd.randomdata .openbsd.randomdata.*)
|
||||
}
|
||||
PROVIDE (__openbsd_randomdata_end = .);
|
||||
.data :
|
||||
{
|
||||
__data_start = . ;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
PROVIDE (_eeprom_start__ = .);
|
||||
*(.eeprom)
|
||||
. = ALIGN(4) ;
|
||||
PROVIDE (_game_descriptors_start__ = .);
|
||||
*(.game_descriptors)
|
||||
PROVIDE (_game_descriptors_end__ = .);
|
||||
KEEP (*(.gnu.linkonce.d.*personality*))
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.eh_frame : { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : { *(.gcc_except_table) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
/* pad CTOR/DTOR, GOT (and PLT if DATA_PLT) to page aligned if PAD_GOT */
|
||||
. = ALIGN(0x1000) + (. & (0x1000 - 1)); .gotpad0 : { __got_start = .; }
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
/* If PAD_CDTOR, CTOR and DTOR relocated here to receive mprotect
|
||||
protection after relocation are finished same as GOT */
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin*.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin*.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.gotpad1 : { __got_end = .;} . = ALIGN(0x1000) + (. & (0x1000 - 1));
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections. */
|
||||
. = ALIGN(32 / 8);
|
||||
}
|
||||
. = ALIGN(32 / 8);
|
||||
_end = .;
|
||||
PROVIDE (end = .);
|
||||
. = DATA_SEGMENT_END (.);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) }
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
/* Default linker script, for normal executables */
|
||||
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
|
||||
"elf64-x86-64")
|
||||
OUTPUT_ARCH(i386:x86-64)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR("/usr/lib");
|
||||
/* Do we need any of these for elf?
|
||||
__DYNAMIC = 0; */
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
. = 0 + SIZEOF_HEADERS;
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) }
|
||||
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
.rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) }
|
||||
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init :
|
||||
{
|
||||
KEEP (*(.init))
|
||||
} =0x90909090
|
||||
.plt : { *(.plt) }
|
||||
.text :
|
||||
{
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
} =0x90909090
|
||||
.fini :
|
||||
{
|
||||
KEEP (*(.fini))
|
||||
} =0x90909090
|
||||
PROVIDE (__etext = .);
|
||||
PROVIDE (_etext = .);
|
||||
PROVIDE (etext = .);
|
||||
. = ALIGN(0x100000) + (. & (0x100000 - 1)) + 0 ;
|
||||
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) }
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
. = ALIGN (0x100000) - ((0x100000 - .) & (0x100000 - 1)); . = DATA_SEGMENT_ALIGN (0x100000, 0x1000);
|
||||
/* Ensure the __preinit_array_start label is properly aligned. We
|
||||
could instead move the label definition inside the section, but
|
||||
the linker would then create the section even if it turns out to
|
||||
be empty, which isn't pretty. */
|
||||
. = ALIGN(64 / 8);
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
.preinit_array : { *(.preinit_array) }
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
PROVIDE (__init_array_start = .);
|
||||
.init_array : { *(.init_array) }
|
||||
PROVIDE (__init_array_end = .);
|
||||
PROVIDE (__fini_array_start = .);
|
||||
.fini_array : { *(.fini_array) }
|
||||
PROVIDE (__fini_array_end = .);
|
||||
PROVIDE (__openbsd_randomdata_start = .);
|
||||
.openbsd.randomdata :
|
||||
{
|
||||
*(.openbsd.randomdata .openbsd.randomdata.*)
|
||||
}
|
||||
PROVIDE (__openbsd_randomdata_end = .);
|
||||
.data :
|
||||
{
|
||||
__data_start = . ;
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
. = ALIGN(16);
|
||||
PROVIDE (_eeprom_start__ = .);
|
||||
*(.eeprom)
|
||||
. = ALIGN(16);
|
||||
PROVIDE (_game_descriptors_start__ = .);
|
||||
*(.game_descriptors)
|
||||
PROVIDE (_game_descriptors_end__ = .);
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
|
||||
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
|
||||
.eh_frame : { KEEP (*(.eh_frame)) }
|
||||
.gcc_except_table : { *(.gcc_except_table) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
.jcr : { KEEP (*(.jcr)) }
|
||||
/* pad CTOR/DTOR, GOT (and PLT if DATA_PLT) to page aligned if PAD_GOT */
|
||||
. = ALIGN(0x100000) + (. & (0x100000 - 1)); .gotpad0 : { __got_start = .; }
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
/* If PAD_CDTOR, CTOR and DTOR relocated here to receive mprotect
|
||||
protection after relocation are finished same as GOT */
|
||||
.ctors :
|
||||
{
|
||||
/* gcc uses crtbegin.o to find the start of
|
||||
the constructors, so we make sure it is
|
||||
first. Because this is a wildcard, it
|
||||
doesn't matter if the user does not
|
||||
actually link against crtbegin.o; the
|
||||
linker won't look for a file to match a
|
||||
wildcard. The wildcard also means that it
|
||||
doesn't matter which directory crtbegin.o
|
||||
is in. */
|
||||
KEEP (*crtbegin*.o(.ctors))
|
||||
/* We don't want to include the .ctor section from
|
||||
from the crtend.o file until after the sorted ctors.
|
||||
The .ctor section from the crtend file contains the
|
||||
end of ctors marker and it must be last */
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
KEEP (*crtbegin*.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
}
|
||||
.gotpad1 : { __got_end = .;} . = ALIGN(0x100000) + (. & (0x100000 - 1));
|
||||
_edata = .;
|
||||
PROVIDE (edata = .);
|
||||
__bss_start = .;
|
||||
.bss :
|
||||
{
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
/* Align here to ensure that the .bss section occupies space up to
|
||||
_end. Align after .bss to ensure correct alignment even if the
|
||||
.bss section disappears because there are no input sections. */
|
||||
. = ALIGN(64 / 8);
|
||||
}
|
||||
. = ALIGN(64 / 8);
|
||||
_end = .;
|
||||
PROVIDE (end = .);
|
||||
. = DATA_SEGMENT_END (.);
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) }
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
#
|
||||
# Automatically generated by make menuconfig: don't edit
|
||||
#
|
||||
|
||||
#
|
||||
# General Setup
|
||||
#
|
||||
MCU=atmega644
|
||||
FREQ=16000000
|
||||
|
||||
#
|
||||
# Borg Hardware
|
||||
#
|
||||
NUM_ROWS=16
|
||||
NUM_COLS=16
|
||||
NUMPLANE=3
|
||||
BORG_HW=HW_BORG_16
|
||||
|
||||
#
|
||||
# Borg16 port setup
|
||||
#
|
||||
HIGH_CONTRAST=y
|
||||
UART_SUPPORT=y
|
||||
UART_BAUDRATE_SETTING=19200
|
||||
COLPORT1=PORTC
|
||||
COLPORT2=PORTA
|
||||
ROWPORT=PORTD
|
||||
PIN_MCLR=4
|
||||
PIN_CLK=6
|
||||
PIN_DATA=7
|
||||
# REVERSE_COLS is not set
|
||||
# INVERT_ROWS is not set
|
||||
# INTERLACED_ROWS is not set
|
||||
# INTERLACED_COLS is not set
|
||||
|
||||
#
|
||||
# Features
|
||||
#
|
||||
RANDOM_SUPPORT=y
|
||||
# LAP_TIME_EXTENSION is not set
|
||||
SCROLLTEXT_SUPPORT=y
|
||||
SCROLLTEXT_FONT=FONT_ARIAL8
|
||||
SCROLLTEXT_BUFFER_SIZE=128
|
||||
SCROLL_X_SPEED=20
|
||||
SCROLL_Y_SPEED=20
|
||||
SCROLLTEXT_TEXT="d/#C#</#T#u/#D#>/#O#p2# #</#www.chaostreff-dortmund.de"
|
||||
# RFM12_SUPPORT is not set
|
||||
|
||||
#
|
||||
# Joystick Support
|
||||
#
|
||||
JOYSTICK_SUPPORT=y
|
||||
JOYSTICK_CHOICE=JOY_PARALLEL
|
||||
|
||||
#
|
||||
# Joystick Settings
|
||||
#
|
||||
PARALLEL_JOYSTICK_SUPPORT=y
|
||||
JOYSTICK_PIN_UP=PINB
|
||||
JOYSTICK_BIT_UP=0
|
||||
JOYSTICK_PIN_DOWN=PINB
|
||||
JOYSTICK_BIT_DOWN=1
|
||||
JOYSTICK_PIN_LEFT=PINB
|
||||
JOYSTICK_BIT_LEFT=2
|
||||
JOYSTICK_PIN_RIGHT=PINB
|
||||
JOYSTICK_BIT_RIGHT=3
|
||||
JOYSTICK_PIN_FIRE=PIND
|
||||
JOYSTICK_BIT_FIRE=3
|
||||
CAN_SUPPORT=y
|
||||
# SPI_HARDWARE is not set
|
||||
SPI_PORTIDX=1
|
||||
SPI_PIN_MOSI=5
|
||||
SPI_PIN_MISO=6
|
||||
SPI_PIN_SCK=7
|
||||
SPI_PIN_SS=4
|
||||
# CAN_INTERRUPT is not set
|
||||
SPI_REG_PIN_MCP_INT=PIND
|
||||
SPI_PIN_MCP_INT=2
|
||||
MENU_SUPPORT=y
|
||||
|
||||
#
|
||||
# Games
|
||||
#
|
||||
GAME_TETRIS_CORE=y
|
||||
GAME_TETRIS=y
|
||||
GAME_BASTET=y
|
||||
GAME_TETRIS_FP=y
|
||||
GAME_SPACE_INVADERS=y
|
||||
GAME_SNAKE=y
|
||||
# SNAKE_POV_CONTROL is not set
|
||||
SNAKE_GAME_DELAY=200
|
||||
GAME_BREAKOUT=y
|
||||
GAME_KART=y
|
||||
|
||||
#
|
||||
# Animations
|
||||
#
|
||||
ANIMATION_SCROLLTEXT=y
|
||||
ANIMATION_SPIRAL=y
|
||||
SPIRAL_DELAY=5
|
||||
ANIMATION_JOERN1=y
|
||||
ANIMATION_SNAKE=y
|
||||
SNAKE_ANIM_DELAY=100
|
||||
SNAKE_TERMINATION_DELAY=60
|
||||
SNAKE_MAX_LENGTH=64
|
||||
SNAKE_MAX_APPLES=10
|
||||
ANIMATION_CHECKERBOARD=y
|
||||
ANIMATION_FIRE=y
|
||||
FIRE_S=30
|
||||
FIRE_N=5
|
||||
FIRE_DIV=44
|
||||
FIRE_DELAY=50
|
||||
FIRE_CYCLES=800
|
||||
ANIMATION_MATRIX=y
|
||||
MATRIX_STREAMER_NUM=30
|
||||
MATRIX_CYCLES=500
|
||||
MATRIX_DELAY=60
|
||||
ANIMATION_RANDOM_BRIGHT=y
|
||||
ANIMATION_STONEFLY=y
|
||||
ANIMATION_FLYINGDOTS=y
|
||||
ANIMATION_GAMEOFLIFE=y
|
||||
GOL_DELAY=100
|
||||
GOL_CYCLES=360
|
||||
ANIMATION_BREAKOUT=y
|
||||
# ANIMATION_MHERWEG is not set
|
||||
ANIMATION_MOIRE=y
|
||||
ANIMATION_LTN_ANT=y
|
||||
# ANIMATION_TIME is not set
|
||||
TIME_MASTER_ADDR=0x00
|
||||
TIME_UPDATE_TIMEOUT=23
|
||||
ANIMATION_BMSCROLLER=y
|
||||
# ANIMATION_LABORLOGO is not set
|
||||
ANIMATION_AMPHIBIAN=y
|
||||
# ANIMATION_LOGO_OOS is not set
|
||||
ANIMATION_FAIRYDUST=y
|
||||
|
||||
#
|
||||
# Fixed-point math patterns
|
||||
#
|
||||
ANIMATION_PLASMA=y
|
||||
FP_PLASMA_DELAY=1
|
||||
ANIMATION_PSYCHEDELIC=y
|
||||
FP_PSYCHO_DELAY=15
|
||||
ANIMATION_BLACKHOLE=y
|
||||
ANIMATION_DNA=y
|
||||
ANIMATION_SQUARES=y
|
||||
ANIMATION_TESTS=y
|
||||
ANIMATION_OFF=y
|
||||
|
||||
#
|
||||
# small Animations
|
||||
#
|
||||
# SMALLANIMATION_ROWWALK is not set
|
||||
SMALLANIMATION_ROWWALK_SPEED=50
|
||||
SMALLANIMATION_ROWWALK_COUNT=10
|
||||
# SMALLANIMATION_COLWALK is not set
|
||||
SMALLANIMATION_COLWALK_SPEED=50
|
||||
SMALLANIMATION_COLWALK_COUNT=10
|
||||
# SMALLANIMATION_ROWBOUNCE is not set
|
||||
SMALLANIMATION_ROWBOUNCE_SPEED=50
|
||||
SMALLANIMATION_ROWBOUNCE_COUNT=10
|
||||
# SMALLANIMATION_COLBOUNCE is not set
|
||||
SMALLANIMATION_COLBOUNCE_SPEED=50
|
||||
SMALLANIMATION_COLBOUNCE_COUNT=10
|
|
@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
|
|||
# lolshield setup
|
||||
#
|
||||
USER_TIMER0_FOR_WAIT=1
|
||||
BRIGHTNESS=127
|
||||
LOLSHIELD=y
|
||||
BRIGHTNESS=120
|
||||
FRAMERATE=80
|
||||
# UART_SUPPORT is not set
|
||||
UART_BAUDRATE_SETTING=19200
|
||||
|
||||
#
|
||||
# Features
|
||||
|
@ -54,7 +57,10 @@ GAME_TETRIS=y
|
|||
# GAME_TETRIS_FP is not set
|
||||
# GAME_SPACE_INVADERS is not set
|
||||
GAME_SNAKE=y
|
||||
# SNAKE_POV_CONTROL is not set
|
||||
SNAKE_GAME_DELAY=200
|
||||
GAME_BREAKOUT=y
|
||||
# GAME_KART is not set
|
||||
|
||||
#
|
||||
# Animations
|
||||
|
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
|
|||
SPIRAL_DELAY=5
|
||||
ANIMATION_JOERN1=y
|
||||
ANIMATION_SNAKE=y
|
||||
SNAKE_GAME_DELAY=200
|
||||
SNAKE_ANIM_DELAY=100
|
||||
SNAKE_TERMINATION_DELAY=60
|
||||
SNAKE_MAX_LENGTH=64
|
||||
|
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
|
|||
ANIMATION_PSYCHEDELIC=y
|
||||
FP_PSYCHO_DELAY=25
|
||||
# ANIMATION_BLACKHOLE is not set
|
||||
# ANIMATION_DNA is not set
|
||||
ANIMATION_SQUARES=y
|
||||
# ANIMATION_TESTS is not set
|
||||
# ANIMATION_OFF is not set
|
||||
|
|
|
@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
|
|||
# lolshield setup
|
||||
#
|
||||
USER_TIMER0_FOR_WAIT=1
|
||||
BRIGHTNESS=127
|
||||
LOLSHIELD=y
|
||||
BRIGHTNESS=120
|
||||
FRAMERATE=80
|
||||
# UART_SUPPORT is not set
|
||||
UART_BAUDRATE_SETTING=19200
|
||||
|
||||
#
|
||||
# Features
|
||||
|
@ -54,7 +57,10 @@ GAME_BASTET=y
|
|||
# GAME_TETRIS_FP is not set
|
||||
GAME_SPACE_INVADERS=y
|
||||
GAME_SNAKE=y
|
||||
# SNAKE_POV_CONTROL is not set
|
||||
SNAKE_GAME_DELAY=200
|
||||
GAME_BREAKOUT=y
|
||||
# GAME_KART is not set
|
||||
|
||||
#
|
||||
# Animations
|
||||
|
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
|
|||
SPIRAL_DELAY=5
|
||||
ANIMATION_JOERN1=y
|
||||
ANIMATION_SNAKE=y
|
||||
SNAKE_GAME_DELAY=200
|
||||
SNAKE_ANIM_DELAY=100
|
||||
SNAKE_TERMINATION_DELAY=60
|
||||
SNAKE_MAX_LENGTH=64
|
||||
|
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
|
|||
ANIMATION_PSYCHEDELIC=y
|
||||
FP_PSYCHO_DELAY=25
|
||||
ANIMATION_BLACKHOLE=y
|
||||
# ANIMATION_DNA is not set
|
||||
ANIMATION_SQUARES=y
|
||||
ANIMATION_TESTS=y
|
||||
ANIMATION_OFF=y
|
||||
|
|
|
@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
|
|||
# lolshield setup
|
||||
#
|
||||
USER_TIMER0_FOR_WAIT=1
|
||||
BRIGHTNESS=127
|
||||
LOLSHIELD=y
|
||||
BRIGHTNESS=120
|
||||
FRAMERATE=80
|
||||
# UART_SUPPORT is not set
|
||||
UART_BAUDRATE_SETTING=19200
|
||||
|
||||
#
|
||||
# Features
|
||||
|
@ -54,7 +57,10 @@ GAME_BASTET=y
|
|||
# GAME_TETRIS_FP is not set
|
||||
GAME_SPACE_INVADERS=y
|
||||
GAME_SNAKE=y
|
||||
# SNAKE_POV_CONTROL is not set
|
||||
SNAKE_GAME_DELAY=200
|
||||
GAME_BREAKOUT=y
|
||||
# GAME_KART is not set
|
||||
|
||||
#
|
||||
# Animations
|
||||
|
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
|
|||
SPIRAL_DELAY=5
|
||||
ANIMATION_JOERN1=y
|
||||
ANIMATION_SNAKE=y
|
||||
SNAKE_GAME_DELAY=200
|
||||
SNAKE_ANIM_DELAY=100
|
||||
SNAKE_TERMINATION_DELAY=60
|
||||
SNAKE_MAX_LENGTH=64
|
||||
|
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
|
|||
ANIMATION_PSYCHEDELIC=y
|
||||
FP_PSYCHO_DELAY=25
|
||||
ANIMATION_BLACKHOLE=y
|
||||
# ANIMATION_DNA is not set
|
||||
ANIMATION_SQUARES=y
|
||||
ANIMATION_TESTS=y
|
||||
ANIMATION_OFF=y
|
||||
|
|
|
@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
|
|||
# lolshield setup
|
||||
#
|
||||
USER_TIMER0_FOR_WAIT=1
|
||||
BRIGHTNESS=127
|
||||
LOLSHIELD=y
|
||||
BRIGHTNESS=120
|
||||
FRAMERATE=80
|
||||
# UART_SUPPORT is not set
|
||||
UART_BAUDRATE_SETTING=19200
|
||||
|
||||
#
|
||||
# Features
|
||||
|
@ -54,7 +57,10 @@ GAME_TETRIS=y
|
|||
# GAME_TETRIS_FP is not set
|
||||
# GAME_SPACE_INVADERS is not set
|
||||
GAME_SNAKE=y
|
||||
# SNAKE_POV_CONTROL is not set
|
||||
SNAKE_GAME_DELAY=200
|
||||
GAME_BREAKOUT=y
|
||||
# GAME_KART is not set
|
||||
|
||||
#
|
||||
# Animations
|
||||
|
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
|
|||
SPIRAL_DELAY=5
|
||||
ANIMATION_JOERN1=y
|
||||
ANIMATION_SNAKE=y
|
||||
SNAKE_GAME_DELAY=200
|
||||
SNAKE_ANIM_DELAY=100
|
||||
SNAKE_TERMINATION_DELAY=60
|
||||
SNAKE_MAX_LENGTH=64
|
||||
|
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
|
|||
ANIMATION_PSYCHEDELIC=y
|
||||
FP_PSYCHO_DELAY=25
|
||||
ANIMATION_BLACKHOLE=y
|
||||
# ANIMATION_DNA is not set
|
||||
ANIMATION_SQUARES=y
|
||||
# ANIMATION_TESTS is not set
|
||||
# ANIMATION_OFF is not set
|
||||
|
|
|
@ -58,6 +58,11 @@ ifeq ($(ANIMATION_TIME),y)
|
|||
SRC += borg_time.c
|
||||
endif
|
||||
|
||||
ifeq ($(ANIMATION_DNA),y)
|
||||
SRC += dna.c
|
||||
endif
|
||||
|
||||
|
||||
include $(MAKETOPDIR)/rules.mk
|
||||
|
||||
include $(MAKETOPDIR)/depend.mk
|
||||
|
|
|
@ -9,7 +9,6 @@ comment "Animations"
|
|||
bool "Joern1" ANIMATION_JOERN1
|
||||
|
||||
dep_bool_menu "Snake" ANIMATION_SNAKE $RANDOM_SUPPORT
|
||||
int "Snake Game Round Delay" SNAKE_GAME_DELAY 200
|
||||
int "Snake Anim Round Delay" SNAKE_ANIM_DELAY 100
|
||||
int "Snake Termination Delay" SNAKE_TERMINATION_DELAY 60
|
||||
uint "Snake Max Length" SNAKE_MAX_LENGTH 64
|
||||
|
@ -64,6 +63,8 @@ comment "Animations"
|
|||
|
||||
bool "Black Hole" ANIMATION_BLACKHOLE
|
||||
|
||||
bool "DNA" ANIMATION_DNA $RANDOM_SUPPORT
|
||||
|
||||
dep_bool "Squares" ANIMATION_SQUARES $RANDOM_SUPPORT
|
||||
|
||||
comment "Special Animations"
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
#include "../config.h"
|
||||
#include <stdint.h>
|
||||
#include "../random/prng.h"
|
||||
#include "../pixel.h"
|
||||
#include "../util.h"
|
||||
|
||||
|
||||
#define HEIGHT 12
|
||||
#define LINE_DISTANCE 4
|
||||
#define SIN_LENGTH 18
|
||||
#define SIN_MAX 6
|
||||
|
||||
// uint8_t sin[SIN_LENGTH] = {0, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 3, 2, 2, 1, 0};
|
||||
|
||||
uint8_t sintab[SIN_LENGTH] = {
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
5,
|
||||
6,
|
||||
6,
|
||||
6,
|
||||
6,
|
||||
6,
|
||||
5,
|
||||
5,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shifts the Pixmap one px right
|
||||
*/
|
||||
static void move(){
|
||||
unsigned char plane, row, byte;
|
||||
|
||||
for(plane=0; plane<NUMPLANE; plane++){
|
||||
for(row=NUM_ROWS; row--;){
|
||||
for(byte=0; byte < LINEBYTES; byte++){
|
||||
pixmap[plane][row][byte] = pixmap[plane][row][byte] >> 1;
|
||||
if(byte < LINEBYTES-1){
|
||||
pixmap[plane][row][byte] =
|
||||
pixmap[plane][row][byte] |
|
||||
(pixmap[plane][row][byte+1] & 0x01) << 7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void dna(){
|
||||
uint8_t mid = NUM_COLS / 2;
|
||||
uint8_t draw_line = 0;
|
||||
|
||||
uint8_t top = 0;
|
||||
uint8_t bottom = 0;
|
||||
|
||||
uint8_t top_color = 3;
|
||||
uint8_t bottom_color = 2;
|
||||
|
||||
uint32_t c = 600;
|
||||
|
||||
uint8_t sinpos = 0;
|
||||
|
||||
int8_t direction = 1;
|
||||
|
||||
clear_screen(0);
|
||||
|
||||
while(c--){
|
||||
top = mid - sintab[sinpos];
|
||||
bottom = mid + sintab[sinpos];
|
||||
|
||||
setpixel((pixel){NUM_COLS-1,top}, top_color);
|
||||
setpixel((pixel){NUM_COLS-1,bottom}, bottom_color);
|
||||
|
||||
if(draw_line == 0){
|
||||
for(uint8_t linex = top+1; linex < bottom; linex++){
|
||||
setpixel((pixel){NUM_COLS-1, linex}, 1);
|
||||
}
|
||||
setpixel((pixel){NUM_COLS-1, mid}, 1);
|
||||
}
|
||||
|
||||
if(sinpos == 0){
|
||||
if(mid-SIN_MAX <= 0){
|
||||
direction = 1;
|
||||
}
|
||||
if(mid+SIN_MAX >= NUM_ROWS-1){
|
||||
direction = -1;
|
||||
}
|
||||
mid = mid + (random8() > 200) * direction;
|
||||
}
|
||||
|
||||
draw_line = (draw_line+1) % LINE_DISTANCE;
|
||||
sinpos = (sinpos + 1) % SIN_LENGTH;
|
||||
|
||||
if(sinpos == 0){
|
||||
uint8_t tmp_color = top_color;
|
||||
top_color = bottom_color;
|
||||
bottom_color = tmp_color;
|
||||
}
|
||||
|
||||
wait(50);
|
||||
move();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* dna.h
|
||||
*
|
||||
* Created on: 15.07.2014
|
||||
* Author: stefan
|
||||
*/
|
||||
|
||||
#ifndef DNA_H_
|
||||
#define DNA_H_
|
||||
|
||||
void dna();
|
||||
|
||||
#endif /* DNA_H_ */
|
|
@ -20,18 +20,20 @@
|
|||
|
||||
#ifdef DOXYGEN
|
||||
/**
|
||||
* Low precision means that we use Q10.5 values and 16 bit types for almost
|
||||
* every calculation (with multiplication and division as notable exceptions
|
||||
* as they and their interim results utilize 32 bit).
|
||||
* Low precision means that we use Q9.6 values and 16 bit types for almost
|
||||
* every calculation (with multiplication being a notable exception as its
|
||||
* interim results utilize 32 bit types).
|
||||
*
|
||||
* Use this precision mode with care as image quality will suffer
|
||||
* noticeably. It produces leaner and faster code, though. This mode should
|
||||
* not be used with resolutions higher than 16x16 as overflows are likely to
|
||||
* occur in interim calculations.
|
||||
* Use this precision mode with care as image quality will suffer noticeably
|
||||
* at higher resolutions. This mode should not be used with resolutions
|
||||
* higher than 16x16 as overflows are likely to occur in interim
|
||||
* calculations. It produces leaner and faster code, though.
|
||||
*
|
||||
* Normal precision (i.e. #undef LOW_PRECISION) conforms to Q7.8 with the
|
||||
* ability to store every interim result as Q23.8. Most operations like
|
||||
* square root, sine, cosine, multiplication etc. utilize 32 bit types.
|
||||
* Normal precision (i.e. #undef LOW_PRECISION) conforms to Q23.8 for actual
|
||||
* values and interim results. Operations like square root, sine, cosine,
|
||||
* multiplication etc. utilize 32 bit types. It's extremly slow on AVR, but
|
||||
* it's your only chance to run those animations on devices with resolutions
|
||||
* higher than 16x16.
|
||||
*/
|
||||
#define FP_LOW_PRECISION
|
||||
#endif /* DOXYGEN */
|
||||
|
@ -66,18 +68,18 @@
|
|||
// lookup table as well!
|
||||
|
||||
/** Multiply a number by this factor to convert it to a fixed-point value.*/
|
||||
#define FIX 32
|
||||
#define FIX 64
|
||||
/** Number of fractional bits of a value (i.e. ceil(log_2(FIX))). */
|
||||
#define FIX_FRACBITS 5
|
||||
#define FIX_FRACBITS 6
|
||||
/**
|
||||
* The number of temporal quantization steps of the sine lookup table. It
|
||||
* must be a divisor of (FIX * 2 * pi) and this divisor must be divisable by
|
||||
* 4 itself. Approximate this value as close as possible to keep rounding
|
||||
* errors at a minimum.
|
||||
*/
|
||||
#define FIX_SIN_COUNT 200
|
||||
#define FIX_SIN_COUNT 200u
|
||||
/** The rounded down quotient of (FIX * 2 * pi) and FIX_SIN_COUNT */
|
||||
#define FIX_SIN_DIVIDER 1
|
||||
#define FIX_SIN_DIVIDER 2u
|
||||
|
||||
/** Type of the lookup table elements. */
|
||||
typedef uint8_t lut_t;
|
||||
|
@ -85,26 +87,26 @@
|
|||
/**
|
||||
* Lookup table of fractional parts which model the first quarter of a
|
||||
* sine period. The rest of that period is calculated by mirroring those
|
||||
* values. These values are intended for Q5 types.
|
||||
* values. These values are intended for Q6 types.
|
||||
*/
|
||||
static lut_t const fix_sine_lut[FIX_SIN_COUNT / 4] =
|
||||
{ 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 10, 11, 12, 13, 14, 14,
|
||||
15, 16, 17, 18, 19, 20, 20, 21,
|
||||
22, 23, 23, 24, 25, 25, 26, 26,
|
||||
27, 27, 28, 28, 29, 29, 30, 30,
|
||||
30, 31, 31, 31, 31, 32, 32, 32,
|
||||
32, 32};
|
||||
{ 0, 2, 4, 6, 8, 10, 12, 14,
|
||||
16, 18, 20, 22, 24, 25, 27, 29,
|
||||
31, 33, 34, 36, 38, 39, 41, 42,
|
||||
44, 45, 47, 48, 49, 51, 52, 53,
|
||||
54, 55, 56, 57, 58, 59, 60, 60,
|
||||
61, 61, 62, 62, 63, 63, 63, 64,
|
||||
64, 64};
|
||||
|
||||
#else
|
||||
/** This is the type we expect ordinary integers to be. */
|
||||
typedef int16_t ordinary_int_t;
|
||||
/** This is the type which we use for fixed-point values. */
|
||||
typedef int16_t fixp_t;
|
||||
typedef int32_t fixp_t;
|
||||
/** This type covers arguments of fixSin() and fixCos(). */
|
||||
typedef int32_t fixp_trig_t;
|
||||
/** This type covers interim results of fixed-point operations. */
|
||||
typedef int32_t fixp_interim_t;
|
||||
typedef uint32_t fixp_interim_t;
|
||||
/** This type covers interim results of the fixSqrt() function. */
|
||||
typedef uint32_t ufixp_interim_t;
|
||||
/** Number of bits the fixSqrt() function can handle. */
|
||||
|
@ -123,12 +125,12 @@
|
|||
* 4 itself. Approximate this value as close as possible to keep rounding
|
||||
* errors at a minimum.
|
||||
*/
|
||||
#define FIX_SIN_COUNT 200
|
||||
#define FIX_SIN_COUNT 200u
|
||||
/** The rounded down quotient of (FIX * 2 * pi) and FIX_SIN_COUNT */
|
||||
#define FIX_SIN_DIVIDER 8
|
||||
#define FIX_SIN_DIVIDER 8u
|
||||
|
||||
/** Type of the lookup table elements. */
|
||||
typedef uint8_t lut_t;
|
||||
typedef int16_t lut_t;
|
||||
|
||||
/**
|
||||
* Lookup table of fractional parts which model the first quarter of a
|
||||
|
@ -142,7 +144,7 @@
|
|||
175, 181, 186, 192, 197, 202, 207, 211,
|
||||
216, 220, 224, 228, 231, 235, 238, 240,
|
||||
243, 245, 247, 249, 251, 252, 253, 254,
|
||||
255, 255};
|
||||
255, 256};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -252,14 +254,14 @@ static fixp_t fixSin(fixp_trig_t fAngle)
|
|||
|
||||
/**
|
||||
* Fixed-point variant of the cosine function which takes a fixed-point angle
|
||||
* (radian). It adds FIX_PI_2 to the given angle and consults the fixSin()
|
||||
* function for the final result.
|
||||
* (radian). It substracts FIX_PI_2 from the given angle and consults the
|
||||
* fixSin() function for the final result.
|
||||
* @param fAngle A fixed-point value in radian.
|
||||
* @return Result of the cosine function normalized to a range from -FIX to FIX.
|
||||
*/
|
||||
static fixp_t fixCos(fixp_trig_t const fAngle)
|
||||
static inline fixp_t fixCos(fixp_trig_t const fAngle)
|
||||
{
|
||||
return fixSin(fAngle + FIX_PI_2);
|
||||
return fixSin(fAngle - FIX_PI_2);
|
||||
}
|
||||
|
||||
|
||||
|
@ -275,7 +277,7 @@ static fixp_t fixSqrt(ufixp_interim_t const a)
|
|||
nRoot = 0; // clear root
|
||||
nRemainingHigh = 0; // clear high part of partial remainder
|
||||
nRemainingLow = a; // get argument into low part of partial remainder
|
||||
nCount = (SQRT_BITS / 2 - 1) + (FIX_FRACBITS >> 1); // load loop counter
|
||||
nCount = ((SQRT_BITS - 1) + FIX_FRACBITS) / 2; // load loop counter
|
||||
do
|
||||
{
|
||||
nRemainingHigh =
|
||||
|
@ -451,16 +453,16 @@ static unsigned char fixAnimPlasma(unsigned char const x,
|
|||
assert(x < (LINEBYTES * 8));
|
||||
assert(y < NUM_ROWS);
|
||||
|
||||
// scaling factor
|
||||
static fixp_t const fPlasmaX = (2 * PI * FIX) / NUM_COLS;
|
||||
|
||||
// reentrant data
|
||||
fixp_plasma_t *const p = (fixp_plasma_t *)r;
|
||||
|
||||
// scaling factor
|
||||
static fixp_t const fPlasmaX = FIX / 3.7;
|
||||
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
p->fFunc2CosArg = NUM_ROWS * fixCos(t) + fixScaleUp(NUM_ROWS);
|
||||
p->fFunc2SinArg = NUM_COLS * fixSin(t) + fixScaleUp(NUM_COLS);
|
||||
p->fFunc2CosArg = NUM_COLS * (fixCos(t) + FIX);
|
||||
p->fFunc2SinArg = NUM_ROWS * (fixSin(t) + FIX);
|
||||
for (unsigned char i = LINEBYTES * 8u; i--;)
|
||||
{
|
||||
p->fFunc1[i] = fixSin(fixMul(fixScaleUp(i), fPlasmaX) + t);
|
||||
|
@ -470,8 +472,8 @@ static unsigned char fixAnimPlasma(unsigned char const x,
|
|||
fixp_t const fFunc2 = fixSin(fixMul(fixDist(fixScaleUp(x), fixScaleUp(y),
|
||||
p->fFunc2SinArg, p->fFunc2CosArg), fPlasmaX));
|
||||
|
||||
unsigned char const nRes = (unsigned char)(fixMul(p->fFunc1[x] + fFunc2 +
|
||||
fixScaleUp(2), ((NUMPLANE + 1) / 4.0 - 0.05) * FIX)) / FIX;
|
||||
unsigned char const nRes = (fixMul(p->fFunc1[x] + fFunc2 +
|
||||
2 * FIX, ((NUMPLANE + 1) / 4.0 - 0.05) * FIX)) / FIX;
|
||||
assert (nRes <= NUMPLANE);
|
||||
|
||||
return nRes;
|
||||
|
@ -484,12 +486,12 @@ void plasma(void)
|
|||
{
|
||||
fixp_plasma_t r;
|
||||
#ifndef __AVR__
|
||||
fixDrawPattern(0, fixScaleUp(75), 0.1 * FIX, 15, fixAnimPlasma, &r);
|
||||
fixDrawPattern(0, fixScaleUp(75), 0.05 * FIX, 15, fixAnimPlasma, &r);
|
||||
#else
|
||||
#ifndef FP_PLASMA_DELAY
|
||||
#define FP_PLASMA_DELAY 1
|
||||
#endif
|
||||
fixDrawPattern(0, fixScaleUp(60), 0.1 * FIX,
|
||||
fixDrawPattern(0, fixScaleUp(60), 0.05 * FIX,
|
||||
FP_PLASMA_DELAY, fixAnimPlasma, &r);
|
||||
#endif /* __AVR__ */
|
||||
}
|
||||
|
@ -505,9 +507,9 @@ void plasma(void)
|
|||
*/
|
||||
typedef struct fixp_psychedelic_s
|
||||
{
|
||||
fixp_t fCos; /**< One of the column factors of the curl. */
|
||||
fixp_t fSin; /**< One of the row factors of the curl. */
|
||||
fixp_interim_t ft10; /**< A value involved in rotating the curl's center. */
|
||||
fixp_t fCos; /**< X-coordinate of the curl's center. */
|
||||
fixp_t fSin; /**< Y-coordinate of the curl's center. */
|
||||
fixp_t fPhaseShift; /**< Phase-shift for the flow effect. */
|
||||
} fixp_psychedelic_t;
|
||||
|
||||
|
||||
|
@ -530,15 +532,15 @@ static unsigned char fixAnimPsychedelic(unsigned char const x,
|
|||
|
||||
if (x == 0 && y == 0)
|
||||
{
|
||||
p->fCos = NUM_COLS/2 * fixCos(t);
|
||||
p->fSin = NUM_ROWS/2 * fixSin(t);
|
||||
p->ft10 = fixMul(t, fixScaleUp(10));
|
||||
p->fCos = (fixp_t)(NUM_COLS * 0.72) * (fixCos(t) + FIX);
|
||||
p->fSin = (fixp_t)(NUM_ROWS * 0.72) * (fixSin(t) + FIX);
|
||||
p->fPhaseShift = t * 8;
|
||||
}
|
||||
|
||||
unsigned char const nResult =
|
||||
(unsigned char)(fixMul(fixSin(fixDist(fixScaleUp(x), fixScaleUp(y),
|
||||
p->fCos, p->fSin) - p->ft10) + fixScaleUp(1),
|
||||
(fixp_t)((NUMPLANE - 1.05) * FIX))) / FIX;
|
||||
fixMul(fixSin(fixDist(fixScaleUp(x), fixScaleUp(y),
|
||||
p->fSin, p->fCos) - p->fPhaseShift) + FIX,
|
||||
(fixp_t)((NUMPLANE - 1.05) * FIX)) / FIX;
|
||||
assert(nResult <= NUMPLANE);
|
||||
|
||||
return nResult;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include "../config.h"
|
||||
#include "../compat/pgmspace.h"
|
||||
#include "../random/prng.h"
|
||||
|
@ -9,33 +10,37 @@
|
|||
|
||||
|
||||
#ifdef ANIMATION_TESTS
|
||||
void test_level(unsigned char level){
|
||||
void test_level(unsigned char level, bool debug){
|
||||
for (unsigned char y=NUM_ROWS;y--;){
|
||||
for (unsigned char x=NUM_COLS;x--;){
|
||||
setpixel((pixel){x,y}, level);
|
||||
wait(5);
|
||||
}
|
||||
}
|
||||
if (!debug) {
|
||||
wait(2000);
|
||||
}
|
||||
}
|
||||
|
||||
void test_palette(){
|
||||
void test_palette(bool debug){
|
||||
for (unsigned char y=NUM_ROWS;y--;){
|
||||
for (unsigned char x=NUM_COLS;x--;){
|
||||
setpixel((pixel){x,y}, y%4);
|
||||
// wait(1);
|
||||
}
|
||||
}
|
||||
if (!debug) {
|
||||
wait(2000);
|
||||
}
|
||||
}
|
||||
|
||||
void test_palette2(){
|
||||
void test_palette2(bool debug){
|
||||
for (unsigned char x=NUM_COLS;x--;){
|
||||
for (unsigned char y=NUM_ROWS;y--;){
|
||||
setpixel((pixel){x,y}, x%4);
|
||||
// wait(1);
|
||||
}
|
||||
}
|
||||
if (!debug) {
|
||||
wait(1000);
|
||||
for (unsigned char x=NUM_COLS;x--;){
|
||||
// shift image right
|
||||
|
@ -43,6 +48,7 @@ void test_palette2(){
|
|||
wait(30);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
#ifndef PROGRAMM_H_
|
||||
#define PROGRAMM_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "../pixel.h"
|
||||
#include "../util.h"
|
||||
|
||||
|
||||
void test_level(unsigned char level);
|
||||
void test_palette();
|
||||
void test_palette2();
|
||||
void test_level(unsigned char level, bool debug);
|
||||
void test_palette(bool debug);
|
||||
void test_palette2(bool debug);
|
||||
|
||||
#ifdef ANIMATION_OFF
|
||||
inline static void off()
|
||||
|
|
|
@ -33,15 +33,34 @@
|
|||
#define COLDDR2 DDR(COLPORT2)
|
||||
#define ROWDDR DDR(ROWPORT)
|
||||
|
||||
#if defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__)
|
||||
/* more ifdef magic :-( */
|
||||
#define OCR0 OCR0A
|
||||
#define TIMER0_COMP_vect TIMER0_COMPA_vect
|
||||
#if defined(__AVR_ATmega164__) || \
|
||||
defined(__AVR_ATmega164P__) || \
|
||||
defined(__AVR_ATmega324__) || \
|
||||
defined(__AVR_ATmega324P__) || \
|
||||
defined(__AVR_ATmega644__) || \
|
||||
defined(__AVR_ATmega644P__) || \
|
||||
defined(__AVR_ATmega1284__) || \
|
||||
defined(__AVR_ATmega1284P__)
|
||||
# define TIMER0_OFF() TCCR0A = 0; TCCR0B = 0
|
||||
# define TIMER0_CTC_CS256() TCCR0A = _BV(WGM01); TCCR0B = _BV(CS02)
|
||||
# define TIMER0_RESET() TCNT0 = 0
|
||||
# define TIMER0_COMPARE(t) OCR0A = t
|
||||
# define TIMER0_INT_ENABLE() TIMSK0 = _BV(OCIE0A)
|
||||
# define TIMER0_ISR TIMER0_COMPA_vect
|
||||
#else // ATmega16/32
|
||||
# define TIMER0_OFF() TCCR0 = 0
|
||||
# define TIMER0_CTC_CS256() TCCR0 = _BV(WGM01) | _BV(CS02)
|
||||
# define TIMER0_RESET() TCNT0 = 0
|
||||
# define TIMER0_COMPARE(t) OCR0 = t
|
||||
# define TIMER0_INT_ENABLE() TIMSK = _BV(OCIE0)
|
||||
# define TIMER0_ISR TIMER0_COMP_vect
|
||||
#endif
|
||||
|
||||
|
||||
// buffer which holds the currently shown frame
|
||||
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
|
||||
|
||||
|
||||
// switch to next row
|
||||
static void nextrow(uint8_t row) {
|
||||
//reset states of preceding row
|
||||
|
@ -80,12 +99,18 @@ static void nextrow(uint8_t row) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// show a row
|
||||
static void rowshow(unsigned char row, unsigned char plane) {
|
||||
// depending on the currently drawn plane, display the row for a specific
|
||||
// amount of time
|
||||
#ifdef HIGH_CONTRAST
|
||||
static unsigned char const ocr_table[] = {2, 5, 22};
|
||||
#else
|
||||
static unsigned char const ocr_table[] = {3, 4, 22};
|
||||
OCR0 = ocr_table[plane];
|
||||
#endif
|
||||
|
||||
TIMER0_COMPARE(ocr_table[plane]);
|
||||
|
||||
// output data of the current row to the column drivers
|
||||
uint8_t tmp, tmp1;
|
||||
|
@ -124,19 +149,19 @@ static void rowshow(unsigned char row, unsigned char plane) {
|
|||
|
||||
}
|
||||
|
||||
// depending on the plane this interrupt triggers at 50 kHz, 31.25 kHz or
|
||||
// 12.5 kHz
|
||||
ISR(TIMER0_COMP_vect) {
|
||||
|
||||
// interrupt handler
|
||||
ISR(TIMER0_ISR) {
|
||||
static unsigned char plane = 0;
|
||||
static unsigned char row = 0;
|
||||
|
||||
// reset watchdog
|
||||
wdt_reset();
|
||||
|
||||
// increment both row and plane
|
||||
if (++plane == NUMPLANE) {
|
||||
plane = 0;
|
||||
if (++row == NUM_ROWS) {
|
||||
// reset watchdog
|
||||
wdt_reset();
|
||||
|
||||
row = 0;
|
||||
}
|
||||
nextrow(row);
|
||||
|
@ -146,49 +171,27 @@ ISR(TIMER0_COMP_vect) {
|
|||
rowshow(row, plane);
|
||||
}
|
||||
|
||||
|
||||
// disables timer, causing the watchdog to reset the MCU
|
||||
void timer0_off() {
|
||||
cli();
|
||||
|
||||
COLPORT1 = 0;
|
||||
COLPORT2 = 0;
|
||||
ROWPORT = 0;
|
||||
|
||||
#if defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__)
|
||||
TCCR0A = 0x00;
|
||||
TCCR0B = 0x00;
|
||||
#else
|
||||
|
||||
TCCR0 = 0x00;
|
||||
#endif
|
||||
TIMER0_OFF();
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
// initialize timer which triggers the interrupt
|
||||
static void timer0_on() {
|
||||
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00
|
||||
CS02 CS01 CS00
|
||||
0 0 0 stop
|
||||
0 0 1 clk
|
||||
0 1 0 clk/8
|
||||
0 1 1 clk/64
|
||||
1 0 0 clk/256
|
||||
1 0 1 clk/1024
|
||||
*/
|
||||
|
||||
#if defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__)
|
||||
TCCR0A = 0x02; // CTC Mode
|
||||
TCCR0B = 0x04; // clk/256
|
||||
TCNT0 = 0; // reset timer
|
||||
OCR0 = 20; // compare with this value
|
||||
TIMSK0 = 0x02; // compare match Interrupt on
|
||||
#else
|
||||
TCCR0 = 0x0C; // CTC Mode, clk/256
|
||||
TCNT0 = 0; // reset timer
|
||||
OCR0 = 20; // compare with this value
|
||||
TIMSK = 0x02; // compare match Interrupt on
|
||||
#endif
|
||||
TIMER0_CTC_CS256(); // CTC mode, prescaling conforms to clk/256
|
||||
TIMER0_RESET(); // set counter to 0
|
||||
TIMER0_COMPARE(20); // compare with this value first
|
||||
TIMER0_INT_ENABLE(); // enable Timer/Counter0 Output Compare Match (A) Int.
|
||||
}
|
||||
|
||||
|
||||
void borg_hw_init() {
|
||||
// switch column ports to output mode
|
||||
COLDDR1 = 0xFF;
|
||||
|
@ -208,5 +211,5 @@ void borg_hw_init() {
|
|||
|
||||
// activate watchdog timer
|
||||
wdt_reset();
|
||||
wdt_enable(0x00); // 17ms watchdog
|
||||
wdt_enable(WDTO_15MS); // 15ms watchdog
|
||||
}
|
||||
|
|
|
@ -973,3 +973,27 @@ void borg_hw_init() {
|
|||
wdt_reset();
|
||||
wdt_enable(WDTO_15MS); // 15ms watchdog
|
||||
}
|
||||
|
||||
void timer0_off() {
|
||||
cli();
|
||||
#if defined (__AVR_ATmega48__) || \
|
||||
defined (__AVR_ATmega48P__) || \
|
||||
defined (__AVR_ATmega88__) || \
|
||||
defined (__AVR_ATmega88P__) || \
|
||||
defined (__AVR_ATmega168__) || \
|
||||
defined (__AVR_ATmega168P__) || \
|
||||
defined (__AVR_ATmega328__) || \
|
||||
defined (__AVR_ATmega328P__) || \
|
||||
defined (__AVR_ATmega1280__) || \
|
||||
defined (__AVR_ATmega2560__)
|
||||
TCCR2A = 0x00;
|
||||
TCCR2B = 0x00;
|
||||
#elif defined (__AVR_ATmega8__) || \
|
||||
defined (__AVR_ATmega128__)
|
||||
TCCR2 = 0x00;
|
||||
#elif defined (__AVR_ATmega32U4__)
|
||||
TCCR1A = 0x00;
|
||||
TCCR1B = 0x00;
|
||||
#endif
|
||||
sei();
|
||||
}
|
||||
|
|
|
@ -17,6 +17,21 @@ comment "Borg16 port setup"
|
|||
#//das dier sind die individuellen Dateneingänge für die Schieberegister
|
||||
#define PIN_SHFT1 PD7
|
||||
|
||||
bool "Higher Contrast" HIGH_CONTRAST n
|
||||
|
||||
bool "UART Support" UART_SUPPORT n
|
||||
choice 'Baud Rate' \
|
||||
"2400 2400 \
|
||||
4800 4800 \
|
||||
9600 9600 \
|
||||
14400 14400 \
|
||||
19200 19200 \
|
||||
28800 28800 \
|
||||
38400 38400 \
|
||||
57600 57600 \
|
||||
76800 76800 \
|
||||
115200 115200" \
|
||||
'19200' UART_BAUDRATE_SETTING
|
||||
|
||||
choice 'Column Port 1 (right)' \
|
||||
"PORTA PORTA \
|
||||
|
|
|
@ -2,8 +2,23 @@ mainmenu_option next_comment
|
|||
comment "lolshield setup"
|
||||
|
||||
define_int USER_TIMER0_FOR_WAIT 1
|
||||
define_bool LOLSHIELD y
|
||||
|
||||
uint "Brightness (0-127)" BRIGHTNESS 127
|
||||
uint "Brightness (0-127)" BRIGHTNESS 120
|
||||
uint "Framerate (default 80)" FRAMERATE 80
|
||||
|
||||
bool "UART Support" UART_SUPPORT n
|
||||
choice 'Baud Rate' \
|
||||
"2400 2400 \
|
||||
4800 4800 \
|
||||
9600 9600 \
|
||||
14400 14400 \
|
||||
19200 19200 \
|
||||
28800 28800 \
|
||||
38400 38400 \
|
||||
57600 57600 \
|
||||
76800 76800 \
|
||||
115200 115200" \
|
||||
'19200' UART_BAUDRATE_SETTING
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
|
||||
#define INIT_EEPROM
|
||||
|
||||
//#define UART_BAUD_RATE 115200L
|
||||
#if defined(UART_SUPPORT) && defined(LOLSHIELD) && defined(__AVR_ATmega32U4__)
|
||||
# error UART not supported on Arduino Leonardo
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_H_ */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
|
||||
#include <setjmp.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.h"
|
||||
|
@ -7,6 +8,7 @@
|
|||
#include "animations/snake.h"
|
||||
#include "animations/program.h"
|
||||
#include "animations/matrix.h"
|
||||
#include "animations/dna.h"
|
||||
#include "animations/gameoflife.h"
|
||||
#include "animations/stonefly.h"
|
||||
#include "animations/flyingdots.h"
|
||||
|
@ -48,7 +50,7 @@
|
|||
# include "joystick/joystick.h"
|
||||
#endif
|
||||
|
||||
volatile unsigned char oldMode, oldOldmode, mode;
|
||||
volatile unsigned char oldMode, oldOldmode, reverseMode, mode;
|
||||
|
||||
jmp_buf newmode_jmpbuf;
|
||||
|
||||
|
@ -65,6 +67,12 @@ void display_loop(){
|
|||
// mcuf_serial_mode();
|
||||
|
||||
mode = setjmp(newmode_jmpbuf);
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
// in case we get here via mode jump, we (re)enable joystick queries
|
||||
waitForFire = 1;
|
||||
#endif
|
||||
|
||||
oldOldmode = oldMode;
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
|
@ -76,6 +84,7 @@ void display_loop(){
|
|||
clear_screen(0);
|
||||
#endif
|
||||
oldMode = mode;
|
||||
|
||||
switch(mode++) {
|
||||
|
||||
#ifdef ANIMATION_SCROLLTEXT
|
||||
|
@ -85,7 +94,8 @@ void display_loop(){
|
|||
#ifdef RANDOM_SUPPORT
|
||||
{
|
||||
char a[28];
|
||||
sprintf(a,"</# counter == %lu ", (unsigned long) percnt_get());
|
||||
sprintf(a,"</# counter == %lu ",
|
||||
(unsigned long)percnt_get(&g_reset_counter, &g_reset_counter_idx));
|
||||
scrolltext(a);
|
||||
}
|
||||
#endif
|
||||
|
@ -250,22 +260,28 @@ void display_loop(){
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ANIMATION_DNA
|
||||
case 26:
|
||||
dna();
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef ANIMATION_TESTS
|
||||
case 31:
|
||||
test_level(1);
|
||||
test_level(1, false);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
test_level(2);
|
||||
test_level(2, false);
|
||||
break;
|
||||
|
||||
case 33:
|
||||
test_level(3);
|
||||
test_level(3, false);
|
||||
break;
|
||||
|
||||
case 35:
|
||||
test_palette();
|
||||
test_palette2();
|
||||
test_palette(false);
|
||||
test_palette2(false);
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
@ -292,26 +308,26 @@ void display_loop(){
|
|||
#endif
|
||||
|
||||
#ifdef MENU_SUPPORT
|
||||
case 42:
|
||||
case 0xFDu:
|
||||
mode = 1;
|
||||
break;
|
||||
|
||||
case 43:
|
||||
case 0xFEu:
|
||||
menu();
|
||||
mode = oldOldmode;
|
||||
break;
|
||||
#else
|
||||
|
||||
case 42:
|
||||
case 0xFDu:
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if (JOYISFIRE)
|
||||
mode = 43;
|
||||
mode = 0xFEu;
|
||||
else
|
||||
#endif
|
||||
mode = 1;
|
||||
break;
|
||||
|
||||
case 43:
|
||||
case 0xFEu:
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
waitForFire = 0; // avoid circular jumps
|
||||
while (JOYISFIRE); // wait until user released the fire button
|
||||
|
@ -354,10 +370,19 @@ void display_loop(){
|
|||
#endif
|
||||
|
||||
#ifdef ANIMATION_OFF
|
||||
case 0xFF:
|
||||
case 0xFFu:
|
||||
off();
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
if (reverseMode) {
|
||||
if (reverseMode-- == (mode - 1)) {
|
||||
mode -= 2;
|
||||
} else {
|
||||
reverseMode = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,13 @@ comment "Games"
|
|||
endmenu
|
||||
|
||||
dep_bool "Space Invaders" GAME_SPACE_INVADERS $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
dep_bool "Snake" GAME_SNAKE $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
|
||||
dep_bool_menu "Snake" GAME_SNAKE y $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
bool "POV Controls" SNAKE_POV_CONTROL n
|
||||
int "Snake Game Round Delay" SNAKE_GAME_DELAY 200
|
||||
endmenu
|
||||
|
||||
dep_bool "Breakout" GAME_BREAKOUT $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
|
||||
dep_bool "Kart" GAME_KART $JOYSTICK_SUPPORT $RANDOM_SUPPORT
|
||||
endmenu
|
||||
|
|
|
@ -224,7 +224,7 @@ void kart_game(){
|
|||
wait(WAIT);
|
||||
}
|
||||
|
||||
snprintf(game_over, sizeof(game_over), "</#Game Over, Score: %i", cycle);
|
||||
snprintf(game_over, sizeof(game_over), "</#Game Over, Score: %lu", cycle);
|
||||
scrolltext(game_over);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "../../config.h"
|
||||
#include "../../compat/pgmspace.h"
|
||||
#include "../../pixel.h"
|
||||
|
@ -36,11 +37,13 @@ game_descriptor_t snake_game_descriptor __attribute__((section(".game_descriptor
|
|||
#endif
|
||||
|
||||
|
||||
#ifdef DOXYGEN
|
||||
/**
|
||||
* If defined, joystick controls are NOT as "seen" by the snake but absolute,
|
||||
* that is, if pressing up, snake goes up, etc.
|
||||
* If defined, joystick controls are bound to the point of view of the
|
||||
* snake, i.e. only the left an right joystick direction can be used.
|
||||
*/
|
||||
#define SNAKE_NEWCONTROL
|
||||
#define SNAKE_POV_CONTROL
|
||||
#endif
|
||||
|
||||
#if !defined USNAKE_MAX_LENGTH || defined DOXYGEN
|
||||
/** The maximum length of the snake. */
|
||||
|
@ -102,6 +105,8 @@ typedef struct snake_protagonist_s
|
|||
uint8_t nHeadIndex; /**< Index of the head segment. */
|
||||
uint8_t nTailIndex; /**< Index of the tail segment. */
|
||||
snake_dir_t dir; /**< Direction of the snake. */
|
||||
bool bJoystickLocked; /**< Avoid double joytick queries
|
||||
between movements. */
|
||||
} snake_protagonist_t;
|
||||
|
||||
|
||||
|
@ -213,6 +218,7 @@ static void snake_initGameProtagonist(snake_protagonist_t *pprotSnake)
|
|||
#endif
|
||||
pprotSnake->nTailIndex = 0;
|
||||
pprotSnake->nHeadIndex = 1;
|
||||
pprotSnake->bJoystickLocked = false;
|
||||
}
|
||||
|
||||
#ifdef GAME_SNAKE
|
||||
|
@ -225,17 +231,10 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
|
|||
snake_dir_t *pdirLast)
|
||||
{
|
||||
snake_dir_t dirJoystick = snake_queryJoystick();
|
||||
#ifdef SNAKE_NEWCONTROL
|
||||
if (dirJoystick != SNAKE_DIR_NONE)
|
||||
{
|
||||
// valid transitions can only be uneven
|
||||
if ((pprotSnake->dir + dirJoystick) & 0x01)
|
||||
{
|
||||
pprotSnake->dir = dirJoystick;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE))
|
||||
# ifdef SNAKE_POV_CONTROL
|
||||
|
||||
if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE) &&
|
||||
(!pprotSnake->bJoystickLocked))
|
||||
{
|
||||
// only left or right movements are valid
|
||||
if (dirJoystick & 0x01)
|
||||
|
@ -244,8 +243,24 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
|
|||
pprotSnake->dir = (pprotSnake->dir +
|
||||
(dirJoystick == SNAKE_DIR_LEFT ? 3 : 1)) % 4u;
|
||||
}
|
||||
// we query the joystick twice as fast as we move the snake, so we
|
||||
// have to ensure that it does not bite its head with its head...uh
|
||||
pprotSnake->bJoystickLocked = true;
|
||||
}
|
||||
*pdirLast = dirJoystick;
|
||||
# else
|
||||
if (dirJoystick != SNAKE_DIR_NONE)
|
||||
{
|
||||
// valid transitions can only be uneven
|
||||
if (((pprotSnake->dir + dirJoystick) & 0x01) &&
|
||||
!pprotSnake->bJoystickLocked)
|
||||
{
|
||||
pprotSnake->dir = dirJoystick;
|
||||
}
|
||||
// we query the joystick twice as fast as we move the snake, so we
|
||||
// have to ensure that it does not bite its head with its head...uh
|
||||
pprotSnake->bJoystickLocked = true;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
@ -362,9 +377,9 @@ static void snake_initApples(snake_apples_t *pApples)
|
|||
* Checks for an apple at a given position and removes it if there is one.
|
||||
* @param pApples The set of apples which are lying on the playing field.
|
||||
* @param pxHead The position to be tested.
|
||||
* @return 0 if no apples were found, 1 otherwise
|
||||
* @return false if no apples were found, true otherwise
|
||||
*/
|
||||
static uint8_t snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
|
||||
static bool snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
|
||||
{
|
||||
for (uint8_t i = pApples->nAppleCount; i--;)
|
||||
{
|
||||
|
@ -376,10 +391,10 @@ static uint8_t snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
|
|||
pApples->aApples[i] = pApples->aApples[i + 1];
|
||||
}
|
||||
--pApples->nAppleCount;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -419,7 +434,7 @@ void snake_engine(uint8_t bDemoMode)
|
|||
clear_screen(0);
|
||||
snake_drawBorder();
|
||||
|
||||
for (uint8_t nTick = 0; 1; nTick ^= SNAKE_COLOR_APPLE)
|
||||
for (uint8_t nTick = 0; true; nTick ^= SNAKE_COLOR_APPLE)
|
||||
{
|
||||
// determine new direction
|
||||
#if defined ANIMATION_SNAKE && defined GAME_SNAKE
|
||||
|
@ -439,6 +454,8 @@ void snake_engine(uint8_t bDemoMode)
|
|||
snake_userControl(&protSnake, &dirLast);
|
||||
if (nTick) {
|
||||
#endif
|
||||
// release joystick lock
|
||||
protSnake.bJoystickLocked = false;
|
||||
|
||||
// actually move head
|
||||
pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex];
|
||||
|
|
|
@ -100,7 +100,7 @@ void initInvaders(Invaders * iv, unsigned char lv)
|
|||
uint16_t mask = 0x0001;
|
||||
for (x = 11; x--;)
|
||||
{
|
||||
iv->map[x][y] = (hansrow & mask) ? 3 : 1;
|
||||
iv->map[x][y] = (hansrow & mask) ? 2 : 1;
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ void initInvaders(Invaders * iv, unsigned char lv)
|
|||
iv->pos.x = (NUM_COLS - 11) / 2;
|
||||
iv->pos.y = SPACESHIP_LINE + 1;
|
||||
|
||||
iv->speed = MIN_SPEED + 2;
|
||||
iv->speed = MIN_SPEED + 40;
|
||||
iv->direction = 1;
|
||||
break;
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ uint16_t tetris_highscore_inputName(void)
|
|||
|
||||
uint16_t tetris_highscore_retrieveHighScore(tetris_highscore_index_t nIndex)
|
||||
{
|
||||
eeprom_busy_wait();
|
||||
uint16_t nHighScore =
|
||||
eeprom_read_word(&g_highScoreTable.nHighScore[nIndex]);
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ void tetris_highscore_saveHighScore(tetris_highscore_index_t nIndex,
|
|||
{
|
||||
if (nHighScore > tetris_highscore_retrieveHighScore(nIndex))
|
||||
{
|
||||
eeprom_busy_wait();
|
||||
eeprom_write_word(&g_highScoreTable.nHighScore[nIndex], nHighScore);
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +92,7 @@ void tetris_highscore_saveHighScore(tetris_highscore_index_t nIndex,
|
|||
inline static
|
||||
uint16_t tetris_highscore_retrieveHighScoreName(tetris_highscore_index_t nIdx)
|
||||
{
|
||||
eeprom_busy_wait();
|
||||
uint16_t nHighScoreName =
|
||||
eeprom_read_word(&g_highScoreTable.nHighScoreName[nIdx]);
|
||||
|
||||
|
@ -107,6 +109,7 @@ inline static
|
|||
void tetris_highscore_saveHighScoreName(tetris_highscore_index_t nIndex,
|
||||
uint16_t nHighscoreName)
|
||||
{
|
||||
eeprom_busy_wait();
|
||||
eeprom_write_word(&g_highScoreTable.nHighScoreName[nIndex], nHighscoreName);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,11 +50,11 @@
|
|||
#define TETRIS_INPUT_REPEAT_DELAY 5
|
||||
|
||||
/** Number of loop cyles the left button is ignored */
|
||||
#define TETRIS_INPUT_CHATTER_TICKS_LEFT 12
|
||||
#define TETRIS_INPUT_CHATTER_TICKS_LEFT 24
|
||||
/** Number of loop cyles the right button is ignored */
|
||||
#define TETRIS_INPUT_CHATTER_TICKS_RIGHT 12
|
||||
#define TETRIS_INPUT_CHATTER_TICKS_RIGHT 24
|
||||
/** Number of loop cyles the down button is ignored */
|
||||
#define TETRIS_INPUT_CHATTER_TICKS_DOWN 12
|
||||
#define TETRIS_INPUT_CHATTER_TICKS_DOWN 24
|
||||
/** Number of loop cyles the clockwise rotation button is ignored */
|
||||
#define TETRIS_INPUT_CHATTER_TICKS_ROT_CW 24
|
||||
/** Number of loop cyles the counter clockwise rotation button is ignored */
|
||||
|
|
|
@ -52,7 +52,8 @@
|
|||
/** color of line counter */
|
||||
#define TETRIS_VIEW_COLORCOUNTER 2
|
||||
|
||||
#if (NUM_ROWS < 16) && (NUM_COLS > NUM_ROWS) && (!defined GAME_TETRIS_FP)
|
||||
#if (((NUM_ROWS < 16) && (NUM_COLS > NUM_ROWS)) || \
|
||||
((NUM_ROWS == 16) && (NUM_COLS == 80))) && (!defined GAME_TETRIS_FP)
|
||||
# define VIEWCOLS NUM_ROWS
|
||||
# define VIEWROWS NUM_COLS
|
||||
# define VIEW_TILT
|
||||
|
@ -77,7 +78,8 @@
|
|||
#if VIEWROWS >= 16
|
||||
#define TETRIS_VIEW_XOFFSET_COUNTER \
|
||||
(TETRIS_VIEW_XOFFSET_DUMP + TETRIS_VIEW_WIDTH_DUMP + 1)
|
||||
#define TETRIS_VIEW_YOFFSET_COUNT100 ((VIEWCOLS - 14) / 2)
|
||||
#define TETRIS_VIEW_YOFFSET_COUNT100 + \
|
||||
TETRIS_VIEW_YOFFSET_DUMP + ((TETRIS_VIEW_HEIGHT_DUMP - 14) / 2)
|
||||
#define TETRIS_VIEW_YOFFSET_COUNT10 (TETRIS_VIEW_YOFFSET_COUNT100 + 2)
|
||||
#define TETRIS_VIEW_YOFFSET_COUNT1 (TETRIS_VIEW_YOFFSET_COUNT10 + 4)
|
||||
|
||||
|
|
17
src/main.c
17
src/main.c
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include <setjmp.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "config.h"
|
||||
|
@ -19,6 +20,10 @@
|
|||
#include "can/borg_can.h"
|
||||
#endif
|
||||
|
||||
#ifdef UART_SUPPORT
|
||||
# include "uart/uart.h"
|
||||
#endif
|
||||
|
||||
#ifdef RFM12_SUPPORT
|
||||
#include "rfm12/borg_rfm12.h"
|
||||
#endif
|
||||
|
@ -27,8 +32,8 @@ int main (void){
|
|||
clear_screen(0);
|
||||
|
||||
#ifdef RANDOM_SUPPORT
|
||||
srandom32(percnt_get());
|
||||
percnt_inc();
|
||||
srandom32(percnt_get(&g_reset_counter, &g_reset_counter_idx));
|
||||
percnt_inc(&g_reset_counter, &g_reset_counter_idx);
|
||||
#endif
|
||||
|
||||
#ifdef RFM12_SUPPORT
|
||||
|
@ -41,12 +46,12 @@ int main (void){
|
|||
bcan_init();
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
joy_init();
|
||||
#ifdef UART_SUPPORT
|
||||
uart_init(UART_BAUD_SELECT(UART_BAUDRATE_SETTING, F_CPU));
|
||||
#endif
|
||||
|
||||
#ifdef UART_SUPPORT
|
||||
uart_init();
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
joy_init();
|
||||
#endif
|
||||
|
||||
sei();
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "../compat/interrupt.h" /* cli() & sei() */
|
||||
#include "../compat/eeprom.h"
|
||||
#include "../config.h"
|
||||
#include "persistentCounter.h"
|
||||
|
||||
#ifdef ERROR_HANDLING
|
||||
# include "error-handling.h"
|
||||
|
@ -16,68 +17,67 @@
|
|||
# define PERSISTENT_COUNTER_WRITER_ERROR (void*)0, 2,4,2
|
||||
#endif
|
||||
|
||||
#define RING_SIZE 168
|
||||
|
||||
uint8_t ring_idx = 0xff;
|
||||
|
||||
uint16_t EEMEM B08_23;
|
||||
uint8_t EEMEM B0_7[RING_SIZE];
|
||||
uint8_t g_reset_counter_idx = 0xff;
|
||||
percnt_t EEMEM g_reset_counter;
|
||||
|
||||
#ifdef INIT_EEPROM
|
||||
void init_buffer(void){
|
||||
void init_buffer(percnt_t *percnt, uint8_t *ring_index) {
|
||||
uint8_t i;
|
||||
eeprom_busy_wait();
|
||||
eeprom_write_word(&B08_23, 0x0000);
|
||||
eeprom_write_word(&(percnt->B08_23), 0x0000);
|
||||
for (i = 0; i < RING_SIZE; ++i) {
|
||||
eeprom_busy_wait();
|
||||
eeprom_write_byte(&(B0_7[i]), 0x00);
|
||||
eeprom_write_byte(&(percnt->B0_7[i]), 0x00);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void percnt_init(void){
|
||||
void percnt_init(percnt_t *percnt, uint8_t *ring_index) {
|
||||
uint8_t i;
|
||||
uint8_t maxidx = 0;
|
||||
uint8_t t,max=eeprom_read_byte(&(B0_7[0]));
|
||||
uint8_t t, max = eeprom_read_byte(&(percnt->B0_7[0]));
|
||||
#ifdef INIT_EEPROM
|
||||
if (eeprom_read_word(&B08_23)==0xFFFF){ /* test if the 2 MSB == 0xFFFF*/
|
||||
if (eeprom_read_word((uint16_t*)&(B0_7[0]))==0xFFFF) /* test the first to bytes of ringbuffer*/
|
||||
init_buffer();
|
||||
/* test if the 2 MSB == 0xFFFF */
|
||||
if (eeprom_read_word(&(percnt->B08_23)) == 0xFFFF) {
|
||||
/* test the first two bytes of ringbuffer */
|
||||
if (eeprom_read_word((uint16_t*) &(percnt->B0_7[0])) == 0xFFFF)
|
||||
init_buffer(percnt, ring_index);
|
||||
}
|
||||
#endif
|
||||
for(i=0; i<RING_SIZE; ++i){ /* this might be speed up, but such optimisation could lead to timing attacks */
|
||||
/* might be faster, but such optimizations are prone to timing attacks */
|
||||
for (i = 0; i < RING_SIZE; ++i) {
|
||||
eeprom_busy_wait();
|
||||
t=eeprom_read_byte(&(B0_7[i]));
|
||||
t = eeprom_read_byte(&(percnt->B0_7[i]));
|
||||
if (t == max + 1) {
|
||||
max = t;
|
||||
maxidx = i;
|
||||
}
|
||||
}
|
||||
ring_idx = (maxidx==RING_SIZE)?0:maxidx;
|
||||
*ring_index = (maxidx == RING_SIZE) ? 0 : maxidx;
|
||||
}
|
||||
|
||||
uint32_t percnt_get(void){
|
||||
uint32_t percnt_get(percnt_t *percnt, uint8_t *ring_index) {
|
||||
uint32_t ret = 0;
|
||||
|
||||
if(ring_idx==0xff)
|
||||
percnt_init();
|
||||
if (*ring_index == 0xff)
|
||||
percnt_init(percnt, ring_index);
|
||||
cli();
|
||||
eeprom_busy_wait();
|
||||
ret=eeprom_read_word(&B08_23)<<8;
|
||||
ret = eeprom_read_word(&(percnt->B08_23)) << 8;
|
||||
eeprom_busy_wait();
|
||||
ret |= eeprom_read_byte(&(B0_7[ring_idx]));
|
||||
ret |= eeprom_read_byte(&(percnt->B0_7[*ring_index]));
|
||||
sei();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void percnt_inc(void){
|
||||
void percnt_inc(percnt_t *percnt, uint8_t *ring_index) {
|
||||
/* we must make this resistant agaist power off while this is running ... */
|
||||
uint32_t u;
|
||||
|
||||
if(ring_idx==0xff)
|
||||
percnt_init();
|
||||
if (*ring_index == 0xff)
|
||||
percnt_init(percnt, ring_index);
|
||||
|
||||
u = percnt_get();
|
||||
u = percnt_get(percnt, ring_index);
|
||||
cli();
|
||||
/* it's important to write msb first! */
|
||||
if ((u & 0x000000ff) == 0xff) {
|
||||
|
@ -89,18 +89,20 @@ void percnt_inc(void){
|
|||
#endif
|
||||
}
|
||||
eeprom_busy_wait();
|
||||
eeprom_write_byte(&(((uint8_t*)&B08_23)[1]),((u+1)>>16)&0xff);
|
||||
eeprom_write_byte(&(((uint8_t*) &(percnt->B08_23))[1]),
|
||||
((u + 1) >> 16) & 0xff);
|
||||
}
|
||||
eeprom_busy_wait();
|
||||
eeprom_write_byte(&(((uint8_t*)&B08_23)[0]),((u+1)>>8)&0xff);
|
||||
eeprom_write_byte(&(((uint8_t*) &(percnt->B08_23))[0]),
|
||||
((u + 1) >> 8) & 0xff);
|
||||
}
|
||||
/* set least significant byte (in ringbuffer) */
|
||||
ring_idx = (ring_idx+1)%RING_SIZE;
|
||||
*ring_index = (*ring_index + 1) % RING_SIZE;
|
||||
eeprom_busy_wait();
|
||||
eeprom_write_byte(&(B0_7[ring_idx]),(u+1)&0xff);
|
||||
eeprom_write_byte(&(percnt->B0_7[*ring_index]), (u + 1) & 0xff);
|
||||
eeprom_busy_wait();
|
||||
|
||||
if(u+1 != percnt_get()){
|
||||
if (u + 1 != percnt_get(percnt, ring_index)) {
|
||||
#ifdef ERROR_HANDLING
|
||||
error(PERSISTENT_COUNTER_WRITER_ERROR);
|
||||
#endif
|
||||
|
|
|
@ -9,15 +9,22 @@
|
|||
#ifndef PERSISTENTCOUNTER_H_
|
||||
#define PERSISTENTCOUNTER_H_
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../compat/eeprom.h"
|
||||
|
||||
#define PERSISTENT_COUNTER_BITS 24
|
||||
#define RING_SIZE 168
|
||||
|
||||
void percnt_init(void);
|
||||
uint32_t percnt_get(void);
|
||||
void percnt_inc(void);
|
||||
typedef struct percnt_s {
|
||||
uint16_t B08_23;
|
||||
uint8_t B0_7[RING_SIZE];
|
||||
} percnt_t;
|
||||
|
||||
extern uint8_t g_reset_counter_idx;
|
||||
extern percnt_t g_reset_counter EEMEM;
|
||||
|
||||
void percnt_init(percnt_t *percnt, uint8_t *ring_index);
|
||||
uint32_t percnt_get(percnt_t *percnt, uint8_t *ring_index);
|
||||
void percnt_inc(percnt_t *percnt, uint8_t *ring_index);
|
||||
|
||||
#endif /*PERSISTENTCOUNTER_H_*/
|
||||
|
|
|
@ -69,14 +69,9 @@ static void clear_text_pixmap(){
|
|||
memset(text_pixmap, 0, NUM_ROWS * LINEBYTES);
|
||||
}
|
||||
|
||||
void update_pixmap(){
|
||||
unsigned char x, y, z;
|
||||
for(x=NUMPLANE;x--;){
|
||||
for(y=NUM_ROWS;y--;){
|
||||
for(z=LINEBYTES;z--;){
|
||||
pixmap[x][y][z] = (*text_pixmap)[y][z];
|
||||
}
|
||||
}
|
||||
static void update_pixmap(){
|
||||
for(unsigned char p = NUMPLANE; p--;){
|
||||
memcpy(&pixmap[p][0][0], text_pixmap, NUM_ROWS * LINEBYTES);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ int win;
|
|||
void wait(unsigned int ms) {
|
||||
if (waitForFire) {
|
||||
if (fakeport & 0x01) {
|
||||
longjmp(newmode_jmpbuf, 43);
|
||||
longjmp(newmode_jmpbuf, 0xFEu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -455,7 +455,7 @@ void wait(int ms)
|
|||
{
|
||||
if (fakeport & 0x01)
|
||||
{
|
||||
longjmp(newmode_jmpbuf, 43);
|
||||
longjmp(newmode_jmpbuf, 0xFEu);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
MAKETOPDIR = ../..
|
||||
|
||||
TARGET = libuart.a
|
||||
|
||||
SRC_SIM :=
|
||||
|
||||
include $(MAKETOPDIR)/defaults.mk
|
||||
|
||||
ifeq ($(UART_SUPPORT),y)
|
||||
SRC = uart.c
|
||||
SRC += uart_commands.c
|
||||
endif
|
||||
|
||||
include $(MAKETOPDIR)/rules.mk
|
||||
|
||||
include $(MAKETOPDIR)/depend.mk
|
|
@ -0,0 +1 @@
|
|||
# nothing for now
|
790
src/uart/uart.c
790
src/uart/uart.c
|
@ -1,188 +1,688 @@
|
|||
/* USART-Init beim ATmegaXX */
|
||||
/*************************************************************************
|
||||
Title: Interrupt UART library with receive/transmit circular buffers
|
||||
Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||
File: $Id: uart.c,v 1.12 2014/01/08 21:58:12 peter Exp $
|
||||
Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher
|
||||
Hardware: any AVR with built-in UART,
|
||||
License: GNU General Public License
|
||||
|
||||
DESCRIPTION:
|
||||
An interrupt is generated when the UART has finished transmitting or
|
||||
receiving a byte. The interrupt handling routines use circular buffers
|
||||
for buffering received and transmitted data.
|
||||
|
||||
The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define
|
||||
the buffer size in bytes. Note that these variables must be a
|
||||
power of 2.
|
||||
|
||||
USAGE:
|
||||
Refere to the header file uart.h for a description of the routines.
|
||||
See also example test_uart.c.
|
||||
|
||||
NOTES:
|
||||
Based on Atmel Application Note AVR306
|
||||
|
||||
LICENSE:
|
||||
Copyright (C) 2006 Peter Fleury
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
*************************************************************************/
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include "uart.h"
|
||||
|
||||
#ifdef ATMEGA128
|
||||
#define UCSRB UCSR0B
|
||||
#define UCSRC UCSR0C
|
||||
#define UDR UDR0
|
||||
#define UBRRH UBRR0H
|
||||
#define UBRRL UBRR0L
|
||||
#define URSEL UMSEL
|
||||
|
||||
/*
|
||||
* constants and macros
|
||||
*/
|
||||
|
||||
/* size of RX/TX buffers */
|
||||
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
|
||||
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
|
||||
|
||||
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
|
||||
#error RX buffer size is not a power of 2
|
||||
#endif
|
||||
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
|
||||
#error TX buffer size is not a power of 2
|
||||
#endif
|
||||
|
||||
#if defined(__AVR_AT90S2313__) \
|
||||
|| defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
|
||||
|| defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
|
||||
|| defined(__AVR_ATmega103__)
|
||||
/* old AVR classic or ATmega103 with one UART */
|
||||
#define AT90_UART
|
||||
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
|
||||
#define UART0_STATUS USR
|
||||
#define UART0_CONTROL UCR
|
||||
#define UART0_DATA UDR
|
||||
#define UART0_UDRIE UDRIE
|
||||
#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
|
||||
/* old AVR classic with one UART */
|
||||
#define AT90_UART
|
||||
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
|
||||
#define UART0_STATUS UCSRA
|
||||
#define UART0_CONTROL UCSRB
|
||||
#define UART0_DATA UDR
|
||||
#define UART0_UDRIE UDRIE
|
||||
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
|
||||
|| defined(__AVR_ATmega323__)
|
||||
/* ATmega with one USART */
|
||||
#define ATMEGA_USART
|
||||
#define UART0_RECEIVE_INTERRUPT USART_RXC_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||
#define UART0_STATUS UCSRA
|
||||
#define UART0_CONTROL UCSRB
|
||||
#define UART0_DATA UDR
|
||||
#define UART0_UDRIE UDRIE
|
||||
#elif defined (__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
|
||||
#define ATMEGA_USART
|
||||
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||
#define UART0_STATUS UCSRA
|
||||
#define UART0_CONTROL UCSRB
|
||||
#define UART0_DATA UDR
|
||||
#define UART0_UDRIE UDRIE
|
||||
#elif defined(__AVR_ATmega163__)
|
||||
/* ATmega163 with one UART */
|
||||
#define ATMEGA_UART
|
||||
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
|
||||
#define UART0_STATUS UCSRA
|
||||
#define UART0_CONTROL UCSRB
|
||||
#define UART0_DATA UDR
|
||||
#define UART0_UDRIE UDRIE
|
||||
#elif defined(__AVR_ATmega162__)
|
||||
/* ATmega with two USART */
|
||||
#define ATMEGA_USART0
|
||||
#define ATMEGA_USART1
|
||||
#define UART0_RECEIVE_INTERRUPT USART0_RXC_vect
|
||||
#define UART1_RECEIVE_INTERRUPT USART1_RXC_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
||||
#define UART0_STATUS UCSR0A
|
||||
#define UART0_CONTROL UCSR0B
|
||||
#define UART0_DATA UDR0
|
||||
#define UART0_UDRIE UDRIE0
|
||||
#define UART1_STATUS UCSR1A
|
||||
#define UART1_CONTROL UCSR1B
|
||||
#define UART1_DATA UDR1
|
||||
#define UART1_UDRIE UDRIE1
|
||||
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
|
||||
/* ATmega with two USART */
|
||||
#define ATMEGA_USART0
|
||||
#define ATMEGA_USART1
|
||||
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
||||
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
||||
#define UART0_STATUS UCSR0A
|
||||
#define UART0_CONTROL UCSR0B
|
||||
#define UART0_DATA UDR0
|
||||
#define UART0_UDRIE UDRIE0
|
||||
#define UART1_STATUS UCSR1A
|
||||
#define UART1_CONTROL UCSR1B
|
||||
#define UART1_DATA UDR1
|
||||
#define UART1_UDRIE UDRIE1
|
||||
#elif defined(__AVR_ATmega161__)
|
||||
/* ATmega with UART */
|
||||
#error "AVR ATmega161 currently not supported by this libaray !"
|
||||
#elif defined(__AVR_ATmega169__)
|
||||
/* ATmega with one USART */
|
||||
#define ATMEGA_USART
|
||||
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||
#define UART0_STATUS UCSRA
|
||||
#define UART0_CONTROL UCSRB
|
||||
#define UART0_DATA UDR
|
||||
#define UART0_UDRIE UDRIE
|
||||
#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) \
|
||||
|| defined(__AVR_ATmega3250__) || defined(__AVR_ATmega3290__) ||defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6490__)
|
||||
/* ATmega with one USART */
|
||||
#define ATMEGA_USART0
|
||||
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||
#define UART0_STATUS UCSR0A
|
||||
#define UART0_CONTROL UCSR0B
|
||||
#define UART0_DATA UDR0
|
||||
#define UART0_UDRIE UDRIE0
|
||||
#elif defined(__AVR_ATtiny2313__)
|
||||
#define ATMEGA_USART
|
||||
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
|
||||
#define UART0_STATUS UCSRA
|
||||
#define UART0_CONTROL UCSRB
|
||||
#define UART0_DATA UDR
|
||||
#define UART0_UDRIE UDRIE
|
||||
#elif defined(__AVR_ATmega329__) || \
|
||||
defined(__AVR_ATmega649__) || \
|
||||
defined(__AVR_ATmega325__) || \
|
||||
defined(__AVR_ATmega645__)
|
||||
/* ATmega with one USART */
|
||||
#define ATMEGA_USART0
|
||||
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||
#define UART0_STATUS UCSR0A
|
||||
#define UART0_CONTROL UCSR0B
|
||||
#define UART0_DATA UDR0
|
||||
#define UART0_UDRIE UDRIE0
|
||||
#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__)
|
||||
/* ATmega with two USART */
|
||||
#define ATMEGA_USART0
|
||||
#define ATMEGA_USART1
|
||||
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
||||
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
||||
#define UART0_STATUS UCSR0A
|
||||
#define UART0_CONTROL UCSR0B
|
||||
#define UART0_DATA UDR0
|
||||
#define UART0_UDRIE UDRIE0
|
||||
#define UART1_STATUS UCSR1A
|
||||
#define UART1_CONTROL UCSR1B
|
||||
#define UART1_DATA UDR1
|
||||
#define UART1_UDRIE UDRIE1
|
||||
#elif defined(__AVR_ATmega644__)
|
||||
/* ATmega with one USART */
|
||||
#define ATMEGA_USART0
|
||||
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||
#define UART0_STATUS UCSR0A
|
||||
#define UART0_CONTROL UCSR0B
|
||||
#define UART0_DATA UDR0
|
||||
#define UART0_UDRIE UDRIE0
|
||||
#elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
|
||||
/* ATmega with two USART */
|
||||
#define ATMEGA_USART0
|
||||
#define ATMEGA_USART1
|
||||
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
|
||||
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
|
||||
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
||||
#define UART0_STATUS UCSR0A
|
||||
#define UART0_CONTROL UCSR0B
|
||||
#define UART0_DATA UDR0
|
||||
#define UART0_UDRIE UDRIE0
|
||||
#define UART1_STATUS UCSR1A
|
||||
#define UART1_CONTROL UCSR1B
|
||||
#define UART1_DATA UDR1
|
||||
#define UART1_UDRIE UDRIE1
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)
|
||||
/* AT90USBxx with one USART */
|
||||
#define AT90USB_USART
|
||||
#define UART0_RECEIVE_INTERRUPT USART1_RX_vect
|
||||
#define UART0_TRANSMIT_INTERRUPT USART1_UDRE_vect
|
||||
#define UART0_STATUS UCSR1A
|
||||
#define UART0_CONTROL UCSR1B
|
||||
#define UART0_DATA UDR1
|
||||
#define UART0_UDRIE UDRIE1
|
||||
#elif defined __AVR
|
||||
#error "no UART definition for MCU available"
|
||||
#endif
|
||||
|
||||
|
||||
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16L))
|
||||
/*
|
||||
* module global variables
|
||||
*/
|
||||
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
|
||||
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
|
||||
static volatile unsigned char UART_TxHead;
|
||||
static volatile unsigned char UART_TxTail;
|
||||
static volatile unsigned char UART_RxHead;
|
||||
static volatile unsigned char UART_RxTail;
|
||||
static volatile unsigned char UART_LastRxError;
|
||||
|
||||
|
||||
#ifdef UART_INTERRUPT
|
||||
volatile static char rxbuf[UART_RXBUFSIZE];
|
||||
volatile static char txbuf[UART_TXBUFSIZE];
|
||||
volatile static char *volatile rxhead, *volatile rxtail;
|
||||
volatile static char *volatile txhead, *volatile txtail;
|
||||
|
||||
|
||||
ISR(USART_UDRE_vect) {
|
||||
#ifdef UART_LEDS
|
||||
PORTC ^= 0x01;
|
||||
#if defined( ATMEGA_USART1 ) && defined (USE_UART1)
|
||||
static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
|
||||
static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
|
||||
static volatile unsigned char UART1_TxHead;
|
||||
static volatile unsigned char UART1_TxTail;
|
||||
static volatile unsigned char UART1_RxHead;
|
||||
static volatile unsigned char UART1_RxTail;
|
||||
static volatile unsigned char UART1_LastRxError;
|
||||
#endif
|
||||
|
||||
if ( txhead == txtail ) {
|
||||
UCSRB &= ~(1 << UDRIE); /* disable data register empty IRQ */
|
||||
|
||||
|
||||
ISR (UART0_RECEIVE_INTERRUPT)
|
||||
/*************************************************************************
|
||||
Function: UART Receive Complete interrupt
|
||||
Purpose: called when the UART has received a character
|
||||
**************************************************************************/
|
||||
{
|
||||
unsigned char tmphead;
|
||||
unsigned char data;
|
||||
unsigned char usr;
|
||||
unsigned char lastRxError;
|
||||
|
||||
|
||||
/* read UART status register and UART data register */
|
||||
usr = UART0_STATUS;
|
||||
data = UART0_DATA;
|
||||
|
||||
/* */
|
||||
#if defined( AT90_UART )
|
||||
lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
|
||||
#elif defined( ATMEGA_USART )
|
||||
lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
|
||||
#elif defined( ATMEGA_USART0 )
|
||||
lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );
|
||||
#elif defined ( ATMEGA_UART )
|
||||
lastRxError = (usr & (_BV(FE)|_BV(DOR)) );
|
||||
#elif defined( AT90USB_USART )
|
||||
lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
|
||||
#endif
|
||||
|
||||
/* calculate buffer index */
|
||||
tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;
|
||||
|
||||
if ( tmphead == UART_RxTail ) {
|
||||
/* error: receive buffer overflow */
|
||||
lastRxError = UART_BUFFER_OVERFLOW >> 8;
|
||||
}else{
|
||||
UDR = *txtail; /* schreibt das Zeichen x auf die Schnittstelle */
|
||||
if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf;
|
||||
/* store new index */
|
||||
UART_RxHead = tmphead;
|
||||
/* store received data in buffer */
|
||||
UART_RxBuf[tmphead] = data;
|
||||
}
|
||||
UART_LastRxError |= lastRxError;
|
||||
}
|
||||
|
||||
|
||||
ISR (UART0_TRANSMIT_INTERRUPT)
|
||||
/*************************************************************************
|
||||
Function: UART Data Register Empty interrupt
|
||||
Purpose: called when the UART is ready to transmit the next byte
|
||||
**************************************************************************/
|
||||
{
|
||||
unsigned char tmptail;
|
||||
|
||||
|
||||
if ( UART_TxHead != UART_TxTail) {
|
||||
/* calculate and store new buffer index */
|
||||
tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;
|
||||
UART_TxTail = tmptail;
|
||||
/* get one byte from buffer and write it to UART */
|
||||
UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */
|
||||
}else{
|
||||
/* tx buffer empty, disable UDRE interrupt */
|
||||
UART0_CONTROL &= ~_BV(UART0_UDRIE);
|
||||
}
|
||||
}
|
||||
|
||||
ISR(USART_RXC_vect) {
|
||||
int diff;
|
||||
|
||||
#ifdef UART_LEDS
|
||||
PORTC ^= 0x02;
|
||||
/*************************************************************************
|
||||
Function: uart_init()
|
||||
Purpose: initialize UART and set baudrate
|
||||
Input: baudrate using macro UART_BAUD_SELECT()
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart_init(unsigned int baudrate)
|
||||
{
|
||||
UART_TxHead = 0;
|
||||
UART_TxTail = 0;
|
||||
UART_RxHead = 0;
|
||||
UART_RxTail = 0;
|
||||
|
||||
#if defined( AT90_UART )
|
||||
/* set baud rate */
|
||||
UBRR = (unsigned char)baudrate;
|
||||
|
||||
/* enable UART receiver and transmmitter and receive complete interrupt */
|
||||
UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
|
||||
|
||||
#elif defined (ATMEGA_USART)
|
||||
/* Set baud rate */
|
||||
if ( baudrate & 0x8000 )
|
||||
{
|
||||
UART0_STATUS = (1<<U2X); //Enable 2x speed
|
||||
baudrate &= ~0x8000;
|
||||
}
|
||||
UBRRH = (unsigned char)(baudrate>>8);
|
||||
UBRRL = (unsigned char) baudrate;
|
||||
|
||||
/* Enable USART receiver and transmitter and receive complete interrupt */
|
||||
UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
|
||||
|
||||
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
||||
#ifdef URSEL
|
||||
UCSRC = (1<<URSEL)|(3<<UCSZ0);
|
||||
#else
|
||||
UCSRC = (3<<UCSZ0);
|
||||
#endif
|
||||
|
||||
/* buffer full? */
|
||||
diff = rxhead - rxtail;
|
||||
if ( diff < 0 ) diff += UART_RXBUFSIZE;
|
||||
if (diff < UART_RXBUFSIZE -1) {
|
||||
// buffer NOT full
|
||||
*rxhead = UDR;
|
||||
if (++rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
|
||||
#elif defined (ATMEGA_USART0 )
|
||||
/* Set baud rate */
|
||||
if ( baudrate & 0x8000 )
|
||||
{
|
||||
UART0_STATUS = (1<<U2X0); //Enable 2x speed
|
||||
baudrate &= ~0x8000;
|
||||
}
|
||||
UBRR0H = (unsigned char)(baudrate>>8);
|
||||
UBRR0L = (unsigned char) baudrate;
|
||||
|
||||
/* Enable USART receiver and transmitter and receive complete interrupt */
|
||||
UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
|
||||
|
||||
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
||||
#ifdef URSEL0
|
||||
UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
|
||||
#else
|
||||
UCSR0C = (3<<UCSZ00);
|
||||
#endif
|
||||
|
||||
#elif defined ( ATMEGA_UART )
|
||||
/* set baud rate */
|
||||
if ( baudrate & 0x8000 )
|
||||
{
|
||||
UART0_STATUS = (1<<U2X); //Enable 2x speed
|
||||
baudrate &= ~0x8000;
|
||||
}
|
||||
UBRRHI = (unsigned char)(baudrate>>8);
|
||||
UBRR = (unsigned char) baudrate;
|
||||
|
||||
/* Enable UART receiver and transmitter and receive complete interrupt */
|
||||
UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
|
||||
|
||||
#elif defined ( AT90USB_USART )
|
||||
/* set baud rate */
|
||||
if ( baudrate & 0x8000 )
|
||||
{
|
||||
UART0_STATUS = (1<<U2X1 ); //Enable 2x speed
|
||||
baudrate &= ~0x8000;
|
||||
}
|
||||
UBRR1H = (unsigned char)(baudrate>>8);
|
||||
UBRR1L = (unsigned char) baudrate;
|
||||
|
||||
/* Enable UART receiver and transmitter and receive complete interrupt */
|
||||
UART0_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
|
||||
|
||||
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
||||
UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);
|
||||
#endif
|
||||
|
||||
}/* uart_init */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart_getc()
|
||||
Purpose: return byte from ringbuffer
|
||||
Returns: lower byte: received byte from ringbuffer
|
||||
higher byte: last receive error
|
||||
**************************************************************************/
|
||||
unsigned int uart_getc(void)
|
||||
{
|
||||
unsigned char tmptail;
|
||||
unsigned char data;
|
||||
|
||||
|
||||
if ( UART_RxHead == UART_RxTail ) {
|
||||
return UART_NO_DATA; /* no data available */
|
||||
}
|
||||
|
||||
/* calculate /store buffer index */
|
||||
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
|
||||
UART_RxTail = tmptail;
|
||||
|
||||
/* get data from receive buffer */
|
||||
data = UART_RxBuf[tmptail];
|
||||
|
||||
data = (UART_LastRxError << 8) + data;
|
||||
UART_LastRxError = 0;
|
||||
return data;
|
||||
|
||||
}/* uart_getc */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart_putc()
|
||||
Purpose: write byte to ringbuffer for transmitting via UART
|
||||
Input: byte to be transmitted
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart_putc(unsigned char data)
|
||||
{
|
||||
unsigned char tmphead;
|
||||
|
||||
|
||||
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
|
||||
|
||||
while ( tmphead == UART_TxTail ){
|
||||
;/* wait for free space in buffer */
|
||||
}
|
||||
|
||||
UART_TxBuf[tmphead] = data;
|
||||
UART_TxHead = tmphead;
|
||||
|
||||
/* enable UDRE interrupt */
|
||||
UART0_CONTROL |= _BV(UART0_UDRIE);
|
||||
|
||||
}/* uart_putc */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart_puts()
|
||||
Purpose: transmit string to UART
|
||||
Input: string to be transmitted
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart_puts(const char *s )
|
||||
{
|
||||
while (*s)
|
||||
uart_putc(*s++);
|
||||
|
||||
}/* uart_puts */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart_puts_p()
|
||||
Purpose: transmit string from program memory to UART
|
||||
Input: program memory string to be transmitted
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart_puts_p(const char *progmem_s )
|
||||
{
|
||||
register char c;
|
||||
|
||||
while ( (c = pgm_read_byte(progmem_s++)) )
|
||||
uart_putc(c);
|
||||
|
||||
}/* uart_puts_p */
|
||||
|
||||
|
||||
/*
|
||||
* these functions are only for ATmegas with two USART
|
||||
*/
|
||||
#if defined( ATMEGA_USART1 ) && defined (USE_UART1)
|
||||
|
||||
ISR(UART1_RECEIVE_INTERRUPT)
|
||||
/*************************************************************************
|
||||
Function: UART1 Receive Complete interrupt
|
||||
Purpose: called when the UART1 has received a character
|
||||
**************************************************************************/
|
||||
{
|
||||
unsigned char tmphead;
|
||||
unsigned char data;
|
||||
unsigned char usr;
|
||||
unsigned char lastRxError;
|
||||
|
||||
|
||||
/* read UART status register and UART data register */
|
||||
usr = UART1_STATUS;
|
||||
data = UART1_DATA;
|
||||
|
||||
/* */
|
||||
lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );
|
||||
|
||||
/* calculate buffer index */
|
||||
tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
|
||||
|
||||
if ( tmphead == UART1_RxTail ) {
|
||||
/* error: receive buffer overflow */
|
||||
lastRxError = UART_BUFFER_OVERFLOW >> 8;
|
||||
}else{
|
||||
UDR; //reads the buffer to clear the interrupt condition
|
||||
/* store new index */
|
||||
UART1_RxHead = tmphead;
|
||||
/* store received data in buffer */
|
||||
UART1_RxBuf[tmphead] = data;
|
||||
}
|
||||
UART1_LastRxError |= lastRxError;
|
||||
}
|
||||
|
||||
#endif // UART_INTERRUPT
|
||||
|
||||
|
||||
void uart_init() {
|
||||
PORTD |= 0x01; //Pullup an RXD an
|
||||
|
||||
UCSRA = 0;
|
||||
UCSRB |= (1<<TXEN); //UART TX einschalten
|
||||
UCSRC |= (1<<URSEL)|(3<<UCSZ0); //Asynchron 8N1
|
||||
|
||||
UCSRB |= ( 1 << RXEN ); //Uart RX einschalten
|
||||
|
||||
// UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
|
||||
// UBRRL=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU));
|
||||
|
||||
UBRRL = 8;
|
||||
|
||||
#ifdef UART_INTERRUPT
|
||||
// init buffers
|
||||
rxhead = rxtail = rxbuf;
|
||||
txhead = txtail = txbuf;
|
||||
|
||||
// activate rx IRQ
|
||||
UCSRB |= (1 << RXCIE);
|
||||
#endif // UART_INTERRUPT
|
||||
}
|
||||
|
||||
#ifdef UART_INTERRUPT
|
||||
void uart_putc(char c) {
|
||||
volatile int diff;
|
||||
|
||||
/* buffer full? */
|
||||
do {
|
||||
diff = txhead - txtail;
|
||||
if ( diff < 0 ) diff += UART_TXBUFSIZE;
|
||||
} while ( diff >= UART_TXBUFSIZE -1 );
|
||||
|
||||
cli();
|
||||
*txhead = c;
|
||||
if (++txhead == (txbuf + UART_TXBUFSIZE)) txhead = txbuf;
|
||||
|
||||
UCSRB |= (1 << UDRIE); /* enable data register empty IRQ */
|
||||
sei();
|
||||
}
|
||||
#else // WITHOUT INTERRUPT
|
||||
void uart_putc(char c) {
|
||||
while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
|
||||
UDR = c; /* schreibt das Zeichen x auf die Schnittstelle */
|
||||
}
|
||||
#endif // UART_INTERRUPT
|
||||
|
||||
|
||||
void uart_putstr(char *str) {
|
||||
while(*str) {
|
||||
uart_putc(*str++);
|
||||
}
|
||||
}
|
||||
|
||||
void uart_putstr_P(PGM_P str) {
|
||||
char tmp;
|
||||
while((tmp = pgm_read_byte(str))) {
|
||||
uart_putc(tmp);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_hexdump(char *buf, int len)
|
||||
ISR(UART1_TRANSMIT_INTERRUPT)
|
||||
/*************************************************************************
|
||||
Function: UART1 Data Register Empty interrupt
|
||||
Purpose: called when the UART1 is ready to transmit the next byte
|
||||
**************************************************************************/
|
||||
{
|
||||
unsigned char x=0;
|
||||
char sbuf[3];
|
||||
unsigned char tmptail;
|
||||
|
||||
while(len--){
|
||||
itoa(*buf++, sbuf, 16);
|
||||
if (sbuf[1] == 0) uart_putc(' ');
|
||||
uart_putstr(sbuf);
|
||||
uart_putc(' ');
|
||||
if(++x == 16) {
|
||||
uart_putstr_P(PSTR("\r\n"));
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if ( UART1_TxHead != UART1_TxTail) {
|
||||
/* calculate and store new buffer index */
|
||||
tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
|
||||
UART1_TxTail = tmptail;
|
||||
/* get one byte from buffer and write it to UART */
|
||||
UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
|
||||
}else{
|
||||
/* tx buffer empty, disable UDRE interrupt */
|
||||
UART1_CONTROL &= ~_BV(UART1_UDRIE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef UART_INTERRUPT
|
||||
char uart_getc()
|
||||
/*************************************************************************
|
||||
Function: uart1_init()
|
||||
Purpose: initialize UART1 and set baudrate
|
||||
Input: baudrate using macro UART_BAUD_SELECT()
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart1_init(unsigned int baudrate)
|
||||
{
|
||||
char val;
|
||||
UART1_TxHead = 0;
|
||||
UART1_TxTail = 0;
|
||||
UART1_RxHead = 0;
|
||||
UART1_RxTail = 0;
|
||||
|
||||
while(rxhead==rxtail) ;
|
||||
|
||||
val = *rxtail;
|
||||
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
|
||||
|
||||
return val;
|
||||
}
|
||||
#else // WITHOUT INTERRUPT
|
||||
char uart_getc()
|
||||
/* Set baud rate */
|
||||
if ( baudrate & 0x8000 )
|
||||
{
|
||||
while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
|
||||
return UDR; // Zeichen aus UDR zurueckgeben
|
||||
UART1_STATUS = (1<<U2X1); //Enable 2x speed
|
||||
baudrate &= ~0x8000;
|
||||
}
|
||||
#endif // UART_INTERRUPT
|
||||
UBRR1H = (unsigned char)(baudrate>>8);
|
||||
UBRR1L = (unsigned char) baudrate;
|
||||
|
||||
// returns 1 on success
|
||||
#ifdef UART_INTERRUPT
|
||||
char uart_getc_nb(char *c)
|
||||
/* Enable USART receiver and transmitter and receive complete interrupt */
|
||||
UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
|
||||
|
||||
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
|
||||
#ifdef URSEL1
|
||||
UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
|
||||
#else
|
||||
UCSR1C = (3<<UCSZ10);
|
||||
#endif
|
||||
}/* uart_init */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart1_getc()
|
||||
Purpose: return byte from ringbuffer
|
||||
Returns: lower byte: received byte from ringbuffer
|
||||
higher byte: last receive error
|
||||
**************************************************************************/
|
||||
unsigned int uart1_getc(void)
|
||||
{
|
||||
if (rxhead==rxtail) return 0;
|
||||
unsigned char tmptail;
|
||||
unsigned char data;
|
||||
|
||||
*c = *rxtail;
|
||||
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
|
||||
|
||||
return 1;
|
||||
if ( UART1_RxHead == UART1_RxTail ) {
|
||||
return UART_NO_DATA; /* no data available */
|
||||
}
|
||||
#else // WITHOUT INTERRUPT
|
||||
char uart_getc_nb(char *c)
|
||||
|
||||
/* calculate /store buffer index */
|
||||
tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
|
||||
UART1_RxTail = tmptail;
|
||||
|
||||
/* get data from receive buffer */
|
||||
data = UART1_RxBuf[tmptail];
|
||||
|
||||
data = (UART1_LastRxError << 8) + data;
|
||||
UART1_LastRxError = 0;
|
||||
return data;
|
||||
|
||||
}/* uart1_getc */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart1_putc()
|
||||
Purpose: write byte to ringbuffer for transmitting via UART
|
||||
Input: byte to be transmitted
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart1_putc(unsigned char data)
|
||||
{
|
||||
if (UCSRA & (1<<RXC)) { // Zeichen verfuegbar
|
||||
*c = UDR;
|
||||
return 1;
|
||||
unsigned char tmphead;
|
||||
|
||||
|
||||
tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
|
||||
|
||||
while ( tmphead == UART1_TxTail ){
|
||||
;/* wait for free space in buffer */
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // UART_INTERRUPT
|
||||
UART1_TxBuf[tmphead] = data;
|
||||
UART1_TxHead = tmphead;
|
||||
|
||||
/* enable UDRE interrupt */
|
||||
UART1_CONTROL |= _BV(UART1_UDRIE);
|
||||
|
||||
}/* uart1_putc */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart1_puts()
|
||||
Purpose: transmit string to UART1
|
||||
Input: string to be transmitted
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart1_puts(const char *s )
|
||||
{
|
||||
while (*s)
|
||||
uart1_putc(*s++);
|
||||
|
||||
}/* uart1_puts */
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
Function: uart1_puts_p()
|
||||
Purpose: transmit string from program memory to UART1
|
||||
Input: program memory string to be transmitted
|
||||
Returns: none
|
||||
**************************************************************************/
|
||||
void uart1_puts_p(const char *progmem_s )
|
||||
{
|
||||
register char c;
|
||||
|
||||
while ( (c = pgm_read_byte(progmem_s++)) )
|
||||
uart1_putc(c);
|
||||
|
||||
}/* uart1_puts_p */
|
||||
|
||||
#endif
|
||||
|
|
236
src/uart/uart.h
236
src/uart/uart.h
|
@ -1,35 +1,223 @@
|
|||
#ifndef UART_H
|
||||
#define UART_H
|
||||
/************************************************************************
|
||||
Title: Interrupt UART library with receive/transmit circular buffers
|
||||
Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
|
||||
File: $Id: uart.h,v 1.12 2012/11/19 19:52:27 peter Exp $
|
||||
Software: AVR-GCC 4.1, AVR Libc 1.4
|
||||
Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz
|
||||
License: GNU General Public License
|
||||
Usage: see Doxygen manual
|
||||
|
||||
LICENSE:
|
||||
Copyright (C) 2006 Peter Fleury
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
************************************************************************/
|
||||
|
||||
/**
|
||||
* UART Library
|
||||
* @defgroup pfleury_uart UART Library
|
||||
* @code #include <uart.h> @endcode
|
||||
*
|
||||
* #define F_CPU 16000000 // Oszillator-Frequenz in Hz
|
||||
* #define UART_INTERRUPT 1
|
||||
* #define UART_BAUD_RATE 19200
|
||||
* #define UART_RXBUFSIZE 16
|
||||
* #define UART_TXBUFSIZE 16
|
||||
* #define UART_LINE_BUFFER_SIZE 40
|
||||
* #define UART_LEDS // LED1 and LED2 toggle on tx and rx interrupt
|
||||
* @brief Interrupt UART library using the built-in UART with transmit and
|
||||
* receive circular buffers.
|
||||
*
|
||||
* This library can be used to transmit and receive data through the built in
|
||||
* UART.
|
||||
*
|
||||
* An interrupt is generated when the UART has finished transmitting or
|
||||
* receiving a byte. The interrupt handling routines use circular buffers
|
||||
* for buffering received and transmitted data.
|
||||
*
|
||||
* The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define the size of
|
||||
* the circular buffers in bytes. Note that these constants must be a power of
|
||||
* 2. You may need to adapt this constants to your target and your application
|
||||
* by adding CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your
|
||||
* Makefile.
|
||||
*
|
||||
* @note Based on Atmel Application Note AVR306
|
||||
* @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <avr/pgmspace.h>
|
||||
/**@{*/
|
||||
|
||||
void uart_init();
|
||||
|
||||
void uart_putc(char c);
|
||||
void uart_putstr(char * str);
|
||||
void uart_putstr_P(PGM_P str);
|
||||
void uart_hexdump(char *buf, int len);
|
||||
|
||||
char uart_getc();
|
||||
char uart_getc_nb(char *c); // returns 1 on success
|
||||
|
||||
//get one Cariage return terminated line
|
||||
//echo charakters back on Uart
|
||||
//returns buffer with zero terminated line on success, 0 pointer otherwise
|
||||
char * uart_getline_nb();
|
||||
#include "../config.h"
|
||||
|
||||
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
|
||||
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* constants and macros
|
||||
*/
|
||||
|
||||
/** @brief UART Baudrate Expression
|
||||
* @param xtalcpu system clock in Mhz, e.g. 4000000UL for 4Mhz
|
||||
* @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
|
||||
*/
|
||||
#define UART_BAUD_SELECT(baudRate,xtalCpu) \
|
||||
(((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL)
|
||||
|
||||
/** @brief UART Baudrate Expression for ATmega double speed mode
|
||||
* @param xtalcpu system clock in Mhz, e.g. 4000000UL for 4Mhz
|
||||
* @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
|
||||
*/
|
||||
#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) \
|
||||
(((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000)
|
||||
|
||||
|
||||
/** Size of the circular receive buffer, must be power of 2 */
|
||||
#ifndef UART_RX_BUFFER_SIZE
|
||||
#define UART_RX_BUFFER_SIZE 32
|
||||
#endif
|
||||
|
||||
/** Size of the circular transmit buffer, must be power of 2 */
|
||||
#ifndef UART_TX_BUFFER_SIZE
|
||||
#define UART_TX_BUFFER_SIZE 32
|
||||
#endif
|
||||
|
||||
/* test if the size of the circular buffers fits into SRAM */
|
||||
#if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) && defined __AVR
|
||||
#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** high byte error return code of uart_getc()
|
||||
*/
|
||||
#define UART_FRAME_ERROR 0x1000 /* Framing Error by UART */
|
||||
#define UART_OVERRUN_ERROR 0x0800 /* Overrun condition by UART */
|
||||
#define UART_PARITY_ERROR 0x0400 /* Parity Error by UART */
|
||||
#define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */
|
||||
#define UART_NO_DATA 0x0100 /* no receive data available */
|
||||
|
||||
|
||||
/*
|
||||
** function prototypes
|
||||
*/
|
||||
|
||||
/**
|
||||
@brief Initialize UART and set baudrate
|
||||
@param baudrate Specify baudrate using macro UART_BAUD_SELECT()
|
||||
@return none
|
||||
*/
|
||||
extern void uart_init(unsigned int baudrate);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get received byte from ringbuffer
|
||||
*
|
||||
* Returns in the lower byte the received character and in the
|
||||
* higher byte the last receive error.
|
||||
* UART_NO_DATA is returned when no data is available.
|
||||
*
|
||||
* @param void
|
||||
* @return lower byte: received byte from ringbuffer
|
||||
* @return higher byte: last receive status
|
||||
* - \b 0 successfully received data from UART
|
||||
* - \b UART_NO_DATA
|
||||
* <br>no receive data available
|
||||
* - \b UART_BUFFER_OVERFLOW
|
||||
* <br>Receive ringbuffer overflow.
|
||||
* We are not reading the receive buffer fast enough,
|
||||
* one or more received character have been dropped
|
||||
* - \b UART_OVERRUN_ERROR
|
||||
* <br>Overrun condition by UART.
|
||||
* A character already present in the UART UDR register was not read
|
||||
* by the interrupt handler before the next character arrived,
|
||||
* one or more received characters have been dropped.
|
||||
* - \b UART_FRAME_ERROR
|
||||
* <br>Framing Error by UART
|
||||
*/
|
||||
extern unsigned int uart_getc(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Put byte to ringbuffer for transmitting via UART
|
||||
* @param data byte to be transmitted
|
||||
* @return none
|
||||
*/
|
||||
extern void uart_putc(unsigned char data);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Put string to ringbuffer for transmitting via UART
|
||||
*
|
||||
* The string is buffered by the uart library in a circular buffer
|
||||
* and one character at a time is transmitted to the UART using interrupts.
|
||||
* Blocks if it can not write the whole string into the circular buffer.
|
||||
*
|
||||
* @param s string to be transmitted
|
||||
* @return none
|
||||
*/
|
||||
extern void uart_puts(const char *s );
|
||||
|
||||
|
||||
/**
|
||||
* @brief Put string from program memory to ringbuffer for transmitting via
|
||||
* UART.
|
||||
*
|
||||
* The string is buffered by the uart library in a circular buffer
|
||||
* and one character at a time is transmitted to the UART using interrupts.
|
||||
* Blocks if it can not write the whole string into the circular buffer.
|
||||
*
|
||||
* @param s program memory string to be transmitted
|
||||
* @return none
|
||||
* @see uart_puts_P
|
||||
*/
|
||||
extern void uart_puts_p(const char *s );
|
||||
|
||||
/**
|
||||
* @brief Macro to automatically put a string constant into program memory
|
||||
*/
|
||||
#define uart_puts_P(__s) uart_puts_p(PSTR(__s))
|
||||
|
||||
|
||||
#if defined USE_UART1 || defined DOXYGEN
|
||||
|
||||
/** @brief Initialize USART1 (only available on selected ATmegas)
|
||||
* @see uart_init
|
||||
*/
|
||||
extern void uart1_init(unsigned int baudrate);
|
||||
|
||||
/** @brief Get received byte of USART1 from ringbuffer (only available on
|
||||
* selected ATmega)
|
||||
* @see uart_getc
|
||||
*/
|
||||
extern unsigned int uart1_getc(void);
|
||||
|
||||
/** @brief Put byte to ringbuffer for transmitting via USART1 (only available
|
||||
* on selected ATmega)
|
||||
* @see uart_putc
|
||||
*/
|
||||
extern void uart1_putc(unsigned char data);
|
||||
|
||||
/** @brief Put string to ringbuffer for transmitting via USART1 (only available
|
||||
* on selected ATmega)
|
||||
* @see uart_puts
|
||||
*/
|
||||
extern void uart1_puts(const char *s );
|
||||
|
||||
/** @brief Put string from program memory to ringbuffer for transmitting via
|
||||
* USART1 (only available on selected ATmega)
|
||||
* @see uart_puts_p
|
||||
*/
|
||||
extern void uart1_puts_p(const char *s );
|
||||
|
||||
/** @brief Macro to automatically put a string constant into program memory */
|
||||
#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s))
|
||||
|
||||
/**@}*/
|
||||
|
||||
#endif // defined USE_UART1 || defined DOXYGEN
|
||||
|
||||
#endif // UART_H
|
||||
|
|
|
@ -0,0 +1,503 @@
|
|||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <setjmp.h>
|
||||
#include <limits.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include "../config.h"
|
||||
#include "../borg_hw/borg_hw.h"
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
#include "../joystick/joystick.h"
|
||||
extern unsigned char waitForFire;
|
||||
#endif
|
||||
#include "../scrolltext/scrolltext.h"
|
||||
#include "../animations/program.h"
|
||||
#include "uart.h"
|
||||
#include "uart_commands.h"
|
||||
|
||||
#ifndef USE_UART1
|
||||
# define UART_PUTS(STR) uart_puts(STR)
|
||||
# define UART_PUTS_P(STR) uart_puts_p(STR)
|
||||
# define UART_GETC uart_getc
|
||||
# define UART_PUTC uart_putc
|
||||
#else
|
||||
# define UART_PUTS(STR) uart1_puts(STR)
|
||||
# define UART_PUTS_P(STR) uart1_puts_p(STR)
|
||||
# define UART_GETC uart1_getc
|
||||
# define UART_PUTC uart1_putc
|
||||
#endif
|
||||
|
||||
#define UART_BUFFER_SIZE (SCROLLTEXT_BUFFER_SIZE + 8)
|
||||
char g_rx_buffer[UART_BUFFER_SIZE];
|
||||
uint8_t g_rx_index;
|
||||
|
||||
extern jmp_buf newmode_jmpbuf;
|
||||
extern volatile unsigned char mode;
|
||||
extern volatile unsigned char reverseMode;
|
||||
|
||||
#define CR "\r\n"
|
||||
|
||||
#if (!(defined(eeprom_update_block) && \
|
||||
((E2PAGESIZE == 2) || (E2PAGESIZE == 4) || (E2PAGESIZE == 8)))) || \
|
||||
!(defined(ANIMATION_TESTS))
|
||||
char const UART_STR_NOTIMPL[] PROGMEM = "Not implemented."CR;
|
||||
#endif
|
||||
|
||||
char const UART_STR_CLEARLINE[] PROGMEM = "\r\033[J";
|
||||
char const UART_STR_BACKSPACE[] PROGMEM = "\b \b";
|
||||
char const UART_STR_PROMPT[] PROGMEM = "> ";
|
||||
char const UART_STR_MODE[] PROGMEM = "%d"CR;
|
||||
char const UART_STR_MODE_ERR[] PROGMEM = "Range is between 0 and 255."CR;
|
||||
char const UART_STR_GAMEMO_ERR[] PROGMEM = "No mode change during games."CR;
|
||||
char const UART_STR_GAMETX_ERR[] PROGMEM = "No text messages during games."CR;
|
||||
char const UART_STR_UART_ERR[] PROGMEM = "Transmission error."CR;
|
||||
char const UART_STR_UNKNOWN[] PROGMEM = "Unknown command or syntax error."CR;
|
||||
char const UART_STR_TOOLONG[] PROGMEM = CR"Command is too long."CR;
|
||||
char const UART_STR_HELP[] PROGMEM = "Allowed commands: erase help mode "
|
||||
"msg next prev reset scroll test"CR;
|
||||
|
||||
char const UART_CMD_ERASE[] PROGMEM = "erase";
|
||||
char const UART_CMD_HELP[] PROGMEM = "help";
|
||||
char const UART_CMD_MODE[] PROGMEM = "mode";
|
||||
char const UART_CMD_MSG[] PROGMEM = "msg ";
|
||||
char const UART_CMD_NEXT[] PROGMEM = "next";
|
||||
char const UART_CMD_PREV[] PROGMEM = "prev";
|
||||
char const UART_CMD_RESET[] PROGMEM = "reset";
|
||||
char const UART_CMD_SCROLL[] PROGMEM = "scroll ";
|
||||
char const UART_CMD_TEST[] PROGMEM = "test";
|
||||
|
||||
#ifdef ANIMATION_TESTS
|
||||
char const UART_STR_TEST_EXIT[] PROGMEM = "Press ENTER to exit test."CR;
|
||||
char const UART_STR_TEST_ERR[] PROGMEM = "Range is between 0 and %d."CR;
|
||||
char const UART_STR_GAMETS_ERR[] PROGMEM = "No display tests during games."CR;
|
||||
char const UART_STR_TEST_UP[] PROGMEM = "UP ";
|
||||
char const UART_STR_TEST_DOWN[] PROGMEM = "DOWN ";
|
||||
char const UART_STR_TEST_LEFT[] PROGMEM = "LEFT ";
|
||||
char const UART_STR_TEST_RIGHT[] PROGMEM = "RIGHT ";
|
||||
char const UART_STR_TEST_FIRE[] PROGMEM = "FIRE";
|
||||
|
||||
enum uartcmd_joytest_e {
|
||||
UARTCMD_JOY_UP = 0x01,
|
||||
UARTCMD_JOY_DOWN = 0x02,
|
||||
UARTCMD_JOY_LEFT = 0x04,
|
||||
UARTCMD_JOY_RIGHT = 0x08,
|
||||
UARTCMD_JOY_FIRE = 0x10
|
||||
};
|
||||
|
||||
# ifdef NDEBUG
|
||||
typedef uint8_t uartcmd_joytest_t;
|
||||
# else
|
||||
typedef enum uartcmd_joytest_e uartcmd_joytest_t;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
bool g_uartcmd_permit_processing = 1;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if command processing is allowed.
|
||||
*/
|
||||
static bool uartcmd_processing_allowed(void) {
|
||||
bool result;
|
||||
cli();
|
||||
result = g_uartcmd_permit_processing;
|
||||
sei();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clears the command string buffer.
|
||||
*/
|
||||
static void uartcmd_clear_buffer(void) {
|
||||
char *p = &g_rx_buffer[0];
|
||||
for (uint8_t i = UART_BUFFER_SIZE; i--;) {
|
||||
*p++ = 0;
|
||||
}
|
||||
g_rx_index = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Erases the complete EEPROM to reset counters and high score tables.
|
||||
*/
|
||||
static void uartcmd_erase_eeprom(void) {
|
||||
#if defined(eeprom_update_block) && \
|
||||
((E2PAGESIZE == 2) || (E2PAGESIZE == 4) || (E2PAGESIZE == 8))
|
||||
uint8_t const eeclear[] =
|
||||
# if E2PAGESIZE == 8
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
# elif E2PAGESIZE == 4
|
||||
{0xFF, 0xFF, 0xFF, 0xFF};
|
||||
# elif E2PAGESIZE == 2
|
||||
{0xFF, 0xFF};
|
||||
# endif
|
||||
for (void *ee = 0; ee < (void *)E2END; ee += E2PAGESIZE) {
|
||||
eeprom_busy_wait();
|
||||
eeprom_update_block(eeclear, ee, E2PAGESIZE);
|
||||
}
|
||||
#else
|
||||
UART_PUTS_P(UART_STR_NOTIMPL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays a simple message without the need to prefix a scrolltext command.
|
||||
*/
|
||||
static void uartcmd_simple_message(void) {
|
||||
if (uartcmd_processing_allowed()) {
|
||||
uartcmd_forbid();
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if (waitForFire) {
|
||||
waitForFire = 0;
|
||||
#endif
|
||||
g_rx_buffer[1] = '<';
|
||||
g_rx_buffer[2] = '/';
|
||||
g_rx_buffer[3] = '#';
|
||||
// text must not be longer than the scroll text buffer
|
||||
g_rx_buffer[1 + SCROLLTEXT_BUFFER_SIZE - 1] = 0;
|
||||
scrolltext(&g_rx_buffer[1]);
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
waitForFire = 1;
|
||||
} else {
|
||||
UART_PUTS_P(UART_STR_GAMETX_ERR);
|
||||
}
|
||||
#endif
|
||||
uartcmd_permit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays a message which may use the complete range of scrolltext commands.
|
||||
*/
|
||||
static void uartcmd_scroll_message(void) {
|
||||
if (uartcmd_processing_allowed()) {
|
||||
uartcmd_forbid();
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if (waitForFire) {
|
||||
waitForFire = 0;
|
||||
#endif
|
||||
// text must not be longer than the scroll text buffer
|
||||
g_rx_buffer[7 + SCROLLTEXT_BUFFER_SIZE - 1] = 0;
|
||||
scrolltext(&g_rx_buffer[7]);
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
waitForFire = 1;
|
||||
} else {
|
||||
UART_PUTS_P(UART_STR_GAMETX_ERR);
|
||||
}
|
||||
#endif
|
||||
uartcmd_permit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As long there's no game active, jump to the next animation.
|
||||
*/
|
||||
static void uartcmd_next_anim(void) {
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if (waitForFire) {
|
||||
#endif
|
||||
UART_PUTS_P(UART_STR_PROMPT);
|
||||
uartcmd_clear_buffer();
|
||||
longjmp(newmode_jmpbuf, mode);
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
} else {
|
||||
UART_PUTS_P(UART_STR_GAMEMO_ERR);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As long there's no game active, jump to the previous animation.
|
||||
*/
|
||||
static void uartcmd_prev_anim(void) {
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if (waitForFire) {
|
||||
#endif
|
||||
reverseMode = mode - 2;
|
||||
UART_PUTS_P(UART_STR_PROMPT);
|
||||
uartcmd_clear_buffer();
|
||||
longjmp(newmode_jmpbuf, mode - 2);
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
} else {
|
||||
UART_PUTS_P(UART_STR_GAMEMO_ERR);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts a positive number from an ASCII string (up to INT_MAX).
|
||||
* @param buffer String to be examined. Preceding whitespaces are skipped.
|
||||
* ASCII control characters and [Space] act as delimiters.
|
||||
* @return The extracted number or -1 if a conversion error occurred.
|
||||
*/
|
||||
int uartcmd_extract_num_arg(char *buffer) {
|
||||
int res = -1;
|
||||
uint8_t i = 0;
|
||||
while (buffer[i] <= ' ' && buffer[i] != 0) ++i; // skip whitespaces
|
||||
for (; buffer[i] > 0x20; ++i) {
|
||||
if (res < 0) {
|
||||
res = 0;
|
||||
}
|
||||
int const d = buffer[i] - '0';
|
||||
if (isdigit(buffer[i]) && (res <= (INT_MAX / 10)) &&
|
||||
((res * 10) <= (INT_MAX - d))) {
|
||||
res = res * 10 + d;
|
||||
} else {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs current mode number via UART.
|
||||
*/
|
||||
static void uartcmd_print_mode(void) {
|
||||
char mode_output[6] = "";
|
||||
snprintf_P(mode_output, 6, UART_STR_MODE, mode - 1);
|
||||
uart_puts(mode_output);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves desired mode number from command line and switches to that mode.
|
||||
*/
|
||||
static void uartcmd_mode(void) {
|
||||
if (g_rx_buffer[4] != 0) {
|
||||
int new_mode = uartcmd_extract_num_arg(&g_rx_buffer[4]);
|
||||
if (new_mode <= UINT8_MAX) {
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if (waitForFire) {
|
||||
#endif
|
||||
UART_PUTS_P(UART_STR_PROMPT);
|
||||
uartcmd_clear_buffer();
|
||||
longjmp(newmode_jmpbuf, new_mode);
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
} else {
|
||||
UART_PUTS_P(UART_STR_GAMEMO_ERR);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
UART_PUTS_P(UART_STR_MODE_ERR);
|
||||
}
|
||||
} else {
|
||||
uartcmd_print_mode();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(ANIMATION_TESTS) && defined(JOYSTICK_SUPPORT)
|
||||
/**
|
||||
* Prints current joystick status via UART.
|
||||
*/
|
||||
static void uartcmd_joy_test(uint8_t *last) {
|
||||
uint8_t joy_value = 0;
|
||||
if (JOYISUP) {
|
||||
joy_value |= UARTCMD_JOY_UP;
|
||||
}
|
||||
if (JOYISDOWN) {
|
||||
joy_value |= UARTCMD_JOY_DOWN;
|
||||
}
|
||||
if (JOYISLEFT) {
|
||||
joy_value |= UARTCMD_JOY_LEFT;
|
||||
}
|
||||
if (JOYISRIGHT) {
|
||||
joy_value |= UARTCMD_JOY_RIGHT;
|
||||
}
|
||||
if (JOYISFIRE) {
|
||||
joy_value |= UARTCMD_JOY_FIRE;
|
||||
}
|
||||
|
||||
if (joy_value != *last) {
|
||||
UART_PUTS_P(UART_STR_CLEARLINE);
|
||||
if (joy_value & UARTCMD_JOY_UP) {
|
||||
UART_PUTS_P(UART_STR_TEST_UP);
|
||||
}
|
||||
if (joy_value & UARTCMD_JOY_DOWN) {
|
||||
UART_PUTS_P(UART_STR_TEST_DOWN);
|
||||
}
|
||||
if (joy_value & UARTCMD_JOY_LEFT) {
|
||||
UART_PUTS_P(UART_STR_TEST_LEFT);
|
||||
}
|
||||
if (joy_value & UARTCMD_JOY_RIGHT) {
|
||||
UART_PUTS_P(UART_STR_TEST_RIGHT);
|
||||
}
|
||||
if (joy_value & UARTCMD_JOY_FIRE) {
|
||||
UART_PUTS_P(UART_STR_TEST_FIRE);
|
||||
}
|
||||
*last = joy_value;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Draws test patterns for display inspection.
|
||||
*/
|
||||
static void uartcmd_test(void) {
|
||||
#ifdef ANIMATION_TESTS
|
||||
# ifdef JOYSTICK_SUPPORT
|
||||
if (waitForFire) {
|
||||
waitForFire = 0;
|
||||
# endif
|
||||
uartcmd_forbid();
|
||||
int pattern_no = uartcmd_extract_num_arg(&g_rx_buffer[4]);
|
||||
if (pattern_no >= 0 && pattern_no <= NUMPLANE + 2) {
|
||||
UART_PUTS_P(UART_STR_TEST_EXIT);
|
||||
if (pattern_no <= NUMPLANE) {
|
||||
test_level(pattern_no, true);
|
||||
} else if (pattern_no == (NUMPLANE + 1)) {
|
||||
test_palette(true);
|
||||
} else if (pattern_no == (NUMPLANE + 2)) {
|
||||
test_palette2(true);
|
||||
}
|
||||
# ifdef JOYSTICK_SUPPORT
|
||||
uint8_t last_joy_value = 0;
|
||||
# endif
|
||||
while (UART_GETC() >= 0x20){ // wait for any control character
|
||||
# ifdef JOYSTICK_SUPPORT
|
||||
uartcmd_joy_test(&last_joy_value);
|
||||
wait(20);
|
||||
# endif
|
||||
}
|
||||
} else {
|
||||
char msg[36] = "";
|
||||
snprintf_P(msg, sizeof(msg), UART_STR_TEST_ERR, NUMPLANE + 2);
|
||||
UART_PUTS(msg);
|
||||
}
|
||||
uartcmd_permit();
|
||||
# ifdef JOYSTICK_SUPPORT
|
||||
waitForFire = 1;
|
||||
} else {
|
||||
UART_PUTS_P(UART_STR_GAMETS_ERR);
|
||||
}
|
||||
# endif
|
||||
#else
|
||||
UART_PUTS_P(UART_STR_NOTIMPL);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform a MCU reset by triggering the watchdog.
|
||||
*/
|
||||
static void uartcmd_reset_borg(void) {
|
||||
timer0_off();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Appends new characters the buffer until a line break is entered.
|
||||
* @return true if a line break was entered, false otherwise.
|
||||
*/
|
||||
static bool uartcmd_read_until_enter(void) {
|
||||
static char last_line_break = '\n';
|
||||
|
||||
while (g_rx_index < (UART_BUFFER_SIZE - 1)) {
|
||||
int uart_result = uart_getc();
|
||||
|
||||
if (uart_result < 0x100u) {
|
||||
switch ((char)uart_result) {
|
||||
case '\n': // line feed
|
||||
case '\r': // carriage return
|
||||
if ((g_rx_index > 0) || (uart_result == last_line_break)) {
|
||||
UART_PUTS(CR);
|
||||
g_rx_buffer[g_rx_index++] = 0;
|
||||
last_line_break = uart_result;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case '\b': // BS
|
||||
case '\177': // DEL
|
||||
if (g_rx_index != 0) {
|
||||
g_rx_buffer[--g_rx_index] = 0;
|
||||
UART_PUTS_P(UART_STR_BACKSPACE);
|
||||
}
|
||||
break;
|
||||
case '\f': // Form Feed (Ctrl-L), reprints the line buffer
|
||||
UART_PUTS_P(UART_STR_CLEARLINE); // clear current line
|
||||
UART_PUTS_P(UART_STR_PROMPT); // output prompt
|
||||
g_rx_buffer[g_rx_index] = 0; // terminate input buffer
|
||||
UART_PUTS(g_rx_buffer); // finally reprint it
|
||||
break;
|
||||
case 21: // NAK (Ctrl-U), clears the line buffer
|
||||
UART_PUTS_P(UART_STR_CLEARLINE); // clear current line
|
||||
UART_PUTS_P(UART_STR_PROMPT); // output prompt
|
||||
uartcmd_clear_buffer(); // clear buffer
|
||||
break;
|
||||
case 27: // ignore Esc
|
||||
break;
|
||||
default:
|
||||
// We don't accept control characters which are not handled
|
||||
// above. We also limit the input to 7 bit ASCII.
|
||||
if ((uart_result < 0x20) || (uart_result > 0x7f)) {
|
||||
UART_PUTC('\a'); // complain via ASCII bell
|
||||
} else {
|
||||
g_rx_buffer[g_rx_index++] = uart_result; // accept input
|
||||
UART_PUTC(uart_result); // echo input back to terminal
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else if ((uart_result & 0xFF00u) != UART_NO_DATA) {
|
||||
uartcmd_clear_buffer();
|
||||
UART_PUTS_P(UART_STR_UART_ERR);
|
||||
UART_PUTS_P(UART_STR_PROMPT);
|
||||
break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_rx_index >= (UART_BUFFER_SIZE - 1)) {
|
||||
uartcmd_clear_buffer();
|
||||
UART_PUTS_P(UART_STR_TOOLONG);
|
||||
UART_PUTS_P(UART_STR_PROMPT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks for entered commands and dispatches them to the appropriate handler.
|
||||
*/
|
||||
void uartcmd_process(void) {
|
||||
if (uartcmd_processing_allowed() && uartcmd_read_until_enter()) {
|
||||
if (!strncmp_P(g_rx_buffer, UART_CMD_ERASE, UART_BUFFER_SIZE)) {
|
||||
uartcmd_erase_eeprom();
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_HELP, UART_BUFFER_SIZE)) {
|
||||
UART_PUTS_P(UART_STR_HELP);
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_MODE, 4)) {
|
||||
uartcmd_mode();
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_MSG, 4)) {
|
||||
uartcmd_simple_message();
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_NEXT, UART_BUFFER_SIZE)) {
|
||||
uartcmd_next_anim();
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_PREV, UART_BUFFER_SIZE)) {
|
||||
uartcmd_prev_anim();
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_RESET, UART_BUFFER_SIZE)) {
|
||||
uartcmd_reset_borg();
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_SCROLL, 7)) {
|
||||
uartcmd_scroll_message();
|
||||
} else if (!strncmp_P(g_rx_buffer, UART_CMD_TEST, 4)) {
|
||||
uartcmd_test();
|
||||
} else if (g_rx_buffer[0] != 0) {
|
||||
UART_PUTS_P(UART_STR_UNKNOWN);
|
||||
}
|
||||
UART_PUTS_P(UART_STR_PROMPT);
|
||||
uartcmd_clear_buffer();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* uart_commands.h
|
||||
*
|
||||
* Created on: 16.08.2014
|
||||
* Author: chris
|
||||
*/
|
||||
|
||||
#ifndef UART_COMMANDS_H_
|
||||
#define UART_COMMANDS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
extern bool g_uartcmd_permit_processing;
|
||||
|
||||
/**
|
||||
* Enables UART command processing.
|
||||
*/
|
||||
inline static void uartcmd_permit(void) {
|
||||
cli();
|
||||
g_uartcmd_permit_processing = true;
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disables UART command processing.
|
||||
*/
|
||||
inline static void uartcmd_forbid(void) {
|
||||
cli();
|
||||
g_uartcmd_permit_processing = false;
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
void uartcmd_process(void);
|
||||
|
||||
#endif /* UART_COMMANDS_H_ */
|
|
@ -19,6 +19,9 @@ extern jmp_buf newmode_jmpbuf;
|
|||
# include "can/borg_can.h"
|
||||
#endif
|
||||
|
||||
#ifdef UART_SUPPORT
|
||||
# include "uart/uart_commands.h"
|
||||
#endif
|
||||
|
||||
void wait(int ms){
|
||||
/* Always use Timer1 except for the Arduino/LoL Shield platform. */
|
||||
|
@ -41,6 +44,10 @@ void wait(int ms){
|
|||
bcan_process_messages();
|
||||
#endif
|
||||
|
||||
#ifdef UART_SUPPORT
|
||||
uartcmd_process();
|
||||
#endif
|
||||
|
||||
#ifdef RFM12_SUPPORT
|
||||
borg_rfm12_tick();
|
||||
#endif
|
||||
|
@ -50,7 +57,7 @@ void wait(int ms){
|
|||
//PORTJOYGND &= ~(1<<BITJOY0);
|
||||
//PORTJOYGND &= ~(1<<BITJOY1);
|
||||
if (JOYISFIRE) {
|
||||
longjmp(newmode_jmpbuf, 43);
|
||||
longjmp(newmode_jmpbuf, 0xFEu);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue