Skip to content

Commit c6eadbd

Browse files
iabdalkaderpennam
authored andcommitted
Update Camera driver.
* Add support for GS from YUV. * Fix frame capture logic. * Add a function to return the sensor color support.
1 parent 63f2cd0 commit c6eadbd

File tree

6 files changed

+46
-44
lines changed

6 files changed

+46
-44
lines changed

libraries/Camera/src/camera.cpp

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#define DCMI_TIM_CLK_DISABLE() __TIM1_CLK_DISABLE()
4040
#define DCMI_TIM_PCLK_FREQ() HAL_RCC_GetPCLK2Freq()
4141
#define DCMI_TIM_FREQUENCY (6000000)
42+
#define DCMI_RESET_PIN (PC_13)
4243
arduino::MbedI2C CameraWire(I2C_SDA, I2C_SCL);
4344

4445
#elif defined(ARDUINO_NICLA_VISION)
@@ -65,6 +66,7 @@ arduino::MbedI2C CameraWire(I2C_SDA2, I2C_SCL2);
6566
#define DCMI_TIM_CLK_DISABLE() __TIM1_CLK_DISABLE()
6667
#define DCMI_TIM_PCLK_FREQ() HAL_RCC_GetPCLK2Freq()
6768
#define DCMI_TIM_FREQUENCY (6000000)
69+
#define DCMI_RESET_PIN (PA_1)
6870
arduino::MbedI2C CameraWire(I2C_SDA1, I2C_SCL1);
6971

7072
#endif
@@ -78,7 +80,7 @@ arduino::MbedI2C CameraWire(I2C_SDA1, I2C_SCL1);
7880

7981
// DCMI GPIO pins struct
8082
static const struct { GPIO_TypeDef *port; uint16_t pin; } dcmi_pins[] = {
81-
#if defined (ARDUINO_PORTENTA_H7_M7) || defined (ARDUINO_PORTENTA_H7_M4)
83+
#if defined (ARDUINO_PORTENTA_H7_M7) || defined (ARDUINO_PORTENTA_H7_M4)
8284
{GPIOA, GPIO_PIN_4 },
8385
{GPIOA, GPIO_PIN_6 },
8486
{GPIOI, GPIO_PIN_4 },
@@ -90,7 +92,7 @@ static const struct { GPIO_TypeDef *port; uint16_t pin; } dcmi_pins[] = {
9092
{GPIOH, GPIO_PIN_11 },
9193
{GPIOH, GPIO_PIN_12 },
9294
{GPIOH, GPIO_PIN_14 },
93-
#elif defined(ARDUINO_NICLA_VISION)
95+
#elif defined(ARDUINO_NICLA_VISION)
9496
{GPIOA, GPIO_PIN_4 },
9597
{GPIOA, GPIO_PIN_6 },
9698
{GPIOC, GPIO_PIN_6 },
@@ -102,7 +104,7 @@ static const struct { GPIO_TypeDef *port; uint16_t pin; } dcmi_pins[] = {
102104
{GPIOE, GPIO_PIN_5 },
103105
{GPIOE, GPIO_PIN_6 },
104106
{GPIOG, GPIO_PIN_9 },
105-
#elif defined(ARDUINO_GIGA)
107+
#elif defined(ARDUINO_GIGA)
106108
{GPIOH, GPIO_PIN_9 },
107109
{GPIOH, GPIO_PIN_10 },
108110
{GPIOH, GPIO_PIN_11 },
@@ -114,14 +116,13 @@ static const struct { GPIO_TypeDef *port; uint16_t pin; } dcmi_pins[] = {
114116
{GPIOA, GPIO_PIN_6 },
115117
{GPIOH, GPIO_PIN_8 },
116118
{GPIOI, GPIO_PIN_5 },
117-
#endif
119+
#endif
118120
};
119121
#define NUM_DCMI_PINS (sizeof(dcmi_pins)/sizeof(dcmi_pins[0]))
120122

121123
static TIM_HandleTypeDef htim = {0};
122124
static DMA_HandleTypeDef hdma = {0};
123125
static DCMI_HandleTypeDef hdcmi = {0};
124-
static volatile uint32_t frame_ready = 0;
125126

126127
const uint32_t pixtab[CAMERA_PMAX] = {
127128
1,
@@ -171,26 +172,27 @@ void HAL_DCMI_MspInit(DCMI_HandleTypeDef *hdcmi)
171172
hgpio.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
172173
hgpio.Alternate = GPIO_AF13_DCMI;
173174

174-
#if defined (ARDUINO_PORTENTA_H7_M7) || defined (ARDUINO_PORTENTA_H7_M4)
175+
#if defined (ARDUINO_PORTENTA_H7_M7) || defined (ARDUINO_PORTENTA_H7_M4)
175176
/* Enable GPIO clocks */
176177
__HAL_RCC_GPIOA_CLK_ENABLE();
177178
__HAL_RCC_GPIOH_CLK_ENABLE();
178179
__HAL_RCC_GPIOI_CLK_ENABLE();
179-
#elif defined(ARDUINO_NICLA_VISION)
180+
#elif defined(ARDUINO_NICLA_VISION)
180181
/* Enable GPIO clocks */
181182
__HAL_RCC_GPIOG_CLK_ENABLE();
182183
__HAL_RCC_GPIOE_CLK_ENABLE();
183184
__HAL_RCC_GPIOD_CLK_ENABLE();
184185
__HAL_RCC_GPIOC_CLK_ENABLE();
185186
__HAL_RCC_GPIOA_CLK_ENABLE();
186-
#elif defined(ARDUINO_GIGA)
187+
#elif defined(ARDUINO_GIGA)
187188
/* Enable GPIO clocks */
188189
__HAL_RCC_GPIOA_CLK_ENABLE();
189190
__HAL_RCC_GPIOG_CLK_ENABLE();
190191
__HAL_RCC_GPIOH_CLK_ENABLE();
191192
__HAL_RCC_GPIOI_CLK_ENABLE();
192193
__HAL_RCC_GPIOJ_CLK_ENABLE();
193-
#endif
194+
#endif
195+
194196
for (uint32_t i=0; i<NUM_DCMI_PINS; i++) {
195197
hgpio.Pin = dcmi_pins[i].pin;
196198
HAL_GPIO_Init(dcmi_pins[i].port, &hgpio);
@@ -262,7 +264,7 @@ __weak int camera_extclk_config(int frequency)
262264
return 0;
263265
}
264266

265-
uint8_t camera_dcmi_config()
267+
uint8_t camera_dcmi_config(bool bsm_skip)
266268
{
267269
// DMA Stream configuration
268270
hdma.Instance = DCMI_DMA_STREAM;
@@ -298,17 +300,16 @@ uint8_t camera_dcmi_config()
298300
hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;
299301
hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
300302
hdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE;
301-
hdcmi.Init.ByteSelectMode = DCMI_BSM_ALL; // Capture all received bytes
302-
hdcmi.Init.ByteSelectStart = DCMI_OEBS_ODD; // Ignored
303-
hdcmi.Init.LineSelectMode = DCMI_LSM_ALL; // Capture all received lines
304-
hdcmi.Init.LineSelectStart = DCMI_OELS_ODD; // Ignored
303+
hdcmi.Init.ByteSelectMode = bsm_skip ? DCMI_BSM_OTHER : DCMI_BSM_ALL;
304+
hdcmi.Init.ByteSelectStart = DCMI_OEBS_ODD; // Ignored unless BSM != ALL
305+
hdcmi.Init.LineSelectMode = DCMI_LSM_ALL; // Capture all received lines
306+
hdcmi.Init.LineSelectStart = DCMI_OELS_ODD; // Ignored, unless LSM != ALL
305307

306308
// Link the DMA handle to the DCMI handle.
307309
__HAL_LINKDMA(&hdcmi, DMA_Handle, hdma);
308310

309311
// Initialize the DCMI
310312
HAL_DCMI_Init(&hdcmi);
311-
__HAL_DCMI_ENABLE_IT(&hdcmi, DCMI_IT_FRAME);
312313
__HAL_DCMI_DISABLE_IT(&hdcmi, DCMI_IT_LINE);
313314

314315
// Configure and enable DCMI IRQ Channel
@@ -327,15 +328,8 @@ void DMA2_Stream3_IRQHandler(void)
327328
HAL_DMA_IRQHandler(&hdma);
328329
}
329330

330-
void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
331-
{
332-
frame_ready++;
333-
}
334-
335331
} // extern "C"
336332

337-
338-
339333
FrameBuffer::FrameBuffer(int32_t x, int32_t y, int32_t bpp) :
340334
_fb_size(x*y*bpp),
341335
_isAllocated(true)
@@ -397,14 +391,14 @@ Camera::Camera(ImageSensor &sensor) :
397391

398392
int Camera::reset()
399393
{
400-
#if defined (ARDUINO_PORTENTA_H7_M7) || defined (ARDUINO_PORTENTA_H7_M4)
401394
// Reset sensor.
402-
digitalWrite(PC_13, LOW);
395+
#if defined(DCMI_RESET_PIN)
396+
digitalWrite(DCMI_RESET_PIN, LOW);
403397
HAL_Delay(10);
404398

405-
digitalWrite(PC_13, HIGH);
406-
HAL_Delay(100);
407-
#endif
399+
digitalWrite(DCMI_RESET_PIN, HIGH);
400+
HAL_Delay(20);
401+
#endif
408402
return 0;
409403
}
410404

@@ -460,7 +454,11 @@ bool Camera::begin(int32_t resolution, int32_t pixformat, int32_t framerate)
460454
return false;
461455
}
462456

463-
if (camera_dcmi_config() != 0) {
457+
// If the pixel format is Grayscale and sensor is Not monochrome, the
458+
// actual pixel format will be YUV (i.e 2 bytes per pixel) and the DCMI
459+
// needs to be configured to skip every other byte to extract the Y channel.
460+
bool gs_from_yuv = (pixformat == CAMERA_GRAYSCALE) && !this->sensor->getMono();
461+
if (camera_dcmi_config(gs_from_yuv) != 0) {
464462
return false;
465463
}
466464

@@ -518,7 +516,13 @@ int Camera::setResolution(int32_t resolution)
518516
* @param YSize DCMI Line number
519517
*/
520518
HAL_DCMI_EnableCROP(&hdcmi);
521-
uint32_t bpl = restab[resolution][0] * pixtab[pixformat];
519+
uint32_t bpl = restab[resolution][0];
520+
if (pixformat == CAMERA_RGB565 ||
521+
(pixformat == CAMERA_GRAYSCALE && !this->sensor->getMono())) {
522+
// If the pixel format is Grayscale and sensor is Not monochrome,
523+
// the actual pixel format will be YUV (i.e 2 bytes per pixel).
524+
bpl *= 2;
525+
}
522526
HAL_DCMI_ConfigCROP(&hdcmi, 0, 0, bpl - 1, restab[resolution][1] - 1);
523527

524528
if (this->sensor->setResolution(resolution) == 0) {
@@ -612,38 +616,31 @@ int Camera::grabFrame(FrameBuffer &fb, uint32_t timeout)
612616
return -1;
613617
}
614618

615-
frame_ready = 0;
616-
617-
if (HAL_DCMI_Resume(&hdcmi) != HAL_OK) {
618-
if (_debug) {
619-
_debug->println("HAL_DCMI_Resume FAILED!");
620-
}
621-
}
622-
623619
// Start the Camera Snapshot Capture.
624-
if (HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT, (uint32_t) framebuffer, framesize / 4) != HAL_OK) {
620+
if (HAL_DCMI_Start_DMA(&hdcmi, DCMI_MODE_SNAPSHOT,
621+
(uint32_t) framebuffer, framesize / 4) != HAL_OK) {
625622
if (_debug) {
626623
_debug->println("HAL_DCMI_Start_DMA FAILED!");
627624
}
628625
}
629626

630627
// Wait until camera frame is ready.
631-
for (uint32_t start = millis(); frame_ready == 0;) {
628+
for (uint32_t start = millis(); (hdcmi.Instance->CR & DCMI_CR_CAPTURE);) {
632629
__WFI();
633630
if ((millis() - start) > timeout) {
634631
if (_debug) {
635632
_debug->println("Timeout expired!");
636633
}
637-
HAL_DMA_Abort(&hdma);
634+
HAL_DCMI_Stop(&hdcmi);
638635
return -1;
639636
}
640637
}
641638

642-
HAL_DCMI_Suspend(&hdcmi);
639+
HAL_DCMI_Stop(&hdcmi);
643640

644641
#if defined(__CORTEX_M7) // only invalidate buffer for Cortex M7
645-
// Invalidate buffer after DMA transfer.
646-
SCB_InvalidateDCache_by_Addr((uint32_t*) framebuffer, framesize);
642+
// Invalidate buffer after DMA transfer.
643+
SCB_InvalidateDCache_by_Addr((uint32_t*) framebuffer, framesize);
647644
#endif
648645
return 0;
649646
}
@@ -686,4 +683,4 @@ void Camera::debug(Stream &stream)
686683
{
687684
_debug = &stream;
688685
this->sensor->debug(stream);
689-
}
686+
}

libraries/Camera/src/camera.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class ImageSensor {
6868
virtual int init() = 0;
6969
virtual int reset() = 0;
7070
virtual int getID() = 0;
71+
virtual bool getMono() = 0;
7172
virtual uint32_t getClockFrequency() = 0;
7273
virtual int setFrameRate(int32_t framerate) = 0;
7374
virtual int setResolution(int32_t resolution) = 0;

libraries/GC2145/gc2145.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ class GC2145: public ImageSensor {
3434
int init();
3535
int reset();
3636
int getID() { return GC2145_I2C_ADDR; };
37+
bool getMono() { return false; };
3738
uint32_t getClockFrequency() { return 12000000; };
3839
int setFrameRate(int32_t framerate);
3940
int setResolution(int32_t resolution);

libraries/Himax_HM01B0/himax.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class HM01B0: public ImageSensor {
3737
int init();
3838
int reset();
3939
int getID() { return HM01B0_I2C_ADDR; };
40+
bool getMono() { return true; };
4041
uint32_t getClockFrequency() { return 6000000; };
4142
int setFrameRate(int32_t framerate);
4243
int setResolution(int32_t resolution);

libraries/Himax_HM0360/hm0360.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class HM0360: public ImageSensor {
3737
int init();
3838
int reset();
3939
int getID() { return HM0360_I2C_ADDR; };
40+
bool getMono() { return true; };
4041
uint32_t getClockFrequency() { return 24000000; };
4142
int setFrameRate(int32_t framerate);
4243
int setResolution(int32_t resolution);

libraries/OV7670/ov7670.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class OV7670: public ImageSensor {
3737
int init();
3838
int reset();
3939
int getID() { return 0x21; };
40+
bool getMono() { return false; };
4041
uint32_t getClockFrequency() { return 12000000; };
4142
int setFrameRate(int32_t framerate);
4243
int setResolution(int32_t resolution);

0 commit comments

Comments
 (0)