flipper_rfidbeacon.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // CC0 1.0 Universal (CC0 1.0)
  2. // Public Domain Dedication
  3. // https://github.com/nmrr
  4. #include <stdio.h>
  5. #include <furi.h>
  6. #include <gui/gui.h>
  7. #include <input/input.h>
  8. #include <notification/notification_messages.h>
  9. #include <furi_hal_rfid.h>
  10. typedef enum {
  11. EventTypeInput,
  12. ClockEventTypeTick,
  13. } EventType;
  14. typedef struct {
  15. EventType type;
  16. InputEvent input;
  17. } EventApp;
  18. const char CW_char[54] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', ',', '?', '\'', '!', '/', '(', ')', '&', ':', ';', '=', '+', '-', '_', '"', '$', '@'};
  19. const uint8_t CW_size[54] = {2, 4, 4, 3, 1, 4, 3, 4, 2, 4, 3, 4, 2, 2, 3, 4, 4, 3, 3, 1, 3, 4, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 5, 5, 6, 5, 6, 6, 5, 5, 6, 6, 6, 7, 6};
  20. const uint8_t CW_value[54] = {0b01000000, 0b10000000, 0b10100000, 0b10000000, 0b00000000, 0b00100000, 0b11000000, 0b00000000, 0b00000000, 0b01110000, 0b10100000, 0b01000000, 0b11000000, 0b10000000, 0b11100000, 0b01100000, 0b11010000, 0b01000000, 0b00000000, 0b10000000, 0b00100000, 0b00010000, 0b01100000, 0b10010000, 0b10110000, 0b11000000, 0b11111000, 0b01111000, 0b00111000, 0b00011000, 0b00001000, 0b00000000, 0b10000000, 0b11000000, 0b11100000, 0b11110000, 0b01010100, 0b11001100, 0b00110000, 0b01111000, 0b10101100, 0b10010000, 0b10110000, 0b10110100, 0b01000000, 0b11100000, 0b10101000, 0b10001000, 0b01010000, 0b10000100, 0b00110100, 0b01001000, 0b00010010, 0b01101000};
  21. typedef struct {
  22. FuriMutex* mutex;
  23. uint8_t status;
  24. uint8_t enableCW_mutex;
  25. } mutexStruct;
  26. static void draw_callback(Canvas* canvas, void* ctx)
  27. {
  28. furi_assert(ctx);
  29. mutexStruct* mutexVal = ctx;
  30. mutexStruct mutexDraw;
  31. furi_mutex_acquire(mutexVal->mutex, FuriWaitForever);
  32. memcpy(&mutexDraw, mutexVal, sizeof(mutexStruct));
  33. furi_mutex_release(mutexVal->mutex);
  34. canvas_set_font(canvas, FontPrimary);
  35. canvas_draw_str_aligned(canvas, 64, 5, AlignCenter, AlignCenter, "RFID Beacon");
  36. char buffer[24];
  37. uint8_t positionBuffer = 0;
  38. buffer[positionBuffer++] = CW_char[mutexVal->status];
  39. buffer[positionBuffer++] = ' ';
  40. buffer[positionBuffer++] = ' ';
  41. buffer[positionBuffer++] = ' ';
  42. buffer[positionBuffer++] = ' ';
  43. uint8_t maskMorse = 0b10000000;
  44. for (uint8_t i=0;i<CW_size[mutexVal->status];i++)
  45. {
  46. if (i != 0)
  47. {
  48. buffer[positionBuffer++] = ' ';
  49. maskMorse >>= 1;
  50. }
  51. if ((CW_value[mutexVal->status] & maskMorse) != 0)
  52. {
  53. buffer[positionBuffer++] = '_';
  54. }
  55. else
  56. {
  57. buffer[positionBuffer++] = '.';
  58. }
  59. }
  60. buffer[positionBuffer++] = '\0';
  61. canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, buffer);
  62. if (mutexVal->enableCW_mutex == 0) canvas_draw_str_aligned(canvas, 64, 59, AlignCenter, AlignCenter, "OFF");
  63. else canvas_draw_str_aligned(canvas, 64, 59, AlignCenter, AlignCenter, "On the air");
  64. }
  65. static void input_callback(InputEvent* input_event, void* ctx)
  66. {
  67. furi_assert(ctx);
  68. FuriMessageQueue* event_queue = ctx;
  69. EventApp event = {.type = EventTypeInput, .input = *input_event};
  70. furi_message_queue_put(event_queue, &event, FuriWaitForever);
  71. }
  72. static void clock_tick(void* ctx) {
  73. furi_assert(ctx);
  74. FuriMessageQueue* queue = ctx;
  75. EventApp event = {.type = ClockEventTypeTick};
  76. furi_message_queue_put(queue, &event, 0);
  77. }
  78. static uint8_t RFID_STATUS = 0;
  79. void RFID_ON(NotificationApp* notification)
  80. {
  81. if (RFID_STATUS == 0)
  82. {
  83. notification_message(notification, &sequence_set_only_red_255);
  84. furi_hal_rfid_tim_read_start(125000, 0.5);
  85. RFID_STATUS = 1;
  86. }
  87. }
  88. void RFID_OFF(NotificationApp* notification)
  89. {
  90. if (RFID_STATUS == 1)
  91. {
  92. notification_message(notification, &sequence_reset_red);
  93. furi_hal_rfid_tim_read_stop();
  94. RFID_STATUS = 0;
  95. }
  96. }
  97. int32_t flipper_rfidbeacon_app()
  98. {
  99. EventApp event;
  100. FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(EventApp));
  101. mutexStruct mutexVal;
  102. mutexVal.status = 0;
  103. mutexVal.enableCW_mutex = 0;
  104. mutexVal.mutex= furi_mutex_alloc(FuriMutexTypeNormal);
  105. if(!mutexVal.mutex)
  106. {
  107. furi_message_queue_free(event_queue);
  108. return 255;
  109. }
  110. ViewPort* view_port = view_port_alloc();
  111. view_port_draw_callback_set(view_port, draw_callback, &mutexVal.mutex);
  112. view_port_input_callback_set(view_port, input_callback, event_queue);
  113. Gui* gui = furi_record_open(RECORD_GUI);
  114. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  115. NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
  116. FuriTimer* timer = furi_timer_alloc(clock_tick, FuriTimerTypePeriodic, event_queue);
  117. furi_timer_start(timer, 100);
  118. uint8_t enableCW = 0;
  119. uint8_t letterState = 0;
  120. uint8_t letterPosition = 0;
  121. uint8_t letterChosen = 0;
  122. // 1 : pause, 2 : dot, 3 : dash
  123. uint8_t draw = 0;
  124. while(1)
  125. {
  126. furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk);
  127. uint8_t screenRefresh = 0;
  128. if(event.type == EventTypeInput)
  129. {
  130. if(event.input.key == InputKeyBack && event.input.type == InputTypeLong)
  131. {
  132. break;
  133. }
  134. else if(event.input.key == InputKeyUp && event.input.type == InputTypeLong)
  135. {
  136. furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
  137. if (enableCW == 0)
  138. {
  139. enableCW = 1;
  140. letterPosition = 0;
  141. draw = 0;
  142. }
  143. else
  144. {
  145. RFID_OFF(notification);
  146. enableCW = 0;
  147. }
  148. mutexVal.enableCW_mutex = enableCW;
  149. screenRefresh = 1;
  150. furi_mutex_release(mutexVal.mutex);
  151. }
  152. else if(event.input.key == InputKeyLeft && event.input.type == InputTypeShort)
  153. {
  154. furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
  155. if (mutexVal.status != 0) mutexVal.status--;
  156. else mutexVal.status = 53;
  157. screenRefresh = 1;
  158. furi_mutex_release(mutexVal.mutex);
  159. }
  160. else if(event.input.key == InputKeyRight && event.input.type == InputTypeShort)
  161. {
  162. furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
  163. if (mutexVal.status != 53) mutexVal.status++;
  164. else mutexVal.status = 0;
  165. screenRefresh = 1;
  166. furi_mutex_release(mutexVal.mutex);
  167. }
  168. }
  169. else if (event.type == ClockEventTypeTick)
  170. {
  171. if (enableCW == 1)
  172. {
  173. if (draw == 0)
  174. {
  175. if (letterPosition == 0)
  176. {
  177. furi_mutex_acquire(mutexVal.mutex, FuriWaitForever);
  178. letterChosen = mutexVal.status;
  179. furi_mutex_release(mutexVal.mutex);
  180. }
  181. if (letterPosition == CW_size[letterChosen])
  182. {
  183. draw = 1;
  184. letterPosition = 0;
  185. }
  186. else
  187. {
  188. uint8_t mask = 0b10000000;
  189. mask >>= letterPosition;
  190. if ((CW_value[letterChosen] & mask) != 0) draw = 3;
  191. else draw = 2;
  192. letterState = 0;
  193. letterPosition++;
  194. }
  195. }
  196. // PAUSE
  197. if (draw == 1)
  198. {
  199. letterState++;
  200. if (letterState == 30)
  201. {
  202. letterState = 0;
  203. draw = 0;
  204. }
  205. }
  206. // DOT
  207. else if (draw == 2)
  208. {
  209. if (letterState == 0)
  210. {
  211. RFID_ON(notification);
  212. letterState = 1;
  213. }
  214. else
  215. {
  216. RFID_OFF(notification);
  217. draw = 0;
  218. letterState = 0;
  219. }
  220. }
  221. // DASH
  222. else if (draw == 3)
  223. {
  224. if (letterState == 0)
  225. {
  226. RFID_ON(notification);
  227. letterState = 1;
  228. }
  229. else
  230. {
  231. if (letterState != 3) letterState++;
  232. else
  233. {
  234. RFID_OFF(notification);
  235. draw = 0;
  236. letterState = 0;
  237. }
  238. }
  239. }
  240. }
  241. }
  242. if (screenRefresh == 1) view_port_update(view_port);
  243. }
  244. RFID_OFF(notification);
  245. furi_timer_free(timer);
  246. furi_message_queue_free(event_queue);
  247. furi_record_close(RECORD_NOTIFICATION);
  248. gui_remove_view_port(gui, view_port);
  249. view_port_free(view_port);
  250. furi_record_close(RECORD_GUI);
  251. return 0;
  252. }