From da17b0cdfbca93c59efb5c1be0a3c0921bb6fb82 Mon Sep 17 00:00:00 2001 From: olikraus Date: Sat, 4 Jun 2011 22:48:53 +0200 Subject: [PATCH] lcd --- .../LiquidCrystal/HelloWorld/HelloWorld.pde | 72 +++++ .../HelloWorld/Makefile.duemilanove | 271 +++++++++++++++++ .../LiquidCrystal/Radio/Makefile.duemilanove | 272 ++++++++++++++++++ arduino/LiquidCrystal/Radio/Radio.pde | 75 +++++ .../SimpleTest/Makefile.duemilanove | 271 +++++++++++++++++ .../LiquidCrystal/SimpleTest/SimpleTest.pde | 57 ++++ .../LiquidCrystal/U32/Makefile.duemilanove | 272 ++++++++++++++++++ arduino/LiquidCrystal/U32/U32.pde | 58 ++++ dev/LiquidCrystal/m2ghlc.h | 36 +++ dev/LiquidCrystal/m2ghlc16x4.cpp | 137 +++++++++ pic/lcd/Radio.jpg | Bin 0 -> 18045 bytes pic/lcd/U32.jpg | Bin 0 -> 12802 bytes txt/menu_system.txt | 2 + 13 files changed, 1523 insertions(+) create mode 100644 arduino/LiquidCrystal/HelloWorld/HelloWorld.pde create mode 100644 arduino/LiquidCrystal/HelloWorld/Makefile.duemilanove create mode 100644 arduino/LiquidCrystal/Radio/Makefile.duemilanove create mode 100644 arduino/LiquidCrystal/Radio/Radio.pde create mode 100644 arduino/LiquidCrystal/SimpleTest/Makefile.duemilanove create mode 100644 arduino/LiquidCrystal/SimpleTest/SimpleTest.pde create mode 100644 arduino/LiquidCrystal/U32/Makefile.duemilanove create mode 100644 arduino/LiquidCrystal/U32/U32.pde create mode 100644 dev/LiquidCrystal/m2ghlc.h create mode 100644 dev/LiquidCrystal/m2ghlc16x4.cpp create mode 100644 pic/lcd/Radio.jpg create mode 100644 pic/lcd/U32.jpg diff --git a/arduino/LiquidCrystal/HelloWorld/HelloWorld.pde b/arduino/LiquidCrystal/HelloWorld/HelloWorld.pde new file mode 100644 index 0000000..1e541c0 --- /dev/null +++ b/arduino/LiquidCrystal/HelloWorld/HelloWorld.pde @@ -0,0 +1,72 @@ +/* + + HelloWorld.pde + + Character LCD Example + + m2tklib = Mini Interative Interface Toolkit Library + + Copyright (C) 2011 olikraus@gmail.com + + 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 3 of the License, or + (at your option) 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include +#include "M2tk.h" + +LiquidCrystal lcd(12, 11, 5, 4, 3, 2); + +void setCursor(uint8_t x, uint8_t y) +{ + /* translate the x-y position from the m2tklib to the LiquidCrystal lib */ + /* assume 16x4 display */ + + y = 3-y; + + if ( y >= 2 ) + { + x+=16; + y-=2; + } + + lcd.setCursor(x, y); +} + +uint8_t m2_gh_liquid_crystal(m2_gfx_arg_p arg) +{ + switch(arg->msg) + { + case M2_GFX_MSG_INIT: + lcd.begin(16, 4); + break; + case M2_GFX_MSG_DRAW_TEXT: + setCursor(arg->x, arg->y); + lcd.print(arg->s); + break; + } + return m2_gh_dummy(arg); +} + +M2_LABEL(hello_world_label, NULL, "Hello World!"); +M2tk m2(&hello_world_label, NULL, NULL, m2_gh_liquid_crystal); + +void setup() { +} + +void loop() { + m2.draw(); +} + + diff --git a/arduino/LiquidCrystal/HelloWorld/Makefile.duemilanove b/arduino/LiquidCrystal/HelloWorld/Makefile.duemilanove new file mode 100644 index 0000000..b828e5a --- /dev/null +++ b/arduino/LiquidCrystal/HelloWorld/Makefile.duemilanove @@ -0,0 +1,271 @@ + +# +# Arduino 0022 Makefile +# +# written by olikraus@gmail.com +# +# Features: +# - boards.txt is used to derive parameters +# - All intermediate files are put into a separate directory (TMPDIRNAME) +# - Simple use: Copy Makefile into the same directory of the .pde file +# +# Limitations: +# - requires UNIX environment +# - TMPDIRNAME must be subdirectory of the current directory. +# +# Targets +# all build everything +# upload build and upload to arduino +# clean remove all temporary files (includes final hex file) +# +# History +# 001 28 Apr 2010 first release +# 002 05 Oct 2010 added 'uno' +# 003 07 May 2011 m2 version +# + +#=== user configuration === +# All ...PATH variables must have a '/' at the end + +# Board (and prozessor) information: see $(ARDUINO_PATH)hardware/arduino/boards.txt +# Some examples: +# BOARD DESCRIPTION +# uno Arduino Uno +# atmega328 Arduino Duemilanove or Nano w/ ATmega328 +# diecimila Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 +# mega Arduino Mega +# mini Arduino Mini +# lilypad328 LilyPad Arduino w/ ATmega328 +BOARD:=atmega328 + +M2TKLIB_PATH:=/home/kraus/src/m2/m2tklib/src/ +M2DEV_PATH:=/home/kraus/src/m2/m2tklib/dev/LiquidCrystal/ + +# The location where the avr tools (e.g. avr-gcc) are located. Requires a '/' at the end. +# Can be empty if all tools are accessable through the search path +AVR_TOOLS_PATH:=/usr/bin/ + +# Install path of the arduino software. Requires a '/' at the end. +ARDUINO_PATH:=/home/kraus/prg/arduino-0022/ + +# Install path for avrdude. Requires a '/' at the end. Can be empty if avrdude is in the search path. +AVRDUDE_PATH:= + +# The unix device where we can reach the arduino board +# Uno: /dev/ttyACM0 +# Duemilanove: /dev/ttyUSB0 +AVRDUDE_PORT:=/dev/ttyUSB0 + +# List of all libaries which should be included. +EXTRA_DIRS=$(ARDUINO_PATH)libraries/LiquidCrystal/ +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/dev/arduino/ +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/cpp/ + +#=== fetch parameter from boards.txt processor parameter === +# the basic idea is to get most of the information from boards.txt + +BOARDS_TXT:=$(ARDUINO_PATH)hardware/arduino/boards.txt + +# get the MCU value from the $(BOARD).build.mcu variable. For the atmega328 board this is atmega328p +MCU:=$(shell sed -n -e "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the F_CPU value from the $(BOARD).build.f_cpu variable. For the atmega328 board this is 16000000 +F_CPU:=$(shell sed -n -e "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_TXT)) + +# avrdude +# get the AVRDUDE_UPLOAD_RATE value from the $(BOARD).upload.speed variable. For the atmega328 board this is 57600 +AVRDUDE_UPLOAD_RATE:=$(shell sed -n -e "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the AVRDUDE_PROGRAMMER value from the $(BOARD).upload.protocol variable. For the atmega328 board this is stk500 +# AVRDUDE_PROGRAMMER:=$(shell sed -n -e "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_TXT)) +# use stk500v1, because stk500 will default to stk500v2 +AVRDUDE_PROGRAMMER:=stk500v1 + +#=== identify user files === +PDESRC:=$(shell ls *.pde) +TARGETNAME=$(basename $(PDESRC)) + +CDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CDIRS:=*.c utility/*.c $(M2TKLIB_PATH)*.c $(M2DEV_PATH)*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +#CDIRS:=*.c utility/*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +CSRC:=$(shell ls $(CDIRS) 2>/dev/null) + +CCSRC:=$(shell ls *.cc 2>/dev/null) + +CPPDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CPPDIRS:=*.cpp utility/*.cpp $(addsuffix *.cpp,$(CPPDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.cpp +CPPSRC:=$(shell ls $(CPPDIRS) 2>/dev/null) + +#=== build internal variables === + +# the name of the subdirectory where everything is stored +TMPDIRNAME:=tmp +TMPDIRPATH:=$(TMPDIRNAME)/ + +AVRTOOLSPATH:=$(AVR_TOOLS_PATH) + +OBJCOPY:=$(AVRTOOLSPATH)avr-objcopy +OBJDUMP:=$(AVRTOOLSPATH)avr-objdump +SIZE:=$(AVRTOOLSPATH)avr-size + +CPPSRC:=$(addprefix $(TMPDIRPATH),$(PDESRC:.pde=.cpp)) $(CPPSRC) + +COBJ:=$(CSRC:.c=.o) +CCOBJ:=$(CCSRC:.cc=.o) +CPPOBJ:=$(CPPSRC:.cpp=.o) + +OBJFILES:=$(COBJ) $(CCOBJ) $(CPPOBJ) +DIRS:= $(dir $(OBJFILES)) + +DEPFILES:=$(OBJFILES:.o=.d) +# assembler files from avr-gcc -S +ASSFILES:=$(OBJFILES:.o=.s) +# disassembled object files with avr-objdump -S +DISFILES:=$(OBJFILES:.o=.dis) + + +LIBNAME:=$(TMPDIRPATH)$(TARGETNAME).a +ELFNAME:=$(TMPDIRPATH)$(TARGETNAME).elf +HEXNAME:=$(TMPDIRPATH)$(TARGETNAME).hex + +AVRDUDE_FLAGS = -V -F +AVRDUDE_FLAGS += -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf +AVRDUDE_FLAGS += -p $(MCU) +AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) +AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += -b $(AVRDUDE_UPLOAD_RATE) +AVRDUDE_FLAGS += -U flash:w:$(HEXNAME) + +AVRDUDE = avrdude + +#=== predefined variable override === +# use "make -p -f/dev/null" to see the default rules and definitions + +# Build C and C++ flags. Include path information must be placed here +COMMON_FLAGS = -DF_CPU=$(F_CPU) -mmcu=$(MCU) $(DEFS) +# COMMON_FLAGS += -gdwarf-2 +COMMON_FLAGS += -Os +COMMON_FLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections +COMMON_FLAGS += -Wl,--relax +COMMON_FLAGS += -mcall-prologues +COMMON_FLAGS += -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +COMMON_FLAGS += -I. -I$(M2TKLIB_PATH) -I$(M2DEV_PATH) +COMMON_FLAGS += -I$(ARDUINO_PATH)hardware/arduino/cores/arduino +COMMON_FLAGS += $(addprefix -I,$(EXTRA_DIRS)) $(addprefix -I,$(addsuffix utility/,$(EXTRA_DIRS))) + +CFLAGS = $(COMMON_FLAGS) -std=gnu99 -Wstrict-prototypes +CXXFLAGS = $(COMMON_FLAGS) + +# Replace standard build tools by avr tools +CC = $(AVRTOOLSPATH)avr-gcc +CXX = $(AVRTOOLSPATH)avr-g++ +AR = @$(AVRTOOLSPATH)avr-ar + + +# "rm" must be able to delete a directory tree +RM = rm -rf + +#=== rules === + +# add rules for the C/C++ files where the .o file is placed in the TMPDIRPATH +# reuse existing variables as far as possible + +$(TMPDIRPATH)%.o: %.c + @echo compile $< + @$(COMPILE.c) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cc + @echo compile $< + @$(COMPILE.cc) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cpp + @echo compile $< + @$(COMPILE.cpp) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.s: %.c + @$(COMPILE.c) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cc + @$(COMPILE.cc) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cpp + @$(COMPILE.cpp) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.dis: $(TMPDIRPATH)%.o + @$(OBJDUMP) -S $< > $@ + +.SUFFIXES: .elf .hex .pde + +.elf.hex: + @$(OBJCOPY) -O ihex -R .eeprom $< $@ + +$(TMPDIRPATH)%.cpp: %.pde + @cat $(ARDUINO_PATH)hardware/arduino/cores/arduino/main.cpp > $@ + @cat $< >> $@ + @echo >> $@ + @echo 'extern "C" void __cxa_pure_virtual() { while (1); }' >> $@ + + +.PHONY: all +all: tmpdir $(HEXNAME) assemblersource showsize + ls -al $(HEXNAME) $(ELFNAME) + +$(ELFNAME): $(LIBNAME)($(addprefix $(TMPDIRPATH),$(OBJFILES))) + $(LINK.o) $(COMMON_FLAGS) $(LIBNAME) $(LOADLIBES) $(LDLIBS) -o $@ + +$(LIBNAME)(): $(addprefix $(TMPDIRPATH),$(OBJFILES)) + +#=== create temp directory === +# not really required, because it will be also created during the dependency handling +.PHONY: tmpdir +tmpdir: + @test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH) + +#=== create assembler files for each C/C++ file === +.PHONY: assemblersource +assemblersource: $(addprefix $(TMPDIRPATH),$(ASSFILES)) $(addprefix $(TMPDIRPATH),$(DISFILES)) + + +#=== show the section sizes of the ELF file === +.PHONY: showsize +showsize: $(ELFNAME) + $(SIZE) $< + +#=== clean up target === +# this is simple: the TMPDIRPATH is removed +.PHONY: clean +clean: + $(RM) $(TMPDIRPATH) + +# Program the device. +# step 1: reset the arduino board with the stty command +# step 2: user avrdude to upload the software +.PHONY: upload +upload: $(HEXNAME) + stty -F $(AVRDUDE_PORT) hupcl + $(AVRDUDE) $(AVRDUDE_FLAGS) + + +# === dependency handling === +# From the gnu make manual (section 4.14, Generating Prerequisites Automatically) +# Additionally (because this will be the first executed rule) TMPDIRPATH is created here. +# Instead of "sed" the "echo" command is used +# cd $(TMPDIRPATH); mkdir -p $(DIRS) 2> /dev/null; cd .. +DEPACTION=test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH);\ +mkdir -p $(addprefix $(TMPDIRPATH),$(DIRS));\ +set -e; echo -n $@ $(dir $@) > $@; $(CC) -MM $(COMMON_FLAGS) $< >> $@ + + +$(TMPDIRPATH)%.d: %.c + @$(DEPACTION) + +$(TMPDIRPATH)%.d: %.cc + @$(DEPACTION) + + +$(TMPDIRPATH)%.d: %.cpp + @$(DEPACTION) + +# Include dependency files. If a .d file is missing, a warning is created and the .d file is created +# This warning is not a problem (gnu make manual, section 3.3 Including Other Makefiles) +-include $(addprefix $(TMPDIRPATH),$(DEPFILES)) + + diff --git a/arduino/LiquidCrystal/Radio/Makefile.duemilanove b/arduino/LiquidCrystal/Radio/Makefile.duemilanove new file mode 100644 index 0000000..80b844d --- /dev/null +++ b/arduino/LiquidCrystal/Radio/Makefile.duemilanove @@ -0,0 +1,272 @@ + +# +# Arduino 0022 Makefile +# +# written by olikraus@gmail.com +# +# Features: +# - boards.txt is used to derive parameters +# - All intermediate files are put into a separate directory (TMPDIRNAME) +# - Simple use: Copy Makefile into the same directory of the .pde file +# +# Limitations: +# - requires UNIX environment +# - TMPDIRNAME must be subdirectory of the current directory. +# +# Targets +# all build everything +# upload build and upload to arduino +# clean remove all temporary files (includes final hex file) +# +# History +# 001 28 Apr 2010 first release +# 002 05 Oct 2010 added 'uno' +# 003 07 May 2011 m2 version +# + +#=== user configuration === +# All ...PATH variables must have a '/' at the end + +# Board (and prozessor) information: see $(ARDUINO_PATH)hardware/arduino/boards.txt +# Some examples: +# BOARD DESCRIPTION +# uno Arduino Uno +# atmega328 Arduino Duemilanove or Nano w/ ATmega328 +# diecimila Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 +# mega Arduino Mega +# mini Arduino Mini +# lilypad328 LilyPad Arduino w/ ATmega328 +BOARD:=atmega328 + +M2TKLIB_PATH:=/home/kraus/src/m2/m2tklib/src/ +M2DEV_PATH:=/home/kraus/src/m2/m2tklib/dev/LiquidCrystal/ + +# The location where the avr tools (e.g. avr-gcc) are located. Requires a '/' at the end. +# Can be empty if all tools are accessable through the search path +AVR_TOOLS_PATH:=/usr/bin/ + +# Install path of the arduino software. Requires a '/' at the end. +ARDUINO_PATH:=/home/kraus/prg/arduino-0022/ + +# Install path for avrdude. Requires a '/' at the end. Can be empty if avrdude is in the search path. +AVRDUDE_PATH:= + +# The unix device where we can reach the arduino board +# Uno: /dev/ttyACM0 +# Duemilanove: /dev/ttyUSB0 +AVRDUDE_PORT:=/dev/ttyUSB0 + +# List of all libaries which should be included. +EXTRA_DIRS=$(ARDUINO_PATH)libraries/LiquidCrystal/ +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/dev/arduino/ +EXTRA_DIRS+=$(M2DEV_PATH) +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/cpp/ + +#=== fetch parameter from boards.txt processor parameter === +# the basic idea is to get most of the information from boards.txt + +BOARDS_TXT:=$(ARDUINO_PATH)hardware/arduino/boards.txt + +# get the MCU value from the $(BOARD).build.mcu variable. For the atmega328 board this is atmega328p +MCU:=$(shell sed -n -e "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the F_CPU value from the $(BOARD).build.f_cpu variable. For the atmega328 board this is 16000000 +F_CPU:=$(shell sed -n -e "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_TXT)) + +# avrdude +# get the AVRDUDE_UPLOAD_RATE value from the $(BOARD).upload.speed variable. For the atmega328 board this is 57600 +AVRDUDE_UPLOAD_RATE:=$(shell sed -n -e "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the AVRDUDE_PROGRAMMER value from the $(BOARD).upload.protocol variable. For the atmega328 board this is stk500 +# AVRDUDE_PROGRAMMER:=$(shell sed -n -e "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_TXT)) +# use stk500v1, because stk500 will default to stk500v2 +AVRDUDE_PROGRAMMER:=stk500v1 + +#=== identify user files === +PDESRC:=$(shell ls *.pde) +TARGETNAME=$(basename $(PDESRC)) + +CDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CDIRS:=*.c utility/*.c $(M2TKLIB_PATH)*.c $(M2DEV_PATH)*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +#CDIRS:=*.c utility/*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +CSRC:=$(shell ls $(CDIRS) 2>/dev/null) + +CCSRC:=$(shell ls *.cc 2>/dev/null) + +CPPDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CPPDIRS:=*.cpp utility/*.cpp $(addsuffix *.cpp,$(CPPDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.cpp +CPPSRC:=$(shell ls $(CPPDIRS) 2>/dev/null) + +#=== build internal variables === + +# the name of the subdirectory where everything is stored +TMPDIRNAME:=tmp +TMPDIRPATH:=$(TMPDIRNAME)/ + +AVRTOOLSPATH:=$(AVR_TOOLS_PATH) + +OBJCOPY:=$(AVRTOOLSPATH)avr-objcopy +OBJDUMP:=$(AVRTOOLSPATH)avr-objdump +SIZE:=$(AVRTOOLSPATH)avr-size + +CPPSRC:=$(addprefix $(TMPDIRPATH),$(PDESRC:.pde=.cpp)) $(CPPSRC) + +COBJ:=$(CSRC:.c=.o) +CCOBJ:=$(CCSRC:.cc=.o) +CPPOBJ:=$(CPPSRC:.cpp=.o) + +OBJFILES:=$(COBJ) $(CCOBJ) $(CPPOBJ) +DIRS:= $(dir $(OBJFILES)) + +DEPFILES:=$(OBJFILES:.o=.d) +# assembler files from avr-gcc -S +ASSFILES:=$(OBJFILES:.o=.s) +# disassembled object files with avr-objdump -S +DISFILES:=$(OBJFILES:.o=.dis) + + +LIBNAME:=$(TMPDIRPATH)$(TARGETNAME).a +ELFNAME:=$(TMPDIRPATH)$(TARGETNAME).elf +HEXNAME:=$(TMPDIRPATH)$(TARGETNAME).hex + +AVRDUDE_FLAGS = -V -F +AVRDUDE_FLAGS += -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf +AVRDUDE_FLAGS += -p $(MCU) +AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) +AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += -b $(AVRDUDE_UPLOAD_RATE) +AVRDUDE_FLAGS += -U flash:w:$(HEXNAME) + +AVRDUDE = avrdude + +#=== predefined variable override === +# use "make -p -f/dev/null" to see the default rules and definitions + +# Build C and C++ flags. Include path information must be placed here +COMMON_FLAGS = -DF_CPU=$(F_CPU) -mmcu=$(MCU) $(DEFS) +# COMMON_FLAGS += -gdwarf-2 +COMMON_FLAGS += -Os +COMMON_FLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections +COMMON_FLAGS += -Wl,--relax +COMMON_FLAGS += -mcall-prologues +COMMON_FLAGS += -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +COMMON_FLAGS += -I. -I$(M2TKLIB_PATH) -I$(M2DEV_PATH) +COMMON_FLAGS += -I$(ARDUINO_PATH)hardware/arduino/cores/arduino +COMMON_FLAGS += $(addprefix -I,$(EXTRA_DIRS)) $(addprefix -I,$(addsuffix utility/,$(EXTRA_DIRS))) + +CFLAGS = $(COMMON_FLAGS) -std=gnu99 -Wstrict-prototypes +CXXFLAGS = $(COMMON_FLAGS) + +# Replace standard build tools by avr tools +CC = $(AVRTOOLSPATH)avr-gcc +CXX = $(AVRTOOLSPATH)avr-g++ +AR = @$(AVRTOOLSPATH)avr-ar + + +# "rm" must be able to delete a directory tree +RM = rm -rf + +#=== rules === + +# add rules for the C/C++ files where the .o file is placed in the TMPDIRPATH +# reuse existing variables as far as possible + +$(TMPDIRPATH)%.o: %.c + @echo compile $< + @$(COMPILE.c) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cc + @echo compile $< + @$(COMPILE.cc) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cpp + @echo compile $< + @$(COMPILE.cpp) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.s: %.c + @$(COMPILE.c) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cc + @$(COMPILE.cc) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cpp + @$(COMPILE.cpp) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.dis: $(TMPDIRPATH)%.o + @$(OBJDUMP) -S $< > $@ + +.SUFFIXES: .elf .hex .pde + +.elf.hex: + @$(OBJCOPY) -O ihex -R .eeprom $< $@ + +$(TMPDIRPATH)%.cpp: %.pde + @cat $(ARDUINO_PATH)hardware/arduino/cores/arduino/main.cpp > $@ + @cat $< >> $@ + @echo >> $@ + @echo 'extern "C" void __cxa_pure_virtual() { while (1); }' >> $@ + + +.PHONY: all +all: tmpdir $(HEXNAME) assemblersource showsize + ls -al $(HEXNAME) $(ELFNAME) + +$(ELFNAME): $(LIBNAME)($(addprefix $(TMPDIRPATH),$(OBJFILES))) + $(LINK.o) $(COMMON_FLAGS) $(LIBNAME) $(LOADLIBES) $(LDLIBS) -o $@ + +$(LIBNAME)(): $(addprefix $(TMPDIRPATH),$(OBJFILES)) + +#=== create temp directory === +# not really required, because it will be also created during the dependency handling +.PHONY: tmpdir +tmpdir: + @test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH) + +#=== create assembler files for each C/C++ file === +.PHONY: assemblersource +assemblersource: $(addprefix $(TMPDIRPATH),$(ASSFILES)) $(addprefix $(TMPDIRPATH),$(DISFILES)) + + +#=== show the section sizes of the ELF file === +.PHONY: showsize +showsize: $(ELFNAME) + $(SIZE) $< + +#=== clean up target === +# this is simple: the TMPDIRPATH is removed +.PHONY: clean +clean: + $(RM) $(TMPDIRPATH) + +# Program the device. +# step 1: reset the arduino board with the stty command +# step 2: user avrdude to upload the software +.PHONY: upload +upload: $(HEXNAME) + stty -F $(AVRDUDE_PORT) hupcl + $(AVRDUDE) $(AVRDUDE_FLAGS) + + +# === dependency handling === +# From the gnu make manual (section 4.14, Generating Prerequisites Automatically) +# Additionally (because this will be the first executed rule) TMPDIRPATH is created here. +# Instead of "sed" the "echo" command is used +# cd $(TMPDIRPATH); mkdir -p $(DIRS) 2> /dev/null; cd .. +DEPACTION=test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH);\ +mkdir -p $(addprefix $(TMPDIRPATH),$(DIRS));\ +set -e; echo -n $@ $(dir $@) > $@; $(CC) -MM $(COMMON_FLAGS) $< >> $@ + + +$(TMPDIRPATH)%.d: %.c + @$(DEPACTION) + +$(TMPDIRPATH)%.d: %.cc + @$(DEPACTION) + + +$(TMPDIRPATH)%.d: %.cpp + @$(DEPACTION) + +# Include dependency files. If a .d file is missing, a warning is created and the .d file is created +# This warning is not a problem (gnu make manual, section 3.3 Including Other Makefiles) +-include $(addprefix $(TMPDIRPATH),$(DEPFILES)) + + diff --git a/arduino/LiquidCrystal/Radio/Radio.pde b/arduino/LiquidCrystal/Radio/Radio.pde new file mode 100644 index 0000000..7da25e0 --- /dev/null +++ b/arduino/LiquidCrystal/Radio/Radio.pde @@ -0,0 +1,75 @@ +/* + + Radio.pde + + LiquidCrystal example + + m2tklib = Mini Interative Interface Toolkit Library + + Copyright (C) 2011 olikraus@gmail.com + + 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 3 of the License, or + (at your option) 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include "M2tk.h" +#include "m2ghlc.h" + +uint8_t uiKeySelectPin = 10; +uint8_t uiKeyNextPin = 9; + +uint8_t select_color = 0; + +void fn_ok(m2_el_fnarg_p fnarg) { + /* accept selection */ +} + +void fn_cancel(m2_el_fnarg_p fnarg) { + /* discard selection */ +} + +M2_LABEL(el_label1, NULL, "red"); +M2_RADIO(el_radio1, "v0", &select_color); + +M2_LABEL(el_label2, NULL, "green"); +M2_RADIO(el_radio2, "v1", &select_color); + +M2_LABEL(el_label3, NULL, "blue"); +M2_RADIO(el_radio3, "v2", &select_color); + +M2_BUTTON(el_cancel, NULL, "cancel", fn_cancel); +M2_BUTTON(el_ok, NULL, "ok", fn_ok); + +M2_LIST(list) = { + &el_label1, &el_radio1, + &el_label2, &el_radio2, + &el_label3, &el_radio3, + &el_cancel, &el_ok +}; +M2_GRIDLIST(list_element, "c2",list); +M2tk m2(&list_element, m2_es_arduino, m2_eh_2bs, m2_gh_lc_16x4); + +void setup() { + m2.setPin(M2_KEY_SELECT, uiKeySelectPin); + m2.setPin(M2_KEY_NEXT, uiKeyNextPin); +} + +void loop() { + m2.checkKey(); + m2.checkKey(); + if ( m2.handleKey() ) + m2.draw(); + m2.checkKey(); +} + diff --git a/arduino/LiquidCrystal/SimpleTest/Makefile.duemilanove b/arduino/LiquidCrystal/SimpleTest/Makefile.duemilanove new file mode 100644 index 0000000..b828e5a --- /dev/null +++ b/arduino/LiquidCrystal/SimpleTest/Makefile.duemilanove @@ -0,0 +1,271 @@ + +# +# Arduino 0022 Makefile +# +# written by olikraus@gmail.com +# +# Features: +# - boards.txt is used to derive parameters +# - All intermediate files are put into a separate directory (TMPDIRNAME) +# - Simple use: Copy Makefile into the same directory of the .pde file +# +# Limitations: +# - requires UNIX environment +# - TMPDIRNAME must be subdirectory of the current directory. +# +# Targets +# all build everything +# upload build and upload to arduino +# clean remove all temporary files (includes final hex file) +# +# History +# 001 28 Apr 2010 first release +# 002 05 Oct 2010 added 'uno' +# 003 07 May 2011 m2 version +# + +#=== user configuration === +# All ...PATH variables must have a '/' at the end + +# Board (and prozessor) information: see $(ARDUINO_PATH)hardware/arduino/boards.txt +# Some examples: +# BOARD DESCRIPTION +# uno Arduino Uno +# atmega328 Arduino Duemilanove or Nano w/ ATmega328 +# diecimila Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 +# mega Arduino Mega +# mini Arduino Mini +# lilypad328 LilyPad Arduino w/ ATmega328 +BOARD:=atmega328 + +M2TKLIB_PATH:=/home/kraus/src/m2/m2tklib/src/ +M2DEV_PATH:=/home/kraus/src/m2/m2tklib/dev/LiquidCrystal/ + +# The location where the avr tools (e.g. avr-gcc) are located. Requires a '/' at the end. +# Can be empty if all tools are accessable through the search path +AVR_TOOLS_PATH:=/usr/bin/ + +# Install path of the arduino software. Requires a '/' at the end. +ARDUINO_PATH:=/home/kraus/prg/arduino-0022/ + +# Install path for avrdude. Requires a '/' at the end. Can be empty if avrdude is in the search path. +AVRDUDE_PATH:= + +# The unix device where we can reach the arduino board +# Uno: /dev/ttyACM0 +# Duemilanove: /dev/ttyUSB0 +AVRDUDE_PORT:=/dev/ttyUSB0 + +# List of all libaries which should be included. +EXTRA_DIRS=$(ARDUINO_PATH)libraries/LiquidCrystal/ +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/dev/arduino/ +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/cpp/ + +#=== fetch parameter from boards.txt processor parameter === +# the basic idea is to get most of the information from boards.txt + +BOARDS_TXT:=$(ARDUINO_PATH)hardware/arduino/boards.txt + +# get the MCU value from the $(BOARD).build.mcu variable. For the atmega328 board this is atmega328p +MCU:=$(shell sed -n -e "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the F_CPU value from the $(BOARD).build.f_cpu variable. For the atmega328 board this is 16000000 +F_CPU:=$(shell sed -n -e "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_TXT)) + +# avrdude +# get the AVRDUDE_UPLOAD_RATE value from the $(BOARD).upload.speed variable. For the atmega328 board this is 57600 +AVRDUDE_UPLOAD_RATE:=$(shell sed -n -e "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the AVRDUDE_PROGRAMMER value from the $(BOARD).upload.protocol variable. For the atmega328 board this is stk500 +# AVRDUDE_PROGRAMMER:=$(shell sed -n -e "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_TXT)) +# use stk500v1, because stk500 will default to stk500v2 +AVRDUDE_PROGRAMMER:=stk500v1 + +#=== identify user files === +PDESRC:=$(shell ls *.pde) +TARGETNAME=$(basename $(PDESRC)) + +CDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CDIRS:=*.c utility/*.c $(M2TKLIB_PATH)*.c $(M2DEV_PATH)*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +#CDIRS:=*.c utility/*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +CSRC:=$(shell ls $(CDIRS) 2>/dev/null) + +CCSRC:=$(shell ls *.cc 2>/dev/null) + +CPPDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CPPDIRS:=*.cpp utility/*.cpp $(addsuffix *.cpp,$(CPPDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.cpp +CPPSRC:=$(shell ls $(CPPDIRS) 2>/dev/null) + +#=== build internal variables === + +# the name of the subdirectory where everything is stored +TMPDIRNAME:=tmp +TMPDIRPATH:=$(TMPDIRNAME)/ + +AVRTOOLSPATH:=$(AVR_TOOLS_PATH) + +OBJCOPY:=$(AVRTOOLSPATH)avr-objcopy +OBJDUMP:=$(AVRTOOLSPATH)avr-objdump +SIZE:=$(AVRTOOLSPATH)avr-size + +CPPSRC:=$(addprefix $(TMPDIRPATH),$(PDESRC:.pde=.cpp)) $(CPPSRC) + +COBJ:=$(CSRC:.c=.o) +CCOBJ:=$(CCSRC:.cc=.o) +CPPOBJ:=$(CPPSRC:.cpp=.o) + +OBJFILES:=$(COBJ) $(CCOBJ) $(CPPOBJ) +DIRS:= $(dir $(OBJFILES)) + +DEPFILES:=$(OBJFILES:.o=.d) +# assembler files from avr-gcc -S +ASSFILES:=$(OBJFILES:.o=.s) +# disassembled object files with avr-objdump -S +DISFILES:=$(OBJFILES:.o=.dis) + + +LIBNAME:=$(TMPDIRPATH)$(TARGETNAME).a +ELFNAME:=$(TMPDIRPATH)$(TARGETNAME).elf +HEXNAME:=$(TMPDIRPATH)$(TARGETNAME).hex + +AVRDUDE_FLAGS = -V -F +AVRDUDE_FLAGS += -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf +AVRDUDE_FLAGS += -p $(MCU) +AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) +AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += -b $(AVRDUDE_UPLOAD_RATE) +AVRDUDE_FLAGS += -U flash:w:$(HEXNAME) + +AVRDUDE = avrdude + +#=== predefined variable override === +# use "make -p -f/dev/null" to see the default rules and definitions + +# Build C and C++ flags. Include path information must be placed here +COMMON_FLAGS = -DF_CPU=$(F_CPU) -mmcu=$(MCU) $(DEFS) +# COMMON_FLAGS += -gdwarf-2 +COMMON_FLAGS += -Os +COMMON_FLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections +COMMON_FLAGS += -Wl,--relax +COMMON_FLAGS += -mcall-prologues +COMMON_FLAGS += -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +COMMON_FLAGS += -I. -I$(M2TKLIB_PATH) -I$(M2DEV_PATH) +COMMON_FLAGS += -I$(ARDUINO_PATH)hardware/arduino/cores/arduino +COMMON_FLAGS += $(addprefix -I,$(EXTRA_DIRS)) $(addprefix -I,$(addsuffix utility/,$(EXTRA_DIRS))) + +CFLAGS = $(COMMON_FLAGS) -std=gnu99 -Wstrict-prototypes +CXXFLAGS = $(COMMON_FLAGS) + +# Replace standard build tools by avr tools +CC = $(AVRTOOLSPATH)avr-gcc +CXX = $(AVRTOOLSPATH)avr-g++ +AR = @$(AVRTOOLSPATH)avr-ar + + +# "rm" must be able to delete a directory tree +RM = rm -rf + +#=== rules === + +# add rules for the C/C++ files where the .o file is placed in the TMPDIRPATH +# reuse existing variables as far as possible + +$(TMPDIRPATH)%.o: %.c + @echo compile $< + @$(COMPILE.c) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cc + @echo compile $< + @$(COMPILE.cc) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cpp + @echo compile $< + @$(COMPILE.cpp) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.s: %.c + @$(COMPILE.c) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cc + @$(COMPILE.cc) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cpp + @$(COMPILE.cpp) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.dis: $(TMPDIRPATH)%.o + @$(OBJDUMP) -S $< > $@ + +.SUFFIXES: .elf .hex .pde + +.elf.hex: + @$(OBJCOPY) -O ihex -R .eeprom $< $@ + +$(TMPDIRPATH)%.cpp: %.pde + @cat $(ARDUINO_PATH)hardware/arduino/cores/arduino/main.cpp > $@ + @cat $< >> $@ + @echo >> $@ + @echo 'extern "C" void __cxa_pure_virtual() { while (1); }' >> $@ + + +.PHONY: all +all: tmpdir $(HEXNAME) assemblersource showsize + ls -al $(HEXNAME) $(ELFNAME) + +$(ELFNAME): $(LIBNAME)($(addprefix $(TMPDIRPATH),$(OBJFILES))) + $(LINK.o) $(COMMON_FLAGS) $(LIBNAME) $(LOADLIBES) $(LDLIBS) -o $@ + +$(LIBNAME)(): $(addprefix $(TMPDIRPATH),$(OBJFILES)) + +#=== create temp directory === +# not really required, because it will be also created during the dependency handling +.PHONY: tmpdir +tmpdir: + @test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH) + +#=== create assembler files for each C/C++ file === +.PHONY: assemblersource +assemblersource: $(addprefix $(TMPDIRPATH),$(ASSFILES)) $(addprefix $(TMPDIRPATH),$(DISFILES)) + + +#=== show the section sizes of the ELF file === +.PHONY: showsize +showsize: $(ELFNAME) + $(SIZE) $< + +#=== clean up target === +# this is simple: the TMPDIRPATH is removed +.PHONY: clean +clean: + $(RM) $(TMPDIRPATH) + +# Program the device. +# step 1: reset the arduino board with the stty command +# step 2: user avrdude to upload the software +.PHONY: upload +upload: $(HEXNAME) + stty -F $(AVRDUDE_PORT) hupcl + $(AVRDUDE) $(AVRDUDE_FLAGS) + + +# === dependency handling === +# From the gnu make manual (section 4.14, Generating Prerequisites Automatically) +# Additionally (because this will be the first executed rule) TMPDIRPATH is created here. +# Instead of "sed" the "echo" command is used +# cd $(TMPDIRPATH); mkdir -p $(DIRS) 2> /dev/null; cd .. +DEPACTION=test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH);\ +mkdir -p $(addprefix $(TMPDIRPATH),$(DIRS));\ +set -e; echo -n $@ $(dir $@) > $@; $(CC) -MM $(COMMON_FLAGS) $< >> $@ + + +$(TMPDIRPATH)%.d: %.c + @$(DEPACTION) + +$(TMPDIRPATH)%.d: %.cc + @$(DEPACTION) + + +$(TMPDIRPATH)%.d: %.cpp + @$(DEPACTION) + +# Include dependency files. If a .d file is missing, a warning is created and the .d file is created +# This warning is not a problem (gnu make manual, section 3.3 Including Other Makefiles) +-include $(addprefix $(TMPDIRPATH),$(DEPFILES)) + + diff --git a/arduino/LiquidCrystal/SimpleTest/SimpleTest.pde b/arduino/LiquidCrystal/SimpleTest/SimpleTest.pde new file mode 100644 index 0000000..363e69f --- /dev/null +++ b/arduino/LiquidCrystal/SimpleTest/SimpleTest.pde @@ -0,0 +1,57 @@ +/* + + SimpleTest.pde + + m2tklib = Mini Interative Interface Toolkit Library + + Copyright (C) 2011 olikraus@gmail.com + + 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 3 of the License, or + (at your option) 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Just test a 16x4 LCD display + +*/ + +#include + +LiquidCrystal lcd(12, 11, 5, 4, 3, 2); + +void setCursor(uint8_t x, uint8_t y) +{ + if ( y >= 2 ) + { + x+=16; + y-=2; + } + lcd.setCursor(x, y); +} + +void setup() { + lcd.begin(16, 4); + lcd.print("Simple Test"); +} + +void loop() { + setCursor(0, 1); + lcd.print("(0,1)"); + + setCursor(0, 2); + lcd.print("(0,2)"); + + setCursor(8, 2); + lcd.print("(8,2)"); + + setCursor(0, 3); + lcd.print(millis()/100); +} diff --git a/arduino/LiquidCrystal/U32/Makefile.duemilanove b/arduino/LiquidCrystal/U32/Makefile.duemilanove new file mode 100644 index 0000000..80b844d --- /dev/null +++ b/arduino/LiquidCrystal/U32/Makefile.duemilanove @@ -0,0 +1,272 @@ + +# +# Arduino 0022 Makefile +# +# written by olikraus@gmail.com +# +# Features: +# - boards.txt is used to derive parameters +# - All intermediate files are put into a separate directory (TMPDIRNAME) +# - Simple use: Copy Makefile into the same directory of the .pde file +# +# Limitations: +# - requires UNIX environment +# - TMPDIRNAME must be subdirectory of the current directory. +# +# Targets +# all build everything +# upload build and upload to arduino +# clean remove all temporary files (includes final hex file) +# +# History +# 001 28 Apr 2010 first release +# 002 05 Oct 2010 added 'uno' +# 003 07 May 2011 m2 version +# + +#=== user configuration === +# All ...PATH variables must have a '/' at the end + +# Board (and prozessor) information: see $(ARDUINO_PATH)hardware/arduino/boards.txt +# Some examples: +# BOARD DESCRIPTION +# uno Arduino Uno +# atmega328 Arduino Duemilanove or Nano w/ ATmega328 +# diecimila Arduino Diecimila, Duemilanove, or Nano w/ ATmega168 +# mega Arduino Mega +# mini Arduino Mini +# lilypad328 LilyPad Arduino w/ ATmega328 +BOARD:=atmega328 + +M2TKLIB_PATH:=/home/kraus/src/m2/m2tklib/src/ +M2DEV_PATH:=/home/kraus/src/m2/m2tklib/dev/LiquidCrystal/ + +# The location where the avr tools (e.g. avr-gcc) are located. Requires a '/' at the end. +# Can be empty if all tools are accessable through the search path +AVR_TOOLS_PATH:=/usr/bin/ + +# Install path of the arduino software. Requires a '/' at the end. +ARDUINO_PATH:=/home/kraus/prg/arduino-0022/ + +# Install path for avrdude. Requires a '/' at the end. Can be empty if avrdude is in the search path. +AVRDUDE_PATH:= + +# The unix device where we can reach the arduino board +# Uno: /dev/ttyACM0 +# Duemilanove: /dev/ttyUSB0 +AVRDUDE_PORT:=/dev/ttyUSB0 + +# List of all libaries which should be included. +EXTRA_DIRS=$(ARDUINO_PATH)libraries/LiquidCrystal/ +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/dev/arduino/ +EXTRA_DIRS+=$(M2DEV_PATH) +EXTRA_DIRS+=/home/kraus/src/m2/m2tklib/cpp/ + +#=== fetch parameter from boards.txt processor parameter === +# the basic idea is to get most of the information from boards.txt + +BOARDS_TXT:=$(ARDUINO_PATH)hardware/arduino/boards.txt + +# get the MCU value from the $(BOARD).build.mcu variable. For the atmega328 board this is atmega328p +MCU:=$(shell sed -n -e "s/$(BOARD).build.mcu=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the F_CPU value from the $(BOARD).build.f_cpu variable. For the atmega328 board this is 16000000 +F_CPU:=$(shell sed -n -e "s/$(BOARD).build.f_cpu=\(.*\)/\1/p" $(BOARDS_TXT)) + +# avrdude +# get the AVRDUDE_UPLOAD_RATE value from the $(BOARD).upload.speed variable. For the atmega328 board this is 57600 +AVRDUDE_UPLOAD_RATE:=$(shell sed -n -e "s/$(BOARD).upload.speed=\(.*\)/\1/p" $(BOARDS_TXT)) +# get the AVRDUDE_PROGRAMMER value from the $(BOARD).upload.protocol variable. For the atmega328 board this is stk500 +# AVRDUDE_PROGRAMMER:=$(shell sed -n -e "s/$(BOARD).upload.protocol=\(.*\)/\1/p" $(BOARDS_TXT)) +# use stk500v1, because stk500 will default to stk500v2 +AVRDUDE_PROGRAMMER:=stk500v1 + +#=== identify user files === +PDESRC:=$(shell ls *.pde) +TARGETNAME=$(basename $(PDESRC)) + +CDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CDIRS:=*.c utility/*.c $(M2TKLIB_PATH)*.c $(M2DEV_PATH)*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +#CDIRS:=*.c utility/*.c $(addsuffix *.c,$(CDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.c +CSRC:=$(shell ls $(CDIRS) 2>/dev/null) + +CCSRC:=$(shell ls *.cc 2>/dev/null) + +CPPDIRS:=$(EXTRA_DIRS) $(addsuffix utility/,$(EXTRA_DIRS)) +CPPDIRS:=*.cpp utility/*.cpp $(addsuffix *.cpp,$(CPPDIRS)) $(ARDUINO_PATH)hardware/arduino/cores/arduino/*.cpp +CPPSRC:=$(shell ls $(CPPDIRS) 2>/dev/null) + +#=== build internal variables === + +# the name of the subdirectory where everything is stored +TMPDIRNAME:=tmp +TMPDIRPATH:=$(TMPDIRNAME)/ + +AVRTOOLSPATH:=$(AVR_TOOLS_PATH) + +OBJCOPY:=$(AVRTOOLSPATH)avr-objcopy +OBJDUMP:=$(AVRTOOLSPATH)avr-objdump +SIZE:=$(AVRTOOLSPATH)avr-size + +CPPSRC:=$(addprefix $(TMPDIRPATH),$(PDESRC:.pde=.cpp)) $(CPPSRC) + +COBJ:=$(CSRC:.c=.o) +CCOBJ:=$(CCSRC:.cc=.o) +CPPOBJ:=$(CPPSRC:.cpp=.o) + +OBJFILES:=$(COBJ) $(CCOBJ) $(CPPOBJ) +DIRS:= $(dir $(OBJFILES)) + +DEPFILES:=$(OBJFILES:.o=.d) +# assembler files from avr-gcc -S +ASSFILES:=$(OBJFILES:.o=.s) +# disassembled object files with avr-objdump -S +DISFILES:=$(OBJFILES:.o=.dis) + + +LIBNAME:=$(TMPDIRPATH)$(TARGETNAME).a +ELFNAME:=$(TMPDIRPATH)$(TARGETNAME).elf +HEXNAME:=$(TMPDIRPATH)$(TARGETNAME).hex + +AVRDUDE_FLAGS = -V -F +AVRDUDE_FLAGS += -C $(ARDUINO_PATH)/hardware/tools/avrdude.conf +AVRDUDE_FLAGS += -p $(MCU) +AVRDUDE_FLAGS += -P $(AVRDUDE_PORT) +AVRDUDE_FLAGS += -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += -b $(AVRDUDE_UPLOAD_RATE) +AVRDUDE_FLAGS += -U flash:w:$(HEXNAME) + +AVRDUDE = avrdude + +#=== predefined variable override === +# use "make -p -f/dev/null" to see the default rules and definitions + +# Build C and C++ flags. Include path information must be placed here +COMMON_FLAGS = -DF_CPU=$(F_CPU) -mmcu=$(MCU) $(DEFS) +# COMMON_FLAGS += -gdwarf-2 +COMMON_FLAGS += -Os +COMMON_FLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections +COMMON_FLAGS += -Wl,--relax +COMMON_FLAGS += -mcall-prologues +COMMON_FLAGS += -Wall -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +COMMON_FLAGS += -I. -I$(M2TKLIB_PATH) -I$(M2DEV_PATH) +COMMON_FLAGS += -I$(ARDUINO_PATH)hardware/arduino/cores/arduino +COMMON_FLAGS += $(addprefix -I,$(EXTRA_DIRS)) $(addprefix -I,$(addsuffix utility/,$(EXTRA_DIRS))) + +CFLAGS = $(COMMON_FLAGS) -std=gnu99 -Wstrict-prototypes +CXXFLAGS = $(COMMON_FLAGS) + +# Replace standard build tools by avr tools +CC = $(AVRTOOLSPATH)avr-gcc +CXX = $(AVRTOOLSPATH)avr-g++ +AR = @$(AVRTOOLSPATH)avr-ar + + +# "rm" must be able to delete a directory tree +RM = rm -rf + +#=== rules === + +# add rules for the C/C++ files where the .o file is placed in the TMPDIRPATH +# reuse existing variables as far as possible + +$(TMPDIRPATH)%.o: %.c + @echo compile $< + @$(COMPILE.c) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cc + @echo compile $< + @$(COMPILE.cc) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.o: %.cpp + @echo compile $< + @$(COMPILE.cpp) $(OUTPUT_OPTION) $< + +$(TMPDIRPATH)%.s: %.c + @$(COMPILE.c) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cc + @$(COMPILE.cc) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.s: %.cpp + @$(COMPILE.cpp) $(OUTPUT_OPTION) -S $< + +$(TMPDIRPATH)%.dis: $(TMPDIRPATH)%.o + @$(OBJDUMP) -S $< > $@ + +.SUFFIXES: .elf .hex .pde + +.elf.hex: + @$(OBJCOPY) -O ihex -R .eeprom $< $@ + +$(TMPDIRPATH)%.cpp: %.pde + @cat $(ARDUINO_PATH)hardware/arduino/cores/arduino/main.cpp > $@ + @cat $< >> $@ + @echo >> $@ + @echo 'extern "C" void __cxa_pure_virtual() { while (1); }' >> $@ + + +.PHONY: all +all: tmpdir $(HEXNAME) assemblersource showsize + ls -al $(HEXNAME) $(ELFNAME) + +$(ELFNAME): $(LIBNAME)($(addprefix $(TMPDIRPATH),$(OBJFILES))) + $(LINK.o) $(COMMON_FLAGS) $(LIBNAME) $(LOADLIBES) $(LDLIBS) -o $@ + +$(LIBNAME)(): $(addprefix $(TMPDIRPATH),$(OBJFILES)) + +#=== create temp directory === +# not really required, because it will be also created during the dependency handling +.PHONY: tmpdir +tmpdir: + @test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH) + +#=== create assembler files for each C/C++ file === +.PHONY: assemblersource +assemblersource: $(addprefix $(TMPDIRPATH),$(ASSFILES)) $(addprefix $(TMPDIRPATH),$(DISFILES)) + + +#=== show the section sizes of the ELF file === +.PHONY: showsize +showsize: $(ELFNAME) + $(SIZE) $< + +#=== clean up target === +# this is simple: the TMPDIRPATH is removed +.PHONY: clean +clean: + $(RM) $(TMPDIRPATH) + +# Program the device. +# step 1: reset the arduino board with the stty command +# step 2: user avrdude to upload the software +.PHONY: upload +upload: $(HEXNAME) + stty -F $(AVRDUDE_PORT) hupcl + $(AVRDUDE) $(AVRDUDE_FLAGS) + + +# === dependency handling === +# From the gnu make manual (section 4.14, Generating Prerequisites Automatically) +# Additionally (because this will be the first executed rule) TMPDIRPATH is created here. +# Instead of "sed" the "echo" command is used +# cd $(TMPDIRPATH); mkdir -p $(DIRS) 2> /dev/null; cd .. +DEPACTION=test -d $(TMPDIRPATH) || mkdir $(TMPDIRPATH);\ +mkdir -p $(addprefix $(TMPDIRPATH),$(DIRS));\ +set -e; echo -n $@ $(dir $@) > $@; $(CC) -MM $(COMMON_FLAGS) $< >> $@ + + +$(TMPDIRPATH)%.d: %.c + @$(DEPACTION) + +$(TMPDIRPATH)%.d: %.cc + @$(DEPACTION) + + +$(TMPDIRPATH)%.d: %.cpp + @$(DEPACTION) + +# Include dependency files. If a .d file is missing, a warning is created and the .d file is created +# This warning is not a problem (gnu make manual, section 3.3 Including Other Makefiles) +-include $(addprefix $(TMPDIRPATH),$(DEPFILES)) + + diff --git a/arduino/LiquidCrystal/U32/U32.pde b/arduino/LiquidCrystal/U32/U32.pde new file mode 100644 index 0000000..2e39171 --- /dev/null +++ b/arduino/LiquidCrystal/U32/U32.pde @@ -0,0 +1,58 @@ +/* + + U32.pde + + LiquidCrystal example + + m2tklib = Mini Interative Interface Toolkit Library + + Copyright (C) 2011 olikraus@gmail.com + + 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 3 of the License, or + (at your option) 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include "M2tk.h" +#include "m2ghlc.h" + +uint8_t uiKeySelectPin = 10; +uint8_t uiKeyNextPin = 9; + +uint32_t number = 1234; + + + +void fn_ok(m2_el_fnarg_p fnarg) { + /* do something with the number */ +} + +M2_LABEL(el_label, NULL, "Num: "); +M2_U32NUM(el_text, "a1c4", &number); +M2_BUTTON(el_ok, "", "ok", fn_ok); +M2_LIST(list) = { &el_label, &el_text, &el_ok }; +M2_HLIST(list_element, NULL, list); +M2tk m2(&list_element, m2_es_arduino, m2_eh_2bs, m2_gh_lc_16x4); + +void setup() { + m2.setPin(M2_KEY_SELECT, uiKeySelectPin); + m2.setPin(M2_KEY_NEXT, uiKeyNextPin); +} + +void loop() { + m2.checkKey(); + m2.checkKey(); + if ( m2.handleKey() ) + m2.draw(); + m2.checkKey(); +} diff --git a/dev/LiquidCrystal/m2ghlc.h b/dev/LiquidCrystal/m2ghlc.h new file mode 100644 index 0000000..e5c54c4 --- /dev/null +++ b/dev/LiquidCrystal/m2ghlc.h @@ -0,0 +1,36 @@ +/* + + m2ghlc.h + + m2tklib = Mini Interative Interface Toolkit Library + + Copyright (C) 2011 olikraus@gmail.com + + 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 3 of the License, or + (at your option) 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#ifndef _M2GHLC_H +#define _M2GHLC_H + +#ifdef __cplusplus +extern "C" { +#endif + +uint8_t m2_gh_lc_16x4(m2_gfx_arg_p arg); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/dev/LiquidCrystal/m2ghlc16x4.cpp b/dev/LiquidCrystal/m2ghlc16x4.cpp new file mode 100644 index 0000000..98afd76 --- /dev/null +++ b/dev/LiquidCrystal/m2ghlc16x4.cpp @@ -0,0 +1,137 @@ +/* + + m2ghlcd16x4.cpp + + Graphics Handler for the LiquidCrystal library from the Arduino Environment + + m2tklib = Mini Interative Interface Toolkit Library + + Copyright (C) 2011 olikraus@gmail.com + + 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 3 of the License, or + (at your option) 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +#include +#include +#include "m2.h" + + +LiquidCrystal m2_lcd(12, 11, 5, 4, 3, 2); + +void m2_set_cursor_16x4(uint8_t x, uint8_t y) +{ + /* translate the x-y position from the m2tklib to the LiquidCrystal lib */ + /* assume 16x4 display */ + + y = 3-y; + + if ( y >= 2 ) + { + x+=16; + y-=2; + } + m2_lcd.setCursor(x, y); +} + +/* + 00000000 0x00 + 00011111 0x1f + 00010001 0x11 + 00010001 0x11 + 00010001 0x11 + 00010001 0x11 + 00011111 0x1f + 00000000 0x00 + + 00000000 0x00 + 00011111 0x1f + 00011111 0x1f + 00011111 0x1f + 00011111 0x1f + 00011111 0x1f + 00011111 0x1f + 00000000 0x00 +*/ + +uint8_t m2_gh_icon_inactive[] = { 0x00, 0x1f, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x00 }; +uint8_t m2_gh_icon_active[] = { 0x00, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x00 }; + +uint8_t m2_gh_lcd_cursor_x; +uint8_t m2_gh_lcd_cursor_y = 255; + +extern "C" uint8_t m2_gh_lc_16x4(m2_gfx_arg_p arg) +{ + switch(arg->msg) + { + case M2_GFX_MSG_INIT: + m2_lcd.begin(16, 4); + m2_lcd.createChar(1, m2_gh_icon_active); + m2_lcd.createChar(2, m2_gh_icon_inactive); + break; + case M2_GFX_MSG_START: + m2_gh_lcd_cursor_y = 255; + m2_lcd.noCursor(); + m2_lcd.noBlink(); + m2_lcd.clear(); + break; + case M2_GFX_MSG_END: + if ( m2_gh_lcd_cursor_y != 255 ) + { + m2_set_cursor_16x4(m2_gh_lcd_cursor_x, m2_gh_lcd_cursor_y); + m2_lcd.cursor(); + } + break; + case M2_GFX_MSG_DRAW_TEXT: + m2_set_cursor_16x4(arg->x, arg->y); + m2_lcd.print(arg->s); + return 0; + case M2_GFX_MSG_DRAW_NORMAL_FOCUS: + case M2_GFX_MSG_DRAW_NORMAL_PARENT_FOCUS: + m2_set_cursor_16x4(arg->x, arg->y); + m2_lcd.print('['); + m2_set_cursor_16x4(arg->x+arg->w-1, arg->y); + m2_lcd.print(']'); + return 0; + case M2_GFX_MSG_DRAW_GO_UP: + m2_set_cursor_16x4(arg->x-1, arg->y); + m2_lcd.print('<'); + m2_set_cursor_16x4(arg->x+arg->w, arg->y); + m2_lcd.print('>'); + return 0; + case M2_GFX_MSG_DRAW_SMALL_FOCUS: + m2_gh_lcd_cursor_x = arg->x; + m2_gh_lcd_cursor_y = arg->y; + return 0; + case M2_GFX_MSG_DRAW_ICON: + m2_set_cursor_16x4(arg->x, arg->y); + if ( arg->icon == M2_ICON_TOGGLE_ACTIVE || arg->icon == M2_ICON_RADIO_ACTIVE ) + m2_lcd.print("\001"); + else + m2_lcd.print("\002"); + return 0; + case M2_GFX_MSG_GET_TEXT_WIDTH: + return strlen(arg->s); + case M2_GFX_MSG_GET_ICON_WIDTH: + case M2_GFX_MSG_GET_ICON_HEIGHT: + case M2_GFX_MSG_GET_CHAR_WIDTH: + case M2_GFX_MSG_GET_CHAR_HEIGHT: + return 1; + case M2_GFX_MSG_GET_NORMAL_BORDER_WIDTH: + return 2; + case M2_GFX_MSG_GET_NORMAL_BORDER_X_OFFSET: + return 1; + } + return m2_gh_dummy(arg); +} diff --git a/pic/lcd/Radio.jpg b/pic/lcd/Radio.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c0d2c57b41cffc61a779804726dde89b2e555156 GIT binary patch literal 18045 zcmeIZXIKh86_vl zNkQN??!C|1=RD_m?z#8R_vb5Sb-i7yR;{WPx~r#$+nL+%AVM`IRV5G#3JORC_ygT8 zlb$L1*xQ0Ys;V3yED#8U4I)561z`Zl7bt`PCIfg7P>4~`KqvseD-Tf6|L_z5Q~ix| z0L=ck4l028fwrUoF9r$;>VLMie+~ZAwjGd*)E+@(#r}7 z@Ph7K{G+lJpqiG_?P_UUE9CqVE{(|TOJKy z%*4MULhl80T*t1fcUW5fh|>2?AvS_!WS$fT3K&29)yt_LGm77bWjMM+)_C z3IUOI(pt;BM1gY55M3q-+thLKm>o|Qveed{ACB|3PkZQ3@XI@6BimFM?wCj z13(b!-}r8J(f)qRS0Am0xC;@B?U`zm$1K1tFSU`)rXxR`1z^X_6<3R)<#{=YcfV>pIgn#RRKfb1^qb{atPV{_m!D19ul{J|Mr-(*YVa1BL#sF+g|ht}YV*cXfC2$v-v! z?}v&1LFI1WF9SC2_`k^?=!5fL!}qgiaR7RESGo&8ZUwBM zCP03N0kfbs;Be=sETDIF*AGzcR^2}Yocs~GcT$NG(#i*%k|IXU)s({Mdd5}B^ z3j+fa104$!6B8R73+Emw-aTC0d-sV+2uNuj(9zO7pr)p0=4PX3e8@yi%`O6Y$jc`v zC`iX9CMnAQh+9CA|IP>sHa7M>+H&S@6vBD5jrsg zpDYH6t_3Ee8!3NqLOvFgTwOOAbo7u}z|uVg8;6{N^8N!BRyKABhoF$Kh^Uyjyn>>V zvWlvj9!%fhv7wQ%m9>rSGdp_+4^J=e=RPldL&L&fy^eSjnV5t~PDxEm&nPHF78RG2 zmX+5xG&VK2w6?YPeCX}_*#Bu@aBO^Ha%y^Jc5ZoPb!~lPb8CC&==kLH?EK>Augkl* zfHd^4u>K>m{}vY!5Em*Kj0VQMiwgzyIZ)7uz~~Ho7{s!=m=S?X;Jbs}fXVtIYyST@OpJg*>AfKeHy089I;;J2-=L z-%`^dHjj7p_k>`b6V@TLmMWq99I$=nqmgC_gL1@=#b%C;c+$6aqy-Hq!ee`+jg8fO zsAGFYmAmtq-KFz$#)6z13diKhxc*~>b#zN5SZ#0V+wz-}$l@w~z7dQ{`<}SC_DpA1 zFL)wuThGXWf9F!Cy+J?tvlR*Ihqz+S$FEEC%7yIS6}A;c^63k{Eprjv+Dv1QZz!AN zm3qv1&9PZ!!`?d3cZ&N8B7-D7E45;I^P-A!dW}quyP)P{fZArMLV9@ROy;bUYz%WG zq~#OcxD|dbl;c&M1=qkUJKTfUq6+aJwcLK2wd-Fy>Lh;pNT`t6wT|o!J9z(5%V$Kx zvYx^;y|M858ZwsKfToU?nixaLZTF+wlVq%^_2|O-@dE*qduFVPEvl1G_c%q<6OEz{ z<|^}?_qr>{U6-WFxE6=snD5>}KYcm6l$g7Xm+_ zM_uwpFm?E8{q$(qpue}@{XHw!#dooMJj%QC^x*<30%vo)mpJ0t;D?8A&<2YM=arWF zy~Wo&PlW=guJR?j=FExu+~=)y0=y(VPCTMreV;XXe8z)Hgb(vV++=7VGu4hkX_fQ4 ze%)pBi*p~S-yr!6JE@^VBu|I`uf0&v&%FRi%OZhTBY z`5cWIKby1NtNf98sD05hxZG-Eg%MnE;+1)U%ziKA)35Bzn$^dA+IyPS5X~=I+GR4B zO&pPGy3mi>bh?iTe>W)-2*Igv4Tp(`78Mk|T$=;!bMEWE{I=+pyymXLRQ2r1+^ms( z-tfjRU6lrb0%uzr`h6z?XH5ZP@~4LhZ1c|dAm_4;Z`7>!oke#)I^2H-S+0^TPP#C$ ziCvs+=)_qTJIFOYwbygtwSOxSAeo*aXxsAYW|m)T{B_LqE4^5(Q&F~);{Fn)<{B5~ z`Y)C9EgH{xA6a42M2t+84vUIAr@E1LwZ_^Ah_|4~@rs>);V4?%>+4&epE+RXTA4Fk zHqvg_!Sfkf?O2>lH~Xw5ab?3g-Mc02DuQ;wZ}N3RhL z-`W@sSEE=YWPe+R+G!A#8rQJcmnS#Aw`uT4t-7hGPfI>?*QT ze??2GGSWLfE8m@}G? z0@`7;ouTrUj>4quFERro$CCKv3n$<#%_*>N>wOmuxN)C|l78xu!0H^mv&3Nc2=`+U z(eaqzXVhogx>`b<6%f+*@uJQ|Y-~fOv?AtCV*R3$oXmF5>pO-YVv+SSIi<2%$_=z0 z%dFCLeSDj*l+-2AGRz-y42=Iho?o(081Kp0i(Yot1uYaiYW(ya zC64MsWYdpPWHrl~LkeTT=9t3$af zjkh3anKnV+Dr5^P*|P!BdzR*}w|dR5JcilkoJmYg4EQo%FxXRIJx9ff)pA=nugs*u zF|=-J$r1MR5r!x2#k%WJX{Scx%d9>!2>bd}xC?Jk7Q0zxj{hT+>K<&iKBo+9}Z zUi2xoD`#~U#IIWW@|0%Su$n1-&G5^?!|(B;BYBcX-^Ow?s%%_@${#({FVst$p-T%< zU9)Pb5!-S2!ikM6vZ)=v_Z4506%Q>GN?~0wRavvRt)qZEC4*bRJ2~&yK4(Z3Ew7rY z98@LK$!NWwS5$00HaU~ulPWkTqs3lJ44rr(*d|!Xcls>SR?BXn;JvgU?1f;u*sfww zVtj_Jc9mcq%{CH@Xd<-QRinHdwOHtM5|~)2dB_usXH`*4O=9e-w!v`npa=P6Bf-%& z@OJi30tMW|QGpLYXut;z1B?a`COQ@v0}BfW8w(Q`3kM$$7YFAa4i*+J;k|o!1OQ>< z5)u*M6XD_GKlu{|82#?6fIs;YIuQc~F(0NZ773#+ zsf8Ohe{lXG8IxQ>T{k&1bW}i4-ZF%Ol7-Fv2rxkf-16^|nSXWhS1yAER7wzmfb_&Vw??*tMAFatU7E3=BF4HQN(<8BbRVv}Uaiqi))WZ8@B2OxGth2YG>=r9PGy2@nR(^BeC^5g0oDQw z+jfGprG<(GD3jea3HUbc`%NG_A#ciBz$0UFI7N%o?>Zta-B5daDtK3;HQQEz6=4y! z4#sFEQSOJvhlvTTu~M}O?C;4QEu@NHAAm%rN7!F}z$saZIpsz91|@u|_5Z zz`xCr;9XWr8c-A2u?Rwgq7Ffl??Q;NXLy2Ce@G()zp^uDF5s?=hCn4~c>WiNKY3mf$oj9K2=`nRDu(v{d@%Z=zEyowD`ANvpsAp|cI2w8B{ zSw~7qy7$Owm<>Y&4(@YgahO)Uphu_&!AP8YpMX6y1}h|!amC|@>NUGiG8LZ-Z_Iy> z$KayzHG++c>b?m#g_x+cv~CD#br5s4WMwHehx>RFb9ju5puJ^`1Xkr0QUN_R&O9KwI#QbE;)7I=& zXXl3LAs^QNmIUp6~8_?k>bb){gz_37$3SMfD92`NDY4&E4*kw)c+c9T@1_K%U6pONc=p9@`|e?E2&+#$O999Y8V{n$6P_;grd09G+E_i{b4 zi`Ch`7(uL==v^9W>3Yw;eVoq49bWqAF}>D?jk@a^7vFAivtTt+{NAChzk|;s%VzYC($!i8 zLx)^k=?P5Fcj8~#cx-BQSa6zpd1n`v2r9a0YJI78SzaisHNsJ7SL^ti3@*+0W?;sb zJ?EP%@^ki{p+lIIZGU?WvqD#zz;}Ax6034EDEobl*)$DDhl(2>isCSb2yIQ8!N==r z^e7-L*6ldvhX&NvXBiWUwMj0^SquzPI#+rN zJBW$Z{KGqYZOVDe-3&aVZb9ow+wbU=MWf4+<(37YME%xzKjWj-aEXt!c@s3M)8g19 zP}Rwr=^f8S>J=pIy?Pc|=?x0U@9;rcoV|$i2l%;K*U8yBbhAPGRwTKDR+BnQs2!fk z&&^KXDmt{^f?#YAAu-5()?${?l5{Ue6g(0>&nk9|T{Lr=TFsSglWUh9lh?Z2I3F{U z#)O1TG7B4YlhfpfYgeffsZpBnt|GZnV}h8nl%X+_%&;;K-DJF)am{)W4b*3kJSI)C zew1AE?|!In9M+ScwDb0OY>xwFZ6X;XRuJH8E0Vm5npKw|vBc5a>D8}%eAziA)_f)$ zQKhq;!S8EnH2AW}QupHql?4RK3azCwTr$%fwIOPrZrY>Z9~_*kQjcnGo7#B9+W70$ za$7_H;Yp6(0&fM~y$69XXorhKvZEe@WI09xoa7A0k%y&aB%|Ajxs*j%-3Answ?He? z;hQnbQTsj99P4vUdr~zdgJk(9e1?Eti3F@fvhBIJa85fK^mXwiZnUK+KQj9>>yA_= z$b8ALO?brlh}2Wro`J`3X||ccJqV^5Uj5=y=8YC%QioNSNN5;bmv!M=tR;VJL^rq< z)WUQaC;c)|U9{0N9X=o}+UP}|QMmRgJ&wEkn=SBw#IbqHX-u1i`*B4o18Y1I?J*Av&*MD1EnZI~$>zK*i&y)aDZuC0>4!YA z4$g`_+6wDY(W#{ma&zoQObm@RjvRMQ930Eb3@XYEuywgJs3H#3w6L0f#>%B3GKdND z@IHFPO%{=Xs(JiZvBnUb62He!*3O+)56;lsnLE#)Y>~>*)Y2j zxZUR{kF2+GYV*ttjUXC%RIYFFn2JS3q_c340KFl4#EY$l)+BKkvI9OgNO!*;laK7_ z7;+vt^z|>Cve*0RzYMzO`XXH#*ujyRW=60=Ag^^sRbX5ntfA1*aQ47tY;141qfxks ziy2hJG(nOz&$kjh>W{L0@-e*X8Qbg>?3ZwnW7Vgsv&Pr+iE}GD1(}FfJwLQdS1$Or zr5?1sJEU_d4svu}*p7(C@3b++PNOti9+k$MBYPL-kkO@?`1^zLTaB00?K^tha5wB! z6O9n5W991J=nHDB5YN=!cQJ<*NQk7sq+V&_#OX5@CQ$>jcIU65tMx)?Sy*OZIWsYwQpzzI<*$s@%HY-2<-PaGa(iRQKvxtfVVIA(04166O(k0CatDcI zDb@4oI=-WPqm~OtcV@>$747$l6vKvo($x$i7ae*rejZgn?i*Mvphx`l!9tA=WTXsY z(?<$dFLA|U>~EUf9*$!apTjML7T5}mv{V!Ngu9`oV%nUDNDLbRC1 zUP?M$vl$CkNH#R=U{c2xNfk=%j&R%rzucaCYd7}U=sE-mW>vD=XDv^LH~;v)KmUct z&r+)DvU~Ccchu>MpPu$77>9decjxg$o9ju%(u$679wO8-PfIa~ZJmZ7S~|e1i2RXy zjzUtf#EV!|?B1c8M_buCh~1Jn8WfWf`@tq*FM=$77!Ndla*w?QAV?61D+UY;VC>SaX)E`2D?eiU`u4#ZMJ>c=+|)+rVT5fXqC&*5JG-O7`Sb}h=i!JUHYXPJ;k;P|Us+5->!P<1wo3(f zLOV ztQzQC#TU;0xJrLw$2=&{1R;Q+(8s%+hMOhgAI_!lIEE$JS*isXsywhviAU2Snj4S~ zYP9$mU*X(&UDf*t@GT-m-ufEv=)Rse6BymijyahZ%=%dkTa=jqL8GE7=gjAPI1$Fk zOmCQ*;-B9Q#gV0-kNb$m9$!y9OEIJ51g9d8)N9<6P;&P#VAboHA4DLLMluPpqr%1Q ziSfemnC47Esyd!zQV5f$_?dZ0$H9~u<*wyYm1o3pW3jmtO|<#Bq;n4w3Cqe7#}!4)+_Upln~-!-{r^W zGBGoz*eFs+Mr(p2LXxa<;6A0Jt1m?+_w(&uciFa-B8$UP;*;^D0_`=)Q{`$yHg6fd??#HDk2xfe88bzD%~ zhOh0TEu;pr0)3UzR@KevI!mQk$*uUS*MM`kMqfM>c3m;PC?Zp{B{q<*r&gvZ)odDI zq{3)pgX4zIsUGSeE7LjzsB<-z(i361yIr{hvbtsx(g@gV#=#S3kw8I^&q;_?;92rTzt(>iJ z=To{Gz4j=h&vs@$kkgzZ4plEUd(TGkMppGN$MIXP`YT3(+pa5N7pKEiQp4nibV8a44$HVXxYlt$9azRo6@V9+ky^-Vg_6IAmTYC)t&df2y{LI;eY>+`HxK4IlUH{m?hbD_xi>+G%e5s%f3G<}C7y2^RTqBPHAD*U%@CC;!jbBtJa^)zzV3^X1us;^H0D*UL#ak;T^*ZVGvDwpKbf+a=oB*;c}!Ry>&Kv5q(O z&TVhVVX}!cMo+Ww$tE`$HSlWbga2hQHXG!NoXZ#0kt?MqD#F68jW5D^UDFX{9KD(F zy6Zr8Toi20SicPxNSFeM#4-@UUMZNU_(Q5I47-Wr8xqYi>UvjxExU^O;#XXyLcS9V z!nkeU-AUT4z($*eYbMz02V-O;7&3%hF}6kxJs!gPsHFcw*I!>PrCRrCa<)bKz%ydB z%8sDM>W?em7ufrmh2YlGZMaI$&te$zJI!^WDjjBlMWFeiAX!yyXVL3C;lfxhNnbEeHSEhaa5h={|Z0$=q@z~3U zcgs261*)=p%{8H^S((k-f!ZQRP(&ZT8rJ{z&XMs%yTTz*l%rW%C^xB@LjI9-mFKc0mkn zQ_y8jtkyd4%b#&p+iXJxgG4rFh^&pDL^ZH+?$b{G7|v!Vx6&0136WA34OD#Jl3fvw zy<@ao1krl1RU@(D>M%Nck5d6QifY?x)Ph{3n!IXfC1%H?;zS7RdH?lPsMA7NJWp0s zHzcGMMMXtejQZN*#9JL(g!u?7k96Ox+wJ`Y=th^nXeM9myzU~>!L`6bV?93gKE~>= z_tD|7{A|^!iP%iLUvule1%0e>?1*w(XA27~JBTbc^HDMcLdOsGSi6w-^(xoD(%IUR z(19(ReoZ%fU}kfC*uKC4Y2zes6VpG|@OoJO#CZHyB)%WzYKsrE>iuZ{NjyqDh`3&G(ABBpn6D4AoSKSWJYT_e-L!O2*8So?`ISPxs?o_1W1DG-bFM}CG$p^h zQ(C&%Uf^WE^)*deT5<{rgC}1%qami7Z2HX3A^QS|wPQ*7l%x zN>Ph;vAX*BS_bA|N{R&+!`np7_;^qobLPE74LeR6p795frO!A7IpA_`CbDVi3GlvB zw*5;4b~ojDaEtz|&ZN}>?F-MfE2In~X{x5Zv2$WPv1i$R2hR*uNGf2Eg?U|R0A#vx zSVW)>J?#xnE>=|^FKQwC#XrQ-xc?}V86_}Fc5#5eo-Jn;>@oX? zCRQDtp}`DvJJrrHGRGiiXOy}Q6>s{57b$d1K2-;Pg>Gq-r&=I&jIptIM{L4%n`!8c z$u_oAE1U>Vb-}rpJ$<}hu;+N9 zyO@NP8g@9+vW6Siiv;j!)8Pdrmph$OL(>J&T8|n1KK6 zP0?X)@$YxB)PVicYZm)3VpYF8jfIoL7drAhD3&nzo$?2 z2L)dK7O-3QmtJWoo$%*lVB-4P-l_D&h(}#rv$&L)HNyfyP6rZ{QNO5{VS~S2kxWUj zaq&Z9?{@^<4qyFqVR5#`#aYp-ry=d z`&C3r^x#xRdP^cpbwV!hoJzk{h-74KI;ciQ{7r?jwzx~_8A1G;u368rH{TdsUdb=1 zJ9s=xa}BC$UQi4_nCW%QH`AtZ+~&fBy#edRD8VETKV@lrax#s2Q3hhSikIkrXsnr3 zec^hzShqkTu-D@;Dkr!Z!94j=ZRcICm_}-{Wt6f*L3!Ms(o~7u2W#Z#8A$D;4?7%n z^DoiJ4Dydm%APs?Xv=GVDgGKstFH7|SI==6Be(rr!kn<;mje#Qpa_HstPG8fQJthZ zA?pxVjBzVBHmAVG+dRPVzyd4j4}7ies3{$=Of4(Zuv>I$^BU&Sl+bgwSyL+-;S!+4 zX2B7C_Z6l8i?}M@j48-%p`Y<)dTloY?&cw8wIUL`9T8RmVL9kf?u-_d8K@=i>ac(u z632+x;8tw8pxCt|hzkS6!r8HHV^T21hU@0Yh4E(%#P%)O5Ut9xEDFvGK5e}9?-!i? zpBkzjC#Z6Y{PO#~I{4)6)@6-R#|w#q(JCR@oJ6+Hf)$UL~yP*@5BtFIhUq@2hb>R>=?L zTxyG_`i?EMFX=;^U$jxa3QC->T~_$r^|VrcElNEIIlqgdS@t=wt(hk}(}Va0Dcfhr z+Wy|lKJ8`3qWYB|aYi?;OboDUfh$cTlN|J>OCzVMKmxWVNJ*1;;HJ$jXsd1O>5ZvJ zBExyiE`Ahp>j9O3@4MF=SHxKMYtpb(dleIS$&g&4{x+nwU3>8zoHlkY+%e{UOhM1d zs<=$jZ>}wA{p@-l({JCe)M4A%`n&pCwmH8$#mmZ~hq>XNDeIXz=4E54CSKAfSPZHR z<9^|6n`9!bA{ou}m}B*d$+hK-uG_n?B>O&3&9 z#Be&__KW*G-BBbcdP3DWm0JlzG7Fi8g&4U9^PdoVNcr|4Cb~X6bvJc2ap3YYHKg1$ z8TB_4FRDNhQq(aW`a~$p?2QRNT~;qOJzBniX?sb3yZ zIdK-y;~i@|Q&Ri#+liF-L4Z}+Cgbkk_ z;$Pp?`LAdDNwOw!+qcCEnaa>d%ljvxxM(8{t%FB8Y#!4;>G{y&bF%Z^kNF3VPwTIb z%=ua~z}+4lwJh@ga7O;Ptk=QiU$ z9KE?0flh5sjeGM>*JMH)$A%UA8Rf`jo|4{RF?ni*Byawihm5v8@bIPxeIuIEJ5dn@ zmCqzkB|*e1ri4{sCQw`GUP=2(m6ha(vpybn+gyD5Yaj^c8`Ts2mbqO@w(UI{GZB-n z@$Cn~P3n{y@k}}5;qus97M@(V8mim=(rlU~wdoF?S@kUI=`tTQ85r0Vzc>+tE_yv| zD-K=8H7&{<$c$4`QZh=vi0_WOKrRA(TAHDq@J&{?zLRotbN~? z?5n7;?YR$Gb6b>@H?=ww)m1z1I@wa*l}sJ%B(a@9=V!Iq7rFArgszqK2glQ%>5Qls zKXLX!>)iNCOq?|Lo`I(86@%~e2lCJzsWLP7mJ;S2eM>5w3{RR~VSk#vxbrt-lP>J~ zWMwceALp<8?>&_k%qs|r7y0r|b2SU%N+6YE_Ayn?jK*fdTI<9xkCQH+Y)F9?Osb^A zs^&>ipR#`WbIEVI`&n`l{OuH6yN z+CKOYurvW1r0Zqr%PZOBsU3%-i8@6v4rES2 zk-GMHiOuGkEtPt-#%HNiogJ)JD2$sFOO*a1W)rwb!|9_@$Rw+aSEf<1)@UPCQhHM2 zNyS!|$hcVOvp>-Bj2si)4_n1WkLTGrjm13w9j13Jdw89Hnf};4P}g2u)7=YNhA=sq zIM0EmtNre6Rtsif2*?wCXQkM*=%<#$^7b>$wM>t-C8?T6kG96Mj>G-X@q-tG##y*X ze&8_#$4K;s5s|bn6XghfytODX_GM(!ffynFC{q<*L!}RT=0pK;f_p-4d<>b3 zix=^r(38vJmody)IRkO+^Pe<78(14YpdBYBlE}Tf;%nJS8mprNgbDu#!o0 zDYuwm4^!i1usdlxGp;#(knH&gp<*+6*rqG(3TYV@d!#+*K~(e-J|T`Q$GaCy9by`w z2r8jq+RKUurJ{<_E~8tmetdM}g`Q{Mf& ze}KwQYy-1!+L3x=8K7$dBPNE&rN0?73R+eyUUGh7$~o1=6v_C_we9dkw@GE65f_zE z2wow4n)NJgZW!;N!#_7pgJD};o^;ZE&Jq5>?O-*Bg~(1Co%m-zx71M zjDIvnzlxbK9_6$-Yrn}Vd1=X#^7XSi{iT5)b5vjK*C^+C#}m>hb?Yh2!6jF1`M6Or znu(GET85dO)$zSA_U&Kd(o@s#)%FGGE$d5cb8x_!7tNoy5YZmxj^nU4ZyA(VjEs)z zRE!BO>JI9C!`-Ylb4<}Om>Ld=Y-Sp(S64kGM}zTQBE4o8msBV*vBsd}Xtgd534JUoQXJR~UB%>7A+ zNldEOJ9bj?k)eaZ5{g}Qv=tB!)bCLjbT!kf<)j@T15zvjD*I4bfi zGnVj!UP*0j&Vj8Sm9I;c#WR1pFHDzQ&|JpjP^(Jy_9>AKSsFLz(b#7XDZ{`hs;IMpi5KAU%_mc{96L0?$pVKO~Lszz6 z-?nLQL9-g(22za^^_RE`Q=AP|;$$78-@3L$#D`_zQh zWYU+ov!rZ}yxcdUi)Ul_h>W=-K^`w-oMT@P>L)I64V2mu?`IN6N@Q*VRnuTKy7w^cD zb?wycVQ|)0X>88ZGEyD%9^vNWWqT!i)~Ojk&807wAwNStXJKFMeGBAX+=I`Y$FR*l zQ_&RY*)8So!n*~18BWZ7?UnB+k}0az*59&8S^e#XRN)rHo$9==_PB_v2%B|E?pT`r zNcqFN*qzg1<+2i)Y5NCHa)i$8^&U=^eO|aKSASws#vvbuB;=L_&4WJD5Em6m_$9rZ zmO=;{kApXH^k^hgm2^7@*#(_dBLsk-vXYI9Iw@{ttuNX<`@l>rHp=-+dCt>~4R^y#{Q zmmQTiWg!;U+#Ba?Vy&B3vP&Lroi%am)ISvpn7==xKXGRIa&6DCC$Ps~Fv-foN>yA~ zvIE!KEe;x_IMT{~Wu2=QA*%Rx=@-%LXapH2s=Hn5z24P0z3oYGPm<4NSzXz0CPy`Y zcJ3M-x3)kItz7o>O;h#^8#R=u%TJ(036y}*vLoA}!J84a3OQq|m97uR5@`-OsRpE^ z-R$?MiMimNU07S&s~=h#tv=!ZN}toPq)OY8)P0+*b{b;fr!v`YA~M0@v{VCINKYFh zQ&l5o$ryva(k&>qC6CFc`da)Ir^TiTx4%4QL_~sp{CJn3z7bux5qMF`1g2eK{~5wz z09Rx75hI-yXkeASN`F36JdMU1??X|m*pIP#c7SfkLLaZXu_B6NTD*+{{93@uWqM0C zs6mESAoIy6bCA593^a&NdXq|6zwRyQ#m2Xq(TFzH3OH;0vD1sDf~T5;sv}FEdY=Vi zCl>P$=kaqV)}#?KF(k_ktG;jZ+#9HEe4I=V)jwzzt>hL@CUs0r}fvVIPAs>gXy+ZQ`Ym9xplXLd&S9#h-5Y+@&+s!~l$ z!Z0Trk>L;jLYTPL5MZM0V$l*Wb-@-)b^nOwOrrmrU>w=r+$v=-jbsRd7M4`-4*OI@ zW`|_l*w?_m#I`IXV> z*F4R==Q!Sql<^ma+Xwdu$48Cxpe#PxW`h=a`9Dbc-Rb_s!QG}rUwkFVbWZq@xBoop zA(zDrR>Ijy_f*6Yk6FotkQd+fuXOCkMKgMOu}!v%YbJ=Rm!w9D?9}Cr z5cEq`33pz(pNHlkSfh1nVyKzQhcJ=H6M65*F^c-5NA;5%hMzghtH2MY@JIWpSy2x5 z(>*DAl-?W;iy5Sik+wjpCuR}0uGMbS7X|w0&FCqG@KRmMrmH1!E=^+OEeL7y(~9ft z+Fz}$t<8J0o%!f}aL>JdFGOP{J5A~V!2`Q0lO&I0RzBh&7P>)bBKG-tWJQ%E$#?+0 zufNV%dwo_$HmZk3dNP6NbozR0D#?zl+UqiGQOQbI4HLKrbgY4Ml=qy_(2uaF*|i)$ z`zQ5wiJEUHPr04=^Y4z)8pA^^f(|6yMzcsKe-l`JQk!T~rG#PM!Nivg-OIKDjtA~t ztZZ8+!@u;PHxBbB#8|=$A<6fGTxDaXjfeO4`XtH^77enTJnzXSjJFGqaO%OfHgYRZ z^L-f|vZ%*CA|MV4Cku4z@&P(7J`91b@Wr>!{l4)rjERfq<~7D}hbpHKBicO+-RqrP zpudYVRn$nlhzqTexQVJQtO66ARR-zE%@^t|M7xW;Wb zT8xKnFO0(I*;zldb@4^kQPtNt@3lf9s;OUxW8PfKM288(o=eI-GoG7i-CLp;Vg@H_ zX zVOW~-0!b#VUj!pe_3GRgvIUCwiL2 zLxz%bMI3Y^<_*j&66?~&) zL-eLt{Ir*>+wlz!4IghFPpG4OAaB)UQTjQd;Bfkk)Cr=1?@xEr2GWgRb}U^;t1IL| z1d9@vk0%0g<=$D~voN8a_m2_b=q1PTmUvZ)5hfPHXrON9%A0l|#5&zdN>Zco^!aOu z>%y~jtgwD-16IW9plVZV{}`FcPJP21UOv4I*JivDrpR@msPpMyVv#F+pXUGz+=G(^ zJo;CPinb7ijc^&gAKAV9Fh>~sqbKu|2rJc_rmF6MTads3#@9C?kw11br+B)_e_Ld5 za6fG6uSm1VCx%v(woa$yp|D{b>W@@mkz+Ue`BBR}AYRZ@&8R3fY^w5zzLLYK=tw5S zB9|KFeUH>&6oGp6uEoNG?`x_q7|zURU114_In#reGb*ZCaNe`_qaDAlgk?j+M||Gc zX%NdT4#3QaFL3JS=R^d#a4kK?FpiisU2+0!mVl z48oi>>bLi|?{n@w``-KG{5i$+s&`daS9R6u)zt$aXOW)(Vl^dIB>)W#4Nw7p0OSf8 zwxX}29RR4Rask)?0N?;bXb=DsME+nS1~CQ5L%~Lhh7O>C9M!1NFn;kY5Yzm@1t8}5 zqXPjk92`py@(Qq#LH;?`F$Vf;>~l~qfd>FLEnVGQe_t83-F$34^&H&18Rc&X2>_@m z{?h%6!vzEdB?Lqy1cVvka0y{yi5qZ$0muvgJsV-r?c+aK3N?jPEC32J0XSR$J@xl& zZh>;>A8ZU_w6xzkXy6PXX}|5%RnJD@9o@^2U@#rhQ&Iw(gg`>g{)0P+W;o-X>| zFtqHq{hy#s%)jZQ#-N@qC6P4UYMQL?RhM?hQ5+M-i&; zuX__V0Qd?DD8Lz`1AJgl0eA-iG3u$FgBbk}hJXSnh?zk-E~*p6s5Pt!VoY!Z6^Kni zj0NIrAoc_?HaG$mEmsB+xauLlW)KU?2|&36D6axB@gE%k$OTo=K|OFyf`&;!ObcRD z5R-uzR0R+qrb1Z+KY1X&4$49JtI__!;4MH0V${mW16Kn5U-r=eGzL(v2+E&>a%K>Z zf%q2cl?2HgoZs)thROjl1c@v%t-AIV-5bm!68XCyWd?;A zaT!q$>=y<#Lr@kVfC<|MP>T}(qFdm#2pB?ogU<)mi=yAxU+~uj4PXPg`!5ZY;QW{L zKfkDIC`AEdg9VMSt2E z$p1bROyaM#`2v)q^t8c2ZD3gJF2SO++=+c>wZj2iFxB1JU13WyHU0xg5AFL;m2#KU+N} zfd1#y3wHkFWE=~g&Hg$Wr-JzJCu1~l(?`7wIiMW!2RooPbC6J*D5~!-j{N(n9n}SP zA{T(005&Ej7A6KZ78Vu`4mK`6IRQQ%9{zPwG9q$1Y6f~bYFb)G7#}+$GY<>6f(_gT64B9^0SE~i zItd!`HFzQi&@jO77^trqe+WEYLoqP1uyJtlK!sLf0D^{&4uPU$U_ik%q6MLj-%t_^ zQYJxpOfnryEM^aKcvxC7Hj6@24~6cBJ(!S{XE+Y-HA<@M)U0gm9GqOjH$+6m#3gRt zQdCk_QB~8^H!w6ZHZirfv9+^zaCGwWe(=!8*Uvv9GAcSIHZC5Ko{^cAos*kaQd(AC zQCU^}r1@z}YumH-j_197ulwH&3=R#CPfSit&&%iwLnnb^FbQIk%IjcRdXO>0!?4K}(u$jU za9D(N_b9A9Kj2=239qp3qeA-?*}oT9`2SO6{|M}#am@qx=-|31K_>xZfv>yXHRKb! zlP0f#q>%NT!!j3-$RkWKd`~D zsdU*zbQJ&23;wf%h^xzZ*{3|+U&e_pj=4_AJ#NoywL9osjW&bUP=-q{{xQA!2~Exm zRUi5&t(|Szv!j@+Q}Ph|InYI|?8&Pd?+mYzb`y$_r@OLWrWr0i=|vYhA_18(B(Myr z_0TevhjL>QsL;_0SP>QFRg^ue)hYlg%!}RaHQFQKA&f-pPSzml-2nYH*tuNDl zKEb4LNK`2N7GFR0#J@2Pha63-pN;FAai}(im~K2DQ;}|%n#6d#5n6juvg6_7ukHBE zsqv{38j@kx$s_gNGHt3`2k1@bYmy6QS>C9_3*IrjrPNXq@-cq>N#dHGs) z+&bQ)BCkwPP>oYkcQt3ost)_*r`pr=sZ)?~5f5jJHuVI!Ih}DI_5onjUfIFk}5^Zpv#q#|I+DWzW0{3ib+8vYYwI9$tu@B&9@4LB8C5UypMV{kN zH+M!~O}V-ZIV_05tc!cD46Ng;D|$TKtkUjCNcBnPVq)nf_qCeU`^RzKpo`X?XsCF} zvoWcR&GY2SPL=U;gtTi`Rw6Oj^8JwVqaS_t7E;4%Hg;f*hov*WH^iuK@oz*tr1>ujl+-l6R0{QUjH7g>Fv9X9t7z*~)o(>!!SQ+gA!5m3-wqw?>bnT+n(l z+Nd60w7)mCoi6or6HD?wN)NCU6d1ujdL!X~uFvoF;KshtX0{UfeWfRQSSg*sZVe36 zWiJD&edKu7;A=Vd3L?cjnwmjy0p;l^?27vAWh8+09WQ;0`jLMi(__3rwVw$K?AK)? zmeTb)^WJ={OrF)C=Cr@uSVTMZ(!U|iwsqTYEqcQcVW{vSwEeTIyUHM~UG3Jg1GU-w z0CWbfipO>|Fa8GZM;BC;$a&E=b0-9Cam;X;x=k=GFWGP9SxVqI%<+-yLqM+-!%~q2 z%7IzsM54x5++l37Dy*aw=Yh}^aQEE_kr*b?G_>yEeS7F`Qa5a+Z?A}97SR#@MK;OA zgyeCW@ilW-;D?a0*X&1)ibbfhQr-$o<%bY;c*pUMhNI)Y6dp{MX^}?8&TGS7>M}%2 zZQA=&vG-B;8SX}+?^}mkGV&(-59-8}zxBHtur{+{-8M^20+G%xY?ni(Jl#?(`+_1XCa;@BQev8dga!QuyF|q@NjYQaj~)Si1G0Wh(N-@BPJmtBq1OqB>YuV zp-?CW6axnX1BVC~8<&Wh3#+H8l|p`Y$yV{GNr9{IjA0PzX8(Hh_tR zhJy>%CN*LJ4J@coC9H9z-EBOG@`aTQp!f_!n2djDeQ0!A?Q2#{DXC80gSH-w)Bi;sIqM z6_iiI(9!cCBd4$oV`gcB3wajz?Cm4}rM^5Zp!`X?x4`^KB+F~3jff)t^}2DOCeu#^ zseax8YPBqzi>g^;@A{^Mz1+U(MVQ0ST2ePL{TcU9hQyYqG-bpxTb|~O1p`AGF2-xA z)v&xXZlhI+4yPZ_vhGfvcMIWrYHB=VAFaws!TBl8$+8n|DBpnugtRtwLZ(Dx!tO5q ztY#?^6Al)naPqijLib!>@)ZI|s#d=H( zJ5bCM?Zb6W;MJq9rwo}UA2yq2r!jjl`R5&fUe!!xKjgY-u4n1RB51gZv}tycH4^=4 z)f7x9=1_iptb^%9-1%;~solIObfN8NQ=O!3jN?4I0UX800Iz1i3KW(PEA|w?{E*e+ za;n!oi3Flo%$F^HD3pkvw^qw$n(EF$tR%-HY_Wbar&Kvzn)q0KQh71}dZUGLE3DZg z0UqbW@8{i%l@wN-Gzx==j4FyyqBL6Q#{Iahq8!vYAp1_!2m3 z5v4!w*~!k;1!vv^y%{E;jThebge}F?O`apZ4eWhhGg|Yt9+R3Gzb@Od{`M-9V<1`@ zli)B~)BcKndGk(J3w?z@Zg!uDYT7*l#q9_5sHiNIIYy)e9NMS6 z_|#C(l%`x5`V5bK{U!JP;dxwRp^>rq7xa03!xN76!KHVq8ou3r!I7bznBB)0?#wTD zL5c8b)1TQiF=XI%6;Nq0ZEiwlvf~PjG9C z3f*2Qpcz^TRtR^6Ph(!@YY3&>k4hJ?JE>pt@qbjfh6E7qc1`iB%kC~Z^$>oV_{;|- zhH?mItA|yhG&-~S%BGJraK>VSIMdk<;p2W*;uVioI8C^^Y8~ul_K#egnn+h^ainGR zzc4{9aE>cxF<^`Hdzw>^p2Tj1{dB-H?+q=1R4FP>G{oOEF~Yx}TtQX{C-(i~wwISYBx==|l&Me_5nFzxbm<7?CRy9DQ=$V3~U zBti$ZE>gn?2Stu_&-)LtoGdNno72b4>ZBqmVF?eq1VZbr)CX<~XANn6Czc5KAaB#C z{vg3(N;KRp2O$@sO(hhx@o~!tA6rC(!aQtn8D4h4$0IpoF%h?JD)-$yfZd2Y)V$#3 z(NxPp8Lv!T@`SNaUE&Yh#F5vQWKP3ayr!8^s$9^Eyy4Z>4%0L(-@p&bgw6N-ZFf?x zAYr4rYHzh1+J1InWU{Gn_KJuifp#u_`XN&aEB@1&qQUP{NMI<^kJ>aj^!@tgn zp(cXfMXt%D+!B*of}(HCT@A%V*s|n+Ov0>wx1wIZ4`OcGt!(IEn+ z{jSBZMB*e5VG~BO$^2ngcmPI|;v`{4Dd9MSfZr5Z1v_#^ETA#VS!GH8C9wBFv3uM7@KRZ z!pgnEqz7~|J0!j*^*Wg!U-=uU52}q9aTD4$-AW+IY9}PPR`}Rf$(FC`UOMCV`R4W? zW*M$Vk9o$F5=X35sFViYkaD35h#CyhziA5$&Db<2l}{D;%0Q)3XDz6csd!~DpLJGo zwe!f2dc242&49J`J1ySP_)L$RIS2_io!drSaajACMz6c@nV4>+x+?oqRo}uEn$@74 zugvdsQ5Q*Y8Cg0KoSg_9=2|+bRZxpXgwSmsvS)DZv-qni-=rCn^|}sMmy^b(h|gs7 zk1KH>&4lGNQ8wtlhZhxeaT?b;HkatL-Io|AB_|g>>7pJMXX6*1$pS=}!3^>k`u1kD z(r3+Q;ifk+KIjsg2vUr6vncbAWyoZ_ug6|-+@5!Motfy1rf?KQCCnM(JVyA%Yga}6 z^>CTSYP2eoHbQ=fA*vd&V35j-_m*o#eHMc=Frzbwk_ zq`G((F0U6cAA{Spk^hi_dBHOvb}8HgqO!ZFr=FQeGJ5YVq_x_5HcyI_+(D5%oy@Ci z%Yny+Bh$iquZ}EtoR?uo$jGf48M2!DyaX5KZ;k%6V?PS+{Jxkph zL{Jp^*Xz*{o26#{I7hc~mcsj<=-)?!>}v@Z;gI;1z1~^$?7x~!cI}SxR?q$XE=Lx3 zea{WLjBG1J)hYwJRI`rnYq6v;3*cWBaN=)C)(gakfx z3NRdd_gYEdPJ6uN;dbcSHOn&mp!B#exwwdTuTGg(-;OP4yJY#>?Zpf~>e3zJR$}a` zfjnJhp6m0@_e?wDha?FzsXI73TBi1Ghf0LuW?Uadwk`aeSiXIzE!XsdrK3Am;Ku1E zpH$E862OO4U}b5PtsKG%x8k%MO7heixCZw8v|3s^NCuN{ zJ8`j3F+NDD887E>mHRGdN;*tVUdn*0o5uw}^B%-;!BwA`9;@ge?A#!kac4;)bN7Q5 z3MvlAjYXS)d^3OXmTISq=_Tg;4gDU`{9J-;Hc7^v3V9PGstmb7A zvK(bJI5%y%;RqS>;apZ&s-A0xwR66=ES{cnj(Ix$B-0LlWU5U{WIt{hS+koiM?vuC z07d+A&fBfR{e$;}%aXdOF3Wn24q*@W|>b$cg z;ygrXebF6~s)^&;-Y zO`lze>&hln9dEXueZV#`i%eDh%JD#~yebZM)CxBwU9c@5B^GJWo{vkLxe9qKJU{#h z2R4z^u6EKW_~>U`^!ScBxGJo-At3tKnNr=4+4blf5e z)jIQ@eN^(+KWd8wh-xkMhTE}PZM~=$pA4#ZH9krUJ1GW;dRumSSd~5=-xzbx2{zAd z#AeSvan>4WQ9u6XY;d*K)hm^x=;EK0GFfFzm(X$w!QzudrcSdcip3$F#1h@=ESljvsyAR4L$CbX+kta$-4z2^b zc&zlR_e?VrJn$`S<|Xy4aJmQlnJOCgueBW}D^S{`?-$|U8;$7hAfJ;@(9vL~Yu`8> z&ze(#VADBt^%adg)PapAMF|%vL={bZg@*INbp3GCX#%t%)BxG|Kpp1iph|z<{9pstPXV5B=10n0e%j zrwer=7f$ul_(DT*q~&+z$e~p@c^PX=dL#Ss1P(B~Tnb@yUKqt8Nte*5?v4t%wJK*L z*^l{rQ(Qwi)pYeBeEIde0S_zl)!qE0x8IDbVyMRLYDG_BzB(e$CyY#nl8XU_VRc_P zUZk=w8WxAyAIHHowta_tbS1nzXaCabF|{&Yo1MhKqQKxQOC=vs=d(?4%2us<+zvLKj|SGmgiyIdHHBrmxagH zule?F_4J}~s$m8xsY<8Id@X;hwsQ2PYms>DMEkOeg2CGhjD?KZp9D2u_#y4e@q>ZF z4$>xNi{g9^iFJ?cf?|4Y-%@(53C~pGTMddZNxdM0%rx9A>x&UdV1Mld_tTB+CMq;V z0(p#&Vcr&W9+JW#{V~^?cVP*I#)HApeMd~rDvAMPD83$u(tGoaHY{_)|RMAuK=Me-j-Iz z`X}~`w69&G277x_uEHCW%LM#vpI?8U&!b6Ko)6-$-lKlTYA-n4G`c~Bb?a$t-*Z}p zf#%4FXKJOL%KPt<8TK!Bm|GUwpUE`#SQ6e4+xQTu4dqTfFBWRs*jIGN5_-MaKtU`2 z!T5TQBYq+Gs~WBmYReYUNWHiXuPkXL{Zhu=@%HbOVgp5Yl?NLmE#QS-sjQ{4{8pSwW2oF2Zdn1m z{d=vj;gccH`-OZ1>(_l|a@`I6d*^@bJ3g=xkB+);?a9B{8pLRad6Cu?czKmN74l&z z0Ruc^Zx-AY7^if#wV-G`p`_!oAQRizr|KL_Y+vS@3%<6TEccP+EBb7Vz^SOY3+ogs zv|R9{$VLB_Lom!^9pA~W^`T22+p+>_okS;#)-^n5ZQb}dB;cD$)W}kIS4tv0ES+Jv zU6xX8ED5R;KHU7}frxKq?#(j`i!G@|AwE(E&k& zKL&y{m3uz=J=!GX>go+VfWO`{pL>+)S3N0~!rLv#?UTvtr#f54ao37$sUx}WQ^B*b zGiTqA{GK|EnxC1CSAm_> z*Uf4v4$9j#!u8yG{im1nZ2hg1&J7B0h!Lo!pRK&fAkSXl6H&p1s$}GzUaxDO9=KMT zK&nX-Xu?sEzwDhi|FiA*+M$6K=DchiJAUGYg_HVhZ7E6gc>=tzt>EUyh}!`h68y&( z%rUzc15~H;z9CUwIEeKDeJA<#c29FQCQe_0a?k8DpEWEm`h^+(6-pAJB$9qx_iku=q#x^1hfK#8MOIsv&lYTnNepYOZ7)lg|;t~lVRPSsaj8s4`;yy`dp z(rPV#IBY$6X6Z@8q4PdE+#<_Mqej!}L)Inx^#t+vS@YC{eno!7akOK86?URsHCxW{ zs-`M%8|BaXzWD_auYcU8j(>J;z*e*1E!m=b7w!Cu^eQEm$7v@LfWNkzee-nD3@3nC z+hDy|4yMKnxw_oi;8YU|ID%BU9eQMPhn=;XTHW9iLt8Iqcv%qp?7i3YQQ$}8h(+(( zD}JiJyIF#&uw#`Bml`aoVHg?xmpae4_HQ(J`xakW3VoE%UKh)}u~A-YC`dpWx4scB z&+H<-T@`si5~BWQ>cF|TAZw)a)>qmEu^I7T27SBQFFCb%#l z0ZXN26V^k?eg~pGxGfzokiaX~gwG{M8+xztJ4WqPb1l8hnd$Uy2jHHYtC;$zhr7be z77er~!QTgo_ndA{ocne5AKJKWR_+t7h^Gx!>NZ1SFUA>NT#xEj_PJI2SiWGY_{X<<+`+Fk@O%mx~Jri9&Ox$^?zJG^{3x)&L^S~K?5O1`bS&iM^Mn!J3pzlqqJG(>RpIIqUQGKD{$~Bg5ik90p{-vpT&ZKA*4>S|P#*JCr^^Qa~!)}t-0f+V9&S0GHP z-mG|-?N7V zwD*}7b9eaeWICy*b-us~cZLEz(3Xm|+@m-XeN$$x8{aW!GxsK<`~$WV#SBy5UVqbm zGWGfA_Q>UAQhx5Dx&aa}rp=dcz*SlNDZTZ**4elH(e7>+UqZ|&A*9*C0$sXX>ee=| zXRVhTi&W2wu_g)CJ;ac$RI}0Z%4ce`Lfr)O?0U{AE$x>#BKz%^0{AbbEfp=S6=)3i zIm0NHGJ#!(?-mGB7{ovCE$_n;-OqYXYFr|1bN92B`c}|wOCVv_P8H$ulGr5EWeD|) z3u@XNZK-Cqr^Z#Zuu_}cSo*voDaF0w8ZS+mFB0F?wjUn8I7_E8WN;C`?Z)ZSoWsFw zq(}va#-Eci9_GJg%pu0Qn>by^_mnSL)41k{3*jhf@qSj5^HE5YX^6H1J@wPb$=vZ) z3%?kbsjeg?3Z6%*h_cYgSyQqf4e>8oZ@7^M$~)husdKnA$lk2*=y)iEli6K4@4iy# zV#E8+ufVlS!N%w-d-kN(&DLtxG*XPV#=0ej)n%3f)9iSm{I#WFnW6iUEB5ccV@lnb z@gLAklC1NjJt2DB8u8#nXmo^E^EwgfKK6Z9*_Wj9vF#LPpE|F3aO1qDd|)c}Byvl% zQRCh|)qZO0=z)rRZBbk(LR`Q{8*Kj)%T_|)Ada*Q13qCXb@PIu!$S8F~ z!&1zr&TP#8PTSb^p}jLb*K$I?DA!s}qoeR!-fT|i9K)duS7XWkceX{g_4&!(HA^ML z1beI`$@Uvuesz_ksEG(93sGE6d+Zb#U|MMAM`&qOa7n;ZXKX8Gm}M!luJKav#y#>e zUp&v_!^!Y0@c_DwJT;q9;)lB?2TpMN!qGfn)Z!@Lf z$Ys%p^NRd!(crajT;N~kM~_G+hs(viT-dMjiuazB)ccx!Vp*d14M-Sb7}d!YyK;;j zpj_yUmOD_9>MVJfbpF;@nbgJgsosbdb0UIqEKWVIMy8allIN+d52u&4S{hXb1qX!j zL3}y&L?3#xCI7I+D_VvRJ$zmWzs|R>$XYDwsMm3XaJzeB7~Av141Zn~ zule!&P*OIpowE)FW4!91c)|Fo^tn*HnE8a3wb@Y1=Ry@9_|RN$g~iKea%?i1 zqZ;x^z$QVjLL)Bulinb}edVIR@m}h1W4GK03HZg}-nLTaQ;R6tks#$RT65&qb-{FV z8h7_WU+D6t&0W@>T`spAKIV4Vozs!MsWC8Ws5hs?o(+BcY}>>c zYScMxio+AW5!WmRKWOJCj2x((Pk+nWR8Q@zYVs<*tbnT>JO)KkB~fjaOf8HL-?#Rw z#6?R(-z)x-Yc>9AW&6X3!}T1xuUMY2#&C72`h`5ey{3_vt=-NtN8-`#YRsAH&yT)L zMw`12v{I)RF*aoUOv1(Dy!fzmnEi;8>zn2wr~V6KjQc8I8oQ4oDlYW0uR(0aw%v<4 zzgZp5d8dyo#RGl7En;O;WdR6I_lkUWyh7-#Uhyrmpl&q|Z*jiZj!|*Rf%RD61sa*k&0$!|yT^nPk7Qdq3MMB;Hm->lORbZ1 zn)%;MW=N@uCnZ$K+-9kkjBN-U#L6{17G}uPMx$STm->xKk;QpPq*}YL12-;A+Gfnz zgx!H0cVA7F#$q9m`?XBTj9^E#_Kt*KD1_M`H;`=9rst%H+Pmt$%+5q&XL$}=bnINy z3XWQRvH#K!A8|trFE$2Ut=_2)+lFcknTzSb1S|X|KN*fhQXjDRn${b{8jZbKIIgX? Kj$YG3&iw~PYp$RG literal 0 HcmV?d00001 diff --git a/txt/menu_system.txt b/txt/menu_system.txt index aae2551..5389c9f 100644 --- a/txt/menu_system.txt +++ b/txt/menu_system.txt @@ -724,4 +724,6 @@ http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc --> erledigt für den ffs handler --> 04.06.2011 ERLEDIGT für alle (in den base handler verschoben) * debounce auch für das loslassen erweitern + + * INFO: LCD mit festem rechteck 520x280, dann auf 50% skalieren \ No newline at end of file