summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2017-06-04 17:33:51 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2017-06-04 17:33:51 +0200
commitd30e3fa68d7192da22c1569f56f564b92896170d (patch)
treefdbfbe53a9c9cb6f5136af53e17f831b069337a2
parenta484b095fb03313f5f192b23c90d04972ca3b957 (diff)
downloadradio-controller-d30e3fa68d7192da22c1569f56f564b92896170d.tar.gz
radio-controller-d30e3fa68d7192da22c1569f56f564b92896170d.tar.bz2
radio-controller-d30e3fa68d7192da22c1569f56f564b92896170d.tar.xz
radio-controller-d30e3fa68d7192da22c1569f56f564b92896170d.zip
o Working decoder for Samsung remotes.
-rw-r--r--CMakeLists.txt2
-rw-r--r--include/daewoo_decoder.h91
-rw-r--r--include/decoder.h77
-rw-r--r--include/samsung_decoder.h38
-rw-r--r--src/radio-controller.cpp39
5 files changed, 190 insertions, 57 deletions
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<uint16_t PeriodTime, uint16_t PulseTime>
+ 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<typename T>
-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<typename T>
class decoder {
public:
- virtual void decode(iterator<sample> *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<sample> *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<typename T>
-class buffer_iterator : public iterator<T> {
+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<uint16_t>(htim->Instance->CCR1);
- debug_pin(2);
+// debug_pin(2);
} else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) {
ir_value2 = static_cast<uint16_t>(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<uint16_t>(ir_value1);
auto pulse = values::to_us<uint16_t>(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();