ini
[aversive.git] / include / aversive.h
1 /*  
2  *  Copyright Droids Corporation, Microb Technology, Eirbot (2007)
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  *  Revision : $Id: aversive.h,v 1.1.2.6 2009-05-18 12:19:51 zer0 Exp $
19  *
20  */
21
22 /**
23  * here are some cute little macros, and other stuff, microcontroller
24  * related ! 
25  */
26
27
28 #ifndef _AVERSIVE_H_
29 #define _AVERSIVE_H_
30
31 #include <autoconf.h>
32
33 #ifndef HOST_VERSION
34 #include <avr/interrupt.h>
35 #include <avr/io.h>
36 #endif
37
38 #include <aversive/types.h>
39 #include <aversive/errno.h>
40 #include <aversive/irq_lock.h>
41
42
43 #ifndef __AVR_LIBC_VERSION__ /* version.h should be included by avr/io.h */
44 #define __AVR_LIBC_VERSION__ 0UL 
45 #endif
46
47 #ifndef HOST_VERSION
48 #if __AVR_LIBC_VERSION__ < 10403UL
49 #include <avr/signal.h>
50 #endif
51 #endif
52
53 #define F_CPU ((unsigned long)CONFIG_QUARTZ)
54
55 #define Hz  1l
56 #define KHz 1000l
57 #define MHz 1000000l
58
59
60
61 /*
62  *  a few "mathematical" macros : maximums and minimums
63  */
64
65 /**
66  *  signed maxmimum : both signs are tested
67  */
68 #define S_MAX(to_saturate, value_max)    \
69 do {                                     \
70    if (to_saturate > value_max)          \
71      to_saturate = value_max;            \
72    else if (to_saturate < -value_max)    \
73      to_saturate = -value_max;           \
74  } while(0)
75
76 /**
77  *  unsigned maximum : result >0 is forced
78  */
79 #define U_MAX(to_saturate, value_max)    \
80 do {                                     \
81    if (to_saturate > value_max)          \
82      to_saturate = value_max;            \
83    else if (to_saturate < 0)             \
84      to_saturate = 0;                    \
85  } while(0)
86
87 /**
88  *   simple maximum
89  */
90 #define MAX(to_saturate, value_max)      \
91 do {                                     \
92    if (to_saturate > value_max)          \
93      to_saturate = value_max;            \
94 } while(0)
95
96 /**
97  *  simple minimum
98  */
99 #define MIN(to_saturate, value_min)      \
100 do {                                     \
101    if (to_saturate < value_min)          \
102      to_saturate = value_min;            \
103 } while(0)
104
105
106 /** absolute
107  *  while the abs() function in the libc works only with int type
108  *  this macro works with every numerical type including floats
109  */
110 #define ABS(val) ({                                     \
111                         __typeof(val) __val = (val);    \
112                         if (__val < 0)                  \
113                                 __val = - __val;        \
114                         __val;                          \
115                 })
116
117 /* 
118  * Extract bytes and u16 from larger integer
119  */
120
121 #if __BYTE_ORDER != __LITTLE_ENDIAN && __BYTE_ORDER != __BIG_ENDIAN
122 # error "Endianness not defined"
123 #endif
124
125 struct extract32 {
126         union {
127                 struct {
128 #if __BYTE_ORDER == __LITTLE_ENDIAN
129                         uint8_t u8_0;
130                         uint8_t u8_1;
131                         uint8_t u8_2;
132                         uint8_t u8_3;
133 #elif __BYTE_ORDER == __BIG_ENDIAN
134                         uint8_t u8_3;
135                         uint8_t u8_2;
136                         uint8_t u8_1;
137                         uint8_t u8_0;
138 #endif
139                 } __attribute__ ((packed)) u8;
140                 struct {
141 #if __BYTE_ORDER == __LITTLE_ENDIAN
142                         uint16_t u16_0;
143                         uint16_t u16_1;
144 #elif __BYTE_ORDER == __BIG_ENDIAN
145                         uint16_t u16_1;
146                         uint16_t u16_0;
147 #endif
148                 } __attribute__ ((packed)) u16;
149                 struct {
150 #if __BYTE_ORDER == __LITTLE_ENDIAN
151                         uint8_t u8_0;
152                         uint16_t u16_mid;
153                         uint8_t u8_3;
154 #elif __BYTE_ORDER == __BIG_ENDIAN
155                         uint8_t u8_3;
156                         uint16_t u16_mid;
157                         uint8_t u8_0;
158 #endif
159                 } __attribute__ ((packed)) u16_b;
160                 uint32_t u32;
161         } __attribute__ ((packed)) u;
162 } __attribute__ ((packed));
163
164 #define extr32_08_0(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_0; })
165 #define extr32_08_1(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_1; })
166 #define extr32_08_2(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_2; })
167 #define extr32_08_3(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_3; })
168
169 #define extr32_16_0(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u16.u16_0; })
170 #define extr32_16_1(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u16.u16_1; })
171 #define extr32_16_mid(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u16_b.u16_mid; })
172
173
174 struct extract16 {
175         union {
176                 struct {
177 #if __BYTE_ORDER == __LITTLE_ENDIAN
178                         uint8_t u8_0;
179                         uint8_t u8_1;
180 #elif __BYTE_ORDER == __BIG_ENDIAN
181                         uint8_t u8_1;
182                         uint8_t u8_0;
183 #endif
184                 } __attribute__ ((packed)) u8;
185                 uint16_t u16;
186         } __attribute__ ((packed)) u;
187 } __attribute__ ((packed));
188
189 #define extr16_08_0(i) ({ struct extract16 __x; __x.u.u16 = i; __x.u.u8.u8_0; })
190 #define extr16_08_1(i) ({ struct extract16 __x; __x.u.u16 = i; __x.u.u8.u8_1; })
191
192
193
194 /* a few asm utilities */
195
196 #ifndef HOST_VERSION
197 #ifndef nop
198 #define nop() __asm__ __volatile__ ("NOP\n") /** nop instruction, 1 CPU cycle consumed */
199 #endif
200 #ifndef nothing
201 #define nothing() __asm__ __volatile__ (" \n")  /** nothing */
202 #endif
203 #ifndef cli
204 #define cli() __asm__ __volatile__ ("CLI\n") /** disable interrupts */
205 #endif
206 #ifndef sei
207 #define sei() __asm__ __volatile__ ("SEI\n") /** enable interrupts */
208 #endif
209 /** simple software reset, but doesn't initialize the registers */
210 #ifndef reset
211 #define reset()                      \
212 do {                                 \
213   __asm__ __volatile__ ("ldi r30,0\n");  \
214   __asm__ __volatile__ ("ldi r31,0\n");  \
215   __asm__ __volatile__ ("ijmp\n");  \
216 } while(0)
217 #endif
218
219 #else /* HOST_VERSION */
220 #define nop() do {} while(0)
221 #define nothing() do {} while(0)
222 #define cli() do {} while(0)
223 #define sei() do {} while(0)
224 #endif /* HOST_VERSION */
225
226 /**
227  *   little bit toggeling macro 
228  *  
229  *  change pin state
230  *  usage :
231  *  BIT_TOGGLE(PORTB,2) to make the pin 2 of PORTB toggle
232  */
233 #define BIT_TOGGLE(port,bit) do {\
234       if(bit_is_set(PIN(port),bit)) \
235         cbi(port,bit); \
236       else \
237         sbi(port,bit); \
238       } while(0)
239
240
241 /** booleans */
242 #define FALSE 0
243 #define TRUE 1
244 #define False FALSE
245 #define false FALSE
246 #define True TRUE
247 #define true TRUE
248
249
250 /** DDR and PINS from port adress */
251 #define DDR(port) (*(&(port) -1))
252 #define PIN(port) (*(&(port) -2))
253
254 /** open collector simulation macros */
255 #define OPEN_CO_INIT(port, bit) sbi(port,bit)
256 #define OPEN_CO_HIGH(port, bit) cbi(DDR(port),bit)
257 #define OPEN_CO_LOW(port, bit)  cbi(DDR(port),bit)
258
259 /** deprecated macros in libc, but they're almost used, so we implement them again ;) */
260 #ifndef cbi
261 #define cbi(sfr, bit) ( sfr &= ~ _BV(bit))
262 #endif
263 #ifndef sbi
264 #define sbi(sfr, bit) ( sfr |= _BV(bit))
265 #endif
266
267
268 #endif /* ifndef _AVERSIVE_H_ */
269