mirror of
https://github.com/Show-maket/IR-protocol.git
synced 2026-09-22 04:49:37 +00:00
136 lines
3.7 KiB
C++
136 lines
3.7 KiB
C++
#pragma once
|
||
|
||
#include "IrFoxProtocolConstants.h"
|
||
#include <cstdint>
|
||
#include <functional>
|
||
|
||
enum IrFoxFrameType : uint8_t
|
||
{
|
||
IRF_FT_DATA_BIT = 1,
|
||
IRF_FT_SYNC_BIT = 2,
|
||
IRF_FT_PACKET_OK = 3,
|
||
IRF_FT_PACKET_CRC_FAIL = 4,
|
||
IRF_FT_OVERFLOW = 5,
|
||
IRF_FT_ABORT = 6,
|
||
IRF_FT_PREAMBLE = 7,
|
||
};
|
||
|
||
/** WithBubble — вызвать on_bit; Quiet — только обновить состояние (для пакета битов с одного фронта). */
|
||
enum class IrFoxEmitBitMode : uint8_t
|
||
{
|
||
WithBubble,
|
||
Quiet,
|
||
};
|
||
|
||
struct IrFoxEmitBit
|
||
{
|
||
int64_t start_sample;
|
||
int64_t end_sample;
|
||
uint8_t frame_type;
|
||
uint64_t bit_value;
|
||
uint64_t bit_index;
|
||
uint8_t mflags;
|
||
bool invert_fix;
|
||
uint8_t err_low;
|
||
uint8_t err_high;
|
||
uint8_t err_other;
|
||
/** Подпись бабла: "0", "1" или склейка "001"; пусто — смотреть bit_value. */
|
||
char bubble_text[32]{};
|
||
};
|
||
|
||
struct IrFoxEmitPacket
|
||
{
|
||
int64_t start_sample;
|
||
int64_t end_sample;
|
||
bool crc_ok;
|
||
uint8_t pack_size;
|
||
uint8_t err_low;
|
||
uint8_t err_high;
|
||
uint8_t err_other;
|
||
uint8_t data_bytes[irfox::kDataByteSizeMax];
|
||
};
|
||
|
||
using IrFoxOnBit = std::function<void(const IrFoxEmitBit&)>;
|
||
using IrFoxOnPacket = std::function<void(const IrFoxEmitPacket&)>;
|
||
|
||
class IrFoxDecoder
|
||
{
|
||
public:
|
||
void reset();
|
||
void processEdge(uint64_t sample, bool rising, uint32_t sample_rate_hz, const IrFoxOnBit& on_bit,
|
||
const IrFoxOnPacket& on_pkt);
|
||
void flushEnd(uint64_t last_sample, uint32_t sample_rate_hz, const IrFoxOnBit& on_bit, const IrFoxOnPacket& on_pkt);
|
||
|
||
private:
|
||
static uint16_t ceil_div_u16(uint16_t val, uint16_t divider);
|
||
static uint8_t crc8(const uint8_t* data, uint8_t start, uint8_t end, uint8_t poly);
|
||
bool crc_check(uint8_t len, uint16_t& crc_out);
|
||
|
||
void first_rx();
|
||
void listen_start(double t_us);
|
||
void check_timeout(double t_us);
|
||
void write_to_buffer(bool bit, bool pack_trace_invert_fix, uint64_t cell_start_s, uint64_t cell_end_s,
|
||
const IrFoxOnBit& on_bit, const IrFoxOnPacket& on_pkt,
|
||
IrFoxEmitBitMode emit_mode = IrFoxEmitBitMode::WithBubble);
|
||
|
||
double sample_to_us(uint64_t sample, uint32_t fs) const { return double(sample) * 1e6 / double(fs); }
|
||
|
||
// --- state (mirror IR_DecoderRaw) ---
|
||
uint8_t data_buffer[irfox::kDataByteSizeMax]{};
|
||
uint8_t err_low_signal = 0;
|
||
uint8_t err_high_signal = 0;
|
||
uint8_t err_other = 0;
|
||
|
||
bool is_available = false;
|
||
uint16_t pack_size = 0;
|
||
uint16_t crc_value = 0;
|
||
bool is_recive = false;
|
||
bool is_recive_raw = false;
|
||
bool is_preamb = false;
|
||
bool is_buffer_overflow = false;
|
||
bool is_wrong_pack = false;
|
||
|
||
uint32_t rise_sync_time_us = irfox::kBitTimeUs;
|
||
|
||
double prev_rise_us = 0;
|
||
double prev_fall_us = 0;
|
||
uint64_t prev_rise_sample = 0;
|
||
uint64_t prev_fall_sample = 0;
|
||
/** Сэмпл предыдущего нарастающего фронта до обновления на текущем тике (граница ячейки бита, см. IR_DecoderRaw::tick). */
|
||
uint64_t rise_period_anchor_sample_ = 0;
|
||
uint64_t preamble_bubble_start_sample_ = 0;
|
||
bool preamble_bubble_start_valid_ = false;
|
||
bool trim_first_data_bit_cell_ = false;
|
||
|
||
double last_edge_time_us = 0;
|
||
uint64_t last_edge_sample = 0;
|
||
double last_processed_edge_us = 0;
|
||
bool have_last_processed = false;
|
||
|
||
void fill_err_snapshot(IrFoxEmitBit& e) const
|
||
{
|
||
e.err_low = err_low_signal;
|
||
e.err_high = err_high_signal;
|
||
e.err_other = err_other;
|
||
}
|
||
|
||
uint32_t rise_period_us = 0;
|
||
uint32_t high_time_us = 0;
|
||
uint32_t low_time_us = 0;
|
||
|
||
int8_t high_count = 0;
|
||
int8_t low_count = 0;
|
||
int8_t all_count = 0;
|
||
|
||
uint16_t wrong_counter = 0;
|
||
int8_t preamb_front_counter = 0;
|
||
int16_t buf_bit_pos = 0;
|
||
bool is_data = true;
|
||
uint16_t i_data_buffer = 0;
|
||
uint16_t next_control_bit = irfox::kBitPerByte;
|
||
uint8_t i_sync_bit = 0;
|
||
uint8_t err_sync_bit = 0;
|
||
uint16_t error_counter = 0;
|
||
uint8_t msg_type_receive = 0;
|
||
};
|