#include "IR_Encoder.h" #include "IR_DecoderRaw.h" #include #include #include #include // Link seams: these paths are not exercised by the pure host timing test. bool IR_DecoderRaw::registerPairMuteEncoder(IR_Encoder *) { return true; } void IR_DecoderRaw::refreshPairMuteState() {} void IR_Encoder::send_HIGH(bool) {} void IR_Encoder::send_LOW() {} void IR_Encoder::send_EMPTY(uint8_t) {} namespace { static_assert(irproto::dataWireBytes(0U) == 7U, "empty DATA wire size changed"); static_assert(irproto::dataWireBytes(3U) == 10U, "DATA wire size changed"); static_assert(irproto::dataWireBytes(24U) == 31U, "maximum DATA wire size changed"); static_assert(irproto::dataWireBytes(25U) == 0U, "oversized DATA must be rejected"); static_assert(irproto::backWireBytes(1U) == 6U, "BACK wire size changed"); static_assert(irproto::backWireBytes(26U) == 31U, "maximum BACK wire size changed"); static_assert(irproto::backToWireBytes(24U) == 31U, "maximum BACK_TO wire size changed"); static_assert(irproto::wireLogicalTicks(6U) == 5472U, "6-byte tick count changed"); static_assert(irproto::wireLogicalTicks(10U) == 8728U, "10-byte tick count changed"); static_assert(irproto::wireLogicalTicks(31U) == 25822U, "31-byte tick count changed"); static_assert(irproto::preambleAirtimeUsCeil() == 7737U, "preamble airtime changed"); static_assert(irproto::wireAirtimeUsCeil(6U) == 72000U, "6-byte airtime changed"); static_assert(irproto::wireAirtimeUsCeil(10U) == 114843U, "10-byte airtime changed"); static_assert(irproto::wireAirtimeUsCeil(31U) == 339764U, "31-byte airtime changed"); static_assert(irproto::responseStartGuardUs() == 57198U, "response-start guard changed"); static_assert(irproto::responseFrameGuardUs(6U) == 131100U, "response-frame guard changed"); uint32_t sumLogicalTicks(const IrTxGateRun *runs, size_t count) { uint32_t total = 0U; for (size_t i = 0U; i < count; ++i) total += runs[i].lenTicks; return total; } void verifyFormulaAgainstTxFsm() { std::array frame{}; std::array runs{}; for (uint8_t wireBytes = 1U; wireBytes <= irproto::kMaxWireFrameBytes; ++wireBytes) { for (uint8_t pattern = 0U; pattern < 4U; ++pattern) { for (uint8_t i = 0U; i < wireBytes; ++i) { frame[i] = pattern == 0U ? 0x00U : pattern == 1U ? 0xFFU : pattern == 2U ? static_cast((i & 1U) ? 0x55U : 0xAAU) : static_cast(i * 73U + 19U); } const size_t count = IR_Encoder::buildGateRuns( frame.data(), wireBytes, runs.data(), runs.size()); assert(count != 0U); assert(sumLogicalTicks(runs.data(), count) == irproto::wireLogicalTicks(wireBytes)); } } } void verifyPublicSendTimeResults() { IR_Encoder encoder(1U, 42U, nullptr, false); uint8_t payload[26]{}; assert(encoder.testSendAccept(1U) == 72U); // six-byte wire frame assert(encoder.testSendTime(1U, payload, 3U) == 115U); // ten-byte wire frame assert(encoder.testSendBack(payload, 26U) == 340U); // 31-byte wire frame } } int main() { verifyFormulaAgainstTxFsm(); verifyPublicSendTimeResults(); std::cout << "IR timing contract tests: OK\n"; return 0; }