Skip to content

[AE-2] Add zoom, flip, and mirror functionality for GC2145 #689

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
May 26, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/compile-examples.yml
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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)
@@ -60,7 +66,7 @@ void setup() {

void loop() {
if(!Serial) {
Serial.begin(921600);
Serial.begin(115200);
while(!Serial);
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* 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_STEP and ZOOM_Y_STEP).
*
* 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
#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 // Zoom in from the highest supported resolution
#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_STEP = 100;
constexpr uint16_t ZOOM_Y_STEP = 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_STEP;

if(currentZoomX > maxZoomX){
currentZoomX = 0;
currentZoomY += ZOOM_Y_STEP;
if(currentZoomY > maxZoomY){
currentZoomY = 0;
}
}
cam.zoomTo(ZOOM_WINDOW_RESOLUTION, currentZoomX, currentZoomY);
}

}
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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;
95 changes: 90 additions & 5 deletions libraries/Camera/src/camera.cpp
Original file line number Diff line number Diff line change
@@ -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,36 +505,120 @@ 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
* @param XSize DCMI Pixel per line
* @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->setResolutionWithZoom(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_enable)
{
return (this->sensor->setVerticalFlip(flip_enable));
}

int Camera::setHorizontalMirror(bool mirror_enable)
{
return (this->sensor->setHorizontalMirror(mirror_enable));
}

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) {
102 changes: 100 additions & 2 deletions libraries/Camera/src/camera.h
Original file line number Diff line number Diff line change
@@ -210,6 +210,18 @@ 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 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;
@@ -276,12 +288,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_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;

/**
@@ -370,13 +383,16 @@ 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
ScanResults<uint8_t> i2cScan(); /// Perform an I2C scan
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:
/**
@@ -522,6 +538,88 @@ class Camera {
*/
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();

/**
* @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.
68 changes: 67 additions & 1 deletion libraries/GC2145/gc2145.cpp
Original file line number Diff line number Diff line change
@@ -763,7 +763,36 @@ int GC2145::setFrameRate(int32_t framerate)
return 0;
}

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_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_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_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_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_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);
}

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;

@@ -809,6 +838,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 +887,6 @@ int GC2145::setResolution(int32_t resolution)
ret |= regWrite(GC2145_I2C_ADDR, 0x9A, 0x0E);

return ret;

}

int GC2145::setPixelFormat(int32_t pixformat)
7 changes: 6 additions & 1 deletion libraries/GC2145/gc2145.h
Original file line number Diff line number Diff line change
@@ -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,14 +39,17 @@ class GC2145: public ImageSensor {
bool getMono() { return false; };
uint32_t getClockFrequency() { return 12000000; };
int setFrameRate(int32_t framerate);
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; };
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_enable);
int setHorizontalMirror(bool mirror_enable);
void debug(Stream &stream);
};

#endif /* __GC2145_H */
20 changes: 20 additions & 0 deletions libraries/Himax_HM01B0/himax.cpp
Original file line number Diff line number Diff line change
@@ -341,10 +341,30 @@ int HM01B0::reset()
return (max_timeout > 0) ? 0 : -1;
}

int HM01B0::setVerticalFlip(bool flip_enable)
{
return -1;
}

int HM01B0::setHorizontalMirror(bool mirror_enable)
{
return -1;
}

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;

if (resolution != zoom_resolution)
{
return -1;
}

switch (resolution) {
case CAMERA_R160x120:
for(uint32_t i = 0; himax_qqvga_regs[i][0]; i++) {
3 changes: 3 additions & 0 deletions libraries/Himax_HM01B0/himax.h
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ class HM01B0: public ImageSensor {
bool getMono() { return true; };
uint32_t getClockFrequency() { return 6000000; };
int setFrameRate(int32_t framerate);
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;
@@ -50,6 +51,8 @@ class HM01B0: public ImageSensor {
int motionDetected();
int pollMotionDetection();
int clearMotionDetection();
int setVerticalFlip(bool flip_enable);
int setHorizontalMirror(bool mirror_enable);

uint8_t printRegs();
void debug(Stream &stream);
20 changes: 20 additions & 0 deletions libraries/Himax_HM0360/hm0360.cpp
Original file line number Diff line number Diff line change
@@ -586,10 +586,30 @@ int HM0360::reset()
return (max_timeout > 0) ? 0 : -1;
}

int HM0360::setVerticalFlip(bool flip_enable)
{
return -1;
}

int HM0360::setHorizontalMirror(bool mirror_enable)
{
return -1;
}

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;

if (resolution != zoom_resolution)
{
return -1;
}

switch (resolution) {
case CAMERA_R160x120:
for(uint32_t i = 0; himax_qqvga_regs[i][0]; i++) {
3 changes: 3 additions & 0 deletions libraries/Himax_HM0360/hm0360.h
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@ class HM0360: public ImageSensor {
bool getMono() { return true; };
uint32_t getClockFrequency() { return 24000000; };
int setFrameRate(int32_t framerate);
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;
@@ -50,6 +51,8 @@ class HM0360: public ImageSensor {
int motionDetected();
int pollMotionDetection();
int clearMotionDetection();
int setVerticalFlip(bool flip_enable);
int setHorizontalMirror(bool mirror_enable);

uint8_t printRegs();
void debug(Stream &stream);
20 changes: 20 additions & 0 deletions libraries/OV7670/ov7670.cpp
Original file line number Diff line number Diff line change
@@ -697,12 +697,32 @@ int OV7670::setFrameRate(int32_t framerate)
return 0;
}

int OV7670::setVerticalFlip(bool flip_enable)
{
return -1;
}

int OV7670::setHorizontalMirror(bool mirror_enable)
{
return -1;
}

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;

const uint8_t (*regs)[2];

if (resolution != zoom_resolution)
{
return -1;
}

switch (resolution) {
case CAMERA_R640x480:
regs = vga_regs;
3 changes: 3 additions & 0 deletions libraries/OV7670/ov767x.h
Original file line number Diff line number Diff line change
@@ -45,13 +45,16 @@ class OV7670: public ImageSensor {
bool getMono() { return false; };
uint32_t getClockFrequency() { return 12000000; };
int setFrameRate(int32_t framerate);
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; };
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_enable);
int setHorizontalMirror(bool mirror_enable);
void debug(Stream &stream);
};