diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
new file mode 100644
index 00000000..f9f7216a
--- /dev/null
+++ b/.github/workflows/build.yaml
@@ -0,0 +1,106 @@
+name: Build and Pack
+
+on: [push]
+
+jobs:
+ build:
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Cache PlatformIO
+ uses: actions/cache@v2
+ with:
+ path: ~/.platformio
+ key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
+
+ - name: Set up Python
+ uses: actions/setup-python@v2
+ - name: Install PlatformIO
+ run: |
+ python -m pip install --upgrade pip
+ pip install --upgrade platformio
+
+ - name: Set Variables
+ id: vars
+ run: |
+ echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
+ echo "::set-output name=date_time::$(git log -1 --format="%at" | xargs -I{} date -d @{} '+%Y-%m-%d %H:%M:%S')"
+ echo "::set-output name=date_time_filename::$(git log -1 --format="%at" | xargs -I{} date -d @{} '+%Y-%m-%d_%H-%M-%S')"
+ #echo "::set-output name=version_string::${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
+ #echo "Version String: ${{ steps.vars.outputs.version_string }}"
+
+
+ - name: Set Version used in HTML Info page
+ run: echo "${{ steps.vars.outputs.date_time }}, ${{ github.ref_name }} (${{ steps.vars.outputs.sha_short }})" > "sd-card/html/version.txt"
+
+
+ - name: Build Firmware
+# run: mkdir -p ./code/.pio/build/esp32cam/; touch ./code/.pio/build/esp32cam/firmware.bin # Testing
+ run: cd code; platformio run --environment esp32cam
+
+
+
+ # Old OTA concept
+ # firmware__*.zip needs to be unpacked before attaching to the release!
+ # The bin filename can contain versioning.
+ - name: Rename firmware file to contain versioning (old ota)
+ run: |
+ mkdir -p ./dist_old_ota
+ cp "./code/.pio/build/esp32cam/firmware.bin" "./dist_old_ota/firmware__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }}).bin"
+ ls -l ./dist_old_ota
+
+ - name: Upload Firmware artifact (old OTA concept)
+ uses: actions/upload-artifact@v3
+ with:
+ name: "firmware__extract_before_upload__only_needed_for_migration_from_11.2.0"
+ path: ./dist_old_ota/*
+
+ - name: Upload Web interface artifact (old OTA concept)
+ uses: actions/upload-artifact@v3
+ with:
+ name: "html__only_needed_for_migration_from_11.2.0__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
+ path: ./sd-card/html/*
+
+
+
+ # New OTA concept
+ # update__version.zip file with following content:
+ # - /firmware.bin
+ # - (optional) /html/*
+ # - (optional) /config/*.tfl
+ - name: Prepare update.zip artifact
+ run: |
+ mkdir -p ./dist
+ cp "./code/.pio/build/esp32cam/firmware.bin" "dist/firmware.bin"
+
+ - name: Upload update.zip Artifact (Firmware only)
+ uses: actions/upload-artifact@v3
+ with:
+ name: "update_firmware_only__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
+ path: ./dist/*
+
+
+ - name: Prepare update.zip artifact (Firmware + Web UI)
+ run: cp -r ./sd-card/html ./dist/
+
+ - name: Upload update.zip artifact (Firmware + Web UI)
+ uses: actions/upload-artifact@v3
+ with:
+ name: "update_firmware+web_ui__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
+ path: ./dist/*
+
+
+ - name: Prepare update.zip artifact (Firmware + Web UI + CNN)
+ run: |
+ mkdir ./dist/config/
+ cp ./sd-card/config/*.tfl ./dist/config/ 2>/dev/null || true
+ cp ./sd-card/config/*.tflite ./dist/config/ 2>/dev/null || true
+
+ - name: Upload update.zip artifact (Firmware + Web UI + CNN)
+ uses: actions/upload-artifact@v3
+ with:
+ name: "update_firmware+web_ui+cnn__${{ steps.vars.outputs.date_time_filename }}__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
+ path: ./dist/*
diff --git a/FeatureRequest.md b/FeatureRequest.md
index c862a4de..8f6cddd7 100644
--- a/FeatureRequest.md
+++ b/FeatureRequest.md
@@ -66,6 +66,8 @@ ____
* Let the device be normally in deep sleep state, and wake it up periodically to collect data and push it via MQTT or HTTP post.
* Support ESP-NOW to reduce the overhead of connecting to wifi and mqtt
* the above should enable battery powered applications
+
+* An other way to set deep sleep would be to enable it in a specific period (at night).
#### #19 Extended log informations
diff --git a/README.md b/README.md
index abac3df1..2ed672a2 100644
--- a/README.md
+++ b/README.md
@@ -40,11 +40,43 @@ In other cases you can contact the developer via email:
-
+#include "esp_nn_defs.h"
/************************** Basic math functions ****************************/
/**
@@ -81,28 +80,15 @@ 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 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,
+void esp_nn_depthwise_conv_s8_ansi(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
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 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 dw_conv_params_t *conv_params,
+ const quant_data_t *quant_data);
/**
* @brief 2d-convolution channelwise
@@ -112,43 +98,26 @@ void esp_nn_depthwise_conv_s8_ansi(const int8_t *input_data,
* 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 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,
+void esp_nn_conv_s8_ansi(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
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 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 conv_params_t *conv_params,
+ const quant_data_t *quant_data);
-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);
+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);
void esp_nn_set_conv_scratch_buf_ansi(const void *buf);
-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);
+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);
void esp_nn_set_depthwise_conv_scratch_buf_ansi(const void *buf);
/************************** Activation functions *****************************/
@@ -252,9 +221,6 @@ 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
*
@@ -268,6 +234,66 @@ 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
*
diff --git a/code/components/esp-nn/include/esp_nn_defs.h b/code/components/esp-nn/include/esp_nn_defs.h
new file mode 100644
index 00000000..756d8e6f
--- /dev/null
+++ b/code/components/esp-nn/include/esp_nn_defs.h
@@ -0,0 +1,83 @@
+// 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
+
+/**
+ * @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;
diff --git a/code/components/esp-nn/include/esp_nn_esp32s3.h b/code/components/esp-nn/include/esp_nn_esp32s3.h
index 58b544e4..0f52c943 100644
--- a/code/components/esp-nn/include/esp_nn_esp32s3.h
+++ b/code/components/esp-nn/include/esp_nn_esp32s3.h
@@ -19,7 +19,7 @@
#pragma once
-#include
+#include "esp_nn_defs.h"
#include "esp_nn_ansi_headers.h"
/************************** Basic math functions *****************************/
@@ -85,28 +85,15 @@ 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 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,
+void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
const int8_t *filter_data,
- const uint16_t filter_wd,
- const uint16_t filter_ht,
const int32_t *bias,
- 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);
+ const data_dims_t *output_dims,
+ int8_t *output_data,
+ const dw_conv_params_t *conv_params,
+ const quant_data_t *quant_data);
/**
* @brief 2d - convolution channelwise
@@ -116,43 +103,26 @@ void esp_nn_depthwise_conv_s8_esp32s3(const int8_t *input_data,
* 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 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,
+void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
const int8_t *filter_data,
- const uint16_t filter_wd,
- const uint16_t filter_ht,
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);
+ const data_dims_t *output_dims,
+ int8_t *output_data,
+ const conv_params_t *conv_params,
+ const quant_data_t *quant_data);
-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);
+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);
void esp_nn_set_conv_scratch_buf_esp32s3(const void *buf);
-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);
+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);
void esp_nn_set_depthwise_conv_scratch_buf_esp32s3(const void *buf);
/************************** Pooling functions *****************************/
diff --git a/code/components/esp-nn/include/esp_nn_esp32.h b/code/components/esp-nn/include/esp_nn_generic_opt.h
similarity index 77%
rename from code/components/esp-nn/include/esp_nn_esp32.h
rename to code/components/esp-nn/include/esp_nn_generic_opt.h
index 03fd8216..136cba5d 100644
--- a/code/components/esp-nn/include/esp_nn_esp32.h
+++ b/code/components/esp-nn/include/esp_nn_generic_opt.h
@@ -13,28 +13,27 @@
// limitations under the License.
/**
- * @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`
+ * @file Header definitions to include for esp_nn generic optimisations
+ * For functions which not having optimisations, _ansi versions are picked.
*/
#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_ansi
+#define esp_nn_depthwise_conv_s8 esp_nn_depthwise_conv_s8_opt
-#define esp_nn_conv_s8 esp_nn_conv_s8_ansi
+#define esp_nn_conv_s8 esp_nn_conv_s8_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_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_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_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_relu6_s8 esp_nn_relu6_s8_ansi
diff --git a/code/components/esp-nn/src/common/common_functions.h b/code/components/esp-nn/src/common/common_functions.h
index 9a5f0dcc..0a74eca4 100644
--- a/code/components/esp-nn/src/common/common_functions.h
+++ b/code/components/esp-nn/src/common/common_functions.h
@@ -41,15 +41,39 @@
__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;
-}
-
-__NN_FORCE_INLINE__ int32_t esp_nn_pick_sat_high32_of64(int64_t val64)
-{
- int32_t sign = (int32_t) (val64 >> 63);
- int32_t to_add = sign & ((1ul << 31) - 1);
- return (int32_t) ((int64_t) (val64 + to_add) >> 31);
+#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
}
/**
@@ -57,8 +81,19 @@ __NN_FORCE_INLINE__ int32_t esp_nn_pick_sat_high32_of64(int64_t val64)
*/
__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)
+{
+ int32_t sign = (int32_t) (val64 >> 63);
+ int32_t to_add = sign & ((1ul << 31) - 1);
+ return (int32_t) ((int64_t) (val64 + to_add) >> 31);
}
__NN_FORCE_INLINE__ int32_t esp_nn_sat_round_doubling_high_mul(int32_t in0, int32_t in1)
@@ -144,7 +179,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 * 2);
+ memset(dst, pad_val, ((input_wd + 2 * pad_wd) * (input_ht + 2 * pad_ht)) * channels);
dst += (pad_wd + input_wd + pad_wd) * channels;
for (int i = 0; i < input_ht; i++) {
@@ -156,7 +191,6 @@ 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,
@@ -169,13 +203,16 @@ 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++;
}
- memset(dst, pad_val, pad_wd * channels);
- dst += pad_wd * channels;
+ if (pad_wd) {
+ memset(dst, pad_val, pad_wd * channels);
+ dst += pad_wd * channels;
+ }
}
/* pad end `pad_ht` lines at end */
- memset(dst, pad_val, (input_wd + pad_wd) * pad_ht * channels);
+ if (pad_ht) {
+ memset(dst, pad_val, (input_wd + pad_wd) * pad_ht * channels);
+ }
}
-#endif
/**
* @brief convert 8 bit input data to 16 bit
diff --git a/code/components/esp-nn/src/convolution/esp_nn_conv_ansi.c b/code/components/esp-nn/src/convolution/esp_nn_conv_ansi.c
index d04f78e1..677c0ad8 100644
--- a/code/components/esp-nn/src/convolution/esp_nn_conv_ansi.c
+++ b/code/components/esp-nn/src/convolution/esp_nn_conv_ansi.c
@@ -12,16 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include
+#include
#include
-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)
+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)
{
return 0;
}
@@ -108,29 +106,35 @@ 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 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,
+void esp_nn_conv_s8_ansi(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
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 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 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 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++) {
diff --git a/code/components/esp-nn/src/convolution/esp_nn_conv_esp32s3.c b/code/components/esp-nn/src/convolution/esp_nn_conv_esp32s3.c
index ea8fdfa5..e13129b2 100644
--- a/code/components/esp-nn/src/convolution/esp_nn_conv_esp32s3.c
+++ b/code/components/esp-nn/src/convolution/esp_nn_conv_esp32s3.c
@@ -12,30 +12,30 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include
#include
+#include
#include
static int16_t *scratch_buffer = NULL;
-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_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_mult4_1x1_esp32s3(const int16_t *input_data,
const uint16_t input_wd,
@@ -81,34 +81,40 @@ 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 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,
+static void esp_nn_conv_s8_unrolled(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
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 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 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 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_channels; out_ch_idx++) {
+ for (out_ch_idx = 0; out_ch_idx < out_ch; out_ch_idx++) {
int32_t conv_out = 0;
const int32_t base_y = stride_ht * out_y - pad_ht;
@@ -124,10 +130,10 @@ static void esp_nn_conv_s8_unrolled(const int8_t *input_data,
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_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++) {
+ 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++) {
conv_out +=
(input_data[input_base_offset + in_ch_idx] + input_offset) *
filter_data[filter_base_offset + in_ch_idx];
@@ -332,18 +338,35 @@ static void esp_nn_conv_s8_pad_valid_ch3_3x3(const int8_t *input_data,
}
}
-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)
+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)
{
+ 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 = 8 * in_ch; /* to store intermediate data */
+
+ 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 align_buf_size = 32; /* extra buffer for alignment */
- return 2 * (filter_size + input_size + transpose_buf_size) + align_buf_size;
+ 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;
}
void esp_nn_set_conv_scratch_buf_esp32s3(void *buf)
@@ -351,29 +374,35 @@ void esp_nn_set_conv_scratch_buf_esp32s3(void *buf)
scratch_buffer = (int16_t *) buf;
}
-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,
+void esp_nn_conv_s8_esp32s3(const data_dims_t *input_dims,
+ const int8_t *input,
+ const data_dims_t *filter_dims,
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 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 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 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);
@@ -387,15 +416,16 @@ void esp_nn_conv_s8_esp32s3(const int8_t *input,
if (channels % 8 == 0 && filter_wd == 1 && filter_ht == 1 &&
pad_wd == 0 && pad_ht == 0 && stride_wd == 1 && stride_ht == 1) {
- int scratch_offset = (int) (filter_data16 + filter_size);
+ int8_t *filter_aligned = (int8_t *) scratch_buffer;
+ int scratch_offset = (int) (filter_aligned + filter_size);
void *scratch_buf = (void *) (scratch_offset + 16 - (scratch_offset & 15));
- 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,
+ 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,
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) % 16 == 0 && /* TODO: remove this check */
+ (input_wd * input_ht) % 4 == 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));
@@ -427,10 +457,7 @@ void esp_nn_conv_s8_esp32s3(const int8_t *input,
}
} else {
/* Basic unrolled version */
- 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);
+ esp_nn_conv_s8_unrolled(input_dims, input, filter_dims, filter_data,
+ bias, output_dims, out_data, conv_params, quant_data);
}
}
diff --git a/code/components/esp-nn/src/convolution/esp_nn_conv_opt.c b/code/components/esp-nn/src/convolution/esp_nn_conv_opt.c
new file mode 100644
index 00000000..be96430e
--- /dev/null
+++ b/code/components/esp-nn/src/convolution/esp_nn_conv_opt.c
@@ -0,0 +1,179 @@
+// 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
+
+#include
+
+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;
+ }
+ }
+ }
+}
diff --git a/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c b/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c
index 9cac6cef..1cd02e0f 100644
--- a/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c
+++ b/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_ansi.c
@@ -12,16 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include
-
+#include
#include
-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)
+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)
{
return 0;
}
@@ -31,29 +28,35 @@ void esp_nn_set_depthwise_conv_scratch_buf_ansi(const void *buf)
}
-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,
+void esp_nn_depthwise_conv_s8_ansi(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
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 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 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 *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;
diff --git a/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_opt.c b/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_opt.c
new file mode 100644
index 00000000..4afea3f3
--- /dev/null
+++ b/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_opt.c
@@ -0,0 +1,291 @@
+// 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
+#include
+
+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;
+ }
+ }
+ }
+ }
+}
diff --git a/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c b/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c
index c588c48f..9167a43f 100644
--- a/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c
+++ b/code/components/esp-nn/src/convolution/esp_nn_depthwise_conv_s8_esp32s3.c
@@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include
#include
+#include
#include
@@ -353,17 +353,59 @@ void esp_nn_depthwise_conv_s8_ch_mult1(const int8_t *input_data,
}
}
-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)
+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)
{
+ 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 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
+ 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
}
void esp_nn_set_depthwise_conv_scratch_buf_esp32s3(void *buf)
@@ -376,29 +418,38 @@ 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 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,
+
+
+
+void esp_nn_depthwise_conv_s8_esp32s3(const data_dims_t *input_dims,
+ const int8_t *input_data,
+ const data_dims_t *filter_dims,
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 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 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 *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;
@@ -423,18 +474,27 @@ void esp_nn_depthwise_conv_s8_esp32s3(const int8_t *input_data,
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 ((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)) {
+ } else if ((channels % 16 == 0) && (pad_wd == 0) && (pad_ht == 0)) {
/* 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_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,
+ 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,
out_mult, activation_min, activation_max);
- } else { /* (channels % 8) == 0 && pad_wd == 1 && pad_ht == 1 */
+ } else { /* (channels % 8) == 0 */
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,
diff --git a/code/components/esp-nn/test_app/sdkconfig.defaults.esp32s3 b/code/components/esp-nn/test_app/sdkconfig.defaults.esp32s3
new file mode 100644
index 00000000..1adc4b01
--- /dev/null
+++ b/code/components/esp-nn/test_app/sdkconfig.defaults.esp32s3
@@ -0,0 +1,8 @@
+# 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
diff --git a/code/components/esp-nn/tests/src/basic_math_test.c b/code/components/esp-nn/tests/src/basic_math_test.c
index 5b96b990..715d7c78 100644
--- a/code/components/esp-nn/tests/src/basic_math_test.c
+++ b/code/components/esp-nn/tests/src/basic_math_test.c
@@ -23,7 +23,9 @@
#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"
@@ -138,6 +140,11 @@ 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;
@@ -194,10 +201,10 @@ elementwise_add_test_cleanup:
if (input2_orig) {
free(input2_orig);
}
- if (out_data_c) {
+ if (out_c_orig) {
free(out_c_orig);
}
- if (out_data_opt) {
+ if (out_opt_orig) {
free(out_opt_orig);
}
}
@@ -282,6 +289,11 @@ 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;
@@ -333,10 +345,10 @@ elementwise_mult_test_cleanup:
if (input2_orig) {
free(input2_orig);
}
- if (out_data_c) {
+ if (out_c_orig) {
free(out_c_orig);
}
- if (out_data_opt) {
+ if (out_opt_orig) {
free(out_opt_orig);
}
}
diff --git a/code/components/esp-nn/tests/src/convolution_test.c b/code/components/esp-nn/tests/src/convolution_test.c
index f3802257..c86bdbab 100644
--- a/code/components/esp-nn/tests/src/convolution_test.c
+++ b/code/components/esp-nn/tests/src/convolution_test.c
@@ -22,8 +22,9 @@
#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
@@ -44,8 +45,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 10 iterations
- for (int itr = 0; itr < 10; itr++) {
+ // run for 15 iterations
+ for (int itr = 0; itr < 15; itr++) {
/* prepare data */
switch (itr) {
case 0: // (ch_mult 1, (channels % 16) = 0), filter (3,3), pad (0,0)
@@ -144,22 +145,52 @@ void esp_nn_depthwise_conv_s8_test()
stride_wd = 2;
stride_ht = 2;
break;
- default:
- input_wd = 4;
- input_ht = 4;
+ case 8: // same as case 7, with large parameters
+ input_wd = 58;
+ input_ht = 58;
filter_ht = 3;
filter_wd = 3;
- ch_mult = 4;
- channels = 4;
- pad_wd = 1;
- pad_ht = 1;
- stride_wd = 1;
- stride_ht = 1;
+ 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;
+ 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);
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;
@@ -210,9 +241,16 @@ void esp_nn_depthwise_conv_s8_test()
out_mult[i] = 0x7eb0e200 + rand() % 50;
}
- int scratch_buf_size = esp_nn_get_depthwise_conv_scratch_size(input_wd, input_ht,
- channels, ch_mult,
- filter_wd, filter_ht);
+ 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);
if (scratch_buf_size > 0) {
#if IDF_HEAP_CAPS
scratch_buf = heap_caps_malloc(scratch_buf_size + 32, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
@@ -234,11 +272,8 @@ void esp_nn_depthwise_conv_s8_test()
}
/* C function */
- 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);
+ 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);
if (itr == 0) {
profile_c_end();
@@ -246,11 +281,8 @@ void esp_nn_depthwise_conv_s8_test()
}
/* Optimized function */
- 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);
+ esp_nn_depthwise_conv_s8(&input_dims, input, &filter_dims, filter_data + 4,
+ bias + 1, &output_dims, out_data_opt, &conv_params, &quant_data);
if (itr == 0) {
/* disable profiler */
@@ -479,8 +511,16 @@ void esp_nn_conv_s8_test()
out_mult[i] = 0x7f67f4f8 + rand() % 50;
}
- int scratch_buf_size = esp_nn_get_conv_scratch_size(in_wd, in_ht, in_channels,
- out_channels, filter_wd, filter_ht);
+ 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);
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);
@@ -502,11 +542,8 @@ void esp_nn_conv_s8_test()
}
/* C function */
- 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);
+ esp_nn_conv_s8_ansi(&input_dims, input, &filter_dims, filter_data + 2,
+ bias, &output_dims, out_data_c, &conv_params, &quant_data);
if (itr == 0) {
profile_c_end();
@@ -514,11 +551,8 @@ void esp_nn_conv_s8_test()
}
/* Optimized function */
- 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);
+ esp_nn_conv_s8(&input_dims, input, &filter_dims, filter_data + 2,
+ bias, &output_dims, out_data_opt, &conv_params, &quant_data);
if (itr == 0) {
/* disable profiler */
diff --git a/code/components/esp-nn_20220724.zip b/code/components/esp-nn_20220724.zip
deleted file mode 100644
index 2bac7498..00000000
Binary files a/code/components/esp-nn_20220724.zip and /dev/null differ
diff --git a/code/components/esp-nn_20220716.zip b/code/components/esp-nn_20220827.zip
similarity index 97%
rename from code/components/esp-nn_20220716.zip
rename to code/components/esp-nn_20220827.zip
index 53c7bef2..43f16002 100644
Binary files a/code/components/esp-nn_20220716.zip and b/code/components/esp-nn_20220827.zip differ
diff --git a/code/components/esp32-camera-master.zip b/code/components/esp32-camera-master.zip
deleted file mode 100644
index 8706b3d8..00000000
Binary files a/code/components/esp32-camera-master.zip and /dev/null differ
diff --git a/code/components/esp32-camera-master_20220724.zip b/code/components/esp32-camera-master_20220724.zip
deleted file mode 100644
index 64f2f896..00000000
Binary files a/code/components/esp32-camera-master_20220724.zip and /dev/null differ
diff --git a/code/components/jomjol_controlcamera/ClassControllCamera.cpp b/code/components/jomjol_controlcamera/ClassControllCamera.cpp
index df42a2d7..ff410da3 100644
--- a/code/components/jomjol_controlcamera/ClassControllCamera.cpp
+++ b/code/components/jomjol_controlcamera/ClassControllCamera.cpp
@@ -263,6 +263,9 @@ void CCamera::EnableAutoExposure(int flashdauer)
ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed");
LEDOnOff(false);
LightOnOff(false);
+ LogFile.SwitchOnOff(true);
+ LogFile.WriteToFile("Camera Capture Failed (Procedure 'EnableAutoExposure') --> Reboot"
+ "Check that your camera module is working and connected properly.");
doReboot();
}
esp_camera_fb_return(fb);
@@ -313,7 +316,7 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
LightOnOff(false);
LogFile.SwitchOnOff(true);
- LogFile.WriteToFile("Camera is not working anymore - most propably hardware problem (instablility, ...). "
+ LogFile.WriteToFile("Camera is not working anymore (CCamera::CaptureToBasisImage) - most propably hardware problem (instablility, ...). "
"System will reboot.");
doReboot();
@@ -410,6 +413,9 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
ESP_LOGE(TAGCAMERACLASS, "CaptureToFile: Camera Capture Failed");
LEDOnOff(false);
LightOnOff(false);
+ LogFile.SwitchOnOff(true);
+ LogFile.WriteToFile("Camera Capture Failed (CCamera::CaptureToFile) --> Reboot"
+ "Check that your camera module is working and connected properly.");
doReboot();
return ESP_FAIL;
diff --git a/code/components/jomjol_fileserver_ota/server_file.cpp b/code/components/jomjol_fileserver_ota/server_file.cpp
index f6a82a12..e6802dc0 100644
--- a/code/components/jomjol_fileserver_ota/server_file.cpp
+++ b/code/components/jomjol_fileserver_ota/server_file.cpp
@@ -120,16 +120,6 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req)
}
-/* Handler to redirect incoming GET request for /index.html to /
- * This can be overridden by uploading file with same name */
-// static esp_err_t index_html_get_handler(httpd_req_t *req)
-// {
-// httpd_resp_set_status(req, "307 Temporary Redirect");
-// httpd_resp_set_hdr(req, "Location", "/");
-// httpd_resp_send(req, NULL, 0); // Response body can be empty
-// return ESP_OK;
-// }
-
/* Send HTTP response with a run-time generated html consisting of
* a list of all files and folders under the requested path.
* In case of SPIFFS this returns empty list when path is any
@@ -716,6 +706,101 @@ void delete_all_in_directory(std::string _directory)
closedir(dir);
}
+std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main)
+{
+ int i, sort_iter;
+ mz_bool status;
+ size_t uncomp_size;
+ mz_zip_archive zip_archive;
+ void* p;
+ char archive_filename[64];
+ std::string zw, ret = "";
+// static const char* s_Test_archive_filename = "testhtml.zip";
+
+ printf("miniz.c version: %s\n", MZ_VERSION);
+ printf("Zipfile: %s\n", _in_zip_file.c_str());
+ printf("Target Dir ZIP: %s\n", _target_zip.c_str());
+ printf("Target Dir BIN: %s\n", _target_bin.c_str());
+
+ // Now try to open the archive.
+ memset(&zip_archive, 0, sizeof(zip_archive));
+ status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), 0);
+ if (!status)
+ {
+ printf("mz_zip_reader_init_file() failed!\n");
+ return ret;
+ }
+
+ // Get and print information about each file in the archive.
+ int numberoffiles = (int)mz_zip_reader_get_num_files(&zip_archive);
+ for (sort_iter = 0; sort_iter < 2; sort_iter++)
+ {
+ memset(&zip_archive, 0, sizeof(zip_archive));
+ status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
+ if (!status)
+ {
+ printf("mz_zip_reader_init_file() failed!\n");
+ return ret;
+ }
+
+ for (i = 0; i < numberoffiles; i++)
+ {
+ mz_zip_archive_file_stat file_stat;
+ mz_zip_reader_file_stat(&zip_archive, i, &file_stat);
+ sprintf(archive_filename, file_stat.m_filename);
+
+ // Try to extract all the files to the heap.
+ p = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0);
+ if (!p)
+ {
+ printf("mz_zip_reader_extract_file_to_heap() failed!\n");
+ mz_zip_reader_end(&zip_archive);
+ return ret;
+ }
+
+ // Save to File.
+ zw = std::string(archive_filename);
+ if (toUpper(zw) == "FIRMWARE.BIN")
+ {
+ zw = _target_bin + zw;
+ ret = zw;
+ }
+ else
+ {
+ std::string _dir = getDirectory(zw);
+
+ if (_dir.length() > 0)
+ {
+ zw = _main + zw;
+ }
+ else
+ {
+ zw = _target_zip + zw;
+ }
+
+ }
+
+ printf("Filename to extract: %s", zw.c_str());
+ DeleteFile(zw);
+ FILE* fpTargetFile = OpenFileAndWait(zw.c_str(), "wb");
+ fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
+ fclose(fpTargetFile);
+
+ printf("Successfully extracted file \"%s\", size %u\n", archive_filename, (uint)uncomp_size);
+ // printf("File data: \"%s\"\n", (const char*)p);
+
+ // We're done.
+ mz_free(p);
+ }
+
+ // Close the archive, freeing any resources it was using
+ mz_zip_reader_end(&zip_archive);
+ }
+
+ printf("Success.\n");
+ return ret;
+}
+
void unzip(std::string _in_zip_file, std::string _target_directory){
int i, sort_iter;
mz_bool status;
@@ -860,15 +945,4 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
};
httpd_register_uri_handler(server, &file_delete);
-
- /* URI handler for getting tflite files from server */
-/*
- httpd_uri_t file_tflite = {
- .uri = "/tflite", // Match all URIs of type /delete/path/to/file
- .method = HTTP_GET,
- .handler = get_tflite_file_handler,
- .user_ctx = server_data // Pass server data as context
- };
- httpd_register_uri_handler(server, &file_tflite);
-*/
}
diff --git a/code/components/jomjol_fileserver_ota/server_file.h b/code/components/jomjol_fileserver_ota/server_file.h
index c179e36e..9dbcc88f 100644
--- a/code/components/jomjol_fileserver_ota/server_file.h
+++ b/code/components/jomjol_fileserver_ota/server_file.h
@@ -4,6 +4,8 @@
void register_server_file_uri(httpd_handle_t server, const char *base_path);
void unzip(std::string _in_zip_file, std::string _target_directory);
+std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/");
+
void delete_all_in_directory(std::string _directory);
diff --git a/code/components/jomjol_fileserver_ota/server_help.cpp b/code/components/jomjol_fileserver_ota/server_help.cpp
index 4bb06ffa..e8238b84 100644
--- a/code/components/jomjol_fileserver_ota/server_help.cpp
+++ b/code/components/jomjol_fileserver_ota/server_help.cpp
@@ -43,6 +43,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename)
}
ESP_LOGI(TAG, "Sending file : %s ...", filename.c_str());
+// httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
set_content_type_from_file(req, filename.c_str());
/* Retrieve the pointer to scratch buffer for temporary storage */
@@ -120,6 +121,8 @@ esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename)
return httpd_resp_set_type(req, "image/x-icon");
} else if (IS_FILE_EXT(filename, ".js")) {
return httpd_resp_set_type(req, "text/javascript");
+ } else if (IS_FILE_EXT(filename, ".css")) {
+ return httpd_resp_set_type(req, "text/css");
}
/* This is a limited set only */
/* For any other type always set as plain text */
diff --git a/code/components/jomjol_fileserver_ota/server_ota.cpp b/code/components/jomjol_fileserver_ota/server_ota.cpp
index 88d301ae..3d41b78f 100644
--- a/code/components/jomjol_fileserver_ota/server_ota.cpp
+++ b/code/components/jomjol_fileserver_ota/server_ota.cpp
@@ -50,6 +50,8 @@ static char ota_write_data[BUFFSIZE + 1] = { 0 };
#define OTA_URL_SIZE 256
static const char *TAGPARTOTA = "server_ota";
+esp_err_t handler_reboot(httpd_req_t *req);
+
static void infinite_loop(void)
{
@@ -207,24 +209,6 @@ static void print_sha256 (const uint8_t *image_hash, const char *label)
static bool diagnostic(void)
{
-/*
- gpio_config_t io_conf;
- io_conf.intr_type = (gpio_int_type_t) GPIO_PIN_INTR_DISABLE;
- io_conf.mode = GPIO_MODE_INPUT;
- io_conf.pin_bit_mask = (1ULL << CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);
- io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
- io_conf.pull_up_en = GPIO_PULLUP_ENABLE;
- gpio_config(&io_conf);
-
- ESP_LOGI(TAGPARTOTA, "Diagnostics (5 sec)...");
- vTaskDelay(5000 / portTICK_PERIOD_MS);
-
- bool diagnostic_is_ok = gpio_get_level(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);
-
- gpio_reset_pin(CONFIG_EXAMPLE_GPIO_DIAGNOSTIC);
-
- return diagnostic_is_ok;
-*/
return true;
}
@@ -326,7 +310,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK)
{
- printf("task is found"); printf(_valuechar); printf("\n");
+ printf("task is found: "); printf(_valuechar); printf("\n");
_task = std::string(_valuechar);
}
@@ -344,16 +328,105 @@ esp_err_t handler_ota_update(httpd_req_t *req)
};
+ if (_task.compare("update") == 0)
+ {
+ std::string filetype = toUpper(getFileType(fn));
+ if (filetype.length() == 0)
+ {
+ std::string zw = "Update failed - no file specified (zip, bin, tfl, tlite)";
+ httpd_resp_sendstr_chunk(req, zw.c_str());
+ httpd_resp_sendstr_chunk(req, NULL);
+ return ESP_OK;
+ }
+
+
+ if ((filetype == "TFLITE") || (filetype == "TFL"))
+ {
+ std::string out = "/sdcard/config/" + getFileFullFileName(fn);
+ DeleteFile(out);
+ CopyFile(fn, out);
+ DeleteFile(fn);
+
+ const char* resp_str = "Neural Network File copied.";
+ httpd_resp_sendstr_chunk(req, resp_str);
+ httpd_resp_sendstr_chunk(req, NULL);
+ return ESP_OK;
+ }
+
+
+ if (filetype == "ZIP")
+ {
+ std::string in, out, outbin, zw, retfirmware;
+
+// in = "/sdcard/firmware/html.zip";
+ out = "/sdcard/html";
+ outbin = "/sdcard/firmware";
+
+// delete_all_in_directory(out);
+
+ retfirmware = unzip_new(fn, out+"/", outbin+"/");
+
+ if (retfirmware.length() > 0)
+ {
+ filetype = "BIN";
+ fn = retfirmware;
+ zw = "HTML Update Successfull!
Additioal firmware found in ZIP file.\n";
+ httpd_resp_sendstr_chunk(req, zw.c_str());
+ }
+ else
+ {
+ zw = "HTML Update Successfull!
No reboot necessary.\n";
+ httpd_resp_sendstr_chunk(req, zw.c_str());
+ httpd_resp_sendstr_chunk(req, NULL);
+ return ESP_OK;
+ }
+ }
+
+
+ if (filetype == "BIN")
+ {
+ const char* resp_str;
+ KillTFliteTasks();
+ gpio_handler_deinit();
+ if (ota_update_task(fn))
+ {
+// resp_str = "rebooting - Firmware Update Successfull!
You can restart now.";
+// httpd_resp_send(req, resp_str, strlen(resp_str));
+// httpd_resp_sendstr_chunk(req, NULL);
+ return handler_reboot(req);
+ }
+ else
+ {
+ resp_str = "Error during Firmware Update!!!
Please check output of console.";
+ }
+
+ httpd_resp_send(req, resp_str, strlen(resp_str));
+
+ #ifdef DEBUG_DETAIL_ON
+ LogFile.WriteHeapInfo("handler_ota_update - Done");
+ #endif
+
+ return ESP_OK;
+ }
+
+
+ std::string zw = "Update failed - no valid file specified (zip, bin, tfl, tlite)";
+ httpd_resp_sendstr_chunk(req, zw.c_str());
+ httpd_resp_sendstr_chunk(req, NULL);
+ return ESP_OK;
+ }
+
+
if (_task.compare("unziphtml") == 0)
{
std::string in, out, zw;
in = "/sdcard/firmware/html.zip";
- out = "/sdcard/html/";
+ out = "/sdcard/html";
delete_all_in_directory(out);
- unzip(in, out);
+ unzip(in, out+"/");
zw = "HTML Update Successfull!
No reboot necessary";
httpd_resp_sendstr_chunk(req, zw.c_str());
httpd_resp_sendstr_chunk(req, NULL);
@@ -371,6 +444,8 @@ esp_err_t handler_ota_update(httpd_req_t *req)
unlink(fn.c_str());
}
/* Respond with an empty chunk to signal HTTP response completion */
+ std::string zw = "file deleted!\n";
+ httpd_resp_sendstr_chunk(req, zw.c_str());
httpd_resp_send_chunk(req, NULL, 0);
return ESP_OK;
}
@@ -416,6 +491,8 @@ void task_reboot(void *pvParameter)
}
void doReboot(){
+ LogFile.SwitchOnOff(true);
+ LogFile.WriteToFile("Reboot triggert by Software (5s).");
ESP_LOGI(TAGPARTOTA, "Reboot in 5sec");
LogFile.WriteToFile("Reboot in 5sec");
xTaskCreate(&task_reboot, "reboot", configMINIMAL_STACK_SIZE * 64, NULL, 10, NULL);
@@ -435,7 +512,7 @@ esp_err_t handler_reboot(httpd_req_t *req)
LogFile.WriteToFile("handler_reboot");
ESP_LOGI(TAGPARTOTA, "!!! System will restart within 5 sec!!!");
- const char* resp_str = "!!! System will restart within 5 sec!!!";
+ const char* resp_str = " ";
httpd_resp_send(req, resp_str, strlen(resp_str));
doReboot();
diff --git a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp
index 75c59418..a60735f6 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp
+++ b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp
@@ -10,7 +10,7 @@
static const char* TAG = "flow_analog";
-bool debugdetailgeneral = false;
+bool debugdetailgeneral = true;
ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNType _cnntype) : ClassFlowImage(NULL, TAG)
{
@@ -28,7 +28,7 @@ ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNTy
flowpostalignment = _flowalign;
}
-string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev)
+string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev, float _vorgaengerAnalog)
{
string result = "";
@@ -41,8 +41,8 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
float zahl = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
int ergebnis_nachkomma = ((int) floor(zahl * 10) + 10) % 10;
- prev = ZeigerEval(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
- if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(analog) zahl=" + std::to_string(zahl) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
+ prev = ZeigerEvalAnalogNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
+// if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(analog) zahl=" + std::to_string(zahl) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
result = std::to_string(prev);
if (_extendedResolution && (CNNType != Digital))
@@ -50,7 +50,7 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
for (int i = GENERAL[_analog]->ROI.size() - 2; i >= 0; --i)
{
- prev = ZeigerEval(GENERAL[_analog]->ROI[i]->result_float, prev);
+ prev = ZeigerEvalAnalogNeu(GENERAL[_analog]->ROI[i]->result_float, prev);
result = std::to_string(prev) + result;
}
return result;
@@ -82,13 +82,14 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
result = std::to_string(ergebnis_vorkomma) + std::to_string(ergebnis_nachkomma);
prev = ergebnis_vorkomma;
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(dig100-ext) ergebnis_vorkomma=" + std::to_string(ergebnis_vorkomma) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
-
-
}
else
{
// prev = ZeigerEval(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
- prev = ZeigerEvalHybrid(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev, prev);
+ if (_vorgaengerAnalog >= 0)
+ prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, _vorgaengerAnalog, prev, true);
+ else
+ prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev, prev);
result = std::to_string(prev);
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(dig100) prev=" + std::to_string(prev));
@@ -105,8 +106,8 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
{
if (GENERAL[_analog]->ROI[i]->result_float >= 0)
{
- prev = ZeigerEvalHybrid(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev);
- if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout#ZeigerEvalHybrid()= " + std::to_string(prev));
+ prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev);
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout#ZeigerEvalHybridNeu()= " + std::to_string(prev));
result = std::to_string(prev) + result;
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout#result= " + result);
@@ -122,55 +123,11 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
return result;
}
-/*
- if (CNNType == Digital100)
- {
- int zif_akt = -1;
-
- float zahl = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
- if (zahl >= 0) // NaN?
- {
- if (_extendedResolution)
- {
- int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
- int ergebnis_vorkomma = ((int) floor(zahl)) % 10;
-
- result = std::to_string(ergebnis_vorkomma) + std::to_string(ergebnis_nachkomma);
- zif_akt = ergebnis_vorkomma;
- }
- else
- {
- zif_akt = ZeigerEvalHybrid(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, -1, -1);
- result = std::to_string(zif_akt);
- }
- }
- else
- {
- result = "N";
- if (_extendedResolution && (CNNType != Digital))
- result = "NN";
- }
-
- for (int i = GENERAL[_analog]->ROI.size() - 2; i >= 0; --i)
- {
- if (GENERAL[_analog]->ROI[i]->result_float >= 0)
- {
- zif_akt = ZeigerEvalHybrid(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, zif_akt);
- result = std::to_string(zif_akt) + result;
- }
- else
- {
- zif_akt = -1;
- result = "N" + result;
- }
- }
- return result;
- }
-*/
return result;
}
+/*
int ClassFlowCNNGeneral::ZeigerEvalHybrid(float zahl, float zahl_vorgaenger, int eval_vorgaenger)
{
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybrid( " + std::to_string(zahl) + ", " + std::to_string(zahl_vorgaenger) + ", " + std::to_string(eval_vorgaenger) + ")");
@@ -189,7 +146,7 @@ int ClassFlowCNNGeneral::ZeigerEvalHybrid(float zahl, float zahl_vorgaenger, int
// 9.0, da bei getReadout() prev als int übergeben wird (9 statt 9.5)
// tritt bei der ersten ziffer von digit auf, wenn analog davor (2. Aufruf von getReadout)
- if ((zahl_vorgaenger >= 0.5 ) && (zahl_vorgaenger < 9.0))
+ if ((zahl_vorgaenger >= 0.5 ) && (zahl_vorgaenger < 9.5))
{
// kein Ziffernwechsel, da Vorkomma weit genug weg ist (0+/-0.5) --> zahl wird gerundet
if ((ergebnis_nachkomma <= 2) || (ergebnis_nachkomma >= 8)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
@@ -220,69 +177,170 @@ int ClassFlowCNNGeneral::ZeigerEvalHybrid(float zahl, float zahl_vorgaenger, int
+ ", zahl_vorgaenger=" + std::to_string(zahl_vorgaenger) + ", eval_vorgaenger=" + std::to_string(eval_vorgaenger));
return -1;
-/*
- if (zahl_vorgaenger > 9.2) // Ziffernwechsel beginnt
+}
+*/
+
+int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger)
+{
+ int result;
+ int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
+ int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
+
+ if (eval_vorgaenger < 0)
{
- if (eval_vorgaenger == 0) // Wechsel hat schon stattgefunden
- {
- return ((int) round(zahl) + 10) % 10; // Annahme, dass die neue Zahl schon in der Nähe des Ziels ist
- }
+ if ((ergebnis_nachkomma <= DigitalUnschaerfe * 10) || (ergebnis_nachkomma >= DigitalUnschaerfe * 10)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
+ result = (int) (round(zahl) + 10) % 10;
else
- {
- if (zahl_vorgaenger <= 9.5) // Wechsel startet gerade, aber beginnt erst
- {
- if ((ergebnis_nachkomma <= 2) || (ergebnis_nachkomma >= 8)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
- return ((int) round(zahl) + 10) % 10;
- else
- return ((int) trunc(zahl) + 10) % 10;
- }
- else
- {
- return ((int) trunc(zahl) + 10) % 10; // Wechsel schon weiter fortgeschritten, d.h. über 2 als Nachkomma
- }
- }
+ result = (int) ((int) trunc(zahl) + 10) % 10;
+
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
+ return result;
}
- if ((ergebnis_nachkomma <= 2) || (ergebnis_nachkomma >= 8)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
- return ((int) round(zahl) + 10) % 10;
+ if (AnalogerVorgaenger)
+ {
+// result = ZeigerEvalAnalogToDigitNeu(zahl, eval_vorgaenger);
+ result = ZeigerEvalAnalogToDigitNeu(zahl, zahl_vorgaenger, eval_vorgaenger);
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - Analoger Vorgänger, Bewertung über ZeigerEvalAnalogNeu = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
+ return result;
+ }
- return ((int) trunc(zahl) + 10) % 10;
-*/
+ if ((zahl_vorgaenger >= DigitalUebergangsbereichVorgaenger ) && (zahl_vorgaenger <= (10.0 - DigitalUebergangsbereichVorgaenger)))
+ {
+ // kein Ziffernwechsel, da Vorgänger weit genug weg ist (0+/-DigitalUebergangsbereichVorgaenger) --> zahl wird gerundet
+ if ((ergebnis_nachkomma <= DigitalBand) || (ergebnis_nachkomma >= (10-DigitalBand))) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
+ result = ((int) round(zahl) + 10) % 10;
+ else
+ result = ((int) trunc(zahl) + 10) % 10;
+
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, kein Ziffernwechsel, da Vorkomma weit genug weg = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
+ return result;
+ }
+
+ if (eval_vorgaenger <= 1) // Nulldurchgang hat stattgefunden (!Bewertung über Prev_value und nicht Zahl!) --> hier aufrunden (2.8 --> 3, aber auch 3.1 --> 3)
+ {
+ if (ergebnis_nachkomma > 5)
+ result = (ergebnis_vorkomma + 1) % 10;
+ else
+ result = ergebnis_vorkomma;
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, Nulldurchgang hat stattgefunden = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
+ return result;
+ }
+
+ // bleibt nur >= 9.5 --> noch kein Nulldurchgang --> 2.8 --> 2, und 3.1 --> 2
+ // alles >=x.4 kann als aktuelle Zahl gelten im Übergang. Bei 9.5 Vorgänger kann die aktuelle
+ // Zahl noch x.6 - x.7 sein.
+ if (ergebnis_nachkomma >= 4)
+ result = ergebnis_vorkomma;
+ else
+ result = (ergebnis_vorkomma - 1 + 10) % 10;
+
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, >= 9.5 --> noch kein Nulldurchgang = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe) + " ergebnis_nachkomma = " + std::to_string(ergebnis_nachkomma));
+ return result;
}
-
-int ClassFlowCNNGeneral::ZeigerEval(float zahl, int ziffer_vorgaenger)
-{
- int ergebnis_nachkomma = ((int) floor(zahl * 10) + 10) % 10;
+int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger)
+{
+ int result;
+ int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
- int ergebnis;
- float ergebnis_rating;
- if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEval erg_v=" + std::to_string(ergebnis_vorkomma) + ", erg_n=" + std::to_string(ergebnis_nachkomma) + ", ziff_v=" + std::to_string(ziffer_vorgaenger));
+
+ if (ziffer_vorgaenger < 0)
+ {
+ result = (int) floor(zahl);
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
+ return result;
+ }
+
+ if ((ziffer_vorgaenger >= DigitalUebergangsbereichVorgaengerAnalogToDigit ) && (ziffer_vorgaenger <= (10.0 - DigitalUebergangsbereichVorgaengerAnalogToDigit)))
+ {
+ // kein Ziffernwechsel, da Vorgänger weit genug weg ist (0+/-DigitalUebergangsbereichVorgaenger) --> zahl wird gerundet
+ if ((ergebnis_nachkomma <= 2) || (ergebnis_nachkomma >= 8)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
+ result = ((int) round(zahl) + 10) % 10;
+ else
+ result = ((int) trunc(zahl) + 10) % 10;
+
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - kein Ziffernwechsel, da Vorkomma weit genug weg = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
+ return result;
+ }
+
+ if (ziffer_vorgaenger <= 1 && eval_vorgaenger<9) // Nulldurchgang hat stattgefunden (!Bewertung über Prev_value und nicht Zahl!) --> hier aufrunden (2.8 --> 3, aber auch 3.1 --> 3)
+ // aber Sonderfall ziffer_vorgaeger = 0.1 vor_vorgaenger 9.9 => eval_vorgaenger ist 9, damit hat Nulldurchgang nicht stattgefunden.
+ {
+ if (ergebnis_nachkomma > 5)
+ result = (ergebnis_vorkomma + 1) % 10;
+ else
+ result = ergebnis_vorkomma;
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - Nulldurchgang hat stattgefunden = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
+ return result;
+ }
+
+ // bleibt nur >= 9.5 --> noch kein Nulldurchgang --> 2.8 --> 2, und 3.1 --> 2
+ // hier auf 4 reduziert, da erst ab Vorgänder 9 anfängt umzustellen. Bei 9.5 Vorgänger kann die aktuelle
+ // Zahl noch x.4 - x.5 sein.
+ if (ergebnis_nachkomma >= 4)
+ result = ergebnis_vorkomma;
+ else
+ result = (ergebnis_vorkomma - 1 + 10) % 10;
+
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - 9.0 --> noch kein Nulldurchgang = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
+ return result;
+}
+
+int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
+{
+ float zahl_min, zahl_max;
+ int result;
if (ziffer_vorgaenger == -1)
- return ergebnis_vorkomma % 10;
+ {
+ result = (int) floor(zahl);
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
+ return result;
+ }
- // Ist die aktuelle Stelle schon umgesprungen und die Vorstelle noch nicht?
- // Akt.: 2.1, Vorstelle = 0.9 => 1.9
- // Problem sind mehrere Rundungen
- // Bsp. zahl=4.5, Vorgänger= 9.6 (ziffer_vorgaenger=0)
- // Tritt nur auf bei Übergang von analog auf digit
- ergebnis_rating = ergebnis_nachkomma - ziffer_vorgaenger;
- if (ergebnis_nachkomma >= 5)
- ergebnis_rating-=5.1;
- else
- ergebnis_rating+=5;
- ergebnis = (int) round(zahl);
- if (ergebnis_rating < 0)
- ergebnis-=1;
- if (ergebnis == -1)
- ergebnis+=10;
+ zahl_min = zahl - AnalogFehler / 10.0;
+ zahl_max = zahl + AnalogFehler / 10.0;
+
+ if ((int) floor(zahl_max) - (int) floor(zahl_min) != 0)
+ {
+ if (ziffer_vorgaenger <= AnalogFehler)
+ {
+ result = ((int) floor(zahl_max) + 10) % 10;
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach oben - Ergebnis = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
+ return result;
+ }
+ if (ziffer_vorgaenger >= 10 - AnalogFehler)
+ {
+ result = ((int) floor(zahl_min) + 10) % 10;
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach unten - Ergebnis = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
+ return result;
+ }
+ }
- ergebnis = (ergebnis + 10) % 10;
- return ergebnis;
+
+ result = ((int) floor(zahl) + 10) % 10;
+ if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - Zahl eindeutig, keine Korrektur notwendig - Ergebnis = " + std::to_string(result) +
+ " zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
+
+ return result;
+
}
+
bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
{
std::vector zerlegt;
@@ -327,11 +385,6 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
{
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
}
-// if ((toUpper(zerlegt[0]) == "MODELTYPE") && (zerlegt.size() > 1))
-// {
-// if (toUpper(zerlegt[1]) == "DIGITHYPRID")
-// CNNType = DigitalHyprid;
-// }
if ((toUpper(zerlegt[0]) == "MODEL") && (zerlegt.size() > 1))
{
@@ -350,6 +403,11 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
neuroi->posy = std::stoi(zerlegt[2]);
neuroi->deltax = std::stoi(zerlegt[3]);
neuroi->deltay = std::stoi(zerlegt[4]);
+ neuroi->CCW = false;
+ if (zerlegt.size() >= 6)
+ {
+ neuroi->CCW = toUpper(zerlegt[5]) == "TRUE";
+ }
neuroi->result_float = -1;
neuroi->image = NULL;
neuroi->image_org = NULL;
@@ -422,7 +480,7 @@ general* ClassFlowCNNGeneral::GetGENERAL(string _name, bool _create = true)
_ret->ROI.push_back(neuroi);
- printf("GetGENERAL - GENERAL %s - roi %s\n", _analog.c_str(), _roi.c_str());
+ printf("GetGENERAL - GENERAL %s - roi %s - CCW: %d\n", _analog.c_str(), _roi.c_str(), neuroi->CCW);
return _ret;
}
@@ -569,10 +627,11 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
CNNType = Digital;
printf("TFlite-Type set to Digital\n");
break;
- case 20:
+/* case 20:
CNNType = DigitalHyprid10;
printf("TFlite-Type set to DigitalHyprid10\n");
break;
+*/
// case 22:
// CNNType = DigitalHyprid;
// printf("TFlite-Type set to DigitalHyprid\n");
@@ -635,8 +694,13 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
f1 = tflite->GetOutputValue(0);
f2 = tflite->GetOutputValue(1);
float result = fmod(atan2(f1, f2) / (M_PI * 2) + 2, 1);
- GENERAL[_ana]->ROI[i]->result_float = result * 10;
- printf("Result General(Analog)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
+
+ if(GENERAL[_ana]->ROI[i]->CCW)
+ GENERAL[_ana]->ROI[i]->result_float = 10 - (result * 10);
+ else
+ GENERAL[_ana]->ROI[i]->result_float = result * 10;
+
+ printf("Result General(Analog)%i - CCW: %d - %f\n", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
if (isLogImage)
LogImage(logPath, GENERAL[_ana]->ROI[i]->name, &GENERAL[_ana]->ROI[i]->result_float, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
} break;
@@ -701,6 +765,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
}
} break;
*/
+/*
case DigitalHyprid10:
{
int _num, _nachkomma;
@@ -736,6 +801,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
}
}
} break;
+*/
case DoubleHyprid10:
{
@@ -769,7 +835,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
_fit = _val + _valminus;
}
- if (result > 10)
+ if (result >= 10)
result = result - 10;
if (result < 0)
result = result + 10;
@@ -827,15 +893,17 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
_num = tflite->GetOutClassification();
- GENERAL[_ana]->ROI[i]->result_float = (float)_num / 10.0;
+ if(GENERAL[_ana]->ROI[i]->CCW)
+ GENERAL[_ana]->ROI[i]->result_float = 10 - ((float)_num / 10.0);
+ else
+ GENERAL[_ana]->ROI[i]->result_float = (float)_num / 10.0;
-
_result_save_file = GENERAL[_ana]->ROI[i]->result_float;
GENERAL[_ana]->ROI[i]->isReject = false;
- printf("Result General(Analog)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
+ printf("Result General(Analog)%i - CCW: %d - %f\n", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
if (isLogImage)
{
diff --git a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.h b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.h
index 66aa56d5..06444ba7 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.h
+++ b/code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.h
@@ -10,7 +10,6 @@ enum t_CNNType {
Analogue,
Analogue100,
Digital,
-// DigitalHyprid,
DigitalHyprid10,
DoubleHyprid10,
Digital100,
@@ -24,18 +23,26 @@ protected:
t_CNNType CNNType;
std::vector GENERAL;
float CNNGoodThreshold;
+ float AnalogFehler = 3.0;
+ float AnalogToDigtalFehler = 0.8;
+ float DigitalUnschaerfe = 0.2;
+ int DigitalBand = 3;
+ float DigitalAnalogerVorgaengerUebergangsbereich = 2;
+ float DigitalUebergangsbereichVorgaengerAnalogToDigit = 1; // war vorher 2
+ float DigitalUebergangsbereichVorgaenger = 0.7; // 9.3 - 0.7
string cnnmodelfile;
int modelxsize, modelysize, modelchannel;
bool isLogImageSelect;
string LogImageSelect;
ClassFlowAlignment* flowpostalignment;
-// ClassFlowPostProcessing *flowpostprocessing = NULL;
- bool SaveAllFiles;
-// bool extendedResolution;
- int ZeigerEval(float zahl, int ziffer_vorgaenger);
- int ZeigerEvalHybrid(float zahl, float zahl_vorgaenger, int eval_vorgaenger);
+ bool SaveAllFiles;
+
+ int ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger);
+ int ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger);
+ int ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger = false);
+
bool doNeuralNetwork(string time);
@@ -50,7 +57,7 @@ public:
bool doFlow(string time);
string getHTMLSingleStep(string host);
- string getReadout(int _analog, bool _extendedResolution = false, int prev = -1);
+ string getReadout(int _analog, bool _extendedResolution = false, int prev = -1, float _vorgaengerAnalog = -1);
void DrawROI(CImageBasis *_zw);
diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp
index 0351dc17..db72aedf 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp
+++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp
@@ -305,6 +305,7 @@ bool ClassFlowControll::doFlow(string time)
if (i) i -= 1; // vorheriger Schritt muss wiederholt werden (vermutlich Bilder aufnehmen)
result = false;
if (repeat > 5) {
+ LogFile.SwitchOnOff(true);
LogFile.WriteToFile("Wiederholung 5x nicht erfolgreich --> reboot");
doReboot();
// Schritt wurde 5x wiederholt --> reboot
@@ -493,6 +494,8 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
// reboot notwendig damit die neue wlan.ini auch benutzt wird !!!
fclose(pfile);
printf("do reboot\n");
+ LogFile.SwitchOnOff(true);
+ LogFile.WriteToFile("Reboot to activate new HOSTNAME.");
esp_restart();
hard_restart();
doReboot();
diff --git a/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h b/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h
index 98432886..c296ca27 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h
+++ b/code/components/jomjol_flowcontroll/ClassFlowDefineTypes.h
@@ -7,7 +7,7 @@ struct roi {
int posx, posy, deltax, deltay;
float result_float;
int result_klasse;
- bool isReject;
+ bool isReject, CCW;
string name;
CImageBasis *image, *image_org;
};
@@ -33,9 +33,9 @@ struct NumberPost {
bool checkDigitIncreaseConsistency;
time_t lastvalue;
string timeStamp;
- float FlowRateAct; // m3 / min
- float PreValue; // letzter Wert, der gut ausgelesen wurde
- float Value; // letzer ausgelesener Wert, inkl. Korrekturen
+ double FlowRateAct; // m3 / min
+ double PreValue; // letzter Wert, der gut ausgelesen wurde
+ double Value; // letzer ausgelesener Wert, inkl. Korrekturen
string ReturnRateValue; // RückgabewertRate
string ReturnChangeAbsolute; // RückgabewertRate
string ReturnRawValue; // Rohwert (mit N & führenden 0)
diff --git a/code/components/jomjol_flowcontroll/ClassFlowImage.cpp b/code/components/jomjol_flowcontroll/ClassFlowImage.cpp
index c50b8cda..4053b5dc 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowImage.cpp
+++ b/code/components/jomjol_flowcontroll/ClassFlowImage.cpp
@@ -63,7 +63,12 @@ void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, i
if (*resultFloat < 0)
sprintf(buf, "N.N_");
else
+ {
sprintf(buf, "%.1f_", *resultFloat);
+ if (strcmp(buf, "10.0_"))
+ sprintf(buf, "0.0_");
+ }
+
} else if (resultInt != NULL) {
sprintf(buf, "%d_", *resultInt);
} else {
diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
index f4e014e9..b82f7afe 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
+++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
@@ -6,6 +6,7 @@
#include "time_sntp.h"
#include "interface_mqtt.h"
#include "ClassFlowPostProcessing.h"
+#include "ClassLogFile.h"
#include
@@ -31,9 +32,7 @@ void ClassFlowMQTT::SetInitialParameter(void)
ListFlowControll = NULL;
disabled = false;
MQTTenable = false;
-
-
-
+ keepAlive = 600; // TODO This must be greater than the Flow Interval!
}
ClassFlowMQTT::ClassFlowMQTT()
@@ -124,11 +123,50 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
printf("InitMQTTInit\n");
mainerrortopic = maintopic + "/connection";
printf("Init MQTT with uri: %s, clientname: %s, user: %s, password: %s, maintopic: %s\n", uri.c_str(), clientname.c_str(), user.c_str(), password.c_str(), mainerrortopic.c_str());
- MQTTInit(uri, clientname, user, password, mainerrortopic, 60);
- MQTTPublish(mainerrortopic, "connected", SetRetainFlag);
- MQTTenable = true;
+ if (!MQTTInit(uri, clientname, user, password, mainerrortopic, keepAlive))
+ { // Failed
+ MQTTenable = false;
+ return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ }
}
+
+ // Try sending mainerrortopic. If it fails, re-run init
+ if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
+ { // Failed
+ LogFile.WriteToFile("MQTT - Re-running init...!");
+ if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
+ { // Failed
+ MQTTenable = false;
+ return false;
+ }
+ }
+
+ // Try again and quit if it fails
+ if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
+ { // Failed
+ MQTTenable = false;
+ return false;
+ }
+
+
+
+ /* if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
+ { // Failed
+ LogFile.WriteToFile("MQTT - Could not publish connection status!");
+ MQTTenable = false;
+ return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ }*/
+
+ /* if(!MQTTPublish(_LWTContext, "", 1))
+ {
+ LogFile.WriteToFile("MQTT - Could not publish LWT!");
+ MQTTenable = false;
+ return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ }*/
+
+
+ MQTTenable = true;
return true;
}
@@ -141,8 +179,44 @@ string ClassFlowMQTT::GetMQTTMainTopic()
bool ClassFlowMQTT::doFlow(string zwtime)
{
- if (!MQTTenable)
- return true;
+ // if (!MQTTenable) {
+ // LogFile.WriteToFile("MQTT not enabled!");
+ //
+ // // Try again to init it
+ // if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
+ // { // Failed
+ // MQTTenable = false;
+ // return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ // }
+ //
+ // if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
+ // { // Failed
+ // MQTTenable = false;
+ // return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ // }
+ //
+ // LogFile.WriteToFile("MQTT is now enabled");
+ // MQTTenable = true;
+ // }
+
+
+ // Try sending mainerrortopic. If it fails, re-run init
+ if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
+ { // Failed
+ LogFile.WriteToFile("MQTT - Re-running init...!");
+ if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
+ { // Failed
+ MQTTenable = false;
+ return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ }
+ }
+
+ // Try again and quit if it fails
+ if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
+ { // Failed
+ MQTTenable = false;
+ return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ }
std::string result;
std::string resulterror = "";
@@ -153,7 +227,10 @@ bool ClassFlowMQTT::doFlow(string zwtime)
string zw = "";
string namenumber = "";
- MQTTPublish(mainerrortopic, "connected");
+ // if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
+ //{ // Failed, skip other topics
+ // return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ //}
zw = maintopic + "/" + "uptime";
char uptimeStr[11];
@@ -163,13 +240,19 @@ bool ClassFlowMQTT::doFlow(string zwtime)
zw = maintopic + "/" + "freeMem";
char freeheapmem[11];
sprintf(freeheapmem, "%zu", esp_get_free_heap_size());
- MQTTPublish(zw, freeheapmem, SetRetainFlag);
+ if (!MQTTPublish(zw, freeheapmem, SetRetainFlag))
+ { // Failed, skip other topics
+ return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
+ }
zw = maintopic + "/" + "wifiRSSI";
char rssi[11];
sprintf(rssi, "%d", get_WIFI_RSSI());
MQTTPublish(zw, rssi, SetRetainFlag);
+ zw = maintopic + "/" + "CPUtemp";
+ std::string cputemp = std::to_string(temperatureRead());
+ MQTTPublish(zw, cputemp, SetRetainFlag);
if (flowpostprocessing)
{
diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h
index 816389b1..3a990c7d 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h
+++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h
@@ -15,6 +15,7 @@ protected:
std::string user, password;
int SetRetainFlag;
bool MQTTenable;
+ int keepAlive;
std::string maintopic, mainerrortopic;
void SetInitialParameter(void);
diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
index 306b6b5f..73feef3e 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
+++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
@@ -9,6 +9,7 @@
#include
#include "time_sntp.h"
+//#define SERIAL_DEBUG // testing debug on serial enabled
#define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S"
@@ -68,7 +69,7 @@ string ClassFlowPostProcessing::GetPreValue(std::string _number)
return result;
}
-void ClassFlowPostProcessing::SetPreValue(float zw, string _numbers, bool _extern)
+void ClassFlowPostProcessing::SetPreValue(double zw, string _numbers, bool _extern)
{
printf("SetPrevalue: %f, %s\n", zw, _numbers.c_str());
for (int j = 0; j < NUMBERS.size(); ++j)
@@ -126,7 +127,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
{
if (NUMBERS[j]->name == name)
{
- NUMBERS[j]->PreValue = stof(zwvalue.c_str());
+ NUMBERS[j]->PreValue = stod(zwvalue.c_str());
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma + 1); // SIcherheitshalber 1 Stelle mehr, da ggf. Exgtended Resolution an ist (wird erst beim ersten Durchlauf gesetzt)
time_t tStart;
@@ -177,7 +178,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
fclose(pFile);
printf("%s", zw);
zwvalue = trim(std::string(zw));
- NUMBERS[0]->PreValue = stof(zwvalue.c_str());
+ NUMBERS[0]->PreValue = stod(zwvalue.c_str());
time_t tStart;
int yy, month, dd, hh, mm, ss;
@@ -238,8 +239,9 @@ void ClassFlowPostProcessing::SavePreValue()
_zw = NUMBERS[j]->name + "\t" + NUMBERS[j]->timeStamp + "\t" + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + "\n";
printf("Write PreValue Zeile: %s\n", _zw.c_str());
-
- fputs(_zw.c_str(), pFile);
+ if (pFile) {
+ fputs(_zw.c_str(), pFile);
+ }
}
UpdatePreValueINI = false;
@@ -568,8 +570,10 @@ void ClassFlowPostProcessing::InitNUMBERS()
NUMBERS.push_back(_number);
}
- for (int i = 0; i < NUMBERS.size(); ++i)
+ for (int i = 0; i < NUMBERS.size(); ++i) {
printf("Number %s, Anz DIG: %d, Anz ANA %d\n", NUMBERS[i]->name.c_str(), NUMBERS[i]->AnzahlDigital, NUMBERS[i]->AnzahlAnalog);
+ }
+
}
string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
@@ -660,27 +664,35 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
previous_value = zw - 48;
}
}
-
+ #ifdef SERIAL_DEBUG
+ printf("After analog->getReadout: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
+ #endif
if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
NUMBERS[j]->ReturnRawValue = "." + NUMBERS[j]->ReturnRawValue;
if (NUMBERS[j]->digit_roi)
{
if (NUMBERS[j]->analog_roi)
- NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, false, previous_value) + NUMBERS[j]->ReturnRawValue;
+ NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, false, previous_value, NUMBERS[j]->analog_roi->ROI[0]->result_float) + NUMBERS[j]->ReturnRawValue;
else
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution nur falls es keine analogen Ziffern gibt
}
-
+ #ifdef SERIAL_DEBUG
+ printf("After digital->getReadout: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
+ #endif
NUMBERS[j]->ReturnRawValue = ShiftDecimal(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->DecimalShift);
- printf("ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
-
+ #ifdef SERIAL_DEBUG
+ printf("After ShiftDecimal: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
+ #endif
if (IgnoreLeadingNaN)
while ((NUMBERS[j]->ReturnRawValue.length() > 1) && (NUMBERS[j]->ReturnRawValue[0] == 'N'))
NUMBERS[j]->ReturnRawValue.erase(0, 1);
+ #ifdef SERIAL_DEBUG
+ printf("After IgnoreLeadingNaN: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
+ #endif
NUMBERS[j]->ReturnValue = NUMBERS[j]->ReturnRawValue;
if (findDelimiterPos(NUMBERS[j]->ReturnValue, "N") != std::string::npos)
@@ -690,18 +702,38 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
else
continue; // es gibt keinen Zahl, da noch ein N vorhanden ist.
}
-
+ #ifdef SERIAL_DEBUG
+ printf("After findDelimiterPos: ReturnValue %s\n", NUMBERS[j]->ReturnRawValue.c_str());
+ #endif
// Lösche führende Nullen (außer es ist nur noch einen 0)
while ((NUMBERS[j]->ReturnValue.length() > 1) && (NUMBERS[j]->ReturnValue[0] == '0'))
NUMBERS[j]->ReturnValue.erase(0, 1);
-
- NUMBERS[j]->Value = std::stof(NUMBERS[j]->ReturnValue);
+ #ifdef SERIAL_DEBUG
+ printf("After removeLeadingZeros: ReturnValue %s\n", NUMBERS[j]->ReturnRawValue.c_str());
+ #endif
+ NUMBERS[j]->Value = std::stod(NUMBERS[j]->ReturnValue);
+ #ifdef SERIAL_DEBUG
+ printf("After setting the Value: Value %f and as double is %f\n", NUMBERS[j]->Value, std::stod(NUMBERS[j]->ReturnValue));
+ #endif
if (NUMBERS[j]->checkDigitIncreaseConsistency)
{
- NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue);
+ if (flowDigit)
+ {
+ if (flowDigit->getCNNType() != Digital)
+ printf("checkDigitIncreaseConsistency = true - ignored due to wrong CNN-Type (not Digital Classification)\n");
+ else
+ NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue);
+ }
+ else
+ {
+ printf("checkDigitIncreaseConsistency = true - no digital numbers defined!\n");
+ }
}
+ #ifdef SERIAL_DEBUG
+ printf("After checkDigitIncreaseConsistency: Value %f\n", NUMBERS[j]->Value);
+ #endif
if (!NUMBERS[j]->AllowNegativeRates)
@@ -714,7 +746,9 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
continue;
}
}
-
+ #ifdef SERIAL_DEBUG
+ printf("After AllowNegativeRates: Value %f\n", NUMBERS[j]->Value);
+ #endif
double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in Sekunden
difference /= 60;
NUMBERS[j]->FlowRateAct = (NUMBERS[j]->Value - NUMBERS[j]->PreValue) / difference;
@@ -722,7 +756,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
if (NUMBERS[j]->useMaxRateValue && PreValueUse && NUMBERS[j]->PreValueOkay)
{
- float _ratedifference;
+ double _ratedifference;
if (NUMBERS[j]->RateType == RateChange)
_ratedifference = NUMBERS[j]->FlowRateAct;
else
@@ -737,7 +771,9 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
continue;
}
}
-
+ #ifdef SERIAL_DEBUG
+ printf("After MaxRateCheck: Value %f\n", NUMBERS[j]->Value);
+ #endif
NUMBERS[j]->ReturnChangeAbsolute = RundeOutput(NUMBERS[j]->Value - NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
NUMBERS[j]->lastvalue = imagetime;
NUMBERS[j]->PreValue = NUMBERS[j]->Value;
@@ -815,7 +851,7 @@ string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror, i
return NUMBERS[_number]->ReturnValue;
}
-string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
+string ClassFlowPostProcessing::RundeOutput(double _in, int _anzNachkomma){
std::stringstream stream;
int _zw = _in;
// printf("AnzNachkomma: %d\n", _anzNachkomma);
@@ -839,7 +875,7 @@ string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
}
-string ClassFlowPostProcessing::ErsetzteN(string input, float _prevalue)
+string ClassFlowPostProcessing::ErsetzteN(string input, double _prevalue)
{
int posN, posPunkt;
int pot, ziffer;
@@ -870,7 +906,7 @@ string ClassFlowPostProcessing::ErsetzteN(string input, float _prevalue)
return input;
}
-float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue){
+float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilamshift, bool _isanalog, double _preValue){
int aktdigit, olddigit;
int aktdigit_before, olddigit_before;
int pot, pot_max;
@@ -882,8 +918,14 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
{
pot++;
}
+ #ifdef SERIAL_DEBUG
+ printf("checkDigitConsistency: pot=%d, decimalshift=%d\n", pot, _decilamshift);
+ #endif
pot_max = ((int) log10(input)) + 1;
-
+ float not_checked_input = floorf(input * pow(10, pot)) / pow(10, pot);
+ #ifdef SERIAL_DEBUG
+ printf("checkDigitConsistency: not_checked_input=%f\n", not_checked_input);
+ #endif
while (pot <= pot_max)
{
zw = input / pow(10, pot-1);
@@ -912,11 +954,13 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
input = input + ((float) (1)) * pow(10, pot); // addiere 1 an der Stelle
}
}
-
+ #ifdef SERIAL_DEBUG
+ printf("checkDigitConsistency: input=%f", input);
+ #endif
pot++;
}
- return input;
+ return not_checked_input + input;
}
string ClassFlowPostProcessing::getReadoutRate(int _number)
diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h
index 34b2309c..0d99958d 100644
--- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h
+++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h
@@ -32,9 +32,9 @@ protected:
bool LoadPreValue(void);
string ShiftDecimal(string in, int _decShift);
- string ErsetzteN(string, float _prevalue);
- float checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue);
- string RundeOutput(float _in, int _anzNachkomma);
+ string ErsetzteN(string, double _prevalue);
+ float checkDigitConsistency(double input, int _decilamshift, bool _isanalog, double _preValue);
+ string RundeOutput(double _in, int _anzNachkomma);
void InitNUMBERS();
void handleDecimalSeparator(string _decsep, string _value);
@@ -58,7 +58,7 @@ public:
string getReadoutTimeStamp(int _number = 0);
void SavePreValue();
string GetPreValue(std::string _number = "");
- void SetPreValue(float zw, string _numbers, bool _extern = false);
+ void SetPreValue(double zw, string _numbers, bool _extern = false);
std::string GetJSON(std::string _id = "", std::string _mac = "", std::string _lineend = "\n");
diff --git a/code/components/jomjol_helper/Helper.cpp b/code/components/jomjol_helper/Helper.cpp
index fe299f54..411553b0 100644
--- a/code/components/jomjol_helper/Helper.cpp
+++ b/code/components/jomjol_helper/Helper.cpp
@@ -209,6 +209,21 @@ size_t findDelimiterPos(string input, string delimiter)
return pos;
}
+void DeleteFile(string fn)
+{
+// ESP_LOGI(logTag, "Deleting file : %s", fn.c_str());
+ /* Delete file */
+ FILE* fpSourceFile = OpenFileAndWait(fn.c_str(), "rb");
+ if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
+ {
+ printf("DeleteFile: File %s existiert nicht!\n", fn.c_str());
+ return;
+ }
+ fclose(fpSourceFile);
+
+ unlink(fn.c_str());
+}
+
void CopyFile(string input, string output)
{
@@ -243,18 +258,48 @@ void CopyFile(string input, string output)
// Close The Files
fclose(fpSourceFile);
fclose(fpTargetFile);
+ printf("File copied: %s to %s", input.c_str(), output.c_str());
}
+string getFileFullFileName(string filename)
+{
+ size_t lastpos = filename.find_last_of('/');
+
+ if (lastpos == string::npos)
+ return "";
+
+// printf("Last position: %d\n", lastpos);
+
+ string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
+
+ return zw;
+}
+
+string getDirectory(string filename)
+{
+ size_t lastpos = filename.find('/');
+
+ if (lastpos == string::npos)
+ return "";
+
+// printf("Directory: %d\n", lastpos);
+
+ string zw = filename.substr(0, lastpos - 1);
+ return zw;
+}
string getFileType(string filename)
{
- int lastpos = filename.find(".", 0);
- int neu_pos;
+ size_t lastpos = filename.find(".", 0);
+ size_t neu_pos;
while ((neu_pos = filename.find(".", lastpos + 1)) > -1)
{
lastpos = neu_pos;
}
+ if (lastpos == string::npos)
+ return "";
+
string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
zw = toUpper(zw);
diff --git a/code/components/jomjol_helper/Helper.h b/code/components/jomjol_helper/Helper.h
index 46fbf8d6..ab263cf2 100644
--- a/code/components/jomjol_helper/Helper.h
+++ b/code/components/jomjol_helper/Helper.h
@@ -10,6 +10,7 @@ std::string FormatFileName(std::string input);
void FindReplace(std::string& line, std::string& oldString, std::string& newString);
void CopyFile(string input, string output);
+void DeleteFile(string fn);
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec = 1);
@@ -19,6 +20,8 @@ string trim(string istring, string adddelimiter = "");
bool ctype_space(const char c, string adddelimiter);
string getFileType(string filename);
+string getFileFullFileName(string filename);
+string getDirectory(string filename);
int mkdir_r(const char *dir, const mode_t mode);
int removeFolder(const char* folderPath, const char* logTag);
diff --git a/code/components/jomjol_logfile/ClassLogFile.cpp b/code/components/jomjol_logfile/ClassLogFile.cpp
index 04a4df4d..f462e7a4 100644
--- a/code/components/jomjol_logfile/ClassLogFile.cpp
+++ b/code/components/jomjol_logfile/ClassLogFile.cpp
@@ -73,7 +73,7 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool
// pFile = OpenFileAndWait(_fn.c_str(), "a");
pFile = fopen(_fn.c_str(), "a+");
- printf("Logfile opened: %s\n", _fn.c_str());
+// printf("Logfile opened: %s\n", _fn.c_str());
if (pFile!=NULL) {
if (_time)
@@ -129,6 +129,7 @@ void ClassLogFile::WriteToFile(std::string info, bool _time)
std::string logpath = logroot + "/" + buffer;
WriteToDedicatedFile(logpath, info, _time);
+ printf((info + "\n").c_str());
}
std::string ClassLogFile::GetCurrentFileName()
diff --git a/code/components/jomjol_mqtt/interface_mqtt.cpp b/code/components/jomjol_mqtt/interface_mqtt.cpp
index ef98aff4..556a50d8 100644
--- a/code/components/jomjol_mqtt/interface_mqtt.cpp
+++ b/code/components/jomjol_mqtt/interface_mqtt.cpp
@@ -19,18 +19,43 @@ esp_mqtt_event_id_t esp_mmqtt_ID = MQTT_EVENT_ANY;
bool mqtt_connected = false;
esp_mqtt_client_handle_t client = NULL;
-void MQTTPublish(std::string _key, std::string _content, int retained_flag){
- if (client && mqtt_connected) {
- int msg_id;
- std::string zw;
- msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
- zw = "sent publish successful in MQTTPublish, msg_id=" + std::to_string(msg_id) + ", " + _key + ", " + _content;
- if (debugdetail) LogFile.WriteToFile(zw);
- ESP_LOGD(TAG_INTERFACEMQTT, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
+bool MQTTPublish(std::string _key, std::string _content, int retained_flag){
+
+ // if (!client) {
+ // LogFile.WriteToFile("MQTT - client not initialized!");
+ // return false;
+ // }
+ // LogFile.WriteToFile("MQTT - client initialized!"); // Debug
+ //
+ // if (!mqtt_connected) {
+ // LogFile.WriteToFile("MQTT - Can not publish, not connected!");
+ // ESP_LOGW(TAG_INTERFACEMQTT, "Problem with Publish, client=%d, mqtt_connected %d", (int) client, (int) mqtt_connected);
+ // return false;
+ // }
+ // LogFile.WriteToFile("MQTT - connected!"); // Debug
+
+ /* if (client && mqtt_connected) {
+ LogFile.WriteToFile("MQTT - connected!"); // Debug
}
- else {
- ESP_LOGW(TAG_INTERFACEMQTT, "Problem with Publish, client=%d, mqtt_connected %d", (int) client, (int) mqtt_connected);
+ else { // init needed
+ if (!MQTTInit(this->uri, this->clientname, this->user, password, mainerrortopic, keepAlive)) // validate{
+ { // Failed
+ return false;
+ }
+ }*/
+
+
+ int msg_id;
+ std::string zw;
+ msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
+ if (msg_id < 0) {
+ LogFile.WriteToFile("MQTT - Failed to publish '" + _key + "'!");
+ return false;
}
+ zw = "MQTT - sent publish successful in MQTTPublish, msg_id=" + std::to_string(msg_id) + ", " + _key + ", " + _content;
+ if (debugdetail) LogFile.WriteToFile(zw);
+ ESP_LOGD(TAG_INTERFACEMQTT, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
+ return true;
}
@@ -90,11 +115,23 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
}
-void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive){
+
+bool MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive){
std::string _zwmessage = "connection lost";
int _lzw = _zwmessage.length();
+/* LWTContext = _LWTContext;
+
+ mqtt_cfg.uri = _mqttURI.c_str();
+ mqtt_cfg.client_id = _clientid.c_str();
+ mqtt_cfg.lwt_topic = _LWTContext.c_str();
+ mqtt_cfg.lwt_msg = _zwmessage.c_str();
+ mqtt_cfg.lwt_retain = 1;
+ mqtt_cfg.lwt_msg_len = _lzw;
+ mqtt_cfg.keepalive = _keepalive;
+*/
+
esp_mqtt_client_config_t mqtt_cfg = {
.uri = _mqttURI.c_str(),
.client_id = _clientid.c_str(),
@@ -105,12 +142,51 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st
.keepalive = _keepalive
};
+ LogFile.WriteToFile("MQTT - Init");
+
if (_user.length() && _password.length()){
mqtt_cfg.username = _user.c_str();
mqtt_cfg.password = _password.c_str();
ESP_LOGI(TAG_INTERFACEMQTT, "Connect to MQTT: %s, %s", mqtt_cfg.username, mqtt_cfg.password);
};
+ MQTTdestroy();
+ client = esp_mqtt_client_init(&mqtt_cfg);
+ if (client)
+ {
+ if (esp_mqtt_client_register_event(client, esp_mmqtt_ID, mqtt_event_handler, client) != ESP_OK)
+ {
+ LogFile.WriteToFile("MQTT - Could not register event!");
+ return false;
+ }
+ if (esp_mqtt_client_start(client) != ESP_OK)
+ {
+ LogFile.WriteToFile("MQTT - Could not start client!");
+ return false;
+ }
+
+ /* if(!MQTTPublish(_LWTContext, "", 1))
+ {
+ LogFile.WriteToFile("MQTT - Could not publish LWT!");
+ return false;
+ }*/
+ }
+ else
+ {
+ LogFile.WriteToFile("MQTT - Could not Init client!");
+ return false;
+ }
+
+ LogFile.WriteToFile("MQTT - Init successful");
+ return true;
+}
+
+/*
+void MQTTReConnect(){
+ std::string _zwmessage = "connection lost";
+ int _lzw = _zwmessage.length();
+
+>>>>>>> Stashed changes
client = esp_mqtt_client_init(&mqtt_cfg);
if (client)
{
@@ -119,14 +195,25 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st
if (esp_mqtt_client_start(client) != ESP_OK)
LogFile.WriteToFile("MQTT - Could not start client!");
- MQTTPublish(_LWTContext, "", 1);
+<<<<<<< Updated upstream
+ if(MQTTPublish(_LWTContext, "", 1)) {
+ LogFile.WriteToFile("MQTT - Client init successful");
+ }
+=======
+ if (mqtt_connected)
+ MQTTPublish(LWTContext, "", 1);
+ else
+ LogFile.WriteToFile("Problem with (Re)Connection not successful!");
+
+>>>>>>> Stashed changes
}
else
{
- LogFile.WriteToFile("MQTT - Could not Init MQTT Client!");
+ LogFile.WriteToFile("MQTT - Could not Init client!");
}
}
+*/
void MQTTdestroy() {
if (client != NULL) {
@@ -185,6 +272,7 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
it->second();
@@ -192,10 +280,11 @@ void MQTTconnected(){
}
}
- if (subscribeFunktionMap != NULL) {
+ if (subscribeFunktionMap != NULL) {
for(std::map>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
ESP_LOGD(TAG_INTERFACEMQTT, "topic %s subscribe successful, msg_id=%d", it->first.c_str(), msg_id);
+ LogFile.WriteToFile("MQTT - topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
}
}
}
diff --git a/code/components/jomjol_mqtt/interface_mqtt.h b/code/components/jomjol_mqtt/interface_mqtt.h
index 397d1787..06210782 100644
--- a/code/components/jomjol_mqtt/interface_mqtt.h
+++ b/code/components/jomjol_mqtt/interface_mqtt.h
@@ -5,12 +5,12 @@
#include