#pragma once #include #include #include namespace radio_controller { struct sample { uint16_t period_us; uint16_t pulse_us; }; namespace decoder_ns { inline static bool between(uint16_t smallest, uint16_t biggest, uint16_t value) { return smallest <= value && value <= biggest; } inline static bool check_pulse(sample s, uint16_t period_time, uint16_t pulse_time) { printf("check_pulse: between(%d, %d, %d) && between(%d, %d, %d)\n", uint16_t(period_time * 0.8), uint16_t(period_time * 1.2), s.period_us, uint16_t(pulse_time * 0.8), uint16_t(pulse_time * 1.2), s.pulse_us); return between(uint16_t(period_time * 0.8), uint16_t(period_time * 1.2), s.period_us) && between(uint16_t(pulse_time * 0.8), uint16_t(pulse_time * 1.2), s.pulse_us); } } // namespace decoder_ns class sample_iterator { public: virtual int size() = 0; virtual void reset() = 0; virtual bool next() = 0; virtual bool has_next() const = 0; virtual const sample &value() const = 0; }; class bit_string final { uint32_t a_ = 0; uint32_t b_ = 0; int size_ = 0; public: int size() const { return size_; } __attribute__((noinline)) uint32_t extract_bits(int start, int count) { if (start + count > 32) { halt(); } uint32_t value = a_ >> start; auto mask = uint32_t((1 << count + 1) - 1); return value & mask; } uint32_t u32(int i) { switch (i) { case 0: return a_; case 1: return b_; default: return 0; } } void append(bool value) { if (size_ < 32) { if (value) { a_ |= 1 << size_; } } else if (size_ < 64) { if (value) { b_ |= 1 << size_ - 32; } } else { return; } size_++; } }; enum class decoding_state { OK, FAIL, // TOO_SHORT, // BAD_START, // SHORT_BODY, // UNKNOWN_TOKEN, }; class decoding_result { public: decoding_state state; bit_string data; int field1; int field2; int field3; decoding_result() : state(decoding_state::OK), data(), field1(0), field2(0), field3(0) {} void fail() { state = decoding_state::FAIL; } }; class decoder { public: virtual decoding_result decode(sample_iterator &it) = 0; }; } // namespace radio_controller