mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-03-13 04:44:44 +00:00
149 lines
5.9 KiB
C++
149 lines
5.9 KiB
C++
#pragma once
|
|
#include "IR_config.h"
|
|
|
|
// TODO: Отложенная передача после завершения приема
|
|
|
|
// Структура для возврата результата отправки
|
|
struct IR_SendResult {
|
|
bool success; // Флаг успешности отправки
|
|
uint32_t sendTimeMs; // Время отправки пакета в миллисекундах
|
|
|
|
IR_SendResult(bool success = false, uint32_t sendTimeMs = 0)
|
|
: success(success), sendTimeMs(sendTimeMs) {}
|
|
};
|
|
|
|
class IR_DecoderRaw;
|
|
class IR_Encoder : public IR_FOX
|
|
{
|
|
friend IR_DecoderRaw;
|
|
static IR_Encoder *head;
|
|
static IR_Encoder *last;
|
|
IR_Encoder *next;
|
|
public:
|
|
static HardwareTimer* IR_Timer;
|
|
|
|
struct IR_TxGateRun {
|
|
uint16_t lenTicks; // number of timer ticks at carrierFrec*2
|
|
bool gate; // true: carrier enabled (output toggles), false: silent (output forced low)
|
|
};
|
|
|
|
using ExternalTxBusyFn = bool (*)(void *ctx);
|
|
using ExternalTxStartFn = bool (*)(void *ctx, IR_Encoder *enc, const uint8_t *packet, uint8_t len);
|
|
private:
|
|
// uint16_t id; /// @brief Адрес передатчика
|
|
public:
|
|
/// @brief Класс передатчика
|
|
/// @param addr Адрес передатчика
|
|
/// @param pin Вывод передатчика
|
|
/// @param decPair Приёмник, для которого отключается приём в момент передачи передатчиком
|
|
IR_Encoder(uint8_t pin, uint16_t addr = 0, IR_DecoderRaw *decPair = nullptr, bool autoHandle = true);
|
|
static void isr();
|
|
static void begin(HardwareTimer* timer, uint8_t channel, IRQn_Type IRQn, uint8_t priority, void(*isrCallback)() = nullptr);
|
|
/** Configure timer frequency for TX clock (carrierFrec*2) without attaching ISR. */
|
|
static void beginClockOnly(HardwareTimer *timer);
|
|
static HardwareTimer* get_IR_Timer();
|
|
/** Call from main loop/tick: if ISR requested carrier stop, pause timer here (not in ISR). */
|
|
static void tick();
|
|
|
|
/** Optional: register external TX backend (e.g. DMA driver). */
|
|
static void setExternalTxBackend(ExternalTxStartFn startFn, ExternalTxBusyFn busyFn, void *ctx);
|
|
|
|
/** Called by external TX backend on actual end of transmission. */
|
|
void externalFinishSend();
|
|
|
|
/** Build RLE runs of carrier gate for a packet (no HW access). */
|
|
static size_t buildGateRuns(const uint8_t *packet, uint8_t len, IR_TxGateRun *outRuns, size_t maxRuns);
|
|
|
|
void enable();
|
|
void disable();
|
|
|
|
void setBlindDecoders(IR_DecoderRaw *decoders[], uint8_t count);
|
|
void rawSend(uint8_t *ptr, uint8_t len);
|
|
|
|
IR_SendResult sendData(uint16_t addrTo, uint8_t dataByte, bool needAccept = false);
|
|
IR_SendResult sendData(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false);
|
|
IR_SendResult sendDataFULL(uint16_t addrFrom, uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false);
|
|
|
|
|
|
IR_SendResult sendAccept(uint16_t addrTo, uint8_t customByte = 0);
|
|
IR_SendResult sendRequest(uint16_t addrTo);
|
|
|
|
IR_SendResult sendBack(uint8_t data);
|
|
IR_SendResult sendBack(uint8_t *data = nullptr, uint8_t len = 0);
|
|
IR_SendResult sendBackTo(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0);
|
|
|
|
// Функция для тестирования времени отправки без фактической отправки
|
|
uint32_t testSendTime(uint16_t addrTo, uint8_t dataByte, bool needAccept = false) const;
|
|
uint32_t testSendTime(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false) const;
|
|
uint32_t testSendTimeFULL(uint16_t addrFrom, uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0, bool needAccept = false) const;
|
|
uint32_t testSendAccept(uint16_t addrTo, uint8_t customByte = 0) const;
|
|
uint32_t testSendRequest(uint16_t addrTo) const;
|
|
uint32_t testSendBack(uint8_t data) const;
|
|
uint32_t testSendBack(uint8_t *data = nullptr, uint8_t len = 0) const;
|
|
uint32_t testSendBackTo(uint16_t addrTo, uint8_t *data = nullptr, uint8_t len = 0) const;
|
|
|
|
inline bool isBusy() const { return isSending;}
|
|
|
|
|
|
~IR_Encoder();
|
|
volatile bool ir_out_virtual;
|
|
|
|
void _isr();
|
|
private:
|
|
static volatile bool carrierStopPending;
|
|
static void carrierResume();
|
|
static void carrierPauseIfIdle();
|
|
|
|
static ExternalTxStartFn externalTxStartFn;
|
|
static ExternalTxBusyFn externalTxBusyFn;
|
|
static void *externalTxCtx;
|
|
IR_SendResult _sendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len);
|
|
|
|
void setDecoder_isSending();
|
|
void sendByte(uint8_t byte, bool *prev, bool LOW_FIRST);
|
|
void addSync(bool *prev, bool *next);
|
|
uint32_t calculateSendTime(uint8_t packSize) const;
|
|
uint32_t testSendBack(bool isAdressed, uint16_t addrTo, uint8_t *data, uint8_t len) const;
|
|
void send_HIGH(bool = 1);
|
|
void send_LOW();
|
|
void send_EMPTY(uint8_t count);
|
|
|
|
enum SignalPart : uint8_t
|
|
{
|
|
noSignal = 0,
|
|
preamb = 1,
|
|
data = 2,
|
|
sync = 3
|
|
};
|
|
|
|
IR_DecoderRaw *decPair;
|
|
IR_DecoderRaw **blindDecoders;
|
|
uint8_t decodersCount;
|
|
|
|
uint8_t sendLen;
|
|
uint8_t sendBuffer[dataByteSizeMax]{0}; /// @brief Буффер данных для отправки
|
|
|
|
volatile bool isSending;
|
|
volatile bool state; /// @brief Текущий уровень генерации
|
|
|
|
volatile uint8_t dataByteCounter;
|
|
|
|
volatile uint8_t toggleCounter; /// @brief Счётчик переключений
|
|
volatile uint8_t dataBitCounter;
|
|
|
|
volatile uint8_t preambFrontCounter;
|
|
volatile uint8_t dataSequenceCounter;
|
|
volatile uint8_t syncSequenceCounter;
|
|
volatile bool syncLastBit;
|
|
|
|
struct BitSequence
|
|
{
|
|
uint8_t low;
|
|
uint8_t high;
|
|
};
|
|
static uint8_t bitHigh[2];
|
|
static uint8_t bitLow[2];
|
|
uint8_t *currentBitSequence = bitLow;
|
|
volatile SignalPart signal;
|
|
};
|