SybexX 1 год назад
Родитель
Сommit
be7146c886

+ 168 - 98
code/components/jomjol_controlcamera/ClassControllCamera.cpp

@@ -32,6 +32,8 @@
 #include "MainFlowControl.h"
 
 #include "ov2640_sharpness.h"
+#include "ov2640_specialEffect.h"
+#include "ov2640_contrast_brightness.h"
 
 #if (ESP_IDF_VERSION_MAJOR >= 5)
 #include "soc/periph_defs.h"
@@ -248,43 +250,43 @@ esp_err_t CCamera::setSensorDatenFromCCstatus(void)
     if (s != NULL)
     {
         s->set_framesize(s, CCstatus.ImageFrameSize);
-        s->set_quality(s, CCstatus.ImageQuality); // 0 - 63
-
-        s->set_brightness(s, CCstatus.ImageBrightness); // -2 to 2
-        s->set_contrast(s, CCstatus.ImageContrast);     // -2 to 2
+		
+        // s->set_contrast(s, CCstatus.ImageContrast);     // -2 to 2
+        // s->set_brightness(s, CCstatus.ImageBrightness); // -2 to 2
+        SetCamContrastBrightness(s, CCstatus.ImageContrast, CCstatus.ImageBrightness);
+		
         s->set_saturation(s, CCstatus.ImageSaturation); // -2 to 2
-        // s->set_sharpness(s, CCstatus.ImageSharpness);   // auto-sharpness is not officially supported, default to 0
-        SetCamSharpness(CCstatus.ImageAutoSharpness, CCstatus.ImageSharpness);
-
-        s->set_denoise(s, CCstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
-
-        s->set_special_effect(s, CCstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
-        s->set_wb_mode(s, CCstatus.ImageWbMode);               // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
-
-        s->set_ae_level(s, CCstatus.ImageAeLevel);   // -2 to 2
-        s->set_aec_value(s, CCstatus.ImageAecValue); // 0 to 1200
-        s->set_agc_gain(s, CCstatus.ImageAgcGain);   // 0 to 30
 
+        s->set_quality(s, CCstatus.ImageQuality); // 0 - 63
+		
         // s->set_gainceiling(s, CCstatus.ImageGainceiling); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
-        ov5640_set_gainceiling(s, CCstatus.ImageGainceiling);
-
-        s->set_lenc(s, CCstatus.ImageLenc);         // 0 = disable , 1 = enable
+        SetCamGainceiling(s, CCstatus.ImageGainceiling);
+		
         s->set_gain_ctrl(s, CCstatus.ImageAgc);     // 0 = disable , 1 = enable
         s->set_exposure_ctrl(s, CCstatus.ImageAec); // 0 = disable , 1 = enable
-
         s->set_hmirror(s, CCstatus.ImageHmirror); // 0 = disable , 1 = enable
         s->set_vflip(s, CCstatus.ImageVflip);     // 0 = disable , 1 = enable
+		
+        s->set_whitebal(s, CCstatus.ImageAwb);     // 0 = disable , 1 = enable
         s->set_aec2(s, CCstatus.ImageAec2);       // 0 = disable , 1 = enable
-
+        s->set_aec_value(s, CCstatus.ImageAecValue); // 0 to 1200
+        // s->set_special_effect(s, CCstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
+        SetCamSpecialEffect(s, CCstatus.ImageSpecialEffect);
+        s->set_wb_mode(s, CCstatus.ImageWbMode);               // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
+        s->set_ae_level(s, CCstatus.ImageAeLevel);   // -2 to 2
+		
+        s->set_dcw(s, CCstatus.ImageDcw); // 0 = disable , 1 = enable
         s->set_bpc(s, CCstatus.ImageBpc); // 0 = disable , 1 = enable
         s->set_wpc(s, CCstatus.ImageWpc); // 0 = disable , 1 = enable
-
-        s->set_raw_gma(s, CCstatus.ImageRawGma); // 0 = disable , 1 = enable
-
         s->set_awb_gain(s, CCstatus.ImageAwbGain); // 0 = disable , 1 = enable
-        s->set_whitebal(s, CCstatus.ImageAwb);     // 0 = disable , 1 = enable
+        s->set_agc_gain(s, CCstatus.ImageAgcGain);   // 0 to 30
+		
+        s->set_raw_gma(s, CCstatus.ImageRawGma); // 0 = disable , 1 = enable
+        s->set_lenc(s, CCstatus.ImageLenc);         // 0 = disable , 1 = enable
 
-        s->set_dcw(s, CCstatus.ImageDcw); // 0 = disable , 1 = enable
+        // s->set_sharpness(s, CCstatus.ImageSharpness);   // auto-sharpness is not officially supported, default to 0
+        SetCamSharpness(CCstatus.ImageAutoSharpness, CCstatus.ImageSharpness);
+        s->set_denoise(s, CCstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
 
         TickType_t cam_xDelay = 100 / portTICK_PERIOD_MS;
         vTaskDelay(cam_xDelay);
@@ -306,30 +308,37 @@ esp_err_t CCamera::getSensorDatenToCCstatus(void)
         CCstatus.CamSensor_id = s->id.PID;
 
         CCstatus.ImageFrameSize = (framesize_t)s->status.framesize;
-        CCstatus.ImageGainceiling = (gainceiling_t)s->status.gainceiling;
-
-        CCstatus.ImageQuality = s->status.quality;
-        CCstatus.ImageBrightness = s->status.brightness;
+		
         CCstatus.ImageContrast = s->status.contrast;
+        CCstatus.ImageBrightness = s->status.brightness;
         CCstatus.ImageSaturation = s->status.saturation;
-        // CCstatus.ImageSharpness = s->status.sharpness; // gibt -1 zurück, da es nicht unterstützt wird
-        CCstatus.ImageWbMode = s->status.wb_mode;
-        CCstatus.ImageAwb = s->status.awb;
-        CCstatus.ImageAwbGain = s->status.awb_gain;
+		
+        CCstatus.ImageQuality = s->status.quality;
+		
+        CCstatus.ImageGainceiling = (gainceiling_t)s->status.gainceiling;
+
+        CCstatus.ImageAgc = s->status.agc;
         CCstatus.ImageAec = s->status.aec;
+        CCstatus.ImageHmirror = s->status.hmirror;
+        CCstatus.ImageVflip = s->status.vflip;
+		
+        CCstatus.ImageAwb = s->status.awb;
         CCstatus.ImageAec2 = s->status.aec2;
-        CCstatus.ImageAeLevel = s->status.ae_level;
         CCstatus.ImageAecValue = s->status.aec_value;
-        CCstatus.ImageAgc = s->status.agc;
-        CCstatus.ImageAgcGain = s->status.agc_gain;
+        CCstatus.ImageSpecialEffect = s->status.special_effect;
+        CCstatus.ImageWbMode = s->status.wb_mode;
+        CCstatus.ImageAeLevel = s->status.ae_level;
+		
+        CCstatus.ImageDcw = s->status.dcw;
         CCstatus.ImageBpc = s->status.bpc;
         CCstatus.ImageWpc = s->status.wpc;
+        CCstatus.ImageAwbGain = s->status.awb_gain;
+        CCstatus.ImageAgcGain = s->status.agc_gain;
+		
         CCstatus.ImageRawGma = s->status.raw_gma;
         CCstatus.ImageLenc = s->status.lenc;
-        CCstatus.ImageSpecialEffect = s->status.special_effect;
-        CCstatus.ImageHmirror = s->status.hmirror;
-        CCstatus.ImageVflip = s->status.vflip;
-        CCstatus.ImageDcw = s->status.dcw;
+
+        // CCstatus.ImageSharpness = s->status.sharpness; // gibt -1 zurück, da es nicht unterstützt wird
         CCstatus.ImageDenoiseLevel = s->status.denoise;
 
         return ESP_OK;
@@ -340,31 +349,96 @@ esp_err_t CCamera::getSensorDatenToCCstatus(void)
     }
 }
 
-// on the OV5640, gainceiling must be set with the real value (x2>>>level = 2, .... x128>>>level = 128)
-int CCamera::ov5640_set_gainceiling(sensor_t *s, gainceiling_t level)
+// on the OV5640, gainceiling must be set with the real value (x2>>>gainceilingLevel = 2, .... x128>>>gainceilingLevel = 128)
+int CCamera::SetCamGainceiling(sensor_t *s, gainceiling_t gainceilingLevel)
 {
 	int ret = 0;
 		
     if (CCstatus.CamSensor_id == OV2640_PID)
     {
-        ret = s->set_gainceiling(s, CCstatus.ImageGainceiling); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
+        ret = s->set_gainceiling(s, gainceilingLevel); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
     }
     else
     {
-		int _level = (1 << ((int)level + 1));
+        int _level = (1 << ((int)gainceilingLevel + 1));
 
-		ret = s->set_reg(s, 0x3A18, 0xFF, (_level >> 8) & 3) || s->set_reg(s, 0x3A19, 0xFF, _level & 0xFF);
+        ret = s->set_reg(s, 0x3A18, 0xFF, (_level >> 8) & 3) || s->set_reg(s, 0x3A19, 0xFF, _level & 0xFF);
 
-		if (ret == 0)
-		{
-			// ESP_LOGD(TAG, "Set gainceiling to: %d", level);
-			s->status.gainceiling = level;
-		}
+        if (ret == 0)
+        {
+            // ESP_LOGD(TAG, "Set gainceiling to: %d", gainceilingLevel);
+            s->status.gainceiling = gainceilingLevel;
+        }
     }
 
     return ret;
 }
 
+void CCamera::SetCamSharpness(bool autoSharpnessEnabled, int sharpnessLevel)
+{
+    sensor_t *s = esp_camera_sensor_get();
+
+    if (s != NULL)
+    {
+        if (CCstatus.CamSensor_id == OV2640_PID)
+        {
+            sharpnessLevel = min(2, max(-2, sharpnessLevel));
+            // The OV2640 does not officially support sharpness, so the detour is made with the ov2640_sharpness.cpp.
+            if (autoSharpnessEnabled)
+            {
+                ov2640_enable_auto_sharpness(s);
+            }
+            else
+            {
+                ov2640_set_sharpness(s, sharpnessLevel);
+            }
+        }
+        else
+        {
+            sharpnessLevel = min(3, max(-3, sharpnessLevel));
+            // for CAMERA_OV5640 and CAMERA_OV3660
+            if (autoSharpnessEnabled)
+            {
+                // autoSharpness is not supported, default to zero
+                s->set_sharpness(s, 0);
+            }
+            else
+            {
+                s->set_sharpness(s, sharpnessLevel);
+            }
+        }
+    }
+    else
+    {
+        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SetCamSharpness, Failed to get Cam control structure");
+    }
+}
+
+void CCamera::SetCamSpecialEffect(sensor_t *s, int specialEffect)
+{
+    if (CCstatus.CamSensor_id == OV2640_PID)
+    {
+        ov2640_set_special_effect(s, specialEffect);
+    }
+    else
+    {
+        s->set_special_effect(s, specialEffect);
+    }
+}
+
+void CCamera::SetCamContrastBrightness(sensor_t *s, int _contrast, int _brightness)
+{
+    if (CCstatus.CamSensor_id == OV2640_PID)
+    {
+        ov2640_set_contrast_brightness(s, _contrast, _brightness);
+    }
+    else
+    {
+        s->set_contrast(s, _contrast);     // -2 to 2
+        s->set_brightness(s, _brightness); // -2 to 2
+    }
+}
+
 // - It always zooms to the image center when offsets are zero
 // - if imageSize = 0 then the image is not zoomed
 // - if imageSize = max value, then the image is fully zoomed in
@@ -518,46 +592,6 @@ void CCamera::SetQualityZoomSize(int qual, framesize_t resol, bool zoomEnabled,
     }
 }
 
-void CCamera::SetCamSharpness(bool _autoSharpnessEnabled, int _sharpnessLevel)
-{
-    sensor_t *s = esp_camera_sensor_get();
-
-    if (s != NULL)
-    {
-        if (CCstatus.CamSensor_id == OV2640_PID)
-        {
-            _sharpnessLevel = min(2, max(-2, _sharpnessLevel));
-            // The OV2640 does not officially support sharpness, so the detour is made with the ov2640_sharpness.cpp.
-            if (_autoSharpnessEnabled)
-            {
-                ov2640_enable_auto_sharpness(s);
-            }
-            else
-            {
-                ov2640_set_sharpness(s, _sharpnessLevel);
-            }
-        }
-        else
-        {
-            _sharpnessLevel = min(3, max(-3, _sharpnessLevel));
-            // for CAMERA_OV5640 and CAMERA_OV3660
-            if (_autoSharpnessEnabled)
-            {
-                // autoSharpness is not supported, default to zero
-                s->set_sharpness(s, 0);
-            }
-            else
-            {
-                s->set_sharpness(s, _sharpnessLevel);
-            }
-        }
-    }
-    else
-    {
-        LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SetCamSharpness, Failed to get Cam control structure");
-    }
-}
-
 void CCamera::SetCamWindow(sensor_t *s, int frameSizeX, int frameSizeY, int xOffset, int yOffset, int xTotal, int yTotal, int xOutput, int yOutput, int imageVflip)
 {
     if (CCstatus.CamSensor_id == OV2640_PID)
@@ -1055,38 +1089,58 @@ void CCamera::SetImageWidthHeightFromResolution(framesize_t resol)
 {
     if (resol == FRAMESIZE_QVGA)
     {
-        CCstatus.ImageHeight = 240;
         CCstatus.ImageWidth = 320;
+        CCstatus.ImageHeight = 240;
     }
     else if (resol == FRAMESIZE_VGA)
     {
-        CCstatus.ImageHeight = 480;
         CCstatus.ImageWidth = 640;
+        CCstatus.ImageHeight = 480;
     }
     else if (resol == FRAMESIZE_SVGA)
     {
-        CCstatus.ImageHeight = 600;
         CCstatus.ImageWidth = 800;
+        CCstatus.ImageHeight = 600;
     }
     else if (resol == FRAMESIZE_XGA)
     {
-        CCstatus.ImageHeight = 768;
         CCstatus.ImageWidth = 1024;
+        CCstatus.ImageHeight = 768;
     }
     else if (resol == FRAMESIZE_HD)
     {
-        CCstatus.ImageHeight = 720;
         CCstatus.ImageWidth = 1280;
+        CCstatus.ImageHeight = 720;
     }
     else if (resol == FRAMESIZE_SXGA)
     {
-        CCstatus.ImageHeight = 1024;
         CCstatus.ImageWidth = 1280;
+        CCstatus.ImageHeight = 1024;
     }
     else if (resol == FRAMESIZE_UXGA)
     {
-        CCstatus.ImageHeight = 1200;
         CCstatus.ImageWidth = 1600;
+        CCstatus.ImageHeight = 1200;
+    }
+    else if (resol == FRAMESIZE_QXGA)
+    {
+        CCstatus.ImageWidth = 2048;
+        CCstatus.ImageHeight = 1536;
+    }
+    else if (resol == FRAMESIZE_WQXGA)
+    {
+        CCstatus.ImageWidth = 2560;
+        CCstatus.ImageHeight = 1600;
+    }
+    else if (resol == FRAMESIZE_QSXGA)
+    {
+        CCstatus.ImageWidth = 2560;
+        CCstatus.ImageHeight = 1920;
+    }
+    else
+    {
+        CCstatus.ImageWidth = 640;
+        CCstatus.ImageHeight = 480;
     }
 }
 
@@ -1116,8 +1170,24 @@ framesize_t CCamera::TextToFramesize(const char *_size)
     {
         return FRAMESIZE_UXGA; // 1600x1200
     }
+    else if (strcmp(_size, "QXGA") == 0)
+    {
+        return FRAMESIZE_QXGA; // 2048x1536
+    }
+    else if (strcmp(_size, "WQXGA") == 0)
+    {
+        return FRAMESIZE_WQXGA; // 2560x1600
+    }
+    else if (strcmp(_size, "QSXGA") == 0)
+    {
+        return FRAMESIZE_QSXGA; // 2560x1920
+    }
+    else
+    {
+        return FRAMESIZE_VGA; // 640x480
+    }
 
-    return CCstatus.ImageFrameSize;
+    // return CCstatus.ImageFrameSize;
 }
 
 std::vector<std::string> demoFiles;

+ 4 - 2
code/components/jomjol_controlcamera/ClassControllCamera.h

@@ -89,14 +89,16 @@ public:
     esp_err_t setSensorDatenFromCCstatus(void);
     esp_err_t getSensorDatenToCCstatus(void);
 
-    int ov5640_set_gainceiling(sensor_t *s, gainceiling_t level);
+    int SetCamGainceiling(sensor_t *s, gainceiling_t gainceilingLevel);
+    void SetCamSharpness(bool autoSharpnessEnabled, int sharpnessLevel);
+    void SetCamSpecialEffect(sensor_t *s, int specialEffect);
+    void SetCamContrastBrightness(sensor_t *s, int _contrast, int _brightness);
 
     esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
     esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);
 
     void SetQualityZoomSize(int qual, framesize_t resol, bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize, int imageVflip);
     void SetZoomSize(bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize, int imageVflip);
-    void SetCamSharpness(bool _autoSharpnessEnabled, int _sharpnessLevel);
 
     void SetLEDIntensity(float _intrel);
     bool testCamera(void);

+ 88 - 0
code/components/jomjol_controlcamera/ov2640_contrast_brightness.cpp

@@ -0,0 +1,88 @@
+// Workaround - bug in cam library - enable bits are set without using bitwise OR logic -> only latest enable setting is used
+// Reference: https://esp32.com/viewtopic.php?f=19&t=14376#p93178
+/* The memory structure is as follows for
+   byte_0 = enable_bits
+      byte_0->bit0 = enable saturation and hue --> OK
+      byte_0->bit1 = enable saturation --> OK
+      byte_0->bit2 = enable brightness and contrast --> OK
+      byte_0->bit3 = enable green -> blue spitial effect (Antique and blunish and greenish and reddish and b&w) enable
+      byte_0->bit4 = anable gray -> red spitial effect (Antique and blunish and greenish and reddish and b&w) enable
+      byte_0->bit5 = remove (UV) in YUV color system
+      byte_0->bit6 = enable negative
+      byte_0->bit7 = remove (Y) in YUV color system
+   byte_1  = saturation1 0-255 --> ?
+   byte_2  = hue 0-255 --> OK
+   byte_3  = saturation2 0-255 --> OK
+   byte_4  = reenter saturation2 in documents --> ?
+   byte_5  = spital effect green -> blue 0-255 --> ?
+   byte_6  = spital effect gray -> red 0-255 --> ?
+   byte_7  = contrast lower byte 0-255 --> OK
+   byte_8  = contrast higher byte 0-255 --> OK
+   byte_9  = brightness 0-255 --> OK
+   byte_10 = if byte_10==4 contrast effective --> ?
+*/
+
+#include <stdint.h>
+#include "esp_camera.h"
+#include "ov2640_contrast_brightness.h"
+
+static const uint8_t brightness_regs[6][5] = {
+    {0x7C, 0x7D, 0x7C, 0x7D, 0x7D },
+    {0x00, 0x04, 0x09, 0x00, 0x00 }, /* -2 */
+    {0x00, 0x04, 0x09, 0x10, 0x00 }, /* -1 */
+    {0x00, 0x04, 0x09, 0x20, 0x00 }, /*  0 */
+    {0x00, 0x04, 0x09, 0x30, 0x00 }, /* +1 */
+    {0x00, 0x04, 0x09, 0x40, 0x00 }, /* +2 */
+};
+
+static const uint8_t contrast_regs[6][7] = {
+    {0x7C, 0x7D, 0x7C, 0x7D, 0x7D, 0x7D, 0x7D },
+    {0x00, 0x04, 0x07, 0x20, 0x18, 0x34, 0x06 }, /* -2 */
+    {0x00, 0x04, 0x07, 0x20, 0x1c, 0x2a, 0x06 }, /* -1 */
+    {0x00, 0x04, 0x07, 0x20, 0x20, 0x20, 0x06 }, /*  0 */
+    {0x00, 0x04, 0x07, 0x20, 0x24, 0x16, 0x06 }, /* +1 */
+    {0x00, 0x04, 0x07, 0x20, 0x28, 0x0c, 0x06 }, /* +2 */
+};
+
+int ov2640_set_contrast_brightness(sensor_t *sensor, int _contrast, int _brightness)
+{
+    int ret=0;
+
+    _contrast += 3;
+    if (_contrast <= 0) {
+        _contrast = 3;
+    }
+	else if (_contrast > 5)
+	{
+		_contrast = 5;
+	}
+    sensor->status.contrast = _contrast-3;
+
+    _brightness += 3;
+    if (_brightness <= 0) {
+        _brightness = 3;
+    }
+	else if (_brightness > 5)
+	{
+		_brightness = 5;
+	}
+	int brightness = brightness_regs[_brightness][3];
+    sensor->status.brightness = _brightness-3;
+
+    // sensor->set_reg(sensor, int reg, int mask, int value)
+    sensor->set_reg(sensor, 0xFF, 0x01, 0x00); // Select DSP bank
+
+    for (int i=0; i<7; i++) 
+	{
+		if (i == 5)
+		{
+			sensor->set_reg(sensor, contrast_regs[0][i], 0xFF, (brightness | contrast_regs[_contrast][i]));
+		}
+		else
+		{
+			sensor->set_reg(sensor, contrast_regs[0][i], 0xFF, contrast_regs[_contrast][i]);
+		}
+    }
+
+    return ret;
+}

+ 10 - 0
code/components/jomjol_controlcamera/ov2640_contrast_brightness.h

@@ -0,0 +1,10 @@
+#pragma once
+
+#ifndef OV2640_CONTRAST_BRIGHTNESS_H
+#define OV2640_CONTRAST_BRIGHTNESS_H
+
+#include "esp_camera.h"
+
+int ov2640_set_contrast_brightness(sensor_t *sensor, int _contrast, int _brightness);
+
+#endif

+ 21 - 22
code/components/jomjol_controlcamera/ov2640_sharpness.cpp

@@ -2,10 +2,9 @@
 #include "esp_camera.h"
 #include "ov2640_sharpness.h"
 
-
 const static uint8_t OV2640_SHARPNESS_AUTO[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0x20, 0x20,
@@ -14,7 +13,7 @@ const static uint8_t OV2640_SHARPNESS_AUTO[]=
 
 const static uint8_t OV2640_SHARPNESS_MANUAL[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0x00, 0x20,
@@ -23,7 +22,7 @@ const static uint8_t OV2640_SHARPNESS_MANUAL[]=
 
 const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0xC0, 0x1F,
@@ -31,7 +30,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0xC1, 0x1F,
@@ -39,7 +38,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0xC2, 0x1F,
@@ -47,7 +46,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0xC4, 0x1F,
@@ -55,7 +54,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0xC8, 0x1F,
@@ -63,7 +62,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0xD0, 0x1F,
@@ -71,7 +70,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
 };
 const static uint8_t OV2640_SHARPNESS_LEVEL6[]=
 {
-	//reg, val, mask
+    //reg, val, mask
     0xFF, 0x00, 0xFF,
     0x92, 0x01, 0xFF,
     0x93, 0xDF, 0x1F,
@@ -91,7 +90,6 @@ const static uint8_t *OV2640_SETTING_SHARPNESS[]=
 
 #define OV2640_MAXLEVEL_SHARPNESS 6
 
-
 static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
 {
     uint8_t address;
@@ -101,9 +99,9 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
     const uint8_t *pdata = ptab;
 
     if (pdata == NULL)
-	{
+    {
         return -1;
-	}
+    }
 
     while (1)
     {   
@@ -112,9 +110,9 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
         mask = *pdata++;
 		
         if ((address == 0) && (value == 0) && (mask == 0))
-		{
+        {
             break;
-		}
+        }
 		
         sensor->set_reg(sensor, address, mask, value);
     }   
@@ -122,31 +120,32 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
     return 0;
 }
 
-
 int ov2640_enable_auto_sharpness(sensor_t *sensor)
 {
     table_mask_write(sensor, OV2640_SHARPNESS_AUTO);
+    sensor->status.sharpness = 0;
 	
     return 0;
 }
 
-
 int ov2640_set_sharpness(sensor_t *sensor, int sharpness)
 {
-	int sharpness_temp = 0;
+    int sharpness_temp = 0;
 	
     if (sharpness < -3)
-	{
+    {
         sharpness_temp = -3;
-	}
+    }
 	
     if (sharpness > OV2640_MAXLEVEL_SHARPNESS - 3)
-	{
+    {
         sharpness_temp = OV2640_MAXLEVEL_SHARPNESS - 3;
-	}	
+    }	
 
     table_mask_write(sensor, OV2640_SHARPNESS_MANUAL);
     table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness_temp + 3]);
 	
+    sensor->status.sharpness = sharpness;
+	
     return 0;
 }

+ 66 - 0
code/components/jomjol_controlcamera/ov2640_specialEffect.cpp

@@ -0,0 +1,66 @@
+// Workaround - bug in cam library - enable bits are set without using bitwise OR logic -> only latest enable setting is used
+// Reference: https://esp32.com/viewtopic.php?f=19&t=14376#p93178
+/* The memory structure is as follows for
+   byte_0 = enable_bits
+      byte_0->bit0 = enable saturation and hue --> OK
+      byte_0->bit1 = enable saturation --> OK
+      byte_0->bit2 = enable brightness and contrast --> OK
+      byte_0->bit3 = enable green -> blue spitial effect (Antique and blunish and greenish and reddish and b&w) enable
+      byte_0->bit4 = anable gray -> red spitial effect (Antique and blunish and greenish and reddish and b&w) enable
+      byte_0->bit5 = remove (UV) in YUV color system
+      byte_0->bit6 = enable negative
+      byte_0->bit7 = remove (Y) in YUV color system
+   byte_1  = saturation1 0-255 --> ?
+   byte_2  = hue 0-255 --> OK
+   byte_3  = saturation2 0-255 --> OK
+   byte_4  = reenter saturation2 in documents --> ?
+   byte_5  = spital effect green -> blue 0-255 --> ?
+   byte_6  = spital effect gray -> red 0-255 --> ?
+   byte_7  = contrast lower byte 0-255 --> OK
+   byte_8  = contrast higher byte 0-255 --> OK
+   byte_9  = brightness 0-255 --> OK
+   byte_10 = if byte_10==4 contrast effective --> ?
+*/
+
+#include <stdint.h>
+#include "esp_camera.h"
+#include "ov2640_specialEffect.h"
+
+static const uint8_t special_effects_regs[8][5] = {
+    {0x7C, 0x7D, 0x7C, 0x7D, 0x7D},
+    {0x00, 0X00, 0x05, 0X80, 0X80}, /* no effect */
+    {0x00, 0X40, 0x05, 0X80, 0X80}, /* negative */
+    {0x00, 0X18, 0x05, 0X80, 0X80}, /* black and white */
+    {0x00, 0X18, 0x05, 0X40, 0XC0}, /* reddish */
+    {0x00, 0X18, 0x05, 0X40, 0X40}, /* greenish */
+    {0x00, 0X18, 0x05, 0XA0, 0X40}, /* blue */
+    {0x00, 0X18, 0x05, 0X40, 0XA6}, /* retro */
+};
+
+int ov2640_set_special_effect(sensor_t *sensor, int effect)
+{
+    int ret = 0;
+    effect++;
+
+    if (effect <= 0 || effect > 7)
+    {
+        effect = 1;
+    }
+
+    sensor->status.special_effect = effect - 1;
+
+    int registerValue = 0x06; // enable saturation, contrast, brightness
+    registerValue |= special_effects_regs[effect][1];
+
+    // sensor->set_reg(sensor, int reg, int mask, int value)
+    sensor->set_reg(sensor, 0xFF, 0x01, 0x00); // Select DSP bank
+    sensor->set_reg(sensor, special_effects_regs[0][0], 0xFF, 0x00);
+    sensor->set_reg(sensor, special_effects_regs[0][1], 0x5E, registerValue);
+
+    for (int i = 2; i < 5; i++)
+    {
+        sensor->set_reg(sensor, special_effects_regs[0][i], 0xFF, special_effects_regs[effect][i]);
+    }
+
+    return ret;
+}

+ 10 - 0
code/components/jomjol_controlcamera/ov2640_specialEffect.h

@@ -0,0 +1,10 @@
+#pragma once
+
+#ifndef OV2640_SPECIALEFFECT_H
+#define OV2640_SPECIALEFFECT_H
+
+#include "esp_camera.h"
+
+int ov2640_set_special_effect(sensor_t *sensor, int effect);
+
+#endif

+ 71 - 55
code/components/jomjol_flowcontroll/MainFlowControl.cpp

@@ -148,31 +148,39 @@ esp_err_t setCCstatusToCFstatus(void)
     CFstatus.CamSensor_id = CCstatus.CamSensor_id;
 
     CFstatus.ImageFrameSize = CCstatus.ImageFrameSize;
-    CFstatus.ImageGainceiling = CCstatus.ImageGainceiling;
 
-    CFstatus.ImageQuality = CCstatus.ImageQuality;
-    CFstatus.ImageBrightness = CCstatus.ImageBrightness;
     CFstatus.ImageContrast = CCstatus.ImageContrast;
+    CFstatus.ImageBrightness = CCstatus.ImageBrightness;
     CFstatus.ImageSaturation = CCstatus.ImageSaturation;
-    CFstatus.ImageSharpness = CCstatus.ImageSharpness;
-    CFstatus.ImageAutoSharpness = CCstatus.ImageAutoSharpness;
-    CFstatus.ImageWbMode = CCstatus.ImageWbMode;
-    CFstatus.ImageAwb = CCstatus.ImageAwb;
-    CFstatus.ImageAwbGain = CCstatus.ImageAwbGain;
+
+    CFstatus.ImageQuality = CCstatus.ImageQuality;
+
+    CFstatus.ImageGainceiling = CCstatus.ImageGainceiling;
+
+    CFstatus.ImageAgc = CCstatus.ImageAgc;
     CFstatus.ImageAec = CCstatus.ImageAec;
+    CFstatus.ImageHmirror = CCstatus.ImageHmirror;
+    CFstatus.ImageVflip = CCstatus.ImageVflip;
+
+    CFstatus.ImageAwb = CCstatus.ImageAwb;
     CFstatus.ImageAec2 = CCstatus.ImageAec2;
-    CFstatus.ImageAeLevel = CCstatus.ImageAeLevel;
     CFstatus.ImageAecValue = CCstatus.ImageAecValue;
-    CFstatus.ImageAgc = CCstatus.ImageAgc;
-    CFstatus.ImageAgcGain = CCstatus.ImageAgcGain;
+    CFstatus.ImageSpecialEffect = CCstatus.ImageSpecialEffect;
+    CFstatus.ImageWbMode = CCstatus.ImageWbMode;
+    CFstatus.ImageAeLevel = CCstatus.ImageAeLevel;
+
+    CFstatus.ImageDcw = CCstatus.ImageDcw;
     CFstatus.ImageBpc = CCstatus.ImageBpc;
     CFstatus.ImageWpc = CCstatus.ImageWpc;
+    CFstatus.ImageAwbGain = CCstatus.ImageAwbGain;
+    CFstatus.ImageAgcGain = CCstatus.ImageAgcGain;
+
     CFstatus.ImageRawGma = CCstatus.ImageRawGma;
     CFstatus.ImageLenc = CCstatus.ImageLenc;
-    CFstatus.ImageSpecialEffect = CCstatus.ImageSpecialEffect;
-    CFstatus.ImageHmirror = CCstatus.ImageHmirror;
-    CFstatus.ImageVflip = CCstatus.ImageVflip;
-    CFstatus.ImageDcw = CCstatus.ImageDcw;
+
+    CFstatus.ImageSharpness = CCstatus.ImageSharpness;
+    CFstatus.ImageAutoSharpness = CCstatus.ImageAutoSharpness;
+
     CFstatus.ImageDenoiseLevel = CCstatus.ImageDenoiseLevel;
 
     CFstatus.ImageLedIntensity = CCstatus.ImageLedIntensity;
@@ -192,31 +200,39 @@ esp_err_t setCFstatusToCCstatus(void)
     // CCstatus.CamSensor_id = CFstatus.CamSensor_id;
 
     CCstatus.ImageFrameSize = CFstatus.ImageFrameSize;
-    CCstatus.ImageGainceiling = CFstatus.ImageGainceiling;
 
-    CCstatus.ImageQuality = CFstatus.ImageQuality;
-    CCstatus.ImageBrightness = CFstatus.ImageBrightness;
     CCstatus.ImageContrast = CFstatus.ImageContrast;
+    CCstatus.ImageBrightness = CFstatus.ImageBrightness;
     CCstatus.ImageSaturation = CFstatus.ImageSaturation;
-    CCstatus.ImageSharpness = CFstatus.ImageSharpness;
-    CCstatus.ImageAutoSharpness = CFstatus.ImageAutoSharpness;
-    CCstatus.ImageWbMode = CFstatus.ImageWbMode;
-    CCstatus.ImageAwb = CFstatus.ImageAwb;
-    CCstatus.ImageAwbGain = CFstatus.ImageAwbGain;
+
+    CCstatus.ImageQuality = CFstatus.ImageQuality;
+
+    CCstatus.ImageGainceiling = CFstatus.ImageGainceiling;
+
+    CCstatus.ImageAgc = CFstatus.ImageAgc;
     CCstatus.ImageAec = CFstatus.ImageAec;
+    CCstatus.ImageHmirror = CFstatus.ImageHmirror;
+    CCstatus.ImageVflip = CFstatus.ImageVflip;
+
+    CCstatus.ImageAwb = CFstatus.ImageAwb;
     CCstatus.ImageAec2 = CFstatus.ImageAec2;
-    CCstatus.ImageAeLevel = CFstatus.ImageAeLevel;
     CCstatus.ImageAecValue = CFstatus.ImageAecValue;
-    CCstatus.ImageAgc = CFstatus.ImageAgc;
-    CCstatus.ImageAgcGain = CFstatus.ImageAgcGain;
+    CCstatus.ImageSpecialEffect = CFstatus.ImageSpecialEffect;
+    CCstatus.ImageWbMode = CFstatus.ImageWbMode;
+    CCstatus.ImageAeLevel = CFstatus.ImageAeLevel;
+
+    CCstatus.ImageDcw = CFstatus.ImageDcw;
     CCstatus.ImageBpc = CFstatus.ImageBpc;
     CCstatus.ImageWpc = CFstatus.ImageWpc;
+    CCstatus.ImageAwbGain = CFstatus.ImageAwbGain;
+    CCstatus.ImageAgcGain = CFstatus.ImageAgcGain;
+
     CCstatus.ImageRawGma = CFstatus.ImageRawGma;
     CCstatus.ImageLenc = CFstatus.ImageLenc;
-    CCstatus.ImageSpecialEffect = CFstatus.ImageSpecialEffect;
-    CCstatus.ImageHmirror = CFstatus.ImageHmirror;
-    CCstatus.ImageVflip = CFstatus.ImageVflip;
-    CCstatus.ImageDcw = CFstatus.ImageDcw;
+
+    CCstatus.ImageSharpness = CFstatus.ImageSharpness;
+    CCstatus.ImageAutoSharpness = CFstatus.ImageAutoSharpness;
+
     CCstatus.ImageDenoiseLevel = CFstatus.ImageDenoiseLevel;
 
     CCstatus.ImageLedIntensity = CFstatus.ImageLedIntensity;
@@ -238,43 +254,43 @@ esp_err_t setCFstatusToCam(void)
     if (s != NULL)
     {
         s->set_framesize(s, CFstatus.ImageFrameSize);
-        s->set_quality(s, CFstatus.ImageQuality); // 0 - 63
 
-        s->set_brightness(s, CFstatus.ImageBrightness); // -2 to 2
-        s->set_contrast(s, CFstatus.ImageContrast);     // -2 to 2
+        // s->set_contrast(s, CFstatus.ImageContrast);     // -2 to 2
+        // s->set_brightness(s, CFstatus.ImageBrightness); // -2 to 2
+        Camera.SetCamContrastBrightness(s, CFstatus.ImageContrast, CFstatus.ImageBrightness);
+		
         s->set_saturation(s, CFstatus.ImageSaturation); // -2 to 2
-        // s->set_sharpness(s, CFstatus.ImageSharpness);   // auto-sharpness is not officially supported, default to 0
-        Camera.SetCamSharpness(CFstatus.ImageAutoSharpness, CFstatus.ImageSharpness);
-
-        s->set_denoise(s, CFstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
 
-        s->set_special_effect(s, CFstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
-        s->set_wb_mode(s, CFstatus.ImageWbMode);               // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
-
-        s->set_ae_level(s, CFstatus.ImageAeLevel);   // -2 to 2
-        s->set_aec_value(s, CFstatus.ImageAecValue); // 0 to 1200
-        s->set_agc_gain(s, CFstatus.ImageAgcGain);   // 0 to 30
+        s->set_quality(s, CFstatus.ImageQuality); // 0 - 63
 
         // s->set_gainceiling(s, CFstatus.ImageGainceiling); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
-        Camera.ov5640_set_gainceiling(s, CFstatus.ImageGainceiling);
+        Camera.SetCamGainceiling(s, CFstatus.ImageGainceiling);
 
-        s->set_lenc(s, CFstatus.ImageLenc);         // 0 = disable , 1 = enable
         s->set_gain_ctrl(s, CFstatus.ImageAgc);     // 0 = disable , 1 = enable
         s->set_exposure_ctrl(s, CFstatus.ImageAec); // 0 = disable , 1 = enable
+        s->set_hmirror(s, CFstatus.ImageHmirror);   // 0 = disable , 1 = enable
+        s->set_vflip(s, CFstatus.ImageVflip);       // 0 = disable , 1 = enable
 
-        s->set_hmirror(s, CFstatus.ImageHmirror); // 0 = disable , 1 = enable
-        s->set_vflip(s, CFstatus.ImageVflip);     // 0 = disable , 1 = enable
-        s->set_aec2(s, CFstatus.ImageAec2);       // 0 = disable , 1 = enable
-
-        s->set_bpc(s, CFstatus.ImageBpc); // 0 = disable , 1 = enable
-        s->set_wpc(s, CFstatus.ImageWpc); // 0 = disable , 1 = enable
+        s->set_whitebal(s, CFstatus.ImageAwb);       // 0 = disable , 1 = enable
+        s->set_aec2(s, CFstatus.ImageAec2);          // 0 = disable , 1 = enable
+        s->set_aec_value(s, CFstatus.ImageAecValue); // 0 to 1200
+        // s->set_special_effect(s, CFstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
+        Camera.SetCamSpecialEffect(s, CFstatus.ImageSpecialEffect);
+        s->set_wb_mode(s, CFstatus.ImageWbMode);   // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
+        s->set_ae_level(s, CFstatus.ImageAeLevel); // -2 to 2
+
+        s->set_dcw(s, CFstatus.ImageDcw);          // 0 = disable , 1 = enable
+        s->set_bpc(s, CFstatus.ImageBpc);          // 0 = disable , 1 = enable
+        s->set_wpc(s, CFstatus.ImageWpc);          // 0 = disable , 1 = enable
+        s->set_awb_gain(s, CFstatus.ImageAwbGain); // 0 = disable , 1 = enable
+        s->set_agc_gain(s, CFstatus.ImageAgcGain); // 0 to 30
 
         s->set_raw_gma(s, CFstatus.ImageRawGma); // 0 = disable , 1 = enable
+        s->set_lenc(s, CFstatus.ImageLenc);      // 0 = disable , 1 = enable
 
-        s->set_awb_gain(s, CFstatus.ImageAwbGain); // 0 = disable , 1 = enable
-        s->set_whitebal(s, CFstatus.ImageAwb);     // 0 = disable , 1 = enable
-
-        s->set_dcw(s, CFstatus.ImageDcw); // 0 = disable , 1 = enable
+        // s->set_sharpness(s, CFstatus.ImageSharpness);   // auto-sharpness is not officially supported, default to 0
+        Camera.SetCamSharpness(CFstatus.ImageAutoSharpness, CFstatus.ImageSharpness);
+        s->set_denoise(s, CFstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
 
         TickType_t xDelay2 = 100 / portTICK_PERIOD_MS;
         vTaskDelay(xDelay2);