Compare commits

...

23 Commits

Author SHA1 Message Date
jomjol
74c7ff7fdf v11.0.1 2022-08-15 22:48:42 +02:00
jomjol
a68ce353ad Merge pull request #910 from haverland/rolling
Fix naming of models and new version
2022-08-13 15:58:57 +02:00
Frank Haverland
0d168f3445 Merge branch 'jomjol:rolling' into rolling 2022-08-13 15:38:57 +02:00
Frank Haverland
073e04a3cc fix naming of models and new versions 2022-08-13 15:37:04 +02:00
jomjol
591dc048d4 v11.0.0 2022-08-13 14:26:04 +02:00
jomjol
bfe8d3b37a v11.0.0 2022-08-13 14:20:40 +02:00
jomjol
9695dba415 Merge branch 'master' into rolling 2022-08-07 21:20:28 +02:00
jomjol
6a48f0502e Merge pull request #885 from haverland/rolling
CNNThreshold removed vor Analog100 and Digital100
2022-08-07 21:19:37 +02:00
Frank Haverland
4a8d6592ab CNNThreshold removed for Analog100 and Digital100 2022-07-28 19:43:45 +02:00
jomjol
434aebd641 Merge pull request #881 from haverland/rolling
Ignore hidden files in configuration->model selection
2022-07-25 19:11:29 +02:00
Frank Haverland
c124c38e70 ignore hidden files in configuration->model selection 2022-07-25 16:30:11 +02:00
Frank Haverland
e6d60bb124 Merge branch 'jomjol:rolling' into rolling 2022-07-24 20:20:53 +02:00
jomjol
085ea2028c v10.6.1 2022-07-24 19:07:43 +02:00
jomjol
0e7c600cf7 Rolling v10.6.1 2022-07-24 18:53:25 +02:00
Frank Haverland
3f3532defe Revert "Fix for #712 "Incorrect rollover digital numbers""
This reverts commit 11bfaf0e91.
2022-07-20 19:12:19 +02:00
Frank Haverland
a0ffc88e47 Merge branch 'rolling' of https://github.com/haverland/AI-on-the-edge-device into rolling 2022-07-20 18:37:05 +02:00
Frank Haverland
11bfaf0e91 Fix for #712 "Incorrect rollover digital numbers" 2022-07-20 18:35:42 +02:00
jomjol
189093d548 Merge pull request #862 from haverland/rolling
Version 1.0 of digital and analog categorical models
2022-07-18 20:33:02 +02:00
Frank Haverland
34eb89b1b6 fix extension finding for tlfite modellist 2022-07-18 19:18:09 +02:00
Frank Haverland
b725d242d3 Add Error to Logfile if output-dimenstion of model inconsistent. 2022-07-18 18:36:42 +02:00
Frank Haverland
568e88314b Merge branch 'jomjol:rolling' into rolling 2022-07-17 20:00:28 +02:00
Frank Haverland
42678ae8e1 Merge branch 'jomjol:rolling' into rolling 2022-07-16 23:09:41 +02:00
Frank Haverland
b6341992f6 Version 1.0 of digital and analog categorical models 2022-07-16 21:29:56 +02:00
234 changed files with 2857 additions and 13080 deletions

BIN
.DS_Store vendored

Binary file not shown.

2
.gitignore vendored
View File

@@ -4,6 +4,7 @@
.code-workspace
/sd-card/htm./.vscode/
/code/build
/sd-card/html/debug/
CMakeLists.txt.user
CMakeCache.txt
@@ -15,3 +16,4 @@ install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps
code/edgeAI.code-workspace

View File

@@ -1,5 +1,151 @@
# Versions
##### 10.6.2 - Stability Increase (2022-07-24)
- **NEW 10.6.2**: ignore hidden files in model selection (configuration page)
- **NEW 10.6.1**: Revoke esp32cam & tflite update
- **NEW 10.6.1**: Bug Fix: tflite-filename with ".", HTML spelling error
- IndluxDB: direct injection into InfluxDB - thanks to **[wetneb](https://github.com/wetneb)**
- MQTT: implemented "Retain Flag" and extend with absolute Change (in addition to rate)
- `config.ini`: removal of modelsize (readout from tflite)
- Updated analog neural network file (`ana1000s2.tflite`) & digital neural network file (`dig1400s2q.tflite`)
- TFMicro/Lite: Update (espressif Version 20220716)
- Updated esp32cam (v20220716)
- ESP-IDF: Update to 4.4
- Internal update (CNN algorithm optimizations, reparation for new neural network type)
- Bug Fix: no time with fixed IP, Postprocessing, MQTT
##### 10.5.2 - Stability Increase (2022-02-22)
- NEW 10.5.2: Bug Fix: wrong `firmware.bin` (no rate update)
- NEW 10.5.1: Bug Fix: wrong return value, rate value & PreValue status, HTML: SSID & IP were not displayed
- MQTT: changed wifi naming to "wifiRSSI"
- HTML: check selectable values for consistency
- Refactoring of check postprocessing consistency (e.g. max rate, negative rate, ...)
- Bug Fix: corrected error in "Check Consistency Increase"
##### 10.4.0 - Stability Increase (2022-02-12)
- Graphical configuration: select available neural network files (*.tfl, *.tflite) from drop down menu
- OTA-update: add option to upload tfl / tflite files to the correct location (`/config/`)
- In the future the new files will also be copied to the `firmware` directory of the repository
- Added Wifi RSSI to MQTT information
- Updated analog neural network file (`ana-s3-q-20220105.tflite`)
- Updated digital neural network file (`dig-s1-q-20220102.tflite`)
- Updated build environment to `Espressif 3.5.0`
##### 10.3.0 - Stability Increase (2022-01-29)
- Implemented LED flash dimming (`LEDIntensity`).
Remark: as auto illumination in the camera is used, this is rather for energy saving. It will not help reducing reflections
- Additional camera parameters: saturation, contrast (although not too much impact yet)
- Some readings will have removable "N"s that can not be removed automatically and are handled with an "error" --> no return value in the field "value" anymore (still reported back via field "raw value")
- Updated esp32 camera hardware driver
- Bug fix: MQTT, HTML improvements
**ATTENTION: The new ESP32 camera hardware driver is much more stable on newer OV2640 versions (no or much less reboots) but seems to be not fully compatible with older versions.**
* If you have problem with stalled systems you can try the following
- Update the parameter `ImageQuality` to `12` instead of current value `5` (manually in the `config.ini`)
- If this is not helping, you might need to update your hardware or stay with version 9.2
##### 10.2.0 - Stability Increase (2022-01-14)
- Due to the updated camera driver, the image looks different and a new setup might be needed
- Update reference image
- Update Alignment marks
- Reduce reboot due to camera problems
- Update esp32-camera to new version (master as of 2022-01-09)
##### 10.1.1 - Stability Increase (2022-01-12)
- Bug Fix MQTT problem
- Issue:
- Changing from v9.x to 10.x the MQTT-parameter "Topic" was renamed into "MainTopic" to address multiple number meters. This renaming should have been done automatically in the background within the graphical configuration, but was not working. Instead the parameter "Topic" was deleted and "MainTopic" was set to disabled and "undefined".
- ToDo
- Update the `html.zip`
- If old `config.ini` available: copy it to `/config`, open the graphical configuration and save it again.
- If old `config.ini` not available: reset the parameter "MainTopic" within the `config.ini` manually
- Reboot
##### 10.1.0 - Stability Increase (2022-01-09)
- Reduce ESP32 frequency to 160MHz
- Update tflite (new source: https://github.com/espressif/tflite-micro-esp-examples)
- Update analog neural network (ana-s3-q-20220105.tflite)
- Update digital neural network (dig-s1-q-20220102.tflite)
- Increased web-server buffers
- bug fix: compiler compatibility
##### 10.0.2 - Stability Increase (2022-01-01)
- NEW v10.0.2: Corrected JSON error
- Updated compiler toolchain to ESP-IDF 4.3
- Removal of memory leak
- Improved error handling during startup (check PSRAM and camera with remark in logfile)
- MQTT: implemented raw value additionally, removal of regex contrain
- Normalized Parameter ``MaxRateValue`` to "change per minute"
- HTML: improved input handling
- Corrected error handling: in case of error the old value, rate, timestamp are not transmitted any more
##### 9.2.0 - External Illumination (2021-12-02)
- Direct JSON access: ``http://IP-ADRESS/json``
- Error message in log file in case camera error during startup
- Upgrade analog CNN to v9.1.0
- Upgrade digital CNN to v13.3.0 (added new images)
- html: support of different ports
##### 9.1.1 - External Illumination (2021-11-16)
- NEW 9.1.1 bug fix: LED implemenetation
- External LEDs: change control mode (resolve bug with more than 2 LEDs)
- Additional info into log file
- Bug fix: decimal shift, html, log file
##### 9.0.0 - External Illumination (2021-10-23)
* Implementation of external illumination to adjust positioning, brightness and color of the illumination now set individually
* Technical details can be found in the wiki: https://github.com/jomjol/AI-on-the-edge-device/wiki/External-LED
<img src="https://raw.githubusercontent.com/jomjol/ai-on-the-edge-device/master/images/intern_vs_external.jpg" width="500">
* New housing published for external LEDs and small clearing: https://www.thingiverse.com/thing:5028229
##### 8.5.0 - Multi Meter Support (2021-10-07)

159
README.md
View File

@@ -33,166 +33,37 @@ If you have any technical topics, you can file a issue in this repository.
In other cases you can contact the developer via email: <img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/mail.jpg" height="25">
------
## Coming next
* Automated update of the neural network file (tflite) to make the learing of additional pictures much easier and automated (GitHub action)
* New "hyprid" neural network for digital numbers --> allowing the detection of intermediate states ("ring between two numbers") as a subdigit
------
## Change log
### Known Issues
* Slow response of web server during picture analysis
**General remark:** Besides the file `firmware.bin`, typically the content of `/html` will need to be updated!
------
##### 11.0.1 - Intermediate Digits
- **NEW v11.0.1**: Bug Fix InfluxDB configuration (only update of html.zip necessary)
##### 10.6.0 - Stability Increase (2022-07-17)
- Implementation of new CNN types to detect intermediate values of digits with rolling numbers
- IndluxDB: direct injection into InfluxDB - thanks to **[wetneb](https://github.com/wetneb)**
- By default the old algo (0, 1, ..., 9, "N") is active (due to the limited types of digits trained so far)
- Activation can be done by selection a tflite file with the new trained model in the 'config.ini'
- **Details can be found in the [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Neural-Network-Types)** (different types, trained image types, naming convention)
- MQTT: implemented "Retain Flag" and extend with absolute Change (in addition to rate)
- Updated neural network files (and adaption to new naming convention)
- `config.ini`: removal of modelsize (readout from tflite)
- Published a tool to download and combine log files - **Thanks to **
- Updated analog neural network file (`ana1000s2.tflite`) & digital neural network file (`dig1400s2q.tflite`)
- Files see ['/tools/logfile-tool'](tbd), How-to see [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Gasmeter-Log-Downloader)
- TFMicro/Lite: Update (espressif Version 20220716)
- Updated esp32cam (v20220716)
- ESP-IDF: Update to 4.4
- Internal update (CNN algorithm optimizations, reparation for new neural network type)
- Bug Fix: no time with fixed IP, Postprocessing, MQTT
- Bug Fix: InfluxDB enabling in grahic configuration
##### 10.5.2 - Stability Increase (2022-02-22)
- NEW 10.5.2: Bug Fix: wrong `firmware.bin` (no rate update)
- NEW 10.5.1: Bug Fix: wrong return value, rate value & PreValue status, HTML: SSID & IP were not displayed
- MQTT: changed wifi naming to "wifiRSSI"
- HTML: check selectable values for consistency
- Refactoring of check postprocessing consistency (e.g. max rate, negative rate, ...)
- Bug Fix: corrected error in "Check Consistency Increase"
##### 10.4.0 - Stability Increase (2022-02-12)
- Graphical configuration: select available neural network files (*.tfl, *.tflite) from drop down menu
- OTA-update: add option to upload tfl / tflite files to the correct location (`/config/`)
- In the future the new files will also be copied to the `firmware` directory of the repository
- Added Wifi RSSI to MQTT information
- Updated analog neural network file (`ana-s3-q-20220105.tflite`)
- Updated digital neural network file (`dig-s1-q-20220102.tflite`)
- Updated build environment to `Espressif 3.5.0`
##### 10.3.0 - Stability Increase (2022-01-29)
- Implemented LED flash dimming (`LEDIntensity`).
Remark: as auto illumination in the camera is used, this is rather for energy saving. It will not help reducing reflections
- Additional camera parameters: saturation, contrast (although not too much impact yet)
- Some readings will have removable "N"s that can not be removed automatically and are handled with an "error" --> no return value in the field "value" anymore (still reported back via field "raw value")
- Updated esp32 camera hardware driver
- Bug fix: MQTT, HTML improvements
**ATTENTION: The new ESP32 camera hardware driver is much more stable on newer OV2640 versions (no or much less reboots) but seems to be not fully compatible with older versions.**
* If you have problem with stalled systems you can try the following
- Update the parameter `ImageQuality` to `12` instead of current value `5` (manually in the `config.ini`)
- If this is not helping, you might need to update your hardware or stay with version 9.2
##### 10.2.0 - Stability Increase (2022-01-14)
- Due to the updated camera driver, the image looks different and a new setup might be needed
- Update reference image
- Update Alignment marks
- Reduce reboot due to camera problems
- Update esp32-camera to new version (master as of 2022-01-09)
##### 10.1.1 - Stability Increase (2022-01-12)
- Bug Fix MQTT problem
- Issue:
- Changing from v9.x to 10.x the MQTT-parameter "Topic" was renamed into "MainTopic" to address multiple number meters. This renaming should have been done automatically in the background within the graphical configuration, but was not working. Instead the parameter "Topic" was deleted and "MainTopic" was set to disabled and "undefined".
- ToDo
- Update the `html.zip`
- If old `config.ini` available: copy it to `/config`, open the graphical configuration and save it again.
- If old `config.ini` not available: reset the parameter "MainTopic" within the `config.ini` manually
- Reboot
##### 10.1.0 - Stability Increase (2022-01-09)
- Reduce ESP32 frequency to 160MHz
- Update tflite (new source: https://github.com/espressif/tflite-micro-esp-examples)
- Update analog neural network (ana-s3-q-20220105.tflite)
- Update digital neural network (dig-s1-q-20220102.tflite)
- Increased web-server buffers
- bug fix: compiler compatibility
##### 10.0.2 - Stability Increase (2022-01-01)
- NEW v10.0.2: Corrected JSON error
- Updated compiler toolchain to ESP-IDF 4.3
- Removal of memory leak
- Improved error handling during startup (check PSRAM and camera with remark in logfile)
- MQTT: implemented raw value additionally, removal of regex contrain
- Normalized Parameter ``MaxRateValue`` to "change per minute"
- HTML: improved input handling
- Corrected error handling: in case of error the old value, rate, timestamp are not transmitted any more
##### 9.2.0 - External Illumination (2021-12-02)
- Direct JSON access: ``http://IP-ADRESS/json``
- Error message in log file in case camera error during startup
- Upgrade analog CNN to v9.1.0
- Upgrade digital CNN to v13.3.0 (added new images)
- html: support of different ports
##### 9.1.1 - External Illumination (2021-11-16)
- NEW 9.1.1 bug fix: LED implemenetation
- External LEDs: change control mode (resolve bug with more than 2 LEDs)
- Additional info into log file
- Bug fix: decimal shift, html, log file
##### 9.0.0 - External Illumination (2021-10-23)
* Implementation of external illumination to adjust positioning, brightness and color of the illumination now set individually
* Technical details can be found in the wiki: https://github.com/jomjol/AI-on-the-edge-device/wiki/External-LED
<img src="https://raw.githubusercontent.com/jomjol/ai-on-the-edge-device/master/images/intern_vs_external.jpg" width="500">
* New housing published for external LEDs and small clearing: https://www.thingiverse.com/thing:5028229
## Tools
* Logfile downloader and combiner (Thx to [reserve85](https://github.com/reserve85))
* Files see ['/tools/logfile-tool'](tbd), How-to see [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Gasmeter-Log-Downloader)
@@ -206,6 +77,10 @@ There are some ideas and feature requests which are not followed currently - mai
## History
##### 10.6.2 - Stability Increase (2022-07-24)
##### 9.2.0 - External Illumination (2021-12-02)
##### 8.5.0 Multi Meter Support (2021-10-07)
##### 7.1.2 MQTT-Update - (2021-06-17)

View File

@@ -5,9 +5,7 @@ set(c_srcs
"src/basic_math/esp_nn_add_ansi.c"
"src/basic_math/esp_nn_mul_ansi.c"
"src/convolution/esp_nn_conv_ansi.c"
"src/convolution/esp_nn_conv_opt.c"
"src/convolution/esp_nn_depthwise_conv_ansi.c"
"src/convolution/esp_nn_depthwise_conv_opt.c"
"src/fully_connected/esp_nn_fully_connected_ansi.c"
"src/softmax/esp_nn_softmax_ansi.c"
"src/softmax/esp_nn_softmax_opt.c"
@@ -25,7 +23,7 @@ if(CONFIG_IDF_TARGET_ESP32S3)
"src/convolution/esp_nn_conv_esp32s3.c"
"src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c"
"src/convolution/esp_nn_conv_s16_mult8_esp32s3.S"
"src/convolution/esp_nn_conv_s8_mult8_1x1_esp32s3.S"
"src/convolution/esp_nn_conv_s16_mult8_1x1_esp32s3.S"
"src/convolution/esp_nn_conv_s16_mult4_1x1_esp32s3.S"
"src/convolution/esp_nn_depthwise_conv_s8_mult1_3x3_padded_esp32s3.S"
"src/convolution/esp_nn_depthwise_conv_s16_mult1_esp32s3.S"

View File

@@ -6,8 +6,8 @@ choice NN_OPTIMIZATIONS
help
Use ANSI-C versions for verification and debug purpose.
Optimisations are automatically picked up for a chipset.
For ESP32-S3, assembly optimisations are selected.
For other platforms(viz., ESP32, ESP32-C3), generic optimisations are used.
For ESP32-S3, assembly Optimisations are selected.
For ESP32, just the ANSI C versions are selected for now.
config NN_ANSI_C
bool "ANSI C"
@@ -17,8 +17,8 @@ config NN_OPTIMIZED
bool "Optimized versions"
help
Optimisations are automatically picked up for a chipset.
For ESP32-S3, assembly optimisations are selected.
For other platforms(viz., ESP32, ESP32-C3), generic optimisations are used.
For ESP32-S3, assembly Optimisations are selected.
For ESP32, just the ANSI C versions are selected for now.
endchoice
config NN_OPTIMIZATIONS

View File

@@ -7,8 +7,7 @@ The library contains optimised NN (Neural Network) functions for various Espress
* Supported ESP chipsets include:
* ESP32-S3 (Assembly versions optimised to benefit from vector instructions of ESP32-S3)
* ESP32 (Generic optimisations)
* ESP32-C3 (Generic optimisations)
* ESP32 (ANSI C versions)
## Performance
@@ -40,8 +39,8 @@ The library contains optimised NN (Neural Network) functions for various Espress
* Optimized versions
* ANSI C
* Default selection is for `Optimized versions`. For ESP32-S3, assembly versions are automatically selected, whereas for other chipsets (viz., ESP32, ESP32-C3), generic optimisations are selected.
* For debugging purposes, you may want to select `ANSI C` reference versions.
* Default selection is for `Optimized versions`. For ESP32-S3, assembly versions are automatically selected, whereas for ESP32, ANSI-C versions are selected by default.
* For debugging purposes, you may want to select `ANSI C`
## Contributing

View File

@@ -15,7 +15,6 @@
#pragma once
#if defined(CONFIG_NN_OPTIMIZED)
// select apt optimisations
#ifdef CONFIG_IDF_TARGET_ESP32S3
#define ARCH_ESP32_S3 1
#endif
@@ -32,11 +31,12 @@ extern "C" {
#include "esp_nn_ansi_headers.h"
#if defined(CONFIG_NN_OPTIMIZED)
#if defined(ARCH_ESP32_S3)
#ifdef ARCH_ESP32_S3
#include "esp_nn_esp32s3.h"
#else // for other platforms use generic optimisations
#include "esp_nn_generic_opt.h"
#endif // #if defined(ARCH_ESP32_S3)
#endif
#ifdef ARCH_ESP32
#include "esp_nn_esp32.h"
#endif
#else
#include "esp_nn_ansi_c.h"
#endif

View File

@@ -19,7 +19,6 @@
#pragma once
#include "esp_nn_defs.h"
#include "esp_nn_ansi_headers.h"
#define esp_nn_add_elementwise_s8 esp_nn_add_elementwise_s8_ansi

View File

@@ -18,7 +18,8 @@
* @file Header definitions to include for esp_nn reference functions
*/
#include "esp_nn_defs.h"
#include <stdint.h>
/************************** Basic math functions ****************************/
/**
@@ -80,15 +81,28 @@ void esp_nn_mul_elementwise_s8_ansi(const int8_t *input1_data,
* optimization notes: Though input_offset is int32 type,
* offset values are contained in 8 bits [-128, 127]
*/
void esp_nn_depthwise_conv_s8_ansi(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
void esp_nn_depthwise_conv_s8_ansi(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const uint16_t ch_mult,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const dw_conv_params_t *conv_params,
const quant_data_t *quant_data);
const uint16_t out_wd,
const uint16_t out_ht,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max);
/**
* @brief 2d-convolution channelwise
@@ -98,26 +112,43 @@ void esp_nn_depthwise_conv_s8_ansi(const data_dims_t *input_dims,
* inputs type: int8_t, output: int8_t
* input offsets: although int32_t, they are contained in 8 bits [-128, 127]
*/
void esp_nn_conv_s8_ansi(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
void esp_nn_conv_s8_ansi(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data);
const uint16_t out_wd,
const uint16_t out_ht,
const uint16_t out_channels,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max);
int esp_nn_get_conv_scratch_size_ansi(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const conv_params_t *conv_params);
int esp_nn_get_conv_scratch_size_ansi(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_ch,
const uint16_t out_ch,
const uint16_t filter_wd,
const uint16_t filter_ht);
void esp_nn_set_conv_scratch_buf_ansi(const void *buf);
int esp_nn_get_depthwise_conv_scratch_size_ansi(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const dw_conv_params_t *conv_params);
int esp_nn_get_depthwise_conv_scratch_size_ansi(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const uint16_t ch_mult,
const uint16_t filter_wd,
const uint16_t filter_ht);
void esp_nn_set_depthwise_conv_scratch_buf_ansi(const void *buf);
/************************** Activation functions *****************************/
@@ -221,6 +252,9 @@ int32_t esp_nn_get_softmax_scratch_size_opt(const int32_t width, const int32_t h
*/
void esp_nn_set_softmax_scratch_buf_ansi(void *buffer);
/* ANSI C function to be hooked up when optimised version needed */
void esp_nn_set_softmax_scratch_buf_opt(void *buffer);
/**
* @brief reference softmax function
*
@@ -234,66 +268,6 @@ void esp_nn_softmax_s8_ansi(const int8_t *input_data,
const int32_t diff_min,
int8_t *output_data);
//////////////////////////// Generic optimisations /////////////////////////////
/************************** Convolution functions *****************************/
/**
* @brief 2d-convolution channelwise optimized version
*
* @note operation: result += (input + offset) * filter
*
* inputs type: int8_t, output: int8_t
* input offsets: although int32_t, they are contained in 8 bits [-128, 127]
*/
void esp_nn_conv_s8_opt(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
const int8_t *filter_data,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data);
/**
* @brief depthwise convolution per channel optimized version
*
* @note inputs type: int8_t, output: int8_t
* Version used in tflite is per channel.
* This version follows the same footsprints.
* Meaning, it has per out_channel shift and multiplier for
* requantization
*
* optimization notes: Though input_offset is int32 type,
* offset values are contained in 8 bits [-128, 127]
*/
void esp_nn_depthwise_conv_s8_opt(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
const int8_t *filter_data,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const dw_conv_params_t *conv_params,
const quant_data_t *quant_data);
int esp_nn_get_conv_scratch_size_opt(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const conv_params_t *conv_params);
void esp_nn_set_conv_scratch_buf_opt(const void *buf);
int esp_nn_get_depthwise_conv_scratch_size_opt(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const dw_conv_params_t *conv_params);
void esp_nn_set_depthwise_conv_scratch_buf_opt(const void *buf);
/* ANSI C function to be hooked up when optimised version needed */
void esp_nn_set_softmax_scratch_buf_opt(void *buffer);
/**
* @brief optimised version of softmax function
*

View File

@@ -1,83 +0,0 @@
// Copyright 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.
#pragma once
#include <stdint.h>
/**
* @brief structure to club data dims
* this structure can be used for input, output and filter
*/
typedef struct data_dims {
int32_t width;
int32_t height;
int32_t channels;
int32_t extra; // can be used as batch or any other param
} data_dims_t;
/**
* @brief 2d data structure (width, height)
*
*/
typedef struct data_2d {
int32_t width;
int32_t height;
} data_2d_t;
/**
* @brief min/max activation
*/
typedef struct act_params {
int32_t min;
int32_t max;
} act_params_t;
/**
* @brief per channel quant data
*
* @note number of shift and mult elements are equal to output channels
*/
typedef struct quant_data {
int32_t *shift;
int32_t *mult;
} quant_data_t;
/**
* @brief params specific to convolution 2d
*
*/
typedef struct conv_params {
int32_t in_offset;
int32_t out_offset;
data_2d_t stride;
data_2d_t padding;
data_2d_t dilation;
act_params_t activation;
} conv_params_t;
/**
* @brief params specific to depthwise convolution 2d
*
*/
typedef struct dw_conv_params {
int32_t in_offset;
int32_t out_offset;
int32_t ch_mult; // channel multiplier. (in_ch * ch_mult = out_ch)
data_2d_t stride;
data_2d_t padding;
data_2d_t dilation;
act_params_t activation;
} dw_conv_params_t;

View File

@@ -13,27 +13,28 @@
// limitations under the License.
/**
* @file Header definitions to include for esp_nn generic optimisations
* For functions which not having optimisations, _ansi versions are picked.
* @file Header definitions to include for esp_nn optimized functions for
* the ESP32 platform.
* We are hooking up just the C versions for now.
* The file hence is exactly same as `esp_nn_ansi_c.h`
*/
#pragma once
#include "esp_nn_defs.h"
#include "esp_nn_ansi_headers.h"
#define esp_nn_add_elementwise_s8 esp_nn_add_elementwise_s8_ansi
#define esp_nn_mul_elementwise_s8 esp_nn_mul_elementwise_s8_ansi
#define esp_nn_depthwise_conv_s8 esp_nn_depthwise_conv_s8_opt
#define esp_nn_depthwise_conv_s8 esp_nn_depthwise_conv_s8_ansi
#define esp_nn_conv_s8 esp_nn_conv_s8_opt
#define esp_nn_conv_s8 esp_nn_conv_s8_ansi
#define esp_nn_get_conv_scratch_size esp_nn_get_conv_scratch_size_opt
#define esp_nn_set_conv_scratch_buf esp_nn_set_conv_scratch_buf_opt
#define esp_nn_get_conv_scratch_size esp_nn_get_conv_scratch_size_ansi
#define esp_nn_set_conv_scratch_buf esp_nn_set_conv_scratch_buf_ansi
#define esp_nn_get_depthwise_conv_scratch_size esp_nn_get_depthwise_conv_scratch_size_opt
#define esp_nn_set_depthwise_conv_scratch_buf esp_nn_set_depthwise_conv_scratch_buf_opt
#define esp_nn_get_depthwise_conv_scratch_size esp_nn_get_depthwise_conv_scratch_size_ansi
#define esp_nn_set_depthwise_conv_scratch_buf esp_nn_set_depthwise_conv_scratch_buf_ansi
#define esp_nn_relu6_s8 esp_nn_relu6_s8_ansi

View File

@@ -19,7 +19,7 @@
#pragma once
#include "esp_nn_defs.h"
#include <stdint.h>
#include "esp_nn_ansi_headers.h"
/************************** Basic math functions *****************************/
@@ -85,15 +85,28 @@ void esp_nn_mul_elementwise_s8_esp32s3(const int8_t *input1_data,
* optimization notes: Though input_offset is int32 type,
* offset values are contained in 8 bits [-128, 127]
*/
void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
void esp_nn_depthwise_conv_s8_esp32s3(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const uint16_t ch_mult,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *output_data,
const dw_conv_params_t *conv_params,
const quant_data_t *quant_data);
int8_t *out_data,
const uint16_t out_wd,
const uint16_t out_ht,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max);
/**
* @brief 2d - convolution channelwise
@@ -103,26 +116,43 @@ void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims,
* inputs type: int8_t, output: int8_t
* input offsets: although int32_t, they are contained in 8 bits [-128, 127]
*/
void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
void esp_nn_conv_s8_esp32s3(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *output_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data);
int8_t *out_data,
const uint16_t out_wd,
const uint16_t out_ht,
const uint16_t out_channels,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max);
int esp_nn_get_conv_scratch_size_esp32s3(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const conv_params_t *conv_params);
int esp_nn_get_conv_scratch_size_esp32s3(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_ch,
const uint16_t out_ch,
const uint16_t filter_wd,
const uint16_t filter_ht);
void esp_nn_set_conv_scratch_buf_esp32s3(const void *buf);
int esp_nn_get_depthwise_conv_scratch_size_esp32s3(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const dw_conv_params_t *conv_params);
int esp_nn_get_depthwise_conv_scratch_size_esp32s3(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const uint16_t ch_mult,
const uint16_t filter_wd,
const uint16_t filter_ht);
void esp_nn_set_depthwise_conv_scratch_buf_esp32s3(const void *buf);
/************************** Pooling functions *****************************/

View File

@@ -41,52 +41,8 @@
__NN_FORCE_INLINE__ int32_t esp_nn_clz32(uint32_t in)
{
#if CONFIG_IDF_TARGET_ARCH_XTENSA
__asm__ volatile("nsau %0, %0" : "+r" (in));
return in;
#elif defined(__GNUC__)
return __builtin_clz(in);
#else
int32_t count = 32;
uint32_t x = in, y = in >> 16;
if (y != 0) {
count -= 16;
x = y;
}
y = x >> 8;
if (y != 0) {
count -= 8;
x = y;
}
y = x >> 4;
if (y != 0) {
count -= 4;
x = y;
}
y = x >> 2;
if (y != 0) {
count -= 2;
x = y;
}
y = x >> 1;
if (y != 0) {
return count - 2;
}
return count - x;
#endif
}
/**
* Signed saturate a 32 bit value to 8 bits keeping output in 32 bit variable.
*/
__NN_FORCE_INLINE__ int32_t esp_nn_saturate8(int32_t in)
{
#if CONFIG_IDF_TARGET_ARCH_XTENSA
__asm__ volatile("clamps %0, %0, 7" : "+a"(in));
return in;
#else
return max(INT8_MIN, min(in, INT8_MAX));
#endif
}
__NN_FORCE_INLINE__ int32_t esp_nn_pick_sat_high32_of64(int64_t val64)
@@ -96,6 +52,15 @@ __NN_FORCE_INLINE__ int32_t esp_nn_pick_sat_high32_of64(int64_t val64)
return (int32_t) ((int64_t) (val64 + to_add) >> 31);
}
/**
* Signed saturate a 32 bit value to 8 bits keeping output in 32 bit variable.
*/
__NN_FORCE_INLINE__ int32_t esp_nn_saturate8(int32_t in)
{
__asm__ volatile("clamps %0, %0, 7" : "+a"(in));
return in;
}
__NN_FORCE_INLINE__ int32_t esp_nn_sat_round_doubling_high_mul(int32_t in0, int32_t in1)
{
int32_t result;
@@ -179,7 +144,7 @@ static void esp_nn_aligned_s8_pad_with_value(const int8_t *src, int8_t *dst,
const uint16_t pad_ht)
{
/* memset with pad_val */
memset(dst, pad_val, ((input_wd + 2 * pad_wd) * (input_ht + 2 * pad_ht)) * channels);
memset(dst, pad_val, ((input_wd + 2 * pad_wd) * (input_ht + 2 * pad_ht)) * channels * 2);
dst += (pad_wd + input_wd + pad_wd) * channels;
for (int i = 0; i < input_ht; i++) {
@@ -191,6 +156,7 @@ static void esp_nn_aligned_s8_pad_with_value(const int8_t *src, int8_t *dst,
}
}
#if 0
static void esp_nn_aligned_s8_pad_end_with_value(const int8_t *src, int8_t *dst,
const uint16_t input_wd,
const uint16_t input_ht,
@@ -203,16 +169,13 @@ static void esp_nn_aligned_s8_pad_end_with_value(const int8_t *src, int8_t *dst,
for (int j = 0; j < input_wd * channels; j++) {
*dst++ = *src++;
}
if (pad_wd) {
memset(dst, pad_val, pad_wd * channels);
dst += pad_wd * channels;
}
memset(dst, pad_val, pad_wd * channels);
dst += pad_wd * channels;
}
/* pad end `pad_ht` lines at end */
if (pad_ht) {
memset(dst, pad_val, (input_wd + pad_wd) * pad_ht * channels);
}
memset(dst, pad_val, (input_wd + pad_wd) * pad_ht * channels);
}
#endif
/**
* @brief convert 8 bit input data to 16 bit

View File

@@ -12,14 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <esp_nn_defs.h>
#include <stdint.h>
#include <common_functions.h>
int esp_nn_get_conv_scratch_size_ansi(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const conv_params_t *conv_params)
int esp_nn_get_conv_scratch_size_ansi(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_ch,
const uint16_t out_ch,
const uint16_t filter_wd,
const uint16_t filter_ht)
{
return 0;
}
@@ -106,35 +108,29 @@ void esp_nn_conv_u8_ansi(const uint8_t *input_data,
* Assumption 2: Pointers are valid
* Assumption 3: dialation width = 1
*/
void esp_nn_conv_s8_ansi(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
void esp_nn_conv_s8_ansi(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data)
const uint16_t out_wd,
const uint16_t out_ht,
const uint16_t out_channels,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t in_channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const uint16_t out_channels = output_dims->channels;
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
int32_t out_ch_idx, out_y, out_x, in_ch_idx, filter_y_idx, filter_x_idx;
for (out_y = 0; out_y < out_ht; out_y++) {

View File

@@ -12,30 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include <stdio.h>
#include <esp_nn_defs.h>
#include <common_functions.h>
static int16_t *scratch_buffer = NULL;
extern void esp_nn_conv_s8_mult8_1x1_esp32s3(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_channels,
const int32_t input_offset,
const int8_t *filter_aligned,
const int32_t *bias,
int8_t *out_data,
const uint16_t out_wd,
const uint16_t out_ht,
const uint16_t out_channels,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max,
void *buffer /* scratch buffer */);
extern void esp_nn_conv_s16_mult8_1x1_esp32s3(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_channels,
const int32_t input_offset,
const int16_t *filter_data,
const int32_t *bias,
int8_t *out_data,
const uint16_t out_wd,
const uint16_t out_ht,
const uint16_t out_channels,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max,
void *buffer /* scratch buffer */);
extern void esp_nn_conv_s16_mult4_1x1_esp32s3(const int16_t *input_data,
const uint16_t input_wd,
@@ -81,40 +81,34 @@ extern void esp_nn_aligned_s8_to_s16_with_offset_esp32s3(const int8_t *src, int1
extern void esp_nn_s8_to_s16_esp32s3(const int8_t *src, int16_t *dst, const int size);
static void esp_nn_conv_s8_unrolled(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
static void esp_nn_conv_s8_unrolled(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data)
const uint16_t out_wd,
const uint16_t out_ht,
const uint16_t out_channels,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t in_ch = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const uint16_t out_ch = output_dims->channels;
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
int32_t out_ch_idx, out_y, out_x, in_ch_idx, filter_y_idx, filter_x_idx;
for (out_y = 0; out_y < out_ht; out_y++) {
for (out_x = 0; out_x < out_wd; out_x++) {
for (out_ch_idx = 0; out_ch_idx < out_ch; out_ch_idx++) {
for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) {
int32_t conv_out = 0;
const int32_t base_y = stride_ht * out_y - pad_ht;
@@ -130,10 +124,10 @@ static void esp_nn_conv_s8_unrolled(const data_dims_t *input_dims,
for (filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) {
const int32_t in_row = base_y + filter_y_idx;
const int32_t in_col = base_x + filter_x_idx;
int32_t input_base_offset = (in_row * input_wd + in_col) * in_ch;
int32_t filter_base_offset = out_ch_idx * in_ch * filter_ht * filter_wd +
(filter_y_idx * filter_wd + filter_x_idx) * in_ch;
for (in_ch_idx = 0; in_ch_idx < in_ch; in_ch_idx++) {
int32_t input_base_offset = (in_row * input_wd + in_col) * in_channels;
int32_t filter_base_offset = out_ch_idx * in_channels * filter_ht * filter_wd +
(filter_y_idx * filter_wd + filter_x_idx) * in_channels;
for (in_ch_idx = 0; in_ch_idx < in_channels; in_ch_idx++) {
conv_out +=
(input_data[input_base_offset + in_ch_idx] + input_offset) *
filter_data[filter_base_offset + in_ch_idx];
@@ -338,35 +332,18 @@ static void esp_nn_conv_s8_pad_valid_ch3_3x3(const int8_t *input_data,
}
}
int esp_nn_get_conv_scratch_size_esp32s3(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const conv_params_t *conv_params)
int esp_nn_get_conv_scratch_size_esp32s3(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t in_ch,
const uint16_t out_ch,
const uint16_t filter_wd,
const uint16_t filter_ht)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t in_ch = input_dims->channels;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_ch = output_dims->channels;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
int filter_size = filter_wd * filter_ht * in_ch * out_ch;
int input_size = input_wd * input_ht * in_ch;
int transpose_buf_size = 2 * (8 * in_ch); /* to store intermediate data */
if (input_wd * input_ht < 8) {
transpose_buf_size = 0; // not using this for leftover
}
int transpose_buf_size = 8 * in_ch; /* to store intermediate data */
int align_buf_size = 32; /* extra buffer for alignment */
if (in_ch % 8 == 0 && filter_wd == 1 && filter_ht == 1 &&
pad_wd == 0 && pad_ht == 0 && stride_wd == 1 && stride_ht == 1) {
return filter_size + transpose_buf_size + align_buf_size;
}
return 2 * (filter_size + input_size) + transpose_buf_size + align_buf_size;
return 2 * (filter_size + input_size + transpose_buf_size) + align_buf_size;
}
void esp_nn_set_conv_scratch_buf_esp32s3(void *buf)
@@ -374,35 +351,29 @@ void esp_nn_set_conv_scratch_buf_esp32s3(void *buf)
scratch_buffer = (int16_t *) buf;
}
void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims,
const int8_t *input,
const data_dims_t *filter_dims,
void esp_nn_conv_s8_esp32s3(const int8_t *input,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data)
const uint16_t out_wd,
const uint16_t out_ht,
const uint16_t out_channels,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const uint16_t out_channels = output_dims->channels;
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
int filter_size = filter_wd * filter_ht * channels * out_channels;
int input_size = input_wd * input_ht * channels;
int align_len = 16 - (filter_size & 15);
@@ -416,16 +387,15 @@ void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims,
if (channels % 8 == 0 && filter_wd == 1 && filter_ht == 1 &&
pad_wd == 0 && pad_ht == 0 && stride_wd == 1 && stride_ht == 1) {
int8_t *filter_aligned = (int8_t *) scratch_buffer;
int scratch_offset = (int) (filter_aligned + filter_size);
int scratch_offset = (int) (filter_data16 + filter_size);
void *scratch_buf = (void *) (scratch_offset + 16 - (scratch_offset & 15));
memcpy(filter_aligned, filter_data, filter_size); // copy to aligned address
esp_nn_conv_s8_mult8_1x1_esp32s3(
input, input_wd, input_ht, channels, input_offset, filter_aligned,
esp_nn_s8_to_s16_esp32s3(filter_data, filter_data16, filter_size);
esp_nn_conv_s16_mult8_1x1_esp32s3(
input, input_wd, input_ht, channels, input_offset, filter_data16,
bias, out_data, out_wd, out_ht, out_channels, out_offset,
out_shift, out_mult, activation_min, activation_max, scratch_buf);
} else if (channels % 4 == 0 && filter_wd == 1 && filter_ht == 1 &&
(input_wd * input_ht) % 4 == 0 && /* TODO: remove this check */
(input_wd * input_ht) % 16 == 0 && /* TODO: remove this check */
pad_wd == 0 && pad_ht == 0 && stride_wd == 1 && stride_ht == 1) {
int scratch_offset = (int) (input_data16 + input_size);
void *scratch_buf = (void *) (scratch_offset + 16 - (scratch_offset & 15));
@@ -457,7 +427,10 @@ void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims,
}
} else {
/* Basic unrolled version */
esp_nn_conv_s8_unrolled(input_dims, input, filter_dims, filter_data,
bias, output_dims, out_data, conv_params, quant_data);
esp_nn_conv_s8_unrolled(input, input_wd, input_ht, channels, input_offset,
pad_wd, pad_ht, stride_wd, stride_ht,
filter_data, filter_wd, filter_ht, bias,
out_data, out_wd, out_ht, out_channels, out_offset, out_shift,
out_mult, activation_min, activation_max);
}
}

View File

@@ -1,179 +0,0 @@
// Copyright 2020-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 <esp_nn_defs.h>
#include <common_functions.h>
int esp_nn_get_conv_scratch_size_opt(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const conv_params_t *conv_params)
{
return 0;
}
void esp_nn_set_conv_scratch_buf_opt(const void *buf)
{
}
__attribute__ ((noinline))
static void esp_nn_conv_s8_1x1(const data_dims_t *input_dims,
const int8_t *input_data,
const int8_t *filter_data,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data)
{
const uint16_t input_wd = input_dims->width;
const uint16_t in_channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const uint16_t out_channels = output_dims->channels;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
for (int32_t in_row = 0; in_row < out_ht * stride_ht; in_row += stride_ht) {
for (int32_t in_col = 0; in_col < out_wd * stride_wd; in_col += stride_wd) {
const int32_t *out_mult = quant_data->mult;
const int32_t *out_shift = quant_data->shift;
const int8_t *filter_ptr = filter_data;
const int8_t *input_base_ptr = input_data + (in_row * input_wd + in_col) * in_channels;
int32_t out_ch_idx = 0;
for (; out_ch_idx < out_channels; out_ch_idx++) {
int32_t conv_out = 0;
const int8_t *input_ptr = input_base_ptr;
int32_t in_ch_idx = 0;
for (; in_ch_idx < in_channels - 3; in_ch_idx += 4) {
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
}
for (; in_ch_idx < in_channels; in_ch_idx ++) {
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
}
if (bias) {
conv_out += bias[out_ch_idx];
}
conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, *out_mult++, *out_shift++);
conv_out += out_offset;
conv_out = max(conv_out, activation_min);
conv_out = min(conv_out, activation_max);
*out_data++ = (int8_t) conv_out;
}
}
}
}
/**
* Assumption 1: i/p channels == o/p channels
* Assumption 2: Pointers are valid
* Assumption 3: dialation width = 1
*/
void esp_nn_conv_s8_opt(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
const int8_t *filter_data,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const conv_params_t *conv_params,
const quant_data_t *quant_data)
{
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
if (filter_wd == 1 && filter_ht == 1) {
esp_nn_conv_s8_1x1(input_dims, input_data, filter_data, bias,
output_dims, out_data, conv_params, quant_data);
return;
}
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t in_channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const uint16_t out_channels = output_dims->channels;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
int32_t out_ch_idx, out_y, out_x, filter_y_idx, filter_x_idx;
for (out_y = 0; out_y < out_ht; out_y++) {
for (out_x = 0; out_x < out_wd; out_x++) {
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
for (out_ch_idx = 0; out_ch_idx < out_channels; out_ch_idx++) {
int32_t conv_out = 0;
const int32_t base_y = stride_ht * out_y - pad_ht;
const int32_t base_x = stride_wd * out_x - pad_wd;
const int32_t filter_y_start = max(0, -base_y);
const int32_t filter_x_start = max(0, -base_x);
const int32_t filter_y_end = min(filter_ht, input_ht - base_y);
const int32_t filter_x_end = min(filter_wd, input_wd - base_x);
for (filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) {
for (filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) {
const int32_t in_row = base_y + filter_y_idx;
const int32_t in_col = base_x + filter_x_idx;
const int8_t *input_ptr = input_data +
(in_row * input_wd + in_col) * in_channels;
const int8_t *filter_ptr = filter_data +
out_ch_idx * in_channels * filter_ht * filter_wd +
(filter_y_idx * filter_wd + filter_x_idx) * in_channels;
int32_t in_ch_idx = 0;
for (; in_ch_idx < in_channels - 3; in_ch_idx += 4) {
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
}
for (; in_ch_idx < in_channels; in_ch_idx ++) {
conv_out += (*input_ptr++ + input_offset) * *filter_ptr++;
}
}
}
if (bias) {
conv_out += bias[out_ch_idx];
}
conv_out = esp_nn_multiply_by_quantized_mult_fast(conv_out, *out_mult++, *out_shift++);
conv_out += out_offset;
conv_out = max(conv_out, activation_min);
conv_out = min(conv_out, activation_max);
*out_data++ = (int8_t) conv_out;
}
}
}
}

View File

@@ -12,13 +12,16 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <esp_nn_defs.h>
#include <stdint.h>
#include <common_functions.h>
int esp_nn_get_depthwise_conv_scratch_size_ansi(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const dw_conv_params_t *conv_params)
int esp_nn_get_depthwise_conv_scratch_size_ansi(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const uint16_t ch_mult,
const uint16_t filter_wd,
const uint16_t filter_ht)
{
return 0;
}
@@ -28,35 +31,29 @@ void esp_nn_set_depthwise_conv_scratch_buf_ansi(const void *buf)
}
void esp_nn_depthwise_conv_s8_ansi(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
void esp_nn_depthwise_conv_s8_ansi(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const uint16_t ch_mult,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const dw_conv_params_t *conv_params,
const quant_data_t *quant_data)
const uint16_t out_wd,
const uint16_t out_ht,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
const uint16_t ch_mult = conv_params->ch_mult;
int out_idx = 0;
for (int out_y = 0; out_y < out_ht; out_y++) { //height loop
const int16_t base_y = (out_y * stride_ht) - pad_ht;

View File

@@ -1,291 +0,0 @@
// Copyright 2020-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 <esp_nn_defs.h>
#include <common_functions.h>
int esp_nn_get_depthwise_conv_scratch_size_opt(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const dw_conv_params_t *conv_params)
{
return 0;
}
void esp_nn_set_depthwise_conv_scratch_buf_opt(const void *buf)
{
}
/* common channel multiplier == 1 case */
__attribute__ ((noinline))
static void esp_nn_depthwise_conv_s8_ch_mult_1(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
const int8_t *filter_data,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const dw_conv_params_t *conv_params,
const quant_data_t *quant_data)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
int out_idx = 0;
for (int out_y = 0; out_y < out_ht; out_y++) { //height loop
const int16_t base_y = (out_y * stride_ht) - pad_ht;
for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop
const int16_t base_x = (out_x * stride_wd) - pad_wd;
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
/* Select filter so as the point doesn't lie outside block */
int filter_y_start = max(0, -base_y);
int filter_x_start = max(0, -base_x);
int filter_y_end = min(filter_ht, input_ht - base_y);
int filter_x_end = min(filter_wd, input_wd - base_x);
int ch_idx = 0;
for (; ch_idx < channels - 3; ch_idx += 4) {//channel_loop
int32_t result0 = 0;
int32_t result1 = 0;
int32_t result2 = 0;
int32_t result3 = 0;
for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) {
const int32_t idx_y = base_y + filter_y_idx;
for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) {
const int32_t idx_x = base_x + filter_x_idx;
int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx;
int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels) + ch_idx;
int32_t input_val0 = input_data[input_index + 0] + input_offset;
int32_t input_val1 = input_data[input_index + 1] + input_offset;
int32_t input_val2 = input_data[input_index + 2] + input_offset;
int32_t input_val3 = input_data[input_index + 3] + input_offset;
int32_t filter_val0 = filter_data[filter_index + 0];
int32_t filter_val1 = filter_data[filter_index + 1];
int32_t filter_val2 = filter_data[filter_index + 2];
int32_t filter_val3 = filter_data[filter_index + 3];
result0 += input_val0 * filter_val0;
result1 += input_val1 * filter_val1;
result2 += input_val2 * filter_val2;
result3 += input_val3 * filter_val3;
}
}
if (bias) {
result0 += bias[ch_idx + 0];
result1 += bias[ch_idx + 1];
result2 += bias[ch_idx + 2];
result3 += bias[ch_idx + 3];
}
result0 = esp_nn_multiply_by_quantized_mult_fast(result0, *out_mult++, *out_shift++);
result1 = esp_nn_multiply_by_quantized_mult_fast(result1, *out_mult++, *out_shift++);
result2 = esp_nn_multiply_by_quantized_mult_fast(result2, *out_mult++, *out_shift++);
result3 = esp_nn_multiply_by_quantized_mult_fast(result3, *out_mult++, *out_shift++);
result0 += out_offset;
result1 += out_offset;
result2 += out_offset;
result3 += out_offset;
result0 = max(result0, activation_min);
result1 = max(result1, activation_min);
result2 = max(result2, activation_min);
result3 = max(result3, activation_min);
result0 = min(result0, activation_max);
result1 = min(result1, activation_max);
result2 = min(result2, activation_max);
result3 = min(result3, activation_max);
out_data[out_idx++] = result0;
out_data[out_idx++] = result1;
out_data[out_idx++] = result2;
out_data[out_idx++] = result3;
}
for (; ch_idx < channels; ch_idx++) {//channel_loop
int32_t result = 0;
for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) {
const int32_t idx_y = base_y + filter_y_idx;
for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) {
const int32_t idx_x = base_x + filter_x_idx;
int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx;
int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels) + ch_idx;
int32_t input_val = input_data[input_index] + input_offset;
int32_t filter_val = filter_data[filter_index];
result += input_val * filter_val;
}
}
if (bias) {
result += bias[ch_idx];
}
result = esp_nn_multiply_by_quantized_mult_fast(result, *out_mult++, *out_shift++);
result += out_offset;
result = max(result, activation_min);
result = min(result, activation_max);
out_data[out_idx++] = result;
}
}
}
}
void esp_nn_depthwise_conv_s8_opt(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
const int8_t *filter_data,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const dw_conv_params_t *conv_params,
const quant_data_t *quant_data)
{
const uint16_t ch_mult = conv_params->ch_mult;
if (ch_mult == 1) {
esp_nn_depthwise_conv_s8_ch_mult_1(input_dims, input_data, filter_dims, filter_data,
bias, output_dims, out_data, conv_params, quant_data);
return;
}
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
int out_idx = 0;
for (int out_y = 0; out_y < out_ht; out_y++) { //height loop
const int16_t base_y = (out_y * stride_ht) - pad_ht;
for (int out_x = 0; out_x < out_wd; out_x++) { //width_loop
const int16_t base_x = (out_x * stride_wd) - pad_wd;
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
/* Select filter so as the point doesn't lie outside block */
int filter_y_start = max(0, -base_y);
int filter_x_start = max(0, -base_x);
int filter_y_end = min(filter_ht, input_ht - base_y);
int filter_x_end = min(filter_wd, input_wd - base_x);
for (int ch_idx = 0; ch_idx < channels; ch_idx++) {//channel_loop
int ch_mult_idx = 0;
for (; ch_mult_idx < ch_mult - 3; ch_mult_idx += 4) {
int32_t result0 = 0;
int32_t result1 = 0;
int32_t result2 = 0;
int32_t result3 = 0;
const int out_ch_idx = ch_idx * ch_mult + ch_mult_idx;
for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) {
const int32_t idx_y = base_y + filter_y_idx;
for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) {
const int32_t idx_x = base_x + filter_x_idx;
int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx;
int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels * ch_mult) + out_ch_idx;
int32_t input_val = input_data[input_index] + input_offset;
int32_t filter_val0 = filter_data[filter_index + 0];
int32_t filter_val1 = filter_data[filter_index + 1];
int32_t filter_val2 = filter_data[filter_index + 2];
int32_t filter_val3 = filter_data[filter_index + 3];
result0 += input_val * filter_val0;
result1 += input_val * filter_val1;
result2 += input_val * filter_val2;
result3 += input_val * filter_val3;
}
}
if (bias) {
result0 += bias[out_ch_idx + 0];
result1 += bias[out_ch_idx + 1];
result2 += bias[out_ch_idx + 2];
result3 += bias[out_ch_idx + 3];
}
result0 = esp_nn_multiply_by_quantized_mult_fast(result0, *out_mult++, *out_shift++);
result1 = esp_nn_multiply_by_quantized_mult_fast(result1, *out_mult++, *out_shift++);
result2 = esp_nn_multiply_by_quantized_mult_fast(result2, *out_mult++, *out_shift++);
result3 = esp_nn_multiply_by_quantized_mult_fast(result3, *out_mult++, *out_shift++);
result0 += out_offset;
result1 += out_offset;
result2 += out_offset;
result3 += out_offset;
result0 = max(result0, activation_min);
result1 = max(result1, activation_min);
result2 = max(result2, activation_min);
result3 = max(result3, activation_min);
result0 = min(result0, activation_max);
result1 = min(result1, activation_max);
result2 = min(result2, activation_max);
result3 = min(result3, activation_max);
out_data[out_idx++] = result0;
out_data[out_idx++] = result1;
out_data[out_idx++] = result2;
out_data[out_idx++] = result3;
}
for (; ch_mult_idx < ch_mult; ch_mult_idx++) {
int32_t result = 0;
const int out_ch_idx = ch_idx * ch_mult + ch_mult_idx;
for (int filter_y_idx = filter_y_start; filter_y_idx < filter_y_end; filter_y_idx++) {
const int32_t idx_y = base_y + filter_y_idx;
for (int filter_x_idx = filter_x_start; filter_x_idx < filter_x_end; filter_x_idx++) {
const int32_t idx_x = base_x + filter_x_idx;
int32_t input_index = (idx_y * input_wd + idx_x) * channels + ch_idx;
int32_t filter_index = (filter_y_idx * filter_wd + filter_x_idx) * (channels * ch_mult) + out_ch_idx;
int32_t input_val = input_data[input_index] + input_offset;
int32_t filter_val = filter_data[filter_index];
result += input_val * filter_val;
}
}
if (bias) {
result += bias[out_ch_idx];
}
result = esp_nn_multiply_by_quantized_mult_fast(result, *out_mult++, *out_shift++);
result += out_offset;
result = max(result, activation_min);
result = min(result, activation_max);
out_data[out_idx++] = result;
}
}
}
}
}

View File

@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdint.h>
#include <stdio.h>
#include <esp_nn_defs.h>
#include <common_functions.h>
@@ -353,59 +353,17 @@ void esp_nn_depthwise_conv_s8_ch_mult1(const int8_t *input_data,
}
}
int esp_nn_get_depthwise_conv_scratch_size_esp32s3(const data_dims_t *input_dims,
const data_dims_t *filter_dims,
const data_dims_t *output_dims,
const dw_conv_params_t *conv_params)
int esp_nn_get_depthwise_conv_scratch_size_esp32s3(const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const uint16_t ch_mult,
const uint16_t filter_wd,
const uint16_t filter_ht)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t channels = input_dims->channels;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t ch_mult = conv_params->ch_mult;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
int filter_size = filter_wd * filter_ht * channels * ch_mult;
int pad_width = 0, pad_height = 0;
if ((ch_mult == 1) && (channels % 8 == 0) && (filter_wd == 3) && (filter_ht == 3)) {
if (channels % 16 == 0) {
if (pad_wd || pad_ht) {
pad_width = pad_wd * 2;
pad_height = pad_ht * 2;
} else {
// check if we need to pad additionally
pad_width = (out_wd * stride_wd + filter_wd - 1) - input_wd;
pad_height = (out_ht * stride_ht + filter_ht - 1) - input_ht;
// printf("in(%d %d %d), out(%d %d), filter (%d %d) stride (%d %d), pad (%d %d)",
// input_wd, input_ht, channels, out_wd, out_ht, filter_wd, filter_ht,
// stride_wd, stride_ht, pad_wd, pad_ht);
}
if (pad_width || pad_height) {
int input_size = (input_wd + pad_width) * (input_ht + pad_height) * channels;
// printf("ask1 %d\n", filter_size + input_size + 16);
return filter_size + input_size + 16; // 16 for alignment
} else {
// printf("ask2 %d\n", filter_size + 16);
return filter_size + 16; // 16 for alignment
}
} else {
int input_size = input_wd * input_ht * channels;
// printf("ask3 %d\n", 2 * (filter_size + input_size) + 16);
return 2 * (filter_size + input_size) + 16; // 16 for alignment
}
} else if (ch_mult % 4 == 0) {
int input_size = input_wd * input_ht * channels;
// printf("ask4 %d\n", 2 * (filter_size + input_size) + 16);
return 2 * (filter_size + input_size) + 16; // 16 for alignment
}
return 32; // just few bytes
int padding_used = ((filter_wd == 3) && (filter_ht == 3)) * 2;
int input_size = (input_wd + padding_used) * (input_ht + padding_used) * channels;
return 2 * (filter_size + input_size) + 16; //16 for alignment
}
void esp_nn_set_depthwise_conv_scratch_buf_esp32s3(void *buf)
@@ -418,38 +376,29 @@ void esp_nn_set_depthwise_conv_scratch_buf_esp32s3(void *buf)
* Assumption 2: Pointers are valid
* Assumption 3: dialation width = 1
*/
void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims,
const int8_t *input_data,
const data_dims_t *filter_dims,
void esp_nn_depthwise_conv_s8_esp32s3(const int8_t *input_data,
const uint16_t input_wd,
const uint16_t input_ht,
const uint16_t channels,
const int32_t input_offset,
const uint16_t pad_wd,
const uint16_t pad_ht,
const uint16_t stride_wd,
const uint16_t stride_ht,
const uint16_t ch_mult,
const int8_t *filter_data,
const uint16_t filter_wd,
const uint16_t filter_ht,
const int32_t *bias,
const data_dims_t *output_dims,
int8_t *out_data,
const dw_conv_params_t *conv_params,
const quant_data_t *quant_data)
const uint16_t out_wd,
const uint16_t out_ht,
const int32_t out_offset,
const int32_t *out_shift,
const int32_t *out_mult,
const int32_t activation_min,
const int32_t activation_max)
{
const uint16_t input_wd = input_dims->width;
const uint16_t input_ht = input_dims->height;
const uint16_t channels = input_dims->channels;
const int32_t input_offset = conv_params->in_offset;
const int32_t out_offset = conv_params->out_offset;
const uint16_t pad_wd = conv_params->padding.width;
const uint16_t pad_ht = conv_params->padding.height;
const uint16_t stride_wd = conv_params->stride.width;
const uint16_t stride_ht = conv_params->stride.height;
const uint16_t filter_wd = filter_dims->width;
const uint16_t filter_ht = filter_dims->height;
const uint16_t out_wd = output_dims->width;
const uint16_t out_ht = output_dims->height;
const int32_t *out_shift = quant_data->shift;
const int32_t *out_mult = quant_data->mult;
const int32_t activation_min = conv_params->activation.min;
const int32_t activation_max = conv_params->activation.max;
const uint16_t ch_mult = conv_params->ch_mult;
int filter_size = filter_wd * filter_ht * channels * ch_mult;
int align_len = 16 - (filter_size & 15);
int input_size = input_wd * input_ht * channels;
@@ -474,27 +423,18 @@ void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims,
stride_wd, stride_ht, filter_aligned, bias,
out_data, out_wd, out_ht, out_offset, out_shift,
out_mult, activation_min, activation_max);
} else if ((channels % 16 == 0) && (pad_wd == 0) && (pad_ht == 0)) {
} else if ((pad_wd == 0) && (pad_ht == 0) &&
// because this does not handle padding offset cases yet, run just for stride (1, 1).
// end padding of input with `-input_offset` should solve this
(stride_wd == 1) && (stride_ht == 1)) {
/* process in 8 bits */
int8_t *filter_aligned = (int8_t *) scratch_buffer;
int8_t *input_padded = (int8_t *) scratch_buffer + filter_size + align_len;
// check if we need to pad additionally
int pad_right = (out_wd * stride_wd + filter_wd - 1) - input_wd;
int pad_bottom = (out_ht * stride_ht + filter_ht - 1) - input_ht;
if (pad_right || pad_bottom) { // pad right and bottom
esp_nn_aligned_s8_pad_end_with_value(input_data, input_padded, input_wd, input_ht,
channels, -input_offset, pad_right, pad_bottom);
} else {
input_padded = (int8_t *) input_data;
}
memcpy(filter_aligned, filter_data, filter_size);
esp_nn_depthwise_conv_s8_mult1_3x3_padded_esp32s3(input_padded, input_wd + pad_right,
input_ht + pad_bottom, channels, input_offset,
stride_wd, stride_ht, filter_aligned, bias,
out_data, out_wd, out_ht, out_offset, out_shift,
esp_nn_depthwise_conv_s8_mult1_3x3_padded_esp32s3(input_data, input_wd, input_ht, channels, input_offset,
stride_wd, stride_ht, filter_aligned,
bias, out_data, out_wd, out_ht, out_offset, out_shift,
out_mult, activation_min, activation_max);
} else { /* (channels % 8) == 0 */
} else { /* (channels % 8) == 0 && pad_wd == 1 && pad_ht == 1 */
esp_nn_s8_to_s16_esp32s3(filter_data, filter_data16, filter_size);
esp_nn_aligned_s8_to_s16_with_offset_esp32s3(input_data, input_data16, input_size, input_offset);
esp_nn_depthwise_conv_s16_mult1_3x3_esp32s3(input_data16, input_wd, input_ht, channels,

View File

@@ -1,8 +0,0 @@
# Default configurations for ESP32-S3
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
CONFIG_ESP32S3_DATA_CACHE_64KB=y
CONFIG_ESP32S3_DATA_CACHE_8WAYS=y
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y

View File

@@ -23,9 +23,7 @@
#include "test_utils.h"
#if CONFIG_IDF_CMAKE
#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
#define IDF_HEAP_CAPS 1
#endif
#if IDF_HEAP_CAPS
#include "esp_heap_caps.h"
@@ -140,11 +138,6 @@ void esp_nn_add_elementwise_s8_test()
out_c_orig = out_data_c;
out_opt_orig = out_data_opt;
#endif
if (input1_orig == NULL || input2_orig == NULL || out_c_orig == NULL ||
out_opt_orig == NULL) {
printf(ANSI_COLOR_RED"%s error allocating buffers\n"ANSI_COLOR_RESET, __FUNCTION__);
goto elementwise_add_test_cleanup;
}
for (int i = 0; i < size; ++i) {
input1[i] = rand() % 256 - 128;
@@ -201,10 +194,10 @@ elementwise_add_test_cleanup:
if (input2_orig) {
free(input2_orig);
}
if (out_c_orig) {
if (out_data_c) {
free(out_c_orig);
}
if (out_opt_orig) {
if (out_data_opt) {
free(out_opt_orig);
}
}
@@ -289,11 +282,6 @@ void esp_nn_mul_elementwise_s8_test()
out_c_orig = out_data_c;
out_opt_orig = out_data_opt;
#endif
if (input1_orig == NULL || input2_orig == NULL || out_c_orig == NULL ||
out_opt_orig == NULL) {
printf(ANSI_COLOR_RED"%s error allocating buffers\n"ANSI_COLOR_RESET, __FUNCTION__);
goto elementwise_mult_test_cleanup;
}
for (int i = 0; i < size; ++i) {
input1[i] = rand() % 256 - 128;
@@ -345,10 +333,10 @@ elementwise_mult_test_cleanup:
if (input2_orig) {
free(input2_orig);
}
if (out_c_orig) {
if (out_data_c) {
free(out_c_orig);
}
if (out_opt_orig) {
if (out_data_opt) {
free(out_opt_orig);
}
}

View File

@@ -22,9 +22,8 @@
#include "test_utils.h"
#if CONFIG_IDF_CMAKE
#if (CONFIG_SPIRAM_SUPPORT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC))
#define IDF_HEAP_CAPS 1
#endif
#if IDF_HEAP_CAPS
#include "esp_heap_caps.h"
#endif
@@ -45,8 +44,8 @@ void esp_nn_depthwise_conv_s8_test()
uint16_t filter_ht, filter_wd, ch_mult;
uint16_t pad_wd, pad_ht, stride_wd, stride_ht;
// run for 15 iterations
for (int itr = 0; itr < 15; itr++) {
// run for 10 iterations
for (int itr = 0; itr < 10; itr++) {
/* prepare data */
switch (itr) {
case 0: // (ch_mult 1, (channels % 16) = 0), filter (3,3), pad (0,0)
@@ -145,52 +144,22 @@ void esp_nn_depthwise_conv_s8_test()
stride_wd = 2;
stride_ht = 2;
break;
case 8: // same as case 7, with large parameters
input_wd = 58;
input_ht = 58;
filter_ht = 3;
filter_wd = 3;
ch_mult = 1;
channels = 128;
pad_wd = 0;
pad_ht = 0;
stride_wd = 2;
stride_ht = 2;
break;
case 9: // (ch_mult 1, (channels % 16) = 0), filter (3,3), pad (0,0) stride (2,2)
input_wd = 6;
input_ht = 6;
filter_ht = 3;
filter_wd = 3;
ch_mult = 1;
channels = 16;
pad_wd = 0;
pad_ht = 0;
stride_wd = 2;
stride_ht = 2;
break;
default:
input_wd = 6;
input_ht = 6;
input_wd = 4;
input_ht = 4;
filter_ht = 3;
filter_wd = 3;
ch_mult = 1;
channels = 16;
stride_wd = rand() % 2 + 1;
stride_ht = stride_wd;
pad_wd = stride_wd == 1 ? 0 : rand() % 2;
pad_ht = pad_wd;
printf("stride(%d), pad (%d)\t", stride_wd, pad_wd);
ch_mult = 4;
channels = 4;
pad_wd = 1;
pad_ht = 1;
stride_wd = 1;
stride_ht = 1;
break;
}
uint16_t out_wd = (input_wd - filter_wd + 1) / stride_wd;
uint16_t out_ht = (input_ht - filter_ht + 1) / stride_ht;
if (itr == 9) {
// expect the function to handle this gracefully
out_wd += 1;
out_ht += 1;
}
int in_size = input_wd * input_ht * channels;
int out_size = out_wd * out_ht * channels * ch_mult;
int filter_size = filter_wd * filter_ht * channels * ch_mult + 4;
@@ -241,16 +210,9 @@ void esp_nn_depthwise_conv_s8_test()
out_mult[i] = 0x7eb0e200 + rand() % 50;
}
data_dims_t input_dims = {.width = input_wd, .height = input_ht, .channels = channels, 1};
data_dims_t output_dims = {.width = out_wd, .height = out_ht, .channels = channels * ch_mult, 1};
data_dims_t filter_dims = {.width = filter_wd, .height = filter_ht, 0, 0};
dw_conv_params_t conv_params = {.in_offset = input_offset, .out_offset = out_offset, .ch_mult = ch_mult,
.stride = {stride_wd, stride_ht}, .padding = {pad_wd, pad_ht},
.dilation = {0, 0}, .activation = {activation_min, activation_max}};
quant_data_t quant_data = {.shift = out_shift, .mult = out_mult};
int scratch_buf_size = esp_nn_get_depthwise_conv_scratch_size(&input_dims, &filter_dims,
&output_dims, &conv_params);
int scratch_buf_size = esp_nn_get_depthwise_conv_scratch_size(input_wd, input_ht,
channels, ch_mult,
filter_wd, filter_ht);
if (scratch_buf_size > 0) {
#if IDF_HEAP_CAPS
scratch_buf = heap_caps_malloc(scratch_buf_size + 32, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
@@ -272,8 +234,11 @@ void esp_nn_depthwise_conv_s8_test()
}
/* C function */
esp_nn_depthwise_conv_s8_ansi(&input_dims, input, &filter_dims, filter_data + 4,
bias + 1, &output_dims, out_data_c, &conv_params, &quant_data);
esp_nn_depthwise_conv_s8_ansi(input, input_wd, input_ht, channels, input_offset,
pad_wd, pad_ht, stride_wd, stride_ht, ch_mult,
filter_data + 4, filter_wd, filter_ht,
bias + 1, out_data_c, out_wd, out_ht, out_offset, out_shift,
out_mult, activation_min, activation_max);
if (itr == 0) {
profile_c_end();
@@ -281,8 +246,11 @@ void esp_nn_depthwise_conv_s8_test()
}
/* Optimized function */
esp_nn_depthwise_conv_s8(&input_dims, input, &filter_dims, filter_data + 4,
bias + 1, &output_dims, out_data_opt, &conv_params, &quant_data);
esp_nn_depthwise_conv_s8(input, input_wd, input_ht, channels, input_offset,
pad_wd, pad_ht, stride_wd, stride_ht, ch_mult,
filter_data + 4, filter_wd, filter_ht,
bias + 1, out_data_opt, out_wd, out_ht, out_offset, out_shift,
out_mult, activation_min, activation_max);
if (itr == 0) {
/* disable profiler */
@@ -511,16 +479,8 @@ void esp_nn_conv_s8_test()
out_mult[i] = 0x7f67f4f8 + rand() % 50;
}
data_dims_t input_dims = {.width = in_wd, .height = in_ht, .channels = in_channels, 1};
data_dims_t output_dims = {.width = out_wd, .height = out_ht, .channels = out_channels, 1};
data_dims_t filter_dims = {.width = filter_wd, .height = filter_ht, 0, 0};
conv_params_t conv_params = {.in_offset = input_offset, .out_offset = out_offset,
.stride = {stride_wd, stride_ht}, .padding = {pad_wd, pad_ht},
.dilation = {0, 0}, .activation = {activation_min, activation_max}};
quant_data_t quant_data = {.shift = out_shift, .mult = out_mult};
int scratch_buf_size = esp_nn_get_conv_scratch_size(&input_dims, &filter_dims,
&output_dims, &conv_params);
int scratch_buf_size = esp_nn_get_conv_scratch_size(in_wd, in_ht, in_channels,
out_channels, filter_wd, filter_ht);
if (scratch_buf_size > 0) {
#if IDF_HEAP_CAPS
void *scratch_buf = heap_caps_malloc(scratch_buf_size + 32, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
@@ -542,8 +502,11 @@ void esp_nn_conv_s8_test()
}
/* C function */
esp_nn_conv_s8_ansi(&input_dims, input, &filter_dims, filter_data + 2,
bias, &output_dims, out_data_c, &conv_params, &quant_data);
esp_nn_conv_s8_ansi(input, in_wd, in_ht, in_channels, input_offset,
pad_wd, pad_ht, stride_wd, stride_ht,
filter_data + 2, filter_wd, filter_ht, bias,
out_data_c, out_wd, out_ht, out_channels, out_offset, out_shift,
out_mult, activation_min, activation_max);
if (itr == 0) {
profile_c_end();
@@ -551,8 +514,11 @@ void esp_nn_conv_s8_test()
}
/* Optimized function */
esp_nn_conv_s8(&input_dims, input, &filter_dims, filter_data + 2,
bias, &output_dims, out_data_opt, &conv_params, &quant_data);
esp_nn_conv_s8(input, in_wd, in_ht, in_channels, input_offset,
pad_wd, pad_ht, stride_wd, stride_ht,
filter_data + 2, filter_wd, filter_ht, bias,
out_data_opt, out_wd, out_ht, out_channels, out_offset, out_shift,
out_mult, activation_min, activation_max);
if (itr == 0) {
/* disable profiler */

Binary file not shown.

View File

@@ -8,37 +8,26 @@ on:
jobs:
build-master:
runs-on: ubuntu-latest
strategy:
matrix:
idf_target: ["esp32", "esp32s2", "esp32s3"]
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: esp-idf build
uses: espressif/esp-idf-ci-action@main
uses: espressif/esp-idf-ci-action@latest
with:
target: ${{ matrix.idf_target }}
path: 'examples'
build-release-v4_4:
name: Build for ${{ matrix.idf_target }} on ${{ matrix.idf_ver }}
build-release-v4_0:
runs-on: ubuntu-latest
strategy:
matrix:
idf_ver: ["v4.4"]
idf_target: ["esp32", "esp32s2", "esp32s3"]
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: esp-idf build
uses: espressif/esp-idf-ci-action@main
uses: espressif/esp-idf-ci-action@release-v4.0
with:
esp_idf_version: ${{ matrix.idf_ver }}
target: ${{ matrix.idf_target }}
path: 'examples'
build-release-v4_1:
@@ -76,3 +65,15 @@ jobs:
uses: espressif/esp-idf-ci-action@release-v4.3
with:
path: 'examples'
build-release-v3_3:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: esp-idf build
uses: espressif/esp-idf-ci-action@release-v3.3
with:
path: 'examples'

View File

@@ -10,10 +10,12 @@ jobs:
- uses: actions/checkout@master
with:
submodules: "recursive"
- name: Upload component to the component registry
uses: espressif/github-actions/upload_components@master
with:
name: "esp32-camera"
version: "git"
namespace: "espressif"
version: ${{ github.ref_name }}
service_url: ${{ secrets.IDF_COMPONENT_API_URL }}
api_token: ${{ secrets.IDF_COMPONENT_API_TOKEN }}

View File

@@ -1,29 +1,5 @@
# get IDF version for comparison
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}")
# set conversion sources
set(COMPONENT_SRCS
conversions/yuv.c
conversions/to_jpg.cpp
conversions/to_bmp.c
conversions/jpge.cpp
conversions/esp_jpg_decode.c
)
set(COMPONENT_PRIV_INCLUDEDIRS
conversions/private_include
)
set(COMPONENT_ADD_INCLUDEDIRS
driver/include
conversions/include
)
set(COMPONENT_REQUIRES driver)
# set driver sources only for supported platforms
if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
list(APPEND COMPONENT_SRCS
set(COMPONENT_SRCS
driver/esp_camera.c
driver/cam_hal.c
driver/sccb.c
@@ -38,14 +14,22 @@ if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET ST
sensors/gc2145.c
sensors/gc032a.c
sensors/bf3005.c
sensors/bf20a6.c
sensors/sc101iot.c
sensors/sc030iot.c
conversions/yuv.c
conversions/to_jpg.cpp
conversions/to_bmp.c
conversions/jpge.cpp
conversions/esp_jpg_decode.c
)
list(APPEND COMPONENT_PRIV_INCLUDEDIRS
set(COMPONENT_ADD_INCLUDEDIRS
driver/include
conversions/include
)
set(COMPONENT_PRIV_INCLUDEDIRS
driver/private_include
sensors/private_include
conversions/private_include
target/private_include
)
@@ -74,13 +58,8 @@ if(IDF_TARGET STREQUAL "esp32" OR IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET ST
)
endif()
set(COMPONENT_REQUIRES driver)
set(COMPONENT_PRIV_REQUIRES freertos nvs_flash)
set(min_version_for_esp_timer "4.2")
if (idf_version VERSION_GREATER_EQUAL min_version_for_esp_timer)
list(APPEND COMPONENT_PRIV_REQUIRES esp_timer)
endif()
register_component()
endif()
register_component()

View File

@@ -69,45 +69,6 @@ menu "Camera configuration"
help
Enable this option if you want to use the BF3005.
Disable this option to save memory.
config BF20A6_SUPPORT
bool "Support BF20A6(BYD20A6) VGA"
default y
help
Enable this option if you want to use the BF20A6.
Disable this option to save memory.
config SC101IOT_SUPPORT
bool "Support SC101IOT HD"
default n
help
Enable this option if you want to use the SC101IOT.
Disable this option to save memory.
choice SC101_REGS_SELECT
prompt "SC101iot default regs"
default SC101IOT_720P_15FPS_ENABLED
depends on SC101IOT_SUPPORT
help
Currently SC010iot has several register sets available.
Select the one that matches your needs.
config SC101IOT_720P_15FPS_ENABLED
bool "xclk20M_720p_15fps"
help
Select this option means that when xclk is 20M, the frame rate is 15fps at 720p resolution.
config SC101IOT_VGA_25FPS_ENABLED
bool "xclk20M_VGA_25fps"
help
Select this option means that when xclk is 20M, the frame rate is 25fps at VGA resolution.
endchoice
config SC030IOT_SUPPORT
bool "Support SC030IOT VGA"
default y
help
Enable this option if you want to use the SC030IOT.
Disable this option to save memory.
choice SCCB_HARDWARE_I2C_PORT
bool "I2C peripheral to use for SCCB"
@@ -164,24 +125,5 @@ menu "Camera configuration"
help
Maximum value of DMA buffer
Larger values may fail to allocate due to insufficient contiguous memory blocks, and smaller value may cause DMA interrupt to be too frequent
config CAMERA_CONVERTER_ENABLED
bool "Enable camera RGB/YUV converter"
depends on IDF_TARGET_ESP32S3
default n
help
Enable this option if you want to use RGB565/YUV422/YUV420/YUV411 format conversion.
choice CAMERA_CONV_PROTOCOL
bool "Camera converter protocol"
depends on CAMERA_CONVERTER_ENABLED
default LCD_CAM_CONV_BT601_ENABLED
help
Supports format conversion under both BT601 and BT709 standards.
config LCD_CAM_CONV_BT601_ENABLED
bool "BT601"
config LCD_CAM_CONV_BT709_ENABLED
bool "BT709"
endchoice
endmenu

View File

@@ -25,9 +25,6 @@ This repository hosts ESP32 series Soc compatible driver for image sensors. Addi
| GC0308 | 640 x 480 | color | YUV/YCbCr422<br/>RAW Bayer<br/>RGB565 | 1/6.5" |
| GC2145 | 1600 x 1200 | color | YUV/YCbCr422<br/>RAW Bayer<br/>RGB565 | 1/5" |
| BF3005 | 640 x 480 | color | YUV/YCbCr422<br/>RAW Bayer<br/>RGB565 | 1/4" |
| BF20A6 | 640 x 480 | color | YUV/YCbCr422<br/>RAW Bayer | 1/10" |
| SC101IOT| 1280 x 720 | color | YUV/YCbCr422<br/>Raw RGB | 1/4.2" |
| SC030IOT| 640 x 480 | color | YUV/YCbCr422<br/>RAW Bayer | 1/6.5" |
## Important to Remember

View File

@@ -21,10 +21,6 @@
#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
@@ -61,7 +57,7 @@ static const char * jd_errors[] = {
"Not supported JPEG standard"
};
static unsigned int _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
static uint32_t _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
{
uint16_t x = rect->left;
uint16_t y = rect->top;
@@ -77,7 +73,7 @@ static unsigned int _jpg_write(JDEC *decoder, void *bitmap, JRECT *rect)
return 0;
}
static unsigned int _jpg_read(JDEC *decoder, uint8_t *buf, unsigned int len)
static uint32_t _jpg_read(JDEC *decoder, uint8_t *buf, uint32_t len)
{
esp_jpg_decoder_t * jpeg = (esp_jpg_decoder_t *)decoder->device;
if (jpeg->len && len > (jpeg->len - jpeg->index)) {

View File

@@ -29,12 +29,7 @@ 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); }

View File

@@ -21,6 +21,19 @@
#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"
@@ -59,12 +72,7 @@ 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
@@ -160,7 +168,7 @@ static bool _rgb565_write(void * arg, uint16_t x, uint16_t y, uint16_t w, uint16
}
//input buffer
static unsigned int _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
static uint32_t _jpg_read(void * arg, size_t index, uint8_t *buf, size_t len)
{
rgb_jpg_decoder * jpeg = (rgb_jpg_decoder *)arg;
if(buf) {

View File

@@ -21,6 +21,21 @@
#include "jpge.h"
#include "yuv.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"
#define TAG ""
@@ -35,12 +50,7 @@ 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)

View File

@@ -18,21 +18,8 @@
#include "ll_cam.h"
#include "cam_hal.h"
#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
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
@@ -106,7 +93,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_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"));
ESP_EARLY_LOGE(TAG, "EV-%s-OVF", cam_event==CAM_IN_SUC_EOF_EVENT ? "EOF" : "VSYNC");
}
}

View File

@@ -57,15 +57,6 @@
#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"
@@ -128,15 +119,6 @@ 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)
@@ -236,23 +218,6 @@ static esp_err_t camera_probe(const camera_config_t *config, camera_model_t *out
return ESP_OK;
}
#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;
@@ -291,7 +256,6 @@ 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");
@@ -299,11 +263,6 @@ 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);

View File

@@ -70,7 +70,6 @@
#include "driver/ledc.h"
#include "sensor.h"
#include "sys/time.h"
#include "sdkconfig.h"
#ifdef __cplusplus
extern "C" {
@@ -92,19 +91,6 @@ 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
*/
@@ -138,9 +124,6 @@ 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
} camera_config_t;
/**

View File

@@ -27,9 +27,6 @@ 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 {
@@ -43,9 +40,6 @@ typedef enum {
CAMERA_GC032A,
CAMERA_GC0308,
CAMERA_BF3005,
CAMERA_BF20A6,
CAMERA_SC101IOT,
CAMERA_SC030IOT,
CAMERA_MODEL_MAX,
CAMERA_NONE,
} camera_model_t;
@@ -61,15 +55,11 @@ 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

View File

@@ -25,11 +25,6 @@ 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 */

View File

@@ -13,9 +13,6 @@ 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] = {

View File

@@ -38,11 +38,6 @@
#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

View File

@@ -1,2 +1,5 @@
description: ESP32 compatible driver for OV2640, OV3660, OV5640, OV7670 and OV7725 image sensors.
url: https://github.com/espressif/esp32-camera
targets:
- esp32
- esp32s2
- esp32s3

View File

@@ -1,404 +0,0 @@
// 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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;
}

View File

@@ -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 uint8_t (*regs)[2], size_t regs_size)
static int write_regs(uint8_t slv_addr, const uint16_t (*regs)[2])
{
int i = 0, ret = 0;
while (!ret && (i < regs_size)) {
while (!ret && regs[i][0] != REGLIST_TAIL) {
if (regs[i][0] == REG_DLY) {
vTaskDelay(regs[i][1] / portTICK_PERIOD_MS);
} else {
@@ -132,12 +132,11 @@ static int reset(sensor_t *sensor)
ESP_LOGE(TAG, "Software Reset FAILED!");
return ret;
}
vTaskDelay(80 / portTICK_PERIOD_MS);
ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs, sizeof(gc0308_sensor_default_regs)/(sizeof(uint8_t) * 2));
vTaskDelay(100 / portTICK_PERIOD_MS);
ret = write_regs(sensor->slv_addr, gc0308_sensor_default_regs);
if (ret == 0) {
ESP_LOGD(TAG, "Camera defaults loaded");
vTaskDelay(80 / portTICK_PERIOD_MS);
vTaskDelay(100 / 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

View File

@@ -1,27 +0,0 @@
#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__

View File

@@ -1,12 +0,0 @@
/*
* 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__

View File

@@ -1,158 +0,0 @@
#include <stdint.h>
#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},
};

View File

@@ -3,9 +3,10 @@
#include <stdint.h>
#define REG_DLY 0xff
#define REG_DLY 0xffff
#define REGLIST_TAIL 0x0000 /* Array end token */
static const uint8_t gc0308_sensor_default_regs[][2] = {
static const uint16_t gc0308_sensor_default_regs[][2] = {
{0xfe, 0x00},
{0xec, 0x20},
{0x05, 0x00},
@@ -238,21 +239,7 @@ static const uint8_t gc0308_sensor_default_regs[][2] = {
{0x65, 0xd3},
{0x66, 0x60},
{0xfe, 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},
{REGLIST_TAIL, 0x00},
};
#endif

View File

@@ -42,8 +42,7 @@ static const DRAM_ATTR uint16_t sensor_default_regs[][2] = {
{ISP_CONTROL_01, 0x83}, // turn color matrix, awb and SDE
//sys reset
{0x3000, 0x20}, // reset MCU
{REG_DLY, 10}, // delay 10ms
{0x3000, 0x00},
{0x3002, 0x1c},
//clock enable

View File

@@ -1,31 +0,0 @@
/*
*
* 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__

View File

@@ -1,491 +0,0 @@
//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 <stdint.h>
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},
};
*/

View File

@@ -1,31 +0,0 @@
/*
*
* 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__

View File

@@ -1,257 +0,0 @@
//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 <stdint.h>
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
};

View File

@@ -1,335 +0,0 @@
/*
* 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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 (i<regs_entry_len) {
res = SCCB_Write(sensor->slv_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;
}

View File

@@ -1,342 +0,0 @@
/*
* 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 <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#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 (i<regs_entry_len) {
res = SCCB_Write(sensor->slv_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;
}

View File

@@ -34,14 +34,10 @@ 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) esp_rom_gpio_connect_in_signal(a,b,c)
#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
#endif
static const char *TAG = "esp32 ll_cam";
@@ -237,7 +233,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
//DBG_PIN_SET(0);
}
bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
bool ll_cam_stop(cam_obj_t *cam)
{
I2S0.conf.rx_start = 0;
I2S_ISR_DISABLE(in_suc_eof);

View File

@@ -21,15 +21,10 @@
#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) esp_rom_gpio_connect_in_signal(a,b,c)
#define ets_delay_us(a) esp_rom_delay_us(a)
#define gpio_matrix_in(a,b,c) gpio_iomux_in(a,b)
#endif
static const char *TAG = "s2 ll_cam";
@@ -75,7 +70,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
}
}
bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
bool ll_cam_stop(cam_obj_t *cam)
{
I2S0.conf.rx_start = 0;

View File

@@ -22,15 +22,10 @@
#include "soc/gdma_reg.h"
#include "ll_cam.h"
#include "cam_hal.h"
#include "esp_rom_gpio.h"
#if (ESP_IDF_VERSION_MAJOR >= 5)
#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)
#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)
#endif
static const char *TAG = "s3 ll_cam";
@@ -79,7 +74,7 @@ static void IRAM_ATTR ll_cam_dma_isr(void *arg)
}
}
bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam)
bool 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;
@@ -175,7 +170,6 @@ 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
@@ -184,52 +178,8 @@ 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
LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 0;
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);
@@ -265,21 +215,15 @@ 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;
ret = ll_cam_dma_init(cam);
esp_err_t err = ll_cam_dma_init(cam);
if(err != ESP_OK) {
return err;
}
return ret;
return ESP_OK;
}
void ll_cam_vsync_intr_enable(cam_obj_t *cam, bool en)
@@ -473,7 +417,6 @@ size_t IRAM_ATTR ll_cam_memcpy(cam_obj_t *cam, uint8_t *out, const uint8_t *in,
}
return len / 2;
}
// just memcpy
memcpy(out, in, len);
@@ -490,22 +433,8 @@ 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) {
#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->in_bytes_per_pixel = 2; // camera sends YU/YV
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;

View File

@@ -116,14 +116,8 @@ 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;

Binary file not shown.

View File

@@ -95,8 +95,13 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req)
_filename = std::string(entry->d_name);
printf("File: %s\t", _filename.c_str());
// ignore all files with starting dot (hidden files)
if (_filename.rfind(".", 0) == 0) {
continue;
}
_fileext = _filename;
pos = _fileext.find(".");
pos = _fileext.find_last_of(".");
if (pos != std::string::npos)
_fileext = _fileext.erase(0, pos + 1);

View File

@@ -113,6 +113,8 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
{
prev = -1;
result = "N" + result;
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(result_float<0 /'N') result_float=" + std::to_string(GENERAL[_analog]->ROI[i]->result_float));
}
}
return result;
@@ -205,7 +207,8 @@ int ClassFlowCNNGeneral::ZeigerEvalHybrid(float zahl, float zahl_vorgaenger, int
return (ergebnis_vorkomma - 1 + 10) % 10;
}
}
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybrid(return -1) zahl=" + std::to_string(zahl)
+ ", zahl_vorgaenger=" + std::to_string(zahl_vorgaenger) + ", eval_vorgaenger=" + std::to_string(eval_vorgaenger));
return -1;
/*
@@ -575,6 +578,7 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
}
break;
default:
LogFile.WriteToFile("ERROR ERROR ERROR - tflite passt nicht zur Firmware - ERROR ERROR ERROR (outout_dimension=" + std::to_string(_anzoutputdimensions) + ")");
printf("ERROR ERROR ERROR - tflite passt nicht zur Firmware - ERROR ERROR ERROR\n");
}
}
@@ -756,7 +760,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
_fit = _val + _valminus;
}
if (result >= 10)
if (result > 10)
result = result - 10;
if (result < 0)
result = result + 10;
@@ -807,34 +811,21 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
case Analogue100:
{
int _num;
float _fit;
float _result_save_file;
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
tflite->Invoke();
_num = tflite->GetOutClassification();
_fit = tflite->GetOutputValue(_num);
GENERAL[_ana]->ROI[i]->result_float = (float)_num / 10.0;
_result_save_file = GENERAL[_ana]->ROI[i]->result_float;
if (_fit < CNNGoodThreshold)
{
GENERAL[_ana]->ROI[i]->isReject = true;
GENERAL[_ana]->ROI[i]->result_float = -1;
_result_save_file+= 100; // Für den Fall, dass fit nicht ausreichend, soll trotzdem das Ergebnis mit "-10x.y" abgespeichert werden.
string zw = "Value Rejected due to Threshold (Fit: " + to_string(_fit) + "Threshold: " + to_string(CNNGoodThreshold);
printf("Value Rejected due to Threshold (Fit: %f, Threshold: %f\n", _fit, CNNGoodThreshold);
LogFile.WriteToFile(zw);
}
else
{
GENERAL[_ana]->ROI[i]->isReject = false;
}
GENERAL[_ana]->ROI[i]->isReject = false;
printf("Result General(Analog)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
if (isLogImage)
@@ -881,11 +872,14 @@ std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
{
printf("Image: %d\n", (int) GENERAL[_ana]->ROI[i]->image);
if (GENERAL[_ana]->ROI[i]->image)
{
if (GENERAL[_ana]->name == "default")
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
else
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
}
HTMLInfo *zw = new HTMLInfo;
if (GENERAL[_ana]->name == "default")

View File

@@ -586,6 +586,8 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
{
std::vector<HTMLInfo*> htmlinfo;
htmlinfo = GetAllDigital();
printf("After getClassFlowControll::GetAllDigital\n");
for (int i = 0; i < htmlinfo.size(); ++i)
{
if (_fn == htmlinfo[i]->filename)

View File

@@ -20,7 +20,7 @@ struct RefInfo {
int fastalg_max = -1;
float fastalg_SAD = -1;
float fastalg_SAD_criteria = -1;
int alignment_algo = 0; // 0 = "Default" (nur R-Kanal), 1 = "HighAccurity" (RGB-Kanal), 2 = "Fast" (1.x RGB, dann isSimilar)
int alignment_algo = 0; // 0 = "Default" (nur R-Kanal), 1 = "HighAccuracy" (RGB-Kanal), 2 = "Fast" (1.x RGB, dann isSimilar)
};

View File

@@ -314,6 +314,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
std::vector<HTMLInfo*> htmlinfodig;
htmlinfodig = tfliteflow.GetAllDigital();
for (int i = 0; i < htmlinfodig.size(); ++i)
{
if (tfliteflow.GetTypeDigital() == Digital)

View File

@@ -25,8 +25,7 @@ list(REMOVE_ITEM srcs_kernels
"${tfmicro_kernels_dir}/depthwise_conv.cc"
"${tfmicro_kernels_dir}/fully_connected.cc"
"${tfmicro_kernels_dir}/mul.cc"
"${tfmicro_kernels_dir}/pooling.cc"
"${tfmicro_kernels_dir}/softmax.cc")
"${tfmicro_kernels_dir}/pooling.cc")
FILE(GLOB esp_nn_kernels
"${tfmicro_kernels_dir}/esp_nn/*.cc")
@@ -39,8 +38,6 @@ set(lib_srcs
"${tflite_dir}/kernels/kernel_util.cc"
"${tflite_dir}/micro/memory_planner/greedy_memory_planner.cc"
"${tflite_dir}/micro/memory_planner/linear_memory_planner.cc"
"${tflite_dir}/micro/arena_allocator/recording_simple_memory_allocator.cc"
"${tflite_dir}/micro/arena_allocator/simple_memory_allocator.cc"
"${tflite_dir}/c/common.cc"
"${tflite_dir}/core/api/error_reporter.cc"
"${tflite_dir}/core/api/flatbuffer_conversions.cc"

View File

@@ -179,8 +179,6 @@ typedef enum {
kTfLiteBuiltinMultinomial = 149,
kTfLiteBuiltinGelu = 150,
kTfLiteBuiltinDynamicUpdateSlice = 151,
kTfLiteBuiltinRelu0To1 = 152,
kTfLiteBuiltinUnsortedSegmentProd = 153,
} TfLiteBuiltinOperator;
#ifdef __cplusplus

View File

@@ -518,9 +518,6 @@ typedef struct {
bool approximate;
} TfLiteGeluParams;
typedef struct {
int num_segments;
} TfLiteUnsortedSegmentProdParams;
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus

View File

@@ -113,13 +113,7 @@ typedef struct TfLiteQuantizationParams {
} TfLiteQuantizationParams;
// --------------------------------------------------------------------------
// Opaque types used by c_api.h, c_api_opaque.h and common.h.
// TfLiteOpaqueContext is an opaque version of TfLiteContext;
typedef struct TfLiteOpaqueContext TfLiteOpaqueContext;
// TfLiteOpaqueNode is an opaque version of TfLiteNode;
typedef struct TfLiteOpaqueNode TfLiteOpaqueNode;
// Opaque types used by c_api_opaque.h.
// TfLiteOpaqueTensor is an opaque version of TfLiteTensor;
typedef struct TfLiteOpaqueTensor TfLiteOpaqueTensor;

View File

@@ -14,33 +14,13 @@ limitations under the License.
==============================================================================*/
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/c/c_api_types.h"
#ifdef TF_LITE_TENSORFLOW_PROFILER
#include <string>
#include "tensorflow/lite/core/macros.h"
#include "tensorflow/lite/tensorflow_profiler_logger.h"
#endif
#ifndef TF_LITE_STATIC_MEMORY
#include <stdlib.h>
#include <string.h>
#endif // TF_LITE_STATIC_MEMORY
#ifdef TF_LITE_TENSORFLOW_PROFILER
namespace tflite {
// Use weak symbols here (even though they are guarded by macros) to avoid
// build breakage when building a benchmark requires TFLite runs. The main
// benchmark library should have tensor_profiler_logger dependency.
TFLITE_ATTRIBUTE_WEAK void OnTfLiteTensorAlloc(TfLiteTensor* tensor,
size_t num_bytes);
TFLITE_ATTRIBUTE_WEAK void OnTfLiteTensorDealloc(TfLiteTensor* tensor);
} // namespace tflite
#endif // TF_LITE_TENSORFLOW_PROFILER
extern "C" {
size_t TfLiteIntArrayGetSizeInBytes(int size) {
@@ -119,12 +99,7 @@ void TfLiteFloatArrayFree(TfLiteFloatArray* a) { free(a); }
void TfLiteTensorDataFree(TfLiteTensor* t) {
if (t->allocation_type == kTfLiteDynamic ||
t->allocation_type == kTfLitePersistentRo) {
if (t->data.raw) {
#ifdef TF_LITE_TENSORFLOW_PROFILER
tflite::OnTfLiteTensorDealloc(t);
#endif
free(t->data.raw);
}
free(t->data.raw);
}
t->data.raw = nullptr;
}
@@ -186,7 +161,7 @@ void TfLiteTensorFree(TfLiteTensor* t) {
t->dims = nullptr;
if (t->dims_signature) {
TfLiteIntArrayFree((TfLiteIntArray*)t->dims_signature);
TfLiteIntArrayFree((TfLiteIntArray *) t->dims_signature);
}
t->dims_signature = nullptr;
@@ -216,12 +191,16 @@ void TfLiteTensorReset(TfLiteType type, const char* name, TfLiteIntArray* dims,
}
TfLiteStatus TfLiteTensorCopy(const TfLiteTensor* src, TfLiteTensor* dst) {
if (!src || !dst) return kTfLiteOk;
if (src->bytes != dst->bytes) return kTfLiteError;
if (src == dst) return kTfLiteOk;
if (!src || !dst)
return kTfLiteOk;
if (src->bytes != dst->bytes)
return kTfLiteError;
if (src == dst)
return kTfLiteOk;
dst->type = src->type;
if (dst->dims) TfLiteIntArrayFree(dst->dims);
if (dst->dims)
TfLiteIntArrayFree(dst->dims);
dst->dims = TfLiteIntArrayCopy(src->dims);
memcpy(dst->data.raw, src->data.raw, src->bytes);
dst->buffer_handle = src->buffer_handle;
@@ -239,17 +218,8 @@ void TfLiteTensorRealloc(size_t num_bytes, TfLiteTensor* tensor) {
// TODO(b/145340303): Tensor data should be aligned.
if (!tensor->data.raw) {
tensor->data.raw = (char*)malloc(num_bytes);
#ifdef TF_LITE_TENSORFLOW_PROFILER
tflite::OnTfLiteTensorAlloc(tensor, num_bytes);
#endif
} else if (num_bytes > tensor->bytes) {
#ifdef TF_LITE_TENSORFLOW_PROFILER
tflite::OnTfLiteTensorDealloc(tensor);
#endif
tensor->data.raw = (char*)realloc(tensor->data.raw, num_bytes);
#ifdef TF_LITE_TENSORFLOW_PROFILER
tflite::OnTfLiteTensorAlloc(tensor, num_bytes);
#endif
}
tensor->bytes = num_bytes;
}

View File

@@ -173,9 +173,9 @@ void TfLiteFloatArrayFree(TfLiteFloatArray* a);
} \
} while (false)
#else // TF_LITE_STRIP_ERROR_STRINGS
#define ARGS_UNUSED(...) (void)sizeof(#__VA_ARGS__)
#define TF_LITE_KERNEL_LOG(context, ...) ARGS_UNUSED(__VA_ARGS__)
#define TF_LITE_MAYBE_KERNEL_LOG(context, ...) ARGS_UNUSED(__VA_ARGS__)
#define UNUSED(...) (void)sizeof(#__VA_ARGS__)
#define TF_LITE_KERNEL_LOG(context, ...) UNUSED(__VA_ARGS__)
#define TF_LITE_MAYBE_KERNEL_LOG(context, ...) UNUSED(__VA_ARGS__)
#endif // TF_LITE_STRIP_ERROR_STRINGS
// Check whether value is true, and if not return kTfLiteError from
@@ -842,32 +842,6 @@ typedef struct TfLiteContext {
size_t* bytes);
} TfLiteContext;
// `TfLiteRegistrationExternal` is an external version of `TfLiteRegistration`
// for C API which doesn't use internal types (such as `TfLiteContext`) but only
// uses stable API types (such as `TfLiteOpaqueContext`). The purpose of each
// field is the exactly the same as with `TfLiteRegistration`.
typedef struct TfLiteRegistrationExternal {
// Custom op name.
const char* custom_name;
// The version of the op. The verion should be higher than 0.
const int version;
// Initializes the op from serialized data.
void* (*init)(TfLiteOpaqueContext* context, const char* buffer,
size_t length);
// The pointer `buffer` is the data previously returned by an init invocation.
void (*free)(TfLiteOpaqueContext* context, void* buffer);
// Called when the inputs that this node depends on have been resized.
TfLiteStatus (*prepare)(TfLiteOpaqueContext* context, TfLiteOpaqueNode* node);
// Called when the node is executed. (should read node->inputs and output to
// node->outputs).
TfLiteStatus (*invoke)(TfLiteOpaqueContext* context, TfLiteOpaqueNode* node);
} TfLiteRegistrationExternal;
typedef struct TfLiteRegistration {
// Initializes the op from serialized data.
// Called only *once* for the lifetime of the op, so any one-time allocations
@@ -929,31 +903,8 @@ typedef struct TfLiteRegistration {
// Note: It is the responsibility of the registration binder to set this
// properly.
int version;
// The external version of `TfLiteRegistration`. Since we can't use internal
// types (such as `TfLiteContext`) for C API to maintain ABI stability.
// C API user will provide `TfLiteRegistrationExternal` to implement custom
// ops. We keep it inside of `TfLiteRegistration` and use it to route
// callbacks properly.
TfLiteRegistrationExternal* registration_external;
} TfLiteRegistration;
// Old version of `TfLiteRegistration` to maintain binary backward
// compatibility.
// WARNING: This structure is deprecated / not an official part of the API.
// It should be only used for binary backward compatibility.
typedef struct TfLiteRegistration_V1 {
void* (*init)(TfLiteContext* context, const char* buffer, size_t length);
void (*free)(TfLiteContext* context, void* buffer);
TfLiteStatus (*prepare)(TfLiteContext* context, TfLiteNode* node);
TfLiteStatus (*invoke)(TfLiteContext* context, TfLiteNode* node);
const char* (*profiling_string)(const TfLiteContext* context,
const TfLiteNode* node);
int32_t builtin_code;
const char* custom_name;
int version;
} TfLiteRegistration_V1;
// The flags used in `TfLiteDelegate`. Note that this is a bitmask, so the
// values should be 1, 2, 4, 8, ...etc.
typedef enum TfLiteDelegateFlags {

View File

@@ -836,16 +836,6 @@ TfLiteStatus ParseOpDataTfLite(const Operator* op, BuiltinOperator op_type,
*builtin_data = params.release();
return kTfLiteOk;
}
case BuiltinOperator_UNSORTED_SEGMENT_PROD: {
auto params = safe_allocator.Allocate<TfLiteUnsortedSegmentProdParams>();
TF_LITE_ENSURE(error_reporter, params != nullptr);
if (const auto* unsorted_segment_prod_params =
op->builtin_options_as_UnsortedSegmentProdOptions()) {
params->num_segments = unsorted_segment_prod_params->num_segments();
}
*builtin_data = params.release();
return kTfLiteOk;
}
// Below are the ops with no builtin_data structure.
// TODO(aselle): Implement call in BuiltinOptions, but nullptrs are
// ok for now, since there is no call implementation either.
@@ -858,7 +848,6 @@ TfLiteStatus ParseOpDataTfLite(const Operator* op, BuiltinOperator op_type,
case BuiltinOperator_MATRIX_DIAG:
case BuiltinOperator_MATRIX_SET_DIAG:
case BuiltinOperator_RELU_N1_TO_1:
case BuiltinOperator_RELU_0_TO_1:
case BuiltinOperator_SELECT:
case BuiltinOperator_SELECT_V2:
case BuiltinOperator_SLICE:

View File

@@ -23,16 +23,6 @@ limitations under the License.
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/schema/schema_generated.h"
// Opaque type similar to TfLiteDelegate / TfLiteOpaqueDelegate.
// This is used for cases (e.g. when using "TF Lite with Google Play Services")
// where the TF Lite runtime might be built using a newer (or older)
// version of the TF Lite sources than the app, and hence might have a
// different definition of the TfLiteDelegate type. TF Lite APIs use
// TfLiteOpaqueDelegate rather than TfLiteDelegate when they want to
// refer to a delegate defined with that potentially different version
// of the TfLiteDelegate type.
struct TfLiteOpaqueDelegateStruct;
namespace tflite {
/// Abstract interface that returns TfLiteRegistrations given op codes or custom
@@ -47,10 +37,8 @@ class OpResolver {
virtual const TfLiteRegistration* FindOp(const char* op,
int version) const = 0;
// Represents a sequence of delegates.
using TfLiteDelegatePtrVector =
std::vector<std::unique_ptr<TfLiteDelegate, void (*)(TfLiteDelegate*)>>;
// Returns optional delegates for resolving and handling ops in the flatbuffer
// model. This may be used in addition to the standard TfLiteRegistration
// lookup for graph resolution.
@@ -59,55 +47,16 @@ class OpResolver {
return {};
}
// Represents a function that creates a TfLite delegate instance.
// Represent a function that creates a TfLite delegate instance.
using TfLiteDelegateCreator =
std::function<std::unique_ptr<TfLiteDelegate, void (*)(TfLiteDelegate*)>(
int /*num_threads*/)>;
// Represents a sequence of delegate creator functions.
using TfLiteDelegateCreators = std::vector<TfLiteDelegateCreator>;
// Returns a vector of delegate creators to create optional delegates for
// resolving and handling ops in the flatbuffer model. This may be used in
// addition to the standard TfLiteRegistration lookup for graph resolution.
//
// Note that this method is not used (will not be called) if you are using
// TF Lite in Google Play Services; the GetOpaqueDelegateCreators method
// (see below) is used for that case.
virtual TfLiteDelegateCreators GetDelegateCreators() const { return {}; }
// TODO(b/202712825): it would be nice if we could avoid the need for separate
// "opaque" types & methods for use only with TF Lite in Google Play Services.
// Represents an opaque delegate instance.
// WARNING: Experimental interface, subject to change.
using TfLiteOpaqueDelegatePtr =
std::unique_ptr<TfLiteOpaqueDelegateStruct,
void (*)(TfLiteOpaqueDelegateStruct*)>;
// Represents a function that creates an opaque delegate instance.
// WARNING: Experimental interface, subject to change.
using TfLiteOpaqueDelegateCreator =
std::function<TfLiteOpaqueDelegatePtr(int /*num_threads*/)>;
// Represents a sequence of opaque delegate creator functions.
// WARNING: Experimental interface, subject to change.
using TfLiteOpaqueDelegateCreators = std::vector<TfLiteOpaqueDelegateCreator>;
// Returns a vector of opaque delegate creators to create optional opaque
// delegates for resolving and handling ops in the flatbuffer model. This may
// be used in addition to the standard TfLiteRegistration lookup for graph
// resolution.
//
// Note that this method will be called only if you are using TF Lite in
// Google Play Services; if you are using regular TF Lite, GetDelegateCreators
// (see above) is used instead.
//
// WARNING: Experimental interface, subject to change.
virtual TfLiteOpaqueDelegateCreators GetOpaqueDelegateCreators() const {
return {};
}
virtual ~OpResolver() {}
private:

View File

@@ -23,9 +23,9 @@ namespace tflite {
namespace reference_ops {
inline int16_t SaturatingLeftShift(int16_t value, int amount) {
int64_t result = static_cast<int64_t>(value) * (1 << amount);
result = std::min<int64_t>(result, std::numeric_limits<int16_t>::max());
result = std::max<int64_t>(result, std::numeric_limits<int16_t>::min());
int32_t result = static_cast<int32_t>(value) * (1 << amount);
result = std::min<int32_t>(result, std::numeric_limits<int16_t>::max());
result = std::max<int32_t>(result, std::numeric_limits<int16_t>::min());
return result;
}

View File

@@ -27,11 +27,6 @@ class RuntimeShape {
public:
RuntimeShape& operator=(RuntimeShape const&) = delete;
// RuntimeShape in TFLM supports up to 5 dimensions.
// The name kMaxSmallSize comes from the same file of the upstream
// tensorflow lite repo and need to be kept the same for max reuse.
static constexpr int kMaxSmallSize = 5;
RuntimeShape() : size_(0) {}
explicit RuntimeShape(int dimensions_count) : size_(dimensions_count) {}
@@ -109,9 +104,11 @@ class RuntimeShape {
sizeof(int32_t) * shape.DimensionsCount());
}
// A maximum of 4 dimensions are supported on TFLM.
static constexpr int kMaxSize = 5;
int32_t size_;
union {
int32_t dims_[kMaxSmallSize];
int32_t dims_[kMaxSize];
};
};

View File

@@ -974,11 +974,11 @@ struct StridedSliceParams {
int8_t strides_count;
int32_t strides[5];
uint16_t begin_mask;
uint16_t ellipsis_mask;
uint16_t end_mask;
uint16_t new_axis_mask;
uint16_t shrink_axis_mask;
int16_t begin_mask;
int16_t ellipsis_mask;
int16_t end_mask;
int16_t new_axis_mask;
int16_t shrink_axis_mask;
};
struct TanhParams {

View File

@@ -308,7 +308,7 @@ TfLiteStatus CalculateShapeForBroadcast(TfLiteContext* context,
const TfLiteTensor* input3,
TfLiteIntArray** output_shape);
// Return the size of given type in bytes. Return 0 in case of string.
// Return the size of given type in bytes. Return 0 in in case of string.
int TfLiteTypeGetSize(TfLiteType type);
// Whether the current platform is mobile (Android or iOS).

View File

@@ -1,165 +0,0 @@
/* 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/micro/arena_allocator/non_persistent_arena_buffer_allocator.h"
#include "tensorflow/lite/micro/memory_helpers.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
NonPersistentArenaBufferAllocator::NonPersistentArenaBufferAllocator(
uint8_t* buffer, size_t buffer_size)
: buffer_head_(buffer),
buffer_tail_(buffer + buffer_size),
head_temp_(buffer),
next_temp_(buffer) {}
NonPersistentArenaBufferAllocator::~NonPersistentArenaBufferAllocator() {}
// Allocates a temporary buffer. This buffer is not resizable.
uint8_t* NonPersistentArenaBufferAllocator::AllocateTemp(size_t size,
size_t alignment) {
uint8_t* const aligned_result = AlignPointerUp(next_temp_, alignment);
const size_t available_memory = buffer_tail_ - aligned_result;
if (available_memory < size) {
MicroPrintf(
"Failed to allocate temp memory. Requested: %u, "
"available %u, missing: %u",
size, available_memory, size - available_memory);
return nullptr;
}
next_temp_ = aligned_result + size;
temp_buffer_ptr_check_sum_ ^= reinterpret_cast<intptr_t>(aligned_result);
temp_buffer_count_++;
return aligned_result;
}
// Signals that a temporary buffer is no longer needed.
void NonPersistentArenaBufferAllocator::DeallocateTemp(uint8_t* temp_buf) {
temp_buffer_ptr_check_sum_ ^= reinterpret_cast<intptr_t>(temp_buf);
temp_buffer_count_--;
}
// Returns true if all temporary buffers are already deallocated.
bool NonPersistentArenaBufferAllocator::IsAllTempDeallocated() {
if (temp_buffer_count_ != 0 || temp_buffer_ptr_check_sum_ != 0) {
MicroPrintf(
"Number of allocated temp buffers: %d. Checksum passing status: %d",
temp_buffer_count_, !temp_buffer_ptr_check_sum_);
return false;
}
return true;
}
// Signals that all temporary allocations can be reclaimed. TFLM calls this
// API when it knows that all temporary buffers that it requested has been
// deallocated. The goal of API is to facilitate implementations of
// INonPersistentBufferAllocator can reuse buffer with some reasonable
// complexity.
TfLiteStatus NonPersistentArenaBufferAllocator::ResetTempAllocations() {
if (!IsAllTempDeallocated()) {
MicroPrintf(
"All temp buffers must be freed before calling ResetTempAllocations()");
return kTfLiteError;
}
next_temp_ = head_temp_;
return kTfLiteOk;
}
// Returns a buffer that is resizable viable ResizeBuffer().
uint8_t* NonPersistentArenaBufferAllocator::AllocateResizableBuffer(
size_t size, size_t alignment) {
// Only supports one resizable buffer, which starts at the buffer head.
uint8_t* expected_resizable_buf = AlignPointerUp(buffer_head_, alignment);
if (head_temp_ != expected_resizable_buf) {
MicroPrintf(
"Cannot allocate a new resizable buffer when one is already allocated");
return nullptr;
}
if (ResizeBuffer(expected_resizable_buf, size, alignment) == kTfLiteOk) {
return expected_resizable_buf;
}
return nullptr;
}
// Resizes a buffer that is previously returned by the AllocateResizableBuffer.
// Note that ResizeBuffer(old_resizable_buf, 0, 1) effectively deallocates
// a previous allocated resizable buffer.
TfLiteStatus NonPersistentArenaBufferAllocator::ResizeBuffer(
uint8_t* resizable_buf, size_t size, size_t alignment) {
// Only supports one resizable buffer, which starts at the buffer head.
uint8_t* expect_resizable_buf = AlignPointerUp(buffer_head_, alignment);
if (resizable_buf != expect_resizable_buf) {
MicroPrintf("Internal error: buffer is not resizable");
return kTfLiteError;
}
if (head_temp_ != next_temp_) {
MicroPrintf("ResetTempAllocations() is not called before ResizeBuffer().");
return kTfLiteError;
}
const size_t available_memory = buffer_tail_ - expect_resizable_buf;
if (available_memory < size) {
MicroPrintf(
"Failed to resize buffer. Requested: %u, available %u, missing: %u",
size, available_memory, size - available_memory);
return kTfLiteError;
}
head_temp_ = expect_resizable_buf + size;
next_temp_ = head_temp_;
return kTfLiteOk;
}
// Frees up the memory occupied by the resizable buffer.
TfLiteStatus NonPersistentArenaBufferAllocator::DeallocateResizableBuffer(
uint8_t* resizable_buf) {
return ResizeBuffer(resizable_buf, 0, 1);
}
// Returns a pointer pointing to the start of the overlay memory, which is
// used for activation tensors and scratch buffers by kernels at Invoke stage.
uint8_t* NonPersistentArenaBufferAllocator::GetOverlayMemoryAddress() const {
return buffer_head_;
}
// Reserves the size of the overlay memory. This overlay is reserved for the
// kernels at Invoke stage. This is referred to as the overlay because before
// Invoket state, the same memory can be used for temp buffers. The layout of
// the memory is planned by the memory planner separately at Invoke stage.
TfLiteStatus
NonPersistentArenaBufferAllocator::ReserveNonPersistentOverlayMemory(
size_t size, size_t alignment) {
uint8_t* expect_resizable_buf = AlignPointerUp(buffer_head_, alignment);
return ResizeBuffer(expect_resizable_buf, size, alignment);
}
// Returns the size of non-persistent buffer in use.
size_t NonPersistentArenaBufferAllocator::GetNonPersistentUsedBytes() const {
return (next_temp_ - buffer_head_);
}
// Returns the number of bytes available with a given alignment. This number
// takes in account any temporary allocations.
size_t NonPersistentArenaBufferAllocator::GetAvailableMemory(
size_t alignment) const {
uint8_t* const aligned_temp = AlignPointerUp(next_temp_, alignment);
uint8_t* const aligned_tail = AlignPointerDown(buffer_tail_, alignment);
return aligned_tail - aligned_temp;
}
} // namespace tflite

View File

@@ -1,104 +0,0 @@
/* 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_MICRO_ARENA_ALLOCATOR_NON_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_
#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_NON_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_
#include <cstddef>
#include <cstdint>
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h"
#include "tensorflow/lite/micro/compatibility.h"
namespace tflite {
// Implement INonPersistentBufferAllocator on an arena that is dedicated for
// non-persistent buffers.
class NonPersistentArenaBufferAllocator : public INonPersistentBufferAllocator {
public:
NonPersistentArenaBufferAllocator(uint8_t* buffer, size_t buffer_size);
virtual ~NonPersistentArenaBufferAllocator();
// Allocates a temporary buffer. This buffer is not resizable.
uint8_t* AllocateTemp(size_t size, size_t alignment) override;
// Signals that a temporary buffer is no longer needed.
void DeallocateTemp(uint8_t* buf) override;
// Returns true if all temporary buffers are already deallocated.
bool IsAllTempDeallocated() override;
// Signals that all temporary allocations can be reclaimed. TFLM calls this
// API when it knows that all temporary buffers that it requested has been
// deallocated.
TfLiteStatus ResetTempAllocations() override;
// Returns a buffer that is resizable viable ResizeBuffer().
uint8_t* AllocateResizableBuffer(size_t size, size_t alignment) override;
// Resizes a buffer that is previously returned by the
// AllocateResizableBuffer.
TfLiteStatus ResizeBuffer(uint8_t* resizable_buf, size_t size,
size_t alignment) override;
// Frees up the memory occupied by the resizable buffer.
TfLiteStatus DeallocateResizableBuffer(uint8_t* resizable_buf) override;
// Returns a pointer pointing to the start of the overlay memory, which is
// used for activation tensors and scratch buffers by kernels at Invoke stage.
uint8_t* GetOverlayMemoryAddress() const override;
// Reserves the size of the overlay memory. This overlay is reserved for the
// kernels at Invoke stage. This is referred to as the overlay because before
// Invoket state, the same memory can be used for temp buffers. The layout of
// the memory is planned by the memory planner separately at Invoke stage.
TfLiteStatus ReserveNonPersistentOverlayMemory(size_t size,
size_t alignment) override;
// Returns the size of non-persistent buffer in use.
size_t GetNonPersistentUsedBytes() const override;
// Returns the number of bytes available with a given alignment. This number
// takes in account any temporary allocations.
size_t GetAvailableMemory(size_t alignment) const override;
TF_LITE_REMOVE_VIRTUAL_DELETE
private:
// The memory arena that this allocator manages.
uint8_t* const buffer_head_;
uint8_t* const buffer_tail_;
// The whole region is split into two parts:
// buffer_head_ to head_temp_ - 1 belongs to the only resizable buffer.
// head_temp_ to buffer_tail_ can be used for (non-resizable) temp buffers.
uint8_t* head_temp_;
// next_temp_ points to the next available temp buffer allocation address and
// its range is between head_temp_ and buffer_tail_
uint8_t* next_temp_;
// XOR Check sum for outstanding temp buffers.
// If all temp buffers are deallocated OR no temp buffers are allocated,
// temp_buffer_ptr_check_sum_ == nullptr.
intptr_t temp_buffer_ptr_check_sum_ = 0;
// Count of outstanding temp buffers.
int temp_buffer_count_ = 0;
};
} // namespace tflite
#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_NON_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_

View File

@@ -1,52 +0,0 @@
/* 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/micro/arena_allocator/persistent_arena_buffer_allocator.h"
#include "tensorflow/lite/micro/memory_helpers.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
PersistentArenaBufferAllocator::PersistentArenaBufferAllocator(
uint8_t* buffer, size_t buffer_size)
: buffer_head_(buffer),
buffer_tail_(buffer + buffer_size),
tail_temp_(buffer_tail_) {}
PersistentArenaBufferAllocator::~PersistentArenaBufferAllocator() {}
uint8_t* PersistentArenaBufferAllocator::AllocatePersistentBuffer(
size_t size, size_t alignment) {
uint8_t* const aligned_result =
AlignPointerDown(tail_temp_ - size, alignment);
if (aligned_result < buffer_head_) {
#ifndef TF_LITE_STRIP_ERROR_STRINGS
const size_t missing_memory = buffer_head_ - aligned_result;
MicroPrintf(
"Failed to allocate tail memory. Requested: %u, "
"available %u, missing: %u",
size, size - missing_memory, missing_memory);
#endif
return nullptr;
}
tail_temp_ = aligned_result;
return aligned_result;
}
size_t PersistentArenaBufferAllocator::GetPersistentUsedBytes() const {
return buffer_tail_ - tail_temp_;
}
} // namespace tflite

View File

@@ -1,59 +0,0 @@
/* 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_MICRO_ARENA_ALLOCATOR_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_
#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_
#include <cstddef>
#include <cstdint>
#include "tensorflow/lite/c/common.h"
#include "tensorflow/lite/core/api/error_reporter.h"
#include "tensorflow/lite/micro/arena_allocator/ibuffer_allocator.h"
#include "tensorflow/lite/micro/compatibility.h"
namespace tflite {
// PersistentArenaBufferAllocator is an implementatation of
// IPersistentBufferAllocator interface on an arena that is dedicated for
// persistent buffers.
class PersistentArenaBufferAllocator : public IPersistentBufferAllocator {
public:
PersistentArenaBufferAllocator(uint8_t* buffer, size_t buffer_size);
virtual ~PersistentArenaBufferAllocator();
// Allocates persistent memory. The persistent buffer is never freed.
// Returns nullptr if errors occured.
uint8_t* AllocatePersistentBuffer(size_t size, size_t alignment) override;
// Returns the size of all persistent allocations in bytes.
size_t GetPersistentUsedBytes() const override;
TF_LITE_REMOVE_VIRTUAL_DELETE
private:
// The memory arena that this allocator manages.
uint8_t* const buffer_head_;
uint8_t* const buffer_tail_;
// The whole region is split into two parts:
// tail_temp_ to buffer_tail_ contains allocated buffers;
// buffer_head_ to tail_temp_ - 1 belongs to still available spaces.
// So in essence, the allocated region grows from the bottom and emulates
// SimpleMemoryAllocator's persistent part.
uint8_t* tail_temp_;
};
} // namespace tflite
#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_PERSISTENT_ARENA_BUFFER_ALLOCATOR_H_

View File

@@ -16,10 +16,10 @@ limitations under the License.
#include "tensorflow/lite/micro/fake_micro_context.h"
#include "tensorflow/lite/kernels/internal/compatibility.h"
#include "tensorflow/lite/micro/arena_allocator/simple_memory_allocator.h"
#include "tensorflow/lite/micro/micro_allocator.h"
#include "tensorflow/lite/micro/micro_arena_constants.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
#include "tensorflow/lite/micro/simple_memory_allocator.h"
namespace tflite {
namespace {

View File

@@ -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_MICRO_ARENA_ALLOCATOR_IBUFFER_ALLOCATOR_H_
#define TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_IBUFFER_ALLOCATOR_H_
#ifndef TENSORFLOW_LITE_MICRO_IBUFFER_ALLOCATOR_H_
#define TENSORFLOW_LITE_MICRO_IBUFFER_ALLOCATOR_H_
#include <cstddef>
#include <cstdint>
@@ -97,4 +97,4 @@ class INonPersistentBufferAllocator {
} // namespace tflite
#endif // TENSORFLOW_LITE_MICRO_ARENA_ALLOCATOR_IBUFFER_ALLOCATOR_H_
#endif // TENSORFLOW_LITE_MICRO_IBUFFER_ALLOCATOR_H_

View File

@@ -24,7 +24,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"
#include "tensorflow/lite/micro/micro_utils.h"
namespace tflite {
@@ -61,8 +60,8 @@ TfLiteStatus ReluEval(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
}
default: {
MicroPrintf("Only float32 is supported currently, got %s",
TfLiteTypeGetName(input->type));
TF_LITE_KERNEL_LOG(context, "Only float32 is supported currently, got %s",
TfLiteTypeGetName(input->type));
return kTfLiteError;
}
}
@@ -100,8 +99,8 @@ TfLiteStatus Relu6Eval(TfLiteContext* context, TfLiteNode* node) {
return kTfLiteOk;
}
default: {
MicroPrintf("Only float32 is supported currently, got %s",
TfLiteTypeGetName(input->type));
TF_LITE_KERNEL_LOG(context, "Only float32 is supported currently, got %s",
TfLiteTypeGetName(input->type));
return kTfLiteError;
}
}
@@ -110,11 +109,25 @@ TfLiteStatus Relu6Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_RELU() {
return tflite::micro::RegisterOp(ReluInit, ReluPrepare, ReluEval);
return {/*init=*/ReluInit,
/*free=*/nullptr,
/*prepare=*/ReluPrepare,
/*invoke=*/ReluEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
TfLiteRegistration Register_RELU6() {
return tflite::micro::RegisterOp(Relu6Init, Relu6Prepare, Relu6Eval);
return {/*init=*/Relu6Init,
/*free=*/nullptr,
/*prepare=*/Relu6Prepare,
/*invoke=*/Relu6Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -159,7 +159,14 @@ TfLiteStatus AddEval(TfLiteContext* context, TfLiteNode* node) {
}
TfLiteRegistration Register_ADD() {
return tflite::micro::RegisterOp(AddInit, AddPrepare, AddEval);
return {/*init=*/AddInit,
/*free=*/nullptr,
/*prepare=*/AddPrepare,
/*invoke=*/AddEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -208,7 +208,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_ADD_N() {
return tflite::micro::RegisterOp(nullptr, Prepare, Eval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/Prepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -104,11 +104,25 @@ TfLiteStatus ArgMaxEval(TfLiteContext* context, TfLiteNode* node) {
} // namespace arg_min_max
TfLiteRegistration Register_ARG_MAX() {
return tflite::micro::RegisterOp(nullptr, nullptr, arg_min_max::ArgMaxEval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/nullptr,
/*invoke=*/arg_min_max::ArgMaxEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
TfLiteRegistration Register_ARG_MIN() {
return tflite::micro::RegisterOp(nullptr, nullptr, arg_min_max::ArgMinEval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/nullptr,
/*invoke=*/arg_min_max::ArgMinEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace micro

View File

@@ -95,7 +95,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace.
TfLiteRegistration Register_ASSIGN_VARIABLE() {
return tflite::micro::RegisterOp(nullptr, Prepare, Eval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/Prepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -105,7 +105,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace.
TfLiteRegistration Register_BATCH_TO_SPACE_ND() {
return tflite::micro::RegisterOp(nullptr, Prepare, Eval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/Prepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -84,8 +84,14 @@ TfLiteStatus BroadcastArgsEval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_BROADCAST_ARGS() {
return tflite::micro::RegisterOp(nullptr, BroadcastArgsPrepare,
BroadcastArgsEval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/BroadcastArgsPrepare,
/*invoke=*/BroadcastArgsEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite
} // namespace tflite

View File

@@ -116,8 +116,14 @@ TfLiteStatus BroadcastToEval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_BROADCAST_TO() {
return tflite::micro::RegisterOp(nullptr, BroadcastToPrepare,
BroadcastToEval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/BroadcastToPrepare,
/*invoke=*/BroadcastToEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite
} // namespace tflite

View File

@@ -82,7 +82,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace.
TfLiteRegistration Register_CALL_ONCE() {
return tflite::micro::RegisterOp(Init, Prepare, Eval);
return {/*init=*/Init,
/*free=*/nullptr,
/*prepare=*/Prepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -108,7 +108,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_CAST() {
return tflite::micro::RegisterOp(nullptr, Prepare, Eval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/Prepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -67,7 +67,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace ceil
TfLiteRegistration Register_CEIL() {
return tflite::micro::RegisterOp(nullptr, ceil::Prepare, ceil::Eval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/ceil::Prepare,
/*invoke=*/ceil::Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace micro

View File

@@ -108,7 +108,14 @@ TfLiteStatus CircularBufferEval(TfLiteContext* context, TfLiteNode* node) {
}
TfLiteRegistration* Register_CIRCULAR_BUFFER() {
static TfLiteRegistration r = tflite::micro::RegisterOp(CircularBufferInit, CircularBufferPrepare, CircularBufferEval);
static TfLiteRegistration r = {/*init=*/CircularBufferInit,
/*free=*/nullptr,
/*prepare=*/CircularBufferPrepare,
/*invoke=*/CircularBufferEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
return &r;
}

View File

@@ -583,33 +583,69 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
} // namespace comparisons
TfLiteRegistration Register_EQUAL() {
return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare,
comparisons::EqualEval);
return {/*init=*/comparisons::Init,
/*free=*/nullptr,
/*prepare=*/comparisons::Prepare,
/*invoke=*/comparisons::EqualEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
TfLiteRegistration Register_NOT_EQUAL() {
return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare,
comparisons::NotEqualEval);
return {/*init=*/comparisons::Init,
/*free=*/nullptr,
/*prepare=*/comparisons::Prepare,
/*invoke=*/comparisons::NotEqualEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
TfLiteRegistration Register_GREATER() {
return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare,
comparisons::GreaterEval);
return {/*init=*/comparisons::Init,
/*free=*/nullptr,
/*prepare=*/comparisons::Prepare,
/*invoke=*/comparisons::GreaterEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
TfLiteRegistration Register_GREATER_EQUAL() {
return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare,
comparisons::GreaterEqualEval);
return {/*init=*/comparisons::Init,
/*free=*/nullptr,
/*prepare=*/comparisons::Prepare,
/*invoke=*/comparisons::GreaterEqualEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
TfLiteRegistration Register_LESS() {
return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare,
comparisons::LessEval);
return {/*init=*/comparisons::Init,
/*free=*/nullptr,
/*prepare=*/comparisons::Prepare,
/*invoke=*/comparisons::LessEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
TfLiteRegistration Register_LESS_EQUAL() {
return tflite::micro::RegisterOp(comparisons::Init, comparisons::Prepare,
comparisons::LessEqualEval);
return {/*init=*/comparisons::Init,
/*free=*/nullptr,
/*prepare=*/comparisons::Prepare,
/*invoke=*/comparisons::LessEqualEval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace micro

View File

@@ -148,12 +148,12 @@ TfLiteStatus Prepare(TfLiteContext* context, TfLiteNode* node) {
TF_LITE_ENSURE(context, input != nullptr);
int num_dimensions = NumDimensions(input);
if (num_dimensions > RuntimeShape::kMaxSmallSize) {
if (num_dimensions > 4) {
TF_LITE_KERNEL_LOG(
context,
"Op Concatenation does not currently support num dimensions > %d "
"Op Concatenation does not currently support num dimensions >4 "
"Tensor has %d dimensions.",
RuntimeShape::kMaxSmallSize, num_dimensions);
num_dimensions);
return kTfLiteError;
}
micro_context->DeallocateTempTfLiteTensor(input);
@@ -252,8 +252,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace concatenation
TfLiteRegistration Register_CONCATENATION() {
return tflite::micro::RegisterOp(concatenation::Init, concatenation::Prepare,
concatenation::Eval);
return {/*init=*/concatenation::Init,
/*free=*/nullptr,
/*prepare=*/concatenation::Prepare,
/*invoke=*/concatenation::Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace micro

View File

@@ -25,7 +25,6 @@ limitations under the License.
#include "tensorflow/lite/kernels/kernel_util.h"
#include "tensorflow/lite/kernels/padding.h"
#include "tensorflow/lite/micro/kernels/kernel_util.h"
#include "tensorflow/lite/micro/micro_error_reporter.h"
namespace tflite {
namespace {
@@ -68,47 +67,23 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorShape(filter),
tflite::micro::GetTensorData<float>(filter),
tflite::micro::GetTensorShape(bias),
tflite::micro::GetOptionalTensorData<float>(bias),
tflite::micro::GetTensorData<float>(bias),
tflite::micro::GetTensorShape(output),
tflite::micro::GetTensorData<float>(output),
tflite::micro::GetTensorShape(nullptr), nullptr);
break;
}
case kTfLiteInt16: {
switch (bias->type) {
case kTfLiteInt32: {
reference_integer_ops::ConvPerChannel(
ConvParamsQuantized(params, data),
data.per_channel_output_multiplier, data.per_channel_output_shift,
tflite::micro::GetTensorShape(input),
tflite::micro::GetTensorData<int16_t>(input),
tflite::micro::GetTensorShape(filter),
tflite::micro::GetTensorData<int8_t>(filter),
tflite::micro::GetTensorShape(bias),
tflite::micro::GetOptionalTensorData<std::int32_t>(bias),
tflite::micro::GetTensorShape(output),
tflite::micro::GetTensorData<int16_t>(output));
break;
}
case kTfLiteInt64: {
reference_integer_ops::ConvPerChannel(
ConvParamsQuantized(params, data),
data.per_channel_output_multiplier, data.per_channel_output_shift,
tflite::micro::GetTensorShape(input),
tflite::micro::GetTensorData<int16_t>(input),
tflite::micro::GetTensorShape(filter),
tflite::micro::GetTensorData<int8_t>(filter),
tflite::micro::GetTensorShape(bias),
tflite::micro::GetOptionalTensorData<std::int64_t>(bias),
tflite::micro::GetTensorShape(output),
tflite::micro::GetTensorData<int16_t>(output));
break;
}
default:
MicroPrintf("Bias type %s (%d) not supported.",
TfLiteTypeGetName(bias->type), bias->type);
return kTfLiteError;
}
reference_integer_ops::ConvPerChannel(
ConvParamsQuantized(params, data), data.per_channel_output_multiplier,
data.per_channel_output_shift, tflite::micro::GetTensorShape(input),
tflite::micro::GetTensorData<int16_t>(input),
tflite::micro::GetTensorShape(filter),
tflite::micro::GetTensorData<int8_t>(filter),
tflite::micro::GetTensorShape(bias),
tflite::micro::GetTensorData<std::int64_t>(bias),
tflite::micro::GetTensorShape(output),
tflite::micro::GetTensorData<int16_t>(output));
break;
}
case kTfLiteInt8: {
@@ -119,14 +94,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
tflite::micro::GetTensorShape(filter),
tflite::micro::GetTensorData<int8_t>(filter),
tflite::micro::GetTensorShape(bias),
tflite::micro::GetOptionalTensorData<int32_t>(bias),
tflite::micro::GetTensorData<int32_t>(bias),
tflite::micro::GetTensorShape(output),
tflite::micro::GetTensorData<int8_t>(output));
break;
}
default:
MicroPrintf("Type %s (%d) not supported.", TfLiteTypeGetName(input->type),
input->type);
TF_LITE_KERNEL_LOG(context, "Type %s (%d) not supported.",
TfLiteTypeGetName(input->type), input->type);
return kTfLiteError;
}
return kTfLiteOk;
@@ -135,7 +110,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_CONV_2D() {
return tflite::micro::RegisterOp(Init, ConvPrepare, Eval);
return {/*init=*/Init,
/*free=*/nullptr,
/*prepare=*/ConvPrepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -97,16 +97,6 @@ TfLiteStatus TestConvQuantizedPerChannel(
float output_scale, int output_zero_point, TfLiteConvParams* conv_params,
TfLiteRegistration registration, int16_t* output_data);
TfLiteStatus TestConvQuantizedPerChannel(
int* input_dims_data, const float* input_data, int16_t* input_quantized,
float input_scale, int input_zero_point, int* filter_dims_data,
const float* filter_data, int8_t* filter_data_quantized,
int* bias_dims_data, const float* bias_data, int32_t* bias_data_quantized,
float* bias_scales, int* bias_zero_points, int* output_dims_data,
const float* expected_output_data, int16_t* expected_output_data_quantized,
float output_scale, int output_zero_point, TfLiteConvParams* conv_params,
TfLiteRegistration registration, int16_t* output_data);
} // namespace testing
} // namespace tflite

View File

@@ -169,7 +169,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_CUMSUM() {
return tflite::micro::RegisterOp(nullptr, Prepare, Eval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/Prepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

View File

@@ -136,7 +136,14 @@ TfLiteStatus Eval(TfLiteContext* context, TfLiteNode* node) {
} // namespace
TfLiteRegistration Register_DEPTH_TO_SPACE() {
return tflite::micro::RegisterOp(nullptr, Prepare, Eval);
return {/*init=*/nullptr,
/*free=*/nullptr,
/*prepare=*/Prepare,
/*invoke=*/Eval,
/*profiling_string=*/nullptr,
/*builtin_code=*/0,
/*custom_name=*/nullptr,
/*version=*/0};
}
} // namespace tflite

Some files were not shown because too many files have changed in this diff Show More