From 67755c5e9684d0d70ac4947f1a150b75593ba105 Mon Sep 17 00:00:00 2001 From: Jérémy Dufour Date: Sun, 9 Mar 2008 19:54:27 +0100 Subject: * digital/io - add asserv communication implementation (not fully completed); - correct a few English errors in asserv module (header and documentation); - add main timer to repeat the main loop every 4.444 ms; - add build system. --- digital/io/src/Makefile | 12 ++ digital/io/src/asserv.c | 255 ++++++++++++++++++++++++++++++++++++++++ digital/io/src/asserv.h | 2 +- digital/io/src/avrconfig.h | 98 +++++++++++++++ digital/io/src/main.c | 131 +++++++++++++++++++++ digital/io/src/main_timer.avr.h | 62 ++++++++++ 6 files changed, 559 insertions(+), 1 deletion(-) create mode 100644 digital/io/src/Makefile create mode 100644 digital/io/src/asserv.c create mode 100644 digital/io/src/avrconfig.h create mode 100644 digital/io/src/main.c create mode 100644 digital/io/src/main_timer.avr.h (limited to 'digital/io/src') diff --git a/digital/io/src/Makefile b/digital/io/src/Makefile new file mode 100644 index 00000000..70dc62c7 --- /dev/null +++ b/digital/io/src/Makefile @@ -0,0 +1,12 @@ +BASE = ../../avr +AVR_PROGS = io +io_SOURCES = main.c asserv.c +MODULES = proto uart twi +CONFIGFILE = avrconfig.h +# atmega8, atmega8535, atmega128... +AVR_MCU = atmega128 +# -O2 : speed +# -Os : size +OPTIMIZE = -O2 + +include $(BASE)/make/Makefile.gen diff --git a/digital/io/src/asserv.c b/digital/io/src/asserv.c new file mode 100644 index 00000000..d36deb91 --- /dev/null +++ b/digital/io/src/asserv.c @@ -0,0 +1,255 @@ +/* asserv.c */ +/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{ + * + * Copyright (C) 2008 Dufour Jérémy + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * 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 "asserv.h" + +#include "modules/twi/twi.h" /* twi_* */ +#include "modules/utils/byte.h" /* v*_to_v* */ + +/** + * Sequence number. + * It is used for the acknowledge of the command send to the asserv. + */ +static uint8_t asserv_twi_seq; + +/** + * Flag to know if last command has been proceed by the asserv board. + */ +static uint8_t asserv_twi_seq_ack; + +/** + * Shared buffer used to send commands to the asserv. + */ +static uint8_t asserv_twi_buffer[7]; + +/** + * Pointer to access the buffer to put the parameters list. + */ +static uint8_t *asserv_twi_buffer_param = &asserv_twi_buffer[2]; + +/** + * Update TWI module until request (send or receive) is finished. + * This functions is blocking. + */ +static inline void +asserv_twi_update (void); + +/** + * Send a command to the asserv board using the TWI module. + * If the command you want to send have some parameters, you need to fill + * asserv_twi_buffer_param buffer. + * @param command the command to send. + * @param length the length of the parameters list (in byte). + * @return + * - 0 when there is no error + * - 1 if there is already a command running on the asserv (not acknowledged + * or not finished yet). + */ +static inline uint8_t +asserv_twi_send_command (uint8_t command, uint8_t length); + + +/** + * Settings list of the asserv program. + */ +enum asserv_setting_e +{ + POSITION_X, + POSITION_Y, + POSITION_ANGULAR, + SPEED +}; + +/* Initialize the asserv control module. */ +void +asserv_init (void) +{ + /* Initialize TWI with my (io) address */ + twi_init (AC_IO_TWI_ADDRESS); + /* We are at first command */ + asserv_twi_seq = asserv_twi_seq_ack = 0; +} + +/* Update TWI module until request (send or receive) is finished. */ +static inline void +asserv_twi_update (void) +{ + while (!twi_ms_is_finished ()) + ; +} + +/* Send a command to the asserv board using the TWI module. */ +static inline uint8_t +asserv_twi_send_command (uint8_t command, uint8_t length) +{ + /* Check we are not doing a command ? */ + if (asserv_twi_seq != asserv_twi_seq_ack) + return 1; + + /* Put the command into the buffer */ + asserv_twi_buffer[0] = command; + /* Put the sequence number */ + asserv_twi_buffer[1] = ++asserv_twi_seq; + + /* Send command to the asserv */ + if (twi_ms_send (AC_ASSERV_TWI_ADDRESS, asserv_twi_buffer, length + 2) != 0) + return -1; + + /* Update until the command is sent */ + asserv_twi_update (); + return 0; +} + +/* Reset the asserv board. */ +void +asserv_reset (void) +{ + /* Send the reset command to the asserv board */ + asserv_twi_send_command ('z', 0); +} + +/* Free the motors (stop controlling them). */ +void +asserv_free_motor (void) +{ + /* Send the free motor command to the asserv board */ + asserv_twi_send_command ('w', 0); +} + +/* Stop the motor (and the bot). */ +void +asserv_stop_motor (void) +{ + /* Send the stop motor command to the asserv board */ + asserv_twi_send_command ('s', 0); +} + +/* Move linearly. */ +void +asserv_move_linearly (int32_t distance) +{ + /* Put distance as parameter */ + asserv_twi_buffer_param[0] = v32_to_v8 (distance, 3); + asserv_twi_buffer_param[1] = v32_to_v8 (distance, 2); + asserv_twi_buffer_param[2] = v32_to_v8 (distance, 1); + /* Send the linear move command to the asserv board */ + asserv_twi_send_command ('l', 3); +} + + /* Move angularly (turn). */ +void +asserv_move_angularly (int16_t angle) +{ + /* Put angle as parameter */ + asserv_twi_buffer_param[0] = v16_to_v8 (angle, 1); + asserv_twi_buffer_param[1] = v16_to_v8 (angle, 0); + /* Send the angular move command to the asserv board */ + asserv_twi_send_command ('a', 2); +} + +/* Go to the wall (moving backward). */ +void +asserv_go_to_the_wall (void) +{ + /* Send the go the wall command to the asserv board */ + asserv_twi_send_command ('f', 0); +} + +/* Move forward to approach a gutter. */ +void +asserv_go_to_gutter (void) +{ + /* Send the go the gutter command to the asserv board */ + asserv_twi_send_command ('F', 0); +} + +/* Move the arm. */ +void +asserv_move_arm (uint16_t position, uint8_t speed) +{ + /* Put position and speed as parameters */ + asserv_twi_buffer_param[0] = v16_to_v8 (position, 1); + asserv_twi_buffer_param[1] = v16_to_v8 (position, 0); + asserv_twi_buffer_param[2] = speed; + /* Send the move the arm command to the asserv board */ + asserv_twi_send_command ('b', 3); +} + +/* Set current X position. */ +void +asserv_set_x_position (int32_t x) +{ + /* 'X' subcommand */ + asserv_twi_buffer_param[0] = 'X'; + /* Put x position as parameter */ + asserv_twi_buffer_param[1] = v32_to_v8 (x, 3); + asserv_twi_buffer_param[2] = v32_to_v8 (x, 2); + asserv_twi_buffer_param[3] = v32_to_v8 (x, 1); + /* Send the set X position command to the asserv board */ + asserv_twi_send_command ('p', 4); +} + +/* Set current Y position. */ +void +asserv_set_y_position (int32_t y) +{ + /* 'Y' subcommand */ + asserv_twi_buffer_param[0] = 'Y'; + /* Put y position as parameter */ + asserv_twi_buffer_param[1] = v32_to_v8 (y, 3); + asserv_twi_buffer_param[2] = v32_to_v8 (y, 2); + asserv_twi_buffer_param[3] = v32_to_v8 (y, 1); + /* Send the set Y position command to the asserv board */ + asserv_twi_send_command ('p', 4); +} + +/* Set current angular position. */ +void +asserv_set_angle_position (int16_t angle) +{ + /* 'A' subcommand */ + asserv_twi_buffer_param[0] = 'A'; + /* Put angle position as parameter */ + asserv_twi_buffer_param[1] = v32_to_v8 (angle, 1); + asserv_twi_buffer_param[2] = v32_to_v8 (angle, 0); + /* Send the set angular position command to the asserv board */ + asserv_twi_send_command ('p', 3); +} + +/* Set speeds of movements. */ +void +asserv_set_speed (uint8_t linear_high, uint8_t angular_high, + uint8_t linear_low, uint8_t angular_low) +{ + /* 's' subcommand */ + asserv_twi_buffer_param[0] = 's'; + /* Put speeds as parameters */ + asserv_twi_buffer_param[1] = linear_high; + asserv_twi_buffer_param[2] = angular_high; + asserv_twi_buffer_param[3] = linear_low; + asserv_twi_buffer_param[4] = angular_low; + /* Send the set speed of movements command to the asserv board */ + asserv_twi_send_command ('p', 5); +} diff --git a/digital/io/src/asserv.h b/digital/io/src/asserv.h index 138fb6f3..a4c680af 100644 --- a/digital/io/src/asserv.h +++ b/digital/io/src/asserv.h @@ -100,7 +100,7 @@ asserv_go_to_gutter (void); /** * Move the arm. - * A complete rotation correspond to 5000 step. + * A complete rotation correspond to 5000 steps. * Arm class command. * @param position desired goal position (in step). * @param speed speed of the movement. diff --git a/digital/io/src/avrconfig.h b/digital/io/src/avrconfig.h new file mode 100644 index 00000000..4d72b213 --- /dev/null +++ b/digital/io/src/avrconfig.h @@ -0,0 +1,98 @@ +#ifndef avrconfig_h +#define avrconfig_h +/* avrconfig.h */ +/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{ + * + * Copyright (C) 2008 Dufour Jérémy + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * 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. + * + * }}} */ + +/* global */ +/** AVR Frequency : 1000000, 1843200, 2000000, 3686400, 4000000, 7372800, + * 8000000, 11059200, 14745600, 16000000, 18432000, 20000000. */ +#define AC_FREQ 14745600 + +/* uart - UART module. */ +/** Select hardware uart for primary uart: 0, 1 or -1 to disable. */ +#define AC_UART0_PORT 1 +/** Baudrate: 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 76800, + * 115200, 230400, 250000, 500000, 1000000. */ +#define AC_UART0_BAUDRATE 38400 +/** Send mode: + * - POLLING: no interrupts. + * - RING: interrupts, ring buffer. */ +#define AC_UART0_SEND_MODE POLLING +/** Recv mode, same as send mode. */ +#define AC_UART0_RECV_MODE POLLING +/** Character size: 5, 6, 7, 8, 9 (only 8 implemented). */ +#define AC_UART0_CHAR_SIZE 8 +/** Parity : ODD, EVEN, NONE. */ +#define AC_UART0_PARITY EVEN +/** Stop bits : 1, 2. */ +#define AC_UART0_STOP_BITS 1 +/** Send buffer size, should be power of 2 for RING mode. */ +#define AC_UART0_SEND_BUFFER_SIZE 32 +/** Recv buffer size, should be power of 2 for RING mode. */ +#define AC_UART0_RECV_BUFFER_SIZE 32 +/** If the send buffer is full when putc: + * - DROP: drop the new byte. + * - WAIT: wait until there is room in the send buffer. */ +#define AC_UART0_SEND_BUFFER_FULL WAIT +/** In HOST compilation: + * - STDIO: use stdin/out. + * - PTS: use pseudo terminal. */ +#define AC_UART0_HOST_DRIVER PTS +/** Same thing for secondary port. */ +#define AC_UART1_PORT -1 +#define AC_UART1_BAUDRATE 115200 +#define AC_UART1_SEND_MODE RING +#define AC_UART1_RECV_MODE RING +#define AC_UART1_CHAR_SIZE 8 +#define AC_UART1_PARITY EVEN +#define AC_UART1_STOP_BITS 1 +#define AC_UART1_SEND_BUFFER_SIZE 32 +#define AC_UART1_RECV_BUFFER_SIZE 32 +#define AC_UART1_SEND_BUFFER_FULL WAIT +#define AC_UART1_HOST_DRIVER PTS + +/* proto - Protocol module. */ +/** Maximum argument size. */ +#define AC_PROTO_ARGS_MAX_SIZE 12 +/** Callback function name. */ +#define AC_PROTO_CALLBACK proto_callback +/** Putchar function name. */ +#define AC_PROTO_PUTC uart0_putc +/** Support for quote parameter. */ +#define AC_PROTO_QUOTE 1 + +/* twi - TWI module. */ +/** Activate master part. */ +#define AC_TWI_MASTER_ENABLE 1 +/** Activate slave part. */ +#define AC_TWI_SLAVE_ENABLE 0 + +/* io - io/ai board. */ +/** TWI address of the io board. */ +#define AC_IO_TWI_ADDRESS 2 +/** TWI address of the asserv board. */ +#define AC_ASSERV_TWI_ADDRESS 4 + +#endif /* avrconfig_h */ diff --git a/digital/io/src/main.c b/digital/io/src/main.c new file mode 100644 index 00000000..602688ef --- /dev/null +++ b/digital/io/src/main.c @@ -0,0 +1,131 @@ +/* main.c */ +/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{ + * + * Copyright (C) 2008 Dufour Jérémy + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * 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 "common.h" +#include "io.h" +#include "modules/uart/uart.h" +#include "modules/proto/proto.h" +#include "modules/utils/utils.h" + +/* AVR include, non HOST */ +#ifndef HOST +# include "main_timer.avr.h" +#endif /* HOST */ + +#include "asserv.h" /* Functions to control the asserv board */ + +/** + * Initialize the main and all its subsystems. + */ +static void main_init (void); + +/** + * Main (and infinite) loop of the io program. + */ +static void main_loop (void); + +/** + * Initialize the main and all its subsystems. + */ +static void +main_init (void) +{ + /* Serial port */ + uart0_init (); + /* Main timer */ + main_timer_init (); + /* Asserv communication */ + asserv_init (); + + /* Enable interrupts */ + sei (); + + /* io initialization done */ + proto_send0 ('z'); +} + +/** + * Main (and infinite) loop of the io program. + */ +static void +main_loop (void) +{ + /* Infinite loop */ + while (1) + { + /* Wait for an overflow of the main timer (4.444ms) */ + main_timer_wait (); + + /* Get the data from the UART */ + while (uart0_poll ()) + /* Manage UART protocol */ + proto_accept (uart0_getc ()); + + /* Update TWI module to get new data */ + // TODO + } +} + +/** + * Manage received UART commands. + * @param cmd commands received. + * @param size the length of arguments. + * @param args the argument of the command. + */ +void +proto_callback (uint8_t cmd, uint8_t size, uint8_t *args) +{ +#define c(cmd, size) (cmd << 8 | size) + switch (c (cmd, size)) + { + case c ('z', 0): + /* Reset */ + utils_reset (); + break; + + default: + /* Unknown commands */ + proto_send0 ('?'); + return; + } + /* When no error, acknowledge commands */ + proto_send (cmd, size, args); +#undef c +} + +/** + * Main function. + */ +int +main (int argc, char **argv) +{ + /* Initialize the main and its subsystems */ + main_init (); + + /* Start the main loop */ + main_loop (); + + return 0; +} diff --git a/digital/io/src/main_timer.avr.h b/digital/io/src/main_timer.avr.h new file mode 100644 index 00000000..528c8e4d --- /dev/null +++ b/digital/io/src/main_timer.avr.h @@ -0,0 +1,62 @@ +#ifndef main_timer_avr_h +#define main_timer_avr_h +/* main_timer.avr.h */ +/* io - Input & Output with Artificial Intelligence (ai) support on AVR. {{{ + * + * Copyright (C) 2008 Dufour Jérémy + * + * APBTeam: + * Web: http://apbteam.org/ + * Email: team AT apbteam DOT org + * + * 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. + * + * }}} */ + +/** + * @file Main timer module. + * Main timer module is used for the main loop of the io board to ensure it is + * executed only to the defined loop time (at the maximum). It uses the + * timer/counter 0 of the AVR. + */ + +/** + * Initialize the main timer to 4.444 ms. + */ +static inline void +main_timer_init (void) +{ + /* Fov = F_io / (prescaler * (TOP + 1)) + * TOP = 0xff + * prescaler = 256 + * Tov = 1 / Fov = 4.444 ms */ + TCCR0 = regv (FOC0, WGM00, COM01, COM0, WGM01, CS02, CS01, CS00, + 0, 0, 0, 0, 0, 1, 1, 0); +} + +/** + * Wait until the main timer overflows. + */ +static inline void +main_timer_wait (void) +{ + /* Loop until an overflow of the timer occurs */ + while (!(TIFR & _BV (TOV0))) + ; + /* Write 1 to clear */ + TIFR = _BV (TOV0); +} + +#endif /* main_timer_avr_h */ -- cgit v1.2.3