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
43 changed files with 2620 additions and 508 deletions

View File

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

View File

@ -36,69 +36,85 @@ OSTYPE = $(shell uname)
MACHINE = $(shell uname -m)
ifeq ($(findstring CYGWIN,$(OSTYPE)),CYGWIN)
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_WIN32 -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),x86_64)
LDFLAGS_SIM = -T ld_scripts/i386pep.x
else
ifeq ($(MACHINE),i686)
LDFLAGS_SIM = -T ld_scripts/i386pe.x
else
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
endif
endif
LIBS_SIM = -lgdi32 -lwinmm -lm
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_WIN32 -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),x86_64)
LDFLAGS_SIM = -T ld_scripts/i386pep.x
else
ifeq ($(MACHINE),i686)
LDFLAGS_SIM = -T ld_scripts/i386pe.x
else
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
endif
endif
LIBS_SIM = -lgdi32 -lwinmm -lm
else
ifeq ($(OSTYPE),FreeBSD)
CFLAGS_SIM = -g -I/usr/local/include -Wall -pedantic -std=c99 -O0
CFLAGS_SIM += -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),amd64)
LDFLAGS_SIM = -L/usr/local/lib -T ld_scripts/elf_x86_64_fbsd.x
else
ifeq ($(MACHINE),i386)
LDFLAGS_SIM = -L/usr/local/lib -T ld_scripts/elf_i386_fbsd.x
else
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
endif
endif
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm
else
ifeq ($(OSTYPE),NetBSD)
CFLAGS_SIM = -g -I /usr/pkg/include -I/usr/X11R7/include -Wall -pedantic -std=c99 -O0
CFLAGS_SIM += -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),amd64)
LDFLAGS_SIM = -L/usr/pkg/lib -L/usr/X11R7/lib -T ld_scripts/elf_x86_64_nbsd.x -Wl,-R/usr/pkg/lib,-R/usr/X11R7/lib
else
ifeq ($(MACHINE),i386)
LDFLAGS_SIM = -L/usr/pkg/lib -L/usr/X11R7/lib -T ld_scripts/elf_i386_nbsd.x -Wl,-R/usr/pkg/lib,-R/usr/X11R7/lib
else
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
endif
endif
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm
else
ifeq ($(OSTYPE),Linux)
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),x86_64)
LDFLAGS_SIM = -T ld_scripts/elf_x86_64.x
else
ifeq ($(MACHINE),i686)
LDFLAGS_SIM = -T ld_scripts/elf_i386.x
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
($(warning $(n)$(n)Simulator build is not supported on your system.$(n)$(n)\
ifeq ($(OSTYPE),FreeBSD)
CFLAGS_SIM = -g -I/usr/local/include -Wall -pedantic -std=c99 -O0
CFLAGS_SIM += -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),amd64)
LDFLAGS_SIM = -L/usr/local/lib -T ld_scripts/elf_x86_64_fbsd.x
else
ifeq ($(MACHINE),i386)
LDFLAGS_SIM = -L/usr/local/lib -T ld_scripts/elf_i386_fbsd.x
else
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
endif
endif
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm
else
ifeq ($(OSTYPE),NetBSD)
CFLAGS_SIM = -g -I /usr/pkg/include -I/usr/X11R7/include -Wall -pedantic -std=c99 -O0
CFLAGS_SIM += -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),amd64)
LDFLAGS_SIM = -L/usr/pkg/lib -L/usr/X11R7/lib -T ld_scripts/elf_x86_64_nbsd.x -Wl,-R/usr/pkg/lib,-R/usr/X11R7/lib
else
ifeq ($(MACHINE),i386)
LDFLAGS_SIM = -L/usr/pkg/lib -L/usr/X11R7/lib -T ld_scripts/elf_i386_nbsd.x -Wl,-R/usr/pkg/lib,-R/usr/X11R7/lib
else
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
endif
endif
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm
else
ifeq ($(OSTYPE),OpenBSD)
CFLAGS_SIM = -g -I/usr/local/include -I/usr/X11R6/include -Wall -pedantic -std=c99 -O0
CFLAGS_SIM += -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),amd64)
LDFLAGS_SIM = -L/usr/local/lib -L/usr/X11R6/lib -T ld_scripts/elf_x86_64_obsd.xd
else
ifeq ($(MACHINE),i386)
LDFLAGS_SIM = -L/usr/local/lib -L/usr/X11R6/lib -T ld_scripts/elf_i386_obsd.xd
else
$(warning $(n)$(n)Simulator build is only supported on i386 and amd64.$(n)$(n))
endif
endif
LIBS_SIM = -lglut -lpthread -lGL -lGLU -lm
else
ifeq ($(OSTYPE),Linux)
CFLAGS_SIM = -g -Wall -pedantic -std=c99 -O0 -D_XOPEN_SOURCE=600
ifeq ($(MACHINE),x86_64)
LDFLAGS_SIM = -T ld_scripts/elf_x86_64.x
else
ifeq ($(MACHINE),i686)
LDFLAGS_SIM = -T ld_scripts/elf_i386.x
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
($(warning $(n)$(n)Simulator build is not supported on your system.$(n)$(n)\
Currently supported platforms:$(n) \
Linux on i386 and amd64$(n) \
FreeBSD on i386 and amd64$(n) \
NetBSD on i386 and amd64$(n) \
Windows (via Cygwin) on i386 and amd64)
endif
endif
endif
Linux on i386 and amd64$(n) \
FreeBSD on i386 and amd64$(n) \
NetBSD on i386 and amd64$(n) \
Windows (via Cygwin) on i386 and amd64)
endif
endif
endif
endif
endif
##############################################################################
# the default target
$(TARGET):
@ -116,38 +132,35 @@ $(MAKETOPDIR)/config.mk:
@echo "#" >>$@
@echo "# Other flags you might want to tune: CPPFLAGS, LDFLAGS ..." >>$@
@echo "Created default config.mk, tune your settings there!"
-include $(MAKETOPDIR)/config.mk
-include $(MAKETOPDIR)/config.mk
##############################################################################
# configure load address for bootloader, if enabled
#
ifneq ($(MAKECMDGOALS),clean)
ifneq ($(MAKECMDGOALS),mrproper)
ifneq ($(MAKECMDGOALS),menuconfig)
ifneq ($(MAKECMDGOALS),mrproper)
ifneq ($(MAKECMDGOALS),menuconfig)
include $(MAKETOPDIR)/.config
CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU)
include $(MAKETOPDIR)/.config
CPPFLAGS += -DF_CPU=$(FREQ)UL -mmcu=$(MCU)
# flags for the linker, choose appropriate linker script
ifeq ($(findstring atmega256,$(MCU)),atmega256)
LDFLAGS += -T ld_scripts/avr6.x -Wl,-Map,image.map -mmcu=$(MCU)
else
ifeq ($(findstring atmega128,$(MCU)),atmega128)
LDFLAGS += -T ld_scripts/avr51.x -Wl,-Map,image.map -mmcu=$(MCU)
else
LDFLAGS += -T ld_scripts/avr5.x -Wl,-Map,image.map -mmcu=$(MCU)
endif
endif
endif # MAKECMDGOALS!=menuconfig
endif # MAKECMDGOALS!=mrproper
# flags for the linker, choose appropriate linker script
ifeq ($(findstring atmega256,$(MCU)),atmega256)
LDFLAGS += -T ld_scripts/avr6.x -Wl,-Map,image.map -mmcu=$(MCU)
else
ifeq ($(findstring atmega128,$(MCU)),atmega128)
LDFLAGS += -T ld_scripts/avr51.x -Wl,-Map,image.map -mmcu=$(MCU)
else
LDFLAGS += -T ld_scripts/avr5.x -Wl,-Map,image.map -mmcu=$(MCU)
endif
endif
endif # MAKECMDGOALS!=menuconfig
endif # MAKECMDGOALS!=mrproper
endif # MAKECMDGOALS!=clean
ifeq ($(BOOTLOADER_SUPPORT),y)
LDFLAGS += -Wl,--section-start=.text=0xE000
CFLAGS += -mcall-prologues
LDFLAGS += -Wl,--section-start=.text=0xE000
CFLAGS += -mcall-prologues
endif

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

@ -973,3 +973,27 @@ void borg_hw_init() {
wdt_reset();
wdt_enable(WDTO_15MS); // 15ms watchdog
}
void timer0_off() {
cli();
#if defined (__AVR_ATmega48__) || \
defined (__AVR_ATmega48P__) || \
defined (__AVR_ATmega88__) || \
defined (__AVR_ATmega88P__) || \
defined (__AVR_ATmega168__) || \
defined (__AVR_ATmega168P__) || \
defined (__AVR_ATmega328__) || \
defined (__AVR_ATmega328P__) || \
defined (__AVR_ATmega1280__) || \
defined (__AVR_ATmega2560__)
TCCR2A = 0x00;
TCCR2B = 0x00;
#elif defined (__AVR_ATmega8__) || \
defined (__AVR_ATmega128__)
TCCR2 = 0x00;
#elif defined (__AVR_ATmega32U4__)
TCCR1A = 0x00;
TCCR1B = 0x00;
#endif
sei();
}

View File

@ -17,6 +17,21 @@ comment "Borg16 port setup"
#//das dier sind die individuellen Dateneingänge für die Schieberegister
#define PIN_SHFT1 PD7
bool "Higher Contrast" HIGH_CONTRAST n
bool "UART Support" UART_SUPPORT n
choice 'Baud Rate' \
"2400 2400 \
4800 4800 \
9600 9600 \
14400 14400 \
19200 19200 \
28800 28800 \
38400 38400 \
57600 57600 \
76800 76800 \
115200 115200" \
'19200' UART_BAUDRATE_SETTING
choice 'Column Port 1 (right)' \
"PORTA PORTA \

View File

@ -2,8 +2,23 @@ mainmenu_option next_comment
comment "lolshield setup"
define_int USER_TIMER0_FOR_WAIT 1
define_bool LOLSHIELD y
uint "Brightness (0-127)" BRIGHTNESS 127
uint "Brightness (0-127)" BRIGHTNESS 120
uint "Framerate (default 80)" FRAMERATE 80
bool "UART Support" UART_SUPPORT n
choice 'Baud Rate' \
"2400 2400 \
4800 4800 \
9600 9600 \
14400 14400 \
19200 19200 \
28800 28800 \
38400 38400 \
57600 57600 \
76800 76800 \
115200 115200" \
'19200' UART_BAUDRATE_SETTING
endmenu

View File

@ -33,6 +33,8 @@
#define INIT_EEPROM
//#define UART_BAUD_RATE 115200L
#if defined(UART_SUPPORT) && defined(LOLSHIELD) && defined(__AVR_ATmega32U4__)
# error UART not supported on Arduino Leonardo
#endif
#endif /* CONFIG_H_ */

View File

@ -1,5 +1,6 @@
#include <setjmp.h>
#include <stdbool.h>
#include <stdio.h>
#include "config.h"
@ -7,6 +8,7 @@
#include "animations/snake.h"
#include "animations/program.h"
#include "animations/matrix.h"
#include "animations/dna.h"
#include "animations/gameoflife.h"
#include "animations/stonefly.h"
#include "animations/flyingdots.h"
@ -48,7 +50,7 @@
# include "joystick/joystick.h"
#endif
volatile unsigned char oldMode, oldOldmode, mode;
volatile unsigned char oldMode, oldOldmode, reverseMode, mode;
jmp_buf newmode_jmpbuf;
@ -65,6 +67,12 @@ void display_loop(){
// mcuf_serial_mode();
mode = setjmp(newmode_jmpbuf);
#ifdef JOYSTICK_SUPPORT
// in case we get here via mode jump, we (re)enable joystick queries
waitForFire = 1;
#endif
oldOldmode = oldMode;
#ifdef JOYSTICK_SUPPORT
@ -76,6 +84,7 @@ void display_loop(){
clear_screen(0);
#endif
oldMode = mode;
switch(mode++) {
#ifdef ANIMATION_SCROLLTEXT
@ -85,7 +94,8 @@ void display_loop(){
#ifdef RANDOM_SUPPORT
{
char a[28];
sprintf(a,"</# counter == %lu ", (unsigned long) percnt_get());
sprintf(a,"</# counter == %lu ",
(unsigned long)percnt_get(&g_reset_counter, &g_reset_counter_idx));
scrolltext(a);
}
#endif
@ -250,22 +260,28 @@ void display_loop(){
break;
#endif
#ifdef ANIMATION_DNA
case 26:
dna();
break;
#endif
#ifdef ANIMATION_TESTS
case 31:
test_level(1);
test_level(1, false);
break;
case 32:
test_level(2);
test_level(2, false);
break;
case 33:
test_level(3);
test_level(3, false);
break;
case 35:
test_palette();
test_palette2();
test_palette(false);
test_palette2(false);
break;
#endif
@ -292,26 +308,26 @@ void display_loop(){
#endif
#ifdef MENU_SUPPORT
case 42:
case 0xFDu:
mode = 1;
break;
case 43:
case 0xFEu:
menu();
mode = oldOldmode;
break;
#else
case 42:
case 0xFDu:
#ifdef JOYSTICK_SUPPORT
if (JOYISFIRE)
mode = 43;
mode = 0xFEu;
else
#endif
mode = 1;
break;
case 43:
case 0xFEu:
#ifdef JOYSTICK_SUPPORT
waitForFire = 0; // avoid circular jumps
while (JOYISFIRE); // wait until user released the fire button
@ -354,10 +370,19 @@ void display_loop(){
#endif
#ifdef ANIMATION_OFF
case 0xFF:
case 0xFFu:
off();
break;
#endif
default:
if (reverseMode) {
if (reverseMode-- == (mode - 1)) {
mode -= 2;
} else {
reverseMode = 0;
}
}
break;
}
}
}

View File

@ -7,7 +7,13 @@ comment "Games"
endmenu
dep_bool "Space Invaders" GAME_SPACE_INVADERS $JOYSTICK_SUPPORT $RANDOM_SUPPORT
dep_bool "Snake" GAME_SNAKE $JOYSTICK_SUPPORT $RANDOM_SUPPORT
dep_bool_menu "Snake" GAME_SNAKE y $JOYSTICK_SUPPORT $RANDOM_SUPPORT
bool "POV Controls" SNAKE_POV_CONTROL n
int "Snake Game Round Delay" SNAKE_GAME_DELAY 200
endmenu
dep_bool "Breakout" GAME_BREAKOUT $JOYSTICK_SUPPORT $RANDOM_SUPPORT
dep_bool "Kart" GAME_KART $JOYSTICK_SUPPORT $RANDOM_SUPPORT
endmenu

View File

@ -224,7 +224,7 @@ void kart_game(){
wait(WAIT);
}
snprintf(game_over, sizeof(game_over), "</#Game Over, Score: %i", cycle);
snprintf(game_over, sizeof(game_over), "</#Game Over, Score: %lu", cycle);
scrolltext(game_over);
}

View File

@ -12,6 +12,7 @@
#include <assert.h>
#include <stdint.h>
#include <stdbool.h>
#include "../../config.h"
#include "../../compat/pgmspace.h"
#include "../../pixel.h"
@ -36,11 +37,13 @@ game_descriptor_t snake_game_descriptor __attribute__((section(".game_descriptor
#endif
/**
* If defined, joystick controls are NOT as "seen" by the snake but absolute,
* that is, if pressing up, snake goes up, etc.
*/
#define SNAKE_NEWCONTROL
#ifdef DOXYGEN
/**
* If defined, joystick controls are bound to the point of view of the
* snake, i.e. only the left an right joystick direction can be used.
*/
#define SNAKE_POV_CONTROL
#endif
#if !defined USNAKE_MAX_LENGTH || defined DOXYGEN
/** The maximum length of the snake. */
@ -102,6 +105,8 @@ typedef struct snake_protagonist_s
uint8_t nHeadIndex; /**< Index of the head segment. */
uint8_t nTailIndex; /**< Index of the tail segment. */
snake_dir_t dir; /**< Direction of the snake. */
bool bJoystickLocked; /**< Avoid double joytick queries
between movements. */
} snake_protagonist_t;
@ -213,6 +218,7 @@ static void snake_initGameProtagonist(snake_protagonist_t *pprotSnake)
#endif
pprotSnake->nTailIndex = 0;
pprotSnake->nHeadIndex = 1;
pprotSnake->bJoystickLocked = false;
}
#ifdef GAME_SNAKE
@ -225,17 +231,10 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
snake_dir_t *pdirLast)
{
snake_dir_t dirJoystick = snake_queryJoystick();
#ifdef SNAKE_NEWCONTROL
if (dirJoystick != SNAKE_DIR_NONE)
{
// valid transitions can only be uneven
if ((pprotSnake->dir + dirJoystick) & 0x01)
{
pprotSnake->dir = dirJoystick;
}
}
#else
if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE))
# ifdef SNAKE_POV_CONTROL
if ((dirJoystick ^ *pdirLast) && (dirJoystick != SNAKE_DIR_NONE) &&
(!pprotSnake->bJoystickLocked))
{
// only left or right movements are valid
if (dirJoystick & 0x01)
@ -244,9 +243,25 @@ static void snake_userControl(snake_protagonist_t *pprotSnake,
pprotSnake->dir = (pprotSnake->dir +
(dirJoystick == SNAKE_DIR_LEFT ? 3 : 1)) % 4u;
}
// we query the joystick twice as fast as we move the snake, so we
// have to ensure that it does not bite its head with its head...uh
pprotSnake->bJoystickLocked = true;
}
*pdirLast = dirJoystick;
#endif
# else
if (dirJoystick != SNAKE_DIR_NONE)
{
// valid transitions can only be uneven
if (((pprotSnake->dir + dirJoystick) & 0x01) &&
!pprotSnake->bJoystickLocked)
{
pprotSnake->dir = dirJoystick;
}
// we query the joystick twice as fast as we move the snake, so we
// have to ensure that it does not bite its head with its head...uh
pprotSnake->bJoystickLocked = true;
}
# endif
}
#endif
@ -362,9 +377,9 @@ static void snake_initApples(snake_apples_t *pApples)
* Checks for an apple at a given position and removes it if there is one.
* @param pApples The set of apples which are lying on the playing field.
* @param pxHead The position to be tested.
* @return 0 if no apples were found, 1 otherwise
* @return false if no apples were found, true otherwise
*/
static uint8_t snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
static bool snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
{
for (uint8_t i = pApples->nAppleCount; i--;)
{
@ -376,10 +391,10 @@ static uint8_t snake_checkForApple(snake_apples_t *pApples, pixel pxHead)
pApples->aApples[i] = pApples->aApples[i + 1];
}
--pApples->nAppleCount;
return 1;
return true;
}
}
return 0;
return false;
}
@ -419,7 +434,7 @@ void snake_engine(uint8_t bDemoMode)
clear_screen(0);
snake_drawBorder();
for (uint8_t nTick = 0; 1; nTick ^= SNAKE_COLOR_APPLE)
for (uint8_t nTick = 0; true; nTick ^= SNAKE_COLOR_APPLE)
{
// determine new direction
#if defined ANIMATION_SNAKE && defined GAME_SNAKE
@ -439,6 +454,8 @@ void snake_engine(uint8_t bDemoMode)
snake_userControl(&protSnake, &dirLast);
if (nTick) {
#endif
// release joystick lock
protSnake.bJoystickLocked = false;
// actually move head
pixel pxOldHead = protSnake.aSegments[protSnake.nHeadIndex];

View File

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

View File

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

View File

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

View File

@ -50,11 +50,11 @@
#define TETRIS_INPUT_REPEAT_DELAY 5
/** Number of loop cyles the left button is ignored */
#define TETRIS_INPUT_CHATTER_TICKS_LEFT 12
#define TETRIS_INPUT_CHATTER_TICKS_LEFT 24
/** Number of loop cyles the right button is ignored */
#define TETRIS_INPUT_CHATTER_TICKS_RIGHT 12
#define TETRIS_INPUT_CHATTER_TICKS_RIGHT 24
/** Number of loop cyles the down button is ignored */
#define TETRIS_INPUT_CHATTER_TICKS_DOWN 12
#define TETRIS_INPUT_CHATTER_TICKS_DOWN 24
/** Number of loop cyles the clockwise rotation button is ignored */
#define TETRIS_INPUT_CHATTER_TICKS_ROT_CW 24
/** Number of loop cyles the counter clockwise rotation button is ignored */

View File

@ -52,7 +52,8 @@
/** color of line counter */
#define TETRIS_VIEW_COLORCOUNTER 2
#if (NUM_ROWS < 16) && (NUM_COLS > NUM_ROWS) && (!defined GAME_TETRIS_FP)
#if (((NUM_ROWS < 16) && (NUM_COLS > NUM_ROWS)) || \
((NUM_ROWS == 16) && (NUM_COLS == 80))) && (!defined GAME_TETRIS_FP)
# define VIEWCOLS NUM_ROWS
# define VIEWROWS NUM_COLS
# define VIEW_TILT
@ -77,7 +78,8 @@
#if VIEWROWS >= 16
#define TETRIS_VIEW_XOFFSET_COUNTER \
(TETRIS_VIEW_XOFFSET_DUMP + TETRIS_VIEW_WIDTH_DUMP + 1)
#define TETRIS_VIEW_YOFFSET_COUNT100 ((VIEWCOLS - 14) / 2)
#define TETRIS_VIEW_YOFFSET_COUNT100 + \
TETRIS_VIEW_YOFFSET_DUMP + ((TETRIS_VIEW_HEIGHT_DUMP - 14) / 2)
#define TETRIS_VIEW_YOFFSET_COUNT10 (TETRIS_VIEW_YOFFSET_COUNT100 + 2)
#define TETRIS_VIEW_YOFFSET_COUNT1 (TETRIS_VIEW_YOFFSET_COUNT10 + 4)

View File

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

View File

@ -9,101 +9,103 @@
#include "../compat/interrupt.h" /* cli() & sei() */
#include "../compat/eeprom.h"
#include "../config.h"
#include "persistentCounter.h"
#ifdef ERROR_HANDLING
#include "error-handling.h"
#define PERSISTENT_COUNTER_OVERFLOW (void*)0, 2,4,1
#define PERSISTENT_COUNTER_WRITER_ERROR (void*)0, 2,4,2
# include "error-handling.h"
# define PERSISTENT_COUNTER_OVERFLOW (void*)0, 2,4,1
# define PERSISTENT_COUNTER_WRITER_ERROR (void*)0, 2,4,2
#endif
#define RING_SIZE 168
uint8_t ring_idx = 0xff;
uint16_t EEMEM B08_23;
uint8_t EEMEM B0_7[RING_SIZE];
uint8_t g_reset_counter_idx = 0xff;
percnt_t EEMEM g_reset_counter;
#ifdef INIT_EEPROM
void init_buffer(void){
void init_buffer(percnt_t *percnt, uint8_t *ring_index) {
uint8_t i;
eeprom_busy_wait();
eeprom_write_word(&B08_23, 0x0000);
for(i=0; i<RING_SIZE; ++i){
eeprom_write_word(&(percnt->B08_23), 0x0000);
for (i = 0; i < RING_SIZE; ++i) {
eeprom_busy_wait();
eeprom_write_byte(&(B0_7[i]), 0x00);
eeprom_write_byte(&(percnt->B0_7[i]), 0x00);
}
}
#endif
void percnt_init(void){
void percnt_init(percnt_t *percnt, uint8_t *ring_index) {
uint8_t i;
uint8_t maxidx=0;
uint8_t t,max=eeprom_read_byte(&(B0_7[0]));
#ifdef INIT_EEPROM
if (eeprom_read_word(&B08_23)==0xFFFF){ /* test if the 2 MSB == 0xFFFF*/
if (eeprom_read_word((uint16_t*)&(B0_7[0]))==0xFFFF) /* test the first to bytes of ringbuffer*/
init_buffer();
}
#endif
for(i=0; i<RING_SIZE; ++i){ /* this might be speed up, but such optimisation could lead to timing attacks */
uint8_t maxidx = 0;
uint8_t t, max = eeprom_read_byte(&(percnt->B0_7[0]));
#ifdef INIT_EEPROM
/* test if the 2 MSB == 0xFFFF */
if (eeprom_read_word(&(percnt->B08_23)) == 0xFFFF) {
/* test the first two bytes of ringbuffer */
if (eeprom_read_word((uint16_t*) &(percnt->B0_7[0])) == 0xFFFF)
init_buffer(percnt, ring_index);
}
#endif
/* might be faster, but such optimizations are prone to timing attacks */
for (i = 0; i < RING_SIZE; ++i) {
eeprom_busy_wait();
t=eeprom_read_byte(&(B0_7[i]));
if(t==max+1){
max=t;
maxidx=i;
t = eeprom_read_byte(&(percnt->B0_7[i]));
if (t == max + 1) {
max = t;
maxidx = i;
}
}
ring_idx = (maxidx==RING_SIZE)?0:maxidx;
*ring_index = (maxidx == RING_SIZE) ? 0 : maxidx;
}
uint32_t percnt_get(void){
uint32_t ret=0;
uint32_t percnt_get(percnt_t *percnt, uint8_t *ring_index) {
uint32_t ret = 0;
if(ring_idx==0xff)
percnt_init();
if (*ring_index == 0xff)
percnt_init(percnt, ring_index);
cli();
eeprom_busy_wait();
ret=eeprom_read_word(&B08_23)<<8;
ret = eeprom_read_word(&(percnt->B08_23)) << 8;
eeprom_busy_wait();
ret |= eeprom_read_byte(&(B0_7[ring_idx]));
ret |= eeprom_read_byte(&(percnt->B0_7[*ring_index]));
sei();
return ret;
}
void percnt_inc(void){
void percnt_inc(percnt_t *percnt, uint8_t *ring_index) {
/* we must make this resistant agaist power off while this is running ... */
uint32_t u;
if(ring_idx==0xff)
percnt_init();
if (*ring_index == 0xff)
percnt_init(percnt, ring_index);
u = percnt_get();
u = percnt_get(percnt, ring_index);
cli();
/* it's important to write msb first! */
if((u&0x000000ff) == 0xff){
if((u&0x0000ffff) == 0xffff){
if((u&0x00ffffff) == 0xffffff){
if ((u & 0x000000ff) == 0xff) {
if ((u & 0x0000ffff) == 0xffff) {
if ((u & 0x00ffffff) == 0xffffff) {
/* we can turn the lights off now. it's time to die */
#ifdef ERROR_HANDLING
#ifdef ERROR_HANDLING
error(PERSISTENT_COUNTER_OVERFLOW);
#endif
#endif
}
eeprom_busy_wait();
eeprom_write_byte(&(((uint8_t*)&B08_23)[1]),((u+1)>>16)&0xff);
eeprom_write_byte(&(((uint8_t*) &(percnt->B08_23))[1]),
((u + 1) >> 16) & 0xff);
}
eeprom_busy_wait();
eeprom_write_byte(&(((uint8_t*)&B08_23)[0]),((u+1)>>8)&0xff);
eeprom_write_byte(&(((uint8_t*) &(percnt->B08_23))[0]),
((u + 1) >> 8) & 0xff);
}
/* set least significant byte (in ringbuffer) */
ring_idx = (ring_idx+1)%RING_SIZE;
*ring_index = (*ring_index + 1) % RING_SIZE;
eeprom_busy_wait();
eeprom_write_byte(&(B0_7[ring_idx]),(u+1)&0xff);
eeprom_write_byte(&(percnt->B0_7[*ring_index]), (u + 1) & 0xff);
eeprom_busy_wait();
if(u+1 != percnt_get()){
#ifdef ERROR_HANDLING
if (u + 1 != percnt_get(percnt, ring_index)) {
#ifdef ERROR_HANDLING
error(PERSISTENT_COUNTER_WRITER_ERROR);
#endif
#endif
}
sei();

View File

@ -9,15 +9,22 @@
#ifndef PERSISTENTCOUNTER_H_
#define PERSISTENTCOUNTER_H_
#include <stdint.h>
#include "../compat/eeprom.h"
#define PERSISTENT_COUNTER_BITS 24
#define RING_SIZE 168
void percnt_init(void);
uint32_t percnt_get(void);
void percnt_inc(void);
typedef struct percnt_s {
uint16_t B08_23;
uint8_t B0_7[RING_SIZE];
} percnt_t;
extern uint8_t g_reset_counter_idx;
extern percnt_t g_reset_counter EEMEM;
void percnt_init(percnt_t *percnt, uint8_t *ring_index);
uint32_t percnt_get(percnt_t *percnt, uint8_t *ring_index);
void percnt_inc(percnt_t *percnt, uint8_t *ring_index);
#endif /*PERSISTENTCOUNTER_H_*/

View File

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

View File

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

View File

@ -455,7 +455,7 @@ void wait(int ms)
{
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/interrupt.h>
#include <stdlib.h>
#include "config.h"
#include <avr/pgmspace.h>
#include "uart.h"
#ifdef ATMEGA128
#define UCSRB UCSR0B
#define UCSRC UCSR0C
#define UDR UDR0
#define UBRRH UBRR0H
#define UBRRL UBRR0L
#define URSEL UMSEL
/*
* constants and macros
*/
/* size of RX/TX buffers */
#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)
#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)
#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )
#error RX buffer size is not a power of 2
#endif
#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )
#error TX buffer size is not a power of 2
#endif
#if defined(__AVR_AT90S2313__) \
|| defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \
|| defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \
|| defined(__AVR_ATmega103__)
/* old AVR classic or ATmega103 with one UART */
#define AT90_UART
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS USR
#define UART0_CONTROL UCR
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)
/* old AVR classic with one UART */
#define AT90_UART
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega323__)
/* ATmega with one USART */
#define ATMEGA_USART
#define UART0_RECEIVE_INTERRUPT USART_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#elif defined (__AVR_ATmega8515__) || defined(__AVR_ATmega8535__)
#define ATMEGA_USART
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#elif defined(__AVR_ATmega163__)
/* ATmega163 with one UART */
#define ATMEGA_UART
#define UART0_RECEIVE_INTERRUPT UART_RX_vect
#define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#elif defined(__AVR_ATmega162__)
/* ATmega with two USART */
#define ATMEGA_USART0
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RXC_vect
#define UART1_RECEIVE_INTERRUPT USART1_RXC_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
/* ATmega with two USART */
#define ATMEGA_USART0
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#elif defined(__AVR_ATmega161__)
/* ATmega with UART */
#error "AVR ATmega161 currently not supported by this libaray !"
#elif defined(__AVR_ATmega169__)
/* ATmega with one USART */
#define ATMEGA_USART
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) \
|| defined(__AVR_ATmega3250__) || defined(__AVR_ATmega3290__) ||defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6490__)
/* ATmega with one USART */
#define ATMEGA_USART0
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#elif defined(__AVR_ATtiny2313__)
#define ATMEGA_USART
#define UART0_RECEIVE_INTERRUPT USART_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect
#define UART0_STATUS UCSRA
#define UART0_CONTROL UCSRB
#define UART0_DATA UDR
#define UART0_UDRIE UDRIE
#elif defined(__AVR_ATmega329__) || \
defined(__AVR_ATmega649__) || \
defined(__AVR_ATmega325__) || \
defined(__AVR_ATmega645__)
/* ATmega with one USART */
#define ATMEGA_USART0
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__)
/* ATmega with two USART */
#define ATMEGA_USART0
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#elif defined(__AVR_ATmega644__)
/* ATmega with one USART */
#define ATMEGA_USART0
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
/* ATmega with two USART */
#define ATMEGA_USART0
#define ATMEGA_USART1
#define UART0_RECEIVE_INTERRUPT USART0_RX_vect
#define UART1_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect
#define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR0A
#define UART0_CONTROL UCSR0B
#define UART0_DATA UDR0
#define UART0_UDRIE UDRIE0
#define UART1_STATUS UCSR1A
#define UART1_CONTROL UCSR1B
#define UART1_DATA UDR1
#define UART1_UDRIE UDRIE1
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__)
/* AT90USBxx with one USART */
#define AT90USB_USART
#define UART0_RECEIVE_INTERRUPT USART1_RX_vect
#define UART0_TRANSMIT_INTERRUPT USART1_UDRE_vect
#define UART0_STATUS UCSR1A
#define UART0_CONTROL UCSR1B
#define UART0_DATA UDR1
#define UART0_UDRIE UDRIE1
#elif defined __AVR
#error "no UART definition for MCU available"
#endif
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16L))
/*
* module global variables
*/
static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART_TxHead;
static volatile unsigned char UART_TxTail;
static volatile unsigned char UART_RxHead;
static volatile unsigned char UART_RxTail;
static volatile unsigned char UART_LastRxError;
#ifdef UART_INTERRUPT
volatile static char rxbuf[UART_RXBUFSIZE];
volatile static char txbuf[UART_TXBUFSIZE];
volatile static char *volatile rxhead, *volatile rxtail;
volatile static char *volatile txhead, *volatile txtail;
ISR(USART_UDRE_vect) {
#ifdef UART_LEDS
PORTC ^= 0x01;
#if defined( ATMEGA_USART1 ) && defined (USE_UART1)
static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];
static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];
static volatile unsigned char UART1_TxHead;
static volatile unsigned char UART1_TxTail;
static volatile unsigned char UART1_RxHead;
static volatile unsigned char UART1_RxTail;
static volatile unsigned char UART1_LastRxError;
#endif
if ( txhead == txtail ) {
UCSRB &= ~(1 << UDRIE); /* disable data register empty IRQ */
} else {
UDR = *txtail; /* schreibt das Zeichen x auf die Schnittstelle */
if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf;
}
}
ISR(USART_RXC_vect) {
int diff;
#ifdef UART_LEDS
PORTC ^= 0x02;
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
/* buffer full? */
diff = rxhead - rxtail;
if ( diff < 0 ) diff += UART_RXBUFSIZE;
if (diff < UART_RXBUFSIZE -1) {
// buffer NOT full
*rxhead = UDR;
if (++rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
} else {
UDR; //reads the buffer to clear the interrupt condition
}
/* 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{
/* store new index */
UART_RxHead = tmphead;
/* store received data in buffer */
UART_RxBuf[tmphead] = data;
}
UART_LastRxError |= lastRxError;
}
#endif // UART_INTERRUPT
void uart_init() {
PORTD |= 0x01; //Pullup an RXD an
UCSRA = 0;
UCSRB |= (1<<TXEN); //UART TX einschalten
UCSRC |= (1<<URSEL)|(3<<UCSZ0); //Asynchron 8N1
UCSRB |= ( 1 << RXEN ); //Uart RX einschalten
// UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
// UBRRL=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU));
UBRRL = 8;
#ifdef UART_INTERRUPT
// init buffers
rxhead = rxtail = rxbuf;
txhead = txtail = txbuf;
// activate rx IRQ
UCSRB |= (1 << RXCIE);
#endif // UART_INTERRUPT
}
#ifdef UART_INTERRUPT
void uart_putc(char c) {
volatile int diff;
/* buffer full? */
do {
diff = txhead - txtail;
if ( diff < 0 ) diff += UART_TXBUFSIZE;
} while ( diff >= UART_TXBUFSIZE -1 );
cli();
*txhead = c;
if (++txhead == (txbuf + UART_TXBUFSIZE)) txhead = txbuf;
UCSRB |= (1 << UDRIE); /* enable data register empty IRQ */
sei();
}
#else // WITHOUT INTERRUPT
void uart_putc(char c) {
while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
UDR = c; /* schreibt das Zeichen x auf die Schnittstelle */
}
#endif // UART_INTERRUPT
void uart_putstr(char *str) {
while(*str) {
uart_putc(*str++);
}
}
void uart_putstr_P(PGM_P str) {
char tmp;
while((tmp = pgm_read_byte(str))) {
uart_putc(tmp);
str++;
}
}
void uart_hexdump(char *buf, int len)
ISR (UART0_TRANSMIT_INTERRUPT)
/*************************************************************************
Function: UART Data Register Empty interrupt
Purpose: called when the UART is ready to transmit the next byte
**************************************************************************/
{
unsigned char x=0;
char sbuf[3];
unsigned char tmptail;
while(len--){
itoa(*buf++, sbuf, 16);
if (sbuf[1] == 0) uart_putc(' ');
uart_putstr(sbuf);
uart_putc(' ');
if(++x == 16) {
uart_putstr_P(PSTR("\r\n"));
x = 0;
}
}
if ( 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);
}
}
#ifdef UART_INTERRUPT
char uart_getc()
/*************************************************************************
Function: uart_init()
Purpose: initialize UART and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
**************************************************************************/
void uart_init(unsigned int baudrate)
{
char val;
UART_TxHead = 0;
UART_TxTail = 0;
UART_RxHead = 0;
UART_RxTail = 0;
while(rxhead==rxtail) ;
#if defined( AT90_UART )
/* set baud rate */
UBRR = (unsigned char)baudrate;
val = *rxtail;
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
/* enable UART receiver and transmmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);
return val;
}
#else // WITHOUT INTERRUPT
char uart_getc()
#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
#elif defined (ATMEGA_USART0 )
/* Set baud rate */
if ( baudrate & 0x8000 )
{
UART0_STATUS = (1<<U2X0); //Enable 2x speed
baudrate &= ~0x8000;
}
UBRR0H = (unsigned char)(baudrate>>8);
UBRR0L = (unsigned char) baudrate;
/* Enable USART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef URSEL0
UCSR0C = (1<<URSEL0)|(3<<UCSZ00);
#else
UCSR0C = (3<<UCSZ00);
#endif
#elif defined ( ATMEGA_UART )
/* set baud rate */
if ( baudrate & 0x8000 )
{
UART0_STATUS = (1<<U2X); //Enable 2x speed
baudrate &= ~0x8000;
}
UBRRHI = (unsigned char)(baudrate>>8);
UBRR = (unsigned char) baudrate;
/* Enable UART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);
#elif defined ( AT90USB_USART )
/* set baud rate */
if ( baudrate & 0x8000 )
{
UART0_STATUS = (1<<U2X1 ); //Enable 2x speed
baudrate &= ~0x8000;
}
UBRR1H = (unsigned char)(baudrate>>8);
UBRR1L = (unsigned char) baudrate;
/* Enable UART receiver and transmitter and receive complete interrupt */
UART0_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
UCSR1C = (1<<UCSZ11)|(1<<UCSZ10);
#endif
}/* uart_init */
/*************************************************************************
Function: uart_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart_getc(void)
{
while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
return UDR; // Zeichen aus UDR zurueckgeben
}
#endif // UART_INTERRUPT
unsigned char tmptail;
unsigned char data;
// returns 1 on success
#ifdef UART_INTERRUPT
char uart_getc_nb(char *c)
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)
{
if (rxhead==rxtail) return 0;
unsigned char tmphead;
*c = *rxtail;
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
return 1;
}
#else // WITHOUT INTERRUPT
char uart_getc_nb(char *c)
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 )
{
if (UCSRA & (1<<RXC)) { // Zeichen verfuegbar
*c = UDR;
return 1;
}
while (*s)
uart_putc(*s++);
return 0;
}/* 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{
/* 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)
/*************************************************************************
Function: UART1 Data Register Empty interrupt
Purpose: called when the UART1 is ready to transmit the next byte
**************************************************************************/
{
unsigned char tmptail;
if ( UART1_TxHead != UART1_TxTail) {
/* calculate and store new buffer index */
tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;
UART1_TxTail = tmptail;
/* get one byte from buffer and write it to UART */
UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */
}else{
/* tx buffer empty, disable UDRE interrupt */
UART1_CONTROL &= ~_BV(UART1_UDRIE);
}
}
/*************************************************************************
Function: uart1_init()
Purpose: initialize UART1 and set baudrate
Input: baudrate using macro UART_BAUD_SELECT()
Returns: none
**************************************************************************/
void uart1_init(unsigned int baudrate)
{
UART1_TxHead = 0;
UART1_TxTail = 0;
UART1_RxHead = 0;
UART1_RxTail = 0;
/* Set baud rate */
if ( baudrate & 0x8000 )
{
UART1_STATUS = (1<<U2X1); //Enable 2x speed
baudrate &= ~0x8000;
}
UBRR1H = (unsigned char)(baudrate>>8);
UBRR1L = (unsigned char) baudrate;
/* Enable USART receiver and transmitter and receive complete interrupt */
UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef URSEL1
UCSR1C = (1<<URSEL1)|(3<<UCSZ10);
#else
UCSR1C = (3<<UCSZ10);
#endif
}/* uart_init */
/*************************************************************************
Function: uart1_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart1_getc(void)
{
unsigned char tmptail;
unsigned char data;
if ( UART1_RxHead == UART1_RxTail ) {
return UART_NO_DATA; /* no data available */
}
/* 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)
{
unsigned char tmphead;
tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
while ( tmphead == UART1_TxTail ){
;/* wait for free space in buffer */
}
UART1_TxBuf[tmphead] = data;
UART1_TxHead = tmphead;
/* enable UDRE interrupt */
UART1_CONTROL |= _BV(UART1_UDRIE);
}/* uart1_putc */
/*************************************************************************
Function: uart1_puts()
Purpose: transmit string to UART1
Input: string to be transmitted
Returns: none
**************************************************************************/
void uart1_puts(const char *s )
{
while (*s)
uart1_putc(*s++);
}/* uart1_puts */
/*************************************************************************
Function: uart1_puts_p()
Purpose: transmit string from program memory to UART1
Input: program memory string to be transmitted
Returns: none
**************************************************************************/
void uart1_puts_p(const char *progmem_s )
{
register char c;
while ( (c = pgm_read_byte(progmem_s++)) )
uart1_putc(c);
}/* uart1_puts_p */
#endif

View File

@ -1,35 +1,223 @@
#ifndef UART_H
#define UART_H
/************************************************************************
Title: Interrupt UART library with receive/transmit circular buffers
Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury
File: $Id: uart.h,v 1.12 2012/11/19 19:52:27 peter Exp $
Software: AVR-GCC 4.1, AVR Libc 1.4
Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz
License: GNU General Public License
Usage: see Doxygen manual
LICENSE:
Copyright (C) 2006 Peter Fleury
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
************************************************************************/
/**
* UART Library
* @defgroup pfleury_uart UART Library
* @code #include <uart.h> @endcode
*
* #define F_CPU 16000000 // Oszillator-Frequenz in Hz
* #define UART_INTERRUPT 1
* #define UART_BAUD_RATE 19200
* #define UART_RXBUFSIZE 16
* #define UART_TXBUFSIZE 16
* #define UART_LINE_BUFFER_SIZE 40
* #define UART_LEDS // LED1 and LED2 toggle on tx and rx interrupt
* @brief Interrupt UART library using the built-in UART with transmit and
* receive circular buffers.
*
* This library can be used to transmit and receive data through the built in
* UART.
*
* An interrupt is generated when the UART has finished transmitting or
* receiving a byte. The interrupt handling routines use circular buffers
* for buffering received and transmitted data.
*
* The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define the size of
* the circular buffers in bytes. Note that these constants must be a power of
* 2. You may need to adapt this constants to your target and your application
* by adding CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your
* Makefile.
*
* @note Based on Atmel Application Note AVR306
* @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury
*/
#include <inttypes.h>
#include <avr/pgmspace.h>
/**@{*/
void uart_init();
void uart_putc(char c);
void uart_putstr(char * str);
void uart_putstr_P(PGM_P str);
void uart_hexdump(char *buf, int len);
char uart_getc();
char uart_getc_nb(char *c); // returns 1 on success
//get one Cariage return terminated line
//echo charakters back on Uart
//returns buffer with zero terminated line on success, 0 pointer otherwise
char * uart_getline_nb();
#include "../config.h"
#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304
#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"
#endif
/*
* constants and macros
*/
/** @brief UART Baudrate Expression
* @param xtalcpu system clock in Mhz, e.g. 4000000UL for 4Mhz
* @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
*/
#define UART_BAUD_SELECT(baudRate,xtalCpu) \
(((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL)
/** @brief UART Baudrate Expression for ATmega double speed mode
* @param xtalcpu system clock in Mhz, e.g. 4000000UL for 4Mhz
* @param baudrate baudrate in bps, e.g. 1200, 2400, 9600
*/
#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) \
(((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000)
/** Size of the circular receive buffer, must be power of 2 */
#ifndef UART_RX_BUFFER_SIZE
#define UART_RX_BUFFER_SIZE 32
#endif
/** Size of the circular transmit buffer, must be power of 2 */
#ifndef UART_TX_BUFFER_SIZE
#define UART_TX_BUFFER_SIZE 32
#endif
/* test if the size of the circular buffers fits into SRAM */
#if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) && defined __AVR
#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"
#endif
/*
** high byte error return code of uart_getc()
*/
#define UART_FRAME_ERROR 0x1000 /* Framing Error by UART */
#define UART_OVERRUN_ERROR 0x0800 /* Overrun condition by UART */
#define UART_PARITY_ERROR 0x0400 /* Parity Error by UART */
#define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */
#define UART_NO_DATA 0x0100 /* no receive data available */
/*
** function prototypes
*/
/**
@brief Initialize UART and set baudrate
@param baudrate Specify baudrate using macro UART_BAUD_SELECT()
@return none
*/
extern void uart_init(unsigned int baudrate);
/**
* @brief Get received byte from ringbuffer
*
* Returns in the lower byte the received character and in the
* higher byte the last receive error.
* UART_NO_DATA is returned when no data is available.
*
* @param void
* @return lower byte: received byte from ringbuffer
* @return higher byte: last receive status
* - \b 0 successfully received data from UART
* - \b UART_NO_DATA
* <br>no receive data available
* - \b UART_BUFFER_OVERFLOW
* <br>Receive ringbuffer overflow.
* We are not reading the receive buffer fast enough,
* one or more received character have been dropped
* - \b UART_OVERRUN_ERROR
* <br>Overrun condition by UART.
* A character already present in the UART UDR register was not read
* by the interrupt handler before the next character arrived,
* one or more received characters have been dropped.
* - \b UART_FRAME_ERROR
* <br>Framing Error by UART
*/
extern unsigned int uart_getc(void);
/**
* @brief Put byte to ringbuffer for transmitting via UART
* @param data byte to be transmitted
* @return none
*/
extern void uart_putc(unsigned char data);
/**
* @brief Put string to ringbuffer for transmitting via UART
*
* The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts.
* Blocks if it can not write the whole string into the circular buffer.
*
* @param s string to be transmitted
* @return none
*/
extern void uart_puts(const char *s );
/**
* @brief Put string from program memory to ringbuffer for transmitting via
* UART.
*
* The string is buffered by the uart library in a circular buffer
* and one character at a time is transmitted to the UART using interrupts.
* Blocks if it can not write the whole string into the circular buffer.
*
* @param s program memory string to be transmitted
* @return none
* @see uart_puts_P
*/
extern void uart_puts_p(const char *s );
/**
* @brief Macro to automatically put a string constant into program memory
*/
#define uart_puts_P(__s) uart_puts_p(PSTR(__s))
#if defined USE_UART1 || defined DOXYGEN
/** @brief Initialize USART1 (only available on selected ATmegas)
* @see uart_init
*/
extern void uart1_init(unsigned int baudrate);
/** @brief Get received byte of USART1 from ringbuffer (only available on
* selected ATmega)
* @see uart_getc
*/
extern unsigned int uart1_getc(void);
/** @brief Put byte to ringbuffer for transmitting via USART1 (only available
* on selected ATmega)
* @see uart_putc
*/
extern void uart1_putc(unsigned char data);
/** @brief Put string to ringbuffer for transmitting via USART1 (only available
* on selected ATmega)
* @see uart_puts
*/
extern void uart1_puts(const char *s );
/** @brief Put string from program memory to ringbuffer for transmitting via
* USART1 (only available on selected ATmega)
* @see uart_puts_p
*/
extern void uart1_puts_p(const char *s );
/** @brief Macro to automatically put a string constant into program memory */
#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s))
/**@}*/
#endif // defined USE_UART1 || defined DOXYGEN
#endif // UART_H

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