// coding: utf-8 // ---------------------------------------------------------------------------- /* * Copyright (c) 2007 Fabian Greif, Roboterclub Aachen e.V. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 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 UTILS_H #define UTILS_H // ---------------------------------------------------------------------------- /** * \defgroup utils_h Gruppe nützlicher Makros und Inline-Funktionen * \brief Nützliche Makros und Funktionen. * * \version $Id: utils.h 758 2010-08-01 23:50:48Z jacobsen $ */ // ---------------------------------------------------------------------------- #include #include #include #include "config.h" // ---------------------------------------------------------------------------- #ifndef TRUE #define TRUE (1==1) #elif !TRUE #error fehlerhafte Definition fuer TRUE #endif #ifndef FALSE #define FALSE (1!=1) #elif FALSE #error fehlerhafte Definition fuer FALSE #endif #ifndef NULL #define NULL ((void*)0) //!< Nullzeiger #endif // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \name Nützliches */ //@{ #define DEGREE_TO_RAD(x) ((x * M_PI) / 180) //@} // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \name Nützliches */ //@{ #define LOW_BYTE(x) ((uint8_t) (x & 0xff)) #define HIGH_BYTE(x) ((uint8_t) (x >> 8)) #define LOW_WORD(x) ((uint16_t) (x & 0xffff)) #define HIGH_WORD(x) ((uint16_t) (x >> 16)) //@} // ---------------------------------------------------------------------------- /** * \ingroup utils_h */ typedef struct { uint8_t b4; // lsb uint8_t b3; uint8_t b2; uint8_t b1; // msb } tLongToByte; // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \name Kritische Sektionen (Interrupts sperren) */ //@{ #if defined(__DOXYGEN__) #define ENTER_CRITICAL_SECTION #define LEAVE_CRITICAL_SECTION #else /* !DOXYGEN */ #include #define ENTER_CRITICAL_SECTION #define LEAVE_CRITICAL_SECTION /* #if __AVR_LIBC_VERSION__ >= 10600UL && !defined (__cplusplus) #include #define ENTER_CRITICAL_SECTION ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { #define LEAVE_CRITICAL_SECTION } #else #define ENTER_CRITICAL_SECTION do { unsigned char sreg_ = SREG; cli(); #define LEAVE_CRITICAL_SECTION SREG = sreg_; } while (0); #endif */ #endif /* DOXYGEN */ //@} // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \brief atomare Operationen */ static inline uint8_t read_and_replace_atomar(volatile uint8_t *data, uint8_t new_data) { uint8_t old_data; ENTER_CRITICAL_SECTION // Daten tauschen old_data = *data; *data = new_data; LEAVE_CRITICAL_SECTION return old_data; } // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \name Volatile Zugriff auf Variablen * * Nützlich um */ //@{ #define vu8(x) (*(volatile uint8_t*)&(x)) #define vs8(x) (*(volatile int8_t*)&(x)) #define vu16(x) (*(volatile uint16_t*)&(x)) #define vs16(x) (*(volatile int16_t*)&(x)) #define vu32(x) (*(volatile uint32_t*)&(x)) #define vs32(x) (*(volatile int32_t*)&(x)) //@} // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \name Port-Makros * * Die Makros RESET(), SET(), SET_OUTPUT(), SET_INPUT() und IS_SET() * beziehen sich immer auf ein bestimmtes Bit eines Ports und helfen somit * den Code sehr portabel zu gestalten. * * Beispiel: * \code * #define LED D,5 // PORTD, Pin 5 * * SET_OUTPUT(LED); // Pin als Ausgang schalten (wird z.B. zu DDRD |= (1<<5);) * * SET(LED); // LED aktivieren * \endcode * * oder auch: * * \code * #define SCHALTER B,1 // PORTB, Pin 1 * * SET_INPUT_WITH_PULLUP(SCHALTER); * * if (IS_SET(SCHALTER)) { * ... * } * \endcode * * Somit muss nur ein Define geaendert werden sobald ein anderer Pin verwendet * werden soll. Ausserdem muss nicht immer noch ein extra define für den * entsprechenden Port angelegt werden wie es bisher immer der Fall war. */ //@{ #if defined(__DOXYGEN__) #define RESET(x) //!< Einzelnes Bit eines bestimmten Ports setzen #define SET(x) //!< Bit löschen #define TOGGLE(x) //!< Bit umschalten #define SET_OUTPUT(x) //!< Einzeles Bit ein Port als Ausgang schalten #define SET_INPUT(x) //!< Bit als Eingang schalten #define SET_PULLUP(x) //!< aktiviert den Pullup eines Pins (nur falls dieser als Eingang geschaltet ist) #define SET_INPUT_WITH_PULLUP(x) //!< Set den Pin als Eingang mit akiviertem Pullup #define IS_SET(x) //!< Zustand eines Eingangs abfragen #else /* !DOXYGEN */ /* Warum hier zum Teil so seltsame Konstrukte notwendig sind wird zum Beispiel * in http://www.mikrocontroller.net/forum/read-1-324854.html#324980 erklaert. */ #define PORT(x) _port2(x) #define DDR(x) _ddr2(x) #define PIN(x) _pin2(x) #define REG(x) _reg(x) #define PIN_NUM(x) _pin_num(x) #define RESET(x) RESET2(x) #define SET(x) SET2(x) #define TOGGLE(x) TOGGLE2(x) #define SET_OUTPUT(x) SET_OUTPUT2(x) #define SET_INPUT(x) SET_INPUT2(x) #define SET_PULLUP(x) SET2(x) #define IS_SET(x) IS_SET2(x) #define SET_INPUT_WITH_PULLUP(x) SET_INPUT_WITH_PULLUP2(x) #define _port2(x) PORT ## x #define _ddr2(x) DDR ## x #define _pin2(x) PIN ## x #define _reg(x,y) x #define _pin_num(x,y) y #define RESET2(x,y) PORT(x) &= ~(1<> 4); else asm volatile ("swap %0" : "=r" (x) : "0" (x)); return x; } // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \brief */ #if defined(DEBUG) && DEBUG #include #define PRINTF(s, ...) do { static prog_char __s[] = (s); \ printf_P(__s, ## __VA_ARGS__); } while (0) #else #define PRINTF(s, ...) #endif // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \brief Zählt die Anzahl der gesetzten Bits in einem Byte * * \param n Byte das verarbeitet werden soll. * \return Anzahl der gesetzten Bits (0..8) * * \see http://infolab.stanford.edu/~manku/bitcount/bitcount.html */ static inline uint8_t bit_count8(uint8_t n) { n = ((n >> 1) & 0x55) + (n & 0x55); n = ((n >> 2) & 0x33) + (n & 0x33); n = ((n >> 4) + n) & 0xf; return n; } #define MASK_01010101 (((uint32_t)(-1))/3) #define MASK_00110011 (((uint32_t)(-1))/5) #define MASK_00001111 (((uint32_t)(-1))/17) // ---------------------------------------------------------------------------- /** * \ingroup utils_h * \brief Zählt die Anzahl der gesetzten Bits in einem Byte * * \param u Wert der verarbeitet werden soll. * \return Anzahl der gesetzten Bits (0..32) */ static inline uint8_t bit_count32(uint32_t n) { n = (n & MASK_01010101) + ((n >> 1) & MASK_01010101); n = (n & MASK_00110011) + ((n >> 2) & MASK_00110011); n = (n & MASK_00001111) + ((n >> 4) & MASK_00001111); return n % 255 ; } #endif // UTILS_H