Files
MAG160C/.superpowers/sdd/task-2-brief.md
T

5.4 KiB

Task 2 Brief: TCM frame codec

Context

Task 1 is complete. Existing files include CMakeLists.txt, include/mag160c/mag160c.h, src/core/error., src/core/context., src/c_api.cpp, and tests/cpp/test_c_api.cpp.

CMake is currently unavailable on PATH in this environment. Still keep CMakeLists.txt correct, but if CMake verification cannot run, use direct MinGW g++ verification and record the substitution in the report.

Global constraints

  • Use only original source code; do not link proprietary SDK binaries.
  • Current workspace is not a git repository; replace commit steps with verification plus updates to progress.md.
  • Keep public C ABI free of C++ types.
  • Use C++17.
  • libusb-1.0 is the only native runtime dependency for the core library.
  • Firmware update commands are not exposed as an easy accidental CLI action.
  • IR protocol gaps return MAG160C_ERR_PROTOCOL_UNKNOWN or MAG160C_ERR_UNSUPPORTED.

Files

  • Create: src/core/tcm_frame.hpp
  • Create: src/core/tcm_frame.cpp
  • Create: tests/cpp/test_tcm_frame.cpp
  • Modify: CMakeLists.txt
  • Modify: include/mag160c/mag160c.h
  • Modify: src/c_api.cpp
  • Update: progress.md with the checkpoint at the end.

Interfaces to produce

  • mag160c::core::TcmFrame
  • mag160c::core::checksum(const uint8_t* data, size_t begin, size_t end)
  • mag160c::core::encode_tcm_frame(uint8_t main_cmd, uint8_t sub_cmd, uint16_t frame_id, const std::vector<uint8_t>& payload)
  • mag160c::core::decode_tcm_frame(const uint8_t* data, size_t size, TcmFrame* out)
  • mag160c_tcm_encode_frame C ABI
  • mag160c_tcm_decode_header C ABI

TCM frame rules

  • Header byte 0 is 0x7e.
  • Bytes 1..2 are big-endian body length.
  • Byte 3 is additive checksum over bytes 0..2.
  • Body is main, sub, frame high, frame low, payload, body checksum.
  • Body checksum is additive checksum over body bytes before the final checksum byte.
  • Body length is payload length + 5.
  • Minimum valid full packet length is 9 bytes.

Required exact test vector

Encoding main 0x02, sub 0x77, frame id 0x0001, payload {0x00, 0x05} must produce:

7e 00 07 85 02 77 00 01 00 05 7f

Required tests

Create tests/cpp/test_tcm_frame.cpp with:

  • test_rotate_frame_encoding: exact bytes above.
  • test_decode_rejects_bad_header_checksum: corrupt byte 3 and expect MAG160C_ERR_CHECKSUM.
  • test_decode_roundtrip: encode then decode and assert main, sub, frame id, payload.

Required C++ header

src/core/tcm_frame.hpp must declare:

#pragma once

#include "mag160c/mag160c.h"

#include <cstddef>
#include <cstdint>
#include <vector>

namespace mag160c::core {

struct TcmFrame {
    uint8_t main_cmd = 0;
    uint8_t sub_cmd = 0;
    uint16_t frame_id = 0;
    std::vector<uint8_t> payload;
};

uint8_t checksum(const uint8_t* data, size_t begin, size_t end);
std::vector<uint8_t> encode_tcm_frame(uint8_t main_cmd, uint8_t sub_cmd, uint16_t frame_id, const std::vector<uint8_t>& payload);
mag160c_error_t decode_tcm_frame(const uint8_t* data, size_t size, TcmFrame* out);

}

Required C ABI declarations

Add to include/mag160c/mag160c.h inside the extern C block:

MAG160C_API mag160c_error_t mag160c_tcm_encode_frame(
    uint8_t main_cmd,
    uint8_t sub_cmd,
    uint16_t frame_id,
    const uint8_t* payload,
    size_t payload_size,
    uint8_t* out_bytes,
    size_t out_capacity,
    size_t* out_size
);

MAG160C_API mag160c_error_t mag160c_tcm_decode_header(
    const uint8_t* data,
    size_t size,
    uint8_t* out_main_cmd,
    uint8_t* out_sub_cmd,
    uint16_t* out_frame_id,
    size_t* out_payload_size
);

Required C ABI behavior

  • mag160c_tcm_encode_frame requires out_size.
  • If output buffer is null or too small, set out_size to the required encoded size and return MAG160C_ERR_INVALID_ARGUMENT.
  • If payload_size is nonzero and payload is null, return MAG160C_ERR_INVALID_ARGUMENT.
  • On success, copy encoded bytes, set out_size, clear last error, return MAG160C_OK.
  • mag160c_tcm_decode_header requires all output pointers.
  • It should call decode_tcm_frame and return any error from it.
  • On success, fill main, sub, frame id, and payload size.

CMake update

  • Add src/core/tcm_frame.cpp to mag160c_core sources.
  • Add test_tcm_frame executable linked to mag160c_core.
  • Give test_tcm_frame access to src private headers.
  • Register test_tcm_frame with CTest.

Verification

First try:

cmake --build build
ctest --test-dir build --output-on-failure

If CMake is unavailable, run direct verification equivalent to:

g++ -std=c++17 -DMAG160C_STATIC -DMAG160C_HAS_LIBUSB=0 -Iinclude -Isrc src\core\error.cpp src\core\context.cpp src\core\tcm_frame.cpp src\c_api.cpp tests\cpp\test_c_api.cpp -o build_task2_c_api_test.exe
.\build_task2_c_api_test.exe
g++ -std=c++17 -DMAG160C_STATIC -DMAG160C_HAS_LIBUSB=0 -Iinclude -Isrc src\core\error.cpp src\core\context.cpp src\core\tcm_frame.cpp src\c_api.cpp tests\cpp\test_tcm_frame.cpp -o build_task2_tcm_frame_test.exe
.\build_task2_tcm_frame_test.exe

Expected: both executables exit 0.

Progress checkpoint

Append this line to progress.md after verification:

- Implemented Task 2 TCM frame codec with byte-exact encode/decode tests and C ABI utility functions.

Report contract

Write a report to .superpowers/sdd/task-2-report.md with:

  • status: DONE, DONE_WITH_CONCERNS, NEEDS_CONTEXT, or BLOCKED
  • files created/modified
  • exact commands run
  • test results
  • concerns, if any
  • self-review notes