From b1f14380727106642388a6d32baa3a4103a03a9b Mon Sep 17 00:00:00 2001 From: Nicolas Schodet Date: Mon, 3 Oct 2011 21:03:58 +0200 Subject: digital/avr/modules/motor: add new output module --- digital/avr/modules/motor/output/Makefile | 5 + digital/avr/modules/motor/output/Makefile.module | 1 + digital/avr/modules/motor/output/avrconfig.h | 36 ++++ digital/avr/modules/motor/output/output.c | 90 +++++++++ digital/avr/modules/motor/output/output.h | 68 +++++++ digital/avr/modules/motor/output/output.txt | 34 ++++ digital/avr/modules/motor/output/output_host.h | 37 ++++ .../avr/modules/motor/output/output_host.host.c | 37 ++++ .../modules/motor/output/pwm_mp/Makefile.module | 1 + .../avr/modules/motor/output/pwm_mp/avrconfig.h | 37 ++++ .../motor/output/pwm_mp/output_pwm_mp.avr.c | 165 +++++++++++++++++ .../modules/motor/output/pwm_mp/output_pwm_mp.h | 37 ++++ .../modules/motor/output/pwm_ocr/Makefile.module | 1 + .../avr/modules/motor/output/pwm_ocr/avrconfig.h | 53 ++++++ .../motor/output/pwm_ocr/output_pwm_ocr.avr.c | 203 +++++++++++++++++++++ .../modules/motor/output/pwm_ocr/output_pwm_ocr.h | 37 ++++ digital/avr/modules/motor/output/test/Makefile | 23 +++ .../avr/modules/motor/output/test/avrconfig_both.h | 136 ++++++++++++++ .../avr/modules/motor/output/test/avrconfig_mp.h | 109 +++++++++++ .../avr/modules/motor/output/test/avrconfig_ocr.h | 117 ++++++++++++ .../avr/modules/motor/output/test/test_output.c | 154 ++++++++++++++++ 21 files changed, 1381 insertions(+) create mode 100644 digital/avr/modules/motor/output/Makefile create mode 100644 digital/avr/modules/motor/output/Makefile.module create mode 100644 digital/avr/modules/motor/output/avrconfig.h create mode 100644 digital/avr/modules/motor/output/output.c create mode 100644 digital/avr/modules/motor/output/output.h create mode 100644 digital/avr/modules/motor/output/output.txt create mode 100644 digital/avr/modules/motor/output/output_host.h create mode 100644 digital/avr/modules/motor/output/output_host.host.c create mode 100644 digital/avr/modules/motor/output/pwm_mp/Makefile.module create mode 100644 digital/avr/modules/motor/output/pwm_mp/avrconfig.h create mode 100644 digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.avr.c create mode 100644 digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.h create mode 100644 digital/avr/modules/motor/output/pwm_ocr/Makefile.module create mode 100644 digital/avr/modules/motor/output/pwm_ocr/avrconfig.h create mode 100644 digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.avr.c create mode 100644 digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.h create mode 100644 digital/avr/modules/motor/output/test/Makefile create mode 100644 digital/avr/modules/motor/output/test/avrconfig_both.h create mode 100644 digital/avr/modules/motor/output/test/avrconfig_mp.h create mode 100644 digital/avr/modules/motor/output/test/avrconfig_ocr.h create mode 100644 digital/avr/modules/motor/output/test/test_output.c (limited to 'digital/avr/modules/motor') diff --git a/digital/avr/modules/motor/output/Makefile b/digital/avr/modules/motor/output/Makefile new file mode 100644 index 00000000..be444ddb --- /dev/null +++ b/digital/avr/modules/motor/output/Makefile @@ -0,0 +1,5 @@ +BASE = ../../.. +DOC = output.html +EXTRACTDOC = output.h avrconfig.h + +include $(BASE)/make/Makefile.gen diff --git a/digital/avr/modules/motor/output/Makefile.module b/digital/avr/modules/motor/output/Makefile.module new file mode 100644 index 00000000..cc7dac52 --- /dev/null +++ b/digital/avr/modules/motor/output/Makefile.module @@ -0,0 +1 @@ +motor_output_SOURCES = output.c output_host.host.c diff --git a/digital/avr/modules/motor/output/avrconfig.h b/digital/avr/modules/motor/output/avrconfig.h new file mode 100644 index 00000000..74f9ce7a --- /dev/null +++ b/digital/avr/modules/motor/output/avrconfig.h @@ -0,0 +1,36 @@ +#ifndef avrconfig_h +#define avrconfig_h +/* avrconfig.h - motor/output configuration template. */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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. + * + * }}} */ + +/* motor/output - Output module. */ +/** Use Output Compare PWM output module. */ +#define AC_OUTPUT_USE_PWM_OCR 1 +/** Use Motor Power PWM output module. */ +#define AC_OUTPUT_USE_PWM_MP 0 +/** Define module and module index for each output. */ +#define AC_OUTPUT_LIST (pwm_ocr, 0), (pwm_ocr, 1) + +#endif /* avrconfig_h */ diff --git a/digital/avr/modules/motor/output/output.c b/digital/avr/modules/motor/output/output.c new file mode 100644 index 00000000..f1e87b95 --- /dev/null +++ b/digital/avr/modules/motor/output/output.c @@ -0,0 +1,90 @@ +/* output.c */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "output.h" + +#ifdef HOST +# include "output_host.h" +# define OUTPUT_MODULES ,host +#else +# if AC_OUTPUT_USE_PWM_OCR +# include "pwm_ocr/output_pwm_ocr.h" +# define OUTPUT_MODULE_1 ,pwm_ocr +# else +# define OUTPUT_MODULE_1 +# endif +# if AC_OUTPUT_USE_PWM_MP +# include "pwm_mp/output_pwm_mp.h" +# define OUTPUT_MODULE_2 ,pwm_mp +# else +# define OUTPUT_MODULE_2 +# endif +# define OUTPUT_MODULES \ + OUTPUT_MODULE_1 OUTPUT_MODULE_2 +#endif + +void +output_init (uint8_t index, output_t *output) +{ + /* Initialize corresponding module. */ +#ifdef HOST + output_host_init (index, output); +#else +# define output_init__(module, module_index) \ + PREPROC_PASTE (output_, module, _init) (module_index, output) +# define output_init_(index, output_info) \ + case index: output_init__ output_info; break; + switch (index) + { + PREPROC_FOR_ENUM (output_init_, AC_OUTPUT_LIST) + } +#endif +} + +void +output_set (output_t *output, int16_t value) +{ + /* Reverse output if requested. */ + if (output->reverse) + value = -value; + /* Saturation and dead zone. */ + if (value > output->max) + output->cur = output->max; + else if (value < -output->max) + output->cur = -output->max; + else if (value > -output->min && value < output->min) + output->cur = 0; + else + output->cur = value; +} + +void +output_update (void) +{ + /* Update each module. */ +#define output_update_(module) PREPROC_PASTE (output_, module, _update) (); + PREPROC_FOR (output_update_ OUTPUT_MODULES) +} + diff --git a/digital/avr/modules/motor/output/output.h b/digital/avr/modules/motor/output/output.h new file mode 100644 index 00000000..a2b19b69 --- /dev/null +++ b/digital/avr/modules/motor/output/output.h @@ -0,0 +1,68 @@ +#ifndef output_h +#define output_h +/* output.h */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "preproc.h" + +/** Absolute maximum output value for any output. */ +#define OUTPUT_MAX 0x3ff + +/** Number of defined outputs. */ +#define OUTPUT_NB PREPROC_NARG (AC_OUTPUT_LIST) + +/** Output state. */ +struct output_t +{ + /** Current value. */ + int16_t cur; + /** Maximum value. */ + int16_t max; + /** Minimum value (dead zone). */ + int16_t min; + /** Reverse this output. */ + uint8_t reverse; +}; +typedef struct output_t output_t; + +/** Initialize an output and attach it to provided output structure. */ +void +output_init (uint8_t index, output_t *output); + +/** Set output value. */ +void +output_set (output_t *output, int16_t value); + +/** Set output reverse flag. */ +extern inline void +output_set_reverse (output_t *output, uint8_t reverse) +{ + output->reverse = reverse; +} + +/** Update output value in hardware. */ +void +output_update (void); + +#endif /* output_h */ diff --git a/digital/avr/modules/motor/output/output.txt b/digital/avr/modules/motor/output/output.txt new file mode 100644 index 00000000..e63ca61a --- /dev/null +++ b/digital/avr/modules/motor/output/output.txt @@ -0,0 +1,34 @@ +===================== + motor/output module +===================== +:Author: Nicolas Schodet + +Introduction +============ + +The output module provides an interface with hardware outputs. They are +usually PWM hardware connected to a H-bridge to power the motors. + +Usage +===== + +The `output_t` structure contains information about the current state and +configuration of the output. The `max` and `min` fields must be initialised +by user code (you can use a data initializer) and left untouched afterward, +then `output_init` should be called to associate each output with hardware. + +Each output hardware is associated with an index fixed in the compile time +configuration. + +To change the current output value, use the `output_set` function. It will +filter value (saturation with `max`, dead zone with `min`, optional negation +if `reverse` is set) and store it for next update. Each output hardware will +reflect this value once `output_update` is called. + +An output can be reversed by setting the `reverse` field before `output_init` +is called or using `output_set_reverse` function. + +API +=== + +.. include:: output.exd diff --git a/digital/avr/modules/motor/output/output_host.h b/digital/avr/modules/motor/output/output_host.h new file mode 100644 index 00000000..9c2845ca --- /dev/null +++ b/digital/avr/modules/motor/output/output_host.h @@ -0,0 +1,37 @@ +#ifndef output_host_h +#define output_host_h +/* output_host.h */ +/* {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "output.h" + +/** See output_init. */ +void +output_host_init (uint8_t index, output_t *output); + +/** See output_update. */ +void +output_host_update (void); + +#endif /* output_host_h */ diff --git a/digital/avr/modules/motor/output/output_host.host.c b/digital/avr/modules/motor/output/output_host.host.c new file mode 100644 index 00000000..e11a6737 --- /dev/null +++ b/digital/avr/modules/motor/output/output_host.host.c @@ -0,0 +1,37 @@ +/* output_host.c */ +/* {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "output_host.h" + +void +output_host_init (uint8_t index, output_t *output) +{ +} + +void +output_host_update (void) +{ +} + diff --git a/digital/avr/modules/motor/output/pwm_mp/Makefile.module b/digital/avr/modules/motor/output/pwm_mp/Makefile.module new file mode 100644 index 00000000..e08ad057 --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_mp/Makefile.module @@ -0,0 +1 @@ +motor_output_pwm_mp_SOURCES = output_pwm_mp.avr.c diff --git a/digital/avr/modules/motor/output/pwm_mp/avrconfig.h b/digital/avr/modules/motor/output/pwm_mp/avrconfig.h new file mode 100644 index 00000000..e4d2ffb2 --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_mp/avrconfig.h @@ -0,0 +1,37 @@ +#ifndef avrconfig_h +#define avrconfig_h +/* avrconfig.h - motor/output/pwm_mp configuration template. */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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. + * + * }}} */ + +/* motor/output/pwm_mp - Motor Power board PWM output module. */ +/** Number of outputs, there is two outputs per board. */ +#define AC_OUTPUT_PWM_MP_NB 4 +/** Slave select for first Motor Power board. + * WARNING: this must match hardware SS pin if using hardware SPI! */ +#define AC_OUTPUT_PWM_MP_SPI_SS_IO_0 B, 0 +/** Slave select for next Motor Power boards. */ +#define AC_OUTPUT_PWM_MP_SPI_SS_IO_1 E, 4 + +#endif /* avrconfig_h */ diff --git a/digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.avr.c b/digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.avr.c new file mode 100644 index 00000000..4e644da9 --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.avr.c @@ -0,0 +1,165 @@ +/* output_pwm_mp.avr.c */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "output_pwm_mp.h" + +#include "modules/spi/spi.h" +#include "io.h" + +/** Define the maximum PWM value for motor power. + * This value is lowered until the bug relatives to maximum value is fixed + * (rounding after shifting bug). */ +#define OUTPUT_PWM_MP_MAX 0x3f0 + +/* Test given configuration. */ +#if AC_OUTPUT_PWM_MP_NB != 2 && AC_OUTPUT_PWM_MP_NB != 4 +# error "motor/output/pwm_mp: unsupported configuration" +#endif + +/* Define test macro. */ +#define IF_MP(mp) (AC_OUTPUT_PWM_MP_NB >= ((mp) + 1) * 2) + +/** Output information. */ +struct output_pwm_mp_t +{ + /** Associated output state. */ + struct output_t *output; +}; +typedef struct output_pwm_mp_t output_pwm_mp_t; + +/** Global output information. */ +output_pwm_mp_t output_pwm_mp[AC_OUTPUT_PWM_MP_NB]; + +/** Global enable flag. */ +uint8_t output_pwm_mp_go; + +static void +output_pwm_mp_update_single (int16_t value1, int16_t value2); + +/** Initialize hardware, to be done once. */ +static void +output_pwm_mp_init_hardware (void) +{ + static uint8_t inited; + if (!inited) + { +#if IF_MP (0) && SPI0_DRIVER != SPI_DRIVER_HARD + /* This is done in spi_init for hardware driver. */ + IO_SET (AC_OUTPUT_PWM_MP_SPI_SS_IO_0); + IO_OUTPUT (AC_OUTPUT_PWM_MP_SPI_SS_IO_0); +#endif +#if IF_MP (1) + IO_SET (AC_OUTPUT_PWM_MP_SPI_SS_IO_1); + IO_OUTPUT (AC_OUTPUT_PWM_MP_SPI_SS_IO_1); +#endif + /* Initialise SPI. */ + spi_init (SPI_MASTER, SPI_CPOL_FALLING | SPI_CPHA_SETUP, + SPI_MSB_FIRST, SPI_FOSC_DIV16); + /* Reset PWM values at reset. */ +#if IF_MP (0) + IO_CLR (AC_OUTPUT_PWM_MP_SPI_SS_IO_0); + output_pwm_mp_update_single (0, 0); + IO_SET (AC_OUTPUT_PWM_MP_SPI_SS_IO_0); +#endif +#if IF_MP (1) + IO_CLR (AC_OUTPUT_PWM_MP_SPI_SS_IO_1); + output_pwm_mp_update_single (0, 0); + IO_SET (AC_OUTPUT_PWM_MP_SPI_SS_IO_1); +#endif + /* Done. */ + inited = 1; + } +} + +void +output_pwm_mp_init (uint8_t index, output_t *output) +{ + /* Need initialized hardware. */ + output_pwm_mp_init_hardware (); + /* Keep output structure for future usage. */ + output_pwm_mp[index].output = output; + /* Reduce maximum output if needed. */ + if (output->max > OUTPUT_PWM_MP_MAX) + output->max = OUTPUT_PWM_MP_MAX; +} + +/** Transmit value to currently selected slave. */ +static void +output_pwm_mp_update_single (int16_t value1, int16_t value2) +{ + uint8_t v; + uint8_t cks; + /* Convert to 12 bits. */ + int16_t pwm1c = value1 << 1; + int16_t pwm2c = value2 << 1; + /* Send, computing checksum on the way. */ + cks = 0x42; + v = ((pwm1c >> 4) & 0xf0) | ((pwm2c >> 8) & 0x0f); + spi_send (v); + cks ^= v; + v = pwm1c; + spi_send (v); + cks ^= v; + v = pwm2c; + spi_send (v); + cks ^= v; + spi_send (cks); +} + +void +output_pwm_mp_update (void) +{ + uint8_t i; + /* Activate output at first non zero value. */ + if (!output_pwm_mp_go) + { + for (i = 0; i < AC_OUTPUT_PWM_MP_NB; i++) + if (output_pwm_mp[i].output->cur) + output_pwm_mp_go = 1; + } + /* Update each output. */ + if (output_pwm_mp_go) + { +#if IF_MP (0) + /* Slave select. */ + IO_CLR (AC_OUTPUT_PWM_MP_SPI_SS_IO_0); + /* Transmit values. */ + output_pwm_mp_update_single (output_pwm_mp[0].output->cur, + output_pwm_mp[1].output->cur); + /* Slave deselect. */ + IO_SET (AC_OUTPUT_PWM_MP_SPI_SS_IO_0); +#endif +#if IF_MP (1) + /* Slave select. */ + IO_CLR (AC_OUTPUT_PWM_MP_SPI_SS_IO_1); + /* Transmit values. */ + output_pwm_mp_update_single (output_pwm_mp[2].output->cur, + output_pwm_mp[3].output->cur); + /* Slave deselect. */ + IO_SET (AC_OUTPUT_PWM_MP_SPI_SS_IO_1); +#endif + } +} + diff --git a/digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.h b/digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.h new file mode 100644 index 00000000..9aa0f6ad --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_mp/output_pwm_mp.h @@ -0,0 +1,37 @@ +#ifndef output_pwm_mp_h +#define output_pwm_mp_h +/* output_pwm_mp.h */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "modules/motor/output/output.h" + +/** See output_init. */ +void +output_pwm_mp_init (uint8_t index, output_t *output); + +/** See output_update. */ +void +output_pwm_mp_update (void); + +#endif /* output_pwm_mp_h */ diff --git a/digital/avr/modules/motor/output/pwm_ocr/Makefile.module b/digital/avr/modules/motor/output/pwm_ocr/Makefile.module new file mode 100644 index 00000000..f45cc8ea --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_ocr/Makefile.module @@ -0,0 +1 @@ +motor_output_pwm_ocr_SOURCES = output_pwm_ocr.avr.c diff --git a/digital/avr/modules/motor/output/pwm_ocr/avrconfig.h b/digital/avr/modules/motor/output/pwm_ocr/avrconfig.h new file mode 100644 index 00000000..ed562039 --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_ocr/avrconfig.h @@ -0,0 +1,53 @@ +#ifndef avrconfig_h +#define avrconfig_h +/* avrconfig.h - motor/output/pwm_ocr configuration template. */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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. + * + * }}} */ + +/* Example from mimot board. */ + +/* motor/output/pwm_ocr - Output Compare PWM output module. */ +/** For each output, define output parameters: + * + * (timer, ocr, pwm_io, dir_io[, brake_io]) + * + * With: + * - timer: timer number (ex: 1 for TIMER1) + * - ocr: output compare (ex: A for output compare A) + * - mode: compare output mode (ex: 2, see datasheet) + * - pwm_io: corresponding io port (ex: B, 1) + * - dir_io: io port used for direction (ex: B, 2) + * - brake_io: optional io port used for brake (ex: B, 3) + */ +#define AC_OUTPUT_PWM_OCR_LIST \ + (1, A, 2, D,5, D,3, A,4), \ + (1, B, 2, D,4, D,2, A,5) +/** Clock select for each used timer. */ +#define AC_OUTPUT_PWM_OCR_CS_1 0b0001 +/** Waveform Generation Mode for each used timer. */ +#define AC_OUTPUT_PWM_OCR_WGM_1 0b0011 +/** Offset added to PWM value to compensate for H-bridge weakness. */ +#define AC_OUTPUT_PWM_OCR_OFFSET 0x40 + +#endif /* avrconfig_h */ diff --git a/digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.avr.c b/digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.avr.c new file mode 100644 index 00000000..635b9bef --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.avr.c @@ -0,0 +1,203 @@ +/* output_pwm_ocr.c */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "output_pwm_ocr.h" + +#include "preproc.h" +#include "io.h" + +/** Mask of used timer. */ +#define TIMERS_MASK \ + (0 PREPROC_FOR (TIMERS_MASK_, AC_OUTPUT_PWM_OCR_LIST)) +#define TIMERS_MASK_(output) TIMERS_MASK__ output +#define TIMERS_MASK__(timer, args...) | _BV (timer) + +/** Test for compatible AVR. */ +#if defined (__AVR_ATmega32__) +# define SUPPORTED_TIMERS 1 +# define SUPPORTED_TIMERS_MASK 0b0010 +#elif defined (__AVR_ATmega64__) \ + || defined (__AVR_ATmega128__) \ + || defined (__AVR_AT90USB646__) \ + || defined (__AVR_AT90USB647__) \ + || defined (__AVR_AT90USB1286__) \ + || defined (__AVR_AT90USB1287__) +# define SUPPORTED_TIMERS 1, 3 +# define SUPPORTED_TIMERS_MASK 0b1010 +#else +# error "motor/output/pwm_ocr: not tested on this chip" +#endif +#if (TIMERS_MASK & ~(SUPPORTED_TIMERS_MASK)) +# error "motor/output/pwm_ocr: unsupported configuration" +#endif + +/** Define timer test macros. */ +#if TIMERS_MASK & _BV (1) +# define IF_TIMER_1(x) x +#else +# define IF_TIMER_1(x) +#endif +#if TIMERS_MASK & _BV (3) +# define IF_TIMER_3(x) x +#else +# define IF_TIMER_3(x) +#endif +#define IF_TIMER(timer, x) PREPROC_PASTE (IF_TIMER_, timer) (x) + +/** Output information. */ +struct output_pwm_ocr_t +{ + /** Associated output state. */ + struct output_t *output; +}; +typedef struct output_pwm_ocr_t output_pwm_ocr_t; + +/** Global output information. */ +output_pwm_ocr_t output_pwm_ocr[PREPROC_NARG (AC_OUTPUT_PWM_OCR_LIST)]; + +/** Initialize hardware, to be done once. */ +static void +output_pwm_ocr_init_hardware (void) +{ + static uint8_t inited; + if (!inited) + { + /* Declare a variable for each used timer to receive compare output + * mode bits. */ +#define DECLARE_TIMER(timer) \ + IF_TIMER (timer, uint8_t PREPROC_PASTE (timer_com_, timer) = 0;) + PREPROC_FOR (DECLARE_TIMER, SUPPORTED_TIMERS); +#undef DECLARE_TIMER + /* Configure each output, set compare output mode variables. */ +#define CONFIGURE_OUTPUT(output) CONFIGURE_OUTPUT_ output +#define CONFIGURE_OUTPUT_(args...) PREPROC_NARG_CALL (CONFIGURE_OUTPUT_, args) +#define CONFIGURE_OUTPUT_7(timer, ocr, mode, pwm_io_port, pwm_io_bit, \ + dir_io_port, dir_io_bit) \ + PREPROC_PASTE (timer_com_, timer) |= (mode) \ + << PREPROC_PASTE (COM, timer, ocr, 0); \ + IO_OUTPUT_ (pwm_io_port, pwm_io_bit); \ + IO_OUTPUT_ (dir_io_port, dir_io_bit); +#define CONFIGURE_OUTPUT_9(timer, ocr, mode, pwm_io_port, pwm_io_bit, \ + dir_io_port, dir_io_bit, \ + brake_io_port, brake_io_bit) \ + CONFIGURE_OUTPUT_7 (timer, ocr, mode, pwm_io_port, pwm_io_bit, \ + dir_io_port, dir_io_bit) \ + IO_OUTPUT_ (brake_io_port, brake_io_bit); + PREPROC_FOR (CONFIGURE_OUTPUT, AC_OUTPUT_PWM_OCR_LIST); +#undef CONFIGURE_OUTPUT +#undef CONFIGURE_OUTPUT_ +#undef CONFIGURE_OUTPUT_7 +#undef CONFIGURE_OUTPUT_9 + /* Initialise used timers. */ +#define WGM_BIT(timer, bit) \ + ((PREPROC_PASTE (AC_OUTPUT_PWM_OCR_WGM_, timer) & _BV (bit)) \ + ? _BV (PREPROC_PASTE (WGM, timer, bit)) : 0) +#define INIT_TIMER(timer) IF_TIMER (timer, INIT_TIMER_ (timer)) +#define INIT_TIMER_(timer) \ + PREPROC_PASTE (TCCR, timer, A) = \ + WGM_BIT (timer, 0) | WGM_BIT (timer, 1) \ + | PREPROC_PASTE (timer_com_, timer); \ + PREPROC_PASTE (TCCR, timer, B) = \ + WGM_BIT (timer, 2) | WGM_BIT (timer, 3) \ + | PREPROC_PASTE (AC_OUTPUT_PWM_OCR_CS_, timer); \ + PREPROC_FOR (INIT_TIMER, SUPPORTED_TIMERS); +#undef WGM_BIT +#undef INIT_TIMER +#undef INIT_TIMER_ + /* Done. */ + inited = 1; + } +} + +void +output_pwm_ocr_init (uint8_t index, output_t *output) +{ + /* Need initialized hardware. */ + output_pwm_ocr_init_hardware (); + /* Keep output structure for future usage. */ + output_pwm_ocr[index].output = output; + /* Reduce maximum output if needed. */ + if (output->max > OUTPUT_MAX - AC_OUTPUT_PWM_OCR_OFFSET) + output->max = OUTPUT_MAX - AC_OUTPUT_PWM_OCR_OFFSET; +} + +/** Update a single output. */ +static inline void +output_pwm_ocr_update_output (uint8_t index, volatile uint16_t *ocr, + volatile uint8_t *dir_io_port, + uint8_t dir_io_bit, + volatile uint8_t *brake_io_port, + uint8_t brake_io_bit) +{ + /* Here, there could be a problem because OCRx are double buffered, not + * PORTx! + * Another problem arise if the OCR sampling is done between left and + * right OCR: the right PWM is one cycle late. + * A solution could be to use interrupts to update PWM or to synchronise + * general timer with PWM. */ + int16_t value = output_pwm_ocr[index].output->cur; + if (value == 0) + { + *ocr = 0; + } + else + { + /* Brake is engaged on first non null value. */ + if (brake_io_port) + *brake_io_port |= _BV (brake_io_bit); + /* Convert signed value to sign and absolute value. */ + if (value < 0) + { + *dir_io_port &= ~_BV (dir_io_bit); + *ocr = -value + AC_OUTPUT_PWM_OCR_OFFSET; + } + else + { + *dir_io_port |= _BV (dir_io_bit); + *ocr = value + AC_OUTPUT_PWM_OCR_OFFSET; + } + } +} + +void +output_pwm_ocr_update (void) +{ + /* Update each output, code will be optimized by compiler. */ +#define UPDATE_OUTPUT(index, output) \ + output_pwm_ocr_update_output (index, UPDATE_OUTPUT_ output); +#define UPDATE_OUTPUT_(timer, ocr, mode, pwm_io_port, pwm_io_bit, \ + dir_io_port, dir_io_bit, args...) \ + &PREPROC_PASTE (OCR, timer, ocr), &IO_PORT_ (dir_io_port, dir_io_bit), \ + dir_io_bit, PREPROC_NARG_CALL (UPDATE_OUTPUT_BRAKE_, args) +#define UPDATE_OUTPUT_BRAKE_0() 0, 0 +#define UPDATE_OUTPUT_BRAKE_2(brake_io_port, brake_io_bit) \ + &IO_PORT_ (brake_io_port, brake_io_bit), brake_io_bit + PREPROC_FOR_ENUM (UPDATE_OUTPUT, AC_OUTPUT_PWM_OCR_LIST) +#undef UPDATE_OUTPUT +#undef UPDATE_OUTPUT_ +#undef UPDATE_OUTPUT_BRAKE_0 +#undef UPDATE_OUTPUT_BRAKE_2 +} + diff --git a/digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.h b/digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.h new file mode 100644 index 00000000..38ed0634 --- /dev/null +++ b/digital/avr/modules/motor/output/pwm_ocr/output_pwm_ocr.h @@ -0,0 +1,37 @@ +#ifndef output_pwm_ocr_h +#define output_pwm_ocr_h +/* output_pwm_ocr.h */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "modules/motor/output/output.h" + +/** See output_init. */ +void +output_pwm_ocr_init (uint8_t index, output_t *output); + +/** See output_update. */ +void +output_pwm_ocr_update (void); + +#endif /* output_pwm_ocr_h */ diff --git a/digital/avr/modules/motor/output/test/Makefile b/digital/avr/modules/motor/output/test/Makefile new file mode 100644 index 00000000..33c13d9c --- /dev/null +++ b/digital/avr/modules/motor/output/test/Makefile @@ -0,0 +1,23 @@ +BASE = ../../../.. +PROGS = test_output +test_output_SOURCES = test_output.c +MODULES = utils uart proto motor/output $(OUTPUT_MODULE) +CONFIGFILE = avrconfig_ocr.h +# atmega8, atmega8535, atmega128... +AVR_MCU = atmega32 +# -O2 : speed +# -Os : size +OPTIMIZE = -Os + +ifeq ($(CONFIGFILE),avrconfig_ocr.h) +OUTPUT_MODULE = motor/output/pwm_ocr +else ifeq ($(CONFIGFILE),avrconfig_mp.h) +OUTPUT_MODULE = motor/output/pwm_mp spi +else +OUTPUT_MODULE = motor/output/pwm_ocr motor/output/pwm_mp spi +endif + +TEST_MCU = atmega128 +TEST_CONFIGFILES = avrconfig_mp.h avrconfig_both.h + +include $(BASE)/make/Makefile.gen diff --git a/digital/avr/modules/motor/output/test/avrconfig_both.h b/digital/avr/modules/motor/output/test/avrconfig_both.h new file mode 100644 index 00000000..7ef23ac3 --- /dev/null +++ b/digital/avr/modules/motor/output/test/avrconfig_both.h @@ -0,0 +1,136 @@ +#ifndef avrconfig_both_h +#define avrconfig_both_h +/* avrconfig_both.h */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 RING +/** Recv mode, same as send mode. */ +#define AC_UART0_RECV_MODE RING +/** 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 DROP +/** In HOST compilation: + * - STDIO: use stdin/out. + * - PTS: use pseudo terminal. */ +#define AC_UART0_HOST_DRIVER STDIO +/** 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 8 +/** 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 + +/* motor/output - Output module. */ +/** Use Output Compare PWM output. */ +#define AC_OUTPUT_USE_PWM_OCR 1 +/** Use Motor Power PWM output. */ +#define AC_OUTPUT_USE_PWM_MP 1 +/** Define module and module index for each output. */ +#define AC_OUTPUT_LIST \ + (pwm_ocr, 0), (pwm_ocr, 1), (pwm_ocr, 2), (pwm_ocr, 3), \ + (pwm_mp, 0), (pwm_mp, 1), (pwm_mp, 2), (pwm_mp, 3) + +/* motor/output/pwm_ocr - Output Compare PWM output module. */ +/** For each output, define output parameters: + * + * (timer, ocr, pwm_io, dir_io[, brake_io]) + * + * With: + * - timer: timer number (ex: 1 for TIMER1) + * - ocr: output compare (ex: A for output compare A) + * - mode: compare output mode (ex: 2, see datasheet) + * - pwm_io: corresponding io port (ex: B, 1) + * - dir_io: io port used for direction (ex: B, 2) + * - brake_io: optional io port used for brake (ex: B, 3) + */ +#define AC_OUTPUT_PWM_OCR_LIST \ + (1, B, 2, B,6, B,4), \ + (1, C, 2, B,7, B,5), \ + (3, B, 2, E,4, E,2), \ + (3, C, 2, E,5, E,3) +/** Clock select for each used timer. */ +#define AC_OUTPUT_PWM_OCR_CS_1 0b0001 +/** Waveform Generation Mode for each used timer. */ +#define AC_OUTPUT_PWM_OCR_WGM_1 0b0111 +/** Offset added to PWM value to compensate for H-bridge weakness. */ +#define AC_OUTPUT_PWM_OCR_OFFSET 0 + +/* motor/output/pwm_mp - Motor Power board PWM output module. */ +/** Number of outputs, there is two outputs per board. */ +#define AC_OUTPUT_PWM_MP_NB 4 +/** Slave select for first Motor Power board. + * WARNING: this must match hardware SS pin if using hardware SPI! */ +#define AC_OUTPUT_PWM_MP_SPI_SS_IO_0 B, 0 +/** Slave select for next Motor Power boards. */ +#define AC_OUTPUT_PWM_MP_SPI_SS_IO_1 E, 4 + +/* spi - SPI module. */ +/** Select driver: HARD, SOFT, or NONE. */ +#define AC_SPI0_DRIVER HARD +/** Same thing for an optionnal second SPI driver. */ +#define AC_SPI1_DRIVER NONE + +#endif /* avrconfig_both_h */ diff --git a/digital/avr/modules/motor/output/test/avrconfig_mp.h b/digital/avr/modules/motor/output/test/avrconfig_mp.h new file mode 100644 index 00000000..1cafe775 --- /dev/null +++ b/digital/avr/modules/motor/output/test/avrconfig_mp.h @@ -0,0 +1,109 @@ +#ifndef avrconfig_mp_h +#define avrconfig_mp_h +/* avrconfig_mp.h */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 RING +/** Recv mode, same as send mode. */ +#define AC_UART0_RECV_MODE RING +/** 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 DROP +/** In HOST compilation: + * - STDIO: use stdin/out. + * - PTS: use pseudo terminal. */ +#define AC_UART0_HOST_DRIVER STDIO +/** 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 8 +/** 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 + +/* motor/output - Output module. */ +/** Use Output Compare PWM output. */ +#define AC_OUTPUT_USE_PWM_OCR 0 +/** Use Motor Power PWM output. */ +#define AC_OUTPUT_USE_PWM_MP 1 +/** Define module and module index for each output. */ +#define AC_OUTPUT_LIST (pwm_mp, 0), (pwm_mp, 1), (pwm_mp, 3), (pwm_mp, 2) + +/* motor/output/pwm_mp - Motor Power board PWM output module. */ +/** Number of outputs, there is two outputs per board. */ +#define AC_OUTPUT_PWM_MP_NB 4 +/** Slave select for first Motor Power board. + * WARNING: this must match hardware SS pin if using hardware SPI! */ +#define AC_OUTPUT_PWM_MP_SPI_SS_IO_0 B, 0 +/** Slave select for next Motor Power boards. */ +#define AC_OUTPUT_PWM_MP_SPI_SS_IO_1 E, 4 + +/* spi - SPI module. */ +/** Select driver: HARD, SOFT, or NONE. */ +#define AC_SPI0_DRIVER HARD +/** Same thing for an optionnal second SPI driver. */ +#define AC_SPI1_DRIVER NONE + +#endif /* avrconfig_mp_h */ diff --git a/digital/avr/modules/motor/output/test/avrconfig_ocr.h b/digital/avr/modules/motor/output/test/avrconfig_ocr.h new file mode 100644 index 00000000..0eb3463a --- /dev/null +++ b/digital/avr/modules/motor/output/test/avrconfig_ocr.h @@ -0,0 +1,117 @@ +#ifndef avrconfig_ocr_h +#define avrconfig_ocr_h +/* avrconfig_ocr.h */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 0 +/** 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 RING +/** Recv mode, same as send mode. */ +#define AC_UART0_RECV_MODE RING +/** 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 DROP +/** In HOST compilation: + * - STDIO: use stdin/out. + * - PTS: use pseudo terminal. */ +#define AC_UART0_HOST_DRIVER STDIO +/** 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 8 +/** 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 + +/* motor/output - Output module. */ +/** Use Output Compare PWM output. */ +#define AC_OUTPUT_USE_PWM_OCR 1 +/** Use Motor Power PWM output. */ +#define AC_OUTPUT_USE_PWM_MP 0 +/** Define module and module index for each output. */ +#define AC_OUTPUT_LIST (pwm_ocr, 0), (pwm_ocr, 1) + +/* motor/output/pwm_ocr - Output Compare PWM output module. */ +/** For each output, define output parameters: + * + * (timer, ocr, pwm_io, dir_io[, brake_io]) + * + * With: + * - timer: timer number (ex: 1 for TIMER1) + * - ocr: output compare (ex: A for output compare A) + * - mode: compare output mode (ex: 2, see datasheet) + * - pwm_io: corresponding io port (ex: B, 1) + * - dir_io: io port used for direction (ex: B, 2) + * - brake_io: optional io port used for brake (ex: B, 3) + */ +#define AC_OUTPUT_PWM_OCR_LIST \ + (1, A, 2, D,5, D,3, A,4), \ + (1, B, 2, D,4, D,2, A,5) +/** Clock select for each used timer. */ +#define AC_OUTPUT_PWM_OCR_CS_1 0b0001 +/** Waveform Generation Mode for each used timer. */ +#define AC_OUTPUT_PWM_OCR_WGM_1 0b0011 +/** Offset added to PWM value to compensate for H-bridge weakness. */ +#define AC_OUTPUT_PWM_OCR_OFFSET 0x40 + +#endif /* avrconfig_ocr_h */ diff --git a/digital/avr/modules/motor/output/test/test_output.c b/digital/avr/modules/motor/output/test/test_output.c new file mode 100644 index 00000000..f38c7383 --- /dev/null +++ b/digital/avr/modules/motor/output/test/test_output.c @@ -0,0 +1,154 @@ +/* test_output.c */ +/* motor - Motor control module. {{{ + * + * Copyright (C) 2011 Nicolas Schodet + * + * 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 "modules/utils/utils.h" +#include "modules/uart/uart.h" +#include "modules/proto/proto.h" + +#include "modules/motor/output/output.h" + +#include "io.h" + +output_t output[OUTPUT_NB]; + +int16_t target[OUTPUT_NB]; +int16_t current[OUTPUT_NB]; + +uint16_t output_speed_cpt = 1, output_speed = 250; +uint16_t output_stat_cpt, output_stat; + +int +main (void) +{ + uint8_t i; + for (i = 0; i < OUTPUT_NB; i++) + { + output[i].min = 0x10; + output[i].max = OUTPUT_MAX; + output_init (i, &output[i]); + } + uart0_init (); + proto_send0 ('z'); + sei (); + while (1) + { + utils_delay_ms (4); + if (output_speed && !--output_speed_cpt) + { + for (i = 0; i < OUTPUT_NB; i++) + { + if (target[i] < current[i]) + current[i]--; + else if (target[i] > output[i].cur) + current[i]++; + output_set (&output[i], current[i]); + } + output_speed_cpt = output_speed; + } + if (output_stat && !--output_stat_cpt) + { + proto_send2w ('W', output[0].cur, output[1].cur); + output_stat_cpt = output_stat; + } + while (uart0_poll ()) + proto_accept (uart0_getc ()); + } +} + +/** Handle incoming messages. */ +void +proto_callback (uint8_t cmd, uint8_t size, uint8_t *args) +{ + uint8_t i; + uint8_t ok = 1; + uint8_t index = args[0]; + int16_t value = v8_to_v16 (args[1], args[2]); +#define c(cmd, size) (cmd << 8 | size) + switch (c (cmd, size)) + { + case c ('z', 0): + /* Reset. */ + utils_reset (); + break; + case c ('w', 0): + /* Set zero value. */ + for (i = 0; i < OUTPUT_NB; i++) + { + output_set (&output[index], 0); + current[index] = target[index] = 0; + } + case c ('w', 3): + /* Set direct value. + * - b: output index. + * - w: output value. */ + if (index < OUTPUT_NB) + { + output_set (&output[index], value); + target[index] = current[index]; + } + else + ok = 0; + break; + case c ('t', 3): + /* Set target. + * - b: output index. + * - w: output target. */ + if (index < OUTPUT_NB) + { + current[index] = output[index].cur; + target[index] = value; + } + else + ok = 0; + break; + case c ('s', 2): + /* Set targeting speed. + * - w: loops between update. */ + output_speed_cpt = output_speed = v8_to_v16 (args[0], args[1]); + break; + case c ('r', 2): + /* Set reverse flag. + * - b: output index. + * - b: reverse flag. */ + if (index < OUTPUT_NB) + output_set_reverse (&output[index], args[1]); + else + ok = 0; + break; + case c ('W', 2): + /* Output stats. */ + output_stat_cpt = output_stat = v8_to_v16 (args[0], args[1]); + break; + default: + ok = 0; + break; + } + if (ok) + proto_send (cmd, size, args); + else + proto_send0 ('?'); +#undef c +} -- cgit v1.2.3