2 * Copyright Droids Corporation, Microb Technology, Eirbot (2005)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Copyright Droids-corporation - Olivier MATZ - 2009
25 #include <aversive/timers.h>
26 #include <aversive/parts.h>
29 * PWM signs & sign ligne inversion.
30 * The pwm mode is defined be the following flags:
32 * PWM_NG_MODE_NORMAL : normal pwm, just to put a value if
33 * nothing else is needed.
34 * PWM_NG_MODE_REVERSE : invert pwm output, not sign.
35 * PWM_NG_MODE_SIGNED : activate the sign output on another port
36 * PWM_NG_MODE_SIGN_INVERTED : invert sign output
37 * PWM_NG_MODE_SPECIAL_SIGN_MODE : if defined, the pwm is always near 0 for
38 * low values, else negative low values are
41 #define PWM_NG_MODE_NORMAL 0x00
42 #define PWM_NG_MODE_REVERSE 0x01
43 #define PWM_NG_MODE_SIGN_INVERTED 0x02
44 #define PWM_NG_MODE_SIGNED 0x04
45 #define PWM_NG_MODE_SPECIAL_SIGN 0x08
50 #define PWM_NG_TIMER_0_MODE
54 type:1, /* timer 8 bits or 16 bits */
55 nbits:2, /* 8, 9, or 10 bits pwm */
58 volatile uint8_t *ocr8;
59 volatile uint16_t *ocr16;
61 volatile uint8_t *sign_port;
66 * Initialize a 8 bits timer to do a PWM. This macro must
67 * be called before pwm_ng_init().
68 * \param n is the number of the timer.
69 * \param t_mode can be TIMER_8_MODE_PWM_PC, TIMER_8_MODE_CTC,
71 * \param prsc is the value to be loaded in
72 * the prescaler register for this timer. For instance,
73 * TIMER0_PRESCALER_DIV_256.
75 #define PWM_NG_TIMER_8BITS_INIT(n, t_mode, prsc) \
77 TCCR##n = ( ((t_mode & 0x01) ? (1 << WGM##n##0):0) | \
78 ((t_mode & 0x02) ? (1 << WGM##n##1):0) | \
79 ((prsc << CS##n##0)) ); \
83 * same, but with timer8 with several OCx (like on atm2560)
85 #define PWM_NG_TIMER_8BITS_INIT_B(n, t_mode, prsc) \
87 TCCR##n##A = ( ((t_mode & 0x01) ? (1 << WGM##n##0):0) | \
88 ((t_mode & 0x02) ? (1 << WGM##n##1):0) | \
89 ((prsc << CS##n##0)) ); \
90 TCCR##n##B = (prsc << CS##n##0); \
94 * Initialize a 16 bits timer to do a PWM. This macro must
95 * be called before pwm_ng_init().
96 * \param n is the number of the timer.
97 * \param timer_mode can be TIMER_16_MODE_PWM_PC, TIMER_16_MODE_CTC,
98 * TIMER_16_MODE_PWM...
99 * \param prsc is the value to be loaded in
100 * the prescaler register for this timer. For instance,
101 * TIMER1_PRESCALER_DIV_256.
103 #define PWM_NG_TIMER_16BITS_INIT(n, t_mode, prsc) do { \
104 TCCR##n##A &= ~((1 << WGM##n##0) | (1 << WGM##n##1)); \
105 TCCR##n##A |= ((t_mode & 0x01) ? (1 << WGM##n##0):0) | \
106 ((t_mode & 0x02) ? (1 << WGM##n##1):0); \
107 TCCR##n##B = ((t_mode & 0x04) ? (1 << WGM##n##2):0) | \
108 ((t_mode & 0x08 ) ? (1 << WGM##n##3):0) | \
109 (prsc << CS##n##0); \
114 * Inititialize a PWM: set its mode, output pin DDR, DDR for sign
115 * bit if any. Example for 8 bits (for atmega128):
116 * pwm_ng_init(&pwm, 8, 8, PWM_NG_MODE_SIGNED|PWM_NG_MODE_SIGN_INVERTED,
117 * &OCR0, COM00, &TCCR0, &PORTB, 4, &PORTE, 3);
118 * Example for 16 bits (for atmega32):
119 * pwm_ng_init(&pwm, 16, 9, PWM_NG_MODE_NORMAL,
120 * &OCR1B, COM1B0, &TCCR1A, &PORTD, 5, NULL, 0);
121 * Note that you can use the helper macros PWM_NG_INIT8() or
122 * PWM_NG_INIT16() instead.
123 * \param pwm is the pointer to the pwm structure that will be
125 * \param nbits is the number of bits for the timer (8 or 16).
126 * \param pwm_mode is the mode of the PWM. See the PWM_NG_MODE_xxx
128 * \param ocrn is a pointer to the OCRn register for this PWM.
129 * \param com0 is the COMn0 for this PWM.
130 * \param pwm_port is the pointer to the PORT of the pwm corresponding
131 * to the configured PWM. For instance &PORTB. This is specified in
132 * the datasheets, and depends on the AVR part.
133 * \param pwm_bit is the bitnum of the configured pwm output. This
134 * is specified in the datasheets, and depends on the AVR part.
135 * \param sign_port is a poinrter to the PORT for the sign bit if
136 * any, else, it can be set to NULL.
137 * \param sign_bit is the bitnum of the configured sign output.
139 void pwm_ng_init(struct pwm_ng *pwm, uint8_t timer_nbits,
140 uint8_t pwm_nbits, uint8_t pwm_mode,
142 uint8_t com0, volatile uint8_t *tccrn,
143 volatile uint8_t *pwm_port, uint8_t pwm_bit,
144 volatile uint8_t *sign_port, uint8_t sign_bit);
146 #define PWM_NG_INIT8(pwm, n, pwm_nbits, pwm_mode, sign_port, sign_bit) \
148 pwm_ng_init(pwm, 8, pwm_nbits, pwm_mode, &OCR##n, \
149 COM##n##0, &TCCR##n, &OC##n##_PORT, \
150 OC##n##_BIT, sign_port, sign_bit); \
153 #define PWM_NG_INIT8_B(pwm, n, m, pwm_nbits, pwm_mode, sign_port, sign_bit) \
155 pwm_ng_init(pwm, 8, pwm_nbits, pwm_mode, &OCR##n##m, \
156 COM##n##m##0, &TCCR##n##A, &OC##n##m##_PORT, \
157 OC##n##m##_BIT, sign_port, sign_bit); \
160 #define PWM_NG_INIT16(pwm, n, m, pwm_nbits, pwm_mode, sign_port, sign_bit) \
162 pwm_ng_init(pwm, 16, pwm_nbits, pwm_mode, &OCR##n##m, \
163 COM##n##m##0, &TCCR##n##A, \
164 &OC##n##m##_PORT, OC##n##m##_BIT, \
165 sign_port, sign_bit); \
169 * \param pwm is a pointer to the struct pwm.
170 * \param value is the value of the pwm. The value is between 0 and
171 * 4095 for a non-signed pwm or -4096 and 4095 for a signed one.
173 void pwm_ng_set(void *pwm, int32_t value);