summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2017-06-04 22:14:04 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2017-06-04 22:14:04 +0200
commit4ee01dab6105e346b731a13321a3e6a5d111d3e4 (patch)
treec5e3b6293a16f83f32f348705e946536a1b955d1
parente758988579c3bf058214bf6e4ae56cf27b52bcfb (diff)
downloadradio-controller-4ee01dab6105e346b731a13321a3e6a5d111d3e4.tar.gz
radio-controller-4ee01dab6105e346b731a13321a3e6a5d111d3e4.tar.bz2
radio-controller-4ee01dab6105e346b731a13321a3e6a5d111d3e4.tar.xz
radio-controller-4ee01dab6105e346b731a13321a3e6a5d111d3e4.zip
o Trying for a more generic decoder structure, should be able to be dynamically programmed later on.
o Adding decoder for NEC.
-rw-r--r--include/decoder.h29
-rw-r--r--include/samsung_decoder.h59
-rw-r--r--include/script_decoder.h110
-rw-r--r--src/radio-controller.cpp66
4 files changed, 229 insertions, 35 deletions
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 <cstdint>
#include <mcu/init.h>
+#include <cstdio>
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 <cstdint>
+#include <cstdio>
+#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 <usbd_cdc_if.h>
#include <cinttypes>
@@ -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<uint8_t *>(reinterpret_cast<const uint8_t *>(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();