From c602781645a70d01b104225bde9d7491e27700c8 Mon Sep 17 00:00:00 2001 From: demonchy Date: Tue, 29 Mar 2005 18:26:54 +0000 Subject: Initial revision --- n/avr/twi-master/Makefile | 18 ++++ n/avr/twi-master/Makefile.avr | 114 ++++++++++++++++++++++++ n/avr/twi-master/avrconfig.h | 30 +++++++ n/avr/twi-master/test_twi_master.c | 63 ++++++++++++++ n/avr/twi-master/testconfig.h | 62 +++++++++++++ n/avr/twi-master/twi_master.c | 173 +++++++++++++++++++++++++++++++++++++ n/avr/twi-master/twi_master.h | 34 ++++++++ 7 files changed, 494 insertions(+) create mode 100644 n/avr/twi-master/Makefile create mode 100644 n/avr/twi-master/Makefile.avr create mode 100644 n/avr/twi-master/avrconfig.h create mode 100644 n/avr/twi-master/test_twi_master.c create mode 100644 n/avr/twi-master/testconfig.h create mode 100644 n/avr/twi-master/twi_master.c create mode 100644 n/avr/twi-master/twi_master.h (limited to 'n/avr/twi-master') diff --git a/n/avr/twi-master/Makefile b/n/avr/twi-master/Makefile new file mode 100644 index 0000000..f286664 --- /dev/null +++ b/n/avr/twi-master/Makefile @@ -0,0 +1,18 @@ +PROGS = test_twi_master +test_twi_master_OBJECTS = test_twi_master.o twi_master.o proto.o rs232.o +DOC = twi_master.html +EXTRACTDOC = avrconfig.h twi_master.h +MODULES = n/avr/rs232 n/avr/proto +CONFIGFILE = testconfig.h +# atmega8, atmega8535, atmega128... +MCU_TARGET = atmega8 +# -O2 : speed +# -Os : size +OPTIMIZE = -O2 + +DEFS = +LIBS = + +include Makefile.avr + +test_twi_master.elf: $(test_twi_master_OBJECTS) diff --git a/n/avr/twi-master/Makefile.avr b/n/avr/twi-master/Makefile.avr new file mode 100644 index 0000000..c010642 --- /dev/null +++ b/n/avr/twi-master/Makefile.avr @@ -0,0 +1,114 @@ +# Flags. {{{1 + +CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) +CPPFLAGS = $(DEFS) -MMD $(INCLUDES) \ + $(if $(CONFIGFILE), $(CONFIGFILE:%=-include %)) +INCLUDES = -Imodules +LDFLAGS = $(CFLAGS) + +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump + +# Main rules. {{{1 + +all: elf lst hex + +.PHONY: all clean elf lst doc text hex srec bin eeprom ehex esrec ebin + +# Rules for modules. {{{1 + +VPATH = $(MODULES:%=modules/%) + +modules_checkout: modules_co + +modules_co: $(MODULES:%=modules_co.%) + +$(MODULES:%=modules_co.%): + mkdir -p modules + cd modules && cvs co $(@:modules_co.%=%) + +modules_update: modules_up + +modules_up: $(MODULES:%=modules_up.%) + +$(MODULES:%=modules_up.%): + cd modules/$(@:modules_up.%=%) && cvs up + +# General rules. {{{1 + +ELFS = $(PROGS:%=%.elf) +OBJECTS = $(filter %.o,$(foreach prog,$(PROGS),$($(prog)_OBJECTS))) + +elf: $(ELFS) +lst: $(PROGS:%=%.lst) + +# Great piece of rules which only works in make 3.80+. +# define PROG_template +# $(1).elf: $$($(1)_OBJECTS) +# endef +# +# $(foreach prog,$(PROGS),$(eval $(call PROG_template,$(prog)))) + +$(ELFS): + $(LINK.o) $^ $(LDLIBS) -o $@ + +%.lst: %.elf + $(OBJDUMP) -h -S $< > $@ + +# Dependency checking. +-include $(OBJECTS:%.o=%.d) + +clean: + rm -f *.o *.d $(ELFS) *.lst *.map *.bak *~ + rm -f $(DOC) *.exd $(EXTRA_CLEAN_FILES) $(TEXTS) $(EEPROMS) + +# Rules for building the doc. {{{1 + +doc: $(DOC) + +%.html: %.txt %.exd + aft $< + +%.exd: $(EXTRACTDOC) + test -n "$^" && extractdoc $^ > $@ || true + +# Rules for building the .text rom images. {{{1 + +TEXTS = $(PROGS:%=%.hex) $(PROGS:%=%.bin) $(PROGS:%=%.srec) + +text: hex bin srec + +hex: $(PROGS:%=%.hex) +bin: $(PROGS:%=%.bin) +srec: $(PROGS:%=%.srec) + +%.hex: %.elf + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.srec: %.elf + $(OBJCOPY) -j .text -j .data -O srec $< $@ + +%.bin: %.elf + $(OBJCOPY) -j .text -j .data -O binary $< $@ + +# Rules for building the .eeprom rom images. {{{1 + +EEPROMS = $(PROGS:%=%_eeprom.hex) $(PROGS:%=%_eeprom.bin) \ + $(PROGS:%=%_eeprom.srec) + +eeprom: ehex ebin esrec + +ehex: $(PROGS:%=%_eeprom.hex) +ebin: $(PROGS:%=%_eeprom.bin) +esrec: $(PROGS:%=%_eeprom.srec) + +%_eeprom.hex: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ + +%_eeprom.srec: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ + +%_eeprom.bin: %.elf + $(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ + diff --git a/n/avr/twi-master/avrconfig.h b/n/avr/twi-master/avrconfig.h new file mode 100644 index 0000000..9bbc81f --- /dev/null +++ b/n/avr/twi-master/avrconfig.h @@ -0,0 +1,30 @@ +#ifndef avrconfig_h +#define avrconfig_h +// avrconfig.h +// n.avr.twi-master - Avr Twi Master Module. {{{ +// +// Copyright (C) 2005 Clément Demonchy +// +// Robot APB Team/Efrei 2005. +// Web: http://assos.efrei.fr/robot/ +// Email: robot AT efrei DOT fr +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// +// }}} + +#define TWI_BUF_SIZE 2 + +#endif // avrconfig_h diff --git a/n/avr/twi-master/test_twi_master.c b/n/avr/twi-master/test_twi_master.c new file mode 100644 index 0000000..dbce0ad --- /dev/null +++ b/n/avr/twi-master/test_twi_master.c @@ -0,0 +1,63 @@ +/* test_twi_master.c */ + +#include "twi_master.h" + +#include +#include +#include +#include + +void proto_callback (uint8_t cmd, uint8_t size, uint8_t *args) +{ + uint8_t data[1] = {0x00}; + int8_t c; + sei (); + switch (cmd) + { + case 's': + if (size == 2) + { + proto_send ('s', 0, 0); + twi_master_send (args[0], &args[1], 1); + proto_send ('f', 0, 0); + } + else + proto_send ('e', 0, 0); + break; + case 'r': + if (size == 2) + { + rs232_putc ('r'); + c = twi_master_read (args[0], data, 1); + if (c != 0) + proto_send ('e', 1 , 0); + else + proto_send ('f', 1, data); + } + else + proto_send ('e', 1, 0); + break; + default: + proto_send ('e', 1, 0); + } +} + +int +main (void) +{ + uint8_t c; + rs232_init (); + twi_master_init (); + rs232_putc ('m'); + rs232_putc ('s'); + rs232_putc ('s'); + rs232_putc ('\n'); + //DDRC = 1; + //PORTC = 1; + while (42) + { + c = rs232_getc (); + proto_accept (c); + } + return 0; +} diff --git a/n/avr/twi-master/testconfig.h b/n/avr/twi-master/testconfig.h new file mode 100644 index 0000000..2bd51a2 --- /dev/null +++ b/n/avr/twi-master/testconfig.h @@ -0,0 +1,62 @@ +#ifndef testconfig_h +#define testconfig_h +/* testconfig.h */ +/* n.avr.proto - Protocol Module. {{{ + * + * Copyright (C) 2004 Nicolas Schodet + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Contact : + * Web: http://perso.efrei.fr/~schodet/ + * Email: + * }}} */ + +#include "avrconfig.h" + +/* proto - Protocol module. */ +/** Maximum argument number. */ +#define AC_PROTO_ARGS_MAX_SIZE 3 +/** Protocol arguments type. */ +#define AC_PROTO_CALLBACK proto_callback +#define AC_PROTO_PUTC rs232_putc + +/* global */ +/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800, + * 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */ +#define AC_FREQ 14745600 + +/* rs232 - RS232 Module. */ +/** Baudrate : 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800, + * 115200, 230400, 250000, 500000, 1000000. */ +#define AC_RS232_BAUDRATE 115200 +/** Send mode : + * - POLLING : no interrupts; + * - RING : interrupts, ring buffer. */ +#define AC_RS232_SEND_MODE POLLING +/** Recv mode, same as send mode. */ +#define AC_RS232_RECV_MODE POLLING +/** Character size : 5, 6, 7, 8, 9 (only 8 implemented). */ +#define AC_RS232_CHAR_SIZE 8 +/** Parity : ODD, EVEN, NONE. */ +#define AC_RS232_PARITY EVEN +/** Stop bits : 1, 2. */ +#define AC_RS232_STOP_BITS 1 +/** Send buffer size, should be power of 2 for RING mode. */ +#define AC_RS232_SEND_BUFFER_SIZE 32 +/** Recv buffer size, should be power of 2 for RING mode. */ +#define AC_RS232_RECV_BUFFER_SIZE 32 + +#endif /* testconfig_h */ diff --git a/n/avr/twi-master/twi_master.c b/n/avr/twi-master/twi_master.c new file mode 100644 index 0000000..ee556ca --- /dev/null +++ b/n/avr/twi-master/twi_master.c @@ -0,0 +1,173 @@ +/* twi_master.c */ +#include "twi_master.h" + +#include +#include +#include +#include +#include + + +#define NB_ITER_WAIT 40000 +#define NB_RETRY 5 + +static uint8_t buffer[TWI_BUF_SIZE]; +static uint8_t twi_dest_addr; +static uint8_t twi_len; +static uint8_t twi_idx; +static uint8_t twi_nb_retry; +uint8_t twi_state = 0; + +#define SYSCLK 14745600UL + +/* compteur 10 ms pour attente du bus 40 000 iterations */ +/* compteur x essais y ms secondes d'attende */ +void +twi_master_init (void) +{ + /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ +#if defined(TWPS0) + TWSR = 0; +#endif + TWBR = (SYSCLK / 100000UL - 16) / 2; + TWCR = _BV (TWEN) | _BV (TWIE); +} + +int8_t +twi_master_send (uint8_t addr, uint8_t data[], uint8_t len) +{ + rs232_putc ('a'); + twi_state = 0; + twi_nb_retry = 0; + if (len > TWI_BUF_SIZE) + return -1; + twi_dest_addr = addr & 0xfe; + twi_len = len; + memcpy (buffer, data, len); + /* envoie du start */ + TWCR |= _BV(TWSTA); + TWCR |= _BV(TWINT); + rs232_putc ('b'); + while (!twi_state) + ; + rs232_putc ('c'); + return twi_state; +} + +int8_t +twi_master_read (uint8_t addr, uint8_t data[], uint8_t len) +{ + rs232_putc ('a'); + twi_state = 0; + twi_nb_retry = 0; + if (len > TWI_BUF_SIZE) + return -1; + twi_dest_addr = addr | 0x01; + twi_len = len; + //TWCR &= ~_BV (TWSTO); + TWCR |= _BV(TWSTA) | _BV (TWINT); + rs232_putc ('z'); + while (!twi_state) + ; + rs232_putc ('x'); + memcpy (data, buffer, len); + rs232_putc ('w'); + return twi_state; +} + +SIGNAL (SIG_2WIRE_SERIAL) +{ + rs232_putc ('y'); + switch (TW_STATUS) + { + /* Master */ + case TW_START: + case TW_REP_START: + /* start transmis, on envoie l'adresse */ + rs232_putc ('d'); + TWCR &= ~ (_BV (TWSTA) | _BV (TWSTO) | _BV (TWINT)); + TWDR = twi_dest_addr; + twi_idx = 0; + break; + case TW_MT_ARB_LOST: /* valable pour le receiver aussi */ + /* todo */ + rs232_putc ('e'); + break; + /* Master Transmitter */ + case TW_MT_DATA_ACK: + case TW_MT_SLA_ACK: + /* slave ok + * On envoi des données si il en reste + */ + if (twi_idx < twi_len) + { + rs232_putc ('f'); + TWDR = buffer[twi_idx ++]; + } + else + { + TWCR |= _BV (TWSTO); + rs232_putc ('g'); + twi_state = 1; + } + break; + case TW_MT_SLA_NACK: + /* le slave ne repond plus + * on essaye NB_RETRY avant d'arreter + */ + if (twi_nb_retry < NB_RETRY) + { + rs232_putc ('h'); + TWCR |= _BV (TWSTA); + twi_nb_retry ++; + } + else + { + rs232_putc ('i'); + TWCR |= _BV (TWSTO); + twi_state = 2; + } + break; + case TW_MT_DATA_NACK: + /* le slave ne veut plus de donnée */ + rs232_putc ('j'); + TWCR |= _BV (TWSTO); + twi_state = 1; + break; + /* Master Receiver */ + case TW_MR_SLA_ACK: + rs232_putc ('p'); + if (twi_len > 1) /* on recoit plusieurs octet */ + { + rs232_putc ('k'); + TWCR |= _BV (TWEA); + } + break; + case TW_MR_SLA_NACK: + if (twi_nb_retry < NB_RETRY) + { + rs232_putc ('l'); + TWCR |= _BV (TWEA); + } + else + { + rs232_putc ('m'); + TWCR |= _BV (TWSTO); + twi_state = -2; + } + break; + case TW_MR_DATA_ACK: + buffer[twi_idx ++] = TWDR; + rs232_putc ('n'); + if (twi_idx == (twi_len - 1)) + TWCR |= _BV (TWEA); + break; + case TW_MR_DATA_NACK: /* dernier byte */ + twi_state = 1; + rs232_putc ('o'); + buffer[twi_idx ++] = TWDR; + TWCR |= _BV (TWSTO); + break; + } + TWCR |= _BV (TWINT); +} diff --git a/n/avr/twi-master/twi_master.h b/n/avr/twi-master/twi_master.h new file mode 100644 index 0000000..0f667c3 --- /dev/null +++ b/n/avr/twi-master/twi_master.h @@ -0,0 +1,34 @@ +#ifndef twi_master_h +#define twi_master_h +/* twi_master.h */ +/* n.avr.twi - AVR TWI Module. {{{ + * + * Copyright (C) 2004 Clément Demonchy + * + * Robot APB Team/Efrei 2005. + * Web: http://assos.efrei.fr/robot/ + * Email: robot AT efrei DOT fr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * }}} */ + +#include + +void twi_master_init (void); +int8_t twi_master_send (uint8_t addr, uint8_t data[], uint8_t len); +int8_t twi_master_read (uint8_t addr, uint8_t data[], uint8_t len); + +#endif /* twi_master_h */ -- cgit v1.2.3