I thought structured programmes could take various forms. And how about the HOOD parts (as in ESA-HOOD) which require: OBject-named source files, a statement of child OBjects, clear English descriptions of their purpose(s) and relationships, function prototypes in plain sight and separated into required and provided operations, rather than out of sight in header files (and I suspect a preference for declaring/defining 'static' variables outside functions)? I can't read C code easily but don't think I see those explicit features which IMHO play such a major part in quickly yielding stable, clearly-related OBjects and stimulating specific and general insights.I'll let you on to a little secret. Everyone uses 'the OBject-based method' as you have described when they become familiar with the C language and intuitively develop a mental picture of the program that needs be created. It might not look that way at first because the functionality is prime but when you refactor for style points it naturally flows into structured methods.
I'm not fond of using the CPP #define for function macros because eventually it becomes an additional mini language hidden (X really means Y) feature instead of a C helper.
https://gcc.gnu.org/onlinedocs/cpp/Macro-Arguments.html
or using #define for simple computation (vs symbolic) 'magic numbers'.
Using the const keyword for fixed variables (there are times when #define must be used) adds C scope structure to programs and results in better compile time error checking with static range type-safety.
C:#ifndef MAGIC_H #define MAGIC_H #ifdef __cplusplus extern "C" { #endif static const double rps = 0.0174532925f; // degrees per second -> radians per second static const uint8_t CAL_DIS_MS = 1; // calibration data element screen display time static const char *build_date = __DATE__, *build_time = __TIME__; static const char imu_missing[] = " MISSING \r\n"; /* * NVRAM storage page variable * const volatile here means it's stored in FLASH for read-only program data access in normal program flow but * also set to volatile because the FLASH write controller can modify the contents out of normal program flow * so we need the compiler TO NOT optimize out reads from the actual memory locations because of read-only data caching * optimizations */ #include "nvram_page.h" const volatile uint32_t myflash[4096] __attribute__((section("myflash"), space(prog), address(NVM_STARTVADDRESS))); #ifdef __cplusplus } #endif #endif /* MAGIC_H */