#pragma #include #include #include "decoder.h" namespace radio_controller { enum class token_type { START, DATA, SPACE, }; enum class instruction_return { CONTINUE, FAIL, END, }; class instruction { public: virtual instruction_return execute(sample s, bit_string &data) const = 0; }; class start : public instruction { const uint16_t period_us_; const uint16_t pulse_us_; public: start(uint16_t period_us, uint16_t pulse_us) noexcept: period_us_(period_us), pulse_us_(pulse_us) {} instruction_return execute(sample s, bit_string &data) const override { return decoder_ns::check_pulse(s, period_us_, pulse_us_) ? instruction_return::CONTINUE : instruction_return::FAIL; } }; class data : public instruction { const uint16_t one_period_us_; const uint16_t one_pulse_us_; const uint16_t zero_period_us_; const uint16_t zero_pulse_us_; public: data(uint16_t one_period_us, uint16_t one_pulse_us, uint16_t zero_period_us, uint16_t zero_pulse_us) noexcept: one_period_us_(one_period_us), one_pulse_us_(one_pulse_us), zero_period_us_(zero_period_us), zero_pulse_us_(zero_pulse_us) {} instruction_return execute(sample s, bit_string &data) const override { if (decoder_ns::check_pulse(s, one_period_us_, one_pulse_us_)) { data.append(true); return instruction_return::CONTINUE; } if (decoder_ns::check_pulse(s, zero_period_us_, zero_pulse_us_)) { data.append(false); return instruction_return::CONTINUE; } return instruction_return::FAIL; } }; class end : public instruction { public: instruction_return execute(sample s, bit_string &data) const override { return instruction_return::END; } }; class script_decoder : public decoder { const instruction *const *const instructions_; const int count_; public: script_decoder(const instruction *const *const instructions, int count) : instructions_(instructions), count_(count) {} decoding_result decode(sample_iterator *it) override { printf("Script, size=%d\n", it->size()); bit_string data; for (int i = 0; i < count_ && it->next(); i++) { sample s = it->value(); // printf("script: period=%d, pulse=%d\n", s.period_us, s.pulse_us); auto &inst = instructions_[i]; switch (inst->execute(s, data)) { case instruction_return::CONTINUE: break; case instruction_return::END: return decoding_result{decoding_state::OK, data}; case instruction_return::FAIL: return decoding_result{decoding_state::FAIL}; } } return {decoding_state::OK, data}; } }; } // namespace radio_controller