├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── classical.c └── three_step.c /.gitignore: -------------------------------------------------------------------------------- 1 | classical 2 | three_step 3 | 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 David Antliff 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-ggdb 3 | 4 | all: classical three_step 5 | 6 | .PSEUDO: clean 7 | clean: 8 | rm -f classical three_step 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # esp32-components 2 | 3 | The top-level project for my ESP32 components. 4 | 5 | ## Design 6 | 7 | https://github.com/DavidAntliff/esp32-components/wiki/Component-Design 8 | 9 | ## Components 10 | 11 | ### General 12 | 13 | #### Utilities 14 | 15 | https://github.com/DavidAntliff/esp32-utils 16 | 17 | ### Interfaces 18 | 19 | #### 1-Wire Bus 20 | 21 | https://github.com/DavidAntliff/esp32-owb 22 | 23 | #### SMBus 24 | 25 | https://github.com/DavidAntliff/esp32-smbus 26 | 27 | ### Devices 28 | 29 | #### DS18B20 1-Wire Digital Thermometer 30 | 31 | https://github.com/DavidAntliff/esp32-ds18b20 32 | 33 | https://github.com/DavidAntliff/esp32-ds18b20-example 34 | 35 | #### TSL2561 Ambient Light Sensor 36 | 37 | https://github.com/DavidAntliff/esp32-tsl2561 38 | 39 | https://github.com/DavidAntliff/esp32-tsl2561-example 40 | 41 | #### HD44780-Compatible 16x2 Character LCD 42 | 43 | https://github.com/DavidAntliff/esp32-i2c-lcd1602 44 | 45 | https://github.com/DavidAntliff/esp32-i2c-lcd1602-example 46 | 47 | Also works with the "2004" version - four rows of twenty characters each. 48 | 49 | #### Incremental Rotary Encoders 50 | 51 | https://github.com/DavidAntliff/esp32-rotary-encoder 52 | 53 | https://github.com/DavidAntliff/esp32-rotary-encoder-example 54 | 55 | Reliable debouncing driver for generating position change events for incremental rotary encoders such as the EC11 and LPD series (e.g. LPD3806). 56 | 57 | ### Applications 58 | 59 | #### Digitally Controlled Oscillator 60 | 61 | Makes use of the RMT or LED PWM peripherals to accurately construct a clock signal of the specified frequency. Supports frequency ranges from < 1 Hz up to > 10 MHz. 62 | 63 | https://github.com/DavidAntliff/esp32-dco 64 | 65 | #### Frequency Counter 66 | 67 | Determine the average frequency of an incoming clock signal. Accuracy is determined by sampling duration. 68 | 69 | https://github.com/DavidAntliff/esp32-freqcount 70 | 71 | https://github.com/DavidAntliff/esp32-freqcount-example 72 | 73 | #### Christmas Lights 74 | 75 | Pretty SPI-controlled LED lights with numerous patterns and colour fades. Intended for use with APA102 or SK9822 LED strips. Remote control is provided over MQTT, and with a bit of configuration the lights can be controlled via TouchOSC on an iPhone or iPad. 76 | 77 | https://github.com/DavidAntliff/esp32-xmas 78 | 79 | #### Pool Control & Monitoring 80 | 81 | An application for the monitoring of a swimming pool solar heating system, consisting of an ESP32, five DS18B20 temperature sensors, a TSL2561 light sensor, a ATtiny84 I2C slave for switch logic and pump control, a 16x2 Character LCD, and MQTT communications to a Raspberry Pi running a TICK stack with Grafana for time series visualisation. 82 | 83 | https://github.com/DavidAntliff/esp32-poolmon 84 | 85 | #### I2C Communication with an AVR Slave 86 | 87 | #### AVR I2C 88 | 89 | An application to enable sending commands and receiving status from an AVR I2C slave device. This was a precursor to the code found in Pool Control & Monitoring above. 90 | 91 | https://github.com/DavidAntliff/esp32-avr-i2c 92 | -------------------------------------------------------------------------------- /classical.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 David Antliff 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | // An example of "classical" C allocation, initialisation and deallocation. 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | // A sub-component 32 | typedef struct 33 | { 34 | int x; 35 | } A; 36 | 37 | // Top-level component 38 | typedef struct 39 | { 40 | A a0; 41 | A * a1; 42 | } B; 43 | 44 | int main(int argc, char ** argv) 45 | { 46 | // static allocation of B 47 | A a1 = { 42 }; 48 | B b0 = { { 17 }, &a1 }; 49 | 50 | // dynamic allocation of B 51 | B * b1 = malloc(sizeof(*b1)); 52 | memset(b1, 0, sizeof(*b1)); 53 | b1->a0.x = 18; 54 | b1->a1 = malloc(sizeof(A)); 55 | b1->a1->x = 42; 56 | 57 | // mixed allocation of B 58 | B b2 = { { 19 }, malloc(sizeof(A)) }; 59 | memset(b2.a1, 0, sizeof(A)); 60 | b2.a1->x = 42; 61 | 62 | printf("b0: a0.x %d, a1->x %d\n", b0.a0.x, b0.a1->x); 63 | printf("b1: a0.x %d, a1->x %d\n", b1->a0.x, b1->a1->x); 64 | printf("b1: a0.x %d, a1->x %d\n", b2.a0.x, b2.a1->x); 65 | 66 | 67 | // no deallocation of statically allocated b0 68 | 69 | // deallocation of dynamically allocated b1 70 | free(b1->a1); 71 | free(b1); 72 | 73 | // dellocation of mixed allocation of B 74 | free(b2.a1); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /three_step.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * 4 | * Copyright (c) 2017 David Antliff 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | */ 24 | 25 | // An example of "three-step" C allocation, initialisation, configuration and deallocation. 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | 33 | // Sub-component use cases (B is main component, A is a sub-component): 34 | // 35 | 36 | #if 0 37 | { 38 | typedef struct 39 | { 40 | int x; 41 | } A; 42 | 43 | typedef struct 44 | { 45 | A a_inline; 46 | A * a_ptr; 47 | } B; 48 | #endif 49 | 50 | 51 | // - statically allocate B, such that A is automatically statically allocated 52 | // - Therefore A must be stored as an inline struct as there is no functional support for this. 53 | // - `init` of B will call init of A. 54 | 55 | #if 0 56 | { 57 | B b; 58 | B_init(&b); // calls A_init(b->a_inline) 59 | B_free(&b); // does not deallocate b (static) 60 | } 61 | #endif 62 | 63 | 64 | // - statically allocate B, then A is provided externally (injected) as a statically or dynamically allocated sub-component 65 | // - Therefore A must be stored as a pointer, or copied into an inline struct, by `init` 66 | // - Where is A initialised? Where is A configured? 67 | // - A would be initialised externally, before being injected 68 | // - A could be configured before or after injection 69 | 70 | #if 0 71 | { 72 | // A is static: 73 | A a; 74 | A_init(&a); 75 | 76 | B b; 77 | B_init(&b, &a); // stores a, does not call A_init() 78 | 79 | B_free(&b); // does not deallocate b (static), does not deallocate a (externally managed) 80 | A_free(&a); // does not deallocate a (static) 81 | 82 | // A is dynamic: 83 | A * a = A_new(); 84 | A_init(a); 85 | 86 | B b; 87 | B_init(&b, &a); // stores a, does not call A_init() 88 | 89 | B_free(&b); // does not deallocate b (static), does not deallocate a (externally managed) 90 | A_free(&a); // deallocates a (dynamic) 91 | } 92 | #endif 93 | 94 | 95 | // - dynamically allocate B, such that A is automatically allocated at the same time 96 | // - A must be dynamically allocated, either separately (stored as pointer) or as part of B (inline) 97 | 98 | #if 0 99 | { 100 | B * b = B_new(); // a is allocated too? But what if it's to be injected? How to know? 101 | B_init(b); // Maybe a is allocated & init'd here instead? 102 | 103 | B_free(&b); // deallocates a, then deallocates b 104 | } 105 | 106 | // - dynamically allocate B, then A is provided externally (injected) as a statically or dynamically allocated sub-component 107 | // - A must be stored as a pointer, or copied into an inline struct, by `init` 108 | // - Where is A initialised? Where is A configured? 109 | // - A would be initialised externally, before being injected 110 | // - A could be configured before or after injection 111 | 112 | #if 0 113 | { 114 | // A is static: 115 | A a; 116 | A_init(&a); 117 | 118 | B * b = B_new(); 119 | B_init_with_a(b, &a); // stores a, does not call A_init() 120 | 121 | B_free(&b); // deallocate b (dynamic), does not deallocate a (externally managed) 122 | A_free(&a); // does not deallocate a (static) 123 | 124 | // A is dynamic: 125 | A * a = A_new(); 126 | A_init(a); 127 | 128 | B * b = B_new(); 129 | B_init_with_a(b, a); // stores a, does not call A_init() 130 | 131 | B_free(&b); // deallocate b (dynamic), does not deallocate a (externally managed) 132 | A_free(&a); // deallocates a (dynamic) 133 | } 134 | #endif 135 | 136 | 137 | 138 | // 139 | // Sub-components may be: 140 | // 141 | // - Private: once allocated (or injected), they are hidden by the API 142 | // - Public: once allocated (or injected), they are directly accessible 143 | 144 | 145 | /* 146 | * Component A Interface 147 | */ 148 | 149 | // Component structure 150 | typedef struct 151 | { 152 | bool init; 153 | int x; 154 | float y; 155 | } A; 156 | 157 | // Dynamica Allocator 158 | A * A_malloc(void); 159 | 160 | // Initialisation 161 | void A_init(A * a); 162 | 163 | // Alternative Initialisation 164 | void A_init_with_x(A * a, int x); 165 | 166 | // Configuration 167 | void A_set_x(A * a, int x); 168 | void A_set_y(A * a, float y); 169 | void A_set_x_y(A * a, int x, float y); 170 | 171 | // Destruction 172 | void A_free(A ** a); 173 | 174 | 175 | /* 176 | * Component B Interface 177 | */ 178 | 179 | // Component structure 180 | typedef struct 181 | { 182 | bool init; 183 | A a0; // inline (private) 184 | A * a1; // dynamic (private) 185 | A * a2; // dynamic (public) 186 | } B; 187 | 188 | // Dynamic Allocator 189 | B * B_malloc(void); 190 | 191 | // Initialisation 192 | void B_init(B * b); 193 | 194 | // Configuration 195 | void B_set_a0_x(B * b, int x); 196 | void B_set_a1_x(B * b, int x); 197 | 198 | // Destruction 199 | void B_free(B ** b); 200 | 201 | 202 | /* 203 | * Example 204 | */ 205 | 206 | int main(int argc, char ** argv) 207 | { 208 | // static allocation 209 | A a1_static; 210 | A * a1 = &a1_static; 211 | 212 | B b0_static; 213 | B * b0 = &b0_static; // use a pointer for consistency 214 | B_init(b0); 215 | B_set_a0_x(b0, 17); 216 | B_set_a1_x(b0, 42); 217 | printf("b0: a0.x %d, a1->x %d\n", b0->a0.x, b0->a1->x); 218 | // B_free(&b0); 219 | 220 | // dynamic allocation 221 | B * b1 = B_malloc(); 222 | B_init(b1); 223 | B_set_a0_x(b1, 18); 224 | B_set_a1_x(b1, 42); 225 | printf("b1: a0.x %d, a1->x %d\n", b1->a0.x, b1->a1->x); 226 | B_free(&b1); 227 | } 228 | 229 | 230 | 231 | 232 | 233 | /* 234 | * Implementation 235 | */ 236 | 237 | 238 | A * A_malloc(void) 239 | { 240 | A * a = malloc(sizeof(*a)); 241 | if (a != NULL) 242 | { 243 | memset(a, 0, sizeof(*a)); 244 | } 245 | 246 | return a; 247 | } 248 | 249 | void A_init(A * a) 250 | { 251 | if (a != NULL) 252 | { 253 | a->x = 0; 254 | a->y = 1.0; // non-zero default 255 | a->init = true; 256 | } 257 | } 258 | 259 | void A_init_with_x(A * a, int x) 260 | { 261 | if (a != NULL) 262 | { 263 | a->x = x; 264 | a->y = 1.0; 265 | a->init = true; 266 | } 267 | } 268 | 269 | void A_set_x(A * a, int x) 270 | { 271 | if (a != NULL && a->init) 272 | { 273 | a->x = x; 274 | } 275 | } 276 | 277 | void A_set_y(A * a, float y) 278 | { 279 | if (a != NULL && a->init) 280 | { 281 | a->y = y; 282 | } 283 | } 284 | 285 | void A_set_x_y(A * a, int x, float y) 286 | { 287 | if (a != NULL && a->init) 288 | { 289 | a->x = x; 290 | a->y = y; 291 | } 292 | } 293 | 294 | void A_free(A ** a) 295 | { 296 | if (a != NULL && (*a != NULL)) 297 | { 298 | free(*a); 299 | *a = NULL; 300 | } 301 | } 302 | 303 | 304 | 305 | B * B_malloc(void) 306 | { 307 | B * b = malloc(sizeof(*b)); 308 | if (b != NULL) 309 | { 310 | memset(b, 0, sizeof(*b)); 311 | b->a1 = A_malloc(); 312 | } 313 | 314 | return b; 315 | } 316 | 317 | void B_init(B * b) 318 | { 319 | if (b != NULL) 320 | { 321 | A_init(&b->a0); // initialise first sub-component 322 | A_init(b->a1); // initialise second sub-component 323 | b->init = true; 324 | } 325 | } 326 | 327 | void B_set_a0_x(B * b, int x) 328 | { 329 | if (b != NULL && b->init) 330 | { 331 | A_set_x(&b->a0, x); 332 | } 333 | } 334 | 335 | void B_set_a1_x(B * b, int x) 336 | { 337 | if (b != NULL && b->init) 338 | { 339 | A_set_x(b->a1, x); 340 | } 341 | } 342 | 343 | void B_free(B ** b) 344 | { 345 | if (b != NULL && (*b != NULL)) 346 | { 347 | A_free(&(*b)->a1); 348 | free(*b); 349 | *b = NULL; 350 | } 351 | } 352 | 353 | 354 | --------------------------------------------------------------------------------