Add updatable ADAU1701 program via flash partition and HTTP API.

Decouple the SigmaStudio RAM download from compiled-in adau1701_program.c:
DRAD v1 blobs in the dsp partition with embedded fallback, POST /api/dsp/program,
and host-tested blob parse/serialize helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-07 09:21:49 +02:00
co-authored by Cursor
parent cd94e36a9d
commit cc4a03168e
31 changed files with 1302 additions and 50 deletions
@@ -0,0 +1,61 @@
/**
* @file DspProgram.hpp
* @brief Ordered ADAU1701 RAM download sequence (pure domain).
*
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
*
* Copyright 2026 Michele Bigi
* SPDX-License-Identifier: Apache-2.0
*
* @author Michele Bigi
* @date 2026-07-07
*/
#pragma once
#include "core/RegisterWrite.hpp"
#include <vector>
namespace core {
/**
* @brief DspProgram — immutable SigmaStudio download script.
*
* @dname DspProgram
* @return n/a (type)
* @pubstate Owns writes_; built from a validated flash blob or embedded export.
*
* @author Michele Bigi
* @date 2026-07-07
*/
class DspProgram {
public:
/**
* @brief DspProgram — construct from an ordered write list.
*
* @dname DspProgram
* @param writes Non-empty register blocks in replay order.
* @pubstate moves writes into writes_.
*
* @author Michele Bigi
* @date 2026-07-07
*/
explicit DspProgram(std::vector<RegisterWrite> writes);
/**
* @brief writes — read the ordered download steps.
*
* @dname writes
* @return Reference to the internal write vector.
* @pubstate reads writes_.
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] const std::vector<RegisterWrite>& writes() const noexcept;
private:
std::vector<RegisterWrite> writes_;
};
} // namespace core
@@ -0,0 +1,71 @@
/**
* @file DspProgramBlob.hpp
* @brief Framed ADAU1701 program blob parse/serialise (pure core).
*
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
*
* Copyright 2026 Michele Bigi
* SPDX-License-Identifier: Apache-2.0
*
* Blob layout (v1, little-endian):
* magic[4] = "DRAD", version u16, write_count u16, payload_crc32 u32,
* then for each write: address u16, length u16, data[length].
*
* @author Michele Bigi
* @date 2026-07-07
*/
#pragma once
#include "core/DspProgram.hpp"
#include "core/DspProgramError.hpp"
#include <cstdint>
#include <expected>
#include <span>
#include <string>
#include <vector>
namespace core {
/**
* @brief parseDspProgramBlob — validate and decode a flash/HTTP blob.
*
* @dname parseDspProgramBlob
* @param blob Raw bytes from the dsp partition or POST body.
* @return DspProgram on success, or DspProgramError.
* @pubstate none
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] std::expected<DspProgram, DspProgramError>
parseDspProgramBlob(std::span<const std::uint8_t> blob);
/**
* @brief serializeDspProgramBlob — encode a program for flash storage.
*
* @dname serializeDspProgramBlob
* @param program Ordered download script.
* @return Framed blob bytes with CRC32.
* @pubstate none
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] std::vector<std::uint8_t>
serializeDspProgramBlob(const DspProgram& program);
/**
* @brief dspProgramErrorToken — stable API/JSON error string.
*
* @dname dspProgramErrorToken
* @param error Parse or store failure.
* @return Short snake_case token.
* @pubstate none
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] const char* dspProgramErrorToken(DspProgramError error) noexcept;
} // namespace core
@@ -0,0 +1,38 @@
/**
* @file DspProgramError.hpp
* @brief Failure causes for ADAU1701 program blob parse and load.
*
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
*
* Copyright 2026 Michele Bigi
* SPDX-License-Identifier: Apache-2.0
*
* @author Michele Bigi
* @date 2026-07-07
*/
#pragma once
namespace core {
/**
* @brief DspProgramError — ADAU1701 program validation failures.
*
* @dname DspProgramError
* @return n/a (type)
* @pubstate n/a
*
* @author Michele Bigi
* @date 2026-07-07
*/
enum class DspProgramError {
Empty, ///< No bytes supplied.
Truncated, ///< Header or write payload shorter than declared.
InvalidMagic,
UnsupportedVersion,
BadCrc,
TooLarge,
FlashReadFailed,
FlashWriteFailed,
};
} // namespace core
@@ -0,0 +1,50 @@
/**
* @file IDspProgramSource.hpp
* @brief Port for loading an ADAU1701 RAM download program.
*
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
*
* Copyright 2026 Michele Bigi
* SPDX-License-Identifier: Apache-2.0
*
* @author Michele Bigi
* @date 2026-07-07
*/
#pragma once
#include "core/DspProgram.hpp"
#include "core/DspProgramError.hpp"
#include <expected>
namespace core {
/**
* @brief IDspProgramSource — supplies DspProgram for Adau1701Driver::boot().
*
* @dname IDspProgramSource
* @return n/a (type)
* @pubstate Implementations live in the adau1701 driver (embedded + flash).
*
* @author Michele Bigi
* @date 2026-07-07
*/
class IDspProgramSource {
public:
virtual ~IDspProgramSource() = default;
/**
* @brief loadProgram — obtain the download script for this boot.
*
* @dname loadProgram
* @return DspProgram on success, or DspProgramError.
* @pubstate none
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] virtual std::expected<DspProgram, DspProgramError>
loadProgram() = 0;
};
} // namespace core
@@ -0,0 +1,75 @@
/**
* @file RegisterWrite.hpp
* @brief One SigmaStudio SIGMA_WRITE_REGISTER_BLOCK transaction.
*
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
*
* Copyright 2026 Michele Bigi
* SPDX-License-Identifier: Apache-2.0
*
* @author Michele Bigi
* @date 2026-07-07
*/
#pragma once
#include <cstdint>
#include <span>
#include <vector>
namespace core {
/**
* @brief RegisterWrite — 16-bit DSP address plus payload bytes.
*
* @dname RegisterWrite
* @return n/a (type)
* @pubstate Owns data_; replayed by Adau1701Driver via SIGMA_WRITE_REGISTER_BLOCK.
*
* @author Michele Bigi
* @date 2026-07-07
*/
class RegisterWrite {
public:
/**
* @brief RegisterWrite — construct one download step.
*
* @dname RegisterWrite
* @param address Target address in the ADAU1701 memory map.
* @param data Payload bytes (may exceed 255; driver chunks I2C).
* @pubstate moves data into data_.
*
* @author Michele Bigi
* @date 2026-07-07
*/
RegisterWrite(std::uint16_t address, std::vector<std::uint8_t> data);
/**
* @brief address — read the 16-bit target address.
*
* @dname address
* @return SigmaStudio register/data address.
* @pubstate reads address_.
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] std::uint16_t address() const noexcept;
/**
* @brief data — read payload bytes.
*
* @dname data
* @return Immutable byte span of the write payload.
* @pubstate reads data_.
*
* @author Michele Bigi
* @date 2026-07-07
*/
[[nodiscard]] std::span<const std::uint8_t> data() const noexcept;
private:
std::uint16_t address_;
std::vector<std::uint8_t> data_;
};
} // namespace core