signal.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
  2. * See the LICENSE file for information about the license. */
  3. #include "app.h"
  4. void decode_signal(RawSamplesBuffer *s, uint64_t len);
  5. /* =============================================================================
  6. * Raw signal detection
  7. * ===========================================================================*/
  8. /* Return the time difference between a and b, always >= 0 since
  9. * the absolute value is returned. */
  10. uint32_t duration_delta(uint32_t a, uint32_t b) {
  11. return a > b ? a - b : b - a;
  12. }
  13. /* This function starts scanning samples at offset idx looking for the
  14. * longest run of pulses, either high or low, that are among 10%
  15. * of each other, for a maximum of three classes. The classes are
  16. * counted separtely for high and low signals (RF on / off) because
  17. * many devices tend to have different pulse lenghts depending on
  18. * the level of the pulse.
  19. *
  20. * For instance Oregon2 sensors, in the case of protocol 2.1 will send
  21. * pulses of ~400us (RF on) VS ~580us (RF off). */
  22. #define SEARCH_CLASSES 3
  23. uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
  24. struct {
  25. uint32_t dur[2]; /* dur[0] = low, dur[1] = high */
  26. uint32_t count[2]; /* Associated observed frequency. */
  27. } classes[SEARCH_CLASSES];
  28. memset(classes,0,sizeof(classes));
  29. uint32_t minlen = 40, maxlen = 4000; /* Depends on data rate, here we
  30. allow for high and low. */
  31. uint32_t len = 0; /* Observed len of coherent samples. */
  32. s->short_pulse_dur = 0;
  33. for (uint32_t j = idx; j < idx+500; j++) {
  34. bool level;
  35. uint32_t dur;
  36. raw_samples_get(s, j, &level, &dur);
  37. if (dur < minlen || dur > maxlen) break; /* return. */
  38. /* Let's see if it matches a class we already have or if we
  39. * can populate a new (yet empty) class. */
  40. uint32_t k;
  41. for (k = 0; k < SEARCH_CLASSES; k++) {
  42. if (classes[k].count[level] == 0) {
  43. classes[k].dur[level] = dur;
  44. classes[k].count[level] = 1;
  45. break; /* Sample accepted. */
  46. } else {
  47. uint32_t classavg = classes[k].dur[level];
  48. uint32_t count = classes[k].count[level];
  49. uint32_t delta = duration_delta(dur,classavg);
  50. if (delta < classavg/10) {
  51. /* It is useful to compute the average of the class
  52. * we are observing. We know how many samples we got so
  53. * far, so we can recompute the average easily.
  54. * By always having a better estimate of the pulse len
  55. * we can avoid missing next samples in case the first
  56. * observed samples are too off. */
  57. classavg = ((classavg * count) + dur) / (count+1);
  58. classes[k].dur[level] = classavg;
  59. classes[k].count[level]++;
  60. break; /* Sample accepted. */
  61. }
  62. }
  63. }
  64. if (k == SEARCH_CLASSES) break; /* No match, return. */
  65. /* If we are here, we accepted this sample. Try with the next
  66. * one. */
  67. len++;
  68. }
  69. /* Update the buffer setting the shortest pulse we found
  70. * among the three classes. This will be used when scaling
  71. * for visualization. */
  72. for (int j = 0; j < SEARCH_CLASSES; j++) {
  73. for (int level = 0; level < 2; level++) {
  74. if (classes[j].dur[level] == 0) continue;
  75. if (classes[j].count[level] < 3) continue;
  76. if (s->short_pulse_dur == 0 ||
  77. s->short_pulse_dur > classes[j].dur[level])
  78. {
  79. s->short_pulse_dur = classes[j].dur[level];
  80. }
  81. }
  82. }
  83. return len;
  84. }
  85. /* Search the buffer with the stored signal (last N samples received)
  86. * in order to find a coherent signal. If a signal that does not appear to
  87. * be just noise is found, it is set in DetectedSamples global signal
  88. * buffer, that is what is rendered on the screen. */
  89. void scan_for_signal(ProtoViewApp *app) {
  90. /* We need to work on a copy: the RawSamples buffer is populated
  91. * by the background thread receiving data. */
  92. RawSamplesBuffer *copy = raw_samples_alloc();
  93. raw_samples_copy(copy,RawSamples);
  94. /* Try to seek on data that looks to have a regular high low high low
  95. * pattern. */
  96. uint32_t minlen = 13; /* Min run of coherent samples. Up to
  97. 12 samples it's very easy to mistake
  98. noise for signal. */
  99. uint32_t i = 0;
  100. while (i < copy->total-1) {
  101. uint32_t thislen = search_coherent_signal(copy,i);
  102. if (thislen > minlen && thislen > app->signal_bestlen) {
  103. app->signal_bestlen = thislen;
  104. raw_samples_copy(DetectedSamples,copy);
  105. DetectedSamples->idx = (DetectedSamples->idx+i)%
  106. DetectedSamples->total;
  107. FURI_LOG_E(TAG, "Displayed sample updated (%d samples)",
  108. (int)thislen);
  109. decode_signal(DetectedSamples,thislen);
  110. }
  111. i += thislen ? thislen : 1;
  112. }
  113. raw_samples_free(copy);
  114. }
  115. /* =============================================================================
  116. * Decoding
  117. *
  118. * The following code will translates the raw singals as received by
  119. * the CC1101 into logical signals: a bitmap of 0s and 1s sampled at
  120. * the detected data clock interval.
  121. *
  122. * Then the converted signal is passed to the protocols decoders, that look
  123. * for protocol-specific information. We stop at the first decoder that is
  124. * able to decode the data, so protocols here should be registered in
  125. * order of complexity and specificity, with the generic ones at the end.
  126. * ===========================================================================*/
  127. /* Set the 'bitpos' bit to value 'val', in the specified bitmap
  128. * 'b' of len 'blen'.
  129. * Out of range bits will silently be discarded. */
  130. void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val) {
  131. uint32_t byte = bitpos/8;
  132. uint32_t bit = bitpos&7;
  133. if (byte >= blen) return;
  134. if (val)
  135. b[byte] |= 1<<bit;
  136. else
  137. b[byte] &= ~(1<<bit);
  138. }
  139. /* Get the bit 'bitpos' of the bitmap 'b' of 'blen' bytes.
  140. * Out of range bits return false (not bit set). */
  141. bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos) {
  142. uint32_t byte = bitpos/8;
  143. uint32_t bit = bitpos&7;
  144. if (byte >= blen) return 0;
  145. return (b[byte] & (1<<bit)) != 0;
  146. }
  147. /* Return true if the specified sequence of bits, provided as a string in the
  148. * form "11010110..." is found in the 'b' bitmap of 'blen' bits at 'bitpos'
  149. * position. */
  150. bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits) {
  151. size_t l = strlen(bits);
  152. for (size_t j = 0; j < l; j++) {
  153. bool expected = (bits[j] == '1') ? true : false;
  154. if (bitmap_get(b,blen,bitpos+j) != expected) return false;
  155. }
  156. return true;
  157. }
  158. /* Search for the specified bit sequence (see bitmap_match_bits() for details)
  159. * in the bitmap 'b' of 'blen' bytes. Returns the offset (in bits) of the
  160. * match, or BITMAP_SEEK_NOT_FOUND if not found.
  161. *
  162. * Note: there are better algorithms, such as Boyer-Moore. Here we hope that
  163. * for the kind of patterns we search we'll have a lot of early stops so
  164. * we use a vanilla approach. */
  165. uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, const char *bits) {
  166. uint32_t endpos = blen*8;
  167. for (uint32_t j = startpos; j < endpos; j++)
  168. if (bitmap_match_bits(b,blen,j,bits)) return j;
  169. return BITMAP_SEEK_NOT_FOUND;
  170. }
  171. /* Take the raw signal and turn it into a sequence of bits inside the
  172. * buffer 'b'. Note that such 0s and 1s are NOT the actual data in the
  173. * signal, but is just a low level representation of the line code. Basically
  174. * if the short pulse we find in the signal is 320us, we convert high and
  175. * low levels in the raw sample in this way:
  176. *
  177. * If for instance we see a high level lasting ~600 us, we will add
  178. * two 1s bit. If then the signal goes down for 330us, we will add one zero,
  179. * and so forth. So for each period of high and low we find the closest
  180. * multiple and set the relevant number of bits.
  181. *
  182. * In case of a short pulse of 320us detected, 320*2 is the closest to a
  183. * high pulse of 600us, so 2 bits will be set.
  184. *
  185. * In other terms what this function does is sampling the signal at
  186. * fixed 'rate' intervals.
  187. *
  188. * This representation makes it simple to decode the signal at a higher
  189. * level later, translating it from Marshal coding or other line codes
  190. * to the actual bits/bytes.
  191. *
  192. * The 'idx' argument marks the detected signal start index into the
  193. * raw samples buffer. The 'count' tells the function how many raw
  194. * samples to convert into bits. The function returns the number of
  195. * bits set into the buffer 'b'. The 'rate' argument, in microseconds, is
  196. * the detected short-pulse duration. We expect the line code to be
  197. * meaningful when interpreted at multiples of 'rate'. */
  198. uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, uint32_t idx, uint32_t count, uint32_t rate) {
  199. if (rate == 0) return 0; /* We can't perform the conversion. */
  200. uint32_t bitpos = 0;
  201. for (uint32_t j = 0; j < count; j++) {
  202. uint32_t dur;
  203. bool level;
  204. raw_samples_get(s, j+idx, &level, &dur);
  205. uint32_t numbits = dur / rate; /* full bits that surely fit. */
  206. uint32_t rest = dur % rate; /* How much we are left with. */
  207. if (rest > rate/2) numbits++; /* There is another one. */
  208. FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", dur,numbits,(int)level);
  209. /* If the signal is too short, let's claim it an interference
  210. * and ignore it completely. */
  211. if (numbits == 0) continue;
  212. while(numbits--) bitmap_set(b,blen,bitpos++,level);
  213. }
  214. return bitpos;
  215. }
  216. /* This function converts the line code used to the final data representation.
  217. * The representation is put inside 'buf', for up to 'buflen' bytes of total
  218. * data. For instance in order to convert manchester I can use "10" and "01"
  219. * as zero and one patterns. It is possible to use "?" inside patterns in
  220. * order to skip certain bits. For instance certain devices encode data twice,
  221. * with each bit encoded in manchester encoding and then in its reversed
  222. * representation. In such a case I could use "10??" and "01??".
  223. *
  224. * The function returns the number of bits converted. It will stop as soon
  225. * as it finds a pattern that does not match zero or one patterns. */
  226. #if 0
  227. uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, const char *zero_pattern, const char *one_pattern)
  228. {
  229. }
  230. #endif
  231. /* Supported protocols go here, with the relevant implementation inside
  232. * protocols/<name>.c */
  233. extern ProtoViewDecoder Oregon2Decoder;
  234. ProtoViewDecoder *Decoders[] = {
  235. &Oregon2Decoder,
  236. NULL
  237. };
  238. /* This function is called when a new signal is detected. It converts it
  239. * to a bitstream, and the calls the protocol specific functions for
  240. * decoding. */
  241. void decode_signal(RawSamplesBuffer *s, uint64_t len) {
  242. uint32_t bitmap_bits_size = 4096*8;
  243. uint32_t bitmap_size = bitmap_bits_size/8;
  244. /* We call the decoders with an offset a few bits before the actual
  245. * signal detected and for a len of a few bits after its end. */
  246. uint32_t before_after_bits = 2;
  247. uint8_t *bitmap = malloc(bitmap_size);
  248. uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_after_bits,len+before_after_bits*2,s->short_pulse_dur);
  249. if (DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */
  250. char *str = malloc(1024);
  251. uint32_t j;
  252. for (j = 0; j < bits && j < 1023; j++) {
  253. str[j] = bitmap_get(bitmap,bitmap_size,j) ? '1' : '0';
  254. }
  255. str[j] = 0;
  256. FURI_LOG_E(TAG, "%lu bits decoded: %s", bits, str);
  257. free(str);
  258. }
  259. /* Try all the decoders available. */
  260. int j = 0;
  261. while(Decoders[j]) {
  262. FURI_LOG_E(TAG, "Calling decoder %s", Decoders[j]->name);
  263. ProtoViewMsgInfo info;
  264. if (Decoders[j]->decode(bitmap,bits,&info)) {
  265. FURI_LOG_E(TAG, "Message detected by %s", Decoders[j]->name);
  266. break;
  267. }
  268. j++;
  269. }
  270. if (Decoders[j] == NULL) FURI_LOG_E(TAG, "No decoding possible");
  271. free(bitmap);
  272. }