Compare commits

..

43 Commits

Author SHA1 Message Date
Christian Kroll 4642f779f9 uart_commands.c: added joytick test 2014-10-06 23:49:08 +02:00
Christian Kroll c9ffc868dc borg_gw_borg16.c: trigger watchdog 134 times per sec. (instead of 6465) 2014-10-06 19:48:15 +02:00
Christian Kroll fa3c01d0c2 borg_hw_borg16.c: some uncluttering 2014-10-06 00:14:30 +02:00
Christian Kroll 47d9b5e548 borg_hw_borg16.c: slightly higher contrast for Borg16 (optional) 2014-10-05 04:37:55 +02:00
Christian Kroll 850e92f766 uart_commands.c etc.: added test command for matrix overhaul 2014-10-05 04:06:01 +02:00
Christian Kroll edda250312 uart_commands.c: removed stray character 2014-10-02 01:31:20 +02:00
Christian Kroll 496f6a9ced uart_commands.c: allow for complete line removal via Ctrl-U 2014-09-28 05:13:25 +02:00
Christian Kroll 45ba07b9d7 uart_commands.c: fixed UART1 ouput, added line reprint via Ctrl-L 2014-09-28 04:27:05 +02:00
Christian Kroll 877bebd41a uart.c: save resources if UART1 isn't used 2014-09-28 00:45:04 +02:00
Christian Kroll 43f4fc9b2c uart_commands.c: typo in error message corrected 2014-09-26 03:28:51 +02:00
Christian Kroll 656ec1c5c3 uart_commands.c: nicer backspace 2014-09-26 00:53:09 +02:00
Christian Kroll 1e99121751 uart_commands.c: sanitizing input even more 2014-09-26 00:14:38 +02:00
Christian Kroll ecec6bae36 uart_commands.c: small cleanups 2014-09-24 02:46:29 +02:00
Christian Kroll f48994b222 uart_commands.c: no more text inception 2014-09-16 23:34:53 +02:00
Christian Kroll 0d69c2d209 added UART support for the LoL Shield (except for Arduino Leonardo) 2014-09-14 18:37:50 +02:00
Christian Kroll 469ac61fa5 Merge remote-tracking branch 'origin/openbsd_port' 2014-09-08 01:45:03 +02:00
Christian Kroll 5ca1b807f4 provide Snake POV control option in Menuconfig 2014-09-08 00:35:12 +02:00
Christian Kroll bf6b2d95dd tetris/input.c: taking more countermeasures against joystick chatter 2014-09-07 23:46:51 +02:00
Christian Kroll d5d58f8c0d add eeprom_busy_wait() to some routines; better safe than sorry 2014-09-07 21:32:49 +02:00
Christian Kroll 7d0022a22d persistentCounter.c etc.: made the persistent counter more versatile, it
is not limited to hard reset counts anymore
2014-09-07 21:06:25 +02:00
Christian Kroll 967ab9a05e snake_game.c: resolved bug where the head gets bitten by itself 2014-09-04 02:15:30 +02:00
Christian Kroll 126c1d0c44 invader_init.c: better playability of level 4 2014-09-04 02:14:13 +02:00
Christian Kroll 09d7d80674 uart_commands.c: improved UART error handling 2014-08-31 23:31:42 +02:00
Christian Kroll 82c44aec65 uart_commands: no text messages during games 2014-08-31 22:45:33 +02:00
Christian Kroll 937d9da592 uart_commands.c etc.: added mode change command 2014-08-28 03:07:37 +02:00
Christian Kroll 09ce8f22b3 display_loop.c, uart_commands.c: more reliable "prev" command 2014-08-27 05:08:39 +02:00
Christian Kroll b9471a6637 uart_commands.c: Backspace/Delete capability 2014-08-27 04:26:30 +02:00
Christian Kroll cc060261d4 scrolltext3.c: small optimization 2014-08-27 00:08:37 +02:00
Christian Kroll 5ad9905dee fancier CTDO scrolltext 2014-08-24 12:45:34 +02:00
Christian Kroll bec7a9edff uart_commands.(ch): small refinements, added "erase" command for EEPROM 2014-08-19 11:01:52 +02:00
Christian Kroll 7937f86137 disable mode change during games 2014-08-17 00:03:54 +02:00
Christian Kroll 6c1b652d46 Amphibian instead of Labor logo in the CTDO profile 2014-08-16 07:56:20 +02:00
Christian Kroll a53a78ea3b oops 2014-08-16 07:27:19 +02:00
Christian Kroll fca9b8f07a UART support for Borg16; using Peter Fleury's UART library 2014-08-16 07:01:07 +02:00
Christian Kroll c6fde40211 kart.c: removed warning 2014-08-16 06:57:34 +02:00
Stefan Kinzel 6057b6e3e8 DNA: corrected uint8_t-error 2014-08-15 00:47:24 +02:00
Stefan Kinzel 95bd1ba238 some more bugfixes for the DNA-animation 2014-08-15 00:30:46 +02:00
Stefan Kinzel b435b52217 some bugfixes for the DNA-animation 2014-08-14 23:46:45 +02:00
Christian Kroll 306ad40288 moved dna anim within display loop 2014-08-14 22:45:34 +02:00
Stefan Kinzel da9d0adc57 first version of the DNA-Animation 2014-08-14 22:35:03 +02:00
Christian Kroll 1dff4f3885 fpmath_patterns.c: fixed some bugs which made the higher precision mode
unusable; animations look slightly different, now
2014-08-10 06:29:01 +02:00
Christian Kroll 3a5052900d tetris view.c: fixed counter offset of oversize displays 2014-07-16 00:10:58 +02:00
Christian Kroll 2919187ae1 OpenBSD support (only amd64 verfified) 2014-07-13 07:22:05 +02:00
47 changed files with 2624 additions and 671 deletions

View File

@ -8,17 +8,21 @@ comment "General Setup"
choice 'Target MCU' \ choice 'Target MCU' \
"ATmega8 atmega8 \ "ATmega8 atmega8 \
ATmega16 atmega16 \ ATmega16 atmega16 \
ATmega164 atmega164 \
ATmega164P atmega164p \
ATmega168 atmega168 \ ATmega168 atmega168 \
ATmega168P atmega168p \ ATmega168P atmega168p \
ATmega32 atmega32 \ ATmega32 atmega32 \
ATmega324 atmega324 \
ATmega324P atmega324p \
ATmega32U4 atmega32u4 \ ATmega32U4 atmega32u4 \
ATmega328 atmega328 \ ATmega328 atmega328 \
ATmega328p atmega328p \ ATmega328P atmega328p \
ATmega644 atmega644 \ ATmega644 atmega644 \
ATmega644p atmega644p \ ATmega644P atmega644p \
ATmega1280 atmega1280 \ ATmega1280 atmega1280 \
ATmega1284 atmega1284 \ ATmega1284 atmega1284 \
ATmega1284p atmega1284p \ ATmega1284P atmega1284p \
ATmega2560 atmega2560 \ ATmega2560 atmega2560 \
ATmega8515 atmega8515" \ ATmega8515 atmega8515" \
'ATmega32' MCU 'ATmega32' MCU
@ -62,9 +66,13 @@ source src/can/config.in
############################################################################### ###############################################################################
### UART Menu #################################################################
source src/uart/config.in
###############################################################################
### Borg Menu ################################################################# ### Borg Menu #################################################################
dep_bool "Menu Support" MENU_SUPPORT $JOYSTICK_SUPPORT dep_bool "Menu Support" MENU_SUPPORT $JOYSTICK_SUPPORT
depends on JOYSTICK_SUPPORT
############################################################################### ###############################################################################

View File

@ -75,6 +75,20 @@ else
endif endif
endif endif
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm 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 else
ifeq ($(OSTYPE),Linux) ifeq ($(OSTYPE),Linux)
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_XOPEN_SOURCE=600 CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_XOPEN_SOURCE=600
@ -99,6 +113,8 @@ Currently supported platforms:$(n) \
endif endif
endif endif
endif endif
endif
############################################################################## ##############################################################################
# the default target # the default target
$(TARGET): $(TARGET):
@ -116,8 +132,8 @@ $(MAKETOPDIR)/config.mk:
@echo "#" >>$@ @echo "#" >>$@
@echo "# Other flags you might want to tune: CPPFLAGS, LDFLAGS ..." >>$@ @echo "# Other flags you might want to tune: CPPFLAGS, LDFLAGS ..." >>$@
@echo "Created default config.mk, tune your settings there!" @echo "Created default config.mk, tune your settings there!"
-include $(MAKETOPDIR)/config.mk
-include $(MAKETOPDIR)/config.mk
############################################################################## ##############################################################################
# configure load address for bootloader, if enabled # configure load address for bootloader, if enabled
@ -125,9 +141,7 @@ $(MAKETOPDIR)/config.mk:
ifneq ($(MAKECMDGOALS),clean) ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),mrproper) ifneq ($(MAKECMDGOALS),mrproper)
ifneq ($(MAKECMDGOALS),menuconfig) ifneq ($(MAKECMDGOALS),menuconfig)
include $(MAKETOPDIR)/.config include $(MAKETOPDIR)/.config
CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU) CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU)
# flags for the linker, choose appropriate linker script # 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) LDFLAGS += -T ld_scripts/avr5.x -Wl,-Map,image.map -mmcu=$(MCU)
endif endif
endif endif
endif # MAKECMDGOALS!=menuconfig endif # MAKECMDGOALS!=menuconfig
endif # MAKECMDGOALS!=mrproper endif # MAKECMDGOALS!=mrproper
endif # MAKECMDGOALS!=clean endif # MAKECMDGOALS!=clean

193
ld_scripts/elf_i386_obsd.xd Normal file
View File

@ -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) }
}

View File

@ -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) }
}

164
profiles/CTDO-Borg Normal file
View File

@ -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

View File

@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
# lolshield setup # lolshield setup
# #
USER_TIMER0_FOR_WAIT=1 USER_TIMER0_FOR_WAIT=1
BRIGHTNESS=127 LOLSHIELD=y
BRIGHTNESS=120
FRAMERATE=80 FRAMERATE=80
# UART_SUPPORT is not set
UART_BAUDRATE_SETTING=19200
# #
# Features # Features
@ -54,7 +57,10 @@ GAME_TETRIS=y
# GAME_TETRIS_FP is not set # GAME_TETRIS_FP is not set
# GAME_SPACE_INVADERS is not set # GAME_SPACE_INVADERS is not set
GAME_SNAKE=y GAME_SNAKE=y
# SNAKE_POV_CONTROL is not set
SNAKE_GAME_DELAY=200
GAME_BREAKOUT=y GAME_BREAKOUT=y
# GAME_KART is not set
# #
# Animations # Animations
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
SPIRAL_DELAY=5 SPIRAL_DELAY=5
ANIMATION_JOERN1=y ANIMATION_JOERN1=y
ANIMATION_SNAKE=y ANIMATION_SNAKE=y
SNAKE_GAME_DELAY=200
SNAKE_ANIM_DELAY=100 SNAKE_ANIM_DELAY=100
SNAKE_TERMINATION_DELAY=60 SNAKE_TERMINATION_DELAY=60
SNAKE_MAX_LENGTH=64 SNAKE_MAX_LENGTH=64
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
ANIMATION_PSYCHEDELIC=y ANIMATION_PSYCHEDELIC=y
FP_PSYCHO_DELAY=25 FP_PSYCHO_DELAY=25
# ANIMATION_BLACKHOLE is not set # ANIMATION_BLACKHOLE is not set
# ANIMATION_DNA is not set
ANIMATION_SQUARES=y ANIMATION_SQUARES=y
# ANIMATION_TESTS is not set # ANIMATION_TESTS is not set
# ANIMATION_OFF is not set # ANIMATION_OFF is not set

View File

@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
# lolshield setup # lolshield setup
# #
USER_TIMER0_FOR_WAIT=1 USER_TIMER0_FOR_WAIT=1
BRIGHTNESS=127 LOLSHIELD=y
BRIGHTNESS=120
FRAMERATE=80 FRAMERATE=80
# UART_SUPPORT is not set
UART_BAUDRATE_SETTING=19200
# #
# Features # Features
@ -54,7 +57,10 @@ GAME_BASTET=y
# GAME_TETRIS_FP is not set # GAME_TETRIS_FP is not set
GAME_SPACE_INVADERS=y GAME_SPACE_INVADERS=y
GAME_SNAKE=y GAME_SNAKE=y
# SNAKE_POV_CONTROL is not set
SNAKE_GAME_DELAY=200
GAME_BREAKOUT=y GAME_BREAKOUT=y
# GAME_KART is not set
# #
# Animations # Animations
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
SPIRAL_DELAY=5 SPIRAL_DELAY=5
ANIMATION_JOERN1=y ANIMATION_JOERN1=y
ANIMATION_SNAKE=y ANIMATION_SNAKE=y
SNAKE_GAME_DELAY=200
SNAKE_ANIM_DELAY=100 SNAKE_ANIM_DELAY=100
SNAKE_TERMINATION_DELAY=60 SNAKE_TERMINATION_DELAY=60
SNAKE_MAX_LENGTH=64 SNAKE_MAX_LENGTH=64
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
ANIMATION_PSYCHEDELIC=y ANIMATION_PSYCHEDELIC=y
FP_PSYCHO_DELAY=25 FP_PSYCHO_DELAY=25
ANIMATION_BLACKHOLE=y ANIMATION_BLACKHOLE=y
# ANIMATION_DNA is not set
ANIMATION_SQUARES=y ANIMATION_SQUARES=y
ANIMATION_TESTS=y ANIMATION_TESTS=y
ANIMATION_OFF=y ANIMATION_OFF=y

View File

@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
# lolshield setup # lolshield setup
# #
USER_TIMER0_FOR_WAIT=1 USER_TIMER0_FOR_WAIT=1
BRIGHTNESS=127 LOLSHIELD=y
BRIGHTNESS=120
FRAMERATE=80 FRAMERATE=80
# UART_SUPPORT is not set
UART_BAUDRATE_SETTING=19200
# #
# Features # Features
@ -54,7 +57,10 @@ GAME_BASTET=y
# GAME_TETRIS_FP is not set # GAME_TETRIS_FP is not set
GAME_SPACE_INVADERS=y GAME_SPACE_INVADERS=y
GAME_SNAKE=y GAME_SNAKE=y
# SNAKE_POV_CONTROL is not set
SNAKE_GAME_DELAY=200
GAME_BREAKOUT=y GAME_BREAKOUT=y
# GAME_KART is not set
# #
# Animations # Animations
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
SPIRAL_DELAY=5 SPIRAL_DELAY=5
ANIMATION_JOERN1=y ANIMATION_JOERN1=y
ANIMATION_SNAKE=y ANIMATION_SNAKE=y
SNAKE_GAME_DELAY=200
SNAKE_ANIM_DELAY=100 SNAKE_ANIM_DELAY=100
SNAKE_TERMINATION_DELAY=60 SNAKE_TERMINATION_DELAY=60
SNAKE_MAX_LENGTH=64 SNAKE_MAX_LENGTH=64
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
ANIMATION_PSYCHEDELIC=y ANIMATION_PSYCHEDELIC=y
FP_PSYCHO_DELAY=25 FP_PSYCHO_DELAY=25
ANIMATION_BLACKHOLE=y ANIMATION_BLACKHOLE=y
# ANIMATION_DNA is not set
ANIMATION_SQUARES=y ANIMATION_SQUARES=y
ANIMATION_TESTS=y ANIMATION_TESTS=y
ANIMATION_OFF=y ANIMATION_OFF=y

View File

@ -20,8 +20,11 @@ BORG_HW=HW_LOLSHIELD
# lolshield setup # lolshield setup
# #
USER_TIMER0_FOR_WAIT=1 USER_TIMER0_FOR_WAIT=1
BRIGHTNESS=127 LOLSHIELD=y
BRIGHTNESS=120
FRAMERATE=80 FRAMERATE=80
# UART_SUPPORT is not set
UART_BAUDRATE_SETTING=19200
# #
# Features # Features
@ -54,7 +57,10 @@ GAME_TETRIS=y
# GAME_TETRIS_FP is not set # GAME_TETRIS_FP is not set
# GAME_SPACE_INVADERS is not set # GAME_SPACE_INVADERS is not set
GAME_SNAKE=y GAME_SNAKE=y
# SNAKE_POV_CONTROL is not set
SNAKE_GAME_DELAY=200
GAME_BREAKOUT=y GAME_BREAKOUT=y
# GAME_KART is not set
# #
# Animations # Animations
@ -64,7 +70,6 @@ ANIMATION_SPIRAL=y
SPIRAL_DELAY=5 SPIRAL_DELAY=5
ANIMATION_JOERN1=y ANIMATION_JOERN1=y
ANIMATION_SNAKE=y ANIMATION_SNAKE=y
SNAKE_GAME_DELAY=200
SNAKE_ANIM_DELAY=100 SNAKE_ANIM_DELAY=100
SNAKE_TERMINATION_DELAY=60 SNAKE_TERMINATION_DELAY=60
SNAKE_MAX_LENGTH=64 SNAKE_MAX_LENGTH=64
@ -107,6 +112,7 @@ FP_PLASMA_DELAY=10
ANIMATION_PSYCHEDELIC=y ANIMATION_PSYCHEDELIC=y
FP_PSYCHO_DELAY=25 FP_PSYCHO_DELAY=25
ANIMATION_BLACKHOLE=y ANIMATION_BLACKHOLE=y
# ANIMATION_DNA is not set
ANIMATION_SQUARES=y ANIMATION_SQUARES=y
# ANIMATION_TESTS is not set # ANIMATION_TESTS is not set
# ANIMATION_OFF is not set # ANIMATION_OFF is not set

View File

@ -58,6 +58,11 @@ ifeq ($(ANIMATION_TIME),y)
SRC += borg_time.c SRC += borg_time.c
endif endif
ifeq ($(ANIMATION_DNA),y)
SRC += dna.c
endif
include $(MAKETOPDIR)/rules.mk include $(MAKETOPDIR)/rules.mk
include $(MAKETOPDIR)/depend.mk include $(MAKETOPDIR)/depend.mk

View File

@ -22,10 +22,6 @@ ifeq ($(ANIMATION_FAIRYDUST),y)
SRC += fairydust.c SRC += fairydust.c
endif endif
ifeq ($(ANIMATION_THISISNOTDETROIT),y)
SRC += thisisnotdetroit.c
endif
include $(MAKETOPDIR)/rules.mk include $(MAKETOPDIR)/rules.mk
include $(MAKETOPDIR)/depend.mk include $(MAKETOPDIR)/depend.mk

View File

@ -3,5 +3,4 @@ dep_bool_menu "Bitmap Scroller" ANIMATION_BMSCROLLER y $RANDOM_SUPPORT
dep_bool "Amphibian" ANIMATION_AMPHIBIAN $ANIMATION_BMSCROLLER dep_bool "Amphibian" ANIMATION_AMPHIBIAN $ANIMATION_BMSCROLLER
dep_bool "Out of Spec Logo" ANIMATION_LOGO_OOS $ANIMATION_BMSCROLLER dep_bool "Out of Spec Logo" ANIMATION_LOGO_OOS $ANIMATION_BMSCROLLER
dep_bool "Fairydust" ANIMATION_FAIRYDUST $ANIMATION_BMSCROLLER dep_bool "Fairydust" ANIMATION_FAIRYDUST $ANIMATION_BMSCROLLER
dep_bool "This is not Detroit" ANIMATION_THISISNOTDETROIT $ANIMATION_BMSCROLLER
endmenu endmenu

View File

@ -1,141 +0,0 @@
#include <stdint.h>
#include <assert.h>
#include "../../compat/pgmspace.h"
#include "bitmapscroller.h"
#include "thisisnotdetroit.h"
static uint8_t const athisIsNotDetroitBitmap[2][55][8] PROGMEM =
{{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x80},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x60},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x20, 0x64},
{0x00, 0x00, 0x00, 0x01, 0x01, 0x18, 0x03, 0x24},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0xe1, 0xd4},
{0x00, 0x00, 0x00, 0x00, 0x01, 0x5f, 0xeb, 0x22},
{0x00, 0x00, 0x00, 0x01, 0x11, 0xfe, 0x10, 0x00},
{0x00, 0x00, 0x06, 0x8f, 0xa5, 0x18, 0x00, 0x00},
{0x00, 0x00, 0x3f, 0xf0, 0xc0, 0x00, 0x00, 0x01},
{0x01, 0x82, 0x7f, 0xfa, 0x00, 0x00, 0x00, 0x00},
{0x03, 0xff, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00},
{0x0f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x1f, 0xf6, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00},
{0x09, 0xc0, 0x00, 0x37, 0xc0, 0x00, 0x00, 0x00},
{0x38, 0x00, 0x0a, 0xe7, 0x40, 0x00, 0x00, 0x00},
{0x38, 0x01, 0xce, 0xff, 0x00, 0x00, 0x00, 0x00},
{0x3c, 0xbe, 0xce, 0xf7, 0xc0, 0x00, 0x00, 0x00},
{0x3c, 0xfd, 0xce, 0xf3, 0xe0, 0x00, 0x00, 0x00},
{0x1c, 0xf8, 0xfe, 0xf0, 0x60, 0x00, 0x00, 0x00},
{0x04, 0x70, 0xfe, 0xf2, 0xe0, 0x00, 0x00, 0x00},
{0x00, 0x70, 0xee, 0xff, 0xe0, 0x00, 0x00, 0x00},
{0x00, 0x70, 0xce, 0xf0, 0x80, 0x06, 0xc0, 0x00},
{0x00, 0x71, 0xce, 0x60, 0x02, 0x1f, 0x80, 0x00},
{0x00, 0x71, 0xc0, 0x00, 0x1f, 0xdf, 0x40, 0x00},
{0x00, 0x70, 0x00, 0x03, 0xbf, 0xd6, 0x00, 0x00},
{0x00, 0x00, 0x00, 0xf3, 0x3d, 0xc6, 0x00, 0x00},
{0x00, 0x01, 0x40, 0xfb, 0xf1, 0xe6, 0x00, 0x00},
{0x00, 0x21, 0xf0, 0xfb, 0xb8, 0xc6, 0x00, 0x00},
{0x00, 0x77, 0x80, 0xfb, 0xf0, 0xe6, 0x00, 0x00},
{0x00, 0x73, 0x80, 0xef, 0xbf, 0xc6, 0x00, 0x00},
{0x00, 0x77, 0xe0, 0xef, 0xbf, 0x84, 0x00, 0x0c},
{0x00, 0x71, 0xf0, 0xef, 0x8e, 0x00, 0x00, 0xf8},
{0x00, 0x70, 0x70, 0xe7, 0x80, 0x00, 0x1b, 0xfc},
{0x00, 0x73, 0xf0, 0xc0, 0x00, 0x0f, 0x1b, 0xf0},
{0x00, 0x73, 0xe0, 0x00, 0x0c, 0x3f, 0x98, 0xf0},
{0x00, 0x70, 0x40, 0x03, 0x7f, 0x7b, 0x98, 0xf0},
{0x00, 0x60, 0x00, 0x5f, 0x7e, 0x73, 0xd8, 0xf0},
{0x00, 0x00, 0x1f, 0x7f, 0x67, 0xf1, 0xd8, 0xf0},
{0x00, 0x0e, 0x1f, 0x7c, 0x77, 0xe3, 0x98, 0xf0},
{0x00, 0x3f, 0x1e, 0x1c, 0x7c, 0xf7, 0x9c, 0xe0},
{0x00, 0x7f, 0xdb, 0x1c, 0x6e, 0x7f, 0x1c, 0x00},
{0x00, 0x71, 0xdf, 0x1c, 0x7f, 0x3f, 0x00, 0x00},
{0x00, 0x71, 0xdb, 0x1c, 0x67, 0x80, 0x00, 0x00},
{0x00, 0x71, 0xdd, 0x1c, 0x50, 0x00, 0x00, 0x00},
{0x00, 0x73, 0xdf, 0x18, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x7f, 0x1f, 0x80, 0x00, 0x00, 0xfc, 0x00},
{0x00, 0x7e, 0x10, 0x00, 0x00, 0x7f, 0xf0, 0x00},
{0x00, 0x68, 0x00, 0x00, 0x2f, 0xff, 0x90, 0x00},
{0x00, 0x00, 0x00, 0x03, 0xfe, 0xa3, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x1f, 0xfd, 0x00, 0x00, 0x00},
{0x00, 0x3c, 0x00, 0x0f, 0xa0, 0x00, 0x00, 0x00},
{0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x60},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x08},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x80, 0x2a},
{0x00, 0x00, 0x00, 0x02, 0x40, 0x3f, 0xf0, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0xc0, 0x00},
{0x00, 0x00, 0x01, 0x41, 0xd7, 0xe0, 0x00, 0x02},
{0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x00},
{0x00, 0x7d, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00},
{0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00},
{0x1f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x0f, 0xf8, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00},
{0x3e, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x00},
{0x38, 0x00, 0x06, 0x77, 0xc0, 0x00, 0x00, 0x00},
{0x18, 0x00, 0xce, 0x66, 0x00, 0x00, 0x00, 0x00},
{0x18, 0x7d, 0xce, 0x67, 0xc0, 0x00, 0x00, 0x00},
{0x1d, 0xfd, 0xce, 0x67, 0xe0, 0x00, 0x00, 0x00},
{0x0d, 0xf1, 0xfe, 0x60, 0xe0, 0x00, 0x00, 0x00},
{0x0c, 0x31, 0xfe, 0x67, 0xe0, 0x00, 0x00, 0x00},
{0x00, 0x31, 0xce, 0x67, 0xc0, 0x00, 0x00, 0x00},
{0x00, 0x31, 0xce, 0x67, 0x00, 0x01, 0xc0, 0x00},
{0x00, 0x31, 0xce, 0x00, 0x00, 0x1f, 0xc0, 0x00},
{0x00, 0x31, 0xc0, 0x00, 0x0f, 0x9f, 0x80, 0x00},
{0x00, 0x30, 0x00, 0x03, 0x1f, 0xc7, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x73, 0xb9, 0xe7, 0x00, 0x00},
{0x00, 0x00, 0xe0, 0x73, 0x38, 0xe7, 0x00, 0x00},
{0x00, 0x13, 0xe0, 0x7b, 0x70, 0xe7, 0x00, 0x00},
{0x00, 0x33, 0xe0, 0x7f, 0x39, 0xc7, 0x00, 0x00},
{0x00, 0x37, 0x00, 0x7f, 0x3f, 0xc7, 0x00, 0x00},
{0x00, 0x33, 0xe0, 0x6f, 0x3f, 0x80, 0x00, 0x00},
{0x00, 0x33, 0xf0, 0x67, 0x1f, 0x00, 0x01, 0xfc},
{0x00, 0x30, 0x70, 0x67, 0x00, 0x00, 0x1d, 0xf8},
{0x00, 0x33, 0xf0, 0x60, 0x00, 0x1f, 0x1d, 0xe0},
{0x00, 0x37, 0xe0, 0x00, 0x00, 0x3f, 0x9c, 0x60},
{0x00, 0x33, 0x80, 0x00, 0x7e, 0x7f, 0xdc, 0x60},
{0x00, 0x00, 0x00, 0x3f, 0x7f, 0x71, 0xdc, 0x60},
{0x00, 0x00, 0x0f, 0x7f, 0x77, 0x61, 0xdc, 0x60},
{0x00, 0x00, 0x1f, 0x7c, 0x7e, 0x71, 0xdc, 0x60},
{0x00, 0x3f, 0x9c, 0x1c, 0x7e, 0x7b, 0x98, 0x60},
{0x00, 0x3f, 0x9f, 0x1c, 0x7e, 0x7f, 0x98, 0x00},
{0x00, 0x33, 0xdf, 0x1c, 0x67, 0x3e, 0x00, 0x00},
{0x00, 0x31, 0xdc, 0x1c, 0x77, 0x00, 0x00, 0x00},
{0x00, 0x31, 0xdb, 0x9c, 0x60, 0x00, 0x00, 0x00},
{0x00, 0x33, 0x9f, 0x9c, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x3f, 0x9f, 0x00, 0x00, 0x01, 0xf8, 0x00},
{0x00, 0x3f, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00},
{0x00, 0x30, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00},
{0x00, 0x00, 0x00, 0x0f, 0xff, 0x5c, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00},
{0x00, 0x1e, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}};
static uint8_t logo_thisIsNotDetroit_getChunk(unsigned char const nBitPlane,
unsigned char const nChunkX,
unsigned char const nChunkY,
unsigned int const nFrame)
{
assert(nBitPlane < 2);
assert(nChunkX < 8);
assert(nChunkY < 55);
return pgm_read_byte(&athisIsNotDetroitBitmap[nBitPlane][nChunkY][nChunkX]);
}
void logo_thisIsNotDetroit()
{
// width 64, height 55, 2 bitplanes (4 colors), 600 frames à 75ms
// frame change and viewport movement after every cyle (both dividers are 1)
bitmap_scroll(64, 55, 2, 600, 75, 1, 1, logo_thisIsNotDetroit_getChunk);
}

View File

@ -1,6 +0,0 @@
#ifndef THISISNOTDETROIT_H_
#define THISISNOTDETROIT_H_
void logo_thisIsNotDetroit();
#endif /* THISISNOTDETROIT_H_ */

View File

@ -9,7 +9,6 @@ comment "Animations"
bool "Joern1" ANIMATION_JOERN1 bool "Joern1" ANIMATION_JOERN1
dep_bool_menu "Snake" ANIMATION_SNAKE $RANDOM_SUPPORT 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 Anim Round Delay" SNAKE_ANIM_DELAY 100
int "Snake Termination Delay" SNAKE_TERMINATION_DELAY 60 int "Snake Termination Delay" SNAKE_TERMINATION_DELAY 60
uint "Snake Max Length" SNAKE_MAX_LENGTH 64 uint "Snake Max Length" SNAKE_MAX_LENGTH 64
@ -64,6 +63,8 @@ comment "Animations"
bool "Black Hole" ANIMATION_BLACKHOLE bool "Black Hole" ANIMATION_BLACKHOLE
bool "DNA" ANIMATION_DNA $RANDOM_SUPPORT
dep_bool "Squares" ANIMATION_SQUARES $RANDOM_SUPPORT dep_bool "Squares" ANIMATION_SQUARES $RANDOM_SUPPORT
comment "Special Animations" comment "Special Animations"

114
src/animations/dna.c Normal file
View File

@ -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();
}
}

13
src/animations/dna.h Normal file
View File

@ -0,0 +1,13 @@
/*
* dna.h
*
* Created on: 15.07.2014
* Author: stefan
*/
#ifndef DNA_H_
#define DNA_H_
void dna();
#endif /* DNA_H_ */

View File

@ -20,18 +20,20 @@
#ifdef DOXYGEN #ifdef DOXYGEN
/** /**
* Low precision means that we use Q10.5 values and 16 bit types for almost * Low precision means that we use Q9.6 values and 16 bit types for almost
* every calculation (with multiplication and division as notable exceptions * every calculation (with multiplication being a notable exception as its
* as they and their interim results utilize 32 bit). * interim results utilize 32 bit types).
* *
* Use this precision mode with care as image quality will suffer * Use this precision mode with care as image quality will suffer noticeably
* noticeably. It produces leaner and faster code, though. This mode should * at higher resolutions. This mode should not be used with resolutions
* not be used with resolutions higher than 16x16 as overflows are likely to * higher than 16x16 as overflows are likely to occur in interim
* occur in interim calculations. * calculations. It produces leaner and faster code, though.
* *
* Normal precision (i.e. #undef LOW_PRECISION) conforms to Q7.8 with the * Normal precision (i.e. #undef LOW_PRECISION) conforms to Q23.8 for actual
* ability to store every interim result as Q23.8. Most operations like * values and interim results. Operations like square root, sine, cosine,
* square root, sine, cosine, multiplication etc. utilize 32 bit types. * 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 #define FP_LOW_PRECISION
#endif /* DOXYGEN */ #endif /* DOXYGEN */
@ -66,18 +68,18 @@
// lookup table as well! // lookup table as well!
/** Multiply a number by this factor to convert it to a fixed-point value.*/ /** 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))). */ /** 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 * 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 * 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 * 4 itself. Approximate this value as close as possible to keep rounding
* errors at a minimum. * 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 */ /** 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. */ /** Type of the lookup table elements. */
typedef uint8_t lut_t; typedef uint8_t lut_t;
@ -85,26 +87,26 @@
/** /**
* Lookup table of fractional parts which model the first quarter of a * Lookup table of fractional parts which model the first quarter of a
* sine period. The rest of that period is calculated by mirroring those * 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] = static lut_t const fix_sine_lut[FIX_SIN_COUNT / 4] =
{ 0, 1, 2, 3, 4, 5, 6, 7, { 0, 2, 4, 6, 8, 10, 12, 14,
8, 9, 10, 11, 12, 13, 14, 14, 16, 18, 20, 22, 24, 25, 27, 29,
15, 16, 17, 18, 19, 20, 20, 21, 31, 33, 34, 36, 38, 39, 41, 42,
22, 23, 23, 24, 25, 25, 26, 26, 44, 45, 47, 48, 49, 51, 52, 53,
27, 27, 28, 28, 29, 29, 30, 30, 54, 55, 56, 57, 58, 59, 60, 60,
30, 31, 31, 31, 31, 32, 32, 32, 61, 61, 62, 62, 63, 63, 63, 64,
32, 32}; 64, 64};
#else #else
/** This is the type we expect ordinary integers to be. */ /** This is the type we expect ordinary integers to be. */
typedef int16_t ordinary_int_t; typedef int16_t ordinary_int_t;
/** This is the type which we use for fixed-point values. */ /** 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(). */ /** This type covers arguments of fixSin() and fixCos(). */
typedef int32_t fixp_trig_t; typedef int32_t fixp_trig_t;
/** This type covers interim results of fixed-point operations. */ /** 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. */ /** This type covers interim results of the fixSqrt() function. */
typedef uint32_t ufixp_interim_t; typedef uint32_t ufixp_interim_t;
/** Number of bits the fixSqrt() function can handle. */ /** Number of bits the fixSqrt() function can handle. */
@ -123,12 +125,12 @@
* 4 itself. Approximate this value as close as possible to keep rounding * 4 itself. Approximate this value as close as possible to keep rounding
* errors at a minimum. * 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 */ /** 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. */ /** 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 * Lookup table of fractional parts which model the first quarter of a
@ -142,7 +144,7 @@
175, 181, 186, 192, 197, 202, 207, 211, 175, 181, 186, 192, 197, 202, 207, 211,
216, 220, 224, 228, 231, 235, 238, 240, 216, 220, 224, 228, 231, 235, 238, 240,
243, 245, 247, 249, 251, 252, 253, 254, 243, 245, 247, 249, 251, 252, 253, 254,
255, 255}; 255, 256};
#endif #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 * 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() * (radian). It substracts FIX_PI_2 from the given angle and consults the
* function for the final result. * fixSin() function for the final result.
* @param fAngle A fixed-point value in radian. * @param fAngle A fixed-point value in radian.
* @return Result of the cosine function normalized to a range from -FIX to FIX. * @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 nRoot = 0; // clear root
nRemainingHigh = 0; // clear high part of partial remainder nRemainingHigh = 0; // clear high part of partial remainder
nRemainingLow = a; // get argument into low 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 do
{ {
nRemainingHigh = nRemainingHigh =
@ -451,16 +453,16 @@ static unsigned char fixAnimPlasma(unsigned char const x,
assert(x < (LINEBYTES * 8)); assert(x < (LINEBYTES * 8));
assert(y < NUM_ROWS); assert(y < NUM_ROWS);
// scaling factor
static fixp_t const fPlasmaX = (2 * PI * FIX) / NUM_COLS;
// reentrant data // reentrant data
fixp_plasma_t *const p = (fixp_plasma_t *)r; fixp_plasma_t *const p = (fixp_plasma_t *)r;
// scaling factor
static fixp_t const fPlasmaX = FIX / 3.7;
if (x == 0 && y == 0) if (x == 0 && y == 0)
{ {
p->fFunc2CosArg = NUM_ROWS * fixCos(t) + fixScaleUp(NUM_ROWS); p->fFunc2CosArg = NUM_COLS * (fixCos(t) + FIX);
p->fFunc2SinArg = NUM_COLS * fixSin(t) + fixScaleUp(NUM_COLS); p->fFunc2SinArg = NUM_ROWS * (fixSin(t) + FIX);
for (unsigned char i = LINEBYTES * 8u; i--;) for (unsigned char i = LINEBYTES * 8u; i--;)
{ {
p->fFunc1[i] = fixSin(fixMul(fixScaleUp(i), fPlasmaX) + t); 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), fixp_t const fFunc2 = fixSin(fixMul(fixDist(fixScaleUp(x), fixScaleUp(y),
p->fFunc2SinArg, p->fFunc2CosArg), fPlasmaX)); p->fFunc2SinArg, p->fFunc2CosArg), fPlasmaX));
unsigned char const nRes = (unsigned char)(fixMul(p->fFunc1[x] + fFunc2 + unsigned char const nRes = (fixMul(p->fFunc1[x] + fFunc2 +
fixScaleUp(2), ((NUMPLANE + 1) / 4.0 - 0.05) * FIX)) / FIX; 2 * FIX, ((NUMPLANE + 1) / 4.0 - 0.05) * FIX)) / FIX;
assert (nRes <= NUMPLANE); assert (nRes <= NUMPLANE);
return nRes; return nRes;
@ -484,12 +486,12 @@ void plasma(void)
{ {
fixp_plasma_t r; fixp_plasma_t r;
#ifndef __AVR__ #ifndef __AVR__
fixDrawPattern(0, fixScaleUp(75), 0.1 * FIX, 15, fixAnimPlasma, &r); fixDrawPattern(0, fixScaleUp(75), 0.05 * FIX, 15, fixAnimPlasma, &r);
#else #else
#ifndef FP_PLASMA_DELAY #ifndef FP_PLASMA_DELAY
#define FP_PLASMA_DELAY 1 #define FP_PLASMA_DELAY 1
#endif #endif
fixDrawPattern(0, fixScaleUp(60), 0.1 * FIX, fixDrawPattern(0, fixScaleUp(60), 0.05 * FIX,
FP_PLASMA_DELAY, fixAnimPlasma, &r); FP_PLASMA_DELAY, fixAnimPlasma, &r);
#endif /* __AVR__ */ #endif /* __AVR__ */
} }
@ -505,9 +507,9 @@ void plasma(void)
*/ */
typedef struct fixp_psychedelic_s typedef struct fixp_psychedelic_s
{ {
fixp_t fCos; /**< One of the column factors of the curl. */ fixp_t fCos; /**< X-coordinate of the curl's center. */
fixp_t fSin; /**< One of the row factors of the curl. */ fixp_t fSin; /**< Y-coordinate of the curl's center. */
fixp_interim_t ft10; /**< A value involved in rotating the curl's center. */ fixp_t fPhaseShift; /**< Phase-shift for the flow effect. */
} fixp_psychedelic_t; } fixp_psychedelic_t;
@ -530,15 +532,15 @@ static unsigned char fixAnimPsychedelic(unsigned char const x,
if (x == 0 && y == 0) if (x == 0 && y == 0)
{ {
p->fCos = NUM_COLS/2 * fixCos(t); p->fCos = (fixp_t)(NUM_COLS * 0.72) * (fixCos(t) + FIX);
p->fSin = NUM_ROWS/2 * fixSin(t); p->fSin = (fixp_t)(NUM_ROWS * 0.72) * (fixSin(t) + FIX);
p->ft10 = fixMul(t, fixScaleUp(10)); p->fPhaseShift = t * 8;
} }
unsigned char const nResult = unsigned char const nResult =
(unsigned char)(fixMul(fixSin(fixDist(fixScaleUp(x), fixScaleUp(y), fixMul(fixSin(fixDist(fixScaleUp(x), fixScaleUp(y),
p->fCos, p->fSin) - p->ft10) + fixScaleUp(1), p->fSin, p->fCos) - p->fPhaseShift) + FIX,
(fixp_t)((NUMPLANE - 1.05) * FIX))) / FIX; (fixp_t)((NUMPLANE - 1.05) * FIX)) / FIX;
assert(nResult <= NUMPLANE); assert(nResult <= NUMPLANE);
return nResult; return nResult;

View File

@ -1,4 +1,5 @@
#include <stdbool.h>
#include "../config.h" #include "../config.h"
#include "../compat/pgmspace.h" #include "../compat/pgmspace.h"
#include "../random/prng.h" #include "../random/prng.h"
@ -9,33 +10,37 @@
#ifdef ANIMATION_TESTS #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 y=NUM_ROWS;y--;){
for (unsigned char x=NUM_COLS;x--;){ for (unsigned char x=NUM_COLS;x--;){
setpixel((pixel){x,y}, level); setpixel((pixel){x,y}, level);
wait(5); wait(5);
} }
} }
if (!debug) {
wait(2000); wait(2000);
} }
}
void test_palette(){ void test_palette(bool debug){
for (unsigned char y=NUM_ROWS;y--;){ for (unsigned char y=NUM_ROWS;y--;){
for (unsigned char x=NUM_COLS;x--;){ for (unsigned char x=NUM_COLS;x--;){
setpixel((pixel){x,y}, y%4); setpixel((pixel){x,y}, y%4);
// wait(1); // wait(1);
} }
} }
if (!debug) {
wait(2000); wait(2000);
} }
}
void test_palette2(){ void test_palette2(bool debug){
for (unsigned char x=NUM_COLS;x--;){ for (unsigned char x=NUM_COLS;x--;){
for (unsigned char y=NUM_ROWS;y--;){ for (unsigned char y=NUM_ROWS;y--;){
setpixel((pixel){x,y}, x%4); setpixel((pixel){x,y}, x%4);
// wait(1);
} }
} }
if (!debug) {
wait(1000); wait(1000);
for (unsigned char x=NUM_COLS;x--;){ for (unsigned char x=NUM_COLS;x--;){
// shift image right // shift image right
@ -43,6 +48,7 @@ void test_palette2(){
wait(30); wait(30);
} }
} }
}
#endif #endif

View File

@ -1,13 +1,14 @@
#ifndef PROGRAMM_H_ #ifndef PROGRAMM_H_
#define PROGRAMM_H_ #define PROGRAMM_H_
#include <stdbool.h>
#include "../pixel.h" #include "../pixel.h"
#include "../util.h" #include "../util.h"
void test_level(unsigned char level); void test_level(unsigned char level, bool debug);
void test_palette(); void test_palette(bool debug);
void test_palette2(); void test_palette2(bool debug);
#ifdef ANIMATION_OFF #ifdef ANIMATION_OFF
inline static void off() inline static void off()

View File

@ -33,15 +33,34 @@
#define COLDDR2 DDR(COLPORT2) #define COLDDR2 DDR(COLPORT2)
#define ROWDDR DDR(ROWPORT) #define ROWDDR DDR(ROWPORT)
#if defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__) #if defined(__AVR_ATmega164__) || \
/* more ifdef magic :-( */ defined(__AVR_ATmega164P__) || \
#define OCR0 OCR0A defined(__AVR_ATmega324__) || \
#define TIMER0_COMP_vect TIMER0_COMPA_vect 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 #endif
// buffer which holds the currently shown frame // buffer which holds the currently shown frame
unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES]; unsigned char pixmap[NUMPLANE][NUM_ROWS][LINEBYTES];
// switch to next row // switch to next row
static void nextrow(uint8_t row) { static void nextrow(uint8_t row) {
//reset states of preceding row //reset states of preceding row
@ -80,12 +99,18 @@ static void nextrow(uint8_t row) {
} }
} }
// show a row // show a row
static void rowshow(unsigned char row, unsigned char plane) { static void rowshow(unsigned char row, unsigned char plane) {
// depending on the currently drawn plane, display the row for a specific // depending on the currently drawn plane, display the row for a specific
// amount of time // 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}; 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 // output data of the current row to the column drivers
uint8_t tmp, tmp1; 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 // interrupt handler
ISR(TIMER0_COMP_vect) { ISR(TIMER0_ISR) {
static unsigned char plane = 0; static unsigned char plane = 0;
static unsigned char row = 0; static unsigned char row = 0;
// reset watchdog
wdt_reset();
// increment both row and plane // increment both row and plane
if (++plane == NUMPLANE) { if (++plane == NUMPLANE) {
plane = 0; plane = 0;
if (++row == NUM_ROWS) { if (++row == NUM_ROWS) {
// reset watchdog
wdt_reset();
row = 0; row = 0;
} }
nextrow(row); nextrow(row);
@ -146,49 +171,27 @@ ISR(TIMER0_COMP_vect) {
rowshow(row, plane); rowshow(row, plane);
} }
// disables timer, causing the watchdog to reset the MCU
void timer0_off() { void timer0_off() {
cli(); cli();
COLPORT1 = 0; COLPORT1 = 0;
COLPORT2 = 0; COLPORT2 = 0;
ROWPORT = 0; ROWPORT = 0;
TIMER0_OFF();
#if defined (__AVR_ATmega644P__) || defined (__AVR_ATmega644__) || (__AVR_ATmega1284P__) || defined (__AVR_ATmega1284__)
TCCR0A = 0x00;
TCCR0B = 0x00;
#else
TCCR0 = 0x00;
#endif
sei(); sei();
} }
// initialize timer which triggers the interrupt // initialize timer which triggers the interrupt
static void timer0_on() { static void timer0_on() {
/* TCCR0: FOC0 WGM00 COM01 COM00 WGM01 CS02 CS01 CS00 TIMER0_CTC_CS256(); // CTC mode, prescaling conforms to clk/256
CS02 CS01 CS00 TIMER0_RESET(); // set counter to 0
0 0 0 stop TIMER0_COMPARE(20); // compare with this value first
0 0 1 clk TIMER0_INT_ENABLE(); // enable Timer/Counter0 Output Compare Match (A) Int.
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
} }
void borg_hw_init() { void borg_hw_init() {
// switch column ports to output mode // switch column ports to output mode
COLDDR1 = 0xFF; COLDDR1 = 0xFF;
@ -208,5 +211,5 @@ void borg_hw_init() {
// activate watchdog timer // activate watchdog timer
wdt_reset(); wdt_reset();
wdt_enable(0x00); // 17ms watchdog wdt_enable(WDTO_15MS); // 15ms watchdog
} }

View File

@ -973,3 +973,27 @@ void borg_hw_init() {
wdt_reset(); wdt_reset();
wdt_enable(WDTO_15MS); // 15ms watchdog 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();
}

View File

@ -17,6 +17,21 @@ comment "Borg16 port setup"
#//das dier sind die individuellen Dateneingänge für die Schieberegister #//das dier sind die individuellen Dateneingänge für die Schieberegister
#define PIN_SHFT1 PD7 #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)' \ choice 'Column Port 1 (right)' \
"PORTA PORTA \ "PORTA PORTA \

View File

@ -2,8 +2,23 @@ mainmenu_option next_comment
comment "lolshield setup" comment "lolshield setup"
define_int USER_TIMER0_FOR_WAIT 1 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 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 endmenu

View File

@ -33,6 +33,8 @@
#define INIT_EEPROM #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_ */ #endif /* CONFIG_H_ */

View File

@ -1,5 +1,6 @@
#include <setjmp.h> #include <setjmp.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include "config.h" #include "config.h"
@ -7,6 +8,7 @@
#include "animations/snake.h" #include "animations/snake.h"
#include "animations/program.h" #include "animations/program.h"
#include "animations/matrix.h" #include "animations/matrix.h"
#include "animations/dna.h"
#include "animations/gameoflife.h" #include "animations/gameoflife.h"
#include "animations/stonefly.h" #include "animations/stonefly.h"
#include "animations/flyingdots.h" #include "animations/flyingdots.h"
@ -16,7 +18,6 @@
#include "animations/bitmapscroller/amphibian.h" #include "animations/bitmapscroller/amphibian.h"
#include "animations/bitmapscroller/outofspec.h" #include "animations/bitmapscroller/outofspec.h"
#include "animations/bitmapscroller/fairydust.h" #include "animations/bitmapscroller/fairydust.h"
#include "animations/bitmapscroller/thisisnotdetroit.h"
#include "animations/fpmath_patterns.h" #include "animations/fpmath_patterns.h"
#include "animations/mherweg.h" #include "animations/mherweg.h"
#include "animations/moire.h" #include "animations/moire.h"
@ -49,7 +50,7 @@
# include "joystick/joystick.h" # include "joystick/joystick.h"
#endif #endif
volatile unsigned char oldMode, oldOldmode, mode; volatile unsigned char oldMode, oldOldmode, reverseMode, mode;
jmp_buf newmode_jmpbuf; jmp_buf newmode_jmpbuf;
@ -66,6 +67,12 @@ void display_loop(){
// mcuf_serial_mode(); // mcuf_serial_mode();
mode = setjmp(newmode_jmpbuf); 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; oldOldmode = oldMode;
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
@ -77,6 +84,7 @@ void display_loop(){
clear_screen(0); clear_screen(0);
#endif #endif
oldMode = mode; oldMode = mode;
switch(mode++) { switch(mode++) {
#ifdef ANIMATION_SCROLLTEXT #ifdef ANIMATION_SCROLLTEXT
@ -86,7 +94,8 @@ void display_loop(){
#ifdef RANDOM_SUPPORT #ifdef RANDOM_SUPPORT
{ {
char a[28]; 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); scrolltext(a);
} }
#endif #endif
@ -227,52 +236,52 @@ void display_loop(){
break; break;
#endif #endif
#ifdef ANIMATION_THISISNOTDETROIT
case 22:
logo_thisIsNotDetroit();
break;
#endif
#ifdef ANIMATION_PLASMA #ifdef ANIMATION_PLASMA
case 23: case 22:
plasma(); plasma();
break; break;
#endif #endif
#ifdef ANIMATION_PSYCHEDELIC #ifdef ANIMATION_PSYCHEDELIC
case 24: case 23:
psychedelic(); psychedelic();
break; break;
#endif #endif
#ifdef ANIMATION_BLACKHOLE #ifdef ANIMATION_BLACKHOLE
case 25: case 24:
blackhole(); blackhole();
break; break;
#endif #endif
#ifdef ANIMATION_SQUARES #ifdef ANIMATION_SQUARES
case 26: case 25:
squares(); squares();
break; break;
#endif #endif
#ifdef ANIMATION_DNA
case 26:
dna();
break;
#endif
#ifdef ANIMATION_TESTS #ifdef ANIMATION_TESTS
case 31: case 31:
test_level(1); test_level(1, false);
break; break;
case 32: case 32:
test_level(2); test_level(2, false);
break; break;
case 33: case 33:
test_level(3); test_level(3, false);
break; break;
case 35: case 35:
test_palette(); test_palette(false);
test_palette2(); test_palette2(false);
break; break;
#endif #endif
@ -299,26 +308,26 @@ void display_loop(){
#endif #endif
#ifdef MENU_SUPPORT #ifdef MENU_SUPPORT
case 42: case 0xFDu:
mode = 1; mode = 1;
break; break;
case 43: case 0xFEu:
menu(); menu();
mode = oldOldmode; mode = oldOldmode;
break; break;
#else #else
case 42: case 0xFDu:
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
if (JOYISFIRE) if (JOYISFIRE)
mode = 43; mode = 0xFEu;
else else
#endif #endif
mode = 1; mode = 1;
break; break;
case 43: case 0xFEu:
#ifdef JOYSTICK_SUPPORT #ifdef JOYSTICK_SUPPORT
waitForFire = 0; // avoid circular jumps waitForFire = 0; // avoid circular jumps
while (JOYISFIRE); // wait until user released the fire button while (JOYISFIRE); // wait until user released the fire button
@ -361,10 +370,19 @@ void display_loop(){
#endif #endif
#ifdef ANIMATION_OFF #ifdef ANIMATION_OFF
case 0xFF: case 0xFFu:
off(); off();
break; break;
#endif #endif
default:
if (reverseMode) {
if (reverseMode-- == (mode - 1)) {
mode -= 2;
} else {
reverseMode = 0;
}
}
break;
} }
} }
} }

View File

@ -7,7 +7,13 @@ comment "Games"
endmenu endmenu
dep_bool "Space Invaders" GAME_SPACE_INVADERS $JOYSTICK_SUPPORT $RANDOM_SUPPORT 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 "Breakout" GAME_BREAKOUT $JOYSTICK_SUPPORT $RANDOM_SUPPORT
dep_bool "Kart" GAME_KART $JOYSTICK_SUPPORT $RANDOM_SUPPORT dep_bool "Kart" GAME_KART $JOYSTICK_SUPPORT $RANDOM_SUPPORT
endmenu endmenu

View File

@ -224,7 +224,7 @@ void kart_game(){
wait(WAIT); 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); scrolltext(game_over);
} }

View File

@ -12,6 +12,7 @@
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "../../config.h" #include "../../config.h"
#include "../../compat/pgmspace.h" #include "../../compat/pgmspace.h"
#include "../../pixel.h" #include "../../pixel.h"
@ -36,11 +37,13 @@ game_descriptor_t snake_game_descriptor __attribute__((section(".game_descriptor
#endif #endif
#ifdef DOXYGEN
/** /**
* If defined, joystick controls are NOT as "seen" by the snake but absolute, * If defined, joystick controls are bound to the point of view of the
* that is, if pressing up, snake goes up, etc. * 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 #if !defined USNAKE_MAX_LENGTH || defined DOXYGEN
/** The maximum length of the snake. */ /** 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 nHeadIndex; /**< Index of the head segment. */
uint8_t nTailIndex; /**< Index of the tail segment. */ uint8_t nTailIndex; /**< Index of the tail segment. */
snake_dir_t dir; /**< Direction of the snake. */ snake_dir_t dir; /**< Direction of the snake. */
bool bJoystickLocked; /**< Avoid double joytick queries
between movements. */
} snake_protagonist_t; } snake_protagonist_t;
@ -213,6 +218,7 @@ static void snake_initGameProtagonist(snake_protagonist_t *pprotSnake)
#endif #endif
pprotSnake->nTailIndex = 0; pprotSnake->nTailIndex = 0;
pprotSnake->nHeadIndex = 1; pprotSnake->nHeadIndex = 1;
pprotSnake->bJoystickLocked = false;
} }
#ifdef GAME_SNAKE #ifdef GAME_SNAKE
@ -225,17 +231,10 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
snake_dir_t *pdirLast) snake_dir_t *pdirLast)
{ {
snake_dir_t dirJoystick = snake_queryJoystick(); snake_dir_t dirJoystick = snake_queryJoystick();
#ifdef SNAKE_NEWCONTROL # ifdef SNAKE_POV_CONTROL
if (dirJoystick != SNAKE_DIR_NONE)
{ if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE) &&
// valid transitions can only be uneven (!pprotSnake->bJoystickLocked))
if ((pprotSnake->dir + dirJoystick) & 0x01)
{
pprotSnake->dir = dirJoystick;
}
}
#else
if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE))
{ {
// only left or right movements are valid // only left or right movements are valid
if (dirJoystick & 0x01) if (dirJoystick & 0x01)
@ -244,8 +243,24 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
pprotSnake->dir = (pprotSnake->dir + pprotSnake->dir = (pprotSnake->dir +
(dirJoystick == SNAKE_DIR_LEFT ? 3 : 1)) % 4u; (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; *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
} }
#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. * 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 pApples The set of apples which are lying on the playing field.
* @param pxHead The position to be tested. * @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--;) 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->aApples[i] = pApples->aApples[i + 1];
} }
--pApples->nAppleCount; --pApples->nAppleCount;
return 1; return true;
} }
} }
return 0; return false;
} }
@ -419,7 +434,7 @@ void snake_engine(uint8_t bDemoMode)
clear_screen(0); clear_screen(0);
snake_drawBorder(); 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 // determine new direction
#if defined ANIMATION_SNAKE && defined GAME_SNAKE #if defined ANIMATION_SNAKE && defined GAME_SNAKE
@ -439,6 +454,8 @@ void snake_engine(uint8_t bDemoMode)
snake_userControl(&protSnake, &dirLast); snake_userControl(&protSnake, &dirLast);
if (nTick) { if (nTick) {
#endif #endif
// release joystick lock
protSnake.bJoystickLocked = false;
// actually move head // actually move head
pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex]; pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex];

View File

@ -100,7 +100,7 @@ void initInvaders(Invaders * iv, unsigned char lv)
uint16_t mask = 0x0001; uint16_t mask = 0x0001;
for (x = 11; x--;) for (x = 11; x--;)
{ {
iv->map[x][y] = (hansrow & mask) ? 3 : 1; iv->map[x][y] = (hansrow & mask) ? 2 : 1;
mask <<= 1; mask <<= 1;
} }
} }
@ -108,7 +108,7 @@ void initInvaders(Invaders * iv, unsigned char lv)
iv->pos.x = (NUM_COLS - 11) / 2; iv->pos.x = (NUM_COLS - 11) / 2;
iv->pos.y = SPACESHIP_LINE + 1; iv->pos.y = SPACESHIP_LINE + 1;
iv->speed = MIN_SPEED + 2; iv->speed = MIN_SPEED + 40;
iv->direction = 1; iv->direction = 1;
break; break;

View File

@ -109,6 +109,7 @@ uint16_t tetris_highscore_inputName(void)
uint16_t tetris_highscore_retrieveHighScore(tetris_highscore_index_t nIndex) uint16_t tetris_highscore_retrieveHighScore(tetris_highscore_index_t nIndex)
{ {
eeprom_busy_wait();
uint16_t nHighScore = uint16_t nHighScore =
eeprom_read_word(&g_highScoreTable.nHighScore[nIndex]); eeprom_read_word(&g_highScoreTable.nHighScore[nIndex]);

View File

@ -78,6 +78,7 @@ void tetris_highscore_saveHighScore(tetris_highscore_index_t nIndex,
{ {
if (nHighScore > tetris_highscore_retrieveHighScore(nIndex)) if (nHighScore > tetris_highscore_retrieveHighScore(nIndex))
{ {
eeprom_busy_wait();
eeprom_write_word(&g_highScoreTable.nHighScore[nIndex], nHighScore); eeprom_write_word(&g_highScoreTable.nHighScore[nIndex], nHighScore);
} }
} }
@ -91,6 +92,7 @@ void tetris_highscore_saveHighScore(tetris_highscore_index_t nIndex,
inline static inline static
uint16_t tetris_highscore_retrieveHighScoreName(tetris_highscore_index_t nIdx) uint16_t tetris_highscore_retrieveHighScoreName(tetris_highscore_index_t nIdx)
{ {
eeprom_busy_wait();
uint16_t nHighScoreName = uint16_t nHighScoreName =
eeprom_read_word(&g_highScoreTable.nHighScoreName[nIdx]); eeprom_read_word(&g_highScoreTable.nHighScoreName[nIdx]);
@ -107,6 +109,7 @@ inline static
void tetris_highscore_saveHighScoreName(tetris_highscore_index_t nIndex, void tetris_highscore_saveHighScoreName(tetris_highscore_index_t nIndex,
uint16_t nHighscoreName) uint16_t nHighscoreName)
{ {
eeprom_busy_wait();
eeprom_write_word(&g_highScoreTable.nHighScoreName[nIndex], nHighscoreName); eeprom_write_word(&g_highScoreTable.nHighScoreName[nIndex], nHighscoreName);
} }

View File

@ -50,11 +50,11 @@
#define TETRIS_INPUT_REPEAT_DELAY 5 #define TETRIS_INPUT_REPEAT_DELAY 5
/** Number of loop cyles the left button is ignored */ /** 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 */ /** 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 */ /** 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 */ /** Number of loop cyles the clockwise rotation button is ignored */
#define TETRIS_INPUT_CHATTER_TICKS_ROT_CW 24 #define TETRIS_INPUT_CHATTER_TICKS_ROT_CW 24
/** Number of loop cyles the counter clockwise rotation button is ignored */ /** Number of loop cyles the counter clockwise rotation button is ignored */

View File

@ -52,7 +52,8 @@
/** color of line counter */ /** color of line counter */
#define TETRIS_VIEW_COLORCOUNTER 2 #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 VIEWCOLS NUM_ROWS
# define VIEWROWS NUM_COLS # define VIEWROWS NUM_COLS
# define VIEW_TILT # define VIEW_TILT
@ -77,7 +78,8 @@
#if VIEWROWS >= 16 #if VIEWROWS >= 16
#define TETRIS_VIEW_XOFFSET_COUNTER \ #define TETRIS_VIEW_XOFFSET_COUNTER \
(TETRIS_VIEW_XOFFSET_DUMP + TETRIS_VIEW_WIDTH_DUMP + 1) (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_COUNT10 (TETRIS_VIEW_YOFFSET_COUNT100 + 2)
#define TETRIS_VIEW_YOFFSET_COUNT1 (TETRIS_VIEW_YOFFSET_COUNT10 + 4) #define TETRIS_VIEW_YOFFSET_COUNT1 (TETRIS_VIEW_YOFFSET_COUNT10 + 4)

View File

@ -1,6 +1,7 @@
#include <setjmp.h> #include <setjmp.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <stdio.h> #include <stdio.h>
#include "config.h" #include "config.h"
@ -19,6 +20,10 @@
#include "can/borg_can.h" #include "can/borg_can.h"
#endif #endif
#ifdef UART_SUPPORT
# include "uart/uart.h"
#endif
#ifdef RFM12_SUPPORT #ifdef RFM12_SUPPORT
#include "rfm12/borg_rfm12.h" #include "rfm12/borg_rfm12.h"
#endif #endif
@ -27,8 +32,8 @@ int main (void){
clear_screen(0); clear_screen(0);
#ifdef RANDOM_SUPPORT #ifdef RANDOM_SUPPORT
srandom32(percnt_get()); srandom32(percnt_get(&g_reset_counter, &g_reset_counter_idx));
percnt_inc(); percnt_inc(&g_reset_counter, &g_reset_counter_idx);
#endif #endif
#ifdef RFM12_SUPPORT #ifdef RFM12_SUPPORT
@ -41,12 +46,12 @@ int main (void){
bcan_init(); bcan_init();
#endif #endif
#ifdef JOYSTICK_SUPPORT #ifdef UART_SUPPORT
joy_init(); uart_init(UART_BAUD_SELECT(UART_BAUDRATE_SETTING, F_CPU));
#endif #endif
#ifdef UART_SUPPORT #ifdef JOYSTICK_SUPPORT
uart_init(); joy_init();
#endif #endif
sei(); sei();

View File

@ -9,6 +9,7 @@
#include "../compat/interrupt.h" /* cli() & sei() */ #include "../compat/interrupt.h" /* cli() & sei() */
#include "../compat/eeprom.h" #include "../compat/eeprom.h"
#include "../config.h" #include "../config.h"
#include "persistentCounter.h"
#ifdef ERROR_HANDLING #ifdef ERROR_HANDLING
# include "error-handling.h" # include "error-handling.h"
@ -16,68 +17,67 @@
# define PERSISTENT_COUNTER_WRITER_ERROR (void*)0, 2,4,2 # define PERSISTENT_COUNTER_WRITER_ERROR (void*)0, 2,4,2
#endif #endif
#define RING_SIZE 168 uint8_t g_reset_counter_idx = 0xff;
percnt_t EEMEM g_reset_counter;
uint8_t ring_idx = 0xff;
uint16_t EEMEM B08_23;
uint8_t EEMEM B0_7[RING_SIZE];
#ifdef INIT_EEPROM #ifdef INIT_EEPROM
void init_buffer(void){ void init_buffer(percnt_t *percnt, uint8_t *ring_index) {
uint8_t i; uint8_t i;
eeprom_busy_wait(); eeprom_busy_wait();
eeprom_write_word(&B08_23, 0x0000); eeprom_write_word(&(percnt->B08_23), 0x0000);
for (i = 0; i < RING_SIZE; ++i) { for (i = 0; i < RING_SIZE; ++i) {
eeprom_busy_wait(); eeprom_busy_wait();
eeprom_write_byte(&(B0_7[i]), 0x00); eeprom_write_byte(&(percnt->B0_7[i]), 0x00);
} }
} }
#endif #endif
void percnt_init(void){ void percnt_init(percnt_t *percnt, uint8_t *ring_index) {
uint8_t i; uint8_t i;
uint8_t maxidx = 0; 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 #ifdef INIT_EEPROM
if (eeprom_read_word(&B08_23)==0xFFFF){ /* test if the 2 MSB == 0xFFFF*/ /* test if the 2 MSB == 0xFFFF */
if (eeprom_read_word((uint16_t*)&(B0_7[0]))==0xFFFF) /* test the first to bytes of ringbuffer*/ if (eeprom_read_word(&(percnt->B08_23)) == 0xFFFF) {
init_buffer(); /* test the first two bytes of ringbuffer */
if (eeprom_read_word((uint16_t*) &(percnt->B0_7[0])) == 0xFFFF)
init_buffer(percnt, ring_index);
} }
#endif #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(); eeprom_busy_wait();
t=eeprom_read_byte(&(B0_7[i])); t = eeprom_read_byte(&(percnt->B0_7[i]));
if (t == max + 1) { if (t == max + 1) {
max = t; max = t;
maxidx = i; 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; uint32_t ret = 0;
if(ring_idx==0xff) if (*ring_index == 0xff)
percnt_init(); percnt_init(percnt, ring_index);
cli(); cli();
eeprom_busy_wait(); eeprom_busy_wait();
ret=eeprom_read_word(&B08_23)<<8; ret = eeprom_read_word(&(percnt->B08_23)) << 8;
eeprom_busy_wait(); eeprom_busy_wait();
ret |= eeprom_read_byte(&(B0_7[ring_idx])); ret |= eeprom_read_byte(&(percnt->B0_7[*ring_index]));
sei(); sei();
return ret; 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 ... */ /* we must make this resistant agaist power off while this is running ... */
uint32_t u; uint32_t u;
if(ring_idx==0xff) if (*ring_index == 0xff)
percnt_init(); percnt_init(percnt, ring_index);
u = percnt_get(); u = percnt_get(percnt, ring_index);
cli(); cli();
/* it's important to write msb first! */ /* it's important to write msb first! */
if ((u & 0x000000ff) == 0xff) { if ((u & 0x000000ff) == 0xff) {
@ -89,18 +89,20 @@ void percnt_inc(void){
#endif #endif
} }
eeprom_busy_wait(); 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_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) */ /* set least significant byte (in ringbuffer) */
ring_idx = (ring_idx+1)%RING_SIZE; *ring_index = (*ring_index + 1) % RING_SIZE;
eeprom_busy_wait(); 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(); eeprom_busy_wait();
if(u+1 != percnt_get()){ if (u + 1 != percnt_get(percnt, ring_index)) {
#ifdef ERROR_HANDLING #ifdef ERROR_HANDLING
error(PERSISTENT_COUNTER_WRITER_ERROR); error(PERSISTENT_COUNTER_WRITER_ERROR);
#endif #endif

View File

@ -9,15 +9,22 @@
#ifndef PERSISTENTCOUNTER_H_ #ifndef PERSISTENTCOUNTER_H_
#define PERSISTENTCOUNTER_H_ #define PERSISTENTCOUNTER_H_
#include <stdint.h> #include <stdint.h>
#include "../compat/eeprom.h"
#define PERSISTENT_COUNTER_BITS 24 #define PERSISTENT_COUNTER_BITS 24
#define RING_SIZE 168
void percnt_init(void); typedef struct percnt_s {
uint32_t percnt_get(void); uint16_t B08_23;
void percnt_inc(void); 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_*/ #endif /*PERSISTENTCOUNTER_H_*/

View File

@ -69,14 +69,9 @@ static void clear_text_pixmap(){
memset(text_pixmap, 0, NUM_ROWS * LINEBYTES); memset(text_pixmap, 0, NUM_ROWS * LINEBYTES);
} }
void update_pixmap(){ static void update_pixmap(){
unsigned char x, y, z; for(unsigned char p = NUMPLANE; p--;){
for(x=NUMPLANE;x--;){ memcpy(&pixmap[p][0][0], text_pixmap, NUM_ROWS * LINEBYTES);
for(y=NUM_ROWS;y--;){
for(z=LINEBYTES;z--;){
pixmap[x][y][z] = (*text_pixmap)[y][z];
}
}
} }
} }

View File

@ -62,7 +62,7 @@ int win;
void wait(unsigned int ms) { void wait(unsigned int ms) {
if (waitForFire) { if (waitForFire) {
if (fakeport & 0x01) { if (fakeport & 0x01) {
longjmp(newmode_jmpbuf, 43); longjmp(newmode_jmpbuf, 0xFEu);
} }
} }

View File

@ -455,7 +455,7 @@ void wait(int ms)
{ {
if (fakeport & 0x01) if (fakeport & 0x01)
{ {
longjmp(newmode_jmpbuf, 43); longjmp(newmode_jmpbuf, 0xFEu);
} }
} }

16
src/uart/Makefile Normal file
View File

@ -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

1
src/uart/config.in Normal file
View File

@ -0,0 +1 @@
# nothing for now

View File

@ -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/io.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <stdlib.h> #include <avr/pgmspace.h>
#include "config.h"
#include "uart.h" #include "uart.h"
#ifdef ATMEGA128
#define UCSRB UCSR0B /*
#define UCSRC UCSR0C * constants and macros
#define UDR UDR0 */
#define UBRRH UBRR0H
#define UBRRL UBRR0L /* size of RX/TX buffers */
#define URSEL UMSEL #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 #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;
#if defined( ATMEGA_USART1 ) && defined (USE_UART1)
#ifdef UART_INTERRUPT static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
volatile static char rxbuf[UART_RXBUFSIZE]; static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
volatile static char txbuf[UART_TXBUFSIZE]; static volatile unsigned char UART1_TxHead;
volatile static char *volatile rxhead, *volatile rxtail; static volatile unsigned char UART1_TxTail;
volatile static char *volatile txhead, *volatile txtail; static volatile unsigned char UART1_RxHead;
static volatile unsigned char UART1_RxTail;
static volatile unsigned char UART1_LastRxError;
ISR(USART_UDRE_vect) {
#ifdef UART_LEDS
PORTC ^= 0x01;
#endif #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{ }else{
UDR = *txtail; /* schreibt das Zeichen x auf die Schnittstelle */ /* store new index */
if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf; 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 #endif
/* buffer full? */ #elif defined (ATMEGA_USART0 )
diff = rxhead - rxtail; /* Set baud rate */
if ( diff < 0 ) diff += UART_RXBUFSIZE; if ( baudrate & 0x8000 )
if (diff < UART_RXBUFSIZE -1) { {
// buffer NOT full UART0_STATUS = (1<<U2X0); //Enable 2x speed
*rxhead = UDR; baudrate &= ~0x8000;
if (++rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf; }
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{ }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
ISR(UART1_TRANSMIT_INTERRUPT)
void uart_init() { /*************************************************************************
PORTD |= 0x01; //Pullup an RXD an Function: UART1 Data Register Empty interrupt
Purpose: called when the UART1 is ready to transmit the next byte
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)
{ {
unsigned char x=0; unsigned char tmptail;
char sbuf[3];
while(len--){
itoa(*buf++, sbuf, 16); if ( UART1_TxHead != UART1_TxTail) {
if (sbuf[1] == 0) uart_putc(' '); /* calculate and store new buffer index */
uart_putstr(sbuf); tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
uart_putc(' '); UART1_TxTail = tmptail;
if(++x == 16) { /* get one byte from buffer and write it to UART */
uart_putstr_P(PSTR("\r\n")); UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
x = 0; }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; /* Set baud rate */
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf; if ( baudrate & 0x8000 )
return val;
}
#else // WITHOUT INTERRUPT
char uart_getc()
{ {
while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar UART1_STATUS = (1<<U2X1); //Enable 2x speed
return UDR; // Zeichen aus UDR zurueckgeben baudrate &= ~0x8000;
} }
#endif // UART_INTERRUPT UBRR1H = (unsigned char)(baudrate>>8);
UBRR1L = (unsigned char) baudrate;
// returns 1 on success /* Enable USART receiver and transmitter and receive complete interrupt */
#ifdef UART_INTERRUPT UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
char uart_getc_nb(char *c)
/* 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 unsigned char tmphead;
*c = UDR;
return 1;
tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
while ( tmphead == UART1_TxTail ){
;/* wait for free space in buffer */
} }
return 0; UART1_TxBuf[tmphead] = data;
} UART1_TxHead = tmphead;
#endif // UART_INTERRUPT
/* 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

View File

@ -1,35 +1,223 @@
#ifndef UART_H #ifndef UART_H
#define 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 * @brief Interrupt UART library using the built-in UART with transmit and
* #define UART_INTERRUPT 1 * receive circular buffers.
* #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
* *
* 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(); #include "../config.h"
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();
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif #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

503
src/uart/uart_commands.c Normal file
View File

@ -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();
}
}

38
src/uart/uart_commands.h Normal file
View File

@ -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_ */

View File

@ -19,6 +19,9 @@ extern jmp_buf newmode_jmpbuf;
# include "can/borg_can.h" # include "can/borg_can.h"
#endif #endif
#ifdef UART_SUPPORT
# include "uart/uart_commands.h"
#endif
void wait(int ms){ void wait(int ms){
/* Always use Timer1 except for the Arduino/LoL Shield platform. */ /* Always use Timer1 except for the Arduino/LoL Shield platform. */
@ -41,6 +44,10 @@ void wait(int ms){
bcan_process_messages(); bcan_process_messages();
#endif #endif
#ifdef UART_SUPPORT
uartcmd_process();
#endif
#ifdef RFM12_SUPPORT #ifdef RFM12_SUPPORT
borg_rfm12_tick(); borg_rfm12_tick();
#endif #endif
@ -50,7 +57,7 @@ void wait(int ms){
//PORTJOYGND &= ~(1<<BITJOY0); //PORTJOYGND &= ~(1<<BITJOY0);
//PORTJOYGND &= ~(1<<BITJOY1); //PORTJOYGND &= ~(1<<BITJOY1);
if (JOYISFIRE) { if (JOYISFIRE) {
longjmp(newmode_jmpbuf, 43); longjmp(newmode_jmpbuf, 0xFEu);
} }
} }
#endif #endif