[FL-2839] Furi stream buffer (#1834)
* Core: stream buffer * stream buffer: API and usage * stream buffer: documentation * stream buffer: more documentation * Furi: fix spelling Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
d1843c0094
commit
38a82a1907
@ -3,7 +3,6 @@
|
|||||||
#include <notification/notification.h>
|
#include <notification/notification.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <furi_hal_uart.h>
|
#include <furi_hal_uart.h>
|
||||||
#include <furi_hal_console.h>
|
#include <furi_hal_console.h>
|
||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
@ -20,7 +19,7 @@ typedef struct {
|
|||||||
ViewDispatcher* view_dispatcher;
|
ViewDispatcher* view_dispatcher;
|
||||||
View* view;
|
View* view;
|
||||||
FuriThread* worker_thread;
|
FuriThread* worker_thread;
|
||||||
StreamBufferHandle_t rx_stream;
|
FuriStreamBuffer* rx_stream;
|
||||||
} UartEchoApp;
|
} UartEchoApp;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -92,13 +91,11 @@ static uint32_t uart_echo_exit(void* context) {
|
|||||||
|
|
||||||
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
UartEchoApp* app = context;
|
UartEchoApp* app = context;
|
||||||
|
|
||||||
if(ev == UartIrqEventRXNE) {
|
if(ev == UartIrqEventRXNE) {
|
||||||
xStreamBufferSendFromISR(app->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
|
||||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +155,7 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
size_t length = 0;
|
size_t length = 0;
|
||||||
do {
|
do {
|
||||||
uint8_t data[64];
|
uint8_t data[64];
|
||||||
length = xStreamBufferReceive(app->rx_stream, data, 64, 0);
|
length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
|
||||||
if(length > 0) {
|
if(length > 0) {
|
||||||
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
|
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
|
||||||
with_view_model(
|
with_view_model(
|
||||||
@ -186,7 +183,7 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
static UartEchoApp* uart_echo_app_alloc() {
|
static UartEchoApp* uart_echo_app_alloc() {
|
||||||
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
UartEchoApp* app = malloc(sizeof(UartEchoApp));
|
||||||
|
|
||||||
app->rx_stream = xStreamBufferCreate(2048, 1);
|
app->rx_stream = furi_stream_buffer_alloc(2048, 1);
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
app->gui = furi_record_open(RECORD_GUI);
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
@ -260,7 +257,7 @@ static void uart_echo_app_free(UartEchoApp* app) {
|
|||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
app->gui = NULL;
|
app->gui = NULL;
|
||||||
|
|
||||||
vStreamBufferDelete(app->rx_stream);
|
furi_stream_buffer_free(app->rx_stream);
|
||||||
|
|
||||||
// Free rest
|
// Free rest
|
||||||
free(app);
|
free(app);
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <pb.h>
|
#include <pb.h>
|
||||||
#include <pb_encode.h>
|
#include <pb_encode.h>
|
||||||
#include <m-list.h>
|
#include <m-list.h>
|
||||||
@ -34,7 +33,7 @@ static uint32_t command_id = 0;
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
RpcSession* session;
|
RpcSession* session;
|
||||||
StreamBufferHandle_t output_stream;
|
FuriStreamBuffer* output_stream;
|
||||||
SemaphoreHandle_t close_session_semaphore;
|
SemaphoreHandle_t close_session_semaphore;
|
||||||
SemaphoreHandle_t terminate_semaphore;
|
SemaphoreHandle_t terminate_semaphore;
|
||||||
TickType_t timeout;
|
TickType_t timeout;
|
||||||
@ -90,7 +89,7 @@ static void test_rpc_setup(void) {
|
|||||||
}
|
}
|
||||||
furi_check(rpc_session[0].session);
|
furi_check(rpc_session[0].session);
|
||||||
|
|
||||||
rpc_session[0].output_stream = xStreamBufferCreate(1000, 1);
|
rpc_session[0].output_stream = furi_stream_buffer_alloc(1000, 1);
|
||||||
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
|
rpc_session_set_send_bytes_callback(rpc_session[0].session, output_bytes_callback);
|
||||||
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
|
rpc_session[0].close_session_semaphore = xSemaphoreCreateBinary();
|
||||||
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();
|
rpc_session[0].terminate_semaphore = xSemaphoreCreateBinary();
|
||||||
@ -110,7 +109,7 @@ static void test_rpc_setup_second_session(void) {
|
|||||||
}
|
}
|
||||||
furi_check(rpc_session[1].session);
|
furi_check(rpc_session[1].session);
|
||||||
|
|
||||||
rpc_session[1].output_stream = xStreamBufferCreate(1000, 1);
|
rpc_session[1].output_stream = furi_stream_buffer_alloc(1000, 1);
|
||||||
rpc_session_set_send_bytes_callback(rpc_session[1].session, output_bytes_callback);
|
rpc_session_set_send_bytes_callback(rpc_session[1].session, output_bytes_callback);
|
||||||
rpc_session[1].close_session_semaphore = xSemaphoreCreateBinary();
|
rpc_session[1].close_session_semaphore = xSemaphoreCreateBinary();
|
||||||
rpc_session[1].terminate_semaphore = xSemaphoreCreateBinary();
|
rpc_session[1].terminate_semaphore = xSemaphoreCreateBinary();
|
||||||
@ -126,7 +125,7 @@ static void test_rpc_teardown(void) {
|
|||||||
rpc_session_close(rpc_session[0].session);
|
rpc_session_close(rpc_session[0].session);
|
||||||
furi_check(xSemaphoreTake(rpc_session[0].terminate_semaphore, portMAX_DELAY));
|
furi_check(xSemaphoreTake(rpc_session[0].terminate_semaphore, portMAX_DELAY));
|
||||||
furi_record_close(RECORD_RPC);
|
furi_record_close(RECORD_RPC);
|
||||||
vStreamBufferDelete(rpc_session[0].output_stream);
|
furi_stream_buffer_free(rpc_session[0].output_stream);
|
||||||
vSemaphoreDelete(rpc_session[0].close_session_semaphore);
|
vSemaphoreDelete(rpc_session[0].close_session_semaphore);
|
||||||
vSemaphoreDelete(rpc_session[0].terminate_semaphore);
|
vSemaphoreDelete(rpc_session[0].terminate_semaphore);
|
||||||
++command_id;
|
++command_id;
|
||||||
@ -141,7 +140,7 @@ static void test_rpc_teardown_second_session(void) {
|
|||||||
xSemaphoreTake(rpc_session[1].terminate_semaphore, 0);
|
xSemaphoreTake(rpc_session[1].terminate_semaphore, 0);
|
||||||
rpc_session_close(rpc_session[1].session);
|
rpc_session_close(rpc_session[1].session);
|
||||||
furi_check(xSemaphoreTake(rpc_session[1].terminate_semaphore, portMAX_DELAY));
|
furi_check(xSemaphoreTake(rpc_session[1].terminate_semaphore, portMAX_DELAY));
|
||||||
vStreamBufferDelete(rpc_session[1].output_stream);
|
furi_stream_buffer_free(rpc_session[1].output_stream);
|
||||||
vSemaphoreDelete(rpc_session[1].close_session_semaphore);
|
vSemaphoreDelete(rpc_session[1].close_session_semaphore);
|
||||||
vSemaphoreDelete(rpc_session[1].terminate_semaphore);
|
vSemaphoreDelete(rpc_session[1].terminate_semaphore);
|
||||||
++command_id;
|
++command_id;
|
||||||
@ -268,8 +267,8 @@ static PB_CommandStatus test_rpc_storage_get_file_error(File* file) {
|
|||||||
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size) {
|
static void output_bytes_callback(void* ctx, uint8_t* got_bytes, size_t got_size) {
|
||||||
RpcSessionContext* callbacks_context = ctx;
|
RpcSessionContext* callbacks_context = ctx;
|
||||||
|
|
||||||
size_t bytes_sent =
|
size_t bytes_sent = furi_stream_buffer_send(
|
||||||
xStreamBufferSend(callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever);
|
callbacks_context->output_stream, got_bytes, got_size, FuriWaitForever);
|
||||||
(void)bytes_sent;
|
(void)bytes_sent;
|
||||||
furi_check(bytes_sent == got_size);
|
furi_check(bytes_sent == got_size);
|
||||||
}
|
}
|
||||||
@ -534,7 +533,8 @@ static bool test_rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_
|
|||||||
TickType_t now = xTaskGetTickCount();
|
TickType_t now = xTaskGetTickCount();
|
||||||
int32_t time_left = session_context->timeout - now;
|
int32_t time_left = session_context->timeout - now;
|
||||||
time_left = MAX(time_left, 0);
|
time_left = MAX(time_left, 0);
|
||||||
bytes_received = xStreamBufferReceive(session_context->output_stream, buf, count, time_left);
|
bytes_received =
|
||||||
|
furi_stream_buffer_receive(session_context->output_stream, buf, count, time_left);
|
||||||
return (count == bytes_received);
|
return (count == bytes_received);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "usb_uart_bridge.h"
|
#include "usb_uart_bridge.h"
|
||||||
#include "furi_hal.h"
|
#include "furi_hal.h"
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <furi_hal_usb_cdc.h>
|
#include <furi_hal_usb_cdc.h>
|
||||||
#include "usb_cdc.h"
|
#include "usb_cdc.h"
|
||||||
#include "cli/cli_vcp.h"
|
#include "cli/cli_vcp.h"
|
||||||
@ -43,7 +42,7 @@ struct UsbUartBridge {
|
|||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
FuriThread* tx_thread;
|
FuriThread* tx_thread;
|
||||||
|
|
||||||
StreamBufferHandle_t rx_stream;
|
FuriStreamBuffer* rx_stream;
|
||||||
|
|
||||||
FuriMutex* usb_mutex;
|
FuriMutex* usb_mutex;
|
||||||
|
|
||||||
@ -74,12 +73,10 @@ static int32_t usb_uart_tx_thread(void* context);
|
|||||||
|
|
||||||
static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
|
|
||||||
if(ev == UartIrqEventRXNE) {
|
if(ev == UartIrqEventRXNE) {
|
||||||
xStreamBufferSendFromISR(usb_uart->rx_stream, &data, 1, &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(usb_uart->rx_stream, &data, 1, 0);
|
||||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
|
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +153,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
|
|
||||||
memcpy(&usb_uart->cfg, &usb_uart->cfg_new, sizeof(UsbUartConfig));
|
memcpy(&usb_uart->cfg, &usb_uart->cfg_new, sizeof(UsbUartConfig));
|
||||||
|
|
||||||
usb_uart->rx_stream = xStreamBufferCreate(USB_UART_RX_BUF_SIZE, 1);
|
usb_uart->rx_stream = furi_stream_buffer_alloc(USB_UART_RX_BUF_SIZE, 1);
|
||||||
|
|
||||||
usb_uart->tx_sem = furi_semaphore_alloc(1, 1);
|
usb_uart->tx_sem = furi_semaphore_alloc(1, 1);
|
||||||
usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
usb_uart->usb_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
@ -189,8 +186,8 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
furi_check((events & FuriFlagError) == 0);
|
furi_check((events & FuriFlagError) == 0);
|
||||||
if(events & WorkerEvtStop) break;
|
if(events & WorkerEvtStop) break;
|
||||||
if(events & WorkerEvtRxDone) {
|
if(events & WorkerEvtRxDone) {
|
||||||
size_t len =
|
size_t len = furi_stream_buffer_receive(
|
||||||
xStreamBufferReceive(usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0);
|
usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0);
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) {
|
if(furi_semaphore_acquire(usb_uart->tx_sem, 100) == FuriStatusOk) {
|
||||||
usb_uart->st.rx_cnt += len;
|
usb_uart->st.rx_cnt += len;
|
||||||
@ -199,7 +196,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
furi_hal_cdc_send(usb_uart->cfg.vcp_ch, usb_uart->rx_buf, len);
|
furi_hal_cdc_send(usb_uart->cfg.vcp_ch, usb_uart->rx_buf, len);
|
||||||
furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk);
|
furi_check(furi_mutex_release(usb_uart->usb_mutex) == FuriStatusOk);
|
||||||
} else {
|
} else {
|
||||||
xStreamBufferReset(usb_uart->rx_stream);
|
furi_stream_buffer_reset(usb_uart->rx_stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -270,7 +267,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||||||
furi_thread_join(usb_uart->tx_thread);
|
furi_thread_join(usb_uart->tx_thread);
|
||||||
furi_thread_free(usb_uart->tx_thread);
|
furi_thread_free(usb_uart->tx_thread);
|
||||||
|
|
||||||
vStreamBufferDelete(usb_uart->rx_stream);
|
furi_stream_buffer_free(usb_uart->rx_stream);
|
||||||
furi_mutex_free(usb_uart->usb_mutex);
|
furi_mutex_free(usb_uart->usb_mutex);
|
||||||
furi_semaphore_free(usb_uart->tx_sem);
|
furi_semaphore_free(usb_uart->tx_sem);
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
#include <lib/toolbox/args.h>
|
#include <lib/toolbox/args.h>
|
||||||
#include <lib/subghz/subghz_keystore.h>
|
#include <lib/subghz/subghz_keystore.h>
|
||||||
@ -194,23 +193,21 @@ void subghz_cli_command_tx(Cli* cli, FuriString* args, void* context) {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
volatile bool overrun;
|
volatile bool overrun;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
size_t packet_count;
|
size_t packet_count;
|
||||||
} SubGhzCliCommandRx;
|
} SubGhzCliCommandRx;
|
||||||
|
|
||||||
static void subghz_cli_command_rx_capture_callback(bool level, uint32_t duration, void* context) {
|
static void subghz_cli_command_rx_capture_callback(bool level, uint32_t duration, void* context) {
|
||||||
SubGhzCliCommandRx* instance = context;
|
SubGhzCliCommandRx* instance = context;
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
LevelDuration level_duration = level_duration_make(level, duration);
|
LevelDuration level_duration = level_duration_make(level, duration);
|
||||||
if(instance->overrun) {
|
if(instance->overrun) {
|
||||||
instance->overrun = false;
|
instance->overrun = false;
|
||||||
level_duration = level_duration_reset();
|
level_duration = level_duration_reset();
|
||||||
}
|
}
|
||||||
size_t ret = xStreamBufferSendFromISR(
|
size_t ret =
|
||||||
instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0);
|
||||||
if(sizeof(LevelDuration) != ret) instance->overrun = true;
|
if(sizeof(LevelDuration) != ret) instance->overrun = true;
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void subghz_cli_command_rx_callback(
|
static void subghz_cli_command_rx_callback(
|
||||||
@ -249,7 +246,8 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
|
|||||||
|
|
||||||
// Allocate context and buffers
|
// Allocate context and buffers
|
||||||
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
|
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
|
||||||
instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
instance->stream =
|
||||||
|
furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
||||||
furi_check(instance->stream);
|
furi_check(instance->stream);
|
||||||
|
|
||||||
SubGhzEnvironment* environment = subghz_environment_alloc();
|
SubGhzEnvironment* environment = subghz_environment_alloc();
|
||||||
@ -279,8 +277,8 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
|
|||||||
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
|
printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency);
|
||||||
LevelDuration level_duration;
|
LevelDuration level_duration;
|
||||||
while(!cli_cmd_interrupt_received(cli)) {
|
while(!cli_cmd_interrupt_received(cli)) {
|
||||||
int ret =
|
int ret = furi_stream_buffer_receive(
|
||||||
xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10);
|
instance->stream, &level_duration, sizeof(LevelDuration), 10);
|
||||||
if(ret == sizeof(LevelDuration)) {
|
if(ret == sizeof(LevelDuration)) {
|
||||||
if(level_duration_is_reset(level_duration)) {
|
if(level_duration_is_reset(level_duration)) {
|
||||||
printf(".");
|
printf(".");
|
||||||
@ -304,7 +302,7 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
|
|||||||
// Cleanup
|
// Cleanup
|
||||||
subghz_receiver_free(receiver);
|
subghz_receiver_free(receiver);
|
||||||
subghz_environment_free(environment);
|
subghz_environment_free(environment);
|
||||||
vStreamBufferDelete(instance->stream);
|
furi_stream_buffer_free(instance->stream);
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
#include <loader/loader.h>
|
#include <loader/loader.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
// Close to ISO, `date +'%Y-%m-%d %H:%M:%S %u'`
|
// Close to ISO, `date +'%Y-%m-%d %H:%M:%S %u'`
|
||||||
#define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d"
|
#define CLI_DATE_FORMAT "%.4d-%.2d-%.2d %.2d:%.2d:%.2d %d"
|
||||||
@ -140,7 +139,7 @@ void cli_command_date(Cli* cli, FuriString* args, void* context) {
|
|||||||
#define CLI_COMMAND_LOG_BUFFER_SIZE 64
|
#define CLI_COMMAND_LOG_BUFFER_SIZE 64
|
||||||
|
|
||||||
void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* context) {
|
void cli_command_log_tx_callback(const uint8_t* buffer, size_t size, void* context) {
|
||||||
xStreamBufferSend(context, buffer, size, 0);
|
furi_stream_buffer_send(context, buffer, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_command_log_level_set_from_string(FuriString* level) {
|
void cli_command_log_level_set_from_string(FuriString* level) {
|
||||||
@ -165,7 +164,7 @@ void cli_command_log_level_set_from_string(FuriString* level) {
|
|||||||
|
|
||||||
void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
StreamBufferHandle_t ring = xStreamBufferCreate(CLI_COMMAND_LOG_RING_SIZE, 1);
|
FuriStreamBuffer* ring = furi_stream_buffer_alloc(CLI_COMMAND_LOG_RING_SIZE, 1);
|
||||||
uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE];
|
uint8_t buffer[CLI_COMMAND_LOG_BUFFER_SIZE];
|
||||||
FuriLogLevel previous_level = furi_log_get_level();
|
FuriLogLevel previous_level = furi_log_get_level();
|
||||||
bool restore_log_level = false;
|
bool restore_log_level = false;
|
||||||
@ -179,7 +178,7 @@ void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
|||||||
|
|
||||||
printf("Press CTRL+C to stop...\r\n");
|
printf("Press CTRL+C to stop...\r\n");
|
||||||
while(!cli_cmd_interrupt_received(cli)) {
|
while(!cli_cmd_interrupt_received(cli)) {
|
||||||
size_t ret = xStreamBufferReceive(ring, buffer, CLI_COMMAND_LOG_BUFFER_SIZE, 50);
|
size_t ret = furi_stream_buffer_receive(ring, buffer, CLI_COMMAND_LOG_BUFFER_SIZE, 50);
|
||||||
cli_write(cli, buffer, ret);
|
cli_write(cli, buffer, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +189,7 @@ void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
|||||||
furi_log_set_level(previous_level);
|
furi_log_set_level(previous_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
vStreamBufferDelete(ring);
|
furi_stream_buffer_free(ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cli_command_vibro(Cli* cli, FuriString* args, void* context) {
|
void cli_command_vibro(Cli* cli, FuriString* args, void* context) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#include <furi_hal_usb_cdc.h>
|
#include <furi_hal_usb_cdc.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include "cli_i.h"
|
#include "cli_i.h"
|
||||||
|
|
||||||
#define TAG "CliVcp"
|
#define TAG "CliVcp"
|
||||||
@ -29,8 +28,8 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
|
|
||||||
StreamBufferHandle_t tx_stream;
|
FuriStreamBuffer* tx_stream;
|
||||||
StreamBufferHandle_t rx_stream;
|
FuriStreamBuffer* rx_stream;
|
||||||
|
|
||||||
volatile bool connected;
|
volatile bool connected;
|
||||||
volatile bool running;
|
volatile bool running;
|
||||||
@ -62,8 +61,8 @@ static const uint8_t ascii_eot = 0x04;
|
|||||||
static void cli_vcp_init() {
|
static void cli_vcp_init() {
|
||||||
if(vcp == NULL) {
|
if(vcp == NULL) {
|
||||||
vcp = malloc(sizeof(CliVcp));
|
vcp = malloc(sizeof(CliVcp));
|
||||||
vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1);
|
vcp->tx_stream = furi_stream_buffer_alloc(VCP_TX_BUF_SIZE, 1);
|
||||||
vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1);
|
vcp->rx_stream = furi_stream_buffer_alloc(VCP_RX_BUF_SIZE, 1);
|
||||||
}
|
}
|
||||||
furi_assert(vcp->thread == NULL);
|
furi_assert(vcp->thread == NULL);
|
||||||
|
|
||||||
@ -113,7 +112,7 @@ static int32_t vcp_worker(void* context) {
|
|||||||
#endif
|
#endif
|
||||||
if(vcp->connected == false) {
|
if(vcp->connected == false) {
|
||||||
vcp->connected = true;
|
vcp->connected = true;
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, FuriWaitForever);
|
furi_stream_buffer_send(vcp->rx_stream, &ascii_soh, 1, FuriWaitForever);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,8 +123,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
#endif
|
#endif
|
||||||
if(vcp->connected == true) {
|
if(vcp->connected == true) {
|
||||||
vcp->connected = false;
|
vcp->connected = false;
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
furi_stream_buffer_send(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +133,7 @@ static int32_t vcp_worker(void* context) {
|
|||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "StreamRx");
|
FURI_LOG_D(TAG, "StreamRx");
|
||||||
#endif
|
#endif
|
||||||
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
if(furi_stream_buffer_spaces_available(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
||||||
flags |= VcpEvtRx;
|
flags |= VcpEvtRx;
|
||||||
missed_rx--;
|
missed_rx--;
|
||||||
}
|
}
|
||||||
@ -142,14 +141,15 @@ static int32_t vcp_worker(void* context) {
|
|||||||
|
|
||||||
// New data received
|
// New data received
|
||||||
if(flags & VcpEvtRx) {
|
if(flags & VcpEvtRx) {
|
||||||
if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
if(furi_stream_buffer_spaces_available(vcp->rx_stream) >= USB_CDC_PKT_LEN) {
|
||||||
int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN);
|
int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Rx %d", len);
|
FURI_LOG_D(TAG, "Rx %d", len);
|
||||||
#endif
|
#endif
|
||||||
if(len > 0) {
|
if(len > 0) {
|
||||||
furi_check(
|
furi_check(
|
||||||
xStreamBufferSend(vcp->rx_stream, vcp->data_buffer, len, FuriWaitForever) ==
|
furi_stream_buffer_send(
|
||||||
|
vcp->rx_stream, vcp->data_buffer, len, FuriWaitForever) ==
|
||||||
(size_t)len);
|
(size_t)len);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -173,7 +173,7 @@ static int32_t vcp_worker(void* context) {
|
|||||||
// CDC write transfer done
|
// CDC write transfer done
|
||||||
if(flags & VcpEvtTx) {
|
if(flags & VcpEvtTx) {
|
||||||
size_t len =
|
size_t len =
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "Tx %d", len);
|
FURI_LOG_D(TAG, "Tx %d", len);
|
||||||
#endif
|
#endif
|
||||||
@ -202,8 +202,8 @@ static int32_t vcp_worker(void* context) {
|
|||||||
furi_hal_usb_unlock();
|
furi_hal_usb_unlock();
|
||||||
furi_hal_usb_set_config(vcp->usb_if_prev, NULL);
|
furi_hal_usb_set_config(vcp->usb_if_prev, NULL);
|
||||||
}
|
}
|
||||||
xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
furi_stream_buffer_receive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0);
|
||||||
xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
furi_stream_buffer_send(vcp->rx_stream, &ascii_eot, 1, FuriWaitForever);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -229,7 +229,7 @@ static size_t cli_vcp_rx(uint8_t* buffer, size_t size, uint32_t timeout) {
|
|||||||
size_t batch_size = size;
|
size_t batch_size = size;
|
||||||
if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE;
|
if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE;
|
||||||
|
|
||||||
size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout);
|
size_t len = furi_stream_buffer_receive(vcp->rx_stream, buffer, batch_size, timeout);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
FURI_LOG_D(TAG, "rx %u ", batch_size);
|
||||||
#endif
|
#endif
|
||||||
@ -262,7 +262,7 @@ static void cli_vcp_tx(const uint8_t* buffer, size_t size) {
|
|||||||
size_t batch_size = size;
|
size_t batch_size = size;
|
||||||
if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN;
|
if(batch_size > USB_CDC_PKT_LEN) batch_size = USB_CDC_PKT_LEN;
|
||||||
|
|
||||||
xStreamBufferSend(vcp->tx_stream, buffer, batch_size, FuriWaitForever);
|
furi_stream_buffer_send(vcp->tx_stream, buffer, batch_size, FuriWaitForever);
|
||||||
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamTx);
|
furi_thread_flags_set(furi_thread_get_id(vcp->thread), VcpEvtStreamTx);
|
||||||
#ifdef CLI_VCP_DEBUG
|
#ifdef CLI_VCP_DEBUG
|
||||||
FURI_LOG_D(TAG, "tx %u", batch_size);
|
FURI_LOG_D(TAG, "tx %u", batch_size);
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include <cli/cli.h>
|
#include <cli/cli.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <m-dict.h>
|
#include <m-dict.h>
|
||||||
|
|
||||||
#define TAG "RpcSrv"
|
#define TAG "RpcSrv"
|
||||||
@ -61,7 +60,7 @@ struct RpcSession {
|
|||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
|
|
||||||
RpcHandlerDict_t handlers;
|
RpcHandlerDict_t handlers;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
PB_Main* decoded_message;
|
PB_Main* decoded_message;
|
||||||
bool terminate;
|
bool terminate;
|
||||||
void** system_contexts;
|
void** system_contexts;
|
||||||
@ -151,7 +150,7 @@ size_t
|
|||||||
furi_assert(encoded_bytes);
|
furi_assert(encoded_bytes);
|
||||||
furi_assert(size > 0);
|
furi_assert(size > 0);
|
||||||
|
|
||||||
size_t bytes_sent = xStreamBufferSend(session->stream, encoded_bytes, size, timeout);
|
size_t bytes_sent = furi_stream_buffer_send(session->stream, encoded_bytes, size, timeout);
|
||||||
|
|
||||||
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData);
|
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData);
|
||||||
|
|
||||||
@ -160,7 +159,7 @@ size_t
|
|||||||
|
|
||||||
size_t rpc_session_get_available_size(RpcSession* session) {
|
size_t rpc_session_get_available_size(RpcSession* session) {
|
||||||
furi_assert(session);
|
furi_assert(session);
|
||||||
return xStreamBufferSpacesAvailable(session->stream);
|
return furi_stream_buffer_spaces_available(session->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
||||||
@ -174,9 +173,9 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
|||||||
size_t bytes_received = 0;
|
size_t bytes_received = 0;
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
bytes_received +=
|
bytes_received += furi_stream_buffer_receive(
|
||||||
xStreamBufferReceive(session->stream, buf + bytes_received, count - bytes_received, 0);
|
session->stream, buf + bytes_received, count - bytes_received, 0);
|
||||||
if(xStreamBufferIsEmpty(session->stream)) {
|
if(furi_stream_buffer_is_empty(session->stream)) {
|
||||||
if(session->buffer_is_empty_callback) {
|
if(session->buffer_is_empty_callback) {
|
||||||
session->buffer_is_empty_callback(session->context);
|
session->buffer_is_empty_callback(session->context);
|
||||||
}
|
}
|
||||||
@ -190,7 +189,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
|
|||||||
} else {
|
} else {
|
||||||
flags = furi_thread_flags_wait(RPC_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
flags = furi_thread_flags_wait(RPC_ALL_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||||
if(flags & RpcEvtDisconnect) {
|
if(flags & RpcEvtDisconnect) {
|
||||||
if(xStreamBufferIsEmpty(session->stream)) {
|
if(furi_stream_buffer_is_empty(session->stream)) {
|
||||||
session->terminate = true;
|
session->terminate = true;
|
||||||
istream->bytes_left = 0;
|
istream->bytes_left = 0;
|
||||||
bytes_received = 0;
|
bytes_received = 0;
|
||||||
@ -279,7 +278,7 @@ static int32_t rpc_session_worker(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(message_decode_failed) {
|
if(message_decode_failed) {
|
||||||
xStreamBufferReset(session->stream);
|
furi_stream_buffer_reset(session->stream);
|
||||||
if(!session->terminate) {
|
if(!session->terminate) {
|
||||||
/* Protobuf can't determine start and end of message.
|
/* Protobuf can't determine start and end of message.
|
||||||
* Handle this by adding varint at beginning
|
* Handle this by adding varint at beginning
|
||||||
@ -329,7 +328,7 @@ static void rpc_session_free_callback(FuriThreadState thread_state, void* contex
|
|||||||
free(session->system_contexts);
|
free(session->system_contexts);
|
||||||
free(session->decoded_message);
|
free(session->decoded_message);
|
||||||
RpcHandlerDict_clear(session->handlers);
|
RpcHandlerDict_clear(session->handlers);
|
||||||
vStreamBufferDelete(session->stream);
|
furi_stream_buffer_free(session->stream);
|
||||||
|
|
||||||
furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever);
|
furi_mutex_acquire(session->callbacks_mutex, FuriWaitForever);
|
||||||
if(session->terminated_callback) {
|
if(session->terminated_callback) {
|
||||||
@ -348,7 +347,7 @@ RpcSession* rpc_session_open(Rpc* rpc) {
|
|||||||
|
|
||||||
RpcSession* session = malloc(sizeof(RpcSession));
|
RpcSession* session = malloc(sizeof(RpcSession));
|
||||||
session->callbacks_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
session->callbacks_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||||
session->stream = xStreamBufferCreate(RPC_BUFFER_SIZE, 1);
|
session->stream = furi_stream_buffer_alloc(RPC_BUFFER_SIZE, 1);
|
||||||
session->rpc = rpc;
|
session->rpc = rpc;
|
||||||
session->terminate = false;
|
session->terminate = false;
|
||||||
session->decode_error = false;
|
session->decode_error = false;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,2.0,,
|
Version,+,2.1,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
Header,+,applications/services/cli/cli_vcp.h,,
|
Header,+,applications/services/cli/cli_vcp.h,,
|
||||||
@ -1342,6 +1342,16 @@ Function,+,furi_semaphore_alloc,FuriSemaphore*,"uint32_t, uint32_t"
|
|||||||
Function,+,furi_semaphore_free,void,FuriSemaphore*
|
Function,+,furi_semaphore_free,void,FuriSemaphore*
|
||||||
Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore*
|
Function,+,furi_semaphore_get_count,uint32_t,FuriSemaphore*
|
||||||
Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore*
|
Function,+,furi_semaphore_release,FuriStatus,FuriSemaphore*
|
||||||
|
Function,+,furi_stream_buffer_alloc,FuriStreamBuffer*,"size_t, size_t"
|
||||||
|
Function,+,furi_stream_buffer_bytes_available,size_t,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_free,void,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_is_empty,_Bool,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_is_full,_Bool,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_receive,size_t,"FuriStreamBuffer*, void*, size_t, uint32_t"
|
||||||
|
Function,+,furi_stream_buffer_reset,FuriStatus,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_buffer_send,size_t,"FuriStreamBuffer*, const void*, size_t, uint32_t"
|
||||||
|
Function,+,furi_stream_buffer_spaces_available,size_t,FuriStreamBuffer*
|
||||||
|
Function,+,furi_stream_set_trigger_level,_Bool,"FuriStreamBuffer*, size_t"
|
||||||
Function,+,furi_string_alloc,FuriString*,
|
Function,+,furi_string_alloc,FuriString*,
|
||||||
Function,+,furi_string_alloc_move,FuriString*,FuriString*
|
Function,+,furi_string_alloc_move,FuriString*,FuriString*
|
||||||
Function,+,furi_string_alloc_printf,FuriString*,"const char[], ..."
|
Function,+,furi_string_alloc_printf,FuriString*,"const char[], ..."
|
||||||
|
|
77
furi/core/stream_buffer.c
Normal file
77
furi/core/stream_buffer.c
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#include "base.h"
|
||||||
|
#include "stream_buffer.h"
|
||||||
|
#include "common_defines.h"
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <FreeRTOS-Kernel/include/stream_buffer.h>
|
||||||
|
|
||||||
|
FuriStreamBuffer* furi_stream_buffer_alloc(size_t size, size_t trigger_level) {
|
||||||
|
return xStreamBufferCreate(size, trigger_level);
|
||||||
|
};
|
||||||
|
|
||||||
|
void furi_stream_buffer_free(FuriStreamBuffer* stream_buffer) {
|
||||||
|
vStreamBufferDelete(stream_buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool furi_stream_set_trigger_level(FuriStreamBuffer* stream_buffer, size_t trigger_level) {
|
||||||
|
return xStreamBufferSetTriggerLevel(stream_buffer, trigger_level) == pdTRUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t furi_stream_buffer_send(
|
||||||
|
FuriStreamBuffer* stream_buffer,
|
||||||
|
const void* data,
|
||||||
|
size_t length,
|
||||||
|
uint32_t timeout) {
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
if(FURI_IS_IRQ_MODE() != 0U) {
|
||||||
|
BaseType_t yield;
|
||||||
|
ret = xStreamBufferSendFromISR(stream_buffer, data, length, &yield);
|
||||||
|
portYIELD_FROM_ISR(yield);
|
||||||
|
} else {
|
||||||
|
ret = xStreamBufferSend(stream_buffer, data, length, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t furi_stream_buffer_receive(
|
||||||
|
FuriStreamBuffer* stream_buffer,
|
||||||
|
void* data,
|
||||||
|
size_t length,
|
||||||
|
uint32_t timeout) {
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
if(FURI_IS_IRQ_MODE() != 0U) {
|
||||||
|
BaseType_t yield;
|
||||||
|
ret = xStreamBufferReceiveFromISR(stream_buffer, data, length, &yield);
|
||||||
|
portYIELD_FROM_ISR(yield);
|
||||||
|
} else {
|
||||||
|
ret = xStreamBufferReceive(stream_buffer, data, length, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t furi_stream_buffer_bytes_available(FuriStreamBuffer* stream_buffer) {
|
||||||
|
return xStreamBufferBytesAvailable(stream_buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t furi_stream_buffer_spaces_available(FuriStreamBuffer* stream_buffer) {
|
||||||
|
return xStreamBufferSpacesAvailable(stream_buffer);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool furi_stream_buffer_is_full(FuriStreamBuffer* stream_buffer) {
|
||||||
|
return xStreamBufferIsFull(stream_buffer) == pdTRUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool furi_stream_buffer_is_empty(FuriStreamBuffer* stream_buffer) {
|
||||||
|
return (xStreamBufferIsEmpty(stream_buffer) == pdTRUE);
|
||||||
|
};
|
||||||
|
|
||||||
|
FuriStatus furi_stream_buffer_reset(FuriStreamBuffer* stream_buffer) {
|
||||||
|
if(xStreamBufferReset(stream_buffer) == pdPASS) {
|
||||||
|
return FuriStatusOk;
|
||||||
|
} else {
|
||||||
|
return FuriStatusError;
|
||||||
|
}
|
||||||
|
}
|
152
furi/core/stream_buffer.h
Normal file
152
furi/core/stream_buffer.h
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
/**
|
||||||
|
* @file stream_buffer.h
|
||||||
|
* Furi stream buffer primitive.
|
||||||
|
*
|
||||||
|
* Stream buffers are used to send a continuous stream of data from one task or
|
||||||
|
* interrupt to another. Their implementation is light weight, making them
|
||||||
|
* particularly suited for interrupt to task and core to core communication
|
||||||
|
* scenarios.
|
||||||
|
*
|
||||||
|
* ***NOTE***: Stream buffer implementation assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader).
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void FuriStreamBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate stream buffer instance.
|
||||||
|
* Stream buffer implementation assumes there is only one task or
|
||||||
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
|
* interrupt that will read from the buffer (the reader).
|
||||||
|
*
|
||||||
|
* @param size The total number of bytes the stream buffer will be able to hold at any one time.
|
||||||
|
* @param trigger_level The number of bytes that must be in the stream buffer
|
||||||
|
* before a task that is blocked on the stream buffer to wait for data is moved out of the blocked state.
|
||||||
|
* @return The stream buffer instance.
|
||||||
|
*/
|
||||||
|
FuriStreamBuffer* furi_stream_buffer_alloc(size_t size, size_t trigger_level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Free stream buffer instance
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance.
|
||||||
|
*/
|
||||||
|
void furi_stream_buffer_free(FuriStreamBuffer* stream_buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set trigger level for stream buffer.
|
||||||
|
* A stream buffer's trigger level is the number of bytes that must be in the
|
||||||
|
* stream buffer before a task that is blocked on the stream buffer to
|
||||||
|
* wait for data is moved out of the blocked state.
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance
|
||||||
|
* @param trigger_level The new trigger level for the stream buffer.
|
||||||
|
* @return true if trigger level can be be updated (new trigger level was less than or equal to the stream buffer's length).
|
||||||
|
* @return false if trigger level can't be be updated (new trigger level was greater than the stream buffer's length).
|
||||||
|
*/
|
||||||
|
bool furi_stream_set_trigger_level(FuriStreamBuffer* stream_buffer, size_t trigger_level);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends bytes to a stream buffer. The bytes are copied into the stream buffer.
|
||||||
|
* Wakes up task waiting for data to become available if called from ISR.
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance.
|
||||||
|
* @param data A pointer to the data that is to be copied into the stream buffer.
|
||||||
|
* @param length The maximum number of bytes to copy from data into the stream buffer.
|
||||||
|
* @param timeout The maximum amount of time the task should remain in the
|
||||||
|
* Blocked state to wait for space to become available if the stream buffer is full.
|
||||||
|
* Will return immediately if timeout is zero.
|
||||||
|
* Setting timeout to FuriWaitForever will cause the task to wait indefinitely.
|
||||||
|
* Ignored if called from ISR.
|
||||||
|
* @return The number of bytes actually written to the stream buffer.
|
||||||
|
*/
|
||||||
|
size_t furi_stream_buffer_send(
|
||||||
|
FuriStreamBuffer* stream_buffer,
|
||||||
|
const void* data,
|
||||||
|
size_t length,
|
||||||
|
uint32_t timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Receives bytes from a stream buffer.
|
||||||
|
* Wakes up task waiting for space to become available if called from ISR.
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance.
|
||||||
|
* @param data A pointer to the buffer into which the received bytes will be
|
||||||
|
* copied.
|
||||||
|
* @param length The length of the buffer pointed to by the data parameter.
|
||||||
|
* @param timeout The maximum amount of time the task should remain in the
|
||||||
|
* Blocked state to wait for data to become available if the stream buffer is empty.
|
||||||
|
* Will return immediately if timeout is zero.
|
||||||
|
* Setting timeout to FuriWaitForever will cause the task to wait indefinitely.
|
||||||
|
* Ignored if called from ISR.
|
||||||
|
* @return The number of bytes read from the stream buffer, if any.
|
||||||
|
*/
|
||||||
|
size_t furi_stream_buffer_receive(
|
||||||
|
FuriStreamBuffer* stream_buffer,
|
||||||
|
void* data,
|
||||||
|
size_t length,
|
||||||
|
uint32_t timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queries a stream buffer to see how much data it contains, which is equal to
|
||||||
|
* the number of bytes that can be read from the stream buffer before the stream
|
||||||
|
* buffer would be empty.
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance.
|
||||||
|
* @return The number of bytes that can be read from the stream buffer before
|
||||||
|
* the stream buffer would be empty.
|
||||||
|
*/
|
||||||
|
size_t furi_stream_buffer_bytes_available(FuriStreamBuffer* stream_buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queries a stream buffer to see how much free space it contains, which is
|
||||||
|
* equal to the amount of data that can be sent to the stream buffer before it
|
||||||
|
* is full.
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance.
|
||||||
|
* @return The number of bytes that can be written to the stream buffer before
|
||||||
|
* the stream buffer would be full.
|
||||||
|
*/
|
||||||
|
size_t furi_stream_buffer_spaces_available(FuriStreamBuffer* stream_buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queries a stream buffer to see if it is full.
|
||||||
|
*
|
||||||
|
* @param stream_buffer stream buffer instance.
|
||||||
|
* @return true if the stream buffer is full.
|
||||||
|
* @return false if the stream buffer is not full.
|
||||||
|
*/
|
||||||
|
bool furi_stream_buffer_is_full(FuriStreamBuffer* stream_buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Queries a stream buffer to see if it is empty.
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance.
|
||||||
|
* @return true if the stream buffer is empty.
|
||||||
|
* @return false if the stream buffer is not empty.
|
||||||
|
*/
|
||||||
|
bool furi_stream_buffer_is_empty(FuriStreamBuffer* stream_buffer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets a stream buffer to its initial, empty, state. Any data that was
|
||||||
|
* in the stream buffer is discarded. A stream buffer can only be reset if there
|
||||||
|
* are no tasks blocked waiting to either send to or receive from the stream buffer.
|
||||||
|
*
|
||||||
|
* @param stream_buffer The stream buffer instance.
|
||||||
|
* @return FuriStatusOk if the stream buffer is reset.
|
||||||
|
* @return FuriStatusError if there was a task blocked waiting to send to or read
|
||||||
|
* from the stream buffer then the stream buffer is not reset.
|
||||||
|
*/
|
||||||
|
FuriStatus furi_stream_buffer_reset(FuriStreamBuffer* stream_buffer);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
33
furi/furi.h
33
furi/furi.h
@ -2,22 +2,23 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <core/check.h>
|
#include "core/check.h"
|
||||||
#include <core/common_defines.h>
|
#include "core/common_defines.h"
|
||||||
#include <core/event_flag.h>
|
#include "core/event_flag.h"
|
||||||
#include <core/kernel.h>
|
#include "core/kernel.h"
|
||||||
#include <core/log.h>
|
#include "core/log.h"
|
||||||
#include <core/memmgr.h>
|
#include "core/memmgr.h"
|
||||||
#include <core/memmgr_heap.h>
|
#include "core/memmgr_heap.h"
|
||||||
#include <core/message_queue.h>
|
#include "core/message_queue.h"
|
||||||
#include <core/mutex.h>
|
#include "core/mutex.h"
|
||||||
#include <core/pubsub.h>
|
#include "core/pubsub.h"
|
||||||
#include <core/record.h>
|
#include "core/record.h"
|
||||||
#include <core/semaphore.h>
|
#include "core/semaphore.h"
|
||||||
#include <core/thread.h>
|
#include "core/thread.h"
|
||||||
#include <core/timer.h>
|
#include "core/timer.h"
|
||||||
#include <core/valuemutex.h>
|
#include "core/valuemutex.h"
|
||||||
#include <core/string.h>
|
#include "core/string.h"
|
||||||
|
#include "core/stream_buffer.h"
|
||||||
|
|
||||||
#include <furi_hal_gpio.h>
|
#include <furi_hal_gpio.h>
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
#define INFRARED_WORKER_RX_TIMEOUT INFRARED_RAW_RX_TIMING_DELAY_US
|
#define INFRARED_WORKER_RX_TIMEOUT INFRARED_RAW_RX_TIMING_DELAY_US
|
||||||
|
|
||||||
@ -50,7 +49,7 @@ struct InfraredWorkerSignal {
|
|||||||
|
|
||||||
struct InfraredWorker {
|
struct InfraredWorker {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
|
|
||||||
InfraredWorkerSignal signal;
|
InfraredWorkerSignal signal;
|
||||||
InfraredWorkerState state;
|
InfraredWorkerState state;
|
||||||
@ -100,15 +99,13 @@ static void infrared_worker_rx_timeout_callback(void* context) {
|
|||||||
static void infrared_worker_rx_callback(void* context, bool level, uint32_t duration) {
|
static void infrared_worker_rx_callback(void* context, bool level, uint32_t duration) {
|
||||||
InfraredWorker* instance = context;
|
InfraredWorker* instance = context;
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
furi_assert(duration != 0);
|
furi_assert(duration != 0);
|
||||||
LevelDuration level_duration = level_duration_make(level, duration);
|
LevelDuration level_duration = level_duration_make(level, duration);
|
||||||
|
|
||||||
size_t ret = xStreamBufferSendFromISR(
|
size_t ret =
|
||||||
instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0);
|
||||||
uint32_t events = (ret == sizeof(LevelDuration)) ? INFRARED_WORKER_RX_RECEIVED :
|
uint32_t events = (ret == sizeof(LevelDuration)) ? INFRARED_WORKER_RX_RECEIVED :
|
||||||
INFRARED_WORKER_OVERRUN;
|
INFRARED_WORKER_OVERRUN;
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
|
|
||||||
uint32_t flags_set = furi_thread_flags_set(furi_thread_get_id(instance->thread), events);
|
uint32_t flags_set = furi_thread_flags_set(furi_thread_get_id(instance->thread), events);
|
||||||
furi_check(flags_set & events);
|
furi_check(flags_set & events);
|
||||||
@ -179,7 +176,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) {
|
|||||||
if(instance->signal.timings_cnt == 0)
|
if(instance->signal.timings_cnt == 0)
|
||||||
notification_message(instance->notification, &sequence_display_backlight_on);
|
notification_message(instance->notification, &sequence_display_backlight_on);
|
||||||
while(sizeof(LevelDuration) ==
|
while(sizeof(LevelDuration) ==
|
||||||
xStreamBufferReceive(
|
furi_stream_buffer_receive(
|
||||||
instance->stream, &level_duration, sizeof(LevelDuration), 0)) {
|
instance->stream, &level_duration, sizeof(LevelDuration), 0)) {
|
||||||
if(!instance->rx.overrun) {
|
if(!instance->rx.overrun) {
|
||||||
bool level = level_duration_get_level(level_duration);
|
bool level = level_duration_get_level(level_duration);
|
||||||
@ -232,7 +229,7 @@ InfraredWorker* infrared_worker_alloc() {
|
|||||||
size_t buffer_size =
|
size_t buffer_size =
|
||||||
MAX(sizeof(InfraredWorkerTiming) * (MAX_TIMINGS_AMOUNT + 1),
|
MAX(sizeof(InfraredWorkerTiming) * (MAX_TIMINGS_AMOUNT + 1),
|
||||||
sizeof(LevelDuration) * MAX_TIMINGS_AMOUNT);
|
sizeof(LevelDuration) * MAX_TIMINGS_AMOUNT);
|
||||||
instance->stream = xStreamBufferCreate(buffer_size, sizeof(InfraredWorkerTiming));
|
instance->stream = furi_stream_buffer_alloc(buffer_size, sizeof(InfraredWorkerTiming));
|
||||||
instance->infrared_decoder = infrared_alloc_decoder();
|
instance->infrared_decoder = infrared_alloc_decoder();
|
||||||
instance->infrared_encoder = infrared_alloc_encoder();
|
instance->infrared_encoder = infrared_alloc_encoder();
|
||||||
instance->blink_enable = false;
|
instance->blink_enable = false;
|
||||||
@ -249,7 +246,7 @@ void infrared_worker_free(InfraredWorker* instance) {
|
|||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
infrared_free_decoder(instance->infrared_decoder);
|
infrared_free_decoder(instance->infrared_decoder);
|
||||||
infrared_free_encoder(instance->infrared_encoder);
|
infrared_free_encoder(instance->infrared_encoder);
|
||||||
vStreamBufferDelete(instance->stream);
|
furi_stream_buffer_free(instance->stream);
|
||||||
furi_thread_free(instance->thread);
|
furi_thread_free(instance->thread);
|
||||||
|
|
||||||
free(instance);
|
free(instance);
|
||||||
@ -259,7 +256,7 @@ void infrared_worker_rx_start(InfraredWorker* instance) {
|
|||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(instance->state == InfraredWorkerStateIdle);
|
furi_assert(instance->state == InfraredWorkerStateIdle);
|
||||||
|
|
||||||
xStreamBufferSetTriggerLevel(instance->stream, sizeof(LevelDuration));
|
furi_stream_set_trigger_level(instance->stream, sizeof(LevelDuration));
|
||||||
|
|
||||||
furi_thread_set_callback(instance->thread, infrared_worker_rx_thread);
|
furi_thread_set_callback(instance->thread, infrared_worker_rx_thread);
|
||||||
furi_thread_start(instance->thread);
|
furi_thread_start(instance->thread);
|
||||||
@ -285,9 +282,9 @@ void infrared_worker_rx_stop(InfraredWorker* instance) {
|
|||||||
furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT);
|
furi_thread_flags_set(furi_thread_get_id(instance->thread), INFRARED_WORKER_EXIT);
|
||||||
furi_thread_join(instance->thread);
|
furi_thread_join(instance->thread);
|
||||||
|
|
||||||
BaseType_t xReturn = xStreamBufferReset(instance->stream);
|
FuriStatus status = furi_stream_buffer_reset(instance->stream);
|
||||||
furi_assert(xReturn == pdPASS);
|
furi_assert(status == FuriStatusOk);
|
||||||
(void)xReturn;
|
(void)status;
|
||||||
|
|
||||||
instance->state = InfraredWorkerStateIdle;
|
instance->state = InfraredWorkerStateIdle;
|
||||||
}
|
}
|
||||||
@ -325,7 +322,7 @@ void infrared_worker_tx_start(InfraredWorker* instance) {
|
|||||||
furi_assert(instance->tx.get_signal_callback);
|
furi_assert(instance->tx.get_signal_callback);
|
||||||
|
|
||||||
// size have to be greater than api hal infrared async tx buffer size
|
// size have to be greater than api hal infrared async tx buffer size
|
||||||
xStreamBufferSetTriggerLevel(instance->stream, sizeof(InfraredWorkerTiming));
|
furi_stream_set_trigger_level(instance->stream, sizeof(InfraredWorkerTiming));
|
||||||
|
|
||||||
furi_thread_set_callback(instance->thread, infrared_worker_tx_thread);
|
furi_thread_set_callback(instance->thread, infrared_worker_tx_thread);
|
||||||
|
|
||||||
@ -358,7 +355,7 @@ static FuriHalInfraredTxGetDataState
|
|||||||
FuriHalInfraredTxGetDataState state;
|
FuriHalInfraredTxGetDataState state;
|
||||||
|
|
||||||
if(sizeof(InfraredWorkerTiming) ==
|
if(sizeof(InfraredWorkerTiming) ==
|
||||||
xStreamBufferReceiveFromISR(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0)) {
|
furi_stream_buffer_receive(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0)) {
|
||||||
*level = timing.level;
|
*level = timing.level;
|
||||||
*duration = timing.duration;
|
*duration = timing.duration;
|
||||||
state = timing.state;
|
state = timing.state;
|
||||||
@ -420,7 +417,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) {
|
|||||||
InfraredWorkerTiming timing;
|
InfraredWorkerTiming timing;
|
||||||
InfraredStatus status = InfraredStatusError;
|
InfraredStatus status = InfraredStatusError;
|
||||||
|
|
||||||
while(!xStreamBufferIsFull(instance->stream) && !instance->tx.need_reinitialization &&
|
while(!furi_stream_buffer_is_full(instance->stream) && !instance->tx.need_reinitialization &&
|
||||||
new_data_available) {
|
new_data_available) {
|
||||||
if(instance->signal.decoded) {
|
if(instance->signal.decoded) {
|
||||||
status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level);
|
status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level);
|
||||||
@ -454,7 +451,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) {
|
|||||||
furi_assert(0);
|
furi_assert(0);
|
||||||
}
|
}
|
||||||
uint32_t written_size =
|
uint32_t written_size =
|
||||||
xStreamBufferSend(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0);
|
furi_stream_buffer_send(instance->stream, &timing, sizeof(InfraredWorkerTiming), 0);
|
||||||
furi_assert(sizeof(InfraredWorkerTiming) == written_size);
|
furi_assert(sizeof(InfraredWorkerTiming) == written_size);
|
||||||
(void)written_size;
|
(void)written_size;
|
||||||
}
|
}
|
||||||
@ -564,10 +561,9 @@ void infrared_worker_tx_stop(InfraredWorker* instance) {
|
|||||||
furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL);
|
furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL);
|
||||||
|
|
||||||
instance->signal.timings_cnt = 0;
|
instance->signal.timings_cnt = 0;
|
||||||
BaseType_t xReturn = pdFAIL;
|
FuriStatus status = furi_stream_buffer_reset(instance->stream);
|
||||||
xReturn = xStreamBufferReset(instance->stream);
|
furi_assert(status == FuriStatusOk);
|
||||||
furi_assert(xReturn == pdPASS);
|
(void)status;
|
||||||
(void)xReturn;
|
|
||||||
instance->state = InfraredWorkerStateIdle;
|
instance->state = InfraredWorkerStateIdle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include <toolbox/stream/file_stream.h>
|
#include <toolbox/stream/file_stream.h>
|
||||||
#include <toolbox/buffer_stream.h>
|
#include <toolbox/buffer_stream.h>
|
||||||
#include <toolbox/varint.h>
|
#include <toolbox/varint.h>
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include "lfrfid_raw_worker.h"
|
#include "lfrfid_raw_worker.h"
|
||||||
#include "lfrfid_raw_file.h"
|
#include "lfrfid_raw_file.h"
|
||||||
#include "tools/varint_pair.h"
|
#include "tools/varint_pair.h"
|
||||||
@ -16,7 +15,7 @@
|
|||||||
// emulate mode
|
// emulate mode
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t overrun_count;
|
size_t overrun_count;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
} RfidEmulateCtx;
|
} RfidEmulateCtx;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -126,20 +125,13 @@ void lfrfid_raw_worker_stop(LFRFIDRawWorker* worker) {
|
|||||||
static void lfrfid_raw_worker_capture(bool level, uint32_t duration, void* context) {
|
static void lfrfid_raw_worker_capture(bool level, uint32_t duration, void* context) {
|
||||||
LFRFIDRawWorkerReadData* ctx = context;
|
LFRFIDRawWorkerReadData* ctx = context;
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
|
|
||||||
bool need_to_send = varint_pair_pack(ctx->pair, level, duration);
|
bool need_to_send = varint_pair_pack(ctx->pair, level, duration);
|
||||||
|
|
||||||
if(need_to_send) {
|
if(need_to_send) {
|
||||||
buffer_stream_send_from_isr(
|
buffer_stream_send_from_isr(
|
||||||
ctx->stream,
|
ctx->stream, varint_pair_get_data(ctx->pair), varint_pair_get_size(ctx->pair));
|
||||||
varint_pair_get_data(ctx->pair),
|
|
||||||
varint_pair_get_size(ctx->pair),
|
|
||||||
&xHigherPriorityTaskWoken);
|
|
||||||
varint_pair_reset(ctx->pair);
|
varint_pair_reset(ctx->pair);
|
||||||
}
|
}
|
||||||
|
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t lfrfid_raw_read_worker_thread(void* thread_context) {
|
static int32_t lfrfid_raw_read_worker_thread(void* thread_context) {
|
||||||
@ -236,7 +228,7 @@ static void rfid_emulate_dma_isr(bool half, void* context) {
|
|||||||
RfidEmulateCtx* ctx = context;
|
RfidEmulateCtx* ctx = context;
|
||||||
|
|
||||||
uint32_t flag = half ? HalfTransfer : TransferComplete;
|
uint32_t flag = half ? HalfTransfer : TransferComplete;
|
||||||
size_t len = xStreamBufferSendFromISR(ctx->stream, &flag, sizeof(uint32_t), pdFALSE);
|
size_t len = furi_stream_buffer_send(ctx->stream, &flag, sizeof(uint32_t), 0);
|
||||||
if(len != sizeof(uint32_t)) {
|
if(len != sizeof(uint32_t)) {
|
||||||
ctx->overrun_count++;
|
ctx->overrun_count++;
|
||||||
}
|
}
|
||||||
@ -251,7 +243,7 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) {
|
|||||||
|
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
data->ctx.overrun_count = 0;
|
data->ctx.overrun_count = 0;
|
||||||
data->ctx.stream = xStreamBufferCreate(sizeof(uint32_t), sizeof(uint32_t));
|
data->ctx.stream = furi_stream_buffer_alloc(sizeof(uint32_t), sizeof(uint32_t));
|
||||||
|
|
||||||
LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage);
|
LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage);
|
||||||
|
|
||||||
@ -287,7 +279,8 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) {
|
|||||||
uint32_t flag = 0;
|
uint32_t flag = 0;
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
size_t size = xStreamBufferReceive(data->ctx.stream, &flag, sizeof(uint32_t), 100);
|
size_t size =
|
||||||
|
furi_stream_buffer_receive(data->ctx.stream, &flag, sizeof(uint32_t), 100);
|
||||||
|
|
||||||
if(size == sizeof(uint32_t)) {
|
if(size == sizeof(uint32_t)) {
|
||||||
size_t start = 0;
|
size_t start = 0;
|
||||||
@ -348,7 +341,7 @@ static int32_t lfrfid_raw_emulate_worker_thread(void* thread_context) {
|
|||||||
FURI_LOG_E(TAG_EMULATE, "overruns: %lu", data->ctx.overrun_count);
|
FURI_LOG_E(TAG_EMULATE, "overruns: %lu", data->ctx.overrun_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
vStreamBufferDelete(data->ctx.stream);
|
furi_stream_buffer_free(data->ctx.stream);
|
||||||
lfrfid_raw_file_free(file);
|
lfrfid_raw_file_free(file);
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
free(data);
|
free(data);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include "lfrfid_worker_i.h"
|
#include "lfrfid_worker_i.h"
|
||||||
#include "tools/t5577.h"
|
#include "tools/t5577.h"
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <toolbox/pulse_protocols/pulse_glue.h>
|
#include <toolbox/pulse_protocols/pulse_glue.h>
|
||||||
#include <toolbox/buffer_stream.h>
|
#include <toolbox/buffer_stream.h>
|
||||||
#include "tools/varint_pair.h"
|
#include "tools/varint_pair.h"
|
||||||
@ -81,17 +80,12 @@ static void lfrfid_worker_read_capture(bool level, uint32_t duration, void* cont
|
|||||||
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, level);
|
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_VALUE, level);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
bool need_to_send = varint_pair_pack(ctx->pair, level, duration);
|
bool need_to_send = varint_pair_pack(ctx->pair, level, duration);
|
||||||
if(need_to_send) {
|
if(need_to_send) {
|
||||||
buffer_stream_send_from_isr(
|
buffer_stream_send_from_isr(
|
||||||
ctx->stream,
|
ctx->stream, varint_pair_get_data(ctx->pair), varint_pair_get_size(ctx->pair));
|
||||||
varint_pair_get_data(ctx->pair),
|
|
||||||
varint_pair_get_size(ctx->pair),
|
|
||||||
&xHigherPriorityTaskWoken);
|
|
||||||
varint_pair_reset(ctx->pair);
|
varint_pair_reset(ctx->pair);
|
||||||
}
|
}
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -407,14 +401,14 @@ typedef enum {
|
|||||||
} LFRFIDWorkerEmulateDMAEvent;
|
} LFRFIDWorkerEmulateDMAEvent;
|
||||||
|
|
||||||
static void lfrfid_worker_emulate_dma_isr(bool half, void* context) {
|
static void lfrfid_worker_emulate_dma_isr(bool half, void* context) {
|
||||||
StreamBufferHandle_t stream = context;
|
FuriStreamBuffer* stream = context;
|
||||||
uint32_t flag = half ? HalfTransfer : TransferComplete;
|
uint32_t flag = half ? HalfTransfer : TransferComplete;
|
||||||
xStreamBufferSendFromISR(stream, &flag, sizeof(uint32_t), pdFALSE);
|
furi_stream_buffer_send(stream, &flag, sizeof(uint32_t), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
|
static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
|
||||||
LFRFIDWorkerEmulateBuffer* buffer = malloc(sizeof(LFRFIDWorkerEmulateBuffer));
|
LFRFIDWorkerEmulateBuffer* buffer = malloc(sizeof(LFRFIDWorkerEmulateBuffer));
|
||||||
StreamBufferHandle_t stream = xStreamBufferCreate(sizeof(uint32_t), sizeof(uint32_t));
|
FuriStreamBuffer* stream = furi_stream_buffer_alloc(sizeof(uint32_t), sizeof(uint32_t));
|
||||||
LFRFIDProtocol protocol = worker->protocol;
|
LFRFIDProtocol protocol = worker->protocol;
|
||||||
PulseGlue* pulse_glue = pulse_glue_alloc();
|
PulseGlue* pulse_glue = pulse_glue_alloc();
|
||||||
|
|
||||||
@ -449,7 +443,7 @@ static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
|
|||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
uint32_t flag = 0;
|
uint32_t flag = 0;
|
||||||
size_t size = xStreamBufferReceive(stream, &flag, sizeof(uint32_t), 100);
|
size_t size = furi_stream_buffer_receive(stream, &flag, sizeof(uint32_t), 100);
|
||||||
|
|
||||||
#ifdef LFRFID_WORKER_READ_DEBUG_GPIO
|
#ifdef LFRFID_WORKER_READ_DEBUG_GPIO
|
||||||
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, true);
|
furi_hal_gpio_write(LFRFID_WORKER_READ_DEBUG_GPIO_LOAD, true);
|
||||||
@ -497,7 +491,7 @@ static void lfrfid_worker_mode_emulate_process(LFRFIDWorker* worker) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
free(buffer);
|
free(buffer);
|
||||||
vStreamBufferDelete(stream);
|
furi_stream_buffer_free(stream);
|
||||||
pulse_glue_free(pulse_glue);
|
pulse_glue_free(pulse_glue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "reader_analyzer.h"
|
#include "reader_analyzer.h"
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <lib/nfc/protocols/nfc_util.h>
|
#include <lib/nfc/protocols/nfc_util.h>
|
||||||
#include <lib/nfc/protocols/mifare_classic.h>
|
#include <lib/nfc/protocols/mifare_classic.h>
|
||||||
#include <m-array.h>
|
#include <m-array.h>
|
||||||
@ -26,7 +25,7 @@ struct ReaderAnalyzer {
|
|||||||
FuriHalNfcDevData nfc_data;
|
FuriHalNfcDevData nfc_data;
|
||||||
|
|
||||||
bool alive;
|
bool alive;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
|
|
||||||
ReaderAnalyzerParseDataCallback callback;
|
ReaderAnalyzerParseDataCallback callback;
|
||||||
@ -86,8 +85,8 @@ int32_t reader_analyzer_thread(void* context) {
|
|||||||
ReaderAnalyzer* reader_analyzer = context;
|
ReaderAnalyzer* reader_analyzer = context;
|
||||||
uint8_t buffer[READER_ANALYZER_MAX_BUFF_SIZE] = {};
|
uint8_t buffer[READER_ANALYZER_MAX_BUFF_SIZE] = {};
|
||||||
|
|
||||||
while(reader_analyzer->alive || !xStreamBufferIsEmpty(reader_analyzer->stream)) {
|
while(reader_analyzer->alive || !furi_stream_buffer_is_empty(reader_analyzer->stream)) {
|
||||||
size_t ret = xStreamBufferReceive(
|
size_t ret = furi_stream_buffer_receive(
|
||||||
reader_analyzer->stream, buffer, READER_ANALYZER_MAX_BUFF_SIZE, 50);
|
reader_analyzer->stream, buffer, READER_ANALYZER_MAX_BUFF_SIZE, 50);
|
||||||
if(ret) {
|
if(ret) {
|
||||||
reader_analyzer_parse(reader_analyzer, buffer, ret);
|
reader_analyzer_parse(reader_analyzer, buffer, ret);
|
||||||
@ -103,7 +102,7 @@ ReaderAnalyzer* reader_analyzer_alloc() {
|
|||||||
instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic];
|
instance->nfc_data = reader_analyzer_nfc_data[ReaderAnalyzerNfcDataMfClassic];
|
||||||
instance->alive = false;
|
instance->alive = false;
|
||||||
instance->stream =
|
instance->stream =
|
||||||
xStreamBufferCreate(READER_ANALYZER_MAX_BUFF_SIZE, sizeof(ReaderAnalyzerHeader));
|
furi_stream_buffer_alloc(READER_ANALYZER_MAX_BUFF_SIZE, sizeof(ReaderAnalyzerHeader));
|
||||||
|
|
||||||
instance->thread = furi_thread_alloc();
|
instance->thread = furi_thread_alloc();
|
||||||
furi_thread_set_name(instance->thread, "ReaderAnalyzerWorker");
|
furi_thread_set_name(instance->thread, "ReaderAnalyzerWorker");
|
||||||
@ -129,7 +128,7 @@ static void reader_analyzer_mfkey_callback(Mfkey32Event event, void* context) {
|
|||||||
void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) {
|
void reader_analyzer_start(ReaderAnalyzer* instance, ReaderAnalyzerMode mode) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
xStreamBufferReset(instance->stream);
|
furi_stream_buffer_reset(instance->stream);
|
||||||
if(mode & ReaderAnalyzerModeDebugLog) {
|
if(mode & ReaderAnalyzerModeDebugLog) {
|
||||||
instance->debug_log = nfc_debug_log_alloc();
|
instance->debug_log = nfc_debug_log_alloc();
|
||||||
}
|
}
|
||||||
@ -171,7 +170,7 @@ void reader_analyzer_free(ReaderAnalyzer* instance) {
|
|||||||
|
|
||||||
reader_analyzer_stop(instance);
|
reader_analyzer_stop(instance);
|
||||||
furi_thread_free(instance->thread);
|
furi_thread_free(instance->thread);
|
||||||
vStreamBufferDelete(instance->stream);
|
furi_stream_buffer_free(instance->stream);
|
||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,12 +214,12 @@ static void reader_analyzer_write(
|
|||||||
ReaderAnalyzerHeader header = {
|
ReaderAnalyzerHeader header = {
|
||||||
.reader_to_tag = reader_to_tag, .crc_dropped = crc_dropped, .len = len};
|
.reader_to_tag = reader_to_tag, .crc_dropped = crc_dropped, .len = len};
|
||||||
size_t data_sent = 0;
|
size_t data_sent = 0;
|
||||||
data_sent = xStreamBufferSend(
|
data_sent = furi_stream_buffer_send(
|
||||||
instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever);
|
instance->stream, &header, sizeof(ReaderAnalyzerHeader), FuriWaitForever);
|
||||||
if(data_sent != sizeof(ReaderAnalyzerHeader)) {
|
if(data_sent != sizeof(ReaderAnalyzerHeader)) {
|
||||||
FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, sizeof(ReaderAnalyzerHeader));
|
FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, sizeof(ReaderAnalyzerHeader));
|
||||||
}
|
}
|
||||||
data_sent = xStreamBufferSend(instance->stream, data, len, FuriWaitForever);
|
data_sent = furi_stream_buffer_send(instance->stream, data, len, FuriWaitForever);
|
||||||
if(data_sent != len) {
|
if(data_sent != len) {
|
||||||
FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, len);
|
FURI_LOG_W(TAG, "Sent %d out of %d bytes", data_sent, len);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include "ibutton_worker_i.h"
|
#include "ibutton_worker_i.h"
|
||||||
#include "ibutton_key_command.h"
|
#include "ibutton_key_command.h"
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
void ibutton_worker_mode_idle_start(iButtonWorker* worker);
|
void ibutton_worker_mode_idle_start(iButtonWorker* worker);
|
||||||
void ibutton_worker_mode_idle_tick(iButtonWorker* worker);
|
void ibutton_worker_mode_idle_tick(iButtonWorker* worker);
|
||||||
@ -65,7 +64,7 @@ void ibutton_worker_mode_idle_stop(iButtonWorker* worker) {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t last_dwt_value;
|
uint32_t last_dwt_value;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
} iButtonReadContext;
|
} iButtonReadContext;
|
||||||
|
|
||||||
void ibutton_worker_comparator_callback(bool level, void* context) {
|
void ibutton_worker_comparator_callback(bool level, void* context) {
|
||||||
@ -75,7 +74,7 @@ void ibutton_worker_comparator_callback(bool level, void* context) {
|
|||||||
|
|
||||||
LevelDuration data =
|
LevelDuration data =
|
||||||
level_duration_make(level, current_dwt_value - read_context->last_dwt_value);
|
level_duration_make(level, current_dwt_value - read_context->last_dwt_value);
|
||||||
xStreamBufferSend(read_context->stream, &data, sizeof(LevelDuration), 0);
|
furi_stream_buffer_send(read_context->stream, &data, sizeof(LevelDuration), 0);
|
||||||
|
|
||||||
read_context->last_dwt_value = current_dwt_value;
|
read_context->last_dwt_value = current_dwt_value;
|
||||||
}
|
}
|
||||||
@ -91,7 +90,7 @@ bool ibutton_worker_read_comparator(iButtonWorker* worker) {
|
|||||||
|
|
||||||
iButtonReadContext read_context = {
|
iButtonReadContext read_context = {
|
||||||
.last_dwt_value = DWT->CYCCNT,
|
.last_dwt_value = DWT->CYCCNT,
|
||||||
.stream = xStreamBufferCreate(sizeof(LevelDuration) * 512, 1),
|
.stream = furi_stream_buffer_alloc(sizeof(LevelDuration) * 512, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
furi_hal_rfid_comp_set_callback(ibutton_worker_comparator_callback, &read_context);
|
furi_hal_rfid_comp_set_callback(ibutton_worker_comparator_callback, &read_context);
|
||||||
@ -100,7 +99,8 @@ bool ibutton_worker_read_comparator(iButtonWorker* worker) {
|
|||||||
uint32_t tick_start = furi_get_tick();
|
uint32_t tick_start = furi_get_tick();
|
||||||
while(true) {
|
while(true) {
|
||||||
LevelDuration level;
|
LevelDuration level;
|
||||||
size_t ret = xStreamBufferReceive(read_context.stream, &level, sizeof(LevelDuration), 100);
|
size_t ret =
|
||||||
|
furi_stream_buffer_receive(read_context.stream, &level, sizeof(LevelDuration), 100);
|
||||||
|
|
||||||
if((furi_get_tick() - tick_start) > 100) {
|
if((furi_get_tick() - tick_start) > 100) {
|
||||||
break;
|
break;
|
||||||
@ -141,7 +141,7 @@ bool ibutton_worker_read_comparator(iButtonWorker* worker) {
|
|||||||
furi_hal_rfid_comp_set_callback(NULL, NULL);
|
furi_hal_rfid_comp_set_callback(NULL, NULL);
|
||||||
furi_hal_rfid_pins_reset();
|
furi_hal_rfid_pins_reset();
|
||||||
|
|
||||||
vStreamBufferDelete(read_context.stream);
|
furi_stream_buffer_free(read_context.stream);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "subghz_file_encoder_worker.h"
|
#include "subghz_file_encoder_worker.h"
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
#include <toolbox/stream/stream.h>
|
#include <toolbox/stream/stream.h>
|
||||||
#include <flipper_format/flipper_format.h>
|
#include <flipper_format/flipper_format.h>
|
||||||
@ -11,7 +10,7 @@
|
|||||||
|
|
||||||
struct SubGhzFileEncoderWorker {
|
struct SubGhzFileEncoderWorker {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
|
|
||||||
Storage* storage;
|
Storage* storage;
|
||||||
FlipperFormat* flipper_format;
|
FlipperFormat* flipper_format;
|
||||||
@ -48,7 +47,7 @@ void subghz_file_encoder_worker_add_level_duration(
|
|||||||
|
|
||||||
if(res) {
|
if(res) {
|
||||||
instance->level = !instance->level;
|
instance->level = !instance->level;
|
||||||
xStreamBufferSend(instance->stream, &duration, sizeof(int32_t), 100);
|
furi_stream_buffer_send(instance->stream, &duration, sizeof(int32_t), 100);
|
||||||
} else {
|
} else {
|
||||||
FURI_LOG_E(TAG, "Invalid level in the stream");
|
FURI_LOG_E(TAG, "Invalid level in the stream");
|
||||||
}
|
}
|
||||||
@ -83,10 +82,7 @@ LevelDuration subghz_file_encoder_worker_get_level_duration(void* context) {
|
|||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
SubGhzFileEncoderWorker* instance = context;
|
SubGhzFileEncoderWorker* instance = context;
|
||||||
int32_t duration;
|
int32_t duration;
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
int ret = furi_stream_buffer_receive(instance->stream, &duration, sizeof(int32_t), 0);
|
||||||
int ret = xStreamBufferReceiveFromISR(
|
|
||||||
instance->stream, &duration, sizeof(int32_t), &xHigherPriorityTaskWoken);
|
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
if(ret == sizeof(int32_t)) {
|
if(ret == sizeof(int32_t)) {
|
||||||
LevelDuration level_duration = {.level = LEVEL_DURATION_RESET};
|
LevelDuration level_duration = {.level = LEVEL_DURATION_RESET};
|
||||||
if(duration < 0) {
|
if(duration < 0) {
|
||||||
@ -137,7 +133,7 @@ static int32_t subghz_file_encoder_worker_thread(void* context) {
|
|||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
while(res && instance->worker_running) {
|
while(res && instance->worker_running) {
|
||||||
size_t stream_free_byte = xStreamBufferSpacesAvailable(instance->stream);
|
size_t stream_free_byte = furi_stream_buffer_spaces_available(instance->stream);
|
||||||
if((stream_free_byte / sizeof(int32_t)) >= SUBGHZ_FILE_ENCODER_LOAD) {
|
if((stream_free_byte / sizeof(int32_t)) >= SUBGHZ_FILE_ENCODER_LOAD) {
|
||||||
if(stream_read_line(stream, instance->str_data)) {
|
if(stream_read_line(stream, instance->str_data)) {
|
||||||
furi_string_trim(instance->str_data);
|
furi_string_trim(instance->str_data);
|
||||||
@ -183,7 +179,7 @@ SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc() {
|
|||||||
furi_thread_set_stack_size(instance->thread, 2048);
|
furi_thread_set_stack_size(instance->thread, 2048);
|
||||||
furi_thread_set_context(instance->thread, instance);
|
furi_thread_set_context(instance->thread, instance);
|
||||||
furi_thread_set_callback(instance->thread, subghz_file_encoder_worker_thread);
|
furi_thread_set_callback(instance->thread, subghz_file_encoder_worker_thread);
|
||||||
instance->stream = xStreamBufferCreate(sizeof(int32_t) * 2048, sizeof(int32_t));
|
instance->stream = furi_stream_buffer_alloc(sizeof(int32_t) * 2048, sizeof(int32_t));
|
||||||
|
|
||||||
instance->storage = furi_record_open(RECORD_STORAGE);
|
instance->storage = furi_record_open(RECORD_STORAGE);
|
||||||
instance->flipper_format = flipper_format_file_alloc(instance->storage);
|
instance->flipper_format = flipper_format_file_alloc(instance->storage);
|
||||||
@ -199,7 +195,7 @@ SubGhzFileEncoderWorker* subghz_file_encoder_worker_alloc() {
|
|||||||
void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* instance) {
|
void subghz_file_encoder_worker_free(SubGhzFileEncoderWorker* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
vStreamBufferDelete(instance->stream);
|
furi_stream_buffer_free(instance->stream);
|
||||||
furi_thread_free(instance->thread);
|
furi_thread_free(instance->thread);
|
||||||
|
|
||||||
furi_string_free(instance->str_data);
|
furi_string_free(instance->str_data);
|
||||||
@ -215,7 +211,7 @@ bool subghz_file_encoder_worker_start(SubGhzFileEncoderWorker* instance, const c
|
|||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(!instance->worker_running);
|
furi_assert(!instance->worker_running);
|
||||||
|
|
||||||
xStreamBufferReset(instance->stream);
|
furi_stream_buffer_reset(instance->stream);
|
||||||
furi_string_set(instance->file_path, file_path);
|
furi_string_set(instance->file_path, file_path);
|
||||||
instance->worker_running = true;
|
instance->worker_running = true;
|
||||||
furi_thread_start(instance->thread);
|
furi_thread_start(instance->thread);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "subghz_tx_rx_worker.h"
|
#include "subghz_tx_rx_worker.h"
|
||||||
|
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#define TAG "SubGhzTxRxWorker"
|
#define TAG "SubGhzTxRxWorker"
|
||||||
@ -13,8 +12,8 @@
|
|||||||
|
|
||||||
struct SubGhzTxRxWorker {
|
struct SubGhzTxRxWorker {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
StreamBufferHandle_t stream_tx;
|
FuriStreamBuffer* stream_tx;
|
||||||
StreamBufferHandle_t stream_rx;
|
FuriStreamBuffer* stream_rx;
|
||||||
|
|
||||||
volatile bool worker_running;
|
volatile bool worker_running;
|
||||||
volatile bool worker_stoping;
|
volatile bool worker_stoping;
|
||||||
@ -30,9 +29,9 @@ struct SubGhzTxRxWorker {
|
|||||||
bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
|
bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
size_t stream_tx_free_byte = xStreamBufferSpacesAvailable(instance->stream_tx);
|
size_t stream_tx_free_byte = furi_stream_buffer_spaces_available(instance->stream_tx);
|
||||||
if(size && (stream_tx_free_byte >= size)) {
|
if(size && (stream_tx_free_byte >= size)) {
|
||||||
if(xStreamBufferSend(
|
if(furi_stream_buffer_send(
|
||||||
instance->stream_tx, data, size, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF) ==
|
instance->stream_tx, data, size, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF) ==
|
||||||
size) {
|
size) {
|
||||||
ret = true;
|
ret = true;
|
||||||
@ -43,12 +42,12 @@ bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t
|
|||||||
|
|
||||||
size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance) {
|
size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
return xStreamBufferBytesAvailable(instance->stream_rx);
|
return furi_stream_buffer_bytes_available(instance->stream_rx);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
|
size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
return xStreamBufferReceive(instance->stream_rx, data, size, 0);
|
return furi_stream_buffer_receive(instance->stream_rx, data, size, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_tx_rx_worker_set_callback_have_read(
|
void subghz_tx_rx_worker_set_callback_have_read(
|
||||||
@ -148,11 +147,11 @@ static int32_t subghz_tx_rx_worker_thread(void* context) {
|
|||||||
|
|
||||||
while(instance->worker_running) {
|
while(instance->worker_running) {
|
||||||
//transmit
|
//transmit
|
||||||
size_tx = xStreamBufferBytesAvailable(instance->stream_tx);
|
size_tx = furi_stream_buffer_bytes_available(instance->stream_tx);
|
||||||
if(size_tx > 0 && !timeout_tx) {
|
if(size_tx > 0 && !timeout_tx) {
|
||||||
timeout_tx = 10; //20ms
|
timeout_tx = 10; //20ms
|
||||||
if(size_tx > SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) {
|
if(size_tx > SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) {
|
||||||
xStreamBufferReceive(
|
furi_stream_buffer_receive(
|
||||||
instance->stream_tx,
|
instance->stream_tx,
|
||||||
&data,
|
&data,
|
||||||
SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE,
|
SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE,
|
||||||
@ -160,20 +159,20 @@ static int32_t subghz_tx_rx_worker_thread(void* context) {
|
|||||||
subghz_tx_rx_worker_tx(instance, data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE);
|
subghz_tx_rx_worker_tx(instance, data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE);
|
||||||
} else {
|
} else {
|
||||||
//todo checking that he managed to write all the data to the TX buffer
|
//todo checking that he managed to write all the data to the TX buffer
|
||||||
xStreamBufferReceive(
|
furi_stream_buffer_receive(
|
||||||
instance->stream_tx, &data, size_tx, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
|
instance->stream_tx, &data, size_tx, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
|
||||||
subghz_tx_rx_worker_tx(instance, data, size_tx);
|
subghz_tx_rx_worker_tx(instance, data, size_tx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//recive
|
//recive
|
||||||
if(subghz_tx_rx_worker_rx(instance, data, size_rx)) {
|
if(subghz_tx_rx_worker_rx(instance, data, size_rx)) {
|
||||||
if(xStreamBufferSpacesAvailable(instance->stream_rx) >= size_rx[0]) {
|
if(furi_stream_buffer_spaces_available(instance->stream_rx) >= size_rx[0]) {
|
||||||
if(instance->callback_have_read &&
|
if(instance->callback_have_read &&
|
||||||
xStreamBufferBytesAvailable(instance->stream_rx) == 0) {
|
furi_stream_buffer_bytes_available(instance->stream_rx) == 0) {
|
||||||
callback_rx = true;
|
callback_rx = true;
|
||||||
}
|
}
|
||||||
//todo checking that he managed to write all the data to the RX buffer
|
//todo checking that he managed to write all the data to the RX buffer
|
||||||
xStreamBufferSend(
|
furi_stream_buffer_send(
|
||||||
instance->stream_rx,
|
instance->stream_rx,
|
||||||
&data,
|
&data,
|
||||||
size_rx[0],
|
size_rx[0],
|
||||||
@ -208,9 +207,9 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() {
|
|||||||
furi_thread_set_context(instance->thread, instance);
|
furi_thread_set_context(instance->thread, instance);
|
||||||
furi_thread_set_callback(instance->thread, subghz_tx_rx_worker_thread);
|
furi_thread_set_callback(instance->thread, subghz_tx_rx_worker_thread);
|
||||||
instance->stream_tx =
|
instance->stream_tx =
|
||||||
xStreamBufferCreate(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
|
furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
|
||||||
instance->stream_rx =
|
instance->stream_rx =
|
||||||
xStreamBufferCreate(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
|
furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
|
||||||
|
|
||||||
instance->status = SubGhzTxRxWorkerStatusIDLE;
|
instance->status = SubGhzTxRxWorkerStatusIDLE;
|
||||||
instance->worker_stoping = true;
|
instance->worker_stoping = true;
|
||||||
@ -221,8 +220,8 @@ SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() {
|
|||||||
void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) {
|
void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(!instance->worker_running);
|
furi_assert(!instance->worker_running);
|
||||||
vStreamBufferDelete(instance->stream_tx);
|
furi_stream_buffer_free(instance->stream_tx);
|
||||||
vStreamBufferDelete(instance->stream_rx);
|
furi_stream_buffer_free(instance->stream_rx);
|
||||||
furi_thread_free(instance->thread);
|
furi_thread_free(instance->thread);
|
||||||
|
|
||||||
free(instance);
|
free(instance);
|
||||||
@ -232,8 +231,8 @@ bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) {
|
|||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(!instance->worker_running);
|
furi_assert(!instance->worker_running);
|
||||||
bool res = false;
|
bool res = false;
|
||||||
xStreamBufferReset(instance->stream_tx);
|
furi_stream_buffer_reset(instance->stream_tx);
|
||||||
xStreamBufferReset(instance->stream_rx);
|
furi_stream_buffer_reset(instance->stream_rx);
|
||||||
|
|
||||||
instance->worker_running = true;
|
instance->worker_running = true;
|
||||||
|
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
#include "subghz_worker.h"
|
#include "subghz_worker.h"
|
||||||
|
|
||||||
#include <stream_buffer.h>
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#define TAG "SubGhzWorker"
|
#define TAG "SubGhzWorker"
|
||||||
|
|
||||||
struct SubGhzWorker {
|
struct SubGhzWorker {
|
||||||
FuriThread* thread;
|
FuriThread* thread;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
|
|
||||||
volatile bool running;
|
volatile bool running;
|
||||||
volatile bool overrun;
|
volatile bool overrun;
|
||||||
@ -30,16 +29,14 @@ struct SubGhzWorker {
|
|||||||
void subghz_worker_rx_callback(bool level, uint32_t duration, void* context) {
|
void subghz_worker_rx_callback(bool level, uint32_t duration, void* context) {
|
||||||
SubGhzWorker* instance = context;
|
SubGhzWorker* instance = context;
|
||||||
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
LevelDuration level_duration = level_duration_make(level, duration);
|
LevelDuration level_duration = level_duration_make(level, duration);
|
||||||
if(instance->overrun) {
|
if(instance->overrun) {
|
||||||
instance->overrun = false;
|
instance->overrun = false;
|
||||||
level_duration = level_duration_reset();
|
level_duration = level_duration_reset();
|
||||||
}
|
}
|
||||||
size_t ret = xStreamBufferSendFromISR(
|
size_t ret =
|
||||||
instance->stream, &level_duration, sizeof(LevelDuration), &xHigherPriorityTaskWoken);
|
furi_stream_buffer_send(instance->stream, &level_duration, sizeof(LevelDuration), 0);
|
||||||
if(sizeof(LevelDuration) != ret) instance->overrun = true;
|
if(sizeof(LevelDuration) != ret) instance->overrun = true;
|
||||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Worker callback thread
|
/** Worker callback thread
|
||||||
@ -52,8 +49,8 @@ static int32_t subghz_worker_thread_callback(void* context) {
|
|||||||
|
|
||||||
LevelDuration level_duration;
|
LevelDuration level_duration;
|
||||||
while(instance->running) {
|
while(instance->running) {
|
||||||
int ret =
|
int ret = furi_stream_buffer_receive(
|
||||||
xStreamBufferReceive(instance->stream, &level_duration, sizeof(LevelDuration), 10);
|
instance->stream, &level_duration, sizeof(LevelDuration), 10);
|
||||||
if(ret == sizeof(LevelDuration)) {
|
if(ret == sizeof(LevelDuration)) {
|
||||||
if(level_duration_is_reset(level_duration)) {
|
if(level_duration_is_reset(level_duration)) {
|
||||||
FURI_LOG_E(TAG, "Overrun buffer");
|
FURI_LOG_E(TAG, "Overrun buffer");
|
||||||
@ -97,7 +94,8 @@ SubGhzWorker* subghz_worker_alloc() {
|
|||||||
furi_thread_set_context(instance->thread, instance);
|
furi_thread_set_context(instance->thread, instance);
|
||||||
furi_thread_set_callback(instance->thread, subghz_worker_thread_callback);
|
furi_thread_set_callback(instance->thread, subghz_worker_thread_callback);
|
||||||
|
|
||||||
instance->stream = xStreamBufferCreate(sizeof(LevelDuration) * 4096, sizeof(LevelDuration));
|
instance->stream =
|
||||||
|
furi_stream_buffer_alloc(sizeof(LevelDuration) * 4096, sizeof(LevelDuration));
|
||||||
|
|
||||||
//setting filter
|
//setting filter
|
||||||
instance->filter_running = true;
|
instance->filter_running = true;
|
||||||
@ -109,7 +107,7 @@ SubGhzWorker* subghz_worker_alloc() {
|
|||||||
void subghz_worker_free(SubGhzWorker* instance) {
|
void subghz_worker_free(SubGhzWorker* instance) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
|
|
||||||
vStreamBufferDelete(instance->stream);
|
furi_stream_buffer_free(instance->stream);
|
||||||
furi_thread_free(instance->thread);
|
furi_thread_free(instance->thread);
|
||||||
|
|
||||||
free(instance);
|
free(instance);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "buffer_stream.h"
|
#include "buffer_stream.h"
|
||||||
#include <stream_buffer.h>
|
|
||||||
|
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
volatile bool occupied;
|
volatile bool occupied;
|
||||||
@ -10,7 +9,7 @@ struct Buffer {
|
|||||||
|
|
||||||
struct BufferStream {
|
struct BufferStream {
|
||||||
size_t stream_overrun_count;
|
size_t stream_overrun_count;
|
||||||
StreamBufferHandle_t stream;
|
FuriStreamBuffer* stream;
|
||||||
|
|
||||||
size_t index;
|
size_t index;
|
||||||
Buffer* buffers;
|
Buffer* buffers;
|
||||||
@ -54,7 +53,7 @@ BufferStream* buffer_stream_alloc(size_t buffer_size, size_t buffers_count) {
|
|||||||
buffer_stream->buffers[i].data = malloc(buffer_size);
|
buffer_stream->buffers[i].data = malloc(buffer_size);
|
||||||
buffer_stream->buffers[i].max_data_size = buffer_size;
|
buffer_stream->buffers[i].max_data_size = buffer_size;
|
||||||
}
|
}
|
||||||
buffer_stream->stream = xStreamBufferCreate(
|
buffer_stream->stream = furi_stream_buffer_alloc(
|
||||||
sizeof(BufferStream*) * buffer_stream->max_buffers_count, sizeof(BufferStream*));
|
sizeof(BufferStream*) * buffer_stream->max_buffers_count, sizeof(BufferStream*));
|
||||||
buffer_stream->stream_overrun_count = 0;
|
buffer_stream->stream_overrun_count = 0;
|
||||||
buffer_stream->index = 0;
|
buffer_stream->index = 0;
|
||||||
@ -66,7 +65,7 @@ void buffer_stream_free(BufferStream* buffer_stream) {
|
|||||||
for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
|
for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
|
||||||
free(buffer_stream->buffers[i].data);
|
free(buffer_stream->buffers[i].data);
|
||||||
}
|
}
|
||||||
vStreamBufferDelete(buffer_stream->stream);
|
furi_stream_buffer_free(buffer_stream->stream);
|
||||||
free(buffer_stream->buffers);
|
free(buffer_stream->buffers);
|
||||||
free(buffer_stream);
|
free(buffer_stream);
|
||||||
}
|
}
|
||||||
@ -83,11 +82,7 @@ static inline int8_t buffer_stream_get_free_buffer(BufferStream* buffer_stream)
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool buffer_stream_send_from_isr(
|
bool buffer_stream_send_from_isr(BufferStream* buffer_stream, const uint8_t* data, size_t size) {
|
||||||
BufferStream* buffer_stream,
|
|
||||||
const uint8_t* data,
|
|
||||||
size_t size,
|
|
||||||
BaseType_t* const task_woken) {
|
|
||||||
Buffer* buffer = &buffer_stream->buffers[buffer_stream->index];
|
Buffer* buffer = &buffer_stream->buffers[buffer_stream->index];
|
||||||
bool result = true;
|
bool result = true;
|
||||||
|
|
||||||
@ -96,7 +91,7 @@ bool buffer_stream_send_from_isr(
|
|||||||
// if buffer is full - send it
|
// if buffer is full - send it
|
||||||
buffer->occupied = true;
|
buffer->occupied = true;
|
||||||
// we always have space for buffer in stream
|
// we always have space for buffer in stream
|
||||||
xStreamBufferSendFromISR(buffer_stream->stream, &buffer, sizeof(Buffer*), task_woken);
|
furi_stream_buffer_send(buffer_stream->stream, &buffer, sizeof(Buffer*), 0);
|
||||||
|
|
||||||
// get new buffer from the pool
|
// get new buffer from the pool
|
||||||
int8_t index = buffer_stream_get_free_buffer(buffer_stream);
|
int8_t index = buffer_stream_get_free_buffer(buffer_stream);
|
||||||
@ -119,7 +114,8 @@ bool buffer_stream_send_from_isr(
|
|||||||
|
|
||||||
Buffer* buffer_stream_receive(BufferStream* buffer_stream, TickType_t timeout) {
|
Buffer* buffer_stream_receive(BufferStream* buffer_stream, TickType_t timeout) {
|
||||||
Buffer* buffer;
|
Buffer* buffer;
|
||||||
size_t size = xStreamBufferReceive(buffer_stream->stream, &buffer, sizeof(Buffer*), timeout);
|
size_t size =
|
||||||
|
furi_stream_buffer_receive(buffer_stream->stream, &buffer, sizeof(Buffer*), timeout);
|
||||||
|
|
||||||
if(size == sizeof(Buffer*)) {
|
if(size == sizeof(Buffer*)) {
|
||||||
return buffer;
|
return buffer;
|
||||||
@ -134,9 +130,8 @@ size_t buffer_stream_get_overrun_count(BufferStream* buffer_stream) {
|
|||||||
|
|
||||||
void buffer_stream_reset(BufferStream* buffer_stream) {
|
void buffer_stream_reset(BufferStream* buffer_stream) {
|
||||||
FURI_CRITICAL_ENTER();
|
FURI_CRITICAL_ENTER();
|
||||||
BaseType_t xReturn = xStreamBufferReset(buffer_stream->stream);
|
furi_stream_buffer_reset(buffer_stream->stream);
|
||||||
furi_assert(xReturn == pdPASS);
|
|
||||||
UNUSED(xReturn);
|
|
||||||
buffer_stream->stream_overrun_count = 0;
|
buffer_stream->stream_overrun_count = 0;
|
||||||
for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
|
for(size_t i = 0; i < buffer_stream->max_buffers_count; i++) {
|
||||||
buffer_reset(&buffer_stream->buffers[i]);
|
buffer_reset(&buffer_stream->buffers[i]);
|
||||||
|
@ -59,14 +59,9 @@ void buffer_stream_free(BufferStream* buffer_stream);
|
|||||||
* @param buffer_stream
|
* @param buffer_stream
|
||||||
* @param data
|
* @param data
|
||||||
* @param size
|
* @param size
|
||||||
* @param task_woken
|
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
bool buffer_stream_send_from_isr(
|
bool buffer_stream_send_from_isr(BufferStream* buffer_stream, const uint8_t* data, size_t size);
|
||||||
BufferStream* buffer_stream,
|
|
||||||
const uint8_t* data,
|
|
||||||
size_t size,
|
|
||||||
BaseType_t* const task_woken);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Receive buffer from stream
|
* @brief Receive buffer from stream
|
||||||
|
Loading…
Reference in New Issue
Block a user