lfrfid_worker_modes.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include "lfrfid_worker_i.h"
  4. #include "tools/t5577.h"
  5. #include <stream_buffer.h>
  6. #include <toolbox/pulse_protocols/pulse_glue.h>
  7. #include <toolbox/buffer_stream.h>
  8. #include "tools/varint_pair.h"
  9. #include "tools/bit_lib.h"
  10. #define TAG "LFRFIDWorker"
  11. /**
  12. * if READ_DEBUG_GPIO is defined:
  13. * gpio_ext_pa7 will repeat signal coming from the comparator
  14. * gpio_ext_pa6 will show load on the decoder
  15. */
  16. // #define LFRFID_WORKER_READ_DEBUG_GPIO 1
  17. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  18. #define LFRFID_WORKER_READ_DEBUG_GPIO_VALUE &gpio_ext_pa7
  19. #define LFRFID_WORKER_READ_DEBUG_GPIO_LOAD &gpio_ext_pa6
  20. #endif
  21. #define LFRFID_WORKER_READ_AVERAGE_COUNT 64
  22. #define LFRFID_WORKER_READ_MIN_TIME_US 16
  23. #define LFRFID_WORKER_READ_DROP_TIME_MS 50
  24. #define LFRFID_WORKER_READ_STABILIZE_TIME_MS 450
  25. #define LFRFID_WORKER_READ_SWITCH_TIME_MS 1500
  26. #define LFRFID_WORKER_WRITE_VERIFY_TIME_MS 1500
  27. #define LFRFID_WORKER_WRITE_DROP_TIME_MS 50
  28. #define LFRFID_WORKER_WRITE_TOO_LONG_TIME_MS 10000
  29. #define LFRFID_WORKER_WRITE_MAX_UNSUCCESSFUL_READS 5
  30. #define LFRFID_WORKER_READ_BUFFER_SIZE 512
  31. #define LFRFID_WORKER_READ_BUFFER_COUNT 8
  32. #define LFRFID_WORKER_EMULATE_BUFFER_SIZE 1024
  33. #define LFRFID_WORKER_DELAY_QUANT 50
  34. void lfrfid_worker_delay(LFRFIDWorker* worker, uint32_t milliseconds) {
  35. for(uint32_t i = 0; i < (milliseconds / LFRFID_WORKER_DELAY_QUANT); i++) {
  36. if(lfrfid_worker_check_for_stop(worker)) break;
  37. furi_delay_ms(LFRFID_WORKER_DELAY_QUANT);
  38. }
  39. }
  40. /**************************************************************************************************/
  41. /********************************************** READ **********************************************/
  42. /**************************************************************************************************/
  43. typedef struct {
  44. BufferStream* stream;
  45. VarintPair* pair;
  46. bool ignore_next_pulse;
  47. } LFRFIDWorkerReadContext;
  48. static void lfrfid_worker_read_capture(bool level, uint32_t duration, void* context) {
  49. LFRFIDWorkerReadContext* ctx = context;
  50. // ignore pulse if last pulse was noise
  51. if(ctx->ignore_next_pulse) {
  52. ctx->ignore_next_pulse = false;
  53. return;
  54. }
  55. // ignore noise spikes
  56. if(duration <= LFRFID_WORKER_READ_MIN_TIME_US) {
  57. if(level) {
  58. ctx->ignore_next_pulse = true;
  59. }
  60. varint_pair_reset(ctx->pair);
  61. return;
  62. }
  63. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  64. furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, level);
  65. #endif
  66. BaseType_t xHigherPriorityTaskWoken = pdFALSE;
  67. bool need_to_send = varint_pair_pack(ctx->pair, level, duration);
  68. if(need_to_send) {
  69. buffer_stream_send_from_isr(
  70. ctx->stream,
  71. varint_pair_get_data(ctx->pair),
  72. varint_pair_get_size(ctx->pair),
  73. &xHigherPriorityTaskWoken);
  74. varint_pair_reset(ctx->pair);
  75. }
  76. portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
  77. }
  78. typedef enum {
  79. LFRFIDWorkerReadOK,
  80. LFRFIDWorkerReadExit,
  81. LFRFIDWorkerReadTimeout,
  82. } LFRFIDWorkerReadState;
  83. static LFRFIDWorkerReadState lfrfid_worker_read_internal(
  84. LFRFIDWorker* worker,
  85. LFRFIDFeature feature,
  86. uint32_t timeout,
  87. ProtocolId* result_protocol) {
  88. LFRFIDWorkerReadState state = LFRFIDWorkerReadTimeout;
  89. furi_hal_rfid_pins_read();
  90. if(feature & LFRFIDFeatureASK) {
  91. furi_hal_rfid_tim_read(125000, 0.5);
  92. FURI_LOG_D(TAG, "Start ASK");
  93. if(worker->read_cb) {
  94. worker->read_cb(LFRFIDWorkerReadStartASK, PROTOCOL_NO, worker->cb_ctx);
  95. }
  96. } else {
  97. furi_hal_rfid_tim_read(62500, 0.25);
  98. FURI_LOG_D(TAG, "Start PSK");
  99. if(worker->read_cb) {
  100. worker->read_cb(LFRFIDWorkerReadStartPSK, PROTOCOL_NO, worker->cb_ctx);
  101. }
  102. }
  103. furi_hal_rfid_tim_read_start();
  104. // stabilize detector
  105. lfrfid_worker_delay(worker, LFRFID_WORKER_READ_STABILIZE_TIME_MS);
  106. protocol_dict_decoders_start(worker->protocols);
  107. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  108. furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, GpioModeOutputPushPull);
  109. furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeOutputPushPull);
  110. #endif
  111. LFRFIDWorkerReadContext ctx;
  112. ctx.pair = varint_pair_alloc();
  113. ctx.stream =
  114. buffer_stream_alloc(LFRFID_WORKER_READ_BUFFER_SIZE, LFRFID_WORKER_READ_BUFFER_COUNT);
  115. furi_hal_rfid_tim_read_capture_start(lfrfid_worker_read_capture, &ctx);
  116. *result_protocol = PROTOCOL_NO;
  117. ProtocolId last_protocol = PROTOCOL_NO;
  118. size_t last_size = protocol_dict_get_max_data_size(worker->protocols);
  119. uint8_t* last_data = malloc(last_size);
  120. uint8_t* protocol_data = malloc(last_size);
  121. size_t last_read_count = 0;
  122. uint32_t switch_os_tick_last = furi_get_tick();
  123. uint32_t average_duration = 0;
  124. uint32_t average_pulse = 0;
  125. size_t average_index = 0;
  126. bool card_detected = false;
  127. FURI_LOG_D(TAG, "Read started");
  128. while(true) {
  129. if(lfrfid_worker_check_for_stop(worker)) {
  130. state = LFRFIDWorkerReadExit;
  131. break;
  132. }
  133. Buffer* buffer = buffer_stream_receive(ctx.stream, 100);
  134. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  135. furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, true);
  136. #endif
  137. if(buffer_stream_get_overrun_count(ctx.stream) > 0) {
  138. FURI_LOG_E(TAG, "Read overrun, recovering");
  139. buffer_stream_reset(ctx.stream);
  140. continue;
  141. }
  142. if(buffer == NULL) {
  143. continue;
  144. }
  145. size_t size = buffer_get_size(buffer);
  146. uint8_t* data = buffer_get_data(buffer);
  147. size_t index = 0;
  148. while(index < size) {
  149. uint32_t duration;
  150. uint32_t pulse;
  151. size_t tmp_size;
  152. if(!varint_pair_unpack(&data[index], size - index, &pulse, &duration, &tmp_size)) {
  153. FURI_LOG_E(TAG, "can't unpack varint pair");
  154. break;
  155. } else {
  156. index += tmp_size;
  157. average_duration += duration;
  158. average_pulse += pulse;
  159. average_index++;
  160. if(average_index >= LFRFID_WORKER_READ_AVERAGE_COUNT) {
  161. float average = (float)average_pulse / (float)average_duration;
  162. average_pulse = 0;
  163. average_duration = 0;
  164. average_index = 0;
  165. if(worker->read_cb) {
  166. if(average > 0.2 && average < 0.8) {
  167. if(!card_detected) {
  168. card_detected = true;
  169. worker->read_cb(
  170. LFRFIDWorkerReadSenseStart, PROTOCOL_NO, worker->cb_ctx);
  171. }
  172. } else {
  173. if(card_detected) {
  174. card_detected = false;
  175. worker->read_cb(
  176. LFRFIDWorkerReadSenseEnd, PROTOCOL_NO, worker->cb_ctx);
  177. }
  178. }
  179. }
  180. }
  181. ProtocolId protocol = PROTOCOL_NO;
  182. protocol = protocol_dict_decoders_feed_by_feature(
  183. worker->protocols, feature, true, pulse);
  184. if(protocol == PROTOCOL_NO) {
  185. protocol = protocol_dict_decoders_feed_by_feature(
  186. worker->protocols, feature, false, duration - pulse);
  187. }
  188. if(protocol != PROTOCOL_NO) {
  189. // reset switch timer
  190. switch_os_tick_last = furi_get_tick();
  191. size_t protocol_data_size =
  192. protocol_dict_get_data_size(worker->protocols, protocol);
  193. protocol_dict_get_data(
  194. worker->protocols, protocol, protocol_data, protocol_data_size);
  195. // validate protocol
  196. if(protocol == last_protocol &&
  197. memcmp(last_data, protocol_data, protocol_data_size) == 0) {
  198. last_read_count = last_read_count + 1;
  199. size_t validation_count =
  200. protocol_dict_get_validate_count(worker->protocols, protocol);
  201. if(last_read_count >= validation_count) {
  202. state = LFRFIDWorkerReadOK;
  203. *result_protocol = protocol;
  204. break;
  205. }
  206. } else {
  207. if(last_protocol == PROTOCOL_NO && worker->read_cb) {
  208. worker->read_cb(
  209. LFRFIDWorkerReadSenseCardStart, protocol, worker->cb_ctx);
  210. }
  211. last_protocol = protocol;
  212. memcpy(last_data, protocol_data, protocol_data_size);
  213. last_read_count = 0;
  214. }
  215. string_t string_info;
  216. string_init(string_info);
  217. for(uint8_t i = 0; i < protocol_data_size; i++) {
  218. if(i != 0) {
  219. string_cat_printf(string_info, " ");
  220. }
  221. string_cat_printf(string_info, "%02X", protocol_data[i]);
  222. }
  223. FURI_LOG_D(
  224. TAG,
  225. "%s, %d, [%s]",
  226. protocol_dict_get_name(worker->protocols, protocol),
  227. last_read_count,
  228. string_get_cstr(string_info));
  229. string_clear(string_info);
  230. protocol_dict_decoders_start(worker->protocols);
  231. }
  232. }
  233. }
  234. buffer_reset(buffer);
  235. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  236. furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, false);
  237. #endif
  238. if(*result_protocol != PROTOCOL_NO) {
  239. break;
  240. }
  241. if((furi_get_tick() - switch_os_tick_last) > timeout) {
  242. state = LFRFIDWorkerReadTimeout;
  243. break;
  244. }
  245. }
  246. FURI_LOG_D(TAG, "Read stopped");
  247. if(last_protocol != PROTOCOL_NO && worker->read_cb) {
  248. worker->read_cb(LFRFIDWorkerReadSenseCardEnd, last_protocol, worker->cb_ctx);
  249. }
  250. if(card_detected && worker->read_cb) {
  251. worker->read_cb(LFRFIDWorkerReadSenseEnd, last_protocol, worker->cb_ctx);
  252. }
  253. furi_hal_rfid_tim_read_capture_stop();
  254. furi_hal_rfid_tim_read_stop();
  255. furi_hal_rfid_pins_reset();
  256. varint_pair_free(ctx.pair);
  257. buffer_stream_free(ctx.stream);
  258. free(protocol_data);
  259. free(last_data);
  260. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  261. furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, GpioModeAnalog);
  262. furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeAnalog);
  263. #endif
  264. return state;
  265. }
  266. static void lfrfid_worker_mode_read_process(LFRFIDWorker* worker) {
  267. LFRFIDFeature feature = LFRFIDFeatureASK;
  268. ProtocolId read_result = PROTOCOL_NO;
  269. LFRFIDWorkerReadState state;
  270. if(worker->read_type == LFRFIDWorkerReadTypePSKOnly) {
  271. feature = LFRFIDFeaturePSK;
  272. } else {
  273. feature = LFRFIDFeatureASK;
  274. }
  275. if(worker->read_type == LFRFIDWorkerReadTypeAuto) {
  276. while(1) {
  277. // read for a while
  278. state = lfrfid_worker_read_internal(
  279. worker, feature, LFRFID_WORKER_READ_SWITCH_TIME_MS, &read_result);
  280. if(state == LFRFIDWorkerReadOK || state == LFRFIDWorkerReadExit) {
  281. break;
  282. }
  283. // switch to next feature
  284. if(feature == LFRFIDFeatureASK) {
  285. feature = LFRFIDFeaturePSK;
  286. } else {
  287. feature = LFRFIDFeatureASK;
  288. }
  289. lfrfid_worker_delay(worker, LFRFID_WORKER_READ_DROP_TIME_MS);
  290. }
  291. } else {
  292. while(1) {
  293. if(worker->read_type == LFRFIDWorkerReadTypeASKOnly) {
  294. state = lfrfid_worker_read_internal(worker, feature, UINT32_MAX, &read_result);
  295. } else {
  296. state = lfrfid_worker_read_internal(
  297. worker, feature, LFRFID_WORKER_READ_SWITCH_TIME_MS, &read_result);
  298. }
  299. if(state == LFRFIDWorkerReadOK || state == LFRFIDWorkerReadExit) {
  300. break;
  301. }
  302. lfrfid_worker_delay(worker, LFRFID_WORKER_READ_DROP_TIME_MS);
  303. }
  304. }
  305. if(state == LFRFIDWorkerReadOK && worker->read_cb) {
  306. worker->read_cb(LFRFIDWorkerReadDone, read_result, worker->cb_ctx);
  307. }
  308. }
  309. /**************************************************************************************************/
  310. /******************************************** EMULATE *********************************************/
  311. /**************************************************************************************************/
  312. typedef struct {
  313. uint32_t duration[LFRFID_WORKER_EMULATE_BUFFER_SIZE];
  314. uint32_t pulse[LFRFID_WORKER_EMULATE_BUFFER_SIZE];
  315. } LFRFIDWorkerEmulateBuffer;
  316. typedef enum {
  317. HalfTransfer,
  318. TransferComplete,
  319. } LFRFIDWorkerEmulateDMAEvent;
  320. static void lfrfid_worker_emulate_dma_isr(bool half, void* context) {
  321. StreamBufferHandle_t stream = context;
  322. uint32_t flag = half ? HalfTransfer : TransferComplete;
  323. xStreamBufferSendFromISR(stream, &flag, sizeof(uint32_t), pdFALSE);
  324. }
  325. static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
  326. LFRFIDWorkerEmulateBuffer* buffer = malloc(sizeof(LFRFIDWorkerEmulateBuffer));
  327. StreamBufferHandle_t stream = xStreamBufferCreate(sizeof(uint32_t), sizeof(uint32_t));
  328. LFRFIDProtocol protocol = worker->protocol;
  329. PulseGlue* pulse_glue = pulse_glue_alloc();
  330. protocol_dict_encoder_start(worker->protocols, protocol);
  331. for(size_t i = 0; i < LFRFID_WORKER_EMULATE_BUFFER_SIZE; i++) {
  332. bool pulse_pop = false;
  333. while(!pulse_pop) {
  334. LevelDuration level_duration =
  335. protocol_dict_encoder_yield(worker->protocols, protocol);
  336. pulse_pop = pulse_glue_push(
  337. pulse_glue,
  338. level_duration_get_level(level_duration),
  339. level_duration_get_duration(level_duration));
  340. }
  341. uint32_t duration, pulse;
  342. pulse_glue_pop(pulse_glue, &duration, &pulse);
  343. buffer->duration[i] = duration - 1;
  344. buffer->pulse[i] = pulse;
  345. }
  346. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  347. furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeOutputPushPull);
  348. #endif
  349. furi_hal_rfid_tim_emulate_dma_start(
  350. buffer->duration,
  351. buffer->pulse,
  352. LFRFID_WORKER_EMULATE_BUFFER_SIZE,
  353. lfrfid_worker_emulate_dma_isr,
  354. stream);
  355. while(true) {
  356. uint32_t flag = 0;
  357. size_t size = xStreamBufferReceive(stream, &flag, sizeof(uint32_t), 100);
  358. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  359. furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, true);
  360. #endif
  361. if(size == sizeof(uint32_t)) {
  362. size_t start = 0;
  363. if(flag == HalfTransfer) {
  364. start = 0;
  365. } else if(flag == TransferComplete) {
  366. start = (LFRFID_WORKER_EMULATE_BUFFER_SIZE / 2);
  367. }
  368. for(size_t i = 0; i < (LFRFID_WORKER_EMULATE_BUFFER_SIZE / 2); i++) {
  369. bool pulse_pop = false;
  370. while(!pulse_pop) {
  371. LevelDuration level_duration =
  372. protocol_dict_encoder_yield(worker->protocols, protocol);
  373. pulse_pop = pulse_glue_push(
  374. pulse_glue,
  375. level_duration_get_level(level_duration),
  376. level_duration_get_duration(level_duration));
  377. }
  378. uint32_t duration, pulse;
  379. pulse_glue_pop(pulse_glue, &duration, &pulse);
  380. buffer->duration[start + i] = duration - 1;
  381. buffer->pulse[start + i] = pulse;
  382. }
  383. }
  384. if(lfrfid_worker_check_for_stop(worker)) {
  385. break;
  386. }
  387. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  388. furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, false);
  389. #endif
  390. }
  391. furi_hal_rfid_tim_emulate_dma_stop();
  392. #ifdef LFRFID_WORKER_READ_DEBUG_GPIO
  393. furi_hal_gpio_init_simple(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, GpioModeAnalog);
  394. #endif
  395. free(buffer);
  396. vStreamBufferDelete(stream);
  397. pulse_glue_free(pulse_glue);
  398. }
  399. /**************************************************************************************************/
  400. /********************************************* WRITE **********************************************/
  401. /**************************************************************************************************/
  402. static void lfrfid_worker_mode_write_process(LFRFIDWorker* worker) {
  403. LFRFIDProtocol protocol = worker->protocol;
  404. LFRFIDWriteRequest* request = malloc(sizeof(LFRFIDWriteRequest));
  405. request->write_type = LFRFIDWriteTypeT5577;
  406. bool can_be_written = protocol_dict_get_write_data(worker->protocols, protocol, request);
  407. uint32_t write_start_time = furi_get_tick();
  408. bool too_long = false;
  409. size_t unsuccessful_reads = 0;
  410. size_t data_size = protocol_dict_get_data_size(worker->protocols, protocol);
  411. uint8_t* verify_data = malloc(data_size);
  412. uint8_t* read_data = malloc(data_size);
  413. protocol_dict_get_data(worker->protocols, protocol, verify_data, data_size);
  414. if(can_be_written) {
  415. while(!lfrfid_worker_check_for_stop(worker)) {
  416. FURI_LOG_D(TAG, "Data write");
  417. t5577_write(&request->t5577);
  418. ProtocolId read_result = PROTOCOL_NO;
  419. LFRFIDWorkerReadState state = lfrfid_worker_read_internal(
  420. worker,
  421. protocol_dict_get_features(worker->protocols, protocol),
  422. LFRFID_WORKER_WRITE_VERIFY_TIME_MS,
  423. &read_result);
  424. if(state == LFRFIDWorkerReadOK) {
  425. protocol_dict_get_data(worker->protocols, protocol, read_data, data_size);
  426. if(memcmp(read_data, verify_data, data_size) == 0) {
  427. if(worker->write_cb) {
  428. worker->write_cb(LFRFIDWorkerWriteOK, worker->cb_ctx);
  429. }
  430. break;
  431. } else {
  432. unsuccessful_reads++;
  433. if(unsuccessful_reads == LFRFID_WORKER_WRITE_MAX_UNSUCCESSFUL_READS) {
  434. if(worker->write_cb) {
  435. worker->write_cb(LFRFIDWorkerWriteFobCannotBeWritten, worker->cb_ctx);
  436. }
  437. }
  438. }
  439. } else if(state == LFRFIDWorkerReadExit) {
  440. break;
  441. }
  442. if(!too_long &&
  443. (furi_get_tick() - write_start_time) > LFRFID_WORKER_WRITE_TOO_LONG_TIME_MS) {
  444. too_long = true;
  445. if(worker->write_cb) {
  446. worker->write_cb(LFRFIDWorkerWriteTooLongToWrite, worker->cb_ctx);
  447. }
  448. }
  449. lfrfid_worker_delay(worker, LFRFID_WORKER_WRITE_DROP_TIME_MS);
  450. }
  451. } else {
  452. if(worker->write_cb) {
  453. worker->write_cb(LFRFIDWorkerWriteProtocolCannotBeWritten, worker->cb_ctx);
  454. }
  455. }
  456. free(request);
  457. free(verify_data);
  458. free(read_data);
  459. }
  460. /**************************************************************************************************/
  461. /******************************************* READ RAW *********************************************/
  462. /**************************************************************************************************/
  463. static void lfrfid_worker_mode_read_raw_process(LFRFIDWorker* worker) {
  464. LFRFIDRawWorker* raw_worker = lfrfid_raw_worker_alloc();
  465. switch(worker->read_type) {
  466. case LFRFIDWorkerReadTypePSKOnly:
  467. lfrfid_raw_worker_start_read(
  468. raw_worker, worker->raw_filename, 62500, 0.25, worker->read_raw_cb, worker->cb_ctx);
  469. break;
  470. case LFRFIDWorkerReadTypeASKOnly:
  471. lfrfid_raw_worker_start_read(
  472. raw_worker, worker->raw_filename, 125000, 0.5, worker->read_raw_cb, worker->cb_ctx);
  473. break;
  474. default:
  475. furi_crash("RAW can be only PSK or ASK");
  476. break;
  477. }
  478. while(!lfrfid_worker_check_for_stop(worker)) {
  479. furi_delay_ms(100);
  480. }
  481. lfrfid_raw_worker_stop(raw_worker);
  482. lfrfid_raw_worker_free(raw_worker);
  483. }
  484. /**************************************************************************************************/
  485. /***************************************** EMULATE RAW ********************************************/
  486. /**************************************************************************************************/
  487. static void lfrfid_worker_mode_emulate_raw_process(LFRFIDWorker* worker) {
  488. LFRFIDRawWorker* raw_worker = lfrfid_raw_worker_alloc();
  489. lfrfid_raw_worker_start_emulate(
  490. raw_worker, worker->raw_filename, worker->emulate_raw_cb, worker->cb_ctx);
  491. while(!lfrfid_worker_check_for_stop(worker)) {
  492. furi_delay_ms(100);
  493. }
  494. lfrfid_raw_worker_stop(raw_worker);
  495. lfrfid_raw_worker_free(raw_worker);
  496. }
  497. /**************************************************************************************************/
  498. /******************************************** MODES ***********************************************/
  499. /**************************************************************************************************/
  500. const LFRFIDWorkerModeType lfrfid_worker_modes[] = {
  501. [LFRFIDWorkerIdle] = {.process = NULL},
  502. [LFRFIDWorkerRead] = {.process = lfrfid_worker_mode_read_process},
  503. [LFRFIDWorkerWrite] = {.process = lfrfid_worker_mode_write_process},
  504. [LFRFIDWorkerEmulate] = {.process = lfrfid_worker_mode_emulate_process},
  505. [LFRFIDWorkerReadRaw] = {.process = lfrfid_worker_mode_read_raw_process},
  506. [LFRFIDWorkerEmulateRaw] = {.process = lfrfid_worker_mode_emulate_raw_process},
  507. };