Loading files
e838b84e2This file is pinned to the selected release. Download the original to open it in your design tool.
#!/usr/bin/env python3
# Copyright 2026 Scott Bezek
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Generate an embeddable C header holding the FaderBuddy offset application
image, for the ESP32 jig's I2C bootloader update step.
Builds the fb_app_only PlatformIO environment (unless --no-build), extracts the
application bytes from the resulting Intel-hex (see fb_image), computes the
CRC16-CCITT the bootloader verifies against, and writes fader_app_image.h.
"""
import argparse
import sys
from pathlib import Path
SCRIPT_DIR = Path(__file__).resolve().parent
REPO_ROOT = SCRIPT_DIR.parents[2] # tools -> programAndTest -> production_tools -> repo
sys.path.insert(0, str(REPO_ROOT / "firmware" / "tools"))
from fb_image import ( # noqa: E402
BL_APP_START, build_offset_app, crc16_ccitt, firmware_version_u16, load_app_image,
)
def emit_header(out_path, image, fw_version):
crc = crc16_ccitt(image)
lines = []
lines.append("/* AUTO-GENERATED by tools/generate_app_image.py -- do not edit. */")
lines.append("#pragma once")
lines.append("#include <stdint.h>")
lines.append("")
lines.append("#define FADER_APP_FLASH_START (0x%04Xu)" % BL_APP_START)
lines.append("#define FADER_APP_IMAGE_SIZE (%uu)" % len(image))
lines.append("#define FADER_APP_IMAGE_CRC16 (0x%04Xu)" % crc)
lines.append("#define FADER_APP_FW_VERSION (%uu)" % fw_version)
lines.append("")
lines.append("const uint8_t FADER_APP_IMAGE[FADER_APP_IMAGE_SIZE] = {")
for i in range(0, len(image), 16):
chunk = image[i:i + 16]
lines.append(" " + "".join("0x%02X, " % b for b in chunk).rstrip())
lines.append("};")
lines.append("")
Path(out_path).write_text("\n".join(lines))
print("Wrote %s: %u bytes, CRC16=0x%04X, FW_VERSION=%u"
% (out_path, len(image), crc, fw_version), flush=True)
def main():
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("--output", default=str(SCRIPT_DIR.parent / "include" / "fader_app_image.h"))
p.add_argument("--no-build", action="store_true", help="use the existing hex, don't rebuild")
args = p.parse_args()
if not args.no_build:
build_offset_app()
emit_header(args.output, load_app_image(), firmware_version_u16())
if __name__ == "__main__":
main()