Custom Firmware Adapt Defines
Adapt Fixture and Hardware Definitions
The new example has two configuration headers. This separation prevents product settings from being mixed with MCU memory details:
Fixture/Inc/fixture_defines.h: product features, identity, defaults, and limits. A fixture developer changes this file.Hardware/<Board_MCU>/Inc/hw_defines.h: physical Flash layout and MCU write properties. Change it only for another Hardware variant.
Do not create project constants for these settings. Every Application project pre-includes fixture_defines.h. BUILD_FOR_BOOTLOADER is the only shared custom build define.
Naming is intentionally consistent: every customer-editable switch starts with FIXTURE_ENABLE_, and every other customer-editable product value starts with FIXTURE_. Constants such as INPUT_WIRELESS_DMX_PROTOCOL_CRMX are fixed choices and are not edited.
Safe order for changing a feature
- Keep the feature's
FIXTURE_ENABLE_...value at0. - Read the matching stable header in
Framework/Interfaces/FixtureorFramework/Interfaces/Hardware. - Look for a finished implementation with the same filename in
Examples. Copy it when it closely matches the product or peripheral. Otherwise copy the pseudo implementation fromTemplate. - Copy the file into the new example's local
Fixture/Srcor selectedHardware/.../Srcfolder. Never edit or compile the Template file in place. - Replace every pseudo operation and manually add the local file to every required CubeIDE configuration or Keil Target.
- Build once while the feature is disabled where possible. Then set the enable to
1, rebuild, and test the real PCB.
Always-required files are fixture_dmx_mapping.c, fixture_rdm.c, hw_flash.c, and hw_system.c. Optional files exist in an example only while their feature is enabled. This is intentional; do not copy all Template files to make a complete-looking folder.
1. Select input sources
#define FIXTURE_ENABLE_INPUT_WIRED_DMX 0
#define FIXTURE_ENABLE_INPUT_WIRELESS_DMX 0
#define FIXTURE_ENABLE_INPUT_VISION 1
#define FIXTURE_ENABLE_INPUT_MANUAL 0
#define FIXTURE_ENABLE_INPUT_AUTO 0
/* Lower number means higher priority. */
#define FIXTURE_INPUT_PRIORITY_WIRED_DMX 1U
#define FIXTURE_INPUT_PRIORITY_WIRELESS 2U
#define FIXTURE_INPUT_PRIORITY_VISION 3U
WIRED_DMXrequires thehw_wired_dmx.cUART/transceiver implementation.WIRELESS_DMXrequireshw_wireless_dmx.cand one selected wireless protocol.VISIONreceives DMX and RDM through Vision SPI.MANUALallows local controls to provide fixture values without a DMX source.AUTOlets Framework select an active source by reception state and priority.
Vision sends frames continuously, so Auto mode must use the Vision library's DMX reception state, not the arrival of a frame. After Vision or wireless control becomes active, Framework disables conflicting wireless receivers until the active source times out.
2. Select CRMX or W-DMX
#define INPUT_WIRELESS_DMX_PROTOCOL_NONE 0
#define INPUT_WIRELESS_DMX_PROTOCOL_CRMX 1
#define INPUT_WIRELESS_DMX_PROTOCOL_WDMX 2
#define FIXTURE_INPUT_WIRELESS_DMX_PROTOCOL \
INPUT_WIRELESS_DMX_PROTOCOL_NONE
A product contains either CRMX or W-DMX, never both. Select one before setting FIXTURE_ENABLE_INPUT_WIRELESS_DMX to 1.
3. Enable fixture functions
#define FIXTURE_ENABLE_LED_OUTPUT 1
#define FIXTURE_ENABLE_DISPLAY 0
#define FIXTURE_ENABLE_MENU 0
#define FIXTURE_ENABLE_COLOR_CONVERTER 0
#define FIXTURE_ENABLE_COLOR_CONVERTER_CALIBRATION 0
#define FIXTURE_ENABLE_COLOR_CONVERTER_DITHERING 0
#define FIXTURE_ENABLE_SETTING_DIMMER_CURVE 1
#define FIXTURE_ENABLE_SETTING_DIMMER_SPEED 0
Enable a function only after its matching Hardware/.../Src/hw_*.c implementation works. Important dependencies are checked by the compiler:
FIXTURE_ENABLE_MENUrequiresFIXTURE_ENABLE_DISPLAY.- Dimmer speed and LED dithering require ColorConverter.
- ColorConverter requires a valid generated model in
fixture_color_converter_model.c. - ColorConverter also requires the LED-PCB temperature sensor.
LED output requires fixture_led.c and hw_led.c. Display requires hw_display.c; custom menu pages additionally require fixture_menu.c. ColorConverter requires fixture_color_converter_model.c, the matching precompiled ColorConverter library, hw_sensors.c, and a real LED-PCB temperature conversion. Do not set FIXTURE_COLOR_CONVERTER_MODEL_IS_VALID to 1 only to bypass the compiler check.
4. Select persistent storage
#define MANAGED_FLASH_LIBRARY_MANAGED_FLASH 0
#define MANAGED_FLASH_LIBRARY_MANAGED_FLASH_SECTOR 1
#define FIXTURE_MANAGED_FLASH_LIBRARY \
MANAGED_FLASH_LIBRARY_MANAGED_FLASH_SECTOR
#define FIXTURE_ENABLE_MANAGED_FLASH_CRC 1
ManagedFlashSector is recommended for new fixtures because it supports CRC, persistent object IDs, shared page usage, and recovery after an interrupted write. Use classic ManagedFlash only for compatibility with an existing Flash format or when minimum code size is more important. Switching implementation or CRC setting reformats the saved settings.
5. Set the RDM product identity
#define FIXTURE_RDM_MANUFACTURER_ID 0xF00AU
#define FIXTURE_RDM_DEVICE_MODEL_ID 2U
#define FIXTURE_RDM_PRODUCT_CATEGORY 1U
#define FIXTURE_RDM_PRODUCT_DETAIL 0x0004U
#define FIXTURE_RDM_MODEL_DESCRIPTION "External Example"
#define FIXTURE_RDM_MANUFACTURER_LABEL "KKT"
#define FIXTURE_RDM_DEFAULT_DEVICE_LABEL "Vision External Example"
Replace every example value with the registered values for the product. Manufacturer ID and Device Model ID must also be entered when generating DFU and production files. A mismatch prevents firmware for one fixture model from being installed on another.
#define FIXTURE_SECURITY_KEY {114U, 194U, 199U, 205U, 253U, 181U, 228U, 103U}
Replace the example security key with the Fixture Security Key generated by the Vision web service. Never ship the example key in a product.
RDM is part of the Framework and has no general enable switch. Generic PIDs such as Device Info, labels, DMX address/personality, lamp settings, standard sensors, errors, and warnings are handled by Framework/Src/rdm.c. Add only product-specific PIDs or special behavior in Fixture/Src/fixture_rdm.c.
6. Set DMX and App Control defaults
#define FIXTURE_DMX_DEFAULT_PERSONALITY 1U
#define FIXTURE_DMX_DEFAULT_START_ADDRESS 1U
#define FIXTURE_DMX_DEFAULT_DIMMER_CURVE 0U
#define FIXTURE_DMX_DEFAULT_DIMMER_SPEED 0U
#define FIXTURE_INPUT_SOURCE_VISION 0U
#define FIXTURE_INPUT_SOURCE_WIRED_DMX 1U
#define FIXTURE_INPUT_SOURCE_WIRELESS_DMX 2U
#define FIXTURE_INPUT_SOURCE_MANUAL 3U
#define FIXTURE_INPUT_SOURCE_AUTO 4U
#define FIXTURE_DEFAULT_INPUT_SOURCE FIXTURE_INPUT_SOURCE_VISION
#define FIXTURE_DMX_TIMEOUT_MS 2000UL
#define FIXTURE_APP_DMX_FOOTPRINT 27U
#define FIXTURE_APP_DIMMER_CURVE 0U
#define FIXTURE_APP_DIMMER_SPEED 0U
Select FIXTURE_DEFAULT_INPUT_SOURCE with one of the named FIXTURE_INPUT_SOURCE_... choices. Do not enter the numeric value directly. The selected source must also be enabled, except that Manual may be used by explicit local/App control as implemented by the product.
FIXTURE_APP_DMX_FOOTPRINT is an explicit channel count. It must exactly match the channel mapping implemented in FixtureDmxMappingApplyAppFrame(). Do not calculate it only from LED count: resolution, master dimmer, control channels, and color channels can change the footprint.
App Control uses temporary curve and speed settings and does not overwrite the saved DMX settings.
7. Understand Auto-mode priorities
Every enabled automatic source must use a different, non-zero priority. Manual/App control is used when explicitly selected and, in Auto mode, only when no higher-priority input has active control.
8. Describe the LED fixture
#define FIXTURE_LED_COUNT 9U
#define FIXTURE_LED_COLOR_COUNT 3U
#define FIXTURE_LED_MAX_COLOR_COUNT 6U
#define FIXTURE_LED_POWER_RED_MW 1578UL
#define FIXTURE_LED_POWER_GREEN_MW 3150UL
#define FIXTURE_LED_POWER_BLUE_MW 2600UL
FIXTURE_LED_COUNT is the number of individually controlled LEDs. FIXTURE_LED_COLOR_COUNT is the number of color channels per LED and may be from three to six in this reference. There is no separate pixel enable. More than one LED automatically represents a multi-LED/pixel fixture.
The power values are used by runtime and battery calculations. Add values for additional colors when the product uses RGBW, RGBA, RGBAL, or another supported model.
9. Configure ColorConverter timing
#define FIXTURE_COLOR_CONVERTER_CALCULATION_PERIOD_MS 1U
#define FIXTURE_LED_OUTPUT_PERIOD_US 1000U
#define FIXTURE_LED_OUTPUT_RESOLUTION 0xFFFFU
#define FIXTURE_LED_MINIMUM_WORKING_PWM 1U
#define FIXTURE_DIMMER_SLOW_RESPONSE_MS 100U
#define FIXTURE_COLOR_CONVERTER_MODEL_IS_VALID 0
Keep ColorConverter disabled until fixture_color_converter_model.c contains a model generated for the real LEDs. The Framework calls the calculation interrupt at the configured period and commits a completed result at the output period. Optional dithering improves low-level PWM output but costs Flash and CPU time.
FIXTURE_ENABLE_COLOR_CONVERTER_CALIBRATION adds storage and RDM write/save/check handling for per-unit calibration. The calibration temperature is received together with the calibration values; it is not a define. Variables registers and saves the calibration object only while this feature is enabled.
10. Configure the power input button
#define FIXTURE_ENABLE_INPUT_POWER_BUTTON 1
#define FIXTURE_POWER_BUTTON_ACTIVE_STATE 0
#define FIXTURE_POWER_BUTTON_LONG_PRESS_STEP_MS 500U
#define FIXTURE_POWER_BUTTON_ON_COUNT 1U
#define FIXTURE_POWER_BUTTON_OFF_COUNT 4U
This is the main fixture power/menu input button, not the additional navigation buttons belonging to a display. Implement it in hw_power_button.c. Display navigation buttons belong to the display/menu Hardware interface.
11. Configure battery and sensors
#define FIXTURE_ENABLE_BATTERY 0
#define FIXTURE_ENABLE_BATTERY_HEALTH 0
#define FIXTURE_BATTERY_CAPACITY_MWH 0UL
#define FIXTURE_BATTERY_LOW_PERCENT 5U
#define FIXTURE_ENABLE_SENSOR_LED_PCB_TEMPERATURE 0
#define FIXTURE_LED_PCB_TEMPERATURE_DIM_C 65U
#define FIXTURE_LED_PCB_TEMPERATURE_MAX_C 85U
hw_battery.c owns ADC or I2C fuel-gauge state and performs asynchronous measurement in its task. Enabling Battery automatically adds Battery Charge as an RDM sensor. Enable Battery Health only when the gauge provides a valid health percentage; Framework then adds that RDM sensor too.
hw_sensors.c acquires and converts the LED-PCB temperature. Framework routes it to RDM and ColorConverter. ColorConverter requires this sensor. Add only extra product sensors in fixture_sensors.c; there is no separate standard-sensor or battery-voltage switch.
Before setting either enable, add the corresponding Hardware source to every Application target and verify nonblocking task operation. ADC or I2C acquisition must not stop SystemTask. fixture_sensors.c is added only when FIXTURE_ENABLE_CUSTOM_SENSORS is enabled.
12. Configure error and warning codes
#define FIXTURE_ENABLE_ERROR_CODES 1
typedef enum
{
FIXTURE_ERROR_CODE_NONE = 0,
FIXTURE_ERROR_CODE_EXAMPLE
} fixture_error_code_t;
#define FIXTURE_ENABLE_WARNING_CODES 1
typedef enum
{
FIXTURE_WARNING_CODE_NONE = 0,
FIXTURE_WARNING_CODE_EXAMPLE
} fixture_warning_code_t;
Define the fixture-specific IDs directly beside each enable in fixture_defines.h. Keep both NONE values at zero and map every other ID to its printable character code in fixture_rdm.c. Framework stores fixed-size arrays of active IDs. Adding the same value again does not create a duplicate. RDM converts the IDs into character codes on demand and separates multiple codes with spaces. A reset clears both lists. When support is disabled, the custom RDM PIDs still ACK and return an empty list/count instead of NACK.
13. Configure system behavior
#define FIXTURE_ENABLE_FEATURE_RUNTIME_LIMIT 0
#define FIXTURE_ENABLE_FEATURE_SLEEP 1
#define FIXTURE_ENABLE_FEATURE_EMERGENCY 0
#define FIXTURE_ENABLE_FEATURE_SHIPPING_MODE 0
#define FIXTURE_ENABLE_FEATURE_ANTITHEFT 1
Sleep is only a low-power state; the fixture remains on and reachable, so Fixture Is On stays asserted. During Wakeup it remains deasserted until the Vision wake signal can be released. Turn-off may keep it asserted during the short transition.
The reference fixture's power animation belongs to fixture_led.c. Change or remove it there; it is not a Framework feature switch.
14. Configure both DFU transports
#define FIXTURE_ENABLE_DFU_USING_VISION 1
#define FIXTURE_ENABLE_DFU_USING_VISION_DMX_ADAPTER 0
#define DFU_RECEIVER_BOOTLOADER 0
#define DFU_RECEIVER_APPLICATION 1
#define FIXTURE_DFU_RECEIVER DFU_RECEIVER_BOOTLOADER
FIXTURE_ENABLE_DFU_USING_VISION: receive fixture firmware through the Vision SPI module.FIXTURE_ENABLE_DFU_USING_VISION_DMX_ADAPTER: receive it as wired RDM through a Vision DMX Adapter. This requires wired DMX.DFU_RECEIVER_BOOTLOADER: recommended. For Vision SPI, the Application stores the reboot request and resets without answering the pending start flag. The Bootloader receives and answers that flag, then receives and writes the image.DFU_RECEIVER_APPLICATION: pseudo integration point. Copy and fully implementTemplate/Fixture/Src/fixture_dfu_staging.cbefore selecting it.
The transport and receiver are independent choices. For example, Vision SPI may send data directly to the Bootloader, or the Application may stage data received from either transport in external Flash.
Application staging must validate the header, store and track numbered packets, prevent concurrent transports, validate the external CRC, request DFU_REBOOT_APPLY_STAGED_UPDATE, and reset with correct response timing. The Bootloader-side install must validate external data before internal erase, copy with correct alignment, validate internal Flash again, and only then mark completion. Test power loss at every stage before production.
15. Set versions and serial-number defaults
#define FIXTURE_DFU_MAX_FIRMWARE_SIZE \
(HW_FLASH_APPLICATION_END - HW_FLASH_APPLICATION_ADDRESS + 1UL)
#define FIXTURE_DFU_CONFIG_VERSION 1UL
#define FIXTURE_DEFAULT_SERIAL_NUMBER 1ULL
#define FIXTURE_BOOTLOADER_VERSION_MAJOR 1U
#define FIXTURE_BOOTLOADER_VERSION_MINOR 2U
#define FIXTURE_BOOTLOADER_VERSION_PATCH 0U
#define FIXTURE_BOOTLOADER_VERSION_RELEASE 255U
#define FIXTURE_FIRMWARE_VERSION_MAJOR 0U
#define FIXTURE_FIRMWARE_VERSION_MINOR 1U
#define FIXTURE_FIRMWARE_VERSION_PATCH 0U
#define FIXTURE_FIRMWARE_VERSION_RELEASE 255U
FIXTURE_DFU_MAX_FIRMWARE_SIZE must describe the complete Application region and must never extend into Managed Flash or another reserved area. Keep the calculation based on the selected Hardware addresses unless the product has a verified reason to use a smaller limit.
The serial number is stored in the shared DFU configuration block because Bootloader and Application both require it. The default is only used when no valid configuration exists. Firmware-package versions must exactly match these values.
16. Configure the Hardware Flash layout
Edit only the selected Hardware variant's hw_defines.h:
#define HW_FLASH_BOOTLOADER_ADDRESS ...
#define HW_FLASH_CONFIG_ADDRESS ...
#define HW_FLASH_APPLICATION_ADDRESS ...
#define HW_FLASH_APPLICATION_END ...
#define HW_FLASH_STORAGE_ADDRESS ...
#define HW_FLASH_STORAGE_SIZE ...
#define HW_FLASH_PAGE_SIZE ...
#define HW_FLASH_WRITE_ALIGNMENT ...
Check the MCU datasheet for erase-page/sector boundaries and write alignment. The Bootloader, shared configuration, Application, and Managed Flash regions must not overlap. Match these values in every IDE linker target.
17. Implement the Fixture source files
fixture_dmx_mapping.c: map personalities and App Control frames to fixture output, then call the LED layer.fixture_rdm.c: special/custom PIDs through RDM library callbacks.fixture_led.c: product output mapping for all LEDs and color channels.fixture_color_converter_model.c: generated ColorConverter model for the fixture LEDs.fixture_sensors.c: additional product sensors.fixture_menu.c: product-specific menu pages.
Also add fixture_variables.c and fixture_variables_custom.h only for FIXTURE_ENABLE_CUSTOM_VARIABLES, and fixture_dfu_staging.c only for Application DFU reception. For every listed file, prefer a close finished example implementation; use the corresponding Template pseudo file when no example matches. Add copied files to every required IDE Target before enabling them.
New screenshot requested: current fixture_defines.h groups and the Fixture folder. Screenshots of the previous flat configuration and implementation layout no longer match the project.
18. Final check
- Keep every unsupported feature at
0. - Build Debug, ReleaseBL, and Bootloader.
- Run
VisionExternalExamples/Tools/TestExamples.ps1. - Confirm the RDM identity, DMX footprint, input priorities, versions, security key, and Flash layout before generating a DFU package.
- Confirm that each enabled Fixture and Hardware implementation is present in every required IDE Target and that no disabled optional implementation remains in the example.
- Test all enabled functions, input timeouts, saved-value reset behavior, and both selected DFU transports on the real PCB.
See System, Vision DMX, RDM Library, Input Sources, Vision Features, and Display.