initial commit

This commit is contained in:
2022-10-23 23:45:43 -07:00
commit e190fa5193
6450 changed files with 8626944 additions and 0 deletions
@@ -0,0 +1,938 @@
//*****************************************************************************
//
//! @file HM01B0.c
//!
//
//*****************************************************************************
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#include "HM01B0.h"
#include "HM01B0_Walking1s_01.h"
#include "platform.h"
#define read_vsync() (AM_REGVAL(AM_REGADDR(GPIO, RDA)) & (1 << HM01B0_PIN_VSYNC))
#define read_hsync() (AM_REGVAL(AM_REGADDR(GPIO, RDA)) & (1 << HM01B0_PIN_HSYNC))
#define read_pclk() (AM_REGVAL(AM_REGADDR(GPIO, RDA)) & (1 << HM01B0_PIN_PCLK))
#define read_byte() (APBDMA->BBINPUT)
const am_hal_gpio_pincfg_t g_HM01B0_pin_int =
{
.uFuncSel = 3,
.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_DISABLE,
.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI,
.eGPInput = AM_HAL_GPIO_PIN_INPUT_ENABLE,
.eGPRdZero = AM_HAL_GPIO_PIN_RDZERO_READPIN
};
//*****************************************************************************
//
//! @brief Write HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the data to be written.
//! @param ui32NumBytes - Length of the data in bytes to be written.
//!
//! This function writes value to HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_write_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes)
{
am_hal_iom_transfer_t Transaction;
//
// Create the transaction.
//
Transaction.ui32InstrLen = sizeof(uint16_t);
Transaction.ui32Instr = (ui16Reg & 0x0000FFFF);
Transaction.eDirection = AM_HAL_IOM_TX;
Transaction.ui32NumBytes = ui32NumBytes;
Transaction.pui32TxBuffer = (uint32_t *) pui8Value;
Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t) psCfg->ui16SlvAddr;
Transaction.bContinue = false;
Transaction.ui8RepeatCount = 0;
Transaction.ui32PauseCondition = 0;
Transaction.ui32StatusSetClr = 0;
//
// Execute the transction over IOM.
//
if (am_hal_iom_blocking_transfer(psCfg->pIOMHandle, &Transaction))
{
return HM01B0_ERR_I2C;
}
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Read HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the buffer for read data to be put into.
//! @param ui32NumBytes - Length of the data to be read.
//!
//! This function reads value from HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_read_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes)
{
am_hal_iom_transfer_t Transaction;
//
// Create the transaction.
//
Transaction.ui32InstrLen = sizeof(uint16_t);
Transaction.ui32Instr = (ui16Reg & 0x0000FFFF);
Transaction.eDirection = AM_HAL_IOM_RX;
Transaction.ui32NumBytes = ui32NumBytes;
Transaction.pui32RxBuffer = (uint32_t *) pui8Value;;
Transaction.uPeerInfo.ui32I2CDevAddr = (uint32_t) psCfg->ui16SlvAddr;
Transaction.bContinue = false;
Transaction.ui8RepeatCount = 0;
Transaction.ui32PauseCondition = 0;
Transaction.ui32StatusSetClr = 0;
//
// Execute the transction over IOM.
//
if (am_hal_iom_blocking_transfer(psCfg->pIOMHandle, &Transaction))
{
return HM01B0_ERR_I2C;
}
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Load HM01B0 a given script
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScrip - Pointer to the script to be loaded.
//! @param ui32ScriptCmdNum - Number of entries in a given script.
//!
//! This function loads HM01B0 a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_load_script(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum)
{
uint32_t ui32Err = HM01B0_ERR_OK;
for (uint32_t idx = 0; idx < ui32ScriptCmdNum; idx++)
{
ui32Err = hm01b0_write_reg(psCfg, \
(psScript + idx)->ui16Reg, \
&((psScript + idx)->ui8Val), \
sizeof(uint8_t));
if (ui32Err != HM01B0_ERR_OK)
{
break;
}
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Power up HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_up(hm01b0_cfg_t *psCfg)
{
// place holder
}
//*****************************************************************************
//
//! @brief Power down HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_down(hm01b0_cfg_t *psCfg)
{
// place holder
}
//*****************************************************************************
//
//! @brief Enable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function utilizes CTimer to generate MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_enable(hm01b0_cfg_t *psCfg)
{
#define MCLK_UI64PATTERN 0x55555555
#define MCLK_UI64PATTERNLEN 31
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
//
// Set up timer.
//
am_hal_ctimer_clear(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
am_hal_ctimer_config_single(psCfg->ui32CTimerModule,
psCfg->ui32CTimerSegment,
(
AM_HAL_CTIMER_FN_PTN_REPEAT |
AM_HAL_CTIMER_HFRC_12MHZ
)
);
//
// Set the pattern in the CMPR registers.
//
am_hal_ctimer_compare_set(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment, 0,
(uint32_t)(MCLK_UI64PATTERN & 0xFFFF));
am_hal_ctimer_compare_set(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment, 1,
(uint32_t)((MCLK_UI64PATTERN >> 16) & 0xFFFF));
//
// Set the timer trigger and pattern length.
//
am_hal_ctimer_config_trigger(psCfg->ui32CTimerModule,
psCfg->ui32CTimerSegment,
(
(MCLK_UI64PATTERNLEN << CTIMER_AUX0_TMRA0LMT_Pos) |
(CTIMER_AUX0_TMRB0TRIG_DIS << CTIMER_AUX0_TMRA0TRIG_Pos)
)
);
//
// Configure timer output pin.
//
am_hal_ctimer_output_config(psCfg->ui32CTimerModule,
psCfg->ui32CTimerSegment,
psCfg->ui32CTimerOutputPin,
AM_HAL_CTIMER_OUTPUT_NORMAL,
AM_HAL_GPIO_PIN_DRIVESTRENGTH_12MA);
//
// Start the timer.
//
am_hal_ctimer_start(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
}
//*****************************************************************************
//
//! @brief Disable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function disable CTimer to stop MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_disable(hm01b0_cfg_t *psCfg)
{
//
// Stop the timer.
//
am_hal_ctimer_stop(psCfg->ui32CTimerModule, psCfg->ui32CTimerSegment);
am_hal_gpio_pinconfig(psCfg->ui32CTimerOutputPin, g_AM_HAL_GPIO_DISABLE);
}
//*****************************************************************************
//
//! @brief Initialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function initializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_if(hm01b0_cfg_t *psCfg)
{
void *pIOMHandle = NULL;
if ( psCfg->ui32IOMModule > AM_REG_IOM_NUM_MODULES )
{
return HM01B0_ERR_I2C;
}
//
// Enable fault detection.
//
#if AM_APOLLO3_MCUCTRL
am_hal_mcuctrl_control(AM_HAL_MCUCTRL_CONTROL_FAULT_CAPTURE_ENABLE, 0);
#else // AM_APOLLO3_MCUCTRL
am_hal_mcuctrl_fault_capture_enable();
#endif // AM_APOLLO3_MCUCTRL
//
// Initialize the IOM instance.
// Enable power to the IOM instance.
// Configure the IOM for Serial operation during initialization.
// Enable the IOM.
//
if (am_hal_iom_initialize(psCfg->ui32IOMModule, &pIOMHandle) ||
am_hal_iom_power_ctrl(pIOMHandle, AM_HAL_SYSCTRL_WAKE, false) ||
am_hal_iom_configure(pIOMHandle, &(psCfg->sIOMCfg)) ||
am_hal_iom_enable(pIOMHandle))
{
return HM01B0_ERR_I2C;
}
else
{
//
// Configure the IOM pins.
//
am_bsp_iom_pins_enable(psCfg->ui32IOMModule, psCfg->eIOMMode);
psCfg->pIOMHandle = pIOMHandle;
}
// initialize pins for camera parallel interface.
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD7);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD7);
am_hal_gpio_fast_pinconfig((uint64_t)0x1 << psCfg->ui8PinD0 |
(uint64_t)0x1 << psCfg->ui8PinD1 |
(uint64_t)0x1 << psCfg->ui8PinD2 |
(uint64_t)0x1 << psCfg->ui8PinD3 |
(uint64_t)0x1 << psCfg->ui8PinD4 |
(uint64_t)0x1 << psCfg->ui8PinD5 |
(uint64_t)0x1 << psCfg->ui8PinD6 |
(uint64_t)0x1 << psCfg->ui8PinD7,
g_AM_HAL_GPIO_INPUT, 0);
am_hal_gpio_pinconfig(psCfg->ui8PinVSYNC, g_AM_HAL_GPIO_INPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinHSYNC, g_AM_HAL_GPIO_INPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinPCLK, g_AM_HAL_GPIO_INPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinTrig, g_AM_HAL_GPIO_OUTPUT);
am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_AM_HAL_GPIO_DISABLE);
// am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_HM01B0_pin_int);
// am_hal_gpio_interrupt_clear(AM_HAL_GPIO_BIT(psCfg->ui8PinInt));
// am_hal_gpio_interrupt_enable(AM_HAL_GPIO_BIT(psCfg->ui8PinInt));
// NVIC_EnableIRQ(GPIO_IRQn);
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Deinitialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function deinitializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_deinit_if(hm01b0_cfg_t *psCfg)
{
am_hal_iom_disable(psCfg->pIOMHandle);
am_hal_iom_uninitialize(psCfg->pIOMHandle);
am_hal_gpio_pinconfig(psCfg->ui8PinSCL, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinSDA, g_AM_HAL_GPIO_DISABLE);
// initialize pins for camera parallel interface.
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_disable(psCfg->ui8PinD7);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD0);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD1);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD2);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD3);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD4);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD5);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD6);
am_hal_gpio_fastgpio_clr(psCfg->ui8PinD7);
am_hal_gpio_pinconfig(psCfg->ui8PinVSYNC, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinHSYNC, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinPCLK, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinTrig, g_AM_HAL_GPIO_DISABLE);
am_hal_gpio_pinconfig(psCfg->ui8PinInt, g_AM_HAL_GPIO_DISABLE);
return HM01B0_ERR_OK;
}
//*****************************************************************************
//
//! @brief Get HM01B0 Model ID
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui16MID - Pointer to buffer for the read back model ID.
//!
//! This function reads back HM01B0 model ID.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_modelid(hm01b0_cfg_t *psCfg, uint16_t *pui16MID)
{
uint8_t ui8Data[1];
uint32_t ui32Err;
*pui16MID = 0x0000;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_MODEL_ID_H, ui8Data, sizeof(ui8Data));
if (ui32Err == HM01B0_ERR_OK)
{
*pui16MID |= (ui8Data[0] << 8);
}
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_MODEL_ID_L, ui8Data, sizeof(ui8Data));
if (ui32Err == HM01B0_ERR_OK)
{
*pui16MID |= ui8Data[0];
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Initialize HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScript - Pointer to HM01B0 initialization script.
//! @param ui32ScriptCmdNum - No. of commands in HM01B0 initialization script.
//!
//! This function initilizes HM01B0 with a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_system(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum)
{
return hm01b0_load_script(psCfg, psScript, ui32ScriptCmdNum);
}
//*****************************************************************************
//
//! @brief Set HM01B0 in the walking 1s test mode
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_test_walking1s(hm01b0_cfg_t *psCfg)
{
uint32_t ui32ScriptCmdNum = sizeof(sHM01b0TestModeScript_Walking1s) / sizeof(hm_script_t);
hm_script_t *psScript = (hm_script_t *)sHM01b0TestModeScript_Walking1s;
return hm01b0_load_script(psCfg, psScript, ui32ScriptCmdNum);
}
//*****************************************************************************
//
//! @brief Check the data read from HM01B0 in the walking 1s test mode
//!
//! @param pui8Buffer - Pointer to data buffer.
//! @param ui32BufferLen - Buffer length
//! @param ui32PrintCnt - Number of mismatched data to be printed out
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
void hm01b0_test_walking1s_check_data_sanity(uint8_t *pui8Buffer, uint32_t ui32BufferLen, uint32_t ui32PrintCnt)
{
uint8_t ui8ByteData = *pui8Buffer;
uint32_t ui32MismatchCnt = 0x00;
for (uint32_t ui32Idx = 0; ui32Idx < ui32BufferLen; ui32Idx++)
{
if (*(pui8Buffer + ui32Idx) != ui8ByteData)
{
if (ui32PrintCnt)
{
am_util_stdio_printf("[0x%08X] actual 0x%02X expected 0x%02X\n", ui32Idx, *(pui8Buffer + ui32Idx), ui8ByteData);
am_util_delay_ms(1);
ui32PrintCnt--;
}
ui32MismatchCnt++;
}
if (ui8ByteData)
ui8ByteData = ui8ByteData << 1;
else
ui8ByteData = 0x01;
}
am_util_stdio_printf("Mismatch Rate %d/%d\n", ui32MismatchCnt, ui32BufferLen);
}
//*****************************************************************************
//
//! @brief Software reset HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function resets HM01B0 by issuing a reset command.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_reset_sw(hm01b0_cfg_t *psCfg)
{
uint8_t ui8Data[1] = {0x00};
return hm01b0_write_reg(psCfg, HM01B0_REG_SW_RESET, ui8Data, sizeof(ui8Data));
}
//*****************************************************************************
//
//! @brief Get current HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Mode - Pointer to buffer
//! - for the read back operation mode to be put into
//!
//! This function get HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_mode(hm01b0_cfg_t *psCfg, uint8_t *pui8Mode)
{
uint8_t ui8Data[1] = {0x01};
uint32_t ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_MODE_SELECT, ui8Data, sizeof(ui8Data));
*pui8Mode = ui8Data[0];
return ui32Err;
}
//*****************************************************************************
//
//! @brief Set HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8Mode - Operation mode. One of:
//! HM01B0_REG_MODE_SELECT_STANDBY
//! HM01B0_REG_MODE_SELECT_STREAMING
//! HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES
//! HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER
//! @param ui8FrameCnt - Frame count for HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES.
//! - Discarded if other modes.
//!
//! This function set HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mode(hm01b0_cfg_t *psCfg, uint8_t ui8Mode, uint8_t ui8FrameCnt)
{
uint32_t ui32Err = HM01B0_ERR_OK;
if (ui8Mode == HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES)
{
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_PMU_PROGRAMMABLE_FRAMECNT, &ui8FrameCnt, sizeof(ui8FrameCnt));
}
if(ui32Err == HM01B0_ERR_OK)
{
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_MODE_SELECT, &ui8Mode, sizeof(ui8Mode));
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Activate the updated settings to HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! Some settings updated to HM01B0 will only be affected after calling this function
//! 1. AE settings
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cmd_update(hm01b0_cfg_t *psCfg)
{
uint8_t ui8Data = HM01B0_REG_GRP_PARAM_HOLD_HOLD;
return hm01b0_write_reg(psCfg, HM01B0_REG_GRP_PARAM_HOLD, &ui8Data, sizeof(ui8Data));
}
//*****************************************************************************
//
//! @brief Get HM01B0 AE convergance
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psAECfg - Pointer to the structure hm01b0_ae_cfg_t.
//!
//! This function checks if AE is converged or not and returns ui32Err accordingly.
//! If caller needs detailed AE settings, psAECfg has to be non NULL.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_ae(hm01b0_cfg_t *psCfg, hm01b0_ae_cfg_t *psAECfg)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8AETargetMean;
uint8_t ui8AEMinMean;
uint8_t ui8AEMean;
uint8_t ui8ConvergeInTh;
uint8_t ui8ConvergeOutTh;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_AE_TARGET_MEAN, &ui8AETargetMean, sizeof(ui8AETargetMean));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_AE_MIN_MEAN, &ui8AEMinMean, sizeof(ui8AEMinMean));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_CONVERGE_IN_TH, &ui8ConvergeInTh, sizeof(ui8ConvergeInTh));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_CONVERGE_OUT_TH, &ui8ConvergeOutTh, sizeof(ui8ConvergeOutTh));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, 0x2020, &ui8AEMean, sizeof(ui8AEMean));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
if ((ui8AEMean < (ui8AETargetMean - ui8ConvergeInTh)) || (ui8AEMean > (ui8AETargetMean + ui8ConvergeInTh)))
ui32Err = HM01B0_ERR_AE_NOT_CONVERGED;
if (psAECfg)
{
psAECfg->ui8AETargetMean = ui8AETargetMean;
psAECfg->ui8AEMinMean = ui8AEMinMean;
psAECfg->ui8ConvergeInTh = ui8ConvergeInTh;
psAECfg->ui8ConvergeOutTh = ui8ConvergeOutTh;
psAECfg->ui8AEMean = ui8AEMean;
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief AE calibration.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8CalFrames - Frame counts for calibratoin.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function lets HM01B0 AE settled as much as possible within a given frame counts.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cal_ae(hm01b0_cfg_t *psCfg, uint8_t ui8CalFrames, uint8_t *pui8Buffer, uint32_t ui32BufferLen)
{
uint32_t ui32Err = HM01B0_ERR_OK;
hm01b0_ae_cfg_t sAECfg;
am_util_stdio_printf("[%s] +\n", __func__);
hm01b0_set_mode(psCfg, HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES, ui8CalFrames);
for (uint8_t i = 0; i < ui8CalFrames; i++)
{
hm01b0_blocking_read_oneframe(psCfg, pui8Buffer, ui32BufferLen);
ui32Err = hm01b0_get_ae(psCfg, &sAECfg);
am_util_stdio_printf("AE Calibration(0x%02X) TargetMean 0x%02X, ConvergeInTh 0x%02X, AEMean 0x%02X\n", \
ui32Err, sAECfg.ui8AETargetMean, sAECfg.ui8ConvergeInTh, sAECfg.ui8AEMean);
// if AE calibration is done in ui8CalFrames, just exit to save some time.
if (ui32Err == HM01B0_ERR_OK)
break;
}
hm01b0_set_mode(psCfg, HM01B0_REG_MODE_SELECT_STANDBY, 0);
am_util_stdio_printf("[%s] -\n", __func__);
return ui32Err;
}
//*****************************************************************************
//
//! @brief Save HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function saves HM01B0 exposure gain settings.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_save_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8IntegrationH;
uint8_t ui8IntegrationL;
uint8_t ui8AGain;
uint8_t ui8DGain_H;
uint8_t ui8DGain_L;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_INTEGRATION_H, &ui8IntegrationH, sizeof(ui8IntegrationH));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_INTEGRATION_L, &ui8IntegrationL, sizeof(ui8IntegrationL));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_ANALOG_GAIN, &ui8AGain, sizeof(ui8AGain));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_H, &ui8DGain_H, sizeof(ui8DGain_H));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_L, &ui8DGain_L, sizeof(ui8DGain_L));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
if (psExpoGainCtrl)
{
psExpoGainCtrl->ui8IntegrationH = ui8IntegrationH;
psExpoGainCtrl->ui8IntegrationL = ui8IntegrationL;
psExpoGainCtrl->ui8AGain = ui8AGain;
psExpoGainCtrl->ui8DGain_H = ui8DGain_H;
psExpoGainCtrl->ui8DGain_L = ui8DGain_L;
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Restore HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function restores HM01B0 exposure gain settings. The call flow shall be
//! hm01b0_restore_exposure_gains() -> hm01b0_cmd_update() -> hm01b0_set_mode()
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_restore_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8Tmp;
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_INTEGRATION_H, &(psExpoGainCtrl->ui8IntegrationH), sizeof(psExpoGainCtrl->ui8IntegrationH));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_INTEGRATION_L, &(psExpoGainCtrl->ui8IntegrationL), sizeof(psExpoGainCtrl->ui8IntegrationL));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_ANALOG_GAIN, &ui8Tmp, sizeof(ui8Tmp));
ui8Tmp = (ui8Tmp & ~(0x7 << 4)) | (psExpoGainCtrl->ui8AGain & (0x7 << 4));
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_ANALOG_GAIN, &ui8Tmp, sizeof(ui8Tmp));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_H, &ui8Tmp, sizeof(ui8Tmp));
ui8Tmp = (ui8Tmp & ~(0x3 << 0)) | (psExpoGainCtrl->ui8DGain_H & (0x3 << 0));
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_H, &ui8Tmp, sizeof(ui8Tmp));
if (ui32Err != HM01B0_ERR_OK) return ui32Err;
ui32Err = hm01b0_read_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_L, &ui8Tmp, sizeof(ui8Tmp));
ui8Tmp = (ui8Tmp & ~(0x3F << 2)) | (psExpoGainCtrl->ui8DGain_L & (0x3F << 2));
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_DIGITAL_GAIN_L, &ui8Tmp, sizeof(ui8Tmp));
return ui32Err;
}
//*****************************************************************************
//
//! @brief Hardware trigger HM01B0 to stream.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bTrigger - True to start streaming
//! - False to stop streaming
//!
//! This function triggers HM01B0 to stream by toggling the TRIG pin.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_hardware_trigger_streaming(hm01b0_cfg_t *psCfg, bool bTrigger)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint8_t ui8Mode;
ui32Err = hm01b0_get_mode(psCfg, &ui8Mode);
if (ui32Err != HM01B0_ERR_OK)
goto end;
if (ui8Mode != HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER)
{
ui32Err = HM01B0_ERR_MODE;
goto end;
}
if (bTrigger)
{
am_hal_gpio_output_set(psCfg->ui8PinTrig);
}
else
{
am_hal_gpio_output_clear(psCfg->ui8PinTrig);
}
end:
return ui32Err;
}
//*****************************************************************************
//
//! @brief Set HM01B0 mirror mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bHmirror - Horizontal mirror
//! @param bVmirror - Vertical mirror
//!
//! This function set HM01B0 mirror mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mirror(hm01b0_cfg_t *psCfg, bool bHmirror, bool bVmirror)
{
uint8_t ui8Data = 0x00;
uint32_t ui32Err = HM01B0_ERR_OK;
if (bHmirror)
{
ui8Data |= HM01B0_REG_IMAGE_ORIENTATION_HMIRROR;
}
if (bVmirror)
{
ui8Data |= HM01B0_REG_IMAGE_ORIENTATION_VMIRROR;
}
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_IMAGE_ORIENTATION, &ui8Data, sizeof(ui8Data));
if (ui32Err == HM01B0_ERR_OK)
{
ui8Data = HM01B0_REG_GRP_PARAM_HOLD_HOLD;
ui32Err = hm01b0_write_reg(psCfg, HM01B0_REG_GRP_PARAM_HOLD, &ui8Data, sizeof(ui8Data));
}
return ui32Err;
}
//*****************************************************************************
//
//! @brief Read data of one frame from HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function read data of one frame from HM01B0.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_blocking_read_oneframe(hm01b0_cfg_t *psCfg, uint8_t *pui8Buffer, uint32_t ui32BufferLen)
{
uint32_t ui32Err = HM01B0_ERR_OK;
uint32_t ui32Idx = 0x00;
am_util_stdio_printf("[%s] +\n", __func__);
uint32_t ui32HsyncCnt = 0x00;
while((ui32HsyncCnt < HM01B0_PIXEL_Y_NUM))
{
while (0x00 == read_hsync());
// read one row
while(read_hsync())
{
while(0x00 == read_pclk());
*(pui8Buffer + ui32Idx++) = read_byte();
if (ui32Idx == ui32BufferLen) {
goto end;
}
while(read_pclk());
}
ui32HsyncCnt++;
}
end:
am_util_stdio_printf("[%s] - Byte Counts %d\n", __func__, ui32Idx);
return ui32Err;
}
@@ -0,0 +1,490 @@
//*****************************************************************************
//
//! @file HM01B0.h
//
//*****************************************************************************
#ifndef HM01B0_H
#define HM01B0_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"
#define HM01B0_DRV_VERSION (0)
#define HM01B0_DRV_SUBVERSION (5)
#define HM01B0_DEFAULT_ADDRESS (0x24)
#define HM01B0_PIXEL_X_NUM (324)
#define HM01B0_PIXEL_Y_NUM (244)
#define HM01B0_REG_MODEL_ID_H (0x0000)
#define HM01B0_REG_MODEL_ID_L (0x0001)
#define HM01B0_REG_SILICON_REV (0x0002)
#define HM01B0_REG_FRAME_COUNT (0x0005)
#define HM01B0_REG_PIXEL_ORDER (0x0006)
#define HM01B0_REG_MODE_SELECT (0x0100)
#define HM01B0_REG_IMAGE_ORIENTATION (0x0101)
#define HM01B0_REG_SW_RESET (0x0103)
#define HM01B0_REG_GRP_PARAM_HOLD (0x0104)
#define HM01B0_REG_INTEGRATION_H (0x0202)
#define HM01B0_REG_INTEGRATION_L (0x0203)
#define HM01B0_REG_ANALOG_GAIN (0x0205)
#define HM01B0_REG_DIGITAL_GAIN_H (0x020E)
#define HM01B0_REG_DIGITAL_GAIN_L (0x020F)
#define HM01B0_REG_AE_TARGET_MEAN (0x2101)
#define HM01B0_REG_AE_MIN_MEAN (0x2102)
#define HM01B0_REG_CONVERGE_IN_TH (0x2103)
#define HM01B0_REG_CONVERGE_OUT_TH (0x2104)
#define HM01B0_REG_I2C_ID_SEL (0x3400)
#define HM01B0_REG_I2C_ID_REG (0x3401)
#define HM01B0_REG_PMU_PROGRAMMABLE_FRAMECNT (0x3020)
// #define HM01B0_REG_MODE_SELECT (0x0100)
#define HM01B0_REG_MODE_SELECT_STANDBY (0x00)
#define HM01B0_REG_MODE_SELECT_STREAMING (0x01)
#define HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES (0x03)
#define HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER (0x05)
// #define HM01B0_REG_IMAGE_ORIENTATION (0x0101)
#define HM01B0_REG_IMAGE_ORIENTATION_DEFAULT (0x00)
#define HM01B0_REG_IMAGE_ORIENTATION_HMIRROR (0x01)
#define HM01B0_REG_IMAGE_ORIENTATION_VMIRROR (0x02)
#define HM01B0_REG_IMAGE_ORIENTATION_HVMIRROR (HM01B0_REG_IMAGE_ORIENTATION_HMIRROR | HM01B0_REG_IMAGE_ORIENTATION_HVMIRROR)
// #define HM01B0_REG_GRP_PARAM_HOLD (0x0104)
#define HM01B0_REG_GRP_PARAM_HOLD_CONSUME (0x00)
#define HM01B0_REG_GRP_PARAM_HOLD_HOLD (0x01)
enum
{
HM01B0_ERR_OK = 0x00,
HM01B0_ERR_I2C,
HM01B0_ERR_MODE,
HM01B0_ERR_AE_NOT_CONVERGED,
};
typedef struct
{
uint16_t ui16Reg;
uint8_t ui8Val;
} hm_script_t;
typedef struct
{
uint16_t ui16SlvAddr;
am_hal_iom_mode_e eIOMMode;
uint32_t ui32IOMModule;
am_hal_iom_config_t sIOMCfg;
void *pIOMHandle;
uint32_t ui32CTimerModule;
uint32_t ui32CTimerSegment;
uint32_t ui32CTimerOutputPin;
uint8_t ui8PinSCL;
uint8_t ui8PinSDA;
uint8_t ui8PinD0;
uint8_t ui8PinD1;
uint8_t ui8PinD2;
uint8_t ui8PinD3;
uint8_t ui8PinD4;
uint8_t ui8PinD5;
uint8_t ui8PinD6;
uint8_t ui8PinD7;
uint8_t ui8PinVSYNC;
uint8_t ui8PinHSYNC;
uint8_t ui8PinPCLK;
uint8_t ui8PinTrig;
uint8_t ui8PinInt;
void (*pfnGpioIsr)(void);
} hm01b0_cfg_t;
typedef struct
{
uint8_t ui8AETargetMean;
uint8_t ui8AEMinMean;
uint8_t ui8ConvergeInTh;
uint8_t ui8ConvergeOutTh;
uint8_t ui8AEMean;
} hm01b0_ae_cfg_t;
typedef struct
{
uint8_t ui8IntegrationH;
uint8_t ui8IntegrationL;
uint8_t ui8AGain;
uint8_t ui8DGain_H;
uint8_t ui8DGain_L;
} hm01b0_snr_expo_gain_ctrl_t;
//*****************************************************************************
//
//! @brief Write HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the data to be written.
//! @param ui32NumBytes - Length of the data in bytes to be written.
//!
//! This function writes value to HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_write_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes);
//*****************************************************************************
//
//! @brief Read HM01B0 registers
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui16Reg - Register address.
//! @param pui8Value - Pointer to the buffer for read data to be put into.
//! @param ui32NumBytes - Length of the data to be read.
//!
//! This function reads value from HM01B0 registers.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_read_reg(hm01b0_cfg_t *psCfg, \
uint16_t ui16Reg, uint8_t *pui8Value, uint32_t ui32NumBytes);
//*****************************************************************************
//
//! @brief Load HM01B0 a given script
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScrip - Pointer to the script to be loaded.
//! @param ui32ScriptCmdNum - Number of entries in a given script.
//!
//! This function loads HM01B0 a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_load_script(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum);
//*****************************************************************************
//
//! @brief Power up HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_up(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Power down HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function powers up HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_power_down(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Enable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function utilizes CTimer to generate MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_enable(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Disable MCLK
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function disable CTimer to stop MCLK for HM01B0.
//!
//! @return none.
//
//*****************************************************************************
void hm01b0_mclk_disable(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Initialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function initializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_if(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Deinitialize interfaces
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function deinitializes interfaces.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_deinit_if(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Get HM01B0 Model ID
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui16MID - Pointer to buffer for the read back model ID.
//!
//! This function reads back HM01B0 model ID.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_modelid(hm01b0_cfg_t *psCfg, uint16_t *pui16MID);
//*****************************************************************************
//
//! @brief Initialize HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psScript - Pointer to HM01B0 initialization script.
//! @param ui32ScriptCmdNum - No. of commands in HM01B0 initialization script.
//!
//! This function initilizes HM01B0 with a given script.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_init_system(hm01b0_cfg_t *psCfg, hm_script_t *psScript, uint32_t ui32ScriptCmdNum);
//*****************************************************************************
//
//! @brief Set HM01B0 in the walking 1s test mode
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_test_walking1s(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Check the data read from HM01B0 in the walking 1s test mode
//!
//! @param pui8Buffer - Pointer to data buffer.
//! @param ui32BufferLen - Buffer length
//! @param ui32PrintCnt - Number of mismatched data to be printed out
//!
//! This function sets HM01B0 in the walking 1s test mode.
//!
//! @return Error code.
//
//*****************************************************************************
void hm01b0_test_walking1s_check_data_sanity(uint8_t *pui8Buffer, uint32_t ui32BufferLen, uint32_t ui32PrintCnt);
//*****************************************************************************
//
//! @brief Software reset HM01B0
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! This function resets HM01B0 by issuing a reset command.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_reset_sw(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Get current HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Mode - Pointer to buffer
//! - for the read back operation mode to be put into
//!
//! This function get HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_mode(hm01b0_cfg_t *psCfg, uint8_t *pui8Mode);
//*****************************************************************************
//
//! @brief Set HM01B0 operation mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8Mode - Operation mode. One of:
//! HM01B0_REG_MODE_SELECT_STANDBY
//! HM01B0_REG_MODE_SELECT_STREAMING
//! HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES
//! HM01B0_REG_MODE_SELECT_STREAMING_HW_TRIGGER
//! @param framecnt - Frame count for HM01B0_REG_MODE_SELECT_STREAMING_NFRAMES.
//! - Discarded if other modes.
//!
//! This function set HM01B0 operation mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mode(hm01b0_cfg_t *psCfg, uint8_t ui8Mode, uint8_t framecnt);
//*****************************************************************************
//
//! @brief Activate the updated settings to HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//!
//! Some settings updated to HM01B0 will only be affected after calling this function
//! 1. AE settings
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cmd_update(hm01b0_cfg_t *psCfg);
//*****************************************************************************
//
//! @brief Get HM01B0 AE settings
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psAECfg - Pointer to the structure hm01b0_ae_cfg_t.
//!
//! This function checks if AE is converged or not and returns ui32Err accordingly.
//! If caller needs detailed AE settings, psAECfg has to be non NULL.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_get_ae(hm01b0_cfg_t *psCfg, hm01b0_ae_cfg_t *psAECfg);
//*****************************************************************************
//
//! @brief AE calibration.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param ui8CalFrames - Frame counts for calibratoin.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function lets HM01B0 AE settled as much as possible within a given frame counts.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_cal_ae(hm01b0_cfg_t *psCfg, uint8_t ui8CalFrames, uint8_t *pui8Buffer, uint32_t ui32BufferLen);
//*****************************************************************************
//
//! @brief Save HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function saves HM01B0 exposure gain settings.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_save_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl);
//*****************************************************************************
//
//! @brief Restore HM01B0 exposure gain settings.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param psExpoGainCtrl - Pointer to the structure hm01b0_snr_expo_gain_ctrl_t
//!
//! This function restores HM01B0 exposure gain settings. The call flow shall be
//! hm01b0_restore_exposure_gains() -> hm01b0_cmd_update() -> hm01b0_set_mode()
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_restore_exposure_gains(hm01b0_cfg_t *psCfg, hm01b0_snr_expo_gain_ctrl_t *psExpoGainCtrl);
//*****************************************************************************
//
//! @brief Hardware trigger HM01B0 to stream.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bTrigger - True to start streaming
//! - False to stop streaming
//!
//! This function triggers HM01B0 to stream by toggling the TRIG pin.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_hardware_trigger_streaming(hm01b0_cfg_t *psCfg, bool bTrigger);
//*****************************************************************************
//
//! @brief Set HM01B0 mirror mode.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param bHmirror - Horizontal mirror
//! @param bVmirror - Vertical mirror
//!
//! This function set HM01B0 mirror mode.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_set_mirror(hm01b0_cfg_t *psCfg, bool bHmirror, bool bVmirror);
//*****************************************************************************
//
//! @brief Read data of one frame from HM01B0.
//!
//! @param psCfg - Pointer to HM01B0 configuration structure.
//! @param pui8Buffer - Pointer to the frame buffer.
//! @param ui32BufferLen - Framebuffer size.
//!
//! This function read data of one frame from HM01B0.
//!
//! @return Error code.
//
//*****************************************************************************
uint32_t hm01b0_blocking_read_oneframe(hm01b0_cfg_t *psCfg, \
uint8_t *pui8Buffer, uint32_t ui32BufferLen);
#ifdef __cplusplus
}
#endif
#endif // AM_HAL_CTIMER_H
@@ -0,0 +1,233 @@
#include "HM01B0.h"
const hm_script_t sHM01B0InitScript[] =
{
// ;*************************************************************************
// ; Sensor: HM01B0
// ; I2C ID: 24
// ; Resolution: 324x244
// ; Lens:
// ; Flicker:
// ; Frequency:
// ; Description: AE control enable
// ; 8-bit mode, LSB first
// ;
// ;
// ; Note:
// ;
// ; $Revision: 1338 $
// ; $Date:: 2017-04-11 15:43:45 +0800#$
// ;*************************************************************************
//
// // ---------------------------------------------------
// // HUB system initial
// // ---------------------------------------------------
// W 20 8A04 01 2 1
// W 20 8A00 22 2 1
// W 20 8A01 00 2 1
// W 20 8A02 01 2 1
// W 20 0035 93 2 1 ; [3]&[1] hub616 20bits in, [5:4]=1 mclk=48/2=24mhz
// W 20 0036 00 2 1
// W 20 0011 09 2 1
// W 20 0012 B6 2 1
// W 20 0014 08 2 1
// W 20 0015 98 2 1
// ;W 20 0130 16 2 1 ; 3m soc, signal buffer control
// ;W 20 0100 44 2 1 ; [6] hub616 20bits in
// W 20 0100 04 2 1 ; [6] hub616 20bits in
// W 20 0121 01 2 1 ; [0] Q1 Intf enable, [1]:4bit mode, [2] msb first, [3] serial mode
// W 20 0150 00 2 1 ;
// W 20 0150 04 2 1 ;
//
//
// //---------------------------------------------------
// // Initial
// //---------------------------------------------------
// W 24 0103 00 2 1 ; software reset-> was 0x22
{0x0103, 0x00,},
// W 24 0100 00 2 1; power up
{0x0100, 0x00,},
//
//
//
// //---------------------------------------------------
// // Analog
// //---------------------------------------------------
// L HM01B0_analog_setting.txt
{0x1003, 0x08,},
{0x1007, 0x08,},
{0x3044, 0x0A,},
{0x3045, 0x00,},
{0x3047, 0x0A,},
{0x3050, 0xC0,},
{0x3051, 0x42,},
{0x3052, 0x50,},
{0x3053, 0x00,},
{0x3054, 0x03,},
{0x3055, 0xF7,},
{0x3056, 0xF8,},
{0x3057, 0x29,},
{0x3058, 0x1F,},
{0x3059, 0x1E,},
{0x3064, 0x00,},
{0x3065, 0x04,},
//
//
// //---------------------------------------------------
// // Digital function
// //---------------------------------------------------
//
// // BLC
// W 24 1000 43 2 1 ; BLC_on, IIR
{0x1000, 0x43,},
// W 24 1001 40 2 1 ; [6] : BLC dithering en
{0x1001, 0x40,},
// W 24 1002 32 2 1 ; // blc_darkpixel_thd
{0x1002, 0x32,},
//
// // Dgain
// W 24 0350 7F 2 1 ; Dgain Control
{0x0350, 0x7F,},
//
// // BLI
// W 24 1006 01 2 1 ; [0] : bli enable
{0x1006, 0x01,},
//
// // DPC
// W 24 1008 00 2 1 ; [2:0] : DPC option 0: DPC off 1 : mono 3 : bayer1 5 : bayer2
{0x1008, 0x00,},
// W 24 1009 A0 2 1 ; cluster hot pixel th
{0x1009, 0xA0,},
// W 24 100A 60 2 1 ; cluster cold pixel th
{0x100A, 0x60,},
// W 24 100B 90 2 1 ; single hot pixel th
{0x100B, 0x90,},
// W 24 100C 40 2 1 ; single cold pixel th
{0x100C, 0x40,},
// //
// advance VSYNC by 1 row
{0x3022, 0x01,},
// W 24 1012 00 2 1 ; Sync. enable VSYNC shift
{0x1012, 0x01,},
//
// // ROI Statistic
// W 24 2000 07 2 1 ; [0] : AE stat en [1] : MD LROI stat en [2] : MD GROI stat en [3] : RGB stat ratio en [4] : IIR selection (1 -> 16, 0 -> 8)
{0x2000, 0x07,},
// W 24 2003 00 2 1 ; MD GROI 0 y start HB
{0x2003, 0x00,},
// W 24 2004 1C 2 1 ; MD GROI 0 y start LB
{0x2004, 0x1C,},
// W 24 2007 00 2 1 ; MD GROI 1 y start HB
{0x2007, 0x00,},
// W 24 2008 58 2 1 ; MD GROI 1 y start LB
{0x2008, 0x58,},
// W 24 200B 00 2 1 ; MD GROI 2 y start HB
{0x200B, 0x00,},
// W 24 200C 7A 2 1 ; MD GROI 2 y start LB
{0x200C, 0x7A,},
// W 24 200F 00 2 1 ; MD GROI 3 y start HB
{0x200F, 0x00,},
// W 24 2010 B8 2 1 ; MD GROI 3 y start LB
{0x2010, 0xB8,},
//
// W 24 2013 00 2 1 ; MD LRIO y start HB
{0x2013, 0x00,},
// W 24 2014 58 2 1 ; MD LROI y start LB
{0x2014, 0x58,},
// W 24 2017 00 2 1 ; MD LROI y end HB
{0x2017, 0x00,},
// W 24 2018 9B 2 1 ; MD LROI y end LB
{0x2018, 0x9B,},
//
// // AE
// W 24 2100 01 2 1 ; [0]: AE control enable
{0x2100, 0x01,},
// W 24 2104 07 2 1 ; converge out th
{0x2104, 0x07,},
// W 24 2105 0C 2 1 ; max INTG Hb
{0x2105, 0x0C,},
// W 24 2106 78 2 1 ; max INTG Lb
{0x2106, 0x78,},
// W 24 2108 03 2 1 ; max AGain in full
{0x2108, 0x03,},
// W 24 2109 03 2 1 ; max AGain in bin2
{0x2109, 0x03,},
// W 24 210B 80 2 1 ; max DGain
{0x210B, 0x80,},
// W 24 210F 00 2 1 ; FS 60Hz Hb
{0x210F, 0x00,},
// W 24 2110 85 2 1 ; FS 60Hz Lb
{0x2110, 0x85,},
// W 24 2111 00 2 1 ; Fs 50Hz Hb
{0x2111, 0x00,},
// W 24 2112 A0 2 1 ; FS 50Hz Lb
{0x2112, 0xA0,},
//
//
// // MD
// W 24 2150 03 2 1 ; [0] : MD LROI en [1] : MD GROI en
{0x2150, 0x03,},
//
//
// //---------------------------------------------------
// // frame rate : 5 FPS
// //---------------------------------------------------
// W 24 0340 0C 2 1 ; smia frame length Hb
{0x0340, 0x0C,},
// W 24 0341 7A 2 1 ; smia frame length Lb 3192
{0x0341, 0x7A,},
//
// W 24 0342 01 2 1 ; smia line length Hb
{0x0342, 0x01,},
// W 24 0343 77 2 1 ; smia line length Lb 375
{0x0343, 0x77,},
//
// //---------------------------------------------------
// // Resolution : QVGA 324x244
// //---------------------------------------------------
// W 24 3010 01 2 1 ; [0] : window mode 0 : full frame 324x324 1 : QVGA
{0x3010, 0x01,},
//
//
// W 24 0383 01 2 1 ;
{0x0383, 0x01,},
// W 24 0387 01 2 1 ;
{0x0387, 0x01,},
// W 24 0390 00 2 1 ;
{0x0390, 0x00,},
//
// //---------------------------------------------------
// // bit width Selection
// //---------------------------------------------------
// W 24 3011 70 2 1 ; [0] : 6 bit mode enable
{0x3011, 0x70,},
//
//
// W 24 3059 02 2 1 ; [7]: Self OSC En, [6]: 4bit mode, [5]: serial mode, [4:0]: keep value as 0x02
{0x3059, 0x02,},
// W 24 3060 01 2 1 ; [5]: gated_clock, [4]: msb first,
{0x3060, 0x20,},
// ; [3:2]: vt_reg_div -> div by 4/8/1/2
// ; [1;0]: vt_sys_div -> div by 8/4/2/1
//
//
{0x0101, 0x01,},
// //---------------------------------------------------
// // CMU update
// //---------------------------------------------------
//
// W 24 0104 01 2 1 ; was 0100
{0x0104, 0x01,},
//
//
//
// //---------------------------------------------------
// // Turn on rolling shutter
// //---------------------------------------------------
// W 24 0100 01 2 1 ; was 0005 ; mode_select 00 : standby - wait fir I2C SW trigger 01 : streaming 03 : output "N" frame, then enter standby 04 : standby - wait for HW trigger (level), then continuous video out til HW TRIG goes off 06 : standby - wait for HW trigger (edge), then output "N" frames then enter standby
{0x0100, 0x00,},
//
// ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
};
@@ -0,0 +1,14 @@
#include "HM01B0.h"
const hm_script_t sHM01b0TestModeScript_Walking1s[] =
{
{0x2100, 0x00,}, //W 24 2100 00 2 1 ; AE
{0x1000, 0x00,}, //W 24 1000 00 2 1 ; BLC
{0x1008, 0x00,}, //W 24 1008 00 2 1 ; DPC
{0x0205, 0x00,}, //W 24 0205 00 2 1 ; AGain
{0x020E, 0x01,}, //W 24 020E 01 2 1 ; DGain
{0x020F, 0x00,}, //W 24 020F 00 2 1 ; DGain
{0x0601, 0x11,}, //W 24 0601 11 2 1 ; Test pattern
{0x0104, 0x01,}, //W 24 0104 01 2 1 ;
};
@@ -0,0 +1,73 @@
// based on demo from Himax
/*
Copyright (c) 2019 SparkFun Electronics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef HM01B0_PLATFORM_H
#define HM01B0_PLATFORM_H
#ifdef __cplusplus
extern "C"
{
#endif
#define HM01B0_PIN_D0 AM_BSP_GPIO_CAMERA_HM01B0_D0
#define HM01B0_PIN_D1 AM_BSP_GPIO_CAMERA_HM01B0_D1
#define HM01B0_PIN_D2 AM_BSP_GPIO_CAMERA_HM01B0_D2
#define HM01B0_PIN_D3 AM_BSP_GPIO_CAMERA_HM01B0_D3
#define HM01B0_PIN_D4 AM_BSP_GPIO_CAMERA_HM01B0_D4
#define HM01B0_PIN_D5 AM_BSP_GPIO_CAMERA_HM01B0_D5
#define HM01B0_PIN_D6 AM_BSP_GPIO_CAMERA_HM01B0_D6
#define HM01B0_PIN_D7 AM_BSP_GPIO_CAMERA_HM01B0_D7
#define HM01B0_PIN_VSYNC AM_BSP_GPIO_CAMERA_HM01B0_VSYNC
#define HM01B0_PIN_HSYNC AM_BSP_GPIO_CAMERA_HM01B0_HSYNC
#define HM01B0_PIN_PCLK AM_BSP_GPIO_CAMERA_HM01B0_PCLK
#define HM01B0_PIN_SCL AM_BSP_CAMERA_HM01B0_I2C_SCL_PIN
#define HM01B0_PIN_SDA AM_BSP_CAMERA_HM01B0_I2C_SDA_PIN
// Some boards do not support TRIG or INT pins
#ifdef AM_BSP_GPIO_CAMERA_HM01B0_TRIG
#define HM01B0_PIN_TRIG AM_BSP_GPIO_CAMERA_HM01B0_TRIG
#endif // AM_BSP_GPIO_CAMERA_HM01B0_TRIG
#ifdef AM_BSP_GPIO_CAMERA_HM01B0_INT
#define HM01B0_PIN_INT AM_BSP_GPIO_CAMERA_HM01B0_INT
#endif // AM_BSP_GPIO_CAMERA_HM01B0_INT
// Define AP3B's CTIMER and output pin for HM01B0 MCLK generation
#define HM01B0_MCLK_GENERATOR_MOD AM_BSP_CAMERA_HM01B0_MCLK_GEN_MOD
#define HM01B0_MCLK_GENERATOR_SEG AM_BSP_CAMERA_HM01B0_MCLK_GEN_SEG
#define HM01B0_PIN_MCLK AM_BSP_CAMERA_HM01B0_MCLK_PIN
// Deifne I2C controller and SCL(pin8)/SDA(pin9) are configured automatically.
#define HM01B0_IOM_MODE AM_HAL_IOM_I2C_MODE
#define HM01B0_IOM_MODULE AM_BSP_CAMERA_HM01B0_I2C_IOM
#define HM01B0_I2C_CLOCK_FREQ AM_HAL_IOM_100KHZ
#ifdef __cplusplus
}
#endif
#endif // HM01B0_PLATFORM_H