MX 7 месяцев назад
Родитель
Сommit
cb25b32916

+ 3 - 2
application.fam

@@ -3,11 +3,12 @@ App(
     apptype=FlipperAppType.EXTERNAL,
     cdefines=["APP_CAMERA_SUITE"],
     entry_point="camera_suite_app",
-    fap_author="@CodyTolene @Z4urce @leedave",
+    fap_author="@CodyTolene @Z4urce @leedave @rnadyrshin",
     fap_category="GPIO",
     fap_description="A camera suite application for the Flipper Zero ESP32-CAM module.",
     fap_icon="icons/camera_suite.png",
-    fap_version="1.8",
+    fap_libs=["assets"],
+    fap_version="1.9",
     fap_weburl="https://github.com/CodyTolene/Flipper-Zero-Cam",
     name="[ESP32] Camera Suite",
     order=1,

+ 7 - 0
docs/CHANGELOG.md

@@ -5,6 +5,13 @@
 - Full screen 90 degree and 270 degree fill (#6).
 - WiFi streaming/connection support (#35).
 
+## v1.9
+
+- Updating the row and column iteration boundaries in the serial stream to cover the full 128×128 image.
+- Changing the camera configuration from QQVGA to 128×128 mode.
+- Adjusting buffer size macros and pixel offset calculations in the camera suite view to accommodate the new image dimensions.
+- New contributor "rnadyrshin", thank you!
+
 ## v1.8
 
 - Use new Flipper Zero "DateTime" type for image filenames as "YYYYMMDD-HHMMSS.bmp" (#52).

+ 1 - 1
helpers/camera_suite_storage.c

@@ -119,4 +119,4 @@ void camera_suite_read_settings(void* context) {
 
     camera_suite_close_config_file(fff_file);
     camera_suite_close_storage();
-}
+}

+ 12 - 12
helpers/camera_suite_storage.h

@@ -8,18 +8,18 @@
 #ifndef CAMERA_SUITE_STORAGE_H
 #define CAMERA_SUITE_STORAGE_H
 
-#define BOILERPLATE_SETTINGS_FILE_VERSION 1
-#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/camera_suite")
-#define BOILERPLATE_SETTINGS_SAVE_PATH CONFIG_FILE_DIRECTORY_PATH "/camera_suite.conf"
-#define BOILERPLATE_SETTINGS_SAVE_PATH_TMP BOILERPLATE_SETTINGS_SAVE_PATH ".tmp"
-#define BOILERPLATE_SETTINGS_HEADER "Camera Suite Config File"
-#define BOILERPLATE_SETTINGS_KEY_ORIENTATION "Orientation"
-#define BOILERPLATE_SETTINGS_KEY_DITHER "Dither"
-#define BOILERPLATE_SETTINGS_KEY_FLASH "Flash"
-#define BOILERPLATE_SETTINGS_KEY_JPEG "SaveJPEG"
-#define BOILERPLATE_SETTINGS_KEY_HAPTIC "Haptic"
-#define BOILERPLATE_SETTINGS_KEY_LED "Led"
-#define BOILERPLATE_SETTINGS_KEY_SPEAKER "Speaker"
+#define BOILERPLATE_SETTINGS_FILE_VERSION      1
+#define CONFIG_FILE_DIRECTORY_PATH             EXT_PATH("apps_data/camera_suite")
+#define BOILERPLATE_SETTINGS_SAVE_PATH         CONFIG_FILE_DIRECTORY_PATH "/camera_suite.conf"
+#define BOILERPLATE_SETTINGS_SAVE_PATH_TMP     BOILERPLATE_SETTINGS_SAVE_PATH ".tmp"
+#define BOILERPLATE_SETTINGS_HEADER            "Camera Suite Config File"
+#define BOILERPLATE_SETTINGS_KEY_ORIENTATION   "Orientation"
+#define BOILERPLATE_SETTINGS_KEY_DITHER        "Dither"
+#define BOILERPLATE_SETTINGS_KEY_FLASH         "Flash"
+#define BOILERPLATE_SETTINGS_KEY_JPEG          "SaveJPEG"
+#define BOILERPLATE_SETTINGS_KEY_HAPTIC        "Haptic"
+#define BOILERPLATE_SETTINGS_KEY_LED           "Led"
+#define BOILERPLATE_SETTINGS_KEY_SPEAKER       "Speaker"
 #define BOILERPLATE_SETTINGS_KEY_SAVE_SETTINGS "SaveSettings"
 
 void camera_suite_save_settings(void* context);

+ 1 - 1
scenes/camera_suite_scene_guide.c

@@ -48,4 +48,4 @@ bool camera_suite_scene_guide_on_event(void* context, SceneManagerEvent event) {
 void camera_suite_scene_guide_on_exit(void* context) {
     CameraSuite* app = context;
     UNUSED(app);
-}
+}

+ 1 - 1
scenes/camera_suite_scene_menu.c

@@ -90,4 +90,4 @@ bool camera_suite_scene_menu_on_event(void* context, SceneManagerEvent event) {
 void camera_suite_scene_menu_on_exit(void* context) {
     CameraSuite* app = context;
     submenu_reset(app->submenu);
-}
+}

+ 1 - 1
scenes/camera_suite_scene_start.c

@@ -52,4 +52,4 @@ bool camera_suite_scene_start_on_event(void* context, SceneManagerEvent event) {
 void camera_suite_scene_start_on_exit(void* context) {
     CameraSuite* app = context;
     UNUSED(app);
-}
+}

+ 46 - 35
views/camera_suite_view_camera.c

@@ -8,31 +8,51 @@
 #include "../helpers/camera_suite_speaker.h"
 #include "../helpers/camera_suite_led.h"
 
-static void draw_pixel_by_orientation(Canvas* canvas, uint8_t x, uint8_t y, uint8_t orientation) {
+static uint8_t get_pixel(uint8_t* buf, uint8_t x, uint8_t y) {
+    uint32_t pix_cnt = (y * FRAME_WIDTH) + x;
+    uint32_t idx = pix_cnt / 8;
+    uint8_t bit = pix_cnt % 8;
+    return buf[idx] & (1 << (7 - bit)) ? 1 : 0;
+}
+
+static void draw_image(Canvas* canvas, uint8_t* cam_buf, uint8_t orientation) {
     furi_assert(canvas);
-    furi_assert(x);
-    furi_assert(y);
     furi_assert(orientation);
 
-    switch(orientation) {
-    default:
-    case 0: { // Camera rotated 0 degrees (right side up, default)
-        canvas_draw_dot(canvas, x, y);
-        break;
-    }
-    case 1: { // Camera rotated 90 degrees
+    for(size_t y = 0; y < FRAME_HEIGHT; y++) {
+        for(size_t x = 0; x < FRAME_WIDTH; x++) {
+            uint8_t x_cam;
+            uint8_t y_cam;
+
+            switch(orientation) {
+            default:
+            case 0: { // Camera rotated 0 degrees (right side up, default)
+                x_cam = x;
+                y_cam = y + 32;
+                break;
+            }
+            case 1: { // Camera rotated 90 degrees
+                x_cam = FRAME_WIDTH - y - 32 - 1;
+                y_cam = x;
+                break;
+            }
+            case 2: { // Camera rotated 180 degrees (upside down)
+                x_cam = FRAME_WIDTH - x - 1;
+                y_cam = FRAME_WIDTH - y - 32 - 1;
+                break;
+            }
+            case 3: { // Camera rotated 270 degrees
+                x_cam = y + 32;
+                y_cam = FRAME_WIDTH - x - 1;
+                break;
+            }
+            }
 
-        canvas_draw_dot(canvas, y, FRAME_WIDTH - 1 - x);
-        break;
-    }
-    case 2: { // Camera rotated 180 degrees (upside down)
-        canvas_draw_dot(canvas, x, FRAME_HEIGHT - 1 - y);
-        break;
-    }
-    case 3: { // Camera rotated 270 degrees
-        canvas_draw_dot(canvas, FRAME_HEIGHT - 1 - y, x);
-        break;
-    }
+            uint8_t pixel = get_pixel(cam_buf, x_cam, y_cam);
+            if(pixel) {
+                canvas_draw_dot(canvas, x, FRAME_HEIGHT - y - 1);
+            }
+        }
     }
 }
 
@@ -48,16 +68,8 @@ static void camera_suite_view_camera_draw(Canvas* canvas, void* model) {
     // Draw the frame.
     canvas_draw_frame(canvas, 0, 0, FRAME_WIDTH, FRAME_HEIGHT);
 
-    for(size_t p = 0; p < FRAME_BUFFER_LENGTH; ++p) {
-        uint8_t x = p % ROW_BUFFER_LENGTH; // 0 .. 15
-        uint8_t y = p / ROW_BUFFER_LENGTH; // 0 .. 63
-
-        for(uint8_t i = 0; i < 8; ++i) {
-            if((uartDumpModel->pixels[p] & (1 << (7 - i))) != 0) {
-                draw_pixel_by_orientation(canvas, (x * 8) + i, y, uartDumpModel->orientation);
-            }
-        }
-    }
+    // Draw the image
+    draw_image(canvas, uartDumpModel->pixels, uartDumpModel->orientation);
 
     // Draw the pinout guide if the camera is not initialized.
     if(!uartDumpModel->is_initialized) {
@@ -215,7 +227,7 @@ static void save_image_to_flipper_sd_card(void* model) {
         // @todo - Save image based on orientation.
         for(size_t i = 64; i > 0; --i) {
             for(size_t j = 0; j < ROW_BUFFER_LENGTH; ++j) {
-                row_buffer[j] = uartDumpModel->pixels[((i - 1) * ROW_BUFFER_LENGTH) + j];
+                row_buffer[j] = uartDumpModel->pixels[((i + 32 - 1) * ROW_BUFFER_LENGTH) + j];
             }
             storage_file_write(file, row_buffer, ROW_BUFFER_LENGTH);
         }
@@ -557,8 +569,7 @@ static int32_t camera_suite_camera_worker(void* context) {
                 }
             } while(length > 0);
 
-            with_view_model(
-                instance->view, UartDumpModel * model, { UNUSED(model); }, true);
+            with_view_model(instance->view, UartDumpModel * model, { UNUSED(model); }, true);
         }
     }
 
@@ -645,4 +656,4 @@ void camera_suite_view_camera_set_callback(
     furi_assert(callback);
     instance->callback = callback;
     instance->context = context;
-}
+}

+ 8 - 8
views/camera_suite_view_camera.h

@@ -20,14 +20,14 @@
 #define UART_CH (FuriHalSerialIdUsart)
 
 #define BITMAP_HEADER_LENGTH 62
-#define FRAME_BIT_DEPTH 1
-#define FRAME_BUFFER_LENGTH 1024
-#define FRAME_HEIGHT 64
-#define FRAME_WIDTH 128
-#define HEADER_LENGTH 3 // 'Y', ':', and row identifier
-#define LAST_ROW_INDEX 1008
-#define RING_BUFFER_LENGTH 19
-#define ROW_BUFFER_LENGTH 16
+#define FRAME_BIT_DEPTH      1
+#define FRAME_BUFFER_LENGTH  (2 * 1024)
+#define FRAME_HEIGHT         64
+#define FRAME_WIDTH          128
+#define HEADER_LENGTH        3 // 'Y', ':', and row identifier
+#define LAST_ROW_INDEX       (2 * 1008)
+#define RING_BUFFER_LENGTH   19
+#define ROW_BUFFER_LENGTH    16
 
 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,

+ 1 - 2
views/camera_suite_view_guide.c

@@ -108,8 +108,7 @@ CameraSuiteViewGuide* camera_suite_view_guide_alloc() {
 void camera_suite_view_guide_free(CameraSuiteViewGuide* instance) {
     furi_assert(instance);
 
-    with_view_model(
-        instance->view, CameraSuiteViewGuideModel * model, { UNUSED(model); }, true);
+    with_view_model(instance->view, CameraSuiteViewGuideModel * model, { UNUSED(model); }, true);
     view_free(instance->view);
     free(instance);
 }

+ 1 - 1
views/camera_suite_view_guide.h

@@ -16,4 +16,4 @@ View* camera_suite_view_guide_get_view(CameraSuiteViewGuide* camera_suite_static
 
 CameraSuiteViewGuide* camera_suite_view_guide_alloc();
 
-void camera_suite_view_guide_free(CameraSuiteViewGuide* camera_suite_static);
+void camera_suite_view_guide_free(CameraSuiteViewGuide* camera_suite_static);

+ 1 - 2
views/camera_suite_view_start.c

@@ -189,8 +189,7 @@ CameraSuiteViewStart* camera_suite_view_start_alloc() {
 void camera_suite_view_start_free(CameraSuiteViewStart* instance) {
     furi_assert(instance);
 
-    with_view_model(
-        instance->view, CameraSuiteViewStartModel * model, { UNUSED(model); }, true);
+    with_view_model(instance->view, CameraSuiteViewStartModel * model, { UNUSED(model); }, true);
     view_free(instance->view);
     free(instance);
 }