Naming adjustment for USE_SERIAL_RX to USE_SERIALRX (#11992)
[betaflight.git] / src / main / pg / pg.h
blobc2cef49a391a28e65665de28cae9fbf2f619d3eb
1 /*
2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
8 * any later version.
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
21 #pragma once
23 #include <stdint.h>
24 #include <stdbool.h>
26 #include "build/build_config.h"
28 typedef uint16_t pgn_t;
30 // parameter group registry flags
31 typedef enum {
32 PGRF_NONE = 0,
33 PGRF_CLASSIFICATON_BIT = (1 << 0)
34 } pgRegistryFlags_e;
36 typedef enum {
37 PGR_PGN_MASK = 0x0fff,
38 PGR_PGN_VERSION_MASK = 0xf000,
39 PGR_SIZE_MASK = 0x0fff,
40 PGR_SIZE_SYSTEM_FLAG = 0x0000 // documentary
41 } pgRegistryInternal_e;
43 // function that resets a single parameter group instance
44 typedef void (pgResetFunc)(void * /* base */);
46 typedef struct pgRegistry_s {
47 pgn_t pgn; // The parameter group number, the top 4 bits are reserved for version
48 uint8_t length; // The number of elements in the group
49 uint16_t size; // Size of the group in RAM, the top 4 bits are reserved for flags
50 uint8_t *address; // Address of the group in RAM.
51 uint8_t *copy; // Address of the copy in RAM.
52 uint8_t **ptr; // The pointer to update after loading the record into ram.
53 union {
54 void *ptr; // Pointer to init template
55 pgResetFunc *fn; // Popinter to pgResetFunc
56 } reset;
57 uint32_t *fnv_hash; // Used to detect if config has changed prior to write
58 } pgRegistry_t;
60 static inline uint16_t pgN(const pgRegistry_t* reg) {return reg->pgn & PGR_PGN_MASK;}
61 static inline uint8_t pgVersion(const pgRegistry_t* reg) {return (uint8_t)(reg->pgn >> 12);}
62 static inline uint16_t pgSize(const pgRegistry_t* reg) {return reg->size & PGR_SIZE_MASK;}
63 static inline uint16_t pgElementSize(const pgRegistry_t* reg) {return (reg->size & PGR_SIZE_MASK) / reg->length;}
65 #define PG_PACKED __attribute__((packed))
67 #ifdef __APPLE__
68 extern const pgRegistry_t __pg_registry_start[] __asm("section$start$__DATA$__pg_registry");
69 extern const pgRegistry_t __pg_registry_end[] __asm("section$end$__DATA$__pg_registry");
70 #define PG_REGISTER_ATTRIBUTES __attribute__ ((section("__DATA,__pg_registry"), used, aligned(4)))
72 extern const uint8_t __pg_resetdata_start[] __asm("section$start$__DATA$__pg_resetdata");
73 extern const uint8_t __pg_resetdata_end[] __asm("section$end$__DATA$__pg_resetdata");
74 #define PG_RESETDATA_ATTRIBUTES __attribute__ ((section("__DATA,__pg_resetdata"), used, aligned(2)))
75 #else
76 extern const pgRegistry_t __pg_registry_start[];
77 extern const pgRegistry_t __pg_registry_end[];
78 #define PG_REGISTER_ATTRIBUTES __attribute__ ((section(".pg_registry"), used, aligned(4)))
80 extern const uint8_t __pg_resetdata_start[];
81 extern const uint8_t __pg_resetdata_end[];
82 #define PG_RESETDATA_ATTRIBUTES __attribute__ ((section(".pg_resetdata"), used, aligned(2)))
83 #endif
85 #define PG_REGISTRY_SIZE (__pg_registry_end - __pg_registry_start)
87 // Helper to iterate over the PG register. Cheaper than a visitor style callback.
88 #define PG_FOREACH(_name) \
89 for (const pgRegistry_t *(_name) = __pg_registry_start; (_name) < __pg_registry_end; _name++)
91 // Reset configuration to default (by name)
92 #define PG_RESET(_name) \
93 do { \
94 extern const pgRegistry_t _name ##_Registry; \
95 pgReset(&_name ## _Registry); \
96 } while (0) \
97 /**/
99 // Declare system config
100 #define PG_DECLARE(_type, _name) \
101 extern _type _name ## _System; \
102 extern _type _name ## _Copy; \
103 static inline const _type* _name(void) { return &_name ## _System; }\
104 static inline _type* _name ## Mutable(void) { return &_name ## _System; }\
105 struct _dummy \
106 /**/
108 // Declare system config array
109 #define PG_DECLARE_ARRAY(_type, _length, _name) \
110 extern _type _name ## _SystemArray[_length]; \
111 extern _type _name ## _CopyArray[_length]; \
112 static inline const _type* _name(int _index) { return &_name ## _SystemArray[_index]; } \
113 static inline _type* _name ## Mutable(int _index) { return &_name ## _SystemArray[_index]; } \
114 static inline _type (* _name ## _array(void))[_length] { return &_name ## _SystemArray; } \
115 struct _dummy \
116 /**/
118 // Register system config
119 #define PG_REGISTER_I(_type, _name, _pgn, _version, _reset) \
120 _type _name ## _System; \
121 _type _name ## _Copy; \
122 uint32_t _name ## _fnv_hash; \
123 /* Force external linkage for g++. Catch multi registration */ \
124 extern const pgRegistry_t _name ## _Registry; \
125 const pgRegistry_t _name ##_Registry PG_REGISTER_ATTRIBUTES = { \
126 .pgn = _pgn | (_version << 12), \
127 .length = 1, \
128 .size = sizeof(_type) | PGR_SIZE_SYSTEM_FLAG, \
129 .address = (uint8_t*)&_name ## _System, \
130 .fnv_hash = &_name ## _fnv_hash, \
131 .copy = (uint8_t*)&_name ## _Copy, \
132 .ptr = 0, \
133 _reset, \
135 /**/
137 #define PG_REGISTER(_type, _name, _pgn, _version) \
138 PG_REGISTER_I(_type, _name, _pgn, _version, .reset = {.ptr = 0}) \
139 /**/
141 #define PG_REGISTER_WITH_RESET_FN(_type, _name, _pgn, _version) \
142 extern void pgResetFn_ ## _name(_type *); \
143 PG_REGISTER_I(_type, _name, _pgn, _version, .reset = {.fn = (pgResetFunc*)&pgResetFn_ ## _name }) \
144 /**/
146 #define PG_REGISTER_WITH_RESET_TEMPLATE(_type, _name, _pgn, _version) \
147 extern const _type pgResetTemplate_ ## _name; \
148 PG_REGISTER_I(_type, _name, _pgn, _version, .reset = {.ptr = (void*)&pgResetTemplate_ ## _name}) \
149 /**/
151 // Register system config array
152 #define PG_REGISTER_ARRAY_I(_type, _length, _name, _pgn, _version, _reset) \
153 _type _name ## _SystemArray[_length]; \
154 _type _name ## _CopyArray[_length]; \
155 uint32_t _name ## _fnv_hash; \
156 extern const pgRegistry_t _name ##_Registry; \
157 const pgRegistry_t _name ## _Registry PG_REGISTER_ATTRIBUTES = { \
158 .pgn = _pgn | (_version << 12), \
159 .length = _length, \
160 .size = (sizeof(_type) * _length) | PGR_SIZE_SYSTEM_FLAG, \
161 .address = (uint8_t*)&_name ## _SystemArray, \
162 .fnv_hash = &_name ## _fnv_hash, \
163 .copy = (uint8_t*)&_name ## _CopyArray, \
164 .ptr = 0, \
165 _reset, \
167 /**/
169 #define PG_REGISTER_ARRAY(_type, _length, _name, _pgn, _version) \
170 PG_REGISTER_ARRAY_I(_type, _length, _name, _pgn, _version, .reset = {.ptr = 0}) \
171 /**/
173 #define PG_REGISTER_ARRAY_WITH_RESET_FN(_type, _length, _name, _pgn, _version) \
174 extern void pgResetFn_ ## _name(_type *); \
175 PG_REGISTER_ARRAY_I(_type, _length, _name, _pgn, _version, .reset = {.fn = (pgResetFunc*)&pgResetFn_ ## _name}) \
176 /**/
178 #if 0
179 // ARRAY reset mechanism is not implemented yet, only few places in code would benefit from it - See pgResetInstance
180 #define PG_REGISTER_ARRAY_WITH_RESET_TEMPLATE(_type, _length, _name, _pgn, _version) \
181 extern const _type pgResetTemplate_ ## _name; \
182 PG_REGISTER_ARRAY_I(_type, _length, _name, _pgn, _version, .reset = {.ptr = (void*)&pgResetTemplate_ ## _name}) \
183 /**/
184 #endif
186 #define PG_ARRAY_ELEMENT_OFFSET(type, index, member) (index * sizeof(type) + offsetof(type, member))
188 // Emit reset defaults for config.
189 // Config must be registered with PG_REGISTER_<xxx>_WITH_RESET_TEMPLATE macro
190 #define PG_RESET_TEMPLATE(_type, _name, ...) \
191 const _type pgResetTemplate_ ## _name PG_RESETDATA_ATTRIBUTES = { \
192 __VA_ARGS__ \
194 /**/
196 #define CONVERT_PARAMETER_TO_FLOAT(param) (0.001f * param)
197 #define CONVERT_PARAMETER_TO_PERCENT(param) (0.01f * param)
199 const pgRegistry_t* pgFind(pgn_t pgn);
201 bool pgLoad(const pgRegistry_t* reg, const void *from, int size, int version);
202 int pgStore(const pgRegistry_t* reg, void *to, int size);
203 void pgResetAll(void);
204 void pgResetInstance(const pgRegistry_t *reg, uint8_t *base);
205 bool pgResetCopy(void *copy, pgn_t pgn);
206 void pgReset(const pgRegistry_t* reg);