|
14 | 14 | * You should have received a copy of the GNU Lesser General Public License
|
15 | 15 | * along with this program. If not, see <https://www.gnu.org/licenses/>.
|
16 | 16 | *
|
17 |
| - * Camera driver. |
18 | 17 | */
|
| 18 | + |
| 19 | +/** |
| 20 | + * @file Camera.h |
| 21 | + * @brief Header file for the Arduino Camera library. |
| 22 | + * |
| 23 | + * This library allows capturing pixels from supported cameras on Arduino products. |
| 24 | + * Supported cameras: OV7670, Himax HM0360, and GC2145. |
| 25 | + * The pixels are returned in a frame buffer from which frames can be retrieved continuously. |
| 26 | + */ |
| 27 | + |
19 | 28 | #ifndef __CAMERA_H
|
20 | 29 | #define __CAMERA_H
|
21 | 30 | #include "Wire.h"
|
22 | 31 |
|
| 32 | +/// Camera I2C addresses |
23 | 33 | #define HM01B0_I2C_ADDR (0x24)
|
24 | 34 | #define HM0360_I2C_ADDR (0x24)
|
25 | 35 | #define GC2145_I2C_ADDR (0x3C)
|
26 | 36 |
|
| 37 | +/** |
| 38 | + * Camera pixel format enumeration |
| 39 | + * The different formats use different number of bits per pixel: |
| 40 | + * Grayscale (8-bit), Bayer (8-bit), RGB565 (16-bit) |
| 41 | + **/ |
27 | 42 | enum {
|
28 | 43 | CAMERA_GRAYSCALE = 0,
|
29 | 44 | CAMERA_BAYER = 1,
|
30 | 45 | CAMERA_RGB565 = 2,
|
31 |
| - CAMERA_PMAX |
| 46 | + CAMERA_PMAX /* Sentinel value */ |
32 | 47 | };
|
33 | 48 |
|
| 49 | +/// Camera resolution enumeration |
34 | 50 | enum {
|
35 | 51 | CAMERA_R160x120 = 0, /* QQVGA Resolution */
|
36 | 52 | CAMERA_R320x240 = 1, /* QVGA Resolution */
|
37 | 53 | CAMERA_R320x320 = 2, /* 320x320 Resolution */
|
38 | 54 | CAMERA_R640x480 = 3, /* VGA */
|
39 | 55 | CAMERA_R800x600 = 5, /* SVGA */
|
40 | 56 | CAMERA_R1600x1200 = 6, /* UXGA */
|
41 |
| - CAMERA_RMAX |
| 57 | + CAMERA_RMAX /* Sentinel value */ |
42 | 58 | };
|
43 | 59 |
|
44 | 60 | // Resolution table
|
45 | 61 | extern const uint32_t restab[CAMERA_RMAX][2];
|
46 | 62 |
|
| 63 | + |
| 64 | +/** |
| 65 | + * @class FrameBuffer |
| 66 | + * @brief Frame buffer class for storing captured frames. |
| 67 | + */ |
47 | 68 | class FrameBuffer {
|
48 | 69 | private:
|
49 |
| - int32_t _fb_size; |
50 |
| - uint8_t *_fb; |
51 |
| - bool _isAllocated; |
| 70 | + int32_t _fb_size; /// Frame buffer size in bytes |
| 71 | + uint8_t *_fb; /// Pointer to the frame buffer |
| 72 | + bool _isAllocated; /// Flag indicating if the buffer is allocated on the heap |
| 73 | + |
52 | 74 | public:
|
| 75 | + /** |
| 76 | + * @brief Construct a new FrameBuffer object with a fixed size. |
| 77 | + * |
| 78 | + * @param x Width of the frame buffer |
| 79 | + * @param y Height of the frame buffer |
| 80 | + * @param bpp Bits per pixel |
| 81 | + */ |
53 | 82 | FrameBuffer(int32_t x, int32_t y, int32_t bpp);
|
| 83 | + |
| 84 | + /** |
| 85 | + * @brief Construct a new FrameBuffer object with a given address. |
| 86 | + * This is useful if a resolution higher than 320x240 is required and external RAM shall be used. |
| 87 | + * In that case, the following code can be used: |
| 88 | + * |
| 89 | + * @code {.cpp} |
| 90 | + * #include "SDRAM.h" |
| 91 | + * FrameBuffer fb(SDRAM_START_ADDRESS); |
| 92 | + * ... |
| 93 | + * // In setup() add: |
| 94 | + * SDRAM.begin(); |
| 95 | + * @endcode |
| 96 | + * It can also be used to store the frame buffer in a different location in the RAM while avoiding the use of malloc(). |
| 97 | + * @param address The memory address of the frame buffer |
| 98 | + */ |
54 | 99 | FrameBuffer(int32_t address);
|
| 100 | + |
| 101 | + /** |
| 102 | + * @brief Construct a new FrameBuffer object with no custom size or address. |
| 103 | + */ |
55 | 104 | FrameBuffer();
|
| 105 | + |
| 106 | + /** |
| 107 | + * @brief Get the buffer size in bytes. |
| 108 | + * |
| 109 | + * @return uint32_t The buffer size in bytes |
| 110 | + */ |
56 | 111 | uint32_t getBufferSize();
|
| 112 | + |
| 113 | + /** |
| 114 | + * @brief Get a pointer to the frame buffer. |
| 115 | + * This can be used to read the pixels from the frame buffer. |
| 116 | + * E.g. to print all pixels to the serial monitor as hex values: |
| 117 | + * @code {.cpp} |
| 118 | + * uint8_t *fb = fb.getBuffer(); |
| 119 | + * for (int i = 0; i < fb.getBufferSize(); i++) { |
| 120 | + * Serial.print(fb[i], HEX); |
| 121 | + * Serial.print(" "); |
| 122 | + * } |
| 123 | + * @endcode |
| 124 | + * @return uint8_t* Pointer to the frame buffer |
| 125 | + */ |
57 | 126 | uint8_t* getBuffer();
|
| 127 | + |
| 128 | + /** |
| 129 | + * @brief Set the frame buffer pointer. |
| 130 | + * |
| 131 | + * @param buffer Pointer to the frame buffer |
| 132 | + */ |
58 | 133 | void setBuffer(uint8_t *buffer);
|
| 134 | + |
| 135 | + /** |
| 136 | + * @brief Check if the frame buffer has a fixed size. |
| 137 | + * This is the case if the frame buffer is constructed with a width, height, and bits per pixel. |
| 138 | + * @return true If the frame buffer has a fixed size |
| 139 | + * @return false Otherwise |
| 140 | + */ |
59 | 141 | bool hasFixedSize();
|
| 142 | + |
| 143 | + /** |
| 144 | + * @brief Check if the frame buffer is allocated on the heap. |
| 145 | + * |
| 146 | + * @return true If the frame buffer is allocated |
| 147 | + * @return false Otherwise |
| 148 | + */ |
60 | 149 | bool isAllocated();
|
61 | 150 | };
|
62 | 151 |
|
| 152 | +/// Function type definition for motion detection callbacks |
63 | 153 | typedef void (*md_callback_t)();
|
64 | 154 |
|
| 155 | + |
65 | 156 | class ImageSensor {
|
66 | 157 | public:
|
67 | 158 | virtual ~ImageSensor() { }
|
@@ -110,36 +201,164 @@ template <typename T> class ScanResults {
|
110 | 201 | int howMany = 0;
|
111 | 202 | };
|
112 | 203 |
|
| 204 | + |
| 205 | +/** |
| 206 | + * @class Camera |
| 207 | + * @brief The main class for controlling a camera using the provided ImageSensor. |
| 208 | + */ |
113 | 209 | class Camera {
|
114 | 210 | private:
|
115 |
| - int32_t pixformat; |
116 |
| - int32_t resolution; |
117 |
| - int32_t framerate; |
118 |
| - ImageSensor *sensor; |
119 |
| - int reset(); |
120 |
| - ScanResults<uint8_t> i2cScan(); |
121 |
| - Stream *_debug; |
122 |
| - arduino::MbedI2C *_i2c; |
123 |
| - FrameBuffer *_framebuffer; |
| 211 | + int32_t pixformat; /// Pixel format |
| 212 | + int32_t resolution; /// Camera resolution |
| 213 | + int32_t framerate; /// Frame rate |
| 214 | + ImageSensor *sensor; /// Pointer to the camera sensor |
| 215 | + int reset(); /// Reset the camera |
| 216 | + ScanResults<uint8_t> i2cScan(); /// Perform an I2C scan |
| 217 | + Stream *_debug; /// Pointer to the debug stream |
| 218 | + arduino::MbedI2C *_i2c; /// Pointer to the I2C interface |
| 219 | + FrameBuffer *_framebuffer; /// Pointer to the frame buffer |
| 220 | + |
124 | 221 | public:
|
| 222 | + /** |
| 223 | + * @brief Construct a new Camera object. |
| 224 | + * |
| 225 | + * @param sensor Reference to the ImageSensor object that is the driver for the camera sensor. |
| 226 | + */ |
125 | 227 | Camera(ImageSensor &sensor);
|
| 228 | + |
| 229 | + /** |
| 230 | + * @brief Initialize the camera. |
| 231 | + * |
| 232 | + * @param resolution Initial resolution (default: CAMERA_R320x240). Note that not all resolutions are supported by all cameras. |
| 233 | + * @param pixformat Initial pixel format (default: CAMERA_GRAYSCALE). Note that not all pixel formats are supported by all cameras. |
| 234 | + * @param framerate Initial frame rate (default: 30) |
| 235 | + * @return true If the camera is successfully initialized |
| 236 | + * @return false Otherwise |
| 237 | + */ |
126 | 238 | bool begin(int32_t resolution=CAMERA_R320x240, int32_t pixformat=CAMERA_GRAYSCALE, int32_t framerate=30);
|
| 239 | + |
| 240 | + /** |
| 241 | + * @brief Get the I2C address of the image sensor. |
| 242 | + * @return int The sensor ID |
| 243 | + */ |
127 | 244 | int getID();
|
| 245 | + |
| 246 | + /** |
| 247 | + * @brief Set the frame rate of the image sensor. |
| 248 | + * |
| 249 | + * @note This has no effect on cameras that do not support variable frame rates. |
| 250 | + * @param framerate The desired frame rate in frames per second |
| 251 | + * @return int 0 on success, non-zero on failure |
| 252 | + */ |
128 | 253 | int setFrameRate(int32_t framerate);
|
| 254 | + |
| 255 | + /** |
| 256 | + * @brief Set the resolution of the image sensor. |
| 257 | + * |
| 258 | + * @note This has no effect on cameras that do not support variable resolutions. |
| 259 | + * @param resolution The desired resolution, as defined in the resolution enum |
| 260 | + * @return int 0 on success, non-zero on failure |
| 261 | + */ |
129 | 262 | int setResolution(int32_t resolution);
|
| 263 | + |
| 264 | + /** |
| 265 | + * @brief Set the pixel (color) format of the image sensor. |
| 266 | + * |
| 267 | + * @note This has no effect on cameras that do not support variable pixel formats. |
| 268 | + * e.g. the Himax HM01B0 only supports grayscale. |
| 269 | + * @param pixelformat The desired pixel format, as defined in the pixel format enum |
| 270 | + * @return int 0 on success, non-zero on failure |
| 271 | + */ |
130 | 272 | int setPixelFormat(int32_t pixelformat);
|
| 273 | + |
| 274 | + /** |
| 275 | + * @brief Set the sensor in standby mode. |
| 276 | + * |
| 277 | + * @note This has no effect on cameras that do not support standby mode. |
| 278 | + * @note None of the currently supported camera drivers implement this function. |
| 279 | + * The HM01B0 and HM0360 cameras can be set in standby mode by calling reset() instead. |
| 280 | + * @param enable true to enable standby mode, false to disable |
| 281 | + * @return int 0 on success, non-zero on failure (or not implemented) |
| 282 | + */ |
131 | 283 | int setStandby(bool enable);
|
| 284 | + |
| 285 | + /** |
| 286 | + * @brief Set the test pattern mode for the sensor. |
| 287 | + * |
| 288 | + * @param enable true to enable test pattern, false to disable |
| 289 | + * @param walking true for walking test pattern, false for other test pattern (if supported) |
| 290 | + * The walking test pattern alternates between black and white pixels which is useful for detecting stuck-at faults |
| 291 | + * @return int 0 on success, non-zero on failure (or not implemented) |
| 292 | + */ |
132 | 293 | int setTestPattern(bool enable, bool walking);
|
| 294 | + |
| 295 | + /** |
| 296 | + * @brief Get the frame size. This is the number of bytes in a frame as determined by the resolution and pixel format. |
| 297 | + * |
| 298 | + * @return int The frame size in bytes |
| 299 | + */ |
133 | 300 | int frameSize();
|
| 301 | + |
| 302 | + /** |
| 303 | + * @brief Capture a frame. |
| 304 | + * |
| 305 | + * @param fb Reference to a FrameBuffer object to store the frame data |
| 306 | + * @param timeout Time in milliseconds to wait for a frame (default: 5000) |
| 307 | + * @return int 0 if successful, non-zero otherwise |
| 308 | + */ |
134 | 309 | int grabFrame(FrameBuffer &fb, uint32_t timeout=5000);
|
| 310 | + |
| 311 | + /** |
| 312 | + * @brief Enable motion detection with the specified callback. |
| 313 | + * @note This has no effect on cameras that do not support motion detection. |
| 314 | + * @param callback Function to be called when motion is detected |
| 315 | + * @return int 0 on success, non-zero on failure |
| 316 | + */ |
135 | 317 | int enableMotionDetection(md_callback_t callback=NULL);
|
| 318 | + |
| 319 | + /** |
| 320 | + * @brief Disable motion detection. |
| 321 | + * |
| 322 | + * @return int 0 on success, non-zero on failure |
| 323 | + */ |
136 | 324 | int disableMotionDetection();
|
| 325 | + |
| 326 | + /** |
| 327 | + * @brief Set the motion detection window. |
| 328 | + * |
| 329 | + * @param x The x-coordinate of the window origin |
| 330 | + * @param y The y-coordinate of the window origin |
| 331 | + * @param w The width of the window |
| 332 | + * @param h The height of the window |
| 333 | + * @return int 0 on success, non-zero on failure |
| 334 | + */ |
137 | 335 | int setMotionDetectionWindow(uint32_t x, uint32_t y, uint32_t w, uint32_t h);
|
| 336 | + |
| 337 | + /** |
| 338 | + * @brief Set the motion detection threshold. |
| 339 | + * On the Himax HM01B0, the recommended threshold range is 3 - 240 (0x03 to 0xF0). |
| 340 | + * @param threshold The motion detection threshold |
| 341 | + * @return int 0 on success, non-zero on failure |
| 342 | + */ |
138 | 343 | int setMotionDetectionThreshold(uint32_t threshold);
|
| 344 | + |
| 345 | + /** |
| 346 | + * @brief Check if motion was detected and clear the motion detection flag. |
| 347 | + * @note This function must be called after the motion detection callback was executed to clear the motion detection flag. |
| 348 | + * @return int 0 if no motion is detected, non-zero if motion is detected |
| 349 | + */ |
139 | 350 | int motionDetected();
|
| 351 | + |
| 352 | + /** |
| 353 | + * @brief Output debug information to a stream. |
| 354 | + * You can use this function to output debug information to the serial port by passing Serial as the stream. |
| 355 | + * @param stream Stream to output the debug information |
| 356 | + */ |
140 | 357 | void debug(Stream &stream);
|
| 358 | + |
141 | 359 | };
|
142 | 360 |
|
143 | 361 | #endif // __CAMERA_H
|
144 | 362 |
|
| 363 | +/// The I2C bus used to communicate with the camera |
145 | 364 | extern arduino::MbedI2C CameraWire;
|
0 commit comments