flipperzero-firmware/applications/examples/ipc.c
coreglitch 942bbfaefe
Core api concept (#144)
* add input debounce code from old fw

* exampl of input api

* change input API to get/release

* revert input API to read

* pointer instead of instance

* add input API description

* add display API

* rewrite display names

* migrate to valuemanager

* add LED API

* add closing brakets

* add sound api

* fix led api

* basic api

* rename API pages

* change pubsub implementation

* move FURI AC -> flapp, add valuemutex example, add valuemanager implementation

* pubsub usage example

* user led example

* update example

* simplify input

* add composed display

* add SPI/GPIO and CC1101 bus

* change cc1101 api

* spi api and devices

* spi api and devices

* move SPI to page, add GPIO

* not block pin open

* backlight API and more

* add minunit tests

* fix logging

* ignore unexisting time service on embedded targets

* fix warning, issue with printf

* Deprecate furi_open and furi_close (#167)

Rename existing furi_open and furi_close to deprecated version

* add exitcode

* migrate to printf

* indicate test by leds

* add testing description

* rename furi.h

* wip basic api

* add valuemutex, pubsub, split files

* add value expanders

* value mutex realization and tests

* valuemutex test added to makefile

* do not build unimplemented files

* fix build furmware target f2

* redesigned minunit tests to allow testing in separate files

* test file for valuemutex minunit testing

* minunit partial test valuemutex

* local cmsis_os2 mutex bindings

* implement furi open/create, tests

* migrate concurrent_access to ValueMutex

* add spi header

* Lib: add mlib submodule.

Co-authored-by: rusdacent <rusdacentx0x08@gmail.com>
Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
2020-10-13 11:22:43 +03:00

155 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_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++;
}
}