Skip to content

Commit

Permalink
Merge pull request #541 from CodyTolene/camera-suite
Browse files Browse the repository at this point in the history
Add Camera Suite GPIO application for the ESP32-CAM module.
  • Loading branch information
xMasterX authored Jul 11, 2023
2 parents bc0722f + 978fecf commit 44baa84
Show file tree
Hide file tree
Showing 30 changed files with 2,061 additions and 0 deletions.
16 changes: 16 additions & 0 deletions applications/external/camera-suite/application.fam
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
App(
appid="camerasuite",
apptype=FlipperAppType.EXTERNAL,
cdefines=["APP_CAMERA_SUITE"],
entry_point="camera_suite_app",
fap_author="Cody Tolene",
fap_category="GPIO",
fap_description="A camera suite application for the Flipper Zero ESP32-CAM module.",
fap_icon="icons/camera-suite.png",
fap_libs=["assets"],
fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam",
name="[ESP32] Camera Suite",
order=1,
requires=["gui", "storage"],
stack_size=8 * 1024
)
139 changes: 139 additions & 0 deletions applications/external/camera-suite/camera-suite.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include "camera-suite.h"
#include <stdlib.h>

bool camera_suite_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
CameraSuite* app = context;
return scene_manager_handle_custom_event(app->scene_manager, event);
}

void camera_suite_tick_event_callback(void* context) {
furi_assert(context);
CameraSuite* app = context;
scene_manager_handle_tick_event(app->scene_manager);
}

//leave app if back button pressed
bool camera_suite_navigation_event_callback(void* context) {
furi_assert(context);
CameraSuite* app = context;
return scene_manager_handle_back_event(app->scene_manager);
}

CameraSuite* camera_suite_app_alloc() {
CameraSuite* app = malloc(sizeof(CameraSuite));
app->gui = furi_record_open(RECORD_GUI);
app->notification = furi_record_open(RECORD_NOTIFICATION);

//Turn backlight on, believe me this makes testing your app easier
notification_message(app->notification, &sequence_display_backlight_on);

//Scene additions
app->view_dispatcher = view_dispatcher_alloc();
view_dispatcher_enable_queue(app->view_dispatcher);

app->scene_manager = scene_manager_alloc(&camera_suite_scene_handlers, app);
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
view_dispatcher_set_navigation_event_callback(
app->view_dispatcher, camera_suite_navigation_event_callback);
view_dispatcher_set_tick_event_callback(
app->view_dispatcher, camera_suite_tick_event_callback, 100);
view_dispatcher_set_custom_event_callback(
app->view_dispatcher, camera_suite_custom_event_callback);
app->submenu = submenu_alloc();

// Set defaults, in case no config loaded
app->orientation = 0; // Orientation is "portrait", zero degrees by default.
app->haptic = 1; // Haptic is on by default
app->speaker = 1; // Speaker is on by default
app->led = 1; // LED is on by default

// Load configs
camera_suite_read_settings(app);

view_dispatcher_add_view(
app->view_dispatcher, CameraSuiteViewIdMenu, submenu_get_view(app->submenu));

app->camera_suite_view_start = camera_suite_view_start_alloc();
view_dispatcher_add_view(
app->view_dispatcher,
CameraSuiteViewIdStartscreen,
camera_suite_view_start_get_view(app->camera_suite_view_start));

app->camera_suite_view_style_1 = camera_suite_view_style_1_alloc();
view_dispatcher_add_view(
app->view_dispatcher,
CameraSuiteViewIdScene1,
camera_suite_view_style_1_get_view(app->camera_suite_view_style_1));

app->camera_suite_view_style_2 = camera_suite_view_style_2_alloc();
view_dispatcher_add_view(
app->view_dispatcher,
CameraSuiteViewIdScene2,
camera_suite_view_style_2_get_view(app->camera_suite_view_style_2));

app->camera_suite_view_guide = camera_suite_view_guide_alloc();
view_dispatcher_add_view(
app->view_dispatcher,
CameraSuiteViewIdGuide,
camera_suite_view_guide_get_view(app->camera_suite_view_guide));

app->button_menu = button_menu_alloc();

app->variable_item_list = variable_item_list_alloc();
view_dispatcher_add_view(
app->view_dispatcher,
CameraSuiteViewIdSettings,
variable_item_list_get_view(app->variable_item_list));

//End Scene Additions

return app;
}

void camera_suite_app_free(CameraSuite* app) {
furi_assert(app);

// Scene manager
scene_manager_free(app->scene_manager);

// View Dispatcher
view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdMenu);
view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdScene1);
view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdScene2);
view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdGuide);
view_dispatcher_remove_view(app->view_dispatcher, CameraSuiteViewIdSettings);
submenu_free(app->submenu);

view_dispatcher_free(app->view_dispatcher);
furi_record_close(RECORD_GUI);

// Free remaining resources
camera_suite_view_start_free(app->camera_suite_view_start);
camera_suite_view_style_1_free(app->camera_suite_view_style_1);
camera_suite_view_style_2_free(app->camera_suite_view_style_2);
camera_suite_view_guide_free(app->camera_suite_view_guide);
button_menu_free(app->button_menu);
variable_item_list_free(app->variable_item_list);

app->gui = NULL;
app->notification = NULL;

//Remove whatever is left
free(app);
}

/** Main entry point for initialization. */
int32_t camera_suite_app(void* p) {
UNUSED(p);
CameraSuite* app = camera_suite_app_alloc();
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
// Init with start scene.
scene_manager_next_scene(app->scene_manager, CameraSuiteSceneStart);
furi_hal_power_suppress_charge_enter();
view_dispatcher_run(app->view_dispatcher);
camera_suite_save_settings(app);
furi_hal_power_suppress_charge_exit();
camera_suite_app_free(app);
return 0;
}
71 changes: 71 additions & 0 deletions applications/external/camera-suite/camera-suite.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

#include "helpers/camera_suite_storage.h"
#include "scenes/camera_suite_scene.h"
#include "views/camera_suite_view_guide.h"
#include "views/camera_suite_view_start.h"
#include "views/camera_suite_view_style_1.h"
#include "views/camera_suite_view_style_2.h"
#include <assets_icons.h>
#include <furi.h>
#include <furi_hal.h>
#include <gui/gui.h>
#include <gui/modules/button_menu.h>
#include <gui/modules/submenu.h>
#include <gui/modules/variable_item_list.h>
#include <gui/scene_manager.h>
#include <gui/view_dispatcher.h>
#include <input/input.h>
#include <notification/notification_messages.h>
#include <stdlib.h>

#define TAG "Camera Suite"

typedef struct {
Gui* gui;
NotificationApp* notification;
ViewDispatcher* view_dispatcher;
Submenu* submenu;
SceneManager* scene_manager;
VariableItemList* variable_item_list;
CameraSuiteViewStart* camera_suite_view_start;
CameraSuiteViewStyle1* camera_suite_view_style_1;
CameraSuiteViewStyle2* camera_suite_view_style_2;
CameraSuiteViewGuide* camera_suite_view_guide;
uint32_t orientation;
uint32_t haptic;
uint32_t speaker;
uint32_t led;
ButtonMenu* button_menu;
} CameraSuite;

typedef enum {
CameraSuiteViewIdStartscreen,
CameraSuiteViewIdMenu,
CameraSuiteViewIdScene1,
CameraSuiteViewIdScene2,
CameraSuiteViewIdGuide,
CameraSuiteViewIdSettings,
} CameraSuiteViewId;

typedef enum {
CameraSuiteOrientation0,
CameraSuiteOrientation90,
CameraSuiteOrientation180,
CameraSuiteOrientation270,
} CameraSuiteOrientationState;

typedef enum {
CameraSuiteHapticOff,
CameraSuiteHapticOn,
} CameraSuiteHapticState;

typedef enum {
CameraSuiteSpeakerOff,
CameraSuiteSpeakerOn,
} CameraSuiteSpeakerState;

typedef enum {
CameraSuiteLedOff,
CameraSuiteLedOn,
} CameraSuiteLedState;
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#pragma once

typedef enum {
// Scene events: Start menu
CameraSuiteCustomEventStartUp,
CameraSuiteCustomEventStartDown,
CameraSuiteCustomEventStartLeft,
CameraSuiteCustomEventStartRight,
CameraSuiteCustomEventStartOk,
CameraSuiteCustomEventStartBack,
// Scene events: Camera style 1
CameraSuiteCustomEventSceneStyle1Up,
CameraSuiteCustomEventSceneStyle1Down,
CameraSuiteCustomEventSceneStyle1Left,
CameraSuiteCustomEventSceneStyle1Right,
CameraSuiteCustomEventSceneStyle1Ok,
CameraSuiteCustomEventSceneStyle1Back,
// Scene events: Camera style 2
CameraSuiteCustomEventSceneStyle2Up,
CameraSuiteCustomEventSceneStyle2Down,
CameraSuiteCustomEventSceneStyle2Left,
CameraSuiteCustomEventSceneStyle2Right,
CameraSuiteCustomEventSceneStyle2Ok,
CameraSuiteCustomEventSceneStyle2Back,
// Scene events: Guide
CameraSuiteCustomEventSceneGuideUp,
CameraSuiteCustomEventSceneGuideDown,
CameraSuiteCustomEventSceneGuideLeft,
CameraSuiteCustomEventSceneGuideRight,
CameraSuiteCustomEventSceneGuideOk,
CameraSuiteCustomEventSceneGuideBack,
} CameraSuiteCustomEvent;

enum CameraSuiteCustomEventType {
// Reserve first 100 events for button types and indexes, starting from 0.
CameraSuiteCustomEventMenuVoid,
CameraSuiteCustomEventMenuSelected,
};

#pragma pack(push, 1)

typedef union {
uint32_t packed_value;
struct {
uint16_t type;
int16_t value;
} content;
} CameraSuiteCustomEventMenu;

#pragma pack(pop)

static inline uint32_t camera_suite_custom_menu_event_pack(uint16_t type, int16_t value) {
CameraSuiteCustomEventMenu event = {.content = {.type = type, .value = value}};
return event.packed_value;
}

static inline void
camera_suite_custom_menu_event_unpack(uint32_t packed_value, uint16_t* type, int16_t* value) {
CameraSuiteCustomEventMenu event = {.packed_value = packed_value};
if(type) *type = event.content.type;
if(value) *value = event.content.value;
}

static inline uint16_t camera_suite_custom_menu_event_get_type(uint32_t packed_value) {
uint16_t type;
camera_suite_custom_menu_event_unpack(packed_value, &type, NULL);
return type;
}

static inline int16_t camera_suite_custom_menu_event_get_value(uint32_t packed_value) {
int16_t value;
camera_suite_custom_menu_event_unpack(packed_value, NULL, &value);
return value;
}
35 changes: 35 additions & 0 deletions applications/external/camera-suite/helpers/camera_suite_haptic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "camera_suite_haptic.h"
#include "../camera-suite.h"

void camera_suite_play_happy_bump(void* context) {
CameraSuite* app = context;
if(app->haptic != 1) {
return;
}
notification_message(app->notification, &sequence_set_vibro_on);
furi_thread_flags_wait(0, FuriFlagWaitAny, 20);
notification_message(app->notification, &sequence_reset_vibro);
}

void camera_suite_play_bad_bump(void* context) {
CameraSuite* app = context;
if(app->haptic != 1) {
return;
}
notification_message(app->notification, &sequence_set_vibro_on);
furi_thread_flags_wait(0, FuriFlagWaitAny, 100);
notification_message(app->notification, &sequence_reset_vibro);
}

void camera_suite_play_long_bump(void* context) {
CameraSuite* app = context;
if(app->haptic != 1) {
return;
}
for(int i = 0; i < 4; i++) {
notification_message(app->notification, &sequence_set_vibro_on);
furi_thread_flags_wait(0, FuriFlagWaitAny, 50);
notification_message(app->notification, &sequence_reset_vibro);
furi_thread_flags_wait(0, FuriFlagWaitAny, 100);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include <notification/notification_messages.h>

void camera_suite_play_happy_bump(void* context);

void camera_suite_play_bad_bump(void* context);

void camera_suite_play_long_bump(void* context);
38 changes: 38 additions & 0 deletions applications/external/camera-suite/helpers/camera_suite_led.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#include "camera_suite_led.h"
#include "../camera-suite.h"

void camera_suite_led_set_rgb(void* context, int red, int green, int blue) {
CameraSuite* app = context;
if(app->led != 1) {
return;
}
NotificationMessage notification_led_message_1;
notification_led_message_1.type = NotificationMessageTypeLedRed;
NotificationMessage notification_led_message_2;
notification_led_message_2.type = NotificationMessageTypeLedGreen;
NotificationMessage notification_led_message_3;
notification_led_message_3.type = NotificationMessageTypeLedBlue;

notification_led_message_1.data.led.value = red;
notification_led_message_2.data.led.value = green;
notification_led_message_3.data.led.value = blue;
const NotificationSequence notification_sequence = {
&notification_led_message_1,
&notification_led_message_2,
&notification_led_message_3,
&message_do_not_reset,
NULL,
};
notification_message(app->notification, &notification_sequence);
//Delay, prevent removal from RAM before LED value set.
furi_thread_flags_wait(0, FuriFlagWaitAny, 10);
}

void camera_suite_led_reset(void* context) {
CameraSuite* app = context;
notification_message(app->notification, &sequence_reset_red);
notification_message(app->notification, &sequence_reset_green);
notification_message(app->notification, &sequence_reset_blue);
//Delay, prevent removal from RAM before LED value set.
furi_thread_flags_wait(0, FuriFlagWaitAny, 300);
}
3 changes: 3 additions & 0 deletions applications/external/camera-suite/helpers/camera_suite_led.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
void camera_suite_led_set_rgb(void* context, int red, int green, int blue);

void camera_suite_led_reset(void* context);
Loading

0 comments on commit 44baa84

Please sign in to comment.