ipc.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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("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 = furi_open(
  64. "test_fb", false, false, handle_fb_change, NULL, &ctx
  65. );
  66. if(fb_record == NULL) {
  67. fuprintf(log, "[display] cannot open fb record\n");
  68. furiac_exit(NULL);
  69. }
  70. #ifdef HW_DISPLAY
  71. // on Flipper target -- open screen
  72. // draw border
  73. #else
  74. // on Local target -- print "blank screen"
  75. {
  76. void* fb = furi_take(fb_record);
  77. print_fb((char*)fb, log);
  78. furi_give(fb_record);
  79. }
  80. #endif
  81. while(1) {
  82. // wait for event
  83. if(xSemaphoreTake(events, portMAX_DELAY) == pdTRUE) {
  84. fuprintf(log, "[display] get fb update\n\n");
  85. #ifdef HW_DISPLAY
  86. // on Flipper target draw the screen
  87. #else
  88. // on local target just print
  89. {
  90. void* fb = furi_take(fb_record);
  91. print_fb((char*)fb, log);
  92. furi_give(fb_record);
  93. }
  94. #endif
  95. }
  96. }
  97. }
  98. // Widget application
  99. void application_ipc_widget(void* p) {
  100. FuriRecordSubscriber* log = get_default_log();
  101. // open record
  102. FuriRecordSubscriber* fb_record = furi_open(
  103. "test_fb", false, false, NULL, NULL, NULL
  104. );
  105. if(fb_record == NULL) {
  106. fuprintf(log, "[widget] cannot create fb record\n");
  107. furiac_exit(NULL);
  108. }
  109. uint8_t counter = 0;
  110. while(1) {
  111. delay(120);
  112. // write some ascii demo here: '#'' symbol run on overall screen
  113. char* fb = (char*)furi_take(fb_record);
  114. if(fb == NULL) furiac_exit(NULL);
  115. for(size_t i = 0; i < FB_SIZE; i++) {
  116. fb[i] = ' ';
  117. }
  118. fb[counter % FB_SIZE] = '#';
  119. furi_commit(fb_record);
  120. counter++;
  121. }
  122. }