lfrfid_raw_worker.c 11 KB

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