#pragma #include #include #include "decoder.h" namespace radio_controller { enum class instruction_return { CONTINUE, FAIL, }; class instruction { public: virtual instruction_return execute(sample_iterator &it, decoding_result &res) 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_iterator &it, decoding_result &res) const override { auto s = it.value(); return decoder_ns::check_pulse(s, period_us_, pulse_us_) ? instruction_return::CONTINUE : instruction_return::FAIL; } }; class nop : public instruction { public: instruction_return execute(sample_iterator &it, decoding_result &res) const override { return instruction_return::CONTINUE; } }; class set_field : public instruction { const int field_no; const int bit_offset; const int bit_count; public: set_field(const int field_no, const int bit_offset, const int bit_count) noexcept : field_no(field_no), bit_offset(bit_offset), bit_count(bit_count) {} instruction_return execute(sample_iterator &it, decoding_result &res) const override { auto value = int(res.data.extract_bits(bit_offset, bit_count)); if (field_no == 1) { res.field1 = value; } else if (field_no == 2) { res.field2 = value; } else if (field_no == 3) { res.field3 = value; } else { return instruction_return::FAIL; } return instruction_return::CONTINUE; } }; 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_iterator &it, decoding_result &res) const override { auto s = it.value(); if (decoder_ns::check_pulse(s, one_period_us_, one_pulse_us_)) { res.data.append(true); return instruction_return::CONTINUE; } if (decoder_ns::check_pulse(s, zero_period_us_, zero_pulse_us_)) { res.data.append(false); return instruction_return::CONTINUE; } return instruction_return::FAIL; } }; 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()); decoding_result res; for (int i = 0; i < count_ && it.next(); i++) { sample s = it.value(); auto &inst = instructions_[i]; switch (inst->execute(it, res)) { case instruction_return::CONTINUE: break; case instruction_return::FAIL: res.fail(); return res; } } return res; } }; } // namespace radio_controller