ipc.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #include "flipper.h"
  2. #include <string.h>
  3. #define FB_WIDTH 10
  4. #define FB_HEIGHT 3
  5. #define FB_SIZE (FB_WIDTH * FB_HEIGHT)
  6. // context structure used for pass some object from app thread to callback
  7. typedef struct {
  8. SemaphoreHandle_t events; // queue to pass events from callback to app thread
  9. FuriRecordSubscriber* log; // app logger
  10. } IpcCtx;
  11. static void handle_fb_change(const void* fb, size_t fb_size, void* raw_ctx) {
  12. IpcCtx* ctx = (IpcCtx*)raw_ctx; // make right type
  13. fuprintf(ctx->log, "[cb] framebuffer updated\n");
  14. // send event to app thread
  15. xSemaphoreGive(ctx->events);
  16. // Attention! Please, do not make blocking operation like IO and waits inside callback
  17. // Remember that callback execute in calling thread/context
  18. }
  19. static void print_fb(char* fb, FuriRecordSubscriber* log) {
  20. if(fb == NULL) return;
  21. /* draw framebuffer like this:
  22. +==========+
  23. | |
  24. | |
  25. | |
  26. +==========+
  27. */
  28. char row_buffer[FB_WIDTH + 1];
  29. row_buffer[FB_WIDTH] = '\0';
  30. // FB layout is hardcoded here
  31. fuprintf(log, "+==========+\n");
  32. for(uint8_t i = 0; i < FB_HEIGHT; i++) {
  33. strncpy(row_buffer, &fb[FB_WIDTH * i], FB_WIDTH);
  34. fuprintf(log, "|%s|\n", row_buffer);
  35. }
  36. fuprintf(log, "+==========+\n");
  37. }
  38. void application_ipc_display(void* p) {
  39. // get logger
  40. FuriRecordSubscriber* log = get_default_log();
  41. // create ASCII "framebuffer"
  42. // FB_WIDTH x FB_HEIGHT char buffer
  43. char _framebuffer[FB_SIZE];
  44. // init framebuffer by spaces
  45. for(size_t i = 0; i < FB_SIZE; i++) {
  46. _framebuffer[i] = ' ';
  47. }
  48. // create record
  49. if(!furi_create_deprecated("test_fb", (void*)_framebuffer, FB_SIZE)) {
  50. fuprintf(log, "[display] cannot create fb record\n");
  51. furiac_exit(NULL);
  52. }
  53. StaticSemaphore_t event_descriptor;
  54. // create stack-based counting semaphore
  55. SemaphoreHandle_t events = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
  56. if(events == NULL) {
  57. fuprintf(log, "[display] cannot create event semaphore\n");
  58. furiac_exit(NULL);
  59. }
  60. // save log and event queue in context structure
  61. IpcCtx ctx = {.events = events, .log = log};
  62. // subscribe to record. ctx will be passed to handle_fb_change
  63. FuriRecordSubscriber* fb_record =
  64. furi_open_deprecated("test_fb", false, false, handle_fb_change, NULL, &ctx);
  65. if(fb_record == NULL) {
  66. fuprintf(log, "[display] cannot open fb record\n");
  67. furiac_exit(NULL);
  68. }
  69. #ifdef HW_DISPLAY
  70. // on Flipper target -- open screen
  71. // draw border
  72. #else
  73. // on Local target -- print "blank screen"
  74. {
  75. void* fb = furi_take(fb_record);
  76. print_fb((char*)fb, log);
  77. furi_give(fb_record);
  78. }
  79. #endif
  80. while(1) {
  81. // wait for event
  82. if(xSemaphoreTake(events, portMAX_DELAY) == pdTRUE) {
  83. fuprintf(log, "[display] get fb update\n\n");
  84. #ifdef HW_DISPLAY
  85. // on Flipper target draw the screen
  86. #else
  87. // on local target just print
  88. {
  89. void* fb = furi_take(fb_record);
  90. print_fb((char*)fb, log);
  91. furi_give(fb_record);
  92. }
  93. #endif
  94. }
  95. }
  96. }
  97. // Widget application
  98. void application_ipc_widget(void* p) {
  99. FuriRecordSubscriber* log = get_default_log();
  100. // open record
  101. FuriRecordSubscriber* fb_record =
  102. furi_open_deprecated("test_fb", false, false, NULL, NULL, NULL);
  103. if(fb_record == NULL) {
  104. fuprintf(log, "[widget] cannot create fb record\n");
  105. furiac_exit(NULL);
  106. }
  107. uint8_t counter = 0;
  108. while(1) {
  109. delay(120);
  110. // write some ascii demo here: '#'' symbol run on overall screen
  111. char* fb = (char*)furi_take(fb_record);
  112. if(fb == NULL) furiac_exit(NULL);
  113. for(size_t i = 0; i < FB_SIZE; i++) {
  114. fb[i] = ' ';
  115. }
  116. fb[counter % FB_SIZE] = '#';
  117. furi_commit(fb_record);
  118. counter++;
  119. }
  120. }