Add sparkfun_edge platform support for micro_vision example.
PiperOrigin-RevId: 257286154
This commit is contained in:
parent
3b753303b1
commit
1ef629438e
@ -75,11 +75,6 @@ static hm01b0_cfg_t s_HM01B0Cfg = {
|
||||
pfnGpioIsr : NULL,
|
||||
};
|
||||
|
||||
static constexpr int kDebugRowLenElements = 16;
|
||||
// Each byte takes two characters plus a space, and the offset takes an
|
||||
// additional 8 characters plus a space.
|
||||
static constexpr int kDebugLineLenBytes = kDebugRowLenElements * 3 + 9;
|
||||
|
||||
bool g_is_camera_initialized = false;
|
||||
|
||||
void boost_mode_enable(tflite::ErrorReporter* error_reporter, bool bEnable) {
|
||||
|
@ -35,6 +35,7 @@ extern "C" {
|
||||
#define HM01B0_PIN_INT 4
|
||||
#define HM01B0_PIN_SCL 8
|
||||
#define HM01B0_PIN_SDA 9
|
||||
#define HM01B0_PIN_DVDD_EN 10
|
||||
|
||||
// Define AP3B's CTIMER and output pin for HM01B0 MCLK generation
|
||||
#define HM01B0_MCLK_GENERATOR_MOD 0
|
||||
|
@ -0,0 +1,199 @@
|
||||
/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
==============================================================================*/
|
||||
|
||||
#include "tensorflow/lite/experimental/micro/examples/micro_vision/image_provider.h"
|
||||
|
||||
#include "tensorflow/lite/experimental/micro/examples/micro_vision/himax_driver/HM01B0.h"
|
||||
#include "tensorflow/lite/experimental/micro/examples/micro_vision/himax_driver/HM01B0_RAW8_QVGA_8bits_lsb_5fps.h"
|
||||
#include "tensorflow/lite/experimental/micro/examples/micro_vision/himax_driver/HM01B0_debug.h"
|
||||
#include "tensorflow/lite/experimental/micro/examples/micro_vision/himax_driver/HM01B0_optimized.h"
|
||||
#include "tensorflow/lite/experimental/micro/examples/micro_vision/himax_driver/platform_Sparkfun_Edge.h"
|
||||
|
||||
// These are headers from Ambiq's Apollo3 SDK.
|
||||
#include "am_bsp.h" // NOLINT
|
||||
#include "am_mcu_apollo.h" // NOLINT
|
||||
#include "am_util.h" // NOLINT
|
||||
|
||||
// #define DEMO_HM01B0_FRAMEBUFFER_DUMP_ENABLE
|
||||
|
||||
// Enabling logging increases power consumption by preventing low power mode
|
||||
// from being enabled.
|
||||
#define ENABLE_LOGGING
|
||||
|
||||
namespace {
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// HM01B0 Configuration
|
||||
//
|
||||
//*****************************************************************************
|
||||
static hm01b0_cfg_t s_HM01B0Cfg = {
|
||||
// i2c settings
|
||||
ui16SlvAddr : HM01B0_DEFAULT_ADDRESS,
|
||||
eIOMMode : HM01B0_IOM_MODE,
|
||||
ui32IOMModule : HM01B0_IOM_MODULE,
|
||||
sIOMCfg : {
|
||||
eInterfaceMode : HM01B0_IOM_MODE,
|
||||
ui32ClockFreq : HM01B0_I2C_CLOCK_FREQ,
|
||||
},
|
||||
pIOMHandle : NULL,
|
||||
|
||||
// MCLK settings
|
||||
ui32CTimerModule : HM01B0_MCLK_GENERATOR_MOD,
|
||||
ui32CTimerSegment : HM01B0_MCLK_GENERATOR_SEG,
|
||||
ui32CTimerOutputPin : HM01B0_PIN_MCLK,
|
||||
|
||||
// data interface
|
||||
ui8PinSCL : HM01B0_PIN_SCL,
|
||||
ui8PinSDA : HM01B0_PIN_SDA,
|
||||
ui8PinD0 : HM01B0_PIN_D0,
|
||||
ui8PinD1 : HM01B0_PIN_D1,
|
||||
ui8PinD2 : HM01B0_PIN_D2,
|
||||
ui8PinD3 : HM01B0_PIN_D3,
|
||||
ui8PinD4 : HM01B0_PIN_D4,
|
||||
ui8PinD5 : HM01B0_PIN_D5,
|
||||
ui8PinD6 : HM01B0_PIN_D6,
|
||||
ui8PinD7 : HM01B0_PIN_D7,
|
||||
ui8PinVSYNC : HM01B0_PIN_VSYNC,
|
||||
ui8PinHSYNC : HM01B0_PIN_HSYNC,
|
||||
ui8PinPCLK : HM01B0_PIN_PCLK,
|
||||
|
||||
ui8PinTrig : HM01B0_PIN_TRIG,
|
||||
ui8PinInt : HM01B0_PIN_INT,
|
||||
pfnGpioIsr : NULL,
|
||||
};
|
||||
|
||||
bool g_is_camera_initialized = false;
|
||||
|
||||
void boost_mode_enable(tflite::ErrorReporter* error_reporter, bool bEnable) {
|
||||
am_hal_burst_avail_e eBurstModeAvailable;
|
||||
am_hal_burst_mode_e eBurstMode;
|
||||
|
||||
// Check that the Burst Feature is available.
|
||||
if (AM_HAL_STATUS_SUCCESS ==
|
||||
am_hal_burst_mode_initialize(&eBurstModeAvailable)) {
|
||||
if (AM_HAL_BURST_AVAIL == eBurstModeAvailable) {
|
||||
error_reporter->Report("Apollo3 Burst Mode is Available\n");
|
||||
} else {
|
||||
error_reporter->Report("Apollo3 Burst Mode is Not Available\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
error_reporter->Report("Failed to Initialize for Burst Mode operation\n");
|
||||
}
|
||||
|
||||
// Make sure we are in "Normal" mode.
|
||||
if (AM_HAL_STATUS_SUCCESS == am_hal_burst_mode_disable(&eBurstMode)) {
|
||||
if (AM_HAL_NORMAL_MODE == eBurstMode) {
|
||||
error_reporter->Report("Apollo3 operating in Normal Mode (48MHz)\n");
|
||||
}
|
||||
} else {
|
||||
error_reporter->Report("Failed to Disable Burst Mode operation\n");
|
||||
}
|
||||
|
||||
// Put the MCU into "Burst" mode.
|
||||
if (bEnable) {
|
||||
if (AM_HAL_STATUS_SUCCESS == am_hal_burst_mode_enable(&eBurstMode)) {
|
||||
if (AM_HAL_BURST_MODE == eBurstMode) {
|
||||
error_reporter->Report("Apollo3 operating in Burst Mode (96MHz)\n");
|
||||
}
|
||||
} else {
|
||||
error_reporter->Report("Failed to Enable Burst Mode operation\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TfLiteStatus InitCamera(tflite::ErrorReporter* error_reporter) {
|
||||
// Enable the ITM print interface.
|
||||
am_bsp_itm_printf_enable();
|
||||
|
||||
error_reporter->Report("Initializing HM01B0...\n");
|
||||
|
||||
am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0);
|
||||
|
||||
// Set the default cache configuration
|
||||
am_hal_cachectrl_config(&am_hal_cachectrl_defaults);
|
||||
am_hal_cachectrl_enable();
|
||||
|
||||
// Configure the board for low power operation. This breaks logging by
|
||||
// turning off the itm and uart interfaces.
|
||||
#ifndef ENABLE_LOGGING
|
||||
am_bsp_low_power_init();
|
||||
#endif
|
||||
|
||||
// Enable interrupts so we can receive messages from the boot host.
|
||||
am_hal_interrupt_master_enable();
|
||||
|
||||
boost_mode_enable(error_reporter, true);
|
||||
|
||||
// Turn on the 1.8V regulator for DVDD on the camera.
|
||||
am_hal_gpio_pinconfig(HM01B0_PIN_DVDD_EN, g_AM_HAL_GPIO_OUTPUT_12);
|
||||
am_hal_gpio_output_set(HM01B0_PIN_DVDD_EN);
|
||||
|
||||
hm01b0_power_up(&s_HM01B0Cfg);
|
||||
|
||||
// TODO(njeff): check the delay time to just fit the spec.
|
||||
am_util_delay_ms(1);
|
||||
|
||||
hm01b0_mclk_enable(&s_HM01B0Cfg);
|
||||
|
||||
// TODO(njeff): check the delay time to just fit the spec.
|
||||
am_util_delay_ms(1);
|
||||
|
||||
hm01b0_init_if(&s_HM01B0Cfg);
|
||||
|
||||
hm01b0_init_system(&s_HM01B0Cfg, (hm_script_t*)sHM01B0InitScript,
|
||||
sizeof(sHM01B0InitScript) / sizeof(hm_script_t));
|
||||
|
||||
// Put camera into streaming mode - this makes it so that the camera
|
||||
// constantly captures images. It is still OK to read and image since the
|
||||
// camera uses a double-buffered input. This means there is always one valid
|
||||
// image to read while the other buffer fills. Streaming mode allows the
|
||||
// camera to perform auto exposure constantly.
|
||||
am_hal_gpio_output_clear(AM_BSP_GPIO_LED_RED);
|
||||
uint32_t error_code =
|
||||
hm01b0_set_mode(&s_HM01B0Cfg, HM01B0_REG_MODE_SELECT_STREAMING, 0);
|
||||
if (error_code == HM01B0_ERR_OK) {
|
||||
am_hal_gpio_output_set(AM_BSP_GPIO_LED_RED);
|
||||
|
||||
return kTfLiteError;
|
||||
}
|
||||
|
||||
return kTfLiteOk;
|
||||
}
|
||||
|
||||
// Capture single frame. Frame pointer passed in to reduce memory usage. This
|
||||
// allows the input tensor to be used instead of requiring an extra copy.
|
||||
TfLiteStatus GetImage(tflite::ErrorReporter* error_reporter, int frame_width,
|
||||
int frame_height, int channels, uint8_t* frame) {
|
||||
if (!g_is_camera_initialized) {
|
||||
TfLiteStatus init_status = InitCamera(error_reporter);
|
||||
if (init_status != kTfLiteOk) {
|
||||
return init_status;
|
||||
}
|
||||
g_is_camera_initialized = true;
|
||||
}
|
||||
|
||||
hm01b0_blocking_read_oneframe_scaled(frame, frame_width, frame_height,
|
||||
channels);
|
||||
|
||||
#ifdef DEMO_HM01B0_FRAMEBUFFER_DUMP_ENABLE
|
||||
hm01b0_framebuffer_dump(frame, frame_width * frame_height * channels);
|
||||
#endif
|
||||
|
||||
return kTfLiteOk;
|
||||
}
|
Loading…
Reference in New Issue
Block a user