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