lfrfid_raw_worker.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. #include <furi_hal_rfid.h>
  2. #include <toolbox/stream/file_stream.h>
  3. #include <toolbox/buffer_stream.h>
  4. #include <toolbox/varint.h>
  5. #include "lfrfid_raw_worker.h"
  6. #include "lfrfid_raw_file.h"
  7. #include "tools/varint_pair.h"
  8. #define EMULATE_BUFFER_SIZE 1024
  9. #define RFID_DATA_BUFFER_SIZE 2048
  10. #define READ_DATA_BUFFER_COUNT 4
  11. #define TAG_EMULATE "RAW EMULATE"
  12. // emulate mode
  13. typedef struct {
  14. size_t overrun_count;
  15. FuriStreamBuffer* stream;
  16. } RfidEmulateCtx;
  17. typedef struct {
  18. uint32_t emulate_buffer_arr[EMULATE_BUFFER_SIZE];
  19. uint32_t emulate_buffer_ccr[EMULATE_BUFFER_SIZE];
  20. RfidEmulateCtx ctx;
  21. } LFRFIDRawWorkerEmulateData;
  22. typedef enum {
  23. HalfTransfer,
  24. TransferComplete,
  25. } LFRFIDRawEmulateDMAEvent;
  26. // read mode
  27. #define READ_TEMP_DATA_SIZE 10
  28. typedef struct {
  29. BufferStream* stream;
  30. VarintPair* pair;
  31. } LFRFIDRawWorkerReadData;
  32. // main worker
  33. struct LFRFIDRawWorker {
  34. FuriString* file_path;
  35. FuriThread* thread;
  36. FuriEventFlag* events;
  37. LFRFIDWorkerEmulateRawCallback emulate_callback;
  38. LFRFIDWorkerReadRawCallback read_callback;
  39. void* context;
  40. float frequency;
  41. float duty_cycle;
  42. };
  43. typedef enum {
  44. LFRFIDRawWorkerEventStop,
  45. } LFRFIDRawWorkerEvent;
  46. static int32_t lfrfid_raw_read_worker_thread(void* thread_context);
  47. static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context);
  48. LFRFIDRawWorker* lfrfid_raw_worker_alloc() {
  49. LFRFIDRawWorker* worker = malloc(sizeof(LFRFIDRawWorker));
  50. worker->thread = furi_thread_alloc();
  51. furi_thread_set_name(worker->thread, "lfrfid_raw_worker");
  52. furi_thread_set_context(worker->thread, worker);
  53. furi_thread_set_stack_size(worker->thread, 2048);
  54. worker->events = furi_event_flag_alloc(NULL);
  55. worker->file_path = furi_string_alloc();
  56. return worker;
  57. }
  58. void lfrfid_raw_worker_free(LFRFIDRawWorker* worker) {
  59. furi_thread_free(worker->thread);
  60. furi_event_flag_free(worker->events);
  61. furi_string_free(worker->file_path);
  62. free(worker);
  63. }
  64. void lfrfid_raw_worker_start_read(
  65. LFRFIDRawWorker* worker,
  66. const char* file_path,
  67. float freq,
  68. float duty_cycle,
  69. LFRFIDWorkerReadRawCallback callback,
  70. void* context) {
  71. furi_check(furi_thread_get_state(worker->thread) == FuriThreadStateStopped);
  72. furi_string_set(worker->file_path, file_path);
  73. worker->frequency = freq;
  74. worker->duty_cycle = duty_cycle;
  75. worker->read_callback = callback;
  76. worker->context = context;
  77. furi_thread_set_callback(worker->thread, lfrfid_raw_read_worker_thread);
  78. furi_thread_start(worker->thread);
  79. }
  80. void lfrfid_raw_worker_start_emulate(
  81. LFRFIDRawWorker* worker,
  82. const char* file_path,
  83. LFRFIDWorkerEmulateRawCallback callback,
  84. void* context) {
  85. furi_check(furi_thread_get_state(worker->thread) == FuriThreadStateStopped);
  86. furi_string_set(worker->file_path, file_path);
  87. worker->emulate_callback = callback;
  88. worker->context = context;
  89. furi_thread_set_callback(worker->thread, lfrfid_raw_emulate_worker_thread);
  90. furi_thread_start(worker->thread);
  91. }
  92. void lfrfid_raw_worker_stop(LFRFIDRawWorker* worker) {
  93. worker->emulate_callback = NULL;
  94. worker->context = NULL;
  95. worker->read_callback = NULL;
  96. worker->context = NULL;
  97. furi_event_flag_set(worker->events, 1 << LFRFIDRawWorkerEventStop);
  98. furi_thread_join(worker->thread);
  99. }
  100. static void lfrfid_raw_worker_capture(bool level, uint32_t duration, void* context) {
  101. LFRFIDRawWorkerReadData* ctx = context;
  102. bool need_to_send = varint_pair_pack(ctx->pair, level, duration);
  103. if(need_to_send) {
  104. buffer_stream_send_from_isr(
  105. ctx->stream, varint_pair_get_data(ctx->pair), varint_pair_get_size(ctx->pair));
  106. varint_pair_reset(ctx->pair);
  107. }
  108. }
  109. static int32_t lfrfid_raw_read_worker_thread(void* thread_context) {
  110. LFRFIDRawWorker* worker = (LFRFIDRawWorker*)thread_context;
  111. Storage* storage = furi_record_open(RECORD_STORAGE);
  112. LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage);
  113. const char* filename = furi_string_get_cstr(worker->file_path);
  114. bool file_valid = lfrfid_raw_file_open_write(file, filename);
  115. LFRFIDRawWorkerReadData* data = malloc(sizeof(LFRFIDRawWorkerReadData));
  116. data->stream = buffer_stream_alloc(RFID_DATA_BUFFER_SIZE, READ_DATA_BUFFER_COUNT);
  117. data->pair = varint_pair_alloc();
  118. if(file_valid) {
  119. // write header
  120. file_valid = lfrfid_raw_file_write_header(
  121. file, worker->frequency, worker->duty_cycle, RFID_DATA_BUFFER_SIZE);
  122. }
  123. if(file_valid) {
  124. // setup carrier
  125. furi_hal_rfid_pins_read();
  126. furi_hal_rfid_tim_read(worker->frequency, worker->duty_cycle);
  127. furi_hal_rfid_tim_read_start();
  128. // stabilize detector
  129. furi_delay_ms(1500);
  130. // start capture
  131. furi_hal_rfid_tim_read_capture_start(lfrfid_raw_worker_capture, data);
  132. while(1) {
  133. Buffer* buffer = buffer_stream_receive(data->stream, 100);
  134. if(buffer != NULL) {
  135. file_valid = lfrfid_raw_file_write_buffer(
  136. file, buffer_get_data(buffer), buffer_get_size(buffer));
  137. buffer_reset(buffer);
  138. }
  139. if(!file_valid) {
  140. if(worker->read_callback != NULL) {
  141. // message file_error to worker
  142. worker->read_callback(LFRFIDWorkerReadRawFileError, worker->context);
  143. }
  144. break;
  145. }
  146. if(buffer_stream_get_overrun_count(data->stream) > 0 &&
  147. worker->read_callback != NULL) {
  148. // message overrun to worker
  149. worker->read_callback(LFRFIDWorkerReadRawOverrun, worker->context);
  150. }
  151. uint32_t flags = furi_event_flag_get(worker->events);
  152. if(FURI_BIT(flags, LFRFIDRawWorkerEventStop)) {
  153. break;
  154. }
  155. }
  156. furi_hal_rfid_tim_read_capture_stop();
  157. furi_hal_rfid_tim_read_stop();
  158. } else {
  159. if(worker->read_callback != NULL) {
  160. // message file_error to worker
  161. worker->read_callback(LFRFIDWorkerReadRawFileError, worker->context);
  162. }
  163. }
  164. if(!file_valid) {
  165. const uint32_t available_flags = (1 << LFRFIDRawWorkerEventStop);
  166. while(true) {
  167. uint32_t flags = furi_event_flag_wait(
  168. worker->events, available_flags, FuriFlagWaitAny, FuriWaitForever);
  169. if(FURI_BIT(flags, LFRFIDRawWorkerEventStop)) {
  170. break;
  171. }
  172. }
  173. }
  174. varint_pair_free(data->pair);
  175. buffer_stream_free(data->stream);
  176. lfrfid_raw_file_free(file);
  177. furi_record_close(RECORD_STORAGE);
  178. free(data);
  179. return 0;
  180. }
  181. static void rfid_emulate_dma_isr(bool half, void* context) {
  182. RfidEmulateCtx* ctx = context;
  183. uint32_t flag = half ? HalfTransfer : TransferComplete;
  184. size_t len = furi_stream_buffer_send(ctx->stream, &flag, sizeof(uint32_t), 0);
  185. if(len != sizeof(uint32_t)) {
  186. ctx->overrun_count++;
  187. }
  188. }
  189. static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) {
  190. LFRFIDRawWorker* worker = thread_context;
  191. bool file_valid = true;
  192. LFRFIDRawWorkerEmulateData* data = malloc(sizeof(LFRFIDRawWorkerEmulateData));
  193. Storage* storage = furi_record_open(RECORD_STORAGE);
  194. data->ctx.overrun_count = 0;
  195. data->ctx.stream = furi_stream_buffer_alloc(sizeof(uint32_t), sizeof(uint32_t));
  196. LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage);
  197. do {
  198. file_valid = lfrfid_raw_file_open_read(file, furi_string_get_cstr(worker->file_path));
  199. if(!file_valid) break;
  200. file_valid = lfrfid_raw_file_read_header(file, &worker->frequency, &worker->duty_cycle);
  201. if(!file_valid) break;
  202. for(size_t i = 0; i < EMULATE_BUFFER_SIZE; i++) {
  203. file_valid = lfrfid_raw_file_read_pair(
  204. file, &data->emulate_buffer_arr[i], &data->emulate_buffer_ccr[i], NULL);
  205. if(!file_valid) break;
  206. data->emulate_buffer_arr[i] /= 8;
  207. data->emulate_buffer_arr[i] -= 1;
  208. data->emulate_buffer_ccr[i] /= 8;
  209. }
  210. } while(false);
  211. furi_hal_rfid_tim_emulate_dma_start(
  212. data->emulate_buffer_arr,
  213. data->emulate_buffer_ccr,
  214. EMULATE_BUFFER_SIZE,
  215. rfid_emulate_dma_isr,
  216. &data->ctx);
  217. if(!file_valid && worker->emulate_callback != NULL) {
  218. // message file_error to worker
  219. worker->emulate_callback(LFRFIDWorkerEmulateRawFileError, worker->context);
  220. }
  221. if(file_valid) {
  222. uint32_t flag = 0;
  223. while(true) {
  224. size_t size =
  225. furi_stream_buffer_receive(data->ctx.stream, &flag, sizeof(uint32_t), 100);
  226. if(size == sizeof(uint32_t)) {
  227. size_t start = 0;
  228. if(flag == TransferComplete) {
  229. start = (EMULATE_BUFFER_SIZE / 2);
  230. }
  231. for(size_t i = 0; i < (EMULATE_BUFFER_SIZE / 2); i++) {
  232. file_valid = lfrfid_raw_file_read_pair(
  233. file,
  234. &data->emulate_buffer_arr[start + i],
  235. &data->emulate_buffer_ccr[start + i],
  236. NULL);
  237. if(!file_valid) break;
  238. data->emulate_buffer_arr[i] /= 8;
  239. data->emulate_buffer_arr[i] -= 1;
  240. data->emulate_buffer_ccr[i] /= 8;
  241. }
  242. } else if(size != 0) {
  243. data->ctx.overrun_count++;
  244. }
  245. if(!file_valid) {
  246. if(worker->emulate_callback != NULL) {
  247. // message file_error to worker
  248. worker->emulate_callback(LFRFIDWorkerEmulateRawFileError, worker->context);
  249. }
  250. break;
  251. }
  252. if(data->ctx.overrun_count > 0 && worker->emulate_callback != NULL) {
  253. // message overrun to worker
  254. worker->emulate_callback(LFRFIDWorkerEmulateRawOverrun, worker->context);
  255. }
  256. uint32_t flags = furi_event_flag_get(worker->events);
  257. if(FURI_BIT(flags, LFRFIDRawWorkerEventStop)) {
  258. break;
  259. };
  260. }
  261. }
  262. furi_hal_rfid_tim_emulate_dma_stop();
  263. if(!file_valid) {
  264. const uint32_t available_flags = (1 << LFRFIDRawWorkerEventStop);
  265. while(true) {
  266. uint32_t flags = furi_event_flag_wait(
  267. worker->events, available_flags, FuriFlagWaitAny, FuriWaitForever);
  268. if(FURI_BIT(flags, LFRFIDRawWorkerEventStop)) {
  269. break;
  270. };
  271. }
  272. }
  273. if(data->ctx.overrun_count) {
  274. FURI_LOG_E(TAG_EMULATE, "overruns: %u", data->ctx.overrun_count);
  275. }
  276. furi_stream_buffer_free(data->ctx.stream);
  277. lfrfid_raw_file_free(file);
  278. furi_record_close(RECORD_STORAGE);
  279. free(data);
  280. return 0;
  281. }