mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-04-28 03:08:08 +00:00
152 lines
4.9 KiB
C++
152 lines
4.9 KiB
C++
/*
|
|
* Тест длинной полезной нагрузки IR (0x5E + строка, как ответ версии в Car).
|
|
* Передача через DMA + TIM17 — как в машинке (Car/src/IR/IR.cpp, BoardTest/IR_DMA).
|
|
* Авто-режим: чередование total длины кадра 24/25 байт.
|
|
*/
|
|
#include "IR_Decoder.h"
|
|
#include "IR_Encoder.h"
|
|
#include "TimerStatic.h"
|
|
|
|
/** 1 — TX через DMA (STM32G4). */
|
|
#ifndef LONGDATA_USE_DMA
|
|
#define LONGDATA_USE_DMA 0
|
|
#endif
|
|
|
|
#if LONGDATA_USE_DMA
|
|
#include <IrDmaTxStm32.h>
|
|
#endif
|
|
|
|
static constexpr uint16_t kIrDeviceAddr = 0;
|
|
static constexpr uint8_t kCmdVersion = 0x5E;
|
|
static constexpr uint32_t kSerialBaud = 115200;
|
|
static constexpr uint32_t kSendPeriodMs = 500;
|
|
static constexpr uint8_t kMaxPayload = bytePerPack;
|
|
static constexpr uint8_t kMaxParamBytes = kMaxPayload - 1;
|
|
|
|
static IR_Encoder enc(PIN_IR_ENC_FORWARD, kIrDeviceAddr, nullptr);
|
|
static HardwareTimer irTimer(TIM17);
|
|
|
|
#if LONGDATA_USE_DMA
|
|
namespace {
|
|
constexpr size_t kIrDmaStreams = 1;
|
|
constexpr uint16_t kIrDmaTxWordCount = 4096U;
|
|
constexpr size_t kIrDmaTxMaxGateRuns = 1024U;
|
|
static uint32_t s_irDmaWords[kIrDmaTxWordCount];
|
|
static IR_Encoder::IR_TxGateRun s_irGateRuns[kIrDmaTxMaxGateRuns];
|
|
} // namespace
|
|
|
|
static IrDmaTxStm32<kIrDmaStreams> dmaBackend;
|
|
static bool txBusy(void * /*ctx*/) { return dmaBackend.busy(); }
|
|
static bool txStart(void * /*ctx*/, IR_Encoder *e, const uint8_t *packet, uint8_t len) {
|
|
return dmaBackend.start(e, packet, len);
|
|
}
|
|
#endif
|
|
|
|
static char s_paramAscii[kMaxParamBytes + 1];
|
|
static uint8_t s_irPayload[kMaxPayload];
|
|
static uint8_t s_irPayloadLen = 0;
|
|
static uint32_t s_lastSendMs = 0;
|
|
static bool s_sendLongerFrame = false;
|
|
|
|
// 24 байта total: msg(1)+addr(2)+addr(2)+data(17)+crc(2), где data=0x5E + 16 ASCII.
|
|
static const char kPayload16[] = "Car_v4.3.9_[12MH";
|
|
// 25 байт total: как выше, но data=0x5E + 17 ASCII.
|
|
static const char kPayload17[] = "Car_v4.3.9_[12MHz]_G491";
|
|
|
|
static void rebuildIrPayload() {
|
|
s_irPayload[0] = kCmdVersion;
|
|
size_t n = 0;
|
|
while (n < sizeof(s_paramAscii) && s_paramAscii[n]) {
|
|
++n;
|
|
}
|
|
const size_t copyLen = (n > kMaxParamBytes) ? kMaxParamBytes : n;
|
|
memcpy(s_irPayload + 1, s_paramAscii, copyLen);
|
|
s_irPayloadLen = static_cast<uint8_t>(1 + copyLen);
|
|
}
|
|
|
|
static void setAlternatingPayload() {
|
|
const char* src = s_sendLongerFrame ? kPayload17 : kPayload16;
|
|
strncpy(s_paramAscii, src, kMaxParamBytes);
|
|
s_paramAscii[kMaxParamBytes] = '\0';
|
|
s_sendLongerFrame = !s_sendLongerFrame;
|
|
}
|
|
|
|
static void sendVersionPacket() {
|
|
rebuildIrPayload();
|
|
const IR_SendResult r = enc.sendData(IR_Broadcast, s_irPayload, s_irPayloadLen);
|
|
Serial.print(F("TX 0x5E + "));
|
|
Serial.print((unsigned)(s_irPayloadLen - 1));
|
|
Serial.print(F(" B, ok="));
|
|
Serial.print(r.success ? F("1") : F("0"));
|
|
Serial.print(F(", t="));
|
|
Serial.print(r.sendTimeMs);
|
|
Serial.println(F(" ms"));
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(kSerialBaud);
|
|
|
|
strncpy(s_paramAscii, kPayload16, kMaxParamBytes);
|
|
s_paramAscii[kMaxParamBytes] = '\0';
|
|
rebuildIrPayload();
|
|
|
|
#if LONGDATA_USE_DMA
|
|
// IR_Encoder::setCarrierMultiply(N); // до beginClockOnly; после смены — retuneCarrierClock()
|
|
IR_Encoder::beginClockOnly(&irTimer);
|
|
|
|
IrDmaTxStm32<kIrDmaStreams>::Config cfg;
|
|
cfg.timer = &irTimer;
|
|
cfg.streamCount = kIrDmaStreams;
|
|
cfg.streams[0].instance = DMA1_Channel1;
|
|
cfg.streams[0].irq = DMA1_Channel1_IRQn;
|
|
cfg.streams[0].dmamuxRequest = DMA_REQUEST_TIM17_UP;
|
|
cfg.streams[0].enc = &enc;
|
|
cfg.streams[0].dmaWords = s_irDmaWords;
|
|
cfg.streams[0].dmaWordCount = kIrDmaTxWordCount;
|
|
cfg.streams[0].gateRuns = s_irGateRuns;
|
|
cfg.streams[0].maxGateRuns = kIrDmaTxMaxGateRuns;
|
|
|
|
if (!dmaBackend.begin(cfg)) {
|
|
Serial.println(F("[IR_DMA] init FAILED"));
|
|
return;
|
|
}
|
|
IR_Encoder::setExternalTxBackend(txStart, txBusy, nullptr);
|
|
#elif LONGDATA_LEGACY_ISR
|
|
IR_Encoder::begin(&irTimer, 1, TIM17_IRQn, 0);
|
|
#else
|
|
IR_Encoder::begin(&irTimer, 1, TIM17_IRQn, 0);
|
|
#endif
|
|
enc.enable();
|
|
|
|
#if LONGDATA_USE_DMA
|
|
Serial.println(F("longData: DMA TX alternating 24/25 bytes"));
|
|
#elif LONGDATA_LEGACY_ISR
|
|
Serial.println(F("longData: legacy ISR TX (pre-unified FSM) 24/25 bytes"));
|
|
#else
|
|
Serial.println(F("longData: ISR TX (unified FSM) alternating 24/25 bytes"));
|
|
#endif
|
|
Serial.print(F("Auto-period ms = "));
|
|
Serial.println((unsigned long)kSendPeriodMs);
|
|
}
|
|
|
|
void loop() {
|
|
#if LONGDATA_USE_DMA
|
|
IR_Encoder::tick();
|
|
#endif
|
|
|
|
const uint32_t now = millis();
|
|
if (now - s_lastSendMs >= kSendPeriodMs) {
|
|
s_lastSendMs = now;
|
|
setAlternatingPayload();
|
|
sendVersionPacket();
|
|
}
|
|
}
|
|
|
|
#if LONGDATA_USE_DMA && defined(STM32G4xx)
|
|
extern "C" void DMA1_Channel1_IRQHandler(void) {
|
|
if (auto *p = IrDmaTxStm32<kIrDmaStreams>::instance()) {
|
|
p->irqForStream(0);
|
|
}
|
|
}
|
|
#endif
|