From d30e3fa68d7192da22c1569f56f564b92896170d Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sun, 4 Jun 2017 17:33:51 +0200 Subject: o Working decoder for Samsung remotes. --- CMakeLists.txt | 2 +- include/daewoo_decoder.h | 91 +++++++++++++++++++++++++++++++++++++++++++++++ include/decoder.h | 77 ++++++++++++++++++++++++++++++++++----- include/samsung_decoder.h | 38 -------------------- src/radio-controller.cpp | 39 ++++++++++++++------ 5 files changed, 190 insertions(+), 57 deletions(-) create mode 100644 include/daewoo_decoder.h delete mode 100644 include/samsung_decoder.h diff --git a/CMakeLists.txt b/CMakeLists.txt index de75f5b..307f18d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(CMAKE_CXX_STANDARD 14) include(thirdparty/mcucpp/cmake/mcucpp.cmake) -add_executable(firmware src/radio-controller.cpp include/radio-controller.h) +add_executable(firmware src/radio-controller.cpp include/radio-controller.h include) target_compile_definitions(firmware PUBLIC MCUCMAKE_USING_STM32CUBE=1) target_include_directories(firmware PUBLIC include) target_link_libraries(firmware PUBLIC gcc) diff --git a/include/daewoo_decoder.h b/include/daewoo_decoder.h new file mode 100644 index 0000000..b790a1a --- /dev/null +++ b/include/daewoo_decoder.h @@ -0,0 +1,91 @@ +#pragma + +#include "decoder.h" + +namespace radio_controller { + +class daewoo_decoder : public decoder { + + inline + bool between(uint16_t smallest, uint16_t biggest, uint16_t value) + { + return smallest <= value && value <= biggest; + } + + template + bool check_pulse(sample s) + { +// printf("between(%d, %d, %d) && between(%d, %d, %d)\n", +// int(PeriodTime * 0.8), int(PeriodTime * 1.2), s.period_us, +// int(PulseTime * 0.8), int(PulseTime * 1.2), s.pulse_us); + + return between(uint16_t(PeriodTime * 0.8), uint16_t(PeriodTime * 1.2), s.period_us) && + between(uint16_t(PulseTime * 0.8), uint16_t(PulseTime * 1.2), s.pulse_us); + } + + inline + bool start_bit(sample s) + { + return check_pulse<9000, 4500>(s); + } + + inline + bool one_bit(sample s) + { + return check_pulse<2250, 560>(s); + } + + inline + bool zero_bit(sample s) + { + return check_pulse<1125, 560>(s); + } + + __noinline + void dump_values(sample_iterator *it) { + while (it->next()) { + auto s = it->value(); + auto pct = int(s.pulse_us / double(s.period_us) * 100); + auto type = start_bit(s) ? "start" : one_bit(s) ? "1" : zero_bit(s) ? "0" : "?"; + printf("% 5d us % 5d us, %s\n", s.period_us, s.pulse_us, type); + } + } + +public: + + __noinline + decoding_result decode(sample_iterator *it) override + { + printf("Daewoo, 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}; + } +}; + +} // namespace radio_controller diff --git a/include/decoder.h b/include/decoder.h index 2a8c58e..55e7d96 100644 --- a/include/decoder.h +++ b/include/decoder.h @@ -2,25 +2,86 @@ namespace radio_controller { -template -class iterator { +struct sample { + uint16_t period_us; + uint16_t pulse_us; +}; + +class sample_iterator { public: + virtual int size() = 0; + + virtual void reset() = 0; + virtual bool next() = 0; virtual bool has_next() const = 0; - virtual const T &value() const = 0; + virtual const sample &value() const = 0; }; -struct sample { - uint16_t period_us; - uint16_t pulse_us; +class bit_string final { + uint32_t a_ = 0; + uint32_t b_ = 0; + int size_ = 0; + +public: + int size() const { + return size_; + } + + uint32_t u32(int i) + { + switch (i) { + case 0: + return a_; + case 1: + return b_; + default: + return 0; + } + } + + __noinline + 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, + TOO_SHORT, + BAD_START, + SHORT_BODY +}; + +class decoding_result { +public: + decoding_state state; + bit_string data; + + decoding_result(decoding_state state) : state(state), data() + {} + + decoding_result(decoding_state state, bit_string data) : state(state), data(data) + {} }; -//template class decoder { public: - virtual void decode(iterator *it) = 0; + virtual decoding_result decode(sample_iterator *it) = 0; }; } // namespace radio_controller diff --git a/include/samsung_decoder.h b/include/samsung_decoder.h deleted file mode 100644 index 5d2b555..0000000 --- a/include/samsung_decoder.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma - -#include "decoder.h" - -namespace radio_controller { - -class samsung_decoder : public decoder { - - inline - bool between(uint16_t smallest, uint16_t biggest, uint16_t value) - { - return smallest <= value && value <= biggest; - } - - inline - bool start_bit(uint16_t time) - { - return between(4200, 4700, time); - } - - inline - bool one_bit(uint16_t time) - { - return between(4200, 4700, time); - } - -public: - void decode(iterator *it) override - { - printf("Samsung\n"); - while (it->next()) { - auto s = it->value(); - printf("% 5d us % 5d us, %.02d%%\n", s.period_us, s.pulse_us, int(s.pulse_us / double(s.period_us) * 100)); - } - } -}; - -} // namespace radio_controller diff --git a/src/radio-controller.cpp b/src/radio-controller.cpp index d31f5b7..8d3149c 100644 --- a/src/radio-controller.cpp +++ b/src/radio-controller.cpp @@ -8,7 +8,7 @@ #include "mcu/util.h" #include "misc.h" #include "decoder.h" -#include "samsung_decoder.h" +#include "daewoo_decoder.h" using mcu::arm::mutex; using namespace radio_controller; @@ -22,7 +22,7 @@ mcu::stm32cube::uart::uart_port uart2(&huart2); mcu::stm32cube::debug::dbg<100> dbg(uart2); template -class buffer_iterator : public iterator { +class buffer_iterator : public sample_iterator { const T *values_; const int size_; int idx_; @@ -31,7 +31,16 @@ public: buffer_iterator(const T *values, int size) : values_(values), size_(size), idx_(-1) {}; - __noinline + int size() override + { + return size_; + } + + void reset() override + { + idx_ = -1; + } + bool next() override { if (has_next()) { @@ -224,9 +233,19 @@ void main_loop() HAL_NVIC_DisableIRQ(TIM2_IRQn); - samsung_decoder d; + daewoo_decoder d; auto it = ir_buffer.iterator(); - d.decode(&it); + auto result = d.decode(&it); + + if (result.state == decoding_state::TOO_SHORT) { + printf("Too short\n"); + } else if (result.state == decoding_state::SHORT_BODY) { + printf("Short body\n"); + } else if (result.state == decoding_state::BAD_START) { + printf("Bad start\n"); + } else if (result.state == 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)); + } ir_buffer.reset(); ir_buffer_lock.unlock(); @@ -283,10 +302,10 @@ void ir_rx(TIM_HandleTypeDef *htim) if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { ir_value1 = static_cast(htim->Instance->CCR1); - debug_pin(2); +// debug_pin(2); } else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { ir_value2 = static_cast(htim->Instance->CCR2); - debug_pin(3); +// debug_pin(3); } if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 && ir_buffer.check_first()) { @@ -298,9 +317,9 @@ void ir_rx(TIM_HandleTypeDef *htim) if (ir_buffer_lock.try_lock()) { auto period = values::to_us(ir_value1); auto pulse = values::to_us(ir_value2); - if (ir_buffer.size() == 0) { - debug_pin(5); - } +// if (ir_buffer.size() == 0) { +// debug_pin(5); +// } ir_buffer.append({.period_us=period, .pulse_us=pulse}); ir_buffer_lock.unlock(); -- cgit v1.2.3