From 4ee01dab6105e346b731a13321a3e6a5d111d3e4 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 4 Jun 2017 22:14:04 +0200 Subject: o Trying for a more generic decoder structure, should be able to be dynamically programmed later on. o Adding decoder for NEC. --- include/decoder.h | 29 ++++++++++-- include/samsung_decoder.h | 59 +++++++++++++------------ include/script_decoder.h | 110 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 32 deletions(-) create mode 100644 include/script_decoder.h (limited to 'include') diff --git a/include/decoder.h b/include/decoder.h index 9aee34d..4ae723c 100644 --- a/include/decoder.h +++ b/include/decoder.h @@ -2,6 +2,7 @@ #include #include +#include namespace radio_controller { @@ -10,6 +11,26 @@ struct sample { 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; @@ -77,9 +98,11 @@ public: enum class decoding_state { OK, - TOO_SHORT, - BAD_START, - SHORT_BODY + FAIL, +// TOO_SHORT, +// BAD_START, +// SHORT_BODY, +// UNKNOWN_TOKEN, }; class decoding_result { diff --git a/include/samsung_decoder.h b/include/samsung_decoder.h index 52978ec..3e55a94 100644 --- a/include/samsung_decoder.h +++ b/include/samsung_decoder.h @@ -57,35 +57,36 @@ public: decoding_result decode(sample_iterator *it) override { - printf("Samsung, size=%d\n", it->size()); - - dump_values(it); - it->reset(); - - sample s{}; - bit_string data; - - if (!it->next()) { - return {decoding_state::TOO_SHORT}; - } - s = it->value(); - if (!start_bit(s)) { - return {decoding_state::BAD_START}; - } - - for (int i = 0; i < 32 && it->next(); i++) { - s = it->value(); - - if (one_bit(s)) { - data.append(true); - } else if (zero_bit(s)) { - data.append(false); - } else { - return {decoding_state::SHORT_BODY}; - } - } - - return {decoding_state::OK, data}; + return decoding_result{decoding_state::FAIL}; +// printf("Samsung, size=%d\n", it->size()); +// +// dump_values(it); +// it->reset(); +// +// sample s{}; +// bit_string data; +// +// if (!it->next()) { +// return {decoding_state::TOO_SHORT}; +// } +// s = it->value(); +// if (!start_bit(s)) { +// return {decoding_state::BAD_START}; +// } +// +// for (int i = 0; i < 32 && it->next(); i++) { +// s = it->value(); +// +// if (one_bit(s)) { +// data.append(true); +// } else if (zero_bit(s)) { +// data.append(false); +// } else { +// return {decoding_state::SHORT_BODY}; +// } +// } +// +// return {decoding_state::OK, data}; } }; diff --git a/include/script_decoder.h b/include/script_decoder.h new file mode 100644 index 0000000..c3ad281 --- /dev/null +++ b/include/script_decoder.h @@ -0,0 +1,110 @@ +#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 -- cgit v1.2.3