lfrfid_raw_worker.c 11 KB

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