Sun position
Sun position algorithm
general.h
Go to the documentation of this file.
1 #ifndef GENERAL_H
2 #define GENERAL_H
3 /*============================================================================*/
4 /*!\file
5  * \brief general.h - definitions of general use to (standard) C programs
6  *
7  * \author David Hoadley <vcrumble@westnet.com.au>
8  *
9  * \details
10  * Definitions that almost all of our C programs can find useful. Defines
11  * bool and fixed size int data types, if the compiler standard does not
12  * (i.e. if this is a pre-C99 compiler). Defines a static_assert() macro
13  * if this is a pre-C11 compiler. Some other useful constants and macros
14  * are defined, including macros for assertions in an embedded context.
15  *
16  *==============================================================================
17  */
18 /* Which C standard(s) does this compiler support here? */
19 #if defined(__STDC__)
20 # define PREDEF_STANDARD_C_1989
21 # if defined(__STDC_VERSION__)
22 # define PREDEF_STANDARD_C_1990
23 # if (__STDC_VERSION__ >= 199409L)
24 # define PREDEF_STANDARD_C_1994
25 # endif
26 # if (__STDC_VERSION__ >= 199901L)
27 # define PREDEF_STANDARD_C_1999
28 # endif
29 # if (__STDC_VERSION__ >= 201112L)
30 # define PREDEF_STANDARD_C_2011
31 # endif
32 # if (__STDC_VERSION__ >= 201710L)
33 # define PREDEF_STANDARD_C_2018
34 # endif
35 # endif
36 #endif
37 
38 /*------------------------------------------------------------------------------
39  *
40  * Possibly missing type definitions
41  *
42  *----------------------------------------------------------------------------*/
43 #ifndef PREDEF_STANDARD_C_1999
44 
45 typedef int bool; /* C89/90 lacks a proper Boolean data type */
46 #define false (bool)(0)
47 #define true (bool)(1)
48 
49 /* In embedded systems, we are implementing code on processors where the word
50  * length is critical to the maths we implement. The size of char, int and long
51  * int varies from processor to processor (and/or compiler to compiler). In
52  * order to get 8, 16 and 32-bit numbers when we want them, declare variables
53  * using the following six typedefs. Change the definitions of these typedefs
54  * here, according to your compiler.
55  * If our compiler supports the C99 standard and we include the <stdint.h>
56  * header file, these types are already defined. */
57 typedef signed char int8_t;
58 typedef unsigned char uint8_t;
59 typedef signed short int int16_t;
60 typedef unsigned short int uint16_t;
61 typedef int int32_t;
62 typedef unsigned int uint32_t;
63 
64 #else
65 #include <stdbool.h> /* for bool, true and false */
66 #include <stdint.h> /* for intX_t and uintX_t types */
67 #endif
68 
69 /* How do we know that our typedef's above are correct? We need a way of
70  * checking this at compile time with a test that will cause a compilation error
71  * if it fails. This is a case for a static assertion.
72  * If our compiler supports the C11 standard, we have access to the
73  * _Static_assert(expression, message) built-in function to do exactly this, and
74  * if we include <assert.h>, there is a macro "static_assert()" already defined
75  * (= _Static_assert()).
76  * But of course, if this is a C89/90 compiler, this macro does not exist.
77  * So it is useful to define one here. Similarly a C99 program can use it.
78  * Here is that definition. Unfortunately it is not quite as smooth as the real
79  * static_assert() introduced in C11, because it generates two irrelevant error
80  * messages:
81  * "warning: division by zero [-Wdiv-by-zero]"
82  * "error: enumerator value for ‘static_assert_nnn’ is not an integer constant"
83  * but the location of the error will tell you what the problem is.
84  * If you are using gcc, you might find that you are drowning in "note:"
85  * messages each time a static assertion fails. If so, compile with the option
86  * -ftrack-macro-expansion=0 */
87 #ifndef PREDEF_STANDARD_C_2011
88 
89 /* Strange token-pasting magic here */
90 #define CONCAT(a, b) a ## b
91 #define EXPCONCAT(a, b) CONCAT(a, b)
92 #define static_assert(e, msg) \
93  enum { EXPCONCAT(static_assert_, __LINE__) = 1/!!(e) }
94 /* typedef char EXPCONCAT(static_assert_, __LINE__)[(e)?1:-1] */
95 
96 #else
97 #include <assert.h>
98 #endif
99 
100 /* Now that we have defined static_assert(), use it to make sure that our
101  * typedefs of fixed size integers are actually correct for this machine
102  * architecture. (This is only a problem with C89/90 where we have typedef'ed
103  * them ourselves) */
104 #ifndef PREDEF_STANDARD_C_1999
105 static_assert(sizeof(int16_t) == 2, "typedef of int16_t is wrong");
106 static_assert(sizeof(uint16_t) == 2, "typedef of uint16_t is wrong");
107 static_assert(sizeof(int32_t) == 4, "typedef of int32_t is wrong");
108 static_assert(sizeof(uint32_t) == 4, "typedef of uint32_t is wrong");
109 #endif
110 
111 
112 /*------------------------------------------------------------------------------
113  *
114  * Peculiar design decisions in the C language
115  *
116  *----------------------------------------------------------------------------*/
117 
118 /*! C has some very silly default behaviours. One of these is to define all
119  * symbols declared at file level as global in scope (i.e. visible to the
120  * linker). This is a recipe for trouble. Secondly, C overloads the 'static'
121  * storage class (which defines how data is allocated to memory) with a second
122  * completely independent meaning - that the scope of the symbol name will be
123  * restricted to the current C source file only. While this is behaviour that
124  * we want, the use of the word 'static' is odd, to say the least. So, use the
125  * following definitions to discipline yourself to sensible behaviour - define
126  * truly global variables and functions as 'GLOBAL', and those which are to be
127  * visible only in the current C source file as 'LOCAL'.
128  * [Each global function definition should be matched with a corresponding
129  * function prototype in the corresponding header file, and each global
130  * variable definition should be matched with a corresponding 'extern'
131  * declaration in that same header file. There should be no 'extern'
132  * declarations outside of header files.] */
133 #define LOCAL static
134 #define GLOBAL /*!< See above */
135 
136 /* Another odd design decision was the requirement to insert the keyword "break"
137  * after every element of a switch-case construct if you did not want to run on
138  * and execute the code of the next element. That is, most of the time you must
139  * insert the word "break", and only occasionally do you write code in which you
140  * don't want it. So on average, if a "break" is missing in a case statement, it
141  * is a bug. So, on those rare occasions when we do intend to run on, we want to
142  * let people know that, this time, it isn't a bug. */
143 #define NOBREAK /*!< Show reader that 'break' was not omitted by accident */
144 #define FALLTHROUGH /*!< or if you prefer, use this word instead. */
145 
146 
147 /*------------------------------------------------------------------------------
148  *
149  * Useful arithmetic constants
150  *
151  *----------------------------------------------------------------------------*/
152 
153 /* A few definitions below are followed by an empty comment containing "!< . "
154  and nothing else. This is just to get Doxygen to include the definitions in
155  its lists and cross-references. But you don't need me to explain what each
156  one is, do you? */
157 /* Double precision constants */
158 #define PI 3.1415926535897932384626433832795028841971 /*!< , */
159 #define HALFPI (PI / 2.0) /*!< , */
160 #define TWOPI (2.0 * PI) /*!< , */
161 #define SQRT2 1.4142135623730950488016887242096980785697 /*!< , */
162 #define SQRT3 1.7320508075688772935274463415058723669428 /*!< , */
163 
164 /* Angle conversions */
165 #define DEG2RAD (PI / 180.0) /*!< degrees to radians */
166 #define RAD2DEG (180.0 / PI) /*!< radians to degrees */
167 
168 /*! A very small number, used to avoid divide by 0 errors */
169 #define SFA 1E-10
170 
171 /*------------------------------------------------------------------------------
172  *
173  * Other useful macros and inline functions
174  *
175  *----------------------------------------------------------------------------*/
176 /* Convert angle from one unit to another */
177 #ifdef PREDEF_STANDARD_C_1999
178 /* Compiler supports inline functions */
179 /*! Returns \a angle_deg converted from degrees to radians */
180 static inline double degToRad(double angle_deg) { return angle_deg * DEG2RAD; }
181 /*! Returns \a angle_rad converted from radians to degrees */
182 static inline double radToDeg(double angle_rad) { return angle_rad * RAD2DEG; }
183 
184 #else
185 /* C89/C90 compiler only - no inline functions. Need macros instead */
186 #define degToRad(angle_deg__) ((angle_deg__) * DEG2RAD)
187 #define radToDeg(angle_rad__) ((angle_rad__) * RAD2DEG)
188 
189 #endif
190 
191 /*! Because C passes arrays to functions by passing only a pointer to the
192  * zero'th element of the array, we often need to pass the array size in a
193  * separate argument to the function. Make that easier. */
194 #define ARRAY_SIZE(x__) (int)(sizeof(x__)/sizeof(x__[0]))
195 
196 /*! There are times when we want to declare arrays or buffers whose dimension is
197  * a power of 2, so that the index value can be bit-masked to enforce wrap-
198  * around. Code based on this assumption will fail if the array size is changed
199  * by someone who doesn't notice this requirement.
200  * Here is a check you can use to help prevent that happening */
201 #define ISPOWER2(x__) (!((x__)&((x__)-1)))
202 
203 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
204 /*! Useful macros for supporting a "Design by Contract" approach to
205  programming embedded systems. These are heavily influenced by the
206  article "Design by Contract (DbC) for Embedded Software" by Miro Samek,
207  to be found on the Barr Group website, at
208  https://barrgroup.com/Embedded-Systems/How-To/Design-by-Contract-for-Embedded-Software
209 
210  To use,
211  1. define an implementation of onAssert__() function as specified below.
212  For example, it could write the first n chars of the filename and the
213  line number to a bit of memory that won't be erased on a reboot, and
214  then force a reboot.
215  2. spread REQUIRE(), ENSURE(), and INVARIANT() macros throughout your
216  code. (In brief, REQUIRE() macros are generally put at the beginning
217  of functions to check the validity of passed parameters. ENSURE()
218  macros are generally placed at the end of functions to check that the
219  functions have not calculated invalid results.)
220  3. put the DEFINE_THIS_FILE statement near the top of each C file that
221  contains any REQUIRE(), ENSURE(), or INVARIANT() macros.
222  4. choose the ASSERTION_LEVEL that you want.
223 
224  (If you define USE_STANDARD_ASSERT as described below, you don't really
225  need to do steps 1 and 3. They are really for embedded systems.)
226 */
227 //#define ASSERTION_LEVEL 0 /* DbC assertions are all disabled */
228 //#define ASSERTION_LEVEL 1 /* Pre-conditions checked (only) */
229 #define ASSERTION_LEVEL 2 /* Pre & post-conditions checked */
230 //#define ASSERTION_LEVEL 3 /* Everything checked */
231 
232 /* Uncomment the following line if you want to use the standard assert() macro,
233  * and NOT use your own onAssert__() function to implement these DbC macros.
234  * Comment it out if you want to create an onAssert__() function, or if assert.h
235  * is not available. */
236 #define USE_STANDARD_ASSERT
237 
238 #if (ASSERTION_LEVEL == 0)
239 /*! Leave DEFINE_THIS_FILE undefined. But we get a -Wextra-semi warning
240  * message if it is defined as nothing at all, so use this dummy
241  * declaration instead. */
242 # define DEFINE_THIS_FILE typedef int dummy_t
243 # define ASSERT(ignore_) ((void)0) /*!< all assertions disabled */
244 
245 #else
246 
247 # if defined(USE_STANDARD_ASSERT)
248 # include <assert.h>
249  /*! Leave DEFINE_THIS_FILE undefined. But we get a -Wextra-semi warning
250  * message if it is defined as nothing at all, so use this dummy
251  * declaration instead. */
252 # define DEFINE_THIS_FILE typedef int dummy_t
253 # define ASSERT(test_) assert(test_) /*!< Uses standard assert */
254 # else
255 # ifdef __cplusplus
256  extern "C"
257  {
258 # endif
259  /*! callback invoked in case of assertion failure */
260  void onAssert__(const char *file, unsigned line);
261 # ifdef __cplusplus
262  }
263 # endif
264 
265 /*! Ensure exe image contains one copy of file name, not one per ASSERT */
266 # define DEFINE_THIS_FILE static char const THIS_FILE__[] = __FILE__
267 # define ASSERT(test_) ((test_) ? (void)0 \
268  : onAssert__(THIS_FILE__, __LINE__))
269 # endif
270 #endif
271 
272 #if (ASSERTION_LEVEL >= 1)
273 # define REQUIRE(test_) ASSERT(test_) /*!< Check preconditions */
274 #else
275 # define REQUIRE(test_) ((void)0) /*!< Pre-condition checks disabled*/
276 #endif
277 
278 #if (ASSERTION_LEVEL >= 2)
279 # define ENSURE(test_) ASSERT(test_) /*!< Check post-conditions */
280 #else
281 # define ENSURE(test_) ((void)0) /*!<Post-condition checks disabled*/
282 #endif
283 
284 #if (ASSERTION_LEVEL == 3)
285 # define INVARIANT(test_) ASSERT(test_) /*!< Check invariants */
286 #else
287 # define INVARIANT(test_) ((void)0) /*!< Invariant checks disabled */
288 #endif
289 
290 #if !defined(ASSERTION_LEVEL) || (ASSERTION_LEVEL < 0) || (ASSERTION_LEVEL > 3)
291 # error "ASSERTION_LEVEL must be set to one of 0, 1, 2, or 3"
292 #endif
293 
294 /* Finally, one more piece of assertion checking that is particularly relevant
295  * to C code. Unlike C++, C does not allow passing parameters to functions by
296  * reference. It allows passing by address/by pointer, but this is not exactly
297  * the same thing. It is quite possible to pass NULL to any parameter in C that
298  * is expecting an address or pointer, and the compiler will not object. After
299  * all, sometimes functions check for NULL pointers and take different actions
300  * if one is passed. But all too often, functions cannot handle getting a NULL
301  * pointer, and will crash if one is passed. An assertion check helps here.
302  * Uncomment the following line if you want to perform NULL checking.
303  * Comment it out if you want to suppress NULL checking. */
304 #define ENABLE_NULL_CHECKING
305 
306 #ifdef ENABLE_NULL_CHECKING
307 # include <stddef.h> /* Make sure NULL is defined */
308 # define REQUIRE_NOT_NULL(pointer_) ASSERT((pointer_) != NULL) /*!< , */
309 #else
310 # define REQUIRE_NOT_NULL(pointer_) ((void)0) /*!< Pointer checking disabled*/
311 #endif
312 
313 #endif /*GENERAL_H*/
RAD2DEG
#define RAD2DEG
radians to degrees
Definition: general.h:166
DEG2RAD
#define DEG2RAD
degrees to radians
Definition: general.h:165
degToRad
static double degToRad(double angle_deg)
Returns angle_deg converted from degrees to radians.
Definition: general.h:180
radToDeg
static double radToDeg(double angle_rad)
Returns angle_rad converted from radians to degrees.
Definition: general.h:182