signal.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  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. /* =============================================================================
  6. * Protocols table.
  7. *
  8. * Supported protocols go here, with the relevant implementation inside
  9. * protocols/<name>.c
  10. * ===========================================================================*/
  11. extern ProtoViewDecoder Oregon2Decoder;
  12. extern ProtoViewDecoder B4B1Decoder;
  13. extern ProtoViewDecoder RenaultTPMSDecoder;
  14. extern ProtoViewDecoder ToyotaTPMSDecoder;
  15. extern ProtoViewDecoder SchraderTPMSDecoder;
  16. extern ProtoViewDecoder SchraderEG53MA4TPMSDecoder;
  17. extern ProtoViewDecoder CitroenTPMSDecoder;
  18. extern ProtoViewDecoder FordTPMSDecoder;
  19. extern ProtoViewDecoder KeeloqDecoder;
  20. extern ProtoViewDecoder ProtoViewChatDecoder;
  21. extern ProtoViewDecoder UnknownDecoder;
  22. ProtoViewDecoder* Decoders[] = {
  23. &Oregon2Decoder, /* Oregon sensors v2.1 protocol. */
  24. &B4B1Decoder, /* PT, SC, ... 24 bits remotes. */
  25. &RenaultTPMSDecoder, /* Renault TPMS. */
  26. &ToyotaTPMSDecoder, /* Toyota TPMS. */
  27. &SchraderTPMSDecoder, /* Schrader TPMS. */
  28. &SchraderEG53MA4TPMSDecoder, /* Schrader EG53MA4 TPMS. */
  29. &CitroenTPMSDecoder, /* Citroen TPMS. */
  30. &FordTPMSDecoder, /* Ford TPMS. */
  31. &KeeloqDecoder, /* Keeloq remote. */
  32. &ProtoViewChatDecoder, /* Protoview simple text messages. */
  33. /* Warning: the following decoder must stay at the end of the
  34. * list. Otherwise would detect most signals and prevent the actaul
  35. * decoders from handling them. */
  36. &UnknownDecoder, /* General protocol detector. */
  37. NULL};
  38. /* =============================================================================
  39. * Raw signal detection
  40. * ===========================================================================*/
  41. /* Return the time difference between a and b, always >= 0 since
  42. * the absolute value is returned. */
  43. uint32_t duration_delta(uint32_t a, uint32_t b) {
  44. return a > b ? a - b : b - a;
  45. }
  46. /* Reset the current signal, so that a new one can be detected. */
  47. void reset_current_signal(ProtoViewApp* app) {
  48. app->signal_bestlen = 0;
  49. app->signal_offset = 0;
  50. app->signal_decoded = false;
  51. raw_samples_reset(DetectedSamples);
  52. raw_samples_reset(RawSamples);
  53. free_msg_info(app->msg_info);
  54. app->msg_info = NULL;
  55. }
  56. /* This function starts scanning samples at offset idx looking for the
  57. * longest run of pulses, either high or low, that are not much different
  58. * from each other, for a maximum of three duration classes.
  59. * So for instance 50 successive pulses that are roughly long 340us or 670us
  60. * will be sensed as a coherent signal (example: 312, 361, 700, 334, 667, ...)
  61. *
  62. * The classes are counted separtely for high and low signals (RF on / off)
  63. * because many devices tend to have different pulse lenghts depending on
  64. * the level of the pulse.
  65. *
  66. * For instance Oregon2 sensors, in the case of protocol 2.1 will send
  67. * pulses of ~400us (RF on) VS ~580us (RF off). */
  68. #define SEARCH_CLASSES 3
  69. uint32_t search_coherent_signal(RawSamplesBuffer* s, uint32_t idx, uint32_t min_duration) {
  70. struct {
  71. uint32_t dur[2]; /* dur[0] = low, dur[1] = high */
  72. uint32_t count[2]; /* Associated observed frequency. */
  73. } classes[SEARCH_CLASSES];
  74. memset(classes, 0, sizeof(classes));
  75. // Set a min/max duration limit for samples to be considered part of a
  76. // coherent signal. The maximum length is fixed while the minimum
  77. // is passed as argument, as depends on the data rate and in general
  78. // on the signal to analyze.
  79. uint32_t max_duration = 4000;
  80. uint32_t len = 0; /* Observed len of coherent samples. */
  81. s->short_pulse_dur = 0;
  82. for(uint32_t j = idx; j < idx + s->total; j++) {
  83. bool level;
  84. uint32_t dur;
  85. raw_samples_get(s, j, &level, &dur);
  86. if(dur < min_duration || dur > max_duration) break; /* return. */
  87. /* Let's see if it matches a class we already have or if we
  88. * can populate a new (yet empty) class. */
  89. uint32_t k;
  90. for(k = 0; k < SEARCH_CLASSES; k++) {
  91. if(classes[k].count[level] == 0) {
  92. classes[k].dur[level] = dur;
  93. classes[k].count[level] = 1;
  94. break; /* Sample accepted. */
  95. } else {
  96. uint32_t classavg = classes[k].dur[level];
  97. uint32_t count = classes[k].count[level];
  98. uint32_t delta = duration_delta(dur, classavg);
  99. /* Is the difference in duration between this signal and
  100. * the class we are inspecting less than a given percentage?
  101. * If so, accept this signal. */
  102. if(delta < classavg / 5) { /* 100%/5 = 20%. */
  103. /* It is useful to compute the average of the class
  104. * we are observing. We know how many samples we got so
  105. * far, so we can recompute the average easily.
  106. * By always having a better estimate of the pulse len
  107. * we can avoid missing next samples in case the first
  108. * observed samples are too off. */
  109. classavg = ((classavg * count) + dur) / (count + 1);
  110. classes[k].dur[level] = classavg;
  111. classes[k].count[level]++;
  112. break; /* Sample accepted. */
  113. }
  114. }
  115. }
  116. if(k == SEARCH_CLASSES) break; /* No match, return. */
  117. /* If we are here, we accepted this sample. Try with the next
  118. * one. */
  119. len++;
  120. }
  121. /* Update the buffer setting the shortest pulse we found
  122. * among the three classes. This will be used when scaling
  123. * for visualization. */
  124. uint32_t short_dur[2] = {0, 0};
  125. for(int j = 0; j < SEARCH_CLASSES; j++) {
  126. for(int level = 0; level < 2; level++) {
  127. if(classes[j].dur[level] == 0) continue;
  128. if(classes[j].count[level] < 3) continue;
  129. if(short_dur[level] == 0 || short_dur[level] > classes[j].dur[level]) {
  130. short_dur[level] = classes[j].dur[level];
  131. }
  132. }
  133. }
  134. /* Use the average between high and low short pulses duration.
  135. * Often they are a bit different, and using the average is more robust
  136. * when we do decoding sampling at short_pulse_dur intervals. */
  137. if(short_dur[0] == 0) short_dur[0] = short_dur[1];
  138. if(short_dur[1] == 0) short_dur[1] = short_dur[0];
  139. s->short_pulse_dur = (short_dur[0] + short_dur[1]) / 2;
  140. return len;
  141. }
  142. /* Called when we detect a message. Just blinks when the message was
  143. * not decoded. Vibrates, too, when the message was correctly decoded. */
  144. void notify_signal_detected(ProtoViewApp* app, bool decoded) {
  145. static const NotificationSequence decoded_seq = {
  146. &message_vibro_on,
  147. &message_green_255,
  148. &message_delay_50,
  149. &message_green_0,
  150. &message_vibro_off,
  151. NULL};
  152. static const NotificationSequence unknown_seq = {
  153. &message_red_255, &message_delay_50, &message_red_0, NULL};
  154. if(decoded)
  155. notification_message(app->notification, &decoded_seq);
  156. else
  157. notification_message(app->notification, &unknown_seq);
  158. }
  159. /* Search the source buffer with the stored signal (last N samples received)
  160. * in order to find a coherent signal. If a signal that does not appear to
  161. * be just noise is found, it is set in DetectedSamples global signal
  162. * buffer, that is what is rendered on the screen. */
  163. void scan_for_signal(ProtoViewApp* app, RawSamplesBuffer* source, uint32_t min_duration) {
  164. /* We need to work on a copy: the source buffer may be populated
  165. * by the background thread receiving data. */
  166. RawSamplesBuffer* copy = raw_samples_alloc();
  167. raw_samples_copy(copy, source);
  168. /* Try to seek on data that looks to have a regular high low high low
  169. * pattern. */
  170. uint32_t minlen = 18; /* Min run of coherent samples. With less
  171. than a few samples it's very easy to
  172. mistake noise for signal. */
  173. uint32_t i = 0;
  174. while(i < copy->total - 1) {
  175. uint32_t thislen = search_coherent_signal(copy, i, min_duration);
  176. /* For messages that are long enough, attempt decoding. */
  177. if(thislen > minlen) {
  178. /* Allocate the message information that some decoder may
  179. * fill, in case it is able to decode a message. */
  180. ProtoViewMsgInfo* info = malloc(sizeof(ProtoViewMsgInfo));
  181. init_msg_info(info, app);
  182. info->short_pulse_dur = copy->short_pulse_dur;
  183. uint32_t saved_idx = copy->idx; /* Save index, see later. */
  184. /* decode_signal() expects the detected signal to start
  185. * from index zero .*/
  186. raw_samples_center(copy, i);
  187. bool decoded = decode_signal(copy, thislen, info);
  188. copy->idx = saved_idx; /* Restore the index as we are scanning
  189. the signal in the loop. */
  190. /* Accept this signal as the new signal if either it's longer
  191. * than the previous undecoded one, or the previous one was
  192. * unknown and this is decoded. */
  193. bool oldsignal_not_decoded = app->signal_decoded == false ||
  194. app->msg_info->decoder == &UnknownDecoder;
  195. if(oldsignal_not_decoded &&
  196. (thislen > app->signal_bestlen || (decoded && info->decoder != &UnknownDecoder))) {
  197. free_msg_info(app->msg_info);
  198. app->msg_info = info;
  199. app->signal_bestlen = thislen;
  200. app->signal_decoded = decoded;
  201. raw_samples_copy(DetectedSamples, copy);
  202. raw_samples_center(DetectedSamples, i);
  203. FURI_LOG_E(
  204. TAG,
  205. "===> Displayed sample updated (%d samples %lu us)",
  206. (int)thislen,
  207. DetectedSamples->short_pulse_dur);
  208. adjust_raw_view_scale(app, DetectedSamples->short_pulse_dur);
  209. if(app->msg_info->decoder != &UnknownDecoder) notify_signal_detected(app, decoded);
  210. } else {
  211. /* If the structure was not filled, discard it. Otherwise
  212. * now the owner is app->msg_info. */
  213. free_msg_info(info);
  214. }
  215. }
  216. i += thislen ? thislen : 1;
  217. }
  218. raw_samples_free(copy);
  219. }
  220. /* =============================================================================
  221. * Decoding
  222. *
  223. * The following code will translates the raw singals as received by
  224. * the CC1101 into logical signals: a bitmap of 0s and 1s sampled at
  225. * the detected data clock interval.
  226. *
  227. * Then the converted signal is passed to the protocols decoders, that look
  228. * for protocol-specific information. We stop at the first decoder that is
  229. * able to decode the data, so protocols here should be registered in
  230. * order of complexity and specificity, with the generic ones at the end.
  231. * ===========================================================================*/
  232. /* Set the 'bitpos' bit to value 'val', in the specified bitmap
  233. * 'b' of len 'blen'.
  234. * Out of range bits will silently be discarded. */
  235. void bitmap_set(uint8_t* b, uint32_t blen, uint32_t bitpos, bool val) {
  236. uint32_t byte = bitpos / 8;
  237. uint32_t bit = 7 - (bitpos & 7);
  238. if(byte >= blen) return;
  239. if(val)
  240. b[byte] |= 1 << bit;
  241. else
  242. b[byte] &= ~(1 << bit);
  243. }
  244. /* Get the bit 'bitpos' of the bitmap 'b' of 'blen' bytes.
  245. * Out of range bits return false (not bit set). */
  246. bool bitmap_get(uint8_t* b, uint32_t blen, uint32_t bitpos) {
  247. uint32_t byte = bitpos / 8;
  248. uint32_t bit = 7 - (bitpos & 7);
  249. if(byte >= blen) return 0;
  250. return (b[byte] & (1 << bit)) != 0;
  251. }
  252. /* Copy 'count' bits from the bitmap 's' of 'slen' total bytes, to the
  253. * bitmap 'd' of 'dlen' total bytes. The bits are copied starting from
  254. * offset 'soff' of the source bitmap to the offset 'doff' of the
  255. * destination bitmap. */
  256. void bitmap_copy(
  257. uint8_t* d,
  258. uint32_t dlen,
  259. uint32_t doff,
  260. uint8_t* s,
  261. uint32_t slen,
  262. uint32_t soff,
  263. uint32_t count) {
  264. /* If we are byte-aligned in both source and destination, use a fast
  265. * path for the number of bytes we can consume this way. */
  266. if((doff & 7) == 0 && (soff & 7) == 0) {
  267. uint32_t didx = doff / 8;
  268. uint32_t sidx = soff / 8;
  269. while(count > 8 && didx < dlen && sidx < slen) {
  270. d[didx++] = s[sidx++];
  271. count -= 8;
  272. }
  273. doff = didx * 8;
  274. soff = sidx * 8;
  275. /* Note that if we entered this path, the count at the end
  276. * of the loop will be < 8. */
  277. }
  278. /* Copy the bits needed to reach an offset where we can copy
  279. * two half bytes of src to a full byte of destination. */
  280. while(count > 8 && (doff & 7) != 0) {
  281. bool bit = bitmap_get(s, slen, soff++);
  282. bitmap_set(d, dlen, doff++, bit);
  283. count--;
  284. }
  285. /* If we are here and count > 8, we have an offset that is byte aligned
  286. * to the destination bitmap, but not aligned to the source bitmap.
  287. * We can copy fast enough by shifting each two bytes of the original
  288. * bitmap.
  289. *
  290. * This is how it works:
  291. *
  292. * dst:
  293. * +--------+--------+--------+
  294. * | 0 | 1 | 2 |
  295. * | | | | <- data to fill
  296. * +--------+--------+--------+
  297. * ^
  298. * |
  299. * doff = 8
  300. *
  301. * src:
  302. * +--------+--------+--------+
  303. * | 0 | 1 | 2 |
  304. * |hellowor|ld!HELLO|WORLDS!!| <- data to copy
  305. * +--------+--------+--------+
  306. * ^
  307. * |
  308. * soff = 11
  309. *
  310. * skew = 11%8 = 3
  311. * each destination byte in dst will receive:
  312. *
  313. * dst[doff/8] = (src[soff/8] << skew) | (src[soff/8+1] >> (8-skew))
  314. *
  315. * dstbyte = doff/8 = 8/8 = 1
  316. * srcbyte = soff/8 = 11/8 = 1
  317. *
  318. * so dst[1] will get:
  319. * src[1] << 3, that is "ld!HELLO" << 3 = "HELLO..."
  320. * xored with
  321. * src[2] << 5, that is "WORLDS!!" >> 5 = ".....WOR"
  322. * That is "HELLOWOR"
  323. */
  324. if(count > 8) {
  325. uint8_t skew = soff % 8; /* Don't worry, compiler will optimize. */
  326. uint32_t didx = doff / 8;
  327. uint32_t sidx = soff / 8;
  328. while(count > 8 && didx < dlen && sidx < slen) {
  329. d[didx] = ((s[sidx] << skew) | (s[sidx + 1] >> (8 - skew)));
  330. sidx++;
  331. didx++;
  332. soff += 8;
  333. doff += 8;
  334. count -= 8;
  335. }
  336. }
  337. /* Here count is guaranteed to be < 8.
  338. * Copy the final bits bit by bit. */
  339. while(count) {
  340. bool bit = bitmap_get(s, slen, soff++);
  341. bitmap_set(d, dlen, doff++, bit);
  342. count--;
  343. }
  344. }
  345. /* We decode bits assuming the first bit we receive is the MSB
  346. * (see bitmap_set/get functions). Certain devices send data
  347. * encoded in the reverse way. */
  348. void bitmap_reverse_bytes_bits(uint8_t* p, uint32_t len) {
  349. for(uint32_t j = 0; j < len; j++) {
  350. uint32_t b = p[j];
  351. /* Step 1: swap the two nibbles: 12345678 -> 56781234 */
  352. b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
  353. /* Step 2: swap adjacent pairs : 56781234 -> 78563412 */
  354. b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
  355. /* Step 3: swap adjacent bits : 78563412 -> 87654321 */
  356. b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
  357. p[j] = b;
  358. }
  359. }
  360. /* Return true if the specified sequence of bits, provided as a string in the
  361. * form "11010110..." is found in the 'b' bitmap of 'blen' bits at 'bitpos'
  362. * position. */
  363. bool bitmap_match_bits(uint8_t* b, uint32_t blen, uint32_t bitpos, const char* bits) {
  364. for(size_t j = 0; bits[j]; j++) {
  365. bool expected = (bits[j] == '1') ? true : false;
  366. if(bitmap_get(b, blen, bitpos + j) != expected) return false;
  367. }
  368. return true;
  369. }
  370. /* Search for the specified bit sequence (see bitmap_match_bits() for details)
  371. * in the bitmap 'b' of 'blen' bytes, looking forward at most 'maxbits' ahead.
  372. * Returns the offset (in bits) of the match, or BITMAP_SEEK_NOT_FOUND if not
  373. * found.
  374. *
  375. * Note: there are better algorithms, such as Boyer-Moore. Here we hope that
  376. * for the kind of patterns we search we'll have a lot of early stops so
  377. * we use a vanilla approach. */
  378. uint32_t bitmap_seek_bits(
  379. uint8_t* b,
  380. uint32_t blen,
  381. uint32_t startpos,
  382. uint32_t maxbits,
  383. const char* bits) {
  384. uint32_t endpos = startpos + blen * 8;
  385. uint32_t end2 = startpos + maxbits;
  386. if(end2 < endpos) endpos = end2;
  387. for(uint32_t j = startpos; j < endpos; j++)
  388. if(bitmap_match_bits(b, blen, j, bits)) return j;
  389. return BITMAP_SEEK_NOT_FOUND;
  390. }
  391. /* Compare bitmaps b1 and b2 (possibly overlapping or the same bitmap),
  392. * at the specified offsets, for cmplen bits. Returns true if the
  393. * exact same bits are found, otherwise false. */
  394. bool bitmap_match_bitmap(
  395. uint8_t* b1,
  396. uint32_t b1len,
  397. uint32_t b1off,
  398. uint8_t* b2,
  399. uint32_t b2len,
  400. uint32_t b2off,
  401. uint32_t cmplen) {
  402. for(uint32_t j = 0; j < cmplen; j++) {
  403. bool bit1 = bitmap_get(b1, b1len, b1off + j);
  404. bool bit2 = bitmap_get(b2, b2len, b2off + j);
  405. if(bit1 != bit2) return false;
  406. }
  407. return true;
  408. }
  409. /* Convert 'len' bitmap bits of the bitmap 'bitmap' into a null terminated
  410. * string, stored at 'dst', that must have space at least for len+1 bytes.
  411. * The bits are extracted from the specified offset. */
  412. void bitmap_to_string(char* dst, uint8_t* b, uint32_t blen, uint32_t off, uint32_t len) {
  413. for(uint32_t j = 0; j < len; j++) dst[j] = bitmap_get(b, blen, off + j) ? '1' : '0';
  414. dst[len] = 0;
  415. }
  416. /* Set the pattern 'pat' into the bitmap 'b' of max length 'blen' bytes,
  417. * starting from the specified offset.
  418. *
  419. * The pattern is given as a string of 0s and 1s characters, like "01101001".
  420. * This function is useful in order to set the test vectors in the protocol
  421. * decoders, to see if the decoding works regardless of the fact we are able
  422. * to actually receive a given signal. */
  423. void bitmap_set_pattern(uint8_t* b, uint32_t blen, uint32_t off, const char* pat) {
  424. uint32_t i = 0;
  425. while(pat[i]) {
  426. bitmap_set(b, blen, i + off, pat[i] == '1');
  427. i++;
  428. }
  429. }
  430. /* Take the raw signal and turn it into a sequence of bits inside the
  431. * buffer 'b'. Note that such 0s and 1s are NOT the actual data in the
  432. * signal, but is just a low level representation of the line code. Basically
  433. * if the short pulse we find in the signal is 320us, we convert high and
  434. * low levels in the raw sample in this way:
  435. *
  436. * If for instance we see a high level lasting ~600 us, we will add
  437. * two 1s bit. If then the signal goes down for 330us, we will add one zero,
  438. * and so forth. So for each period of high and low we find the closest
  439. * multiple and set the relevant number of bits.
  440. *
  441. * In case of a short pulse of 320us detected, 320*2 is the closest to a
  442. * high pulse of 600us, so 2 bits will be set.
  443. *
  444. * In other terms what this function does is sampling the signal at
  445. * fixed 'rate' intervals.
  446. *
  447. * This representation makes it simple to decode the signal at a higher
  448. * level later, translating it from Marshal coding or other line codes
  449. * to the actual bits/bytes.
  450. *
  451. * The 'idx' argument marks the detected signal start index into the
  452. * raw samples buffer. The 'count' tells the function how many raw
  453. * samples to convert into bits. The function returns the number of
  454. * bits set into the buffer 'b'. The 'rate' argument, in microseconds, is
  455. * the detected short-pulse duration. We expect the line code to be
  456. * meaningful when interpreted at multiples of 'rate'. */
  457. uint32_t convert_signal_to_bits(
  458. uint8_t* b,
  459. uint32_t blen,
  460. RawSamplesBuffer* s,
  461. uint32_t idx,
  462. uint32_t count,
  463. uint32_t rate) {
  464. if(rate == 0) return 0; /* We can't perform the conversion. */
  465. uint32_t bitpos = 0;
  466. for(uint32_t j = 0; j < count; j++) {
  467. uint32_t dur;
  468. bool level;
  469. raw_samples_get(s, j + idx, &level, &dur);
  470. uint32_t numbits = dur / rate; /* full bits that surely fit. */
  471. uint32_t rest = dur % rate; /* How much we are left with. */
  472. if(rest > rate / 2) numbits++; /* There is another one. */
  473. /* Limit how much a single sample can spawn. There are likely no
  474. * protocols doing such long pulses when the rate is low. */
  475. if(numbits > 1024) numbits = 1024;
  476. if(0) /* Super verbose, so not under the DEBUG_MSG define. */
  477. FURI_LOG_E(TAG, "%lu converted into %lu (%d) bits", dur, numbits, (int)level);
  478. /* If the signal is too short, let's claim it an interference
  479. * and ignore it completely. */
  480. if(numbits == 0) continue;
  481. while(numbits--) bitmap_set(b, blen, bitpos++, level);
  482. }
  483. return bitpos;
  484. }
  485. /* This function converts the line code used to the final data representation.
  486. * The representation is put inside 'buf', for up to 'buflen' bytes of total
  487. * data. For instance in order to convert manchester you can use "10" and "01"
  488. * as zero and one patterns. However this function does not handle differential
  489. * encodings. See below for convert_from_diff_manchester().
  490. *
  491. * The function returns the number of bits converted. It will stop as soon
  492. * as it finds a pattern that does not match zero or one patterns, or when
  493. * the end of the bitmap pointed by 'bits' is reached (the length is
  494. * specified in bytes by the caller, via the 'len' parameters).
  495. *
  496. * The decoding starts at the specified offset (in bits) 'off'. */
  497. uint32_t convert_from_line_code(
  498. uint8_t* buf,
  499. uint64_t buflen,
  500. uint8_t* bits,
  501. uint32_t len,
  502. uint32_t off,
  503. const char* zero_pattern,
  504. const char* one_pattern) {
  505. uint32_t decoded = 0; /* Number of bits extracted. */
  506. len *= 8; /* Convert bytes to bits. */
  507. while(off < len) {
  508. bool bitval;
  509. if(bitmap_match_bits(bits, len, off, zero_pattern)) {
  510. bitval = false;
  511. off += strlen(zero_pattern);
  512. } else if(bitmap_match_bits(bits, len, off, one_pattern)) {
  513. bitval = true;
  514. off += strlen(one_pattern);
  515. } else {
  516. break;
  517. }
  518. bitmap_set(buf, buflen, decoded++, bitval);
  519. if(decoded / 8 == buflen) break; /* No space left on target buffer. */
  520. }
  521. return decoded;
  522. }
  523. /* Convert the differential Manchester code to bits. This is similar to
  524. * convert_from_line_code() but specific for diff-Manchester. The user must
  525. * supply the value of the previous symbol before this stream, since
  526. * in differential codings the next bits depend on the previous one.
  527. *
  528. * Parameters and return values are like convert_from_line_code(). */
  529. uint32_t convert_from_diff_manchester(
  530. uint8_t* buf,
  531. uint64_t buflen,
  532. uint8_t* bits,
  533. uint32_t len,
  534. uint32_t off,
  535. bool previous) {
  536. uint32_t decoded = 0;
  537. len *= 8; /* Conver to bits. */
  538. for(uint32_t j = off; j < len; j += 2) {
  539. bool b0 = bitmap_get(bits, len, j);
  540. bool b1 = bitmap_get(bits, len, j + 1);
  541. if(b0 == previous) break; /* Each new bit must switch value. */
  542. bitmap_set(buf, buflen, decoded++, b0 == b1);
  543. previous = b1;
  544. if(decoded / 8 == buflen) break; /* No space left on target buffer. */
  545. }
  546. return decoded;
  547. }
  548. /* Free the message info and allocated data. */
  549. void free_msg_info(ProtoViewMsgInfo* i) {
  550. if(i == NULL) return;
  551. fieldset_free(i->fieldset);
  552. free(i->bits);
  553. free(i);
  554. }
  555. /* Reset the message info structure before passing it to the decoding
  556. * functions. */
  557. void init_msg_info(ProtoViewMsgInfo* i, ProtoViewApp* app) {
  558. UNUSED(app);
  559. memset(i, 0, sizeof(ProtoViewMsgInfo));
  560. i->bits = NULL;
  561. i->fieldset = fieldset_new();
  562. }
  563. /* This function is called when a new signal is detected. It converts it
  564. * to a bitstream, and the calls the protocol specific functions for
  565. * decoding. If the signal was decoded correctly by some protocol, true
  566. * is returned. Otherwise false is returned. */
  567. bool decode_signal(RawSamplesBuffer* s, uint64_t len, ProtoViewMsgInfo* info) {
  568. uint32_t bitmap_bits_size = 4096 * 8;
  569. uint32_t bitmap_size = bitmap_bits_size / 8;
  570. /* We call the decoders with an offset a few samples before the actual
  571. * signal detected and for a len of a few bits after its end. */
  572. uint32_t before_samples = 32;
  573. uint32_t after_samples = 100;
  574. uint8_t* bitmap = malloc(bitmap_size);
  575. uint32_t bits = convert_signal_to_bits(
  576. bitmap,
  577. bitmap_size,
  578. s,
  579. -before_samples,
  580. len + before_samples + after_samples,
  581. s->short_pulse_dur);
  582. if(DEBUG_MSG) { /* Useful for debugging purposes. Don't remove. */
  583. char* str = malloc(1024);
  584. uint32_t j;
  585. for(j = 0; j < bits && j < 1023; j++) {
  586. str[j] = bitmap_get(bitmap, bitmap_size, j) ? '1' : '0';
  587. }
  588. str[j] = 0;
  589. FURI_LOG_E(TAG, "%lu bits sampled: %s", bits, str);
  590. free(str);
  591. }
  592. /* Try all the decoders available. */
  593. int j = 0;
  594. bool decoded = false;
  595. while(Decoders[j]) {
  596. uint32_t start_time = furi_get_tick();
  597. decoded = Decoders[j]->decode(bitmap, bitmap_size, bits, info);
  598. uint32_t delta = furi_get_tick() - start_time;
  599. FURI_LOG_E(TAG, "Decoder %s took %lu ms", Decoders[j]->name, (unsigned long)delta);
  600. if(decoded) {
  601. info->decoder = Decoders[j];
  602. break;
  603. }
  604. j++;
  605. }
  606. if(!decoded) {
  607. FURI_LOG_E(TAG, "No decoding possible");
  608. } else {
  609. FURI_LOG_E(TAG, "+++ Decoded %s", info->decoder->name);
  610. /* The message was correctly decoded: fill the info structure
  611. * with the decoded signal. The decoder may not implement offset/len
  612. * filling of the structure. In such case we have no info and
  613. * pulses_count will be set to zero. */
  614. if(info->pulses_count) {
  615. info->bits_bytes = (info->pulses_count + 7) / 8; // Round to full byte.
  616. info->bits = malloc(info->bits_bytes);
  617. bitmap_copy(
  618. info->bits,
  619. info->bits_bytes,
  620. 0,
  621. bitmap,
  622. bitmap_size,
  623. info->start_off,
  624. info->pulses_count);
  625. }
  626. }
  627. free(bitmap);
  628. return decoded;
  629. }