parse_neighbor: replace printf printf_P
[protos/xbee-avr.git] / 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
91
92
93 /** absolute
94  *  while the abs() function in the libc works only with int type
95  *  this macro works with every numerical type including floats
96  */
97 #define ABS(val) ({                                     \
98                         __typeof(val) __val = (val);    \
99                         if (__val < 0)                  \
100                                 __val = - __val;        \
101                         __val;                          \
102                 })
103
104 /* 
105  * Extract bytes and u16 from larger integer
106  */
107
108 #if __BYTE_ORDER != __LITTLE_ENDIAN && __BYTE_ORDER != __BIG_ENDIAN
109 # error "Endianness not defined"
110 #endif
111
112 struct extract32 {
113         union {
114                 struct {
115 #if __BYTE_ORDER == __LITTLE_ENDIAN
116                         uint8_t u8_0;
117                         uint8_t u8_1;
118                         uint8_t u8_2;
119                         uint8_t u8_3;
120 #elif __BYTE_ORDER == __BIG_ENDIAN
121                         uint8_t u8_3;
122                         uint8_t u8_2;
123                         uint8_t u8_1;
124                         uint8_t u8_0;
125 #endif
126                 } __attribute__ ((packed)) u8;
127                 struct {
128 #if __BYTE_ORDER == __LITTLE_ENDIAN
129                         uint16_t u16_0;
130                         uint16_t u16_1;
131 #elif __BYTE_ORDER == __BIG_ENDIAN
132                         uint16_t u16_1;
133                         uint16_t u16_0;
134 #endif
135                 } __attribute__ ((packed)) u16;
136                 struct {
137 #if __BYTE_ORDER == __LITTLE_ENDIAN
138                         uint8_t u8_0;
139                         uint16_t u16_mid;
140                         uint8_t u8_3;
141 #elif __BYTE_ORDER == __BIG_ENDIAN
142                         uint8_t u8_3;
143                         uint16_t u16_mid;
144                         uint8_t u8_0;
145 #endif
146                 } __attribute__ ((packed)) u16_b;
147                 uint32_t u32;
148         } __attribute__ ((packed)) u;
149 } __attribute__ ((packed));
150
151 #define extr32_08_0(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_0; })
152 #define extr32_08_1(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_1; })
153 #define extr32_08_2(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_2; })
154 #define extr32_08_3(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u8.u8_3; })
155
156 #define extr32_16_0(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u16.u16_0; })
157 #define extr32_16_1(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u16.u16_1; })
158 #define extr32_16_mid(i) ({ struct extract32 __x; __x.u.u32 = i; __x.u.u16_b.u16_mid; })
159
160
161 struct extract16 {
162         union {
163                 struct {
164 #if __BYTE_ORDER == __LITTLE_ENDIAN
165                         uint8_t u8_0;
166                         uint8_t u8_1;
167 #elif __BYTE_ORDER == __BIG_ENDIAN
168                         uint8_t u8_1;
169                         uint8_t u8_0;
170 #endif
171                 } __attribute__ ((packed)) u8;
172                 uint16_t u16;
173         } __attribute__ ((packed)) u;
174 } __attribute__ ((packed));
175
176 #define extr16_08_0(i) ({ struct extract16 __x; __x.u.u16 = i; __x.u.u8.u8_0; })
177 #define extr16_08_1(i) ({ struct extract16 __x; __x.u.u16 = i; __x.u.u8.u8_1; })
178
179
180
181 /* a few asm utilities */
182
183 #ifndef HOST_VERSION
184 #ifndef nop
185 #define nop() __asm__ __volatile__ ("NOP\n") /** nop instruction, 1 CPU cycle consumed */
186 #endif
187 #ifndef nothing
188 #define nothing() __asm__ __volatile__ (" \n")  /** nothing */
189 #endif
190 #ifndef cli
191 #define cli() __asm__ __volatile__ ("CLI\n") /** disable interrupts */
192 #endif
193 #ifndef sei
194 #define sei() __asm__ __volatile__ ("SEI\n") /** enable interrupts */
195 #endif
196 /** simple software reset, but doesn't initialize the registers */
197 #ifndef reset
198 #define reset()                      \
199 do {                                 \
200   __asm__ __volatile__ ("ldi r30,0\n");  \
201   __asm__ __volatile__ ("ldi r31,0\n");  \
202   __asm__ __volatile__ ("ijmp\n");  \
203 } while(0)
204 #endif
205
206 #else /* HOST_VERSION */
207 #define nop() do {} while(0)
208 #define nothing() do {} while(0)
209 #define cli() do {} while(0)
210 #define sei() do {} while(0)
211 #define reset() exit(1)
212 #endif /* HOST_VERSION */
213
214 /**
215  *   little bit toggeling macro 
216  *  
217  *  change pin state
218  *  usage :
219  *  BIT_TOGGLE(PORTB,2) to make the pin 2 of PORTB toggle
220  */
221 #define BIT_TOGGLE(port,bit) do {\
222       if(bit_is_set(PIN(port),bit)) \
223         cbi(port,bit); \
224       else \
225         sbi(port,bit); \
226       } while(0)
227
228
229 /** booleans */
230
231
232 /** DDR and PINS from port adress */
233 #define DDR(port) (*(&(port) -1))
234 #define PIN(port) (*(&(port) -2))
235
236 /** open collector simulation macros */
237 #define OPEN_CO_INIT(port, bit) sbi(port,bit)
238 #define OPEN_CO_HIGH(port, bit) cbi(DDR(port),bit)
239 #define OPEN_CO_LOW(port, bit)  cbi(DDR(port),bit)
240
241 /** deprecated macros in libc, but they're almost used, so we implement them again ;) */
242 #ifndef cbi
243 #define cbi(sfr, bit) ( sfr &= ~ _BV(bit))
244 #endif
245 #ifndef sbi
246 #define sbi(sfr, bit) ( sfr |= _BV(bit))
247 #endif
248
249
250 #endif /* ifndef _AVERSIVE_H_ */
251