diff options
author | Yves Fischer <yvesf-git@xapek.org> | 2011-10-11 21:50:49 +0200 |
---|---|---|
committer | Yves Fischer <yvesf-git@xapek.org> | 2011-10-11 21:50:49 +0200 |
commit | 324c5ba9098c1010d0aa8c1e26b95509878ce9f2 (patch) | |
tree | f6ef2d537decaa2e1af6d4b9c4c31161b22333ec | |
download | mini-octopus-324c5ba9098c1010d0aa8c1e26b95509878ce9f2.tar.gz mini-octopus-324c5ba9098c1010d0aa8c1e26b95509878ce9f2.zip |
Mini-Octopus build from r@171
44 files changed, 8066 insertions, 0 deletions
diff --git a/firmware/93c46.c b/firmware/93c46.c new file mode 100644 index 0000000..4af0f45 --- /dev/null +++ b/firmware/93c46.c @@ -0,0 +1,359 @@ +/* + * Author: Benedikt Sauter <sauter@ixbat.de> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "common.h" +#include "protocol.h" + +#include <util/delay.h> + + +#include "93c46.h" + +void flash_93c46_parser(char *buf) +{ + //UARTWrite("flash parser\r\n"); + switch(buf[3]) + { + case CMD_93C46_INIT: + flash_93c46_init_usb(); + break; + case CMD_93C46_DEINIT: + flash_93c46_deinit_usb(); + break; + case CMD_93C46_READ: + // read addr, length, buffer + flash_93c46_read_usb((unsigned char)buf[4], (int)buf[5], &buf[6]); + break; + case CMD_93C46_WRITE: + flash_93c46_write_usb((unsigned char)buf[4], (int)buf[5], &buf[6]); + break; + default: + //UARTWrite("default\r\n"); + answer[0] = buf[0]; + answer[1] = RSP_UNKOWN_CMD; + answer[2] = 0; + CommandAnswer(3); + } +} + +void flash_93c46_init_usb(void) +{ + answer[0] = CMD_93C46_INIT; + answer[1] = (unsigned char) flash_93c46_init(); + answer[2] = 0; + CommandAnswer(3); +} + + +int flash_93c46_init(void) +{ + //UARTWrite("init\r\n"); + SET_DDR_OUT(CS); + SET_DDR_OUT(SK); + + SET_DDR_OUT(DI); + SET_DDR_IN(DO); + + SET_DDR_OUT(DIN0); + SET_DDR_OUT(DIN1); + + CLRPIN(DIN0); + CLRPIN(DIN1); + + //SETPIN(DIN0) = D4 = low + //SETPIN(DIN1) = D4 = low + + octopus.ports[19]=PIN_OUT; + octopus.ports[18]=PIN_OUT; + octopus.ports[17]=PIN_OUT; + octopus.ports[16]=PIN_IN; + + return RSP_OK; +} + +void flash_93c46_deinit_usb(void) +{ + answer[0]=CMD_93C46_DEINIT; + answer[1]=(unsigned char)flash_93c46_deinit(); + answer[2]=0; + CommandAnswer(3); +} + +int flash_93c46_deinit(void) +{ + octopus.ports[5]=PIN_OUT; // this is wrong! + octopus.ports[6]=PIN_OUT; // this is wrong! + octopus.ports[7]=PIN_OUT; // this is wrong! + + return RSP_OK; +} + +void flash_93c46_read_usb(unsigned char address, unsigned int length, char * buf) +{ + answer[0]=CMD_93C46_READ; + answer[1]=(unsigned char)flash_93c46_read(address,length,(char*)&answer[2]); + CommandAnswer(length+2); +} + +int flash_93c46_read(unsigned char address, unsigned int length, char * buf) +{ + //UARTWrite("read\r\n"); + //SendHex((uint8_t)address); + //SendHex(flash_93c46_read_word((uint8_t)address)); + unsigned int i; + for(i = 0; i < length; i++) + buf[i] = (char)flash_93c46_read_word((uint8_t)address+i); + + return RSP_OK; +} + + +void flash_93c46_write_usb(unsigned char address, unsigned int length, char * buf) +{ + answer[0]=CMD_93C46_WRITE; + answer[1]=(unsigned char)flash_93c46_write(address,length, buf); + answer[2]=0x00; + CommandAnswer(3); +} + +int flash_93c46_write(unsigned char address, unsigned int length, char * buf) +{ + unsigned int i; + //UARTWrite("write\r\n"); + //SendHex((uint8_t)address); + //SendHex(length); + //SendHex(buf[0]); + + for(i=0;i<length;i++) + flash_93c46_write_word((uint8_t)address+i,buf[i]); + + return RSP_OK; +} + + + +// Write enable must precede all programming modes. + + + +void start_of_ins(void) +{ + CLRPIN(CS); + CLRPIN(SK); + CLRPIN(DI); + + _delay_ms(5); + //SETPIN(DO); + SETPIN(CS); + //_delay_us(2); + + _delay_us(2); + SETPIN(DI); //SB + SETPIN(SK); + _delay_us(2); +} + + +void send_sb_opcode(uint8_t ins) +{ + uint8_t i; + for( i =0; i <2; i ++) + { + CLRPIN(SK); + if ( ins & 0x80 ) SETPIN(DI); else CLRPIN(DI); + _delay_us(2); + SETPIN(SK); + _delay_us(2); + ins = ins <<1; + } +} + +void send_address(uint8_t da) +{ + uint8_t i; + da = da << 1; + for( i = 0; i <7; i ++) + { + CLRPIN(SK); + if ( da & 0x80 ) SETPIN(DI); else CLRPIN(DI); + _delay_us(2); + SETPIN(SK); + _delay_us(2); + da = da << 1; + } +} + +void send_data_byte(uint8_t da) +{ + uint8_t i; + for( i = 0; i <8; i ++) + { + CLRPIN(SK); + if ( da & 0x80 ) SETPIN(DI); else CLRPIN(DI); + _delay_us(2); + SETPIN(SK); + _delay_us(2); + da = da << 1; + } +} + + +uint8_t end_of_erase_write(void) +{ + + uint8_t delay_tmp =0xff; + CLRPIN(SK); + CLRPIN(DI); + _delay_us(2); + SETPIN(SK); + _delay_us(2); + CLRPIN(SK); + CLRPIN(CS); + _delay_us(2); + SETPIN(SK); + _delay_us(2); + CLRPIN(SK); + _delay_us(2); + SETPIN(CS); + + do{ + if(delay_tmp-- > 0) return 0; + SETPIN(SK); + _delay_us(2); + CLRPIN(SK); + _delay_us(2); + } while (GETPIN(DO)); + + return 1; +} + +void end_of_erase_write_disable(void) +{ + CLRPIN(SK); + CLRPIN(CS); + CLRPIN(DI); + SETPIN(DO); +} + +void erase_write_enable(void) +{ + start_of_ins(); + send_sb_opcode(CMD_EWEN); + send_address(0x60); +} + +void erase_write_disable(void) +{ + start_of_ins(); + send_sb_opcode(CMD_EWDS); + send_address(0x00); + end_of_erase_write_disable(); +} + + +uint8_t write_word_step(uint8_t add,uint8_t wd) +{ + start_of_ins(); + send_sb_opcode(CMD_WRITE); + send_address(add); + send_data_byte(wd); + return 1; + //return( end_of_erase_write() ); +} + +uint8_t erase_word(uint8_t add) +{ + start_of_ins(); + send_sb_opcode(CMD_ERASE); + send_address(add); + return( end_of_erase_write() ); +} + +uint8_t recv_data_word(void) +{ + uint8_t i; + uint8_t da=0; + CLRPIN(SK); + _delay_us(2); + CLRPIN(DI); + + for( i =0; i <8; i ++) + { + da *= 2; + SETPIN(SK); + _delay_us(2); + CLRPIN(SK); + if (GETPIN(DO)) da++; + _delay_us(2); + } + + CLRPIN(CS); + SETPIN(SK); + _delay_us(2); + SETPIN(CS); + CLRPIN(SK); + _delay_us(2); + return da; +} + +uint8_t flash_93c46_read_word(uint8_t add) +{ + //if(add < 0 && add > 127 ) + // return 0; + + start_of_ins(); + send_sb_opcode(CMD_READ); + send_address(add); + return( recv_data_word() ); +} + + +uint8_t flash_93c46_write_word(uint8_t add,uint8_t wd) +{ + +// if(add < 0 && add > 127 ) +// return 0; + + erase_write_enable(); + write_word_step(add,wd); + //_delay_ms(1); + + return 1; + do + { + //write_word_step(add,wd); + _delay_us(10); + } while (flash_93c46_read_word(add)!=wd); + return 1; +} + diff --git a/firmware/93c46.h b/firmware/93c46.h new file mode 100644 index 0000000..817eade --- /dev/null +++ b/firmware/93c46.h @@ -0,0 +1,113 @@ +/* + * Author: Benedikt Sauter <sauter@ixbat.de> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SPI_H +#define SPI_H + +#include <avr/io.h> +#include <avr/pgmspace.h> + + +#include "io.h" + + +#define CS (B, 0) +#define SK (B, 1) +#define DI (B, 2) +#define DO (B, 3) + + + + + + +#define DIN0 (B, 4) +#define DIN1 (B, 5) + +#define CMD_READ 0x80 +#define CMD_EWEN 0x30 +#define CMD_ERASE 0xc0 +#define CMD_WRITE 0x40 +#define CMD_ERAL 0x20 +#define CMD_WRAL 0x10 +#define CMD_EWDS 0x00 + + +#define PIN_S PB0 +#define PIN_C PB1 +#define PIN_D PB2 +#define PIN_Q PB3 + +void flash_93c46_parser(char *buf); + +int flash_93c46_init(void); +int flash_93c46_deinit(void); + +int flash_93c46_read(unsigned char address, unsigned int length, char * buf); +int flash_93c46_write(unsigned char address, unsigned int length, char* buf); + +void flash_93c46_init_usb(void); +void flash_93c46_deinit_usb(void); + +void flash_93c46_read_usb(unsigned char address, unsigned int length, char* buf); +void flash_93c46_write_usb(unsigned char address, unsigned int length, char* buf); + + +void start_of_ins(void); +void send_sb_opcode(uint8_t ins); +void send_data_byte(uint8_t da); +uint8_t end_of_erase_write(void); +void end_of_erase_write_disable(void); +void erase_write_enable(void); +void send_address(uint8_t da); +uint8_t write_word_step(uint8_t add,uint8_t wd); +uint8_t recv_data_word(void); +uint8_t erase_word(uint8_t add); +void erase_write_disable(void); + + + +uint8_t flash_93c46_read_word(uint8_t add); +uint8_t flash_93c46_write_word(uint8_t add,uint8_t wd); + + + + + + + + + + + +#endif /* SPI_H */ diff --git a/firmware/Makefile b/firmware/Makefile new file mode 100644 index 0000000..f3553b5 --- /dev/null +++ b/firmware/Makefile @@ -0,0 +1,458 @@ +# Hey Emacs, this is a -*- makefile -*-
+#
+# WinAVR makefile written by Eric B. Weddington, Jörg Wunsch, et al.
+# Released to the Public Domain
+# Please read the make user manual!
+#
+# Additional material for this makefile was submitted by:
+# Tim Henigan
+# Peter Fleury
+# Reiner Patommel
+# Sander Pool
+# Frederik Rouleau
+# Markus Pfaff
+#
+# On command line:
+#
+# make all = Make software.
+#
+# make clean = Clean out built project files.
+#
+# make coff = Convert ELF to AVR COFF (for use with AVR Studio 3.x or VMLAB).
+#
+# make extcoff = Convert ELF to AVR Extended COFF (for use with AVR Studio
+# 4.07 or greater).
+#
+# make program = Download the hex file to the device, using avrdude. Please
+# customize the avrdude settings below first!
+#
+# make filename.s = Just compile filename.c into the assembler code only
+#
+# To rebuild project do "make clean" then "make all".
+#
+
+# mth 2004/09
+# Differences from WinAVR 20040720 sample:
+# - DEPFLAGS according to Eric Weddingtion's fix (avrfreaks/gcc-forum)
+# - F_OSC Define in CFLAGS and AFLAGS
+
+
+# MCU name
+#MCU = atmega128
+MCU = at90can128
+
+# Main Oscillator Frequency
+# This is only used to define F_OSC in all assembler and c-sources.
+F_OSC = 16000000 +
+# Output format. (can be srec, ihex, binary)
+FORMAT = ihex
+
+# Target file name (without extension).
+TARGET = main
+
+
+# List C source files here. (C dependencies are automatically generated.)
+#SRC = $(TARGET).c uart.c usbn2mc/main/usbn960x.c usbn2mc.c usbn2mc/main/usbnapi.c
+
+SRC = $(TARGET).c wait.c uart.c ../usbn2mc/main/usbn960x.c usbn2mc.c ../usbn2mc/main/usbnapi.c common.c fifo.c io.c adc.c i2c.c spi.c 93c46.c pwm.c debug.c +
+
+# List Assembler source files here.
+# Make them always end in a capital .S. Files ending in a lowercase .s
+# will not be considered source files but generated files (assembler
+# output from the compiler), and will be deleted upon "make clean"!
+# Even though the DOS/Win* filesystem matches both .s and .S the same,
+# it will preserve the spelling of the filenames, and gcc itself does
+# care about how the name is spelled on its command-line.
+ASRC =
+
+
+
+# Optimization level, can be [0, 1, 2, 3, s].
+# 0 = turn off optimization. s = optimize for size.
+# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
+OPT = s
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
+# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
+DEBUG = stabs
+#DEBUG = dwarf-2
+
+# List any extra directories to look for include files here.
+# Each directory must be seperated by a space.
+EXTRAINCDIRS =
+
+
+# Compiler flag to set the C Standard level.
+# c89 - "ANSI" C
+# gnu89 - c89 plus GCC extensions
+# c99 - ISO C99 standard (not yet fully implemented)
+# gnu99 - c99 plus GCC extensions
+CSTANDARD = -std=gnu99
+
+# Place -D or -U options here
+CDEFS =
+
+# Place -I options here
+CINCS =
+
+
+# Compiler flags.
+# -g*: generate debugging information
+# -O*: optimization level
+# -f...: tuning, see GCC manual and avr-libc documentation
+# -Wall...: warning level
+# -Wa,...: tell GCC to pass this to the assembler.
+# -adhlns...: create assembler listing
+CFLAGS = -g$(DEBUG)
+CFLAGS += $(CDEFS) $(CINCS)
+CFLAGS += -O$(OPT)
+CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
+CFLAGS += -Wall -Wstrict-prototypes
+#CFLAGS += -Wall
+CFLAGS += -Wa,-adhlns=$(<:.c=.lst)
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
+CFLAGS += $(CSTANDARD)
+CFLAGS += -DF_OSC=$(F_OSC)
+
+
+
+# Assembler flags.
+# -Wa,...: tell GCC to pass this to the assembler.
+# -ahlms: create listing
+# -gstabs: have the assembler create line number information; note that
+# for use in COFF files, additional information about filenames
+# and function names needs to be present in the assembler source
+# files -- see avr-libc docs [FIXME: not yet described there]
+ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
+ASFLAGS += -DF_OSC=$(F_OSC)
+
+
+#Additional libraries.
+
+# Minimalistic printf version
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
+
+# Floating point printf version (requires MATH_LIB = -lm below)
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
+
+PRINTF_LIB =
+
+# Minimalistic scanf version
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
+
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
+
+SCANF_LIB =
+
+MATH_LIB = -lm
+
+# External memory options
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# used for variables (.data/.bss) and heap (malloc()).
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# only used for heap (malloc()).
+#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff
+
+EXTMEMOPTS =
+
+# Linker flags.
+# -Wl,...: tell GCC to pass this to linker.
+# -Map: create map file
+# --cref: add cross reference to map file
+LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
+LDFLAGS += $(EXTMEMOPTS)
+LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
+
+
+
+
+# Programming support using avrdude. Settings and variables.
+
+# Programming hardware: alf avr910 avrisp bascom bsd
+# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
+#
+# Type: avrdude -c ?
+# to get a full listing.
+#
+AVRDUDE_PROGRAMMER = stk500
+
+# com1 = serial port. Use lpt1 to connect to parallel port.
+AVRDUDE_PORT = com1 # programmer connected to serial device
+
+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
+#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
+
+
+# Uncomment the following if you want avrdude's erase cycle counter.
+# Note that this counter needs to be initialized first using -Yn,
+# see avrdude manual.
+#AVRDUDE_ERASE_COUNTER = -y
+
+# Uncomment the following if you do /not/ wish a verification to be
+# performed after programming the device.
+#AVRDUDE_NO_VERIFY = -V
+
+# Increase verbosity level. Please use this when submitting bug
+# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
+# to submit bug reports.
+#AVRDUDE_VERBOSE = -v -v
+
+AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
+AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
+AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
+AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
+
+
+
+# ---------------------------------------------------------------------------
+
+# Define directories, if needed.
+DIRAVR = c:/winavr
+DIRAVRBIN = $(DIRAVR)/bin
+DIRAVRUTILS = $(DIRAVR)/utils/bin
+DIRINC = .
+DIRLIB = $(DIRAVR)/avr/lib
+
+
+# Define programs and commands.
+SHELL = sh
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+NM = avr-nm
+AVRDUDE = avrdude
+REMOVE = rm -f
+COPY = cp
+
+
+
+
+# Define Messages
+# English
+MSG_ERRORS_NONE = Errors: none
+MSG_BEGIN = -------- begin --------
+MSG_END = -------- end --------
+MSG_SIZE_BEFORE = Size before:
+MSG_SIZE_AFTER = Size after:
+MSG_COFF = Converting to AVR COFF:
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
+MSG_FLASH = Creating load file for Flash:
+MSG_EEPROM = Creating load file for EEPROM:
+MSG_EXTENDED_LISTING = Creating Extended Listing:
+MSG_SYMBOL_TABLE = Creating Symbol Table:
+MSG_LINKING = Linking:
+MSG_COMPILING = Compiling:
+MSG_ASSEMBLING = Assembling:
+MSG_CLEANING = Cleaning project:
+
+
+
+
+# Define all object files.
+OBJ = $(SRC:.c=.o) $(ASRC:.S=.o)
+
+# Define all listing files.
+LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
+
+
+# Compiler flags to generate dependency files.
+### GENDEPFLAGS = -Wp,-M,-MP,-MT,$(*F).o,-MF,.dep/$(@F).d
+GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d
+
+# Combine all necessary flags and optional flags.
+# Add target processor to flags.
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
+
+
+
+
+
+# Default target.
+all: begin gccversion sizebefore build sizeafter finished end
+
+build: elf hex eep lss sym
+
+elf: $(TARGET).elf
+hex: $(TARGET).hex
+eep: $(TARGET).eep
+lss: $(TARGET).lss
+sym: $(TARGET).sym
+
+
+
+# Eye candy.
+# AVR Studio 3.x does not check make's exit code but relies on
+# the following magic strings to be generated by the compile job.
+begin:
+ @echo
+ @echo $(MSG_BEGIN)
+
+finished:
+ @echo $(MSG_ERRORS_NONE)
+
+end:
+ @echo $(MSG_END)
+ @echo
+
+
+# Display size of file.
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
+ELFSIZE = $(SIZE) -A $(TARGET).elf
+sizebefore:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); echo; fi
+
+sizeafter:
+ @if [ -f $(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
+
+
+
+# Display compiler version information.
+gccversion :
+ @$(CC) --version
+
+
+
+# Program the device.
+program: $(TARGET).hex $(TARGET).eep
+ $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT=$(OBJCOPY) --debugging \
+--change-section-address .data-0x800000 \
+--change-section-address .bss-0x800000 \
+--change-section-address .noinit-0x800000 \
+--change-section-address .eeprom-0x810000
+
+
+coff: $(TARGET).elf
+ @echo
+ @echo $(MSG_COFF) $(TARGET).cof
+ $(COFFCONVERT) -O coff-avr $< $(TARGET).cof
+
+
+extcoff: $(TARGET).elf
+ @echo
+ @echo $(MSG_EXTENDED_COFF) $(TARGET).cof
+ $(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
+
+
+
+# Create final output files (.hex, .eep) from ELF output file.
+%.hex: %.elf
+ @echo
+ @echo $(MSG_FLASH) $@
+ $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
+
+%.eep: %.elf
+ @echo
+ @echo $(MSG_EEPROM) $@
+ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
+
+# Create extended listing file from ELF output file.
+%.lss: %.elf
+ @echo
+ @echo $(MSG_EXTENDED_LISTING) $@
+ $(OBJDUMP) -h -S $< > $@
+
+# Create a symbol table from ELF output file.
+%.sym: %.elf
+ @echo
+ @echo $(MSG_SYMBOL_TABLE) $@
+ $(NM) -n $< > $@
+
+
+
+# Link: create ELF output file from object files.
+.SECONDARY : $(TARGET).elf
+.PRECIOUS : $(OBJ)
+%.elf: $(OBJ)
+ @echo
+ @echo $(MSG_LINKING) $@
+ $(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
+
+
+# Compile: create object files from C source files.
+%.o : %.c
+ @echo
+ @echo $(MSG_COMPILING) $<
+ $(CC) -c $(ALL_CFLAGS) $< -o $@
+
+
+# Compile: create assembler files from C source files.
+%.s : %.c
+ $(CC) -S $(ALL_CFLAGS) $< -o $@
+
+
+# Assemble: create object files from assembler source files.
+%.o : %.S
+ @echo
+ @echo $(MSG_ASSEMBLING) $<
+ $(CC) -c $(ALL_ASFLAGS) $< -o $@
+
+
+
+# Target: clean project.
+clean: begin clean_list finished end
+
+clean_list :
+ @echo
+ @echo $(MSG_CLEANING)
+ $(REMOVE) $(TARGET).hex
+ $(REMOVE) $(TARGET).eep
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).cof
+ $(REMOVE) $(TARGET).elf
+ $(REMOVE) $(TARGET).map
+ $(REMOVE) $(TARGET).obj
+ $(REMOVE) $(TARGET).a90
+ $(REMOVE) $(TARGET).sym
+ $(REMOVE) $(TARGET).lnk
+ $(REMOVE) $(TARGET).lss
+ $(REMOVE) $(OBJ)
+ $(REMOVE) $(LST)
+ $(REMOVE) $(SRC:.c=.s)
+ $(REMOVE) $(SRC:.c=.d)
+ $(REMOVE) .dep/*
+
+
+
+# Include the dependency files.
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
+
+
+# Listing of phony targets.
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
+build elf hex eep lss sym coff extcoff \
+clean clean_list program
+
+download:
+ avrdude -p m128 -c avrispv2 -P usb -U flash:w:main.hex
+ +download_can:
+ avrdude -p c128 -c avrispv2 -P usb -U flash:w:main.hex
+ +fuse:
+ avrdude -p m128 -c avrispv2 -P usb -U lfuse:w:0xe0:m
+ avrdude -p m128 -c avrispv2 -P usb -U efuse:w:0xff:m
+ avrdude -p m128 -c avrispv2 -P usb -U hfuse:w:0xdd:m
+
+fuse_can:
+ avrdude -p c128 -c avrispv2 -B 10 -P usb -U lfuse:w:0xe0:m
+ avrdude -p c128 -c avrispv2 -B 10 -P usb -U efuse:w:0xff:m
+ avrdude -p c128 -c avrispv2 -B 10 -P usb -U hfuse:w:0xdd:m
+ +usbprog:
+ avrdude -p c128 -c avrispv2 -P usb -U flash:w:main.hex
diff --git a/firmware/adc.c b/firmware/adc.c new file mode 100644 index 0000000..a9449b7 --- /dev/null +++ b/firmware/adc.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2007 empronix (http://www.empronix.com) + * Author: Benedikt Sauter <sauter@empronix.com> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF USE, + * DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common.h" +#include "protocol.h" +#include "adc.h" + +void adc_parser(char *buf) +{ + switch(buf[0]) + { + case CMD_ADC_INIT_PIN: + adc_init_usb((int)buf[2]); + break; + case CMD_ADC_GET: + adc_get_usb((int)buf[2]); + break; + case CMD_ADC_REF: + adc_ref_usb((int)buf[2]); + break; + + default: + answer[0]=buf[0]; + answer[1]=RSP_UNKOWN_CMD; + answer[2]=0; + CommandAnswer(3); + } +} + +int adc_init(int pin) +{ + if (pin >= 33 && pin <= 40) + { + octopus.ports[pin] = PIN_AD; + + switch(pin) + { + case 40: break; + case 39: break; + case 38: break; + case 37: break; + case 36: break; + case 35: break; + case 34: break; + case 33: break; + default: + return RSP_IMPOSSIBLE_PIN_CONFIG; + } + return RSP_OK; + } + return RSP_UNKOWN_PIN; +} + +void adc_init_usb(int pin) +{ + answer[0]=CMD_ADC_INIT_PIN; + answer[1]= (unsigned char)adc_init(pin); + answer[2]=0; + + CommandAnswer(3); +} + +void adc_get_usb(int pin) +{ + + uint16_t result; + //uint8_t result[2]; + + answer[0]=CMD_ADC_GET; + answer[1]=adc_get(pin,&result); + //result[0] = 0x77; + //result[1] = 0x88; + //answer[2]=(char)result[1]; //high + //answer[3]=(char)result[0]; //low + answer[2]=(char)(result>>8); //high + answer[3]=(char)(result); //low + CommandAnswer(4); +} + + +int adc_get(int pin, uint16_t *value) +{ + *value = 0; + + if (octopus.ports[pin] == PIN_AD) + { + switch (pin) + { + case 40: *value =_adc_read_channel(0); break; + case 39: *value =_adc_read_channel(1); break; + case 38: *value =_adc_read_channel(2); break; + case 37: *value =_adc_read_channel(3); break; + case 36: *value =_adc_read_channel(4); break; + case 35: *value =_adc_read_channel(5); break; + case 34: *value =_adc_read_channel(6); break; + case 33: *value =_adc_read_channel(7); break; + default: + return RSP_IMPOSSIBLE_PIN_CONFIG; + } + return RSP_OK; + } + else + { + return RSP_WRONG_PIN_CONFIG; + } +} + +void adc_ref_usb(int ref) +{ + answer[0]=CMD_ADC_REF; + answer[1]=adc_ref(ref); + CommandAnswer(2); +} + +int adc_ref(int ref) +{ + ADMUX = 0x00; + + switch(ref){ + case PARAM_ADC_AREF: break; + case PARAM_ADC_AVCC: ADMUX |= (1<<REFS0); break; + case PARAM_ADC_INTERNAL: ADMUX |= (1<<REFS1) | (1<<REFS0); break; + default: + return RSP_ERROR; + } + return RSP_OK; +} + +uint16_t _adc_read_channel(int mux) +{ + int i; + uint16_t result; + + ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler + // setzen auf 8 (1) und ADC aktivieren (1) + + //ADMUX |= (unsigned char)mux; // Kanal waehlen + ADMUX = (ADMUX & 0xF0) | (unsigned char) mux; // select channel + + //ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen + + /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest + also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */ + + ADCSRA |= (1<<ADSC); // eine ADC-Wandlung + while ( ADCSRA & (1<<ADSC) ) { + ; // auf Abschluss der Konvertierung warten + } + result = ADCW; // ADCW muss einmal gelesen werden, + // sonst wird Ergebnis der nächsten Wandlung + // nicht übernommen. + + /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */ + result = 0; + for( i=0; i<4; i++ ) + { + ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" + while ( ADCSRA & (1<<ADSC) ) { + ; // auf Abschluss der Konvertierung warten + } + result += ADCW; // Wandlungsergebnisse aufaddieren + } + ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2) + + result /= 4; // Summe durch vier teilen = arithm. Mittelwert + + return result; +} diff --git a/firmware/adc.h b/firmware/adc.h new file mode 100644 index 0000000..3aa0a6f --- /dev/null +++ b/firmware/adc.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007 empronix (http://www.empronix.com) + * Author: Benedikt Sauter <sauter@empronix.com> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef ADC_H +#define ADC_H + +#include <avr/io.h> +#include <avr/pgmspace.h> + + +void adc_parser(char *buf); + +int adc_init(int pin); +void adc_init_usb(int pin); + +void adc_ref_usb(int ref); +int adc_ref(int ref); + + + +int adc_get(int pin, uint16_t *value); +void adc_get_usb(int pin); +uint16_t _adc_read_channel(int mux); + +#endif /* ADC_H */ diff --git a/firmware/common.c b/firmware/common.c new file mode 100644 index 0000000..9947c59 --- /dev/null +++ b/firmware/common.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2006, Benedikt Sauter <sauter@empronix.com> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <avr/io.h> +#include <stdint.h> +#include <avr/interrupt.h> +#include <inttypes.h> + +#include "common.h" +#include "protocol.h" +#include "io.h" +#include "93c46.h" + + + +void common_latency_timer_init(void) +{ + // us = 256 - x/2 + octopus.latency_timer = 206; // 255 = 2us, 254 = 4us ... + + #ifdef OCTOPUS_CAN + TIMSK0 = (1<<TOIE0); /* enable TCNT0 overflow */ + TCNT0 = octopus.latency_timer; /* TCNT0 Timer auf 50ms einstellen */ + TCCR0A = 3; /* count with cpu clock/32 */ + #else + TIMSK = (1<<TOIE0); /* enable TCNT0 overflow */ + TCNT0 = octopus.latency_timer; /* TCNT0 Timer auf 50ms einstellen */ + TCCR0 = 3; /* count with cpu clock/32 */ + #endif +} + +void common_scheduler(void){} + +void common_scheduler_add(int id,void(*userFunc)(void)){} + + +void common_parser(char *buf) +{ + switch(buf[0]) + { + case CMD_GET_HW_ID: + common_hwdesc(); + break; + default: + ; + } +} + +void common_init(void) +{ + int i; + for(i=1;i<=19;i++) + io_init(i); + for(i=26;i<=44;i++) + io_init(i); +} + + +void common_hwdesc(void) +{ + answer[0] = CMD_GET_HW_ID; + answer[1] = RSP_OK; + answer[2] = 11; + answer[3] = 'o'; answer[4] = 'c';answer[5] = 't';answer[6] = 'o'; + #ifdef OCTOPUS_CAN + answer[7] = 'c'; answer[8] = 'a';answer[9] = 'n';answer[10] = '_'; + #else + answer[7] = 'p'; answer[8] = 'u';answer[9] = 's';answer[10] = '_'; + #endif + answer[11] = '0'; answer[12] = '1'; + answer[13] = 0x00; + CommandAnswer(14); +} + + diff --git a/firmware/common.h b/firmware/common.h new file mode 100644 index 0000000..3229718 --- /dev/null +++ b/firmware/common.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2006, Benedikt Sauter <sauter@embedded-projects.net> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +enum signals {PIN_NONE,PIN_IN,PIN_OUT,PIN_TRI, + PIN_AD,PIN_RX,PIN_TX, + PIN_SS,PIN_SCK,PIN_MISO,PIN_MOSI, + PIN_SCL,PIN_SDA,PIN_PWM, + PIN_UART}; + + +#define OCTOPUS_CAN + +//#define DEBUG + +#define F_CPU 16000000UL +#define STATUS_LED_PIN PB7 +#define STATUS_LED_PORT PORTB + +/* red status led */ +#define STATUS_LED_on (STATUS_LED_PORT |= (1 << STATUS_LED_PIN)) +#define STATUS_LED_off (STATUS_LED_PORT &= ~(1 << STATUS_LED_PIN)) + + +volatile struct octopus_t +{ + volatile unsigned char latency_timer; + int ports[45]; + volatile char * msg[20]; + volatile int datatogl; + volatile unsigned int long_rx_cmd; + volatile unsigned int long_rx_index; + volatile unsigned int long_rx_bytes; + + volatile unsigned int long_index; + volatile unsigned int long_bytes; + volatile unsigned int long_running; +} octopus; + + + +void CommandAnswer(unsigned int length); +void CommandAnswerRest(void); +void USBCommandRX(char *buf); +void USBMessageIn(char *buf); + + +volatile unsigned char answer[320]; +volatile unsigned char request[320]; + +void common_latency_timer_init(void); + +void common_scheduler(void); + +void common_scheduler_add(int id,void(*userFunc)(void)); + +void common_parser(char *buf); + +void common_init(void); + +void common_hwdesc(void); + diff --git a/firmware/debug.c b/firmware/debug.c new file mode 100644 index 0000000..539a3e2 --- /dev/null +++ b/firmware/debug.c @@ -0,0 +1,72 @@ +#include <inttypes.h> +#include <avr/io.h> + +#include "uart.h" +#include "debug.h" +#include "common.h" +#include "protocol.h" + +#define UART_PORT 0 + +void debug_init(void) { + uart_init(UART_PORT); + uart_baudrate(UART_PORT, 25, 0, 0, 0); + uart_stopbits(UART_PORT, 1); + uart_databits(UART_PORT, 8); + uart_parity(UART_PORT, 'N'); +} + +void debug_deinit(void) { + uart_deinit(UART_PORT); +} + +void debug_write(char *buf) { + while(*buf) + uart_putchar(UART_PORT, *buf++); +} + +unsigned char debug_AsciiToHex(unsigned char high, unsigned char low) +{ + unsigned char new; + + // check if lower equal 9 ( ascii 57 ) + if(high <= 57) // high is a number + high = high -48; + else // high is a letter + high = high -87; + + high = high << 4; + high = high & 0xF0; + + // check if lower equal 9 ( ascii 57 ) + if(low <= 57) // high is a number + low = low -48; + else // high is a letter + low = low -87; + low = low & 0x0F; + + new = high | low; + + return new; +} + +void debug_SendHex(unsigned char hex) +{ + unsigned char high,low; + // get highnibble + high = hex & 0xF0; + high = high >> 4; + + // get lownibble + low = hex & 0x0F; + + if(high<=9) + uart_putchar(UART_PORT, high+48); + else + uart_putchar(UART_PORT, high+87); + + if(low<=9) + uart_putchar(UART_PORT, low+48); + else + uart_putchar(UART_PORT, low+87); +} diff --git a/firmware/debug.h b/firmware/debug.h new file mode 100644 index 0000000..8aa15d9 --- /dev/null +++ b/firmware/debug.h @@ -0,0 +1,5 @@ +void debug_init(void); +void debug_deinit(void); +void debug_write(char *buf); +unsigned char debug_AsciiToHex(unsigned char high, unsigned char low); +void debug_SendHex(unsigned char hex); diff --git a/firmware/fifo.c b/firmware/fifo.c new file mode 100644 index 0000000..a1e0f87 --- /dev/null +++ b/firmware/fifo.c @@ -0,0 +1,27 @@ +#include "fifo.h" + +void fifo_init (fifo_t *f, uint8_t *buffer, const uint8_t size) +{ + f->count = 0; + f->pread = f->pwrite = buffer; + f->read2end = f->write2end = f->size = size; +} + +uint8_t fifo_put (fifo_t *f, const uint8_t data) +{ + return _inline_fifo_put (f, data); +} + +uint8_t fifo_get_wait (fifo_t *f) +{ + while (!f->count); + + return _inline_fifo_get (f); +} + +int fifo_get_nowait (fifo_t *f) +{ + if (!f->count) return -1; + + return (int) _inline_fifo_get (f); +} diff --git a/firmware/fifo.h b/firmware/fifo.h new file mode 100644 index 0000000..32c3264 --- /dev/null +++ b/firmware/fifo.h @@ -0,0 +1,75 @@ +#ifndef _FIFO_H_ +#define _FIFO_H_ + +#include <avr/io.h> +#include <avr/interrupt.h> + +typedef struct +{ + uint8_t volatile count; // # Zeichen im Puffer + uint8_t size; // Puffer-Größe + uint8_t *pread; // Lesezeiger + uint8_t *pwrite; // Schreibzeiger + uint8_t read2end, write2end; // # Zeichen bis zum Überlauf Lese-/Schreibzeiger +} fifo_t; + +extern void fifo_init (fifo_t*, uint8_t* buf, const uint8_t size); +extern uint8_t fifo_put (fifo_t*, const uint8_t data); +extern uint8_t fifo_get_wait (fifo_t*); +extern int fifo_get_nowait (fifo_t*); + +static inline uint8_t +_inline_fifo_put (fifo_t *f, const uint8_t data) +{ + if (f->count >= f->size) + return 0; + + uint8_t * pwrite = f->pwrite; + + *(pwrite++) = data; + + uint8_t write2end = f->write2end; + + if (--write2end == 0) + { + write2end = f->size; + pwrite -= write2end; + } + + f->write2end = write2end; + f->pwrite = pwrite; + + uint8_t sreg = SREG; + cli(); + f->count++; + SREG = sreg; + + return 1; +} + +static inline uint8_t +_inline_fifo_get (fifo_t *f) +{ + uint8_t *pread = f->pread; + uint8_t data = *(pread++); + uint8_t read2end = f->read2end; + + if (--read2end == 0) + { + read2end = f->size; + pread -= read2end; + } + + f->pread = pread; + f->read2end = read2end; + + uint8_t sreg = SREG; + cli(); + f->count--; + SREG = sreg; + + return data; +} + +#endif /* _FIFO_H_ */ + diff --git a/firmware/i2c.c b/firmware/i2c.c new file mode 100644 index 0000000..b7d55fe --- /dev/null +++ b/firmware/i2c.c @@ -0,0 +1,216 @@ +/* + * Author: Benedikt Sauter + * Author: Peter Huewe, Hubert Hogel + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common.h" +#include "protocol.h" +#include "i2c.h" + +void i2c_parser(char *buf) { +answer[0] = buf[0]; + switch(buf[0]){ + case CMD_I2C_INIT: + i2c_init_usb(); + break; + case CMD_I2C_DEINIT: + i2c_deinit_usb(); + break; + case CMD_I2C_SET_BITRATE: + i2c_set_bitrate_usb((char)buf[2]); + break; + case CMD_I2C_SEND_BYTE: + i2c_send_byte_usb((int)buf[2]); + break; + case CMD_I2C_RECV_BYTES: + i2c_reveice_bytes_usb((int)buf[3],(int)buf[1]-4, (int)buf[2]); + break; + case CMD_I2C_SEND_START: + i2c_send_start_usb(); + break; + case CMD_I2C_SEND_STOP: + i2c_send_stop_usb(); + break; + default: + answer[0]=buf[0]; + answer[1]=RSP_UNKOWN_CMD; + answer[2]=0; + CommandAnswer(3); + } +} + + +unsigned char i2c_get_twsr(void) +{ + return (TWSR & 0xF8); +} + + +void i2c_wait_for_complete(void) +{ + while (!(TWCR & (1<<TWINT))){ + //do nothing just wait + ; + } +} + + +void i2c_init_usb(void) +{ + answer[0]=CMD_I2C_INIT; + answer[1]=(unsigned char)i2c_init(); + answer[2]=0; + CommandAnswer(3); +} + +int i2c_init(void) +{ + TWCR |= (1<<TWEN); + octopus.ports[12] = PIN_SCL; + octopus.ports[13] = PIN_SDA; + + return RSP_OK; +} + + +void i2c_deinit_usb(void) +{ + answer[0]=CMD_I2C_DEINIT; + answer[1]=(unsigned char)i2c_deinit(); + answer[2]=0; + CommandAnswer(3); +} + +int i2c_deinit(void) +{ + TWCR &= ~(1<<TWEN); // deinit + octopus.ports[12]=PIN_OUT; // this is wrong! + octopus.ports[13]=PIN_OUT; // this is wrong! + + return RSP_OK; +} + + +void i2c_set_bitrate_usb(char bitrate) { + answer[0] = CMD_I2C_SET_BITRATE; + answer[1] = (unsigned char)i2c_set_bitrate(bitrate); + answer[2] = '\0'; + CommandAnswer(3); +} + +int i2c_set_bitrate(char bitrate) { + TWBR = bitrate; + + TWSR &= ~((1<<TWPS1) | (1<<TWPS0)); + TWSR |= (0<<TWPS0); + + return RSP_OK; +} + + +void i2c_send_start_usb(void) +{ + answer[0] = CMD_I2C_SEND_START; + answer[1] = (unsigned char)i2c_send_start(); + answer[2] = '\0'; + CommandAnswer(3); +} + +int i2c_send_start(void) +{ + i2c_get_twsr(); + TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); + i2c_wait_for_complete(); + return RSP_OK; +} + +void i2c_send_stop_usb(void) +{ + answer[0]=CMD_I2C_SEND_STOP; + answer[1]=(unsigned char)i2c_send_stop(); + answer[2]=0; + CommandAnswer(3); +} + + +int i2c_send_stop(void) +{ + TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO); + return RSP_OK; +} + + +void i2c_send_byte_usb(char data) +{ + i2c_send_byte(data); + + answer[0] = CMD_I2C_SEND_BYTE; + answer[1] = RSP_OK; + answer[2] = '\0'; + CommandAnswer(3); +} + +void i2c_send_byte(char data) +{ + TWDR = data; + TWCR = (1<<TWINT) | (1<<TWEN); + i2c_wait_for_complete(); +} + +void i2c_reveice_bytes_usb(int address,int len, int timeout) +{ + /* receive */ + //i2c_get_twsr(); + //print_hex(s); + + //i2c_send_start(); + /* slave address = 0x10; */ + //buf[3] = (0x10 << 1)|1; /* (00010000<<1) | R */ + //i2c_send_byte( (0x10 << 1)|1); + + + answer[0]=CMD_I2C_RECV_BYTES; + answer[1]=RSP_OK; + answer[2]=1; + answer[3]=i2c_receive_byte(); + CommandAnswer(5); +} + + +unsigned char i2c_receive_byte(void) +{ + TWCR = (1<<TWINT) | (1<<TWEN); + i2c_wait_for_complete(); + return TWDR; +} + diff --git a/firmware/i2c.h b/firmware/i2c.h new file mode 100644 index 0000000..89834ea --- /dev/null +++ b/firmware/i2c.h @@ -0,0 +1,68 @@ +/* + * Author: Benedikt Sauter + * Author: Peter Huewe, Hubert Hogel + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef I2C_H +#define I2C_H + +#include <avr/io.h> +#include <avr/pgmspace.h> + + +void i2c_parser(char *buf); + +int i2c_init(void); +int i2c_deinit(void); + +int i2c_set_bitrate(char); +int i2c_send_start(void); +int i2c_send_stop(void); +void i2c_send_byte(char data); +unsigned char i2c_receive_byte(void); + + +unsigned char i2c_get_twsr(void); +void i2c_wait_for_complete(void); + +void i2c_init_usb(void); +void i2c_deinit_usb(void); + +void i2c_set_bitrate_usb(char); +void i2c_send_start_usb(void); +void i2c_send_stop_usb(void); +void i2c_send_byte_usb(char data); + +void i2c_reveice_bytes_usb(int address,int len, int timeout); + + +#endif /* I2C_H */ diff --git a/firmware/io.c b/firmware/io.c new file mode 100644 index 0000000..280f892 --- /dev/null +++ b/firmware/io.c @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2007 Embedded Projects (http://www.embedded-projects.net) + * Author: Benedikt Sauter <sauter@ + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF USE, + * DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common.h" +#include "protocol.h" +#include "io.h" + +void io_parser(char *buf) +{ + switch(buf[0]) + { + case CMD_IO_INIT_PORT: + io_init_port_usb((uint8_t)buf[2]); + break; + case CMD_IO_INIT_PIN: + io_init_usb((uint8_t)buf[2]); + break; + case CMD_IO_PORT_DIRECTION_IN: + io_set_port_direction_in_usb((uint8_t)buf[2],(uint8_t)buf[3]); + break; + case CMD_IO_PORT_DIRECTION_OUT: + io_set_port_direction_out_usb((uint8_t)buf[2],(uint8_t)buf[3]); + break; + case CMD_IO_PORT_DIRECTION_TRI: + io_set_port_direction_tri_usb((uint8_t)buf[2],(uint8_t)buf[3]); + break; + case CMD_IO_PIN_DIRECTION_IN: + io_set_pin_direction_in_usb((uint8_t)buf[2]); + break; + case CMD_IO_PIN_DIRECTION_OUT: + io_set_pin_direction_out_usb((uint8_t)buf[2]); + break; + case CMD_IO_PIN_DIRECTION_TRI: + io_set_pin_direction_tri_usb((uint8_t)buf[2]); + break; + case CMD_IO_PORT_SET: + io_set_port_usb((uint8_t)buf[2],(uint8_t)buf[3]); + break; + case CMD_IO_PORT_GET: + io_get_port_usb((uint8_t)buf[2]); + break; + case CMD_IO_PIN_SET: + io_set_pin_usb((uint8_t)buf[2],(uint8_t)buf[3]); + break; + case CMD_IO_PIN_GET: + io_get_pin_usb((uint8_t)buf[2]); + break; + default: + answer[0] = buf[0]; + answer[1] = RSP_UNKOWN_CMD; + answer[2] = 0; + CommandAnswer(3); + } +} + +uint8_t io_init(uint8_t pin) +{ + if ((pin >= 1 && pin <= 19) || (pin >= 26 && pin <= 44)) + { + io_set_pin_direction_out(pin); + return RSP_OK; + } + return RSP_UNKOWN_PIN; +} + +void io_init_usb(uint8_t pin) +{ + answer[0] = CMD_IO_INIT_PIN; + answer[1] = (unsigned char)io_init(pin); + answer[2] = 0; + CommandAnswer(3); +} + +uint8_t io_init_port(uint8_t port) +{ + /* TODO implement this function */ + return RSP_OK; +} + +void io_init_port_usb(uint8_t port) +{ + answer[0] = CMD_IO_INIT_PORT; + answer[1] = (unsigned char)io_init_port(port); + answer[2] = 0; + CommandAnswer(3); +} + +uint8_t io_set_port_direction_out(uint8_t port,uint8_t mask) +{ + /* TODO + switch (port)
+ {
+ case 1: DDRB = mask; break;
+ case 2: DDRC = mask; break; // PC7 = /CS (output) - do we need to mask this ?
+ case 3: DDRD = mask; break;
+ case 4: DDRE = mask; break; // PE4 = INT4 (input) - do we need to mask this ?
+ case 5: DDRF = mask; break;
+ default: return RSP_UNKOWN_PIN;
+ } + */
+ return RSP_OK; +} + +uint8_t io_set_port_direction_in(uint8_t port,uint8_t mask) +{ + /* TODO implement */ + return RSP_OK; +} + +uint8_t io_set_port_direction_tri(uint8_t port,uint8_t mask) +{ + /* TODO implement */ + return RSP_OK; +} + +void io_set_port_direction_out_usb (uint8_t port, uint8_t mask) +{ + answer[0] = CMD_IO_PORT_DIRECTION_OUT; + answer[1] = (unsigned char)io_set_port_direction_out (port, mask); + answer[2] = 0; + CommandAnswer(3); +} + +void io_set_port_direction_in_usb(uint8_t port, uint8_t mask) +{ + answer[0] = CMD_IO_PORT_DIRECTION_IN; + answer[1] = (unsigned char)io_set_port_direction_in (port, mask); + answer[2] = 0; + CommandAnswer(3); +} +void io_set_port_direction_tri_usb(uint8_t port, uint8_t mask) +{ + answer[0] = CMD_IO_PORT_DIRECTION_TRI; + answer[1] = (unsigned char)io_set_port_direction_tri (port, mask); + answer[2] = 0; + CommandAnswer(3); +} + + +uint8_t io_set_pin_direction_out(uint8_t pin) +{ + if((pin >= 1 && pin <= 19) || (pin >=26 && pin <=44) ) + { + octopus.ports[pin] = PIN_OUT; + + switch(pin) + { + case 1: OX_DDR1 |=(1<<OX_P1); break; + case 2: OX_DDR2 |=(1<<OX_P2); break; + case 3: OX_DDR3 |=(1<<OX_P3); break; + case 4: OX_DDR4 |=(1<<OX_P4); break; + case 5: OX_DDR5 |=(1<<OX_P5); break; + case 6: OX_DDR6 |=(1<<OX_P6); break; + case 7: OX_DDR7 |=(1<<OX_P7); break; + case 8: OX_DDR8 |=(1<<OX_P8); break; + case 9: OX_DDR9 |=(1<<OX_P9); break; + case 10: OX_DDR10 |=(1<<OX_P10); break; + case 11: OX_DDR11 |=(1<<OX_P11); break; + case 12: OX_DDR12 |=(1<<OX_P12); break; + case 13: OX_DDR13 |=(1<<OX_P13); break; + case 14: OX_DDR14 |=(1<<OX_P14); break; + case 15: OX_DDR15 |=(1<<OX_P15); break; + case 16: OX_DDR16 |=(1<<OX_P16); break; + case 17: OX_DDR17 |=(1<<OX_P17); break; + case 18: OX_DDR18 |=(1<<OX_P18); break; + case 19: OX_DDR19 |=(1<<OX_P19); break; + + case 26: OX_DDR26 |=(1<<OX_P26); break; + case 27: OX_DDR27 |=(1<<OX_P27); break; + case 28: OX_DDR28 |=(1<<OX_P28); break; + case 29: OX_DDR29 |=(1<<OX_P29); break; + case 30: OX_DDR30 |=(1<<OX_P30); break; + case 31: OX_DDR31 |=(1<<OX_P31); break; + case 32: OX_DDR32 |=(1<<OX_P32); break; + case 33: OX_DDR33 |=(1<<OX_P33); break; + case 34: OX_DDR34 |=(1<<OX_P34); break; + case 35: OX_DDR35 |=(1<<OX_P35); break; + case 36: OX_DDR36 |=(1<<OX_P36); break; + case 37: OX_DDR37 |=(1<<OX_P37); break; + case 38: OX_DDR38 |=(1<<OX_P38); break; + case 39: OX_DDR39 |=(1<<OX_P39); break; + case 40: OX_DDR40 |=(1<<OX_P40); break; + case 41: OX_DDR41 |=(1<<OX_P41); break; + case 42: OX_DDR42 |=(1<<OX_P42); break; + case 43: OX_DDR43 |=(1<<OX_P43); break; + case 44: OX_DDR44 |=(1<<OX_P44); break; + default: + return RSP_UNKOWN_PIN; + } + return RSP_OK; + } + else { + return RSP_UNKOWN_PIN; + } +} + +uint8_t io_set_pin_direction_in(uint8_t pin) +{ + if((pin >= 1 && pin <= 19) || (pin >=26 && pin <=44) ) + { + octopus.ports[pin] = PIN_IN; + switch (pin) + { + case 1: OX_DDR1 &=~(1<<OX_P1); break; + case 2: OX_DDR2 &=~(1<<OX_P2); break; + case 3: OX_DDR3 &=~(1<<OX_P3); break; + case 4: OX_DDR4 &=~(1<<OX_P4); break; + case 5: OX_DDR5 &=~(1<<OX_P5); break; + case 6: OX_DDR6 &=~(1<<OX_P6); break; + case 7: OX_DDR7 &=~(1<<OX_P7); break; + case 8: OX_DDR8 &=~(1<<OX_P8); break; + case 9: OX_DDR9 &=~(1<<OX_P9); break; + case 10: OX_DDR10 &=~(1<<OX_P10); break; + case 11: OX_DDR11 &=~(1<<OX_P11); break; + case 12: OX_DDR12 &=~(1<<OX_P12); break; + case 13: OX_DDR13 &=~(1<<OX_P13); break; + case 14: OX_DDR14 &=~(1<<OX_P14); break; + case 15: OX_DDR15 &=~(1<<OX_P15); break; + case 16: OX_DDR16 &=~(1<<OX_P16); break; + case 17: OX_DDR17 &=~(1<<OX_P17); break; + case 18: OX_DDR18 &=~(1<<OX_P18); break; + case 19: OX_DDR19 &=~(1<<OX_P19); break; + + case 26: OX_DDR26 &=~(1<<OX_P26); break; + case 27: OX_DDR27 &=~(1<<OX_P27); break; + case 28: OX_DDR28 &=~(1<<OX_P28); break; + case 29: OX_DDR29 &=~(1<<OX_P29); break; + case 30: OX_DDR30 &=~(1<<OX_P30); break; + case 31: OX_DDR31 &=~(1<<OX_P31); break; + case 32: OX_DDR32 &=~(1<<OX_P32); break; + case 33: OX_DDR33 &=~(1<<OX_P33); break; + case 34: OX_DDR34 &=~(1<<OX_P34); break; + case 35: OX_DDR35 &=~(1<<OX_P35); break; + case 36: OX_DDR36 &=~(1<<OX_P36); break; + case 37: OX_DDR37 &=~(1<<OX_P37); break; + case 38: OX_DDR38 &=~(1<<OX_P38); break; + case 39: OX_DDR39 &=~(1<<OX_P39); break; + case 40: OX_DDR40 &=~(1<<OX_P40); break; + case 41: OX_DDR41 &=~(1<<OX_P41); break; + case 42: OX_DDR42 &=~(1<<OX_P42); break; + case 43: OX_DDR43 &=~(1<<OX_P43); break; + case 44: OX_DDR44 &=~(1<<OX_P44); break; + default: + return RSP_UNKOWN_PIN; + } + return RSP_OK; + } + else + { + return RSP_UNKOWN_PIN; + } +} + +uint8_t io_set_pin_direction_tri(uint8_t pin) +{ + if ((pin >= 1 && pin <= 19) || (pin >=26 && pin <=44) ) + { + octopus.ports[pin] = PIN_TRI; + io_set_pin_direction_out(pin); + io_set_pin(pin,1); + return RSP_OK; + } + else + { + return RSP_UNKOWN_PIN; + } +} + + +void io_set_pin_direction_out_usb(uint8_t pin) +{ + answer[0] = CMD_IO_PIN_DIRECTION_OUT; + answer[1] = (unsigned char)io_set_pin_direction_out(pin); + answer[2] = 0; + CommandAnswer(3); +} + +void io_set_pin_direction_in_usb(uint8_t pin) +{ + answer[0] = CMD_IO_PIN_DIRECTION_IN; + answer[1] = (unsigned char)io_set_pin_direction_in(pin); + answer[2] = 0; + CommandAnswer(3); +} + +void io_set_pin_direction_tri_usb(uint8_t pin) +{ + answer[0] = CMD_IO_PIN_DIRECTION_TRI; + answer[1] = (unsigned char)io_set_pin_direction_tri(pin); + answer[2] = 0; + CommandAnswer(3); +} + + + +uint8_t io_get_port (uint8_t port, uint8_t *pvalue) +{ + uint8_t value;
+
+ *pvalue = 0;
+ switch (port)
+ {
+ case 1: value = PINB; break;
+ case 2: value = PINC; break; /* PC7 = /CS */
+ case 3: value = PIND; break;
+ case 4: value = PINE; break; /* PE4 = INTR */
+ case 5: value = PINF; break;
+ default: return RSP_UNKOWN_PORT;
+ }
+ *pvalue = value;
+ return RSP_OK; +} + +void io_get_port_usb (uint8_t port)
+{
+ uint8_t value;
+ + answer[0] = CMD_IO_PORT_GET;
+ answer[1] = (unsigned char)io_get_port (port, &value);
+ answer[2] = (unsigned char)value;
+ CommandAnswer(3);
+} + +uint8_t io_set_port(uint8_t port, uint8_t value) +{ + switch (port)
+ {
+ case 1: PORTB = value; break;
+ case 2: PORTC = value; break; // PC7 = /CS
+ case 3: PORTD = value; break;
+ case 4: PORTE = value; break; // PE4 = INTR
+ case 5: PORTF = value; break;
+ default: return RSP_UNKOWN_PIN;
+ }
+ return RSP_OK; +} + +void io_set_port_usb (uint8_t port, uint8_t value)
+{
+ answer[0] = CMD_IO_PORT_SET;
+ answer[1] = (unsigned char)io_set_port (port, value);
+ answer[2] = 0;
+ CommandAnswer(3);
+} + + +void io_set_pin_usb(uint8_t pin, uint8_t value) +{ + answer[0] = CMD_IO_PIN_SET; + answer[1] = (unsigned char)io_set_pin(pin,value); + answer[2] = 0; + CommandAnswer(3); +} + + +uint8_t io_set_pin(uint8_t pin, uint8_t value) +{ + if(octopus.ports[pin] == PIN_OUT) + { + switch(pin) + { + case 1: if(value) OX_PORT1 |=(1<<OX_P1); else OX_PORT1 &=~(1<<OX_P1); break; + case 2: if(value) OX_PORT2 |=(1<<OX_P2); else OX_PORT2 &=~(1<<OX_P2); break; + case 3: if(value) OX_PORT3 |=(1<<OX_P3); else OX_PORT3 &=~(1<<OX_P3); break; + case 4: if(value) OX_PORT4 |=(1<<OX_P4); else OX_PORT4 &=~(1<<OX_P4); break; + case 5: if(value) OX_PORT5 |=(1<<OX_P5); else OX_PORT5 &=~(1<<OX_P5); break; + case 6: if(value) OX_PORT6 |=(1<<OX_P6); else OX_PORT6 &=~(1<<OX_P6); break; + case 7: if(value) OX_PORT7 |=(1<<OX_P7); else OX_PORT7 &=~(1<<OX_P7); break; + case 8: if(value) OX_PORT8 |=(1<<OX_P8); else OX_PORT8 &=~(1<<OX_P8); break; + case 9: if(value) OX_PORT9 |=(1<<OX_P9); else OX_PORT9 &=~(1<<OX_P9); break; + case 10: if(value) OX_PORT10 |=(1<<OX_P10); else OX_PORT10 &=~(1<<OX_P10); break; + case 11: if(value) OX_PORT11 |=(1<<OX_P11); else OX_PORT11 &=~(1<<OX_P11); break; + case 12: if(value) OX_PORT12 |=(1<<OX_P12); else OX_PORT12 &=~(1<<OX_P12); break; + case 13: if(value) OX_PORT13 |=(1<<OX_P13); else OX_PORT13 &=~(1<<OX_P13); break; + case 14: if(value) OX_PORT14 |=(1<<OX_P14); else OX_PORT14 &=~(1<<OX_P14); break; + case 15: if(value) OX_PORT15 |=(1<<OX_P15); else OX_PORT15 &=~(1<<OX_P15); break; + case 16: if(value) OX_PORT16 |=(1<<OX_P16); else OX_PORT16 &=~(1<<OX_P16); break; + case 17: if(value) OX_PORT17 |=(1<<OX_P17); else OX_PORT17 &=~(1<<OX_P17); break; + case 18: if(value) OX_PORT18 |=(1<<OX_P18); else OX_PORT18 &=~(1<<OX_P18); break; + case 19: if(value) OX_PORT19 |=(1<<OX_P19); else OX_PORT19 &=~(1<<OX_P19); break; + + case 26: if(value) OX_PORT26 |=(1<<OX_P26); else OX_PORT26 &=~(1<<OX_P26); break; + case 27: if(value) OX_PORT27 |=(1<<OX_P27); else OX_PORT27 &=~(1<<OX_P27); break; + case 28: if(value) OX_PORT28 |=(1<<OX_P28); else OX_PORT28 &=~(1<<OX_P28); break; + case 29: if(value) OX_PORT29 |=(1<<OX_P29); else OX_PORT29 &=~(1<<OX_P29); break; + case 30: if(value) OX_PORT30 |=(1<<OX_P30); else OX_PORT30 &=~(1<<OX_P30); break; + case 31: if(value) OX_PORT31 |=(1<<OX_P31); else OX_PORT31 &=~(1<<OX_P31); break; + case 32: if(value) OX_PORT32 |=(1<<OX_P32); else OX_PORT32 &=~(1<<OX_P32); break; + case 33: if(value) OX_PORT33 |=(1<<OX_P33); else OX_PORT33 &=~(1<<OX_P33); break; + case 34: if(value) OX_PORT34 |=(1<<OX_P34); else OX_PORT34 &=~(1<<OX_P34); break; + case 35: if(value) OX_PORT35 |=(1<<OX_P35); else OX_PORT35 &=~(1<<OX_P35); break; + case 36: if(value) OX_PORT36 |=(1<<OX_P36); else OX_PORT36 &=~(1<<OX_P36); break; + case 37: if(value) OX_PORT37 |=(1<<OX_P37); else OX_PORT37 &=~(1<<OX_P37); break; + case 38: if(value) OX_PORT38 |=(1<<OX_P38); else OX_PORT38 &=~(1<<OX_P38); break; + case 39: if(value) OX_PORT39 |=(1<<OX_P39); else OX_PORT39 &=~(1<<OX_P39); break; + case 40: if(value) OX_PORT40 |=(1<<OX_P40); else OX_PORT40 &=~(1<<OX_P40); break; + case 41: if(value) OX_PORT41 |=(1<<OX_P41); else OX_PORT41 &=~(1<<OX_P41); break; + case 42: if(value) OX_PORT42 |=(1<<OX_P42); else OX_PORT42 &=~(1<<OX_P42); break; + case 43: if(value) OX_PORT43 |=(1<<OX_P43); else OX_PORT43 &=~(1<<OX_P43); break; + case 44: if(value) OX_PORT44 |=(1<<OX_P44); else OX_PORT44 &=~(1<<OX_P44); break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; + } + else + { + return RSP_WRONG_PIN_CONFIG; + } +} + + +void io_get_pin_usb(uint8_t pin) +{ + uint8_t value; + + answer[0] = CMD_IO_PIN_GET; + answer[1] = (unsigned char)io_get_pin(pin,&value); + answer[2] = (unsigned char)value; + CommandAnswer(3); +} + +uint8_t io_get_pin(uint8_t pin, uint8_t *value) +{ + *value = 0;
+ if (octopus.ports[pin] == PIN_IN)
+ {
+ switch (pin)
+ {
+ case 1: if (OX_PIN1 & (1<<OX_P1)) *value=1; break;
+ case 2: if (OX_PIN2 & (1<<OX_P2)) *value=1; break;
+ case 3: if (OX_PIN3 & (1<<OX_P3)) *value=1; break;
+ case 4: if (OX_PIN4 & (1<<OX_P4)) *value=1; break;
+ case 5: if (OX_PIN5 & (1<<OX_P5)) *value=1; break;
+ case 6: if (OX_PIN6 & (1<<OX_P6)) *value=1; break;
+ case 7: if (OX_PIN7 & (1<<OX_P7)) *value=1; break;
+ case 8: if (OX_PIN8 & (1<<OX_P8)) *value=1; break;
+ case 9: if (OX_PIN9 & (1<<OX_P9)) *value=1; break;
+ case 10: if (OX_PIN10 & (1<<OX_P10)) *value=1; break;
+ case 11: if (OX_PIN11 & (1<<OX_P11)) *value=1; break;
+ case 12: if (OX_PIN12 & (1<<OX_P12)) *value=1; break;
+ case 13: if (OX_PIN13 & (1<<OX_P13)) *value=1; break;
+ case 14: if (OX_PIN14 & (1<<OX_P14)) *value=1; break;
+ case 15: if (OX_PIN15 & (1<<OX_P15)) *value=1; break;
+ case 16: if (OX_PIN16 & (1<<OX_P16)) *value=1; break;
+ case 17: if (OX_PIN17 & (1<<OX_P17)) *value=1; break;
+ case 18: if (OX_PIN18 & (1<<OX_P18)) *value=1; break;
+ case 19: if (OX_PIN19 & (1<<OX_P19)) *value=1; break;
+
+ case 26: if (OX_PIN26 & (1<<OX_P26)) *value=1; break;
+ case 27: if (OX_PIN27 & (1<<OX_P27)) *value=1; break;
+ case 28: if (OX_PIN28 & (1<<OX_P28)) *value=1; break;
+ case 29: if (OX_PIN29 & (1<<OX_P29)) *value=1; break;
+ case 30: if (OX_PIN30 & (1<<OX_P30)) *value=1; break;
+ case 31: if (OX_PIN31 & (1<<OX_P31)) *value=1; break;
+ case 32: if (OX_PIN32 & (1<<OX_P32)) *value=1; break;
+ case 33: if (OX_PIN33 & (1<<OX_P33)) *value=1; break;
+ case 34: if (OX_PIN34 & (1<<OX_P34)) *value=1; break;
+ case 35: if (OX_PIN35 & (1<<OX_P35)) *value=1; break;
+ case 36: if (OX_PIN36 & (1<<OX_P36)) *value=1; break;
+ case 37: if (OX_PIN37 & (1<<OX_P37)) *value=1; break;
+ case 38: if (OX_PIN38 & (1<<OX_P38)) *value=1; break;
+ case 39: if (OX_PIN39 & (1<<OX_P39)) *value=1; break;
+ case 40: if (OX_PIN40 & (1<<OX_P40)) *value=1; break;
+ case 41: if (OX_PIN41 & (1<<OX_P41)) *value=1; break;
+ case 42: if (OX_PIN42 & (1<<OX_P42)) *value=1; break;
+ case 43: if (OX_PIN43 & (1<<OX_P43)) *value=1; break;
+ case 44: if (OX_PIN44 & (1<<OX_P44)) *value=1; break;
+ default: return RSP_UNKOWN_PIN;
+ }
+ return RSP_OK;
+ }
+ else
+ {
+ return RSP_WRONG_PIN_CONFIG;
+ } +} + + diff --git a/firmware/io.h b/firmware/io.h new file mode 100644 index 0000000..f86314f --- /dev/null +++ b/firmware/io.h @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2007 Embedded Projects (http://www.embedded-projecs.net) + * Author: Benedikt Sauter <sauter@embedded-projects.net + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef IO_H +#define IO_H + +#include <avr/io.h> +#include <avr/pgmspace.h> + + +#define OX_PIN1 PINE +#define OX_PIN2 PINE +#define OX_PIN3 PINE +#define OX_PIN4 PINB +#define OX_PIN5 PINB +#define OX_PIN6 PINB +#define OX_PIN7 PINB +#define OX_PIN8 PINB +#define OX_PIN9 PINB +#define OX_PIN10 PINB +#define OX_PIN11 PINB +#define OX_PIN12 PIND +#define OX_PIN13 PIND +#define OX_PIN14 PIND +#define OX_PIN15 PIND +#define OX_PIN16 PIND +#define OX_PIN17 PIND +#define OX_PIN18 PIND +#define OX_PIN19 PIND + +#define OX_PIN26 PINC +#define OX_PIN27 PINC +#define OX_PIN28 PINC +#define OX_PIN29 PINC +#define OX_PIN30 PINC +#define OX_PIN31 PINC +#define OX_PIN32 PINC +#define OX_PIN33 PINF +#define OX_PIN34 PINF +#define OX_PIN35 PINF +#define OX_PIN36 PINF +#define OX_PIN37 PINF +#define OX_PIN38 PINF +#define OX_PIN39 PINF +#define OX_PIN40 PINF +#define OX_PIN41 PINE +#define OX_PIN42 PINE +#define OX_PIN43 PINE +#define OX_PIN44 PINE + +#define OX_PORT1 PORTE +#define OX_PORT2 PORTE +#define OX_PORT3 PORTE +#define OX_PORT4 PORTB +#define OX_PORT5 PORTB +#define OX_PORT6 PORTB +#define OX_PORT7 PORTB +#define OX_PORT8 PORTB +#define OX_PORT9 PORTB +#define OX_PORT10 PORTB +#define OX_PORT11 PORTB +#define OX_PORT12 PORTD +#define OX_PORT13 PORTD +#define OX_PORT14 PORTD +#define OX_PORT15 PORTD +#define OX_PORT16 PORTD +#define OX_PORT17 PORTD +#define OX_PORT18 PORTD +#define OX_PORT19 PORTD + +#define OX_PORT26 PORTC +#define OX_PORT27 PORTC +#define OX_PORT28 PORTC +#define OX_PORT29 PORTC +#define OX_PORT30 PORTC +#define OX_PORT31 PORTC +#define OX_PORT32 PORTC +#define OX_PORT33 PORTF +#define OX_PORT34 PORTF +#define OX_PORT35 PORTF +#define OX_PORT36 PORTF +#define OX_PORT37 PORTF +#define OX_PORT38 PORTF +#define OX_PORT39 PORTF +#define OX_PORT40 PORTF +#define OX_PORT41 PORTE +#define OX_PORT42 PORTE +#define OX_PORT43 PORTE +#define OX_PORT44 PORTE + +#define OX_DDR1 DDRE +#define OX_DDR2 DDRE +#define OX_DDR3 DDRE +#define OX_DDR4 DDRB +#define OX_DDR5 DDRB +#define OX_DDR6 DDRB +#define OX_DDR7 DDRB +#define OX_DDR8 DDRB +#define OX_DDR9 DDRB +#define OX_DDR10 DDRB +#define OX_DDR11 DDRB +#define OX_DDR12 DDRD +#define OX_DDR13 DDRD +#define OX_DDR14 DDRD +#define OX_DDR15 DDRD +#define OX_DDR16 DDRD +#define OX_DDR17 DDRD +#define OX_DDR18 DDRD +#define OX_DDR19 DDRD + +#define OX_DDR26 DDRC +#define OX_DDR27 DDRC +#define OX_DDR28 DDRC +#define OX_DDR29 DDRC +#define OX_DDR30 DDRC +#define OX_DDR31 DDRC +#define OX_DDR32 DDRC +#define OX_DDR33 DDRF +#define OX_DDR34 DDRF +#define OX_DDR35 DDRF +#define OX_DDR36 DDRF +#define OX_DDR37 DDRF +#define OX_DDR38 DDRF +#define OX_DDR39 DDRF +#define OX_DDR40 DDRF +#define OX_DDR41 DDRE +#define OX_DDR42 DDRE +#define OX_DDR43 DDRE +#define OX_DDR44 DDRE + + +#define OX_P1 PE5 +#define OX_P2 PE6 +#define OX_P3 PE7 +#define OX_P4 PB0 +#define OX_P5 PB1 +#define OX_P6 PB2 +#define OX_P7 PB3 +#define OX_P8 PB4 +#define OX_P9 PB5 +#define OX_P10 PB6 +#define OX_P11 PB7 +#define OX_P12 PD0 +#define OX_P13 PD1 +#define OX_P14 PD2 +#define OX_P15 PD3 +#define OX_P16 PD4 +#define OX_P17 PD5 +#define OX_P18 PD6 +#define OX_P19 PD7 + +#define OX_P26 PC0 +#define OX_P27 PC1 +#define OX_P28 PC2 +#define OX_P29 PC3 +#define OX_P30 PC4 +#define OX_P31 PC5 +#define OX_P32 PC6 +#define OX_P33 PF7 +#define OX_P34 PF6 +#define OX_P35 PF5 +#define OX_P36 PF4 +#define OX_P37 PF3 +#define OX_P38 PF2 +#define OX_P39 PF1 +#define OX_P40 PF0 +#define OX_P41 PE0 +#define OX_P42 PE1 +#define OX_P43 PE2 +#define OX_P44 PE3 + + + +void io_parser(char *buf); + +uint8_t io_init(uint8_t pin); +void io_init_usb(uint8_t pin); + +uint8_t io_init_port(uint8_t port); +void io_init_port_usb(uint8_t port); + +uint8_t io_set_port_direction_out(uint8_t port,uint8_t mask); +uint8_t io_set_port_direction_in(uint8_t port, uint8_t mask); +uint8_t io_set_port_direction_tri(uint8_t port, uint8_t mask); + + +void io_set_port_direction_out_usb (uint8_t port, uint8_t mask); +void io_set_port_direction_in_usb(uint8_t port, uint8_t mask); +void io_set_port_direction_tri_usb(uint8_t port, uint8_t mask); + +uint8_t io_set_pin_direction_out(uint8_t pin); +uint8_t io_set_pin_direction_in(uint8_t pin); +uint8_t io_set_pin_direction_tri(uint8_t pin); + +void io_set_pin_direction_out_usb(uint8_t pin); +void io_set_pin_direction_in_usb(uint8_t pin); +void io_set_pin_direction_tri_usb(uint8_t pin); + +uint8_t io_get_port (uint8_t port, uint8_t *pvalue); +void io_get_port_usb (uint8_t port); + + +uint8_t io_set_port(uint8_t port, uint8_t value); +void io_set_port_usb (uint8_t port, uint8_t value); + +uint8_t io_set_pin(uint8_t pin, uint8_t value); +void io_set_pin_usb(uint8_t pin, uint8_t value); + +uint8_t io_get_pin(uint8_t pin, uint8_t *value); +void io_get_pin_usb(uint8_t pin); + + +#define PORT(port,pin) (PORT##port) +#define DDR(port,pin) (DDR##port) +#define PIN(port,pin) (PIN##port) +#define PIN_MASK(port,pin) (1<<(pin)) + +/* Set a pin */ +#define SETPIN(pindef) PORT pindef |= PIN_MASK pindef + +/* Clear a pin */ +#define CLRPIN(pindef) PORT pindef &= ~PIN_MASK pindef + +/* Get pin value */ +#define GETPIN(pindef) (PIN pindef & PIN_MASK pindef) + +/* Toggle a pin */ +#define TOGGLEPIN(pindef) PIN pindef |= PIN_MASK pindef + +/* Set a IO to output */ +#define SET_DDR_OUT(pindef) DDR pindef |= PIN_MASK pindef + +/* Set a IO to input */ +#define SET_DDR_IN(pindef) DDR pindef &= ~PIN_MASK pindef + + + +#endif /* IO_H */ diff --git a/firmware/main.c b/firmware/main.c new file mode 100644 index 0000000..ef802a2 --- /dev/null +++ b/firmware/main.c @@ -0,0 +1,287 @@ +#include <stdlib.h> +#include <avr/io.h> +#include <stdint.h> +#include <avr/interrupt.h> +#include <inttypes.h> +#include <avr/pgmspace.h> + +#include "usbn2mc.h" +#define F_CPU 16000000UL +#include <util/delay.h> + +#include "../usbn2mc/main/usbnapi.h" +#include "usbn2mc.h" + +#include "common.h" +#include "protocol.h" +#include "wait.h" + +#include "io.h" +#include "adc.h" +#include "i2c.h" +#include "spi.h" +#include "pwm.h" +#include "uart.h" + +#include "93c46.h" +#include "debug.h" + +//#define DEBUG 1 + + + +SIGNAL (SIG_INTERRUPT4) +{ + USBNInterrupt (); +} + +SIGNAL (SIG_UART0_RECV) +{ + +} + +/* internal timer */ +SIGNAL (SIG_OVERFLOW0) +{ + common_scheduler (); + TCNT0 = octopus.latency_timer; +} + + +void +USBCommandRX (char *buf) +{ + int i; + +#ifdef DEBUG + debug_write("get \0"); + debug_SendHex(buf[1]); + debug_write("\r\n"); +#endif + + /* a paket can be max 255 bytes */ + if (octopus.long_rx_cmd == 1) + { +#ifdef DEBUG + debug_write("get next\r\n"); +#endif + for (i = 0; i < 64; i++) + request[octopus.long_rx_index + i] = buf[i]; + + octopus.long_rx_index = octopus.long_rx_index + i; + + if (octopus.long_rx_index >= octopus.long_rx_bytes) + { + octopus.long_rx_cmd = 0; + USBMessageIn (request); + } + } + else + { +#ifdef DEBUG + debug_write("get and execute\r\n\0"); +#endif + octopus.long_rx_index = 0; + for (i = 0; i < 64; i++) + request[octopus.long_rx_index + i] = buf[i]; + + octopus.long_rx_index = i; + + if ((unsigned int) buf[1] < 64) + { + octopus.long_rx_cmd = 0; + USBMessageIn (request); + } + else + { + octopus.long_rx_cmd = 1; + octopus.long_rx_bytes = (unsigned int) buf[1]; + } + } +} + +/* is called when received data from pc */ +void +USBMessageIn (char *buf) +{ + octopus.long_index = 0; + octopus.long_running = 0; + + STATUS_LED_on; +#ifdef DEBUG + debug_write("parser\r\n\0"); +#endif + int check = ((int) buf[0] >> 4) & 0x0F; + + switch (check) + { + case 0: + if (buf[0] == CMD_EXTERNAL_DEVICE) + { + switch (buf[2]) + { + case CMD_EXTERNAL_93C46: + flash_93c46_parser (buf); + break; + default: + ; + } + } + else + common_parser (buf); + break; + case 1: + io_parser (buf); + break; + case 2: + adc_parser (buf); + break; + case 3: + i2c_parser (buf); + break; + case 4: + spi_parser (buf); + break; + case 5: + pwm_parser (buf); + break; + case 6: + uart_parser (buf); + break; + default: + answer[0] = buf[0]; + answer[1] = RSP_UNKOWN_CMD; + answer[2] = 0; + CommandAnswer (3); + } + + STATUS_LED_off; +} + + +void +CommandAnswer (unsigned int length) +{ + int i; + + // if first packet of a lang message + if (length > 64 && octopus.long_running == 0) + { + octopus.long_index = 0; + octopus.long_bytes = length; + octopus.long_running = 1; + length = 64; + } + + USBNWrite (FIFOTXC1, FLUSH); + + for (i = 0; i < length; i++) + USBNWrite (TXD1, answer[octopus.long_index + i]); + + /* control togl bit */ + if (octopus.datatogl == 1) + { + USBNWrite (FIFOTXC1, TX_LAST + TX_EN + TX_TOGL); + octopus.datatogl = 0; + } + else + { + USBNWrite (FIFOTXC1, TX_LAST + TX_EN); + octopus.datatogl = 1; + } +} + + +void +CommandAnswerRest (void) +{ + if (octopus.long_running == 1) + { + if (octopus.long_index < octopus.long_bytes) + { + int dif = octopus.long_bytes - octopus.long_index; + octopus.long_index = octopus.long_index + 64; + + if (dif > 64) + CommandAnswer (64); + + else + { + /* last packet */ + CommandAnswer (dif); + octopus.long_running = 0; + } + } + } +} + + +int +main (void) +{ + DDRB = 0xFF; + PORTB = 0xFF; + + + int interf; + int conf; + + + STATUS_LED_off; + + USBNInit (); + + // setup your device + USBNDeviceVendorID (0x1781); // 0x0400 is the number from national + USBNDeviceProductID (0x0c65); // add your product id + USBNDeviceBCDDevice (0x0001); // you can use it as version e.g. version 1.02 + + char lang[] = { 0x09, 0x04, 0x00 }; + _USBNAddStringDescriptor (lang); // language descriptor + + + /* Attention!!! Descriptors must be a factor of 8 (error in the stack) */ + USBNDeviceManufacture ("EmbeddedProjects"); + USBNDeviceProduct ("OctopusUSB Interface Converter and I/O Extension"); + USBNDeviceSerialNumber ("20081108"); + + conf = USBNAddConfiguration (); + + USBNConfigurationPower (conf, 100); + + interf = USBNAddInterface (conf, 0); + USBNAlternateSetting (conf, interf, 0); + + /* communication */ + USBNAddInEndpoint (conf, interf, 1, 0x01, BULK, 64, 0, &CommandAnswerRest); + USBNAddOutEndpoint (conf, interf, 1, 0x01, BULK, 64, 0, &USBCommandRX); + + USBNInitMC (); + + octopus.datatogl = 0; + octopus.long_rx_cmd = 0; + + /* start usb chip */ + USBNStart (); + + /* UARTInit2(38400,8,'N',1); */ + #ifdef DEBUG + debug_init(); + #endif + + /* hello world led pattern */ + DDRC = 0xFF; + PORTC = 0xAA; + delay_250ms (); + PORTC = 0xD5; + delay_250ms (); + PORTC = 0x80; + + // testpin + //PORTB = 0xFF; + //PORTB = 0x00; + + while (1); + + return 0; +} diff --git a/firmware/main.hex b/firmware/main.hex new file mode 100644 index 0000000..3d38158 --- /dev/null +++ b/firmware/main.hex @@ -0,0 +1,844 @@ +:100000000C94FA000C9417010C9417010C9417012E
+:100010000C9417010C9408030C9417010C9417010D
+:100020000C9417010C9417010C9417010C941701F0
+:100030000C9475170C9417010C9417010C9417016C
+:100040000C9417010C94E1020C9417010C94170105
+:100050000C9417010C9419010C9417010C941701BE
+:100060000C9417010C9417010C9417010C941701B0
+:100070000C9417010C9417010C9417010C941701A0
+:100080000C9417010C9417010C9417010C94170190
+:100090000C941701AA0DAC0DAE0DB00DB20DB40D40
+:1000A000B60DB80DBA0DBC0DBE0DC00DC20DC40D00
+:1000B000C60DC80DCA0DCC0DCE0DFC0DFC0DFC0DF2
+:1000C000FC0DFC0DFC0DD00DD20DD40DD60DD80DB0
+:1000D000DA0DDC0DDE0DE00DE20DE40DE60DE80DB0
+:1000E000EA0DEC0DEE0DF00DF20DF60D490E4B0E76
+:1000F0004D0E4F0E510E530E550E570E590E5B0EF0
+:100100005D0E5F0E610E630E650E670E690E6B0E5F
+:100110006D0E9B0E9B0E9B0E9B0E9B0E9B0E6F0EF1
+:10012000710E730E750E770E790E7B0E7D0E7F0E9F
+:10013000810E830E850E870E890E8B0E8D0E8F0E0F
+:10014000910E950E090F0F0F150F1B0F210F270F83
+:100150002D0F330F390F3F0F450F4B0F510F570F17
+:100160005D0F630F690F6F0F750F060F060F060FF8
+:10017000060F060F060F7B0F810F870F8D0F930F52
+:10018000990F9F0FA50FAB0FB10FB70FBD0FC30F87
+:10019000C90FCF0FD50FDB0FE10FE70F37103A1064
+:1001A0003D1040104310461049104C104F10521093
+:1001B000551058105B105E106110641067106A10C3
+:1001C0006D1034103410341034103410341070109A
+:1001D0007310761079107C107F10821085108810B3
+:1001E0008B108E109110941097109A109D10A010E3
+:1001F000A310A61011241FBECFEFD0E1DEBFCDBFEC
+:1002000011E0A0E0B1E0E2E4F4E300E00BBF02C0E3
+:1002100007900D92A435B107D9F714E0A4E5B1E039
+:1002200001C01D92A93BB107E1F70C9423010C9486
+:1002300000001F920F920FB60F9211240F900FBE65
+:100240000F901F901895CCEFD0E1DEBFCDBF8FEFA0
+:1002500084B985B92F980E94650781E897E10E94CB
+:10026000B00785E69CE00E94B50781E090E00E941F
+:10027000BA07DE011196EBE4F1E083E001900D9204
+:100280008150E1F7CE0101960E94AF0B80E091E032
+:100290000E944B0C81E191E00E94430C82E491E0CA
+:1002A0000E943B0C0E94850B4C0164E670E00E94AA
+:1002B000C80760E070E0C4010E94F10A3C0140E020
+:1002C00050E0BC01C4010E94E90720EFA22E21E00A
+:1002D000B22ECC24DD2490E4E92EF12C02E021E0C2
+:1002E00030E041E050E0B301C4010E94860A87E794
+:1002F000A82E82E0B82E21E030E041E050E0B301CA
+:10030000C4010E94BE0A0E940A071092E1011092E5
+:10031000E0011092E3011092E2010E94790C8FEF4C
+:1003200087B98AEA88B90E942C0385ED88B90E94B2
+:100330002C0380E888B9FFCF0F931F93CF93DF93EF
+:10034000EC0181349105B0F08091EC019091ED01C8
+:10035000892B81F41092E9011092E801D093EB010E
+:10036000C093EA0181E090E09093ED018093EC016D
+:10037000C0E4D0E068E08BE20E94500700E010E0AB
+:100380000EC0E091E801F091E901E00FF11FEE5C91
+:10039000FC4F608189E20E9450070F5F1F4F0C17CE
+:1003A0001D0779F78091E0019091E101019749F4EF
+:1003B00067E08BE20E9450071092E1011092E00189
+:1003C0000AC063E08BE20E94500781E090E09093C6
+:1003D000E1018093E001DF91CF911F910F9108958A
+:1003E0008091EC019091ED01019771F52091E80168
+:1003F0003091E9018091EA019091EB0128173907CA
+:1004000018F52091EA013091EB018091E80190917B
+:10041000E901281B390B8091E8019091E901805C8A
+:100420009F4F9093E9018093E801213431052CF02E
+:1004300080E490E00E949C010895C9010E949C0103
+:100440001092ED011092EC010895FC011092E90167
+:100450001092E8011092ED011092EC0100002F9A29
+:100460002081822F82958F7099278230910511F11A
+:10047000833091052CF4009761F0019759F516C06F
+:1004800084309105F9F084309105C4F0059711F599
+:100490001DC0263039F48281813039F5CF010E94A8
+:1004A000421723C0CF010E94F30C1FC0CF010E944E
+:1004B00084111BC0CF010E94E71217C0CF010E9418
+:1004C0002A1413C0CF010E945C150FC0CF010E94F7
+:1004D00092180BC02093320383E080933303109271
+:1004E000340383E090E00E949C012F980895CF93FD
+:1004F000DF93EC018091E2019091E301019751F5C6
+:1005000020E030E0E091E401F091E501E20FF31F1B
+:10051000DE01A20FB31F8C91EE50FE4F80832F5F40
+:100520003F4F2034310571F78091E4019091E5014E
+:10053000805C9F4F9093E5018093E4012091E4015A
+:100540003091E5018091E6019091E7012817390784
+:10055000A8F11FC01092E5011092E40120E030E004
+:10056000E091E401F091E501E20FF31FDE01A20F3B
+:10057000B31F8C91EE50FE4F80832F5F3F4F20348E
+:10058000310571F73093E5012093E401A981A0348E
+:1005900048F41092E3011092E20182EF91E00E9490
+:1005A00025020CC081E090E09093E3018093E2018A
+:1005B0008A2F99279093E7018093E601DF91CF91ED
+:1005C00008951F920F920FB60F9211242F933F930D
+:1005D0004F935F936F937F938F939F93AF93BF934B
+:1005E000EF93FF930E94C50C80915D0186BDFF9142
+:1005F000EF91BF91AF919F918F917F916F915F919B
+:100600004F913F912F910F900FBE0F901F90189513
+:100610001F920F920FB60F9211242F933F934F9377
+:100620005F936F937F938F939F93AF93BF93EF935A
+:10063000FF930E94530CFF91EF91BF91AF919F9157
+:100640008F917F916F915F914F913F912F910F907B
+:100650000FBE0F901F90189520E080E49CE9019751
+:10066000F1F72F5F2931C9F70895FF920F931F9378
+:10067000162F042FF22E9C01442737FD4095542F4E
+:1006800060E472E48FE090E00E94D0192150304085
+:10069000163061F0173019F0153019F404C0E1E09C
+:1006A00003C0E1E004C0E0E070E002C0E0E071E01F
+:1006B000053439F00F3419F451E041E004C050E042
+:1006C00001C051E040E082E0F81611F462E001C0A0
+:1006D00060E0832F992787FD9A958093C50020932A
+:1006E000C40088E18093C100770FEE0FEE0FE72B77
+:1006F0005295550F507E5E2B4295407F452B660FDD
+:10070000660F660F642B6093C2001F910F91FF90DC
+:1007100008951092C50089E18093C40088E1809318
+:10072000C10086E08093C20008950895982F8091BB
+:10073000C00085FFFCCF9093C60008958091C00053
+:1007400087FFFCCF8091C600992708958A3310F463
+:10075000805301C087556A3310F4605301C0675558
+:100760006F708295807F682B862F99270895FC01F2
+:1007700007C08091C00085FFFCCF31969093C600E2
+:1007800090819923B1F70895982F92959F70282F03
+:100790002F709A3030F48091C00085FFFCCF905DBF
+:1007A00005C08091C00085FFFCCF995A9093C60088
+:1007B0002A3030F48091C00085FFFCCF205D05C059
+:1007C0008091C00085FFFCCF295A2093C600089570
+:1007D00087E280939A0485E28093990490E2909353
+:1007E0009B0410929C0428E030E030939E042093F8
+:1007F0009D0483E28093A60481E28093A5049093F4
+:10080000A7041092A8043093AA042093A904089581
+:1008100008956091B20481E20E945007089568E053
+:100820008BE20E94500761E188E20E94500768E075
+:100830008FE20E94500761E18CE20E94500761E064
+:100840008FE20E9450071092E1011092E00165E0F2
+:1008500083E20E94500708950F931F938C0160E478
+:1008600080E20E945007F8016281605884E00E9493
+:100870005007F80182818093B1041F910F91089570
+:100880000F931F93CF93DF93EC01288539851216C0
+:100890001306DCF58E819F81821793071CF568E0B3
+:1008A00083E20E94500700E010E00FC08A859B851C
+:1008B000E80FF91F608181E20E9450078E819F81BD
+:1008C00001969F838E830F5F1F4FEE81FF81888586
+:1008D0009985083011051CF4E817F9073CF3E8176F
+:1008E000F90724F061E087E20E9450078B81813094
+:1008F00031F465E089810E9450071B8206C061E0E7
+:1009000089810E94500781E08B83DF91CF911F91F5
+:100910000F910895CF93DF93CDB7DEB724970FB62D
+:10092000F894DEBF0FBECDBFDC01FC012281338114
+:100930001092AC041092AB0481E08093A804832F42
+:1009400099278230D9F0833069F1813009F057C09E
+:100950008091850499279093AE048093AD0485E837
+:1009600094E09093B0048093AF04868197818034A3
+:10097000910509F044C088E090E029C0FD0186811E
+:1009800097819093AE048093AD04E22FFF27EE0F82
+:10099000FF1F8091970490919804E80FF91F8081C0
+:1009A000918129C02223C1F0E22FFF27EE0FFF1F04
+:1009B0008091F0019091F101E80FF91F0190F08111
+:1009C000E02DF093B004E093AF04808199279093D9
+:1009D000AE048093AD0413C094E0998383E08A83CE
+:1009E00089E08B839C8384E090E09093AE048093B5
+:1009F000AD04CE0101969093B0048093AF0485EAD4
+:100A000094E00E94400424960FB6F894DEBF0FBE17
+:100A1000CDBFDF91CF910895CF93DF9382E20E9403
+:100A20002B07C82FDD27C5FF1AC068E083E20E94AC
+:100A30005007C6FF10C02091AB043091AC048091E8
+:100A4000AD049091AE04281739072CF485EA94E0A0
+:100A50000E94400404C061E087E20E945007DF91D9
+:100A6000CF9108951F93CF93DF9388E00E942B07C7
+:100A7000182FC82FDD27C6FF18C060E085E00E9450
+:100A8000500760E884E00E94500760E080E20E9426
+:100A9000500768E083E20E94500761E087E20E940D
+:100AA000500762E085E00E945007C4FF04C060EC7C
+:100AB00089E00E94500717FF04C060ED89E00E94A2
+:100AC0005007DF91CF911F9108958AE00E942B0774
+:100AD000992780FF03C00E940C05089581FF0DC077
+:100AE0008AE20E942B0780917204813061F4E091C8
+:100AF0007504F09176040995089582E30E942B070E
+:100B00008AE30E942B0708958EE00E942B0768E07D
+:100B10008FE20E94500761E08FE20E94500720910F
+:100B2000AD043091AE048091A9049091AA0482177B
+:100B300093075CF468E083E20E94500761E087E27B
+:100B40000E94500781E08093A8040895AF92BF925D
+:100B5000CF92DF92EF92FF920F931F93CF93DF9389
+:100B6000CDB7DEB728970FB6F894DEBF0FBECDBF66
+:100B700086E20E942B0786FF7EC08E010F5F1F4F0B
+:100B8000580169E0C62ED12CCC0EDD1E809199044F
+:100B90000E942B07F80181938F017501EC15FD056B
+:100BA000A9F768E087E20E94500768E083E20E94AC
+:100BB000500780E20E942B078F77682F80E20E9407
+:100BC000500789819927807690708032910509F4C9
+:100BD00040C080349105D1F1892BF1F5F501818177
+:100BE0008630D9F0873048F48130F1F18130C8F097
+:100BF0008330D1F1853081F521C0893019F18A30F7
+:100C000018F4883049F505C08A3071F18B3021F530
+:100C100020C0C5010E94090427C0C5010E948A04A2
+:100C200023C068E083E20E94500761E081E20E94F5
+:100C3000500760E081E20E9450070BC0C5010E948E
+:100C40002C0412C0C5010E940F040EC0C5010E94F1
+:100C5000080765E083E206C080E20E942B07805807
+:100C6000682F80E20E945007F70180818823D1F429
+:100C700065E083E215C02091AD043091AE0480910F
+:100C8000A9049091AA048217930764F41092AE0409
+:100C90001092AD0468E083E20E94500761E087E2B1
+:100CA0000E94500728960FB6F894DEBF0FBECDBF46
+:100CB000DF91CF911F910F91FF90EF90DF90CF9038
+:100CC000BF90AF900895CF92DF92EF92FF920F9373
+:100CD0001F93CF93DF93CDB7DEB7C054D0400FB68C
+:100CE000F894DEBF0FBECDBF8CE00E942B07992782
+:100CF00080FF03C00E94A6057BC081FF2AC08EE250
+:100D00000E942B078DE20E942B0789838E010F5FC3
+:100D10001F4F6801FFE3EF2EF12CE00EF11E0F5F75
+:100D20001F4F0E941907F80180830E151F05B9F7A0
+:100D300080915401813031F4E0915701F0915801D4
+:100D4000C601099568E08FE20E94500761E08FE2DA
+:100D50002BC082FF2CC086E30E942B0785E30E94F4
+:100D60002B0789838E010F5F1F4F6801EFE3EE2E83
+:100D7000F12CE00EF11E0F5F1F4F0E941907F801C2
+:100D800080830E151F05B9F780915501813031F42C
+:100D9000E0915901F0915A01C601099568E087E395
+:100DA0000E94500761E087E30E94500721C083FF43
+:100DB0001FC08EE30E942B078E010F5F1F4F68013B
+:100DC00071E4E72EF12CEC0EFD1E8DE30E942B0743
+:100DD000F80181938F01EE15FF05B9F78091560157
+:100DE000813031F4E0915701F0915801C601099525
+:100DF000C05CDF4F0FB6F894DEBF0FBECDBFDF91F2
+:100E0000CF911F910F91FF90EF90DF90CF900895B9
+:100E10000895089581E080936A0080E18DBB83B3DB
+:100E2000876083BB84B3836084BB3F9A479A78947E
+:100E3000089588B1805888B984B322E0822784BBA2
+:100E40000000000080B198B1905898B994B39227EF
+:100E500094BB992708959FEF91B982B988B18058C2
+:100E600088B984B395E0892784BB88B1805888B954
+:100E700084B3892784BB000011B80E941907992701
+:100E8000089582B988B1805888B984B391E08927E0
+:100E900084BB88B1805888B984B3892784BB0895FE
+:100EA00082B98FEF81B988B1805888B984B395E051
+:100EB000892784BB88B1805888B984B3892784BBCB
+:100EC000862F0E9441070895089582E1809385044A
+:100ED00081E08093860480E191E090938804809380
+:100EE00087041092890410928A0410928B0488E07F
+:100EF00080938C0410928E0410928D0410929004B2
+:100F000010928F0410929204109291041092930404
+:100F10001092940410929504109296041092540129
+:100F2000109255011092560110927204109273049F
+:100F30001092740410927C0410927B041092EF01C2
+:100F40001092EE01089590938E0480938D04709317
+:100F5000900460938F0450939204409391040895F9
+:100F600090938E0480938D040895909390048093C1
+:100F70008F04089590939204809391040895809330
+:100F80008904089580938A04089580938B040895BA
+:100F9000CF93DF939C01CB01E0917B04F0917C0423
+:100FA00062E070E00E94BD190FC0A081B181828112
+:100FB000823039F4ED018D8199278217930709F466
+:100FC00068870780F085E02D309779F7DF91CF9122
+:100FD0000895CF93DF939C01E0917B04F0917C0412
+:100FE00014C0A081B1818281843061F48481992709
+:100FF0008217930739F4868199278617970711F48A
+:10100000ED014B830780F085E02D309751F7DF919C
+:10101000CF910895BF92CF92DF92EF92FF920F93FC
+:101020001F93CF93DF936C01162FF42EB22EC09135
+:101030007B04D0917C042097A1F489E090E00E9489
+:10104000C418FC0190937C0480937B04D182C082FD
+:10105000138310861782F282B4820583E68215C05C
+:10106000EC018F8198850097D9F789E090E00E9484
+:10107000C418FC0198878F83D182C0821383F282C7
+:10108000B4820583E68210861782DF91CF911F918B
+:101090000F91FF90EF90DF90CF90BF900895EF9267
+:1010A000FF921F93CF93DF937C01C091EE01D0910B
+:1010B000EF01209711F011E012C085E090E00E944E
+:1010C000C418FC019093EF018093EE01F182E0825D
+:1010D00012821482138210E012C01F5FEC018B8118
+:1010E0009C810097D1F785E090E00E94C418FC0134
+:1010F0009C838B83F182E082128314821382812F7E
+:101100009927DF91CF911F91FF90EF900895EF9273
+:10111000FF920F931F93CF93DF93E091EE01F09135
+:10112000EF0180E090E00380F481E02D019630979C
+:10113000D1F7880F991F0E94C4189093F1018093F2
+:10114000F0010091EE011091EF01E801E880F980D3
+:101150008A81C82FDD27CC0FDD1F8091F00190918F
+:10116000F101C80FD91FF701808199270E94C41887
+:101170009983888320E030E017C0E801EA81FF27E7
+:10118000EE0FFF1F8091F0019091F101E80FF91F20
+:101190000190F081E02DE20FF31FD701A20FB31FE2
+:1011A0008C9180832F5F3F4FF7018081992728170B
+:1011B00039071CF3E8018B819C81009711F08C01A9
+:1011C000C4CFDF91CF911F910F91FF90EF900895C1
+:1011D0004F925F926F927F928F929F92AF92BF9247
+:1011E000CF92DF92EF92FF920F931F93CF93DF93F3
+:1011F000E0917B04F0917C046624772409C082810D
+:10120000823019F40894611C711C0780F085E02D70
+:101210003097A9F74301880C991CC4010E94C41897
+:101220009093980480939704E1E0EE2EF12CAA2489
+:10123000BB2455C0E0917B04F0917C0479E0C72E7B
+:10124000D12C15C0A081B181848199278E159F056D
+:1012500019F48381C80ED11CED018D818E1521F406
+:101260008281823009F45D010780F085E02D30979E
+:1012700049F7009197041091980402501040080D0E
+:10128000191DC6010E94C418F8019183808320E0D3
+:1012900030E0E0919704F0919804E80DF91D329741
+:1012A0000190F081E02DE20FF31FD501A20FB31FD3
+:1012B0008C9180832F5F3F4F2930310551F7E091AA
+:1012C0009704F0919804E80DF91D32970190F08190
+:1012D000E02D8C2D875F82830894E11CF11C6E1435
+:1012E0007F040CF0A7CF61E0C62ED12C59E0A52ECB
+:1012F000B12C4424552442E0842E912CA1C0A0910D
+:101300007B04B0917C0412C0ED91FC911197818116
+:10131000823049F4858199278C159D0521F48481BB
+:10132000482E552405C0ED01AF81B885109761F7AF
+:1013300031E0E32EF12C79C060917B0470917C0444
+:101340006DC0FB01C081D1818981843009F063C007
+:10135000868199278E159F0509F05DC084819927A4
+:101360008C159D0509F057C0950140E050E0E091D3
+:101370009704F0919804E80DF91D32970190F081DF
+:10138000E02DE20FF31FDE01A40FB51F8C918083C7
+:101390002F5F3F4F4F5F5F4F4930510541F789E065
+:1013A00090E0A80EB91EC0917B04D0917C0431C09E
+:1013B0008A81853059F58C8199278C159D0531F5E9
+:1013C0008D8199278E159F0509F508811981950151
+:1013D00040E050E0E0919704F0919804E80DF91D89
+:1013E00032970190F081E02DE20FF31FD801A40F96
+:1013F000B51F8C9180832F5F3F4F4F5F5F4F47300A
+:10140000510541F7E7E0F0E0AE0EBF1E0F80D88532
+:10141000C02D209769F6EB016F8178856115710504
+:1014200009F08FCF0894E11CF11C4E145F040CF0FE
+:1014300083CF0894C11CD11CE2E0F0E08E0E9F1E09
+:101440006C147D040CF05BCFDF91CF911F910F9155
+:10145000FF90EF90DF90CF90BF90AF909F908F90D4
+:101460007F906F905F904F9008956F927F928F92D0
+:101470009F92AF92BF92CF92DF92EF92FF920F9323
+:10148000CF93DF935C013B014901E0917B04F09134
+:101490007C0416C0A081B18184819927A816B90661
+:1014A00061F4868199278615970539F48281843005
+:1014B00021F4ED018C818F5F8C830780F085E02D16
+:1014C000309741F787E090E00E94C418FC0187E064
+:1014D000808385E0818382820383F582E482C682F1
+:1014E000EE24062D2A2D45E067E0CF010E940A0870
+:1014F000DF91CF910F91FF90EF90DF90CF90BF9051
+:10150000AF909F908F907F906F900895AF92BF9211
+:10151000CF92DF92EF92FF920F93FC01A114B104DE
+:1015200001F14230510571F04330510599F04130DD
+:101530005105B9F481E080937204B0927604A092D0
+:1015400075040FC081E080937304B0927804A09278
+:10155000770407C081E080937404B0927A04A0926B
+:10156000790420583F4FCF010E94350A0F91FF9018
+:10157000EF90DF90CF90BF90AF900895AF92BF9261
+:10158000CF92DF92EF92FF920F93FC014230510510
+:1015900071F04330510599F041305105B9F481E0C3
+:1015A00080935401B0925801A09257010FC081E07E
+:1015B00080935501B0925A01A092590107C081E071
+:1015C00080935601B0925C01A0925B01CF010E9412
+:1015D000350A0F91FF90EF90DF90CF90BF90AF90C2
+:1015E0000895CF92DF92EF920F931F93CF93DF93E3
+:1015F0006C018B01A0917B04B0917C04C0E0D0E031
+:1016000014C02D913C911197F90185818C1551F4ED
+:10161000FD018281823031F4F90184818F5F8483FE
+:10162000C82FDD27FD01A781B085109751F789E00C
+:1016300090E00E94C418FC0189E0808384E08183EB
+:101640000283138214821582168217821086EC2E72
+:1016500000E02C2D44E069E0CF010E940A08CE0191
+:10166000DF91CF911F910F91EF90DF90CF90089570
+:10167000BF92CF92DF92EF92FF920F931F93CF937F
+:10168000DF936C017B01142FB22EA0917B04B091EB
+:101690007C04C0E0D0E014C02D913C911197F90179
+:1016A00085818C1551F4FD018281823031F4F9017C
+:1016B00084818F5F8483C82FDD27FD01A781B085DA
+:1016C000109751F789E090E00E94C418FC0189E06E
+:1016D000808384E08183E282138214821583B68240
+:1016E00007831086EC2E00E02C2D44E069E0CF014A
+:1016F0000E940A08CE01DF91CF911F910F91FF90B8
+:10170000EF90DF90CF90BF900895EF920F931F93CB
+:10171000109196041F5F1093960489E090E00E9458
+:10172000C418FC0189E0808389E090E09383828380
+:1017300082E0818314821583168280EA87838AE19E
+:101740008087EE2400E020E042E069E0CF010E94C3
+:101750000A08812F99271F910F91EF900895CF9339
+:10176000DF93EC01FC0101900020E9F7E81BF90B85
+:10177000CF01880F991F0E94C4189C01FE0101909F
+:101780000020E9F7EC1BFD0BEE0FFF1FDC01EC93D3
+:1017900083E0F901818340E050E009C0FE01E40FDD
+:1017A000F51F80818C93FD0111824F5F5F4F129670
+:1017B000FE0101900020E9F73197EC1BFD0B4E175D
+:1017C0005F0760F3C9010E944F089927DF91CF910D
+:1017D0000895EF92FF920F931F93CF93DF938C01A5
+:1017E0007B01CA010E94AF0B9C01E0917B04F09148
+:1017F0007C0414C0A081B1818281843061F4848131
+:1018000099278017910739F4868199278E159F05AE
+:1018100011F4ED0128870780F085E02D309751F70E
+:10182000DF91CF911F910F91FF90EF9008950F934B
+:101830001F93CF93DF938C01CB010E94AF0B9C01D0
+:10184000E0917B04F0917C040FC0A081B181828182
+:10185000823039F4ED018D8199278017910709F4C1
+:101860002E830780F085E02D309779F7DF91CF91B7
+:101870001F910F9108950E94AF0B1816190614F4CA
+:101880008093950408950E94AF0B1816190614F45E
+:101890008093940408950E94AF0B1816190614F44F
+:1018A0008093930408951F9386E00E942B07992745
+:1018B00086FF03C00E9463060EC082FF03C00E9421
+:1018C000650509C081FF03C00E94320504C084FF82
+:1018D00002C00E94840587E00E942B07182F60E059
+:1018E00087E00E945007612F87E00E9450071F91F8
+:1018F00008950E94E8080E9487080E94E80361E0BA
+:1019000080E00E94500780E00E942B0780FDFBCF03
+:1019100062E081E00E94500760E884E00E94500786
+:1019200060E480E20E94500768E083E20E94500772
+:1019300069E087E20E9450076FE08DE00E94500747
+:101940006FE08BE00E94500768ED89E00E9450072D
+:1019500063E38FE00E94500766ED87E00E94500726
+:1019600062E085E00E9450076CEC80E00E94500726
+:1019700008958EEC80935D0181E080936E008091EC
+:101980005D0186BD83E084BD08950895089583E0D8
+:101990008093320381E0809333038BE080933403A0
+:1019A0002FE62093350393E69093360384E78093E4
+:1019B0003703209338039093390381E680933A03E9
+:1019C0008EE680933B038FE580933C0380E3809316
+:1019D0003D0381E380933E0310923F038EE090E04D
+:1019E0000E949C010895FC018081833011F40E94C3
+:1019F000C70C0895CF93DF93C1E0D0E08C2F0E94F5
+:101A00000B0E2196C431D105C9F7CAE1D0E08C2F65
+:101A10000E940B0E2196CD32D105C9F7DF91CF91EF
+:101A20000895CF93DF93DC01EC01EA81FB812191E2
+:101A30008E81815019F48981E81BF109ED01FB8346
+:101A4000EA838E839FB7F8948C9181508C939FBFCB
+:101A5000822F9927DF91CF910895FC011082758321
+:101A60006483738362834183478346830895CF935E
+:101A7000DF93DC019C91ED018981981718F080E0DB
+:101A800090E016C0ED01EC81FD8161938F81815062
+:101A900019F48981E81BF109ED018F83FD83EC8343
+:101AA0009FB7F8948C918F5F8C939FBF81E090E0FB
+:101AB000DF91CF910895FC0180818823E9F3CF0164
+:101AC0000E94110D99270895FC018081882319F443
+:101AD0008FEF9FEF0895CF010E94110D9927089570
+:101AE00081E090E0089581E090E0089581E090E049
+:101AF000089581E090E00895CF93DF93CDB7DEB7EE
+:101B000022970FB6F894DEBF0FBECDBF282F8150AD
+:101B1000833120F08951833108F06EC0E22FFF2716
+:101B2000EE0FFF1FE35AFE4F82E090E09283818325
+:101B3000822F9927AA27BB27FC013197EC32F105A8
+:101B400008F05AC0E65BFF4FEE0FFF1F0590F491BF
+:101B5000E02D09946D9A47C06E9A49C06F9A43C0B0
+:101B6000209A45C0219A3FC0229A41C0239A3BC087
+:101B7000249A3DC0259A37C0269A39C0279A33C087
+:101B8000509A35C0519A2FC0529A31C0539A2BC0E7
+:101B9000549A2DC0559A27C0569A29C0579A23C0E7
+:101BA000389A25C0399A1FC03A9A21C03B9A1BC067
+:101BB0003C9A1DC03D9A17C03E9A19C0879A13C01F
+:101BC000869A15C0859A0FC0849A11C0839A0BC05B
+:101BD000829A0DC0819A07C0809A09C0689A03C092
+:101BE000699A05C06A9A81E090E008C06B9AE1E0CA
+:101BF000F0E0FA83E98304C084E090E09A8389836B
+:101C000089819A8122960FB6F894DEBF0FBECDBFB0
+:101C1000DF91CF910895982F8150833130F0895111
+:101C2000833118F084E090E00895892F0E947C0DA4
+:101C300081E090E00895CF93DF93CDB7DEB7229790
+:101C40000FB6F894DEBF0FBECDBF282F8150833171
+:101C500020F08951833108F06EC0E22FFF27EE0F8C
+:101C6000FF1FE35AFE4F81E090E092838183822F31
+:101C70009927AA27BB27FC013197EC32F10508F020
+:101C80005AC0EA58FF4FEE0FFF1F0590F491E02D68
+:101C900009946D9847C06E9849C06F9843C02098CA
+:101CA00045C021983FC0229841C023983BC024984A
+:101CB0003DC0259837C0269839C0279833C0509822
+:101CC00035C051982FC0529831C053982BC05498AA
+:101CD0002DC0559827C0569829C0579823C03898CA
+:101CE00025C039981FC03A9821C03B981BC03C982A
+:101CF0001DC03D9817C03E9819C0879813C086989C
+:101D000015C085980FC0849811C083980BC0829825
+:101D10000DC0819807C0809809C0689803C0699871
+:101D200005C06A9881E090E008C06B98E1E0F0E0BF
+:101D3000FA83E98304C084E090E09A8389838981EF
+:101D40009A8122960FB6F894DEBF0FBECDBFDF9109
+:101D5000CF910895FB011082833091F0843028F4F4
+:101D6000813051F0823029F409C0843059F0853037
+:101D700059F085E090E0089583B107C086B105C0B1
+:101D800089B103C08CB101C08FB1808381E090E044
+:101D90000895833091F0843028F4813051F08230FE
+:101DA00029F409C0843059F0853069F084E090E06E
+:101DB000089565B905C068B903C06BB901C06EB9B3
+:101DC00081E090E0089561BB81E090E00895282FC4
+:101DD000E82FFF27EE0FFF1FE35AFE4F818192810C
+:101DE000029719F086E090E00895822F9927AA279C
+:101DF000BB27FC013197EC32F10540F4EE55FF4F63
+:101E0000EE0FFF1F0590F491E02D099484E090E01F
+:101E10000895662311F0759ADDC07598DBC06623BE
+:101E200011F0769AD7C07698D5C0662311F0779ACC
+:101E3000D1C07798CFC0662311F0289ACBC02898DC
+:101E4000C9C0662311F0299AC5C02998C3C066236A
+:101E500011F02A9ABFC02A98BDC0662311F02B9AB0
+:101E6000B9C02B98B7C0662311F02C9AB3C02C9838
+:101E7000B1C0662311F02D9AADC02D98ABC066237A
+:101E800011F02E9AA7C02E98A5C0662311F02F9AA4
+:101E9000A1C02F989FC0662311F0589A9BC05898F4
+:101EA00099C0662311F0599A95C0599893C066233A
+:101EB00011F05A9A8FC05A988DC0662311F05B9A20
+:101EC00089C05B9887C0662311F05C9A83C05C98D8
+:101ED00081C0662311F05D9A7DC05D987BC066234A
+:101EE00011F05E9A77C05E9875C0662311F05F9A14
+:101EF00071C05F986FC0662311F0409A6BC0409824
+:101F000069C0662311F0419A65C0419863C0662399
+:101F100011F0429A5FC042985DC0662311F0439A67
+:101F200059C0439857C0662311F0449A53C044984F
+:101F300051C0662311F0459A4DC045984BC06623A9
+:101F400011F0469A47C0469845C0662311F08F9A13
+:101F500041C08F983FC0662311F08E9A3BC08E9887
+:101F600039C0662311F08D9A35C08D9833C0662331
+:101F700011F08C9A2FC08C982DC0662311F08B9A8B
+:101F800029C08B9827C0662311F08A9A23C08A98AB
+:101F900021C0662311F0899A1DC089981BC0662351
+:101FA00011F0889A17C0889815C0662311F0709AAE
+:101FB00011C070980FC0662311F0719A0BC0719810
+:101FC00009C0662311F0729A05C0729803C0662397
+:101FD00021F0739A81E090E00895739881E090E099
+:101FE00008951F93182F8150833130F08951833128
+:101FF00018F084E090E013C0E12FFF27EE0FFF1FE1
+:10200000E35AFE4F83E090E092838183812F0E9408
+:102010007C0D61E0812F0E94E70E81E090E01F912E
+:102020000895CF93DF93282FEB011882E82FFF2725
+:10203000EE0FFF1FE35AFE4F81819281019719F045
+:1020400086E090E089C0822F9927AA27BB27FC0150
+:102050003197EC32F10540F4E253FF4FEE0FFF1FD2
+:102060000590F491E02D099484E090E075C0659BA3
+:1020700071C06EC0669B6EC06BC0679B6BC068C052
+:10208000189B68C065C0199B65C062C01A9B62C07E
+:102090005FC01B9B5FC05CC01C9B5CC059C01D9B8C
+:1020A00059C056C01E9B56C053C01F9B53C050C042
+:1020B000489B50C04DC0499B4DC04AC04A9B4AC036
+:1020C00047C04B9B47C044C04C9B44C041C04D9B44
+:1020D00041C03EC04E9B3EC03BC04F9B3BC038C042
+:1020E000309B38C035C0319B35C032C0329B32C0C6
+:1020F0002FC0339B2FC02CC0349B2CC029C0359BD4
+:1021000029C026C0369B26C023C07F9B23C020C089
+:102110007E9B20C01DC07D9B1DC01AC07C9B1AC029
+:1021200017C07B9B17C014C07A9B14C011C0799B49
+:1021300011C00EC0789B0EC00BC0609B0BC008C0C6
+:10214000619B08C005C0629B05C002C0639B02C0C2
+:1021500081E0888381E090E0DF91CF910895CF9373
+:10216000DF93CDB7DEB721970FB6F894DEBF0FBE71
+:10217000CDBF9BE190933203BE016F5F7F4F0E9402
+:1021800011108093330389818093340383E090E0BE
+:102190000E949C0121960FB6F894DEBF0FBECDBF02
+:1021A000DF91CF9108959AE1909332030E94E70E58
+:1021B000809333031092340383E090E00E949C01EB
+:1021C000089598E1909332030E94C90E80933303DF
+:1021D0001092340383E090E00E949C010895982FB0
+:1021E00089E180933203933099F0943028F4913050
+:1021F00059F0923029F40AC0943061F0953061F0C2
+:1022000085E090E020E00BC023B107C026B105C0F7
+:1022100029B103C02CB101C02FB181E090E08093BF
+:1022200033032093340383E090E00E949C010895DF
+:1022300097E1909332030E94F10F80933303109241
+:10224000340383E090E00E949C01089595E190930F
+:1022500032030E941B0E809333031092340383E0F9
+:1022600090E00E949C01089596E1909332030E94B1
+:102270007C0D809333031092340383E090E00E943E
+:102280009C01089584E18093320381E080933303BD
+:102290001092340383E090E00E949C01089582E153
+:1022A0008093320381E0809333031092340383E000
+:1022B00090E00E949C01089583E18093320381E0C5
+:1022C000809333031092340383E090E00E949C01DA
+:1022D000089580E18093320381E08093330310926C
+:1022E000340383E090E00E949C01089591E1909373
+:1022F00032030E940B0E809333031092340383E069
+:1023000090E00E949C010895FC0180818531C9F113
+:10231000863180F4823131F1833130F48031D1F073
+:10232000813109F04CC01AC0833109F1843109F0C0
+:1023300046C022C0883189F1893128F4863129F1DB
+:102340008731E9F526C08A3189F18A3158F18B311C
+:10235000B1F531C082810E946911089582810E9485
+:1023600076110895638182810E944F1108956381DF
+:1023700082810E945C110895638182810E944211D2
+:10238000089582810E942611089582810E9434114D
+:10239000089582810E9418110895638182810E94AC
+:1023A000E110089582810E94EF1008956381828177
+:1023B0000E94D310089582810E94AF1008958093E7
+:1023C000320383E0809333031092340383E090E080
+:1023D0000E949C010895FC018197089718F084E001
+:1023E00090E00895EE0FFF1FE35AFE4F84E090E067
+:1023F0009283818381E090E0089510927C00823086
+:10240000910541F08330910569F0019741F082E038
+:1024100090E0089580917C00806480937C0081E04E
+:1024200090E0089580917C00806C80937C0081E036
+:1024300090E0089593E890937A0090917C00907FCB
+:10244000982B90937C0080917A00806480937A002E
+:1024500080917A0086FDFCCF809178009091790080
+:1024600020E030E040E050E080917A00806480938A
+:102470007A0080917A0086FDFCCF8091780090915F
+:102480007900480F591F2F5F3F4F2430310561F706
+:1024900080917A008F7780937A00CA01969587950C
+:1024A000969587950895CF93DF939C01EB01198250
+:1024B0001882FC01EE0FFF1FE35AFE4F81819281CB
+:1024C000049719F086E090E03CC02432310541F1D8
+:1024D0002532310554F42232310541F123323105E0
+:1024E00014F52132310569F424C02632310591F00A
+:1024F0002632310594F02732310549F02832310572
+:1025000019F087E090E01DC080E090E014C081E009
+:1025100090E011C082E090E00EC083E090E00BC03C
+:1025200084E090E008C085E090E005C086E090E09F
+:1025300002C087E090E00E941A129983888381E0AC
+:1025400090E0DF91CF91089522E2209332030E9420
+:10255000FD118093330382E090E00E949C01089576
+:10256000CF93DF93CDB7DEB722970FB6F894DEBFD7
+:102570000FBECDBF21E220933203BE016F5F7F4FBC
+:102580000E9453128093330329813A81832F992724
+:10259000809334032093350384E090E00E949C01F3
+:1025A00022960FB6F894DEBF0FBECDBFDF91CF915C
+:1025B000089520E2209332030E94EB1180933303AD
+:1025C0001092340383E090E00E949C010895FC0186
+:1025D0008081813249F0823261F0803279F48281E7
+:1025E00099270E94D9120895828199270E94B012DA
+:1025F0000895828199270E94A4120895809332033E
+:1026000083E0809333031092340383E090E00E94D0
+:102610009C0108958091B9009927887F9070089552
+:102620008091BC0087FFFCCF0895ECEBF0E0808147
+:10263000846080838BE090E09093770180937601B3
+:102640008CE090E0909379018093780181E090E0B4
+:102650000895ECEBF0E080818B7F808382E090E056
+:10266000909377018093760190937901809378011C
+:1026700081E090E008958130910511F48CE00BC069
+:102680008230910511F488E106C0039719F082E0C9
+:1026900090E0089588E48093B8008091B9008C7F21
+:1026A0008093B9008091B9008093B90081E090E0F7
+:1026B00008958091B90084EA8093BC008091BC00A9
+:1026C00087FFFCCF81E090E0089584E98093BC000F
+:1026D00081E090E008958093BB0084E88093BC0083
+:1026E0008091BC0087FFFCCF80E090E0089584E8F3
+:1026F0008093BC008091BC0087FFFCCF8091BB0021
+:102700009927089585E38093320381E08093330312
+:102710008093340384E88093BC008091BC0087FFE1
+:10272000FCCF8091BB008093350385E090E00E9450
+:102730009C01089540E050E00FC0F901E40FF51F3F
+:1027400080818093BB0084E88093BC008091BC00B2
+:1027500087FFFCCF4F5F5F4F4617570774F384E343
+:102760008093320381E0809333031092340383E03B
+:1027700090E00E949C01089587E38093320384E9EE
+:102780008093BC0081E0809333031092340383E094
+:1027900090E00E949C01089586E38093320380912B
+:1027A000B90084EA8093BC008091BC0087FFFCCF15
+:1027B00081E0809333031092340383E090E00E9421
+:1027C0009C01089522E3209332030E943B138093DF
+:1027D00033031092340383E090E00E949C0108953B
+:1027E00081E380933203ECEBF0E080818B7F808388
+:1027F00082E090E090937701809376019093790145
+:102800008093780181E0809333031092340383E056
+:1028100090E00E949C01089580E380933203ECEBEA
+:10282000F0E08081846080838BE090E0909377017A
+:10283000809376018CE090E0909379018093780109
+:1028400081E0809333031092340383E090E00E9490
+:102850009C010895FC0180818433D9F0853338F4DC
+:10286000813379F0823381F0803389F507C0863374
+:1028700041F18633D8F0873351F526C00E940C14FD
+:1028800008950E94F0130895828199270E94E2130F
+:102890000895428155276181772764507040838174
+:1028A00034969F0199270E949A13089542815527D3
+:1028B0006181772764507040838199270E94821339
+:1028C00008950E94CC1308950E94BC13089580932C
+:1028D000320383E0809333031092340383E090E06B
+:1028E0000E949C01089585B1817F85B9239886E077
+:1028F00084B91CBC1DBC83E58CBD88E090E090933E
+:102900006901809368018AE090E090936B01809365
+:102910006A0189E090E090936D0180936C0181E001
+:1029200090E008951CBC1DBC82E090E0909369018A
+:102930008093680190936B0180936A0190936D017D
+:1029400080936C0181E090E00895089581E090E02B
+:102950000895AC0120E030E00AC0FA01E20FF31F55
+:1029600080818EBD0DB407FEFDCF2F5F3F4F261730
+:1029700037079CF381E090E00895DC0120E030E02F
+:1029800040E050E015C01EBC09C04F5F5F4F83E0C0
+:10299000493E58071CF088E090E008950DB407FE0A
+:1029A000F4CFFD01E20FF31F8EB580832F5F3F4F01
+:1029B0002617370744F381E090E00895CF93DF9323
+:1029C000EC0120E030E0A0E0B0E018C0FE01E20F32
+:1029D000F31F80818EBD08C0119683E0A93EB80721
+:1029E0001CF088E090E00FC00DB407FEF5CFFB01AE
+:1029F000E20FF31F8EB580832F5F3F4F24173507FB
+:102A00002CF381E090E0DF91CF9108950F931F9315
+:102A10008B0123E420933203AB0164E373E00E9453
+:102A2000DE148093330310923403C80102960E948F
+:102A30009C011F910F9108950F931F938C0184E4C3
+:102A400080933203B80184E393E00E94BD14809325
+:102A5000330310923403C80102960E949C011F9117
+:102A60000F91089523E4209332030E94A9148093C8
+:102A700033031092340383E090E00E949C01089598
+:102A800081E4809332030E94921480933303109266
+:102A9000340383E090E00E949C01089580E48093D9
+:102AA00032030E947314809333031092350383E042
+:102AB00090E00E949C010895CF93DF93EC01888100
+:102AC0008334A1F0843438F4813469F0823458F5C9
+:102AD0008034F1F405C0843481F08534C9F411C028
+:102AE0000E944E1520C00E9440151DC069817727A5
+:102AF000CE0102960E94321516C0898199270E9444
+:102B00001C1569817727CE0102960E9406150BC01D
+:102B10008093320383E0809333031092340383E085
+:102B200090E00E949C01DF91CF910895209A219A14
+:102B3000229A2398249A259A2C982D9882E090E046
+:102B40009093850180938401909383018093820107
+:102B5000909381018093800181E090E090937F01C8
+:102B600080937E01089582E090E0909369018093C4
+:102B7000680190936B0180936A0190936D0180933B
+:102B80006C0181E090E00895289829982A9880E2C5
+:102B90009EE40197F1F7289A8AE0982F9A95F1F729
+:102BA0002A9A299A8A95F1F70895282F299887FD5E
+:102BB00002C02A9801C02A9A8AE0982F9A95F1F7C4
+:102BC000299A8A95F1F7299826FF02C02A9A01C00E
+:102BD0002A988AE0982F9A95F1F7299A8A95F1F721
+:102BE0000895282F220F30E0299827FF02C02A9A43
+:102BF00001C02A988AE0982F9A95F1F7299A8A9528
+:102C0000F1F73F5F373011F0220FEECF0895282FF4
+:102C100030E0299827FF02C02A9A01C02A988AE04A
+:102C2000982F9A95F1F7299A8A95F1F73F5F3830F6
+:102C300011F0220FEECF089529982A988AE0982F54
+:102C40009A95F1F7299A982F9A95F1F7299828984B
+:102C5000982F9A95F1F7299A982F9A95F1F7299834
+:102C60008A95F1F7289A80E090E0089529982898AD
+:102C70002A982B9A08950E94C41580E30E94D515C6
+:102C800080E60E94F11508950E94C41580E00E941C
+:102C9000D51580E00E94F1150E94361608950F9315
+:102CA0001F93182F062F0E94C41580E40E94D5158B
+:102CB000812F0E94F115802F0E94071681E090E07D
+:102CC0001F910F9108951F93182F0E94C41580EC37
+:102CD0000E94D515812F0E94F1150E941C1699277C
+:102CE0001F91089529988AE08A95F1F72A9830E093
+:102CF00090E0990F299A2AE0822F8A95F1F7299876
+:102D00001B999F5F822F8A95F1F73F5F383089F7D3
+:102D10002898299A822F8A95F1F7289A29982A9536
+:102D2000F1F7892F992708951F93182F0E94C41532
+:102D300080E80E94D515812F0E94F1150E9472161D
+:102D400099271F910895DF92EF92FF920F931F939F
+:102D5000CF93DF93D82E7B018A01C0E0D0E009C079
+:102D60008D2D8C0F0E949416F801EC0FFD1F8083AF
+:102D70002196CE15DF05A1F781E090E0DF91CF919C
+:102D80001F910F91FF90EF90DF9008950F931F9385
+:102D9000082F162F0E943B16612F802F0E944F167E
+:102DA00081E090E01F910F910895DF92EF92FF92E2
+:102DB0000F931F93CF93DF93D82E7B018A01C0E03E
+:102DC000D0E009C0F801EC0FFD1F60818D2D8C0F44
+:102DD0000E94C6162196CE15DF05A1F781E090E08E
+:102DE000DF91CF911F910F91FF90EF90DF900895A9
+:102DF00094E0909332030E94D5168093330310928F
+:102E0000340383E090E00E949C0108950F931F9388
+:102E10008B0193E09093320344E353E00E94A316A6
+:102E200080933303C80102960E949C011F910F9169
+:102E3000089582E08093320382E090E090936901EC
+:102E40008093680190936B0180936A0190936D0168
+:102E500080936C0181E0809333031092340383E00C
+:102E600090E00E949C01089581E0809332030E94CB
+:102E70009615809333031092340383E090E00E9410
+:102E80009C010895FC018381823069F0833018F43D
+:102E90008130F1F405C0833049F08430C9F40FC0AB
+:102EA0000E94341708950E9419170895AF014A5FD0
+:102EB0005F4F6581772784810E9406170895AF01CF
+:102EC0004A5F5F4F6581772784810E94F8160895D5
+:102ED00080818093320383E0809333031092340324
+:102EE00083E090E00E949C0108951F920F920FB61C
+:102EF0000F9211240F900FBE0F901F9018959C01F8
+:102F00000897029718F084E090E00895F901EE0F19
+:102F1000FF1FE35AFE4F8DE090E0928381832830BB
+:102F20003105B1F02930310519F087E090E00895BE
+:102F3000259A81E090E0909389008093880081E851
+:102F40008093800089E08093810081E090E0089583
+:102F5000249A81E08093B30089E68093B00081E0F9
+:102F600090E008959C01FC01EE0FFF1FE35AFE4F15
+:102F7000818192810D9719F086E090E008952830C4
+:102F8000310539F12930310519F087E090E00895D5
+:102F900063307105B1F06430710544F4613071053E
+:102FA00061F06230710509F040C009C064307105FC
+:102FB00051F065307105C9F508C081E007C082E0B5
+:102FC00005C083E003C084E001C085E080938100F8
+:102FD00029C064307105E9F06530710554F4623040
+:102FE000710599F06330710594F461307105E9F46D
+:102FF0000AC06630710589F06630710564F067308B
+:10300000710599F40CC089E60BC08AE609C08BE60D
+:1030100007C08CE605C08DE603C08EE601C08FE6D2
+:103020008093B00081E090E0089581E090E0089501
+:103030009C01FC01EE0FFF1FE35AFE4F818192813C
+:103040000D9719F086E090E008952830310569F079
+:103050002930310519F087E090E0089570938900D8
+:103060006093880081E090E008956093B30081E070
+:1030700090E0089523E5209332030E94181880936E
+:1030800033031092340383E090E00E949C01089582
+:1030900022E5209332030E94B217809333031092EB
+:1030A000340383E090E00E949C01089520E5209382
+:1030B00032030E947F17809333031092340383E01E
+:1030C00090E00E949C0108959C01FC01EE0FFF1FFF
+:1030D000E35AFE4F82E090E09283818328303105ED
+:1030E00031F02930310531F086E090E008951092FA
+:1030F000B00004C01092810010928000822F0E94C4
+:103100007C0D81E090E0089521E5209332030E9438
+:103110006418809333031092340383E090E00E949C
+:103120009C010895FC018081813579F0823518F485
+:103130008035F1F405C0823569F08335C9F411C0DA
+:10314000828199270E9456180895828199270E94AA
+:103150008418089563817727828199270E944818EF
+:10316000089563817727828199270E943A180895EC
+:103170008093320383E0809333031092340383E01F
+:1031800090E00E949C010895CF93DF93AC010297D9
+:1031900010F442E050E0A091B704B091B804FD01F2
+:1031A000C0E0D0E020E030E020C080819181841731
+:1031B000950769F482819381209719F09B838A8314
+:1031C00004C09093B8048093B704CF0132C048176D
+:1031D000590738F42115310519F08217930708F4BF
+:1031E0009C01EF010280F381E02D3097F1F621156B
+:1031F000310589F1C901841B950B049708F4A901D5
+:10320000E0E0F0E026C08D919C9111978217930722
+:10321000E9F44817590779F4ED018A819B813097C9
+:1032200019F09383828304C09093B8048093B70409
+:10323000CD01029649C0841B950BFD01E80FF91FD3
+:103240004193519302978D939C933AC0FD01A281C3
+:10325000B3811097C1F68091B5049091B604892B83
+:1032600041F480915001909151019093B604809364
+:10327000B50420915201309153012115310541F4DB
+:103280002DB73EB780914E0190914F01281B390B0D
+:10329000E091B504F091B6042E1B3F0B24173507BF
+:1032A00088F0CA0102962817390760F0CF01840F11
+:1032B000951F02969093B6048093B5044193519361
+:1032C000CF0102C080E090E0DF91CF910895CF93CD
+:1032D000DF93009709F44EC0EC0122971B821A82FB
+:1032E000A091B704B091B804109711F140E050E0FC
+:1032F00001C0DC01AC17BD0700F1BB83AA83FE014E
+:1033000021913191E20FF31FEA17FB0771F42E5F51
+:103310003F4F8D919C911197820F931F99838883C2
+:10332000FD01828193819B838A834115510559F464
+:10333000D093B804C093B7041DC0FD01828193816E
+:10334000AD010097B1F6FA01D383C2832191319187
+:10335000E20FF31FEC17FD0769F42E5F3F4F8881E2
+:103360009981820F931FFA01918380838A819B81C7
+:1033700093838283DF91CF91089597FB092E0726CF
+:103380000AD077FD04D027D006D000201AF470951B
+:1033900061957F4F0895F6F7909581959F4F089519
+:1033A00097FB092E05260ED057FD04D028D00AD051
+:1033B000001C38F450954095309521953F4F4F4F64
+:1033C0005F4F0895F6F790958095709561957F4FC2
+:1033D0008F4F9F4F0895AA1BBB1B51E107C0AA1F27
+:1033E000BB1FA617B70710F0A61BB70B881F991FA6
+:1033F0005A95A9F780959095BC01CD010895A1E259
+:103400001A2EAA1BBB1BFD010DC0AA1FBB1FEE1F5E
+:10341000FF1FA217B307E407F50720F0A21BB30BA9
+:10342000E40BF50B661F771F881F991F1A9469F725
+:1034300060957095809590959B01AC01BD01CF0181
+:023440000895ED
+:10344200456D62656464656450726F6A6563747326
+:10345200004F63746F70757355534220496E7465E3
+:10346200726661636520436F6E7665727465722061
+:10347200616E6420492F4F20457874656E73696FC1
+:103482006E0032303038313130380009040020000B
+:04349200B904000079
+:00000001FF
diff --git a/firmware/octopus.hex b/firmware/octopus.hex new file mode 100644 index 0000000..1dde146 --- /dev/null +++ b/firmware/octopus.hex @@ -0,0 +1,830 @@ +:100000000C94CA000C94E7000C94E7000C94E700F1
+:100010000C94E7000C94D8020C94E7000C94E700D1
+:100020000C94E7000C94E7000C94E7000C94E700B4
+:100030000C9483170C94E7000C94E7000C94E700F1
+:100040000C94B1020C94E7000C94E9000C94E700C6
+:100050000C94E7000C94E7000C94E7000C94E70084
+:100060000C94E7000C94E7000C94E7000C94E70074
+:100070000C94E7000C94E7000C94E7000C94E70064
+:100080000C94E7000C94E7000C94E7005D0D5F0D05
+:10009000610D630D650D670D690D6B0D6D0D6F0DB8
+:1000A000710D730D750D770D790D7B0D7D0D7F0D28
+:1000B000810DC30DC30DC30DC30DC30DC30D830D42
+:1000C000850D870D890D8B0D8D0D8F0D910D950D66
+:1000D000990D9F0DA30DA70DAB0DAF0DB50DB70D70
+:1000E000B90DBD0D0D0E0F0E110E130E150E170EC0
+:1000F000190E1B0E1D0E1F0E210E230E250E270E90
+:10010000290E2B0E2D0E2F0E310E730E730E730E45
+:10011000730E730E730E330E350E370E390E3B0E03
+:100120003D0E3F0E410E450E490E4F0E530E570E1B
+:100130005B0E5F0E650E670E690E6D0EAF0EB50E8F
+:10014000BB0EC10EC70ECD0ED30ED90EDF0EE50EBF
+:10015000EB0EF10EF70EFD0E030F090F0F0F150F2B
+:100160001B0FAC0EAC0EAC0EAC0EAC0EAC0E210FD9
+:10017000270F2D0F330F390F3F0F450F4B0F550F23
+:10018000610F6B0F750F7F0F890F930F9D0FA30FDB
+:10019000A90FAF0F11241FBECFEFD0E1DEBFCDBF3F
+:1001A00011E0A0E0B1E0E4E6F3E300E00BBF02C041
+:1001B00007900D92A435B107D9F714E0A4E5B1E09A
+:1001C00001C01D92A93BB107E1F70C94F3000C9418
+:1001D00000001F920F920FB60F9211240F900FBEC6
+:1001E0000F901F901895CCEFD0E1DEBFCDBF8FEF01
+:1001F00087BB88BBC7980E94270781E897E10E94C8
+:10020000720785E69CE00E94770781E090E00E94FB
+:100210007C07DE011196EBE4F1E083E001900D92A2
+:100220008150E1F7CE0101960E94710B80E091E0D0
+:100230000E940D0C81E191E00E94050C82E491E0A6
+:100240000E94FD0B0E94470B4C0164E670E00E9487
+:100250008A0760E070E0C4010E94B30A3C0140E0FC
+:1002600050E0BC01C4010E94AB0720ECA22E21E0AB
+:10027000B22ECC24DD2490E4E92EF12C02E021E022
+:1002800030E041E050E0B301C4010E94480A87E435
+:10029000A82E82E0B82E21E030E041E050E0B3012A
+:1002A000C4010E94800A0E94C1061092E1011092CE
+:1002B000E0011092E3011092E2010E943B0C8FEFEB
+:1002C00084BB8AEA85BB0E94FC0285ED85BB0E9447
+:1002D000FC0280E885BBFFCF0F931F93CF93DF9382
+:1002E000EC0181349105B0F08091EC019091ED0129
+:1002F000892B81F41092E9011092E801D093EB016F
+:10030000C093EA0181E090E09093ED018093EC01CD
+:10031000C0E4D0E068E08BE20E94100700E010E04B
+:100320000EC0E091E801F091E901E00FF11FEE5CF1
+:10033000FC4F608189E20E9410070F5F1F4F0C176E
+:100340001D0779F78091E0019091E101019749F44F
+:1003500067E08BE20E9410071092E1011092E00129
+:100360000AC063E08BE20E94100781E090E0909366
+:10037000E1018093E001DF91CF911F910F910895EA
+:100380008091EC019091ED01019771F52091E801C8
+:100390003091E9018091EA019091EB01281739072A
+:1003A00018F52091EA013091EB018091E8019091DC
+:1003B000E901281B390B8091E8019091E901805CEB
+:1003C0009F4F9093E9018093E801213431052CF08F
+:1003D00080E490E00E946C010895C9010E946C01C4
+:1003E0001092ED011092EC010895FC011092E901C8
+:1003F0001092E8011092ED011092EC010000C79AF2
+:100400002081822F82958F7099278230910511F17A
+:10041000833091052CF4009761F0019759F516C0CF
+:1004200084309105F9F084309105C4F0059711F5F9
+:100430001DC0263039F48281813039F5CF010E9408
+:10044000501723C0CF010E94B50C1FC0CF010E94DE
+:10045000DD111BC0CF010E94FB1217C0CF010E940B
+:100460003B1413C0CF010E946A150FC0CF010E9438
+:100470002E180BC02093320383E080933303109235
+:10048000340383E090E00E946C01C7980895CF93F5
+:10049000DF93EC018091E2019091E301019751F526
+:1004A00020E030E0E091E401F091E501E20FF31F7C
+:1004B000DE01A20FB31F8C91EE50FE4F80832F5FA1
+:1004C0003F4F2034310571F78091E4019091E501AF
+:1004D000805C9F4F9093E5018093E4012091E401BB
+:1004E0003091E5018091E6019091E70128173907E5
+:1004F000A8F11FC01092E5011092E40120E030E065
+:10050000E091E401F091E501E20FF31FDE01A20F9B
+:10051000B31F8C91EE50FE4F80832F5F3F4F2034EE
+:10052000310571F73093E5012093E401A981A034EE
+:1005300048F41092E3011092E20182EF91E00E94F0
+:10054000F5010CC081E090E09093E3018093E2011B
+:100550008A2F99279093E7018093E601DF91CF914D
+:1005600008951F920F920FB60F9211242F933F936D
+:100570004F935F936F937F938F939F93AF93BF93AB
+:10058000EF93FF930E94860C80915D0182BFFF91E3
+:10059000EF91BF91AF919F918F917F916F915F91FB
+:1005A0004F913F912F910F900FBE0F901F90189574
+:1005B0001F920F920FB60F9211242F933F934F93D8
+:1005C0005F936F937F938F939F93AF93BF93EF93BB
+:1005D000FF930E94150CFF91EF91BF91AF919F91F6
+:1005E0008F917F916F915F914F913F912F910F90DC
+:1005F0000FBE0F901F90189520E080E49CE90197B2
+:10060000F1F72F5F2931C9F70895FF920F931F93D8
+:10061000162F042FF22E9C01442737FD4095542FAE
+:1006200060E472E48FE090E00E9461192150304054
+:10063000163061F0173019F0153019F404C0E1E0FC
+:1006400003C0E1E004C0E0E070E002C0E0E071E07F
+:10065000053439F00F3419F451E041E004C050E0A2
+:1006600001C051E040E082E0F81611F462E001C000
+:1006700060E0832F992787FD9A958093900029B990
+:1006800088E18AB9770FEE0FEE0FE72B5295550FE1
+:10069000507E5E2B4295407F452B660F660F660F9E
+:1006A000642B609395001F910F91FF900895109215
+:1006B000900089E189B988E18AB986E08093950044
+:1006C000089508955D9BFECF8CB908955F9BFECF82
+:1006D0008CB1992708958A3310F4805301C087554F
+:1006E0006A3310F4605301C067556F708295807F44
+:1006F000682B862F99270895FC0104C05D9BFECFCF
+:1007000031968CB980818823C9F70895982F9295E6
+:100710009F708F709A3020F45D9BFECF905D03C078
+:100720005D9BFECF995A9CB98A3020F45D9BFECF29
+:10073000805D03C05D9BFECF895A8CB9089587E226
+:1007400080939A0485E28093990490E290939B04AD
+:1007500010929C0428E030E030939E0420939D0486
+:1007600083E28093A60481E28093A5049093A7047A
+:100770001092A8043093AA042093A9040895089520
+:100780006091B20481E20E941007089568E08BE254
+:100790000E94100761E188E20E94100768E08FE282
+:1007A0000E94100761E18CE20E94100761E08FE275
+:1007B0000E9410071092E1011092E00165E083E2CF
+:1007C0000E94100708950F931F938C0160E480E24C
+:1007D0000E941007F8016281605884E00E941007AF
+:1007E000F80182818093B1041F910F9108950F93B6
+:1007F0001F93CF93DF93EC012885398512161306DA
+:10080000DCF58E819F81821793071CF568E083E2F7
+:100810000E94100700E010E00FC08A859B85E80F5A
+:10082000F91F608181E20E9410078E819F810196ED
+:100830009F838E830F5F1F4FEE81FF81888599858F
+:10084000083011051CF4E817F9073CF3E817F9071D
+:1008500024F061E087E20E9410078B81813031F43F
+:1008600065E089810E9410071B8206C061E08981D2
+:100870000E94100781E08B83DF91CF911F910F9130
+:100880000895CF93DF93CDB7DEB724970FB6F894D2
+:10089000DEBF0FBECDBFDC01FC012281338110928F
+:1008A000AC041092AB0481E08093A804832F9927B5
+:1008B0008230D9F0833069F1813009F057C08091DE
+:1008C000850499279093AE048093AD0485E894E065
+:1008D0009093B0048093AF04868197818034910512
+:1008E00009F044C088E090E029C0FD01868197812D
+:1008F0009093AE048093AD04E22FFF27EE0FFF1F0D
+:100900008091970490919804E80FF91F808191815C
+:1009100029C02223C1F0E22FFF27EE0FFF1F809195
+:10092000F0019091F101E80FF91F0190F081E02DA5
+:10093000F093B004E093AF04808199279093AE04C4
+:100940008093AD0413C094E0998383E08A8389E0A7
+:100950008B839C8384E090E09093AE048093AD04FD
+:10096000CE0101969093B0048093AF0485EA94E0A1
+:100970000E94F70324960FB6F894DEBF0FBECDBFDA
+:10098000DF91CF910895CF93DF9382E20E94E70633
+:10099000C82FDD27C5FF1AC068E083E20E94100758
+:1009A000C6FF10C02091AB043091AC048091AD041F
+:1009B0009091AE04281739072CF485EA94E00E9440
+:1009C000F70304C061E087E20E941007DF91CF9136
+:1009D00008951F93CF93DF9388E00E94E706182FB6
+:1009E000C82FDD27C6FF18C060E085E00E94100711
+:1009F00060E884E00E94100760E080E20E94100737
+:100A000068E083E20E94100761E087E20E9410071D
+:100A100062E085E00E941007C4FF04C060EC89E03A
+:100A20000E94100717FF04C060ED89E00E941007C4
+:100A3000DF91CF911F9108958AE00E94E7069927E0
+:100A400080FF03C00E94C304089581FF0DC08AE2A5
+:100A50000E94E70680917204813061F4E091750490
+:100A6000F09176040995089582E30E94E7068AE3EF
+:100A70000E94E70608958EE00E94E70668E08FE294
+:100A80000E94100761E08FE20E9410072091AD04E0
+:100A90003091AE048091A9049091AA048217930723
+:100AA0005CF468E083E20E94100761E087E20E9444
+:100AB000100781E08093A8040895AF92BF92CF926F
+:100AC000DF92EF92FF920F931F93CF93DF93CDB7F7
+:100AD000DEB728970FB6F894DEBF0FBECDBF86E213
+:100AE0000E94E70686FF7EC08E010F5F1F4F5801F0
+:100AF00069E0C62ED12CCC0EDD1E809199040E9497
+:100B0000E706F80181938F017501EC15FD05A9F742
+:100B100068E087E20E94100768E083E20E94100705
+:100B200080E20E94E7068F77682F80E20E9410071C
+:100B300089819927807690708032910509F440C0B0
+:100B400080349105D1F1892BF1F5F5018181863051
+:100B5000D9F0873048F48130F1F18130C8F083302A
+:100B6000D1F1853081F521C0893019F18A3018F42E
+:100B7000883049F505C08A3071F18B3021F520C0ED
+:100B8000C5010E94C00327C0C5010E94410423C0C3
+:100B900068E083E20E94100761E081E20E94100792
+:100BA00060E081E20E9410070BC0C5010E94E303D0
+:100BB00012C0C5010E94C6030EC0C5010E94BF0637
+:100BC00065E083E206C080E20E94E7068058682F55
+:100BD00080E20E941007F70180818823D1F465E04C
+:100BE00083E215C02091AD043091AE048091A90438
+:100BF0009091AA048217930764F41092AE041092A5
+:100C0000AD0468E083E20E94100761E087E20E9481
+:100C1000100728960FB6F894DEBF0FBECDBFDF9148
+:100C2000CF911F910F91FF90EF90DF90CF90BF90E9
+:100C3000AF900895CF92DF92EF92FF920F931F93A0
+:100C4000CF93DF93CDB7DEB7C054D0400FB6F89442
+:100C5000DEBF0FBECDBF8CE00E94E706992780FF64
+:100C600003C00E945D057BC081FF2AC08EE20E9406
+:100C7000E7068DE20E94E70689838E010F5F1F4F12
+:100C80006801FFE3EF2EF12CE00EF11E0F5F1F4F06
+:100C90000E94D306F80180830E151F05B9F78091D5
+:100CA0005401813031F4E0915701F0915801C601AF
+:100CB000099568E08FE20E94100761E08FE22BC087
+:100CC00082FF2CC086E30E94E70685E30E94E706C8
+:100CD00089838E010F5F1F4F6801EFE3EE2EF12C29
+:100CE000E00EF11E0F5F1F4F0E94D306F8018083B4
+:100CF0000E151F05B9F780915501813031F4E0914F
+:100D00005901F0915A01C601099568E087E30E94F4
+:100D1000100761E087E30E94100721C083FF1FC016
+:100D20008EE30E94E7068E010F5F1F4F680171E49A
+:100D3000E72EF12CEC0EFD1E8DE30E94E706F80174
+:100D400081938F01EE15FF05B9F78091560181302F
+:100D500031F4E0915701F0915801C6010995C05C4A
+:100D6000DF4F0FB6F894DEBF0FBECDBFDF91CF913E
+:100D70001F910F91FF90EF90DF90CF90089508950D
+:100D8000089581E08ABF80E189BFE4E6F0E08081D8
+:100D900087608083E5E6F0E0808183608083A79AA6
+:100DA000AF9A7894089585B3805885BBE5E6F0E066
+:100DB000808122E0822780830000000089B395B300
+:100DC000905895BB908192279083992708959FEF23
+:100DD0009ABB8BBB85B3805885BBE5E6F0E080818C
+:100DE00095E08927808385B3805885BB80818927DA
+:100DF000808300001ABA0E94D306992708958BBBFE
+:100E000085B3805885BBE5E6F0E0808191E08927D5
+:100E1000808385B3805885BB80818927808308952E
+:100E20008BBB8FEF8ABB85B3805885BBE5E6F0E0CE
+:100E3000808195E08927808385B3805885BB808138
+:100E400089278083862F0E94FF060895089582E1F6
+:100E50008093850481E08093860480E191E0909303
+:100E60008804809387041092890410928A04109257
+:100E70008B0488E080938C0410928E0410928D0471
+:100E80001092900410928F04109292041092910488
+:100E90001092930410929404109295041092960468
+:100EA0001092540110925501109256011092720442
+:100EB000109273041092740410927C0410927B04BC
+:100EC0001092EF011092EE01089590938E0480939A
+:100ED0008D047093900460938F0450939204409318
+:100EE0009104089590938E0480938D0408959093B7
+:100EF000900480938F0408959093920480939104BA
+:100F0000089580938904089580938A0408958093B6
+:100F10008B040895CF93DF939C01CB01E0917B0478
+:100F2000F0917C0462E070E00E944E190FC0A08135
+:100F3000B1818281823039F4ED018D819927821748
+:100F4000930709F468870780F085E02D309779F7DB
+:100F5000DF91CF910895CF93DF939C01E0917B04C3
+:100F6000F0917C0414C0A081B1818281843061F44D
+:100F7000848199278217930739F4868199278617E8
+:100F8000970711F4ED014B830780F085E02D309732
+:100F900051F7DF91CF910895BF92CF92DF92EF92F8
+:100FA000FF920F931F93CF93DF936C01162FF42EB4
+:100FB000B22EC0917B04D0917C042097A1F489E0EB
+:100FC00090E00E945518FC0190937C0480937B0470
+:100FD000D182C082138310861782F282B482058385
+:100FE000E68215C0EC018F8198850097D9F789E0DA
+:100FF00090E00E945518FC0198878F83D182C082AF
+:101000001383F282B4820583E68210861782DF9111
+:10101000CF911F910F91FF90EF90DF90CF90BF90F5
+:101020000895EF92FF921F93CF93DF937C01C091BD
+:10103000EE01D091EF01209711F011E012C085E090
+:1010400090E00E945518FC019093EF018093EE010F
+:10105000F182E08212821482138210E012C01F5FBC
+:10106000EC018B819C810097D1F785E090E00E9494
+:101070005518FC019C838B83F182E08212831482D9
+:101080001382812F9927DF91CF911F91FF90EF90CD
+:101090000895EF92FF920F931F93CF93DF93E09108
+:1010A000EE01F091EF0180E090E00380F481E02D0B
+:1010B00001963097D1F7880F991F0E945518909389
+:1010C000F1018093F0010091EE011091EF01E80130
+:1010D000E880F9808A81C82FDD27CC0FDD1F809141
+:1010E000F0019091F101C80FD91FF7018081992774
+:1010F0000E9455189983888320E030E017C0E801EA
+:10110000EA81FF27EE0FFF1F8091F0019091F1011E
+:10111000E80FF91F0190F081E02DE20FF31FD701D6
+:10112000A20FB31F8C9180832F5F3F4FF701808107
+:101130009927281739071CF3E8018B819C810097B8
+:1011400011F08C01C4CFDF91CF911F910F91FF90CF
+:10115000EF9008954F925F926F927F928F929F923D
+:10116000AF92BF92CF92DF92EF92FF920F931F93B5
+:10117000CF93DF93E0917B04F0917C046624772485
+:1011800009C08281823019F40894611C711C0780A7
+:10119000F085E02D3097A9F74301880C991CC40114
+:1011A0000E9455189093980480939704E1E0EE2EE6
+:1011B000F12CAA24BB2455C0E0917B04F0917C045F
+:1011C00079E0C72ED12C15C0A081B18184819927E7
+:1011D0008E159F0519F48381C80ED11CED018D81F8
+:1011E0008E1521F48281823009F45D010780F0853B
+:1011F000E02D309749F70091970410919804025020
+:101200001040080D191DC6010E945518F801918360
+:10121000808320E030E0E0919704F0919804E80D9D
+:10122000F91D32970190F081E02DE20FF31FD501F7
+:10123000A20FB31F8C9180832F5F3F4F2930310560
+:1012400051F7E0919704F0919804E80DF91D329759
+:101250000190F081E02D8C2D875F82830894E11C42
+:10126000F11C6E147F040CF0A7CF61E0C62ED12CC8
+:1012700059E0A52EB12C4424552442E0842E912C13
+:10128000A1C0A0917B04B0917C0412C0ED91FC91AF
+:1012900011978181823049F4858199278C159D05AC
+:1012A00021F48481482E552405C0ED01AF81B88515
+:1012B000109761F731E0E32EF12C79C060917B0447
+:1012C00070917C046DC0FB01C081D1818981843023
+:1012D00009F063C0868199278E159F0509F05DC0CE
+:1012E000848199278C159D0509F057C0950140E030
+:1012F00050E0E0919704F0919804E80DF91D3297C1
+:101300000190F081E02DE20FF31FDE01A40FB51F65
+:101310008C9180832F5F3F4F4F5F5F4F4930510566
+:1013200041F789E090E0A80EB91EC0917B04D091EE
+:101330007C0431C08A81853059F58C8199278C15C0
+:101340009D0531F58D8199278E159F0509F5088139
+:101350001981950140E050E0E0919704F0919804E4
+:10136000E80DF91D32970190F081E02DE20FF31F97
+:10137000D801A40FB51F8C9180832F5F3F4F4F5F23
+:101380005F4F4730510541F7E7E0F0E0AE0EBF1E7A
+:101390000F80D885C02D209769F6EB016F81788585
+:1013A0006115710509F08FCF0894E11CF11C4E14F2
+:1013B0005F040CF083CF0894C11CD11CE2E0F0E084
+:1013C0008E0E9F1E6C147D040CF05BCFDF91CF91CD
+:1013D0001F910F91FF90EF90DF90CF90BF90AF9053
+:1013E0009F908F907F906F905F904F9008956F9235
+:1013F0007F928F929F92AF92BF92CF92DF92EF92A5
+:10140000FF920F93CF93DF935C013B014901E09181
+:101410007B04F0917C0416C0A081B181848199275E
+:10142000A816B90661F4868199278615970539F4BF
+:101430008281843021F4ED018C818F5F8C83078061
+:10144000F085E02D309741F787E090E00E94551835
+:10145000FC0187E0808385E0818382820383F582BB
+:10146000E482C682EE24062D2A2D45E067E0CF01F6
+:101470000E94CC07DF91CF910F91FF90EF90DF900A
+:10148000CF90BF90AF909F908F907F906F90089576
+:10149000AF92BF92CF92DF92EF92FF920F93FC0137
+:1014A000A114B10401F14230510571F043305105EE
+:1014B00099F041305105B9F481E080937204B09203
+:1014C0007604A09275040FC081E080937304B092FB
+:1014D0007804A092770407C081E080937404B092EE
+:1014E0007A04A092790420583F4FCF010E94F70957
+:1014F0000F91FF90EF90DF90CF90BF90AF90089545
+:10150000AF92BF92CF92DF92EF92FF920F93FC01C6
+:101510004230510571F04330510599F04130510589
+:10152000B9F481E080935401B0925801A092570120
+:101530000FC081E080935501B0925A01A0925901E9
+:1015400007C081E080935601B0925C01A0925B01DC
+:10155000CF010E94F7090F91FF90EF90DF90CF909D
+:10156000BF90AF900895CF92DF92EF920F931F93A9
+:10157000CF93DF936C018B01A0917B04B0917C042D
+:10158000C0E0D0E014C02D913C911197F901858104
+:101590008C1551F4FD018281823031F4F90184818E
+:1015A0008F5F8483C82FDD27FD01A781B085109749
+:1015B00051F789E090E00E945518FC0189E0808392
+:1015C00084E081830283138214821582168217823B
+:1015D0001086EC2E00E02C2D44E069E0CF010E9443
+:1015E000CC07CE01DF91CF911F910F91EF90DF904B
+:1015F000CF900895BF92CF92DF92EF92FF920F9318
+:101600001F93CF93DF936C017B01142FB22EA09117
+:101610007B04B0917C04C0E0D0E014C02D913C91DB
+:101620001197F90185818C1551F4FD018281823079
+:1016300031F4F90184818F5F8483C82FDD27FD0198
+:10164000A781B085109751F789E090E00E94551866
+:10165000FC0189E0808384E08183E282138214822A
+:101660001583B68207831086EC2E00E02C2D44E013
+:1016700069E0CF010E94CC07CE01DF91CF911F918D
+:101680000F91FF90EF90DF90CF90BF900895EF9271
+:101690000F931F93109196041F5F1093960489E097
+:1016A00090E00E945518FC0189E0808389E090E079
+:1016B0009383828382E0818314821583168280EA79
+:1016C00087838AE18087EE2400E020E042E069E041
+:1016D000CF010E94CC07812F99271F910F91EF9086
+:1016E0000895CF93DF93EC01FC0101900020E9F70E
+:1016F000E81BF90BCF01880F991F0E9455189C0118
+:10170000FE0101900020E9F7EC1BFD0BEE0FFF1F1F
+:10171000DC01EC9383E0F901818340E050E009C0F3
+:10172000FE01E40FF51F80818C93FD0111824F5F54
+:101730005F4F1296FE0101900020E9F73197EC1BF4
+:10174000FD0B4E175F0760F3C9010E94110899272E
+:10175000DF91CF910895EF92FF920F931F93CF9354
+:10176000DF938C017B01CA010E94710B9C01E09107
+:101770007B04F0917C0414C0A081B181828184300B
+:1017800061F4848199278017910739F4868199271C
+:101790008E159F0511F4ED0128870780F085E02D57
+:1017A000309751F7DF91CF911F910F91FF90EF90FC
+:1017B00008950F931F93CF93DF938C01CB010E9469
+:1017C000710B9C01E0917B04F0917C040FC0A0811F
+:1017D000B1818281823039F4ED018D8199278017A2
+:1017E000910709F42E830780F085E02D309779F773
+:1017F000DF91CF911F910F9108950E94710B1816E0
+:10180000190614F48093950408950E94710B18161C
+:10181000190614F48093940408950E94710B18160D
+:10182000190614F48093930408951F9386E00E9490
+:10183000E706992786FF03C00E941A060EC082FFA2
+:1018400003C00E941C0509C081FF03C00E94E90477
+:1018500004C084FF02C00E943B0587E00E94E706A7
+:10186000182F60E087E00E941007612F87E00E9438
+:1018700010071F9108950E94AA080E9449080E941B
+:101880009F0361E080E00E94100780E00E94E7066D
+:1018900080FDFBCF62E081E00E94100760E884E0F9
+:1018A0000E94100760E480E20E94100768E083E273
+:1018B0000E94100769E087E20E9410076FE08DE048
+:1018C0000E9410076FE08BE00E94100768ED89E02E
+:1018D0000E94100763E38FE00E94100766ED87E027
+:1018E0000E94100762E085E00E9410076CEC80E027
+:1018F0000E94100708958EEC80935D0181E087BF00
+:1019000080915D0182BF83E083BF089508950895AB
+:1019100083E08093320381E0809333038BE08093F4
+:1019200034039FE69093350383E68093360384E780
+:10193000809337039093380380E78093390385E7DA
+:1019400080933A0383E780933B038FE580933C03C6
+:1019500080E380933D0381E380933E0310923F0335
+:101960008EE090E00E946C010895FC01808183303C
+:1019700011F40E94880C0895CF93DF93C1E0D0E06A
+:10198000CE010E94D20D2196C431D105C9F7CAE11A
+:10199000D0E0CE010E94D20D2196CD32D105C9F7FB
+:1019A000DF91CF910895CF93DF93DC01EC01EA81C1
+:1019B000FB8121918E81815019F48981E81BF10905
+:1019C000ED01FB83EA838E839FB7F8948C9181505D
+:1019D0008C939FBF822F9927DF91CF910895FC01AF
+:1019E0001082758364837383628341834783468354
+:1019F0000895CF93DF93DC019C91ED0189819817C5
+:101A000018F080E090E016C0ED01EC81FD8161935B
+:101A10008F81815019F48981E81BF109ED018F83D1
+:101A2000FD83EC839FB7F8948C918F5F8C939FBF5D
+:101A300081E090E0DF91CF910895FC0180818823BF
+:101A4000E9F3CF010E94D30C99270895FC0180810E
+:101A5000882319F48FEF9FEF0895CF010E94D30CD4
+:101A6000992708950895CF93DF93CDB7DEB72297D6
+:101A70000FB6F894DEBF0FBECDBF9C010197439710
+:101A800028F0C9014A97439708F07DC0F901EE0F8D
+:101A9000FF1FE35AFE4F82E090E092838183F901B9
+:101AA0003197EC32F10508F06EC0EA5BFF4FEE0FA4
+:101AB000FF1F0590F491E02D0994159A5BC0169ACA
+:101AC0005DC0179A57C0B89A59C0B99A53C0BA9A0C
+:101AD00055C0BB9A4FC0BC9A51C0BD9A4BC0BE9A6C
+:101AE0004DC0BF9A47C0889A49C0899A43C08A9A14
+:101AF00045C08B9A3FC08C9A41C08D9A3BC08E9A4C
+:101B00003DC08F9A37C0A09A39C0A19A33C0A29A1B
+:101B100035C0A39A2FC0A49A31C0A59A2BC0A69A0B
+:101B20002DC080916100806807C080916100806451
+:101B300019C0809161008062809361001BC0809118
+:101B4000610080610FC0809161008860F5CF809155
+:101B50006100846007C0809161008260EDCF809158
+:101B6000610081608093610009C0109A03C0119ADE
+:101B700005C0129A81E090E008C0139AE1E0F0E01D
+:101B8000FA83E98304C084E090E09A8389838981A1
+:101B90009A8122960FB6F894DEBF0FBECDBFDF91BB
+:101BA000CF9108959C010197439738F0C9014A9756
+:101BB000439718F084E090E00895C9010E94330D26
+:101BC00081E090E00895CF93DF93CDB7DEB7229701
+:101BD0000FB6F894DEBF0FBECDBF9C0101974397AF
+:101BE00028F0C9014A97439708F07DC0F901EE0F2C
+:101BF000FF1FE35AFE4F81E090E092838183F90159
+:101C00003197EC32F10508F06EC0EE58FF4FEE0F41
+:101C1000FF1F0590F491E02D099415985BC016986C
+:101C20005DC0179857C0B89859C0B99853C0BA98B2
+:101C300055C0BB984FC0BC9851C0BD984BC0BE9812
+:101C40004DC0BF9847C0889849C0899843C08A98BA
+:101C500045C08B983FC08C9841C08D983BC08E98F2
+:101C60003DC08F9837C0A09839C0A19833C0A298C2
+:101C700035C0A3982FC0A49831C0A5982BC0A698B2
+:101C80002DC0809161008F7707C0809161008F7BAC
+:101C900019C0809161008F7D809361001BC080918D
+:101CA00061008F7E0FC080916100877FF5CF8091AA
+:101CB00061008B7F07C0809161008D7FEDCF8091A7
+:101CC00061008E7F8093610009C0109803C0119855
+:101CD00005C0129881E090E008C01398E1E0F0E0C0
+:101CE000FA83E98304C084E090E09A838983898140
+:101CF0009A8122960FB6F894DEBF0FBECDBFDF915A
+:101D0000CF91089580E090E0089580E090E00895FC
+:101D100080E090E008950895089508950895089545
+:101D2000089508959C01FC01EE0FFF1FE35AFE4F3A
+:101D300081819281029719F085E090E00895F90180
+:101D40003197EC32F10540F4E256FF4FEE0FFF1FE2
+:101D50000590F491E02D099484E090E00895672BBC
+:101D600011F01D9AFFC01D98FDC0672B11F01E9A3F
+:101D7000F9C01E98F7C0672B11F01F9AF3C01F9887
+:101D8000F1C0672B11F0C09AEDC0C098EBC0672B73
+:101D900011F0C19AE7C0C198E5C0672B11F0C29A53
+:101DA000E1C0C298DFC0672B11F0C39ADBC0C398B3
+:101DB000D9C0672B11F0C49AD5C0C498D3C0672B83
+:101DC00011F0C59ACFC0C598CDC0672B11F0C69A47
+:101DD000C9C0C698C7C0672B11F0C79AC3C0C798BF
+:101DE000C1C0672B11F0909ABDC09098BBC0672B03
+:101DF00011F0919AB7C09198B5C0672B11F0929AE3
+:101E0000B1C09298AFC0672B11F0939AABC0939872
+:101E1000A9C0672B11F0949AA5C09498A3C0672B12
+:101E200011F0959A9FC095989DC0672B11F0969AD6
+:101E300099C0969897C0672B11F0979A93C097987E
+:101E400091C0672B11F0A89A8DC0A8988BC0672B02
+:101E500011F0A99A87C0A99885C0672B11F0AA9A9A
+:101E600081C0AA987FC0672B11F0AB9A7BC0AB985A
+:101E700079C0672B11F0AC9A75C0AC9873C0672B12
+:101E800011F0AD9A6FC0AD986DC0672B11F0AE9A8E
+:101E900069C0AE9867C0672B21F0809162008068AE
+:101EA0000DC0809162008F7709C0672B21F080916F
+:101EB0006200806403C0809162008F7B8093620027
+:101EC00051C0672B21F0809162008062F7CF809132
+:101ED00062008F7DF3CF672B21F0809162008061DB
+:101EE000EDCF809162008F7EE9CF672B21F080914A
+:101EF00062008860E3CF80916200877FDFCF672B2D
+:101F000021F0809162008460D9CF809162008B7F44
+:101F1000D5CF672B21F0809162008260CFCF809176
+:101F200062008D7FCBCF672B21F0809162008160B2
+:101F3000C5CF809162008E7FC1CF672B11F0189AB8
+:101F400011C018980FC0672B11F0199A0BC019987F
+:101F500009C0672B11F01A9A05C01A9803C0672BA5
+:101F600021F01B9A81E090E008951B9881E090E0B9
+:101F70000895CF93DF93EC010197439738F0CE019A
+:101F80004A97439718F084E090E013C0FE01EE0FEB
+:101F9000FF1FE35AFE4F83E090E092838183CE01DE
+:101FA0000E94330D61E070E0CE010E94920E81E04C
+:101FB00090E0DF91CF91089508959C01DB01119687
+:101FC0001C921E92FC01EE0FFF1FE35AFE4F81810F
+:101FD00092818130910519F085E090E008952130DB
+:101FE000310531F4859B28C011963C932E9324C073
+:101FF0002230310531F4869B2AC011969C938E9332
+:1020000026C02330310531F40F9B2CC011969C93D0
+:102010008E9328C02430310531F4B09B2EC0119628
+:102020009C938E932AC02530310531F4B19B30C08A
+:1020300011969C938E932CC02630310541F4B29BAF
+:1020400032C081E090E011969C938E932CC0273093
+:10205000310541F4B39B32C081E090E011969C932E
+:102060008E932CC02830310541F4B49B32C081E0FE
+:1020700090E011969C938E932CC02930310541F449
+:10208000B59B32C081E090E011969C938E932CC05A
+:102090002A30310541F4B69B32C081E090E01196C0
+:1020A0009C938E932CC02B30310541F4B79B32C0EA
+:1020B00081E090E011969C938E932CC02C303105DA
+:1020C00041F4809B32C081E090E011969C938E9306
+:1020D0002CC02D30310541F4819B32C081E090E06D
+:1020E00011969C938E932CC02E30310541F4829B27
+:1020F00032C081E090E011969C938E932CC02F30DB
+:10210000310541F4839B32C081E090E011969C93AD
+:102110008E932CC02031310541F4849B32C081E084
+:1021200090E011969C938E932CC02131310541F49F
+:10213000859B32C081E090E011969C938E932CC0D9
+:102140002231310541F4869B32C081E090E0119646
+:102150009C938E932CC02331310541F4879B32C070
+:1021600081E090E011969C938E932CC02A3131052A
+:1021700041F4809B32C081E090E011969C938E9355
+:102180002CC02B31310541F4999B32C081E090E0A5
+:1021900011969C938E932CC02C31310541F49A9B5F
+:1021A00032C081E090E011969C938E932CC02D312B
+:1021B000310541F49B9B32C081E090E011969C93E5
+:1021C0008E932CC02E31310541F49C9B32C081E0AE
+:1021D00090E011969C938E932CC02F31310541F4E1
+:1021E0009D9B32C081E090E011969C938E932CC011
+:1021F0002032310541F49E9B32C081E090E011967F
+:102200009C938E932CC02132310541F4079B32C040
+:1022100081E090E011969C938E932CC02232310580
+:1022200041F4069B32C081E090E011969C938E931E
+:102230002CC02332310541F4059B32C081E090E08F
+:1022400011969C938E932CC02432310541F4049B4B
+:102250002AC081E090E011969C938E9324C0253291
+:10226000310541F4039B25C081E090E011969C93D9
+:102270008E931FC02632310541F4029B20C081E0BD
+:1022800090E011969C938E931AC02732310541F449
+:10229000019B1BC081E090E011969C938E9315C02A
+:1022A0002832310519F02932310519F4809B17C005
+:1022B00011C02A32310519F4099B11C00BC02B3211
+:1022C000310519F40A9B0BC005C02C32310539F4D5
+:1022D0000B9B05C081E090E08D939C93089581E075
+:1022E00090E008950895CF93DF93CDB7DEB722979E
+:1022F0000FB6F894DEBF0FBECDBF2BE120933203A3
+:10230000BE016F5F7F4F0E94DD0F80933303898191
+:102310008093340383E090E00E946C0122960FB614
+:10232000F894DEBF0FBECDBFDF91CF9108952AE1B3
+:10233000209332030E94920E809333031092340351
+:1023400083E090E00E946C01089527E1209332031E
+:102350000E94B90F809333031092340383E090E01E
+:102360000E946C01089525E1209332030E94E30D41
+:10237000809333031092340383E090E00E946C0159
+:10238000089526E1209332030E94330D8093330396
+:102390001092340383E090E00E946C01089521E1E3
+:1023A000209332030E94D20D8093330310923403A2
+:1023B00083E090E00E946C010895FC0180818631E9
+:1023C000E9F0873138F48531A0F48231C0F58031ED
+:1023D00058F10AC08A3118F4883188F514C08A315E
+:1023E000B9F08B3109F51BC0828199270E94CF116A
+:1023F0000895828199270E94B311089582819927B7
+:102400000E94C1110895828199270E94B90F0895F1
+:1024100063817727828199270E949711089582818D
+:1024200099270E94731108958093320383E080936B
+:1024300033031092340383E090E00E946C0108950E
+:10244000FC018197089718F084E090E00895EE0F62
+:10245000FF1FE35AFE4F84E090E09283818381E086
+:1024600090E0089517B88230910541F083309105CE
+:1024700049F0019721F082E090E008953E9A81E0D2
+:1024800090E0089587B1806C87B981E090E008956D
+:1024900093E896B997B1907F982B97B9369A369969
+:1024A000FECF84B195B120E030E040E050E0369AB4
+:1024B0003699FECF84B195B1480F591F2F5F3F4F1A
+:1024C00024303105A1F73798CA01969587959695DE
+:1024D00087950895CF93DF939C01EB0119821882B1
+:1024E000FC01EE0FFF1FE35AFE4F8181928104979A
+:1024F000D1F52432310559F12532310554F4223217
+:10250000310559F1233231052CF52132310559F5C8
+:1025100027C026323105A9F026323105ACF027322A
+:10252000310531F028323105F1F480E090E002C04D
+:1025300081E090E00E9448129983888381E090E0D6
+:1025400014C082E090E0F6CF83E090E0F3CF84E027
+:1025500090E0F0CF85E090E0EDCF86E090E0EACF2C
+:1025600087E090E0E7CF85E090E0DF91CF9108959C
+:1025700022E2209332030E9432128093330382E0DE
+:1025800090E00E946C010895CF93DF93CDB7DEB742
+:1025900022970FB6F894DEBF0FBECDBF21E2209385
+:1025A0003203BE016F5F7F4F0E946A128093330334
+:1025B00029813A81832F992780933403209335030F
+:1025C00084E090E00E946C0122960FB6F894DEBF82
+:1025D0000FBECDBFDF91CF91089520E2209332034B
+:1025E0000E942012809333031092340383E090E022
+:1025F0000E946C010895FC018081813249F0823291
+:1026000061F0803279F4828199270E94ED12089559
+:10261000828199270E94C4120895828199270E947D
+:10262000B81208958093320383E0809333031092AD
+:10263000340383E090E00E946C0108958091710062
+:102640009927887F907008958091740087FFFCCF50
+:102650000895E4E7F0E08081846080838BE090E07F
+:1026600090937701809376018CE090E090937901CC
+:102670008093780181E090E00895E4E7F0E08081C4
+:102680008B7F808382E090E0909377018093760146
+:10269000909379018093780108958130910511F428
+:1026A0008CE00BC08230910511F488E106C00397DD
+:1026B00019F082E090E0089588E4809370008091A2
+:1026C00071008C7F80937100809171008093710004
+:1026D00081E090E008958091710084EA8093740015
+:1026E0008091740087FFFCCF81E090E0089584E939
+:1026F0008093740081E090E008958093730084E8F3
+:10270000809374008091740087FFFCCF80E090E09C
+:10271000089584E8809374008091740087FFFCCF53
+:10272000809173009927089585E38093320381E0B7
+:10273000809333038093340384E880937400809102
+:10274000740087FFFCCF809173008093350385E090
+:1027500090E00E946C01089540E050E00FC0F90144
+:10276000E40FF51F80818093730084E880937400E8
+:102770008091740087FFFCCF4F5F5F4F461757076C
+:1027800074F384E38093320381E0809333031092E7
+:10279000340383E090E00E946C01089587E3809306
+:1027A000320384E98093740081E0809333031092B4
+:1027B000340383E090E00E946C01089586E38093E7
+:1027C00032038091710084EA8093740080917400D8
+:1027D00087FFFCCF81E0809333031092340383E0C2
+:1027E00090E00E946C01089522E3209332030E943E
+:1027F0004D13809333031092340383E090E00E94E2
+:102800006C01089581E380933203E4E7F0E0808176
+:102810008B7F808382E090E09093770180937601B4
+:1028200090937901809378011092330310923403CE
+:1028300083E090E00E946C01089580E3809332036E
+:10284000E4E7F0E08081846080838BE090E0909307
+:102850007701809376018CE090E0909379018093EA
+:10286000780181E0809333031092340383E090E099
+:102870000E946C010895FC0180818433D9F0853376
+:1028800038F4813379F0823381F0803389F507C0E1
+:10289000863341F18633D8F0873351F526C00E9444
+:1028A0001D1408950E9402140895828199270E94A0
+:1028B000F413089542815527618177276450704051
+:1028C000838134969F0199270E94AC130895428119
+:1028D00055276181772764507040838199270E9432
+:1028E000941308950E94DE1308950E94CE13089554
+:1028F0008093320383E0809333031092340383E0A8
+:1029000090E00E946C01089588B3817F88BBBB98DA
+:1029100086E087BB1DB81EB883E58DB988E090E0DE
+:1029200090936901809368018AE090E090936B0135
+:1029300080936A0189E090E090936D0180936C012F
+:1029400081E090E008951DB81EB882E090E0909379
+:1029500069018093680190936B0180936A01909361
+:102960006D0180936C0181E090E00895089581E00D
+:1029700090E00895AC0120E030E009C0FA01E20FD8
+:10298000F31F80818FB9779BFECF2F5F3F4F2617B4
+:102990003707A4F381E090E00895DC0120E030E007
+:1029A00040E050E014C01FB809C04F5F5F4F83E0A4
+:1029B000493E58071CF086E090E00895779BF5CFDC
+:1029C000FD01E20FF31F8FB180832F5F3F4F26176A
+:1029D00037074CF381E090E00895CF93DF93EC014B
+:1029E00020E030E0A0E0B0E017C0FE01E20FF31FEE
+:1029F00080818FB908C0119683E0A93EB8071CF00A
+:102A000086E090E00EC0779BF6CFFB01E20FF31F4C
+:102A10008FB180832F5F3F4F2417350734F381E058
+:102A200090E0DF91CF9108950F931F938B0123E4E2
+:102A300020933203AB0164E373E00E94ED148093B2
+:102A4000330310923403C80102960E946C011F9157
+:102A50000F9108950F931F938C0184E480933203A8
+:102A6000B80184E393E00E94CD1480933303109265
+:102A70003403C80102960E946C011F910F910895C2
+:102A800023E4209332030E94BA14809333031092FC
+:102A9000340383E090E00E946C01089581E4809308
+:102AA00032030E94A314809333031092340383E013
+:102AB00090E00E946C01089580E4809332030E94AC
+:102AC0008414809333031092350383E090E00E94D6
+:102AD0006C010895CF93DF93EC0188818334A1F0DA
+:102AE000843438F4813469F0823458F58034F1F458
+:102AF00005C0843481F08534C9F411C00E945C158E
+:102B000020C00E944E151DC069817727CE01029614
+:102B10000E94401516C0898199270E942A15698153
+:102B20007727CE0102960E9414150BC080933203C2
+:102B300083E0809333031092340383E090E00E949B
+:102B40006C01DF91CF910895B89AB99ABA9ABB985F
+:102B5000BC9ABD9AC498C59882E090E09093850194
+:102B600080938401909383018093820190938101EB
+:102B70008093800181E090E090937F0180937E01BB
+:102B8000089582E090E090936901809368019093AA
+:102B90006B0180936A0190936D0180936C0181E0D9
+:102BA00090E00895C098C198C29880E29EE4019791
+:102BB000F1F7C09A8AE0982F9A95F1F7C29AC19AD4
+:102BC0008A95F1F70895282FC19887FD02C0C29811
+:102BD00001C0C29A8AE0982F9A95F1F7C19A8A9516
+:102BE000F1F7C19826FF02C0C29A01C0C2988AE0DC
+:102BF000982F9A95F1F7C19A8A95F1F70895282FA1
+:102C0000220F30E0C19827FF02C0C29A01C0C298CB
+:102C10008AE0982F9A95F1F7C19A8A95F1F73F5F6C
+:102C2000373011F0220FEECF0895282F30E0C198F1
+:102C300027FF02C0C29A01C0C2988AE0982F9A95D5
+:102C4000F1F7C19A8A95F1F73F5F383011F0220F02
+:102C5000EECF0895C198C2988AE0982F9A95F1F71F
+:102C6000C19A982F9A95F1F7C198C098982F9A9584
+:102C7000F1F7C19A982F9A95F1F7C1988A95F1F7D3
+:102C8000C09A80E090E00895C198C098C298C39A15
+:102C900008950E94D21580E30E94E31580E60E9409
+:102CA000FF1508950E94D21580E00E94E31580E090
+:102CB0000E94FF150E94441608950F931F93182F2A
+:102CC000062F0E94D21580E40E94E315812F0E94F6
+:102CD000FF15802F0E94151681E090E01F910F9143
+:102CE00008951F93182F0E94D21580EC0E94E315BF
+:102CF000812F0E94FF150E942A1699271F9108957F
+:102D0000C1988AE08A95F1F7C29830E090E0990F77
+:102D1000C19A2AE0822F8A95F1F7C198B3999F5FF3
+:102D2000822F8A95F1F73F5F383089F7C098C19AB2
+:102D3000822F8A95F1F7C09AC1982A95F1F7892FC9
+:102D4000992708951F93182F0E94D21580E80E949A
+:102D5000E315812F0E94FF150E94801699271F916D
+:102D60000895DF92EF92FF920F931F93CF93DF931B
+:102D7000D82E7B018A01C0E0D0E009C08D2D8C0FD8
+:102D80000E94A216F801EC0FFD1F80832196CE153C
+:102D9000DF05A1F781E090E0DF91CF911F910F91C6
+:102DA000FF90EF90DF9008950F931F93082F162F39
+:102DB0000E944916612F802F0E945D1681E090E0ED
+:102DC0001F910F910895DF92EF92FF920F931F933F
+:102DD000CF93DF93D82E7B018A01C0E0D0E009C0F9
+:102DE000F801EC0FFD1F60818D2D8C0F0E94D41611
+:102DF0002196CE15DF05A1F781E090E0DF91CF911C
+:102E00001F910F91FF90EF90DF90089594E09093C1
+:102E100032030E94E316809333031092340383E05D
+:102E200090E00E946C0108950F931F938B0193E033
+:102E30009093320344E353E00E94B116809333032E
+:102E4000C80102960E946C011F910F91089582E0C3
+:102E50008093320382E090E090936901809368014F
+:102E600090936B0180936A0190936D0180936C0144
+:102E700081E0809333031092340383E090E00E945A
+:102E80006C01089581E0809332030E94A415809321
+:102E900033031092340383E090E00E946C010895A4
+:102EA000FC018381823069F0833018F48130F1F4C1
+:102EB00005C0833049F08430C9F40FC00E94421726
+:102EC00008950E9427170895AF014A5F5F4F6581FB
+:102ED000772784810E9414170895AF014A5F5F4FDE
+:102EE0006581772784810E940617089580818093E9
+:102EF000320383E0809333031092340383E090E045
+:102F00000E946C0108951F920F920FB60F92112428
+:102F10008F939F938091B3049091B4049BBD8ABD1D
+:102F20009F918F910F900FBE0F901F901895FC01ED
+:102F30000897029718F084E090E00895EE0FFF1FC5
+:102F4000E35AFE4F8DE090E09283818381E090E030
+:102F500008959C01FC01EE0FFF1FE35AFE4F818193
+:102F600092810D97F1F428303105F1F029303105C7
+:102F7000C1F48091B3049091B404892B31F480E8BA
+:102F800090E09093B4048093B3046130710561F4D0
+:102F90008FB5816A8FBD8EB581608EBD81E090E076
+:102FA000089585E090E0089581E090E008959C0107
+:102FB000FC01EE0FFF1FE35AFE4F818192810D97B6
+:102FC00059F42830310529F02930310529F47BBD29
+:102FD0006ABD81E090E0089585E090E008959C014D
+:102FE00082E580933203F901EE0FFF1FE35AFE4F93
+:102FF000818192810D9759F42830310529F02930CB
+:10300000310529F47BBD6ABD81E090E002C085E016
+:1030100090E0809333031092340383E090E00E94A9
+:103020006C01089521E5209332030E94A917809333
+:1030300033031092340383E090E00E946C01089502
+:1030400020E5209332030E94971780933303109258
+:10305000340383E090E00E946C010895FC018081BC
+:10306000813549F0823571F0803599F48281992754
+:103070000E942018089563817727828199270E94F2
+:103080001218089563817727828199270E94EF178C
+:1030900008958093320383E08093330310923403C6
+:1030A00083E090E00E946C010895CF93DF93AC0120
+:1030B000029710F442E050E0A091B704B091B80438
+:1030C000FD01C0E0D0E020E030E020C080819181AF
+:1030D0008417950769F482819381209719F09B8367
+:1030E0008A8304C09093B8048093B704CF0132C0A0
+:1030F0004817590738F42115310519F0821793073D
+:1031000008F49C01EF010280F381E02D3097F1F685
+:103110002115310589F1C901841B950B049708F429
+:10312000A901E0E0F0E026C08D919C9111978217F3
+:103130009307E9F44817590779F4ED018A819B81D7
+:10314000309719F09383828304C09093B8048093DE
+:10315000B704CD01029649C0841B950BFD01E80F11
+:10316000F91F4193519302978D939C933AC0FD01AF
+:10317000A281B3811097C1F68091B5049091B604F5
+:10318000892B41F480915001909151019093B604A4
+:103190008093B504209152013091530121153105DE
+:1031A00041F42DB73EB780914E0190914F01281BFD
+:1031B000390BE091B504F091B6042E1B3F0B241798
+:1031C000350788F0CA0102962817390760F0CF0149
+:1031D000840F951F02969093B6048093B504419393
+:1031E0005193CF0102C080E090E0DF91CF9108952C
+:1031F000CF93DF93009709F44EC0EC0122971B8216
+:103200001A82A091B704B091B804109711F140E070
+:1032100050E001C0DC01AC17BD0700F1BB83AA83FD
+:10322000FE0121913191E20FF31FEA17FB0771F4C0
+:103230002E5F3F4F8D919C911197820F931F998321
+:103240008883FD01828193819B838A834115510587
+:1032500059F4D093B804C093B7041DC0FD01828116
+:103260009381AD010097B1F6FA01D383C283219116
+:103270003191E20FF31FEC17FD0769F42E5F3F4F0A
+:1032800088819981820F931FFA01918380838A81BB
+:103290009B8193838283DF91CF91089597FB092EC1
+:1032A00007260AD077FD04D027D006D000201AF4D4
+:1032B000709561957F4F0895F6F7909581959F4F92
+:1032C000089597FB092E05260ED057FD04D028D06F
+:1032D0000AD0001C38F450954095309521953F4F09
+:1032E0004F4F5F4F0895F6F79095809570956195D3
+:1032F0007F4F8F4F9F4F0895AA1BBB1B51E107C003
+:10330000AA1FBB1FA617B70710F0A61BB70B881F75
+:10331000991F5A95A9F780959095BC01CD01089504
+:10332000A1E21A2EAA1BBB1BFD010DC0AA1FBB1FC9
+:10333000EE1FFF1FA217B307E407F50720F0A21B3B
+:10334000B30BE40BF50B661F771F881F991F1A94A8
+:1033500069F760957095809590959B01AC01BD01D2
+:04336000CF010895FC
+:10336400456D62656464656450726F6A6563747305
+:10337400004F63746F70757355534220496E7465C2
+:10338400726661636520436F6E7665727465722040
+:10339400616E6420492F4F20457874656E73696FA0
+:1033A4006E003230303831313038000904002000EA
+:0433B400B904000058
+:00000001FF
diff --git a/firmware/octopus_can.hex b/firmware/octopus_can.hex new file mode 100644 index 0000000..aa546f0 --- /dev/null +++ b/firmware/octopus_can.hex @@ -0,0 +1,842 @@ +:100000000C94FA000C9417010C9417010C9417012E
+:100010000C9417010C9408030C9417010C9417010D
+:100020000C9417010C9417010C9417010C941701F0
+:100030000C9475170C9417010C9417010C9417016C
+:100040000C9417010C94E1020C9417010C94170105
+:100050000C9417010C9419010C9417010C941701BE
+:100060000C9417010C9417010C9417010C941701B0
+:100070000C9417010C9417010C9417010C941701A0
+:100080000C9417010C9417010C9417010C94170190
+:100090000C941701AA0DAC0DAE0DB00DB20DB40D40
+:1000A000B60DB80DBA0DBC0DBE0DC00DC20DC40D00
+:1000B000C60DC80DCA0DCC0DCE0DFC0DFC0DFC0DF2
+:1000C000FC0DFC0DFC0DD00DD20DD40DD60DD80DB0
+:1000D000DA0DDC0DDE0DE00DE20DE40DE60DE80DB0
+:1000E000EA0DEC0DEE0DF00DF20DF60D490E4B0E76
+:1000F0004D0E4F0E510E530E550E570E590E5B0EF0
+:100100005D0E5F0E610E630E650E670E690E6B0E5F
+:100110006D0E9B0E9B0E9B0E9B0E9B0E9B0E6F0EF1
+:10012000710E730E750E770E790E7B0E7D0E7F0E9F
+:10013000810E830E850E870E890E8B0E8D0E8F0E0F
+:10014000910E950E090F0F0F150F1B0F210F270F83
+:100150002D0F330F390F3F0F450F4B0F510F570F17
+:100160005D0F630F690F6F0F750F060F060F060FF8
+:10017000060F060F060F7B0F810F870F8D0F930F52
+:10018000990F9F0FA50FAB0FB10FB70FBD0FC30F87
+:10019000C90FCF0FD50FDB0FE10FE70F37103A1064
+:1001A0003D1040104310461049104C104F10521093
+:1001B000551058105B105E106110641067106A10C3
+:1001C0006D1034103410341034103410341070109A
+:1001D0007310761079107C107F10821085108810B3
+:1001E0008B108E109110941097109A109D10A010E3
+:1001F000A310A61011241FBECFEFD0E1DEBFCDBFEC
+:1002000011E0A0E0B1E0E0E3F4E300E00BBF02C0E6
+:1002100007900D92A435B107D9F714E0A4E5B1E039
+:1002200001C01D92A93BB107E1F70C9423010C9486
+:1002300000001F920F920FB60F9211240F900FBE65
+:100240000F901F901895CCEFD0E1DEBFCDBF8FEFA0
+:1002500084B985B92F980E94650781E897E10E94CB
+:10026000B00785E69CE00E94B50781E090E00E941F
+:10027000BA07DE011196EBE4F1E083E001900D9204
+:100280008150E1F7CE0101960E94AF0B80E091E032
+:100290000E944B0C81E191E00E94430C82E491E0CA
+:1002A0000E943B0C0E94850B4C0164E670E00E94AA
+:1002B000C80760E070E0C4010E94F10A3C0140E020
+:1002C00050E0BC01C4010E94E90720EFA22E21E00A
+:1002D000B22ECC24DD2490E4E92EF12C02E021E0C2
+:1002E00030E041E050E0B301C4010E94860A87E794
+:1002F000A82E82E0B82E21E030E041E050E0B301CA
+:10030000C4010E94BE0A0E940A071092E1011092E5
+:10031000E0011092E3011092E2010E94790C8FEF4C
+:1003200087B98AEA88B90E942C0385ED88B90E94B2
+:100330002C0380E888B9FFCF0F931F93CF93DF93EF
+:10034000EC0181349105B0F08091EC019091ED01C8
+:10035000892B81F41092E9011092E801D093EB010E
+:10036000C093EA0181E090E09093ED018093EC016D
+:10037000C0E4D0E068E08BE20E94500700E010E0AB
+:100380000EC0E091E801F091E901E00FF11FEE5C91
+:10039000FC4F608189E20E9450070F5F1F4F0C17CE
+:1003A0001D0779F78091E0019091E101019749F4EF
+:1003B00067E08BE20E9450071092E1011092E00189
+:1003C0000AC063E08BE20E94500781E090E09093C6
+:1003D000E1018093E001DF91CF911F910F9108958A
+:1003E0008091EC019091ED01019771F52091E80168
+:1003F0003091E9018091EA019091EB0128173907CA
+:1004000018F52091EA013091EB018091E80190917B
+:10041000E901281B390B8091E8019091E901805C8A
+:100420009F4F9093E9018093E801213431052CF02E
+:1004300080E490E00E949C010895C9010E949C0103
+:100440001092ED011092EC010895FC011092E90167
+:100450001092E8011092ED011092EC0100002F9A29
+:100460002081822F82958F7099278230910511F11A
+:10047000833091052CF4009761F0019759F516C06F
+:1004800084309105F9F084309105C4F0059711F599
+:100490001DC0263039F48281813039F5CF010E94A8
+:1004A000421723C0CF010E94F30C1FC0CF010E944E
+:1004B00084111BC0CF010E94E71217C0CF010E9418
+:1004C0002A1413C0CF010E945C150FC0CF010E94F7
+:1004D00089180BC02093320383E08093330310927A
+:1004E000340383E090E00E949C012F980895CF93FD
+:1004F000DF93EC018091E2019091E301019751F5C6
+:1005000020E030E0E091E401F091E501E20FF31F1B
+:10051000DE01A20FB31F8C91EE50FE4F80832F5F40
+:100520003F4F2034310571F78091E4019091E5014E
+:10053000805C9F4F9093E5018093E4012091E4015A
+:100540003091E5018091E6019091E7012817390784
+:10055000A8F11FC01092E5011092E40120E030E004
+:10056000E091E401F091E501E20FF31FDE01A20F3B
+:10057000B31F8C91EE50FE4F80832F5F3F4F20348E
+:10058000310571F73093E5012093E401A981A0348E
+:1005900048F41092E3011092E20182EF91E00E9490
+:1005A00025020CC081E090E09093E3018093E2018A
+:1005B0008A2F99279093E7018093E601DF91CF91ED
+:1005C00008951F920F920FB60F9211242F933F930D
+:1005D0004F935F936F937F938F939F93AF93BF934B
+:1005E000EF93FF930E94C50C80915D0186BDFF9142
+:1005F000EF91BF91AF919F918F917F916F915F919B
+:100600004F913F912F910F900FBE0F901F90189513
+:100610001F920F920FB60F9211242F933F934F9377
+:100620005F936F937F938F939F93AF93BF93EF935A
+:10063000FF930E94530CFF91EF91BF91AF919F9157
+:100640008F917F916F915F914F913F912F910F907B
+:100650000FBE0F901F90189520E080E49CE9019751
+:10066000F1F72F5F2931C9F70895FF920F931F9378
+:10067000162F042FF22E9C01442737FD4095542F4E
+:1006800060E472E48FE090E00E94C719215030408E
+:10069000163061F0173019F0153019F404C0E1E09C
+:1006A00003C0E1E004C0E0E070E002C0E0E071E01F
+:1006B000053439F00F3419F451E041E004C050E042
+:1006C00001C051E040E082E0F81611F462E001C0A0
+:1006D00060E0832F992787FD9A958093C50020932A
+:1006E000C40088E18093C100770FEE0FEE0FE72B77
+:1006F0005295550F507E5E2B4295407F452B660FDD
+:10070000660F660F642B6093C2001F910F91FF90DC
+:1007100008951092C50089E18093C40088E1809318
+:10072000C10086E08093C20008950895982F8091BB
+:10073000C00085FFFCCF9093C60008958091C00053
+:1007400087FFFCCF8091C600992708958A3310F463
+:10075000805301C087556A3310F4605301C0675558
+:100760006F708295807F682B862F99270895FC01F2
+:1007700007C08091C00085FFFCCF31969093C600E2
+:1007800090819923B1F70895982F92959F70282F03
+:100790002F709A3030F48091C00085FFFCCF905DBF
+:1007A00005C08091C00085FFFCCF995A9093C60088
+:1007B0002A3030F48091C00085FFFCCF205D05C059
+:1007C0008091C00085FFFCCF295A2093C600089570
+:1007D00087E280939A0485E28093990490E2909353
+:1007E0009B0410929C0428E030E030939E042093F8
+:1007F0009D0483E28093A60481E28093A5049093F4
+:10080000A7041092A8043093AA042093A904089581
+:1008100008956091B20481E20E945007089568E053
+:100820008BE20E94500761E188E20E94500768E075
+:100830008FE20E94500761E18CE20E94500761E064
+:100840008FE20E9450071092E1011092E00165E0F2
+:1008500083E20E94500708950F931F938C0160E478
+:1008600080E20E945007F8016281605884E00E9493
+:100870005007F80182818093B1041F910F91089570
+:100880000F931F93CF93DF93EC01288539851216C0
+:100890001306DCF58E819F81821793071CF568E0B3
+:1008A00083E20E94500700E010E00FC08A859B851C
+:1008B000E80FF91F608181E20E9450078E819F81BD
+:1008C00001969F838E830F5F1F4FEE81FF81888586
+:1008D0009985083011051CF4E817F9073CF3E8176F
+:1008E000F90724F061E087E20E9450078B81813094
+:1008F00031F465E089810E9450071B8206C061E0E7
+:1009000089810E94500781E08B83DF91CF911F91F5
+:100910000F910895CF93DF93CDB7DEB724970FB62D
+:10092000F894DEBF0FBECDBFDC01FC012281338114
+:100930001092AC041092AB0481E08093A804832F42
+:1009400099278230D9F0833069F1813009F057C09E
+:100950008091850499279093AE048093AD0485E837
+:1009600094E09093B0048093AF04868197818034A3
+:10097000910509F044C088E090E029C0FD0186811E
+:1009800097819093AE048093AD04E22FFF27EE0F82
+:10099000FF1F8091970490919804E80FF91F8081C0
+:1009A000918129C02223C1F0E22FFF27EE0FFF1F04
+:1009B0008091F0019091F101E80FF91F0190F08111
+:1009C000E02DF093B004E093AF04808199279093D9
+:1009D000AE048093AD0413C094E0998383E08A83CE
+:1009E00089E08B839C8384E090E09093AE048093B5
+:1009F000AD04CE0101969093B0048093AF0485EAD4
+:100A000094E00E94400424960FB6F894DEBF0FBE17
+:100A1000CDBFDF91CF910895CF93DF9382E20E9403
+:100A20002B07C82FDD27C5FF1AC068E083E20E94AC
+:100A30005007C6FF10C02091AB043091AC048091E8
+:100A4000AD049091AE04281739072CF485EA94E0A0
+:100A50000E94400404C061E087E20E945007DF91D9
+:100A6000CF9108951F93CF93DF9388E00E942B07C7
+:100A7000182FC82FDD27C6FF18C060E085E00E9450
+:100A8000500760E884E00E94500760E080E20E9426
+:100A9000500768E083E20E94500761E087E20E940D
+:100AA000500762E085E00E945007C4FF04C060EC7C
+:100AB00089E00E94500717FF04C060ED89E00E94A2
+:100AC0005007DF91CF911F9108958AE00E942B0774
+:100AD000992780FF03C00E940C05089581FF0DC077
+:100AE0008AE20E942B0780917204813061F4E091C8
+:100AF0007504F09176040995089582E30E942B070E
+:100B00008AE30E942B0708958EE00E942B0768E07D
+:100B10008FE20E94500761E08FE20E94500720910F
+:100B2000AD043091AE048091A9049091AA0482177B
+:100B300093075CF468E083E20E94500761E087E27B
+:100B40000E94500781E08093A8040895AF92BF925D
+:100B5000CF92DF92EF92FF920F931F93CF93DF9389
+:100B6000CDB7DEB728970FB6F894DEBF0FBECDBF66
+:100B700086E20E942B0786FF7EC08E010F5F1F4F0B
+:100B8000580169E0C62ED12CCC0EDD1E809199044F
+:100B90000E942B07F80181938F017501EC15FD056B
+:100BA000A9F768E087E20E94500768E083E20E94AC
+:100BB000500780E20E942B078F77682F80E20E9407
+:100BC000500789819927807690708032910509F4C9
+:100BD00040C080349105D1F1892BF1F5F501818177
+:100BE0008630D9F0873048F48130F1F18130C8F097
+:100BF0008330D1F1853081F521C0893019F18A30F7
+:100C000018F4883049F505C08A3071F18B3021F530
+:100C100020C0C5010E94090427C0C5010E948A04A2
+:100C200023C068E083E20E94500761E081E20E94F5
+:100C3000500760E081E20E9450070BC0C5010E948E
+:100C40002C0412C0C5010E940F040EC0C5010E94F1
+:100C5000080765E083E206C080E20E942B07805807
+:100C6000682F80E20E945007F70180818823D1F429
+:100C700065E083E215C02091AD043091AE0480910F
+:100C8000A9049091AA048217930764F41092AE0409
+:100C90001092AD0468E083E20E94500761E087E2B1
+:100CA0000E94500728960FB6F894DEBF0FBECDBF46
+:100CB000DF91CF911F910F91FF90EF90DF90CF9038
+:100CC000BF90AF900895CF92DF92EF92FF920F9373
+:100CD0001F93CF93DF93CDB7DEB7C054D0400FB68C
+:100CE000F894DEBF0FBECDBF8CE00E942B07992782
+:100CF00080FF03C00E94A6057BC081FF2AC08EE250
+:100D00000E942B078DE20E942B0789838E010F5FC3
+:100D10001F4F6801FFE3EF2EF12CE00EF11E0F5F75
+:100D20001F4F0E941907F80180830E151F05B9F7A0
+:100D300080915401813031F4E0915701F0915801D4
+:100D4000C601099568E08FE20E94500761E08FE2DA
+:100D50002BC082FF2CC086E30E942B0785E30E94F4
+:100D60002B0789838E010F5F1F4F6801EFE3EE2E83
+:100D7000F12CE00EF11E0F5F1F4F0E941907F801C2
+:100D800080830E151F05B9F780915501813031F42C
+:100D9000E0915901F0915A01C601099568E087E395
+:100DA0000E94500761E087E30E94500721C083FF43
+:100DB0001FC08EE30E942B078E010F5F1F4F68013B
+:100DC00071E4E72EF12CEC0EFD1E8DE30E942B0743
+:100DD000F80181938F01EE15FF05B9F78091560157
+:100DE000813031F4E0915701F0915801C601099525
+:100DF000C05CDF4F0FB6F894DEBF0FBECDBFDF91F2
+:100E0000CF911F910F91FF90EF90DF90CF900895B9
+:100E10000895089581E080936A0080E18DBB83B3DB
+:100E2000876083BB84B3836084BB3F9A479A78947E
+:100E3000089588B1805888B984B322E0822784BBA2
+:100E40000000000080B198B1905898B994B39227EF
+:100E500094BB992708959FEF91B982B988B18058C2
+:100E600088B984B395E0892784BB88B1805888B954
+:100E700084B3892784BB000011B80E941907992701
+:100E8000089582B988B1805888B984B391E08927E0
+:100E900084BB88B1805888B984B3892784BB0895FE
+:100EA00082B98FEF81B988B1805888B984B395E051
+:100EB000892784BB88B1805888B984B3892784BBCB
+:100EC000862F0E9441070895089582E1809385044A
+:100ED00081E08093860480E191E090938804809380
+:100EE00087041092890410928A0410928B0488E07F
+:100EF00080938C0410928E0410928D0410929004B2
+:100F000010928F0410929204109291041092930404
+:100F10001092940410929504109296041092540129
+:100F2000109255011092560110927204109273049F
+:100F30001092740410927C0410927B041092EF01C2
+:100F40001092EE01089590938E0480938D04709317
+:100F5000900460938F0450939204409391040895F9
+:100F600090938E0480938D040895909390048093C1
+:100F70008F04089590939204809391040895809330
+:100F80008904089580938A04089580938B040895BA
+:100F9000CF93DF939C01CB01E0917B04F0917C0423
+:100FA00062E070E00E94B4190FC0A081B18182811B
+:100FB000823039F4ED018D8199278217930709F466
+:100FC00068870780F085E02D309779F7DF91CF9122
+:100FD0000895CF93DF939C01E0917B04F0917C0412
+:100FE00014C0A081B1818281843061F48481992709
+:100FF0008217930739F4868199278617970711F48A
+:10100000ED014B830780F085E02D309751F7DF919C
+:10101000CF910895BF92CF92DF92EF92FF920F93FC
+:101020001F93CF93DF936C01162FF42EB22EC09135
+:101030007B04D0917C042097A1F489E090E00E9489
+:10104000BB18FC0190937C0480937B04D182C08206
+:10105000138310861782F282B4820583E68215C05C
+:10106000EC018F8198850097D9F789E090E00E9484
+:10107000BB18FC0198878F83D182C0821383F282D0
+:10108000B4820583E68210861782DF91CF911F918B
+:101090000F91FF90EF90DF90CF90BF900895EF9267
+:1010A000FF921F93CF93DF937C01C091EE01D0910B
+:1010B000EF01209711F011E012C085E090E00E944E
+:1010C000BB18FC019093EF018093EE01F182E08266
+:1010D00012821482138210E012C01F5FEC018B8118
+:1010E0009C810097D1F785E090E00E94BB18FC013D
+:1010F0009C838B83F182E082128314821382812F7E
+:101100009927DF91CF911F91FF90EF900895EF9273
+:10111000FF920F931F93CF93DF93E091EE01F09135
+:10112000EF0180E090E00380F481E02D019630979C
+:10113000D1F7880F991F0E94BB189093F1018093FB
+:10114000F0010091EE011091EF01E801E880F980D3
+:101150008A81C82FDD27CC0FDD1F8091F00190918F
+:10116000F101C80FD91FF701808199270E94BB1890
+:101170009983888320E030E017C0E801EA81FF27E7
+:10118000EE0FFF1F8091F0019091F101E80FF91F20
+:101190000190F081E02DE20FF31FD701A20FB31FE2
+:1011A0008C9180832F5F3F4FF7018081992728170B
+:1011B00039071CF3E8018B819C81009711F08C01A9
+:1011C000C4CFDF91CF911F910F91FF90EF900895C1
+:1011D0004F925F926F927F928F929F92AF92BF9247
+:1011E000CF92DF92EF92FF920F931F93CF93DF93F3
+:1011F000E0917B04F0917C046624772409C082810D
+:10120000823019F40894611C711C0780F085E02D70
+:101210003097A9F74301880C991CC4010E94BB18A0
+:101220009093980480939704E1E0EE2EF12CAA2489
+:10123000BB2455C0E0917B04F0917C0479E0C72E7B
+:10124000D12C15C0A081B181848199278E159F056D
+:1012500019F48381C80ED11CED018D818E1521F406
+:101260008281823009F45D010780F085E02D30979E
+:1012700049F7009197041091980402501040080D0E
+:10128000191DC6010E94BB18F8019183808320E0DC
+:1012900030E0E0919704F0919804E80DF91D329741
+:1012A0000190F081E02DE20FF31FD501A20FB31FD3
+:1012B0008C9180832F5F3F4F2930310551F7E091AA
+:1012C0009704F0919804E80DF91D32970190F08190
+:1012D000E02D8C2D875F82830894E11CF11C6E1435
+:1012E0007F040CF0A7CF61E0C62ED12C59E0A52ECB
+:1012F000B12C4424552442E0842E912CA1C0A0910D
+:101300007B04B0917C0412C0ED91FC911197818116
+:10131000823049F4858199278C159D0521F48481BB
+:10132000482E552405C0ED01AF81B885109761F7AF
+:1013300031E0E32EF12C79C060917B0470917C0444
+:101340006DC0FB01C081D1818981843009F063C007
+:10135000868199278E159F0509F05DC084819927A4
+:101360008C159D0509F057C0950140E050E0E091D3
+:101370009704F0919804E80DF91D32970190F081DF
+:10138000E02DE20FF31FDE01A40FB51F8C918083C7
+:101390002F5F3F4F4F5F5F4F4930510541F789E065
+:1013A00090E0A80EB91EC0917B04D0917C0431C09E
+:1013B0008A81853059F58C8199278C159D0531F5E9
+:1013C0008D8199278E159F0509F508811981950151
+:1013D00040E050E0E0919704F0919804E80DF91D89
+:1013E00032970190F081E02DE20FF31FD801A40F96
+:1013F000B51F8C9180832F5F3F4F4F5F5F4F47300A
+:10140000510541F7E7E0F0E0AE0EBF1E0F80D88532
+:10141000C02D209769F6EB016F8178856115710504
+:1014200009F08FCF0894E11CF11C4E145F040CF0FE
+:1014300083CF0894C11CD11CE2E0F0E08E0E9F1E09
+:101440006C147D040CF05BCFDF91CF911F910F9155
+:10145000FF90EF90DF90CF90BF90AF909F908F90D4
+:101460007F906F905F904F9008956F927F928F92D0
+:101470009F92AF92BF92CF92DF92EF92FF920F9323
+:10148000CF93DF935C013B014901E0917B04F09134
+:101490007C0416C0A081B18184819927A816B90661
+:1014A00061F4868199278615970539F48281843005
+:1014B00021F4ED018C818F5F8C830780F085E02D16
+:1014C000309741F787E090E00E94BB18FC0187E06D
+:1014D000808385E0818382820383F582E482C682F1
+:1014E000EE24062D2A2D45E067E0CF010E940A0870
+:1014F000DF91CF910F91FF90EF90DF90CF90BF9051
+:10150000AF909F908F907F906F900895AF92BF9211
+:10151000CF92DF92EF92FF920F93FC01A114B104DE
+:1015200001F14230510571F04330510599F04130DD
+:101530005105B9F481E080937204B0927604A092D0
+:1015400075040FC081E080937304B0927804A09278
+:10155000770407C081E080937404B0927A04A0926B
+:10156000790420583F4FCF010E94350A0F91FF9018
+:10157000EF90DF90CF90BF90AF900895AF92BF9261
+:10158000CF92DF92EF92FF920F93FC014230510510
+:1015900071F04330510599F041305105B9F481E0C3
+:1015A00080935401B0925801A09257010FC081E07E
+:1015B00080935501B0925A01A092590107C081E071
+:1015C00080935601B0925C01A0925B01CF010E9412
+:1015D000350A0F91FF90EF90DF90CF90BF90AF90C2
+:1015E0000895CF92DF92EF920F931F93CF93DF93E3
+:1015F0006C018B01A0917B04B0917C04C0E0D0E031
+:1016000014C02D913C911197F90185818C1551F4ED
+:10161000FD018281823031F4F90184818F5F8483FE
+:10162000C82FDD27FD01A781B085109751F789E00C
+:1016300090E00E94BB18FC0189E0808384E08183F4
+:101640000283138214821582168217821086EC2E72
+:1016500000E02C2D44E069E0CF010E940A08CE0191
+:10166000DF91CF911F910F91EF90DF90CF90089570
+:10167000BF92CF92DF92EF92FF920F931F93CF937F
+:10168000DF936C017B01142FB22EA0917B04B091EB
+:101690007C04C0E0D0E014C02D913C911197F90179
+:1016A00085818C1551F4FD018281823031F4F9017C
+:1016B00084818F5F8483C82FDD27FD01A781B085DA
+:1016C000109751F789E090E00E94BB18FC0189E077
+:1016D000808384E08183E282138214821583B68240
+:1016E00007831086EC2E00E02C2D44E069E0CF014A
+:1016F0000E940A08CE01DF91CF911F910F91FF90B8
+:10170000EF90DF90CF90BF900895EF920F931F93CB
+:10171000109196041F5F1093960489E090E00E9458
+:10172000BB18FC0189E0808389E090E09383828389
+:1017300082E0818314821583168280EA87838AE19E
+:101740008087EE2400E020E042E069E0CF010E94C3
+:101750000A08812F99271F910F91EF900895CF9339
+:10176000DF93EC01FC0101900020E9F7E81BF90B85
+:10177000CF01880F991F0E94BB189C01FE010190A8
+:101780000020E9F7EC1BFD0BEE0FFF1FDC01EC93D3
+:1017900083E0F901818340E050E009C0FE01E40FDD
+:1017A000F51F80818C93FD0111824F5F5F4F129670
+:1017B000FE0101900020E9F73197EC1BFD0B4E175D
+:1017C0005F0760F3C9010E944F089927DF91CF910D
+:1017D0000895EF92FF920F931F93CF93DF938C01A5
+:1017E0007B01CA010E94AF0B9C01E0917B04F09148
+:1017F0007C0414C0A081B1818281843061F4848131
+:1018000099278017910739F4868199278E159F05AE
+:1018100011F4ED0128870780F085E02D309751F70E
+:10182000DF91CF911F910F91FF90EF9008950F934B
+:101830001F93CF93DF938C01CB010E94AF0B9C01D0
+:10184000E0917B04F0917C040FC0A081B181828182
+:10185000823039F4ED018D8199278017910709F4C1
+:101860002E830780F085E02D309779F7DF91CF91B7
+:101870001F910F9108950E94AF0B1816190614F4CA
+:101880008093950408950E94AF0B1816190614F45E
+:101890008093940408950E94AF0B1816190614F44F
+:1018A0008093930408951F9386E00E942B07992745
+:1018B00086FF03C00E9463060EC082FF03C00E9421
+:1018C000650509C081FF03C00E94320504C084FF82
+:1018D00002C00E94840587E00E942B07182F60E059
+:1018E00087E00E945007612F87E00E9450071F91F8
+:1018F00008950E94E8080E9487080E94E80361E0BA
+:1019000080E00E94500780E00E942B0780FDFBCF03
+:1019100062E081E00E94500760E884E00E94500786
+:1019200060E480E20E94500768E083E20E94500772
+:1019300069E087E20E9450076FE08DE00E94500747
+:101940006FE08BE00E94500768ED89E00E9450072D
+:1019500063E38FE00E94500766ED87E00E94500726
+:1019600062E085E00E9450076CEC80E00E94500726
+:1019700008958EEC80935D0181E080936E008091EC
+:101980005D0186BD83E084BD08950895089583E0D8
+:101990008093320381E0809333038BE080933403A0
+:1019A0002FE62093350393E69093360384E78093E4
+:1019B0003703209338039093390381E680933A03E9
+:1019C0008EE680933B038FE580933C0380E3809316
+:1019D0003D0381E380933E0310923F038EE090E04D
+:1019E0000E949C010895FC018081833011F40E94C3
+:1019F000C70C0895CF93DF93C1E0D0E08C2F0E94F5
+:101A00000B0E2196C431D105C9F7CAE1D0E08C2F65
+:101A10000E940B0E2196CD32D105C9F7DF91CF91EF
+:101A20000895CF93DF93DC01EC01EA81FB812191E2
+:101A30008E81815019F48981E81BF109ED01FB8346
+:101A4000EA838E839FB7F8948C9181508C939FBFCB
+:101A5000822F9927DF91CF910895FC011082758321
+:101A60006483738362834183478346830895CF935E
+:101A7000DF93DC019C91ED018981981718F080E0DB
+:101A800090E016C0ED01EC81FD8161938F81815062
+:101A900019F48981E81BF109ED018F83FD83EC8343
+:101AA0009FB7F8948C918F5F8C939FBF81E090E0FB
+:101AB000DF91CF910895FC0180818823E9F3CF0164
+:101AC0000E94110D99270895FC018081882319F443
+:101AD0008FEF9FEF0895CF010E94110D9927089570
+:101AE00081E090E0089581E090E0089581E090E049
+:101AF000089581E090E00895CF93DF93CDB7DEB7EE
+:101B000022970FB6F894DEBF0FBECDBF282F8150AD
+:101B1000833120F08951833108F06EC0E22FFF2716
+:101B2000EE0FFF1FE35AFE4F82E090E09283818325
+:101B3000822F9927AA27BB27FC013197EC32F105A8
+:101B400008F05AC0E65BFF4FEE0FFF1F0590F491BF
+:101B5000E02D09946D9A47C06E9A49C06F9A43C0B0
+:101B6000209A45C0219A3FC0229A41C0239A3BC087
+:101B7000249A3DC0259A37C0269A39C0279A33C087
+:101B8000509A35C0519A2FC0529A31C0539A2BC0E7
+:101B9000549A2DC0559A27C0569A29C0579A23C0E7
+:101BA000389A25C0399A1FC03A9A21C03B9A1BC067
+:101BB0003C9A1DC03D9A17C03E9A19C0879A13C01F
+:101BC000869A15C0859A0FC0849A11C0839A0BC05B
+:101BD000829A0DC0819A07C0809A09C0689A03C092
+:101BE000699A05C06A9A81E090E008C06B9AE1E0CA
+:101BF000F0E0FA83E98304C084E090E09A8389836B
+:101C000089819A8122960FB6F894DEBF0FBECDBFB0
+:101C1000DF91CF910895982F8150833130F0895111
+:101C2000833118F084E090E00895892F0E947C0DA4
+:101C300081E090E00895CF93DF93CDB7DEB7229790
+:101C40000FB6F894DEBF0FBECDBF282F8150833171
+:101C500020F08951833108F06EC0E22FFF27EE0F8C
+:101C6000FF1FE35AFE4F81E090E092838183822F31
+:101C70009927AA27BB27FC013197EC32F10508F020
+:101C80005AC0EA58FF4FEE0FFF1F0590F491E02D68
+:101C900009946D9847C06E9849C06F9843C02098CA
+:101CA00045C021983FC0229841C023983BC024984A
+:101CB0003DC0259837C0269839C0279833C0509822
+:101CC00035C051982FC0529831C053982BC05498AA
+:101CD0002DC0559827C0569829C0579823C03898CA
+:101CE00025C039981FC03A9821C03B981BC03C982A
+:101CF0001DC03D9817C03E9819C0879813C086989C
+:101D000015C085980FC0849811C083980BC0829825
+:101D10000DC0819807C0809809C0689803C0699871
+:101D200005C06A9881E090E008C06B98E1E0F0E0BF
+:101D3000FA83E98304C084E090E09A8389838981EF
+:101D40009A8122960FB6F894DEBF0FBECDBFDF9109
+:101D5000CF910895FB011082833091F0843028F4F4
+:101D6000813051F0823029F409C0843059F0853037
+:101D700059F085E090E0089583B107C086B105C0B1
+:101D800089B103C08CB101C08FB1808381E090E044
+:101D90000895833091F0843028F4813051F08230FE
+:101DA00029F409C0843059F0853069F084E090E06E
+:101DB000089565B905C068B903C06BB901C06EB9B3
+:101DC00081E090E0089561BB81E090E00895282FC4
+:101DD000E82FFF27EE0FFF1FE35AFE4F818192810C
+:101DE000029719F086E090E00895822F9927AA279C
+:101DF000BB27FC013197EC32F10540F4EE55FF4F63
+:101E0000EE0FFF1F0590F491E02D099484E090E01F
+:101E10000895662311F0759ADDC07598DBC06623BE
+:101E200011F0769AD7C07698D5C0662311F0779ACC
+:101E3000D1C07798CFC0662311F0289ACBC02898DC
+:101E4000C9C0662311F0299AC5C02998C3C066236A
+:101E500011F02A9ABFC02A98BDC0662311F02B9AB0
+:101E6000B9C02B98B7C0662311F02C9AB3C02C9838
+:101E7000B1C0662311F02D9AADC02D98ABC066237A
+:101E800011F02E9AA7C02E98A5C0662311F02F9AA4
+:101E9000A1C02F989FC0662311F0589A9BC05898F4
+:101EA00099C0662311F0599A95C0599893C066233A
+:101EB00011F05A9A8FC05A988DC0662311F05B9A20
+:101EC00089C05B9887C0662311F05C9A83C05C98D8
+:101ED00081C0662311F05D9A7DC05D987BC066234A
+:101EE00011F05E9A77C05E9875C0662311F05F9A14
+:101EF00071C05F986FC0662311F0409A6BC0409824
+:101F000069C0662311F0419A65C0419863C0662399
+:101F100011F0429A5FC042985DC0662311F0439A67
+:101F200059C0439857C0662311F0449A53C044984F
+:101F300051C0662311F0459A4DC045984BC06623A9
+:101F400011F0469A47C0469845C0662311F08F9A13
+:101F500041C08F983FC0662311F08E9A3BC08E9887
+:101F600039C0662311F08D9A35C08D9833C0662331
+:101F700011F08C9A2FC08C982DC0662311F08B9A8B
+:101F800029C08B9827C0662311F08A9A23C08A98AB
+:101F900021C0662311F0899A1DC089981BC0662351
+:101FA00011F0889A17C0889815C0662311F0709AAE
+:101FB00011C070980FC0662311F0719A0BC0719810
+:101FC00009C0662311F0729A05C0729803C0662397
+:101FD00021F0739A81E090E00895739881E090E099
+:101FE00008951F93182F8150833130F08951833128
+:101FF00018F084E090E013C0E12FFF27EE0FFF1FE1
+:10200000E35AFE4F83E090E092838183812F0E9408
+:102010007C0D61E0812F0E94E70E81E090E01F912E
+:102020000895CF93DF93282FEB011882E82FFF2725
+:10203000EE0FFF1FE35AFE4F81819281019719F045
+:1020400086E090E089C0822F9927AA27BB27FC0150
+:102050003197EC32F10540F4E253FF4FEE0FFF1FD2
+:102060000590F491E02D099484E090E075C0659BA3
+:1020700071C06EC0669B6EC06BC0679B6BC068C052
+:10208000189B68C065C0199B65C062C01A9B62C07E
+:102090005FC01B9B5FC05CC01C9B5CC059C01D9B8C
+:1020A00059C056C01E9B56C053C01F9B53C050C042
+:1020B000489B50C04DC0499B4DC04AC04A9B4AC036
+:1020C00047C04B9B47C044C04C9B44C041C04D9B44
+:1020D00041C03EC04E9B3EC03BC04F9B3BC038C042
+:1020E000309B38C035C0319B35C032C0329B32C0C6
+:1020F0002FC0339B2FC02CC0349B2CC029C0359BD4
+:1021000029C026C0369B26C023C07F9B23C020C089
+:102110007E9B20C01DC07D9B1DC01AC07C9B1AC029
+:1021200017C07B9B17C014C07A9B14C011C0799B49
+:1021300011C00EC0789B0EC00BC0609B0BC008C0C6
+:10214000619B08C005C0629B05C002C0639B02C0C2
+:1021500081E0888381E090E0DF91CF910895CF9373
+:10216000DF93CDB7DEB721970FB6F894DEBF0FBE71
+:10217000CDBF9BE190933203BE016F5F7F4F0E9402
+:1021800011108093330389818093340383E090E0BE
+:102190000E949C0121960FB6F894DEBF0FBECDBF02
+:1021A000DF91CF9108959AE1909332030E94E70E58
+:1021B000809333031092340383E090E00E949C01EB
+:1021C000089598E1909332030E94C90E80933303DF
+:1021D0001092340383E090E00E949C010895982FB0
+:1021E00089E180933203933099F0943028F4913050
+:1021F00059F0923029F40AC0943061F0953061F0C2
+:1022000085E090E020E00BC023B107C026B105C0F7
+:1022100029B103C02CB101C02FB181E090E08093BF
+:1022200033032093340383E090E00E949C010895DF
+:1022300097E1909332030E94F10F80933303109241
+:10224000340383E090E00E949C01089595E190930F
+:1022500032030E941B0E809333031092340383E0F9
+:1022600090E00E949C01089596E1909332030E94B1
+:102270007C0D809333031092340383E090E00E943E
+:102280009C01089584E18093320381E080933303BD
+:102290001092340383E090E00E949C01089582E153
+:1022A0008093320381E0809333031092340383E000
+:1022B00090E00E949C01089583E18093320381E0C5
+:1022C000809333031092340383E090E00E949C01DA
+:1022D000089580E18093320381E08093330310926C
+:1022E000340383E090E00E949C01089591E1909373
+:1022F00032030E940B0E809333031092340383E069
+:1023000090E00E949C010895FC0180818531C9F113
+:10231000863180F4823131F1833130F48031D1F073
+:10232000813109F04CC01AC0833109F1843109F0C0
+:1023300046C022C0883189F1893128F4863129F1DB
+:102340008731E9F526C08A3189F18A3158F18B311C
+:10235000B1F531C082810E946911089582810E9485
+:1023600076110895638182810E944F1108956381DF
+:1023700082810E945C110895638182810E944211D2
+:10238000089582810E942611089582810E9434114D
+:10239000089582810E9418110895638182810E94AC
+:1023A000E110089582810E94EF1008956381828177
+:1023B0000E94D310089582810E94AF1008958093E7
+:1023C000320383E0809333031092340383E090E080
+:1023D0000E949C010895FC018197089718F084E001
+:1023E00090E00895EE0FFF1FE35AFE4F84E090E067
+:1023F0009283818381E090E0089510927C00823086
+:10240000910541F08330910569F0019741F082E038
+:1024100090E0089580917C00806480937C0081E04E
+:1024200090E0089580917C00806C80937C0081E036
+:1024300090E0089593E890937A0090917C00907FCB
+:10244000982B90937C0080917A00806480937A002E
+:1024500080917A0086FDFCCF809178009091790080
+:1024600020E030E040E050E080917A00806480938A
+:102470007A0080917A0086FDFCCF8091780090915F
+:102480007900480F591F2F5F3F4F2430310561F706
+:1024900080917A008F7780937A00CA01969587950C
+:1024A000969587950895CF93DF939C01EB01198250
+:1024B0001882FC01EE0FFF1FE35AFE4F81819281CB
+:1024C000049719F086E090E03CC02432310541F1D8
+:1024D0002532310554F42232310541F123323105E0
+:1024E00014F52132310569F424C02632310591F00A
+:1024F0002632310594F02732310549F02832310572
+:1025000019F087E090E01DC080E090E014C081E009
+:1025100090E011C082E090E00EC083E090E00BC03C
+:1025200084E090E008C085E090E005C086E090E09F
+:1025300002C087E090E00E941A129983888381E0AC
+:1025400090E0DF91CF91089522E2209332030E9420
+:10255000FD118093330382E090E00E949C01089576
+:10256000CF93DF93CDB7DEB722970FB6F894DEBFD7
+:102570000FBECDBF21E220933203BE016F5F7F4FBC
+:102580000E9453128093330329813A81832F992724
+:10259000809334032093350384E090E00E949C01F3
+:1025A00022960FB6F894DEBF0FBECDBFDF91CF915C
+:1025B000089520E2209332030E94EB1180933303AD
+:1025C0001092340383E090E00E949C010895FC0186
+:1025D0008081813249F0823261F0803279F48281E7
+:1025E00099270E94D9120895828199270E94B012DA
+:1025F0000895828199270E94A4120895809332033E
+:1026000083E0809333031092340383E090E00E94D0
+:102610009C0108958091B9009927887F9070089552
+:102620008091BC0087FFFCCF0895ECEBF0E0808147
+:10263000846080838BE090E09093770180937601B3
+:102640008CE090E0909379018093780181E090E0B4
+:102650000895ECEBF0E080818B7F808382E090E056
+:10266000909377018093760190937901809378011C
+:1026700081E090E008958130910511F48CE00BC069
+:102680008230910511F488E106C0039719F082E0C9
+:1026900090E0089588E48093B8008091B9008C7F21
+:1026A0008093B9008091B9008093B90081E090E0F7
+:1026B00008958091B90084EA8093BC008091BC00A9
+:1026C00087FFFCCF81E090E0089584E98093BC000F
+:1026D00081E090E008958093BB0084E88093BC0083
+:1026E0008091BC0087FFFCCF80E090E0089584E8F3
+:1026F0008093BC008091BC0087FFFCCF8091BB0021
+:102700009927089585E38093320381E08093330312
+:102710008093340384E88093BC008091BC0087FFE1
+:10272000FCCF8091BB008093350385E090E00E9450
+:102730009C01089540E050E00FC0F901E40FF51F3F
+:1027400080818093BB0084E88093BC008091BC00B2
+:1027500087FFFCCF4F5F5F4F4617570774F384E343
+:102760008093320381E0809333031092340383E03B
+:1027700090E00E949C01089587E38093320384E9EE
+:102780008093BC0081E0809333031092340383E094
+:1027900090E00E949C01089586E38093320380912B
+:1027A000B90084EA8093BC008091BC0087FFFCCF15
+:1027B00081E0809333031092340383E090E00E9421
+:1027C0009C01089522E3209332030E943B138093DF
+:1027D00033031092340383E090E00E949C0108953B
+:1027E00081E380933203ECEBF0E080818B7F808388
+:1027F00082E090E090937701809376019093790145
+:102800008093780181E0809333031092340383E056
+:1028100090E00E949C01089580E380933203ECEBEA
+:10282000F0E08081846080838BE090E0909377017A
+:10283000809376018CE090E0909379018093780109
+:1028400081E0809333031092340383E090E00E9490
+:102850009C010895FC0180818433D9F0853338F4DC
+:10286000813379F0823381F0803389F507C0863374
+:1028700041F18633D8F0873351F526C00E940C14FD
+:1028800008950E94F0130895828199270E94E2130F
+:102890000895428155276181772764507040838174
+:1028A00034969F0199270E949A13089542815527D3
+:1028B0006181772764507040838199270E94821339
+:1028C00008950E94CC1308950E94BC13089580932C
+:1028D000320383E0809333031092340383E090E06B
+:1028E0000E949C01089585B1817F85B9239886E077
+:1028F00084B91CBC1DBC83E58CBD88E090E090933E
+:102900006901809368018AE090E090936B01809365
+:102910006A0189E090E090936D0180936C0181E001
+:1029200090E008951CBC1DBC82E090E0909369018A
+:102930008093680190936B0180936A0190936D017D
+:1029400080936C0181E090E00895089581E090E02B
+:102950000895AC0120E030E00AC0FA01E20FF31F55
+:1029600080818EBD0DB407FEFDCF2F5F3F4F261730
+:1029700037079CF381E090E00895DC0120E030E02F
+:1029800040E050E015C01EBC09C04F5F5F4F83E0C0
+:10299000493E58071CF088E090E008950DB407FE0A
+:1029A000F4CFFD01E20FF31F8EB580832F5F3F4F01
+:1029B0002617370744F381E090E00895CF93DF9323
+:1029C000EC0120E030E0A0E0B0E018C0FE01E20F32
+:1029D000F31F80818EBD08C0119683E0A93EB80721
+:1029E0001CF088E090E00FC00DB407FEF5CFFB01AE
+:1029F000E20FF31F8EB580832F5F3F4F24173507FB
+:102A00002CF381E090E0DF91CF9108950F931F9315
+:102A10008B0123E420933203AB0164E373E00E9453
+:102A2000DE148093330310923403C80102960E948F
+:102A30009C011F910F9108950F931F938C0184E4C3
+:102A400080933203B80184E393E00E94BD14809325
+:102A5000330310923403C80102960E949C011F9117
+:102A60000F91089523E4209332030E94A9148093C8
+:102A700033031092340383E090E00E949C01089598
+:102A800081E4809332030E94921480933303109266
+:102A9000340383E090E00E949C01089580E48093D9
+:102AA00032030E947314809333031092350383E042
+:102AB00090E00E949C010895CF93DF93EC01888100
+:102AC0008334A1F0843438F4813469F0823458F5C9
+:102AD0008034F1F405C0843481F08534C9F411C028
+:102AE0000E944E1520C00E9440151DC069817727A5
+:102AF000CE0102960E94321516C0898199270E9444
+:102B00001C1569817727CE0102960E9406150BC01D
+:102B10008093320383E0809333031092340383E085
+:102B200090E00E949C01DF91CF910895209A219A14
+:102B3000229A2398249A259A2C982D9882E090E046
+:102B40009093850180938401909383018093820107
+:102B5000909381018093800181E090E090937F01C8
+:102B600080937E01089582E090E0909369018093C4
+:102B7000680190936B0180936A0190936D0180933B
+:102B80006C0181E090E00895289829982A9880E2C5
+:102B90009EE40197F1F7289A8AE0982F9A95F1F729
+:102BA0002A9A299A8A95F1F70895282F299887FD5E
+:102BB00002C02A9801C02A9A8AE0982F9A95F1F7C4
+:102BC000299A8A95F1F7299826FF02C02A9A01C00E
+:102BD0002A988AE0982F9A95F1F7299A8A95F1F721
+:102BE0000895282F220F30E0299827FF02C02A9A43
+:102BF00001C02A988AE0982F9A95F1F7299A8A9528
+:102C0000F1F73F5F373011F0220FEECF0895282FF4
+:102C100030E0299827FF02C02A9A01C02A988AE04A
+:102C2000982F9A95F1F7299A8A95F1F73F5F3830F6
+:102C300011F0220FEECF089529982A988AE0982F54
+:102C40009A95F1F7299A982F9A95F1F7299828984B
+:102C5000982F9A95F1F7299A982F9A95F1F7299834
+:102C60008A95F1F7289A80E090E0089529982898AD
+:102C70002A982B9A08950E94C41580E30E94D515C6
+:102C800080E60E94F11508950E94C41580E00E941C
+:102C9000D51580E00E94F1150E94361608950F9315
+:102CA0001F93182F062F0E94C41580E40E94D5158B
+:102CB000812F0E94F115802F0E94071681E090E07D
+:102CC0001F910F9108951F93182F0E94C41580EC37
+:102CD0000E94D515812F0E94F1150E941C1699277C
+:102CE0001F91089529988AE08A95F1F72A9830E093
+:102CF00090E0990F299A2AE0822F8A95F1F7299876
+:102D00001B999F5F822F8A95F1F73F5F383089F7D3
+:102D10002898299A822F8A95F1F7289A29982A9536
+:102D2000F1F7892F992708951F93182F0E94C41532
+:102D300080E80E94D515812F0E94F1150E9472161D
+:102D400099271F910895DF92EF92FF920F931F939F
+:102D5000CF93DF93D82E7B018A01C0E0D0E009C079
+:102D60008D2D8C0F0E949416F801EC0FFD1F8083AF
+:102D70002196CE15DF05A1F781E090E0DF91CF919C
+:102D80001F910F91FF90EF90DF9008950F931F9385
+:102D9000082F162F0E943B16612F802F0E944F167E
+:102DA00081E090E01F910F910895DF92EF92FF92E2
+:102DB0000F931F93CF93DF93D82E7B018A01C0E03E
+:102DC000D0E009C0F801EC0FFD1F60818D2D8C0F44
+:102DD0000E94C6162196CE15DF05A1F781E090E08E
+:102DE000DF91CF911F910F91FF90EF90DF900895A9
+:102DF00094E0909332030E94D5168093330310928F
+:102E0000340383E090E00E949C0108950F931F9388
+:102E10008B0193E09093320344E353E00E94A316A6
+:102E200080933303C80102960E949C011F910F9169
+:102E3000089582E08093320382E090E090936901EC
+:102E40008093680190936B0180936A0190936D0168
+:102E500080936C0181E0809333031092340383E00C
+:102E600090E00E949C01089581E0809332030E94CB
+:102E70009615809333031092340383E090E00E9410
+:102E80009C010895FC018381823069F0833018F43D
+:102E90008130F1F405C0833049F08430C9F40FC0AB
+:102EA0000E94341708950E9419170895AF014A5FD0
+:102EB0005F4F6581772784810E9406170895AF01CF
+:102EC0004A5F5F4F6581772784810E94F8160895D5
+:102ED00080818093320383E0809333031092340324
+:102EE00083E090E00E949C0108951F920F920FB61C
+:102EF0000F9211240F900FBE0F901F9018959C01F8
+:102F00000897029718F084E090E00895F901EE0F19
+:102F1000FF1FE35AFE4F8DE090E0928381832830BB
+:102F2000310531F02930310531F087E090E0089526
+:102F300081E090E00895259A81E090E090938900E7
+:102F40008093880081E88093800089E080938100ED
+:102F500081E090E008959C01FC01EE0FFF1FE35A11
+:102F6000FE4F818192810D9719F086E090E00895DF
+:102F70002830310539F12930310519F087E090E02A
+:102F8000089563307105B1F06430710544F4613027
+:102F9000710561F06230710509F040C009C064300C
+:102FA000710551F065307105C9F508C081E007C0B1
+:102FB00082E005C083E003C084E001C085E0809327
+:102FC000810029C064307105E9F06530710554F461
+:102FD0006230710599F06330710594F461307105C8
+:102FE000E9F40AC06630710589F06630710564F055
+:102FF0006730710599F40CC089E60BC08AE609C0F8
+:103000008BE607C08CE605C08DE603C08EE601C0E6
+:103010008FE68093B00081E090E0089581E090E039
+:1030200008959C01FC01EE0FFF1FE35AFE4F8181C2
+:1030300092810D9719F086E090E0089528303105CF
+:1030400069F02930310519F087E090E00895709318
+:1030500089006093880081E090E008956093B30058
+:1030600081E090E0089523E5209332030E94111837
+:10307000809333031092340383E090E00E949C011C
+:10308000089522E5209332030E94AB178093330307
+:103090001092340383E090E00E949C01089520E5A3
+:1030A000209332030E947F178093330310923403DE
+:1030B00083E090E00E949C0108959C01FC01EE0FCA
+:1030C000FF1FE35AFE4F82E090E092838183283015
+:1030D000310531F02930310531F086E090E0089576
+:1030E0001092B00002C010928100822F0E947C0DCD
+:1030F00081E090E0089521E5209332030E945D185D
+:10310000809333031092340383E090E00E949C018B
+:103110000895FC018081813579F0823518F480357D
+:10312000F1F405C0823569F08335C9F411C082819C
+:1031300099270E944F180895828199270E947B1831
+:10314000089563817727828199270E944118089505
+:1031500063817727828199270E943318089580938D
+:10316000320383E0809333031092340383E090E0D2
+:103170000E949C010895CF93DF93AC01029710F455
+:1031800042E050E0A091B704B091B804FD01C0E066
+:10319000D0E020E030E020C0808191818417950745
+:1031A00069F482819381209719F09B838A8304C0FC
+:1031B0009093B8048093B704CF0132C048175907E1
+:1031C00038F42115310519F08217930708F49C0192
+:1031D000EF010280F381E02D3097F1F621153105E2
+:1031E00089F1C901841B950B049708F4A901E0E05B
+:1031F000F0E026C08D919C91119782179307E9F416
+:103200004817590779F4ED018A819B81309719F0AD
+:103210009383828304C09093B8048093B704CD0154
+:10322000029649C0841B950BFD01E80FF91F4193DD
+:10323000519302978D939C933AC0FD01A281B38173
+:103240001097C1F68091B5049091B604892B41F492
+:1032500080915001909151019093B6048093B504F0
+:1032600020915201309153012115310541F42DB7C0
+:103270003EB780914E0190914F01281B390BE09190
+:10328000B504F091B6042E1B3F0B2417350788F0C8
+:10329000CA0102962817390760F0CF01840F951FE5
+:1032A00002969093B6048093B50441935193CF0155
+:1032B00002C080E090E0DF91CF910895CF93DF933B
+:1032C000009709F44EC0EC0122971B821A82A0914C
+:1032D000B704B091B804109711F140E050E001C07C
+:1032E000DC01AC17BD0700F1BB83AA83FE0121916D
+:1032F0003191E20FF31FEA17FB0771F42E5F3F4F86
+:103300008D919C911197820F931F99838883FD0162
+:10331000828193819B838A834115510559F4D0930F
+:10332000B804C093B7041DC0FD0182819381AD0133
+:103330000097B1F6FA01D383C28321913191E20F54
+:10334000F31FEC17FD0769F42E5F3F4F88819981C9
+:10335000820F931FFA01918380838A819B819383DB
+:103360008283DF91CF91089597FB092E07260AD01B
+:1033700077FD04D027D006D000201AF4709561950F
+:103380007F4F0895F6F7909581959F4F089597FB8D
+:10339000092E05260ED057FD04D028D00AD0001CD7
+:1033A00038F450954095309521953F4F4F4F5F4FE2
+:1033B0000895F6F790958095709561957F4F8F4FA2
+:1033C0009F4F0895AA1BBB1B51E107C0AA1FBB1F3B
+:1033D000A617B70710F0A61BB70B881F991F5A95A1
+:1033E000A9F780959095BC01CD010895A1E21A2E10
+:1033F000AA1BBB1BFD010DC0AA1FBB1FEE1FFF1F99
+:10340000A217B307E407F50720F0A21BB30BE40BE8
+:10341000F50B661F771F881F991F1A9469F760952F
+:103420007095809590959B01AC01BD01CF010895E9
+:10343000456D62656464656450726F6A6563747338
+:10344000004F63746F70757355534220496E7465F5
+:10345000726661636520436F6E7665727465722073
+:10346000616E6420492F4F20457874656E73696FD3
+:103470006E0032303038313130380009040020001D
+:04348000B90400008B
+:00000001FF
diff --git a/firmware/protocol.h b/firmware/protocol.h new file mode 100644 index 0000000..fce8eda --- /dev/null +++ b/firmware/protocol.h @@ -0,0 +1,94 @@ +/** + * Protocol is under GNU/GPL2! + * Author: Benedikt Sauter sauter@empronix.com, 2007-09-02 + * + * BYTE command + * BYTE parameter + * BYTE length body <x> + * <x> BYTES body + * + * max body length = 60 bytes + */ + +/** + * The first byte in the body of an response packet + * is always a value from the next table. + */ + +#define RSP_OK 0x01 +#define RSP_ERROR 0x02 +#define RSP_UNKOWN_CMD 0x03 +#define RSP_UNKOWN_PIN 0x04 +#define RSP_UNKOWN_PORT 0x05 +#define RSP_WRONG_PIN_CONFIG 0x06 +#define RSP_IMPOSSIBLE_PIN_CONFIG 0x07 +#define RSP_TIMEOUT 0x08 + + +#define CMD_LATENCY_TIMER_SET 0x01 +#define CMD_LATENCY_TIMER_GET 0x02 +#define CMD_GET_HW_ID 0x03 +#define CMD_EXTERNAL_DEVICE 0x06 + +#define CMD_IO_INIT_PORT 0x10 +#define CMD_IO_INIT_PIN 0x11 +#define CMD_IO_PORT_DIRECTION_IN 0x12 +#define CMD_IO_PORT_DIRECTION_OUT 0x13 +#define CMD_IO_PORT_DIRECTION_TRI 0x14 +#define CMD_IO_PIN_DIRECTION_IN 0x15 +#define CMD_IO_PIN_DIRECTION_OUT 0x16 +#define CMD_IO_PIN_DIRECTION_TRI 0x17 +#define CMD_IO_PORT_SET 0x18 +#define CMD_IO_PORT_GET 0x19 +#define CMD_IO_PIN_SET 0x1A +#define CMD_IO_PIN_GET 0x1B + +#define CMD_ADC_INIT_PIN 0x20 +#define CMD_ADC_GET 0x21 +#define CMD_ADC_REF 0x22 + +#define CMD_I2C_INIT 0x30 +#define CMD_I2C_DEINIT 0x31 +#define CMD_I2C_SET_BITRATE 0x32 +#define CMD_I2C_SEND_BYTE 0x34 +#define CMD_I2C_RECV_BYTES 0x35 +#define CMD_I2C_SEND_START 0x36 +#define CMD_I2C_SEND_STOP 0x37 + +#define CMD_SPI_INIT 0x40 +#define CMD_SPI_DEINIT 0x41 +#define CMD_SPI_SPEED 0x42 +#define CMD_SPI_SEND 0x43 +#define CMD_SPI_RECV 0x44 +#define CMD_SPI_SEND_AND_RECV 0x45 + + +#define CMD_PWM_INIT_PIN 0x50 +#define CMD_PWM_DEINIT_PIN 0x51 +#define CMD_PWM_SPEED 0x52 +#define CMD_PWM_VALUE 0x53 + + +#define CMD_UART_INIT 0x60 +#define CMD_UART_DEINIT 0x61 +#define CMD_UART_BAUDRATE 0x62 +#define CMD_UART_STOPBITS 0x63 +#define CMD_UART_DATABITS 0x64 +#define CMD_UART_PARITY 0x65 +#define CMD_UART_RECV 0x67 +#define CMD_UART_SEND 0x68 + + +#define PARAM_ADC_AREF 0x01 +#define PARAM_ADC_AVCC 0x02 +#define PARAM_ADC_INTERNAL 0x03 + + +/* microwire eeprom */ +#define CMD_EXTERNAL_93C46 0x01 + + +#define CMD_93C46_INIT 0x01 +#define CMD_93C46_DEINIT 0x02 +#define CMD_93C46_READ 0x03 +#define CMD_93C46_WRITE 0x04 diff --git a/firmware/pwm.c b/firmware/pwm.c new file mode 100644 index 0000000..9e3666d --- /dev/null +++ b/firmware/pwm.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2007 empronix (http://www.empronix.com) + * Author: Benedikt Sauter <sauter@empronix.com> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES{} LOSS OF USE, + * DATA, OR PROFITS{} OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "common.h" +#include "protocol.h" +#include "adc.h" +#include "io.h" +#include "pwm.h" + +#include <avr/interrupt.h> + +volatile unsigned int counter; + + SIGNAL(SIG_OUTPUT_COMPARE1A){ + //OCR1A = counter; + } + + + +void pwm_parser(char *buf) +{ + switch(buf[0]) + { + case CMD_PWM_INIT_PIN: + pwm_init_usb((int)buf[2]); + break; + case CMD_PWM_DEINIT_PIN: + pwm_deinit_usb((int)buf[2]); + break; + case CMD_PWM_SPEED: + pwm_speed_usb((int)buf[2],(int)buf[3]); + break; + case CMD_PWM_VALUE: + pwm_value_usb((int)buf[2],(int)buf[3]); + break; + + default: + answer[0]=buf[0]; + answer[1]=RSP_UNKOWN_CMD; + answer[2]=0; + CommandAnswer(3); + } +} + +int pwm_init(int pin) +{ + if (pin >= 8 && pin <= 9) + { + octopus.ports[pin] = PIN_PWM; + + switch(pin) + { + case 9: + /* set pin as output */ + OX_DDR9 |=(1<<OX_P9); + OCR1A=1; // TOP +#ifdef OCTOPUS_CAN + /* configure timer, (WGM = FAST PWM) (clear on OCnA, set on TOP COM1A1)*/ + TCCR1A = (1<<WGM10)|(1<<COM1A1); + TCCR1B = (1<<WGM12)|(1<<CS10); // system clock +#else + /* configure timer */ + //TCCR1 = (1<<WGM10)|(1<<COM01)|(1<<CS01); + //TCCR1B = (1<<CS10); // system clock +#endif + break; + case 8: + OX_DDR8 |=(1<<OX_P8); +#ifdef OCTOPUS_CAN + OCR2A=1; // TOP + /* configure timer, (WGM = FAST PWM) (clear on OCnA, set on TOP COM1A1)*/ + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS20); + //TCCR1B = (1<<WGM12)|(1<<CS10); // system clock +#else + /* configure timer */ + //TCCR1 = (1<<WGM10)|(1<<COM01)|(1<<CS01); + //TCCR1B = (1<<CS10); // system clock +#endif + break; + default: + return RSP_IMPOSSIBLE_PIN_CONFIG; + } + return RSP_OK; + } + return RSP_UNKOWN_PIN; +} + +void pwm_init_usb(int pin) +{ + answer[0]=CMD_PWM_INIT_PIN; + answer[1]= (unsigned char)pwm_init(pin); + answer[2]=0; + + CommandAnswer(3); +} + + + +void pwm_deinit_usb(int pin) +{ + answer[0]=CMD_PWM_DEINIT_PIN; + answer[1]=(unsigned char)pwm_deinit(pin); + answer[2]=0; + CommandAnswer(3); +} + +int pwm_deinit(int pin) +{ + octopus.ports[pin]=PIN_OUT; // this is wrong! +#ifdef OCTOPUS_CAN + switch(pin) + { + case 8: TCCR2A = 0; break; + case 9: TCCR1B = 0; TCCR1A = 0; break; + default: return RSP_WRONG_PIN_CONFIG; + + } + io_set_pin_direction_out(pin); +#endif + return RSP_OK; +} + + + +void pwm_speed_usb(int pin, int speed) +{ + answer[0]=CMD_PWM_SPEED; + answer[1]=pwm_speed(pin,speed); + answer[2]=0; + CommandAnswer(3); +} + + +int pwm_speed(int pin, int speed) +{ + if (octopus.ports[pin] == PIN_PWM) + { + switch (pin) + { + case 9: + switch (speed) + { + case 1: + TCCR1B = (1<<CS10); // system clock 33 kHz + break; + case 2: + TCCR1B = (1<<CS11); // div 8 // 500 Hz + break; + case 3: + TCCR1B = (1<<CS11)|(1<<CS10); // div 64 + break; + case 4: + TCCR1B = (1<<CS12); // div 256 + break; + case 5: + TCCR1B = (1<<CS12)|(1<<CS10); // div 1024 + break; + + default: + ; + } + break; + case 8: +#ifdef OCTOPUS_CAN + + switch (speed) + { + case 1: + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS20); // external 32kHz + break; + case 2: + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS21); // external div 8 + break; + case 3: + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS20)|(1<<CS21); //div 32 + break; + case 4: + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS22); //div 64 + break; + case 5: + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS20)|(1<<CS22); //div 128 + break; + case 6: + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS21)|(1<<CS22); //div 256 + break; + case 7: + TCCR2A = (1<<WGM20)| (1<<WGM21)|(1<<COM2A1)|(1<<CS21)|(1<<CS22)|(1<<CS20); //div 1024 + break; + default: + ; + } +#endif + break; + default: + return RSP_IMPOSSIBLE_PIN_CONFIG; + } + return RSP_OK; + } + else + { + return RSP_WRONG_PIN_CONFIG; + } +} + +void pwm_value_usb(int pin, unsigned int value) +{ + answer[0]=CMD_PWM_VALUE; + answer[1]=pwm_value(pin,value); + answer[2]=0; + CommandAnswer(3); +} + + +int pwm_value(int pin, unsigned int value) +{ + if (octopus.ports[pin] == PIN_PWM) + { + switch (pin) + { + case 9: + OCR1A = value; + break; + case 8: +#ifdef OCTOPUS_CAN + OCR2A = value; +#endif + ; + break; + default: + return RSP_IMPOSSIBLE_PIN_CONFIG; + } + return RSP_OK; + } + else + { + return RSP_WRONG_PIN_CONFIG; + } +} diff --git a/firmware/pwm.h b/firmware/pwm.h new file mode 100644 index 0000000..99e24db --- /dev/null +++ b/firmware/pwm.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2007 empronix (http://www.empronix.com) + * Author: Benedikt Sauter <sauter@empronix.com> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef PWM_H +#define PWM_H + +#include <avr/io.h> +#include <avr/pgmspace.h> + + +void pwm_parser(char *buf); + +int pwm_init(int pin); +void pwm_init_usb(int pin); + +int pwm_deinit(int pin); +void pwm_deinit_usb(int pin); + +void pwm_speed_usb(int pin, int speed); +int pwm_speed(int pin, int speed); + +void pwm_value_usb(int pin, unsigned int value); +int pwm_value(int pin, unsigned int value); + +#endif /* PWM_H */ diff --git a/firmware/spi.c b/firmware/spi.c new file mode 100644 index 0000000..2b8abb1 --- /dev/null +++ b/firmware/spi.c @@ -0,0 +1,188 @@ +/* + * Author: Benedikt Sauter <sauter@ixbat.de> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "common.h" +#include "protocol.h" + +#include "spi.h" + +void spi_parser(char *buf) +{ + switch(buf[0]) { + case CMD_SPI_INIT: + spi_init_usb(); + break; + case CMD_SPI_DEINIT: + spi_deinit_usb(); + break; + case CMD_SPI_SPEED: + spi_set_speed_usb((int)buf[2]); + break; + case CMD_SPI_SEND: + spi_send_usb(&buf[2], (int)buf[1]); + break; + case CMD_SPI_RECV: + spi_receive_usb((int)buf[1]); + case CMD_SPI_SEND_AND_RECV: + spi_send_and_receive_usb(&buf[2], (int)buf[1]); + break; + default: + answer[0] = buf[0]; + answer[1] = RSP_UNKOWN_CMD; + answer[2] = 0; + CommandAnswer(3); + } +} + +void spi_init_usb(void) +{ + answer[0] = CMD_SPI_INIT; + answer[1] = (unsigned char) spi_init(); + answer[3] = 0; + CommandAnswer(3); +} + + +int spi_init(void) +{ + PORTB &= ~((1 << SCK)|(1<<MISO)|(1<<MOSI)); // SCK have to be low in IDLE + DDRB &=~(1 << MISO); + DDRB = (1 << MOSI)|(1 << SCK); + + SPCR = 0; + SPSR = 0; + + SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0)|(1<<SPR1); + + octopus.ports[5]=PIN_SCK; + octopus.ports[6]=PIN_MOSI; + octopus.ports[7]=PIN_MISO; + + return RSP_OK; +} + +void spi_deinit_usb(void) +{ + answer[0]=CMD_SPI_DEINIT; + answer[1]=(unsigned char)spi_deinit(); + answer[2]=0; + CommandAnswer(3); +} + +int spi_deinit(void) +{ + SPCR = 0; + SPSR = 0; + + octopus.ports[5]=PIN_OUT; // this is wrong! + octopus.ports[6]=PIN_OUT; // this is wrong! + octopus.ports[7]=PIN_OUT; // this is wrong! + + return RSP_OK; +} + +void spi_set_speed_usb(int speed){ + +} + +int spi_set_speed(int speed){ + + return RSP_OK; +} + +void spi_send_usb(char * buf, int length) +{ + answer[0]=CMD_SPI_SEND; + answer[1]=(unsigned char)spi_send(buf,length); + answer[2]=0; + CommandAnswer(3); +} + +int spi_send(char * buf, int length) +{ + int i; + for(i=0;i<length;i++){ + SPDR = buf[i]; + while ( !(SPSR & (1 << SPIF)) ) ; + } + return RSP_OK; +} + + +void spi_receive_usb(int length) +{ + answer[0]=CMD_SPI_RECV; + answer[1]=(unsigned char)spi_receive((char*)&answer[2],length); + answer[2]=0; + CommandAnswer(length+2); +} + + +unsigned char spi_receive( char * buf, int length) +{ + int i; + int timeout = 0; + for(i=0;i<length;i++){ + SPDR = 0; + while(!(SPSR & (1 << SPIF))) { timeout++; if( timeout > 1000) return RSP_TIMEOUT; } + buf[i]=SPDR; + } + return RSP_OK; +} + +void spi_send_and_receive_usb(char * txbuf, int length) +{ + answer[0]=CMD_SPI_SEND; + answer[1]=(unsigned char)spi_send_and_receive(txbuf,(char *)&answer[2],length); + answer[2]=0; + CommandAnswer(2+length); + +} + +int spi_send_and_receive(char * txbuf, char * rxbuf, int length){ + + int i, timeout=0; + for(i=0;i<length;i++){ + SPDR = txbuf[i]; + //while ( !(SPSR & (1 << SPIF)) ) ; + while(!(SPSR & (1 << SPIF))) { timeout++; if( timeout > 1000) return RSP_TIMEOUT; } + rxbuf[i]=SPDR; + } + return RSP_OK; +} + + + + + + diff --git a/firmware/spi.h b/firmware/spi.h new file mode 100644 index 0000000..d7cfbf1 --- /dev/null +++ b/firmware/spi.h @@ -0,0 +1,64 @@ +/* + * Author: Benedikt Sauter <sauter@ixbat.de> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef SPI_H +#define SPI_H + +#include <avr/io.h> +#include <avr/pgmspace.h> + +#define MOSI PB2 +#define MISO PB3 +#define SCK PB1 + +void spi_parser(char *buf); + +int spi_init(void); +int spi_deinit(void); + +int spi_set_speed(int speed); +int spi_send(char * buf, int length); +unsigned char spi_receive( char * buf, int length); +int spi_send_and_receive(char * txbuf, char * rxbuf, int length); + + +void spi_init_usb(void); +void spi_deinit_usb(void); + +void spi_set_speed_usb(int speed); +void spi_send_usb(char * buf, int length); +void spi_receive_usb(int length); +void spi_send_and_receive_usb(char * txbuf, int length); + + +#endif /* SPI_H */ diff --git a/firmware/uart.c b/firmware/uart.c new file mode 100644 index 0000000..02b4a87 --- /dev/null +++ b/firmware/uart.c @@ -0,0 +1,381 @@ +#include <inttypes.h> +#include <avr/io.h> + +#include "uart.h" +#include "common.h" +#include "protocol.h" + +void uart_parser(char *buf) +{ + answer[0] = buf[0]; + + switch(buf[0]) + { + case CMD_UART_INIT: + uart_init_usb((char)buf[2]); + break; + case CMD_UART_DEINIT: + uart_deinit_usb((char)buf[2]); + break; + + case CMD_UART_BAUDRATE: + uart_baudrate_usb((char)buf[2], (char)buf[3], (char)buf[4], (char)buf[5], (char)buf[6]); + break; + case CMD_UART_STOPBITS: + uart_stopbits_usb((char)buf[2], (char)buf[3]); + break; + case CMD_UART_DATABITS: + uart_stopbits_usb((char)buf[2], (char)buf[3]); + break; + case CMD_UART_PARITY: + uart_parity_usb((char)buf[2], (char)buf[3]); + break; + + case CMD_UART_SEND: + uart_send_usb((char)buf[2], (char)buf[3], &buf[4]); + break; + case CMD_UART_RECV: + uart_recv_usb((char)buf[2], (char)buf[3]); + break; + default: + answer[1] = RSP_UNKOWN_CMD; + answer[2] = '\0'; + CommandAnswer(3); + } +} + +void uart_init_usb(char uartport) +{ + answer[1] = (unsigned char)uart_init(uartport); + answer[2] = '\0'; + + CommandAnswer(3); +} + +char uart_init(char uartport) +{ + switch(uartport) + { + case 0: + octopus.ports[41] = PIN_UART; + octopus.ports[42] = PIN_UART; + /* enable transmitter receiver */ + UCSR0B = (1 << RXEN0) | (1 << TXEN0); + break; + case 1: + octopus.ports[14] = PIN_UART; + octopus.ports[15] = PIN_UART; + /* enable transmitter receiver */ + UCSR1B = (1 << RXEN1) | (1 << TXEN1); + break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; +} + +void uart_deinit_usb(char uartport) +{ + answer[1] = (unsigned char)uart_deinit(uartport); + answer[2] = '\0'; + + CommandAnswer(3); +} + +char uart_deinit(char uartport) +{ + switch(uartport) + { + case 0: + octopus.ports[41] = PIN_NONE; + octopus.ports[42] = PIN_NONE; + UBRR0H = 0; + UBRR0L = 0; + UCSR0B = 0; + UCSR0C = 0; + break; + case 1: + octopus.ports[14] = PIN_NONE; + octopus.ports[15] = PIN_NONE; + UBRR1H = 0; + UBRR1L = 0; + UCSR1B = 0; + UCSR1C = 0; + break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; +} + +void uart_baudrate_usb(char uartport, char ubrrll, char ubrrlh, char ubrrhl, char ubrrhh) +{ + answer[1] = (unsigned char)uart_baudrate(uartport, ubrrll, ubrrlh, ubrrhl, ubrrhh); + answer[2] = '\0'; + + CommandAnswer(3); +} + +char uart_baudrate(char uartport, char ubrrll, char ubrrlh, char ubrrhl, char ubrrhh) +{ + switch(uartport) + { + case 0: + UBRR0H = (ubrrhh << 8) | ubrrhl; + UBRR0L = (ubrrhl << 8) | ubrrll; + break; + case 1: + UBRR1H = (ubrrhh << 8) | ubrrhl; + UBRR1L = (ubrrhl << 8) | ubrrll; + break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; +} + +void uart_stopbits_usb(char uartport, char stopbits) +{ + answer[1] = (unsigned char)uart_stopbits(uartport, stopbits); + answer[2] = '\0'; + + CommandAnswer(3); +} + +char uart_stopbits(char uartport, char stopbits) +{ + char usbs; + + switch(stopbits) + { + case 1: usbs = 0; break; + case 2: usbs = 2; break; + default: usbs = 0; break; + } + + switch(uartport) + { + case 0: + UCSR0C |= (usbs << USBS0); + break; + case 1: + UCSR1C |= (usbs << USBS1); + break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; +} + +void uart_databits_usb(char uartport, char databits) +{ + answer[1] = (unsigned char)uart_databits(uartport, databits); + answer[2] = '\0'; + + CommandAnswer(3); +} + +char uart_databits(char uartport, char databits) +{ + char ucsz1,ucsz0; + + switch(databits) { + case 5: ucsz1 = 0; ucsz0 = 0; break; + case 6: ucsz1 = 0; ucsz0 = 1; break; + case 7: ucsz1 = 1; ucsz0 = 0; break; + case 8: ucsz1 = 1; ucsz0 = 1; break; + default: ucsz1 = 1; ucsz0 = 1; break; + } + + switch(uartport) + { + case 0: + UCSR0C |= (ucsz1 << UCSZ01) | (ucsz0 << UCSZ00); + break; + case 1: + UCSR1C |= (ucsz1 << UCSZ11) | (ucsz0 << UCSZ10); + break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; +} + +void uart_parity_usb(char uartport, char parity) +{ + answer[1] = (unsigned char)uart_databits(uartport, parity); + answer[2] = '\0'; + + CommandAnswer(3); +} + +char uart_parity(char uartport, char parity) +{ + char upm1, upm0; + switch(parity) + { + case 'N': upm1 = 0; upm0 = 0; break; + case 'E': upm1 = 1; upm0 = 0; break; + case 'O': upm1 = 1; upm0 = 1; break; + default: upm1 = 0; upm0 = 0; break; + } + + switch(uartport) + { + case 0: + UCSR0C |= (upm1 << UPM01) | (upm0 << UPM00); + break; + case 1: + UCSR1C |= (upm1 << UPM11) | (upm0 << UPM10); + break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; +} + +void uart_send_usb(char uartport, char length, char *buf) +{ + answer[1] = (unsigned char)uart_send(uartport, length, buf); + answer[2] = '\0'; + + CommandAnswer(3); +} + + +char uart_send(char uartport, unsigned int length, char *buf) +{ + if(uartport != 0 && uartport != 1) + return RSP_UNKOWN_PIN; + + while(length--) + { + uart_putchar(uartport, *buf++); + } + + return RSP_OK; +} + +char uart_putchar(char uartport, char data) +{ + switch(uartport) + { + case 0: + /* Wait for empty transmit buffer */ + while (!(UCSR0A & (1 << UDRE0))); + /* Put data into buffer, sends the data */ + UDR0 = data; + break; + case 1: + /* Wait for empty transmit buffer */ + while (!(UCSR1A & (1 << UDRE1))); + /* Put data into buffer, sends the data */ + UDR1 = data; + break; + default: + return RSP_UNKOWN_PIN; + } + + return RSP_OK; +} + +void uart_recv_usb(char uartport, int length) +{ + char data[length]; + int i; + + answer[1] = (char)uart_recv(uartport, data, length); + + for(i = 0; i < length; i++) + answer[2+i] = data[i]; + + CommandAnswer(3+length); +} + +char uart_recv(char uartport, char * buf, int length) +{ + if(uartport != 0 && uartport != 1) + return RSP_UNKOWN_PIN; + + while(length-- > 0) + *buf++ = uart_getchar(uartport); + + return RSP_OK; +} + +char uart_getchar(char uartport) +{ + char c; + + switch(uartport) + { + case 0: + while (!(UCSR0A & (1 << RXC0))); + c = UDR0; + break; + case 1: + while (!(UCSR1A & (1 << RXC1))); + c = UDR1; + break; + default: + return RSP_UNKOWN_PIN; + } + + return c; +} + +/* +unsigned char AsciiToHex(unsigned char high,unsigned char low) +{ + unsigned char new; + + // check if lower equal 9 ( ascii 57 ) + if(high <= 57) // high is a number + high = high -48; + else // high is a letter + high = high -87; + + high = high << 4; + high = high & 0xF0; + + // check if lower equal 9 ( ascii 57 ) + if(low <= 57) // high is a number + low = low -48; + else // high is a letter + low = low -87; + low = low & 0x0F; + + new = high | low; + + return new; +} + +void SendHex(unsigned char hex) +{ + unsigned char high,low; + // get highnibble + high = hex & 0xF0; + high = high >> 4; + + // get lownibble + low = hex & 0x0F; + + if(high<=9) + UARTPutChar(high+48); + else + UARTPutChar(high+87); + + + if(low<=9) + UARTPutChar(low+48); + else + UARTPutChar(low+87); + +} +*/ diff --git a/firmware/uart.h b/firmware/uart.h new file mode 100644 index 0000000..fc89a0a --- /dev/null +++ b/firmware/uart.h @@ -0,0 +1,19 @@ +void uart_parser(char *); +char uart_init(char); +void uart_init_usb(char); +char uart_deinit(char); +void uart_deinit_usb(char); +char uart_baudrate(char uartport, char, char, char, char); +void uart_baudrate_usb(char uartport, char, char, char, char); +char uart_stopbits(char, char); +void uart_stopbits_usb(char, char); +char uart_databits(char, char); +void uart_databits_usb(char, char); +char uart_parity(char, char); +void uart_parity_usb(char, char); +char uart_putchar(char, char); +char uart_getchar(char uartport); +char uart_send(char uartport, unsigned int length, char *buf); +void uart_send_usb(char uartport, char length, char *buf); +void uart_recv_usb(char uartport, int length); +char uart_recv(char uartport, char * buf, int length); diff --git a/firmware/usbn2mc.c b/firmware/usbn2mc.c new file mode 100644 index 0000000..d9b0fdd --- /dev/null +++ b/firmware/usbn2mc.c @@ -0,0 +1,153 @@ +/* usbn960x.c +* Copyright (C) 2005 Benedikt Sauter +* +* 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 +* (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, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include <avr/io.h> +#include <avr/interrupt.h> +#include "usbn2mc.h" +#include "uart.h" + +//******************************************************************* +// add own vendor requests +// ******************************************************************** + +// decode your own vendor requests + +void +USBNDecodeVendorRequest (DeviceRequest * req) +{ +#if 0 + //SendHex(req->bRequest); // decode request code + SendHex (req->wLength); // decode request code + USBNWrite (RXC0, RX_EN); + USBNRead (RXD0); + USBNRead (RXD0); + + //USBNWrite(TXC0,FLUSH); + //USBNWrite(TXD0,0x24); + //USBNWrite(TXD0,0x25); +#endif +} + + +void +USBNDecodeClassRequest (DeviceRequest * req) +{ +#if 0 + //SendHex(req->bRequest); // decode request code + SendHex (req->wLength); // decode request code + USBNWrite (RXC0, RX_EN); + USBNRead (RXD0); + USBNRead (RXD0); +#endif +} + + + +// ******************************************************************** +// This subroutine handles the communication with usbn9604 +// ******************************************************************** + + +// Read data from usbn96x register + +void +USBNInitMC (void) +{ + // interrupt on INT4 pin falling edge (atmega128) + //EICRB = (0 << ISC41) | (1 << ISC40); + EICRB = (1 << ISC40); + // interrupts on! + //EIMSK = (1 << INT4); // allow extern irq4 + EIMSK = (1 << INT4); + + USB_CTRL_DDR |= (1 << PF_A0) | (1 << PF_RD) | (1 << PF_WR); // output (a0,rd,wr) + //USB_CTRL_PORT |= ((1 << PF_RD) | (1 << PF_WR) & ~(PF_A0)); + USB_CTRL_PORT |= ((1 << PF_RD) | (1 << PF_WR)); + USB_CS_DDR |= (1 << PF_CS); + USB_CS_PORT |= (1 << PF_CS); + + sei (); +} + + +unsigned char +USBNRead (unsigned char Adr) +{ + USB_DATA_DDR = 0xff; // set for output + USB_DATA_OUT = Adr; // load address + + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_WR) | (1 << PF_A0); // strobe the CS, WR, and A0 pins + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_WR) | (1 << PF_A0); // strobe the CS, WR, and A0 pins +// USB_CS_PORT ^=(1<<PF_CS); +// USB_CTRL_PORT ^= (1<<PF_WR) |(1<<PF_A0); + asm ("nop"); // pause for data to get to bus + USB_DATA_DDR = 0x00; // set PortD for input + return (USBNBurstRead ()); // get data off the bus +} + + +unsigned char +USBNBurstRead (void) +{ + unsigned char result; + + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_RD); + + asm ("nop"); // pause for data to get to bus + asm ("nop"); + result = USB_DATA_IN; + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_RD); + return result; +} + + +// Write data to usbn96x register +void +USBNWrite (unsigned char Adr, unsigned char Data) +{ + USB_DATA_OUT = Adr; // put the address on the bus + USB_DATA_DDR = 0xff; // set for output + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_WR) | (1 << PF_A0); + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_WR) | (1 << PF_A0); + USBNBurstWrite (Data); +} + + +void +USBNBurstWrite (unsigned char Data) +{ + USB_DATA_OUT = Data; // put data on the bus + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_WR); + USB_CS_PORT ^= (1 << PF_CS); + USB_CTRL_PORT ^= (1 << PF_WR); +} + + + +void +USBNDebug (char *msg) +{ +// UARTWrite (msg); +} diff --git a/firmware/usbn2mc.h b/firmware/usbn2mc.h new file mode 100644 index 0000000..2e7f8e7 --- /dev/null +++ b/firmware/usbn2mc.h @@ -0,0 +1,73 @@ +/* mciface.h +* Copyright (C) 2005 Benedikt Sauter +* +* 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 +* (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, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ +#ifndef _MCIFACE_H_ +#define _MCIFACE_H_ + +#include <stdint.h> +#include <avr/interrupt.h> +#include <inttypes.h> + + +#include "../usbn2mc/main/usbnapi.h" + +unsigned char USBNRead(unsigned char Adr); +unsigned char USBNBurstRead(void); +void USBNWrite(unsigned char Adr,unsigned char Data); +void USBNBurstWrite(unsigned char Data); + +void USBNInitMC(void); + +// print debug messages +void USBNDebug(char *msg); + +void USBNDecodeVendorRequest(DeviceRequest *req); +void USBNDecodeClassRequest(DeviceRequest *req); + + +/// The Atmega register used to send data/address to the USBN9604 +#define USB_DATA_OUT PORTA + +/// The Atmega register used to receive data from the USBN9604 +#define USB_DATA_IN PINA + +/// The Atmega register that controls the i/o direction of the USB_DATA_OUT +#define USB_DATA_DDR DDRA + +/// The Atmega port used to send control signals to the USBN9604 +#define USB_CTRL_PORT PORTG + +/// The Atmega register that controls the i/o direction of USB_CTRL_PORT +#define USB_CTRL_DDR DDRG + + +#define USB_CS_DDR DDRC +#define USB_CS_PORT PORTC + +/// The pin address of the chip select signal +#define PF_CS PC7 + +/// The pin address of the Address enable signal +#define PF_A0 PG2 + +/// The pin address of the write strobe signal +#define PF_WR PG0 + +/// The pin address of the read strobe signal +#define PF_RD PG1 + +#endif /* _MCIFACE_H_ */ diff --git a/firmware/wait.c b/firmware/wait.c new file mode 100644 index 0000000..91ef62a --- /dev/null +++ b/firmware/wait.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006, Benedikt Sauter <sauter@embedded-projects.net> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <stdint.h> +#include "wait.h" +#define F_CPU 16000000U +#include <util/delay.h> + +void delay_250ms (void) +{ + uint8_t i; + + for (i = 0; i < 25; i++) + _delay_ms (10); +} diff --git a/firmware/wait.h b/firmware/wait.h new file mode 100644 index 0000000..f1b56f8 --- /dev/null +++ b/firmware/wait.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2006, Benedikt Sauter <sauter@embedded-projects.net> + * All rights reserved. + * + * Short descripton of file: + * + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of the FH Augsburg nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef WAIT_H +#define WAIT_H + + +void delay_250ms (void); +#endif /* WAIT_H */ diff --git a/liboctopus/.gitignore b/liboctopus/.gitignore new file mode 100644 index 0000000..cc78368 --- /dev/null +++ b/liboctopus/.gitignore @@ -0,0 +1,2 @@ +*.so +*.o diff --git a/liboctopus/Makefile b/liboctopus/Makefile new file mode 100644 index 0000000..70d2625 --- /dev/null +++ b/liboctopus/Makefile @@ -0,0 +1,10 @@ +CC=gcc +CFLAGS= -fPIC +LDFLAGS=`pkg-config --libs libusb` + +all: octopus.o + gcc -fPIC -shared octopus.o $(LDFLAGS) -o liboctopus.so + +.PHONY: clean +clean: + rm -vf octopus.o liboctopus.so diff --git a/liboctopus/octopus.c b/liboctopus/octopus.c new file mode 100644 index 0000000..5471d7b --- /dev/null +++ b/liboctopus/octopus.c @@ -0,0 +1,815 @@ +/*************************************************************************** + octopus.c - description + ------------------- + begin : Aug 2007 + author : Benedikt Sauter, sauter@embedded-projects.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software, you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License * + * version 2.1 as published by the Free Software Foundation. * + * * + ***************************************************************************/ + +/** + \mainpage liboctopus API documentation + + Library to talk to octopus devices. You find the latest versions of liboctopus at + http://www.embedded-projects.net/octopus + + The library is easy to use. Have a look at this short example: + \include simple.c + + More examples can be found in the "examples" directory. +*/ +/** \addtogroup liboctopus */ +/* @{ */ + +#include <usb.h> +#include <string.h> +#include <errno.h> + +#include "octopus.h" +#include "../firmware/protocol.h" + +#define F_CPU 16000000UL + +#define octopus_error_return(code, str) do { \ + octopus->error_str = str; \ + return code; \ + } while(0); + + +/* + * initial octopus handle before use octopus_open + */ +int octopus_init(struct octopus_context *octopus) +{ + if (octopus == NULL) + octopus_error_return(-1,"octopus not valid"); + + octopus->error_str = NULL; + octopus->usb_handle = NULL; + + return 1; +} + +/* + * open first octopus on usb + */ +int octopus_open(struct octopus_context *octopus) +{ + if (octopus_open_id(octopus,VID,PID) < 0) + octopus_error_return(-1,"could not found octopus device with pid and vid"); + + return 1; +} + +/* + * open octopus with a given usb vendor and product id + */ +int octopus_open_id(struct octopus_context *octopus, int vendor, int product) +{ + struct usb_bus *busses; + struct usb_bus *bus; + struct usb_device *dev; + + usb_init(); + + if (usb_find_busses() < 0) + octopus_error_return(-1, "usb_find_busses() failed"); + + if (usb_find_devices() < 0) + octopus_error_return(-2, "usb_find_devices() failed"); + + busses = usb_get_busses(); + + if (busses == NULL) + octopus_error_return(-3, "usb_get_busses() failed"); + + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + if (dev->descriptor.idVendor == vendor && dev->descriptor.idProduct == product) + { + octopus_open_dev(octopus,dev); + return 1; + } + } + } + octopus_error_return(-4,"could not found octopus device with pid and vid"); + return -1; +} + +/* + * open octopus with a given usb name description (not tested!) + */ +int octopus_open_serial(struct octopus_context *octopus, char * serial) +{ + struct usb_bus *busses; + struct usb_dev_handle* usb_handle; + struct usb_bus *bus; + struct usb_device *dev; + char usbserial[64]; + int length=0; + + usb_init(); + + if (usb_find_busses() < 0) + octopus_error_return(-1, "usb_find_busses() failed"); + if (usb_find_devices() < 0) + octopus_error_return(-2, "usb_find_devices() failed"); + + busses = usb_get_busses(); + if(busses==NULL) + octopus_error_return(-3, "usb_get_busses() failed"); + + for (bus = busses; bus; bus = bus->next) + { + for (dev = bus->devices; dev; dev = dev->next) + { + usb_handle = usb_open(dev); + usb_set_configuration(usb_handle,0); + length = usb_get_string_simple(usb_handle,3,usbserial,64); + usb_close(usb_handle); + + if (strncmp(serial,usbserial,length) == 0) + { + octopus_open_dev(octopus,dev); + return 1; + } + } + } + + octopus_error_return(-4,"could not found octopus device with serial number"); + return -1; +} + +/* + * open octopus with a libusb dev handle + */ +int octopus_open_dev(struct octopus_context *octopus, struct usb_device *dev) +{ + if (octopus == NULL) + octopus_error_return(-1,"octopus handle is wrong or missing"); + + if (dev == NULL) + octopus_error_return(-2,"device handle is wrong or missing"); + + if (!(octopus->usb_handle = usb_open(dev))) + octopus_error_return(-3,"can't open usb device"); + + if (usb_set_configuration (octopus->usb_handle,dev->config[0].bConfigurationValue) < 0) + octopus_error_return(-4,"can't set configuration for given usb device"); + + if (usb_claim_interface(octopus->usb_handle, 0) < 0) + octopus_error_return(-5,"can't claim interface for given usb device"); + + if (usb_set_altinterface(octopus->usb_handle,0) < 0) + octopus_error_return(-6,"can't set altinterface for given usb device"); + + return 1; +} + +/* + * close a open octopus handle + */ +int octopus_close(struct octopus_context *octopus) +{ + if (octopus == NULL) + octopus_error_return(-1,"octopus is not a valid handle"); + + if (usb_close(octopus->usb_handle) < 0) + octopus_error_return(-2,usb_strerror()); + + return 1; +} + +/* + * send message to octopus + */ +int octopus_message(struct octopus_context *octopus, char *msg, + int msglen, char *answer, int answerlen) +{ + int timeout=0; + + if (usb_bulk_write(octopus->usb_handle,1,msg,msglen,100) < msglen) + octopus_error_return(-1,"transfer error occurred"); + + if (answerlen>0){ + while(1) + { + if(usb_bulk_read(octopus->usb_handle,0x81,(char*)answer,answerlen,100)>0) + break; + + if(timeout++ >= 1000) + octopus_error_return(-2,"receive error occurred"); + } + + if(answer[1]==RSP_OK) + { + return 1; + } + else if (answer[1]==RSP_UNKOWN_CMD) + { + octopus_error_return(-1,"unkown command"); + } + else if (answer[1]==RSP_UNKOWN_PIN) + { + octopus_error_return(-2,"unkown pin"); + } + else if (answer[1]==RSP_WRONG_PIN_CONFIG) + { + octopus_error_return(-3,"pin is in wrong configuration"); + } + else if (answer[1]==RSP_ERROR) + { + octopus_error_return(-4,"error in usb device"); + } + else if (answer[1]==RSP_TIMEOUT) + { + octopus_error_return(-4,"timeout error in usb device"); + } + else + { + octopus_error_return(-5,"unknown error"); + } + } + return 1; +} + +/* + * get internal device description of octopus (octopus_1, octocan_01) + */ +char * octopus_get_hwdesc(struct octopus_context *octopus, char *desc) +{ + + char msg[] = {CMD_GET_HW_ID,0x00,0x00}; + int i; + char answer[64]; + + for (i=0;i<64;i++) + answer[i]=0; + + if (octopus_message(octopus,msg,3,answer,14) == RSP_OK) + { + if ((int)answer[2] > 0) + memcpy(desc,answer+3,(int)answer[2]); + return desc; + } + else + { + octopus_error_return(NULL,octopus->error_str); + } + return desc; +} + +/* + * use pin as gpio + */ +int octopus_io_init(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_IO_INIT_PIN,0x01,0x00}; + msg[2] = (char)pin; + if (octopus_message(octopus,msg,3,answer,3) > 0) + return 1; + else return -1; +} + + +int octopus_io_init_port(struct octopus_context *octopus, int port) +{ + char msg[] = {CMD_IO_INIT_PORT,0x01,0x00}; + char answer[3]; + msg[2] = (char)port; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; +} + +int octopus_io_set_port_direction_out(struct octopus_context *octopus, int port,unsigned char mask) +{ + char answer[3]; + char msg[] = {CMD_IO_PORT_DIRECTION_OUT,0x02,0x00,0x00}; + msg[2] = (char)port; + msg[3] = mask; + if(octopus_message(octopus,msg,4,answer,3)) + return 1; + else return -1; +} + +int octopus_io_set_port_direction_in(struct octopus_context *octopus, int port, unsigned char mask) +{ + char answer[3]; + char msg[] = {CMD_IO_PORT_DIRECTION_IN,0x02,0x00,0x00}; + msg[2] = (char)port; + msg[3] = mask; + if(octopus_message(octopus,msg,4,answer,3)) + return 1; + else return -1; +} + + +int octopus_io_set_port_direction_tri(struct octopus_context *octopus, int port, unsigned char mask) +{ + char answer[3]; + char msg[] = {CMD_IO_PORT_DIRECTION_TRI,0x02,0x00,0x00}; + msg[2] = (char)port; + msg[3] = mask; + if(octopus_message(octopus,msg,4,answer,3)) + return 1; + else return -1; +} + +/* + * use pin as output + */ +int octopus_io_set_pin_direction_out(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_IO_PIN_DIRECTION_OUT,0x01,0x00}; + msg[2] = (char)pin; + if (octopus_message(octopus,msg,3,answer,3) == RSP_OK) + return 1; + else + octopus_error_return(-1,octopus->error_str); +} + + +int octopus_io_set_pin_direction_in(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_IO_PIN_DIRECTION_IN,0x01,0x00}; + msg[2] = (char)pin; + if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) + return 1; + else + octopus_error_return(-1,octopus->error_str); +} + + + +int octopus_io_set_pin_direction_tri(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_IO_PIN_DIRECTION_TRI,0x01,0x00}; + msg[2] = (char)pin; + if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) + return 1; + else + octopus_error_return(-1,octopus->error_str); +} + +unsigned char octopus_io_get_port(struct octopus_context *octopus, int port) +{ + char answer[3]; + char msg[] = {CMD_IO_PORT_GET,0x01,0x00}; + msg[2] = (char)port; + if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) + return (unsigned char) answer[2]; + else + return 0; + //octopus_error_return((unsigned char)NULL,octopus->error_str); +} + + +int octopus_io_set_port(struct octopus_context *octopus, int port, unsigned char value) +{ + char answer[3]; + char msg[] = {CMD_IO_PORT_SET,0x01,0x00,0x00}; + msg[2] = (char)port; + msg[3] = (char)value; + if(octopus_message(octopus,msg,4,answer,3)) + return 1; + else return -1; +} + + +int octopus_io_set_pin(struct octopus_context *octopus, int pin, int value) +{ + char answer[3]; + char msg[] = {CMD_IO_PIN_SET,0x01,0x00,0x00}; + msg[2] = (char)pin; + msg[3] = (char)value; + if(octopus_message(octopus,msg,4,answer,3)==RSP_OK) + return 1; + else + octopus_error_return(-1,octopus->error_str); +} + + +int octopus_io_get_pin(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_IO_PIN_GET,0x01,0x00}; + msg[2] = (char)pin; + //msg[3] = 0x00; + if(octopus_message(octopus,msg,3,answer,3)==RSP_OK) + return (int)answer[2]; + else + octopus_error_return(-1,octopus->error_str); +} + + + +/// part: adc +int octopus_adc_init(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_ADC_INIT_PIN,0x01,0x00}; + msg[2] = (char)pin; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; +} + + + +int octopus_adc_get(struct octopus_context *octopus, int pin) +{ + unsigned char answer[4]; + char msg[] = { CMD_ADC_GET, 0x01, 0x00 }; + msg[2] = (char) pin; + + //XXX ???? + if (octopus_message (octopus, msg, 3, (char *)answer, sizeof (answer)) >0) + { + unsigned int low = (unsigned int)answer[3]; + unsigned int high = (unsigned int)answer[2]; + + return((int)((unsigned int)(low | (high << 8)))); + } + else + return -1; +} + +int octopus_adc_ref(struct octopus_context *octopus, int ref) +{ + char answer[3]; + char msg[] = {CMD_ADC_REF,0x01,0x00}; + msg[2] = (char)ref; + if(octopus_message(octopus,msg,3,answer,3)>0) + return (int)answer[1]; + else + octopus_error_return(-1,octopus->error_str); +} + + + +int octopus_adc_get_bulk(struct octopus_context *octopus, + int pin, int number, int * buf) +{ + return 1; +} + +int octopus_i2c_init(struct octopus_context *octopus) +{ + char answer[3]; + char msg[] = {CMD_I2C_INIT,0x01,0x00}; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; +} + +int octopus_i2c_deinit(struct octopus_context *octopus) +{ + char answer[3]; + char msg[] = {CMD_I2C_DEINIT,0x01,0x00}; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; +} + +int octopus_i2c_set_bitrate(struct octopus_context *octopus, int scl_freq) { + char answer[3]; + char msg[] = {CMD_I2C_SET_BITRATE, 0x01, 0x00}; + + //XXX rounding XXX + int bitrate = ((F_CPU/scl_freq)-16) / 2; + msg[2] = bitrate; + + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; +} + + +int octopus_i2c_send_byte(struct octopus_context *octopus, char data) +{ + char answer[3]; + + // cmd = cmd,len,timeout,address,data1,data2,..) + char msg[] = {CMD_I2C_SEND_BYTE,0x01,0x00}; + msg[2] = (char)data; + + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else + octopus_error_return(-1,octopus->error_str); +} + + +int octopus_i2c_send_bytes(struct octopus_context *octopus, char *buf, int len) +{ + while(len > 0) { + if(octopus_i2c_send_byte(octopus,buf[len--]) <= 0) + return 0; + } + + return 1; +} + + +unsigned char octopus_i2c_receive_byte(struct octopus_context *octopus, + int address,int timeout) +{ + char tmp[1]; + + if(octopus_i2c_receive_bytes(octopus,address,tmp,1,1)>0) + return tmp[1]; + else + return -1; +} + + +int octopus_i2c_receive_bytes(struct octopus_context *octopus, + int address,char *buf, int len, int timeout) +{ + if(len>60){ + return -1; // max 60 bytes + } + + char msg[64] = {CMD_I2C_RECV_BYTES,0x01,0x00}; + msg[1] = (char)(len+4); + msg[2] = (char)timeout; + msg[3] = (char)address; + + char answer[64]; + int i; + + if(octopus_message(octopus,msg,4,answer,len+3)>0){ + for(i=0;i<len;i++) + buf[i]=answer[i+3]; + return (int)answer[2]; + } + else + octopus_error_return(-1,octopus->error_str); + + return 1; +} + +int octopus_i2c_send_start(struct octopus_context *octopus) +{ + char answer[3]; + char msg[] = {CMD_I2C_SEND_START,0x01,0x00}; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; + + return 1; +} + +int octopus_i2c_send_stop(struct octopus_context *octopus) +{ + char answer[3]; + char msg[] = {CMD_I2C_SEND_STOP,0x00,0x00}; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; + + return 1; +} + +/// part: SPI +int octopus_spi_init(struct octopus_context *octopus) +{ + char answer[2]; + char msg[] = {CMD_SPI_INIT,0x00,0x00}; + if(octopus_message(octopus,msg,3,answer,2)>0) + return 1; + else return -1; + +} + +int octopus_spi_deinit(struct octopus_context *octopus) +{ + char answer[2]; + char msg[] = {CMD_SPI_DEINIT,0x00,0x00}; + if(octopus_message(octopus,msg,3,answer,2)>0) + return 1; + else return -1; + +} + +int octopus_spi_speed(struct octopus_context *octopus, int speed) +{ + return 0; +} + + +int octopus_spi_send(struct octopus_context *octopus, unsigned char * buf, int length) +{ + if(length>60){ + return -1; // max 60 bytes + } + + char answer[2]; + + // cmd = cmd,len,timeout,address,data1,data2,..) + char msg[64] = {CMD_SPI_SEND,0x01,0x00}; + msg[1] = (char)(length); + + // build send array + int i; + for(i=0;i<length;i++) + msg[i+2]=(char)buf[i]; + + if(octopus_message(octopus,msg,2+length,answer,2)>0) + return 1; + else + octopus_error_return(-1,octopus->error_str); + + return 1; +} + +int octopus_spi_recv(struct octopus_context *octopus, unsigned char * buf, int length) +{ + if(length>60){ + return -1; // max 60 bytes + } + + char answer[64]; + + char msg[64] = {CMD_SPI_RECV,0x01,0x00}; + msg[1] = (char)(length); + + int i; + + if(octopus_message(octopus,msg,2,answer,2+length)>0) { + for(i=0;i<length;i++) + buf[i]=answer[i+2]; + + return 1; + } + else + octopus_error_return(-1,octopus->error_str); +} + +int octopus_spi_send_and_recv(struct octopus_context *octopus, unsigned char * buf, int length) +{ + if(length>60){ + return -1; // max 60 bytes + } + + char answer[2]; + + // cmd = cmd,len,timeout,address,data1,data2,..) + char msg[64] = {CMD_SPI_SEND_AND_RECV,0x01,0x00}; + msg[1] = (char)(length); + + // build send array + int i; + for(i=0;i<length;i++) + msg[i+2]=(char)buf[i]; + + if(octopus_message(octopus,msg,2+length,answer,2+length)>0) { + + for(i=0;i<length;i++) + buf[i]=answer[i+2]; + + return 1; + } + else + octopus_error_return(-1,octopus->error_str); + + return 1; + +} + +/// part: Flash 93c46 +int octopus_93c46_init(struct octopus_context *octopus) +{ + char answer[3]; + char msg[] = {CMD_EXTERNAL_DEVICE,0x00,CMD_EXTERNAL_93C46,CMD_93C46_INIT}; + msg[1] = 4; + if(octopus_message(octopus,msg,4,answer,3)>0) + return 1; + else return -1; +} + +int octopus_93c46_deinit(struct octopus_context *octopus) +{ + char answer[3]; + char msg[] = {CMD_EXTERNAL_DEVICE,CMD_EXTERNAL_93C46,CMD_93C46_DEINIT}; + if (octopus_message(octopus,msg,3,answer,3) > 0) + return 1; + else return -1; +} + +int octopus_93c46_write(struct octopus_context *octopus, unsigned char address, int length, unsigned char * buf) +{ + /* + if(length>59){ + return -1; // max 60 bytes + } + */ + + char answer[3]; + + // cmd = cmd,len,timeout,address,data1,data2,..) + char msg[150] = {CMD_EXTERNAL_DEVICE,0x00,CMD_EXTERNAL_93C46,CMD_93C46_WRITE}; + msg[1] = (unsigned char)(6 + length); + msg[4] = (unsigned char)(address); + msg[5] = (unsigned char)(length); + + // build send array + int i; + for(i=0;i<length;i++) + msg[i+6]=(char)buf[i]; + + if(octopus_message(octopus,msg,6+length,answer,3)>0) + return 1; + else + octopus_error_return(-1,octopus->error_str); + + return 1; +} + +int octopus_93c46_read(struct octopus_context *octopus, unsigned char address, int length, unsigned char * buf) +{ + /* + if(length>59) + { + return -1; // max 60 bytes + }*/ + + char answer[150]; + + char msg[6] = {CMD_EXTERNAL_DEVICE,0x00,CMD_EXTERNAL_93C46,CMD_93C46_READ}; + + msg[1] = 6; + msg[4] = (unsigned char)(address); + msg[5] = (unsigned char)(length); + + int i; + + if (octopus_message(octopus, msg, 6, answer, 2 + length) > 0) + { + for(i=0;i<length;i++) + buf[i]=answer[i+2]; + + return 1; + } + else + octopus_error_return(-1,octopus->error_str); +} + + +/// part: PWM +int octopus_pwm_init(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_PWM_INIT_PIN,0x01,0x00}; + msg[2] = (char)pin; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; +} + +int octopus_pwm_deinit(struct octopus_context *octopus, int pin) +{ + char answer[3]; + char msg[] = {CMD_PWM_DEINIT_PIN,0x01,0x00}; + msg[2] = (char)pin; + if(octopus_message(octopus,msg,3,answer,3)>0) + return 1; + else return -1; +} + +int octopus_pwm_speed(struct octopus_context *octopus, int pin, int speed) +{ + char answer[3]; + char msg[] = {CMD_PWM_SPEED,0x02,0x00,0x00}; + msg[2] = (char)pin; + msg[3] = (char)speed; + if(octopus_message(octopus,msg,4,answer,3)>0) + return 1; + else return -1; +} + +int octopus_pwm_value(struct octopus_context *octopus, int pin, unsigned char value) +{ + char answer[3]; + char msg[] = {CMD_PWM_VALUE,0x02,0x00,0x00}; + msg[2] = (char)pin; + msg[3] = (char)value; + if(octopus_message(octopus,msg,4,answer,3)>0) + return 1; + else return -1; +} + +; diff --git a/liboctopus/octopus.h b/liboctopus/octopus.h new file mode 100644 index 0000000..b123335 --- /dev/null +++ b/liboctopus/octopus.h @@ -0,0 +1,141 @@ +/*************************************************************************** + octopus.h - description + ------------------- + begin : Fri Apr 1 2007 + copyright : (C) 2007 by Embedded Projects + email : sauter@embedded-projects.net + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU Lesser General Public License * + * version 2.1 as published by the Free Software Foundation; * + * * + ***************************************************************************/ + +#ifndef __liboctopus_h__ +#define __liboctopus_h__ + +#include <usb.h> + + +#define VID 0x1781 +#define PID 0x0c65 + +/** + \brief Main context structure for all liboctopus functions. + + Do not access directly if possible. +*/ +struct octopus_context { + // USB specific + /// libusb's usb_dev_handle + struct usb_dev_handle *usb_handle; + + /// String representation of last error + char *error_str; +}; + +/** + \brief list of usb devices created by octopus_usb_find_all() +*/ +struct octopus_device_list { + /// pointer to next entry + struct octopus_device_list *next; + /// pointer to libusb's usb_device + struct usb_device *dev; +}; + +#ifdef __cplusplus +extern "C" { +#endif + + int octopus_init(struct octopus_context *octopus); + + int octopus_open(struct octopus_context *octopus); + int octopus_open_id(struct octopus_context *octopus, int vendor, int product); + int octopus_open_serial(struct octopus_context *octopus, char * serial); + + int octopus_open_dev(struct octopus_context *octopus, struct usb_device *dev); + + int octopus_close(struct octopus_context *octopus); + + int octopus_message(struct octopus_context *octopus, char *msg, + int msglen, char *answer, int answerlen); + + char * octopus_get_hwdesc(struct octopus_context *octopus, char *desc); + + /// part: IO + + int octopus_io_init(struct octopus_context *octopus, int pin); + int octopus_io_init_port(struct octopus_context *octopus, int port); + + int octopus_io_set_port_direction_out(struct octopus_context *octopus, + int port,unsigned char mask); + int octopus_io_set_port_direction_in(struct octopus_context *octopus, + int port, unsigned char mask); + int octopus_io_set_port_direction_tri(struct octopus_context *octopus, + int port, unsigned char mask); + + int octopus_io_set_pin_direction_out(struct octopus_context *octopus, int pin); + int octopus_io_set_pin_direction_in(struct octopus_context *octopus, int pin); + //int octopus_io_set_pin_direction_in_pullup(struct octopus_context *octopus, int pin); + int octopus_io_set_pin_direction_tri(struct octopus_context *octopus, int pin); + + unsigned char octopus_io_get_port(struct octopus_context *octopus, int port); + + int octopus_io_set_port(struct octopus_context *octopus, int port, unsigned char value); + + int octopus_io_set_pin(struct octopus_context *octopus, int pin, int value); //buffered + + int octopus_io_get_pin(struct octopus_context *octopus, int pin); + + /// part: adc + + int octopus_adc_init(struct octopus_context *octopus, int pin); + int octopus_adc_get(struct octopus_context *octopus, int pin); + int octopus_adc_ref(struct octopus_context *octopus, int ref); + // 1= extern AREF, 2 = AVCC as reference, 3=intern voltage + + + /// part: I2C + int octopus_i2c_init(struct octopus_context *octopus); + int octopus_i2c_deinit(struct octopus_context *octopus); + + int octopus_i2c_set_bitrate(struct octopus_context *octopus, int bitrate); + int octopus_i2c_send_byte(struct octopus_context *octopus, char data); + int octopus_i2c_send_bytes(struct octopus_context *octopus, char *buf, int len); + unsigned char octopus_i2c_receive_byte(struct octopus_context *octopus, int address,int timeout); + int octopus_i2c_receive_bytes(struct octopus_context *octopus, int address,char *buf, int len, int timeout); + + int octopus_i2c_send_start(struct octopus_context *octopus); + int octopus_i2c_send_stop(struct octopus_context *octopus); + + /// part: SPI + int octopus_spi_init(struct octopus_context *octopus); + int octopus_spi_deinit(struct octopus_context *octopus); + + int octopus_spi_speed(struct octopus_context *octopus, int speed); + int octopus_spi_send(struct octopus_context *octopus, unsigned char * buf, int length); + int octopus_spi_recv(struct octopus_context *octopus, unsigned char * buf, int length); + int octopus_spi_send_and_recv(struct octopus_context *octopus, unsigned char * buf, int length); + + /// part: Flash 93c46 + int octopus_93c46_init(struct octopus_context *octopus); + int octopus_93c46_deinit(struct octopus_context *octopus); + + int octopus_93c46_read(struct octopus_context *octopus, unsigned char address, int length, unsigned char * buf); + int octopus_93c46_write(struct octopus_context *octopus, unsigned char address, int length, unsigned char * buf); + + /// part: PWM + int octopus_pwm_init(struct octopus_context *octopus, int pin); + int octopus_pwm_deinit(struct octopus_context *octopus, int pin); + int octopus_pwm_speed(struct octopus_context *octopus, int pin, int speed); + int octopus_pwm_value(struct octopus_context *octopus, int pin, unsigned char value); + +#ifdef __cplusplus +} +#endif + +#endif /* __liboctopus_h__ */ diff --git a/liboctopus/python/.gitignore b/liboctopus/python/.gitignore new file mode 100644 index 0000000..5b2c896 --- /dev/null +++ b/liboctopus/python/.gitignore @@ -0,0 +1,2 @@ +octopus.py +octopus_wrap.c diff --git a/liboctopus/python/Makefile b/liboctopus/python/Makefile new file mode 100644 index 0000000..e0e6f29 --- /dev/null +++ b/liboctopus/python/Makefile @@ -0,0 +1,19 @@ +CC=gcc +CFLAGS= -fPIC +CFLAGS+=-I.. +CFLAGS+=`python-config --cflags` +LDFLAGS=`pkg-config --libs libusb` + +all: octopus.o octopus_wrap.o + gcc -fPIC -shared octopus_wrap.o octopus.o $(LDFLAGS) -o _octopus.so + +octopus_wrap.o: + swig -python octopus.i + $(CC) -c -o octopus_wrap.o octopus_wrap.c $(CFLAGS) + +octopus.o: + $(CC) -c -o octopus.o ../octopus.c $(CFLAGS) + +.PHONY: clean +clean: + rm -vf octopus.o octopus.py _octopus.so octopus_wrap.o octopus.pyc octopus_wrap.c diff --git a/liboctopus/python/demos/adc.py b/liboctopus/python/demos/adc.py new file mode 100644 index 0000000..5e55ab7 --- /dev/null +++ b/liboctopus/python/demos/adc.py @@ -0,0 +1,19 @@ + + +from octopus import * +import time + + +op=octopus_context() +octopus_init(op) +octopus_open(op) +octopus_adc_init(op, 33) +octopus_adc_ref(op, 2) + +while 1: + value = octopus_adc_get(op, 33) + callin = "Value %i" % value + print callin + time.sleep(1) + + diff --git a/liboctopus/python/demos/blink.py b/liboctopus/python/demos/blink.py new file mode 100644 index 0000000..3e454af --- /dev/null +++ b/liboctopus/python/demos/blink.py @@ -0,0 +1,22 @@ +#blink.py +#laesst die led1 (26) blinken + + +from octopus import * +import time + + +op=octopus_context() +octopus_init(op) +octopus_open(op) +octopus_io_init(op,26) + +octopus_io_set_pin_direction_out(op,26) + +while 1: + octopus_io_set_pin(op,26,1) + time.sleep(1) + octopus_io_set_pin(op,26,0) + time.sleep(1) + + diff --git a/liboctopus/python/demos/blink_all.py b/liboctopus/python/demos/blink_all.py new file mode 100644 index 0000000..32c963b --- /dev/null +++ b/liboctopus/python/demos/blink_all.py @@ -0,0 +1,58 @@ +#blink_all.py +#laesst die led1 - led6 auf einmal blinken + +import sys + +sys.path.append("../../libs/python") + +from octopus import * +import time + + +op=octopus_context() +octopus_init(op) +octopus_open(op) +octopus_io_init(op,26) +octopus_io_init(op,27) +octopus_io_init(op,28) +octopus_io_init(op,29) +octopus_io_init(op,30) +octopus_io_init(op,31) +octopus_io_init(op,32) + +octopus_io_set_pin_direction_out(op,26) +octopus_io_set_pin_direction_out(op,27) +octopus_io_set_pin_direction_out(op,28) +octopus_io_set_pin_direction_out(op,29) +octopus_io_set_pin_direction_out(op,30) +octopus_io_set_pin_direction_out(op,31) +octopus_io_set_pin_direction_out(op,32) + +octopus_io_set_pin(op,26,0) +octopus_io_set_pin(op,27,0) +octopus_io_set_pin(op,28,0) +octopus_io_set_pin(op,29,0) +octopus_io_set_pin(op,30,0) +octopus_io_set_pin(op,31,0) +octopus_io_set_pin(op,32,0) + + + + +while 1: + octopus_io_set_pin(op,26,1) + octopus_io_set_pin(op,27,1) + octopus_io_set_pin(op,28,1) + octopus_io_set_pin(op,29,1) + octopus_io_set_pin(op,30,1) + octopus_io_set_pin(op,31,1) + octopus_io_set_pin(op,32,1) + time.sleep(1) + octopus_io_set_pin(op,26,0) + octopus_io_set_pin(op,27,0) + octopus_io_set_pin(op,28,0) + octopus_io_set_pin(op,29,0) + octopus_io_set_pin(op,30,0) + octopus_io_set_pin(op,31,0) + octopus_io_set_pin(op,32,0) + time.sleep(1) diff --git a/liboctopus/python/demos/blink_i2c.py b/liboctopus/python/demos/blink_i2c.py new file mode 100644 index 0000000..5fd4cb9 --- /dev/null +++ b/liboctopus/python/demos/blink_i2c.py @@ -0,0 +1,29 @@ +# blink_i2c.py +# laesst die led des i2c (0x10) blinken + +import sys +sys.path.append("..\\..\\libs\\python") + +from octopus import * +import time + + +op=octopus_context() +octopus_init(op) +octopus_open(op) +octopus_i2c_init(op) +octopus_i2c_set_bitrate(op,3) # 100khz + + +octopus_i2c_send_start(op) + +while 1: + #octopus_i2c_receive_byte(op,0x10,1) + octopus_i2c_send_byte(op,0x20,1) + octopus_i2c_send_byte(op,1,1) + time.sleep(1) + octopus_i2c_send_byte(op,0x20,1) + octopus_i2c_send_byte(op,0,1) + time.sleep(1) + + diff --git a/liboctopus/python/demos/blink_lauf.py b/liboctopus/python/demos/blink_lauf.py new file mode 100644 index 0000000..00f73e7 --- /dev/null +++ b/liboctopus/python/demos/blink_lauf.py @@ -0,0 +1,67 @@ +#blink_lauf.py +#laesst alle leds nacheinander blinken + +from octopus import * +import time + + +op=octopus_context() +octopus_init(op) +octopus_open(op) +octopus_io_init(op,26) +octopus_io_init(op,27) +octopus_io_init(op,28) +octopus_io_init(op,29) +octopus_io_init(op,30) +octopus_io_init(op,31) +octopus_io_init(op,32) + +octopus_io_set_pin_direction_out(op,26) +octopus_io_set_pin_direction_out(op,27) +octopus_io_set_pin_direction_out(op,28) +octopus_io_set_pin_direction_out(op,29) +octopus_io_set_pin_direction_out(op,30) +octopus_io_set_pin_direction_out(op,31) +octopus_io_set_pin_direction_out(op,32) + +octopus_io_set_pin(op,26,0) +octopus_io_set_pin(op,27,0) +octopus_io_set_pin(op,28,0) +octopus_io_set_pin(op,29,0) +octopus_io_set_pin(op,30,0) +octopus_io_set_pin(op,31,0) +octopus_io_set_pin(op,32,0) + + + + +while 1: + octopus_io_set_pin(op,26,1) + time.sleep(1) + octopus_io_set_pin(op,26,0) + time.sleep(0.5) + octopus_io_set_pin(op,27,1) + time.sleep(1) + octopus_io_set_pin(op,27,0) + time.sleep(0.5) + octopus_io_set_pin(op,28,1) + time.sleep(1) + octopus_io_set_pin(op,28,0) + time.sleep(0.5) + octopus_io_set_pin(op,29,1) + time.sleep(1) + octopus_io_set_pin(op,29,0) + time.sleep(0.5) + octopus_io_set_pin(op,30,1) + time.sleep(1) + octopus_io_set_pin(op,30,0) + time.sleep(0.5) + octopus_io_set_pin(op,31,1) + time.sleep(1) + octopus_io_set_pin(op,31,0) + time.sleep(0.5) + octopus_io_set_pin(op,32,1) + time.sleep(1) + octopus_io_set_pin(op,32,0) + time.sleep(0.5) + diff --git a/liboctopus/python/demos/blink_status.py b/liboctopus/python/demos/blink_status.py new file mode 100644 index 0000000..c4b0945 --- /dev/null +++ b/liboctopus/python/demos/blink_status.py @@ -0,0 +1,26 @@ +# blink_status.py +# laesst die status led (11) blinken + +import sys +sys.path.append("..\\..\\libs\\python") + + +from octopus import * +import time + + +op=octopus_context() +octopus_init(op) +octopus_open(op) +octopus_io_init(op,11) + +octopus_io_set_pin_direction_out(op,11) + +octopus_io_set_pin(op,11,0) + + +while 1: + octopus_io_set_pin(op,11,1) + time.sleep(1) + octopus_io_set_pin(op,11,0) + time.sleep(1) diff --git a/liboctopus/python/demos/eeprom_i2c.py b/liboctopus/python/demos/eeprom_i2c.py new file mode 100644 index 0000000..17707a4 --- /dev/null +++ b/liboctopus/python/demos/eeprom_i2c.py @@ -0,0 +1,36 @@ +# blink_i2c.py +# laesst die led des i2c (0x10) blinken + +from octopus import * +import time + + +op=octopus_context() +octopus_init(op) +octopus_open(op) +octopus_i2c_init(op) +octopus_i2c_set_bitrate(op,3) # 100khz + + +octopus_i2c_send_start(op) +octopus_i2c_send_byte(op,0xae,1) +octopus_i2c_send_byte(op,1,1) +octopus_i2c_send_byte(op,0,1) +octopus_i2c_send_byte(op,0x77,1) +octopus_i2c_send_stop(op) + + + +octopus_i2c_send_start(op) +octopus_i2c_send_byte(op,0xae,1) +octopus_i2c_send_byte(op,1,1) +octopus_i2c_send_byte(op,0,1) +octopus_i2c_send_start(op) + +octopus_i2c_send_byte(op,0xaf,1) + +print octopus_i2c_receive_byte(op,1,1) + +octopus_i2c_send_stop(op) + + diff --git a/liboctopus/python/octopus.i b/liboctopus/python/octopus.i new file mode 100644 index 0000000..4999a19 --- /dev/null +++ b/liboctopus/python/octopus.i @@ -0,0 +1,5 @@ +%module octopus +%{ +#include "../octopus.h" +%} +%include "../octopus.h" |