decoder_ioprox.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include "decoder_ioprox.h"
  2. #include <furi_hal.h>
  3. #include <cli/cli.h>
  4. #include <utility>
  5. constexpr uint32_t clocks_in_us = 64;
  6. constexpr uint32_t jitter_time_us = 20;
  7. constexpr uint32_t min_time_us = 64;
  8. constexpr uint32_t max_time_us = 80;
  9. constexpr uint32_t baud_time_us = 500;
  10. constexpr uint32_t min_time = (min_time_us - jitter_time_us) * clocks_in_us;
  11. constexpr uint32_t mid_time = ((max_time_us - min_time_us) / 2 + min_time_us) * clocks_in_us;
  12. constexpr uint32_t max_time = (max_time_us + jitter_time_us) * clocks_in_us;
  13. constexpr uint32_t baud_time = baud_time_us * clocks_in_us;
  14. bool DecoderIoProx::read(uint8_t* data, uint8_t data_size) {
  15. bool result = false;
  16. furi_assert(data_size >= 4);
  17. if(ready) {
  18. result = true;
  19. ioprox.decode(raw_data, sizeof(raw_data), data, data_size);
  20. ready = false;
  21. }
  22. return result;
  23. }
  24. void DecoderIoProx::process_front(bool is_rising_edge, uint32_t time) {
  25. if(ready) {
  26. return;
  27. }
  28. // Always track the time that's gone by.
  29. current_period_duration += time;
  30. demodulation_sample_duration += time;
  31. // If a baud time has elapsed, we're at a sample point.
  32. if(demodulation_sample_duration >= baud_time) {
  33. // Start a new baud period...
  34. demodulation_sample_duration = 0;
  35. demodulated_value_invalid = false;
  36. // ... and if we didn't have any baud errors, capture a sample.
  37. if(!demodulated_value_invalid) {
  38. store_data(current_demodulated_value);
  39. }
  40. }
  41. //
  42. // FSK demodulator.
  43. //
  44. // If this isn't a rising edge, this isn't a pulse of interest.
  45. // We're done.
  46. if(!is_rising_edge) {
  47. return;
  48. }
  49. bool is_valid_low = (current_period_duration > min_time) &&
  50. (current_period_duration <= mid_time);
  51. bool is_valid_high = (current_period_duration > mid_time) &&
  52. (current_period_duration < max_time);
  53. // If this is between the minimum and our threshold, this is a logical 0.
  54. if(is_valid_low) {
  55. current_demodulated_value = false;
  56. }
  57. // Otherwise, if between our threshold and the max time, it's a logical 1.
  58. else if(is_valid_high) {
  59. current_demodulated_value = true;
  60. }
  61. // Otherwise, invalidate this sample.
  62. else {
  63. demodulated_value_invalid = true;
  64. }
  65. // We're starting a new period; track that.
  66. current_period_duration = 0;
  67. }
  68. DecoderIoProx::DecoderIoProx() {
  69. reset_state();
  70. }
  71. void DecoderIoProx::store_data(bool data) {
  72. for(int i = 0; i < 7; ++i) {
  73. raw_data[i] = (raw_data[i] << 1) | ((raw_data[i + 1] >> 7) & 1);
  74. }
  75. raw_data[7] = (raw_data[7] << 1) | data;
  76. if(ioprox.can_be_decoded(raw_data, sizeof(raw_data))) {
  77. ready = true;
  78. }
  79. }
  80. void DecoderIoProx::reset_state() {
  81. current_demodulated_value = false;
  82. demodulated_value_invalid = false;
  83. current_period_duration = 0;
  84. demodulation_sample_duration = 0;
  85. ready = false;
  86. }