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 ++++++++++++++++++++++++++++++++++++++++++++++ src/radio-controller.cpp | 66 ++++++++++++++++++++++++++-- 4 files changed, 229 insertions(+), 35 deletions(-) create mode 100644 include/script_decoder.h 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 diff --git a/src/radio-controller.cpp b/src/radio-controller.cpp index e4218cc..11da06f 100644 --- a/src/radio-controller.cpp +++ b/src/radio-controller.cpp @@ -1,5 +1,6 @@ #include "decoder.h" -#include "samsung_decoder.h" +//#include "samsung_decoder.h" +#include "script_decoder.h" #include #include @@ -12,7 +13,10 @@ #include "misc.h" using mcu::arm::mutex; -using namespace radio_controller; +using radio_controller::sample_iterator; +using radio_controller::sample; +using radio_controller::instruction; +using radio_controller::script_decoder; extern IWDG_HandleTypeDef hiwdg; extern TIM_HandleTypeDef htim1; @@ -195,12 +199,42 @@ void main_post_init() static uint32_t tick_next = 0; +radio_controller::end end; + +/* +static const radio_controller::start samsung_start{9000, 4500}; +static const radio_controller::data samsung_data{2250, 560, 1125, 560}; + +static const instruction *const samsung_instructions[] = { + &samsung_start, + &samsung_data, + &end, +}; +*/ + +// NEC? +static const radio_controller::start nec_start{13500, 9000}; +static const radio_controller::data nec_data{2250, 560, 1125, 560}; + +static const instruction *const nec_instructions[] = { + &nec_start, + &nec_data, &nec_data, &nec_data, &nec_data, + &nec_data, &nec_data, &nec_data, &nec_data, + &nec_data, &nec_data, &nec_data, &nec_data, + &nec_data, &nec_data, &nec_data, &nec_data, + &nec_data, &nec_data, &nec_data, &nec_data, + &nec_data, &nec_data, &nec_data, &nec_data, + &nec_data, &nec_data, &nec_data, &nec_data, + &nec_data, &nec_data, &nec_data, &nec_data, + &end, +}; + void main_loop() { auto now = HAL_GetTick(); if (now >= tick_next) { - printf("now=%" PRIu32 "\n", now); +// printf("now=%" PRIu32 "\n", now); // auto *str = "1234567890\n"; // CDC_Transmit_FS(const_cast(reinterpret_cast(str)), 5); @@ -234,6 +268,7 @@ void main_loop() HAL_NVIC_DisableIRQ(TIM2_IRQn); + /* samsung_decoder d; auto it = ir_buffer.iterator(); auto result = d.decode(&it); @@ -252,6 +287,31 @@ void main_loop() printf("Samsung: Manufacturer=%" PRIu32 ", 0x%" PRIx32 ", command=%" PRIu32 ", 0x%" PRIx32 "\n", manufacturer, manufacturer, command, command); } + */ + +// script_decoder sd{samsung_instructions, SizeOfArray(samsung_instructions_)}; + script_decoder sd{nec_instructions, SizeOfArray(nec_instructions)}; + + auto it = ir_buffer.iterator(); + auto result = sd.decode(&it); + + if (result.state == radio_controller::decoding_state::FAIL) { + printf("FAIL\n"); + + it.reset(); + while (it.next()) { + auto s = it.value(); + printf("% 5d us % 5d us\n", s.period_us, s.pulse_us); + } + + } else if (result.state == radio_controller::decoding_state::OK) { + printf("OK: size=%d, value: 0x%08" PRIx32 "%08" PRIx32 "\n", result.data.size(), + result.data.u32(1), result.data.u32(0)); +// uint32_t manufacturer = result.data.extract_bits(0, 12); +// uint32_t command = result.data.extract_bits(12, 8); +// printf("Samsung: Manufacturer=%" PRIu32 ", 0x%" PRIx32 ", command=%" PRIu32 ", 0x%" PRIx32 "\n", +// manufacturer, manufacturer, command, command); + } ir_buffer.reset(); ir_buffer_lock.unlock(); -- cgit v1.2.3