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