1 /* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #if defined(ARDUINO) && !defined(ARDUINO_SFE_EDGE)
17 #define ARDUINO_EXCLUDE_CODE
18 #endif // defined(ARDUINO) && !defined(ARDUINO_SFE_EDGE)
19
20 #ifndef ARDUINO_EXCLUDE_CODE
21
22 #include "HM01B0.h"
23
24 #include "HM01B0_Walking1s_01.h"
25 #include "am_bsp.h"
26 #include "am_mcu_apollo.h"
27 #include "am_util.h"
28 #include "platform.h" // TARGET specific implementation
29
30 //#define ENABLE_ASYNC
31
32 const am_hal_gpio_pincfg_t g_HM01B0_pin_vsync = {
33 .uFuncSel = 3,
34 .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
35 #ifdef ENABLE_ASYNC
36 .eIntDir = AM_HAL_GPIO_PIN_INTDIR_BOTH,
37 #endif
38 .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE,
39 .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN};
40
41 const am_hal_gpio_pincfg_t g_HM01B0_pin_int = {
42 .uFuncSel = 3,
43 .eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
44 .eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI,
45 .eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE,
46 .eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN};
47
48 #ifdef ENABLE_ASYNC
49 static bool s_bVsyncAsserted = false;
50
51 //*****************************************************************************
52 //
53 // GPIO ISR
54 //
55 //*****************************************************************************
hm01b0_gpio_isr(void)56 static void hm01b0_gpio_isr(void) {
57 //
58 // Clear the GPIO Interrupt (write to clear).
59 //
60 am_hal_gpio_interrupt_clear(1 << HM01B0_PIN_VSYNC);
61
62 if (read_vsync()) {
63 s_bVsyncAsserted = true;
64 } else {
65 s_bVsyncAsserted = false;
66 }
67 }
68 #endif
69
70 //*****************************************************************************
71 //
72 //! @brief Write HM01B0 registers
73 //!
74 //! @param psCfg - Pointer to HM01B0 configuration structure.
75 //! @param ui16Reg - Register address.
76 //! @param pui8Value - Pointer to the data to be written.
77 //! @param ui32NumBytes - Length of the data in bytes to be written.
78 //!
79 //! This function writes value to HM01B0 registers.
80 //!
81 //! @return Error code.
82 //
83 //*****************************************************************************
hm01b0_write_reg(hm01b0_cfg_t * psCfg,uint16_t ui16Reg,uint8_t * pui8Value,uint32_t ui32NumBytes)84 static uint32_t hm01b0_write_reg(hm01b0_cfg_t* psCfg, uint16_t ui16Reg,
85 uint8_t* pui8Value, uint32_t ui32NumBytes) {
86 am_hal_iom_transfer_t Transaction;
87
88 //
89 // Create the transaction.
90 //
91 Transaction.ui32InstrLen = sizeof(uint16_t);
92 Transaction.ui32Instr = (ui16Reg & 0x0000FFFF);
93 Transaction.eDirection = AM_HAL_IOM_TX;
94 Transaction.ui32NumBytes = ui32NumBytes;
95 Transaction.pui32TxBuffer = (uint32_t*)pui8Value;
96 Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t)psCfg->ui16SlvAddr;
97 Transaction.bContinue = false;
98 Transaction.ui8RepeatCount = 0;
99 Transaction.ui32PauseCondition = 0;
100 Transaction.ui32StatusSetClr = 0;
101
102 //
103 // Execute the transaction over IOM.
104 //
105 if (am_hal_iom_blocking_transfer(psCfg->pIOMHandle, &Transaction)) {
106 return HM01B0_ERR_I2C;
107 }
108
109 return HM01B0_ERR_OK;
110 }
111
112 //*****************************************************************************
113 //
114 //! @brief Read HM01B0 registers
115 //!
116 //! @param psCfg - Pointer to HM01B0 configuration structure.
117 //! @param ui16Reg - Register address.
118 //! @param pui8Value - Pointer to the buffer for read data to be put
119 //! into.
120 //! @param ui32NumBytes - Length of the data to be read.
121 //!
122 //! This function reads value from HM01B0 registers.
123 //!
124 //! @return Error code.
125 //
126 //*****************************************************************************
hm01b0_read_reg(hm01b0_cfg_t * psCfg,uint16_t ui16Reg,uint8_t * pui8Value,uint32_t ui32NumBytes)127 static uint32_t hm01b0_read_reg(hm01b0_cfg_t* psCfg, uint16_t ui16Reg,
128 uint8_t* pui8Value, uint32_t ui32NumBytes) {
129 am_hal_iom_transfer_t Transaction;
130
131 //
132 // Create the transaction.
133 //
134 Transaction.ui32InstrLen = sizeof(uint16_t);
135 Transaction.ui32Instr = (ui16Reg & 0x0000FFFF);
136 Transaction.eDirection = AM_HAL_IOM_RX;
137 Transaction.ui32NumBytes = ui32NumBytes;
138 Transaction.pui32RxBuffer = (uint32_t*)pui8Value;
139 ;
140 Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t)psCfg->ui16SlvAddr;
141 Transaction.bContinue = false;
142 Transaction.ui8RepeatCount = 0;
143 Transaction.ui32PauseCondition = 0;
144 Transaction.ui32StatusSetClr = 0;
145
146 //
147 // Execute the transaction over IOM.
148 //
149 if (am_hal_iom_blocking_transfer(psCfg->pIOMHandle, &Transaction)) {
150 return HM01B0_ERR_I2C;
151 }
152
153 return HM01B0_ERR_OK;
154 }
155
156 //*****************************************************************************
157 //
158 //! @brief Load HM01B0 a given script
159 //!
160 //! @param psCfg - Pointer to HM01B0 configuration structure.
161 //! @param psScrip - Pointer to the script to be loaded.
162 //! @param ui32ScriptCmdNum - Number of entries in a given script.
163 //!
164 //! This function loads HM01B0 a given script.
165 //!
166 //! @return Error code.
167 //
168 //*****************************************************************************
hm01b0_load_script(hm01b0_cfg_t * psCfg,hm_script_t * psScript,uint32_t ui32ScriptCmdNum)169 static uint32_t hm01b0_load_script(hm01b0_cfg_t* psCfg, hm_script_t* psScript,
170 uint32_t ui32ScriptCmdNum) {
171 uint32_t ui32Err = HM01B0_ERR_OK;
172 for (uint32_t idx = 0; idx < ui32ScriptCmdNum; idx++) {
173 ui32Err = hm01b0_write_reg(psCfg, (psScript + idx)->ui16Reg,
174 &((psScript + idx)->ui8Val), sizeof(uint8_t));
175 if (ui32Err != HM01B0_ERR_OK) {
176 break;
177 }
178 }
179
180 return ui32Err;
181 }
182
183 //*****************************************************************************
184 //
185 //! @brief Power up HM01B0
186 //!
187 //! @param psCfg - Pointer to HM01B0 configuration structure.
188 //!
189 //! This function powers up HM01B0.
190 //!
191 //! @return none.
192 //
193 //*****************************************************************************
hm01b0_power_up(hm01b0_cfg_t * psCfg)194 void hm01b0_power_up(hm01b0_cfg_t* psCfg) {
195 // place holder
196 }
197
198 //*****************************************************************************
199 //
200 //! @brief Power down HM01B0
201 //!
202 //! @param psCfg - Pointer to HM01B0 configuration structure.
203 //!
204 //! This function powers up HM01B0.
205 //!
206 //! @return none.
207 //
208 //*****************************************************************************
hm01b0_power_down(hm01b0_cfg_t * psCfg)209 void hm01b0_power_down(hm01b0_cfg_t* psCfg) {
210 // place holder
211 }
212
213 //*****************************************************************************
214 //
215 //! @brief Enable MCLK
216 //!
217 //! @param psCfg - Pointer to HM01B0 configuration structure.
218 //!
219 //! This function utilizes CTimer to generate MCLK for HM01B0.
220 //!
221 //! @return none.
222 //
223 //*****************************************************************************
hm01b0_mclk_enable(hm01b0_cfg_t * psCfg)224 void hm01b0_mclk_enable(hm01b0_cfg_t* psCfg) {
225 #define MCLK_UI64PATTERN 0x55555555
226 #define MCLK_UI64PATTERNLEN 31
227
228 am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
229
230 //
231 // Set up timer.
232 //
233 am_hal_ctimer_clear(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
234
235 am_hal_ctimer_config_single(
236 psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment,
237 (AM_HAL_CTIMER_FN_PTN_REPEAT | AM_HAL_CTIMER_HFRC_12MHZ));
238
239 //
240 // Set the pattern in the CMPR registers.
241 //
242 am_hal_ctimer_compare_set(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment,
243 0, (uint32_t)(MCLK_UI64PATTERN & 0xFFFF));
244 am_hal_ctimer_compare_set(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment,
245 1, (uint32_t)((MCLK_UI64PATTERN >> 16) & 0xFFFF));
246
247 //
248 // Set the timer trigger and pattern length.
249 //
250 am_hal_ctimer_config_trigger(
251 psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment,
252 ((MCLK_UI64PATTERNLEN << CTIMER_AUX0_TMRA0LMT_Pos) |
253 (CTIMER_AUX0_TMRB0TRIG_DIS << CTIMER_AUX0_TMRA0TRIG_Pos)));
254
255 //
256 // Configure timer output pin.
257 //
258 am_hal_ctimer_output_config(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment,
259 psCfg->ui32CTimerOutputPin,
260 AM_HAL_CTIMER_OUTPUT_NORMAL,
261 AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA);
262
263 //
264 // Start the timer.
265 //
266 am_hal_ctimer_start(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
267 }
268
269 //*****************************************************************************
270 //
271 //! @brief Disable MCLK
272 //!
273 //! @param psCfg - Pointer to HM01B0 configuration structure.
274 //!
275 //! This function disable CTimer to stop MCLK for HM01B0.
276 //!
277 //! @return none.
278 //
279 //*****************************************************************************
hm01b0_mclk_disable(hm01b0_cfg_t * psCfg)280 void hm01b0_mclk_disable(hm01b0_cfg_t* psCfg) {
281 //
282 // Stop the timer.
283 //
284 am_hal_ctimer_stop(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
285 am_hal_gpio_pinconfig(psCfg->ui32CTimerOutputPin, g_AM_HAL_GPIO_DISABLE);
286 }
287
288 //*****************************************************************************
289 //
290 //! @brief Initialize interfaces
291 //!
292 //! @param psCfg - Pointer to HM01B0 configuration structure.
293 //!
294 //! This function initializes interfaces.
295 //!
296 //! @return Error code.
297 //
298 //*****************************************************************************
hm01b0_init_if(hm01b0_cfg_t * psCfg)299 uint32_t hm01b0_init_if(hm01b0_cfg_t* psCfg) {
300 void* pIOMHandle = NULL;
301
302 if (psCfg->ui32IOMModule > AM_REG_IOM_NUM_MODULES) {
303 return HM01B0_ERR_I2C;
304 }
305
306 //
307 // Enable fault detection.
308 //
309 #if AM_APOLLO3_MCUCTRL
310 am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_FAULT_CAPTURE_ENABLE, 0);
311 #else // AM_APOLLO3_MCUCTRL
312 am_hal_mcuctrl_fault_capture_enable();
313 #endif // AM_APOLLO3_MCUCTRL
314
315 //
316 // Initialize the IOM instance.
317 // Enable power to the IOM instance.
318 // Configure the IOM for Serial operation during initialization.
319 // Enable the IOM.
320 //
321 if (am_hal_iom_initialize(psCfg->ui32IOMModule, &pIOMHandle) ||
322 am_hal_iom_power_ctrl(pIOMHandle, AM_HAL_SYSCTRL_WAKE, false) ||
323 am_hal_iom_configure(pIOMHandle, &(psCfg->sIOMCfg)) ||
324 am_hal_iom_enable(pIOMHandle)) {
325 return HM01B0_ERR_I2C;
326 } else {
327 //
328 // Configure the IOM pins.
329 //
330 am_bsp_iom_pins_enable(psCfg->ui32IOMModule, psCfg->eIOMMode);
331
332 psCfg->pIOMHandle = pIOMHandle;
333 }
334
335 // initialize pins for camera parallel interface.
336 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD0);
337 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD1);
338 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD2);
339 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD3);
340 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD4);
341 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD5);
342 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD6);
343 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD7);
344
345 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD0);
346 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD1);
347 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD2);
348 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD3);
349 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD4);
350 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD5);
351 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD6);
352 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD7);
353
354 am_hal_gpio_fast_pinconfig(
355 (uint64_t)0x1 << psCfg->ui8PinD0 | (uint64_t)0x1 << psCfg->ui8PinD1 |
356 (uint64_t)0x1 << psCfg->ui8PinD2 | (uint64_t)0x1 << psCfg->ui8PinD3 |
357 (uint64_t)0x1 << psCfg->ui8PinD4 | (uint64_t)0x1 << psCfg->ui8PinD5 |
358 (uint64_t)0x1 << psCfg->ui8PinD6 | (uint64_t)0x1 << psCfg->ui8PinD7,
359 g_AM_HAL_GPIO_INPUT, 0);
360
361 am_hal_gpio_pinconfig(psCfg->ui8PinVSYNC, g_HM01B0_pin_vsync);
362 #ifdef ENABLE_ASYNC
363 psCfg->pfnGpioIsr = hm01b0_gpio_isr;
364 am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(psCfg->ui8PinVSYNC));
365 am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(psCfg->ui8PinVSYNC));
366 NVIC_EnableIRQ(GPIO_IRQn);
367 #endif
368 am_hal_gpio_pinconfig(psCfg->ui8PinHSYNC, g_AM_HAL_GPIO_INPUT);
369 am_hal_gpio_pinconfig(psCfg->ui8PinPCLK, g_AM_HAL_GPIO_INPUT);
370
371 am_hal_gpio_pinconfig(psCfg->ui8PinTrig, g_AM_HAL_GPIO_OUTPUT);
372
373 am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_AM_HAL_GPIO_DISABLE);
374 // am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_HM01B0_pin_int);
375 // am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(psCfg->ui8PinInt));
376 // am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(psCfg->ui8PinInt));
377 // NVIC_EnableIRQ(GPIO_IRQn);
378
379 return HM01B0_ERR_OK;
380 }
381
382 //*****************************************************************************
383 //
384 //! @brief Deinitialize interfaces
385 //!
386 //! @param psCfg - Pointer to HM01B0 configuration structure.
387 //!
388 //! This function deinitializes interfaces.
389 //!
390 //! @return Error code.
391 //
392 //*****************************************************************************
hm01b0_deinit_if(hm01b0_cfg_t * psCfg)393 uint32_t hm01b0_deinit_if(hm01b0_cfg_t* psCfg) {
394 am_hal_iom_disable(psCfg->pIOMHandle);
395 am_hal_iom_uninitialize(psCfg->pIOMHandle);
396
397 am_hal_gpio_pinconfig(psCfg->ui8PinSCL, g_AM_HAL_GPIO_DISABLE);
398 am_hal_gpio_pinconfig(psCfg->ui8PinSDA, g_AM_HAL_GPIO_DISABLE);
399
400 // initialize pins for camera parallel interface.
401 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD0);
402 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD1);
403 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD2);
404 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD3);
405 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD4);
406 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD5);
407 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD6);
408 am_hal_gpio_fastgpio_disable(psCfg->ui8PinD7);
409
410 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD0);
411 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD1);
412 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD2);
413 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD3);
414 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD4);
415 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD5);
416 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD6);
417 am_hal_gpio_fastgpio_clr(psCfg->ui8PinD7);
418
419 am_hal_gpio_pinconfig(psCfg->ui8PinVSYNC, g_AM_HAL_GPIO_DISABLE);
420 #ifdef ENABLE_ASYNC
421 NVIC_DisableIRQ(GPIO_IRQn);
422 am_hal_gpio_interrupt_disable(AM_HAL_GPIO_BIT(psCfg->ui8PinVSYNC));
423 am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(psCfg->ui8PinVSYNC));
424 psCfg->pfnGpioIsr = NULL;
425 #endif
426 am_hal_gpio_pinconfig(psCfg->ui8PinHSYNC, g_AM_HAL_GPIO_DISABLE);
427 am_hal_gpio_pinconfig(psCfg->ui8PinPCLK, g_AM_HAL_GPIO_DISABLE);
428
429 am_hal_gpio_pinconfig(psCfg->ui8PinTrig, g_AM_HAL_GPIO_DISABLE);
430 am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_AM_HAL_GPIO_DISABLE);
431
432 return HM01B0_ERR_OK;
433 }
434
435 //*****************************************************************************
436 //
437 //! @brief Get HM01B0 Model ID
438 //!
439 //! @param psCfg - Pointer to HM01B0 configuration structure.
440 //! @param pui16MID - Pointer to buffer for the read back model ID.
441 //!
442 //! This function reads back HM01B0 model ID.
443 //!
444 //! @return Error code.
445 //
446 //*****************************************************************************
hm01b0_get_modelid(hm01b0_cfg_t * psCfg,uint16_t * pui16MID)447 uint32_t hm01b0_get_modelid(hm01b0_cfg_t* psCfg, uint16_t* pui16MID) {
448 uint8_t ui8Data[1];
449 uint32_t ui32Err;
450
451 *pui16MID = 0x0000;
452
453 ui32Err =
454 hm01b0_read_reg(psCfg, HM01B0_REG_MODEL_ID_H, ui8Data, sizeof(ui8Data));
455 if (ui32Err == HM01B0_ERR_OK) {
456 *pui16MID |= (ui8Data[0] << 8);
457 }
458
459 ui32Err =
460 hm01b0_read_reg(psCfg, HM01B0_REG_MODEL_ID_L, ui8Data, sizeof(ui8Data));
461 if (ui32Err == HM01B0_ERR_OK) {
462 *pui16MID |= ui8Data[0];
463 }
464
465 return ui32Err;
466 }
467
468 //*****************************************************************************
469 //
470 //! @brief Initialize HM01B0
471 //!
472 //! @param psCfg - Pointer to HM01B0 configuration structure.
473 //! @param psScript - Pointer to HM01B0 initialization script.
474 //! @param ui32ScriptCmdNum - No. of commands in HM01B0 initialization
475 //! script.
476 //!
477 //! This function initializes HM01B0 with a given script.
478 //!
479 //! @return Error code.
480 //
481 //*****************************************************************************
hm01b0_init_system(hm01b0_cfg_t * psCfg,hm_script_t * psScript,uint32_t ui32ScriptCmdNum)482 uint32_t hm01b0_init_system(hm01b0_cfg_t* psCfg, hm_script_t* psScript,
483 uint32_t ui32ScriptCmdNum) {
484 return hm01b0_load_script(psCfg, psScript, ui32ScriptCmdNum);
485 }
486
487 //*****************************************************************************
488 //
489 //! @brief Set HM01B0 in the walking 1s test mode
490 //!
491 //! @param psCfg - Pointer to HM01B0 configuration structure.
492 //!
493 //! This function sets HM01B0 in the walking 1s test mode.
494 //!
495 //! @return Error code.
496 //
497 //*****************************************************************************
hm01b0_test_walking1s(hm01b0_cfg_t * psCfg)498 uint32_t hm01b0_test_walking1s(hm01b0_cfg_t* psCfg) {
499 uint32_t ui32ScriptCmdNum =
500 sizeof(sHM01b0TestModeScript_Walking1s) / sizeof(hm_script_t);
501 hm_script_t* psScript = (hm_script_t*)sHM01b0TestModeScript_Walking1s;
502
503 return hm01b0_load_script(psCfg, psScript, ui32ScriptCmdNum);
504 }
505
506 //*****************************************************************************
507 //
508 //! @brief Software reset HM01B0
509 //!
510 //! @param psCfg - Pointer to HM01B0 configuration structure.
511 //!
512 //! This function resets HM01B0 by issuing a reset command.
513 //!
514 //! @return Error code.
515 //
516 //*****************************************************************************
hm01b0_reset_sw(hm01b0_cfg_t * psCfg)517 uint32_t hm01b0_reset_sw(hm01b0_cfg_t* psCfg) {
518 uint8_t ui8Data[1] = {0x00};
519 return hm01b0_write_reg(psCfg, HM01B0_REG_SW_RESET, ui8Data, sizeof(ui8Data));
520 }
521
522 //*****************************************************************************
523 //
524 //! @brief Get current HM01B0 operation mode.
525 //!
526 //! @param psCfg - Pointer to HM01B0 configuration structure.
527 //! @param pui8Mode - Pointer to buffer
528 //! - for the read back operation mode to be put into
529 //!
530 //! This function get HM01B0 operation mode.
531 //!
532 //! @return Error code.
533 //
534 //*****************************************************************************
hm01b0_get_mode(hm01b0_cfg_t * psCfg,uint8_t * pui8Mode)535 uint32_t hm01b0_get_mode(hm01b0_cfg_t* psCfg, uint8_t* pui8Mode) {
536 uint8_t ui8Data[1] = {0x01};
537 uint32_t ui32Err;
538
539 ui32Err =
540 hm01b0_read_reg(psCfg, HM01B0_REG_MODE_SELECT, ui8Data, sizeof(ui8Data));
541
542 *pui8Mode = ui8Data[0];
543
544 return ui32Err;
545 }
546
547 //*****************************************************************************
548 //
549 //! @brief Set HM01B0 operation mode.
550 //!
551 //! @param psCfg - Pointer to HM01B0 configuration structure.
552 //! @param ui8Mode - Operation mode. One of:
553 //! HM01B0_REG_MODE_SELECT_STANDBY
554 //! HM01B0_REG_MODE_SELECT_STREAMING
555 //! HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES
556 //! HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER
557 //! @param ui8FrameCnt - Frame count for
558 //! HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES.
559 //! - Discarded if other modes.
560 //!
561 //! This function set HM01B0 operation mode.
562 //!
563 //! @return Error code.
564 //
565 //*****************************************************************************
hm01b0_set_mode(hm01b0_cfg_t * psCfg,uint8_t ui8Mode,uint8_t ui8FrameCnt)566 uint32_t hm01b0_set_mode(hm01b0_cfg_t* psCfg, uint8_t ui8Mode,
567 uint8_t ui8FrameCnt) {
568 uint32_t ui32Err = HM01B0_ERR_OK;
569
570 if (ui8Mode == HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES) {
571 ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_PMU_PROGRAMMABLE_FRAMECNT,
572 &ui8FrameCnt, sizeof(ui8FrameCnt));
573 }
574
575 if (ui32Err == HM01B0_ERR_OK) {
576 ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_MODE_SELECT, &ui8Mode,
577 sizeof(ui8Mode));
578 }
579
580 return ui32Err;
581 }
582
583 //*****************************************************************************
584 //
585 //! @brief Hardware trigger HM01B0 to stream.
586 //!
587 //! @param psCfg - Pointer to HM01B0 configuration structure.
588 //! @param bTrigger - True to start streaming
589 //! - False to stop streaming
590 //!
591 //! This function triggers HM01B0 to stream by toggling the TRIG pin.
592 //!
593 //! @return Error code.
594 //
595 //*****************************************************************************
hm01b0_hardware_trigger_streaming(hm01b0_cfg_t * psCfg,bool bTrigger)596 uint32_t hm01b0_hardware_trigger_streaming(hm01b0_cfg_t* psCfg, bool bTrigger) {
597 uint32_t ui32Err = HM01B0_ERR_OK;
598 uint8_t ui8Mode;
599
600 ui32Err = hm01b0_get_mode(psCfg, &ui8Mode);
601
602 if (ui32Err != HM01B0_ERR_OK) goto end;
603
604 if (ui8Mode != HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER) {
605 ui32Err = HM01B0_ERR_MODE;
606 goto end;
607 }
608
609 if (bTrigger) {
610 am_hal_gpio_output_set(psCfg->ui8PinTrig);
611 } else {
612 am_hal_gpio_output_clear(psCfg->ui8PinTrig);
613 }
614
615 end:
616 return ui32Err;
617 }
618
619 //*****************************************************************************
620 //
621 //! @brief Set HM01B0 mirror mode.
622 //!
623 //! @param psCfg - Pointer to HM01B0 configuration structure.
624 //! @param bHmirror - Horizontal mirror
625 //! @param bVmirror - Vertical mirror
626 //!
627 //! This function set HM01B0 mirror mode.
628 //!
629 //! @return Error code.
630 //
631 //*****************************************************************************
hm01b0_set_mirror(hm01b0_cfg_t * psCfg,bool bHmirror,bool bVmirror)632 uint32_t hm01b0_set_mirror(hm01b0_cfg_t* psCfg, bool bHmirror, bool bVmirror) {
633 uint8_t ui8Data = 0x00;
634 uint32_t ui32Err = HM01B0_ERR_OK;
635
636 if (bHmirror) {
637 ui8Data |= HM01B0_REG_IMAGE_ORIENTATION_HMIRROR;
638 }
639
640 if (bVmirror) {
641 ui8Data |= HM01B0_REG_IMAGE_ORIENTATION_VMIRROR;
642 }
643
644 ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_IMAGE_ORIENTATION, &ui8Data,
645 sizeof(ui8Data));
646
647 if (ui32Err == HM01B0_ERR_OK) {
648 ui8Data = HM01B0_REG_GRP_PARAM_HOLD_HOLD;
649 ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_GRP_PARAM_HOLD, &ui8Data,
650 sizeof(ui8Data));
651 }
652
653 return ui32Err;
654 }
655
656 //*****************************************************************************
657 //
658 //! @brief Read data of one frame from HM01B0.
659 //!
660 //! @param psCfg - Pointer to HM01B0 configuration structure.
661 //! @param pui8Buffer - Pointer to the frame buffer.
662 //! @param ui32BufferLen - Framebuffer size.
663 //!
664 //! This function read data of one frame from HM01B0.
665 //!
666 //! @return Error code.
667 //
668 //*****************************************************************************
hm01b0_blocking_read_oneframe(hm01b0_cfg_t * psCfg,uint8_t * pui8Buffer,uint32_t ui32BufferLen)669 uint32_t hm01b0_blocking_read_oneframe(hm01b0_cfg_t* psCfg, uint8_t* pui8Buffer,
670 uint32_t ui32BufferLen) {
671 uint32_t ui32Err = HM01B0_ERR_OK;
672 uint32_t ui32Idx = 0x00;
673
674 am_util_stdio_printf("[%s] +\n", __func__);
675 #ifdef ENABLE_ASYNC
676 while (!s_bVsyncAsserted)
677 ;
678
679 while (s_bVsyncAsserted) {
680 // we don't check HSYNC here on the basis of assuming HM01B0 in the gated
681 // PCLK mode which PCLK toggles only when HSYNC is asserted. And also to
682 // minimize the overhead of polling.
683
684 if (read_pclk()) {
685 *(pui8Buffer + ui32Idx++) = read_byte();
686
687 if (ui32Idx == ui32BufferLen) {
688 goto end;
689 }
690
691 while (read_pclk())
692 ;
693 }
694 }
695 #else
696 uint32_t ui32HsyncCnt = 0x00;
697
698 while ((ui32HsyncCnt < HM01B0_PIXEL_Y_NUM)) {
699 while (0x00 == read_hsync())
700 ;
701
702 // read one row
703 while (read_hsync()) {
704 while (0x00 == read_pclk())
705 ;
706
707 *(pui8Buffer + ui32Idx++) = read_byte();
708
709 if (ui32Idx == ui32BufferLen) {
710 goto end;
711 }
712
713 while (read_pclk())
714 ;
715 }
716
717 ui32HsyncCnt++;
718 }
719 #endif
720 end:
721 am_util_stdio_printf("[%s] - Byte Counts %d\n", __func__, ui32Idx);
722 return ui32Err;
723 }
724
hm01b0_single_frame_capture(hm01b0_cfg_t * psCfg)725 uint32_t hm01b0_single_frame_capture(hm01b0_cfg_t* psCfg) {
726 hm01b0_write_reg(psCfg, HM01B0_REG_PMU_PROGRAMMABLE_FRAMECNT, 0x01, 1);
727 hm01b0_write_reg(psCfg, HM01B0_REG_MODE_SELECT,
728 HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES, 1);
729 hm01b0_write_reg(psCfg, HM01B0_REG_GRP_PARAM_HOLD, 0x01, 1);
730 }
731
732 #endif // ARDUINO_EXCLUDE_CODE
733