* proof of concept * fix syntax for rust and add auto fix syntax * fix syntax for C * fix bug with files owner * add information to wiki * try to add ci * format code from master * even more format fixes * change docker to docker-compose * Exclude ./target_*/build directories from format check * Run rustfmt only on project files * add ulimit setup for long clang list * merge * fix rustfmt, exclude target Inc directory * sync with master * abspath Co-authored-by: aanper <mail@s3f.ru> Co-authored-by: Vadim Kaushan <admin@disasm.info>
		
			
				
	
	
		
			154 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#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("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("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("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++;
 | 
						|
    }
 | 
						|
} |