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)
4243arduino::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)
6870arduino::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
8082static 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
121123static TIM_HandleTypeDef htim = {0 };
122124static DMA_HandleTypeDef hdma = {0 };
123125static DCMI_HandleTypeDef hdcmi = {0 };
124- static volatile uint32_t frame_ready = 0 ;
125126
126127const 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-
339333FrameBuffer::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
398392int 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+ }
0 commit comments