├── .gitignore ├── electronics ├── .gitignore ├── gerber │ ├── dimension.txt │ ├── forcefoot_gerber.zip │ └── forcefoot.txt ├── BOM.xlsx ├── BOM_3p.xlsx └── README.md ├── firmware ├── .gitignore ├── src │ ├── uart │ │ ├── Makefile.sources │ │ ├── dir.h │ │ ├── dir.c │ │ ├── uart.h │ │ └── uart.c │ ├── dxl │ │ ├── Makefile.sources │ │ ├── types.h │ │ ├── registers.h │ │ ├── byte_queue.h │ │ ├── dxl.h │ │ ├── byte_queue.c │ │ └── dxl.c │ ├── terminal │ │ ├── Makefile.sources │ │ ├── terminal.h │ │ └── terminal.c │ ├── terminal_main │ │ ├── Makefile.sources │ │ └── main.c │ ├── util │ │ ├── Makefile.sources │ │ ├── out.h │ │ ├── pgmspace.h │ │ ├── out.c │ │ └── pgmspace.c │ └── main │ │ ├── Makefile.sources │ │ ├── led.h │ │ ├── hx711.h │ │ ├── led.c │ │ ├── main.c │ │ └── hx711.c ├── bin │ ├── flash.sh │ ├── firmware_123.bin │ └── firmware_124.bin ├── build │ └── flash ├── fuse-m328p.sh ├── fuse-m328pb.sh ├── Makefile.config ├── Makefile ├── README.md └── .map ├── 3d ├── cell.ipt ├── cleat.ipt ├── foot.iam ├── foot.ipt ├── jauge.ipt ├── nylon_spacer.ipt ├── README.md └── lockfile.lck ├── docs ├── 3d.png ├── board.odg ├── board.pdf ├── board.png ├── full-bridge.png ├── half-bridge.png ├── src │ └── gauges.odg └── sigmaban_foot.png ├── misc ├── crtatmega328pb.o ├── libatmega328pb.a ├── io.h └── iom328pb.h ├── atmega328pb-update.sh └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | **.swp 2 | -------------------------------------------------------------------------------- /electronics/.gitignore: -------------------------------------------------------------------------------- 1 | *#* 2 | *.pro 3 | *.epf 4 | -------------------------------------------------------------------------------- /firmware/.gitignore: -------------------------------------------------------------------------------- 1 | **.o 2 | **.elf 3 | **.bin 4 | -------------------------------------------------------------------------------- /firmware/src/uart/Makefile.sources: -------------------------------------------------------------------------------- 1 | SOURCES := uart.c dir.c 2 | -------------------------------------------------------------------------------- /firmware/src/dxl/Makefile.sources: -------------------------------------------------------------------------------- 1 | SOURCES := byte_queue.c dxl.c 2 | -------------------------------------------------------------------------------- /firmware/src/terminal/Makefile.sources: -------------------------------------------------------------------------------- 1 | SOURCES := terminal.c 2 | -------------------------------------------------------------------------------- /firmware/src/terminal_main/Makefile.sources: -------------------------------------------------------------------------------- 1 | SOURCES := main.c 2 | -------------------------------------------------------------------------------- /firmware/src/util/Makefile.sources: -------------------------------------------------------------------------------- 1 | SOURCES := pgmspace.c out.c 2 | -------------------------------------------------------------------------------- /firmware/src/main/Makefile.sources: -------------------------------------------------------------------------------- 1 | SOURCES := main.c hx711.c led.c 2 | -------------------------------------------------------------------------------- /3d/cell.ipt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/3d/cell.ipt -------------------------------------------------------------------------------- /3d/cleat.ipt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/3d/cleat.ipt -------------------------------------------------------------------------------- /3d/foot.iam: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/3d/foot.iam -------------------------------------------------------------------------------- /3d/foot.ipt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/3d/foot.ipt -------------------------------------------------------------------------------- /3d/jauge.ipt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/3d/jauge.ipt -------------------------------------------------------------------------------- /docs/3d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/3d.png -------------------------------------------------------------------------------- /docs/board.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/board.odg -------------------------------------------------------------------------------- /docs/board.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/board.pdf -------------------------------------------------------------------------------- /docs/board.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/board.png -------------------------------------------------------------------------------- /electronics/gerber/dimension.txt: -------------------------------------------------------------------------------- 1 | The board is 60 x 44 mm 2 | 200 SMT 3 | 30 TH 4 | -------------------------------------------------------------------------------- /firmware/bin/flash.sh: -------------------------------------------------------------------------------- 1 | sudo avrdude -c avrisp2 -p m328pb -P usb -U flash:w:build/$1:r 2 | -------------------------------------------------------------------------------- /3d/nylon_spacer.ipt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/3d/nylon_spacer.ipt -------------------------------------------------------------------------------- /docs/full-bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/full-bridge.png -------------------------------------------------------------------------------- /docs/half-bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/half-bridge.png -------------------------------------------------------------------------------- /docs/src/gauges.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/src/gauges.odg -------------------------------------------------------------------------------- /electronics/BOM.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/electronics/BOM.xlsx -------------------------------------------------------------------------------- /firmware/build/flash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/firmware/build/flash -------------------------------------------------------------------------------- /docs/sigmaban_foot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/docs/sigmaban_foot.png -------------------------------------------------------------------------------- /electronics/BOM_3p.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/electronics/BOM_3p.xlsx -------------------------------------------------------------------------------- /misc/crtatmega328pb.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/misc/crtatmega328pb.o -------------------------------------------------------------------------------- /misc/libatmega328pb.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/misc/libatmega328pb.a -------------------------------------------------------------------------------- /firmware/bin/firmware_123.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/firmware/bin/firmware_123.bin -------------------------------------------------------------------------------- /firmware/bin/firmware_124.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/firmware/bin/firmware_124.bin -------------------------------------------------------------------------------- /electronics/gerber/forcefoot_gerber.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Rhoban/ForceFoot/HEAD/electronics/gerber/forcefoot_gerber.zip -------------------------------------------------------------------------------- /firmware/src/main/led.h: -------------------------------------------------------------------------------- 1 | #ifndef _LED_H 2 | #define _LED_H 3 | 4 | void led_init(); 5 | void led_set(int en); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /firmware/src/uart/dir.h: -------------------------------------------------------------------------------- 1 | #ifndef _UART_DIR_H 2 | #define _UART_DIR_H 3 | 4 | void dir_set(int en); 5 | void dir_init(); 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /firmware/src/util/out.h: -------------------------------------------------------------------------------- 1 | #ifndef _OUT_H 2 | #define _OUT_H 3 | 4 | void out_int(int i); 5 | void out_str(char *s); 6 | 7 | #endif // _OUT_H 8 | -------------------------------------------------------------------------------- /firmware/fuse-m328p.sh: -------------------------------------------------------------------------------- 1 | # Configure the fuses of the ATMEGA to use the external quartz 2 | sudo avrdude -p m328p -P usb -c avrisp2 -U lfuse:w:0b11101111:m 3 | -------------------------------------------------------------------------------- /firmware/fuse-m328pb.sh: -------------------------------------------------------------------------------- 1 | # Configure the fuses of the ATMEGA to use the external quartz 2 | sudo avrdude -p m328pb -P usb -c avrisp2 -U lfuse:w:0b11101111:m 3 | -------------------------------------------------------------------------------- /firmware/Makefile.config: -------------------------------------------------------------------------------- 1 | MODULES := uart util main terminal dxl 2 | 3 | MCU_TARGET := atmega328pb 4 | 5 | F_CPU := 16000000 6 | 7 | DEFS := -DBAUDRATE=1000000 -DNO_ADC 8 | -------------------------------------------------------------------------------- /firmware/src/main/hx711.h: -------------------------------------------------------------------------------- 1 | #ifndef _HX_711_H 2 | #define _HX_711_H 3 | 4 | #include 5 | 6 | extern int32_t hx711_values[4]; 7 | void hx711_init(); 8 | void hx711_tick(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /firmware/src/main/led.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "led.h" 3 | 4 | void led_init() 5 | { 6 | // DDRD |= _BV(PD5); 7 | } 8 | 9 | void led_set(int en) 10 | { 11 | // if (en) PORTD |= _BV(PD5); 12 | // if (!en) PORTD &= ~_BV(PD5); 13 | } 14 | -------------------------------------------------------------------------------- /firmware/src/util/pgmspace.h: -------------------------------------------------------------------------------- 1 | #ifndef _UTIL_PGMSPACE_H 2 | #define _UTIL_PGMSPACE_H 3 | 4 | /** 5 | * Reads an object from the pgmspace to a destination 6 | */ 7 | void pgm_read_object(void *dest, const void *address, int size); 8 | 9 | /** 10 | * Reads a string from the pgmspace to a destination 11 | */ 12 | void pgm_read_string(char *str, const void *address, int size); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /atmega328pb-update.sh: -------------------------------------------------------------------------------- 1 | echo "deb http://archive.ubuntu.com/ubuntu/ bionic main restricted universe multiverse" > /etc/apt/sources.list.d/tmp.list 2 | apt-get update 3 | apt-get install -y gcc-avr avrdude avr-libc 4 | rm /etc/apt/sources.list.d/tmp.list 5 | apt-get update 6 | cp /etc/avrdude.conf /etc/avrdude_save.conf 7 | cp misc/avrdude.conf /etc/ 8 | cp misc/*.h /usr/lib/avr/include/avr/ 9 | cp misc/crtatmega328pb.o misc/libatmega328pb.a /usr/lib/avr/lib/avr5/ 10 | -------------------------------------------------------------------------------- /firmware/src/util/out.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void out_int(int i) 5 | { 6 | char buf[16] = {0}; 7 | char *pos = buf + 14; 8 | 9 | if (i < 0) { 10 | uart_putc('-'); 11 | i *= -1; 12 | } 13 | 14 | if (i == 0) { 15 | uart_putc('0'); 16 | } else { 17 | while (i) { 18 | *(pos--) = (i%10) + '0'; 19 | i /= 10; 20 | } 21 | 22 | uart_puts(pos+1); 23 | } 24 | } 25 | 26 | void out_str(char *s) 27 | { 28 | uart_puts(s); 29 | } 30 | -------------------------------------------------------------------------------- /firmware/src/util/pgmspace.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void pgm_read_object(void *dest, const void *address, int size) 5 | { 6 | unsigned int i; 7 | 8 | for (i=0; i 2 | #include 3 | #include 4 | #include "dir.h" 5 | 6 | void dir_set(int en) 7 | { 8 | if (!en) { 9 | // Waits for the TX buffer to be empty 10 | while (uart_tx_has_data()); 11 | } else { 12 | // Disable receiver 13 | uart_enable_receiver(0); 14 | } 15 | 16 | _delay_us(20); 17 | if (en) PORTD |= _BV(PD2); 18 | else PORTD &= ~_BV(PD2); 19 | _delay_us(20); 20 | 21 | if (!en) { 22 | // Enables the receiver 23 | uart_enable_receiver(1); 24 | } 25 | } 26 | 27 | void dir_init() 28 | { 29 | dir_set(0); 30 | DDRD |= _BV(PD2); 31 | } 32 | -------------------------------------------------------------------------------- /firmware/src/terminal_main/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main (void) 15 | { 16 | wdt_disable(); 17 | 18 | cli(); 19 | // Initializing UART 20 | uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(BAUDRATE, F_CPU)); 21 | sei(); 22 | 23 | #ifndef NO_ADC 24 | adc_run(1); 25 | #endif 26 | 27 | printf("\r\nStarting!\r\n"); 28 | terminal_init(); 29 | 30 | while (1) { 31 | terminal_tick(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Force foot 2 | 3 | **Note that this is the v2 version, you can have a look at the v1 branch for 4 | the previous release** 5 | 6 | Here is a design of a robot foot using strain gauges as force sensors. 7 | It was used by the Rhoban Football Club (France) during the RoboCup 2016. 8 | 9 | If you have any question feel free to contact team@rhoban.com to ask it, 10 | or open an issue on this repository. 11 | 12 | ![force foot](docs/sigmaban_foot.png) 13 | 14 | ## Repository contents 15 | 16 | Here are the repository contents, you can click on below links to get the documentation: 17 | 18 | * A [**mechanical design**](3d) suitable for Rhoban robots, that can be a good base 19 | to be adapted to fit your needs; 20 | * Schematics for an  [**electronics board**](electronics) containing all the components to get 21 | the values from the sensors and communicate them through dynamixel; 22 | * A [**firmware**](firmware) for the controller that is on the electronics. 23 | 24 | -------------------------------------------------------------------------------- /firmware/src/dxl/types.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* types.h */ 3 | /* Author : Olivier Ly */ 4 | /* Date : 2007/02 */ 5 | /*****************************************************************************/ 6 | #ifndef TYPES_H 7 | #define TYPES_H 8 | 9 | /*****************************************************************************/ 10 | /*! Types */ 11 | /*****************************************************************************/ 12 | 13 | /*! \name Base Types */ /*@{*/ 14 | 15 | /*! \brief Unsigned integer on 8 bits */ 16 | typedef unsigned char ui8; 17 | /*! \brief Unsigned integer on 16 bits */ 18 | typedef unsigned short ui16; 19 | /*! \brief Unsigned integer on 16 bits */ 20 | typedef unsigned int ui32; 21 | 22 | #define ui8_max(a,b) ((a 4 | 5 | #define TERMINAL_BUFFER_SIZE 64 6 | #define TERMINAL_MAX_COMMANDS 32 7 | 8 | /** 9 | * Prototype of a terminal command 10 | */ 11 | typedef void terminal_command_func(char *parameters); 12 | 13 | /** 14 | * A command definition for the terminal 15 | */ 16 | struct terminal_command 17 | { 18 | const char *name; 19 | const char *description; 20 | terminal_command_func *command; 21 | }; 22 | 23 | /** 24 | * Registers a command 25 | */ 26 | void terminal_register(const struct terminal_command *command); 27 | 28 | #define TERMINAL_COMMAND(name, description) terminal_command_func terminal_command_ ## name; \ 29 | \ 30 | PROGMEM const char terminal_command_name_ ## name [] = #name; \ 31 | PROGMEM const char terminal_command_description_ ## name [] = description; \ 32 | \ 33 | PROGMEM const struct terminal_command terminal_command_definition_ ## name = { \ 34 | terminal_command_name_ ## name , terminal_command_description_ ## name , terminal_command_ ## name \ 35 | }; \ 36 | \ 37 | __attribute__((constructor)) \ 38 | void terminal_command_init_ ## name () { \ 39 | terminal_register(&terminal_command_definition_ ## name ); \ 40 | } \ 41 | \ 42 | void terminal_command_ ## name (char *parameters) 43 | 44 | /** 45 | * Terminal ticking 46 | */ 47 | void terminal_tick(); 48 | 49 | /** 50 | * Initializing terminal 51 | */ 52 | void terminal_init(); 53 | 54 | #endif // _TERMINAL_H 55 | -------------------------------------------------------------------------------- /firmware/src/dxl/registers.h: -------------------------------------------------------------------------------- 1 | #ifndef DXL_REGISTERS_H 2 | #define DXL_REGISTERS_H 3 | 4 | __attribute__((packed)) 5 | struct dxl_registers 6 | { 7 | volatile struct dxl_eeprom { 8 | unsigned short modelNumber; 9 | unsigned char firmwareVersion; 10 | unsigned char id; 11 | unsigned char baudrate; 12 | unsigned char returnDelay; 13 | unsigned short cwLimit; 14 | unsigned short ccwLimit; 15 | unsigned char _dummy; 16 | unsigned char temperatureLimit; 17 | unsigned char lowestVoltage; 18 | unsigned char highestVoltage; 19 | unsigned short maxTorque; 20 | unsigned char returnStatus; 21 | unsigned char alarmLed; 22 | unsigned char alarmShutdown; 23 | } eeprom; 24 | 25 | volatile unsigned char _dummy2[5]; 26 | 27 | volatile struct dxl_ram { 28 | unsigned char torqueEnable; 29 | unsigned char led; 30 | unsigned char cwComplianceMargin; 31 | unsigned char ccwComplianceMargin; 32 | unsigned char cwComplianceSlope; 33 | unsigned char ccwComplianceSlope; 34 | unsigned short goalPosition; 35 | unsigned short movingSpeed; 36 | unsigned short torqueLimit; 37 | unsigned short presentPosition; 38 | unsigned short presentSpeed; 39 | unsigned short presentLoad; 40 | unsigned char presentVoltage; 41 | unsigned char presentTemperature; 42 | unsigned char registeredInstruction; 43 | unsigned char _dummy3; 44 | unsigned char moving; 45 | unsigned char lock; 46 | unsigned short punch; 47 | } ram; 48 | 49 | volatile char eeprom_dirty; 50 | }; 51 | 52 | #endif // DXL_REGISTERS_H 53 | -------------------------------------------------------------------------------- /firmware/Makefile: -------------------------------------------------------------------------------- 1 | include Makefile.config 2 | 3 | CC := avr-gcc 4 | LD := avr-gcc 5 | OBJCOPY := avr-objcopy 6 | 7 | SRC_DIR := $(addprefix src/,$(MODULES)) 8 | BUILD_DIR := $(addprefix build/,$(MODULES)) 9 | 10 | DEFS += -DF_CPU=$(F_CPU) 11 | LIBS := 12 | 13 | SRC := 14 | OBJ := 15 | INCLUDES := -Isrc/ 16 | add-src = $(eval include src/$1/Makefile.sources); \ 17 | $(eval SRC += $(addprefix src/$1/,$(SOURCES))); \ 18 | $(eval OBJ += $(addprefix build/$1/,$(subst .S,.o,$(subst .cpp,.o,$(subst .c,.o,$(SOURCES)))))); \ 19 | 20 | $(foreach module,$(MODULES),$(call add-src,$(module))) 21 | 22 | override CFLAGS := -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -O2 23 | override LDFLAGS := -Wl,-Map,$(PRG).map 24 | 25 | vpath %.c $(SRC_DIR) 26 | 27 | 28 | all: checkdirs build/flash.bin 29 | 30 | build/flash.bin: build/flash 31 | $(OBJCOPY) -j .text -j .data -O binary $< $@ 32 | 33 | build/flash: $(OBJ) 34 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) 35 | 36 | checkdirs: $(BUILD_DIR) 37 | 38 | define make-goal 39 | $1/%.o: $2/%.cpp 40 | $(CPP) $(CFLAGS) $(DEFS) $(INCLUDES) -c $$< -o $$@ 41 | 42 | $1/%.o: $2/%.c 43 | $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) -c $$< -o $$@ 44 | 45 | $1/%.o: $2/%.S 46 | $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) -c $$< -o $$@ 47 | endef 48 | 49 | $(BUILD_DIR): 50 | @mkdir -p $@ 51 | 52 | clean: 53 | @rm -rf build/* 54 | 55 | $(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir),$(patsubst build/%,src/%,$(bdir))))) 56 | 57 | sendisp: 58 | avrdude -c usbtiny -p $(MCU_TARGET) -U flash:w:build/flash.bin:r 59 | 60 | sendu: 61 | avrdude -c arduino -p $(MCU_TARGET) -P /dev/ttyUSB0 -U flash:w:build/flash.bin:r 62 | 63 | send: 64 | avrdude -c arduino -p $(MCU_TARGET) -P /dev/ttyACM0 -U flash:w:build/flash.bin:r 65 | 66 | sendi: erasei 67 | sudo avrdude -c avrisp2 -p $(MCU_TARGET) -P usb -U flash:w:build/flash.bin:r 68 | 69 | sendd: 70 | ./dynamixel/flash /dev/ttyUSB0 build/flash.bin 71 | 72 | erasei: 73 | sudo avrdude -c avrisp2 -p $(MCU_TARGET) -P usb -e 74 | -------------------------------------------------------------------------------- /electronics/gerber/forcefoot.txt: -------------------------------------------------------------------------------- 1 | C1 6.55 17.41 0 1uF 0805 2 | C2 9.35 7.75 0 1uF 0805 3 | C3 1.60 2.40 90 1uF 0805 4 | C4 12.33 7.85 0 0.1uF 0805 5 | C5 19.63 17.39 0 1uF 0805 6 | C6 22.16 7.70 0 1uF 0805 7 | C7 14.09 2.15 90 1uF 0805 8 | C8 25.07 7.75 0 0.1uF 0805 9 | C9 38.14 17.44 0 1uF 0805 10 | C10 41.76 7.93 0 1uF 0805 11 | C11 34.16 2.05 90 1uF 0805 12 | C12 44.76 8.04 0 0.1uF 0805 13 | C13 51.14 17.77 0 1uF 0805 14 | C14 54.96 8.36 0 1uF 0805 15 | C15 46.93 2.65 90 1uF 0805 16 | C16 57.76 8.37 0 0.1uF 0805 17 | C17 21.80 27.20 90 22 C0603 18 | C18 21.80 23.80 270 22 C0603 19 | HX1 9.00 12.60 90 HX711SO16 SO16 20 | HX2 22.26 12.63 90 HX711SO16 SO16 21 | HX3 40.46 12.91 90 HX711SO16 SO16 22 | HX4 53.73 13.11 90 HX711SO16 SO16 23 | MAX485 7.40 28.20 0 MAX485 SO8 24 | R1 2.40 28.20 90 3k R0805 25 | R2 6.60 33.20 180 3k R0805 26 | R3 11.46 5.11 270 1k 0805 27 | R4 19.13 7.81 180 20k 0805 28 | R5 20.74 5.61 180 8.2k 0805 29 | R6 24.07 5.01 270 1k 0805 30 | R7 38.73 7.86 180 20k 0805 31 | R8 40.16 5.87 180 8.2k 0805 32 | R9 44.23 5.45 270 1k 0805 33 | R10 51.83 8.43 180 20k 0805 34 | R11 53.66 6.24 180 8.2k 0805 35 | R12 58.26 5.55 270 1k 0805 36 | R13 7.60 24.20 0 3k R0805 37 | R14 13.20 27.20 180 22 R0805 38 | R15 13.20 29.40 180 22 R0805 39 | R16 6.19 7.76 180 20k 0805 40 | R17 7.26 5.72 180 8.2k 0805 41 | R18 11.00 33.20 180 3k R0805 42 | R19 5.90 3.90 0 3K 0805 43 | R20 3.60 2.40 90 3K 0805 44 | R21 18.20 4.00 0 3K 0805 45 | R22 16.00 2.10 90 3K 0805 46 | R23 38.20 4.20 0 3K 0805 47 | R24 36.20 2.00 90 3K 0805 48 | R25 51.60 4.20 0 3K 0805 49 | R26 49.00 2.60 90 3K 0805 50 | R27 38.20 27.20 90 10k 0805 51 | R28 40.60 32.20 0 3K 0805 52 | R29 40.60 30.80 0 3K 0805 53 | U$1 2.54 6.68 90 8550-PNP SOT-23 54 | U$2 46.80 27.60 90 47uF PANASONIC_D 55 | U$4 12.40 39.40 180 220uF PANASONIC_D8 56 | U$6 15.58 6.88 90 8550-PNP SOT-23 57 | U$9 34.95 7.07 90 8550-PNP SOT-23 58 | U$12 48.12 6.87 90 8550-PNP SOT-23 59 | U2 30.20 25.50 0 ATMEGA168 TQFP32-08 60 | -------------------------------------------------------------------------------- /firmware/src/dxl/byte_queue.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* Byte queue */ 3 | /* Date : 2008/07 */ 4 | /*****************************************************************************/ 5 | #ifndef QUEUE_H 6 | #define QUEUE_H 7 | 8 | /* General use ui8 queue. 9 | * The queue size must be less than 255 byte, because of the size of 10 | * the indexes */ 11 | 12 | /*****************************************************************************/ 13 | /* Data Structure */ 14 | /*****************************************************************************/ 15 | 16 | /* Note that the real size of the queue is size-1. Indeed, in order to save space 17 | we do not use any indicator to distinguish the empty state from the full state. 18 | Therefore, we forbid q_end to come over q_start after a complete turn of the 19 | queue. */ 20 | 21 | typedef struct { 22 | ui8 * q_buffer; 23 | int q_size; 24 | int q_start; 25 | int q_end; 26 | } ui8_queue; 27 | 28 | /*****************************************************************************/ 29 | /* Interface */ 30 | /*****************************************************************************/ 31 | int incr_queue_index(ui8_queue * queue, int i); 32 | 33 | void init_queue(ui8_queue * queue, ui8 * buffer, int size); 34 | void reset_queue(ui8_queue * queue); 35 | int queue_byte_nb(ui8_queue * queue); 36 | 37 | /* get a new byte from the queue. 38 | * Caution: if the queue is empty, return 0. */ 39 | ui8 queue_get_byte(ui8_queue * queue); 40 | 41 | /* get the nth byte from the beginning of the queue */ 42 | ui8 queue_get_nth_byte(ui8_queue * queue, int n); 43 | void queue_push_byte(ui8_queue * queue, ui8 b); 44 | 45 | #endif /* QUEUE_H */ 46 | /*****************************************************************************/ 47 | /*****************************************************************************/ 48 | -------------------------------------------------------------------------------- /firmware/src/dxl/dxl.h: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* protocol.h 3 | * Dynamixel protocol 4 | * 5 | * Date: 2012/03 6 | * Rhoban Project 7 | *****************************************************************************/ 8 | #ifndef DXL_H 9 | #define DXL_H 10 | #include 11 | 12 | // Dynamixel registers 13 | #define DXL_MODEL_NB_ADDR 0 14 | #define DXL_TORQUE_ENABLE 24 15 | #define DXL_GOAL_POSITION 30 16 | #define DXL_LED 25 17 | 18 | // A dynamixel packet representation 19 | struct dxl_packet { 20 | ui8 id; 21 | union { 22 | ui8 instruction; 23 | ui8 error; 24 | }; 25 | ui8 parameter_nb; 26 | ui8 parameters[256]; 27 | }; 28 | 29 | // Enable bufferization ? 30 | //#define DXL_BUFFERIZE 31 | 32 | // I/O buffer sizes 33 | #ifdef DXL_BUFFERIZE 34 | #define DXL_INCOMING_BUFFER_SIZE 1024 35 | #define DXL_OUTGOING_PAQUET_SIZE 1024 36 | #endif 37 | 38 | // Initialize the dxl module 39 | void dxl_init(); 40 | 41 | // Push an incoming byte to the dynamixel protocol 42 | void dxl_push_incoming_byte(ui8 b); 43 | 44 | // Run the scheduler on the buffer 45 | void dxl_protocol_scheduler(); 46 | 47 | // Protocol status 48 | #define DXL_COMMAND_AVOIDED 0 49 | #define DXL_ERROR 1 50 | #define DXL_CHECKSUM_ERROR 2 51 | #define DXL_HEAD_ERROR 3 52 | #define DXL_INCOMING_QUEUE_OVERFLOW 4 53 | 54 | extern ui8 protocol_status; 55 | #define dxl_check_protocol_status(bit) (protocol_status & (1 << bit)) 56 | #define dxl_set_protocol_status(bit) (protocol_status = (protocol_status | (1 << bit))) 57 | void dxl_reset_protocol_status(); 58 | 59 | /** 60 | * Methods to implement 61 | */ 62 | 63 | // Is this id handled by the module ? 64 | ui8 dxl_check_id(ui8 id); 65 | 66 | // The dynamixel module sends a packet (through UART for instance) 67 | void dxl_send_bytes(ui8 * bytes, ui8 nb); 68 | 69 | // Write in some registers 70 | void dxl_write_data(ui8 id, ui8 addr, ui8 *values, ui8 length); 71 | 72 | // A register is read 73 | void dxl_read_data(ui8 id, ui8 addr, ui8 *values, ui8 length, ui8 *error); 74 | 75 | #endif // DXL_H 76 | -------------------------------------------------------------------------------- /firmware/src/dxl/byte_queue.c: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* Byte queue */ 3 | /* Author : Olivier Ly */ 4 | /* Date : 2008/07 */ 5 | /*****************************************************************************/ 6 | #include 7 | #include 8 | 9 | inline 10 | int incr_queue_index(ui8_queue * queue, int i) { 11 | register int idx = i; 12 | idx++; 13 | if (idx == queue->q_size) 14 | idx=0; 15 | return idx; 16 | } 17 | 18 | void init_queue(ui8_queue * queue, ui8 * buffer, int size) { 19 | queue->q_buffer = buffer; 20 | queue->q_size = size; 21 | reset_queue(queue); 22 | } 23 | 24 | void reset_queue(ui8_queue * queue) { 25 | queue->q_start=0; 26 | queue->q_end=0; 27 | } 28 | 29 | int queue_byte_nb(ui8_queue * queue) { 30 | if (queue->q_end >= queue->q_start) 31 | return queue->q_end - queue->q_start; 32 | else 33 | return queue->q_end + (queue->q_size - queue->q_start); 34 | } 35 | 36 | ui8 queue_get_byte(ui8_queue * queue) { 37 | if (queue->q_start == queue->q_end) 38 | return 0; 39 | 40 | ui8 c = queue->q_buffer[queue->q_start]; 41 | queue->q_start = incr_queue_index(queue, queue->q_start); 42 | return c; 43 | } 44 | 45 | ui8 queue_get_nth_byte(ui8_queue * queue, int n) { 46 | if (n >= queue_byte_nb(queue)) return 0; // ERROR 47 | 48 | register int idx = queue->q_start + n; 49 | if (idx > queue->q_size) 50 | idx = idx - queue->q_size; 51 | return queue->q_buffer[idx]; 52 | } 53 | 54 | /* TODO : error if the queue is full */ 55 | void queue_push_byte(ui8_queue * queue, ui8 b) { 56 | int idx = incr_queue_index(queue, queue->q_end); 57 | 58 | if (idx == queue->q_start) { /* if the queue is full, error */ 59 | // TODO: queue overfull error 60 | return; 61 | } 62 | 63 | queue->q_buffer[queue->q_end] = b; 64 | queue->q_end = idx; 65 | } 66 | 67 | 68 | /*****************************************************************************/ 69 | /*****************************************************************************/ 70 | -------------------------------------------------------------------------------- /firmware/src/main/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "hx711.h" 16 | #include "led.h" 17 | 18 | #define DXL_MODEL 5004 19 | #define DXL_ID 124 20 | // #define DXL_RETURN_DELAY 250 21 | 22 | // Dynamixel registers 23 | struct dxl_registers registers; 24 | 25 | // Is this id handled by the module ? 26 | ui8 dxl_check_id(ui8 id) 27 | { 28 | return (id == DXL_ID); 29 | } 30 | 31 | // Write in some registers 32 | void dxl_write_data(ui8 id, ui8 addr, ui8 *values, ui8 length) 33 | { 34 | // XXX: Ignored 35 | } 36 | 37 | static void putValue(int32_t val, unsigned char *data) 38 | { 39 | data[0] = (val >> 0)&0xff; 40 | data[1] = (val >> 8)&0xff; 41 | data[2] = (val >> 16)&0xff; 42 | } 43 | 44 | // A register is read 45 | void dxl_read_data(ui8 id, ui8 addr, ui8 *values, ui8 length, ui8 *error) 46 | { 47 | *error = 0; 48 | 49 | #ifdef DXL_RETURN_DELAY 50 | _delay_us(DXL_RETURN_DELAY); 51 | #endif 52 | 53 | int k; 54 | unsigned char *rvalues = ®isters.ram.presentPosition; 55 | for (k=0; k<4; k++) { 56 | putValue(hx711_values[k], rvalues+3*k); 57 | } 58 | 59 | memcpy(values, ((ui8*)®isters)+addr, length); 60 | } 61 | 62 | int main (void) 63 | { 64 | wdt_disable(); 65 | // Direction pin 66 | dir_set(0); 67 | dir_init(); 68 | 69 | cli(); 70 | // Initializing UART 71 | uart_init(UART_BAUD_SELECT_DOUBLE_SPEED(BAUDRATE, F_CPU)); 72 | sei(); 73 | 74 | // Registers 75 | registers.eeprom.id = DXL_ID; 76 | registers.eeprom.modelNumber = DXL_MODEL; 77 | registers.eeprom.firmwareVersion = 1; 78 | 79 | // Initializing DXL module 80 | dxl_init(); 81 | 82 | // Initializing HX711s 83 | hx711_init(); 84 | 85 | led_init(); 86 | 87 | while (1) { 88 | // Reading the balances 89 | hx711_tick(); 90 | 91 | // Reading serial data 92 | while (uart_available()) { 93 | ui8 c = uart_getc()&0xff; 94 | dxl_push_incoming_byte(c); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /3d/README.md: -------------------------------------------------------------------------------- 1 | # 3D design 2 | 3 | ![3d](../docs/3d.png) 4 | 5 | This is 3D designs for a foot. The files were created using Autodesk Inventor 6 | 2015 CAD software. If you are student, you can get a free version here: 7 | http://www.autodesk.com/education/free-software/all 8 | 9 | This design can be used as a reference or "as-is", if you decide to buy the 10 | same gauges. 11 | 12 | ## Sourcing the gauges 13 | 14 | The design is based on [Strain gauges](https://en.wikipedia.org/wiki/Strain_gauge). 15 | You can buy the sensor itself separately, and also find it with mechanical 16 | (mostly aluminium) shaft, we recommend this last option since it's not expansive 17 | and already guarantee to have a correct bending. 18 | 19 | The first thing you'll need is to get gauges fitting your needs, we used 5kg 20 | nominal, which is about the maximum weight that they should have to hold 21 | separately. 22 | 23 | You can buy low-cost ones from AliExpress, 24 | eBay or any general purpose market place. 25 | 26 | There is different gauges out there, we recommend suing 27 | differential ones (featuring wheatstone bridge arrangement, 4 wires). 28 | 29 | ## Cells of this design 30 | 31 | The cells in this design are 40 kg nominal, made of steel with 2 M4 holes with 32 | 27mm spacing 33 | 34 | They can be found under the reference "HL703" or "TAL230A" 35 | 36 | * [eBay](http://www.ebay.fr/itm/40kg-Aluminium-Alloy-Portable-Rectangle-Kitchen-Scale-Weight-Sensor-Load-Cell-/311507964552?hash=item4887525288:g:QxYAAOSwY3BZEuAr) 37 | * [AliExpress](https://www.aliexpress.com/item/10pcs-40kg-weight-sensor-miniature-full-bridge-sensor-weighing-force-sensor-freeshipping/32498871281.html?spm=2114.01010208.3.126.DWqRNl&ws_ab_test=searchweb0_0,searchweb201602_5_10152_10065_10151_10068_5010015_10136_10137_10157_10060_10138_10155_10062_10156_437_10154_10056_10055_10054_10059_303_100031_10099_10103_10102_10101_10096_10147_10052_10053_10107_10050_10142_10051_5020016_10084_10083_10080_10082_10081_10177_10110_519_10111_10112_10113_10114_10180_10182_10185_10184_10078_10079_10073_10186_10123_142,searchweb201603_2,ppcSwitch_5&btsid=9c118a6d-5c25-40a6-ae97-44e3d203d671&algo_expid=1c5b80d4-c289-412d-ace7-c203356e1b79-17&algo_pvid=1c5b80d4-c289-412d-ace7-c203356e1b79) 38 | 39 | ## Foot part 40 | 41 | ### OnShape model 42 | 43 | You can check out the Sigmaban humanoid model on OnShape to see the current mounting 44 | of the Rhoban team foot force sensors: 45 | 46 | * [OnShape Sigmaban public assembly](https://cad.onshape.com/documents/f3bdef32bffd81536fce83d1/v/779c691df8f135bba01eead1/e/a530b1889ee09acb5e1d7ff9) 47 | 48 | ### Autodesk (old) 49 | 50 | The `foot.ipt` represents the foot plate, we recommend adjusting 51 | the holes to fix it to the rest of your robot. 52 | 53 | When printing it, you may fill this part with a reasonable amount of material. 54 | 55 | [Continue through the docs with electronics »](../electronics) 56 | -------------------------------------------------------------------------------- /electronics/README.md: -------------------------------------------------------------------------------- 1 | # Electronics 2 | 3 | Here you'll find the schematics and (auto)routed board for sampling the gauge and communicate 4 | through the dynamixel bus. 5 | 6 | ## Options 7 | 8 | Some optional resistors on this board can be used to support dynamixel TTL/485 and 3/4 wire 9 | gauges: 10 | 11 | ![optional features](../docs/board.png) 12 | 13 | ### Dynamixel RS485 or TTL 14 | 15 | The two resistors (see yellow zones above) are only required if you want to use TTL Dynamixel. 16 | In this case, you can solder a 3-pin connector on the dynamixel zone and it will do the job. 17 | 18 | Actually, the A pin of the RS485 transciever is exactly the same as TTL when driving the line. 19 | this change brings the B pin at VCC/2 (which should be 2.5V), so that when listening an high 20 | A is 2.5V above B and a low A is 2.5V below B, which meets the RS485 requirements and makes 21 | the MAX485 (or ST485) chip able to listen TTL, while perfectly respecting its specifications. 22 | 23 | ### 3-wire or 4-wire gauges 24 | 25 | There is two main kind of mounting, half-bridges, which looks like that: 26 | 27 | ![half-bridge](../docs/half-bridge.png) 28 | 29 | Here, there is three wire, so you'll have to compare the voltage value to 2.5V, this is why you 30 | should solder the resistors (see cyan part of the above image) which will bring A- to V+/2 and 31 | solder the third wire to A+. 32 | 33 | The another option is a full-bridge: 34 | 35 | ![full-bridge](../docs/full-bridge.png) 36 | 37 | We recommend this system since it is more accurate and robust. You'll have to solder the two 38 | wires to A- and A+. The order of soldering doesn't really matter, since it will only affect the 39 | sign of the measured value. 40 | 41 | ## Components 42 | 43 | Here's a list of components you'll need to build the board with example links for buying them 44 | 45 | ### Controller 46 | 47 | * ATmega328PB 48 | * 16 Mhz HC49US quartz 49 | 50 | ### Resistors (all are 0805 package) 51 | 52 | * 22 ohms 53 | * 3 Kohms 54 | * 8.2 Kohms 55 | * 20 Kohms 56 | 57 | ### Capacitors (all are 0805 package) 58 | 59 | * 1uF 60 | * 0.2uF 61 | * 22 pF 62 | 63 | ### Polar capacitor, for decoupling 64 | 65 | * EEE1CA470SP: 47uF 66 | * EEEFK1C221XP: 220uF 67 | 68 | ### Power 69 | 70 | You can buy a 7805, but we recommend using a switching instead, like the TRACO TSR 1-2450 71 | to avoid intensive heating. 72 | 73 | ### ICs 74 | 75 | The amps are HX711, a really widespread chip that is use in weight scales 76 | This chips regulates the reference voltage for the amp, using an external 77 | PNP transistor (SOT-23 package). S8550 or BC857B,215 can be used. 78 | 79 | ### Connectors for jauges 80 | 81 | You can use any 1.5mm pitch connector you like. We recommend the 82 | [JST-ZH 4P](https://fr.aliexpress.com/item/40-SETS-Mini-Micro-ZH-1-5-4-Pin-JST-Connector-with-Wires-Cables/32612842708.html?spm=2114.13010608.0.0.3bLgYh). 83 | 84 | Note that the order of the pins, from left to right are: 85 | 86 | GND VCC A B 87 | 88 | Which corresponds typically on cells to: 89 | 90 | BLACK RED WHITE GREEN 91 | 92 | If you use only half bridge, do not connect the 3rd (white) pin, and solder the two 93 | resistors that can apply VCC/2 on it. 94 | 95 | [Continue through the docs with the firmware »](../firmware) 96 | -------------------------------------------------------------------------------- /firmware/README.md: -------------------------------------------------------------------------------- 1 | # Firmware 2 | 3 | You will need an ICSP/ISP tool that uses the the 6-pin AVR header. We recommend 4 | that you use the AVR ISP MkII. You can also use Arduino Uno as ISP. 5 | 6 | ## Fuses 7 | 8 | The first step is configuring the fuses, in order to configure it to use the 9 | external 16Mhz quartz. You can run the fuse.sh script: 10 | 11 | ./fuse-m328p.sh 12 | 13 | Alternatively, you can use: 14 | 15 | ./fuse-m328pb.sh 16 | 17 | For the ATmega328PB 18 | 19 | This assumes you use the AVR ISP MkII, you can however change this script according 20 | to your hardware. 21 | 22 | ## Building 23 | 24 | First, edit `Makefile.config` to set `MCU_TARGET` to either `atmega328p` or `atmega328pb`. 25 | 26 | To build the firmware, simply run: 27 | 28 | make 29 | 30 | In the firmware directory 31 | 32 | ## Flashing 33 | 34 | You can flash the firmware using the: 35 | 36 | make sendisp 37 | 38 | Command, this still assumes AVR ISP MkII, you can edit the `Makefile` if you're 39 | using other hardware. 40 | 41 | ## Protocol 42 | 43 | The protocol is very straightforward, the board will appear exactly like a dynamixel 44 | servo, with a fancy model number and its own ID. 45 | 46 | Model ID, ID and baudrate are not configurable on-the-fly with the current version, it 47 | can be changed in the header of `src/main/main.c`. (Default model number 5004, id 123 and baudrate 48 | 1000000). 49 | 50 | Each gauge value is a signed 24 bit value (least significant byte first), resulting in a total 51 | of 3 bytes. Thus, the values of the four gauges are 12 bytes. These bytes can be read at the 52 | present position address of the dynamixel registers (``0x24`` / 36). 53 | 54 | 0x24 → 0x26 | 0x27 → 0x29 | 0x2a → 0x2c | 0x2d → 0x2f 55 | -------|--------|-------|-------- 56 | Jauge 1 | Jauge 2 | Jauge 3 | Jauge 4 57 | 58 | Here is an example of C code to read the values from one jauge: 59 | 60 | ```C 61 | #include 62 | 63 | // The bytes are here LSB, the same order that it appear in the dynamixel 64 | // (For instance, jauge 1 values are at dynamixel addresses 0x24 for b0, 0x25 65 | // for b1 and 0x26 for b2) 66 | int32_t decode24bits(uint8_t b0, uint8_t b1, uint8_t b2) 67 | { 68 | int32_t result = ( 69 | (b2 << 24) 70 | | (b1 << 16) 71 | | (b0 << 8) 72 | ) >> 8; 73 | 74 | return result; 75 | } 76 | ``` 77 | 78 | ## How to use the values 79 | 80 | ### Calibration 81 | 82 | Note that the values will not be trimmed, you'll have to write some code to get the 0-offset 83 | and save it somewhere. 84 | 85 | Then, you may want to calibrate each gauge using objects of known mass and applying linear 86 | regression on some values. You'll be then able to get the force, corresponding statically 87 | to the weight applied to the robot on each gauge. 88 | 89 | ### Weight 90 | 91 | An interresting value is the total weight of the robot, this can for instance tell you if your 92 | robot is on the floor or being handled. 93 | 94 | ### Weight ratio 95 | 96 | The weight ratio is the distribution of the weight over the two foots. This can be used to know 97 | what is the actual support phase during the walk (i.e which foot is actually on the ground supporting 98 | the robot). 99 | 100 | ### Center of pressure 101 | 102 | The center of pressure can be computed using barycenter of the points (the x,y of your cleats) weighted 103 | with the force applied on it. 104 | 105 | This result can be found using the sum of moments equation (a simimar problem is solved in [this 106 | thesis, page 34](http://ir.library.oregonstate.edu/xmlui/bitstream/handle/1957/29797/SchaferChristopherA2005.pdf)). 107 | 108 | -------------------------------------------------------------------------------- /firmware/src/main/hx711.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "hx711.h" 6 | 7 | int32_t hx711_values[4]; 8 | 9 | void hx711_clock_set(int index, int en) 10 | { 11 | switch (index) { 12 | case 0: 13 | if (en) PORTC |= _BV(PC0); 14 | if (!en) PORTC &= ~_BV(PC0); 15 | break; 16 | case 1: 17 | if (en) PORTC |= _BV(PC2); 18 | if (!en) PORTC &= ~_BV(PC2); 19 | break; 20 | case 2: 21 | if (en) PORTD |= _BV(PD3); 22 | if (!en) PORTD &= ~_BV(PD3); 23 | break; 24 | case 3: 25 | #if defined(__AVR_ATmega328PB__) 26 | if (en) PORTE |= _BV(PE2); 27 | if (!en) PORTE &= ~_BV(PE2); 28 | #else 29 | if (en) PORTB |= _BV(PB0); 30 | if (!en) PORTB &= ~_BV(PB0); 31 | #endif 32 | break; 33 | } 34 | } 35 | 36 | int hx711_read(int index) 37 | { 38 | switch (index) { 39 | case 0: 40 | return ((PINC&_BV(PC1))!=0); 41 | break; 42 | case 1: 43 | return ((PINC&_BV(PC3))!=0); 44 | break; 45 | case 2: 46 | return ((PIND&_BV(PD4))!=0); 47 | break; 48 | case 3: 49 | #if defined(__AVR_ATmega328PB__) 50 | return ((PINE&_BV(PE3))!=0); 51 | #else 52 | return ((PINB&_BV(PB1))!=0); 53 | #endif 54 | break; 55 | } 56 | return 0; 57 | } 58 | 59 | int hx711_available(int index) 60 | { 61 | return !hx711_read(index); 62 | } 63 | 64 | #define VALUE_SIGN(value, length) \ 65 | ((value < (1<<(length-1))) ? \ 66 | (value) \ 67 | : (value-(1<= 4) current = 0; 110 | } 111 | 112 | void hx711_init() 113 | { 114 | hx711_clock_set(0, 0); 115 | hx711_clock_set(1, 0); 116 | hx711_clock_set(2, 0); 117 | hx711_clock_set(3, 0); 118 | 119 | // Clocks as outputs 120 | DDRC |= _BV(PC0) | _BV(PC2); 121 | DDRD |= _BV(PD3); 122 | #if defined(__AVR_ATmega328PB__) 123 | DDRE |= _BV(PE2); 124 | #else 125 | DDRB |= _BV(PB0); 126 | #endif 127 | 128 | // Enabling pull up on inputs 129 | PORTC |= _BV(PC1) | _BV(PC3); 130 | PORTD |= _BV(PD4); 131 | 132 | #if defined(__AVR_ATmega328PB__) 133 | PORTE |= _BV(PE3); 134 | #else 135 | PORTB |= _BV(PB1); 136 | #endif 137 | 138 | int k; 139 | for (k=0; k<4; k++) { 140 | hx711_values[k] = 0; 141 | } 142 | 143 | /* 144 | // XXX: Debug: print all the values 145 | dir_set(1); 146 | _delay_ms(100); 147 | while (1) { 148 | int k; 149 | for (k=0; k<4; k++) { 150 | while (!hx711_available(k)); 151 | printf("%ld\t", hx711_sample(k)); 152 | } 153 | printf("\r\n"); 154 | } 155 | */ 156 | } 157 | -------------------------------------------------------------------------------- /firmware/src/terminal/terminal.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | static char terminal_buffer[TERMINAL_BUFFER_SIZE]; 14 | 15 | static unsigned int terminal_size = 0; 16 | 17 | static unsigned int terminal_pos = 0; 18 | 19 | static const struct terminal_command *terminal_commands[TERMINAL_MAX_COMMANDS]; 20 | 21 | static unsigned int terminal_command_count = 0; 22 | 23 | /** 24 | * Registers a command 25 | */ 26 | void terminal_register(const struct terminal_command *command) 27 | { 28 | terminal_commands[terminal_command_count++] = command; 29 | } 30 | 31 | /** 32 | * Internal helping command 33 | */ 34 | TERMINAL_COMMAND(help, "Displays the help about commands") 35 | { 36 | unsigned int i; 37 | 38 | uart_puts("Available commands :\r\n\r\n"); 39 | 40 | for (i=0; i 0) { 124 | terminal_execute(terminal_buffer, command_name_length, parameters); 125 | } 126 | 127 | terminal_pos = 0; 128 | terminal_size = 0; 129 | terminal_prompt(); 130 | } 131 | 132 | /** 133 | * Ticking the terminal, this will cause lookup for characters and eventually 134 | * a call to the process function on new lines 135 | */ 136 | void terminal_tick() 137 | { 138 | unsigned int uartChar; 139 | char c; 140 | 141 | while ((uartChar = uart_getc()) != UART_NO_DATA) { 142 | c = uartChar & 0xff; 143 | 144 | if (c == '\r' || c == '\n') { 145 | terminal_buffer[terminal_pos] = '\0'; 146 | terminal_process(); 147 | } else if (c == '\x7f') { 148 | if (terminal_pos > 0) { 149 | terminal_pos--; 150 | terminal_size--; 151 | ///dir_set(1); 152 | //uart_puts("\x8 \x8"); 153 | //dir_set(0); 154 | } 155 | } else { 156 | terminal_buffer[terminal_pos] = c; 157 | dir_set(1); 158 | uart_putc(c); 159 | dir_set(0); 160 | 161 | if (terminal_pos < TERMINAL_BUFFER_SIZE-1) { 162 | terminal_pos++; 163 | } 164 | 165 | if (terminal_size < terminal_pos) { 166 | terminal_size = terminal_pos; 167 | } 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /firmware/src/uart/uart.h: -------------------------------------------------------------------------------- 1 | #ifndef UART_H 2 | #define UART_H 3 | /************************************************************************ 4 | Title: Interrupt UART library with receive/transmit circular buffers 5 | Author: Peter Fleury http://jump.to/fleury 6 | File: $Id: uart.h,v 1.8.2.1 2007/07/01 11:14:38 peter Exp $ 7 | Software: AVR-GCC 4.1, AVR Libc 1.4 8 | Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz 9 | License: GNU General Public License 10 | Usage: see Doxygen manual 11 | 12 | LICENSE: 13 | Copyright (C) 2006 Peter Fleury 14 | 15 | This program is free software; you can redistribute it and/or modify 16 | it under the terms of the GNU General Public License as published by 17 | the Free Software Foundation; either version 2 of the License, or 18 | any later version. 19 | 20 | This program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | ************************************************************************/ 26 | 27 | /** 28 | * @defgroup pfleury_uart UART Library 29 | * @code #include @endcode 30 | * 31 | * @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. 32 | * 33 | * This library can be used to transmit and receive data through the built in UART. 34 | * 35 | * An interrupt is generated when the UART has finished transmitting or 36 | * receiving a byte. The interrupt handling routines use circular buffers 37 | * for buffering received and transmitted data. 38 | * 39 | * The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define 40 | * the size of the circular buffers in bytes. Note that these constants must be a power of 2. 41 | * You may need to adapt this constants to your target and your application by adding 42 | * CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile. 43 | * 44 | * @note Based on Atmel Application Note AVR306 45 | * @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury 46 | */ 47 | 48 | /**@{*/ 49 | 50 | 51 | #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 52 | #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" 53 | #endif 54 | 55 | 56 | /* 57 | ** constants and macros 58 | */ 59 | 60 | /** @brief UART Baudrate Expression 61 | * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz 62 | * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 63 | */ 64 | #define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) 65 | 66 | /** @brief UART Baudrate Expression for ATmega double speed mode 67 | * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz 68 | * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 69 | */ 70 | #define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000) 71 | 72 | 73 | /** Size of the circular receive buffer, must be power of 2 */ 74 | #ifndef UART_RX_BUFFER_SIZE 75 | #define UART_RX_BUFFER_SIZE 64 76 | #endif 77 | /** Size of the circular transmit buffer, must be power of 2 */ 78 | #ifndef UART_TX_BUFFER_SIZE 79 | #define UART_TX_BUFFER_SIZE 64 80 | #endif 81 | 82 | /* test if the size of the circular buffers fits into SRAM */ 83 | #if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) 84 | #error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM " 85 | #endif 86 | 87 | /* 88 | ** high byte error return code of uart_getc() 89 | */ 90 | #define UART_FRAME_ERROR 0x0800 /* Framing Error by UART */ 91 | #define UART_OVERRUN_ERROR 0x0400 /* Overrun condition by UART */ 92 | #define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */ 93 | #define UART_NO_DATA 0x0100 /* no receive data available */ 94 | 95 | // Is there data in the output buffer? 96 | int uart_tx_has_data(); 97 | 98 | // Enable/Disable the receiver 99 | void uart_enable_receiver(int en); 100 | 101 | /* 102 | ** function prototypes 103 | */ 104 | 105 | /** 106 | @brief Initialize UART and set baudrate 107 | @param baudrate Specify baudrate using macro UART_BAUD_SELECT() 108 | @return none 109 | */ 110 | extern void uart_init(unsigned int baudrate); 111 | 112 | 113 | /** 114 | * @brief Get received byte from ringbuffer 115 | * 116 | * Returns in the lower byte the received character and in the 117 | * higher byte the last receive error. 118 | * UART_NO_DATA is returned when no data is available. 119 | * 120 | * @param void 121 | * @return lower byte: received byte from ringbuffer 122 | * @return higher byte: last receive status 123 | * - \b 0 successfully received data from UART 124 | * - \b UART_NO_DATA 125 | *
no receive data available 126 | * - \b UART_BUFFER_OVERFLOW 127 | *
Receive ringbuffer overflow. 128 | * We are not reading the receive buffer fast enough, 129 | * one or more received character have been dropped 130 | * - \b UART_OVERRUN_ERROR 131 | *
Overrun condition by UART. 132 | * A character already present in the UART UDR register was 133 | * not read by the interrupt handler before the next character arrived, 134 | * one or more received characters have been dropped. 135 | * - \b UART_FRAME_ERROR 136 | *
Framing Error by UART 137 | */ 138 | extern unsigned int uart_getc(void); 139 | 140 | extern int uart_available(); 141 | 142 | 143 | /** 144 | * @brief Put byte to ringbuffer for transmitting via UART 145 | * @param data byte to be transmitted 146 | * @return none 147 | */ 148 | extern void uart_putc(unsigned char data); 149 | 150 | 151 | /** 152 | * @brief Put string to ringbuffer for transmitting via UART 153 | * 154 | * The string is buffered by the uart library in a circular buffer 155 | * and one character at a time is transmitted to the UART using interrupts. 156 | * Blocks if it can not write the whole string into the circular buffer. 157 | * 158 | * @param s string to be transmitted 159 | * @return none 160 | */ 161 | extern void uart_puts(const char *s ); 162 | 163 | 164 | /** 165 | * @brief Put string from program memory to ringbuffer for transmitting via UART. 166 | * 167 | * The string is buffered by the uart library in a circular buffer 168 | * and one character at a time is transmitted to the UART using interrupts. 169 | * Blocks if it can not write the whole string into the circular buffer. 170 | * 171 | * @param s program memory string to be transmitted 172 | * @return none 173 | * @see uart_puts_P 174 | */ 175 | extern void uart_puts_p(const char *s ); 176 | 177 | /** 178 | * @brief Macro to automatically put a string constant into program memory 179 | */ 180 | #define uart_puts_P(__s) uart_puts_p(PSTR(__s)) 181 | 182 | 183 | 184 | /** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */ 185 | extern void uart1_init(unsigned int baudrate); 186 | /** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */ 187 | extern unsigned int uart1_getc(void); 188 | /** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */ 189 | extern void uart1_putc(unsigned char data); 190 | /** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */ 191 | extern void uart1_puts(const char *s ); 192 | /** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */ 193 | extern void uart1_puts_p(const char *s ); 194 | /** @brief Macro to automatically put a string constant into program memory */ 195 | #define uart1_puts_P(__s) uart1_puts_p(PSTR(__s)) 196 | 197 | /**@}*/ 198 | 199 | 200 | #endif // UART_H 201 | 202 | -------------------------------------------------------------------------------- /firmware/src/dxl/dxl.c: -------------------------------------------------------------------------------- 1 | /*****************************************************************************/ 2 | /* protocol.c 3 | * Dynamixel protocol 4 | * 5 | * Date: 2012/03 6 | * Rhoban Project 7 | *****************************************************************************/ 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include
16 | 17 | // Protocol definition 18 | #define DXL_PING 0x01 19 | #define DXL_READ_DATA 0x02 20 | #define DXL_WRITE_DATA 0x03 21 | #define DXL_REG_WRITE 0x04 22 | #define DXL_ACTION 0x05 23 | #define DXL_RESET 0x06 24 | #define DXL_SYNC_WRITE 0x83 25 | #define DXL_NO_ERROR 0x00 26 | #define DXL_BROADCAST 0xFE 27 | 28 | ui8 protocol_status = 0; 29 | 30 | void dxl_reset_protocol_status() { 31 | protocol_status = 0; 32 | } 33 | 34 | // Data bufferization 35 | #ifdef DXL_BUFFERIZE 36 | ui8 incoming_buffer[DXL_INCOMING_BUFFER_SIZE]; 37 | ui8_queue incoming_queue; 38 | 39 | ui8 answers[DXL_OUTGOING_PAQUET_SIZE]; 40 | unsigned int answers_size = 0; 41 | #endif 42 | 43 | // Internal functions 44 | void dxl_process_command(); 45 | ui8 dxl_compute_checksum(); 46 | void dxl_push_answer_instruction(); 47 | void dxl_flush_answer(); 48 | void uart_putc(ui8 byte); 49 | void dxl_push_byte(ui8 b); 50 | 51 | // The current command (being read or written) 52 | struct dxl_packet current_command; 53 | ui8 dxl_state; 54 | 55 | // Initializes the dynamixel module 56 | void dxl_init() { 57 | dxl_state = 0; 58 | 59 | #ifdef DXL_BUFFERIZE 60 | init_queue(&incoming_queue, incoming_buffer, DXL_INCOMING_BUFFER_SIZE); 61 | #endif 62 | } 63 | 64 | // Computes the dynamixel checksum of the current command 65 | ui8 dxl_compute_checksum() { 66 | int i; 67 | ui32 sum = 0; 68 | 69 | sum += current_command.id; 70 | sum += current_command.instruction; 71 | sum += current_command.parameter_nb+2; 72 | 73 | for (i=0; i 0) { 113 | uart_putcs(answers, answers_size); 114 | answers_size=0; 115 | } 116 | #endif 117 | } 118 | 119 | // Dispatches a command 120 | void dxl_process() { 121 | if (dxl_check_id(current_command.id) || current_command.id == DXL_BROADCAST) { 122 | switch (current_command.instruction) { 123 | case DXL_PING: 124 | // Answers the ping 125 | if (current_command.id != DXL_BROADCAST) { 126 | current_command.error = DXL_NO_ERROR; 127 | current_command.parameter_nb = 0; 128 | dxl_push_answer_instruction(); 129 | } 130 | break; 131 | 132 | case DXL_WRITE_DATA: 133 | // Write data 134 | dxl_write_data(current_command.id, 135 | current_command.parameters[0], 136 | ¤t_command.parameters[1], 137 | current_command.parameter_nb-1); 138 | break; 139 | 140 | case DXL_SYNC_WRITE: { 141 | ui8 addr = current_command.parameters[0]; 142 | int length = current_command.parameters[1] + 1; 143 | int K = (current_command.parameter_nb-2) / length; 144 | int i; 145 | 146 | for (i=0; i current_command.parameter_nb) { 197 | goto pc_ended; 198 | 199 | } else { 200 | current_command.parameters[dxl_state - 5] = b; 201 | } 202 | 203 | if (dxl_state > 128) { 204 | goto pc_error; 205 | } 206 | } 207 | 208 | dxl_state++; 209 | return; 210 | 211 | pc_ended: 212 | if (dxl_compute_checksum() == b) { 213 | dxl_process(); 214 | } else { 215 | dxl_set_protocol_status(DXL_CHECKSUM_ERROR); 216 | } 217 | 218 | dxl_state = 0; 219 | 220 | #ifdef DXL_BUFFERIZE 221 | reset_queue(&incoming_queue); 222 | #endif 223 | 224 | return; 225 | pc_error: 226 | dxl_set_protocol_status(DXL_ERROR); 227 | 228 | dxl_state = 0; 229 | 230 | #ifdef DXL_BUFFERIZE 231 | reset_queue(&incoming_queue); 232 | #endif 233 | } 234 | 235 | // Pushes a byte in the dynamixel module 236 | void dxl_push_incoming_byte(ui8 b) { 237 | #ifdef DXL_BUFFERIZE 238 | if (queue_byte_nb(&incoming_queue) < DXL_INCOMING_BUFFER_SIZE) 239 | queue_push_byte(&incoming_queue, b); 240 | else 241 | dxl_set_protocol_status(DXL_INCOMING_QUEUE_OVERFLOW); 242 | #else 243 | dxl_push_byte(b); 244 | #endif 245 | } 246 | 247 | // Calls the scheduler (useless if there is no buffer) 248 | void dxl_protocol_scheduler() { 249 | #ifdef DXL_BUFFERIZE 250 | while (queue_byte_nb(&incoming_queue)) { 251 | dxl_push_byte(queue_get_byte(&incoming_queue)); 252 | } 253 | 254 | dxl_flush_answer(); 255 | #endif 256 | } 257 | -------------------------------------------------------------------------------- /3d/lockfile.lck: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /misc/io.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2002,2003,2005,2006,2007 Marek Michalkiewicz, Joerg Wunsch 2 | Copyright (c) 2007 Eric B. Weddington 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | * Neither the name of the copyright holders nor the names of 17 | contributors may be used to endorse or promote products derived 18 | from this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | POSSIBILITY OF SUCH DAMAGE. */ 31 | 32 | /* $Id$ */ 33 | 34 | /** \file */ 35 | /** \defgroup avr_io : AVR device-specific IO definitions 36 | \code #include \endcode 37 | 38 | This header file includes the apropriate IO definitions for the 39 | device that has been specified by the -mmcu= compiler 40 | command-line switch. This is done by diverting to the appropriate 41 | file <avr/ioXXXX.h> which should 42 | never be included directly. Some register names common to all 43 | AVR devices are defined directly within <avr/common.h>, 44 | which is included in <avr/io.h>, 45 | but most of the details come from the respective include file. 46 | 47 | Note that this file always includes the following files: 48 | \code 49 | #include 50 | #include 51 | #include 52 | #include 53 | \endcode 54 | See \ref avr_sfr for more details about that header file. 55 | 56 | Included are definitions of the IO register set and their 57 | respective bit values as specified in the Atmel documentation. 58 | Note that inconsistencies in naming conventions, 59 | so even identical functions sometimes get different names on 60 | different devices. 61 | 62 | Also included are the specific names useable for interrupt 63 | function definitions as documented 64 | \ref avr_signames "here". 65 | 66 | Finally, the following macros are defined: 67 | 68 | - \b RAMEND 69 |
70 | The last on-chip RAM address. 71 |
72 | - \b XRAMEND 73 |
74 | The last possible RAM location that is addressable. This is equal to 75 | RAMEND for devices that do not allow for external RAM. For devices 76 | that allow external RAM, this will be larger than RAMEND. 77 |
78 | - \b E2END 79 |
80 | The last EEPROM address. 81 |
82 | - \b FLASHEND 83 |
84 | The last byte address in the Flash program space. 85 |
86 | - \b SPM_PAGESIZE 87 |
88 | For devices with bootloader support, the flash pagesize 89 | (in bytes) to be used for the \c SPM instruction. 90 | - \b E2PAGESIZE 91 |
92 | The size of the EEPROM page. 93 | 94 | */ 95 | 96 | #ifndef _AVR_IO_H_ 97 | #define _AVR_IO_H_ 98 | 99 | #include 100 | 101 | #if defined (__AVR_AT94K__) 102 | # include 103 | #elif defined (__AVR_AT43USB320__) 104 | # include 105 | #elif defined (__AVR_AT43USB355__) 106 | # include 107 | #elif defined (__AVR_AT76C711__) 108 | # include 109 | #elif defined (__AVR_AT86RF401__) 110 | # include 111 | #elif defined (__AVR_AT90PWM1__) 112 | # include 113 | #elif defined (__AVR_AT90PWM2__) 114 | # include 115 | #elif defined (__AVR_AT90PWM2B__) 116 | # include 117 | #elif defined (__AVR_AT90PWM3__) 118 | # include 119 | #elif defined (__AVR_AT90PWM3B__) 120 | # include 121 | #elif defined (__AVR_AT90PWM216__) 122 | # include 123 | #elif defined (__AVR_AT90PWM316__) 124 | # include 125 | #elif defined (__AVR_AT90PWM161__) 126 | # include 127 | #elif defined (__AVR_AT90PWM81__) 128 | # include 129 | #elif defined (__AVR_ATmega8U2__) 130 | # include 131 | #elif defined (__AVR_ATmega16M1__) 132 | # include 133 | #elif defined (__AVR_ATmega16U2__) 134 | # include 135 | #elif defined (__AVR_ATmega16U4__) 136 | # include 137 | #elif defined (__AVR_ATmega32C1__) 138 | # include 139 | #elif defined (__AVR_ATmega32M1__) 140 | # include 141 | #elif defined (__AVR_ATmega32U2__) 142 | # include 143 | #elif defined (__AVR_ATmega32U4__) 144 | # include 145 | #elif defined (__AVR_ATmega32U6__) 146 | # include 147 | #elif defined (__AVR_ATmega64C1__) 148 | # include 149 | #elif defined (__AVR_ATmega64M1__) 150 | # include 151 | #elif defined (__AVR_ATmega128__) 152 | # include 153 | #elif defined (__AVR_ATmega128A__) 154 | # include 155 | #elif defined (__AVR_ATmega1280__) 156 | # include 157 | #elif defined (__AVR_ATmega1281__) 158 | # include 159 | #elif defined (__AVR_ATmega1284__) 160 | # include 161 | #elif defined (__AVR_ATmega1284P__) 162 | # include 163 | #elif defined (__AVR_ATmega128RFA1__) 164 | # include 165 | #elif defined (__AVR_ATmega1284RFR2__) 166 | # include 167 | #elif defined (__AVR_ATmega128RFR2__) 168 | # include 169 | #elif defined (__AVR_ATmega2564RFR2__) 170 | # include 171 | #elif defined (__AVR_ATmega256RFR2__) 172 | # include 173 | #elif defined (__AVR_ATmega2560__) 174 | # include 175 | #elif defined (__AVR_ATmega2561__) 176 | # include 177 | #elif defined (__AVR_AT90CAN32__) 178 | # include 179 | #elif defined (__AVR_AT90CAN64__) 180 | # include 181 | #elif defined (__AVR_AT90CAN128__) 182 | # include 183 | #elif defined (__AVR_AT90USB82__) 184 | # include 185 | #elif defined (__AVR_AT90USB162__) 186 | # include 187 | #elif defined (__AVR_AT90USB646__) 188 | # include 189 | #elif defined (__AVR_AT90USB647__) 190 | # include 191 | #elif defined (__AVR_AT90USB1286__) 192 | # include 193 | #elif defined (__AVR_AT90USB1287__) 194 | # include 195 | #elif defined (__AVR_ATmega644RFR2__) 196 | # include 197 | #elif defined (__AVR_ATmega64RFR2__) 198 | # include 199 | #elif defined (__AVR_ATmega64__) 200 | # include 201 | #elif defined (__AVR_ATmega64A__) 202 | # include 203 | #elif defined (__AVR_ATmega640__) 204 | # include 205 | #elif defined (__AVR_ATmega644__) 206 | # include 207 | #elif defined (__AVR_ATmega644A__) 208 | # include 209 | #elif defined (__AVR_ATmega644P__) 210 | # include 211 | #elif defined (__AVR_ATmega644PA__) 212 | # include 213 | #elif defined (__AVR_ATmega645__) 214 | # include 215 | #elif (defined __AVR_ATmega645A__) 216 | #include 217 | #elif (defined __AVR_ATmega645P__) 218 | #include 219 | #elif defined (__AVR_ATmega6450__) 220 | # include 221 | #elif (defined __AVR_ATmega6450A__) 222 | #include 223 | #elif (defined __AVR_ATmega6450P__) 224 | #include 225 | #elif defined (__AVR_ATmega649__) 226 | # include 227 | #elif (defined __AVR_ATmega649A__) 228 | #include 229 | #elif defined (__AVR_ATmega6490__) 230 | # include 231 | #elif (defined __AVR_ATmega6490A__) 232 | #include 233 | #elif (defined __AVR_ATmega6490P__) 234 | #include 235 | #elif defined (__AVR_ATmega649P__) 236 | # include 237 | #elif defined (__AVR_ATmega64HVE__) 238 | # include 239 | #elif defined (__AVR_ATmega64HVE2__) 240 | # include 241 | #elif defined (__AVR_ATmega103__) 242 | # include 243 | #elif defined (__AVR_ATmega32__) 244 | # include 245 | #elif defined (__AVR_ATmega32A__) 246 | # include 247 | #elif defined (__AVR_ATmega323__) 248 | # include 249 | #elif defined (__AVR_ATmega324P__) 250 | # include 251 | #elif (defined __AVR_ATmega324A__) 252 | #include 253 | #elif defined (__AVR_ATmega324PA__) 254 | # include 255 | #elif defined (__AVR_ATmega325__) 256 | # include 257 | #elif (defined __AVR_ATmega325A__) 258 | #include 259 | #elif defined (__AVR_ATmega325P__) 260 | # include 261 | #elif defined (__AVR_ATmega325PA__) 262 | # include 263 | #elif defined (__AVR_ATmega3250__) 264 | # include 265 | #elif (defined __AVR_ATmega3250A__) 266 | #include 267 | #elif defined (__AVR_ATmega3250P__) 268 | # include 269 | #elif defined (__AVR_ATmega3250PA__) 270 | # include 271 | #elif defined (__AVR_ATmega328PB__) 272 | # include 273 | #elif defined (__AVR_ATmega328P__) 274 | # include 275 | #elif (defined __AVR_ATmega328__) 276 | #include 277 | #elif defined (__AVR_ATmega329__) 278 | # include 279 | #elif (defined __AVR_ATmega329A__) 280 | #include 281 | #elif defined (__AVR_ATmega329P__) 282 | # include 283 | #elif (defined __AVR_ATmega329PA__) 284 | #include 285 | #elif (defined __AVR_ATmega3290PA__) 286 | #include 287 | #elif defined (__AVR_ATmega3290__) 288 | # include 289 | #elif (defined __AVR_ATmega3290A__) 290 | #include 291 | #elif defined (__AVR_ATmega3290P__) 292 | # include 293 | #elif defined (__AVR_ATmega32HVB__) 294 | # include 295 | #elif defined (__AVR_ATmega32HVBREVB__) 296 | # include 297 | #elif defined (__AVR_ATmega406__) 298 | # include 299 | #elif defined (__AVR_ATmega16__) 300 | # include 301 | #elif defined (__AVR_ATmega16A__) 302 | # include 303 | #elif defined (__AVR_ATmega161__) 304 | # include 305 | #elif defined (__AVR_ATmega162__) 306 | # include 307 | #elif defined (__AVR_ATmega163__) 308 | # include 309 | #elif defined (__AVR_ATmega164P__) 310 | # include 311 | #elif (defined __AVR_ATmega164A__) 312 | #include 313 | #elif defined (__AVR_ATmega164PA__) 314 | # include 315 | #elif defined (__AVR_ATmega165__) 316 | # include 317 | #elif defined (__AVR_ATmega165A__) 318 | # include 319 | #elif defined (__AVR_ATmega165P__) 320 | # include 321 | #elif defined (__AVR_ATmega165PA__) 322 | # include 323 | #elif defined (__AVR_ATmega168__) 324 | # include 325 | #elif defined (__AVR_ATmega168A__) 326 | # include 327 | #elif defined (__AVR_ATmega168P__) 328 | # include 329 | #elif defined (__AVR_ATmega168PA__) 330 | # include 331 | #elif defined (__AVR_ATmega168PB__) 332 | # include 333 | #elif defined (__AVR_ATmega169__) 334 | # include 335 | #elif (defined __AVR_ATmega169A__) 336 | #include 337 | #elif defined (__AVR_ATmega169P__) 338 | # include 339 | #elif defined (__AVR_ATmega169PA__) 340 | # include 341 | #elif defined (__AVR_ATmega8HVA__) 342 | # include 343 | #elif defined (__AVR_ATmega16HVA__) 344 | # include 345 | #elif defined (__AVR_ATmega16HVA2__) 346 | # include 347 | #elif defined (__AVR_ATmega16HVB__) 348 | # include 349 | #elif defined (__AVR_ATmega16HVBREVB__) 350 | # include 351 | #elif defined (__AVR_ATmega8__) 352 | # include 353 | #elif defined (__AVR_ATmega8A__) 354 | # include 355 | #elif defined (__AVR_ATmega48__) 356 | # include 357 | #elif defined (__AVR_ATmega48A__) 358 | # include 359 | #elif defined (__AVR_ATmega48PA__) 360 | # include 361 | #elif defined (__AVR_ATmega48PB__) 362 | # include 363 | #elif defined (__AVR_ATmega48P__) 364 | # include 365 | #elif defined (__AVR_ATmega88__) 366 | # include 367 | #elif defined (__AVR_ATmega88A__) 368 | # include 369 | #elif defined (__AVR_ATmega88P__) 370 | # include 371 | #elif defined (__AVR_ATmega88PA__) 372 | # include 373 | #elif defined (__AVR_ATmega88PB__) 374 | # include 375 | #elif defined (__AVR_ATmega8515__) 376 | # include 377 | #elif defined (__AVR_ATmega8535__) 378 | # include 379 | #elif defined (__AVR_AT90S8535__) 380 | # include 381 | #elif defined (__AVR_AT90C8534__) 382 | # include 383 | #elif defined (__AVR_AT90S8515__) 384 | # include 385 | #elif defined (__AVR_AT90S4434__) 386 | # include 387 | #elif defined (__AVR_AT90S4433__) 388 | # include 389 | #elif defined (__AVR_AT90S4414__) 390 | # include 391 | #elif defined (__AVR_ATtiny22__) 392 | # include 393 | #elif defined (__AVR_ATtiny26__) 394 | # include 395 | #elif defined (__AVR_AT90S2343__) 396 | # include 397 | #elif defined (__AVR_AT90S2333__) 398 | # include 399 | #elif defined (__AVR_AT90S2323__) 400 | # include 401 | #elif defined (__AVR_AT90S2313__) 402 | # include 403 | #elif defined (__AVR_ATtiny4__) 404 | # include 405 | #elif defined (__AVR_ATtiny5__) 406 | # include 407 | #elif defined (__AVR_ATtiny9__) 408 | # include 409 | #elif defined (__AVR_ATtiny10__) 410 | # include 411 | #elif defined (__AVR_ATtiny20__) 412 | # include 413 | #elif defined (__AVR_ATtiny40__) 414 | # include 415 | #elif defined (__AVR_ATtiny2313__) 416 | # include 417 | #elif defined (__AVR_ATtiny2313A__) 418 | # include 419 | #elif defined (__AVR_ATtiny13__) 420 | # include 421 | #elif defined (__AVR_ATtiny13A__) 422 | # include 423 | #elif defined (__AVR_ATtiny25__) 424 | # include 425 | #elif defined (__AVR_ATtiny4313__) 426 | # include 427 | #elif defined (__AVR_ATtiny45__) 428 | # include 429 | #elif defined (__AVR_ATtiny85__) 430 | # include 431 | #elif defined (__AVR_ATtiny24__) 432 | # include 433 | #elif defined (__AVR_ATtiny24A__) 434 | # include 435 | #elif defined (__AVR_ATtiny44__) 436 | # include 437 | #elif defined (__AVR_ATtiny44A__) 438 | # include 439 | #elif defined (__AVR_ATtiny441__) 440 | # include 441 | #elif defined (__AVR_ATtiny84__) 442 | # include 443 | #elif defined (__AVR_ATtiny84A__) 444 | # include 445 | #elif defined (__AVR_ATtiny841__) 446 | # include 447 | #elif defined (__AVR_ATtiny261__) 448 | # include 449 | #elif defined (__AVR_ATtiny261A__) 450 | # include 451 | #elif defined (__AVR_ATtiny461__) 452 | # include 453 | #elif defined (__AVR_ATtiny461A__) 454 | # include 455 | #elif defined (__AVR_ATtiny861__) 456 | # include 457 | #elif defined (__AVR_ATtiny861A__) 458 | # include 459 | #elif defined (__AVR_ATtiny43U__) 460 | # include 461 | #elif defined (__AVR_ATtiny48__) 462 | # include 463 | #elif defined (__AVR_ATtiny88__) 464 | # include 465 | #elif defined (__AVR_ATtiny828__) 466 | # include 467 | #elif defined (__AVR_ATtiny87__) 468 | # include 469 | #elif defined (__AVR_ATtiny167__) 470 | # include 471 | #elif defined (__AVR_ATtiny1634__) 472 | # include 473 | #elif defined (__AVR_AT90SCR100__) 474 | # include 475 | #elif defined (__AVR_ATxmega8E5__) 476 | # include 477 | #elif defined (__AVR_ATxmega16A4__) 478 | # include 479 | #elif defined (__AVR_ATxmega16A4U__) 480 | # include 481 | #elif defined (__AVR_ATxmega16C4__) 482 | # include 483 | #elif defined (__AVR_ATxmega16D4__) 484 | # include 485 | #elif defined (__AVR_ATxmega16E5__) 486 | # include 487 | #elif defined (__AVR_ATxmega32A4__) 488 | # include 489 | #elif defined (__AVR_ATxmega32A4U__) 490 | # include 491 | #elif defined (__AVR_ATxmega32C3__) 492 | # include 493 | #elif defined (__AVR_ATxmega32C4__) 494 | # include 495 | #elif defined (__AVR_ATxmega32D3__) 496 | # include 497 | #elif defined (__AVR_ATxmega32D4__) 498 | # include 499 | #elif defined (__AVR_ATxmega32E5__) 500 | # include 501 | #elif defined (__AVR_ATxmega64A1__) 502 | # include 503 | #elif defined (__AVR_ATxmega64A1U__) 504 | # include 505 | #elif defined (__AVR_ATxmega64A3__) 506 | # include 507 | #elif defined (__AVR_ATxmega64A3U__) 508 | # include 509 | #elif defined (__AVR_ATxmega64A4U__) 510 | # include 511 | #elif defined (__AVR_ATxmega64B1__) 512 | # include 513 | #elif defined (__AVR_ATxmega64B3__) 514 | # include 515 | #elif defined (__AVR_ATxmega64C3__) 516 | # include 517 | #elif defined (__AVR_ATxmega64D3__) 518 | # include 519 | #elif defined (__AVR_ATxmega64D4__) 520 | # include 521 | #elif defined (__AVR_ATxmega128A1__) 522 | # include 523 | #elif defined (__AVR_ATxmega128A1U__) 524 | # include 525 | #elif defined (__AVR_ATxmega128A4U__) 526 | # include 527 | #elif defined (__AVR_ATxmega128A3__) 528 | # include 529 | #elif defined (__AVR_ATxmega128A3U__) 530 | # include 531 | #elif defined (__AVR_ATxmega128B1__) 532 | # include 533 | #elif defined (__AVR_ATxmega128B3__) 534 | # include 535 | #elif defined (__AVR_ATxmega128C3__) 536 | # include 537 | #elif defined (__AVR_ATxmega128D3__) 538 | # include 539 | #elif defined (__AVR_ATxmega128D4__) 540 | # include 541 | #elif defined (__AVR_ATxmega192A3__) 542 | # include 543 | #elif defined (__AVR_ATxmega192A3U__) 544 | # include 545 | #elif defined (__AVR_ATxmega192C3__) 546 | # include 547 | #elif defined (__AVR_ATxmega192D3__) 548 | # include 549 | #elif defined (__AVR_ATxmega256A3__) 550 | # include 551 | #elif defined (__AVR_ATxmega256A3U__) 552 | # include 553 | #elif defined (__AVR_ATxmega256A3B__) 554 | # include 555 | #elif defined (__AVR_ATxmega256A3BU__) 556 | # include 557 | #elif defined (__AVR_ATxmega256C3__) 558 | # include 559 | #elif defined (__AVR_ATxmega256D3__) 560 | # include 561 | #elif defined (__AVR_ATxmega384C3__) 562 | # include 563 | #elif defined (__AVR_ATxmega384D3__) 564 | # include 565 | #elif defined (__AVR_ATA5702M322__) 566 | # include 567 | #elif defined (__AVR_ATA5782__) 568 | # include 569 | #elif defined (__AVR_ATA5790__) 570 | # include 571 | #elif defined (__AVR_ATA5790N__) 572 | # include 573 | #elif defined (__AVR_ATA5791__) 574 | # include 575 | #elif defined (__AVR_ATA5831__) 576 | # include 577 | #elif defined (__AVR_ATA5272__) 578 | # include 579 | #elif defined (__AVR_ATA5505__) 580 | # include 581 | #elif defined (__AVR_ATA5795__) 582 | # include 583 | #elif defined (__AVR_ATA6285__) 584 | # include 585 | #elif defined (__AVR_ATA6286__) 586 | # include 587 | #elif defined (__AVR_ATA6289__) 588 | # include 589 | #elif defined (__AVR_ATA6612C__) 590 | # include 591 | #elif defined (__AVR_ATA6613C__) 592 | # include 593 | #elif defined (__AVR_ATA6614Q__) 594 | # include 595 | #elif defined (__AVR_ATA6616C__) 596 | # include 597 | #elif defined (__AVR_ATA6617C__) 598 | # include 599 | #elif defined (__AVR_ATA664251__) 600 | # include 601 | #elif defined (__AVR_ATA8210__) 602 | # include 603 | #elif defined (__AVR_ATA8510__) 604 | # include 605 | /* avr1: the following only supported for assembler programs */ 606 | #elif defined (__AVR_ATtiny28__) 607 | # include 608 | #elif defined (__AVR_AT90S1200__) 609 | # include 610 | #elif defined (__AVR_ATtiny15__) 611 | # include 612 | #elif defined (__AVR_ATtiny12__) 613 | # include 614 | #elif defined (__AVR_ATtiny11__) 615 | # include 616 | #elif defined (__AVR_M3000__) 617 | # include 618 | #elif defined (__AVR_DEV_LIB_NAME__) 619 | # define __concat__(a,b) a##b 620 | # define __header1__(a,b) __concat__(a,b) 621 | # define __AVR_DEVICE_HEADER__ 622 | # include __AVR_DEVICE_HEADER__ 623 | #else 624 | # if !defined(__COMPILING_AVR_LIBC__) 625 | # warning "device type not defined" 626 | # endif 627 | #endif 628 | 629 | #include 630 | 631 | #include 632 | 633 | #include 634 | 635 | #if __AVR_ARCH__ >= 100 636 | # include 637 | #endif 638 | 639 | /* Include fuse.h after individual IO header files. */ 640 | #include 641 | 642 | /* Include lock.h after individual IO header files. */ 643 | #include 644 | 645 | #endif /* _AVR_IO_H_ */ 646 | -------------------------------------------------------------------------------- /firmware/src/uart/uart.c: -------------------------------------------------------------------------------- 1 | /************************************************************************* 2 | Title: Interrupt UART library with receive/transmit circular buffers 3 | Author: Peter Fleury http://jump.to/fleury 4 | File: $Id: uart.c,v 1.6.2.2 2009/11/29 08:56:12 Peter Exp $ 5 | Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher 6 | Hardware: any AVR with built-in UART, 7 | License: GNU General Public License 8 | 9 | DESCRIPTION: 10 | An interrupt is generated when the UART has finished transmitting or 11 | receiving a byte. The interrupt handling routines use circular buffers 12 | for buffering received and transmitted data. 13 | 14 | The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define 15 | the buffer size in bytes. Note that these variables must be a 16 | power of 2. 17 | 18 | USAGE: 19 | Refere to the header file uart.h for a description of the routines. 20 | See also example test_uart.c. 21 | 22 | NOTES: 23 | Based on Atmel Application Note AVR306 24 | 25 | LICENSE: 26 | Copyright (C) 2006 Peter Fleury 27 | 28 | This program is free software; you can redistribute it and/or modify 29 | it under the terms of the GNU General Public License as published by 30 | the Free Software Foundation; either version 2 of the License, or 31 | any later version. 32 | 33 | This program is distributed in the hope that it will be useful, 34 | but WITHOUT ANY WARRANTY; without even the implied warranty of 35 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 36 | GNU General Public License for more details. 37 | 38 | *************************************************************************/ 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | 45 | /* 46 | * constants and macros 47 | */ 48 | 49 | /* Enables half-duplex */ 50 | //#define HALF_DUPLEX 51 | 52 | /* Enables PD2 as direction PIN */ 53 | //#define DIRECTION_PIN 54 | 55 | /* size of RX/TX buffers */ 56 | #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1) 57 | #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1) 58 | 59 | #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) 60 | #error RX buffer size is not a power of 2 61 | #endif 62 | #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK ) 63 | #error TX buffer size is not a power of 2 64 | #endif 65 | 66 | #if defined(__AVR_AT90S2313__) \ 67 | || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \ 68 | || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \ 69 | || defined(__AVR_ATmega103__) 70 | /* old AVR classic or ATmega103 with one UART */ 71 | #define AT90_UART 72 | #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV 73 | #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA 74 | #define UART0_STATUS USR 75 | #define UART0_CONTROL UCR 76 | #define UART0_DATA UDR 77 | #define UART0_UDRIE UDRIE 78 | #elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__) 79 | /* old AVR classic with one UART */ 80 | #define AT90_UART 81 | #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV 82 | #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA 83 | #define UART0_STATUS UCSRA 84 | #define UART0_CONTROL UCSRB 85 | #define UART0_DATA UDR 86 | #define UART0_UDRIE UDRIE 87 | #elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \ 88 | || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \ 89 | || defined(__AVR_ATmega323__) 90 | /* ATmega with one USART */ 91 | #define ATMEGA_USART 92 | #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV 93 | #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA 94 | #define UART0_STATUS UCSRA 95 | #define UART0_CONTROL UCSRB 96 | #define UART0_DATA UDR 97 | #define UART0_UDRIE UDRIE 98 | #define UART0_TXCIE TXCIE 99 | #elif defined(__AVR_ATmega163__) 100 | /* ATmega163 with one UART */ 101 | #define ATMEGA_UART 102 | #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV 103 | #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA 104 | #define UART0_STATUS UCSRA 105 | #define UART0_CONTROL UCSRB 106 | #define UART0_DATA UDR 107 | #define UART0_UDRIE UDRIE 108 | #elif defined(__AVR_ATmega162__) 109 | /* ATmega with two USART */ 110 | #define ATMEGA_USART0 111 | #define ATMEGA_USART1 112 | #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV 113 | #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV 114 | #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA 115 | #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA 116 | #define UART0_STATUS UCSR0A 117 | #define UART0_CONTROL UCSR0B 118 | #define UART0_DATA UDR0 119 | #define UART0_UDRIE UDRIE0 120 | #define UART1_STATUS UCSR1A 121 | #define UART1_CONTROL UCSR1B 122 | #define UART1_DATA UDR1 123 | #define UART1_UDRIE UDRIE1 124 | #elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega328PB__) 125 | /* ATmega with two USART */ 126 | #define ATMEGA_USART0 127 | #define ATMEGA_USART1 128 | #define UART0_RECEIVE_INTERRUPT SIG_UART0_RECV 129 | #define UART1_RECEIVE_INTERRUPT SIG_UART1_RECV 130 | #define UART0_TRANSMIT_INTERRUPT SIG_UART0_DATA 131 | #define UART1_TRANSMIT_INTERRUPT SIG_UART1_DATA 132 | #define UART0_STATUS UCSR0A 133 | #define UART0_CONTROL UCSR0B 134 | #define UART0_DATA UDR0 135 | #define UART0_UDRIE UDRIE0 136 | #define UART1_STATUS UCSR1A 137 | #define UART1_CONTROL UCSR1B 138 | #define UART1_DATA UDR1 139 | #define UART1_UDRIE UDRIE1 140 | #define UART0_TXCIE TXCIE0 141 | 142 | #define USART_UDRE_vect USART0_UDRE_vect 143 | #define USART_RXC_vect USART0_RX_vect 144 | #define USART_TXC_vect USART0_TX_vect 145 | #define USART1_RXC_vect USART1_RX_vect 146 | #define USART1_TXC_vect USART1_TX_vect 147 | 148 | #elif defined(__AVR_ATmega161__) 149 | /* ATmega with UART */ 150 | #error "AVR ATmega161 currently not supported by this libaray !" 151 | #elif defined(__AVR_ATmega169__) 152 | /* ATmega with one USART */ 153 | #define ATMEGA_USART 154 | #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV 155 | #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA 156 | #define UART0_STATUS UCSRA 157 | #define UART0_CONTROL UCSRB 158 | #define UART0_DATA UDR 159 | #define UART0_UDRIE UDRIE 160 | #elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__) 161 | /* ATmega with one USART */ 162 | #define ATMEGA_USART0 163 | #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV 164 | #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA 165 | #define UART0_STATUS UCSR0A 166 | #define UART0_CONTROL UCSR0B 167 | #define UART0_DATA UDR0 168 | #define UART0_UDRIE UDRIE0 169 | #define UART0_TXCIE TXCIE0 170 | #define USART_TXC_vect USART_TX_vect 171 | #define USART_RXC_vect USART_RX_vect 172 | #elif defined(__AVR_ATtiny2313__) 173 | #define ATMEGA_USART 174 | #define UART0_RECEIVE_INTERRUPT SIG_USART0_RX 175 | #define UART0_TRANSMIT_INTERRUPT SIG_USART0_UDRE 176 | #define UART0_STATUS UCSRA 177 | #define UART0_CONTROL UCSRB 178 | #define UART0_DATA UDR 179 | #define UART0_UDRIE UDRIE 180 | #elif defined(__AVR_ATmega329__) ||defined(__AVR_ATmega3290__) ||\ 181 | defined(__AVR_ATmega649__) ||defined(__AVR_ATmega6490__) ||\ 182 | defined(__AVR_ATmega325__) ||defined(__AVR_ATmega3250__) ||\ 183 | defined(__AVR_ATmega645__) ||defined(__AVR_ATmega6450__) 184 | /* ATmega with one USART */ 185 | #define ATMEGA_USART0 186 | #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV 187 | #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA 188 | #define UART0_STATUS UCSR0A 189 | #define UART0_CONTROL UCSR0B 190 | #define UART0_DATA UDR0 191 | #define UART0_UDRIE UDRIE0 192 | #elif defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega640__) || defined(__AVR_ATmega328PB__) 193 | /* ATmega with two USART */ 194 | #define ATMEGA_USART0 195 | #define ATMEGA_USART1 196 | #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV 197 | #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV 198 | #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA 199 | #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA 200 | #define UART0_STATUS UCSR0A 201 | #define UART0_CONTROL UCSR0B 202 | #define UART0_DATA UDR0 203 | #define UART0_UDRIE UDRIE0 204 | #define UART1_STATUS UCSR1A 205 | #define UART1_CONTROL UCSR1B 206 | #define UART1_DATA UDR1 207 | #define UART1_UDRIE UDRIE1 208 | #elif defined(__AVR_ATmega644__) 209 | /* ATmega with one USART */ 210 | #define ATMEGA_USART0 211 | #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV 212 | #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA 213 | #define UART0_STATUS UCSR0A 214 | #define UART0_CONTROL UCSR0B 215 | #define UART0_DATA UDR0 216 | #define UART0_UDRIE UDRIE0 217 | #elif defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__) 218 | /* ATmega with two USART */ 219 | #define ATMEGA_USART0 220 | #define ATMEGA_USART1 221 | #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV 222 | #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV 223 | #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA 224 | #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA 225 | #define UART0_STATUS UCSR0A 226 | #define UART0_CONTROL UCSR0B 227 | #define UART0_DATA UDR0 228 | #define UART0_UDRIE UDRIE0 229 | #define UART1_STATUS UCSR1A 230 | #define UART1_CONTROL UCSR1B 231 | #define UART1_DATA UDR1 232 | #define UART1_UDRIE UDRIE1 233 | #else 234 | #error "no UART definition for MCU available" 235 | #endif 236 | 237 | 238 | /* 239 | * module global variables 240 | */ 241 | static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE]; 242 | static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE]; 243 | static volatile unsigned char UART_TxHead; 244 | static volatile unsigned char UART_TxTail; 245 | static volatile unsigned char UART_RxHead; 246 | static volatile unsigned char UART_RxTail; 247 | static volatile unsigned char UART_LastRxError; 248 | 249 | #if defined( ATMEGA_USART1 ) 250 | static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE]; 251 | static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE]; 252 | static volatile unsigned char UART1_TxHead; 253 | static volatile unsigned char UART1_TxTail; 254 | static volatile unsigned char UART1_RxHead; 255 | static volatile unsigned char UART1_RxTail; 256 | static volatile unsigned char UART1_LastRxError; 257 | #endif 258 | 259 | int uart_tx_has_data() 260 | { 261 | return UART_TxHead != UART_TxTail; 262 | } 263 | 264 | static int UART_ReceiverEnabled = 1; 265 | 266 | void uart_enable_receiver(int en) 267 | { 268 | UART_RxHead = UART_RxTail; 269 | UART_ReceiverEnabled = en; 270 | } 271 | 272 | 273 | ISR(USART_RXC_vect) 274 | /************************************************************************* 275 | Function: UART Receive Complete interrupt 276 | Purpose: called when the UART has received a character 277 | **************************************************************************/ 278 | { 279 | unsigned char tmphead; 280 | unsigned char data; 281 | unsigned char usr; 282 | unsigned char lastRxError; 283 | 284 | /* read UART status register and UART data register */ 285 | usr = UART0_STATUS; 286 | data = UART0_DATA; 287 | 288 | /* */ 289 | #if defined( AT90_UART ) 290 | lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); 291 | #elif defined( ATMEGA_USART ) 292 | lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); 293 | #elif defined( ATMEGA_USART0 ) 294 | lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) ); 295 | #elif defined ( ATMEGA_UART ) 296 | lastRxError = (usr & (_BV(FE)|_BV(DOR)) ); 297 | #endif 298 | 299 | if (!UART_ReceiverEnabled) { 300 | return; 301 | } 302 | 303 | /* calculate buffer index */ 304 | tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK; 305 | 306 | if ( tmphead == UART_RxTail ) { 307 | /* error: receive buffer overflow */ 308 | lastRxError = UART_BUFFER_OVERFLOW >> 8; 309 | }else{ 310 | /* store new index */ 311 | UART_RxHead = tmphead; 312 | /* store received data in buffer */ 313 | UART_RxBuf[tmphead] = data; 314 | } 315 | UART_LastRxError = lastRxError; 316 | } 317 | 318 | 319 | ISR(USART_UDRE_vect) 320 | /************************************************************************* 321 | Function: UART Data Register Empty interrupt 322 | Purpose: called when the UART is ready to transmit the next byte 323 | **************************************************************************/ 324 | { 325 | unsigned char tmptail; 326 | 327 | 328 | if ( UART_TxHead != UART_TxTail) { 329 | /* calculate and store new buffer index */ 330 | tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK; 331 | UART_TxTail = tmptail; 332 | /* get one byte from buffer and write it to UART */ 333 | UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */ 334 | }else{ 335 | /* tx buffer empty, disable UDRE interrupt */ 336 | UART0_CONTROL &= ~_BV(UART0_UDRIE); 337 | } 338 | } 339 | 340 | void uart_disable_tx() 341 | { 342 | #if defined (ATMEGA_USART) 343 | UART0_CONTROL = _BV(RXCIE)|(1<>8); 419 | UBRRL = (unsigned char) baudrate; 420 | 421 | /* Enable USART receiver and transmitter and receive complete interrupt */ 422 | UART0_CONTROL = _BV(RXCIE)|(1<>8); 443 | UBRR0L = (unsigned char) baudrate; 444 | 445 | /* Enable USART receiver and transmitter and receive complete interrupt */ 446 | UART0_CONTROL = _BV(RXCIE0)|(1<>8); 467 | UBRR = (unsigned char) baudrate; 468 | 469 | /* Enable UART receiver and transmitter and receive complete interrupt */ 470 | UART0_CONTROL = _BV(RXCIE)|(1<> 8; 629 | }else{ 630 | /* store new index */ 631 | UART1_RxHead = tmphead; 632 | /* store received data in buffer */ 633 | UART1_RxBuf[tmphead] = data; 634 | } 635 | UART1_LastRxError = lastRxError; 636 | } 637 | 638 | 639 | ISR(USART1_TXC_vect) 640 | /************************************************************************* 641 | Function: UART1 Data Register Empty interrupt 642 | Purpose: called when the UART1 is ready to transmit the next byte 643 | **************************************************************************/ 644 | { 645 | unsigned char tmptail; 646 | 647 | 648 | if ( UART1_TxHead != UART1_TxTail) { 649 | /* calculate and store new buffer index */ 650 | tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK; 651 | UART1_TxTail = tmptail; 652 | /* get one byte from buffer and write it to UART */ 653 | UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */ 654 | }else{ 655 | /* tx buffer empty, disable UDRE interrupt */ 656 | UART1_CONTROL &= ~_BV(UART1_UDRIE); 657 | } 658 | } 659 | 660 | 661 | /************************************************************************* 662 | Function: uart1_init() 663 | Purpose: initialize UART1 and set baudrate 664 | Input: baudrate using macro UART_BAUD_SELECT() 665 | Returns: none 666 | **************************************************************************/ 667 | void uart1_init(unsigned int baudrate) 668 | { 669 | UART1_TxHead = 0; 670 | UART1_TxTail = 0; 671 | UART1_RxHead = 0; 672 | UART1_RxTail = 0; 673 | 674 | 675 | /* Set baud rate */ 676 | if ( baudrate & 0x8000 ) 677 | { 678 | UART1_STATUS = (1<>8); 682 | UBRR1L = (unsigned char) baudrate; 683 | 684 | /* Enable USART receiver and transmitter and receive complete interrupt */ 685 | UART1_CONTROL = _BV(RXCIE1)|(1< instead of this file." 41 | #endif 42 | 43 | #ifndef _AVR_IOXXX_H_ 44 | # define _AVR_IOXXX_H_ "iom328pb.h" 45 | #else 46 | # error "Attempt to include more than one file." 47 | #endif 48 | 49 | /* Registers and associated bit numbers */ 50 | 51 | #define PINB _SFR_IO8(0x03) 52 | #define PINB7 7 53 | #define PINB6 6 54 | #define PINB5 5 55 | #define PINB4 4 56 | #define PINB3 3 57 | #define PINB2 2 58 | #define PINB1 1 59 | #define PINB0 0 60 | 61 | #define DDRB _SFR_IO8(0x04) 62 | #define DDRB7 7 63 | // Inserted "DDB7" from "DDRB7" due to compatibility 64 | #define DDB7 7 65 | #define DDRB6 6 66 | // Inserted "DDB6" from "DDRB6" due to compatibility 67 | #define DDB6 6 68 | #define DDRB5 5 69 | // Inserted "DDB5" from "DDRB5" due to compatibility 70 | #define DDB5 5 71 | #define DDRB4 4 72 | // Inserted "DDB4" from "DDRB4" due to compatibility 73 | #define DDB4 4 74 | #define DDRB3 3 75 | // Inserted "DDB3" from "DDRB3" due to compatibility 76 | #define DDB3 3 77 | #define DDRB2 2 78 | // Inserted "DDB2" from "DDRB2" due to compatibility 79 | #define DDB2 2 80 | #define DDRB1 1 81 | // Inserted "DDB1" from "DDRB1" due to compatibility 82 | #define DDB1 1 83 | #define DDRB0 0 84 | // Inserted "DDB0" from "DDRB0" due to compatibility 85 | #define DDB0 0 86 | 87 | #define PORTB _SFR_IO8(0x05) 88 | #define PORTB7 7 89 | #define PORTB6 6 90 | #define PORTB5 5 91 | #define PORTB4 4 92 | #define PORTB3 3 93 | #define PORTB2 2 94 | #define PORTB1 1 95 | #define PORTB0 0 96 | 97 | #define PINC _SFR_IO8(0x06) 98 | #define PINC6 6 99 | #define PINC5 5 100 | #define PINC4 4 101 | #define PINC3 3 102 | #define PINC2 2 103 | #define PINC1 1 104 | #define PINC0 0 105 | 106 | #define DDRC _SFR_IO8(0x07) 107 | #define DDRC6 6 108 | // Inserted "DDC6" from "DDRC6" due to compatibility 109 | #define DDC6 6 110 | #define DDRC5 5 111 | // Inserted "DDC5" from "DDRC5" due to compatibility 112 | #define DDC5 5 113 | #define DDRC4 4 114 | // Inserted "DDC4" from "DDRC4" due to compatibility 115 | #define DDC4 4 116 | #define DDRC3 3 117 | // Inserted "DDC3" from "DDRC3" due to compatibility 118 | #define DDC3 3 119 | #define DDRC2 2 120 | // Inserted "DDC2" from "DDRC2" due to compatibility 121 | #define DDC2 2 122 | #define DDRC1 1 123 | // Inserted "DDC1" from "DDRC1" due to compatibility 124 | #define DDC1 1 125 | #define DDRC0 0 126 | // Inserted "DDC0" from "DDRC0" due to compatibility 127 | #define DDC0 0 128 | 129 | #define PORTC _SFR_IO8(0x08) 130 | #define PORTC6 6 131 | #define PORTC5 5 132 | #define PORTC4 4 133 | #define PORTC3 3 134 | #define PORTC2 2 135 | #define PORTC1 1 136 | #define PORTC0 0 137 | 138 | #define PIND _SFR_IO8(0x09) 139 | #define PIND7 7 140 | #define PIND6 6 141 | #define PIND5 5 142 | #define PIND4 4 143 | #define PIND3 3 144 | #define PIND2 2 145 | #define PIND1 1 146 | #define PIND0 0 147 | 148 | #define DDRD _SFR_IO8(0x0A) 149 | #define DDRD7 7 150 | // Inserted "DDD7" from "DDRD7" due to compatibility 151 | #define DDD7 7 152 | #define DDRD6 6 153 | // Inserted "DDD6" from "DDRD6" due to compatibility 154 | #define DDD6 6 155 | #define DDRD5 5 156 | // Inserted "DDD5" from "DDRD5" due to compatibility 157 | #define DDD5 5 158 | #define DDRD4 4 159 | // Inserted "DDD4" from "DDRD4" due to compatibility 160 | #define DDD4 4 161 | #define DDRD3 3 162 | // Inserted "DDD3" from "DDRD3" due to compatibility 163 | #define DDD3 3 164 | #define DDRD2 2 165 | // Inserted "DDD2" from "DDRD2" due to compatibility 166 | #define DDD2 2 167 | #define DDRD1 1 168 | // Inserted "DDD1" from "DDRD1" due to compatibility 169 | #define DDD1 1 170 | #define DDRD0 0 171 | // Inserted "DDD0" from "DDRD0" due to compatibility 172 | #define DDD0 0 173 | 174 | #define PORTD _SFR_IO8(0x0B) 175 | #define PORTD7 7 176 | #define PORTD6 6 177 | #define PORTD5 5 178 | #define PORTD4 4 179 | #define PORTD3 3 180 | #define PORTD2 2 181 | #define PORTD1 1 182 | #define PORTD0 0 183 | 184 | #define PINE _SFR_IO8(0x0C) 185 | #define PINE3 3 186 | #define PINE2 2 187 | #define PINE1 1 188 | #define PINE0 0 189 | 190 | #define DDRE _SFR_IO8(0x0D) 191 | #define DDRE3 3 192 | // Inserted "DDE3" from "DDRE3" due to compatibility 193 | #define DDE3 3 194 | #define DDRE2 2 195 | // Inserted "DDE2" from "DDRE2" due to compatibility 196 | #define DDE2 2 197 | #define DDRE1 1 198 | // Inserted "DDE1" from "DDRE1" due to compatibility 199 | #define DDE1 1 200 | #define DDRE0 0 201 | // Inserted "DDE0" from "DDRE0" due to compatibility 202 | #define DDE0 0 203 | 204 | #define PORTE _SFR_IO8(0x0E) 205 | #define PORTE3 3 206 | #define PORTE2 2 207 | #define PORTE1 1 208 | #define PORTE0 0 209 | 210 | /* Reserved [0x0F..0x14] */ 211 | 212 | #define TIFR0 _SFR_IO8(0x15) 213 | #define TOV0 0 214 | #define OCF0A 1 215 | #define OCF0B 2 216 | 217 | #define TIFR1 _SFR_IO8(0x16) 218 | #define TOV1 0 219 | #define OCF1A 1 220 | #define OCF1B 2 221 | #define ICF1 5 222 | 223 | #define TIFR2 _SFR_IO8(0x17) 224 | #define TOV2 0 225 | #define OCF2A 1 226 | #define OCF2B 2 227 | 228 | #define TIFR3 _SFR_IO8(0x18) 229 | #define TOV3 0 230 | #define OCF3A 1 231 | #define OCF3B 2 232 | #define ICF3 5 233 | 234 | #define TIFR4 _SFR_IO8(0x19) 235 | #define TOV4 0 236 | #define OCF4A 1 237 | #define OCF4B 2 238 | #define ICF4 5 239 | 240 | /* Reserved [0x1A] */ 241 | 242 | #define PCIFR _SFR_IO8(0x1B) 243 | #define PCIF0 0 244 | #define PCIF1 1 245 | #define PCIF2 2 246 | #define PCIF3 3 247 | 248 | #define EIFR _SFR_IO8(0x1C) 249 | #define INTF0 0 250 | #define INTF1 1 251 | 252 | #define EIMSK _SFR_IO8(0x1D) 253 | #define INT0 0 254 | #define INT1 1 255 | 256 | #define GPIOR0 _SFR_IO8(0x1E) 257 | 258 | #define EECR _SFR_IO8(0x1F) 259 | #define EERE 0 260 | #define EEPE 1 261 | #define EEMPE 2 262 | #define EERIE 3 263 | #define EEPM0 4 264 | #define EEPM1 5 265 | 266 | #define EEDR _SFR_IO8(0x20) 267 | 268 | /* Combine EEARL and EEARH */ 269 | #define EEAR _SFR_IO16(0x21) 270 | 271 | #define EEARL _SFR_IO8(0x21) 272 | #define EEARH _SFR_IO8(0x22) 273 | 274 | #define GTCCR _SFR_IO8(0x23) 275 | #define PSRSYNC 0 276 | #define TSM 7 277 | #define PSRASY 1 278 | 279 | #define TCCR0A _SFR_IO8(0x24) 280 | #define WGM00 0 281 | #define WGM01 1 282 | #define COM0B0 4 283 | #define COM0B1 5 284 | #define COM0A0 6 285 | #define COM0A1 7 286 | 287 | #define TCCR0B _SFR_IO8(0x25) 288 | #define CS00 0 289 | #define CS01 1 290 | #define CS02 2 291 | #define WGM02 3 292 | #define FOC0B 6 293 | #define FOC0A 7 294 | 295 | #define TCNT0 _SFR_IO8(0x26) 296 | 297 | #define OCR0A _SFR_IO8(0x27) 298 | 299 | #define OCR0B _SFR_IO8(0x28) 300 | 301 | /* Reserved [0x29] */ 302 | 303 | #define GPIOR1 _SFR_IO8(0x2A) 304 | 305 | #define GPIOR2 _SFR_IO8(0x2B) 306 | 307 | #define SPCR0 _SFR_IO8(0x2C) 308 | #define SPR00 0 309 | #define SPR01 1 310 | #define CPHA0 2 311 | #define CPOL0 3 312 | #define MSTR0 4 313 | #define DORD0 5 314 | #define SPE0 6 315 | #define SPIE0 7 316 | 317 | #define SPSR0 _SFR_IO8(0x2D) 318 | #define SPI2X0 0 319 | #define WCOL0 6 320 | #define SPIF0 7 321 | 322 | #define SPDR0 _SFR_IO8(0x2E) 323 | 324 | /* Reserved [0x2F] */ 325 | 326 | #define ACSR _SFR_IO8(0x30) 327 | #define ACIS0 0 328 | #define ACIS1 1 329 | #define ACIC 2 330 | #define ACIE 3 331 | #define ACI 4 332 | #define ACO 5 333 | #define ACBG 6 334 | #define ACD 7 335 | 336 | /* Reserved [0x31..0x32] */ 337 | 338 | #define SMCR _SFR_IO8(0x33) 339 | #define SE 0 340 | #define SM0 1 341 | #define SM1 2 342 | #define SM2 3 343 | 344 | #define MCUSR _SFR_IO8(0x34) 345 | #define PORF 0 346 | #define EXTRF 1 347 | #define BORF 2 348 | #define WDRF 3 349 | 350 | #define MCUCR _SFR_IO8(0x35) 351 | #define IVCE 0 352 | #define IVSEL 1 353 | #define PUD 4 354 | #define BODSE 5 355 | #define BODS 6 356 | 357 | /* Reserved [0x36] */ 358 | 359 | #define SPMCSR _SFR_IO8(0x37) 360 | #define SPMEN 0 361 | #define PGERS 1 362 | #define PGWRT 2 363 | #define BLBSET 3 364 | #define RWWSRE 4 365 | #define SIGRD 5 366 | #define RWWSB 6 367 | #define SPMIE 7 368 | 369 | /* Reserved [0x38..0x3C] */ 370 | 371 | /* SP [0x3D..0x3E] */ 372 | 373 | /* SREG [0x3F] */ 374 | 375 | #define WDTCSR _SFR_MEM8(0x60) 376 | #define WDE 3 377 | #define WDCE 4 378 | #define WDP0 0 379 | #define WDP1 1 380 | #define WDP2 2 381 | #define WDP3 5 382 | #define WDIE 6 383 | #define WDIF 7 384 | 385 | #define CLKPR _SFR_MEM8(0x61) 386 | #define CLKPS0 0 387 | #define CLKPS1 1 388 | #define CLKPS2 2 389 | #define CLKPS3 3 390 | #define CLKPCE 7 391 | 392 | #define XFDCSR _SFR_MEM8(0x62) 393 | #define XFDIE 0 394 | #define XFDIF 1 395 | 396 | /* Reserved [0x63] */ 397 | 398 | #define PRR0 _SFR_MEM8(0x64) 399 | #define PRADC 0 400 | #define PRUSART0 1 401 | #define PRSPI0 2 402 | #define PRTIM1 3 403 | #define PRUSART1 4 404 | #define PRTIM0 5 405 | #define PRTIM2 6 406 | #define PRTWI0 7 407 | 408 | #define __AVR_HAVE_PRR0 ((1<