view_direct_sampling.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
  2. * See the LICENSE file for information about the license. */
  3. #include "app.h"
  4. #include <cc1101.h>
  5. #define CAPTURED_BITMAP_SIZE 128*64/8
  6. typedef struct {
  7. uint8_t *captured; // Bitmap with the last captured screen.
  8. uint32_t usec_per_pixel; // Number of useconds a pixel should represent
  9. } DirectSamplingViewPrivData;
  10. /* Read directly from the G0 CC1101 pin, and draw a black or white
  11. * dot depending on the level. */
  12. void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app) {
  13. if (!app->direct_sampling_enabled) {
  14. canvas_set_font(canvas, FontSecondary);
  15. canvas_draw_str(canvas,2,9,"Direct sampling is a special");
  16. canvas_draw_str(canvas,2,18,"mode that displays the signal");
  17. canvas_draw_str(canvas,2,27,"captured in real time. Like in");
  18. canvas_draw_str(canvas,2,36,"a old CRT TV. It's very slow.");
  19. canvas_draw_str(canvas,2,45,"Can crash your Flipper.");
  20. canvas_set_font(canvas, FontPrimary);
  21. canvas_draw_str(canvas,14,60,"To enable press OK");
  22. return;
  23. }
  24. /* Allocate the bitmap only the first time. */
  25. DirectSamplingViewPrivData *privdata = app->view_privdata;
  26. if (privdata->captured == NULL)
  27. privdata->captured = malloc(CAPTURED_BITMAP_SIZE);
  28. /* Read from data from GPIO */
  29. if (privdata->captured == NULL)
  30. FURI_LOG_E(TAG, "captured is NULL reading GPIO.");
  31. for (int j = 0; j < CAPTURED_BITMAP_SIZE*8; j++) {
  32. uint32_t start_time = DWT->CYCCNT;
  33. bool level = furi_hal_gpio_read(&gpio_cc1101_g0);
  34. bitmap_set(privdata->captured,CAPTURED_BITMAP_SIZE,j,level);
  35. uint32_t period =
  36. furi_hal_cortex_instructions_per_microsecond() *
  37. privdata->usec_per_pixel;
  38. while(DWT->CYCCNT - start_time < period);
  39. }
  40. /* Draw on screen. */
  41. int idx = 0;
  42. for (int y = 0; y < 64; y++) {
  43. for (int x = 0; x < 128; x++) {
  44. bool level = bitmap_get(privdata->captured,
  45. CAPTURED_BITMAP_SIZE,idx++);
  46. if (level) canvas_draw_dot(canvas,x,y);
  47. uint32_t x = 250; while(x--);
  48. }
  49. }
  50. canvas_set_font(canvas, FontSecondary);
  51. canvas_draw_str_with_border(canvas,36,60,"Direct sampling",
  52. ColorWhite,ColorBlack);
  53. }
  54. /* Handle input */
  55. void process_input_direct_sampling(ProtoViewApp *app, InputEvent input) {
  56. if (input.type == InputTypePress && input.key == InputKeyOk) {
  57. app->direct_sampling_enabled = !app->direct_sampling_enabled;
  58. }
  59. }
  60. /* Enter view. Stop the subghz thread to prevent access as we read
  61. * the CC1101 data directly. */
  62. void view_enter_direct_sampling(ProtoViewApp *app) {
  63. /* Set view defaults. */
  64. DirectSamplingViewPrivData *privdata = app->view_privdata;
  65. privdata->usec_per_pixel = 30;
  66. if (app->txrx->txrx_state == TxRxStateRx &&
  67. !app->txrx->debug_timer_sampling)
  68. {
  69. furi_hal_subghz_stop_async_rx();
  70. /* To read data asynchronously directly from the view, we need
  71. * to put the CC1101 back into reception mode (the previous call
  72. * to stop the async RX will put it into idle) and configure the
  73. * G0 pin for reading. */
  74. furi_hal_subghz_rx();
  75. furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo,
  76. GpioSpeedLow);
  77. } else {
  78. raw_sampling_worker_stop(app);
  79. }
  80. }
  81. /* Exit view. Restore the subghz thread. */
  82. void view_exit_direct_sampling(ProtoViewApp *app) {
  83. DirectSamplingViewPrivData *privdata = app->view_privdata;
  84. if (privdata->captured) free(privdata->captured);
  85. app->direct_sampling_enabled = false;
  86. /* Restart normal data feeding. */
  87. if (app->txrx->txrx_state == TxRxStateRx &&
  88. !app->txrx->debug_timer_sampling)
  89. {
  90. furi_hal_subghz_start_async_rx(protoview_rx_callback, NULL);
  91. } else {
  92. raw_sampling_worker_start(app);
  93. }
  94. }