| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- #include "flipper.h"
- #include <string.h>
- #define FB_WIDTH 10
- #define FB_HEIGHT 3
- #define FB_SIZE (FB_WIDTH * FB_HEIGHT)
- // context structure used for pass some object from app thread to callback
- typedef struct {
- SemaphoreHandle_t events; // queue to pass events from callback to app thread
- FuriRecordSubscriber* log; // app logger
- } IpcCtx;
- static void handle_fb_change(const void* fb, size_t fb_size, void* raw_ctx) {
- IpcCtx* ctx = (IpcCtx*)raw_ctx; // make right type
- fuprintf(ctx->log, "[cb] framebuffer updated\n");
- // send event to app thread
- xSemaphoreGive(ctx->events);
- // Attention! Please, do not make blocking operation like IO and waits inside callback
- // Remember that callback execute in calling thread/context
- }
- static void print_fb(char* fb, FuriRecordSubscriber* log) {
- if(fb == NULL) return;
- /* draw framebuffer like this:
- +==========+
- | |
- | |
- | |
- +==========+
- */
- char row_buffer[FB_WIDTH + 1];
- row_buffer[FB_WIDTH] = '\0';
- // FB layout is hardcoded here
- fuprintf(log, "+==========+\n");
- for(uint8_t i = 0; i < FB_HEIGHT; i++) {
- strncpy(row_buffer, &fb[FB_WIDTH * i], FB_WIDTH);
- fuprintf(log, "|%s|\n", row_buffer);
- }
- fuprintf(log, "+==========+\n");
- }
- void application_ipc_display(void* p) {
- // get logger
- FuriRecordSubscriber* log = get_default_log();
- // create ASCII "framebuffer"
- // FB_WIDTH x FB_HEIGHT char buffer
- char _framebuffer[FB_SIZE];
- // init framebuffer by spaces
- for(size_t i = 0; i < FB_SIZE; i++) {
- _framebuffer[i] = ' ';
- }
- // create record
- if(!furi_create_deprecated("test_fb", (void*)_framebuffer, FB_SIZE)) {
- fuprintf(log, "[display] cannot create fb record\n");
- furiac_exit(NULL);
- }
- StaticSemaphore_t event_descriptor;
- // create stack-based counting semaphore
- SemaphoreHandle_t events = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
- if(events == NULL) {
- fuprintf(log, "[display] cannot create event semaphore\n");
- furiac_exit(NULL);
- }
- // save log and event queue in context structure
- IpcCtx ctx = {.events = events, .log = log};
- // subscribe to record. ctx will be passed to handle_fb_change
- FuriRecordSubscriber* fb_record =
- furi_open_deprecated("test_fb", false, false, handle_fb_change, NULL, &ctx);
- if(fb_record == NULL) {
- fuprintf(log, "[display] cannot open fb record\n");
- furiac_exit(NULL);
- }
- #ifdef HW_DISPLAY
- // on Flipper target -- open screen
- // draw border
- #else
- // on Local target -- print "blank screen"
- {
- void* fb = furi_take(fb_record);
- print_fb((char*)fb, log);
- furi_give(fb_record);
- }
- #endif
- while(1) {
- // wait for event
- if(xSemaphoreTake(events, portMAX_DELAY) == pdTRUE) {
- fuprintf(log, "[display] get fb update\n\n");
- #ifdef HW_DISPLAY
- // on Flipper target draw the screen
- #else
- // on local target just print
- {
- void* fb = furi_take(fb_record);
- print_fb((char*)fb, log);
- furi_give(fb_record);
- }
- #endif
- }
- }
- }
- // Widget application
- void application_ipc_widget(void* p) {
- FuriRecordSubscriber* log = get_default_log();
- // open record
- FuriRecordSubscriber* fb_record =
- furi_open_deprecated("test_fb", false, false, NULL, NULL, NULL);
- if(fb_record == NULL) {
- fuprintf(log, "[widget] cannot create fb record\n");
- furiac_exit(NULL);
- }
- uint8_t counter = 0;
- while(1) {
- delay(120);
- // write some ascii demo here: '#'' symbol run on overall screen
- char* fb = (char*)furi_take(fb_record);
- if(fb == NULL) furiac_exit(NULL);
- for(size_t i = 0; i < FB_SIZE; i++) {
- fb[i] = ' ';
- }
- fb[counter % FB_SIZE] = '#';
- furi_commit(fb_record);
- counter++;
- }
- }
|