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
src
general.h
Generated by
1.8.17