signal.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info);
  5. void initialize_msg_info(ProtoViewMsgInfo *i);
  6. /* =============================================================================
  7. * Raw signal detection
  8. * ===========================================================================*/
  9. /* Return the time difference between a and b, always >= 0 since
  10. * the absolute value is returned. */
  11. uint32_t duration_delta(uint32_t a, uint32_t b) {
  12. return a > b ? a - b : b - a;
  13. }
  14. /* Reset the current signal, so that a new one can be detected. */
  15. void reset_current_signal(ProtoViewApp *app) {
  16. app->signal_bestlen = 0;
  17. app->signal_offset = 0;
  18. app->signal_decoded = false;
  19. raw_samples_reset(DetectedSamples);
  20. raw_samples_reset(RawSamples);
  21. }
  22. /* This function starts scanning samples at offset idx looking for the
  23. * longest run of pulses, either high or low, that are not much different
  24. * from each other, for a maximum of three duration classes.
  25. * So for instance 50 successive pulses that are roughly long 340us or 670us
  26. * will be sensed as a coherent signal (example: 312, 361, 700, 334, 667, ...)
  27. *
  28. * The classes are counted separtely for high and low signals (RF on / off)
  29. * because many devices tend to have different pulse lenghts depending on
  30. * the level of the pulse.
  31. *
  32. * For instance Oregon2 sensors, in the case of protocol 2.1 will send
  33. * pulses of ~400us (RF on) VS ~580us (RF off). */
  34. #define SEARCH_CLASSES 3
  35. uint32_t search_coherent_signal(RawSamplesBuffer *s, uint32_t idx) {
  36. struct {
  37. uint32_t dur[2]; /* dur[0] = low, dur[1] = high */
  38. uint32_t count[2]; /* Associated observed frequency. */
  39. } classes[SEARCH_CLASSES];
  40. memset(classes,0,sizeof(classes));
  41. uint32_t minlen = 30, maxlen = 4000; /* Depends on data rate, here we
  42. allow for high and low. */
  43. uint32_t len = 0; /* Observed len of coherent samples. */
  44. s->short_pulse_dur = 0;
  45. for (uint32_t j = idx; j < idx+500; j++) {
  46. bool level;
  47. uint32_t dur;
  48. raw_samples_get(s, j, &level, &dur);
  49. if (dur < minlen || dur > maxlen) break; /* return. */
  50. /* Let's see if it matches a class we already have or if we
  51. * can populate a new (yet empty) class. */
  52. uint32_t k;
  53. for (k = 0; k < SEARCH_CLASSES; k++) {
  54. if (classes[k].count[level] == 0) {
  55. classes[k].dur[level] = dur;
  56. classes[k].count[level] = 1;
  57. break; /* Sample accepted. */
  58. } else {
  59. uint32_t classavg = classes[k].dur[level];
  60. uint32_t count = classes[k].count[level];
  61. uint32_t delta = duration_delta(dur,classavg);
  62. /* Is the difference in duration between this signal and
  63. * the class we are inspecting less than a given percentage?
  64. * If so, accept this signal. */
  65. if (delta < classavg/8) { /* 100%/8 = 12%. */
  66. /* It is useful to compute the average of the class
  67. * we are observing. We know how many samples we got so
  68. * far, so we can recompute the average easily.
  69. * By always having a better estimate of the pulse len
  70. * we can avoid missing next samples in case the first
  71. * observed samples are too off. */
  72. classavg = ((classavg * count) + dur) / (count+1);
  73. classes[k].dur[level] = classavg;
  74. classes[k].count[level]++;
  75. break; /* Sample accepted. */
  76. }
  77. }
  78. }
  79. if (k == SEARCH_CLASSES) break; /* No match, return. */
  80. /* If we are here, we accepted this sample. Try with the next
  81. * one. */
  82. len++;
  83. }
  84. /* Update the buffer setting the shortest pulse we found
  85. * among the three classes. This will be used when scaling
  86. * for visualization. */
  87. uint32_t short_dur[2] = {0,0};
  88. for (int j = 0; j < SEARCH_CLASSES; j++) {
  89. for (int level = 0; level < 2; level++) {
  90. if (classes[j].dur[level] == 0) continue;
  91. if (classes[j].count[level] < 3) continue;
  92. if (short_dur[level] == 0 ||
  93. short_dur[level] > classes[j].dur[level])
  94. {
  95. short_dur[level] = classes[j].dur[level];
  96. }
  97. }
  98. }
  99. /* Use the average between high and low short pulses duration.
  100. * Often they are a bit different, and using the average is more robust
  101. * when we do decoding sampling at short_pulse_dur intervals. */
  102. if (short_dur[0] == 0) short_dur[0] = short_dur[1];
  103. if (short_dur[1] == 0) short_dur[1] = short_dur[0];
  104. s->short_pulse_dur = (short_dur[0]+short_dur[1])/2;
  105. return len;
  106. }
  107. /* Search the buffer with the stored signal (last N samples received)
  108. * in order to find a coherent signal. If a signal that does not appear to
  109. * be just noise is found, it is set in DetectedSamples global signal
  110. * buffer, that is what is rendered on the screen. */
  111. void scan_for_signal(ProtoViewApp *app) {
  112. /* We need to work on a copy: the RawSamples buffer is populated
  113. * by the background thread receiving data. */
  114. RawSamplesBuffer *copy = raw_samples_alloc();
  115. raw_samples_copy(copy,RawSamples);
  116. /* Try to seek on data that looks to have a regular high low high low
  117. * pattern. */
  118. uint32_t minlen = 13; /* Min run of coherent samples. Up to
  119. 12 samples it's very easy to mistake
  120. noise for signal. */
  121. ProtoViewMsgInfo *info = malloc(sizeof(ProtoViewMsgInfo));
  122. uint32_t i = 0;
  123. while (i < copy->total-1) {
  124. uint32_t thislen = search_coherent_signal(copy,i);
  125. /* For messages that are long enough, attempt decoding. */
  126. if (thislen > minlen) {
  127. initialize_msg_info(info);
  128. uint32_t saved_idx = copy->idx; /* Save index, see later. */
  129. /* decode_signal() expects the detected signal to start
  130. * from index .*/
  131. raw_samples_center(copy,i);
  132. bool decoded = decode_signal(copy,thislen,info);
  133. copy->idx = saved_idx; /* Restore the index as we are scanning
  134. the signal in the loop. */
  135. /* Accept this signal as the new signal if either it's longer
  136. * than the previous one, or the previous one was unknown and
  137. * this is decoded. */
  138. if (thislen > app->signal_bestlen ||
  139. (app->signal_decoded == false && decoded))
  140. {
  141. app->signal_info = *info;
  142. app->signal_bestlen = thislen;
  143. app->signal_decoded = decoded;
  144. raw_samples_copy(DetectedSamples,copy);
  145. raw_samples_center(DetectedSamples,i);
  146. FURI_LOG_E(TAG, "Displayed sample updated (%d samples %lu us)",
  147. (int)thislen, DetectedSamples->short_pulse_dur);
  148. }
  149. }
  150. i += thislen ? thislen : 1;
  151. }
  152. raw_samples_free(copy);
  153. free(info);
  154. }
  155. /* =============================================================================
  156. * Decoding
  157. *
  158. * The following code will translates the raw singals as received by
  159. * the CC1101 into logical signals: a bitmap of 0s and 1s sampled at
  160. * the detected data clock interval.
  161. *
  162. * Then the converted signal is passed to the protocols decoders, that look
  163. * for protocol-specific information. We stop at the first decoder that is
  164. * able to decode the data, so protocols here should be registered in
  165. * order of complexity and specificity, with the generic ones at the end.
  166. * ===========================================================================*/
  167. /* Set the 'bitpos' bit to value 'val', in the specified bitmap
  168. * 'b' of len 'blen'.
  169. * Out of range bits will silently be discarded. */
  170. void bitmap_set(uint8_t *b, uint32_t blen, uint32_t bitpos, bool val) {
  171. uint32_t byte = bitpos/8;
  172. uint32_t bit = 7-(bitpos&7);
  173. if (byte >= blen) return;
  174. if (val)
  175. b[byte] |= 1<<bit;
  176. else
  177. b[byte] &= ~(1<<bit);
  178. }
  179. /* Get the bit 'bitpos' of the bitmap 'b' of 'blen' bytes.
  180. * Out of range bits return false (not bit set). */
  181. bool bitmap_get(uint8_t *b, uint32_t blen, uint32_t bitpos) {
  182. uint32_t byte = bitpos/8;
  183. uint32_t bit = 7-(bitpos&7);
  184. if (byte >= blen) return 0;
  185. return (b[byte] & (1<<bit)) != 0;
  186. }
  187. /* We decode bits assuming the first bit we receive is the LSB
  188. * (see bitmap_set/get functions). Many devices send data
  189. * encoded in the reverse way. */
  190. void bitmap_invert_bytes_bits(uint8_t *p, uint32_t len) {
  191. for (uint32_t j = 0; j < len*8; j += 8) {
  192. bool bits[8];
  193. for (int i = 0; i < 8; i++) bits[i] = bitmap_get(p,len,j+i);
  194. for (int i = 0; i < 8; i++) bitmap_set(p,len,j+i,bits[7-i]);
  195. }
  196. }
  197. /* Return true if the specified sequence of bits, provided as a string in the
  198. * form "11010110..." is found in the 'b' bitmap of 'blen' bits at 'bitpos'
  199. * position. */
  200. bool bitmap_match_bits(uint8_t *b, uint32_t blen, uint32_t bitpos, const char *bits) {
  201. size_t l = strlen(bits);
  202. for (size_t j = 0; j < l; j++) {
  203. bool expected = (bits[j] == '1') ? true : false;
  204. if (bitmap_get(b,blen,bitpos+j) != expected) return false;
  205. }
  206. return true;
  207. }
  208. /* Search for the specified bit sequence (see bitmap_match_bits() for details)
  209. * in the bitmap 'b' of 'blen' bytes. Returns the offset (in bits) of the
  210. * match, or BITMAP_SEEK_NOT_FOUND if not found.
  211. *
  212. * Note: there are better algorithms, such as Boyer-Moore. Here we hope that
  213. * for the kind of patterns we search we'll have a lot of early stops so
  214. * we use a vanilla approach. */
  215. uint32_t bitmap_seek_bits(uint8_t *b, uint32_t blen, uint32_t startpos, const char *bits) {
  216. uint32_t endpos = blen*8;
  217. for (uint32_t j = startpos; j < endpos; j++)
  218. if (bitmap_match_bits(b,blen,j,bits)) return j;
  219. return BITMAP_SEEK_NOT_FOUND;
  220. }
  221. /* Set the pattern 'pat' into the bitmap 'b' of max length 'blen' bytes.
  222. * The pattern is given as a string of 0s and 1s characters, like "01101001".
  223. * This function is useful in order to set the test vectors in the protocol
  224. * decoders, to see if the decoding works regardless of the fact we are able
  225. * to actually receive a given signal. */
  226. void bitmap_set_pattern(uint8_t *b, uint32_t blen, const char *pat) {
  227. uint32_t i = 0;
  228. while(pat[i]) {
  229. bitmap_set(b,blen,i,pat[i] == '1');
  230. i++;
  231. }
  232. }
  233. /* Take the raw signal and turn it into a sequence of bits inside the
  234. * buffer 'b'. Note that such 0s and 1s are NOT the actual data in the
  235. * signal, but is just a low level representation of the line code. Basically
  236. * if the short pulse we find in the signal is 320us, we convert high and
  237. * low levels in the raw sample in this way:
  238. *
  239. * If for instance we see a high level lasting ~600 us, we will add
  240. * two 1s bit. If then the signal goes down for 330us, we will add one zero,
  241. * and so forth. So for each period of high and low we find the closest
  242. * multiple and set the relevant number of bits.
  243. *
  244. * In case of a short pulse of 320us detected, 320*2 is the closest to a
  245. * high pulse of 600us, so 2 bits will be set.
  246. *
  247. * In other terms what this function does is sampling the signal at
  248. * fixed 'rate' intervals.
  249. *
  250. * This representation makes it simple to decode the signal at a higher
  251. * level later, translating it from Marshal coding or other line codes
  252. * to the actual bits/bytes.
  253. *
  254. * The 'idx' argument marks the detected signal start index into the
  255. * raw samples buffer. The 'count' tells the function how many raw
  256. * samples to convert into bits. The function returns the number of
  257. * bits set into the buffer 'b'. The 'rate' argument, in microseconds, is
  258. * the detected short-pulse duration. We expect the line code to be
  259. * meaningful when interpreted at multiples of 'rate'. */
  260. uint32_t convert_signal_to_bits(uint8_t *b, uint32_t blen, RawSamplesBuffer *s, uint32_t idx, uint32_t count, uint32_t rate) {
  261. if (rate == 0) return 0; /* We can't perform the conversion. */
  262. uint32_t bitpos = 0;
  263. for (uint32_t j = 0; j < count; j++) {
  264. uint32_t dur;
  265. bool level;
  266. raw_samples_get(s, j+idx, &level, &dur);
  267. uint32_t numbits = dur / rate; /* full bits that surely fit. */
  268. uint32_t rest = dur % rate; /* How much we are left with. */
  269. if (rest > rate/2) numbits++; /* There is another one. */
  270. /* Limit how much a single sample can spawn. There are likely no
  271. * protocols doing such long pulses when the rate is low. */
  272. if (numbits > 1024) numbits = 1024;
  273. if (0) /* Super verbose, so not under the DEBUG_MSG define. */
  274. FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits",
  275. dur,numbits,(int)level);
  276. /* If the signal is too short, let's claim it an interference
  277. * and ignore it completely. */
  278. if (numbits == 0) continue;
  279. while(numbits--) bitmap_set(b,blen,bitpos++,level);
  280. }
  281. return bitpos;
  282. }
  283. /* This function converts the line code used to the final data representation.
  284. * The representation is put inside 'buf', for up to 'buflen' bytes of total
  285. * data. For instance in order to convert manchester I can use "10" and "01"
  286. * as zero and one patterns. It is possible to use "?" inside patterns in
  287. * order to skip certain bits. For instance certain devices encode data twice,
  288. * with each bit encoded in manchester encoding and then in its reversed
  289. * representation. In such a case I could use "10??" and "01??".
  290. *
  291. * The function returns the number of bits converted. It will stop as soon
  292. * as it finds a pattern that does not match zero or one patterns, or when
  293. * the end of the bitmap pointed by 'bits' is reached (the length is
  294. * specified in bytes by the caller, via the 'len' parameters).
  295. *
  296. * The decoding starts at the specified offset (in bits) 'off'. */
  297. uint32_t convert_from_line_code(uint8_t *buf, uint64_t buflen, uint8_t *bits, uint32_t len, uint32_t off, const char *zero_pattern, const char *one_pattern)
  298. {
  299. uint32_t decoded = 0; /* Number of bits extracted. */
  300. len *= 8; /* Convert bytes to bits. */
  301. while(off < len) {
  302. bool bitval;
  303. if (bitmap_match_bits(bits,len,off,zero_pattern)) {
  304. bitval = false;
  305. off += strlen(zero_pattern);
  306. } else if (bitmap_match_bits(bits,len,off,one_pattern)) {
  307. bitval = true;
  308. off += strlen(one_pattern);
  309. } else {
  310. break;
  311. }
  312. bitmap_set(buf,buflen,decoded++,bitval);
  313. if (decoded/8 == buflen) break; /* No space left on target buffer. */
  314. }
  315. return decoded;
  316. }
  317. /* Supported protocols go here, with the relevant implementation inside
  318. * protocols/<name>.c */
  319. extern ProtoViewDecoder Oregon2Decoder;
  320. extern ProtoViewDecoder B4B1Decoder;
  321. extern ProtoViewDecoder RenaultTPMSDecoder;
  322. ProtoViewDecoder *Decoders[] = {
  323. &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */
  324. &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */
  325. &RenaultTPMSDecoder, /* Renault TPMS. */
  326. NULL
  327. };
  328. /* Reset the message info structure before passing it to the decoding
  329. * functions. */
  330. void initialize_msg_info(ProtoViewMsgInfo *i) {
  331. memset(i,0,sizeof(ProtoViewMsgInfo));
  332. }
  333. /* This function is called when a new signal is detected. It converts it
  334. * to a bitstream, and the calls the protocol specific functions for
  335. * decoding. If the signal was decoded correctly by some protocol, true
  336. * is returned. Otherwise false is returned. */
  337. bool decode_signal(RawSamplesBuffer *s, uint64_t len, ProtoViewMsgInfo *info) {
  338. uint32_t bitmap_bits_size = 4096*8;
  339. uint32_t bitmap_size = bitmap_bits_size/8;
  340. /* We call the decoders with an offset a few bits before the actual
  341. * signal detected and for a len of a few bits after its end. */
  342. uint32_t before_after_bits = 2;
  343. uint8_t *bitmap = malloc(bitmap_size);
  344. uint32_t bits = convert_signal_to_bits(bitmap,bitmap_size,s,-before_after_bits,len+before_after_bits*2,s->short_pulse_dur);
  345. if (DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */
  346. char *str = malloc(1024);
  347. uint32_t j;
  348. for (j = 0; j < bits && j < 1023; j++) {
  349. str[j] = bitmap_get(bitmap,bitmap_size,j) ? '1' : '0';
  350. }
  351. str[j] = 0;
  352. FURI_LOG_E(TAG, "%lu bits sampled: %s", bits, str);
  353. free(str);
  354. }
  355. /* Try all the decoders available. */
  356. int j = 0;
  357. bool decoded = false;
  358. while(Decoders[j]) {
  359. FURI_LOG_E(TAG, "Calling decoder %s", Decoders[j]->name);
  360. if (Decoders[j]->decode(bitmap,bitmap_size,bits,info)) {
  361. FURI_LOG_E(TAG, "Message detected by %s", Decoders[j]->name);
  362. decoded = true;
  363. break;
  364. }
  365. j++;
  366. }
  367. if (!decoded) {
  368. FURI_LOG_E(TAG, "No decoding possible");
  369. } else {
  370. FURI_LOG_E(TAG, "Decoded %s, raw=%s info=[%s,%s,%s]", info->name, info->raw, info->info1, info->info2, info->info3);
  371. }
  372. free(bitmap);
  373. return decoded;
  374. }