From 1dd0b4c4b8e68495d322d210f21d618c057152a9 Mon Sep 17 00:00:00 2001 From: Hunter Laux Date: Sun, 5 Nov 2017 20:59:20 -0800 Subject: [PATCH] Add QDec library based on AVR1600 app note The code was obtained from here: http://www.atmel.com/Images/AVR1600.zip * TC_EVACT_FRQ_gc was misspelled as TC_EVACT_FRW_gc https://lists.nongnu.org/archive/html/avr-libc-commit/2015-01/msg00001.html * .c files renamed to .cpp for arduino compilation. --- QDec/LICENSE | 25 ++++ QDec/avr_compiler.h | 154 +++++++++++++++++++ QDec/documentation.h | 57 +++++++ QDec/qdec_driver.cpp | 263 +++++++++++++++++++++++++++++++++ QDec/qdec_driver.h | 106 +++++++++++++ QDec/qdec_signal_generator.cpp | 222 ++++++++++++++++++++++++++++ QDec/qdec_signal_generator.h | 9 ++ README.md | 1 + 8 files changed, 837 insertions(+) create mode 100644 QDec/LICENSE create mode 100644 QDec/avr_compiler.h create mode 100644 QDec/documentation.h create mode 100644 QDec/qdec_driver.cpp create mode 100644 QDec/qdec_driver.h create mode 100644 QDec/qdec_signal_generator.cpp create mode 100644 QDec/qdec_signal_generator.h diff --git a/QDec/LICENSE b/QDec/LICENSE new file mode 100644 index 0000000..08dc722 --- /dev/null +++ b/QDec/LICENSE @@ -0,0 +1,25 @@ +Copyright (c) 2008, Atmel Corporation All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. The name of ATMEL may not be used to endorse or promote products derived +from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND +SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/QDec/avr_compiler.h b/QDec/avr_compiler.h new file mode 100644 index 0000000..10d0e29 --- /dev/null +++ b/QDec/avr_compiler.h @@ -0,0 +1,154 @@ +/* This file has been prepared for Doxygen automatic documentation generation.*/ +/*! \file ********************************************************************* + * + * \brief This file implements some macros that makes the IAR C-compiler and + * avr-gcc work with the same code base for the AVR architecture. + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Revision: 1699 $ + * $Date: 2008-07-30 09:20:10 +0200 (on, 30 jul 2008) $ \n + * + * Copyright (c) 2008, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef COMPILER_AVR_H +#define COMPILER_AVR_H + +#ifndef F_CPU +/*! \brief Define default CPU frequency, if this is not already defined. */ +#define F_CPU 2000000UL +#endif + +#include +#include +#include + +/*! \brief This macro will protect the following code from interrupts. */ +#define AVR_ENTER_CRITICAL_REGION( ) uint8_t volatile saved_sreg = SREG; \ + cli(); + +/*! \brief This macro must always be used in conjunction with AVR_ENTER_CRITICAL_REGION + * so the interrupts are enabled again. + */ +#define AVR_LEAVE_CRITICAL_REGION( ) SREG = saved_sreg; + +#if defined( __ICCAVR__ ) + +#include +#include +#include +#include + +#ifndef __HAS_ELPM__ +#define _MEMATTR __flash +#else /* __HAS_ELPM__ */ +#define _MEMATTR __farflash +#endif /* __HAS_ELPM__ */ + +/*! \brief Perform a delay of \c us microseconds. + * + * The macro F_CPU is supposed to be defined to a constant defining the CPU + * clock frequency (in Hertz). + * + * The maximal possible delay is 262.14 ms / F_CPU in MHz. + * + * \note For the IAR compiler, currently F_CPU must be a + * multiple of 1000000UL (1 MHz). + */ +#define delay_us( us ) ( __delay_cycles( ( F_CPU / 1000000UL ) * ( us ) ) ) + +/*! \brief Preprocessor magic. + * + * Some preprocessor magic to allow for a header file abstraction of + * interrupt service routine declarations for the IAR compiler. This + * requires the use of the C99 _Pragma() directive (rather than the + * old #pragma one that could not be used as a macro replacement), as + * well as two different levels of preprocessor concetanations in + * order to do both, assign the correct interrupt vector name, as well + * as construct a unique function name for the ISR. + * + * \note Do *NOT* try to reorder the macros below, as this will only + * work in the given order. + */ +#define PRAGMA(x) _Pragma( #x ) +#define ISR(vec) PRAGMA( vector=vec ) __interrupt void handler_##vec(void) +#define sei( ) (__enable_interrupt( )) +#define cli( ) (__disable_interrupt( )) + +/*! \brief Define the no operation macro. */ +#define nop( ) (__no_operation()) + +/*! \brief Define the watchdog reset macro. */ +#define watchdog_reset( ) (__watchdog_reset( )) + + +#define INLINE PRAGMA( inline=forced ) static + +#define FLASH_DECLARE(x) _MEMATTR x +#define FLASH_STRING(x) ((_MEMATTR const char *)(x)) +#define FLASH_STRING_T char const _MEMATTR * +#define FLASH_BYTE_ARRAY_T uint8_t const _MEMATTR * +#define PGM_READ_BYTE(x) *(x) +#define PGM_READ_WORD(x) *(x) + +#define SHORTENUM /**/ + +#elif defined( __GNUC__ ) + +#include +#include +#include +#include + +/*! \brief Define the delay_us macro for GCC. */ +#define delay_us( us ) (_delay_us( us )) + +#define INLINE static inline + +/*! \brief Define the no operation macro. */ +#define nop() do { __asm__ __volatile__ ("nop"); } while (0) + +#define MAIN_TASK_PROLOGUE int + + +#define MAIN_TASK_EPILOGUE() return -1; + +#define SHORTENUM __attribute__ ((packed)) + +#else +#error Compiler not supported. +#endif + +#endif + diff --git a/QDec/documentation.h b/QDec/documentation.h new file mode 100644 index 0000000..4805675 --- /dev/null +++ b/QDec/documentation.h @@ -0,0 +1,57 @@ +/* Doxygen documentation mainpage ********************************************/ +/*! \mainpage + * \section intro Introduction + * This documents the firmware for the application note. \n + * + * \section compinfo Compilation Info + * This firmware was compiled with IAR Embedded Workbench 5.10 and WinAVR 20080411.\n + * + * To make the project in IAR EWAVR:\n + * Add the .c files (and .S90 files where applicable) for the given example to your + * project. Use device ATxmega128A1 and enable bit definitions in I/O include files, + * optimization low for debug target and high for release, output format: ubrof8 for + * Debug and intel_extended for Release, select Normal DLIB as library. \n + * + * To make the project in WinAVR:\n + * Add the .c files (and .S files where applicable) for the given example to your project. + * Use device ATxmega128A1, optimization low for debug target and high for release. \n + * + * \section deviceinfo Device Info + * All XMEGA devices with the targeted module can be used. The example is + * written for ATxmega128A1. + * + * \section contactinfo Contact Info + * For more info about Atmel AVR visit http://www.atmel.com/products/AVR/ \n + * For application notes visit + * http://www.atmel.com/dyn/products/app_notes.asp?family_id=607 \n + * Support mail: avr@atmel.com \n + * + * $Revision: 1699 $ + * $Date: 2008-07-30 09:20:10 +0200 (on, 30 jul 2008) $ + * + * Copyright (c) 2008, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ diff --git a/QDec/qdec_driver.cpp b/QDec/qdec_driver.cpp new file mode 100644 index 0000000..3915cf3 --- /dev/null +++ b/QDec/qdec_driver.cpp @@ -0,0 +1,263 @@ +/* This file has been prepared for Doxygen automatic documentation generation. */ +/*! \file ********************************************************************* + * + * \brief The XMEGA Quadrature Decoder driver source file. + * + * This file contains the function prototypes and enumerator definitions + * for various configuration parameters for the XMEGA Quadrature Decoder. + * + * The driver is not intended for size and/or speed critical code. The + * driver is intended for rapid prototyping and documentation purposes for + * getting started with the XMEGA Quadrature Decoder. + * + * For size and/or speed critical code, it is recommended to copy the + * function contents directly into your application instead of making + * a function call. + * + * Several functions use the following construct: + * "some_register = ... | (some_parameter ? SOME_BIT_bm : 0) | ..." + * Although the use of the ternary operator ( if ? then : else ) is + * discouraged, in some occasions the operator makes it possible to + * write pretty clean and neat code. In this driver, the construct is + * used to set or not set a configuration bit based on a boolean input + * parameter, such as the "some_parameter" in the example above. + * + * \par Application note: + * AVR1600: Using the XMEGA Quadrature Decoder + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Revision: 1699 $ + * $Date: 2008-07-30 09:20:10 +0200 (on, 30 jul 2008) $ + * + * Copyright (c) 2008, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "qdec_driver.h" + +/*! \brief Wrapperfunction to set up all parameters for the quadrature decoder. + * + * This function combines the following functions for a total setup: + * QDEC_Port_Setup, QDEC_EVSYS_Setup and QDEC_TC_Dec_Setup. + * + * \param qPort The port to use. + * \param qPin The first input pin (QDPH0) to use (0 - 5/6). + * \param invIO True if IO pins should be inverted. + * + * \param qEvMux Which event channel to use. Only 0, 2 and 4 is available. + * \param qPinInput The pin input of QDPH0 to the EVSYS.CHMUX . + * \param useIndex True if an optional Index pin is used. + * \param qIndexState In which state the index signal will trigger. + * + * \param qTimer The timer to use for QDEC. + * \param qEventChannel The event channel to listen to. + * \param lineCount The number of lines in the quadrature encoder. + * + * \return bool True if setup was ok, false if any errors. +*/ +bool QDEC_Total_Setup(PORT_t * qPort, + uint8_t qPin, + bool invIO, + uint8_t qEvMux, + EVSYS_CHMUX_t qPinInput, + bool useIndex, + EVSYS_QDIRM_t qIndexState, + TC0_t * qTimer, + TC_EVSEL_t qEventChannel, + uint8_t lineCount) +{ + if( !QDEC_Port_Setup(qPort, qPin, useIndex, invIO) ) + return false; + if( !QDEC_EVSYS_Setup(qEvMux, qPinInput, useIndex, qIndexState ) ) + return false; + QDEC_TC_Dec_Setup(qTimer, qEventChannel, lineCount); + + return true; +} + + +/*! \brief This function set up the needed configuration for the port used for + * the quadrature decoding. + * + * \param qPort The port to use. + * \param qPin The first input pin (QDPH0) to use (0 - 5/6). + * \param useIndex True if an optional Index pin is used. + * \param invIO True if IO pins should be inverted. + * + * \return bool True if setup was ok, false if any errors. + */ +bool QDEC_Port_Setup(PORT_t * qPort, uint8_t qPin, bool useIndex, bool invIO) +{ + /* Make setup depending on if Index signal is used. */ + if(useIndex){ + if(qPin > 5){ + return false; + } + qPort->DIRCLR = (0x07<PIN0CTRL = (qPort->PIN0CTRL & ~PORT_ISC_gm) | PORT_ISC_BOTHEDGES_gc + | (invIO ? PORT_INVEN_bm : 0); + + + }else{ + if(qPin > 6){ + return false; + } + qPort->DIRCLR = (0x03<PIN0CTRL = (qPort->PIN0CTRL & ~PORT_ISC_gm) | PORT_ISC_LEVEL_gc + | (invIO ? PORT_INVEN_bm : 0); + + return true; +} + + +/*! \brief This function configure the event system for quadrature decoding. + * + * \param qEvMux Which event channel to use. Only 0, 2 and 4 is available. + * \param qPinInput The pin input of QDPH0 to the EVSYS.CHMUX . + * \param useIndex True if an optional Index pin is used. + * \param qIndexState In which state the index signal will trigger. + * + * \return bool True if setup was ok, false if any errors. + */ +bool QDEC_EVSYS_Setup(uint8_t qEvMux, + EVSYS_CHMUX_t qPinInput, + bool useIndex, + EVSYS_QDIRM_t qIndexState ) +{ + switch (qEvMux){ + case 0: + + /* Configure event channel 0 for quadrature decoding of pins. */ + EVSYS.CH0MUX = qPinInput; + EVSYS.CH0CTRL = EVSYS_QDEN_bm | EVSYS_DIGFILT_2SAMPLES_gc; + if(useIndex){ + /* Configure event channel 1 as index channel. Note + * that when enabling Index in channel n, the channel + * n+1 must be configured for the index signal.*/ + EVSYS.CH1MUX = qPinInput + 2; + EVSYS.CH1CTRL = EVSYS_DIGFILT_2SAMPLES_gc; + EVSYS.CH0CTRL |= (uint8_t) qIndexState | EVSYS_QDIEN_bm; + + } + break; + case 2: + EVSYS.CH2MUX = qPinInput; + EVSYS.CH2CTRL = EVSYS_QDEN_bm | EVSYS_DIGFILT_2SAMPLES_gc; + if(useIndex){ + EVSYS.CH3MUX = qPinInput + 2; + EVSYS.CH3CTRL = EVSYS_DIGFILT_2SAMPLES_gc; + EVSYS.CH2CTRL |= (uint8_t) qIndexState | EVSYS_QDIEN_bm; + } + break; + case 4: + EVSYS.CH4MUX = qPinInput; + EVSYS.CH4CTRL = EVSYS_QDEN_bm | EVSYS_DIGFILT_2SAMPLES_gc; + if(useIndex){ + EVSYS.CH5MUX = qPinInput + 2; + EVSYS.CH5CTRL = EVSYS_DIGFILT_2SAMPLES_gc; + EVSYS.CH4CTRL |= (uint8_t) qIndexState | EVSYS_QDIEN_bm; + } + break; + default: + return false; + } + return true; +} + +/*! \brief This function set up the needed configuration for the Timer/Counter + * to handle the quadrature decoding from the event system. + * + * \param qTimer The timer to use for QDEC. + * \param qEventChannel The event channel to listen to. + * \param lineCount The number of lines in the quadrature encoder. + */ +void QDEC_TC_Dec_Setup(TC0_t * qTimer, TC_EVSEL_t qEventChannel, uint8_t lineCount) +{ + /* Configure TC as a quadrature counter. */ + qTimer->CTRLD = (uint8_t) TC_EVACT_QDEC_gc | qEventChannel; + qTimer->PER = (lineCount * 4) - 1; + qTimer->CTRLA = TC_CLKSEL_DIV1_gc; +} + + +/*! \brief This function set up the needed configuration for a Timer/Counter + * to handle the frequency/speed measurement from the event system. + * + * \note The real frequency of rotation can be calculated from the capture register + * by using the folowing function. + * FREQ = ( F_CPU / clk_div ) / ( CAPTURE * lineCount ) + * + * \param qTimer The timer to use for QDEC. + * \param qEventChannel The event channel to listen to. + * \param qPinInput The pin input of QDPH0 to the EVSYS.CHMUX. + * \param clksel The clk div to use for timer. + */ +void QDEC_TC_Freq_Setup(TC0_t * qTimer, + TC_EVSEL_t qEventChannel, + EVSYS_CHMUX_t qPinInput, + TC_CLKSEL_t clksel) +{ + /* Configure channel 2 to input pin for freq calculation. */ + EVSYS.CH2MUX = qPinInput; + EVSYS.CH2CTRL = EVSYS_DIGFILT_4SAMPLES_gc; + + /* Configure TC to capture frequency. */ + qTimer->CTRLD = (uint8_t) TC_EVACT_FRQ_gc | qEventChannel; + qTimer->PER = 0xFFFF; + qTimer->CTRLB = TC0_CCAEN_bm; + qTimer->CTRLA = clksel; +} + + +/*! \brief This function return the direction of the counter/QDEC. + * + * \param qTimer The timer used for QDEC. + * + * \retval CW_DIR if clockwise/up counting, + * \retval CCW_DIR if counter clockwise/down counting. + */ +uint8_t QDEC_Get_Direction(TC0_t * qTimer) +{ + if (qTimer->CTRLFSET & TC0_DIR_bm){ + return CW_DIR; + }else{ + return CCW_DIR; + } +} diff --git a/QDec/qdec_driver.h b/QDec/qdec_driver.h new file mode 100644 index 0000000..8ffb615 --- /dev/null +++ b/QDec/qdec_driver.h @@ -0,0 +1,106 @@ +/* This file has been prepared for Doxygen automatic documentation generation. */ +/*! \file ********************************************************************* + * + * \brief The XMEGA Quadrature Decoder driver header file. + * + * This file contains the function prototypes and enumerator definitions + * for various configuration parameters for the XMEGA Quadrature Decoder. + * + * The driver is not intended for size and/or speed critical code. The + * driver is intended for rapid prototyping and documentation purposes for + * getting started with the XMEGA Quadrature Decoder. + * + * For size and/or speed critical code, it is recommended to copy the + * function contents directly into your application instead of making + * a function call. + * + * \par Application note: + * AVR1600: Using the XMEGA Quadrature Decoder + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Revision: 1699 $ + * $Date: 2008-07-30 09:20:10 +0200 (on, 30 jul 2008) $ + * + * Copyright (c) 2008, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#ifndef __QDEC_DRIVER_H__ +#define __QDEC_DRIVER_H__ + +#include "avr_compiler.h" + +#define CW_DIR 0 /* Clockwise direction. */ +#define CCW_DIR 1 /* Counter Clockwise direction. */ + +/* Definitions of macros. */ + +/*! \brief This macro return the value of the capture register. + * + * \param _tc The Timer/Counter to get the capture value from. + */ +#define GetCaptureValue(_tc) ( _tc.CCA ) + + +/* Prototyping of functions. */ + +bool QDEC_Total_Setup(PORT_t * qPort, + uint8_t qPin, + bool invIO, + uint8_t qEvMux, + EVSYS_CHMUX_t qPinInput, + bool useIndex, + EVSYS_QDIRM_t qIndexState, + TC0_t * qTimer, + TC_EVSEL_t qEventChannel, + uint8_t lineCount); + +bool QDEC_Port_Setup(PORT_t * qPort, uint8_t qPin, bool useIndex, bool invIO); + +bool QDEC_EVSYS_Setup(uint8_t qEvMux, + EVSYS_CHMUX_t qPinInput, + bool useIndex, + EVSYS_QDIRM_t qIndexState ); + +void QDEC_TC_Dec_Setup(TC0_t * qTimer, + TC_EVSEL_t qEventChannel, + uint8_t lineCount); + +void QDEC_TC_Freq_Setup(TC0_t * qTimer, + TC_EVSEL_t qEventChannel, + EVSYS_CHMUX_t qPinInput, + TC_CLKSEL_t clksel); + +uint8_t QDEC_Get_Direction(TC0_t * qTimer); + +#endif /* __QDEC_DRIVER_H__ */ diff --git a/QDec/qdec_signal_generator.cpp b/QDec/qdec_signal_generator.cpp new file mode 100644 index 0000000..c3a816b --- /dev/null +++ b/QDec/qdec_signal_generator.cpp @@ -0,0 +1,222 @@ +/* This file has been prepared for Doxygen automatic documentation generation. */ +/*! \file ********************************************************************* + * + * \brief Test signal generation, generates a Quadrature signal. + * + * This file contains code to generate a Quadrature signal for testing + * of the system. The signal generated goes either direction given by a define + * the CW_DIR_SIG gives a signal that counts in clockwise direction. The + * CCW_DIR_SIG define gives a signal in counter clockwise direction. + * + * To use the test signal the GENERATE_TEST_SIGNAL has to be uncommented in the + * qdec_example.c file. + * The generate_qdec_signal will then be included and a signal generated. + * The signal output pins then has to be connected with the input pins to the + * Quadrature decoder. + * + * When the signal is connected and the output portC is connected to the led’s + * the frequency value will be displayed in hex, pin0 LSB. + * + * To test that the index signal is correct, when enabled, one can set a + * breakpoint in the timer counter C0 error interrupt routine. If the + * interrupt routine is run more than 1 time (first time resets the count) + * the index setting is wrong. If it is correct the execution should not break + * when the index signal is connected, but if the signal is disconnected (remove cable) + * the code should break. + * + * If a scope is used the frequency measurement can be controlled, the measured + * frequency should be equal to the frequency on the scope given by the time + * between the index signal. + * + * \par Application note: + * AVR1600: Using the XMEGA Quadrature Decoder + * + * \par Documentation + * For comprehensive code documentation, supported compilers, compiler + * settings and supported devices see readme.html + * + * \author + * Atmel Corporation: http://www.atmel.com \n + * Support email: avr@atmel.com + * + * $Revision: 1699 $ + * $Date: 2008-07-30 09:20:10 +0200 (on, 30 jul 2008) $ + * + * Copyright (c) 2008, Atmel Corporation All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of ATMEL may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND + * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *****************************************************************************/ + +#include "avr_compiler.h" +#include "qdec_signal_generator.h" + +/*! \brief The port to set the signal out on. */ +PORT_t * q_test_sig_Port; + + +/*! \brief Number of lines in the Quadrature encoder. */ +uint8_t test_lineCount; + + +/*! \brief Initializes TCE0 to create Qadrature signal. + * + * Calculates the values to create a Quadrature signal that has a + * frequency given from the freq parameter. + * + * \param qPort The port to set the signal out on. + * \param lineCount The number of lines in the Quadrature encoder. + * \param freq The frequency that is put out, + * (time between index signal/one rotation). + * \param dir The direction of the signal to be generated, + * clockwise or counterclockwise signal. + */ +void generate_qdec_signal(PORT_t * qPort, uint8_t lineCount, uint8_t freq, bool dir) +{ + uint16_t ticks, quarter, half_quarter; + + /* The following code calculates the upper boundary of the timer and the + * interrupt positions to get a correct Quadrature signal of the given frequency. + * + * The different compare interrupts sets the phase0 and phase90 signals. + * Compare A interrupt sets phase0 and clears phase90 + * Compare B interrupt sets phase0 and phase90 + * Compare C interrupt clears phase0 and sets phase90 + * Compare D interrupt clears phase0 and phase90. + * + * Ccompare A interrupt also sets the index signal when one round has passed. + */ + + /* Calculates upper boundary of timer to get desired frequency.*/ + ticks = F_CPU / (freq * lineCount); + quarter = ticks/4; + half_quarter = ticks/8; + + if(dir == 1){ + TCE0.CCA = half_quarter; + TCE0.CCB = half_quarter+quarter; + TCE0.CCC = half_quarter+(2*quarter); + TCE0.CCD = half_quarter+(3*quarter); + }else{ + TCE0.CCA = half_quarter+(3*quarter); + TCE0.CCB = half_quarter+(2*quarter); + TCE0.CCC = half_quarter+quarter; + TCE0.CCD = half_quarter; + } + + TCE0.PER = ticks; + TCE0.CTRLA = TC_CLKSEL_DIV1_gc; + + /* Enable low level interrupt on CCA, CCB, CCC and CCD.*/ + TCE0.INTCTRLB = TC0_CCAINTLVL0_bm | TC0_CCBINTLVL0_bm | + TC0_CCCINTLVL0_bm | TC0_CCDINTLVL0_bm; + TCC0.INTCTRLA = TC0_ERRINTLVL0_bm; + + qPort->DIRSET = 0xFF; + q_test_sig_Port = qPort; + + test_lineCount = lineCount; +} + + +/*! \brief Creates a Quadrature signal, up or down counting depending + * on CW_DIR_SIG or CCW_DIR_SIG. + */ +ISR(TCE0_CCA_vect) +{ + static uint16_t i = 0; + + /* Set pin0 Phase0 signal.*/ + q_test_sig_Port->OUT = (q_test_sig_Port->OUT & ~0x03) | 0x01; + + i++; + + /* Clear index.*/ + q_test_sig_Port->OUT = (q_test_sig_Port->OUT & ~0x04); + + /* When (i = test_lineCount) one round has passed. + * Includes a check for i "bigger than" for error handling. + */ + if(i>=test_lineCount){ + + /* Set index. Lasts 4 states.*/ + q_test_sig_Port->OUT |= 0x04; + i = 0; + } +} + + +/*! \brief Creates a Quadrature signal, up or down counting depending + * on CW_DIR_SIG or CCW_DIR_SIG. + */ +ISR(TCE0_CCB_vect) +{ + /* Set pin0 and pin1 phase0 and phase90 signal.*/ + q_test_sig_Port->OUT = (q_test_sig_Port->OUT & ~0x03) | 0x01 | 0x02; +} + + +/*! \brief Creates a Quadrature signal, up or down counting depending + * on CW_DIR_SIG or CCW_DIR_SIG. + */ +ISR(TCE0_CCC_vect) +{ + /* Set pin1 phase90 signal. Clear pin0 phase0 signal.*/ + q_test_sig_Port->OUT = (q_test_sig_Port->OUT & ~0x03) | 0x02; +} + + +/*! \brief Creates a Quadrature signal, up or down counting depending + * on CW_DIR_SIG or CCW_DIR_SIG. + */ +ISR(TCE0_CCD_vect) +{ + /* Clear pin0 and pin1, phase0 and phase90 signal.*/ + q_test_sig_Port->OUT = (q_test_sig_Port->OUT & ~0x03); +} + + +/*! \brief Error interrupt routine for when index signal is used. + * + * This interrupt happens if the count value is not at BOTTOM + * when the index signal comes. The interrupt also happens if + * the count value passes the BOTTOM value. + */ +ISR(TCC0_ERR_vect) +{ + static uint8_t j = 0; + j++; + + /* Since index needs to initialize, one error will happen first round. + * If output is desired at every error, remove if statement or set (j>0). + */ + if(j>2){ + + /* To test if index works, set breakpoint here. + * It should NOT break when index is correct. + */ + q_test_sig_Port->OUT = q_test_sig_Port->OUT ^ 0x40; + j=0; + } +} diff --git a/QDec/qdec_signal_generator.h b/QDec/qdec_signal_generator.h new file mode 100644 index 0000000..a2018a1 --- /dev/null +++ b/QDec/qdec_signal_generator.h @@ -0,0 +1,9 @@ +#ifndef __QDEC_SIGNAL_GENERATOR_H__ +#define __QDEC_SIGNAL_GENERATOR_H__ + +void generate_qdec_signal(PORT_t * qPort, + uint8_t lineCount, + uint8_t freq, + bool dir); + +#endif /* __QDEC_SIGNAL_GENERATOR_H__ */ \ No newline at end of file diff --git a/README.md b/README.md index e182792..0b45eba 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ XSPI - SPI library, modified for XMega. Use '#include <XSPI.h>'
XSD - SD Card library, modified for XMega. Use '#include <XSD.h>'
XWire - 'Wire' library, modified for XMega. Use '#include <XWire.h>'
I2CDev - A modified version of the 'I2CDev' library that works with XWire
+QDec - Quadrature decoding library. Modified from the AVR1600 code.


Most (if not all) of the libraries are derived from the originals shipped with