From d30e3fa68d7192da22c1569f56f564b92896170d Mon Sep 17 00:00:00 2001
From: Trygve Laugstøl <trygvis@inamo.no>
Date: Sun, 4 Jun 2017 17:33:51 +0200
Subject: o Working decoder for Samsung remotes.

---
 include/daewoo_decoder.h  | 91 +++++++++++++++++++++++++++++++++++++++++++++++
 include/decoder.h         | 77 ++++++++++++++++++++++++++++++++++-----
 include/samsung_decoder.h | 38 --------------------
 3 files changed, 160 insertions(+), 46 deletions(-)
 create mode 100644 include/daewoo_decoder.h
 delete mode 100644 include/samsung_decoder.h

(limited to 'include')

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
-- 
cgit v1.2.3