### Data Stream: Initialize and Feed Float Buffer Source: https://context7.com/hardwario/twr-sdk/llms.txt This example demonstrates initializing a circular buffer for float data and feeding it with simulated readings. It requires at least 5 samples before statistics become valid. ```c #include #include // Declare a float buffer for 32 samples (uses stack/global storage) TWR_DATA_STREAM_FLOAT_BUFFER(temperature_stream_buf, 32) twr_data_stream_t temperature_stream; void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); // Require at least 5 samples before statistics are valid twr_data_stream_init(&temperature_stream, 5, &temperature_stream_buf); // Feed simulated readings float samples[] = {22.1f, 22.5f, 21.9f, 22.3f, 22.8f, 23.0f}; for (size_t i = 0; i < sizeof(samples)/sizeof(*samples); i++) twr_data_stream_feed(&temperature_stream, &samples[i]); float avg, med, mn, mx; if (twr_data_stream_get_average(&temperature_stream, &avg)) twr_log_debug("Average: %.2f", avg); // 22.43 if (twr_data_stream_get_median(&temperature_stream, &med)) twr_log_debug("Median: %.2f", med); // 22.40 if (twr_data_stream_get_min(&temperature_stream, &mn)) twr_log_debug("Min: %.2f", mn); // 21.90 if (twr_data_stream_get_max(&temperature_stream, &mx)) twr_log_debug("Max: %.2f", mx); // 23.00 twr_log_debug("Samples collected: %d", twr_data_stream_get_length(&temperature_stream)); } ``` -------------------------------- ### Graphics: Draw UI Elements on LCD Source: https://context7.com/hardwario/twr-sdk/llms.txt This example demonstrates using the `twr_gfx` library to draw various UI elements on the HARDWARIO LCD Module, including filled rectangles, strings with different fonts, lines, and circles. ```c #include // includes twr_module_lcd.h, twr_gfx.h twr_gfx_t *gfx; twr_button_t button; int counter = 0; void button_event_handler(twr_button_t *self, twr_button_event_t event, void *param) { (void) self; (void) param; if (event != TWR_BUTTON_EVENT_PRESS) return; counter++; twr_gfx_clear(gfx); // Header bar twr_gfx_draw_fill_rectangle(gfx, 0, 0, 128, 14, true); twr_gfx_set_font(gfx, &twr_font_ubuntu_11); twr_gfx_draw_string(gfx, 2, 1, "HARDWARIO Demo", false); // inverse text // Body text twr_gfx_set_font(gfx, &twr_font_ubuntu_15); twr_gfx_printf(gfx, 5, 20, true, "Count: %d", counter); // Decorative elements twr_gfx_draw_line(gfx, 0, 16, 128, 16, true); twr_gfx_draw_circle(gfx, 100, 45, 12, true); twr_gfx_draw_fill_circle(gfx, 100, 45, 8, true); twr_gfx_update(gfx); // flush framebuffer to display } void application_init(void) { twr_module_lcd_init(); gfx = twr_module_lcd_get_gfx(); twr_button_init(&button, TWR_GPIO_BUTTON, TWR_GPIO_PULL_DOWN, false); twr_button_set_event_handler(&button, button_event_handler, NULL); } ``` -------------------------------- ### Initialize and Use EEPROM Driver Source: https://context7.com/hardwario/twr-sdk/llms.txt Provides an interface to the internal EEPROM (data flash). Supports synchronous and asynchronous writes, synchronous reads, and size queries. Address space starts at 0. Ensure no other operations conflict with EEPROM access during asynchronous writes. ```c #include #include void eeprom_write_done(twr_eepromc_event_t event, void *param) { (void) param; if (event == TWR_EEPROM_EVENT_ASYNC_WRITE_DONE) twr_log_info("Async EEPROM write complete"); else twr_log_error("Async EEPROM write failed"); } void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); twr_log_debug("EEPROM size: %d bytes", twr_eeprom_get_size()); // Write float + string to address 0 float pi = 3.14159f; const char msg[] = "hello world!"; twr_eeprom_write(0, &pi, sizeof(pi)); twr_eeprom_write(sizeof(pi), msg, sizeof(msg)); // Read back float read_pi; char read_msg[13]; twr_eeprom_read(0, &read_pi, sizeof(read_pi)); twr_eeprom_read(sizeof(pi), read_msg, 12); read_msg[12] = '\0'; twr_log_debug("pi=%.5f msg=%s", read_pi, read_msg); // Output: [0.050] pi=3.14159 msg=hello world! // Async write (non-blocking) static uint32_t counter = 42; twr_eeprom_async_write(20, &counter, sizeof(counter), eeprom_write_done, NULL); } ``` -------------------------------- ### Radio Node: Publish Button Clicks Source: https://context7.com/hardwario/twr-sdk/llms.txt Node firmware uses `twr_radio_pub_*` helpers to publish typed sensor readings. This example shows how a sleeping, battery-powered sensor node publishes button click counts over the radio. ```c #include twr_led_t led; twr_button_t button; uint16_t click_count = 0; void button_event_handler(twr_button_t *self, twr_button_event_t event, void *param) { (void) self; (void) param; if (event == TWR_BUTTON_EVENT_CLICK) { click_count++; // Publish button event count over radio twr_radio_pub_push_button(&click_count); twr_led_pulse(&led, 100); } } void radio_event_handler(twr_radio_event_t event, void *param) { (void) param; if (event == TWR_RADIO_EVENT_PAIRED) twr_led_blink(&led, 3); else if (event == TWR_RADIO_EVENT_TX_ERROR) twr_led_set_mode(&led, TWR_LED_MODE_BLINK_FAST); } void application_init(void) { twr_led_init(&led, TWR_GPIO_LED, false, false); twr_button_init(&button, TWR_GPIO_BUTTON, TWR_GPIO_PULL_DOWN, false); twr_button_set_event_handler(&button, button_event_handler, NULL); twr_radio_init(TWR_RADIO_MODE_NODE_SLEEPING); twr_radio_set_event_handler(radio_event_handler, NULL); // Request pairing with gateway twr_radio_pairing_request("button-node", "1.0.0"); } ``` -------------------------------- ### Radio Gateway: Decode Button Clicks and Publish Custom Data Source: https://context7.com/hardwario/twr-sdk/llms.txt In gateway firmware, override weak `twr_radio_on_*` symbols to receive and decode messages. This example shows how to log button clicks and publish temperature and custom data. ```c // In gateway firmware, override the weak twr_radio_on_push_button symbol: void twr_radio_on_push_button(uint64_t *peer_id, uint16_t *event_count) { twr_log_info("Node %llx button click #%u", *peer_id, *event_count); // Publish temperature and custom topic float temp = 22.5f; twr_radio_pub_temperature(TWR_RADIO_PUB_CHANNEL_R1_I2C0_ADDRESS_DEFAULT, &temp); twr_radio_pub_float("custom/sensor/value", &temp); } ``` -------------------------------- ### Generate Binary Output Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Includes a utility script to generate the final firmware binary file. ```cmake # Generate the final "firmware.bin" in "out" directory and root directory include(${TOOLCHAIN_DIR}/utils.cmake) generate_object(${CMAKE_PROJECT_NAME} .bin binary) ``` -------------------------------- ### Initialize and Handle Button Events Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes a button with specified GPIO, pull-up configuration, and idle state. Sets up an event handler for button events like click and hold, with configurable debounce, click timeout, and hold times. ```c #include #include twr_button_t button; void button_event_handler(twr_button_t *self, twr_button_event_t event, void *param) { (void) self; (void) param; if (event == TWR_BUTTON_EVENT_CLICK) { twr_log_info("Button clicked"); } else if (event == TWR_BUTTON_EVENT_HOLD) { twr_log_warning("Button held for 3 s"); } } void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); // Active LOW button with internal pull-up, idle state = 1 twr_button_init(&button, TWR_GPIO_BUTTON, TWR_GPIO_PULL_UP, 1); twr_button_set_event_handler(&button, button_event_handler, NULL); // Optional: tune timing (all in ms / ticks) twr_button_set_debounce_time(&button, 20); // 20 ms debounce twr_button_set_click_timeout(&button, 500); // click if released < 500 ms twr_button_set_hold_time(&button, 3000); // hold after 3 s twr_button_set_scan_interval(&button, 10); // poll every 10 ms } ``` -------------------------------- ### GPIO Pin Configuration and Control Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes GPIO pins for input or output, sets pull-up/pull-down resistors, and controls output states. Useful for direct hardware interaction. ```c #include void application_init(void) { // Drive P6 as digital output, push-pull twr_gpio_init(TWR_GPIO_P6); twr_gpio_set_mode(TWR_GPIO_P6, TWR_GPIO_MODE_OUTPUT); twr_gpio_set_output(TWR_GPIO_P6, 1); // set HIGH // Read P7 as digital input with pull-up twr_gpio_init(TWR_GPIO_P7); twr_gpio_set_pull(TWR_GPIO_P7, TWR_GPIO_PULL_UP); twr_gpio_set_mode(TWR_GPIO_P7, TWR_GPIO_MODE_INPUT); int state = twr_gpio_get_input(TWR_GPIO_P7); // 1 = HIGH, 0 = LOW // Toggle output on each call twr_gpio_toggle_output(TWR_GPIO_P6); } ``` -------------------------------- ### Initialize and Use ADC Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes the ADC module and configures specific channels for measurement. Supports asynchronous measurements with callbacks and synchronous (blocking) reads, as well as reading the VDDA supply voltage. ```c #include #include void adc_event_handler(twr_adc_channel_t channel, twr_adc_event_t event, void *param) { (void) param; if (event == TWR_ADC_EVENT_DONE) { float voltage; if (twr_adc_async_get_voltage(channel, &voltage)) { twr_log_info("A0 = %.3f V", voltage); } } } void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); twr_adc_init(); // Configure channel: 12-bit, 16× oversampling twr_adc_resolution_set(TWR_ADC_CHANNEL_A0, TWR_ADC_RESOLUTION_12_BIT); twr_adc_oversampling_set(TWR_ADC_CHANNEL_A0, TWR_ADC_OVERSAMPLING_16); // Async mode: register callback, then trigger twr_adc_set_event_handler(TWR_ADC_CHANNEL_A0, adc_event_handler, NULL); twr_adc_async_measure(TWR_ADC_CHANNEL_A0); // Synchronous read (blocking) uint16_t raw; if (twr_adc_get_value(TWR_ADC_CHANNEL_A1, &raw)) { twr_log_debug("A1 raw = %u", raw); // 0–4095 for 12-bit } // Supply voltage float vdda; twr_adc_get_vdda_voltage(&vdda); twr_log_info("VDDA = %.3f V", vdda); } ``` -------------------------------- ### Set Helper Variables Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Defines output and toolchain directories for the build process. ```cmake set(OUT_DIR out) set(TOOLCHAIN_DIR toolchain) ``` -------------------------------- ### Configure Executable and Output Directory Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Sets the file extension for executables and the runtime output directory. ```cmake set(CMAKE_EXECUTABLE_SUFFIX ".elf") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/${OUT_DIR}/${TYPE}/) ``` -------------------------------- ### Initialize and Handle Climate Module Events Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes the climate module and sets up a callback for sensor updates and errors. Configures all sensors to update every 2.5 seconds. Requires twr_module_climate.h and twr_usb_cdc.h. ```c #include // includes twr_module_climate.h, twr_usb_cdc.h void climate_event_handler(twr_module_climate_event_t event, void *param) { (void) param; // All sensors share one callback; guard on event type if (event == TWR_MODULE_CLIMATE_EVENT_UPDATE_BAROMETER) { float temp_c, humidity, lux, pressure_pa; twr_module_climate_get_temperature_celsius(&temp_c); twr_module_climate_get_humidity_percentage(&humidity); twr_module_climate_get_illuminance_lux(&lux); twr_module_climate_get_pressure_pascal(&pressure_pa); // Derived values float temp_f, altitude_m; twr_module_climate_get_temperature_fahrenheit(&temp_f); twr_module_climate_get_altitude_meter(&altitude_m); char buf[128]; snprintf(buf, sizeof(buf), "T=%.2f°C (%.2f°F) H=%.1f%% L=%.0flux P=%.0fPa Alt=%.1fm\r\n", temp_c, temp_f, humidity, lux, pressure_pa, altitude_m); twr_usb_cdc_write(buf, strlen(buf)); } else if (event == TWR_MODULE_CLIMATE_EVENT_ERROR_THERMOMETER) { // handle sensor error } } void application_init(void) { twr_usb_cdc_init(); twr_module_climate_init(); twr_module_climate_set_event_handler(climate_event_handler, NULL); // Measure all sensors every 2.5 s; can set per-sensor intervals too twr_module_climate_set_update_interval_all_sensors(2500); } ``` -------------------------------- ### Initialize and Handle Battery Module Events Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes the battery module and sets up a callback for battery status updates and low/critical level events. Configures measurements every 60 seconds and sets voltage thresholds for low (3.5V) and critical (3.1V) levels. Requires twr_module_battery.h and twr_log.h. ```c #include #include void battery_event_handler(twr_module_battery_event_t event, void *param) { (void) param; float voltage; int charge; twr_module_battery_get_voltage(&voltage); twr_module_battery_get_charge_level(&charge); if (event == TWR_MODULE_BATTERY_EVENT_UPDATE) { twr_log_info("Battery: %.3f V %d%%", voltage, charge); } else if (event == TWR_MODULE_BATTERY_EVENT_LEVEL_LOW) { twr_log_warning("Battery LOW: %.3f V", voltage); } else if (event == TWR_MODULE_BATTERY_EVENT_LEVEL_CRITICAL) { twr_log_error("Battery CRITICAL: %.3f V", voltage); } } void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); twr_module_battery_init(); twr_module_battery_set_event_handler(battery_event_handler, NULL); twr_module_battery_set_update_interval(60000); // measure every 60 s twr_module_battery_set_threshold_levels(3.5f, 3.1f); // low / critical V if (twr_module_battery_is_present()) twr_log_info("Battery format: %d", twr_module_battery_get_format()); } ``` -------------------------------- ### Configure Linker Options Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Sets various linker options, including the memory map file, CPU architecture, endianness, and library linking. ```cmake target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -T${CMAKE_CURRENT_SOURCE_DIR}/sys/lkr/stm32l083cz.ld) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -Wl,-Map=${CMAKE_SOURCE_DIR}/${OUT_DIR}/${TYPE}/${CMAKE_PROJECT_NAME}.map) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -mcpu=cortex-m0plus) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -mthumb) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -mlittle-endian) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -Wl,-lm) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -Wl,-lc) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -static) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -Wl,--gc-sections) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -Wl,--print-memory-usage) target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -Wl,-u,__errno) ``` ```cmake # Disable LOAD segment with RWX permissions warning target_link_options(${CMAKE_PROJECT_NAME} PUBLIC -Wl,--no-warn-rwx-segments) ``` -------------------------------- ### Initialize and Use SPI Master Driver Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes the SPI master driver with a specified speed and mode. Demonstrates both synchronous and asynchronous data transfers. Ensure the SPI peripheral is not used by other modules before initialization. ```c #include #include void spi_done(twr_spi_event_t event, void *param) { (void) param; if (event == TWR_SPI_EVENT_DONE) twr_log_info("Async SPI transfer complete"); } void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); // Mode 0, 4 MHz twr_spi_init(TWR_SPI_SPEED_4_MHZ, TWR_SPI_MODE_0); // Synchronous full-duplex transfer uint8_t tx[] = {0x9F, 0x00, 0x00, 0x00}; // read JEDEC ID uint8_t rx[4] = {0}; if (twr_spi_transfer(tx, rx, sizeof(tx))) { twr_log_debug("JEDEC: %02X %02X %02X", rx[1], rx[2], rx[3]); } // Async transfer (non-blocking, callback fires on completion) static uint8_t tx2[] = {0x05}; // READ STATUS static uint8_t rx2[2]; twr_spi_async_transfer(tx2, rx2, sizeof(tx2), spi_done, NULL); } ``` -------------------------------- ### LED Driver Modes and Patterns Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes and controls LEDs using various modes including steady on/off, blinking, custom patterns, and timed pulses. Supports integration with the scheduler. ```c #include twr_led_t led; void application_init(void) { // Init on-board LED (active HIGH, push-pull, idle LOW) twr_led_init(&led, TWR_GPIO_LED, false, false); // Blink at standard rate (toggle every 500 ms) twr_led_set_mode(&led, TWR_LED_MODE_BLINK); // Custom pattern: 0b10110000... — 32 slots, each slot = default 100 ms twr_led_set_slot_interval(&led, 100); twr_led_set_pattern(&led, 0xF0F0F0F0); // One-shot timed pulse for 1500 ms, then reverts twr_led_pulse(&led, 1500); // Blink exactly 3 times then stop twr_led_blink(&led, 3); // Steady on twr_led_set_mode(&led, TWR_LED_MODE_ON); } ``` -------------------------------- ### Initialize and Use UART Driver Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes a UART channel with specified baud rate and settings. Configures FIFO buffers for asynchronous operation and demonstrates both blocking and asynchronous data transfers. UART2 is the default logging port. ```c #include #include static uint8_t tx_buf[64]; static uint8_t rx_buf[64]; static twr_fifo_t tx_fifo; static twr_fifo_t rx_fifo; void uart_event_handler(twr_uart_channel_t ch, twr_uart_event_t event, void *param) { (void) param; if (event == TWR_UART_EVENT_ASYNC_READ_DATA) { uint8_t data[32]; size_t n = twr_uart_async_read(ch, data, sizeof(data)); // echo back twr_uart_async_write(ch, data, n); } } void application_init(void) { // UART1 at 115200 8N1 twr_uart_init(TWR_UART_UART1, TWR_UART_BAUDRATE_115200, TWR_UART_SETTING_8N1); // Set up FIFO buffers for async operation twr_fifo_init(&tx_fifo, tx_buf, sizeof(tx_buf)); twr_fifo_init(&rx_fifo, rx_buf, sizeof(rx_buf)); twr_uart_set_async_fifo(TWR_UART_UART1, &tx_fifo, &rx_fifo); twr_uart_set_event_handler(TWR_UART_UART1, uart_event_handler, NULL); twr_uart_async_read_start(TWR_UART_UART1, 500); // 500 ms read timeout // Blocking write const char *hello = "Hello UART\r\n"; twr_uart_write(TWR_UART_UART1, hello, strlen(hello)); } ``` -------------------------------- ### Initialize and Use Serial Logging Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes the serial logging facility to output to UART2 with specified severity level and timestamp format. Provides macros for logging messages at different levels and for dumping buffer contents. ```c #include void application_init(void) { // Initialize logging at DEBUG level, absolute timestamps twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); twr_log_debug("Application started, free RAM: %d bytes", 6144); twr_log_info("Firmware version 1.2.3"); twr_log_warning("Battery low: %.2f V", 3.1f); twr_log_error("Sensor read failed on I2C0"); // Hex dump of a buffer uint8_t buf[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02}; twr_log_dump(buf, sizeof(buf), "Raw SPI response (%d bytes):", sizeof(buf)); // Output: [0.125] Raw SPI response (6 bytes): // DE AD BE EF 01 02 } ``` -------------------------------- ### Link Libraries and Directories Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Specifies the static C library to link and the directory where libraries can be found. ```cmake target_link_libraries(${CMAKE_PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/lib/picolibc/lib/libc.a) target_link_directories(${CMAKE_PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/lib/picolibc/lib) ``` -------------------------------- ### Configure Release Build Options Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Adds release-specific compiler flags and defines the 'RELEASE' macro when the build type is 'release'. ```cmake if(TYPE MATCHES "release") target_compile_options(${CMAKE_PROJECT_NAME} PUBLIC -Os) target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC RELEASE) ENDIF() ``` -------------------------------- ### Create Executable Target Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Defines the main executable target for the project. ```cmake add_executable(${CMAKE_PROJECT_NAME}) ``` -------------------------------- ### Scheduler Task Management with twr_scheduler Source: https://context7.com/hardwario/twr-sdk/llms.txt Demonstrates registering tasks with the cooperative scheduler, planning their execution relative to current time or absolutely, and managing task IDs. Tasks are designed to put the MCU to sleep between activations. ```c #include twr_led_t led; twr_scheduler_task_id_t id_turn_on; twr_scheduler_task_id_t id_turn_off; void task_turn_on(void *param) { twr_led_t *p = (twr_led_t *)param; twr_led_set_mode(p, TWR_LED_MODE_ON); // Schedule turn-off 500 ms from now (relative to current spin) twr_scheduler_plan_relative(id_turn_off, 500); } void task_turn_off(void *param) { twr_led_t *p = (twr_led_t *)param; twr_led_set_mode(p, TWR_LED_MODE_OFF); } void application_init(void) { twr_led_init(&led, TWR_GPIO_LED, false, false); // TWR_TICK_INFINITY = do not auto-run; fire only on demand id_turn_on = twr_scheduler_register(task_turn_on, &led, TWR_TICK_INFINITY); id_turn_off = twr_scheduler_register(task_turn_off, &led, TWR_TICK_INFINITY); } // application_task() is the default task, called automatically void application_task(void) { twr_scheduler_plan_now(id_turn_on); // fire turn-on immediately twr_scheduler_plan_current_relative(1000); // re-run this task in 1 s } ``` -------------------------------- ### Define Compile-Time Macros from Environment Variables Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Conditionally defines preprocessor macros based on environment variables for firmware version, Git version, and build date. ```cmake if(DEFINED ENV{FW_VERSION}) target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC FW_VERSION="$ENV{FW_VERSION}") endif() if(DEFINED ENV{GIT_VERSION}) target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC GIT_VERSION="$ENV{GIT_VERSION}") endif() string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S" UTC) target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC BUILD_DATE="${BUILD_DATE}") ``` ```cmake IF(DEFINED ENV{BAND}) target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC BAND=$ENV{BAND}) ELSE() target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC BAND=868) ENDIF() ``` -------------------------------- ### EEPROM Driver Source: https://context7.com/hardwario/twr-sdk/llms.txt Provides an interface to the internal EEPROM (data flash) for reading and writing data, supporting both synchronous and asynchronous operations. ```APIDOC ## EEPROM — `twr_eeprom` Simple interface to the STM32L083's internal EEPROM (data flash). Supports synchronous write-with-verify, asynchronous write, synchronous read, and size query. Address space starts at 0. ### Get Size Queries the total size of the EEPROM. ```c twr_eeprom_get_size(); ``` ### Synchronous Write Writes data to a specified address in the EEPROM. ```c // Write float + string to address 0 float pi = 3.14159f; const char msg[] = "hello world!"; twr_eeprom_write(0, &pi, sizeof(pi)); twr_eeprom_write(sizeof(pi), msg, sizeof(msg)); ``` ### Synchronous Read Reads data from a specified address in the EEPROM. ```c // Read back float read_pi; char read_msg[13]; twr_eeprom_read(0, &read_pi, sizeof(read_pi)); twr_eeprom_read(sizeof(pi), read_msg, 12); read_msg[12] = '\0'; ``` ### Asynchronous Write Initiates an asynchronous write operation. A callback function is invoked upon completion. ```c void eeprom_write_done(twr_eepromc_event_t event, void *param) { if (event == TWR_EEPROM_EVENT_ASYNC_WRITE_DONE) // Write successful else // Write failed } // Async write (non-blocking) static uint32_t counter = 42; twr_eeprom_async_write(20, &counter, sizeof(counter), eeprom_write_done, NULL); ``` ``` -------------------------------- ### Include Subdirectories Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Includes other CMake subdirectories for modular build components. ```cmake # All other directories with source files # You need to update the specific CMakeLists files in the respective directories if you want to update the SDK add_subdirectory(twr) add_subdirectory(bcl) add_subdirectory(stm) add_subdirectory(sys) add_subdirectory(lib) ``` -------------------------------- ### Button Driver - twr_button Source: https://context7.com/hardwario/twr-sdk/llms.txt Event-driven button driver with built-in debouncing. Fires callbacks for PRESS, RELEASE, CLICK, and HOLD events. Timing parameters are configurable. ```APIDOC ## Button Driver - `twr_button` ### Description Event-driven button driver with built-in debouncing. Fires callbacks for PRESS, RELEASE, CLICK (press + release within timeout), and HOLD (sustained press). All timing parameters are configurable. Supports both physical GPIO and virtual buttons via a driver interface. ### Initialization and Event Handling ```c #include #include twr_button_t button; void button_event_handler(twr_button_t *self, twr_button_event_t event, void *param) { (void) self; (void) param; if (event == TWR_BUTTON_EVENT_CLICK) { twr_log_info("Button clicked"); } else if (event == TWR_BUTTON_EVENT_HOLD) { twr_log_warning("Button held for 3 s"); } } void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); // Active LOW button with internal pull-up, idle state = 1 twr_button_init(&button, TWR_GPIO_BUTTON, TWR_GPIO_PULL_UP, 1); twr_button_set_event_handler(&button, button_event_handler, NULL); // Optional: tune timing (all in ms / ticks) twr_button_set_debounce_time(&button, 20); // 20 ms debounce twr_button_set_click_timeout(&button, 500); // click if released < 500 ms twr_button_set_hold_time(&button, 3000); // hold after 3 s twr_button_set_scan_interval(&button, 10); // poll every 10 ms } ``` ``` -------------------------------- ### Logging Driver - twr_log Source: https://context7.com/hardwario/twr-sdk/llms.txt Serial logging facility that outputs to UART2. Supports five severity levels with optional timestamps. Log macros compile to nothing when building with -DRELEASE. ```APIDOC ## Logging Driver - `twr_log` ### Description Serial logging facility that outputs to UART2 (TXD2) at 115200/8N1. Five severity levels (DUMP, DEBUG, INFO, WARNING, ERROR) with optional absolute or relative timestamps. All log macros compile to nothing when building with `-DRELEASE`. ### Usage ```c #include void application_init(void) { // Initialize logging at DEBUG level, absolute timestamps twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); twr_log_debug("Application started, free RAM: %d bytes", 6144); twr_log_info("Firmware version 1.2.3"); twr_log_warning("Battery low: %.2f V", 3.1f); twr_log_error("Sensor read failed on I2C0"); // Hex dump of a buffer uint8_t buf[] = {0xDE, 0xAD, 0xBE, 0xEF, 0x01, 0x02}; twr_log_dump(buf, sizeof(buf), "Raw SPI response (%d bytes):", sizeof(buf)); // Output: [0.125] Raw SPI response (6 bytes): // DE AD BE EF 01 02 } ``` ``` -------------------------------- ### Initialize and Use I2C Communication Source: https://context7.com/hardwario/twr-sdk/llms.txt Initializes an I2C interface with a specified speed. Provides functions for memory-mapped read/write operations with 8-bit or 16-bit addresses, including single-byte transfers and bulk memory reads. ```c #include #include #define SENSOR_ADDR 0x40 // example: SHT30 at 0x40 void application_init(void) { twr_log_init(TWR_LOG_LEVEL_DEBUG, TWR_LOG_TIMESTAMP_ABS); twr_i2c_init(TWR_I2C_I2C0, TWR_I2C_SPEED_400_KHZ); // Write a command byte to a device register if (!twr_i2c_memory_write_8b(TWR_I2C_I2C0, SENSOR_ADDR, 0x22, 0x00)) { twr_log_error("I2C write failed"); } // Read 2-byte register uint16_t value; if (twr_i2c_memory_read_16b(TWR_I2C_I2C0, SENSOR_ADDR, 0x00, &value)) { twr_log_debug("Reg 0x00 = 0x%04X", value); } // Bulk memory read uint8_t rx[6]; twr_i2c_memory_transfer_t mt = { .device_address = SENSOR_ADDR, .memory_address = 0x00, .buffer = rx, .length = sizeof(rx) }; if (twr_i2c_memory_read(TWR_I2C_I2C0, &mt)) { twr_log_dump(rx, sizeof(rx), "Sensor data:"); } } ``` -------------------------------- ### Configure Debug Build Options Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Adds debug-specific compiler flags and defines the 'DEBUG' macro when the build type is 'debug'. ```cmake if(TYPE MATCHES "debug") target_compile_options(${CMAKE_PROJECT_NAME} PUBLIC -g3) target_compile_options(${CMAKE_PROJECT_NAME} PUBLIC -Og) target_compile_definitions(${CMAKE_PROJECT_NAME} PUBLIC DEBUG) ENDIF() ``` -------------------------------- ### SPI Driver Source: https://context7.com/hardwario/twr-sdk/llms.txt The SPI master driver supports various speeds, modes, and transfer types (synchronous and asynchronous). ```APIDOC ## SPI — `twr_spi` SPI master driver with speeds from 125 kHz to 16 MHz, all four CPOL/CPHA modes, optional manual CS control, and both synchronous and asynchronous (DMA-backed) transfers. ### Initialization ```c twr_spi_init(TWR_SPI_SPEED_4_MHZ, TWR_SPI_MODE_0); ``` ### Synchronous Transfer Performs a full-duplex synchronous SPI transfer. ```c // Synchronous full-duplex transfer uint8_t tx[] = {0x9F, 0x00, 0x00, 0x00}; // read JEDEC ID uint8_t rx[4] = {0}; if (twr_spi_transfer(tx, rx, sizeof(tx))) { // Process rx data } ``` ### Asynchronous Transfer Initiates an asynchronous SPI transfer. A callback function is invoked upon completion. ```c void spi_done(twr_spi_event_t event, void *param) { // Handle event } // Async transfer (non-blocking, callback fires on completion) static uint8_t tx2[] = {0x05}; // READ STATUS static uint8_t rx2[2]; twr_spi_async_transfer(tx2, rx2, sizeof(tx2), spi_done, NULL); ``` ``` -------------------------------- ### UART Driver Source: https://context7.com/hardwario/twr-sdk/llms.txt The UART driver supports multiple hardware channels with configurable baud rates, data settings, and transfer modes (blocking and asynchronous). ```APIDOC ## UART — `twr_uart` Driver for three hardware UART channels (UART0–UART2) supporting baud rates from 9600 to 921600 bps, configurable data/parity/stop settings, blocking read/write, and non-blocking async transfers backed by FIFO buffers. UART2 is the default logging port. ### Initialization Initializes a UART channel with specified baud rate and settings. ```c // UART1 at 115200 8N1 twr_uart_init(TWR_UART_UART1, TWR_UART_BAUDRATE_115200, TWR_UART_SETTING_8N1); ``` ### Asynchronous Operation Setup Configures FIFO buffers and an event handler for asynchronous transfers. ```c static uint8_t tx_buf[64]; static uint8_t rx_buf[64]; static twr_fifo_t tx_fifo; static twr_fifo_t rx_fifo; // Set up FIFO buffers for async operation twr_fifo_init(&tx_fifo, tx_buf, sizeof(tx_buf)); twr_fifo_init(&rx_fifo, rx_buf, sizeof(rx_buf)); twr_uart_set_async_fifo(TWR_UART_UART1, &tx_fifo, &rx_fifo); twr_uart_set_event_handler(TWR_UART_UART1, uart_event_handler, NULL); twr_uart_async_read_start(TWR_UART_UART1, 500); // 500 ms read timeout ``` ### Blocking Write Performs a blocking write operation to the UART. ```c const char *hello = "Hello UART\r\n"; twr_uart_write(TWR_UART_UART1, hello, strlen(hello)); ``` ### Asynchronous Read Handler Example Handles asynchronous read events, echoing received data back. ```c void uart_event_handler(twr_uart_channel_t ch, twr_uart_event_t event, void *param) { if (event == TWR_UART_EVENT_ASYNC_READ_DATA) { uint8_t data[32]; size_t n = twr_uart_async_read(ch, data, sizeof(data)); // echo back twr_uart_async_write(ch, data, n); } } ``` ``` -------------------------------- ### Climate Module - `twr_module_climate` Source: https://context7.com/hardwario/twr-sdk/llms.txt Driver for the HARDWARIO Climate Module. It supports temperature, humidity, lux, and barometer sensors. You can configure update intervals for each sensor type and receive typed events when measurements are ready. This driver internally composes SHT20/SHT30, OPT3001, and MPL3115A2 drivers over I2C0. ```APIDOC ## Climate Module — `twr_module_climate` All-in-one driver for the HARDWARIO Climate Module (temperature, humidity, lux, barometer). Configures update intervals per sensor type and fires typed events when measurements are ready. Internally composes the SHT20/SHT30, OPT3001, and MPL3115A2 drivers over I2C0. ### Initialization ```c #include void application_init(void) { twr_usb_cdc_init(); twr_module_climate_init(); twr_module_climate_set_event_handler(climate_event_handler, NULL); // Measure all sensors every 2.5 s; can set per-sensor intervals too twr_module_climate_set_update_interval_all_sensors(2500); } ``` ### Event Handler ```c void climate_event_handler(twr_module_climate_event_t event, void *param) { (void) param; // All sensors share one callback; guard on event type if (event == TWR_MODULE_CLIMATE_EVENT_UPDATE_BAROMETER) { float temp_c, humidity, lux, pressure_pa; twr_module_climate_get_temperature_celsius(&temp_c); twr_module_climate_get_humidity_percentage(&humidity); twr_module_climate_get_illuminance_lux(&lux); twr_module_climate_get_pressure_pascal(&pressure_pa); // Derived values float temp_f, altitude_m; twr_module_climate_get_temperature_fahrenheit(&temp_f); twr_module_climate_get_altitude_meter(&altitude_m); char buf[128]; snprintf(buf, sizeof(buf), "T=%.2f°C (%.2f°F) H=%.1f%% L=%.0flux P=%.0fPa Alt=%.1fm\r\n", temp_c, temp_f, humidity, lux, pressure_pa, altitude_m); twr_usb_cdc_write(buf, strlen(buf)); } else if (event == TWR_MODULE_CLIMATE_EVENT_ERROR_THERMOMETER) { // handle sensor error } } ``` ### Functions - `twr_module_climate_init()`: Initializes the climate module. - `twr_module_climate_set_event_handler(twr_module_climate_event_handler_t handler, void *param)`: Sets the event handler for the climate module. - `twr_module_climate_set_update_interval_all_sensors(uint16_t interval)`: Sets the update interval for all climate sensors. - `twr_module_climate_get_temperature_celsius(float *temperature)`: Gets the temperature in Celsius. - `twr_module_climate_get_temperature_fahrenheit(float *temperature)`: Gets the temperature in Fahrenheit. - `twr_module_climate_get_humidity_percentage(float *humidity)`: Gets the humidity percentage. - `twr_module_climate_get_illuminance_lux(float *illuminance)`: Gets the illuminance in lux. - `twr_module_climate_get_pressure_pascal(float *pressure)`: Gets the pressure in Pascals. - `twr_module_climate_get_altitude_meter(float *altitude)`: Gets the altitude in meters. ``` -------------------------------- ### LED - twr_led Source: https://context7.com/hardwario/twr-sdk/llms.txt High-level LED driver with built-in scheduler integration. Supports various modes including steady on/off, blinking, flashing, custom patterns, and timed pulses. ```APIDOC ## LED — `twr_led` High-level LED driver with built-in scheduler integration. Supports steady on/off, standard blink rates, fast/slow blink, flash mode, custom 32-bit bit-pattern sequences, and timed pulses. Works with physical GPIO channels or virtual (e.g. LCD backlight) channels via a driver interface. ```c #include twr_led_t led; void application_init(void) { // Init on-board LED (active HIGH, push-pull, idle LOW) twr_led_init(&led, TWR_GPIO_LED, false, false); // Blink at standard rate (toggle every 500 ms) twr_led_set_mode(&led, TWR_LED_MODE_BLINK); // Custom pattern: 0b10110000... — 32 slots, each slot = default 100 ms twr_led_set_slot_interval(&led, 100); twr_led_set_pattern(&led, 0xF0F0F0F0); // One-shot timed pulse for 1500 ms, then reverts twr_led_pulse(&led, 1500); // Blink exactly 3 times then stop twr_led_blink(&led, 3); // Steady on twr_led_set_mode(&led, TWR_LED_MODE_ON); } ``` ``` -------------------------------- ### GPIO - twr_gpio Source: https://context7.com/hardwario/twr-sdk/llms.txt Low-level driver for general-purpose I/O pins. Supports input, output, open-drain, and alternate function modes with optional pull-up/pull-down resistors. ```APIDOC ## GPIO — `twr_gpio` Low-level driver for all general-purpose I/O pins on the Core Module (P0–P17, LED, BUTTON, INT, SCL0/SDA0). Supports input, output, open-drain, and alternate function modes with optional pull-up/pull-down resistors. ```c #include void application_init(void) { // Drive P6 as digital output, push-pull twr_gpio_init(TWR_GPIO_P6); twr_gpio_set_mode(TWR_GPIO_P6, TWR_GPIO_MODE_OUTPUT); twr_gpio_set_output(TWR_GPIO_P6, 1); // set HIGH // Read P7 as digital input with pull-up twr_gpio_init(TWR_GPIO_P7); twr_gpio_set_pull(TWR_GPIO_P7, TWR_GPIO_PULL_UP); twr_gpio_set_mode(TWR_GPIO_P7, TWR_GPIO_MODE_INPUT); int state = twr_gpio_get_input(TWR_GPIO_P7); // 1 = HIGH, 0 = LOW // Toggle output on each call twr_gpio_toggle_output(TWR_GPIO_P6); } ``` ``` -------------------------------- ### Set Default Build Type Source: https://github.com/hardwario/twr-sdk/blob/master/CMakeLists.txt Sets the build type to 'debug' if not explicitly defined. ```cmake if(NOT DEFINED TYPE) set(TYPE debug) ENDIF() ```