* \author Bernardo Innocenti <bernie@develer.com>
* \author Giovanni Bajo <rasky@develer.com>
*/
-
-/*#*
- *#* $Log$
- *#* Revision 1.11 2007/02/06 15:22:12 asterix
- *#* Add ROTL and ROTR macros for bit rotating.
- *#*
- *#* Revision 1.10 2006/09/13 18:31:37 bernie
- *#* BV8(), BV16(), BV32(): New macros for CPUs with small word size; SWAP_T(): New macro to support old compilers.
- *#*
- *#* Revision 1.9 2006/07/19 12:56:25 bernie
- *#* Convert to new Doxygen style.
- *#*
- *#* Revision 1.8 2006/03/13 02:06:55 bernie
- *#* ROUND_UP2: Rename from ROUND2.
- *#*
- *#* Revision 1.7 2006/02/20 14:34:58 bernie
- *#* Use portable type checking.
- *#*
- *#* Revision 1.6 2006/02/10 12:36:57 bernie
- *#* Pacify IAR warnings for side-effects.
- *#*
- *#* Revision 1.5 2005/11/04 16:20:01 bernie
- *#* Fix reference to README.devlib in header.
- *#*
- *#* Revision 1.4 2005/07/03 15:19:09 bernie
- *#* Doxygen fix.
- *#*
- *#* Revision 1.3 2005/06/27 21:23:32 bernie
- *#* ROUND_DOWN, ROUND_UP, ROUND_NEAREST: New macros.
- *#*
- *#* Revision 1.2 2005/04/11 19:10:27 bernie
- *#* Include top-level headers from cfg/ subdir.
- *#*
- *#* Revision 1.1 2005/04/11 19:04:13 bernie
- *#* Move top-level headers to cfg/ subdir.
- *#*
- *#* Revision 1.10 2005/01/22 04:19:50 bernie
- *#* Use non-uglified typeof().
- *#*
- *#* Revision 1.9 2004/12/08 08:51:34 bernie
- *#* Add type-generic macros for C++.
- *#*
- *#* Revision 1.8 2004/10/19 07:14:20 bernie
- *#* Add macros to test for specific compiler features.
- *#*
- *#* Revision 1.7 2004/09/20 03:30:45 bernie
- *#* C++ also has variadic macros.
- *#*
- *#* Revision 1.6 2004/09/14 21:02:04 bernie
- *#* SWAP(), MINMAX(): New macros.
- *#*
- *#* Revision 1.5 2004/08/29 21:57:58 bernie
- *#* Move back STATIC_ASSERT() to compiler.h as it's needed in cpu.h;
- *#* iptr_t, const_iptr_t: Replace IPTR macro with a real typedef.
- *#*
- *#* Revision 1.3 2004/08/24 14:13:48 bernie
- *#* Restore a few macros that were lost in the way.
- *#*
- *#* Revision 1.2 2004/08/24 13:32:14 bernie
- *#* PP_CAT(), PP_STRINGIZE(): Move back to compiler.h to break circular dependency between cpu.h/compiler.h/macros.h;
- *#* offsetof(), countof(): Move back to compiler.h to avoid including macros.h almost everywhere;
- *#* Trim CVS log;
- *#* Rename header guards;
- *#* Don't include arch_config.h in compiler.h as it's not needed there.
- *#*
- *#* Revision 1.1 2004/08/14 19:37:57 rasky
- *#* Merge da SC: macros.h, pool.h, BIT_CHANGE, nome dei processi, etc.
- *#*
- *#* Revision 1.4 2004/08/14 18:36:50 rasky
- *#* Doxygen fix e un livello di parentesi aggiuntivi per la macro
- *#*
- *#* Revision 1.3 2004/08/12 20:01:32 rasky
- *#* Aggiunte macro BIT_CHANGE e BIT_CHANGE_BV
- *#*
- *#* Revision 1.2 2004/08/10 21:36:14 rasky
- *#* Aggiunto include macros.h dove serve
- *#* Aggiunta dipendenza da compiler.h in macros.h
- *#*
- *#* Revision 1.1 2004/08/10 21:30:00 rasky
- *#* Estratte le funzioni macro in macros.h
- *#*
- *#*/
-
-#ifndef MACROS_H
-#define MACROS_H
+#ifndef CFG_MACROS_H
+#define CFG_MACROS_H
#include <cfg/compiler.h>
/** Same as BV() but with 8 bit result */
#define BV8(x) ((uint8_t)1<<(x))
-
+/**
+ * Perform an integer division rounding the result to the nearest int value.
+ * \note \a divisor should preferibly be a costant, otherwise this macro generates
+ * 2 division. Also divisor is evaluated twice.
+ */
+#define DIV_ROUND(dividend, divisor) (((dividend) + (divisor) / 2) / (divisor))
/** Round up \a x to an even multiple of the 2's power \a pad. */
#define ROUND_UP2(x, pad) (((x) + ((pad) - 1)) & ~((pad) - 1))
*/
#include "kdebug_at91.h"
-#include <cfg/macros.h> /* for BV() */
+#include <cfg/macros.h> /* for BV(), DIV_ROUND */
#include <appconfig.h>
#include <hw_cpu.h> /* for CLOCK_FREQ */
#include <hw_ser.h> /* Required for bus macros overrides */
/* Reset DBGU */
DBGU_CR = BV(US_RSTRX) | BV(US_RSTTX) | BV(US_RXDIS) | BV(US_TXDIS);
/* Set baudrate */
- DBGU_BRGR = (CLOCK_FREQ + (16 * CONFIG_KDEBUG_BAUDRATE) / 2) / (16 * CONFIG_KDEBUG_BAUDRATE);
+ DBGU_BRGR = DIV_ROUND(CLOCK_FREQ, 16 * CONFIG_KDEBUG_BAUDRATE);
/* Set DBGU mode to 8 data bits, no parity and 1 stop bit. */
DBGU_MR = US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1;
/* Enable DBGU transmitter. */
#include <cpu/types.h>
#include <cpu/attr.h>
-#include <cfg/macros.h> /* for BV() */
+#include <cfg/macros.h> /* for BV(), DIV_ROUND */
#include <appconfig.h>
#include <hw_cpu.h> /* for CLOCK_FREQ */
#include <hw_ser.h> /* Required for bus macros overrides */
SER_BITBANG_INIT;
#else /* CONFIG_KDEBUG_PORT != 666 */
/* Compute the baud rate */
- uint16_t period = (((CLOCK_FREQ / 16UL) + (CONFIG_KDEBUG_BAUDRATE / 2)) / CONFIG_KDEBUG_BAUDRATE) - 1;
+ uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, CONFIG_KDEBUG_BAUDRATE) - 1;
#if (CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128)
#if CONFIG_KDEBUG_PORT == 0
#include <hw_cpu.h> /* CLOCK_FREQ */
#include <appconfig.h>
+#include <cfg/macros.h> /* DIV_ROUND */
#include <cfg/debug.h>
#include <drv/timer.h>
#include <mware/fifobuf.h>
static void uart0_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
/* Compute baud-rate period */
- uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
+ uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, rate) - 1;
#if !CPU_AVR_ATMEGA103
UBRR0H = (period) >> 8;
static void uart1_setbaudrate(UNUSED_ARG(struct SerialHardware *, _hw), unsigned long rate)
{
/* Compute baud-rate period */
- uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
+ uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, rate) - 1;
UBRR1H = (period) >> 8;
UBRR1L = (period);
void _ser_setbaudrate(unsigned long rate)
{
/* Compute baud-rate period */
- uint16_t period = (((CLOCK_FREQ / 16UL) + (rate / 2)) / rate) - 1;
+ uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, rate) - 1;
UBRR0H = (period) >> 8;
UBRR0L = (period);
#include <appconfig.h> /* CONFIG_TIMER */
#include <cfg/compiler.h> /* uint8_t */
+#include <cfg/macros.h> /* DIV_ROUND */
#include <hw_cpu.h> /* CLOCK_FREQ */
/**
/** This value is the maximum in overflow based timers. */
#define TIMER_HW_CNT (1 << TIMER_HW_BITS)
#define DEFINE_TIMER_ISR SIGNAL(SIG_OVERFLOW1)
- #define TIMER_TICKS_PER_SEC ((TIMER_HW_HPTICKS_PER_SEC + TIMER_HW_CNT / 2) / TIMER_HW_CNT)
+ #define TIMER_TICKS_PER_SEC DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, TIMER_HW_CNT)
/// Type of time expressed in ticks of the hardware high precision timer
typedef uint16_t hptime_t;
/** This value is the maximum in overflow based timers. */
#define TIMER_HW_CNT (1 << TIMER_HW_BITS)
#define DEFINE_TIMER_ISR SIGNAL(SIG_OVERFLOW3)
- #define TIMER_TICKS_PER_SEC ((TIMER_HW_HPTICKS_PER_SEC + TIMER_HW_CNT / 2) / TIMER_HW_CNT)
+ #define TIMER_TICKS_PER_SEC DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, TIMER_HW_CNT)
/// Type of time expressed in ticks of the hardware high precision timer
typedef uint16_t hptime_t;
/** Frequency of the hardware high precision timer. */
-#define TIMER_HW_HPTICKS_PER_SEC ((CLOCK_FREQ + TIMER_PRESCALER / 2) / TIMER_PRESCALER)
+#define TIMER_HW_HPTICKS_PER_SEC DIV_ROUND(CLOCK_FREQ, TIMER_PRESCALER)
/**
* System timer: additional division after the prescaler
* 12288000 / 64 / 192 (0..191) = 1 ms
*/
-#define OCR_DIVISOR (((CLOCK_FREQ + TIMER_PRESCALER / 2) / TIMER_PRESCALER + TIMER_TICKS_PER_SEC / 2) / TIMER_TICKS_PER_SEC - 1)
+#define OCR_DIVISOR (DIV_ROUND(DIV_ROUND(CLOCK_FREQ, TIMER_PRESCALER), TIMER_TICKS_PER_SEC) - 1)
/** Not needed, IRQ timer flag cleared automatically */
#define timer_hw_irq() do {} while (0)
if (triacs[dev].duty != TRIAC_MAX_DUTY)
TRIAC_OFF(dev);
/* Compute delay from duty */
- timer_setDelay(&triacs[dev].timer, ((period * (TRIAC_MAX_DUTY - triacs[dev].duty) + TRIAC_MAX_DUTY / 2) / TRIAC_MAX_DUTY));
+ timer_setDelay(&triacs[dev].timer, DIV_ROUND(period * (TRIAC_MAX_DUTY - triacs[dev].duty), TRIAC_MAX_DUTY));
/* This check avoids inserting the same timer twice
* in case of an intempestive zerocross or spike */
#define DRV_TIMER_H
#include <cfg/os.h>
+#include <cfg/macros.h>
#include <cpu/attr.h>
#include <cpu/irq.h>
+
/*
* Include platform-specific binding header if we're hosted.
* Try the CPU specific one for bare-metal environments.
return (ms * TIMER_TICKS_PER_SEC) / 1000;
#else
/* Fast timer: don't overflow ticks_t. */
- return ms * ((TIMER_TICKS_PER_SEC + 500) / 1000);
+ return ms * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000);
#endif
}
return ((us / 1000) * TIMER_TICKS_PER_SEC) / 1000;
#else
/* Fast timer: don't overflow ticks_t. */
- return (us * ((TIMER_TICKS_PER_SEC + 500) / 1000)) / 1000;
+ return (us * DIV_ROUND(TIMER_TICKS_PER_SEC, 1000)) / 1000;
#endif
}
INLINE hptime_t us_to_hptime(utime_t us)
{
#if TIMER_HW_HPTICKS_PER_SEC > 10000000UL
- return us * ((TIMER_HW_HPTICKS_PER_SEC + 500000UL) / 1000000UL);
+ return us * DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000000UL);
#else
return (us * ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL) + 500) / 1000UL;
#endif
INLINE utime_t hptime_to_us(hptime_t hpticks)
{
#if TIMER_HW_HPTICKS_PER_SEC < 100000UL
- return hpticks * ((1000000UL + TIMER_HW_HPTICKS_PER_SEC / 2) / TIMER_HW_HPTICKS_PER_SEC);
+ return hpticks * DIV_ROUND(1000000UL, TIMER_HW_HPTICKS_PER_SEC);
#else
- return (hpticks * 1000UL) / ((TIMER_HW_HPTICKS_PER_SEC + 500) / 1000UL);
+ return (hpticks * 1000UL) / DIV_ROUND(TIMER_HW_HPTICKS_PER_SEC, 1000UL);
#endif /* TIMER_HW_HPTICKS_PER_SEC < 100000UL */
}