lfrfid_raw_worker.c 11 KB

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