From 4a46b5879b8ceb221a8614de5f5f27912dd084ca Mon Sep 17 00:00:00 2001 From: Alrik Vidstrom Date: Wed, 29 Mar 2023 18:18:52 +0200 Subject: [PATCH 01/12] Add zoom, flip, and mirror functionality Adds the functions zoomTo(), zoomToCenter(), setVerticalFlip(), setHorizontalMirror(), getResolutionWidth(), and getResolutionHeight() to the Camera library. The old setResolution() function is changed into the new private function setResolutionWithZoom(), which is called by the new version of setResolution(), as well as by the zoomTo() and zoomToCenter() functions. These changes required some changes in the abstract class ImageSensor, which, in turn, required further changes in the camera drivers. The only camera driver that fully supports the new functionality is GC2145, and the others return -1 on all calls. The function signature for setResolution() is changed, and two new functions are added: setVerticalFlip() and setHorizontalMirror(). --- libraries/Camera/src/camera.cpp | 95 +++++++++++++++++++++++++++++-- libraries/Camera/src/camera.h | 20 ++++++- libraries/GC2145/gc2145.cpp | 65 ++++++++++++++++++++- libraries/GC2145/gc2145.h | 6 +- libraries/Himax_HM01B0/himax.cpp | 17 +++++- libraries/Himax_HM01B0/himax.h | 4 +- libraries/Himax_HM0360/hm0360.cpp | 17 +++++- libraries/Himax_HM0360/hm0360.h | 4 +- libraries/OV7670/ov7670.cpp | 17 +++++- libraries/OV7670/ov767x.h | 4 +- 10 files changed, 233 insertions(+), 16 deletions(-) diff --git a/libraries/Camera/src/camera.cpp b/libraries/Camera/src/camera.cpp index 82a679755..1ec4c4b54 100644 --- a/libraries/Camera/src/camera.cpp +++ b/libraries/Camera/src/camera.cpp @@ -137,6 +137,7 @@ const uint32_t restab[CAMERA_RMAX][2] = { {320, 240 }, // QVGA {320, 320 }, {640, 480 }, // VGA + {0, 0 }, // Empty entry because there's a jump in the resolution enum initializers {800, 600 }, // SVGA {1600, 1200}, // UXGA }; @@ -504,13 +505,32 @@ int Camera::setFrameRate(int32_t framerate) return -1; } -int Camera::setResolution(int32_t resolution) +int Camera::setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, int32_t zoom_x, int32_t zoom_y) { if (this->sensor == NULL || resolution >= CAMERA_RMAX || pixformat >= CAMERA_PMAX || pixformat == -1) { return -1; } + // resolution = the full resolution to set the camera to + // zoom_resolution = the resolution to crop to when zooming (set equal to resolution for no zoom) + // final_resolution = the resolution to crop to (depends on zoom or not) + int32_t final_resolution; + // Check if zooming is asked for + if (resolution != zoom_resolution) + { + // Can't zoom into a larger window than the original + if (zoom_resolution > resolution) + { + return -1; + } + final_resolution = zoom_resolution; + } + else + { + final_resolution = resolution; + } + /* * @param X0 DCMI window X offset * @param Y0 DCMI window Y offset @@ -518,22 +538,87 @@ int Camera::setResolution(int32_t resolution) * @param YSize DCMI Line number */ HAL_DCMI_EnableCROP(&hdcmi); - uint32_t bpl = restab[resolution][0]; + uint32_t bpl = restab[final_resolution][0]; if (pixformat == CAMERA_RGB565 || (pixformat == CAMERA_GRAYSCALE && !this->sensor->getMono())) { // If the pixel format is Grayscale and sensor is Not monochrome, // the actual pixel format will be YUV (i.e 2 bytes per pixel). bpl *= 2; } - HAL_DCMI_ConfigCROP(&hdcmi, 0, 0, bpl - 1, restab[resolution][1] - 1); + HAL_DCMI_ConfigCROP(&hdcmi, 0, 0, bpl - 1, restab[final_resolution][1] - 1); - if (this->sensor->setResolution(resolution) == 0) { - this->resolution = resolution; + if (this->sensor->setResolution(resolution, zoom_resolution, zoom_x, zoom_y) == 0) { + this->resolution = final_resolution; return 0; } return -1; } +int Camera::setResolution(int32_t resolution) +{ + // Check for resolutions that would cause out-of-bounds indexing of restab + // This check is here because original_resolution will be trusted in all other code + if ((resolution < 0) || (resolution >= CAMERA_RMAX)) + { + return -1; + } + original_resolution = resolution; + return setResolutionWithZoom(resolution, resolution, 0, 0); +} + +int Camera::zoomTo(int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) +{ + // Check for zoom resolutions that would cause out-of-bounds indexing of restab + if ((zoom_resolution < 0) || (zoom_resolution >= CAMERA_RMAX)) + { + return -1; + } + // Check if the zoom window goes outside the frame on the x axis + // Notice that this form prevents uint32_t wraparound, so don't change it + if (zoom_x >= (restab[this->original_resolution][0]) - (restab[zoom_resolution][0])) + { + return -1; + } + // Check if the zoom window goes outside the frame on the y axis + // Notice that this form prevents uint32_t wraparound, so don't change it + if (zoom_y >= (restab[this->original_resolution][1]) - (restab[zoom_resolution][1])) + { + return -1; + } + return setResolutionWithZoom(this->original_resolution, zoom_resolution, zoom_x, zoom_y); +} + +int Camera::zoomToCenter(int32_t zoom_resolution) +{ + // Check for zoom resolutions that would cause out-of-bounds indexing of restab + if ((zoom_resolution < 0) || (zoom_resolution >= CAMERA_RMAX)) + { + return -1; + } + uint32_t zoom_x = (restab[this->original_resolution][0] - restab[zoom_resolution][0]) / 2; + uint32_t zoom_y = (restab[this->original_resolution][1] - restab[zoom_resolution][1]) / 2; + return setResolutionWithZoom(this->original_resolution, zoom_resolution, zoom_x, zoom_y); +} + +int Camera::setVerticalFlip(bool flip_mode) +{ + return (this->sensor->setVerticalFlip(flip_mode)); +} + +int Camera::setHorizontalMirror(bool mirror_mode) +{ + return (this->sensor->setHorizontalMirror(mirror_mode)); +} + +uint32_t Camera::getResolutionWidth() +{ + return (restab[this->original_resolution][0]); +} +uint32_t Camera::getResolutionHeight() +{ + return (restab[this->original_resolution][1]); +} + int Camera::setPixelFormat(int32_t pixformat) { if (this->sensor == NULL || pixformat >= CAMERA_PMAX) { diff --git a/libraries/Camera/src/camera.h b/libraries/Camera/src/camera.h index 1e5872daa..54c4442ec 100644 --- a/libraries/Camera/src/camera.h +++ b/libraries/Camera/src/camera.h @@ -210,9 +210,12 @@ class ImageSensor { * @brief Set the resolution of the image sensor. * @note This has no effect on cameras that do not support variable resolutions. * @param resolution The desired resolution, as defined in the resolution enum + * @param zoom_resolution The desired zoom window size. + * @param zoom_x The desired x position of the zoom window. + * @param zoom_y The desired y position of the zoom window. * @return int 0 on success, non-zero on failure */ - virtual int setResolution(int32_t resolution) = 0; + virtual int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) = 0; /** * @brief Set the pixel (color) format of the image sensor. @@ -277,11 +280,15 @@ class ImageSensor { */ virtual int motionDetected() = 0; + virtual int setVerticalFlip(bool flip_mode) = 0; + virtual int setHorizontalMirror(bool flip_mode) = 0; + + /** * @brief Output debug information to a stream. * You can use this function to output debug information to the serial port by passing Serial as the stream. * @param stream Stream to output the debug information - */ + */ virtual void debug(Stream &stream) = 0; /** @@ -370,6 +377,7 @@ class Camera { private: int32_t pixformat; /// Pixel format int32_t resolution; /// Camera resolution + int32_t original_resolution; /// The resolution originally set through setResolution() int32_t framerate; /// Frame rate ImageSensor *sensor; /// Pointer to the camera sensor int reset(); /// Reset the camera @@ -377,6 +385,8 @@ class Camera { Stream *_debug; /// Pointer to the debug stream arduino::MbedI2C *_i2c; /// Pointer to the I2C interface FrameBuffer *_framebuffer; /// Pointer to the frame buffer + int setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, int32_t zoom_x, int32_t zoom_y); + public: /** @@ -521,6 +531,12 @@ class Camera { * @return int 0 if no motion is detected, non-zero if motion is detected */ int motionDetected(); + int zoomTo(int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int zoomToCenter(int32_t zoom_resolution); + int setVerticalFlip(bool flip_mode); + int setHorizontalMirror(bool mirror_mode); + uint32_t getResolutionWidth(); + uint32_t getResolutionHeight(); /** * @brief Output debug information to a stream. diff --git a/libraries/GC2145/gc2145.cpp b/libraries/GC2145/gc2145.cpp index 435621618..848568010 100644 --- a/libraries/GC2145/gc2145.cpp +++ b/libraries/GC2145/gc2145.cpp @@ -763,7 +763,31 @@ int GC2145::setFrameRate(int32_t framerate) return 0; } -int GC2145::setResolution(int32_t resolution) +int GC2145::setVerticalFlip(bool flip_mode) +{ + // The GC2145 doesn't return this value when reading the Analog mode 1 register + // so we have to save it for setHorizontalMirror() + vertical_flip_state = flip_mode; + // Using the Analog mode 1 register (0x17) + uint8_t old_value = regRead(GC2145_I2C_ADDR, 0x17); + int retVal = regWrite(GC2145_I2C_ADDR, 0x17, (old_value & 0b11111100) | (flip_mode << 1) | horizontal_mirror_state); + // Notice that the error codes from regWrite() are positive ones passed on from Wire, not -1 + return ((0 == retVal) ? 0 : -1); +} + +int GC2145::setHorizontalMirror(bool mirror_mode) +{ + // The GC2145 doesn't return this value when reading the Analog mode 1 register + // so we have to save it for setVerticalFlip() + horizontal_mirror_state = mirror_mode; + // Using the Analog mode 1 register (0x17) + uint8_t old_value = regRead(GC2145_I2C_ADDR, 0x17); + int retVal = regWrite(GC2145_I2C_ADDR, 0x17, (old_value & 0b11111100) | mirror_mode | (vertical_flip_state << 1)); + // Notice that the error codes from regWrite() are positive ones passed on from Wire, not -1 + return ((0 == retVal) ? 0 : -1); +} + +int GC2145::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; @@ -809,6 +833,44 @@ int GC2145::setResolution(int32_t resolution) // Set readout window first. ret |= setWindow(0x09, win_x, win_y, win_w + 16, win_h + 8); + // Zoom mode active + if (resolution != zoom_resolution) + { + // Can't zoom into a larger window than the original + if (zoom_resolution > resolution) + { + return -1; + } + + // The zoom resolution constant is outside of the allowed range + if ((zoom_resolution < 0) || (zoom_resolution >= CAMERA_RMAX)) + { + return -1; + } + + uint32_t zoom_w = restab[zoom_resolution][0]; + uint32_t zoom_h = restab[zoom_resolution][1]; + + // Check if the zoom window goes outside the frame on the x axis + // Notice that this form prevents uint32_t wraparound, so don't change it + if (zoom_x >= (w - zoom_w)) + { + return -1; + } + // Check of the zoom window goes outside the frame on the y axis + // Notice that this form prevents uint32_t wraparound, so don't change it + if (zoom_y >= (h - zoom_h)) + { + return -1; + } + + // Set the cropping window parameters to the zoom window parameters + x = zoom_x; + y = zoom_y; + w = zoom_w; + h = zoom_h; + } + // Set cropping window next. ret |= setWindow(0x91, x, y, w, h); @@ -820,7 +882,6 @@ int GC2145::setResolution(int32_t resolution) ret |= regWrite(GC2145_I2C_ADDR, 0x9A, 0x0E); return ret; - } int GC2145::setPixelFormat(int32_t pixformat) diff --git a/libraries/GC2145/gc2145.h b/libraries/GC2145/gc2145.h index dce65b33b..3db372343 100644 --- a/libraries/GC2145/gc2145.h +++ b/libraries/GC2145/gc2145.h @@ -28,6 +28,8 @@ class GC2145: public ImageSensor { arduino::MbedI2C *_i2c; int regWrite(uint8_t dev_addr, uint16_t reg_addr, uint8_t reg_data, bool wide_addr = false); uint8_t regRead(uint8_t dev_addr, uint16_t reg_addr, bool wide_addr = false); + bool vertical_flip_state = false; + bool horizontal_mirror_state = false; public: GC2145(arduino::MbedI2C &i2c = CameraWire); @@ -37,13 +39,15 @@ class GC2145: public ImageSensor { bool getMono() { return false; }; uint32_t getClockFrequency() { return 12000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution); + int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); int setPixelFormat(int32_t pixformat); int enableMotionDetection(md_callback_t callback) { return 0; }; int disableMotionDetection() { return 0; }; int setMotionDetectionWindow(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { return 0; }; int setMotionDetectionThreshold(uint32_t threshold) { return 0; }; int motionDetected() { return 0; }; + int setVerticalFlip(bool flip_mode); + int setHorizontalMirror(bool mirror_mode); void debug(Stream &stream); }; diff --git a/libraries/Himax_HM01B0/himax.cpp b/libraries/Himax_HM01B0/himax.cpp index ee27b452b..a1bf4a97c 100644 --- a/libraries/Himax_HM01B0/himax.cpp +++ b/libraries/Himax_HM01B0/himax.cpp @@ -341,10 +341,25 @@ int HM01B0::reset() return (max_timeout > 0) ? 0 : -1; } -int HM01B0::setResolution(int32_t resolution) +int HM01B0::setVerticalFlip(bool flip_mode) +{ + return -1; +} + +int HM01B0::setHorizontalMirror(bool mirror_mode) +{ + return -1; +} + +int HM01B0::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; + if (resolution != zoom_resolution) + { + return -1; + } + switch (resolution) { case CAMERA_R160x120: for(uint32_t i = 0; himax_qqvga_regs[i][0]; i++) { diff --git a/libraries/Himax_HM01B0/himax.h b/libraries/Himax_HM01B0/himax.h index 38695d9b5..4de16a712 100644 --- a/libraries/Himax_HM01B0/himax.h +++ b/libraries/Himax_HM01B0/himax.h @@ -40,7 +40,7 @@ class HM01B0: public ImageSensor { bool getMono() { return true; }; uint32_t getClockFrequency() { return 6000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution); + int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); int setPixelFormat(int32_t pixformat); int setTestPattern(bool enable, bool walking) override; int enableMotionDetection(md_callback_t callback=NULL); @@ -50,6 +50,8 @@ class HM01B0: public ImageSensor { int motionDetected(); int pollMotionDetection(); int clearMotionDetection(); + int setVerticalFlip(bool flip_mode); + int setHorizontalMirror(bool mirror_mode); uint8_t printRegs(); void debug(Stream &stream); diff --git a/libraries/Himax_HM0360/hm0360.cpp b/libraries/Himax_HM0360/hm0360.cpp index 8cd0b3703..9a9372167 100644 --- a/libraries/Himax_HM0360/hm0360.cpp +++ b/libraries/Himax_HM0360/hm0360.cpp @@ -586,10 +586,25 @@ int HM0360::reset() return (max_timeout > 0) ? 0 : -1; } -int HM0360::setResolution(int32_t resolution) +int HM0360::setVerticalFlip(bool flip_mode) +{ + return -1; +} + +int HM0360::setHorizontalMirror(bool mirror_mode) +{ + return -1; +} + +int HM0360::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; + if (resolution != zoom_resolution) + { + return -1; + } + switch (resolution) { case CAMERA_R160x120: for(uint32_t i = 0; himax_qqvga_regs[i][0]; i++) { diff --git a/libraries/Himax_HM0360/hm0360.h b/libraries/Himax_HM0360/hm0360.h index 5745bc101..54f456091 100644 --- a/libraries/Himax_HM0360/hm0360.h +++ b/libraries/Himax_HM0360/hm0360.h @@ -40,7 +40,7 @@ class HM0360: public ImageSensor { bool getMono() { return true; }; uint32_t getClockFrequency() { return 24000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution); + int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); int setPixelFormat(int32_t pixformat); int setTestPattern(bool enable, bool walking) override; int enableMotionDetection(md_callback_t callback=NULL); @@ -50,6 +50,8 @@ class HM0360: public ImageSensor { int motionDetected(); int pollMotionDetection(); int clearMotionDetection(); + int setVerticalFlip(bool flip_mode); + int setHorizontalMirror(bool mirror_mode); uint8_t printRegs(); void debug(Stream &stream); diff --git a/libraries/OV7670/ov7670.cpp b/libraries/OV7670/ov7670.cpp index d4e8f9fd4..1b55f55c0 100644 --- a/libraries/OV7670/ov7670.cpp +++ b/libraries/OV7670/ov7670.cpp @@ -697,12 +697,27 @@ int OV7670::setFrameRate(int32_t framerate) return 0; } -int OV7670::setResolution(int32_t resolution) +int OV7670::setVerticalFlip(bool flip_mode) +{ + return -1; +} + +int OV7670::setHorizontalMirror(bool mirror_mode) +{ + return -1; +} + +int OV7670::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; const uint8_t (*regs)[2]; + if (resolution != zoom_resolution) + { + return -1; + } + switch (resolution) { case CAMERA_R640x480: regs = vga_regs; diff --git a/libraries/OV7670/ov767x.h b/libraries/OV7670/ov767x.h index 60f89c025..06033986a 100644 --- a/libraries/OV7670/ov767x.h +++ b/libraries/OV7670/ov767x.h @@ -45,13 +45,15 @@ class OV7670: public ImageSensor { bool getMono() { return false; }; uint32_t getClockFrequency() { return 12000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution); + int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); int setPixelFormat(int32_t pixformat); int enableMotionDetection(md_callback_t callback) { return 0; }; int disableMotionDetection() { return 0; }; int setMotionDetectionWindow(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { return 0; }; int setMotionDetectionThreshold(uint32_t threshold) { return 0; }; int motionDetected() { return 0; }; + int setVerticalFlip(bool flip_mode); + int setHorizontalMirror(bool mirror_mode); void debug(Stream &stream); }; From a6a013adcdbe08d56594fd7d4ab50563fcf0e03a Mon Sep 17 00:00:00 2001 From: Alrik Vidstrom Date: Fri, 14 Apr 2023 13:14:20 +0200 Subject: [PATCH 02/12] Change parameter names for flipping and mirroring The parameter names are changed from _mode to _enable. --- libraries/Camera/src/camera.cpp | 8 ++++---- libraries/Camera/src/camera.h | 13 +++++-------- libraries/GC2145/gc2145.cpp | 12 ++++++------ libraries/GC2145/gc2145.h | 4 ++-- libraries/Himax_HM01B0/himax.cpp | 4 ++-- libraries/Himax_HM01B0/himax.h | 4 ++-- libraries/Himax_HM0360/hm0360.cpp | 4 ++-- libraries/Himax_HM0360/hm0360.h | 4 ++-- libraries/OV7670/ov7670.cpp | 4 ++-- libraries/OV7670/ov767x.h | 4 ++-- 10 files changed, 29 insertions(+), 32 deletions(-) diff --git a/libraries/Camera/src/camera.cpp b/libraries/Camera/src/camera.cpp index 1ec4c4b54..4968e3cc1 100644 --- a/libraries/Camera/src/camera.cpp +++ b/libraries/Camera/src/camera.cpp @@ -600,14 +600,14 @@ int Camera::zoomToCenter(int32_t zoom_resolution) return setResolutionWithZoom(this->original_resolution, zoom_resolution, zoom_x, zoom_y); } -int Camera::setVerticalFlip(bool flip_mode) +int Camera::setVerticalFlip(bool flip_enable) { - return (this->sensor->setVerticalFlip(flip_mode)); + return (this->sensor->setVerticalFlip(flip_enable)); } -int Camera::setHorizontalMirror(bool mirror_mode) +int Camera::setHorizontalMirror(bool mirror_enable) { - return (this->sensor->setHorizontalMirror(mirror_mode)); + return (this->sensor->setHorizontalMirror(mirror_enable)); } uint32_t Camera::getResolutionWidth() diff --git a/libraries/Camera/src/camera.h b/libraries/Camera/src/camera.h index 54c4442ec..d8db68b90 100644 --- a/libraries/Camera/src/camera.h +++ b/libraries/Camera/src/camera.h @@ -279,16 +279,13 @@ class ImageSensor { * @return int 0 if no motion is detected, non-zero if motion is detected */ virtual int motionDetected() = 0; - - virtual int setVerticalFlip(bool flip_mode) = 0; - virtual int setHorizontalMirror(bool flip_mode) = 0; - - + virtual int setVerticalFlip(bool flip_enable) = 0; + virtual int setHorizontalMirror(bool flip_enable) = 0; /** * @brief Output debug information to a stream. * You can use this function to output debug information to the serial port by passing Serial as the stream. * @param stream Stream to output the debug information - */ + */ virtual void debug(Stream &stream) = 0; /** @@ -533,8 +530,8 @@ class Camera { int motionDetected(); int zoomTo(int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); int zoomToCenter(int32_t zoom_resolution); - int setVerticalFlip(bool flip_mode); - int setHorizontalMirror(bool mirror_mode); + int setVerticalFlip(bool flip_enable); + int setHorizontalMirror(bool mirror_enable; uint32_t getResolutionWidth(); uint32_t getResolutionHeight(); diff --git a/libraries/GC2145/gc2145.cpp b/libraries/GC2145/gc2145.cpp index 848568010..f46262d0f 100644 --- a/libraries/GC2145/gc2145.cpp +++ b/libraries/GC2145/gc2145.cpp @@ -763,26 +763,26 @@ int GC2145::setFrameRate(int32_t framerate) return 0; } -int GC2145::setVerticalFlip(bool flip_mode) +int GC2145::setVerticalFlip(bool flip_enable) { // The GC2145 doesn't return this value when reading the Analog mode 1 register // so we have to save it for setHorizontalMirror() - vertical_flip_state = flip_mode; + vertical_flip_state = flip_enable; // Using the Analog mode 1 register (0x17) uint8_t old_value = regRead(GC2145_I2C_ADDR, 0x17); - int retVal = regWrite(GC2145_I2C_ADDR, 0x17, (old_value & 0b11111100) | (flip_mode << 1) | horizontal_mirror_state); + int retVal = regWrite(GC2145_I2C_ADDR, 0x17, (old_value & 0b11111100) | (flip_enable << 1) | horizontal_mirror_state); // Notice that the error codes from regWrite() are positive ones passed on from Wire, not -1 return ((0 == retVal) ? 0 : -1); } -int GC2145::setHorizontalMirror(bool mirror_mode) +int GC2145::setHorizontalMirror(bool mirror_enable) { // The GC2145 doesn't return this value when reading the Analog mode 1 register // so we have to save it for setVerticalFlip() - horizontal_mirror_state = mirror_mode; + horizontal_mirror_state = mirror_enable; // Using the Analog mode 1 register (0x17) uint8_t old_value = regRead(GC2145_I2C_ADDR, 0x17); - int retVal = regWrite(GC2145_I2C_ADDR, 0x17, (old_value & 0b11111100) | mirror_mode | (vertical_flip_state << 1)); + int retVal = regWrite(GC2145_I2C_ADDR, 0x17, (old_value & 0b11111100) | mirror_enable | (vertical_flip_state << 1)); // Notice that the error codes from regWrite() are positive ones passed on from Wire, not -1 return ((0 == retVal) ? 0 : -1); } diff --git a/libraries/GC2145/gc2145.h b/libraries/GC2145/gc2145.h index 3db372343..8a20b4694 100644 --- a/libraries/GC2145/gc2145.h +++ b/libraries/GC2145/gc2145.h @@ -46,8 +46,8 @@ class GC2145: public ImageSensor { int setMotionDetectionWindow(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { return 0; }; int setMotionDetectionThreshold(uint32_t threshold) { return 0; }; int motionDetected() { return 0; }; - int setVerticalFlip(bool flip_mode); - int setHorizontalMirror(bool mirror_mode); + int setVerticalFlip(bool flip_enable); + int setHorizontalMirror(bool mirror_enable); void debug(Stream &stream); }; diff --git a/libraries/Himax_HM01B0/himax.cpp b/libraries/Himax_HM01B0/himax.cpp index a1bf4a97c..182a4461a 100644 --- a/libraries/Himax_HM01B0/himax.cpp +++ b/libraries/Himax_HM01B0/himax.cpp @@ -341,12 +341,12 @@ int HM01B0::reset() return (max_timeout > 0) ? 0 : -1; } -int HM01B0::setVerticalFlip(bool flip_mode) +int HM01B0::setVerticalFlip(bool flip_enable) { return -1; } -int HM01B0::setHorizontalMirror(bool mirror_mode) +int HM01B0::setHorizontalMirror(bool mirror_enable) { return -1; } diff --git a/libraries/Himax_HM01B0/himax.h b/libraries/Himax_HM01B0/himax.h index 4de16a712..fd13a6f98 100644 --- a/libraries/Himax_HM01B0/himax.h +++ b/libraries/Himax_HM01B0/himax.h @@ -50,8 +50,8 @@ class HM01B0: public ImageSensor { int motionDetected(); int pollMotionDetection(); int clearMotionDetection(); - int setVerticalFlip(bool flip_mode); - int setHorizontalMirror(bool mirror_mode); + int setVerticalFlip(bool flip_enable); + int setHorizontalMirror(bool mirror_enable); uint8_t printRegs(); void debug(Stream &stream); diff --git a/libraries/Himax_HM0360/hm0360.cpp b/libraries/Himax_HM0360/hm0360.cpp index 9a9372167..f32ce4c8a 100644 --- a/libraries/Himax_HM0360/hm0360.cpp +++ b/libraries/Himax_HM0360/hm0360.cpp @@ -586,12 +586,12 @@ int HM0360::reset() return (max_timeout > 0) ? 0 : -1; } -int HM0360::setVerticalFlip(bool flip_mode) +int HM0360::setVerticalFlip(bool flip_enable) { return -1; } -int HM0360::setHorizontalMirror(bool mirror_mode) +int HM0360::setHorizontalMirror(bool mirror_enable) { return -1; } diff --git a/libraries/Himax_HM0360/hm0360.h b/libraries/Himax_HM0360/hm0360.h index 54f456091..e9a616a16 100644 --- a/libraries/Himax_HM0360/hm0360.h +++ b/libraries/Himax_HM0360/hm0360.h @@ -50,8 +50,8 @@ class HM0360: public ImageSensor { int motionDetected(); int pollMotionDetection(); int clearMotionDetection(); - int setVerticalFlip(bool flip_mode); - int setHorizontalMirror(bool mirror_mode); + int setVerticalFlip(bool flip_enable); + int setHorizontalMirror(bool mirror_enable); uint8_t printRegs(); void debug(Stream &stream); diff --git a/libraries/OV7670/ov7670.cpp b/libraries/OV7670/ov7670.cpp index 1b55f55c0..f5e97d6b7 100644 --- a/libraries/OV7670/ov7670.cpp +++ b/libraries/OV7670/ov7670.cpp @@ -697,12 +697,12 @@ int OV7670::setFrameRate(int32_t framerate) return 0; } -int OV7670::setVerticalFlip(bool flip_mode) +int OV7670::setVerticalFlip(bool flip_enable) { return -1; } -int OV7670::setHorizontalMirror(bool mirror_mode) +int OV7670::setHorizontalMirror(bool mirror_enable) { return -1; } diff --git a/libraries/OV7670/ov767x.h b/libraries/OV7670/ov767x.h index 06033986a..cf06cf30c 100644 --- a/libraries/OV7670/ov767x.h +++ b/libraries/OV7670/ov767x.h @@ -52,8 +52,8 @@ class OV7670: public ImageSensor { int setMotionDetectionWindow(uint32_t x, uint32_t y, uint32_t w, uint32_t h) { return 0; }; int setMotionDetectionThreshold(uint32_t threshold) { return 0; }; int motionDetected() { return 0; }; - int setVerticalFlip(bool flip_mode); - int setHorizontalMirror(bool mirror_mode); + int setVerticalFlip(bool flip_enable); + int setHorizontalMirror(bool mirror_enable); void debug(Stream &stream); }; From 36fd82bba8ddab781aa34e51c06214d72642ecec Mon Sep 17 00:00:00 2001 From: Alrik Vidstrom Date: Fri, 14 Apr 2023 13:36:53 +0200 Subject: [PATCH 03/12] Separate setResolutionWithZoom() and setResolution() Adds back the setResolution() function to the camera drivers by calling setResolutionWithZoom() with default parameters. --- libraries/Camera/src/camera.cpp | 2 +- libraries/Camera/src/camera.h | 6 ++++-- libraries/GC2145/gc2145.cpp | 7 ++++++- libraries/GC2145/gc2145.h | 5 +++-- libraries/Himax_HM01B0/himax.cpp | 7 ++++++- libraries/Himax_HM01B0/himax.h | 3 ++- libraries/Himax_HM0360/hm0360.cpp | 7 ++++++- libraries/Himax_HM0360/hm0360.h | 3 ++- libraries/OV7670/ov7670.cpp | 7 ++++++- libraries/OV7670/ov767x.h | 3 ++- 10 files changed, 38 insertions(+), 12 deletions(-) diff --git a/libraries/Camera/src/camera.cpp b/libraries/Camera/src/camera.cpp index 4968e3cc1..e82ddfe90 100644 --- a/libraries/Camera/src/camera.cpp +++ b/libraries/Camera/src/camera.cpp @@ -547,7 +547,7 @@ int Camera::setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, i } HAL_DCMI_ConfigCROP(&hdcmi, 0, 0, bpl - 1, restab[final_resolution][1] - 1); - if (this->sensor->setResolution(resolution, zoom_resolution, zoom_x, zoom_y) == 0) { + if (this->sensor->setResolutionWithZoom(resolution, zoom_resolution, zoom_x, zoom_y) == 0) { this->resolution = final_resolution; return 0; } diff --git a/libraries/Camera/src/camera.h b/libraries/Camera/src/camera.h index d8db68b90..fd477c93f 100644 --- a/libraries/Camera/src/camera.h +++ b/libraries/Camera/src/camera.h @@ -215,7 +215,9 @@ class ImageSensor { * @param zoom_y The desired y position of the zoom window. * @return int 0 on success, non-zero on failure */ - virtual int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) = 0; + virtual int setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) = 0; + + virtual int setResolution(int32_t resolution) = 0; /** * @brief Set the pixel (color) format of the image sensor. @@ -531,7 +533,7 @@ class Camera { int zoomTo(int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); int zoomToCenter(int32_t zoom_resolution); int setVerticalFlip(bool flip_enable); - int setHorizontalMirror(bool mirror_enable; + int setHorizontalMirror(bool mirror_enable); uint32_t getResolutionWidth(); uint32_t getResolutionHeight(); diff --git a/libraries/GC2145/gc2145.cpp b/libraries/GC2145/gc2145.cpp index f46262d0f..21ec73d31 100644 --- a/libraries/GC2145/gc2145.cpp +++ b/libraries/GC2145/gc2145.cpp @@ -787,7 +787,12 @@ int GC2145::setHorizontalMirror(bool mirror_enable) return ((0 == retVal) ? 0 : -1); } -int GC2145::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) +int GC2145::setResolution(int32_t resolution) +{ + setResolutionWithZoom(resolution, resolution, 0, 0); +} + +int GC2145::setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; diff --git a/libraries/GC2145/gc2145.h b/libraries/GC2145/gc2145.h index 8a20b4694..378a1b5f9 100644 --- a/libraries/GC2145/gc2145.h +++ b/libraries/GC2145/gc2145.h @@ -39,7 +39,8 @@ class GC2145: public ImageSensor { bool getMono() { return false; }; uint32_t getClockFrequency() { return 12000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolution(int32_t resolution); int setPixelFormat(int32_t pixformat); int enableMotionDetection(md_callback_t callback) { return 0; }; int disableMotionDetection() { return 0; }; @@ -50,5 +51,5 @@ class GC2145: public ImageSensor { int setHorizontalMirror(bool mirror_enable); void debug(Stream &stream); }; - + #endif /* __GC2145_H */ diff --git a/libraries/Himax_HM01B0/himax.cpp b/libraries/Himax_HM01B0/himax.cpp index 182a4461a..81833ed69 100644 --- a/libraries/Himax_HM01B0/himax.cpp +++ b/libraries/Himax_HM01B0/himax.cpp @@ -351,7 +351,12 @@ int HM01B0::setHorizontalMirror(bool mirror_enable) return -1; } -int HM01B0::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) +int HM01B0::setResolution(int32_t resolution) +{ + setResolutionWithZoom(resolution, resolution, 0, 0); +} + +int HM01B0::setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; diff --git a/libraries/Himax_HM01B0/himax.h b/libraries/Himax_HM01B0/himax.h index fd13a6f98..2aa365fa9 100644 --- a/libraries/Himax_HM01B0/himax.h +++ b/libraries/Himax_HM01B0/himax.h @@ -40,7 +40,8 @@ class HM01B0: public ImageSensor { bool getMono() { return true; }; uint32_t getClockFrequency() { return 6000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolution(int32_t resolution); int setPixelFormat(int32_t pixformat); int setTestPattern(bool enable, bool walking) override; int enableMotionDetection(md_callback_t callback=NULL); diff --git a/libraries/Himax_HM0360/hm0360.cpp b/libraries/Himax_HM0360/hm0360.cpp index f32ce4c8a..3924afcc9 100644 --- a/libraries/Himax_HM0360/hm0360.cpp +++ b/libraries/Himax_HM0360/hm0360.cpp @@ -596,7 +596,12 @@ int HM0360::setHorizontalMirror(bool mirror_enable) return -1; } -int HM0360::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) +int HM0360::setResolution(int32_t resolution) +{ + setResolutionWithZoom(resolution, resolution, 0, 0); +} + +int HM0360::setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; diff --git a/libraries/Himax_HM0360/hm0360.h b/libraries/Himax_HM0360/hm0360.h index e9a616a16..8a4946b80 100644 --- a/libraries/Himax_HM0360/hm0360.h +++ b/libraries/Himax_HM0360/hm0360.h @@ -40,7 +40,8 @@ class HM0360: public ImageSensor { bool getMono() { return true; }; uint32_t getClockFrequency() { return 24000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolution(int32_t resolution); int setPixelFormat(int32_t pixformat); int setTestPattern(bool enable, bool walking) override; int enableMotionDetection(md_callback_t callback=NULL); diff --git a/libraries/OV7670/ov7670.cpp b/libraries/OV7670/ov7670.cpp index f5e97d6b7..f6fd3255b 100644 --- a/libraries/OV7670/ov7670.cpp +++ b/libraries/OV7670/ov7670.cpp @@ -707,7 +707,12 @@ int OV7670::setHorizontalMirror(bool mirror_enable) return -1; } -int OV7670::setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) +int OV7670::setResolution(int32_t resolution) +{ + setResolutionWithZoom(resolution, resolution, 0, 0); +} + +int OV7670::setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) { int ret = 0; diff --git a/libraries/OV7670/ov767x.h b/libraries/OV7670/ov767x.h index cf06cf30c..2160de798 100644 --- a/libraries/OV7670/ov767x.h +++ b/libraries/OV7670/ov767x.h @@ -45,7 +45,8 @@ class OV7670: public ImageSensor { bool getMono() { return false; }; uint32_t getClockFrequency() { return 12000000; }; int setFrameRate(int32_t framerate); - int setResolution(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + int setResolution(int32_t resolution); int setPixelFormat(int32_t pixformat); int enableMotionDetection(md_callback_t callback) { return 0; }; int disableMotionDetection() { return 0; }; From 060ff9dd7799de26bcb16dc4354f6d6a21582d57 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Wed, 24 May 2023 17:54:15 +0200 Subject: [PATCH 04/12] camera: Add documentation for the zoom feature. --- libraries/Camera/src/camera.h | 76 +++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/libraries/Camera/src/camera.h b/libraries/Camera/src/camera.h index fd477c93f..4c31d5171 100644 --- a/libraries/Camera/src/camera.h +++ b/libraries/Camera/src/camera.h @@ -530,11 +530,87 @@ class Camera { * @return int 0 if no motion is detected, non-zero if motion is detected */ int motionDetected(); + + /** + * @brief Zoom to a specific region of the image by setting the zoom window size and its position. + * The camera resolution must be set to a higher resolution than the zoom resolution for this to work. + * The zooming is done by cropping a higher resolution image to the zoom window. + * @note This function is currently only supported by the GC2145 sensor on the Arduino Nicla Vision. + * @param zoom_resolution The resolution of the zoom window. + * The resolution must be one of the following: + * - CAMERA_R160x120 + * - CAMERA_R320x240 + * - CAMERA_R320x320 + * - CAMERA_R640x480 + * - CAMERA_R800x600 + * If the desired resolution doesn't fit in the built-in memory, + * the framebuffer should be allocated on external RAM. + * @param zoom_x The x position of the zoom window. + * The value must be lower or equal to the width of the image minus the width of the zoom window. + * @param zoom_y The y position of the zoom window. + * The value must be lower or equal to the height of the image minus the height of the zoom window. + * @return 0 on success, -1 on failure. + */ int zoomTo(int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y); + + /** + * @brief Zoom to the center of the image by setting the zoom window size. + * + * @param zoom_resolution The resolution of the zoom window. + * The resolution must be one of the following: + * - CAMERA_R160x120 + * - CAMERA_R320x240 + * - CAMERA_R320x320 + * - CAMERA_R640x480 + * - CAMERA_R800x600 + * If the desired resolution doesn't fit in the built-in memory, + * the framebuffer should be allocated on external RAM. + * @return 0 on success, -1 on failure. + */ int zoomToCenter(int32_t zoom_resolution); + + /** + * @brief Flips the camera image vertically. + * + * @param flip_enable Set to true to enable vertical flip, false to disable. + * @return 0 on success, -1 on failure. + */ int setVerticalFlip(bool flip_enable); + + /** + * @brief Mirrors the camera image horizontally. + * + * @param mirror_enable Set to true to enable horizontal mirror, false to disable. + * @return 0 on success, -1 on failure. + */ int setHorizontalMirror(bool mirror_enable); + + /** + * @brief Get the width of the current camera resolution. + * This can for example be used to calculate the zoom window position and size. + * In the following example, the camera is zoomed to the top right side of the image: + * @code + * // Calculate the zoom window position + * uint32_t max_zoom_x = camera.getResolutionWidth() - 320; + * // Zoom to the calculated position and size + * camera.zoomTo(CAMERA_R320x240, max_zoom_x, 0); + * @endcode + * @return uint32_t The width of the camera resolution. + */ uint32_t getResolutionWidth(); + + /** + * @brief Get the height of the current camera resolution. + * This can for example be used to calculate the zoom window position and size. + * In the following example, the camera is zoomed to the bottom left side of the image: + * @code + * // Calculate the zoom window position + * uint32_t max_zoom_y = camera.getResolutionHeight() - 240; + * // Zoom to the calculated position and size + * camera.zoomTo(CAMERA_R320x240, 0, max_zoom_y); + * @endcode + * @return uint32_t The height of the camera resolution. + */ uint32_t getResolutionHeight(); /** From 6deae7f0a0bbe10d8236509b3f9e15f1295a01ae Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 10:40:47 +0200 Subject: [PATCH 05/12] camera: Add missing documentation. --- libraries/Camera/src/camera.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libraries/Camera/src/camera.h b/libraries/Camera/src/camera.h index 4c31d5171..e7b2d77df 100644 --- a/libraries/Camera/src/camera.h +++ b/libraries/Camera/src/camera.h @@ -217,6 +217,13 @@ class ImageSensor { */ virtual int setResolutionWithZoom(int32_t resolution, int32_t zoom_resolution, uint32_t zoom_x, uint32_t zoom_y) = 0; + /** + * @brief Set the resolution of the image sensor. + * + * @note This has no effect on cameras that do not support variable resolutions. + * @param resolution The desired resolution, as defined in the resolution enum + * @return int 0 on success, non-zero on failure + */ virtual int setResolution(int32_t resolution) = 0; /** From 1632762f2621ff1d85584d75bd9efe02b46f5ef4 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 10:41:10 +0200 Subject: [PATCH 06/12] camera: Add example with zoom. --- .../CameraCaptureZoomPan.ino | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino diff --git a/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino b/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino new file mode 100644 index 000000000..0a6d291c3 --- /dev/null +++ b/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino @@ -0,0 +1,109 @@ +#include "camera.h" + +#ifndef ARDUINO_NICLA_VISION +#error "This sketch only works on Nicla Vision." +#endif + +#include "gc2145.h" +GC2145 galaxyCore; +Camera cam(galaxyCore); +#define IMAGE_MODE CAMERA_RGB565 + +#define CHUNK_SIZE 512 // Size of chunks in bytes +#define RESOLUTION CAMERA_R1600x1200 +#define ZOOM_WINDOW_RESOLUTION CAMERA_R320x240 + +constexpr uint16_t ZOOM_WINDOW_WIDTH = 320; +constexpr uint16_t ZOOM_WINDOW_HEIGHT = 240; +constexpr uint16_t ZOOM_X_STEPS = 100; +constexpr uint16_t ZOOM_Y_STEPS = 100; + +FrameBuffer frameBuffer; +uint32_t currentZoomX = 0; +uint32_t currentZoomY = 0; +uint32_t maxZoomX = 0; // Will be calculated in setup() +uint32_t maxZoomY = 0; // Will be calculated in setup() + + +void blinkLED(uint32_t count = 0xFFFFFFFF) +{ + pinMode(LED_BUILTIN, OUTPUT); + + while (count--) { + digitalWrite(LED_BUILTIN, LOW); // turn the LED on (HIGH is the voltage level) + delay(50); // wait for a second + digitalWrite(LED_BUILTIN, HIGH); // turn the LED off by making the voltage LOW + delay(50); // wait for a second + } +} + +void setup() { + // Init the cam QVGA, 30FPS + if (!cam.begin(RESOLUTION, IMAGE_MODE, 30)) { + blinkLED(); + } + + blinkLED(5); + + pinMode(LEDB, OUTPUT); + digitalWrite(LEDB, HIGH); + + // Flips the image vertically + cam.setVerticalFlip(true); + + // Mirrors the image horizontally + cam.setHorizontalMirror(true); + + // Calculate the max zoom window position + maxZoomX = cam.getResolutionWidth() - ZOOM_WINDOW_WIDTH; + maxZoomY = cam.getResolutionHeight() - ZOOM_WINDOW_HEIGHT; + + // Set the zoom window to 0,0 + cam.zoomTo(ZOOM_WINDOW_RESOLUTION, currentZoomX, currentZoomY); +} + +void sendFrame(){ + // Grab frame and write to serial + if (cam.grabFrame(frameBuffer, 3000) == 0) { + byte* buffer = frameBuffer.getBuffer(); + size_t bufferSize = cam.frameSize(); + digitalWrite(LEDB, LOW); + + // Split buffer into chunks + for(size_t i = 0; i < bufferSize; i += CHUNK_SIZE) { + size_t chunkSize = min(bufferSize - i, CHUNK_SIZE); + Serial.write(buffer + i, chunkSize); + Serial.flush(); + delay(1); // Small delay to allow the receiver to process the data + } + + digitalWrite(LEDB, HIGH); + } else { + blinkLED(20); + } +} + +void loop() { + if(!Serial) { + Serial.begin(115200); + while(!Serial); + } + + if(!Serial.available()) return; + byte request = Serial.read(); + + if(request == 1){ + sendFrame(); + currentZoomX += ZOOM_X_STEPS; + + if(currentZoomX > maxZoomX){ + currentZoomX = 0; + currentZoomY += ZOOM_Y_STEPS; + if(currentZoomY > maxZoomY){ + currentZoomY = 0; + } + } + cam.zoomTo(ZOOM_WINDOW_RESOLUTION, currentZoomX, currentZoomY); + } + +} From 5eda61d38dfdbcff8bd778d26e7604f52645bdf2 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 13:13:11 +0200 Subject: [PATCH 07/12] camera: Decrease baud rate for more stability. --- .../examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino | 2 +- .../CameraRawBytesVisualizer/CameraRawBytesVisualizer.pde | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino b/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino index 65458f26a..c6d618cd6 100644 --- a/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino +++ b/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino @@ -60,7 +60,7 @@ void setup() { void loop() { if(!Serial) { - Serial.begin(921600); + Serial.begin(115200); while(!Serial); } diff --git a/libraries/Camera/extras/CameraRawBytesVisualizer/CameraRawBytesVisualizer.pde b/libraries/Camera/extras/CameraRawBytesVisualizer/CameraRawBytesVisualizer.pde index 43427a142..e8e098b13 100644 --- a/libraries/Camera/extras/CameraRawBytesVisualizer/CameraRawBytesVisualizer.pde +++ b/libraries/Camera/extras/CameraRawBytesVisualizer/CameraRawBytesVisualizer.pde @@ -20,7 +20,7 @@ final int cameraHeight = 240; final boolean useGrayScale = true; // Must match the baud rate in the Arduino sketch -final int baudRate = 921600; +final int baudRate = 115200; final int cameraBytesPerPixel = useGrayScale ? 1 : 2; final int cameraPixelCount = cameraWidth * cameraHeight; From df134fd8409e021f0b84ec0ede1807e212a7e6de Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 13:18:32 +0200 Subject: [PATCH 08/12] camera: Add documentation to the zoom sketch. --- .../CameraCaptureZoomPan.ino | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino b/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino index 0a6d291c3..304ff9012 100644 --- a/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino +++ b/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino @@ -1,3 +1,20 @@ +/* + * This example shows how to use the Nicla Vision to capture images from the camera + * with a zoom window and send them over the serial port. + * The zoom window will move from left to right and top to bottom + * in the predefined steps of pixels (ZOOM_X_STEPS and ZOOM_Y_STEPS). + * + * Whenever the board sends a frame over the serial port, the blue LED will blink. + * + * Instructions: + * 1. Upload this sketch to Nicla Vision. + * 2. Open the CameraRawBytesVisualizer.pde Processing sketch and change `useGrayScale` to `false`. + * 3. Adjust the serial port in the Processing sketch to match the one used by Nicla Vision. + * 4. Run the Processing sketch. + * + * Initial author: Sebastian Romero @sebromero + */ + #include "camera.h" #ifndef ARDUINO_NICLA_VISION @@ -10,7 +27,7 @@ Camera cam(galaxyCore); #define IMAGE_MODE CAMERA_RGB565 #define CHUNK_SIZE 512 // Size of chunks in bytes -#define RESOLUTION CAMERA_R1600x1200 +#define RESOLUTION CAMERA_R1600x1200 // Zoom in from the highest supported resolution #define ZOOM_WINDOW_RESOLUTION CAMERA_R320x240 constexpr uint16_t ZOOM_WINDOW_WIDTH = 320; From 7c42b18883a8bab9ef1b28f60335b94cef327566 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 13:54:48 +0200 Subject: [PATCH 09/12] misc: Update sketch paths in GA. --- .github/workflows/compile-examples.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/compile-examples.yml b/.github/workflows/compile-examples.yml index ac94cd971..fc5c9e4c8 100644 --- a/.github/workflows/compile-examples.yml +++ b/.github/workflows/compile-examples.yml @@ -76,7 +76,8 @@ jobs: - libraries/doom - libraries/KernelDebug - libraries/MCUboot - - libraries/Camera/examples + - libraries/Camera/examples/CameraCaptureRawBytes + - libraries/Camera/examples/CameraMotionDetect - libraries/Portenta_lvgl/examples/Portenta_lvgl - libraries/Portenta_SDCARD - libraries/Portenta_SDRAM @@ -115,6 +116,7 @@ jobs: additional-sketch-paths: | - libraries/PDM - libraries/Camera/examples/CameraCaptureRawBytes + - libraries/Camera/examples/CameraCaptureZoomPan - libraries/SE05X - libraries/STM32H747_System - libraries/ThreadDebug From 936228d09d939d6edc1bb6e8cbfa2e74a1e07c6c Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 14:35:56 +0200 Subject: [PATCH 10/12] camera: Rename variable. --- .../CameraCaptureZoomPan/CameraCaptureZoomPan.ino | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino b/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino index 304ff9012..964897a6a 100644 --- a/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino +++ b/libraries/Camera/examples/CameraCaptureZoomPan/CameraCaptureZoomPan.ino @@ -2,7 +2,7 @@ * This example shows how to use the Nicla Vision to capture images from the camera * with a zoom window and send them over the serial port. * The zoom window will move from left to right and top to bottom - * in the predefined steps of pixels (ZOOM_X_STEPS and ZOOM_Y_STEPS). + * in the predefined steps of pixels (ZOOM_X_STEP and ZOOM_Y_STEP). * * Whenever the board sends a frame over the serial port, the blue LED will blink. * @@ -32,8 +32,8 @@ Camera cam(galaxyCore); constexpr uint16_t ZOOM_WINDOW_WIDTH = 320; constexpr uint16_t ZOOM_WINDOW_HEIGHT = 240; -constexpr uint16_t ZOOM_X_STEPS = 100; -constexpr uint16_t ZOOM_Y_STEPS = 100; +constexpr uint16_t ZOOM_X_STEP = 100; +constexpr uint16_t ZOOM_Y_STEP = 100; FrameBuffer frameBuffer; uint32_t currentZoomX = 0; @@ -111,11 +111,11 @@ void loop() { if(request == 1){ sendFrame(); - currentZoomX += ZOOM_X_STEPS; + currentZoomX += ZOOM_X_STEP; if(currentZoomX > maxZoomX){ currentZoomX = 0; - currentZoomY += ZOOM_Y_STEPS; + currentZoomY += ZOOM_Y_STEP; if(currentZoomY > maxZoomY){ currentZoomY = 0; } From 6b713cbd299b784b65c8bb623970dd8e00ddaccb Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 16:09:21 +0200 Subject: [PATCH 11/12] camera: Make HM0360 the default for the motion detection sketch. --- .../examples/CameraMotionDetect/CameraMotionDetect.ino | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libraries/Camera/examples/CameraMotionDetect/CameraMotionDetect.ino b/libraries/Camera/examples/CameraMotionDetect/CameraMotionDetect.ino index c920b0e0c..e0299c1e6 100644 --- a/libraries/Camera/examples/CameraMotionDetect/CameraMotionDetect.ino +++ b/libraries/Camera/examples/CameraMotionDetect/CameraMotionDetect.ino @@ -1,6 +1,12 @@ #include "camera.h" -#include "himax.h" -HM01B0 himax; + +// uncomment the correct camera in use +#include "hm0360.h" +HM0360 himax; + +// #include "himax.h" +// HM01B0 himax; + Camera cam(himax); #ifdef ARDUINO_NICLA_VISION From cb7ec8122ce4dd9ce28e419c98db32780ba90255 Mon Sep 17 00:00:00 2001 From: Sebastian Romero Date: Fri, 26 May 2023 16:10:37 +0200 Subject: [PATCH 12/12] camera: Add comment for using older camera on Vision Shield. --- .../CameraCaptureRawBytes/CameraCaptureRawBytes.ino | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino b/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino index c6d618cd6..a0ca20775 100644 --- a/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino +++ b/libraries/Camera/examples/CameraCaptureRawBytes/CameraCaptureRawBytes.ino @@ -6,8 +6,14 @@ Camera cam(galaxyCore); #define IMAGE_MODE CAMERA_RGB565 #elif defined(ARDUINO_PORTENTA_H7_M7) + // uncomment the correct camera in use #include "hm0360.h" HM0360 himax; + + // #include "himax.h" + // HM01B0 himax; + // Camera cam(himax); + Camera cam(himax); #define IMAGE_MODE CAMERA_GRAYSCALE #elif defined(ARDUINO_GIGA)