diff --git a/README.md b/README.md
index b90f660e..990e8606 100644
--- a/README.md
+++ b/README.md
@@ -69,6 +69,15 @@ In other cases you can contact the developer via email:
RAW Bayer
RGB565 | 1/6.5" |
| GC2145 | 1600 x 1200 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/5" |
| BF3005 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer
RGB565 | 1/4" |
+| BF20A6 | 640 x 480 | color | YUV/YCbCr422
RAW Bayer | 1/10" |
+| SC101IOT| 1280 x 720 | color | YUV/YCbCr422
Raw RGB | 1/4.2" |
+| SC030IOT| 640 x 480 | color | YUV/YCbCr422
RAW Bayer | 1/6.5" |
## Important to Remember
@@ -128,8 +131,8 @@ static camera_config_t camera_config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
- .pin_sscb_sda = CAM_PIN_SIOD,
- .pin_sscb_scl = CAM_PIN_SIOC,
+ .pin_sccb_sda = CAM_PIN_SIOD,
+ .pin_sccb_scl = CAM_PIN_SIOC,
.pin_d7 = CAM_PIN_D7,
.pin_d6 = CAM_PIN_D6,
diff --git a/code/components/esp32-camera-master/conversions/esp_jpg_decode.c b/code/components/esp32-camera-master/conversions/esp_jpg_decode.c
index a9615e36..52833a73 100644
--- a/code/components/esp32-camera-master/conversions/esp_jpg_decode.c
+++ b/code/components/esp32-camera-master/conversions/esp_jpg_decode.c
@@ -21,6 +21,10 @@
#include "tjpgd.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/tjpgd.h"
+#elif CONFIG_IDF_TARGET_ESP32C3
+#include "esp32c3/rom/tjpgd.h"
+#elif CONFIG_IDF_TARGET_ESP32H2
+#include "esp32h2/rom/tjpgd.h"
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif
@@ -57,7 +61,7 @@ static const char * jd_errors[] = {
"Not supported JPEG standard"
};
-static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
+static unsigned int _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
{
uint16_t x = rect->left;
uint16_t y = rect->top;
@@ -73,7 +77,7 @@ static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
return 0;
}
-static uint32_t _jpg_read(JDEC *decoder, uint8_t *buf, uint32_t len)
+static unsigned int _jpg_read(JDEC *decoder, uint8_t *buf, unsigned int len)
{
esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device;
if (jpeg->len && len > (jpeg->len - jpeg->index)) {
diff --git a/code/components/esp32-camera-master/conversions/jpge.cpp b/code/components/esp32-camera-master/conversions/jpge.cpp
index a8ab93e0..dd6790e6 100644
--- a/code/components/esp32-camera-master/conversions/jpge.cpp
+++ b/code/components/esp32-camera-master/conversions/jpge.cpp
@@ -29,7 +29,12 @@ namespace jpge {
if(b){
return b;
}
+ // check if SPIRAM is enabled and allocate on SPIRAM if allocatable
+#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
return heap_caps_malloc(nSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+#else
+ return NULL;
+#endif
}
static inline void jpge_free(void *p) { free(p); }
diff --git a/code/components/esp32-camera-master/conversions/to_bmp.c b/code/components/esp32-camera-master/conversions/to_bmp.c
index 5a54bdba..27072f71 100644
--- a/code/components/esp32-camera-master/conversions/to_bmp.c
+++ b/code/components/esp32-camera-master/conversions/to_bmp.c
@@ -21,19 +21,6 @@
#include "esp_jpg_decode.h"
#include "esp_system.h"
-#if ESP_IDF_VERSION_MAJOR >= 4 // IDF 4+
-#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
-#include "esp32/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/spiram.h"
-#else
-#error Target CONFIG_IDF_TARGET is not supported
-#endif
-#else // ESP32 Before IDF 4.0
-#include "esp_spiram.h"
-#endif
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
#include "esp32-hal-log.h"
@@ -72,7 +59,12 @@ typedef struct {
static void *_malloc(size_t size)
{
+ // check if SPIRAM is enabled and allocate on SPIRAM if allocatable
+#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+#endif
+ // try allocating in internal memory
+ return malloc(size);
}
//output buffer and image width
@@ -168,7 +160,7 @@ static bool _rgb565_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16
}
//input buffer
-static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
+static unsigned int _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
{
rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
if(buf) {
@@ -310,7 +302,13 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
*out_len = 0;
int pix_count = width*height;
- size_t out_size = (pix_count * 3) + BMP_HEADER_LEN;
+
+ // With BMP, 8-bit greyscale requires a palette.
+ // For a 640x480 image though, that's a savings
+ // over going RGB-24.
+ int bpp = (format == PIXFORMAT_GRAYSCALE) ? 1 : 3;
+ int palette_size = (format == PIXFORMAT_GRAYSCALE) ? 4 * 256 : 0;
+ size_t out_size = (pix_count * bpp) + BMP_HEADER_LEN + palette_size;
uint8_t * out_buf = (uint8_t *)_malloc(out_size);
if(!out_buf) {
ESP_LOGE(TAG, "_malloc failed! %u", out_size);
@@ -322,45 +320,51 @@ bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixf
bmp_header_t * bitmap = (bmp_header_t*)&out_buf[2];
bitmap->reserved = 0;
bitmap->filesize = out_size;
- bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN;
+ bitmap->fileoffset_to_pixelarray = BMP_HEADER_LEN + palette_size;
bitmap->dibheadersize = 40;
bitmap->width = width;
bitmap->height = -height;//set negative for top to bottom
bitmap->planes = 1;
- bitmap->bitsperpixel = 24;
+ bitmap->bitsperpixel = bpp * 8;
bitmap->compression = 0;
- bitmap->imagesize = pix_count * 3;
+ bitmap->imagesize = pix_count * bpp;
bitmap->ypixelpermeter = 0x0B13 ; //2835 , 72 DPI
bitmap->xpixelpermeter = 0x0B13 ; //2835 , 72 DPI
bitmap->numcolorspallette = 0;
bitmap->mostimpcolor = 0;
- uint8_t * rgb_buf = out_buf + BMP_HEADER_LEN;
+ uint8_t * palette_buf = out_buf + BMP_HEADER_LEN;
+ uint8_t * pix_buf = palette_buf + palette_size;
uint8_t * src_buf = src;
+ if (palette_size > 0) {
+ // Grayscale palette
+ for (int i = 0; i < 256; ++i) {
+ for (int j = 0; j < 3; ++j) {
+ *palette_buf = i;
+ palette_buf++;
+ }
+ // Reserved / alpha channel.
+ *palette_buf = 0;
+ palette_buf++;
+ }
+ }
//convert data to RGB888
if(format == PIXFORMAT_RGB888) {
- memcpy(rgb_buf, src_buf, pix_count*3);
+ memcpy(pix_buf, src_buf, pix_count*3);
} else if(format == PIXFORMAT_RGB565) {
int i;
uint8_t hb, lb;
for(i=0; i> 3;
- *rgb_buf++ = hb & 0xF8;
+ *pix_buf++ = (lb & 0x1F) << 3;
+ *pix_buf++ = (hb & 0x07) << 5 | (lb & 0xE0) >> 3;
+ *pix_buf++ = hb & 0xF8;
}
} else if(format == PIXFORMAT_GRAYSCALE) {
- int i;
- uint8_t b;
- for(i=0; i= 4 // IDF 4+
-#if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4
-#include "esp32/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/spiram.h"
-#elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/spiram.h"
-#else
-#error Target CONFIG_IDF_TARGET is not supported
-#endif
-#else // ESP32 Before IDF 4.0
-#include "esp_spiram.h"
-#endif
-
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
#include "esp32-hal-log.h"
#define TAG ""
@@ -50,7 +35,12 @@ static void *_malloc(size_t size)
if(res) {
return res;
}
+
+ // check if SPIRAM is enabled and is allocatable
+#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
+#endif
+ return NULL;
}
static IRAM_ATTR void convert_line_format(uint8_t * src, pixformat_t format, uint8_t * dst, size_t width, size_t in_channels, size_t line)
diff --git a/code/components/esp32-camera-master/driver/cam_hal.c b/code/components/esp32-camera-master/driver/cam_hal.c
index 9b7e12b5..27f66b68 100644
--- a/code/components/esp32-camera-master/driver/cam_hal.c
+++ b/code/components/esp32-camera-master/driver/cam_hal.c
@@ -18,8 +18,27 @@
#include "ll_cam.h"
#include "cam_hal.h"
-static const char *TAG = "cam_hal";
+#if (ESP_IDF_VERSION_MAJOR == 3) && (ESP_IDF_VERSION_MINOR == 3)
+#include "rom/ets_sys.h"
+#else
+#include "esp_timer.h"
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/rom/ets_sys.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/rom/ets_sys.h"
+#endif
+#endif // ESP_IDF_VERSION_MAJOR
+#define ESP_CAMERA_ETS_PRINTF ets_printf
+#if CONFIG_CAM_TASK_STACK_SIZE
+#define CAM_TASK_STACK CONFIG_CAM_TASK_STACK_SIZE
+#else
+#define CAM_TASK_STACK (2*1024)
+#endif
+
+static const char *TAG = "cam_hal";
static cam_obj_t *cam_obj = NULL;
static const uint32_t JPEG_SOI_MARKER = 0xFFD8FF; // written in little-endian for esp32
@@ -32,7 +51,7 @@ static int cam_verify_jpeg_soi(const uint8_t *inbuf, uint32_t length)
for (uint32_t i = 0; i < length; i++) {
sig = *((uint32_t *)(&inbuf[i])) & 0xFFFFFF;
if (sig == JPEG_SOI_MARKER) {
- ESP_LOGW(TAG, "SOI: %d", i);
+ ESP_LOGW(TAG, "SOI: %d", (int) i);
return i;
}
}
@@ -93,7 +112,7 @@ void IRAM_ATTR ll_cam_send_event(cam_obj_t *cam, cam_event_t cam_event, BaseType
if (xQueueSendFromISR(cam->event_queue, (void *)&cam_event, HPTaskAwoken) != pdTRUE) {
ll_cam_stop(cam);
cam->state = CAM_STATE_IDLE;
- ESP_EARLY_LOGE(TAG, "EV-%s-OVF", cam_event==CAM_IN_SUC_EOF_EVENT ? "EOF" : "VSYNC");
+ ESP_CAMERA_ETS_PRINTF(DRAM_STR("cam_hal: EV-%s-OVF\r\n"), cam_event==CAM_IN_SUC_EOF_EVENT ? DRAM_STR("EOF") : DRAM_STR("VSYNC"));
}
}
@@ -104,7 +123,7 @@ static void cam_task(void *arg)
int frame_pos = 0;
cam_obj->state = CAM_STATE_IDLE;
cam_event_t cam_event = 0;
-
+
xQueueReset(cam_obj->event_queue);
while (1) {
@@ -127,7 +146,7 @@ static void cam_task(void *arg)
case CAM_STATE_READ_BUF: {
camera_fb_t * frame_buffer_event = &cam_obj->frames[frame_pos].fb;
size_t pixels_per_dma = (cam_obj->dma_half_buffer_size * cam_obj->fb_bytes_per_pixel) / (cam_obj->dma_bytes_per_item * cam_obj->in_bytes_per_pixel);
-
+
if (cam_event == CAM_IN_SUC_EOF_EVENT) {
if(!cam_obj->psram_mode){
if (cam_obj->fb_size < (frame_buffer_event->len + pixels_per_dma)) {
@@ -137,8 +156,8 @@ static void cam_task(void *arg)
continue;
}
frame_buffer_event->len += ll_cam_memcpy(cam_obj,
- &frame_buffer_event->buf[frame_buffer_event->len],
- &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
+ &frame_buffer_event->buf[frame_buffer_event->len],
+ &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
cam_obj->dma_half_buffer_size);
}
//Check for JPEG SOI in the first buffer. stop if not found
@@ -160,8 +179,8 @@ static void cam_task(void *arg)
cnt--;
} else {
frame_buffer_event->len += ll_cam_memcpy(cam_obj,
- &frame_buffer_event->buf[frame_buffer_event->len],
- &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
+ &frame_buffer_event->buf[frame_buffer_event->len],
+ &cam_obj->dma_buffer[(cnt % cam_obj->dma_half_buffer_cnt) * cam_obj->dma_half_buffer_size],
cam_obj->dma_half_buffer_size);
}
}
@@ -179,7 +198,7 @@ static void cam_task(void *arg)
} else if (!cam_obj->jpeg_mode) {
if (frame_buffer_event->len != cam_obj->fb_size) {
cam_obj->frames[frame_pos].en = 1;
- ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, cam_obj->fb_size);
+ ESP_LOGE(TAG, "FB-SIZE: %u != %u", frame_buffer_event->len, (unsigned) cam_obj->fb_size);
}
}
//send frame
@@ -245,8 +264,9 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
cam_obj->dma_node_cnt = (cam_obj->dma_buffer_size) / cam_obj->dma_node_buffer_size; // Number of DMA nodes
cam_obj->frame_copy_cnt = cam_obj->recv_size / cam_obj->dma_half_buffer_size; // Number of interrupted copies, ping-pong copy
- ESP_LOGI(TAG, "buffer_size: %d, half_buffer_size: %d, node_buffer_size: %d, node_cnt: %d, total_cnt: %d",
- cam_obj->dma_buffer_size, cam_obj->dma_half_buffer_size, cam_obj->dma_node_buffer_size, cam_obj->dma_node_cnt, cam_obj->frame_copy_cnt);
+ ESP_LOGI(TAG, "buffer_size: %d, half_buffer_size: %d, node_buffer_size: %d, node_cnt: %d, total_cnt: %d",
+ (int) cam_obj->dma_buffer_size, (int) cam_obj->dma_half_buffer_size, (int) cam_obj->dma_node_buffer_size,
+ (int) cam_obj->dma_node_cnt, (int) cam_obj->frame_copy_cnt);
cam_obj->dma_buffer = NULL;
cam_obj->dma = NULL;
@@ -276,13 +296,19 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
cam_obj->frames[x].fb_offset = 0;
cam_obj->frames[x].en = 0;
ESP_LOGI(TAG, "Allocating %d Byte frame buffer in %s", alloc_size, _caps & MALLOC_CAP_SPIRAM ? "PSRAM" : "OnBoard RAM");
+#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 3, 0)
+ // In IDF v4.2 and earlier, memory returned by heap_caps_aligned_alloc must be freed using heap_caps_aligned_free.
+ // And heap_caps_aligned_free is deprecated on v4.3.
+ cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_aligned_alloc(16, alloc_size, _caps);
+#else
cam_obj->frames[x].fb.buf = (uint8_t *)heap_caps_malloc(alloc_size, _caps);
+#endif
CAM_CHECK(cam_obj->frames[x].fb.buf != NULL, "frame buffer malloc failed", ESP_FAIL);
if (cam_obj->psram_mode) {
//align PSRAM buffer. TODO: save the offset so proper address can be freed later
cam_obj->frames[x].fb_offset = dma_align - ((uint32_t)cam_obj->frames[x].fb.buf & (dma_align - 1));
cam_obj->frames[x].fb.buf += cam_obj->frames[x].fb_offset;
- ESP_LOGI(TAG, "Frame[%d]: Offset: %u, Addr: 0x%08X", x, cam_obj->frames[x].fb_offset, (uint32_t)cam_obj->frames[x].fb.buf);
+ ESP_LOGI(TAG, "Frame[%d]: Offset: %u, Addr: 0x%08X", x, cam_obj->frames[x].fb_offset, (unsigned) cam_obj->frames[x].fb.buf);
cam_obj->frames[x].dma = allocate_dma_descriptors(cam_obj->dma_node_cnt, cam_obj->dma_node_buffer_size, cam_obj->frames[x].fb.buf);
CAM_CHECK(cam_obj->frames[x].dma != NULL, "frame dma malloc failed", ESP_FAIL);
}
@@ -292,8 +318,8 @@ static esp_err_t cam_dma_config(const camera_config_t *config)
if (!cam_obj->psram_mode) {
cam_obj->dma_buffer = (uint8_t *)heap_caps_malloc(cam_obj->dma_buffer_size * sizeof(uint8_t), MALLOC_CAP_DMA);
if(NULL == cam_obj->dma_buffer) {
- ESP_LOGE(TAG,"%s(%d): DMA buffer %d Byte malloc failed, the current largest free block:%d Byte", __FUNCTION__, __LINE__,
- cam_obj->dma_buffer_size, heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
+ ESP_LOGE(TAG,"%s(%d): DMA buffer %d Byte malloc failed, the current largest free block:%d Byte", __FUNCTION__, __LINE__,
+ (int) cam_obj->dma_buffer_size, (int) heap_caps_get_largest_free_block(MALLOC_CAP_DMA));
return ESP_FAIL;
}
@@ -359,7 +385,7 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint
cam_obj->recv_size = cam_obj->width * cam_obj->height * cam_obj->in_bytes_per_pixel;
cam_obj->fb_size = cam_obj->width * cam_obj->height * cam_obj->fb_bytes_per_pixel;
}
-
+
ret = cam_dma_config(config);
CAM_CHECK_GOTO(ret == ESP_OK, "cam_dma_config failed", err);
@@ -376,13 +402,13 @@ esp_err_t cam_config(const camera_config_t *config, framesize_t frame_size, uint
ret = ll_cam_init_isr(cam_obj);
CAM_CHECK_GOTO(ret == ESP_OK, "cam intr alloc failed", err);
-
+
#if CONFIG_CAMERA_CORE0
- xTaskCreatePinnedToCore(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 0);
+ xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 0);
#elif CONFIG_CAMERA_CORE1
- xTaskCreatePinnedToCore(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 1);
+ xTaskCreatePinnedToCore(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle, 1);
#else
- xTaskCreate(cam_task, "cam_task", 2048, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle);
+ xTaskCreate(cam_task, "cam_task", CAM_TASK_STACK, NULL, configMAX_PRIORITIES - 2, &cam_obj->task_handle);
#endif
ESP_LOGI(TAG, "cam config ok");
diff --git a/code/components/esp32-camera-master/driver/esp_camera.c b/code/components/esp32-camera-master/driver/esp_camera.c
index 5b671c0e..5d6c97d0 100644
--- a/code/components/esp32-camera-master/driver/esp_camera.c
+++ b/code/components/esp32-camera-master/driver/esp_camera.c
@@ -57,6 +57,15 @@
#if CONFIG_BF3005_SUPPORT
#include "bf3005.h"
#endif
+#if CONFIG_BF20A6_SUPPORT
+#include "bf20a6.h"
+#endif
+#if CONFIG_SC101IOT_SUPPORT
+#include "sc101iot.h"
+#endif
+#if CONFIG_SC030IOT_SUPPORT
+#include "sc030iot.h"
+#endif
#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
#include "esp32-hal-log.h"
@@ -119,10 +128,20 @@ static const sensor_func_t g_sensors[] = {
#if CONFIG_BF3005_SUPPORT
{bf3005_detect, bf3005_init},
#endif
+#if CONFIG_BF20A6_SUPPORT
+ {bf20a6_detect, bf20a6_init},
+#endif
+#if CONFIG_SC101IOT_SUPPORT
+ {sc101iot_detect, sc101iot_init},
+#endif
+#if CONFIG_SC030IOT_SUPPORT
+ {sc030iot_detect, sc030iot_init},
+#endif
};
static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out_camera_model)
{
+ esp_err_t ret = ESP_OK;
*out_camera_model = CAMERA_NONE;
if (s_state != NULL) {
return ESP_ERR_INVALID_STATE;
@@ -138,9 +157,17 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
CAMERA_ENABLE_OUT_CLOCK(config);
}
- if (config->pin_sscb_sda != -1) {
- ESP_LOGD(TAG, "Initializing SSCB");
- SCCB_Init(config->pin_sscb_sda, config->pin_sscb_scl);
+ if (config->pin_sccb_sda != -1) {
+ ESP_LOGD(TAG, "Initializing SCCB");
+ ret = SCCB_Init(config->pin_sccb_sda, config->pin_sccb_scl);
+ } else {
+ ESP_LOGD(TAG, "Using existing I2C port");
+ ret = SCCB_Use_Port(config->sccb_i2c_port);
+ }
+
+ if(ret != ESP_OK) {
+ ESP_LOGE(TAG, "sccb init err");
+ goto err;
}
if (config->pin_pwdn >= 0) {
@@ -170,15 +197,14 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
vTaskDelay(10 / portTICK_PERIOD_MS);
}
-
ESP_LOGD(TAG, "Searching for camera address");
vTaskDelay(10 / portTICK_PERIOD_MS);
uint8_t slv_addr = SCCB_Probe();
if (slv_addr == 0) {
- CAMERA_DISABLE_OUT_CLOCK();
- return ESP_ERR_NOT_FOUND;
+ ret = ESP_ERR_NOT_FOUND;
+ goto err;
}
ESP_LOGI(TAG, "Detected camera at address=0x%02x", slv_addr);
@@ -203,9 +229,9 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
}
if (CAMERA_NONE == *out_camera_model) { //If no supported sensors are detected
- CAMERA_DISABLE_OUT_CLOCK();
ESP_LOGE(TAG, "Detected camera not supported.");
- return ESP_ERR_NOT_SUPPORTED;
+ ret = ESP_ERR_NOT_SUPPORTED;
+ goto err;
}
ESP_LOGI(TAG, "Camera PID=0x%02x VER=0x%02x MIDL=0x%02x MIDH=0x%02x",
@@ -213,11 +239,30 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
ESP_LOGD(TAG, "Doing SW reset of sensor");
vTaskDelay(10 / portTICK_PERIOD_MS);
- s_state->sensor.reset(&s_state->sensor);
-
- return ESP_OK;
+
+ return s_state->sensor.reset(&s_state->sensor);
+err :
+ CAMERA_DISABLE_OUT_CLOCK();
+ return ret;
}
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+static pixformat_t get_output_data_format(camera_conv_mode_t conv_mode)
+{
+ pixformat_t format = PIXFORMAT_RGB565;
+ switch (conv_mode) {
+ case YUV422_TO_YUV420:
+ format = PIXFORMAT_YUV420;
+ break;
+ case YUV422_TO_RGB565: // default format is RGB565
+ default:
+ break;
+ }
+ ESP_LOGD(TAG, "Convert to %d format enabled", format);
+ return format;
+}
+#endif
+
esp_err_t esp_camera_init(const camera_config_t *config)
{
esp_err_t err;
@@ -256,6 +301,7 @@ esp_err_t esp_camera_init(const camera_config_t *config)
s_state->sensor.status.framesize = frame_size;
s_state->sensor.pixformat = pix_format;
+
ESP_LOGD(TAG, "Setting frame size to %dx%d", resolution[frame_size].width, resolution[frame_size].height);
if (s_state->sensor.set_framesize(&s_state->sensor, frame_size) != 0) {
ESP_LOGE(TAG, "Failed to set frame size");
@@ -263,6 +309,11 @@ esp_err_t esp_camera_init(const camera_config_t *config)
goto fail;
}
s_state->sensor.set_pixformat(&s_state->sensor, pix_format);
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+ if(config->conv_mode) {
+ s_state->sensor.pixformat = get_output_data_format(config->conv_mode); // If conversion enabled, change the out data format by conversion mode
+ }
+#endif
if (s_state->sensor.id.PID == OV2640_PID) {
s_state->sensor.set_gainceiling(&s_state->sensor, GAINCEILING_2X);
diff --git a/code/components/esp32-camera-master/driver/include/esp_camera.h b/code/components/esp32-camera-master/driver/include/esp_camera.h
index b6047d31..ee84b307 100644
--- a/code/components/esp32-camera-master/driver/include/esp_camera.h
+++ b/code/components/esp32-camera-master/driver/include/esp_camera.h
@@ -18,8 +18,8 @@
.pin_pwdn = PIN_PWDN,
.pin_reset = PIN_RESET,
.pin_xclk = PIN_XCLK,
- .pin_sscb_sda = PIN_SIOD,
- .pin_sscb_scl = PIN_SIOC,
+ .pin_sccb_sda = PIN_SIOD,
+ .pin_sccb_scl = PIN_SIOC,
.pin_d7 = PIN_D7,
.pin_d6 = PIN_D6,
.pin_d5 = PIN_D5,
@@ -70,6 +70,7 @@
#include "driver/ledc.h"
#include "sensor.h"
#include "sys/time.h"
+#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
@@ -91,6 +92,19 @@ typedef enum {
CAMERA_FB_IN_DRAM /*!< Frame buffer is placed in internal DRAM */
} camera_fb_location_t;
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+/**
+ * @brief Camera RGB\YUV conversion mode
+ */
+typedef enum {
+ CONV_DISABLE,
+ RGB565_TO_YUV422,
+
+ YUV422_TO_RGB565,
+ YUV422_TO_YUV420
+} camera_conv_mode_t;
+#endif
+
/**
* @brief Configuration structure for camera initialization
*/
@@ -98,8 +112,14 @@ typedef struct {
int pin_pwdn; /*!< GPIO pin for camera power down line */
int pin_reset; /*!< GPIO pin for camera reset line */
int pin_xclk; /*!< GPIO pin for camera XCLK line */
- int pin_sscb_sda; /*!< GPIO pin for camera SDA line */
- int pin_sscb_scl; /*!< GPIO pin for camera SCL line */
+ union {
+ int pin_sccb_sda; /*!< GPIO pin for camera SDA line */
+ int pin_sscb_sda __attribute__((deprecated("please use pin_sccb_sda instead"))); /*!< GPIO pin for camera SDA line (legacy name) */
+ };
+ union {
+ int pin_sccb_scl; /*!< GPIO pin for camera SCL line */
+ int pin_sscb_scl __attribute__((deprecated("please use pin_sccb_scl instead"))); /*!< GPIO pin for camera SCL line (legacy name) */
+ };
int pin_d7; /*!< GPIO pin for camera D7 line */
int pin_d6; /*!< GPIO pin for camera D6 line */
int pin_d5; /*!< GPIO pin for camera D5 line */
@@ -124,6 +144,11 @@ typedef struct {
size_t fb_count; /*!< Number of frame buffers to be allocated. If more than one, then each frame will be acquired (double speed) */
camera_fb_location_t fb_location; /*!< The location where the frame buffer will be allocated */
camera_grab_mode_t grab_mode; /*!< When buffers should be filled */
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+ camera_conv_mode_t conv_mode; /*!< RGB<->YUV Conversion mode */
+#endif
+
+ int sccb_i2c_port; /*!< If pin_sccb_sda is -1, use the already configured I2C bus by number */
} camera_config_t;
/**
diff --git a/code/components/esp32-camera-master/driver/include/sensor.h b/code/components/esp32-camera-master/driver/include/sensor.h
index b2bf55f1..4aa14c90 100644
--- a/code/components/esp32-camera-master/driver/include/sensor.h
+++ b/code/components/esp32-camera-master/driver/include/sensor.h
@@ -27,6 +27,9 @@ typedef enum {
GC032A_PID = 0x232a,
GC0308_PID = 0x9b,
BF3005_PID = 0x30,
+ BF20A6_PID = 0x20a6,
+ SC101IOT_PID = 0xda4a,
+ SC030IOT_PID = 0x9a46,
} camera_pid_t;
typedef enum {
@@ -40,6 +43,9 @@ typedef enum {
CAMERA_GC032A,
CAMERA_GC0308,
CAMERA_BF3005,
+ CAMERA_BF20A6,
+ CAMERA_SC101IOT,
+ CAMERA_SC030IOT,
CAMERA_MODEL_MAX,
CAMERA_NONE,
} camera_model_t;
@@ -55,11 +61,15 @@ typedef enum {
GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1
GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1
BF3005_SCCB_ADDR = 0x6E,
+ BF20A6_SCCB_ADDR = 0x6E,
+ SC101IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1
+ SC030IOT_SCCB_ADDR = 0x68,// 0xd0 >> 1
} camera_sccb_addr_t;
typedef enum {
PIXFORMAT_RGB565, // 2BPP/RGB565
PIXFORMAT_YUV422, // 2BPP/YUV422
+ PIXFORMAT_YUV420, // 1.5BPP/YUV420
PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
PIXFORMAT_JPEG, // JPEG/COMPRESSED
PIXFORMAT_RGB888, // 3BPP/RGB888
@@ -199,7 +209,7 @@ typedef struct _sensor {
// Sensor function pointers
int (*init_status) (sensor_t *sensor);
- int (*reset) (sensor_t *sensor);
+ int (*reset) (sensor_t *sensor); // Reset the configuration of the sensor, and return ESP_OK if reset is successful
int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat);
int (*set_framesize) (sensor_t *sensor, framesize_t framesize);
int (*set_contrast) (sensor_t *sensor, int level);
diff --git a/code/components/esp32-camera-master/driver/private_include/sccb.h b/code/components/esp32-camera-master/driver/private_include/sccb.h
index ace081a4..9e445338 100644
--- a/code/components/esp32-camera-master/driver/private_include/sccb.h
+++ b/code/components/esp32-camera-master/driver/private_include/sccb.h
@@ -10,6 +10,7 @@
#define __SCCB_H__
#include
int SCCB_Init(int pin_sda, int pin_scl);
+int SCCB_Use_Port(int sccb_i2c_port);
int SCCB_Deinit(void);
uint8_t SCCB_Probe();
uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg);
diff --git a/code/components/esp32-camera-master/driver/sccb.c b/code/components/esp32-camera-master/driver/sccb.c
index 314dd982..945bd9bd 100644
--- a/code/components/esp32-camera-master/driver/sccb.c
+++ b/code/components/esp32-camera-master/driver/sccb.c
@@ -25,6 +25,11 @@ static const char* TAG = "sccb";
#include "driver/i2c.h"
+// support IDF 5.x
+#ifndef portTICK_RATE_MS
+#define portTICK_RATE_MS portTICK_PERIOD_MS
+#endif
+
#define SCCB_FREQ CONFIG_SCCB_CLK_FREQ /*!< I2C master frequency*/
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
@@ -33,16 +38,26 @@ static const char* TAG = "sccb";
#define ACK_VAL 0x0 /*!< I2C ack value */
#define NACK_VAL 0x1 /*!< I2C nack value */
#if CONFIG_SCCB_HARDWARE_I2C_PORT1
-const int SCCB_I2C_PORT = 1;
+const int SCCB_I2C_PORT_DEFAULT = 1;
#else
-const int SCCB_I2C_PORT = 0;
+const int SCCB_I2C_PORT_DEFAULT = 0;
#endif
+static int sccb_i2c_port;
+static bool sccb_owns_i2c_port;
+
int SCCB_Init(int pin_sda, int pin_scl)
{
ESP_LOGI(TAG, "pin_sda %d pin_scl %d", pin_sda, pin_scl);
i2c_config_t conf;
+ esp_err_t ret;
+
memset(&conf, 0, sizeof(i2c_config_t));
+
+ sccb_i2c_port = SCCB_I2C_PORT_DEFAULT;
+ sccb_owns_i2c_port = true;
+ ESP_LOGI(TAG, "sccb_i2c_port=%d\n", sccb_i2c_port);
+
conf.mode = I2C_MODE_MASTER;
conf.sda_io_num = pin_sda;
conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
@@ -50,30 +65,37 @@ int SCCB_Init(int pin_sda, int pin_scl)
conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
conf.master.clk_speed = SCCB_FREQ;
- i2c_param_config(SCCB_I2C_PORT, &conf);
- i2c_driver_install(SCCB_I2C_PORT, conf.mode, 0, 0, 0);
- return 0;
+ if ((ret = i2c_param_config(sccb_i2c_port, &conf)) != ESP_OK) {
+ return ret;
+ }
+
+ return i2c_driver_install(sccb_i2c_port, conf.mode, 0, 0, 0);
+}
+
+int SCCB_Use_Port(int i2c_num) { // sccb use an already initialized I2C port
+ if (sccb_owns_i2c_port) {
+ SCCB_Deinit();
+ }
+ if (i2c_num < 0 || i2c_num > I2C_NUM_MAX) {
+ return ESP_ERR_INVALID_ARG;
+ }
+ sccb_i2c_port = i2c_num;
+ return ESP_OK;
}
int SCCB_Deinit(void)
{
- return i2c_driver_delete(SCCB_I2C_PORT);
+ if (!sccb_owns_i2c_port) {
+ return ESP_OK;
+ }
+ sccb_owns_i2c_port = false;
+ return i2c_driver_delete(sccb_i2c_port);
}
uint8_t SCCB_Probe(void)
{
uint8_t slave_addr = 0x0;
- // for (size_t i = 1; i < 0x80; i++) {
- // i2c_cmd_handle_t cmd = i2c_cmd_link_create();
- // i2c_master_start(cmd);
- // i2c_master_write_byte(cmd, ( i << 1 ) | WRITE_BIT, ACK_CHECK_EN);
- // i2c_master_stop(cmd);
- // esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
- // i2c_cmd_link_delete(cmd);
- // if( ret == ESP_OK) {
- // ESP_LOGW(TAG, "Found I2C Device at 0x%02X", i);
- // }
- // }
+
for (size_t i = 0; i < CAMERA_MODEL_MAX; i++) {
if (slave_addr == camera_sensor[i].sccb_addr) {
continue;
@@ -83,7 +105,7 @@ uint8_t SCCB_Probe(void)
i2c_master_start(cmd);
i2c_master_write_byte(cmd, ( slave_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_stop(cmd);
- esp_err_t ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
+ esp_err_t ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if( ret == ESP_OK) {
return slave_addr;
@@ -101,7 +123,7 @@ uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
i2c_master_write_byte(cmd, ( slv_addr << 1 ) | WRITE_BIT, ACK_CHECK_EN);
i2c_master_write_byte(cmd, reg, ACK_CHECK_EN);
i2c_master_stop(cmd);
- ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
+ ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) return -1;
cmd = i2c_cmd_link_create();
@@ -109,7 +131,7 @@ uint8_t SCCB_Read(uint8_t slv_addr, uint8_t reg)
i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(cmd, &data, NACK_VAL);
i2c_master_stop(cmd);
- ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
+ ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "SCCB_Read Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
@@ -126,7 +148,7 @@ uint8_t SCCB_Write(uint8_t slv_addr, uint8_t reg, uint8_t data)
i2c_master_write_byte(cmd, reg, ACK_CHECK_EN);
i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
i2c_master_stop(cmd);
- ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
+ ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "SCCB_Write Failed addr:0x%02x, reg:0x%02x, data:0x%02x, ret:%d", slv_addr, reg, data, ret);
@@ -146,7 +168,7 @@ uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
i2c_master_write_byte(cmd, reg_u8[0], ACK_CHECK_EN);
i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN);
i2c_master_stop(cmd);
- ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
+ ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) return -1;
cmd = i2c_cmd_link_create();
@@ -154,7 +176,7 @@ uint8_t SCCB_Read16(uint8_t slv_addr, uint16_t reg)
i2c_master_write_byte(cmd, ( slv_addr << 1 ) | READ_BIT, ACK_CHECK_EN);
i2c_master_read_byte(cmd, &data, NACK_VAL);
i2c_master_stop(cmd);
- ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
+ ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "W [%04x]=%02x fail\n", reg, data);
@@ -175,7 +197,7 @@ uint8_t SCCB_Write16(uint8_t slv_addr, uint16_t reg, uint8_t data)
i2c_master_write_byte(cmd, reg_u8[1], ACK_CHECK_EN);
i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
i2c_master_stop(cmd);
- ret = i2c_master_cmd_begin(SCCB_I2C_PORT, cmd, 1000 / portTICK_RATE_MS);
+ ret = i2c_master_cmd_begin(sccb_i2c_port, cmd, 1000 / portTICK_RATE_MS);
i2c_cmd_link_delete(cmd);
if(ret != ESP_OK) {
ESP_LOGE(TAG, "W [%04x]=%02x %d fail\n", reg, data, i++);
diff --git a/code/components/esp32-camera-master/driver/sensor.c b/code/components/esp32-camera-master/driver/sensor.c
index bf6d313f..2f4c9711 100644
--- a/code/components/esp32-camera-master/driver/sensor.c
+++ b/code/components/esp32-camera-master/driver/sensor.c
@@ -13,6 +13,9 @@ const camera_sensor_info_t camera_sensor[CAMERA_MODEL_MAX] = {
{CAMERA_GC032A, "GC032A", GC032A_SCCB_ADDR, GC032A_PID, FRAMESIZE_VGA, false},
{CAMERA_GC0308, "GC0308", GC0308_SCCB_ADDR, GC0308_PID, FRAMESIZE_VGA, false},
{CAMERA_BF3005, "BF3005", BF3005_SCCB_ADDR, BF3005_PID, FRAMESIZE_VGA, false},
+ {CAMERA_BF20A6, "BF20A6", BF20A6_SCCB_ADDR, BF20A6_PID, FRAMESIZE_VGA, false},
+ {CAMERA_SC101IOT, "SC101IOT", SC101IOT_SCCB_ADDR, SC101IOT_PID, FRAMESIZE_HD, false},
+ {CAMERA_SC030IOT, "SC030IOT", SC030IOT_SCCB_ADDR, SC030IOT_PID, FRAMESIZE_VGA, false},
};
const resolution_info_t resolution[FRAMESIZE_INVALID] = {
diff --git a/code/components/esp32-camera-master/examples/main/take_picture.c b/code/components/esp32-camera-master/examples/main/take_picture.c
index 1cbad908..783fcc01 100644
--- a/code/components/esp32-camera-master/examples/main/take_picture.c
+++ b/code/components/esp32-camera-master/examples/main/take_picture.c
@@ -38,6 +38,11 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
+// support IDF 5.x
+#ifndef portTICK_RATE_MS
+#define portTICK_RATE_MS portTICK_PERIOD_MS
+#endif
+
#include "esp_camera.h"
#define BOARD_WROVER_KIT 1
@@ -94,8 +99,8 @@ static camera_config_t camera_config = {
.pin_pwdn = CAM_PIN_PWDN,
.pin_reset = CAM_PIN_RESET,
.pin_xclk = CAM_PIN_XCLK,
- .pin_sscb_sda = CAM_PIN_SIOD,
- .pin_sscb_scl = CAM_PIN_SIOC,
+ .pin_sccb_sda = CAM_PIN_SIOD,
+ .pin_sccb_scl = CAM_PIN_SIOC,
.pin_d7 = CAM_PIN_D7,
.pin_d6 = CAM_PIN_D6,
diff --git a/code/components/esp32-camera-master/idf_component.yml b/code/components/esp32-camera-master/idf_component.yml
index 848e1cd8..2b98f8d0 100644
--- a/code/components/esp32-camera-master/idf_component.yml
+++ b/code/components/esp32-camera-master/idf_component.yml
@@ -1,5 +1,2 @@
description: ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.
-targets:
- - esp32
- - esp32s2
- - esp32s3
+url: https://github.com/espressif/esp32-camera
diff --git a/code/components/esp32-camera-master/sensors/bf20a6.c b/code/components/esp32-camera-master/sensors/bf20a6.c
new file mode 100644
index 00000000..b1179c30
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/bf20a6.c
@@ -0,0 +1,404 @@
+// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
+//
+// 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
+#include
+#include
+#include
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "sccb.h"
+#include "bf20a6.h"
+#include "bf20a6_regs.h"
+#include "bf20a6_settings.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#else
+#include "esp_log.h"
+static const char *TAG = "bf20a6";
+#endif
+
+#define H8(v) ((v)>>8)
+#define L8(v) ((v)&0xff)
+
+//#define REG_DEBUG_ON
+
+static int read_reg(uint8_t slv_addr, const uint16_t reg)
+{
+ int ret = SCCB_Read(slv_addr, reg);
+ // ESP_LOGI(TAG, "READ Register 0x%02x VALUE: 0x%02x", reg, ret);
+#ifdef REG_DEBUG_ON
+ if (ret < 0) {
+ ESP_LOGE(TAG, "READ REG 0x%04x FAILED: %d", reg, ret);
+ }
+#endif
+ return ret;
+}
+
+static int write_reg(uint8_t slv_addr, const uint16_t reg, uint8_t value)
+{
+ int ret = SCCB_Write(slv_addr, reg, value);
+#ifdef REG_DEBUG_ON
+ if (ret < 0) {
+ ESP_LOGE(TAG, "WRITE REG 0x%04x FAILED: %d", reg, ret);
+ }
+#endif
+ return ret;
+}
+
+#ifdef DEBUG_PRINT_REG
+static int check_reg_mask(uint8_t slv_addr, uint16_t reg, uint8_t mask)
+{
+ return (read_reg(slv_addr, reg) & mask) == mask;
+}
+
+static void print_regs(uint8_t slv_addr)
+{
+ vTaskDelay(pdMS_TO_TICKS(100));
+ ESP_LOGI(TAG, "REG list look ======================");
+ for (size_t i = 0xf0; i <= 0xfe; i++) {
+ ESP_LOGI(TAG, "reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+ }
+ ESP_LOGI(TAG, "\npage 0 ===");
+ write_reg(slv_addr, 0xfe, 0x00); // page 0
+ for (size_t i = 0x03; i <= 0x24; i++) {
+ ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+ }
+ for (size_t i = 0x40; i <= 0x95; i++) {
+ ESP_LOGI(TAG, "p0 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+ }
+ ESP_LOGI(TAG, "\npage 3 ===");
+ write_reg(slv_addr, 0xfe, 0x03); // page 3
+ for (size_t i = 0x01; i <= 0x43; i++) {
+ ESP_LOGI(TAG, "p3 reg[0x%02x] = 0x%02x", i, read_reg(slv_addr, i));
+ }
+}
+
+static int read_regs(uint8_t slv_addr, const uint16_t(*regs)[2])
+{
+ int i = 0, ret = 0;
+ while (regs[i][0] != REGLIST_TAIL) {
+ if (regs[i][0] == REG_DLY) {
+ vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
+ } else {
+ ret = read_reg(slv_addr, regs[i][0]);
+ }
+ i++;
+ }
+ return ret;
+}
+#endif
+
+static int set_reg_bits(sensor_t *sensor, uint8_t reg, uint8_t offset, uint8_t length, uint8_t value)
+{
+ int ret = 0;
+
+ ret = SCCB_Read(sensor->slv_addr, reg);
+ if (ret < 0) {
+ return ret;
+ }
+ uint8_t mask = ((1 << length) - 1) << offset;
+ value = (ret & ~mask) | ((value << offset) & mask);
+ ret = SCCB_Write(sensor->slv_addr, reg & 0xFF, value);
+ return ret;
+}
+
+static int write_regs(uint8_t slv_addr, const uint16_t(*regs)[2])
+{
+ int i = 0, ret = 0;
+ while (!ret && regs[i][0] != REGLIST_TAIL) {
+ if (regs[i][0] == REG_DLY) {
+ vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
+ } else {
+ ret = write_reg(slv_addr, regs[i][0], regs[i][1]);
+ }
+ i++;
+ }
+ return ret;
+}
+
+static int reset(sensor_t *sensor)
+{
+ int ret;
+ // Software Reset: clear all registers and reset them to their default values
+ ret = write_reg(sensor->slv_addr, RESET_RELATED, 0x01);
+ if (ret) {
+ ESP_LOGE(TAG, "Software Reset FAILED!");
+ return ret;
+ }
+ vTaskDelay(100 / portTICK_PERIOD_MS);
+
+ ret = write_regs(sensor->slv_addr, bf20a6_default_init_regs);
+ if (ret == 0) {
+ ESP_LOGD(TAG, "Camera defaults loaded");
+ vTaskDelay(100 / portTICK_PERIOD_MS);
+ }
+
+ // int test_value = read_regs(sensor->slv_addr, bf20a6_default_init_regs);
+
+ return ret;
+}
+
+static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
+{
+ int ret = 0;
+ switch (pixformat) {
+ case PIXFORMAT_YUV422:
+ set_reg_bits(sensor, 0x12, 0, 1, 0);
+ break;
+ case PIXFORMAT_RAW:
+ set_reg_bits(sensor, 0x12, 0, 1, 0x1);
+ break;
+ default:
+ ESP_LOGW(TAG, "set_pix unsupport format");
+ ret = -1;
+ break;
+ }
+ if (ret == 0) {
+ sensor->pixformat = pixformat;
+ ESP_LOGD(TAG, "Set pixformat to: %u", pixformat);
+ }
+
+ return ret;
+}
+
+static int set_framesize(sensor_t *sensor, framesize_t framesize)
+{
+ int ret = 0;
+ if (framesize > FRAMESIZE_VGA) {
+ return -1;
+ }
+ uint16_t w = resolution[framesize].width;
+ uint16_t h = resolution[framesize].height;
+
+ sensor->status.framesize = framesize;
+
+ // Write MSBs
+ ret |= SCCB_Write(sensor->slv_addr, 0x17, 0);
+ ret |= SCCB_Write(sensor->slv_addr, 0x18, w >> 2);
+
+ ret |= SCCB_Write(sensor->slv_addr, 0x19, 0);
+ ret |= SCCB_Write(sensor->slv_addr, 0x1a, h >> 2);
+
+ // Write LSBs
+ ret |= SCCB_Write(sensor->slv_addr, 0x1b, 0);
+
+ if ((w <= 320) && (h <= 240)) {
+ ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 4));
+ ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 4));
+
+ ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 4));
+
+ ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 4));
+
+ } else if ((w <= 640) && (h <= 480)) {
+ ret |= SCCB_Write(sensor->slv_addr, 0x17, (80 - w / 8));
+ ret |= SCCB_Write(sensor->slv_addr, 0x18, (80 + w / 8));
+
+ ret |= SCCB_Write(sensor->slv_addr, 0x19, (60 - h / 8));
+
+ ret |= SCCB_Write(sensor->slv_addr, 0x1a, (60 + h / 8));
+ }
+
+ // Delay
+ vTaskDelay(30 / portTICK_PERIOD_MS);
+
+ return ret;
+}
+
+static int set_hmirror(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ sensor->status.hmirror = enable;
+ //ret = write_reg(sensor->slv_addr, 0xfe, 0x00);
+ ret |= set_reg_bits(sensor, 0x4a, 3, 0x01, enable);
+ if (ret == 0) {
+ ESP_LOGD(TAG, "Set h-mirror to: %d", enable);
+ }
+ return ret;
+}
+
+static int set_vflip(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ sensor->status.vflip = enable;
+ //ret = write_reg(sensor->slv_addr, 0xfe, 0x00);
+ ret |= set_reg_bits(sensor, 0x4a, 2, 0x01, enable);
+ if (ret == 0) {
+ ESP_LOGD(TAG, "Set v-flip to: %d", enable);
+ }
+ return ret;
+}
+
+static int set_colorbar(sensor_t *sensor, int value)
+{
+ int ret = 0;
+ ret = write_reg(sensor->slv_addr, 0xb6, value);
+ if (ret == 0) {
+ sensor->status.colorbar = value;
+ ESP_LOGD(TAG, "Set colorbar to: %d", value);
+ }
+ return ret;
+}
+
+static int set_sharpness(sensor_t *sensor, int level)
+{
+ int ret = 0;
+ ret = SCCB_Write(sensor->slv_addr, 0x70, level);
+ if (ret == 0) {
+ ESP_LOGD(TAG, "Set sharpness to: %d", level);
+ sensor->status.sharpness = level;
+ }
+ return ret;
+}
+
+static int get_reg(sensor_t *sensor, int reg, int mask)
+{
+ int ret = 0;
+ if (mask > 0xFF) {
+ ESP_LOGE(TAG, "mask should not more than 0xff");
+ } else {
+ ret = read_reg(sensor->slv_addr, reg);
+ }
+ if (ret > 0) {
+ ret &= mask;
+ }
+ return ret;
+}
+
+static int set_reg(sensor_t *sensor, int reg, int mask, int value)
+{
+ int ret = 0;
+ if (mask > 0xFF) {
+ ESP_LOGE(TAG, "mask should not more than 0xff");
+ } else {
+ ret = read_reg(sensor->slv_addr, reg);
+ }
+ if (ret < 0) {
+ return ret;
+ }
+ value = (ret & ~mask) | (value & mask);
+
+ if (mask > 0xFF) {
+
+ } else {
+ ret = write_reg(sensor->slv_addr, reg, value);
+ }
+ return ret;
+}
+
+static int init_status(sensor_t *sensor)
+{
+ // write_reg(sensor->slv_addr, 0xfe, 0x00);
+ sensor->status.brightness = SCCB_Read(sensor->slv_addr, 0x6f);
+ sensor->status.contrast = SCCB_Read(sensor->slv_addr, 0xd6);
+ sensor->status.saturation = 0;
+ sensor->status.sharpness = SCCB_Read(sensor->slv_addr, 0x70);
+ sensor->status.denoise = 0;
+ sensor->status.ae_level = 0;
+ sensor->status.gainceiling = SCCB_Read(sensor->slv_addr, 0x13);
+ sensor->status.awb = 0;
+ sensor->status.dcw = 0;
+ sensor->status.agc = 0;
+ sensor->status.aec = 0;
+ sensor->status.hmirror = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x01);
+ sensor->status.vflip = 0;// check_reg_mask(sensor->slv_addr, P0_CISCTL_MODE1, 0x02);
+ sensor->status.colorbar = 0;
+ sensor->status.bpc = 0;
+ sensor->status.wpc = 0;
+ sensor->status.raw_gma = 0;
+ sensor->status.lenc = 0;
+ sensor->status.quality = 0;
+ sensor->status.special_effect = 0;
+ sensor->status.wb_mode = 0;
+ sensor->status.awb_gain = 0;
+ sensor->status.agc_gain = 0;
+ sensor->status.aec_value = 0;
+ sensor->status.aec2 = 0;
+ return 0;
+}
+
+static int set_dummy(sensor_t *sensor, int val)
+{
+ ESP_LOGW(TAG, "dummy Unsupported");
+ return -1;
+}
+static int set_gainceiling_dummy(sensor_t *sensor, gainceiling_t val)
+{
+ ESP_LOGW(TAG, "gainceiling Unsupported");
+ return -1;
+}
+
+int bf20a6_detect(int slv_addr, sensor_id_t *id)
+{
+ if (BF20A6_SCCB_ADDR == slv_addr) {
+ uint8_t MIDL = SCCB_Read(slv_addr, SENSOR_ID_LOW);
+ uint8_t MIDH = SCCB_Read(slv_addr, SENSOR_ID_HIGH);
+ uint16_t PID = MIDH << 8 | MIDL;
+ if (BF20A6_PID == PID) {
+ id->PID = PID;
+ return PID;
+ } else {
+ ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
+ }
+ }
+ return 0;
+}
+
+int bf20a6_init(sensor_t *sensor)
+{
+ sensor->init_status = init_status;
+ sensor->reset = reset;
+ sensor->set_pixformat = set_pixformat;
+ sensor->set_framesize = set_framesize;
+ sensor->set_contrast = set_dummy;
+ sensor->set_brightness = set_dummy;
+ sensor->set_saturation = set_dummy;
+ sensor->set_sharpness = set_sharpness;
+ sensor->set_denoise = set_dummy;
+ sensor->set_gainceiling = set_gainceiling_dummy;
+ sensor->set_quality = set_dummy;
+ sensor->set_colorbar = set_colorbar;
+ sensor->set_whitebal = set_dummy;
+ sensor->set_gain_ctrl = set_dummy;
+ sensor->set_exposure_ctrl = set_dummy;
+ sensor->set_hmirror = set_hmirror; // set_hmirror;
+ sensor->set_vflip = set_vflip; // set_vflip;
+
+ sensor->set_aec2 = set_dummy;
+ sensor->set_awb_gain = set_dummy;
+ sensor->set_agc_gain = set_dummy;
+ sensor->set_aec_value = set_dummy;
+
+ sensor->set_special_effect = set_dummy;
+ sensor->set_wb_mode = set_dummy;
+ sensor->set_ae_level = set_dummy;
+
+ sensor->set_dcw = set_dummy;
+ sensor->set_bpc = set_dummy;
+ sensor->set_wpc = set_dummy;
+
+ sensor->set_raw_gma = set_dummy;
+ sensor->set_lenc = set_dummy;
+
+ sensor->get_reg = get_reg;
+ sensor->set_reg = set_reg;
+ sensor->set_res_raw = NULL;
+ sensor->set_pll = NULL;
+ sensor->set_xclk = NULL;
+
+ ESP_LOGD(TAG, "BF20A6 Attached");
+ return 0;
+}
diff --git a/code/components/esp32-camera-master/sensors/gc0308.c b/code/components/esp32-camera-master/sensors/gc0308.c
index 8b106a3a..f19025eb 100644
--- a/code/components/esp32-camera-master/sensors/gc0308.c
+++ b/code/components/esp32-camera-master/sensors/gc0308.c
@@ -88,10 +88,10 @@ static int set_reg_bits(uint8_t slv_addr, uint16_t reg, uint8_t offset, uint8_t
return ret;
}
-static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2])
+static int write_regs(uint8_t slv_addr, const uint8_t (*regs)[2], size_t regs_size)
{
int i = 0, ret = 0;
- while (!ret && regs[i][0] != REGLIST_TAIL) {
+ while (!ret && (i < regs_size)) {
if (regs[i][0] == REG_DLY) {
vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
} else {
@@ -132,11 +132,12 @@ static int reset(sensor_t *sensor)
ESP_LOGE(TAG, "Software Reset FAILED!");
return ret;
}
- vTaskDelay(100 / portTICK_PERIOD_MS);
- ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs);
+
+ vTaskDelay(80 / portTICK_PERIOD_MS);
+ ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs, sizeof(gc0308_sensor_default_regs)/(sizeof(uint8_t) * 2));
if (ret == 0) {
ESP_LOGD(TAG, "Camera defaults loaded");
- vTaskDelay(100 / portTICK_PERIOD_MS);
+ vTaskDelay(80 / portTICK_PERIOD_MS);
write_reg(sensor->slv_addr, 0xfe, 0x00);
#ifdef CONFIG_IDF_TARGET_ESP32
set_reg_bits(sensor->slv_addr, 0x28, 4, 0x07, 1); //frequency division for esp32, ensure pclk <= 15MHz
diff --git a/code/components/esp32-camera-master/sensors/private_include/bf20a6.h b/code/components/esp32-camera-master/sensors/private_include/bf20a6.h
new file mode 100644
index 00000000..8c925eb5
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/private_include/bf20a6.h
@@ -0,0 +1,27 @@
+
+#ifndef __BF20A6_H__
+#define __BF20A6_H__
+
+#include "sensor.h"
+
+/**
+ * @brief Detect sensor pid
+ *
+ * @param slv_addr SCCB address
+ * @param id Detection result
+ * @return
+ * 0: Can't detect this sensor
+ * Nonzero: This sensor has been detected
+ */
+int bf20a6_detect(int slv_addr, sensor_id_t *id);
+
+/**
+ * @brief initialize sensor function pointers
+ *
+ * @param sensor pointer of sensor
+ * @return
+ * Always 0
+ */
+int bf20a6_init(sensor_t *sensor);
+
+#endif // __BF20A6_H__
diff --git a/code/components/esp32-camera-master/sensors/private_include/bf20a6_regs.h b/code/components/esp32-camera-master/sensors/private_include/bf20a6_regs.h
new file mode 100644
index 00000000..ab1ff69e
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/private_include/bf20a6_regs.h
@@ -0,0 +1,12 @@
+/*
+ * BF20A6 register definitions.
+ */
+#ifndef __BF20A6_REG_REGS_H__
+#define __BF20A6_REG_REGS_H__
+
+#define SENSOR_ID_HIGH 0XFC
+#define SENSOR_ID_LOW 0XFD
+#define RESET_RELATED 0XF2
+
+
+#endif //__BF20A6_REG_REGS_H__
diff --git a/code/components/esp32-camera-master/sensors/private_include/bf20a6_settings.h b/code/components/esp32-camera-master/sensors/private_include/bf20a6_settings.h
new file mode 100644
index 00000000..0414bbac
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/private_include/bf20a6_settings.h
@@ -0,0 +1,158 @@
+
+#include
+
+#define REG_DLY 0xffff
+#define REGLIST_TAIL 0xffff /* Array end token */
+
+static const uint16_t bf20a6_default_init_regs[][2] = {
+ {0xf2,0x01},
+ {0x12,0x20},
+ {0x3a,0x00},
+ {0xe1,0x92},
+ {0xe3,0x12},// PLL Control, important for framerate(choice: 0x02\0x12\0x22\0x32\0x82)
+ {0xe0,0x00},
+ {0x2a,0x98},
+ {0xcd,0x17},
+ {0xc0,0x10},
+ {0xc6,0x1d},
+ {0x10,0x35},
+ {0xe2,0x09},
+ {0xe4,0x72},
+ {0xe5,0x22},
+ {0xe6,0x24},
+ {0xe7,0x64},
+ {0xe8,0xa2}, // DVP:a2}, SPI:f2 VDDIO=1.8V,E8[2]=1},VDDIO=2.8V,E8[2]=0},
+ {0x4a,0x00},
+ {0x00,0x03},
+ {0x1f,0x02},
+ {0x22,0x02},
+ {0x0c,0x31},
+
+ {0x00,0x00},
+ {0x60,0x81},
+ {0x61,0x81},
+
+ {0xa0,0x08},
+ {0x01,0x1a},
+ // {0x01,0x1a},
+ // {0x01,0x1a},
+ // {0x02,0x15},
+ // {0x02,0x15},
+ {0x02,0x15},
+ {0x13,0x08},
+ {0x8a,0x96},
+ {0x8b,0x06},
+ {0x87,0x18},
+
+
+ {0x34,0x48}, // lens
+ {0x35,0x40},
+ {0x36,0x40},
+
+ {0x71,0x44},
+ {0x72,0x48},
+ {0x74,0xa2},
+ {0x75,0xa9},
+ {0x78,0x12},
+ {0x79,0xa0},
+ {0x7a,0x94},
+ {0x7c,0x97},
+ {0x40,0x30},
+ {0x41,0x30},
+ {0x42,0x28},
+ {0x43,0x1f},
+ {0x44,0x1c},
+ {0x45,0x16},
+ {0x46,0x13},
+ {0x47,0x10},
+ {0x48,0x0D},
+ {0x49,0x0C},
+ {0x4B,0x0A},
+ {0x4C,0x0B},
+ {0x4E,0x09},
+ {0x4F,0x08},
+ {0x50,0x08},
+
+
+ {0x5f,0x29},
+ {0x23,0x33},
+ {0xa1,0x10}, // AWB
+ {0xa2,0x0d},
+ {0xa3,0x30},
+ {0xa4,0x06},
+ {0xa5,0x22},
+ {0xa6,0x56},
+ {0xa7,0x18},
+ {0xa8,0x1a},
+ {0xa9,0x12},
+ {0xaa,0x12},
+ {0xab,0x16},
+ {0xac,0xb1},
+ {0xba,0x12},
+ {0xbb,0x12},
+ {0xad,0x12},
+ {0xae,0x56},
+ {0xaf,0x0a},
+ {0x3b,0x30},
+ {0x3c,0x12},
+ {0x3d,0x22},
+ {0x3e,0x3f},
+ {0x3f,0x28},
+ {0xb8,0xc3},
+ {0xb9,0xa3},
+ {0x39,0x47}, // pure color threshold
+ {0x26,0x13},
+ {0x27,0x16},
+ {0x28,0x14},
+ {0x29,0x18},
+ {0xee,0x0d},
+
+
+ {0x13,0x05},
+ {0x24,0x3C},
+ {0x81,0x20},
+ {0x82,0x40},
+ {0x83,0x30},
+ {0x84,0x58},
+ {0x85,0x30},
+ {0x92,0x08},
+ {0x86,0x80},
+ {0x8a,0x96},
+ {0x91,0xff},
+ {0x94,0x62},
+ {0x9a,0x18}, // outdoor threshold
+ {0xf0,0x45}, // integral time control, important for framerate(choice: 0x46\0x45\0x44..)
+ {0x51,0x17}, // color normal
+ {0x52,0x03},
+ {0x53,0x5F},
+ {0x54,0x47},
+ {0x55,0x66},
+ {0x56,0x0F},
+ {0x7e,0x14},
+ {0x57,0x36}, // color
+ {0x58,0x2A},
+ {0x59,0xAA},
+ {0x5a,0xA8},
+ {0x5b,0x43},
+ {0x5c,0x10},
+ {0x5d,0x00},
+ {0x7d,0x36},
+ {0x5e,0x10},
+
+ {0xd6,0x88}, // contrast
+ {0xd5,0x20}, // bright
+ {0xb0,0x84}, // low light ctrl in gray section
+ {0xb5,0x08}, // the threshold of GLB_GAIN
+ {0xb1,0xc8}, // saturation
+ {0xb2,0xc0},
+ {0xb3,0xd0},
+ {0xb4,0xB0},
+
+ {0x32,0x10},
+ // {0x8a,0x00},
+ // {0x8b,0x10},
+ {0xa0,0x09},
+ {0x00,0x03},
+ {0x0b,0x02},
+ {REGLIST_TAIL, 0x00},
+};
diff --git a/code/components/esp32-camera-master/sensors/private_include/gc0308_settings.h b/code/components/esp32-camera-master/sensors/private_include/gc0308_settings.h
index 32ef3816..adf5f28d 100644
--- a/code/components/esp32-camera-master/sensors/private_include/gc0308_settings.h
+++ b/code/components/esp32-camera-master/sensors/private_include/gc0308_settings.h
@@ -3,10 +3,9 @@
#include
-#define REG_DLY 0xffff
-#define REGLIST_TAIL 0x0000 /* Array end token */
+#define REG_DLY 0xff
-static const uint16_t gc0308_sensor_default_regs[][2] = {
+static const uint8_t gc0308_sensor_default_regs[][2] = {
{0xfe, 0x00},
{0xec, 0x20},
{0x05, 0x00},
@@ -239,7 +238,21 @@ static const uint16_t gc0308_sensor_default_regs[][2] = {
{0x65, 0xd3},
{0x66, 0x60},
{0xfe, 0x00},
- {REGLIST_TAIL, 0x00},
+
+ {0x01, 0x32}, //frame setting
+ {0x02, 0x0c},
+ {0x0f, 0x01},
+ {0xe2, 0x00},
+ {0xe3, 0x78},
+ {0xe4, 0x00},
+ {0xe5, 0xfe},
+ {0xe6, 0x01},
+ {0xe7, 0xe0},
+ {0xe8, 0x01},
+ {0xe9, 0xe0},
+ {0xea, 0x01},
+ {0xeb, 0xe0},
+ {0xfe, 0x00},
};
#endif
diff --git a/code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h b/code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h
index fec7d679..f52572fa 100644
--- a/code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h
+++ b/code/components/esp32-camera-master/sensors/private_include/ov5640_settings.h
@@ -42,7 +42,8 @@ static const DRAM_ATTR uint16_t sensor_default_regs[][2] = {
{ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE
//sys reset
- {0x3000, 0x00},
+ {0x3000, 0x20}, // reset MCU
+ {REG_DLY, 10}, // delay 10ms
{0x3002, 0x1c},
//clock enable
diff --git a/code/components/esp32-camera-master/sensors/private_include/sc030iot.h b/code/components/esp32-camera-master/sensors/private_include/sc030iot.h
new file mode 100644
index 00000000..19298b76
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/private_include/sc030iot.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * SC030IOT DVP driver.
+ *
+ */
+#ifndef __SC030IOT_H__
+#define __SC030IOT_H__
+
+#include "sensor.h"
+
+/**
+ * @brief Detect sensor pid
+ *
+ * @param slv_addr SCCB address
+ * @param id Detection result
+ * @return
+ * 0: Can't detect this sensor
+ * Nonzero: This sensor has been detected
+ */
+int sc030iot_detect(int slv_addr, sensor_id_t *id);
+
+/**
+ * @brief initialize sensor function pointers
+ *
+ * @param sensor pointer of sensor
+ * @return
+ * Always 0
+ */
+int sc030iot_init(sensor_t *sensor);
+
+#endif // __SC030IOT_H__
diff --git a/code/components/esp32-camera-master/sensors/private_include/sc030iot_settings.h b/code/components/esp32-camera-master/sensors/private_include/sc030iot_settings.h
new file mode 100644
index 00000000..56f5654c
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/private_include/sc030iot_settings.h
@@ -0,0 +1,491 @@
+//version: V01P00_20220303
+//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16
+//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI
+//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P
+//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data
+//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data
+//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR
+//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M
+//pin :BIT0 pwdn// BIT1:reset
+//avdd 0:3.3V// 1:2.5V// 2:1.8V
+//dovdd 0:2.8V// 1:2.5V// 2:1.8V
+//dvdd 0:1.8V// 1:1.5V// 2:1.2V
+
+/*
+[DataBase]
+DBName=Dothinkey
+
+[Vendor]
+VendorName=SmartSens
+
+[Sensor]
+SensorName=SC031IOT
+width=640
+height=480
+port=1
+type=2
+pin=3
+SlaveID=0xd0
+mode=0
+FlagReg=0xf7
+FlagMask=0xff
+FlagData=0xfa
+FlagReg1=0xf8
+FlagMask1=0xff
+FlagData1=0x46
+outformat=0
+mclk=20
+avdd=2.80000
+dovdd=2.800000
+dvdd=1.5
+
+Ext0=0
+Ext1=0
+Ext2=0
+AFVCC=0.0000
+VPP=0.000000
+*/
+#include
+
+static const uint8_t sc030iot_default_init_regs[][2] = {
+ {0xf0, 0x30},
+ {0x01, 0xff},
+ {0x02, 0xff},
+ {0x22, 0x07},
+ {0x19, 0xff},
+ {0x3f, 0x82},
+ {0x30, 0x02},
+ {0xf0, 0x01},
+ {0x70, 0x00},
+ {0x71, 0x80},
+ {0x72, 0x20},
+ {0x73, 0x00},
+ {0x74, 0xe0},
+ {0x75, 0x10},
+ {0x76, 0x81},
+ {0x77, 0x88},
+ {0x78, 0xe1},
+ {0x79, 0x01},
+ {0xf5, 0x01},
+ {0xf4, 0x0a},
+ {0xf0, 0x36},
+ {0x37, 0x79},
+ {0x31, 0x82},
+ {0x3e, 0x60},
+ {0x30, 0xf0},
+ {0x33, 0x33},
+ {0xf0, 0x32},
+ {0x48, 0x02},
+ {0xf0, 0x33},
+ {0x02, 0x12},
+ {0x7c, 0x02},
+ {0x7d, 0x0e},
+ {0xa2, 0x04},
+ {0x5e, 0x06},
+ {0x5f, 0x0a},
+ {0x0b, 0x58},
+ {0x06, 0x38},
+ {0xf0, 0x32},
+ {0x48, 0x02},
+ {0xf0, 0x39},
+ {0x02, 0x70},
+ {0xf0, 0x45},
+ {0x09, 0x1c},
+ {0xf0, 0x37},
+ {0x22, 0x0d},
+ {0xf0, 0x33},
+ {0x33, 0x10},
+ {0xb1, 0x80},
+ {0x34, 0x40},
+ {0x0b, 0x54},
+ {0xb2, 0x78},
+ {0xf0, 0x36},
+ {0x11, 0x80},
+ {0xf0, 0x30},
+ {0x38, 0x44},
+ {0xf0, 0x33},
+ {0xb3, 0x51},
+ {0x01, 0x10},
+ {0x0b, 0x6c},
+ {0x06, 0x24},
+ {0xf0, 0x36},
+ {0x31, 0x82},
+ {0x3e, 0x60},
+ {0x30, 0xf0},
+ {0x33, 0x33},
+ {0xf0, 0x34},
+ {0x9f, 0x02},
+ {0xa6, 0x40},
+ {0xa7, 0x47},
+ {0xe8, 0x5f},
+ {0xa8, 0x51},
+ {0xa9, 0x44},
+ {0xe9, 0x36},
+ {0xf0, 0x33},
+ {0xb3, 0x51},
+ {0x64, 0x17},
+ {0x90, 0x01},
+ {0x91, 0x03},
+ {0x92, 0x07},
+ {0x01, 0x10},
+ {0x93, 0x10},
+ {0x94, 0x10},
+ {0x95, 0x10},
+ {0x96, 0x01},
+ {0x97, 0x07},
+ {0x98, 0x1f},
+ {0x99, 0x10},
+ {0x9a, 0x20},
+ {0x9b, 0x28},
+ {0x9c, 0x28},
+ {0xf0, 0x36},
+ {0x70, 0x54},
+ {0xb6, 0x40},
+ {0xb7, 0x41},
+ {0xb8, 0x43},
+ {0xb9, 0x47},
+ {0xba, 0x4f},
+ {0xb0, 0x8b},
+ {0xb1, 0x8b},
+ {0xb2, 0x8b},
+ {0xb3, 0x9b},
+ {0xb4, 0xb8},
+ {0xb5, 0xf0},
+ {0x7e, 0x41},
+ {0x7f, 0x47},
+ {0x77, 0x80},
+ {0x78, 0x84},
+ {0x79, 0x8a},
+ {0xa0, 0x47},
+ {0xa1, 0x5f},
+ {0x96, 0x43},
+ {0x97, 0x44},
+ {0x98, 0x54},
+ {0xf0, 0x00},
+ {0xf0, 0x01},
+ {0x73, 0x00},
+ {0x74, 0xe0},
+ {0x70, 0x00},
+ {0x71, 0x80},
+ {0xf0, 0x36},
+ {0x37, 0x74},
+ {0xf0, 0x3f},
+ {0x03, 0xa1},
+ {0xf0, 0x36},//cvbs_off
+ {0x11, 0x80},
+ {0xf0, 0x01},
+ {0x79, 0xc1},
+ {0xf0, 0x37},
+ {0x24, 0x21},
+ {0xf0, 0x36},
+ {0x41, 0x00},
+ {0xea, 0x09},
+ {0xeb, 0x03},
+ {0xec, 0x19},
+ {0xed, 0x38},
+ {0xe9, 0x30},
+ {0xf0, 0x33},
+ {0x33, 0x00},
+ {0x34, 0x00},
+ {0xb1, 0x00},
+ {0xf0, 0x00},
+ {0xe0, 0x04},
+ {0xf0, 0x01},
+ {0x73, 0x00},
+ {0x74, 0xe0},
+ {0x70, 0x00},
+ {0x71, 0x80},
+ {0xf0, 0x36},
+ {0x32, 0x44},
+ {0xf0, 0x36},
+ {0x3e, 0xe0},
+ {0x70, 0x56},
+ {0x7c, 0x43},
+ {0x7d, 0x47},
+ {0x74, 0x00},
+ {0x75, 0x00},
+ {0x76, 0x00},
+ {0xa0, 0x47},
+ {0xa1, 0x5f},
+ {0x96, 0x22},
+ {0x97, 0x22},
+ {0x98, 0x22},
+ {0xf0, 0x00},
+ {0x72, 0x38},
+ {0x7a, 0x80},
+ {0x85, 0x18},
+ {0x9b, 0x35},
+ {0x9e, 0x20},
+ {0xd0, 0x66},
+ {0xd1, 0x34},
+ {0Xd3, 0x44},
+ {0xd6, 0x44},
+ {0xb0, 0x41},
+ {0xb2, 0x48},
+ {0xb3, 0xf4},
+ {0xb4, 0x0b},
+ {0xb5, 0x78},
+ {0xba, 0xff},
+ {0xbb, 0xc0},
+ {0xbc, 0x90},
+ {0xbd, 0x3a},
+ {0xc1, 0x67},
+ {0xf0, 0x01},
+ {0x20, 0x11},
+ {0x23, 0x90},
+ {0x24, 0x15},
+ {0x25, 0x87},
+ {0xbc, 0x9f},
+ {0xbd, 0x3a},
+ {0x48, 0xe6},
+ {0x49, 0xc0},
+ {0x4a, 0xd0},
+ {0x4b, 0x48},
+
+ // [cvbs_on]
+ {0xf0, 0x36},
+ {0x11, 0x00},
+ {0xf0, 0x01},
+ {0x79, 0xf1},
+
+ // [cvbs_off]
+ {0xf0, 0x36},
+ {0x11, 0x80},
+ {0xf0, 0x01},
+ {0x79, 0xc1},
+};
+
+/*
+[Sensor]
+SensorName=SC031IOT
+width=640
+height=480
+port=1
+type=2
+pin=3
+SlaveID=0xd0
+mode=0
+FlagReg=0xf7
+FlagMask=0xff
+FlagData=0xfa
+FlagReg1=0xf8
+FlagMask1=0xff
+FlagData1=0x46
+outformat=0
+mclk=27
+avdd=2.80000
+dovdd=2.800000
+dvdd=1.5
+
+Ext0=0
+Ext1=0
+Ext2=0
+AFVCC=0.0000
+VPP=0.000000
+*/
+/* 27M MCLK, 30fps
+static const uint8_t sc030iot_default_init_regs[][2] = {
+ {0xf0, 0x30},
+ {0x01, 0xff},
+ {0x02, 0xff},
+ {0x22, 0x07},
+ {0x19, 0xff},
+ {0x3f, 0x82},
+ {0x30, 0x02},
+ {0xf0, 0x01},
+ {0x70, 0x00},
+ {0x71, 0x80},
+ {0x72, 0x20},
+ {0x73, 0x00},
+ {0x74, 0xe0},
+ {0x75, 0x10},
+ {0x76, 0x81},
+ {0x77, 0x88},
+ {0x78, 0xe1},
+ {0x79, 0x01},
+ {0xf5, 0x01},
+ {0xf4, 0x0a},
+ {0xf0, 0x36},
+ {0x37, 0x79},
+ {0x31, 0x82},
+ {0x3e, 0x60},
+ {0x30, 0xf0},
+ {0x33, 0x33},
+ {0xf0, 0x32},
+ {0x48, 0x02},
+ {0xf0, 0x33},
+ {0x02, 0x12},
+ {0x7c, 0x02},
+ {0x7d, 0x0e},
+ {0xa2, 0x04},
+ {0x5e, 0x06},
+ {0x5f, 0x0a},
+ {0x0b, 0x58},
+ {0x06, 0x38},
+ {0xf0, 0x32},
+ {0x48, 0x02},
+ {0xf0, 0x39},
+ {0x02, 0x70},
+ {0xf0, 0x45},
+ {0x09, 0x1c},
+ {0xf0, 0x37},
+ {0x22, 0x0d},
+ {0xf0, 0x33},
+ {0x33, 0x10},
+ {0xb1, 0x80},
+ {0x34, 0x40},
+ {0x0b, 0x54},
+ {0xb2, 0x78},
+ {0xf0, 0x36},
+ {0x11, 0x80},
+ {0xf0, 0x30},
+ {0x38, 0x44},
+ {0xf0, 0x33},
+ {0xb3, 0x51},
+ {0x01, 0x10},
+ {0x0b, 0x6c},
+ {0x06, 0x24},
+ {0xf0, 0x36},
+ {0x31, 0x82},
+ {0x3e, 0x60},
+ {0x30, 0xf0},
+ {0x33, 0x33},
+ {0xf0, 0x34},
+ {0x9f, 0x02},
+ {0xa6, 0x40},
+ {0xa7, 0x47},
+ {0xe8, 0x5f},
+ {0xa8, 0x51},
+ {0xa9, 0x44},
+ {0xe9, 0x36},
+ {0xf0, 0x33},
+ {0xb3, 0x51},
+ {0x64, 0x17},
+ {0x90, 0x01},
+ {0x91, 0x03},
+ {0x92, 0x07},
+ {0x01, 0x10},
+ {0x93, 0x10},
+ {0x94, 0x10},
+ {0x95, 0x10},
+ {0x96, 0x01},
+ {0x97, 0x07},
+ {0x98, 0x1f},
+ {0x99, 0x10},
+ {0x9a, 0x20},
+ {0x9b, 0x28},
+ {0x9c, 0x28},
+ {0xf0, 0x36},
+ {0x70, 0x54},
+ {0xb6, 0x40},
+ {0xb7, 0x41},
+ {0xb8, 0x43},
+ {0xb9, 0x47},
+ {0xba, 0x4f},
+ {0xb0, 0x8b},
+ {0xb1, 0x8b},
+ {0xb2, 0x8b},
+ {0xb3, 0x9b},
+ {0xb4, 0xb8},
+ {0xb5, 0xf0},
+ {0x7e, 0x41},
+ {0x7f, 0x47},
+ {0x77, 0x80},
+ {0x78, 0x84},
+ {0x79, 0x8a},
+ {0xa0, 0x47},
+ {0xa1, 0x5f},
+ {0x96, 0x43},
+ {0x97, 0x44},
+ {0x98, 0x54},
+ {0xf0, 0x00},
+ {0xf0, 0x01},
+ {0x73, 0x00},
+ {0x74, 0xe0},
+ {0x70, 0x00},
+ {0x71, 0x80},
+ {0xf0, 0x36},
+ {0x37, 0x74},
+ {0xf0, 0x3f},
+ {0x03, 0x93},
+ {0xf0, 0x36},//cvbs_off
+ {0x11, 0x80},
+ {0xf0, 0x01},
+ {0x79, 0xc1},
+ {0xf0, 0x37},
+ {0x24, 0x21},
+ {0xf0, 0x36},
+ {0x41, 0x00},
+ {0xe9, 0x2c},
+ {0xf0, 0x33},
+ {0x33, 0x00},
+ {0x34, 0x00},
+ {0xb1, 0x00},
+ {0xf0, 0x00},
+ {0xe0, 0x04},
+ {0xf0, 0x01},
+ {0x73, 0x00},
+ {0x74, 0xe0},
+ {0x70, 0x00},
+ {0x71, 0x80},
+ {0xf0, 0x36},
+ {0x32, 0x44},
+ {0xf0, 0x36},
+ {0x3e, 0xe0},
+ {0x70, 0x56},
+ {0x7c, 0x43},
+ {0x7d, 0x47},
+ {0x74, 0x00},
+ {0x75, 0x00},
+ {0x76, 0x00},
+ {0xa0, 0x47},
+ {0xa1, 0x5f},
+ {0x96, 0x22},
+ {0x97, 0x22},
+ {0x98, 0x22},
+ {0xf0, 0x00},
+ {0x72, 0x38},
+ {0x7a, 0x80},
+ {0x85, 0x18},
+ {0x9b, 0x35},
+ {0x9e, 0x20},
+ {0xd0, 0x66},
+ {0xd1, 0x34},
+ {0Xd3, 0x44},
+ {0xd6, 0x44},
+ {0xb0, 0x41},
+ {0xb2, 0x48},
+ {0xb3, 0xf4},
+ {0xb4, 0x0b},
+ {0xb5, 0x78},
+ {0xba, 0xff},
+ {0xbb, 0xc0},
+ {0xbc, 0x90},
+ {0xbd, 0x3a},
+ {0xc1, 0x67},
+ {0xf0, 0x01},
+ {0x20, 0x11},
+ {0x23, 0x90},
+ {0x24, 0x15},
+ {0x25, 0x87},
+ {0xbc, 0x9f},
+ {0xbd, 0x3a},
+ {0x48, 0xe6},
+ {0x49, 0xc0},
+ {0x4a, 0xd0},
+ {0x4b, 0x48},
+
+ // [cvbs_on]
+ {0xf0, 0x36},
+ {0x11, 0x00},
+ {0xf0, 0x01},
+ {0x79, 0xf1},
+
+ // [cvbs_off]
+ {0xf0, 0x36},
+ {0x11, 0x80},
+ {0xf0, 0x01},
+ {0x79, 0xc1},
+};
+
+*/
\ No newline at end of file
diff --git a/code/components/esp32-camera-master/sensors/private_include/sc101iot.h b/code/components/esp32-camera-master/sensors/private_include/sc101iot.h
new file mode 100644
index 00000000..85858498
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/private_include/sc101iot.h
@@ -0,0 +1,31 @@
+/*
+ *
+ * SC101IOT DVP driver.
+ *
+ */
+#ifndef __SC101IOT_H__
+#define __SC101IOT_H__
+
+#include "sensor.h"
+
+/**
+ * @brief Detect sensor pid
+ *
+ * @param slv_addr SCCB address
+ * @param id Detection result
+ * @return
+ * 0: Can't detect this sensor
+ * Nonzero: This sensor has been detected
+ */
+int sc101iot_detect(int slv_addr, sensor_id_t *id);
+
+/**
+ * @brief initialize sensor function pointers
+ *
+ * @param sensor pointer of sensor
+ * @return
+ * Always 0
+ */
+int sc101iot_init(sensor_t *sensor);
+
+#endif // __SC101IOT_H__
diff --git a/code/components/esp32-camera-master/sensors/private_include/sc101iot_settings.h b/code/components/esp32-camera-master/sensors/private_include/sc101iot_settings.h
new file mode 100644
index 00000000..2eb14398
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/private_include/sc101iot_settings.h
@@ -0,0 +1,257 @@
+//Preview Type:0:DVP Raw 10 bit// 1:Raw 8 bit// 2:YUV422// 3:RAW16
+//Preview Type:4:RGB565// 5:Pixart SPI// 6:MIPI 10bit// 7:MIPI 12bit// 8: MTK SPI
+//port 0:MIPI// 1:Parallel// 2:MTK// 3:SPI// 4:TEST// 5: HISPI// 6 : Z2P/Z4P
+//I2C Mode :0:Normal 8Addr,8Data// 1:Samsung 8 Addr,8Data// 2:Micron 8 Addr,16Data
+//I2C Mode :3:Stmicro 16Addr,8Data//4:Micron2 16 Addr,16Data
+//Out Format :0:YCbYCr/RG_GB// 1:YCrYCb/GR_BG// 2:CbYCrY/GB_RG// 3:CrYCbY/BG_GR
+//MCLK Speed :0:6M//1:8M//2:10M//3:11.4M//4:12M//5:12.5M//6:13.5M//7:15M//8:18M//9:24M
+//pin :BIT0 pwdn// BIT1:reset
+//avdd 0:2.8V// 1:2.5V// 2:1.8V
+//dovdd 0:2.8V// 1:2.5V// 2:1.8V
+//dvdd 0:1.8V// 1:1.5V// 2:1.2V
+/*
+[DataBase]
+DBName=DemoSens
+
+[Vendor]
+VendorName=SmartSens
+I2C_CRC=0
+
+[Sensor]
+SensorName=SC101AP_raw
+width=1280
+height=720
+port=1
+type=2
+pin=3
+SlaveID=0xd0
+mode=0
+FlagReg=0xf7
+FlagMask=0xff
+FlagData=0xda
+FlagReg1=0xf8
+FlagMask1=0xff
+FlagData1=0x4a
+outformat=0
+mclk=20
+avdd=2.800000
+dovdd=2.800000
+dvdd=1.200000
+
+Ext0=0
+Ext1=0
+Ext2=0
+AFVCC=0.00
+VPP=0.000000
+*/
+#include
+
+static const uint8_t sc101iot_default_init_regs[][2] = {
+#if CONFIG_SC101IOT_720P_15FPS_ENABLED // 720P+YUV422+15FPS sensor default regs
+/* Here are some test results:
+# size xclk fps pic pclk
+# ------- ------- ------ --------- ------- --- --- --- --- ---
+# 720p 4 3 err
+# 720p 8 5 normal 15
+# 720p 10 7.8 normal 19
+# 720p 20 15 warning 37.5
+# VGA 8 6 normal
+# VGA 20 16 normal
+
+*/
+ {0xf0, 0x30},
+ {0x01, 0xff},
+ {0x02, 0xe0},
+ {0x30, 0x10},
+ {0x3f, 0x81},
+ {0xf0, 0x00},
+ {0x70, 0x6b},
+ {0x72, 0x30},
+ {0x84, 0xb4},
+ {0x8b, 0x00},
+ {0x8c, 0x20},
+ {0x8d, 0x02},
+ {0x8e, 0xec},
+ {0x9e, 0x10},
+ {0xb0, 0xc1},
+ {0xc8, 0x10},
+ {0xc9, 0x10},
+ {0xc6, 0x00},
+ {0xe0, 0x0f},
+ {0xb5, 0xf0},
+ {0xde, 0x80},
+ {0xb5, 0xf0},
+ {0xde, 0x80},
+ {0xb2, 0x50},
+ {0xb3, 0xfc},
+ {0xb4, 0x40},
+ {0xb5, 0xc0},
+ {0xb6, 0x50},
+ {0xb7, 0xfc},
+ {0xb8, 0x40},
+ {0xb9, 0xc0},
+ {0xba, 0xff},
+ {0xbb, 0xcc},
+ {0xbc, 0xa9},
+ {0xbd, 0x7d},
+ {0xc1, 0x77},
+ {0xf0, 0x01},
+ {0x70, 0x02},
+ {0x71, 0x02},
+ {0x72, 0x50},
+ {0x73, 0x02},
+ {0x74, 0xd2},
+ {0x75, 0x20},
+ {0x76, 0x81},
+ {0x77, 0x8c},
+ {0x78, 0x81},
+ {0xf4, 0x01},
+ {0xf5, 0x00},
+ {0xf6, 0x00},
+ {0xf0, 0x36},
+ {0x40, 0x03},
+ {0x41, 0x01},
+ {0xf0, 0x39},
+ {0x02, 0x70},
+ {0xf0, 0x32},
+ {0x41, 0x00},
+ {0x43, 0x01},
+ {0x48, 0x02},
+ {0xf0, 0x45},
+ {0x09, 0x20},
+ {0xf0, 0x33},
+ {0x33, 0x10},
+ {0xf0, 0x30},
+ {0x38, 0x44},
+ {0xf0, 0x39},
+ {0x07, 0x00},
+ {0x08, 0x19},
+ {0x47, 0x00},
+ {0x48, 0x00},
+ {0xf0, 0x37},
+ {0x24, 0x31},
+ {0xf0, 0x34},
+ {0x9f, 0x02},
+ {0xa6, 0x51},
+ {0xa7, 0x57},
+ {0xe8, 0x5f},
+ {0xa8, 0x50},
+ {0xa9, 0x50},
+ {0xe9, 0x50},
+ {0xf0, 0x33},
+ {0xb3, 0x58},
+ {0xb2, 0x78},
+ {0xf0, 0x34},
+ {0x9f, 0x03},
+ {0xa6, 0x51},
+ {0xa7, 0x57},
+ {0xaa, 0x01},
+ {0xab, 0x28},
+ {0xac, 0x01},
+ {0xad, 0x38},
+ {0xf0, 0x33},
+ {0x0a, 0x01},
+ {0x0b, 0x28},
+ {0xf0, 0x33},
+ {0x64, 0x0f},
+ {0xec, 0x51},
+ {0xed, 0x57},
+ {0x06, 0x58},
+ {0xe9, 0x58},
+ {0xeb, 0x68},
+ {0xf0, 0x33},
+ {0x64, 0x0f},
+ {0xf0, 0x36},
+ {0x70, 0xdf},
+ {0xb6, 0x40},
+ {0xb7, 0x51},
+ {0xb8, 0x53},
+ {0xb9, 0x57},
+ {0xba, 0x5f},
+ {0xb0, 0x84},
+ {0xb1, 0x82},
+ {0xb2, 0x84},
+ {0xb3, 0x88},
+ {0xb4, 0x90},
+ {0xb5, 0x90},
+ {0xf0, 0x36},
+ {0x7e, 0x50},
+ {0x7f, 0x51},
+ {0x77, 0x81},
+ {0x78, 0x86},
+ {0x79, 0x89},
+ {0xf0, 0x36},
+ {0x70, 0xdf},
+ {0x9c, 0x51},
+ {0x9d, 0x57},
+ {0x90, 0x54},
+ {0x91, 0x54},
+ {0x92, 0x56},
+ {0xf0, 0x36},
+ {0xa0, 0x51},
+ {0xa1, 0x57},
+ {0x96, 0x33},
+ {0x97, 0x43},
+ {0x98, 0x43},
+ {0xf0, 0x36},
+ {0x70, 0xdf},
+ {0x7c, 0x40},
+ {0x7d, 0x53},
+ {0x74, 0xd0},
+ {0x75, 0xf0},
+ {0x76, 0xf0},
+ {0xf0, 0x37},
+ {0x0f, 0xd5},
+ {0x7a, 0x40},
+ {0x7b, 0x57},
+ {0x71, 0x09},
+ {0x72, 0x09},
+ {0x73, 0x05},
+ {0xf0, 0x33},
+ {0x01, 0x44},
+ {0xf0, 0x36},
+ {0x37, 0xfb},
+ {0xf0, 0x36},
+ {0x3c, 0x0d},
+ {0xf0, 0x33},
+ {0x14, 0x95},
+ {0xf0, 0x33},
+ {0x8f, 0x80},
+ {0xf0, 0x37},
+ {0x27, 0x14},
+ {0x28, 0x03},
+ {0xf0, 0x36},
+ {0x37, 0xf4},
+ {0xf0, 0x33},
+ {0x01, 0x44},
+ {0xf0, 0x36},
+ {0x79, 0x89},
+ {0xf0, 0x34},
+ {0xac, 0x01},
+ {0xad, 0x40},
+ {0xf0, 0x33},
+ {0xeb, 0x70},
+ {0xf0, 0x34},
+ {0xa8, 0x50},
+ {0xa9, 0x50},
+ {0xf0, 0x33},
+ {0xb3, 0x58},
+ {0xf0, 0x36},
+ {0x11, 0x80},
+ {0xf0, 0x36},
+ {0x41, 0x51},
+ {0xf0, 0x3f},
+ {0x03, 0x09},
+ {0xf0, 0x32},
+ {0x0c, 0x06},
+ {0x0d, 0x82},
+ {0x0e, 0x02},
+ {0x0f, 0xee},
+ {0xf0, 0x36},
+ {0xea, 0x09},
+ {0xeb, 0xf5},
+ {0xec, 0x11},
+ {0xed, 0x27},
+ {0xe9, 0x20},
+#endif
+};
diff --git a/code/components/esp32-camera-master/sensors/sc030iot.c b/code/components/esp32-camera-master/sensors/sc030iot.c
new file mode 100644
index 00000000..86f525f3
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/sc030iot.c
@@ -0,0 +1,335 @@
+/*
+ * SC030IOT driver.
+ *
+ * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD
+ *
+ * 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
+#include
+#include
+#include
+#include "sccb.h"
+#include "xclk.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "sc030iot.h"
+#include "sc030iot_settings.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#else
+#include "esp_log.h"
+static const char* TAG = "sc030";
+#endif
+
+#define SC030_SENSOR_ID_HIGH_REG 0XF7
+#define SC030_SENSOR_ID_LOW_REG 0XF8
+#define SC030_MAX_FRAME_WIDTH (640)
+#define SC030_MAX_FRAME_HIGH (480)
+
+// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int get_reg(sensor_t *sensor, int reg, int reg_value_mask)
+{
+ int ret = 0;
+ uint8_t reg_high = (reg>>8) & 0xFF;
+ uint8_t reg_low = reg & 0xFF;
+
+ if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+ return -1;
+ }
+
+ ret = SCCB_Read(sensor->slv_addr, reg_low);
+ if(ret > 0){
+ ret &= reg_value_mask;
+ }
+ return ret;
+}
+
+// sc030 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int set_reg(sensor_t *sensor, int reg, int mask, int value)
+{
+ int ret = 0;
+ uint8_t reg_high = (reg>>8) & 0xFF;
+ uint8_t reg_low = reg & 0xFF;
+
+ if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+ return -1;
+ }
+
+ ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF);
+ return ret;
+}
+
+static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len)
+{
+ int i=0, res = 0;
+ while (islv_addr, regs[i][0], regs[i][1]);
+ if (res) {
+ return res;
+ }
+ i++;
+ }
+ return res;
+}
+
+static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value)
+{
+ int ret = 0;
+ ret = get_reg(sensor, reg, 0xff);
+ if(ret < 0){
+ return ret;
+ }
+ uint8_t mask = ((1 << length) - 1) << offset;
+ value = (ret & ~mask) | ((value << offset) & mask);
+ ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value);
+ return ret;
+}
+
+#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;}
+#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;}
+#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;}
+
+static int set_hmirror(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ if(enable) {
+ SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // mirror on
+ } else {
+ SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // mirror off
+ }
+
+ return ret;
+}
+
+static int set_vflip(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ if(enable) {
+ SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on
+ } else {
+ SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off
+ }
+
+ return ret;
+}
+
+static int set_colorbar(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable test pattern mode
+
+ return ret;
+}
+
+static int set_sharpness(sensor_t *sensor, int level)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement
+ WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value
+ WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit
+
+ return ret;
+}
+
+static int set_agc_gain(sensor_t *sensor, int gain)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control
+ WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1
+ WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2
+ WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3
+ WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4
+
+ return ret;
+}
+
+static int set_aec_value(sensor_t *sensor, int value)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control
+ WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target
+
+ return ret;
+}
+
+static int set_awb_gain(sensor_t *sensor, int value)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control
+ WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain
+ WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain
+ return ret;
+}
+
+static int set_saturation(sensor_t *sensor, int level)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control
+ WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128)
+ WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128)
+ return ret;
+}
+
+static int set_contrast(sensor_t *sensor, int level)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control
+ WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64)
+ return ret;
+}
+
+static int reset(sensor_t *sensor)
+{
+ int ret = set_regs(sensor, sc030iot_default_init_regs, sizeof(sc030iot_default_init_regs)/(sizeof(uint8_t) * 2));
+
+ // Delay
+ vTaskDelay(50 / portTICK_PERIOD_MS);
+
+ // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor
+ // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff));
+ if (ret) {
+ ESP_LOGE(TAG, "reset fail");
+ }
+ return ret;
+}
+
+static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h)
+{
+ int ret = 0;
+ //sc:H_start={0x0172[1:0],0x0170},H_end={0x0172[5:4],0x0171},
+ WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff);
+ WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff);
+ WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x03) | (((offset_x+w)>>4)&0x30));
+
+ //sc:V_start={0x0175[1:0],0x0173},H_end={0x0175[5:4],0x0174},
+ WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff);
+ WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff);
+ WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x03) | (((offset_y+h)>>4)&0x30));
+
+ vTaskDelay(10 / portTICK_PERIOD_MS);
+
+ return ret;
+}
+
+static int set_framesize(sensor_t *sensor, framesize_t framesize)
+{
+ uint16_t w = resolution[framesize].width;
+ uint16_t h = resolution[framesize].height;
+ if(w>SC030_MAX_FRAME_WIDTH || h > SC030_MAX_FRAME_HIGH) {
+ goto err;
+ }
+
+ uint16_t offset_x = (640-w) /2;
+ uint16_t offset_y = (480-h) /2;
+
+ if(set_window(sensor, offset_x, offset_y, w, h)) {
+ goto err;
+ }
+
+ sensor->status.framesize = framesize;
+ return 0;
+err:
+ ESP_LOGE(TAG, "frame size err");
+ return -1;
+}
+
+static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
+{
+ int ret=0;
+ sensor->pixformat = pixformat;
+
+ switch (pixformat) {
+ case PIXFORMAT_RGB565:
+ case PIXFORMAT_RAW:
+ case PIXFORMAT_GRAYSCALE:
+ ESP_LOGE(TAG, "Not support");
+ break;
+ case PIXFORMAT_YUV422: // For now, sc030/sc031 sensor only support YUV422.
+ break;
+ default:
+ return -1;
+ }
+
+ return ret;
+}
+
+static int init_status(sensor_t *sensor)
+{
+ return 0;
+}
+
+static int set_dummy(sensor_t *sensor, int val){ return -1; }
+
+static int set_xclk(sensor_t *sensor, int timer, int xclk)
+{
+ int ret = 0;
+ sensor->xclk_freq_hz = xclk * 1000000U;
+ ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
+ return ret;
+}
+
+int sc030iot_detect(int slv_addr, sensor_id_t *id)
+{
+ if (SC030IOT_SCCB_ADDR == slv_addr) {
+ uint8_t MIDL = SCCB_Read(slv_addr, SC030_SENSOR_ID_LOW_REG);
+ uint8_t MIDH = SCCB_Read(slv_addr, SC030_SENSOR_ID_HIGH_REG);
+ uint16_t PID = MIDH << 8 | MIDL;
+ if (SC030IOT_PID == PID) {
+ id->PID = PID;
+ return PID;
+ } else {
+ ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
+ }
+ }
+ return 0;
+}
+
+int sc030iot_init(sensor_t *sensor)
+{
+ // Set function pointers
+ sensor->reset = reset;
+ sensor->init_status = init_status;
+ sensor->set_pixformat = set_pixformat;
+ sensor->set_framesize = set_framesize;
+
+ sensor->set_saturation= set_saturation;
+ sensor->set_colorbar = set_colorbar;
+ sensor->set_hmirror = set_hmirror;
+ sensor->set_vflip = set_vflip;
+ sensor->set_sharpness = set_sharpness;
+ sensor->set_agc_gain = set_agc_gain;
+ sensor->set_aec_value = set_aec_value;
+ sensor->set_awb_gain = set_awb_gain;
+ sensor->set_contrast = set_contrast;
+ //not supported
+ sensor->set_denoise = set_dummy;
+ sensor->set_quality = set_dummy;
+ sensor->set_special_effect = set_dummy;
+ sensor->set_wb_mode = set_dummy;
+ sensor->set_ae_level = set_dummy;
+
+
+ sensor->get_reg = get_reg;
+ sensor->set_reg = set_reg;
+ sensor->set_xclk = set_xclk;
+
+ ESP_LOGD(TAG, "sc030iot Attached");
+
+ return 0;
+}
\ No newline at end of file
diff --git a/code/components/esp32-camera-master/sensors/sc101iot.c b/code/components/esp32-camera-master/sensors/sc101iot.c
new file mode 100644
index 00000000..310a0476
--- /dev/null
+++ b/code/components/esp32-camera-master/sensors/sc101iot.c
@@ -0,0 +1,342 @@
+/*
+ * SC101IOT driver.
+ *
+ * Copyright 2020-2022 Espressif Systems (Shanghai) PTE LTD
+ *
+ * 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
+#include
+#include
+#include
+#include "sccb.h"
+#include "xclk.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "sc101iot.h"
+#include "sc101iot_settings.h"
+
+#if defined(ARDUINO_ARCH_ESP32) && defined(CONFIG_ARDUHAL_ESP_LOG)
+#include "esp32-hal-log.h"
+#else
+#include "esp_log.h"
+static const char* TAG = "sc101";
+#endif
+
+#define SC101_SENSOR_ID_HIGH_REG 0XF7
+#define SC101_SENSOR_ID_LOW_REG 0XF8
+#define SC101_MAX_FRAME_WIDTH (1280)
+#define SC101_MAX_FRAME_HIGH (720)
+
+// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int get_reg(sensor_t *sensor, int reg, int mask)
+{
+ int ret = 0;
+ uint8_t reg_high = (reg>>8) & 0xFF;
+ uint8_t reg_low = reg & 0xFF;
+
+ if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+ return -1;
+ }
+
+ ret = SCCB_Read(sensor->slv_addr, reg_low);
+ if(ret > 0){
+ ret &= mask;
+ }
+ return ret;
+}
+
+// sc101 use "i2c paging mode", so the high byte of the register needs to be written to the 0xf0 reg.
+// For more information please refer to the Technical Reference Manual.
+static int set_reg(sensor_t *sensor, int reg, int mask, int value)
+{
+ int ret = 0;
+ uint8_t reg_high = (reg>>8) & 0xFF;
+ uint8_t reg_low = reg & 0xFF;
+
+ if(SCCB_Write(sensor->slv_addr, 0xf0, reg_high)) {
+ return -1;
+ }
+
+ ret = SCCB_Write(sensor->slv_addr, reg_low, value & 0xFF);
+ return ret;
+}
+
+static int set_regs(sensor_t *sensor, const uint8_t (*regs)[2], uint32_t regs_entry_len)
+{
+ int i=0, res = 0;
+ while (islv_addr, regs[i][0], regs[i][1]);
+ if (res) {
+ return res;
+ }
+ i++;
+ }
+ return res;
+}
+
+static int set_reg_bits(sensor_t *sensor, int reg, uint8_t offset, uint8_t length, uint8_t value)
+{
+ int ret = 0;
+ ret = get_reg(sensor, reg, 0xff);
+ if(ret < 0){
+ return ret;
+ }
+ uint8_t mask = ((1 << length) - 1) << offset;
+ value = (ret & ~mask) | ((value << offset) & mask);
+ ret = set_reg(sensor, reg & 0xFFFF, 0xFFFF, value);
+ return ret;
+}
+
+#define WRITE_REGS_OR_RETURN(regs, regs_entry_len) ret = set_regs(sensor, regs, regs_entry_len); if(ret){return ret;}
+#define WRITE_REG_OR_RETURN(reg, val) ret = set_reg(sensor, reg, 0xFF, val); if(ret){return ret;}
+#define SET_REG_BITS_OR_RETURN(reg, offset, length, val) ret = set_reg_bits(sensor, reg, offset, length, val); if(ret){return ret;}
+
+static int set_hmirror(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ if(enable) {
+ SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x3); // enable mirror
+ } else {
+ SET_REG_BITS_OR_RETURN(0x3221, 1, 2, 0x0); // disable mirror
+ }
+
+ return ret;
+}
+
+static int set_vflip(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ if(enable) {
+ SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x3); // flip on
+ } else {
+ SET_REG_BITS_OR_RETURN(0x3221, 5, 2, 0x0); // flip off
+ }
+
+ return ret;
+}
+
+static int set_colorbar(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x0100, 7, 1, enable & 0xff); // enable colorbar mode
+ return ret;
+}
+
+static int set_raw_gma(sensor_t *sensor, int enable)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00f5, 1, 1, enable & 0xff); // enable gamma compensation
+
+ return ret;
+}
+
+static int set_sharpness(sensor_t *sensor, int level)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00e0, 1, 1, 1); // enable edge enhancement
+ WRITE_REG_OR_RETURN(0x00d0, level & 0xFF); // base value
+ WRITE_REG_OR_RETURN(0x00d2, (level >> 8) & 0xFF); // limit
+
+ return ret;
+}
+
+static int set_agc_gain(sensor_t *sensor, int gain)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x0070, 1, 1, 1); // enable auto agc control
+ WRITE_REG_OR_RETURN(0x0068, gain & 0xFF); // Window weight setting1
+ WRITE_REG_OR_RETURN(0x0069, (gain >> 8) & 0xFF); // Window weight setting2
+ WRITE_REG_OR_RETURN(0x006a, (gain >> 16) & 0xFF); // Window weight setting3
+ WRITE_REG_OR_RETURN(0x006b, (gain >> 24) & 0xFF); // Window weight setting4
+
+ return ret;
+}
+
+static int set_aec_value(sensor_t *sensor, int value)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x0070, 0, 1, 1); // enable auto aec control
+ WRITE_REG_OR_RETURN(0x0072, value & 0xFF); // AE target
+
+ return ret;
+}
+
+static int set_awb_gain(sensor_t *sensor, int value)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00b0, 0, 1, 1); // enable awb control
+ WRITE_REG_OR_RETURN(0x00c8, value & 0xFF); // blue gain
+ WRITE_REG_OR_RETURN(0x00c9, (value>>8) & 0XFF); // red gain
+ return ret;
+}
+
+static int set_saturation(sensor_t *sensor, int level)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00f5, 5, 1, 0); // enable saturation control
+ WRITE_REG_OR_RETURN(0x0149, level & 0xFF); // blue saturation gain (/128)
+ WRITE_REG_OR_RETURN(0x014a, (level>>8) & 0XFF); // red saturation gain (/128)
+ return ret;
+}
+
+static int set_contrast(sensor_t *sensor, int level)
+{
+ int ret = 0;
+ SET_REG_BITS_OR_RETURN(0x00f5, 6, 1, 0); // enable contrast control
+ WRITE_REG_OR_RETURN(0x014b, level); // contrast coefficient(/64)
+ return ret;
+}
+
+static int reset(sensor_t *sensor)
+{
+ int ret = set_regs(sensor, sc101iot_default_init_regs, sizeof(sc101iot_default_init_regs)/(sizeof(uint8_t) * 2));
+
+ // Delay
+ vTaskDelay(50 / portTICK_PERIOD_MS);
+
+ // ESP_LOGI(TAG, "set_reg=%0x", set_reg(sensor, 0x0100, 0xffff, 0x00)); // write 0x80 to enter test mode if you want to test the sensor
+ // ESP_LOGI(TAG, "0x0100=%0x", get_reg(sensor, 0x0100, 0xffff));
+ if (ret) {
+ ESP_LOGE(TAG, "reset fail");
+ }
+ return ret;
+}
+
+static int set_window(sensor_t *sensor, int offset_x, int offset_y, int w, int h)
+{
+ int ret = 0;
+ //sc:H_start={0x0172[3:0],0x0170},H_end={0x0172[7:4],0x0171},
+ WRITE_REG_OR_RETURN(0x0170, offset_x & 0xff);
+ WRITE_REG_OR_RETURN(0x0171, (offset_x+w) & 0xff);
+ WRITE_REG_OR_RETURN(0x0172, ((offset_x>>8) & 0x0f) | (((offset_x+w)>>4)&0xf0));
+
+ //sc:V_start={0x0175[3:0],0x0173},H_end={0x0175[7:4],0x0174},
+ WRITE_REG_OR_RETURN(0x0173, offset_y & 0xff);
+ WRITE_REG_OR_RETURN(0x0174, (offset_y+h) & 0xff);
+ WRITE_REG_OR_RETURN(0x0175, ((offset_y>>8) & 0x0f) | (((offset_y+h)>>4)&0xf0));
+
+ vTaskDelay(10 / portTICK_PERIOD_MS);
+
+ return ret;
+}
+
+static int set_framesize(sensor_t *sensor, framesize_t framesize)
+{
+ uint16_t w = resolution[framesize].width;
+ uint16_t h = resolution[framesize].height;
+ if(w>SC101_MAX_FRAME_WIDTH || h > SC101_MAX_FRAME_HIGH) {
+ goto err;
+ }
+
+ uint16_t offset_x = (SC101_MAX_FRAME_WIDTH-w) /2;
+ uint16_t offset_y = (SC101_MAX_FRAME_HIGH-h) /2;
+
+ if(set_window(sensor, offset_x, offset_y, w, h)) {
+ goto err;
+ }
+
+ sensor->status.framesize = framesize;
+ return 0;
+err:
+ ESP_LOGE(TAG, "frame size err");
+ return -1;
+}
+
+static int set_pixformat(sensor_t *sensor, pixformat_t pixformat)
+{
+ int ret=0;
+ sensor->pixformat = pixformat;
+
+ switch (pixformat) {
+ case PIXFORMAT_RGB565:
+ case PIXFORMAT_RAW:
+ case PIXFORMAT_GRAYSCALE:
+ ESP_LOGE(TAG, "Not support");
+ break;
+ case PIXFORMAT_YUV422: // For now, sc101 sensor only support YUV422.
+ break;
+ default:
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int init_status(sensor_t *sensor)
+{
+ return 0;
+}
+
+static int set_dummy(sensor_t *sensor, int val){ return -1; }
+
+static int set_xclk(sensor_t *sensor, int timer, int xclk)
+{
+ int ret = 0;
+ sensor->xclk_freq_hz = xclk * 1000000U;
+ ret = xclk_timer_conf(timer, sensor->xclk_freq_hz);
+ return ret;
+}
+
+int sc101iot_detect(int slv_addr, sensor_id_t *id)
+{
+ if (SC101IOT_SCCB_ADDR == slv_addr) {
+ uint8_t MIDL = SCCB_Read(slv_addr, SC101_SENSOR_ID_LOW_REG);
+ uint8_t MIDH = SCCB_Read(slv_addr, SC101_SENSOR_ID_HIGH_REG);
+ uint16_t PID = MIDH << 8 | MIDL;
+ if (SC101IOT_PID == PID) {
+ id->PID = PID;
+ return PID;
+ } else {
+ ESP_LOGI(TAG, "Mismatch PID=0x%x", PID);
+ }
+ }
+ return 0;
+}
+
+int sc101iot_init(sensor_t *sensor)
+{
+ // Set function pointers
+ sensor->reset = reset;
+ sensor->init_status = init_status;
+ sensor->set_pixformat = set_pixformat;
+ sensor->set_framesize = set_framesize;
+ sensor->set_hmirror = set_hmirror;
+ sensor->set_vflip = set_vflip;
+ sensor->set_colorbar = set_colorbar;
+ sensor->set_raw_gma = set_raw_gma;
+ sensor->set_sharpness = set_sharpness;
+ sensor->set_agc_gain = set_agc_gain;
+ sensor->set_aec_value = set_aec_value;
+ sensor->set_awb_gain = set_awb_gain;
+ sensor->set_saturation= set_saturation;
+ sensor->set_contrast = set_contrast;
+
+ sensor->set_denoise = set_dummy;
+ sensor->set_quality = set_dummy;
+ sensor->set_special_effect = set_dummy;
+ sensor->set_wb_mode = set_dummy;
+ sensor->set_ae_level = set_dummy;
+
+
+ sensor->get_reg = get_reg;
+ sensor->set_reg = set_reg;
+ sensor->set_xclk = set_xclk;
+
+ ESP_LOGD(TAG, "sc101iot Attached");
+
+ return 0;
+}
\ No newline at end of file
diff --git a/code/components/esp32-camera-master/target/esp32/ll_cam.c b/code/components/esp32-camera-master/target/esp32/ll_cam.c
index d0f0c862..ed7f9413 100644
--- a/code/components/esp32-camera-master/target/esp32/ll_cam.c
+++ b/code/components/esp32-camera-master/target/esp32/ll_cam.c
@@ -34,10 +34,14 @@ static inline int gpio_ll_get_level(gpio_dev_t *hw, int gpio_num)
#include "xclk.h"
#include "cam_hal.h"
+#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3)
+#include "esp_rom_gpio.h"
+#endif
+
#if (ESP_IDF_VERSION_MAJOR >= 5)
#define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE
#define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE
-#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
+#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
#endif
static const char *TAG = "esp32 ll_cam";
@@ -233,7 +237,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
//DBG_PIN_SET(0);
}
-bool ll_cam_stop(cam_obj_t *cam)
+bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
{
I2S0.conf.rx_start = 0;
I2S_ISR_DISABLE(in_suc_eof);
@@ -308,7 +312,7 @@ esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
I2S0.clkm_conf.clkm_div_a = 0;
I2S0.clkm_conf.clkm_div_b = 0;
I2S0.clkm_conf.clkm_div_num = 2;
-
+
I2S0.fifo_conf.dscr_en = 1;
I2S0.fifo_conf.rx_fifo_mod = sampling_mode;
I2S0.fifo_conf.rx_fifo_mod_force_en = 1;
@@ -442,9 +446,12 @@ static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
}
// Calculate DMA size
dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
-
- ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u, dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u, image_size: %u",
- node_size * cam->dma_bytes_per_item, nodes_per_line, lines_per_node, dma_half_buffer_min * cam->dma_bytes_per_item, dma_half_buffer * cam->dma_bytes_per_item, lines_per_half_buffer, dma_buffer_size * cam->dma_bytes_per_item, image_size);
+
+ ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u, dma_half_buffer_min: %5u, dma_half_buffer: %5u,"
+ "lines_per_half_buffer: %2u, dma_buffer_size: %5u, image_size: %u",
+ (unsigned) (node_size * cam->dma_bytes_per_item), (unsigned) nodes_per_line, (unsigned) lines_per_node,
+ (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item),
+ (unsigned) (lines_per_half_buffer), (unsigned) (dma_buffer_size * cam->dma_bytes_per_item), (unsigned) image_size);
cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
diff --git a/code/components/esp32-camera-master/target/esp32s2/ll_cam.c b/code/components/esp32-camera-master/target/esp32s2/ll_cam.c
index e54b81f0..b6f0a92b 100644
--- a/code/components/esp32-camera-master/target/esp32s2/ll_cam.c
+++ b/code/components/esp32-camera-master/target/esp32s2/ll_cam.c
@@ -21,10 +21,15 @@
#include "xclk.h"
#include "cam_hal.h"
+#if (ESP_IDF_VERSION_MAJOR >= 4) && (ESP_IDF_VERSION_MINOR >= 3)
+#include "esp_rom_gpio.h"
+#endif
+
#if (ESP_IDF_VERSION_MAJOR >= 5)
#define GPIO_PIN_INTR_POSEDGE GPIO_INTR_POSEDGE
#define GPIO_PIN_INTR_NEGEDGE GPIO_INTR_NEGEDGE
-#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
+#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
+#define ets_delay_us(a) esp_rom_delay_us(a)
#endif
static const char *TAG = "s2 ll_cam";
@@ -70,7 +75,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
}
}
-bool ll_cam_stop(cam_obj_t *cam)
+bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
{
I2S0.conf.rx_start = 0;
@@ -119,7 +124,7 @@ bool ll_cam_start(cam_obj_t *cam, int frame_pos)
} else {
I2S0.in_link.addr = ((uint32_t)&cam->frames[frame_pos].dma[0]) & 0xfffff;
}
-
+
I2S0.in_link.start = 1;
I2S0.conf.rx_start = 1;
return true;
@@ -299,8 +304,8 @@ static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
}
}
- ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
- node_size * cam->dma_bytes_per_item, nodes_per_line, lines_per_node);
+ ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
+ (unsigned) (node_size * cam->dma_bytes_per_item), nodes_per_line, lines_per_node);
cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
@@ -332,9 +337,10 @@ static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
size_t dma_buffer_max = 2 * dma_half_buffer_max;
size_t dma_buffer_size = dma_buffer_max;
dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
-
- ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
- dma_half_buffer_min * cam->dma_bytes_per_item, dma_half_buffer * cam->dma_bytes_per_item, lines_per_half_buffer, dma_buffer_size * cam->dma_bytes_per_item);
+
+ ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
+ (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item),
+ (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item));
cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
diff --git a/code/components/esp32-camera-master/target/esp32s3/ll_cam.c b/code/components/esp32-camera-master/target/esp32s3/ll_cam.c
index ce405d16..7520cac3 100644
--- a/code/components/esp32-camera-master/target/esp32s3/ll_cam.c
+++ b/code/components/esp32-camera-master/target/esp32s3/ll_cam.c
@@ -22,10 +22,15 @@
#include "soc/gdma_reg.h"
#include "ll_cam.h"
#include "cam_hal.h"
+#include "esp_rom_gpio.h"
#if (ESP_IDF_VERSION_MAJOR >= 5)
-#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
-#define gpio_matrix_out(a,b,c,d) gpio_iomux_out(a,b,c)
+#include "soc/gpio_sig_map.h"
+#include "soc/gpio_periph.h"
+#include "soc/io_mux_reg.h"
+#define gpio_matrix_in(a,b,c) esp_rom_gpio_connect_in_signal(a,b,c)
+#define gpio_matrix_out(a,b,c,d) esp_rom_gpio_connect_out_signal(a,b,c,d)
+#define ets_delay_us(a) esp_rom_delay_us(a)
#endif
static const char *TAG = "s3 ll_cam";
@@ -74,7 +79,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
}
}
-bool ll_cam_stop(cam_obj_t *cam)
+bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
{
if (cam->jpeg_mode || !cam->psram_mode) {
GDMA.channel[cam->dma_num].in.int_ena.in_suc_eof = 0;
@@ -170,6 +175,7 @@ static esp_err_t ll_cam_dma_init(cam_obj_t *cam)
}
GDMA.channel[cam->dma_num].in.conf1.in_check_owner = 0;
+ // GDMA.channel[cam->dma_num].in.conf1.in_ext_mem_bk_size = 2;
GDMA.channel[cam->dma_num].in.peri_sel.sel = 5;
//GDMA.channel[cam->dma_num].in.pri.rx_pri = 1;//rx prio 0-15
@@ -178,8 +184,57 @@ static esp_err_t ll_cam_dma_init(cam_obj_t *cam)
return ESP_OK;
}
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+static esp_err_t ll_cam_converter_config(cam_obj_t *cam, const camera_config_t *config)
+{
+ esp_err_t ret = ESP_OK;
+
+ switch (config->conv_mode) {
+ case YUV422_TO_YUV420:
+ if (config->pixel_format != PIXFORMAT_YUV422) {
+ ret = ESP_FAIL;
+ } else {
+ ESP_LOGI(TAG, "YUV422 to YUV420 mode");
+ LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 1;
+ LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
+ LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 1;
+ }
+ break;
+ case YUV422_TO_RGB565:
+ if (config->pixel_format != PIXFORMAT_YUV422) {
+ ret = ESP_FAIL;
+ } else {
+ ESP_LOGI(TAG, "YUV422 to RGB565 mode");
+ LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 3;
+ LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
+ LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 0;
+ }
+ break;
+ default:
+ break;
+ }
+#if CONFIG_LCD_CAM_CONV_BT709_ENABLED
+ LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 1;
+#else
+ LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 0;
+#endif
+#if CONFIG_LCD_CAM_CONV_FULL_RANGE_ENABLED
+ LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 1;
+ LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 1;
+#else
+ LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 0;
+ LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 0;
+#endif
+ LCD_CAM.cam_rgb_yuv.cam_conv_mode_8bits_on = 1;
+ LCD_CAM.cam_rgb_yuv.cam_conv_bypass = 1;
+ cam->conv_mode = config->conv_mode;
+ return ret;
+}
+#endif
+
esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
{
+ esp_err_t ret = ESP_OK;
if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) {
REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN);
@@ -188,7 +243,7 @@ esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
}
LCD_CAM.cam_ctrl.val = 0;
-
+
LCD_CAM.cam_ctrl.cam_clkm_div_b = 0;
LCD_CAM.cam_ctrl.cam_clkm_div_a = 0;
LCD_CAM.cam_ctrl.cam_clkm_div_num = 160000000 / config->xclk_freq_hz;
@@ -215,15 +270,21 @@ esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config)
LCD_CAM.cam_rgb_yuv.val = 0;
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+ if (config->conv_mode) {
+ ret = ll_cam_converter_config(cam, config);
+ if(ret != ESP_OK) {
+ return ret;
+ }
+ }
+#endif
+
LCD_CAM.cam_ctrl.cam_update = 1;
LCD_CAM.cam_ctrl1.cam_start = 1;
- esp_err_t err = ll_cam_dma_init(cam);
- if(err != ESP_OK) {
- return err;
- }
-
- return ESP_OK;
+ ret = ll_cam_dma_init(cam);
+
+ return ret;
}
void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en)
@@ -262,11 +323,12 @@ esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config)
gpio_set_pull_mode(data_pins[i], GPIO_FLOATING);
gpio_matrix_in(data_pins[i], CAM_DATA_IN0_IDX + i, false);
}
-
- PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_xclk], PIN_FUNC_GPIO);
- gpio_set_direction(config->pin_xclk, GPIO_MODE_OUTPUT);
- gpio_set_pull_mode(config->pin_xclk, GPIO_FLOATING);
- gpio_matrix_out(config->pin_xclk, CAM_CLK_IDX, false, false);
+ if (config->pin_xclk >= 0) {
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[config->pin_xclk], PIN_FUNC_GPIO);
+ gpio_set_direction(config->pin_xclk, GPIO_MODE_OUTPUT);
+ gpio_set_pull_mode(config->pin_xclk, GPIO_FLOATING);
+ gpio_matrix_out(config->pin_xclk, CAM_CLK_IDX, false, false);
+ }
return ESP_OK;
}
@@ -338,8 +400,8 @@ static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
}
}
- ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
- node_size * cam->dma_bytes_per_item, nodes_per_line, lines_per_node);
+ ESP_LOGI(TAG, "node_size: %4u, nodes_per_line: %u, lines_per_node: %u",
+ (unsigned) (node_size * cam->dma_bytes_per_item), (unsigned) nodes_per_line, (unsigned) lines_per_node);
cam->dma_node_buffer_size = node_size * cam->dma_bytes_per_item;
@@ -371,9 +433,10 @@ static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
if (!cam->psram_mode) {
dma_buffer_size =(dma_buffer_max / dma_half_buffer) * dma_half_buffer;
}
-
- ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
- dma_half_buffer_min * cam->dma_bytes_per_item, dma_half_buffer * cam->dma_bytes_per_item, lines_per_half_buffer, dma_buffer_size * cam->dma_bytes_per_item);
+
+ ESP_LOGI(TAG, "dma_half_buffer_min: %5u, dma_half_buffer: %5u, lines_per_half_buffer: %2u, dma_buffer_size: %5u",
+ (unsigned) (dma_half_buffer_min * cam->dma_bytes_per_item), (unsigned) (dma_half_buffer * cam->dma_bytes_per_item),
+ (unsigned) lines_per_half_buffer, (unsigned) (dma_buffer_size * cam->dma_bytes_per_item));
cam->dma_buffer_size = dma_buffer_size * cam->dma_bytes_per_item;
cam->dma_half_buffer_size = dma_half_buffer * cam->dma_bytes_per_item;
@@ -382,7 +445,7 @@ static bool ll_cam_calc_rgb_dma(cam_obj_t *cam){
}
bool ll_cam_dma_sizes(cam_obj_t *cam)
-{
+{
cam->dma_bytes_per_item = 1;
if (cam->jpeg_mode) {
if (cam->psram_mode) {
@@ -433,8 +496,22 @@ esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_
}
cam->fb_bytes_per_pixel = 1; // frame buffer stores Y8
} else if (pix_format == PIXFORMAT_YUV422 || pix_format == PIXFORMAT_RGB565) {
- cam->in_bytes_per_pixel = 2; // camera sends YU/YV
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+ switch (cam->conv_mode) {
+ case YUV422_TO_YUV420:
+ cam->in_bytes_per_pixel = 1.5; // for DMA receive
+ cam->fb_bytes_per_pixel = 1.5; // frame buffer stores YUV420
+ break;
+ case YUV422_TO_RGB565:
+ default:
+ cam->in_bytes_per_pixel = 2; // for DMA receive
cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
+ break;
+ }
+#else
+ cam->in_bytes_per_pixel = 2; // for DMA receive
+ cam->fb_bytes_per_pixel = 2; // frame buffer stores YU/YV/RGB565
+#endif
} else if (pix_format == PIXFORMAT_JPEG) {
cam->in_bytes_per_pixel = 1;
cam->fb_bytes_per_pixel = 1;
diff --git a/code/components/esp32-camera-master/target/private_include/ll_cam.h b/code/components/esp32-camera-master/target/private_include/ll_cam.h
index 7d30c370..34c8da36 100644
--- a/code/components/esp32-camera-master/target/private_include/ll_cam.h
+++ b/code/components/esp32-camera-master/target/private_include/ll_cam.h
@@ -101,7 +101,7 @@ typedef struct {
QueueHandle_t frame_buffer_queue;
TaskHandle_t task_handle;
intr_handle_t cam_intr_handle;
-
+
uint8_t dma_num;//ESP32-S3
intr_handle_t dma_intr_handle;//ESP32-S3
@@ -116,8 +116,14 @@ typedef struct {
//for RGB/YUV modes
uint16_t width;
uint16_t height;
+#if CONFIG_CAMERA_CONVERTER_ENABLED
+ float in_bytes_per_pixel;
+ float fb_bytes_per_pixel;
+ camera_conv_mode_t conv_mode;
+#else
uint8_t in_bytes_per_pixel;
uint8_t fb_bytes_per_pixel;
+#endif
uint32_t fb_size;
cam_state_t state;
@@ -134,7 +140,7 @@ esp_err_t ll_cam_init_isr(cam_obj_t *cam);
void ll_cam_do_vsync(cam_obj_t *cam);
uint8_t ll_cam_get_dma_align(cam_obj_t *cam);
bool ll_cam_dma_sizes(cam_obj_t *cam);
-size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len);
+size_t ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in, size_t len);
esp_err_t ll_cam_set_sample_mode(cam_obj_t *cam, pixformat_t pix_format, uint32_t xclk_freq_hz, uint16_t sensor_pid);
// implemented in cam_hal
diff --git a/code/components/esp32-camera-master/test/test_camera.c b/code/components/esp32-camera-master/test/test_camera.c
index 89ad0619..f03b7c6a 100644
--- a/code/components/esp32-camera-master/test/test_camera.c
+++ b/code/components/esp32-camera-master/test/test_camera.c
@@ -6,6 +6,7 @@
#include "unity.h"
#include
#include "esp_log.h"
+#include "driver/i2c.h"
#include "esp_camera.h"
@@ -105,11 +106,16 @@
#endif
+#define I2C_MASTER_SCL_IO 4 /*!< GPIO number used for I2C master clock */
+#define I2C_MASTER_SDA_IO 5 /*!< GPIO number used for I2C master data */
+#define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
+#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
+
static const char *TAG = "test camera";
typedef void (*decode_func_t)(uint8_t *jpegbuffer, uint32_t size, uint8_t *outbuffer);
-static esp_err_t init_camera(uint32_t xclk_freq_hz, pixformat_t pixel_format, framesize_t frame_size, uint8_t fb_count)
+static esp_err_t init_camera(uint32_t xclk_freq_hz, pixformat_t pixel_format, framesize_t frame_size, uint8_t fb_count, int sccb_sda_gpio_num, int sccb_port)
{
framesize_t size_bak = frame_size;
if (PIXFORMAT_JPEG == pixel_format && FRAMESIZE_SVGA > frame_size) {
@@ -119,8 +125,9 @@ static esp_err_t init_camera(uint32_t xclk_freq_hz, pixformat_t pixel_format, fr
.pin_pwdn = PWDN_GPIO_NUM,
.pin_reset = RESET_GPIO_NUM,
.pin_xclk = XCLK_GPIO_NUM,
- .pin_sscb_sda = SIOD_GPIO_NUM,
- .pin_sscb_scl = SIOC_GPIO_NUM,
+ .pin_sccb_sda = sccb_sda_gpio_num, // If pin_sccb_sda is -1, sccb will use the already initialized i2c port specified by `sccb_i2c_port`.
+ .pin_sccb_scl = SIOC_GPIO_NUM,
+ .sccb_i2c_port = sccb_port,
.pin_d7 = Y9_GPIO_NUM,
.pin_d6 = Y8_GPIO_NUM,
@@ -226,7 +233,7 @@ static void camera_performance_test(uint32_t xclk_freq, uint32_t pic_num)
{
esp_err_t ret = ESP_OK;
//detect sensor information
- TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2));
+ TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1));
sensor_t *s = esp_camera_sensor_get();
camera_sensor_info_t *info = esp_camera_sensor_get_info(&s->id);
TEST_ASSERT_NOT_NULL(info);
@@ -249,7 +256,7 @@ static void camera_performance_test(uint32_t xclk_freq, uint32_t pic_num)
for (; format_s <= format_e; format_s++) {
for (size_t i = 0; i <= max_size; i++) {
ESP_LOGI(TAG, "\n\n===> Testing format:%s resolution: %d x %d <===", get_cam_format_name(*format_s), resolution[i].width, resolution[i].height);
- ret = init_camera(xclk_freq, *format_s, i, 2);
+ ret = init_camera(xclk_freq, *format_s, i, 2, SIOD_GPIO_NUM, -1);
vTaskDelay(100 / portTICK_RATE_MS);
if (ESP_OK != ret) {
ESP_LOGW(TAG, "Testing init failed :-(, skip this item");
@@ -276,7 +283,7 @@ static void camera_performance_test(uint32_t xclk_freq, uint32_t pic_num)
TEST_CASE("Camera driver init, deinit test", "[camera]")
{
uint64_t t1 = esp_timer_get_time();
- TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2));
+ TEST_ESP_OK(init_camera(20000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1));
uint64_t t2 = esp_timer_get_time();
ESP_LOGI(TAG, "Camera init time %llu ms", (t2 - t1) / 1000);
@@ -285,7 +292,7 @@ TEST_CASE("Camera driver init, deinit test", "[camera]")
TEST_CASE("Camera driver take RGB565 picture test", "[camera]")
{
- TEST_ESP_OK(init_camera(10000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2));
+ TEST_ESP_OK(init_camera(10000000, PIXFORMAT_RGB565, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1));
vTaskDelay(500 / portTICK_RATE_MS);
ESP_LOGI(TAG, "Taking picture...");
camera_fb_t *pic = esp_camera_fb_get();
@@ -301,7 +308,7 @@ TEST_CASE("Camera driver take RGB565 picture test", "[camera]")
TEST_CASE("Camera driver take YUV422 picture test", "[camera]")
{
- TEST_ESP_OK(init_camera(10000000, PIXFORMAT_YUV422, FRAMESIZE_QVGA, 2));
+ TEST_ESP_OK(init_camera(10000000, PIXFORMAT_YUV422, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1));
vTaskDelay(500 / portTICK_RATE_MS);
ESP_LOGI(TAG, "Taking picture...");
camera_fb_t *pic = esp_camera_fb_get();
@@ -317,7 +324,7 @@ TEST_CASE("Camera driver take YUV422 picture test", "[camera]")
TEST_CASE("Camera driver take JPEG picture test", "[camera]")
{
- TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2));
+ TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2, SIOD_GPIO_NUM, -1));
vTaskDelay(500 / portTICK_RATE_MS);
ESP_LOGI(TAG, "Taking picture...");
camera_fb_t *pic = esp_camera_fb_get();
@@ -484,6 +491,25 @@ static void img_jpeg_decode_test(uint16_t pic_index, uint16_t lib_index)
jpg_decode_test(lib_index, DECODE_RGB565, imgs[pic_index].buf, imgs[pic_index].length, imgs[pic_index].w, imgs[pic_index].h, 16);
}
+/**
+ * @brief i2c master initialization
+ */
+static esp_err_t i2c_master_init(int i2c_port)
+{
+ i2c_config_t conf = {
+ .mode = I2C_MODE_MASTER,
+ .sda_io_num = I2C_MASTER_SDA_IO,
+ .scl_io_num = I2C_MASTER_SCL_IO,
+ .sda_pullup_en = GPIO_PULLUP_ENABLE,
+ .scl_pullup_en = GPIO_PULLUP_ENABLE,
+ .master.clk_speed = I2C_MASTER_FREQ_HZ,
+ };
+
+ i2c_param_config(i2c_port, &conf);
+
+ return i2c_driver_install(i2c_port, conf.mode, 0, 0, 0);
+}
+
TEST_CASE("Conversions image 227x149 jpeg decode test", "[camera]")
{
img_jpeg_decode_test(0, 0);
@@ -498,3 +524,12 @@ TEST_CASE("Conversions image 480x320 jpeg decode test", "[camera]")
{
img_jpeg_decode_test(2, 0);
}
+
+TEST_CASE("Camera driver uses an i2c port initialized by other devices test", "[camera]")
+{
+ TEST_ESP_OK(i2c_master_init(I2C_MASTER_NUM));
+ TEST_ESP_OK(init_camera(20000000, PIXFORMAT_JPEG, FRAMESIZE_QVGA, 2, -1, I2C_MASTER_NUM));
+ vTaskDelay(500 / portTICK_RATE_MS);
+ TEST_ESP_OK(esp_camera_deinit());
+ TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM));
+}
diff --git a/code/components/esp32-camera-master_20220924.zip b/code/components/esp32-camera-master_20220924.zip
new file mode 100644
index 00000000..0ed83dd1
Binary files /dev/null and b/code/components/esp32-camera-master_20220924.zip differ
diff --git a/code/components/tflite-lib/CMakeLists.txt b/code/components/tflite-lib/CMakeLists.txt
index aaf56231..e09fd092 100644
--- a/code/components/tflite-lib/CMakeLists.txt
+++ b/code/components/tflite-lib/CMakeLists.txt
@@ -51,18 +51,28 @@ set(lib_srcs
"${tflite_dir}/kernels/internal/quantization_util.cc"
"${tflite_dir}/schema/schema_utils.cc")
+set(priv_req esp-nn)
+
+# include component requirements which were introduced after IDF version 4.1
+if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.1")
+ list(APPEND priv_req esp_timer driver)
+endif()
+
idf_component_register(
SRCS "${lib_srcs}"
INCLUDE_DIRS "." "third_party/gemmlowp"
"third_party/flatbuffers/include"
"third_party/ruy"
"third_party/kissfft"
- REQUIRES "esp-nn")
+ REQUIRES ${pub_req}
+ PRIV_REQUIRES ${priv_req})
# Reduce the level of paranoia to be able to compile TF sources
target_compile_options(${COMPONENT_LIB} PRIVATE
-Wno-maybe-uninitialized
-Wno-missing-field-initializers
+ -Wno-error=sign-compare
+ -Wno-error=double-promotion
-DESP_NN # enables ESP-NN optimizations by Espressif
-Wno-type-limits)
diff --git a/code/components/tflite-lib/tensorflow/lite/builtin_ops.h b/code/components/tflite-lib/tensorflow/lite/builtin_ops.h
index 01156c39..33707308 100644
--- a/code/components/tflite-lib/tensorflow/lite/builtin_ops.h
+++ b/code/components/tflite-lib/tensorflow/lite/builtin_ops.h
@@ -185,6 +185,7 @@ typedef enum {
kTfLiteBuiltinUnsortedSegmentSum = 155,
kTfLiteBuiltinAtan2 = 156,
kTfLiteBuiltinUnsortedSegmentMin = 157,
+ kTfLiteBuiltinSign = 158,
} TfLiteBuiltinOperator;
#ifdef __cplusplus
diff --git a/code/components/tflite-lib/tensorflow/lite/c/common.cc b/code/components/tflite-lib/tensorflow/lite/c/common.cc
index ae5c44b5..f10d3bfe 100644
--- a/code/components/tflite-lib/tensorflow/lite/c/common.cc
+++ b/code/components/tflite-lib/tensorflow/lite/c/common.cc
@@ -283,4 +283,25 @@ const char* TfLiteTypeGetName(TfLiteType type) {
TfLiteDelegate TfLiteDelegateCreate() { return TfLiteDelegate{}; }
+struct TfLiteOpaqueDelegateStruct* TfLiteOpaqueDelegateCreate(
+ const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder) {
+ if (!opaque_delegate_builder) return nullptr;
+
+ TfLiteDelegate* result = new TfLiteDelegate{};
+ result->opaque_delegate_builder = new TfLiteOpaqueDelegateBuilder{};
+ *(result->opaque_delegate_builder) = *opaque_delegate_builder;
+
+ return reinterpret_cast(result);
+}
+
+void TfLiteOpaqueDelegateDelete(
+ const struct TfLiteOpaqueDelegateStruct* opaque_delegate) {
+ if (!opaque_delegate) return;
+
+ const TfLiteDelegate* tflite_delegate =
+ reinterpret_cast(opaque_delegate);
+ delete tflite_delegate->opaque_delegate_builder;
+ delete tflite_delegate;
+}
+
} // extern "C"
diff --git a/code/components/tflite-lib/tensorflow/lite/c/common.h b/code/components/tflite-lib/tensorflow/lite/c/common.h
index cc856f9a..f60b65ed 100644
--- a/code/components/tflite-lib/tensorflow/lite/c/common.h
+++ b/code/components/tflite-lib/tensorflow/lite/c/common.h
@@ -63,6 +63,8 @@ typedef enum TfLiteExternalContextType {
struct TfLiteContext;
struct TfLiteDelegate;
struct TfLiteRegistration;
+struct TfLiteOpaqueDelegateStruct;
+struct TfLiteOpaqueDelegateBuilder;
// An external context is a collection of information unrelated to the TF Lite
// framework, but useful to a subset of the ops. TF Lite knows very little
@@ -973,7 +975,7 @@ typedef enum TfLiteDelegateFlags {
typedef struct TfLiteDelegate {
// Data that delegate needs to identify itself. This data is owned by the
// delegate. The delegate is owned in the user code, so the delegate is
- // responsible for doing this when it is destroyed.
+ // responsible for deallocating this when it is destroyed.
void* data_;
// Invoked by ModifyGraphWithDelegate. This prepare is called, giving the
@@ -1010,12 +1012,83 @@ typedef struct TfLiteDelegate {
// Bitmask flags. See the comments in `TfLiteDelegateFlags`.
int64_t flags;
+
+ // The opaque delegate builder associated with this object. If set then the
+ // TF Lite runtime will give precedence to this field. E.g. instead of
+ // invoking 'Prepare' via the function pointer inside the 'TfLiteDelegate'
+ // object, the runtime will first check if the corresponding function
+ // pointer inside 'opaque_delegate_builder' is set and if so invoke that.
+ //
+ // If this field is non-null, then the 'Prepare' field (of the
+ // 'TfLiteDelegate') should be null.
+ struct TfLiteOpaqueDelegateBuilder* opaque_delegate_builder;
} TfLiteDelegate;
// Build a 'null' delegate, with all the fields properly set to their default
// values.
TfLiteDelegate TfLiteDelegateCreate(void);
+// `TfLiteOpaqueDelegateBuilder` is used for constructing
+// `TfLiteOpaqueDelegateStruct`, see `TfLiteOpaqueDelegateCreate` below. Note:
+// This struct is not ABI stable.
+//
+// For forward source compatibility `TfLiteOpaqueDelegateBuilder` objects should
+// be brace-initialized, so that all fields (including any that might be added
+// in the future) get zero-initialized. The purpose of each field is exactly
+// the same as with `TfLiteDelegate`.
+//
+// WARNING: This is an experimental interface that is subject to change.
+typedef struct TfLiteOpaqueDelegateBuilder {
+ // Data that delegate needs to identify itself. This data is owned by the
+ // delegate. The delegate is owned in the user code, so the delegate is
+ // responsible for deallocating this when it is destroyed.
+ void* data;
+ // Invoked by ModifyGraphWithDelegate. This prepare is called, giving the
+ // delegate a view of the current graph through TfLiteContext*. It typically
+ // will look at the nodes and call ReplaceNodeSubsetsWithDelegateKernels()
+ // to ask the TensorFlow lite runtime to create macro-nodes to represent
+ // delegated subgraphs of the original graph.
+ TfLiteStatus (*Prepare)(TfLiteOpaqueContext* context, // NOLINT
+ struct TfLiteOpaqueDelegateStruct* delegate,
+ void* data);
+ // Copies the data from delegate buffer handle into raw memory of the given
+ // 'tensor'. Note that the delegate is allowed to allocate the raw bytes as
+ // long as it follows the rules for kTfLiteDynamic tensors, in which case this
+ // cannot be null.
+ TfLiteStatus (*CopyFromBufferHandle)( // NOLINT
+ TfLiteOpaqueContext* context, struct TfLiteOpaqueDelegateStruct* delegate,
+ void* data, TfLiteBufferHandle buffer_handle, TfLiteOpaqueTensor* tensor);
+ // Copies the data from raw memory of the given 'tensor' to delegate buffer
+ // handle. This can be null if the delegate doesn't use its own buffer.
+ TfLiteStatus (*CopyToBufferHandle)( // NOLINT
+ TfLiteOpaqueContext* context, struct TfLiteOpaqueDelegateStruct* delegate,
+ void* data, TfLiteBufferHandle buffer_handle, TfLiteOpaqueTensor* tensor);
+ // Frees the Delegate Buffer Handle. Note: This only frees the handle, but
+ // this doesn't release the underlying resource (e.g. textures). The
+ // resources are either owned by application layer or the delegate.
+ // This can be null if the delegate doesn't use its own buffer.
+ void (*FreeBufferHandle)(TfLiteOpaqueContext* context, // NOLINT
+ struct TfLiteOpaqueDelegateStruct* delegate,
+ void* data, TfLiteBufferHandle* handle);
+ // Bitmask flags. See the comments in `TfLiteDelegateFlags`.
+ int64_t flags;
+} TfLiteOpaqueDelegateBuilder;
+
+// Creates an opaque delegate and returns its address. The opaque delegate will
+// behave according to the provided 'opaque_delegate_builder'. The lifetime of
+// the fields within the 'opaque_delegate_builder' must outlive any interaction
+// between the runtime and the returned 'TfLiteOpaqueDelegateStruct'. The
+// returned address should be passed to 'TfLiteOpaqueDelegateDelete' for
+// deletion. If 'opaque_delegate_builder' is a null pointer, then a null
+// pointer will be returned.
+struct TfLiteOpaqueDelegateStruct* TfLiteOpaqueDelegateCreate(
+ const TfLiteOpaqueDelegateBuilder* opaque_delegate_builder);
+
+// Deletes the provided opaque 'delegate'. This function has no effect if the
+// 'delegate' is a null pointer.
+void TfLiteOpaqueDelegateDelete(
+ const struct TfLiteOpaqueDelegateStruct* delegate);
+
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
diff --git a/code/components/tflite-lib/tensorflow/lite/context_util.h b/code/components/tflite-lib/tensorflow/lite/context_util.h
index 7c8a5abd..ed42cc73 100644
--- a/code/components/tflite-lib/tensorflow/lite/context_util.h
+++ b/code/components/tflite-lib/tensorflow/lite/context_util.h
@@ -12,8 +12,9 @@ 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.
==============================================================================*/
-// This provides a few C++ helpers that are useful for manipulating C structures
-// in C++.
+/// \file
+/// This provides a few C++ helpers that are useful for manipulating C
+/// structures in C++.
#ifndef TENSORFLOW_LITE_CONTEXT_UTIL_H_
#define TENSORFLOW_LITE_CONTEXT_UTIL_H_
@@ -23,13 +24,14 @@ limitations under the License.
namespace tflite {
-// Provide a range iterable wrapper for TfLiteIntArray* (C lists that TfLite
-// C api uses. Can't use the google array_view, since we can't depend on even
+/// Provides a range iterable wrapper for TfLiteIntArray* (C lists) that TfLite
+/// C api uses.
+// Can't use the google array_view, since we can't depend on even
// absl for embedded device reasons.
class TfLiteIntArrayView {
public:
- // Construct a view of a TfLiteIntArray*. Note, `int_array` should be non-null
- // and this view does not take ownership of it.
+ /// Construct a view of a TfLiteIntArray*. Note, `int_array` should be
+ /// non-null and this view does not take ownership of it.
explicit TfLiteIntArrayView(const TfLiteIntArray* int_array)
: int_array_(int_array) {}
diff --git a/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.cc b/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.cc
index 1ecefa47..37d7661c 100644
--- a/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.cc
+++ b/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.cc
@@ -457,6 +457,10 @@ TfLiteStatus ParseOpDataTfLite(const Operator* op, BuiltinOperator op_type,
return ParseRsqrt(op, error_reporter, allocator, builtin_data);
}
+ case BuiltinOperator_SELECT_V2: {
+ return ParseSelectV2(op, error_reporter, allocator, builtin_data);
+ }
+
case BuiltinOperator_SHAPE: {
return ParseShape(op, error_reporter, allocator, builtin_data);
}
@@ -865,7 +869,6 @@ TfLiteStatus ParseOpDataTfLite(const Operator* op, BuiltinOperator op_type,
case BuiltinOperator_RELU_0_TO_1:
case BuiltinOperator_SCATTER_ND:
case BuiltinOperator_SELECT:
- case BuiltinOperator_SELECT_V2:
case BuiltinOperator_SLICE:
case BuiltinOperator_TILE:
case BuiltinOperator_TOPK_V2:
@@ -881,6 +884,7 @@ TfLiteStatus ParseOpDataTfLite(const Operator* op, BuiltinOperator op_type,
case BuiltinOperator_UNSORTED_SEGMENT_PROD:
case BuiltinOperator_UNSORTED_SEGMENT_SUM:
case BuiltinOperator_ATAN2:
+ case BuiltinOperator_SIGN:
case BuiltinOperator_WHERE:
return kTfLiteOk;
case BuiltinOperator_PLACEHOLDER_FOR_GREATER_OP_CODES:
@@ -1982,6 +1986,14 @@ TfLiteStatus ParseRsqrt(const Operator*, ErrorReporter*, BuiltinDataAllocator*,
return kTfLiteOk;
}
+// We have this parse function instead of directly returning kTfLiteOk from the
+// switch-case in ParseOpData because this function is used as part of the
+// selective registration for the OpResolver implementation in micro.
+TfLiteStatus ParseSelectV2(const Operator*, ErrorReporter*,
+ BuiltinDataAllocator*, void**) {
+ return kTfLiteOk;
+}
+
TfLiteStatus ParseShape(const Operator* op, ErrorReporter* error_reporter,
BuiltinDataAllocator* allocator, void** builtin_data) {
SafeBuiltinDataAllocator safe_allocator(allocator);
diff --git a/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.h b/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.h
index ed317b81..c7653f01 100644
--- a/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.h
+++ b/code/components/tflite-lib/tensorflow/lite/core/api/flatbuffer_conversions.h
@@ -319,6 +319,10 @@ TfLiteStatus ParseRound(const Operator* op, ErrorReporter* error_reporter,
TfLiteStatus ParseRsqrt(const Operator* op, ErrorReporter* error_reporter,
BuiltinDataAllocator* allocator, void** builtin_data);
+TfLiteStatus ParseSelectV2(const Operator* op, ErrorReporter* error_reporter,
+ BuiltinDataAllocator* allocator,
+ void** builtin_data);
+
TfLiteStatus ParseShape(const Operator* op, ErrorReporter* error_reporter,
BuiltinDataAllocator* allocator, void** builtin_data);
diff --git a/code/components/tflite-lib/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cc b/code/components/tflite-lib/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cc
index 55457f4d..f1e781b2 100644
--- a/code/components/tflite-lib/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cc
+++ b/code/components/tflite-lib/tensorflow/lite/experimental/microfrontend/lib/kiss_fft_int16.cc
@@ -1,3 +1,5 @@
+#include
+
#include "tensorflow/lite/experimental/microfrontend/lib/kiss_fft_common.h"
#define FIXED_POINT 16
diff --git a/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/hard_swish.h b/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/hard_swish.h
index d9fe32e9..81fcd63e 100644
--- a/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/hard_swish.h
+++ b/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/hard_swish.h
@@ -12,8 +12,8 @@ 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.
==============================================================================*/
-#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ACTIVATIONS_H_
-#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_ACTIVATIONS_H_
+#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_HARD_SWISH_H_
+#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_HARD_SWISH_H_
#include
@@ -165,4 +165,4 @@ inline void HardSwish(const HardSwishParams& params,
} // namespace reference_ops
} // namespace tflite
-#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_CONV_H_
+#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_HARD_SWISH_H_
diff --git a/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/mul.h b/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/mul.h
index b977104c..53197732 100644
--- a/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/mul.h
+++ b/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/mul.h
@@ -16,6 +16,7 @@ limitations under the License.
#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_MUL_H_
#include
+#include
#include "tensorflow/lite/kernels/internal/common.h"
@@ -61,6 +62,20 @@ inline void Mul(const ArithmeticParams& params,
}
}
+inline void Mul(const ArithmeticParams& params,
+ const RuntimeShape& input1_shape,
+ const std::complex* input1_data,
+ const RuntimeShape& input2_shape,
+ const std::complex* input2_data,
+ const RuntimeShape& output_shape,
+ std::complex* output_data) {
+ const int flat_size =
+ MatchingExtendedShapeFlatSize(input1_shape, input2_shape, output_shape);
+ for (int i = 0; i < flat_size; ++i) {
+ output_data[i] = input1_data[i] * input2_data[i];
+ }
+}
+
inline void Mul(const ArithmeticParams& params,
const RuntimeShape& input1_shape, const uint8_t* input1_data,
const RuntimeShape& input2_shape, const uint8_t* input2_data,
@@ -162,6 +177,37 @@ void BroadcastMul4DSlow(const ArithmeticParams& params,
}
}
+inline void BroadcastMul4DSlow(const ArithmeticParams& params,
+ const RuntimeShape& unextended_input1_shape,
+ const std::complex* input1_data,
+ const RuntimeShape& unextended_input2_shape,
+ const std::complex* input2_data,
+ const RuntimeShape& unextended_output_shape,
+ std::complex* output_data) {
+ TFLITE_DCHECK_LE(unextended_input1_shape.DimensionsCount(), 4);
+ TFLITE_DCHECK_LE(unextended_input2_shape.DimensionsCount(), 4);
+ TFLITE_DCHECK_LE(unextended_output_shape.DimensionsCount(), 4);
+ const RuntimeShape output_shape =
+ RuntimeShape::ExtendedShape(4, unextended_output_shape);
+
+ NdArrayDesc<4> desc1;
+ NdArrayDesc<4> desc2;
+ NdArrayDescsForElementwiseBroadcast(unextended_input1_shape,
+ unextended_input2_shape, &desc1, &desc2);
+
+ for (int b = 0; b < output_shape.Dims(0); ++b) {
+ for (int y = 0; y < output_shape.Dims(1); ++y) {
+ for (int x = 0; x < output_shape.Dims(2); ++x) {
+ for (int c = 0; c < output_shape.Dims(3); ++c) {
+ output_data[Offset(output_shape, b, y, x, c)] =
+ input1_data[SubscriptToIndex(desc1, b, y, x, c)] *
+ input2_data[SubscriptToIndex(desc2, b, y, x, c)];
+ }
+ }
+ }
+ }
+}
+
} // namespace reference_ops
} // namespace tflite
diff --git a/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/select.h b/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/select.h
new file mode 100644
index 00000000..82b6097c
--- /dev/null
+++ b/code/components/tflite-lib/tensorflow/lite/kernels/internal/reference/select.h
@@ -0,0 +1,151 @@
+/* Copyright 2022 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.
+==============================================================================*/
+#ifndef TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SELECT_H_
+#define TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SELECT_H_
+
+#include
+
+#include "ruy/profiler/instrumentation.h" // from @ruy
+#include "tensorflow/lite/kernels/internal/common.h"
+#include "tensorflow/lite/kernels/internal/types.h"
+
+namespace tflite {
+namespace reference_ops {
+
+template
+void Select(const RuntimeShape& input_condition_shape,
+ const D* input_condition_data, const RuntimeShape& input_x_shape,
+ const T* input_x_data, const RuntimeShape& input_y_shape,
+ const T* input_y_data, const RuntimeShape& output_shape,
+ T* output_data) {
+ ruy::profiler::ScopeLabel label("Select");
+ int64_t flatsize;
+ // Allow select operator executions on mixed scalar tensors and one element
+ // tensors.
+ if (input_condition_shape.FlatSize() == 1 && input_x_shape.FlatSize() == 1 &&
+ input_y_shape.FlatSize() == 1 && output_shape.FlatSize() == 1) {
+ flatsize = 1;
+ } else {
+ flatsize = MatchingFlatSize(input_condition_shape, input_x_shape,
+ input_y_shape, output_shape);
+ }
+ for (int64_t i = 0; i < flatsize; ++i) {
+ output_data[i] =
+ input_condition_data[i] ? input_x_data[i] : input_y_data[i];
+ }
+}
+
+template
+void RankOneSelect(const RuntimeShape& input_condition_shape,
+ const D* input_condition_data,
+ const RuntimeShape& input_x_shape, const T* input_x_data,
+ const RuntimeShape& input_y_shape, const T* input_y_data,
+ const RuntimeShape& output_shape, T* output_data) {
+ ruy::profiler::ScopeLabel label("Select/RankOneSelect");
+ const int64_t outer_size = input_condition_shape.FlatSize();
+ int64_t inner_size;
+ if (input_condition_shape.DimensionsCount() == 0) {
+ inner_size = MatchingFlatSize(input_x_shape, input_y_shape, output_shape);
+ } else {
+ TFLITE_DCHECK_EQ(
+ MatchingDim(input_x_shape, 0, input_y_shape, 0, output_shape, 0),
+ outer_size);
+ inner_size =
+ MatchingFlatSizeSkipDim(input_x_shape, 0, input_y_shape, output_shape);
+ }
+
+ int64_t offset = 0;
+ for (int64_t i = 0; i < outer_size; i++) {
+ const T* input_data = input_condition_data[i] ? input_x_data : input_y_data;
+ memcpy(output_data + offset, input_data + offset, inner_size * sizeof(T));
+ offset += inner_size;
+ }
+}
+
+template
+void BroadcastSelect5DSlow(const RuntimeShape& input_condition_shape,
+ const D* input_condition_data,
+ const RuntimeShape& input_x_shape,
+ const T* input_x_data,
+ const RuntimeShape& input_y_shape,
+ const T* input_y_data,
+ const RuntimeShape& output_shape, T* output_data) {
+ ruy::profiler::ScopeLabel label("Select/BroadcastSelectSlow");
+ TFLITE_DCHECK_LE(input_condition_shape.DimensionsCount(), 5);
+ TFLITE_DCHECK_LE(input_x_shape.DimensionsCount(), 5);
+ TFLITE_DCHECK_LE(input_y_shape.DimensionsCount(), 5);
+ TFLITE_DCHECK_LE(output_shape.DimensionsCount(), 5);
+
+ NdArrayDesc<5> desc_condition;
+ NdArrayDesc<5> desc_x;
+ NdArrayDesc<5> desc_y;
+ NdArrayDesc<5> desc_output;
+ const RuntimeShape extended_output_shape =
+ RuntimeShape::ExtendedShape(5, output_shape);
+ CopyDimsToDesc(extended_output_shape, &desc_output);
+ NdArrayDescsForElementwiseBroadcast(input_condition_shape, input_x_shape,
+ input_y_shape, &desc_condition, &desc_x,
+ &desc_y);
+
+ // In Tensorflow, the dimensions are canonically named (batch_number, row,
+ // col, channel), with extents (batches, height, width, depth), with the
+ // trailing dimension changing most rapidly (channels has the smallest
+ // stride, typically 1 element).
+ //
+ // In generated C code, we store arrays with the dimensions reversed. The
+ // first dimension has smallest stride.
+ //
+ // We name our variables by their Tensorflow convention, but generate C code
+ // nesting loops such that the innermost loop has the smallest stride for
+ // the best cache behavior.
+ for (int n = 0; n < desc_output.extents[0]; ++n) {
+ int out_idx_n = desc_output.extents[1] * n;
+ int cond_idx_n = desc_condition.strides[0] * n;
+ int in_idx1_n = desc_x.strides[0] * n;
+ int in_idx2_n = desc_y.strides[0] * n;
+ for (int b = 0; b < desc_output.extents[1]; ++b) {
+ int out_idx_b = (out_idx_n + b) * desc_output.extents[2];
+ int cond_idx_b = cond_idx_n + desc_condition.strides[1] * b;
+ int in_idx1_b = in_idx1_n + desc_x.strides[1] * b;
+ int in_idx2_b = in_idx2_n + desc_y.strides[1] * b;
+ for (int y = 0; y < desc_output.extents[2]; ++y) {
+ int out_idx_y = (out_idx_b + y) * desc_output.extents[3];
+ int cond_idx_y = cond_idx_b + desc_condition.strides[2] * y;
+ int in_idx1_y = in_idx1_b + desc_x.strides[2] * y;
+ int in_idx2_y = in_idx2_b + desc_y.strides[2] * y;
+ for (int x = 0; x < desc_output.extents[3]; ++x) {
+ int out_idx = (out_idx_y + x) * desc_output.extents[4];
+ int cond_idx = cond_idx_y + desc_condition.strides[3] * x;
+ int in_idx1 = in_idx1_y + desc_x.strides[3] * x;
+ int in_idx2 = in_idx2_y + desc_y.strides[3] * x;
+ for (int c = 0; c < desc_output.extents[4]; ++c) {
+ output_data[out_idx] = input_condition_data[cond_idx]
+ ? input_x_data[in_idx1]
+ : input_y_data[in_idx2];
+ out_idx++;
+ cond_idx += desc_condition.strides[4];
+ in_idx1 += desc_x.strides[4];
+ in_idx2 += desc_y.strides[4];
+ }
+ }
+ }
+ }
+ }
+}
+
+} // namespace reference_ops
+} // namespace tflite
+
+#endif // TENSORFLOW_LITE_KERNELS_INTERNAL_REFERENCE_SELECT_H_
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/all_ops_resolver.cc b/code/components/tflite-lib/tensorflow/lite/micro/all_ops_resolver.cc
index abbe34e7..df792264 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/all_ops_resolver.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/all_ops_resolver.cc
@@ -92,6 +92,7 @@ AllOpsResolver::AllOpsResolver() {
AddResizeNearestNeighbor();
AddRound();
AddRsqrt();
+ AddSelectV2();
AddShape();
AddSin();
AddSlice();
@@ -102,6 +103,7 @@ AllOpsResolver::AllOpsResolver() {
AddSplitV();
AddSqrt();
AddSquare();
+ AddSquaredDifference();
AddSqueeze();
AddStridedSlice();
AddSub();
@@ -110,6 +112,7 @@ AllOpsResolver::AllOpsResolver() {
AddTanh();
AddTranspose();
AddTransposeConv();
+ AddUnidirectionalSequenceLSTM();
AddUnpack();
AddVarHandle();
AddWhile();
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/add.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/add.h
index 88526153..e2e5d23b 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/add.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/add.h
@@ -1,4 +1,4 @@
-/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+/* Copyright 2022 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.
@@ -59,6 +59,19 @@ TfLiteStatus CalculateOpDataAdd(TfLiteContext* context, TfLiteAddParams* params,
TfLiteStatus AddPrepare(TfLiteContext* context, TfLiteNode* node);
+// Generic must define registration function.
+TfLiteRegistration Register_ADD();
+
+#if defined(CMSIS_NN)
+TfLiteRegistration Register_ADD_INT8();
+
+TfLiteRegistration Register_ADD_INT16();
+#else
+// Fallback registration
+inline TfLiteRegistration Register_ADD_INT8() { return Register_ADD(); }
+
+inline TfLiteRegistration Register_ADD_INT16() { return Register_ADD(); }
+#endif
} // namespace tflite
#endif // TENSORFLOW_LITE_MICRO_KERNELS_ADD_H_
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/add_n.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/add_n.cc
index ce064687..35336681 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/add_n.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/add_n.cc
@@ -121,8 +121,8 @@ TfLiteStatus CalculateOpData(TfLiteContext* context, TfLiteNode* node) {
context, kTfLiteActNone, output, &data->output_activation_min,
&data->output_activation_max));
} else {
- TF_LITE_KERNEL_LOG(context, "ADD_N only supports FLOAT32 and INT8, got %s.",
- TfLiteTypeGetName(output->type));
+ MicroPrintf("ADD_N only supports FLOAT32 and INT8, got %s.",
+ TfLiteTypeGetName(output->type));
return kTfLiteError;
}
@@ -198,8 +198,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} else if (output->type == kTfLiteInt8) {
EvalAddNQuantized(context, node, output);
} else {
- TF_LITE_KERNEL_LOG(context, "ADD_N only supports FLOAT32 and INT8, got %s.",
- TfLiteTypeGetName(output->type));
+ MicroPrintf("ADD_N only supports FLOAT32 and INT8, got %s.",
+ TfLiteTypeGetName(output->type));
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/arg_min_max.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/arg_min_max.cc
index a8aa5a48..d06b94a6 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/arg_min_max.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/arg_min_max.cc
@@ -70,21 +70,20 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node, bool is_arg_max) {
TF_LITE_ARG_MIN_MAX(int8_t, int32_t, int32_t);
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Only float32, uint8_t and int8_t are "
- "supported currently, got %s.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf(
+ "Only float32, uint8_t and int8_t are "
+ "supported currently, got %s.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
} else {
- TF_LITE_KERNEL_LOG(context,
- "Only int32_t are supported currently, got %s.",
- TfLiteTypeGetName(output->type));
+ MicroPrintf("Only int32_t are supported currently, got %s.",
+ TfLiteTypeGetName(output->type));
return kTfLiteError;
}
} else {
- TF_LITE_KERNEL_LOG(context, "Only int32_t are supported currently, got %s.",
- TfLiteTypeGetName(axis->type));
+ MicroPrintf("Only int32_t are supported currently, got %s.",
+ TfLiteTypeGetName(axis->type));
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/batch_to_space_nd.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/batch_to_space_nd.cc
index be82d942..eebf7c68 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/batch_to_space_nd.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/batch_to_space_nd.cc
@@ -95,8 +95,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorData(output));
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/circular_buffer.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/circular_buffer.cc
index 399d1648..a45a8d26 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/circular_buffer.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/circular_buffer.cc
@@ -90,7 +90,7 @@ TfLiteStatus CircularBufferEval(TfLiteContext* context, TfLiteNode* node) {
EvalInt8(tflite::micro::GetTensorData(input), num_slots, depth,
tflite::micro::GetTensorData(output));
} else {
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
+ MicroPrintf("Type %s (%d) not supported.",
TfLiteTypeGetName(input->type), input->type);
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/comparisons.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/comparisons.cc
index cff15e4d..409373fb 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/comparisons.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/comparisons.cc
@@ -118,8 +118,8 @@ TfLiteStatus EqualEval(TfLiteContext* context, TfLiteNode* node) {
output_data);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input1->type), input1->type);
+ MicroPrintf("Type %s (%d) not supported.",
+ TfLiteTypeGetName(input1->type), input1->type);
return kTfLiteError;
}
return kTfLiteOk;
@@ -210,8 +210,8 @@ TfLiteStatus NotEqualEval(TfLiteContext* context, TfLiteNode* node) {
output_data);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input1->type), input1->type);
+ MicroPrintf("Type %s (%d) not supported.",
+ TfLiteTypeGetName(input1->type), input1->type);
return kTfLiteError;
}
return kTfLiteOk;
@@ -288,8 +288,8 @@ TfLiteStatus GreaterEval(TfLiteContext* context, TfLiteNode* node) {
output_data);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input1->type), input1->type);
+ MicroPrintf("Type %s (%d) not supported.",
+ TfLiteTypeGetName(input1->type), input1->type);
return kTfLiteError;
}
return kTfLiteOk;
@@ -366,8 +366,8 @@ TfLiteStatus GreaterEqualEval(TfLiteContext* context, TfLiteNode* node) {
output_data);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input1->type), input1->type);
+ MicroPrintf("Type %s (%d) not supported.",
+ TfLiteTypeGetName(input1->type), input1->type);
return kTfLiteError;
}
return kTfLiteOk;
@@ -444,8 +444,8 @@ TfLiteStatus LessEval(TfLiteContext* context, TfLiteNode* node) {
output_data);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input1->type), input1->type);
+ MicroPrintf("Type %s (%d) not supported.",
+ TfLiteTypeGetName(input1->type), input1->type);
return kTfLiteError;
}
return kTfLiteOk;
@@ -522,8 +522,8 @@ TfLiteStatus LessEqualEval(TfLiteContext* context, TfLiteNode* node) {
output_data);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input1->type), input1->type);
+ MicroPrintf("Type %s (%d) not supported.",
+ TfLiteTypeGetName(input1->type), input1->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/concatenation.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/concatenation.cc
index 34622c22..8b4d68d9 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/concatenation.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/concatenation.cc
@@ -133,7 +133,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
TF_LITE_ENSURE(context,
input_type == kTfLiteFloat32 || input_type == kTfLiteInt8 ||
input_type == kTfLiteInt16 || input_type == kTfLiteInt32 ||
- input_type == kTfLiteInt64);
+ input_type == kTfLiteInt64 || input_type == kTfLiteBool);
// Output type must match input type
TF_LITE_ENSURE_EQ(context, output_type, input_type);
@@ -149,8 +149,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
int num_dimensions = NumDimensions(input);
if (num_dimensions > RuntimeShape::kMaxSmallSize) {
- TF_LITE_KERNEL_LOG(
- context,
+ MicroPrintf(
"Op Concatenation does not currently support num dimensions > %d "
"Tensor has %d dimensions.",
RuntimeShape::kMaxSmallSize, num_dimensions);
@@ -168,6 +167,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
TF_LITE_ENSURE(context, output != nullptr);
switch (output_type) { // Already know in/outtypes are same.
+ case kTfLiteBool:
case kTfLiteFloat32:
case kTfLiteInt16:
case kTfLiteInt32:
@@ -205,9 +205,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
break;
}
default:
- TF_LITE_KERNEL_LOG(
- context, "Op Concatenation does not currently support Type '%s'.",
- TfLiteTypeGetName(output_type));
+ MicroPrintf("Op Concatenation does not currently support Type '%s'.",
+ TfLiteTypeGetName(output_type));
return kTfLiteError;
}
@@ -238,11 +237,13 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
case kTfLiteInt16:
EvalUnquantized(context, node);
break;
+ case kTfLiteBool:
+ EvalUnquantized(context, node);
+ break;
default:
- TF_LITE_KERNEL_LOG(
- context, "Op Concatenation does not currently support Type '%s'.",
- TfLiteTypeGetName(output_type));
+ MicroPrintf("Op Concatenation does not currently support Type '%s'.",
+ TfLiteTypeGetName(output_type));
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/cumsum.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/cumsum.cc
index eedc61fd..751654fe 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/cumsum.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/cumsum.cc
@@ -123,7 +123,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
if (axis < 0) axis += input_shape.DimensionsCount();
if (axis < 0 || axis >= input_shape.DimensionsCount()) {
- TF_LITE_KERNEL_LOG(context, "CUMSUM Invalid axis: %d", axis);
+ MicroPrintf("CUMSUM Invalid axis: %d", axis);
return kTfLiteError;
}
@@ -156,9 +156,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} break;
default: {
- TF_LITE_KERNEL_LOG(context,
- "CUMSUM only supports FLOAT32 and INT8, got %s.",
- TfLiteTypeGetName(output->type));
+ MicroPrintf("CUMSUM only supports FLOAT32 and INT8, got %s.",
+ TfLiteTypeGetName(output->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/depth_to_space.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/depth_to_space.cc
index ec000540..4dda7192 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/depth_to_space.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/depth_to_space.cc
@@ -124,9 +124,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorData(output));
break;
default:
- TF_LITE_KERNEL_LOG(
- context, "DEPTH_TO_SPACE only supports FLOAT32 and INT8, got %s.",
- TfLiteTypeGetName(output->type));
+ MicroPrintf("DEPTH_TO_SPACE only supports FLOAT32 and INT8, got %s.",
+ TfLiteTypeGetName(output->type));
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/depthwise_conv.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/depthwise_conv.cc
index d2468ff9..c2ed8892 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/depthwise_conv.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/depthwise_conv.cc
@@ -82,8 +82,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
break;
}
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/div.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/div.cc
index 099c0225..34bf6d7c 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/div.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/div.cc
@@ -162,8 +162,7 @@ TfLiteStatus EvalQuantized(TfLiteContext* context, TfLiteNode* node,
}
#undef TF_LITE_DIV
} else {
- TF_LITE_KERNEL_LOG(
- context, "Unsupported combination of input and output types in DIV.");
+ MicroPrintf("Unsupported combination of input and output types in DIV.");
return kTfLiteError;
}
@@ -189,10 +188,10 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
TF_LITE_ENSURE_OK(context, EvalQuantized(context, node, params, data,
input1, input2, output));
} else {
- TF_LITE_KERNEL_LOG(context,
- "DIV only supports FLOAT32, quantized INT8 "
- "now, got type %s (%d).",
- TfLiteTypeGetName(output->type), output->type);
+ MicroPrintf(
+ "DIV only supports FLOAT32, quantized INT8 "
+ "now, got type %s (%d).",
+ TfLiteTypeGetName(output->type), output->type);
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/elementwise.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/elementwise.cc
index b1cb1dcb..bb3c6545 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/elementwise.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/elementwise.cc
@@ -90,8 +90,8 @@ TfLiteStatus GenericPrepare(TfLiteContext* context, TfLiteNode* node) {
TF_LITE_ENSURE(context, output != nullptr);
TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type);
if (!IsSupportedType(input->type)) {
- TF_LITE_KERNEL_LOG(context, "Input data type %s (%d) is not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Input data type %s (%d) is not supported.",
+ TfLiteTypeGetName(input->type), input->type);
return kTfLiteError;
}
@@ -112,8 +112,8 @@ TfLiteStatus PrepareAbsRsqrt(TfLiteContext* context, TfLiteNode* node) {
TF_LITE_ENSURE(context, output != nullptr);
TF_LITE_ENSURE_TYPES_EQ(context, input->type, output->type);
if (!IsSupportedType(input->type)) {
- TF_LITE_KERNEL_LOG(context, "Input data type %s (%d) is not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Input data type %s (%d) is not supported.",
+ TfLiteTypeGetName(input->type), input->type);
return kTfLiteError;
}
@@ -317,8 +317,8 @@ TfLiteStatus AbsEval(TfLiteContext* context, TfLiteNode* node) {
type);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Current data type %s is not supported.",
- TfLiteTypeGetName(type));
+ MicroPrintf("Current data type %s is not supported.",
+ TfLiteTypeGetName(type));
return kTfLiteError;
break;
}
@@ -355,8 +355,8 @@ TfLiteStatus RsqrtEval(TfLiteContext* context, TfLiteNode* node) {
elementwise::validate_input_func, type);
default:
- TF_LITE_KERNEL_LOG(context, "Current data type %s is not supported.",
- TfLiteTypeGetName(type));
+ MicroPrintf("Current data type %s is not supported.",
+ TfLiteTypeGetName(type));
return kTfLiteError;
}
}
@@ -426,4 +426,4 @@ TfLiteRegistration Register_LOGICAL_NOT() {
} // namespace micro
} // namespace ops
-} // namespace tflite
\ No newline at end of file
+} // namespace tflite
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/elu.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/elu.cc
index 0b64e89d..7d1169d1 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/elu.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/elu.cc
@@ -25,7 +25,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/internal/types.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
-#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
namespace {
@@ -136,9 +135,8 @@ TfLiteStatus EluEval(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
}
default:
- TF_LITE_KERNEL_LOG(
- context, "ELU only supports float32 and int8 currently, got %s.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("ELU only supports float32 and int8 currently, got %s.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/conv.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/conv.cc
index 919dd006..b442e8ed 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/conv.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/conv.cc
@@ -26,7 +26,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/padding.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
-#include "freertos/FreeRTOS.h"
#include
#if ESP_NN
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc
index a2460248..41a2bff7 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/depthwise_conv.cc
@@ -27,7 +27,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/padding.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
-#include "freertos/FreeRTOS.h"
#include
#if ESP_NN
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/softmax.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/softmax.cc
index 9a967839..df0da908 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/softmax.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/esp_nn/softmax.cc
@@ -25,7 +25,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
-#include "freertos/FreeRTOS.h"
#include
#if ESP_NN
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/exp.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/exp.cc
index ae26f636..64de090e 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/exp.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/exp.cc
@@ -19,6 +19,7 @@ limitations under the License.
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
+#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
namespace {
@@ -63,8 +64,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
static_cast(flat_size),
tflite::micro::GetTensorData(output));
} else {
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) currently not supported by Exp.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) currently not supported by Exp.",
+ TfLiteTypeGetName(input->type), input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/expand_dims.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/expand_dims.cc
index 4b105bf6..85e3e37c 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/expand_dims.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/expand_dims.cc
@@ -31,8 +31,7 @@ TfLiteStatus GetAxisValueFromTensor(TfLiteContext* context,
int32_t* axis_value) {
const int axis_dims = (tflite::GetTensorShape(axis)).DimensionsCount();
if (axis_dims > 1) {
- TF_LITE_KERNEL_LOG(context, "Axis has only one element for Expand_Dims.",
- axis_dims);
+ MicroPrintf("Axis has only one element for Expand_Dims.", axis_dims);
return kTfLiteError;
}
@@ -41,9 +40,8 @@ TfLiteStatus GetAxisValueFromTensor(TfLiteContext* context,
*axis_value = axis_ptr[0];
return kTfLiteOk;
} else {
- TF_LITE_KERNEL_LOG(context,
- "Axis type %s (%d) not supported by Expand_Dims.",
- TfLiteTypeGetName(axis->type), axis->type);
+ MicroPrintf("Axis type %s (%d) not supported by Expand_Dims.",
+ TfLiteTypeGetName(axis->type), axis->type);
return kTfLiteError;
}
}
@@ -99,8 +97,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
TF_LITE_ENSURE(context, output != nullptr);
output->type = input->type;
if (IsDynamicTensor(axis)) {
- TF_LITE_KERNEL_LOG(context,
- "DynamicTensor is not yet supported by Expand_Dims.");
+ MicroPrintf("DynamicTensor is not yet supported by Expand_Dims.");
return kTfLiteError;
}
TF_LITE_ENSURE_OK(context, VerifyTensorDim(context, input, axis, output));
@@ -135,8 +132,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorData(input), flat_size);
} break;
default:
- TF_LITE_KERNEL_LOG(
- context,
+ MicroPrintf(
"Expand_Dims only currently supports int8 and float32, got %d.",
input->type);
return kTfLiteError;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/fill.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/fill.cc
index 9f438b89..1191eba8 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/fill.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/fill.cc
@@ -53,9 +53,8 @@ TfLiteStatus EnsureEq(TfLiteContext* context, const TfLiteIntArray* array,
case kTfLiteInt64:
return EnsureEqImpl(context, array, tensor);
default:
- TF_LITE_KERNEL_LOG(context,
- "cannot compare int array to tensor of type %d.",
- tensor->type);
+ MicroPrintf("cannot compare int array to tensor of type %d.",
+ tensor->type);
return kTfLiteError;
}
}
@@ -123,9 +122,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
FillImpl(value, output);
break;
default:
- TF_LITE_KERNEL_LOG(
- context, "Fill only currently supports float32 for input 1, got %d.",
- TfLiteTypeGetName(value->type));
+ MicroPrintf("Fill only currently supports float32 for input 1, got %d.",
+ TfLiteTypeGetName(value->type));
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_div.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_div.cc
index 333a1eba..d8a96734 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_div.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_div.cc
@@ -74,7 +74,7 @@ TfLiteStatus EvalFloorDiv(TfLiteContext* context,
// Validate the denominator.
for (int i = 0; i < tflite::ElementCount(*input2->dims); ++i) {
if (std::equal_to()(denominator_data[i], 0)) {
- TF_LITE_KERNEL_LOG(context, "Division by 0");
+ MicroPrintf("Division by 0");
return kTfLiteError;
}
}
@@ -113,8 +113,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
return EvalFloorDiv(context, input1, input2, output);
}
default: {
- TF_LITE_KERNEL_LOG(context, "Type '%s' is not supported by FLOOR_DIV.",
- TfLiteTypeGetName(input1->type));
+ MicroPrintf("Type '%s' is not supported by FLOOR_DIV.",
+ TfLiteTypeGetName(input1->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_mod.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_mod.cc
index 9bb49497..ca12800c 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_mod.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/floor_mod.cc
@@ -111,8 +111,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
output);
}
default: {
- TF_LITE_KERNEL_LOG(context, "Type '%s' is not supported by FLOOR_MOD.",
- TfLiteTypeGetName(input1->type));
+ MicroPrintf("Type '%s' is not supported by FLOOR_MOD.",
+ TfLiteTypeGetName(input1->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/fully_connected.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/fully_connected.cc
index a083edd7..82d87284 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/fully_connected.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/fully_connected.cc
@@ -141,8 +141,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
}
default: {
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather.cc
index 6035efa7..ec4e2e5a 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather.cc
@@ -118,9 +118,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
case kTfLiteInt32:
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Positions of type '%s' are not supported by gather.",
- TfLiteTypeGetName(coords->type));
+ MicroPrintf("Positions of type '%s' are not supported by gather.",
+ TfLiteTypeGetName(coords->type));
return kTfLiteError;
break;
}
@@ -134,8 +133,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
case kTfLiteInt8:
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type '%s' is not supported by gather.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Type '%s' is not supported by gather.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
break;
}
@@ -207,8 +206,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
return Gather(params, input, coords, output);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type '%s' is not supported by gather.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Type '%s' is not supported by gather.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
break;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather_nd.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather_nd.cc
index 4327177d..5bb4dd84 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather_nd.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/gather_nd.cc
@@ -47,9 +47,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
case kTfLiteInt8:
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Params of type '%s' are not supported by gather_nd.",
- TfLiteTypeGetName(params->type));
+ MicroPrintf("Params of type '%s' are not supported by gather_nd.",
+ TfLiteTypeGetName(params->type));
return kTfLiteError;
break;
}
@@ -57,9 +56,8 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
case kTfLiteInt32:
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Indices of type '%s' are not supported by gather_nd.",
- TfLiteTypeGetName(indices->type));
+ MicroPrintf("Indices of type '%s' are not supported by gather_nd.",
+ TfLiteTypeGetName(indices->type));
return kTfLiteError;
}
@@ -67,22 +65,20 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
const int indices_rank = NumDimensions(indices);
const int indices_nd = SizeOfDimension(indices, indices_rank - 1);
if (params_rank < 1) {
- TF_LITE_KERNEL_LOG(context, "Params must be at least a vector.");
+ MicroPrintf("Params must be at least a vector.");
return kTfLiteError;
}
if (indices_rank < 1) {
- TF_LITE_KERNEL_LOG(context, "Indices must be at least a vector.");
+ MicroPrintf("Indices must be at least a vector.");
return kTfLiteError;
}
if (indices_nd > params_rank) {
- TF_LITE_KERNEL_LOG(
- context, "Index innermost dimension length must be <= params rank.");
+ MicroPrintf("Index innermost dimension length must be <= params rank.");
return kTfLiteError;
}
if (indices_nd > MAX_INDICES_ND) {
- TF_LITE_KERNEL_LOG(context,
- "Index innermost dimension length must not exceed %d.",
- MAX_INDICES_ND);
+ MicroPrintf("Index innermost dimension length must not exceed %d.",
+ MAX_INDICES_ND);
return kTfLiteError;
}
@@ -171,13 +167,12 @@ TfLiteStatus EvalGatherNd(TfLiteContext* context,
status = GatherNd(params, indices, output);
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Params type '%s' are not supported by gather_nd.",
- TfLiteTypeGetName(params->type));
+ MicroPrintf("Params type '%s' are not supported by gather_nd.",
+ TfLiteTypeGetName(params->type));
return kTfLiteError;
}
if (status != kTfLiteOk) {
- TF_LITE_KERNEL_LOG(context, "gather_nd index out of bounds");
+ MicroPrintf("gather_nd index out of bounds");
}
return status;
}
@@ -195,9 +190,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
return EvalGatherNd(context, params, indices, output);
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Indices of type '%s' are not supported by gather_nd.",
- TfLiteTypeGetName(indices->type));
+ MicroPrintf("Indices of type '%s' are not supported by gather_nd.",
+ TfLiteTypeGetName(indices->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.cc
index dd4c14f4..7e61ef29 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.cc
@@ -106,5 +106,17 @@ TfLiteStatus KernelRunner::Invoke() {
return kTfLiteOk;
}
+TfLiteStatus KernelRunner::Free() {
+ tflite::micro::ClearBufferApi(&context_);
+ context_.GetScratchBuffer = MicroContextGetScratchBuffer;
+
+ if (registration_.free == nullptr) {
+ MicroPrintf("TfLiteRegistration missing free function pointer!");
+ return kTfLiteError;
+ }
+
+ registration_.free(&context_, node_.user_data);
+ return kTfLiteOk;
+}
} // namespace micro
-} // namespace tflite
+} // namespace tflite
\ No newline at end of file
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.h
index 4482b70e..c7d53c3a 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_runner.h
@@ -48,6 +48,11 @@ class KernelRunner {
// passed into the constructor of this class.
TfLiteStatus Invoke();
+ // Calls Free on a given TfLiteRegistration pointer(if it's implemented).
+ // After successful Free, kTfLiteOk status will be returned. If Free is not
+ // implemented for a given kernel kTfLiteError will be returned.
+ TfLiteStatus Free();
+
// Returns a pointer to the internal MockMicroGraph which KernelRunner uses
// to stub out MicroGraph methods and track invocations on each subgraph.
MockMicroGraph* GetMockGraph() { return &mock_micro_graph_; }
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.cc
index 91c0bc91..a8e88d30 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.cc
@@ -17,6 +17,7 @@ limitations under the License.
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/micro/memory_helpers.h"
+#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
namespace micro {
@@ -39,9 +40,10 @@ int ValidateTensorIndexing(const TfLiteContext* context, int index,
TfLiteRegistration RegisterOp(
void* (*init)(TfLiteContext* context, const char* buffer, size_t length),
TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node),
- TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node)) {
+ TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node),
+ void (*free)(TfLiteContext* context, void* buffer)) {
return {/*init=*/init,
- /*free=*/nullptr,
+ /*free=*/free,
/*prepare=*/prepare,
/*invoke=*/invoke,
/*profiling_string=*/nullptr,
@@ -160,6 +162,46 @@ TfLiteStatus CopyOpInputsToOpOutputs(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
}
+// Args:
+// 1. int8_t tensor_data - int8_t buffer of unknown size who's data you'd
+// like
+// to print
+// 2. int n_btyes - a small int representing number of bytes you want to
+// print
+// to debug output. It should always be <= tensor_data's size.
+// 3. prefix - optional message you'd like to print before printing bytes
+//
+// Purpose:
+// Function takes in paramaters above and prints n_bytes bytes from the
+// tensor_data buffer. This can be use to debug the output of a model and it's
+// op.
+
+void PrintNBytes(const int8_t* tensor_data, int n_bytes, const char* prefix) {
+ if (prefix != nullptr) {
+ MicroPrintf("%s", prefix);
+ }
+
+ for (int i = 0; i < n_bytes; ++i) {
+ MicroPrintf(" %x", tensor_data[i]);
+ }
+ MicroPrintf("\n");
+}
+
+// same as the PrintNBytes above but the buffer needs to be extracted out of the
+// TfLiteEvalTensor*
+void PrintNBytes(const TfLiteEvalTensor* tensor, int n_bytes,
+ const char* prefix) {
+ const int8_t* tensor_data = tflite::micro::GetTensorData(tensor);
+ PrintNBytes(tensor_data, n_bytes, prefix);
+}
+
+// same as the PrintNBytes above but the buffer needs to be extracted out of the
+// TfLiteEvalTensor*
+void PrintNBytes(const TfLiteTensor* tensor, int n_bytes, const char* prefix) {
+ const int8_t* tensor_data = tflite::GetTensorData(tensor);
+ PrintNBytes(tensor_data, n_bytes, prefix);
+}
+
TfLiteStatus CopyOpInputsToSubgraphInputs(TfLiteContext* context,
TfLiteNode* node,
MicroGraph* graph_info,
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.h
index d6f20c72..6ac1cb36 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/kernel_util.h
@@ -21,8 +21,10 @@ limitations under the License.
#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/compatibility.h"
+#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/internal/types.h"
#include "tensorflow/lite/micro/micro_context.h"
+#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
namespace micro {
@@ -30,7 +32,20 @@ namespace micro {
TfLiteRegistration RegisterOp(
void* (*init)(TfLiteContext* context, const char* buffer, size_t length),
TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node),
- TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node));
+ TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node),
+ void (*free)(TfLiteContext* context, void* buffer) = nullptr);
+
+// Prints out n bytes in a int8_t buffer as hex
+void PrintNBytes(const int8_t* tensor_data, int n_bytes,
+ const char* prefix = nullptr);
+
+// Prints out the the n bytes in a TfLiteEvalTensor as hex
+void PrintNBytes(const TfLiteEvalTensor* tensor, int n_bytes,
+ const char* prefix = nullptr);
+
+// Prints out the the n bytes in a TfLiteTensor as hex
+void PrintNBytes(const TfLiteTensor* tensor, int n_bytes,
+ const char* prefix = nullptr);
// Returns a mutable tensor for a given input index. is_variable must be checked
// during prepare when the full TfLiteTensor is available.
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2_pool_2d.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2_pool_2d.cc
index 2b2a27bf..fbba4e0b 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2_pool_2d.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2_pool_2d.cc
@@ -125,9 +125,8 @@ TfLiteStatus L2Eval(TfLiteContext* context, TfLiteNode* node) {
L2EvalFloat(*params, *input, &op_params, output);
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "L2_POOL_2D only supports float32 currently, got %s.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("L2_POOL_2D only supports float32 currently, got %s.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2norm.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2norm.cc
index 45858e78..e8ce4ec0 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2norm.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/l2norm.cc
@@ -126,8 +126,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorData(input),
tflite::micro::GetTensorData(output));
} else {
- TF_LITE_KERNEL_LOG(context, "Output type is %s, requires float.",
- TfLiteTypeGetName(output->type));
+ MicroPrintf("Output type is %s, requires float.",
+ TfLiteTypeGetName(output->type));
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/log_softmax.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/log_softmax.cc
index 5fd87612..5958319a 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/log_softmax.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/log_softmax.cc
@@ -132,9 +132,8 @@ TfLiteStatus LogSoftmaxEval(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
}
default:
- TF_LITE_KERNEL_LOG(context,
- "LOG_SOFTMAX only supports float32, int8, got %s.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("LOG_SOFTMAX only supports float32, int8, got %s.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/lstm_eval.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/lstm_eval.cc
index f157a8d0..58484638 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/lstm_eval.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/lstm_eval.cc
@@ -22,6 +22,8 @@ limitations under the License.
#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/kernels/internal/compatibility.h"
+#include "tensorflow/lite/kernels/internal/reference/integer_ops/logistic.h"
+#include "tensorflow/lite/kernels/internal/reference/integer_ops/tanh.h"
#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
@@ -530,11 +532,20 @@ void CalculateLstmGateInteger8x8_16(
// Apply activation
switch (activation) {
case kTfLiteActSigmoid:
- micro_tensor_utils::ApplySigmoid(gate, n_batch, n_cell, gate);
- break;
- case kTfLiteActTanh:
- micro_tensor_utils::ApplyTanh(3, gate, n_batch, n_cell, gate);
+
+ reference_integer_ops::Logistic(
+ 0 /*data->input_multiplier*/, 0 /*data->input_left_shift */,
+ n_batch * n_cell /*NumElements(input->dims)*/,
+ gate /* tflite::micro::GetTensorData(input) */,
+ gate /*tflite::micro::GetTensorData(output) */);
+
break;
+ case kTfLiteActTanh: {
+ int32_t dims_data = n_batch * n_cell;
+ RuntimeShape tanh_inp_shape = RuntimeShape(1, &dims_data);
+ reference_integer_ops::Tanh(0, 0, tanh_inp_shape, gate, tanh_inp_shape,
+ gate);
+ } break;
default:
// Only Sigmoid or Tanh is used.
TFLITE_ASSERT_FALSE;
@@ -599,7 +610,7 @@ void UpdateLstmCellInteger(int n_batch, int n_cell, int16_t* cell_state,
// - scratch1: scratch area of size n_batch*n_cell
// - scratch2: scratch area used by MatrixBatchVectorMultiplyAccumulate
void CalculateLstmOutputInteger8x8_16(
- int n_batch, int n_cell, int n_output, const int16_t* cell_state,
+ int n_batch, int n_cell, int n_output, int16_t* cell_state,
int32_t cell_state_scale, const int16_t* output_gate,
int32_t hidden_scale_a, int32_t hidden_scale_b, int32_t hidden_zp,
const int8_t* projection_weights, int32_t proj_scale_a,
@@ -607,8 +618,23 @@ void CalculateLstmOutputInteger8x8_16(
int32_t output_state_zp, int8_t quantized_proj_clip, int8_t* output_state,
int16_t* scratch0, int8_t* scratch1, int32_t* scratch2) {
// Note: unlike float/hybrid, the activation is always Tanh.
- micro_tensor_utils::ApplyTanh(15 + cell_state_scale, cell_state, n_batch,
- n_cell, scratch0);
+
+ {
+ int32_t tanh_input_left_shift = (15 + cell_state_scale) - 3;
+ int32_t dims_data = n_batch * n_cell;
+ if (tanh_input_left_shift < 0) /* handling negative shift value */
+ {
+ int32_t i;
+ tanh_input_left_shift = -tanh_input_left_shift;
+ for (i = 0; i < dims_data; i++) {
+ cell_state[i] = cell_state[i] >> tanh_input_left_shift;
+ }
+ tanh_input_left_shift = 0;
+ }
+ RuntimeShape tanh_inp_shape = RuntimeShape(1, &dims_data);
+ reference_integer_ops::Tanh(0, tanh_input_left_shift, tanh_inp_shape,
+ cell_state, tanh_inp_shape, scratch0);
+ }
micro_tensor_utils::CwiseMul(output_gate, scratch0, hidden_scale_a,
hidden_scale_b, n_batch, n_cell, hidden_zp,
scratch1);
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/maximum_minimum.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/maximum_minimum.cc
index 7964f1e6..cb3cae24 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/maximum_minimum.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/maximum_minimum.cc
@@ -98,15 +98,13 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
TFLiteOperation(context, node, op_context);
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Type %s (%d) is not supported by Maximum/Minimum.",
- TfLiteTypeGetName(op_context.output->type),
- op_context.output->type);
+ MicroPrintf("Type %s (%d) is not supported by Maximum/Minimum.",
+ TfLiteTypeGetName(op_context.output->type),
+ op_context.output->type);
return kTfLiteError;
}
} else {
- TF_LITE_KERNEL_LOG(context,
- "Kernel type not supported by Maximum/Minimum.");
+ MicroPrintf("Kernel type not supported by Maximum/Minimum.");
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_ops.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_ops.h
index c4dec92d..68583f75 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_ops.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_ops.h
@@ -72,6 +72,7 @@ TfLiteRegistration Register_READ_VARIABLE();
TfLiteRegistration Register_RELU();
TfLiteRegistration Register_RELU6();
TfLiteRegistration Register_RESIZE_BILINEAR();
+TfLiteRegistration Register_SELECT_V2();
TfLiteRegistration Register_SHAPE();
TfLiteRegistration Register_SLICE();
TfLiteRegistration Register_SPACE_TO_BATCH_ND();
@@ -79,6 +80,7 @@ TfLiteRegistration Register_SPACE_TO_DEPTH();
TfLiteRegistration Register_SQUARED_DIFFERENCE();
TfLiteRegistration Register_SQUEEZE();
TfLiteRegistration Register_SUB();
+TfLiteRegistration Register_SUM();
TfLiteRegistration Register_SVDF();
TfLiteRegistration Register_TRANSPOSE();
TfLiteRegistration Register_TRANSPOSE_CONV();
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_tensor_utils.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_tensor_utils.cc
index 88b097c7..32c68121 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_tensor_utils.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/micro_tensor_utils.cc
@@ -663,7 +663,7 @@ void PortableCwiseMul(const int16_t* input_1, const int16_t* input_2,
const int16_t b = input_2[index];
int32_t value = static_cast(a) * static_cast(b);
value = MultiplyByQuantizedMultiplier(value, multiplier, shift);
- value -= output_zp;
+ value += output_zp;
value = std::min(std::max(static_cast(-128), value),
static_cast(127));
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/mul.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/mul.h
index e6d1a9b1..0c6379e1 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/mul.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/mul.h
@@ -1,4 +1,4 @@
-/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+/* Copyright 2022 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.
@@ -60,6 +60,15 @@ void EvalMulFloatReference(TfLiteContext* context, TfLiteNode* node,
const TfLiteEvalTensor* input2,
TfLiteEvalTensor* output);
+// Generic must define registration function.
+TfLiteRegistration Register_MUL();
+
+#if defined(CMSIS_NN)
+TfLiteRegistration Register_MUL_INT8();
+#else
+// Fallback registration
+inline TfLiteRegistration Register_MUL_INT8() { return Register_MUL(); }
+#endif
} // namespace tflite
#endif // TENSORFLOW_LITE_MICRO_KERNELS_MUL_H_
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/neg.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/neg.cc
index 59dd8cb8..03cbbb09 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/neg.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/neg.cc
@@ -41,8 +41,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorData(output));
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pack.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pack.cc
index 56f3b96e..01d62f77 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pack.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pack.cc
@@ -95,8 +95,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
data->axis);
}
default: {
- TF_LITE_KERNEL_LOG(context, "Type '%s' is not supported by pack.",
- TfLiteTypeGetName(output->type));
+ MicroPrintf("Type '%s' is not supported by pack.",
+ TfLiteTypeGetName(output->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pad.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pad.cc
index b645f983..61c304bf 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pad.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pad.cc
@@ -213,8 +213,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s not currently supported by Pad.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Type %s not currently supported by Pad.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.cc
index a2ef8b62..f32014e8 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.cc
@@ -45,8 +45,8 @@ TfLiteStatus AverageEval(TfLiteContext* context, TfLiteNode* node) {
AveragePoolingEvalQuantized(context, node, params, data, input, output);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Input type %s is not currently supported",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Input type %s is not currently supported",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
return kTfLiteOk;
@@ -73,8 +73,8 @@ TfLiteStatus MaxEval(TfLiteContext* context, TfLiteNode* node) {
MaxPoolingEvalQuantized(context, node, params, data, input, output);
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s not currently supported.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Type %s not currently supported.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.h
index a80f1f59..493250ee 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/pooling.h
@@ -1,4 +1,4 @@
-/* Copyright 2021 The TensorFlow Authors. All Rights Reserved.
+/* Copyright 2022 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.
@@ -20,6 +20,7 @@ limitations under the License.
#include "tensorflow/lite/c/builtin_op_data.h"
#include "tensorflow/lite/c/common.h"
+#include "tensorflow/lite/micro/kernels/micro_ops.h"
namespace tflite {
@@ -66,6 +67,19 @@ void MaxPoolingEvalQuantized(TfLiteContext* context, TfLiteNode* node,
const TfLiteEvalTensor* input,
TfLiteEvalTensor* output);
+#if defined(CMSIS_NN)
+TfLiteRegistration Register_AVERAGE_POOL_2D_INT8();
+
+TfLiteRegistration Register_MAX_POOL_2D_INT8();
+#else
+inline TfLiteRegistration Register_AVERAGE_POOL_2D_INT8() {
+ return tflite::Register_AVERAGE_POOL_2D();
+}
+
+inline TfLiteRegistration Register_MAX_POOL_2D_INT8() {
+ return tflite::Register_MAX_POOL_2D();
+}
+#endif
} // namespace tflite
#endif // TENSORFLOW_LITE_MICRO_KERNELS_POOLING_H_
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/prelu.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/prelu.cc
index 54cc0e02..6c5a8a4f 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/prelu.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/prelu.cc
@@ -61,9 +61,8 @@ TfLiteStatus PreluEval(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
} break;
default:
- TF_LITE_KERNEL_LOG(
- context, "Only float32 and uint8_t are supported currently, got %d.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Only float32 and uint8_t are supported currently, got %d.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/reduce_common.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/reduce_common.cc
index a6f940c6..b191ba21 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/reduce_common.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/reduce_common.cc
@@ -28,7 +28,7 @@ limitations under the License.
namespace tflite {
-const int kMaxNumberOfAxis = 4;
+const int kMaxNumberOfAxis = 5;
const int kMaxNumberOfReducedAxis = 2;
TfLiteStatus PrepareSimple(TfLiteContext* context, TfLiteNode* node,
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_bilinear.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_bilinear.cc
index a90057b9..f2acd9f4 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_bilinear.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_bilinear.cc
@@ -55,8 +55,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
auto* params =
reinterpret_cast(node->builtin_data);
if (params->half_pixel_centers && params->align_corners) {
- TF_LITE_KERNEL_LOG(
- context, "If half_pixel_centers is True, align_corners must be False.");
+ MicroPrintf("If half_pixel_centers is True, align_corners must be False.");
return kTfLiteError;
}
@@ -100,8 +99,7 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorShape(output),
tflite::micro::GetTensorData(output));
} else {
- TF_LITE_KERNEL_LOG(context, "Output type is %d, requires float or int8.",
- output->type);
+ MicroPrintf("Output type is %d, requires float or int8.", output->type);
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc
index ce507445..aa3b8fa1 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/resize_nearest_neighbor.cc
@@ -21,7 +21,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
-#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
namespace ops {
@@ -55,7 +54,7 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
output->type = input->type;
if (!IsConstantTensor(size)) {
- TF_LITE_KERNEL_LOG(context, "Dynamic tensors are unsupported in tfmicro.");
+ MicroPrintf("Dynamic tensors are unsupported in tfmicro.");
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/select.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/select.cc
new file mode 100644
index 00000000..0bcbfbea
--- /dev/null
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/select.cc
@@ -0,0 +1,196 @@
+/* Copyright 2022 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/kernels/internal/reference/select.h"
+
+#include
+#include
+
+#include "tensorflow/lite/c/common.h"
+#include "tensorflow/lite/kernels/internal/tensor_ctypes.h"
+#include "tensorflow/lite/kernels/kernel_util.h"
+#include "tensorflow/lite/micro/kernels/kernel_util.h"
+
+namespace tflite {
+
+constexpr int kInputTensorCondition = 0;
+constexpr int kInputTensorX = 1;
+constexpr int kInputTensorY = 2;
+constexpr int kOutputTensor = 0;
+
+struct OpData {
+ bool requires_broadcast;
+ // True if input condition is scalar or input condition has rank one and
+ // matches the first dimension of other inputs.
+ bool has_low_rank_input_condition;
+};
+
+void* SelectInit(TfLiteContext* context, const char* buffer, size_t length) {
+ TFLITE_DCHECK(context->AllocatePersistentBuffer != nullptr);
+ auto* data = static_cast(
+ context->AllocatePersistentBuffer(context, sizeof(OpData)));
+ data->requires_broadcast = false;
+ data->has_low_rank_input_condition = false;
+ return data;
+}
+
+TfLiteStatus CheckBroadcastShape(TfLiteContext* context,
+ const TfLiteTensor* input1,
+ const TfLiteTensor* input2,
+ const TfLiteTensor* input3,
+ const TfLiteIntArray* output_shape) {
+ const int dims1 = NumDimensions(input1);
+ const int dims2 = NumDimensions(input2);
+ const int dims3 = NumDimensions(input3);
+ const int out_dims = std::max(std::max(dims1, dims2), dims3);
+ TF_LITE_ENSURE_EQ(context, out_dims, output_shape->size);
+
+ for (int i = 0; i < out_dims; ++i) {
+ const int d1 = i >= dims1 ? 1 : SizeOfDimension(input1, dims1 - i - 1);
+ const int d2 = i >= dims2 ? 1 : SizeOfDimension(input2, dims2 - i - 1);
+ const int d3 = i >= dims3 ? 1 : SizeOfDimension(input3, dims3 - i - 1);
+ const int min_value = std::min(std::min(d1, d2), d3);
+ int max_value = std::max(std::max(d1, d2), d3);
+ // If one dimention is 0, others must be 0 or 1.
+ if (min_value == 0) max_value = 0;
+ if (!(d1 == 1 || d1 == max_value) || !(d2 == 1 || d2 == max_value) ||
+ !(d3 == 1 || d3 == max_value)) {
+ MicroPrintf("Given shapes are not broadcastable.");
+ return kTfLiteError;
+ }
+ TF_LITE_ENSURE_EQ(context, output_shape->data[out_dims - i - 1], max_value);
+ }
+ return kTfLiteOk;
+}
+
+TfLiteStatus SelectPrepare(TfLiteContext* context, TfLiteNode* node) {
+ OpData* data = reinterpret_cast(node->user_data);
+
+ TF_LITE_ENSURE_EQ(context, NumInputs(node), 3);
+ TF_LITE_ENSURE_EQ(context, NumOutputs(node), 1);
+
+ MicroContext* micro_context = GetMicroContext(context);
+ TfLiteTensor* input_condition =
+ micro_context->AllocateTempInputTensor(node, kInputTensorCondition);
+
+ TfLiteTensor* input_x =
+ micro_context->AllocateTempInputTensor(node, kInputTensorX);
+
+ TfLiteTensor* input_y =
+ micro_context->AllocateTempInputTensor(node, kInputTensorY);
+
+ TfLiteTensor* output =
+ micro_context->AllocateTempOutputTensor(node, kOutputTensor);
+
+ // Input must be bool.
+ TF_LITE_ENSURE_TYPES_EQ(context, input_condition->type, kTfLiteBool);
+ TF_LITE_ENSURE_TYPES_EQ(context, input_x->type, input_y->type);
+ output->type = input_x->type;
+
+ // Respect the original output shape when there are mixed shapes to represent
+ // a scalar data.
+ if (GetTensorShape(input_condition).FlatSize() == 1 &&
+ GetTensorShape(input_x).FlatSize() == 1 &&
+ GetTensorShape(input_y).FlatSize() == 1 &&
+ GetTensorShape(output).FlatSize() == 1) {
+ return kTfLiteOk;
+ }
+
+ bool same_shape = HaveSameShapes(input_condition, input_x) &&
+ HaveSameShapes(input_x, input_y);
+ if (!same_shape) {
+ TF_LITE_ENSURE_OK(
+ context, CheckBroadcastShape(context, input_condition, input_x, input_y,
+ output->dims));
+ data->requires_broadcast = true;
+ }
+
+ micro_context->DeallocateTempTfLiteTensor(input_condition);
+ micro_context->DeallocateTempTfLiteTensor(input_x);
+ micro_context->DeallocateTempTfLiteTensor(input_y);
+ micro_context->DeallocateTempTfLiteTensor(output);
+
+ return kTfLiteOk;
+}
+
+TfLiteStatus SelectEval(TfLiteContext* context, TfLiteNode* node) {
+ OpData* data = static_cast(node->user_data);
+ MicroContext* micro_context = GetMicroContext(context);
+
+ TfLiteTensor* input_condition =
+ micro_context->AllocateTempInputTensor(node, kInputTensorCondition);
+
+ TfLiteTensor* input_x =
+ micro_context->AllocateTempInputTensor(node, kInputTensorX);
+
+ TfLiteTensor* input_y =
+ micro_context->AllocateTempInputTensor(node, kInputTensorY);
+
+ TfLiteTensor* output =
+ micro_context->AllocateTempOutputTensor(node, kOutputTensor);
+
+#define TF_LITE_SELECT(type, op) \
+ reference_ops::op(GetTensorShape(input_condition), \
+ GetTensorData(input_condition), \
+ GetTensorShape(input_x), GetTensorData(input_x), \
+ GetTensorShape(input_y), GetTensorData(input_y), \
+ GetTensorShape(output), GetTensorData(output));
+
+#define TF_LITE_SWITCH(type, op) \
+ switch (type) { \
+ case kTfLiteFloat32: \
+ TF_LITE_SELECT(float, op); \
+ break; \
+ case kTfLiteInt8: \
+ TF_LITE_SELECT(int8_t, op); \
+ break; \
+ case kTfLiteInt16: \
+ TF_LITE_SELECT(int16_t, op); \
+ break; \
+ default: \
+ MicroPrintf("Does not support type other than %s, but got %s", \
+ "int8|int16|float32", TfLiteTypeGetName(type)); \
+ return kTfLiteError; \
+ }
+
+ if (data->has_low_rank_input_condition) {
+ MicroPrintf("Not yet implemented.");
+ return kTfLiteError;
+ } else if (data->requires_broadcast) {
+ TF_LITE_SWITCH(input_x->type, BroadcastSelect5DSlow);
+ } else {
+ TF_LITE_SWITCH(input_x->type, Select);
+ }
+
+#undef TF_LITE_SELECT
+#undef TF_LITE_SWITCH
+ micro_context->DeallocateTempTfLiteTensor(input_condition);
+ micro_context->DeallocateTempTfLiteTensor(input_x);
+ micro_context->DeallocateTempTfLiteTensor(input_y);
+ micro_context->DeallocateTempTfLiteTensor(output);
+
+ return kTfLiteOk;
+}
+
+// SelectV2 op selects values of 'x' if the corresponding value of 'condition'
+// is true or the value of 'y' if false. There are valid condition input sizes:
+//
+// 1. Either the same shape (in which case the select is elementwise), or
+// 2. Broadcastable shapes between 'condition', 'x' and 'y'.
+TfLiteRegistration Register_SELECT_V2() {
+ return tflite::micro::RegisterOp(tflite::SelectInit, tflite::SelectPrepare,
+ tflite::SelectEval);
+}
+
+} // namespace tflite
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/shape.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/shape.cc
index 02f663a8..b8bd5544 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/shape.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/shape.cc
@@ -47,8 +47,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
TfLiteEvalTensor* output =
tflite::micro::GetEvalOutput(context, node, kOutputTensor);
if (output->type != kTfLiteInt32) {
- TF_LITE_KERNEL_LOG(context, "Output type %s (%d) not supported.",
- TfLiteTypeGetName(output->type), output->type);
+ MicroPrintf("Output type %s (%d) not supported.",
+ TfLiteTypeGetName(output->type), output->type);
return kTfLiteError;
} else {
ExtractShape(input, tflite::micro::GetTensorData(output));
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/slice.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/slice.cc
index 212cf47f..a6ecd935 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/slice.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/slice.cc
@@ -106,8 +106,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
GetBeginAndSizeVectors(input->dims->size, begin, size,
op_params.begin, op_params.size);
} else {
- TF_LITE_KERNEL_LOG(context, "Begin tensor type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Begin tensor type %s (%d) not supported.",
+ TfLiteTypeGetName(input->type), input->type);
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/softmax.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/softmax.cc
index c2cee3c5..1ad5be0c 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/softmax.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/softmax.cc
@@ -75,8 +75,8 @@ TfLiteStatus SoftmaxEval(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
}
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_batch_nd.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_batch_nd.cc
index 21f81312..7a7f61e9 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_batch_nd.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_batch_nd.cc
@@ -104,8 +104,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorData(output));
break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_depth.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_depth.cc
index 30519b27..b8635de8 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_depth.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/space_to_depth.cc
@@ -109,9 +109,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
micro::GetTensorData(output));
break;
default:
- TF_LITE_KERNEL_LOG(
- context, "SPACE_TO_DEPTH only supports FLOAT32 and INT8, got %s.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("SPACE_TO_DEPTH only supports FLOAT32 and INT8, got %s.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/split_v.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/split_v.cc
index 3ea35130..959796c3 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/split_v.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/split_v.cc
@@ -111,8 +111,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
return SplitImpl(context, node, input, axis_value);
}
default:
- TF_LITE_KERNEL_LOG(context, "Type %s currently not supported.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Type %s currently not supported.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/squeeze.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/squeeze.cc
index e81b5b56..86841753 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/squeeze.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/squeeze.cc
@@ -90,8 +90,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
const TfLiteEvalTensor* input = tflite::micro::GetEvalInput(context, node, 0);
if (input->type == kTfLiteString) {
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/strided_slice.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/strided_slice.cc
index 832e2ccd..344698d6 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/strided_slice.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/strided_slice.cc
@@ -183,9 +183,16 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorShape(output),
tflite::micro::GetTensorData(output));
break;
+ case kTfLiteBool:
+ reference_ops::StridedSlice(op_params,
+ tflite::micro::GetTensorShape(input),
+ tflite::micro::GetTensorData(input),
+ tflite::micro::GetTensorShape(output),
+ tflite::micro::GetTensorData(output));
+ break;
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/svdf.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/svdf.h
index 7a04a5c6..0915c9fd 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/svdf.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/svdf.h
@@ -1,4 +1,4 @@
-/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+/* Copyright 2022 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.
@@ -82,7 +82,7 @@ TfLiteStatus PrepareSvdf(TfLiteContext* context, TfLiteNode* node);
// (reference or optimized) must define this function.
TfLiteRegistration Register_SVDF();
-#if defined(HEXAGON)
+#if defined(HEXAGON) || defined(CMSIS_NN)
TfLiteRegistration Register_SVDF_INT8();
#else
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/tanh.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/tanh.cc
index e97a9035..bb4133bf 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/tanh.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/tanh.cc
@@ -185,9 +185,9 @@ TfLiteStatus TanhEval(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
} break;
default:
- TF_LITE_KERNEL_LOG(context, "Input %s, output %s not supported.",
- TfLiteTypeGetName(input->type),
- TfLiteTypeGetName(output->type));
+ MicroPrintf("Input %s, output %s not supported.",
+ TfLiteTypeGetName(input->type),
+ TfLiteTypeGetName(output->type), context);
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose.cc
index 9f77e04d..740ef5f9 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose.cc
@@ -103,10 +103,10 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorData(output));
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "Type %s is currently not supported by Transpose. "
- "Only float32 and int8 is supported",
- TfLiteTypeGetName(input->type));
+ MicroPrintf(
+ "Type %s is currently not supported by Transpose. "
+ "Only float32 and int8 is supported",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose_conv.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose_conv.cc
index 0b2afd5b..1b1e8b3b 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose_conv.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/transpose_conv.cc
@@ -327,8 +327,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
break;
}
default:
- TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
- TfLiteTypeGetName(input->type), input->type);
+ MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
+ input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h b/code/components/tflite-lib/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h
index e37c0efd..24c838fa 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/unidirectional_sequence_lstm_test_config.h
@@ -24,7 +24,7 @@ namespace testing {
// kernel is reconciled with reference kernel
#if !defined(XTENSA)
-typedef struct LstmIntegerTestConfig {
+struct LstmIntegerTestConfig {
const int n_batch;
const int n_input;
const int n_cell;
@@ -100,9 +100,9 @@ typedef struct LstmIntegerTestConfig {
bool asymmetric_quantize_inputs;
const float ranges[25][2];
-} LstmIntegerTestConfig;
+};
-typedef struct LstmFloatTestConfig {
+struct LstmFloatTestConfig {
const int n_batch;
const int n_input;
const int n_cell;
@@ -153,9 +153,9 @@ typedef struct LstmFloatTestConfig {
float* output;
const float* expected_output_original;
float* expected_output;
-} LstmFloatTestConfig;
+};
-typedef struct LstmWeightQuantizationBuffers {
+struct LstmWeightQuantizationBuffers {
int8_t* lstm_i2i_quant;
float* lstm_i2i_scale;
int* lstm_i2i_zp;
@@ -215,7 +215,7 @@ typedef struct LstmWeightQuantizationBuffers {
float* lstm_proj_w_scale;
int* lstm_proj_w_zp;
TfLiteAffineQuantization* lstm_proj_w_qparam;
-} LstmWeightQuantizationBuffers;
+};
extern LstmIntegerTestConfig lstm_integer_no_peephole_config;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/unpack.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/unpack.cc
index d199add0..9a0ef177 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/unpack.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/unpack.cc
@@ -91,8 +91,8 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
return UnpackImpl(context, node, input, data->num, data->axis);
}
default: {
- TF_LITE_KERNEL_LOG(context, "Type '%s' is not supported by unpack.",
- TfLiteTypeGetName(input->type));
+ MicroPrintf("Type '%s' is not supported by unpack.",
+ TfLiteTypeGetName(input->type));
return kTfLiteError;
}
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/kernels/zeros_like.cc b/code/components/tflite-lib/tensorflow/lite/micro/kernels/zeros_like.cc
index fd6e6612..9c77e7ad 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/kernels/zeros_like.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/kernels/zeros_like.cc
@@ -70,10 +70,10 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
resetZeros(tflite::micro::GetTensorData(output), flat_size);
break;
default:
- TF_LITE_KERNEL_LOG(context,
- "ZerosLike only currently supports int64, int32, "
- "and float32, got %d.",
- input->type);
+ MicroPrintf(
+ "ZerosLike only currently supports int64, int32, "
+ "and float32, got %d.",
+ input->type);
return kTfLiteError;
}
return kTfLiteOk;
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_allocation_info.cc b/code/components/tflite-lib/tensorflow/lite/micro/micro_allocation_info.cc
index edab2b83..c1ebac3f 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_allocation_info.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_allocation_info.cc
@@ -323,8 +323,12 @@ TfLiteStatus AllocationInfoBuilder::GetOfflinePlannedOffsets(
if (model_->metadata()) {
for (size_t i = 0; i < model_->metadata()->size(); ++i) {
auto metadata = model_->metadata()->Get(i);
- if (strncmp(metadata->name()->c_str(), kOfflineMemAllocMetadata,
- strlen(kOfflineMemAllocMetadata)) == 0) {
+ const size_t metadata_name_size = (size_t)metadata->name()->size();
+
+ if ((strncmp(metadata->name()->c_str(), kOfflineMemAllocMetadata,
+ std::min(metadata_name_size,
+ strlen(kOfflineMemAllocMetadata))) == 0) &&
+ metadata_name_size == strlen(kOfflineMemAllocMetadata)) {
const flatbuffers::Vector>* buffers =
model_->buffers();
auto* buffer = (*buffers)[metadata->buffer()];
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.cc b/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.cc
index 6b78fdc0..707f2e83 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.cc
@@ -509,14 +509,15 @@ TfLiteStatus MicroAllocator::FinishModelAllocation(
return kTfLiteError;
}
- // Allocate scratch buffer metadata and buffers for variable tensors.
+ // Allocate scratch buffer metadata.
+ TF_LITE_ENSURE_STATUS(AllocateScratchBufferHandles(
+ scratch_buffer_handles, scratch_buffer_request_count_));
+
+ // Allocate buffers for variable tensors.
for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size();
subgraph_idx++) {
const SubGraph* subgraph = model->subgraphs()->Get(subgraph_idx);
TFLITE_DCHECK(subgraph != nullptr);
-
- TF_LITE_ENSURE_STATUS(AllocateScratchBufferHandles(
- scratch_buffer_handles, scratch_buffer_request_count_));
TF_LITE_ENSURE_STATUS(AllocateVariables(
subgraph, subgraph_allocations[subgraph_idx].tensors));
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.h b/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.h
index 7381489d..f9bd8b75 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_allocator.h
@@ -54,7 +54,7 @@ TfLiteStatus InitializeTfLiteTensorFromFlatbuffer(
// of a sequential, array of ScratchBufferHandle allocations in the tail
// section. These allocations are indexed by the request API defined in the
// TfLiteContext struct.
-typedef struct {
+struct ScratchBufferRequest {
// Number of bytes required by the buffer. The actual allocated size might be
// greater than `bytes` due to buffer alignment.
size_t bytes;
@@ -63,29 +63,29 @@ typedef struct {
// have `before` = node_idx and `after` = node_idx.
int node_idx;
int subgraph_idx;
-} ScratchBufferRequest;
+};
} // namespace internal
-typedef struct {
+struct NodeAndRegistration {
TfLiteNode node;
const TfLiteRegistration* registration;
-} NodeAndRegistration;
+};
// Holds a pointer to a buffer for a scratch buffer requested by a kernel during
// the model prepare stage. This struct is allocated in-place and allows for
// quick pointer-indexed lookup for speed during model inference.
-typedef struct {
+struct ScratchBufferHandle {
// Pointer to location of the scratch buffer:
uint8_t* data;
-} ScratchBufferHandle;
+};
// Stores all per-subgraph allocations. This includes the node and registration
-// array, tensor list and scratch buffer handles for each subgraph.
-typedef struct {
+// array, and tensor list for each subgraph.
+struct SubgraphAllocations {
NodeAndRegistration* node_and_registrations;
TfLiteEvalTensor* tensors;
-} SubgraphAllocations;
+};
// Allocator responsible for allocating memory for all intermediate tensors
// necessary to invoke a model.
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.cc b/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.cc
index f726a5f3..50fe7911 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.cc
@@ -317,7 +317,17 @@ TfLiteTensor* MicroInterpreter::output(size_t index) {
}
return output_tensors_[index];
}
+// Repurposing free subgraphs to reset state for some ops for now
+// will reset api is made. See b/220940833#comment25 for more context.
+TfLiteStatus MicroInterpreter::Reset() {
+ TfLiteStatus status = graph_.FreeSubgraphs();
+ if (status != kTfLiteOk) {
+ return status;
+ }
+ return graph_.ResetVariableTensors();
+}
+// TODO: remove this API completely in favor of MicroInterpreter::Reset
TfLiteStatus MicroInterpreter::ResetVariableTensors() {
return graph_.ResetVariableTensors();
}
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.h b/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.h
index aa409386..285a890f 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_interpreter.h
@@ -31,7 +31,7 @@ limitations under the License.
#include "tensorflow/lite/portable_type_to_tflitetype.h"
#include "tensorflow/lite/schema/schema_generated.h"
-// Copied from tensorflow/lite/version.h to avoid a dependency chain into
+/// Copied from tensorflow/lite/version.h to avoid a dependency chain into
// tensorflow/core.
#define TFLITE_SCHEMA_VERSION (3)
@@ -116,6 +116,11 @@ class MicroInterpreter {
return nullptr;
}
+ // Reset the state to be what you would expect when the interpreter is first
+ // created. i.e. after Init and Prepare is called for the very first time.
+ TfLiteStatus Reset();
+
+ // TODO(b/244457206): remove this in favor of Reset()
// Reset all variable tensors to the default value.
TfLiteStatus ResetVariableTensors();
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_mutable_op_resolver.h b/code/components/tflite-lib/tensorflow/lite/micro/micro_mutable_op_resolver.h
index 4b273417..738cd4fb 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_mutable_op_resolver.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_mutable_op_resolver.h
@@ -24,11 +24,13 @@ limitations under the License.
#include "tensorflow/lite/kernels/internal/compatibility.h"
#include "tensorflow/lite/kernels/op_macros.h"
#include "tensorflow/lite/micro/compatibility.h"
+#include "tensorflow/lite/micro/kernels/add.h"
#include "tensorflow/lite/micro/kernels/conv.h"
#include "tensorflow/lite/micro/kernels/depthwise_conv.h"
#include "tensorflow/lite/micro/kernels/ethosu.h"
#include "tensorflow/lite/micro/kernels/fully_connected.h"
#include "tensorflow/lite/micro/kernels/micro_ops.h"
+#include "tensorflow/lite/micro/kernels/pooling.h"
#include "tensorflow/lite/micro/kernels/reduce.h"
#include "tensorflow/lite/micro/kernels/softmax.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
@@ -140,9 +142,9 @@ class MicroMutableOpResolver : public MicroOpResolver {
tflite::Register_ASSIGN_VARIABLE(), ParseAssignVariable);
}
- TfLiteStatus AddAveragePool2D() {
- return AddBuiltin(BuiltinOperator_AVERAGE_POOL_2D,
- tflite::Register_AVERAGE_POOL_2D(), ParsePool);
+ TfLiteStatus AddAveragePool2D(
+ const TfLiteRegistration& registration = Register_AVERAGE_POOL_2D()) {
+ return AddBuiltin(BuiltinOperator_AVERAGE_POOL_2D, registration, ParsePool);
}
TfLiteStatus AddBatchToSpaceNd() {
@@ -363,9 +365,9 @@ class MicroMutableOpResolver : public MicroOpResolver {
tflite::ops::micro::Register_MAXIMUM(), ParseMaximum);
}
- TfLiteStatus AddMaxPool2D() {
- return AddBuiltin(BuiltinOperator_MAX_POOL_2D,
- tflite::Register_MAX_POOL_2D(), ParsePool);
+ TfLiteStatus AddMaxPool2D(
+ const TfLiteRegistration& registration = Register_MAX_POOL_2D()) {
+ return AddBuiltin(BuiltinOperator_MAX_POOL_2D, registration, ParsePool);
}
TfLiteStatus AddMirrorPad() {
@@ -382,8 +384,8 @@ class MicroMutableOpResolver : public MicroOpResolver {
tflite::ops::micro::Register_MINIMUM(), ParseMinimum);
}
- TfLiteStatus AddMul() {
- return AddBuiltin(BuiltinOperator_MUL, tflite::Register_MUL(), ParseMul);
+ TfLiteStatus AddMul(const TfLiteRegistration& registration = Register_MUL()) {
+ return AddBuiltin(BuiltinOperator_MUL, registration, ParseMul);
}
TfLiteStatus AddNeg() {
@@ -466,6 +468,11 @@ class MicroMutableOpResolver : public MicroOpResolver {
tflite::ops::micro::Register_RSQRT(), ParseRsqrt);
}
+ TfLiteStatus AddSelectV2() {
+ return AddBuiltin(BuiltinOperator_SELECT_V2, Register_SELECT_V2(),
+ ParseSelectV2);
+ }
+
TfLiteStatus AddShape() {
return AddBuiltin(BuiltinOperator_SHAPE, Register_SHAPE(), ParseShape);
}
@@ -519,6 +526,12 @@ class MicroMutableOpResolver : public MicroOpResolver {
tflite::ops::micro::Register_SQUARE(), ParseSquare);
}
+ TfLiteStatus AddSquaredDifference() {
+ return AddBuiltin(BuiltinOperator_SQUARED_DIFFERENCE,
+ tflite::Register_SQUARED_DIFFERENCE(),
+ ParseSquaredDifference);
+ }
+
TfLiteStatus AddStridedSlice() {
return AddBuiltin(BuiltinOperator_STRIDED_SLICE,
tflite::ops::micro::Register_STRIDED_SLICE(),
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.cc b/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.cc
index 72f3d37f..86b1ebbb 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.cc
@@ -16,6 +16,7 @@ limitations under the License.
#include
#include
+#include
#include "tensorflow/lite/kernels/internal/compatibility.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
@@ -67,4 +68,48 @@ void MicroProfiler::LogCsv() const {
#endif
}
+void MicroProfiler::LogTicksPerTagCsv() {
+#if !defined(TF_LITE_STRIP_ERROR_STRINGS)
+ MicroPrintf(
+ "\"Unique Tag\",\"Total ticks across all events with that tag.\"");
+ int total_ticks = 0;
+ for (int i = 0; i < num_events_; ++i) {
+ uint32_t ticks = end_ticks_[i] - start_ticks_[i];
+ TFLITE_DCHECK(tags_[i] != nullptr);
+ int position = FindExistingOrNextPosition(tags_[i]);
+ TFLITE_DCHECK(position >= 0);
+ total_ticks_per_tag[position].tag = tags_[i];
+ total_ticks_per_tag[position].ticks =
+ total_ticks_per_tag[position].ticks + ticks;
+ total_ticks += ticks;
+ }
+
+ for (int i = 0; i < num_events_; ++i) {
+ TicksPerTag each_tag_entry = total_ticks_per_tag[i];
+ if (each_tag_entry.tag == nullptr) {
+ break;
+ }
+ MicroPrintf("%s, %d", each_tag_entry.tag, each_tag_entry.ticks);
+ }
+ MicroPrintf("total number of ticks, %d", total_ticks);
+#endif
+}
+
+// This method finds a particular array element in the total_ticks_per_tag array
+// with the matching tag_name passed in the method. If it can find a
+// matching array element that has the same tag_name, then it will return the
+// position of the matching element. But if it unable to find a matching element
+// with the given tag_name, it will return the next available empty position
+// from the array.
+int MicroProfiler::FindExistingOrNextPosition(const char* tag_name) {
+ int pos = 0;
+ for (; pos < num_events_; pos++) {
+ TicksPerTag each_tag_entry = total_ticks_per_tag[pos];
+ if (each_tag_entry.tag == nullptr ||
+ strcmp(each_tag_entry.tag, tag_name) == 0) {
+ return pos;
+ }
+ }
+ return pos < num_events_ ? pos : -1;
+}
} // namespace tflite
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.h b/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.h
index 41f41a35..c37978a0 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.h
+++ b/code/components/tflite-lib/tensorflow/lite/micro/micro_profiler.h
@@ -61,6 +61,11 @@ class MicroProfiler {
// Separated Value) form.
void LogCsv() const;
+ // Prints total ticks for each unique tag in CSV format.
+ // Output will have one row for each unique tag along with the
+ // total ticks summed across all events with that particular tag.
+ void LogTicksPerTagCsv();
+
private:
// Maximum number of events that this class can keep track of. If we call
// AddEvent more than kMaxEvents number of times, then the oldest event's
@@ -72,6 +77,17 @@ class MicroProfiler {
uint32_t end_ticks_[kMaxEvents];
int num_events_ = 0;
+ struct TicksPerTag {
+ const char* tag;
+ uint32_t ticks;
+ };
+ // In practice, the number of tags will be much lower than the number of
+ // events. But it is theoretically possible that each event to be unique and
+ // hence we allow total_ticks_per_tag to have kMaxEvents entries.
+ TicksPerTag total_ticks_per_tag[kMaxEvents] = {};
+
+ int FindExistingOrNextPosition(const char* tag_name);
+
TF_LITE_REMOVE_VIRTUAL_DELETE;
};
diff --git a/code/components/tflite-lib/tensorflow/lite/micro/recording_micro_allocator.cc b/code/components/tflite-lib/tensorflow/lite/micro/recording_micro_allocator.cc
index 61f7816a..cdfcc272 100644
--- a/code/components/tflite-lib/tensorflow/lite/micro/recording_micro_allocator.cc
+++ b/code/components/tflite-lib/tensorflow/lite/micro/recording_micro_allocator.cc
@@ -163,10 +163,12 @@ TfLiteStatus RecordingMicroAllocator::AllocateNodeAndRegistrations(
TfLiteStatus status =
MicroAllocator::AllocateNodeAndRegistrations(model, subgraph_allocations);
+
+ RecordAllocationUsage(allocations,
+ recorded_node_and_registration_array_data_);
+
for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size();
subgraph_idx++) {
- RecordAllocationUsage(allocations,
- recorded_node_and_registration_array_data_);
// The allocation count in SingleArenaBufferAllocator will only be 1. To
// provide better logging, decrement by 1 and add in the actual number of
// operators used in the graph: The allocation for this recording will
@@ -176,8 +178,12 @@ TfLiteStatus RecordingMicroAllocator::AllocateNodeAndRegistrations(
// potential for fragmentation, manually adjust the accounting by
// decrementing by 1 and adding the actual number of nodes used in the
// graph:
- recorded_node_and_registration_array_data_.count +=
- model->subgraphs()->Get(subgraph_idx)->operators()->size() - 1;
+ if (model->subgraphs()->Get(subgraph_idx)->operators()) {
+ recorded_node_and_registration_array_data_.count +=
+ model->subgraphs()->Get(subgraph_idx)->operators()->size() - 1;
+ } else {
+ recorded_node_and_registration_array_data_.count -= 1;
+ }
}
return status;
}
@@ -188,9 +194,11 @@ TfLiteStatus RecordingMicroAllocator::AllocateTfLiteEvalTensors(
TfLiteStatus status =
MicroAllocator::AllocateTfLiteEvalTensors(model, subgraph_allocations);
+
+ RecordAllocationUsage(allocations, recorded_tflite_eval_tensor_data_);
+
for (size_t subgraph_idx = 0; subgraph_idx < model->subgraphs()->size();
subgraph_idx++) {
- RecordAllocationUsage(allocations, recorded_tflite_eval_tensor_data_);
// The allocation for this recording will always be 1. This is because the
// parent class mallocs one large allocation for the number of tensors in
// the graph (e.g. sizeof(TfLiteEvalTensor) * num_tensors). To prevent extra
diff --git a/code/components/tflite-lib/tensorflow/lite/schema/schema_generated.h b/code/components/tflite-lib/tensorflow/lite/schema/schema_generated.h
index 5d1cee85..b3a6831a 100644
--- a/code/components/tflite-lib/tensorflow/lite/schema/schema_generated.h
+++ b/code/components/tflite-lib/tensorflow/lite/schema/schema_generated.h
@@ -6,6 +6,13 @@
#include "flatbuffers/flatbuffers.h"
+// Ensure the included flatbuffers.h is the same version as when this file was
+// generated, otherwise it may not be compatible.
+static_assert(FLATBUFFERS_VERSION_MAJOR == 2 &&
+ FLATBUFFERS_VERSION_MINOR == 0 &&
+ FLATBUFFERS_VERSION_REVISION == 6,
+ "Non-compatible flatbuffers version included");
+
namespace tflite {
struct CustomQuantization;
@@ -36,6 +43,10 @@ struct SparsityParameters;
struct SparsityParametersBuilder;
struct SparsityParametersT;
+struct VariantSubType;
+struct VariantSubTypeBuilder;
+struct VariantSubTypeT;
+
struct Tensor;
struct TensorBuilder;
struct TensorT;
@@ -528,6 +539,10 @@ struct UnsortedSegmentMinOptions;
struct UnsortedSegmentMinOptionsBuilder;
struct UnsortedSegmentMinOptionsT;
+struct SignOptions;
+struct SignOptionsBuilder;
+struct SignOptionsT;
+
struct OperatorCode;
struct OperatorCodeBuilder;
struct OperatorCodeT;
@@ -560,7 +575,7 @@ struct Model;
struct ModelBuilder;
struct ModelT;
-enum TensorType {
+enum TensorType : int8_t {
TensorType_FLOAT32 = 0,
TensorType_FLOAT16 = 1,
TensorType_INT32 = 2,
@@ -635,7 +650,7 @@ inline const char *EnumNameTensorType(TensorType e) {
return EnumNamesTensorType()[index];
}
-enum QuantizationDetails {
+enum QuantizationDetails : uint8_t {
QuantizationDetails_NONE = 0,
QuantizationDetails_CustomQuantization = 1,
QuantizationDetails_MIN = QuantizationDetails_NONE,
@@ -673,6 +688,14 @@ template<> struct QuantizationDetailsTraits {
static const QuantizationDetails enum_value = QuantizationDetails_CustomQuantization;
};
+template struct QuantizationDetailsUnionTraits {
+ static const QuantizationDetails enum_value = QuantizationDetails_NONE;
+};
+
+template<> struct QuantizationDetailsUnionTraits {
+ static const QuantizationDetails enum_value = QuantizationDetails_CustomQuantization;
+};
+
struct QuantizationDetailsUnion {
QuantizationDetails type;
void *value;
@@ -690,17 +713,15 @@ struct QuantizationDetailsUnion {
void Reset();
-#ifndef FLATBUFFERS_CPP98_STL
template
void Set(T&& val) {
- using RT = typename std::remove_reference::type;
+ typedef typename std::remove_reference::type RT;
Reset();
- type = QuantizationDetailsTraits::enum_value;
+ type = QuantizationDetailsUnionTraits