diff --git a/06-joystick/06-joystick.ino b/06-joystick/06-joystick.ino index fd57474..6aa5087 100644 --- a/06-joystick/06-joystick.ino +++ b/06-joystick/06-joystick.ino @@ -120,6 +120,8 @@ typedef struct Joystick { int errno; Button calibration_button; Joystick js; + +alignas(Freenove_ESP32_WS2812) uint8_t strip_storage[sizeof(Freenove_ESP32_WS2812)]; Freenove_ESP32_WS2812 *strip; /******************************************************************************/ @@ -131,7 +133,7 @@ void initSerial() int init2812(Freenove_ESP32_WS2812 **strip) { - Freenove_ESP32_WS2812 *obj = new Freenove_ESP32_WS2812(8, PIN_2812, 0, TYPE_GRB); + Freenove_ESP32_WS2812 *obj = new(strip_storage) Freenove_ESP32_WS2812(8, PIN_2812, 0, TYPE_GRB); if ( obj == NULL ) { ERROR(ERRNO_NULLPOINTER); } diff --git a/06-joystick/README.md b/06-joystick/README.md index 9bf4c6e..2acdfa9 100644 --- a/06-joystick/README.md +++ b/06-joystick/README.md @@ -8,22 +8,41 @@ * How to select pin assignments on the ESP32 without relying on the tutorial * How to calibrate joysticks -## Not trusting C++ +## I still don't trust C++ To be fair, I give C++ more hate than it deserves. But the way some people write it really does the language no favors. -The WS2812 tutorial(s) use a global variable with an initializer. +The WS2812 tutorial(s) use a global variable with an initializer that is called outside of the scope of any function. This is something that you can do in C++ that you really can't do in C, and I tend to think C is right where C++ is wrong. -I chose to use a heap allocation rather than use a global scope class initializer. Calling code outside of a function in a C-derived language just feels wrong to me. The objects live in the data segment, whcih is nice, but the compiler will generate some magic unspecified initializer function wherein it will call the constructors on the object, before it calls `main()`. But the order of those initializers is not guaranteed, so if A depends on B, you may be shit out of luck. And I especially don't trust global initializers that seem to be touching hardware. The whole thing just feels *wrong*. +```arduino +Freenove_ESP32_WS2812 strip = Freenove_ESP32_WS2812(8, PIN_2812, 0, TYPE_GRB); +``` + +In C the code wouldn't compile, because you can't execute code (beyond setting initializer values with builtin types) outside of a function. In C++, this is valid for constructors. The compiler puts the objects in the data segment, which is nice, as the alternative might be to call `new()` on it and get storage from the heap, which is nasty. But the compiler will generate some magic unspecified initializer function wherein it will call the constructors on the object, before it calls `main()`. And the order of those initializers is not guaranteed, so if A depends on B, you may be shit out of luck. And I especially don't trust global initializers that seem to be touching hardware. The whole thing just feels *wrong*.
