Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update companions to newer fz sdk #48

Merged
merged 1 commit into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
App(
appid="mayhem_camera",
name="[MAYHEM] Camera v1.0.0",
name="[MAYHEM] Camera",
apptype=FlipperAppType.EXTERNAL,
entry_point="camera_app",
cdefines=["APP_CAMERA"],
requires=["gui"],
stack_size=8*1024,
stack_size=8 * 1024,
order=1,
fap_icon="icon.png",
fap_category="GPIO",
fap_description="ESP32-CAM live feed and photo capture, use left/right for orientation/mode, up/down for brightness and center for saving a screenshot. [Unplug the USB cable to test with Mayhem]",
fap_author="Z4urce",
fap_weburl="https://github.com/Z4urce/flipper-camera"
)
fap_icon="icon.png",
fap_category="GPIO/MAYHEM",
fap_description="ESP32-CAM live feed and photo capture, use left/right for orientation/mode, up/down for brightness and center for saving a screenshot. [Unplug the USB cable to test with Mayhem]",
fap_author="Z4urce",
fap_weburl="https://github.com/Z4urce/flipper-camera",
)
126 changes: 72 additions & 54 deletions flipper_companion_apps/applications/external/esp32cam_camera/camera.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "camera.h"

#include <expansion/expansion.h>

static void camera_view_draw_callback(Canvas* canvas, void* _model) {
UartDumpModel* model = _model;
Expand All @@ -20,16 +21,15 @@ static void camera_view_draw_callback(Canvas* canvas, void* _model) {
}
}

if (!model->initialized){

if(!model->initialized) {
/*if(!model->marauderInitialized)
{
// Init marauder into stream mode
uint8_t data[] = "\nstream\n";
furi_hal_uart_tx(FuriHalUartIdUSART1, data, sizeof(data));
furi_hal_serial_tx(app->serial_handle, data, sizeof(data));
}*/
canvas_draw_icon(canvas, 74, 16, &I_DolphinCommon_56x48);

canvas_draw_icon(canvas, 80, 21, &I_WarningDolphinFlip_45x42);
canvas_set_font(canvas, FontSecondary);
canvas_draw_str(canvas, 8, 12, "Waiting ESP32-CAM...");
canvas_draw_str(canvas, 20, 24, "VCC - 3V3/5V");
Expand All @@ -40,11 +40,11 @@ static void camera_view_draw_callback(Canvas* canvas, void* _model) {
}

void get_timefilename(FuriString* name) {
FuriHalRtcDateTime datetime = {0};
DateTime datetime = {0};
furi_hal_rtc_get_datetime(&datetime);
furi_string_printf(
name,
EXT_PATH("DCIM/%.4d%.2d%.2d-%.2d%.2d%.2d.bmp"),
APP_DATA_PATH("%.4d%.2d%.2d-%.2d%.2d%.2d.bmp"),
datetime.year,
datetime.month,
datetime.day,
Expand Down Expand Up @@ -74,22 +74,26 @@ static void save_image(void* context) {
get_timefilename(file_name);

// this functions open a file, using write access and creates new file if not exist.
bool result = storage_file_open(file, furi_string_get_cstr(file_name), FSAM_WRITE, FSOM_OPEN_ALWAYS);
bool result =
storage_file_open(file, furi_string_get_cstr(file_name), FSAM_WRITE, FSOM_OPEN_ALWAYS);
//bool result = storage_file_open(file, EXT_PATH("DCIM/test.bmp"), FSAM_WRITE, FSOM_OPEN_ALWAYS);
furi_string_free(file_name);

if (result){
if(result) {
storage_file_write(file, bitmap_header, BITMAP_HEADER_LENGTH);
with_view_model(app->view, UartDumpModel * model, {
int8_t row_buffer[ROW_BUFFER_LENGTH];
for (size_t i = 64; i > 0; --i) {
for (size_t j = 0; j < ROW_BUFFER_LENGTH; ++j){
row_buffer[j] = model->pixels[((i-1)*ROW_BUFFER_LENGTH) + j];
with_view_model(
app->view,
UartDumpModel * model,
{
int8_t row_buffer[ROW_BUFFER_LENGTH];
for(size_t i = 64; i > 0; --i) {
for(size_t j = 0; j < ROW_BUFFER_LENGTH; ++j) {
row_buffer[j] = model->pixels[((i - 1) * ROW_BUFFER_LENGTH) + j];
}
storage_file_write(file, row_buffer, ROW_BUFFER_LENGTH);
}
storage_file_write(file, row_buffer, ROW_BUFFER_LENGTH);
}

}, false);
},
false);
}

// Closing the "file descriptor"
Expand All @@ -102,26 +106,23 @@ static void save_image(void* context) {
}

static bool camera_view_input_callback(InputEvent* event, void* context) {
if (event->type == InputTypePress){
if(event->type == InputTypePress) {
uint8_t data[1];
if (event->key == InputKeyUp){
if(event->key == InputKeyUp) {
data[0] = 'C';
}
else if (event->key == InputKeyDown){
} else if(event->key == InputKeyDown) {
data[0] = 'c';
}
else if (event->key == InputKeyRight){
} else if(event->key == InputKeyRight) {
data[0] = '>';
}
else if (event->key == InputKeyLeft){
} else if(event->key == InputKeyLeft) {
data[0] = '<';
}
else if (event->key == InputKeyOk){
} else if(event->key == InputKeyOk) {
save_image(context);
}
furi_hal_uart_tx(FuriHalUartIdUSART1, data, 1);
UartEchoApp* app = context;
furi_hal_serial_tx(app->serial_handle, data, 1);
}

return false;
}

Expand All @@ -130,47 +131,52 @@ static uint32_t camera_exit(void* context) {
return VIEW_NONE;
}

static void camera_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
static void
camera_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
furi_assert(context);
UartEchoApp* app = context;

if(ev == UartIrqEventRXNE) {
if(event == FuriHalSerialRxEventData) {
uint8_t data = furi_hal_serial_async_rx(handle);
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
}
}

static void process_ringbuffer(UartDumpModel* model, uint8_t byte) {

//// 1. Phase: filling the ringbuffer
if (model->ringbuffer_index == 0 && byte != 'Y'){ // First char has to be 'Y' in the buffer.
if(model->ringbuffer_index == 0 && byte != 'Y') { // First char has to be 'Y' in the buffer.
return;
}

if (model->ringbuffer_index == 1 && byte != ':'){ // Second char has to be ':' in the buffer or reset.

if(model->ringbuffer_index == 1 &&
byte != ':') { // Second char has to be ':' in the buffer or reset.
model->ringbuffer_index = 0;
process_ringbuffer(model, byte);
return;
}

model->row_ringbuffer[model->ringbuffer_index] = byte; // Assign current byte to the ringbuffer;
model->row_ringbuffer[model->ringbuffer_index] =
byte; // Assign current byte to the ringbuffer;
++model->ringbuffer_index; // Increment the ringbuffer index

if (model->ringbuffer_index < RING_BUFFER_LENGTH){ // Let's wait 'till the buffer fills.
if(model->ringbuffer_index < RING_BUFFER_LENGTH) { // Let's wait 'till the buffer fills.
return;
}

//// 2. Phase: flushing the ringbuffer to the framebuffer
model->ringbuffer_index = 0; // Let's reset the ringbuffer
model->initialized = true; // We've successfully established the connection
size_t row_start_index = model->row_ringbuffer[2] * ROW_BUFFER_LENGTH; // Third char will determine the row number
size_t row_start_index =
model->row_ringbuffer[2] * ROW_BUFFER_LENGTH; // Third char will determine the row number

if (row_start_index > LAST_ROW_INDEX){ // Failsafe
if(row_start_index > LAST_ROW_INDEX) { // Failsafe
row_start_index = 0;
}

for (size_t i = 0; i < ROW_BUFFER_LENGTH; ++i) {
model->pixels[row_start_index + i] = model->row_ringbuffer[i+3]; // Writing the remaining 16 bytes into the frame buffer
for(size_t i = 0; i < ROW_BUFFER_LENGTH; ++i) {
model->pixels[row_start_index + i] =
model->row_ringbuffer[i + 3]; // Writing the remaining 16 bytes into the frame buffer
}
}

Expand All @@ -192,10 +198,11 @@ static int32_t camera_worker(void* context) {
length = furi_stream_buffer_receive(app->rx_stream, data, intended_data_size, 0);

if(length > 0) {
//furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
//furi_hal_serial_tx(app->serial_handle, data, length);
with_view_model(
app->view,
UartDumpModel * model, {
UartDumpModel * model,
{
for(size_t i = 0; i < length; i++) {
process_ringbuffer(model, data[i]);
}
Expand All @@ -205,7 +212,8 @@ static int32_t camera_worker(void* context) {
} while(length > 0);

notification_message(app->notification, &sequence_notification);
with_view_model(app->view, UartDumpModel * model, { UNUSED(model); }, true);
with_view_model(
app->view, UartDumpModel * model, { UNUSED(model); }, true);
}
}

Expand Down Expand Up @@ -251,19 +259,19 @@ static UartEchoApp* camera_app_alloc() {
furi_thread_start(app->worker_thread);

// Enable uart listener
furi_hal_console_disable();
furi_hal_uart_set_br(FuriHalUartIdUSART1, 230400);
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, camera_on_irq_cb, app);
app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
furi_check(app->serial_handle);
furi_hal_serial_init(app->serial_handle, 230400);
furi_hal_serial_async_rx_start(app->serial_handle, camera_on_irq_cb, app, false);

furi_hal_power_disable_external_3_3v();
furi_hal_power_disable_otg();
furi_delay_ms(200);
furi_hal_power_enable_external_3_3v();
furi_hal_power_enable_otg();
for(int i=0;i<2;i++)
{
furi_delay_ms(500);
furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t[1]){'c'}, 1);
for(int i = 0; i < 2; i++) {
furi_delay_ms(500);
furi_hal_serial_tx(app->serial_handle, (uint8_t[1]){'c'}, 1);
}
furi_delay_ms(1);
return app;
Expand All @@ -272,7 +280,9 @@ static UartEchoApp* camera_app_alloc() {
static void camera_app_free(UartEchoApp* app) {
furi_assert(app);

furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
furi_hal_serial_async_rx_stop(app->serial_handle);
furi_hal_serial_deinit(app->serial_handle);
furi_hal_serial_control_release(app->serial_handle);

furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
furi_thread_join(app->worker_thread);
Expand All @@ -298,11 +308,19 @@ static void camera_app_free(UartEchoApp* app) {
int32_t camera_app(void* p) {
UNUSED(p);

// Disable expansion protocol to avoid interference with UART Handle
Expansion* expansion = furi_record_open(RECORD_EXPANSION);
expansion_disable(expansion);

UartEchoApp* app = camera_app_alloc();
view_dispatcher_run(app->view_dispatcher);
camera_app_free(app);

furi_hal_power_disable_otg();

// Return previous state of expansion
expansion_enable(expansion);
furi_record_close(RECORD_EXPANSION);

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,33 @@
#include <notification/notification.h>
#include <notification/notification_messages.h>
#include <gui/elements.h>
#include <furi_hal_uart.h>
#include <furi_hal_console.h>
#include <furi_hal_serial_control.h>
#include <furi_hal_serial.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/dialog_ex.h>
#include <storage/filesystem_api_defines.h>
#include <storage/storage.h>

#include <assets_icons.h>

#define THREAD_ALLOC 2048

#define FRAME_WIDTH 128
#define FRAME_HEIGTH 64
#define FRAME_BIT_DEPTH 1
#define FRAME_BUFFER_LENGTH (FRAME_WIDTH * FRAME_HEIGTH * FRAME_BIT_DEPTH / 8) // 128*64*1 / 8 = 1024
#define FRAME_BUFFER_LENGTH \
(FRAME_WIDTH * FRAME_HEIGTH * FRAME_BIT_DEPTH / 8) // 128*64*1 / 8 = 1024
#define ROW_BUFFER_LENGTH (FRAME_WIDTH / 8) // 128/8 = 16
#define LAST_ROW_INDEX (FRAME_BUFFER_LENGTH - ROW_BUFFER_LENGTH) // 1024 - 16 = 1008
#define RING_BUFFER_LENGTH (ROW_BUFFER_LENGTH + 3) // ROW_BUFFER_LENGTH + Header => 16 + 3 = 19
#define BITMAP_HEADER_LENGTH 62
#define IMAGE_FILE_DIRECTORY_PATH EXT_PATH("DCIM")

static const unsigned char bitmap_header[BITMAP_HEADER_LENGTH] = {
0x42, 0x4D, 0x3E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00,
0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0x00
};

const uint8_t _I_DolphinCommon_56x48_0[] = {0x01,0x00,0xdf,0x00,0x00,0x1f,0xfe,0x0e,0x05,0x3f,0x04,0x06,0x78,0x06,0x30,0x20,0xf8,0x00,0xc6,0x12,0x1c,0x04,0x0c,0x0a,0x38,0x08,0x08,0x0c,0x60,0xc0,0x21,0xe0,0x04,0x0a,0x18,0x02,0x1b,0x00,0x18,0xa3,0x00,0x21,0x90,0x01,0x8a,0x20,0x02,0x19,0x80,0x18,0x80,0x64,0x09,0x20,0x89,0x81,0x8c,0x3e,0x41,0xe2,0x80,0x50,0x00,0x43,0x08,0x01,0x0c,0xfc,0x68,0x40,0x61,0xc0,0x50,0x30,0x00,0x63,0xa0,0x7f,0x80,0xc4,0x41,0x19,0x07,0xff,0x02,0x06,0x18,0x24,0x03,0x41,0xf3,0x2b,0x10,0x19,0x38,0x10,0x30,0x31,0x7f,0xe0,0x34,0x08,0x30,0x19,0x60,0x80,0x65,0x86,0x0a,0x4c,0x0c,0x30,0x81,0xb9,0x41,0xa0,0x54,0x08,0xc7,0xe2,0x06,0x8a,0x18,0x25,0x02,0x21,0x0f,0x19,0x88,0xd8,0x6e,0x1b,0x01,0xd1,0x1b,0x86,0x39,0x66,0x3a,0xa4,0x1a,0x50,0x06,0x48,0x18,0x18,0xd0,0x03,0x01,0x41,0x98,0xcc,0x60,0x39,0x01,0x49,0x2d,0x06,0x03,0x50,0xf8,0x40,0x3e,0x02,0xc1,0x82,0x86,0xc7,0xfe,0x0f,0x28,0x2c,0x91,0xd2,0x90,0x9a,0x18,0x19,0x3e,0x6d,0x73,0x12,0x16,0x00,0x32,0x49,0x72,0xc0,0x7e,0x5d,0x44,0xba,0x2c,0x08,0xa4,0xc8,0x82,0x06,0x17,0xe0,0x81,0x90,0x2a,0x40,0x61,0xe1,0xa2,0x44,0x0c,0x76,0x2b,0xe8,0x89,0x26,0x43,0x83,0x31,0x8c,0x78,0x0c,0xb0,0x48,0x10,0x1a,0xe0,0x00,0x63,};
const uint8_t* const _I_DolphinCommon_56x48[] = {_I_DolphinCommon_56x48_0};
const Icon I_DolphinCommon_56x48 = {.width=56,.height=48,.frame_count=1,.frame_rate=0,.frames=_I_DolphinCommon_56x48};
0x42, 0x4D, 0x3E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x28, 0x00,
0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00};

typedef struct UartDumpModel UartDumpModel;

Expand All @@ -55,6 +51,7 @@ typedef struct {
View* view;
FuriThread* worker_thread;
FuriStreamBuffer* rx_stream;
FuriHalSerialHandle* serial_handle;
} UartEchoApp;

struct UartDumpModel {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
App(
appid="mayhem_marauder",
name="[MAYHEM] Marauder v0.6.6",
fap_version=(6,6),
name="[MAYHEM] Marauder",
fap_version=(6, 6),
apptype=FlipperAppType.EXTERNAL,
entry_point="wifi_marauder_app",
requires=["gui"],
stack_size=4 * 1024,
order=2,
fap_icon="wifi_10px.png",
fap_category="GPIO",
fap_category="GPIO/MAYHEM",
fap_icon_assets="assets",
fap_description="ESP32-CAM version of Marauder. Includes all functionality from the original plus some options to trigger the camera and flashlight. [Unplug the USB cable to test with Mayhem]",
)
Loading