add ballboard commands on mainboard
[aversive.git] / modules / hardware / pwm_ng / pwm_ng.h
1 /*  
2  *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
3  * 
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.
8  *
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.
13  *
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
17  *
18  *  Copyright Droids-corporation - Olivier MATZ - 2009
19  */
20
21 #ifndef _PWM_NG_H_
22 #define _PWM_NG_H_
23
24 #include <aversive.h>
25 #include <aversive/timers.h>
26 #include <aversive/parts.h>
27
28 /*
29  * PWM signs & sign ligne inversion.
30  * The pwm mode is defined be the following flags:
31  *
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 
39  *                                 near 100%
40  */
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
46
47 /*
48  * Timer modes.
49  */
50 #define PWM_NG_TIMER_0_MODE
51
52 struct pwm_ng {
53         uint8_t mode:4,
54                 type:1, /* timer 8 bits or 16 bits */
55                 nbits:2, /* 8, 9, or 10 bits pwm */
56                 reserved:1;
57         union {
58                 volatile uint8_t *ocr8;
59                 volatile uint16_t *ocr16;
60         } u;
61         volatile uint8_t *sign_port;
62         uint8_t sign_bit;
63 };
64
65  /** 
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, 
70   * TIMER_8_MODE_PWM.
71   * \param prsc is the value to be loaded in
72   * the prescaler register for this timer. For instance,
73   * TIMER0_PRESCALER_DIV_256.
74   */
75 #define PWM_NG_TIMER_8BITS_INIT(n, t_mode, prsc)                        \
76         do {                                                            \
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)) );                    \
80         } while(0)
81
82 /** 
83  * same, but with timer8 with several OCx (like on atm2560)
84  */
85 #define PWM_NG_TIMER_8BITS_INIT_B(n, t_mode, prsc)                      \
86         do {                                                            \
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);                        \
91         } while(0)
92
93  /** 
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.
102   */
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);                             \
110         } while(0)
111
112
113 /**
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
124  * filled.
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
127  * flags above.
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.
138  */
139 void pwm_ng_init(struct pwm_ng *pwm, uint8_t timer_nbits, 
140                  uint8_t pwm_nbits, uint8_t pwm_mode, 
141                  volatile void *ocrn, 
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);
145
146 #define PWM_NG_INIT8(pwm, n, pwm_nbits, pwm_mode, sign_port, sign_bit)  \
147         do {                                                            \
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);          \
151         } while(0)
152
153 #define PWM_NG_INIT8_B(pwm, n, m, pwm_nbits, pwm_mode, sign_port, sign_bit) \
154         do {                                                            \
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);       \
158         } while(0)
159
160 #define PWM_NG_INIT16(pwm, n, m, pwm_nbits, pwm_mode, sign_port, sign_bit) \
161         do {                                                            \
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);                       \
166         } while(0)
167
168 /** apply a PWM.
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.
172  */
173 void pwm_ng_set(void *pwm, int32_t value); 
174
175 #endif // _PWM_H_