diff --git a/core/el_types.h b/core/el_types.h index 6aec7d6b..93ce0b82 100644 --- a/core/el_types.h +++ b/core/el_types.h @@ -150,6 +150,11 @@ typedef struct EL_ATTR_PACKED el_sensor_info_t { el_sensor_state_t state; } el_sensor_info_t; +typedef struct el_sensor_opt_t { + uint8_t id; + const char* details; +} el_sensor_opt_t; + typedef enum { EL_MODEL_FMT_UNDEFINED = 0u, EL_MODEL_FMT_PACKED_TFLITE = 1u, diff --git a/docs/protocol/at_protocol.md b/docs/protocol/at_protocol.md index 4f42349d..a4da50b6 100644 --- a/docs/protocol/at_protocol.md +++ b/docs/protocol/at_protocol.md @@ -305,7 +305,14 @@ Response: { "id": 1, "type": 1, - "state": 1 + "state": 1, + "opt_id": 0, + "opt_detail": "240x240 Auto", + "opts": { + "2": "640x480 Auto", + "1": "480x480 Auto", + "0": "240x240 Auto" + } } ] }\n @@ -327,7 +334,9 @@ Response: "data": { "id": 1, "type": 1, - "state": 1 + "state": 1, + "opt_id": 0, + "opt_detail": "240x240 Auto" } }\n ``` @@ -572,9 +581,9 @@ Note: `"model": {..., "type": , ...}`. #### Set a default sensor by sensor ID -Pattern: `AT+SENSOR=\r` +Pattern: `AT+SENSOR=\r` -Request: `AT+SENSOR=1,1\r` +Request: `AT+SENSOR=1,1,0\r` Response: @@ -587,7 +596,9 @@ Response: "sensor": { "id": 1, "type": 1, - "state": 1 + "state": 1, + "opt_id": 0, + "opt_detail": "240x240 Auto" } } }\n diff --git a/porting/el_camera.h b/porting/el_camera.h index 825f1cca..04158a30 100644 --- a/porting/el_camera.h +++ b/porting/el_camera.h @@ -28,6 +28,7 @@ #include #include +#include #include "core/el_types.h" @@ -35,11 +36,30 @@ namespace edgelab { class Camera { public: - Camera() : _is_present(false), _is_streaming(false) {} + using SensorOptIdType = decltype(el_sensor_opt_t::id); + + Camera(uint32_t supported_opts_mask = 0) : _is_present(false), _is_streaming(false) { + std::forward_list presets = { + el_sensor_opt_t{.id = 0, .details = "240x240 Auto"}, + el_sensor_opt_t{.id = 1, .details = "480x480 Auto"}, + el_sensor_opt_t{.id = 2, .details = "640x480 Auto"}, + el_sensor_opt_t{.id = 3, .details = "1280x720 Auto"}, + el_sensor_opt_t{.id = 4, .details = "1920x1080 Auto"} + }; + + for (auto& opt : presets) { + if (supported_opts_mask & (1 << opt.id)) _supported_opts.push_front(opt); + } + + if (!_supported_opts.empty()) { + _current_opt_id = _supported_opts.front().id; + } + } + virtual ~Camera() = default; - virtual el_err_code_t init(size_t width, size_t height) = 0; - virtual el_err_code_t deinit() = 0; + virtual el_err_code_t init(SensorOptIdType opt_id) = 0; + virtual el_err_code_t deinit() = 0; virtual el_err_code_t start_stream() = 0; virtual el_err_code_t stop_stream() = 0; @@ -51,9 +71,21 @@ class Camera { bool is_streaming() const { return _is_streaming; } + SensorOptIdType current_opt_id() const { return _current_opt_id; } + const char* current_opt_detail() const { + for (auto& opt : _supported_opts) { + if (opt.id == _current_opt_id) return opt.details; + } + return "Unknown"; + } + const std::forward_list& supported_opts() const { return _supported_opts; } + protected: volatile bool _is_present; volatile bool _is_streaming; + + SensorOptIdType _current_opt_id; + std::forward_list _supported_opts; }; } // namespace edgelab diff --git a/porting/espressif/el_camera_esp.cpp b/porting/espressif/el_camera_esp.cpp index 1f4e41b1..a733fce9 100644 --- a/porting/espressif/el_camera_esp.cpp +++ b/porting/espressif/el_camera_esp.cpp @@ -34,7 +34,13 @@ namespace edgelab { -el_err_code_t CameraEsp::init(size_t width, size_t height) { +CameraEsp::CameraEsp() : Camera(0b00000001), config(), fb(nullptr), sensor(nullptr) {} + +el_err_code_t CameraEsp::init(SensorOptIdType opt_id) { + if ((1 << opt_id) != 0b00000001) { + return EL_EINVAL; + } + config.ledc_channel = LEDC_CHANNEL_0; config.ledc_timer = LEDC_TIMER_0; config.pin_d0 = CAMERA_PIN_D0; diff --git a/porting/espressif/el_camera_esp.h b/porting/espressif/el_camera_esp.h index 34df7d75..a492ae81 100644 --- a/porting/espressif/el_camera_esp.h +++ b/porting/espressif/el_camera_esp.h @@ -35,10 +35,10 @@ namespace edgelab { class CameraEsp final : public Camera { public: - CameraEsp() = default; + CameraEsp(); ~CameraEsp() = default; - el_err_code_t init(size_t width, size_t height) override; + el_err_code_t init(SensorOptIdType opt_id) override; el_err_code_t deinit() override; el_err_code_t start_stream() override; diff --git a/porting/himax/we1/el_camera_we1.cpp b/porting/himax/we1/el_camera_we1.cpp index 5acb102d..995f124a 100644 --- a/porting/himax/we1/el_camera_we1.cpp +++ b/porting/himax/we1/el_camera_we1.cpp @@ -32,8 +32,14 @@ extern "C" { namespace edgelab { -el_err_code_t CameraWE1::init(size_t width, size_t height) { - ERROR_T ret = ERROR_NONE; +CameraWE1::CameraWE1() : Camera(0b00000001) {} + +el_err_code_t CameraWE1::init(SensorOptIdType opt_id) { + ERROR_T ret = ERROR_NONE; + + uint16_t width = 240; + uint16_t height = 240; + this->config.sensor_type = SENSOR_CAMERA; this->config.data.camera_cfg.width = width; this->config.data.camera_cfg.height = height; diff --git a/porting/himax/we1/el_camera_we1.h b/porting/himax/we1/el_camera_we1.h index 6d6f142a..d2af483d 100644 --- a/porting/himax/we1/el_camera_we1.h +++ b/porting/himax/we1/el_camera_we1.h @@ -38,10 +38,10 @@ namespace edgelab { class CameraWE1 final : public Camera { public: - CameraWE1() = default; + CameraWE1(); ~CameraWE1() = default; - el_err_code_t init(size_t width, size_t height) override; + el_err_code_t init(SensorOptIdType opt_id) override; el_err_code_t deinit() override; el_err_code_t start_stream() override; diff --git a/porting/himax/we2/drivers/drv_common.h b/porting/himax/we2/drivers/drv_common.h new file mode 100644 index 00000000..7eef5363 --- /dev/null +++ b/porting/himax/we2/drivers/drv_common.h @@ -0,0 +1,27 @@ +#ifndef _DRV_COMMON_H_ +#define _DRV_COMMON_H_ + +#include +#include +#include + +el_res_t _drv_fit_res(uint16_t width, uint16_t height) { + el_res_t res; + + if (width > 320 || height > 240) { + res.width = 640; + res.height = 480; + } else if (width > 160 || height > 120) { + res.width = 320; + res.height = 240; + } else { + res.width = 160; + res.height = 120; + } + + EL_LOGD("fit width: %d height: %d", res.width, res.height); + + return res; +} + +#endif diff --git a/porting/himax/we2/drivers/drv_hm0360.c b/porting/himax/we2/drivers/drv_hm0360.c index 8dc9b45b..7c2b6849 100644 --- a/porting/himax/we2/drivers/drv_hm0360.c +++ b/porting/himax/we2/drivers/drv_hm0360.c @@ -1,5 +1,8 @@ #include "drv_hm0360.h" +#include "drv_common.h" +#include "drv_shared_cfg.h" + static HX_CIS_SensorSetting_t HM0360_init_setting[] = { #include "HM0360_24MHz_Bayer_640x480_setA_VGA_setB_QVGA_MIPI_4b_ParallelOutput_R2.i" }; @@ -18,40 +21,31 @@ static HX_CIS_SensorSetting_t HM0360_stream_xsleep[] = { static volatile bool _frame_ready = false; static volatile uint32_t _frame_count = 0; -static volatile uint32_t _wdma1_baseaddr = 0x36000000; -static volatile uint32_t _wdma2_baseaddr = 0; -static volatile uint32_t _wdma3_baseaddr = 0; -static volatile uint32_t _jpegsize_baseaddr = 0; +static volatile uint32_t _wdma1_baseaddr = HW1_ADDR_BASE; +static volatile uint32_t _wdma2_baseaddr = JPEG_BASE_ADDR; +static volatile uint32_t _wdma3_baseaddr = YUV422_BASE_ADDR; +static volatile uint32_t _jpegsize_baseaddr = JPEG_SZ_BASE_ADDR; static el_img_t _frame, _jpeg; -el_res_t _drv_hm0360_fit_res(uint16_t width, uint16_t height) { - el_res_t res; - if (width > 320 || height > 240) { - res.width = 640; - res.height = 480; - } else if (width > 160 || height > 120) { - res.width = 320; - res.height = 240; - } else { - res.width = 160; - res.height = 120; - } - EL_LOGD("fit width: %d height: %d", res.width, res.height); - return res; +static void memset_fb() { + memset((void*)_wdma1_baseaddr, 0, HW1_ADDR_SIZE); + memset((void*)_wdma2_baseaddr, 0, JPEG_SIZE_MAX); + memset((void*)_wdma3_baseaddr, 0, YUV422_SIZE_MAX); + memset((void*)_jpegsize_baseaddr, 0, JPEG_SZ_SIZE); } -void drv_hm0360_cb(SENSORDPLIB_STATUS_E event) { - // EL_LOGD("Event: %d", event); +static void drv_hm0360_cb(SENSORDPLIB_STATUS_E event) { + EL_LOGD("Event: %d", event); + switch (event) { case SENSORDPLIB_STATUS_XDMA_FRAME_READY: _frame_ready = true; _frame_count++; break; default: - EL_LOGD("unkonw event"); + EL_LOGW("Unkonw event: %d", event); break; } - return; } el_err_code_t drv_hm0360_init(uint16_t width, uint16_t height) { @@ -106,41 +100,30 @@ el_err_code_t drv_hm0360_init(uint16_t width, uint16_t height) { goto err; } - res = _drv_hm0360_fit_res(width, height); + res = _drv_fit_res(width, height); start_x = (res.width - width) / 2; start_y = (res.height - height) / 2; EL_LOGD("start_x: %d start_y: %d width: %d height: %d", start_x, start_y, width, height); - // DMA - if (!_jpegsize_baseaddr) - _jpegsize_baseaddr = (uint32_t)el_aligned_malloc_once(32, 64); - if (_jpegsize_baseaddr == 0) { - ret = EL_ENOMEM; - goto err; - } + _frame.width = width; + _frame.height = height; + _frame.rotate = EL_PIXEL_ROTATE_0; + _frame.format = EL_PIXEL_FORMAT_YUV422; + _frame.size = width * height * 3 / 2; - { - size_t bs = (((623 + (size_t)(res.width / 16) * (size_t)(res.height / 16) * 128 + 35) >> 2) << 2); - if (!_wdma1_baseaddr) - _wdma1_baseaddr = (uint32_t)el_aligned_malloc_once(32, bs); // JPEG - } - if (_wdma1_baseaddr == 0) { - ret = EL_ENOMEM; - goto err; - } - _wdma2_baseaddr = _wdma1_baseaddr; + _jpeg.width = width; + _jpeg.height = height; + _jpeg.rotate = EL_PIXEL_ROTATE_0; + _jpeg.format = EL_PIXEL_FORMAT_JPEG; + _jpeg.size = width * height / 4; - if (!_wdma3_baseaddr) - _wdma3_baseaddr = (uint32_t)el_aligned_malloc_once(32, res.width * res.height * 3 / 2); - if (_wdma3_baseaddr == 0) { - ret = EL_ENOMEM; - goto err; - } + // DMA + memset_fb(); - sensordplib_set_xDMA_baseaddrbyapp(_wdma1_baseaddr, _wdma2_baseaddr, _wdma3_baseaddr); - sensordplib_set_jpegfilesize_addrbyapp(_jpegsize_baseaddr); + _frame.data = _wdma3_baseaddr; + _jpeg.data = _wdma2_baseaddr; EL_LOGD("WD1[%x], WD2_J[%x], WD3_RAW[%x], JPAuto[%x]", _wdma1_baseaddr, @@ -148,22 +131,10 @@ el_err_code_t drv_hm0360_init(uint16_t width, uint16_t height) { _wdma3_baseaddr, _jpegsize_baseaddr); - _frame.data = _wdma3_baseaddr; - _frame.size = width * height * 3 / 2; - _frame.height = height; - _frame.width = width; - _frame.rotate = EL_PIXEL_ROTATE_0; - _frame.format = EL_PIXEL_FORMAT_YUV422; - - _jpeg.data = _wdma2_baseaddr; - _jpeg.size = width * height / 4; - _jpeg.height = height; - _jpeg.width = width; - _jpeg.rotate = EL_PIXEL_ROTATE_0; - _jpeg.format = EL_PIXEL_FORMAT_JPEG; + sensordplib_set_xDMA_baseaddrbyapp(_wdma1_baseaddr, _wdma2_baseaddr, _wdma3_baseaddr); + sensordplib_set_jpegfilesize_addrbyapp(_jpegsize_baseaddr); // datapath init - if (HM0360_MAX_WIDTH / res.width == 3) { sensordplib_set_sensorctrl_inp(SENSORDPLIB_SENSOR_HM0360_MODE3, SENSORDPLIB_STREAM_NONEAOS, @@ -226,21 +197,9 @@ el_err_code_t drv_hm0360_init(uint16_t width, uint16_t height) { err: // power off EL_LOGD("hm0360 init failed!"); + hx_drv_sensorctrl_set_xSleep(0); - // if (_jpegsize_baseaddr != 0) { - // el_free(_jpegsize_baseaddr); - // _jpegsize_baseaddr = 0; - // } - // if (_wdma3_baseaddr != 0) { - // el_free(_wdma3_baseaddr); - // _wdma3_baseaddr = 0; - // } - // if (_wdma1_baseaddr) { - // el_free(_wdma3_baseaddr); - // _wdma1_baseaddr = 0; - // _wdma2_baseaddr = 0; - // } return ret; } @@ -249,13 +208,16 @@ el_err_code_t drv_hm0360_deinit() { sensordplib_stop_capture(); sensordplib_start_swreset(); sensordplib_stop_swreset_WoSensorCtrl(); + // stream off if (hx_drv_cis_setRegTable(HM0360_stream_off, HX_CIS_SIZE_N(HM0360_stream_off, HX_CIS_SensorSetting_t)) != HX_CIS_NO_ERROR) { return EL_EIO; } + // power off hx_drv_sensorctrl_set_xSleep(0); + return EL_OK; } @@ -266,14 +228,14 @@ el_err_code_t drv_hm0360_capture(uint32_t timeout) { if (el_get_time_ms() - time >= timeout) { return EL_ETIMOUT; } - el_sleep(1); + el_sleep(5); } return EL_OK; } -el_err_code_t drv_hm0360_capture_stop(){ - _frame_ready = false; +el_err_code_t drv_hm0360_capture_stop() { + _frame_ready = false; sensordplib_retrigger_capture(); return EL_OK; @@ -284,17 +246,23 @@ el_img_t drv_hm0360_get_frame() { return _frame; } el_img_t drv_hm0360_get_jpeg() { uint8_t frame_no, buffer_no = 0; uint32_t reg_val = 0, mem_val = 0; + hx_drv_xdma_get_WDMA2_bufferNo(&buffer_no); hx_drv_xdma_get_WDMA2NextFrameIdx(&frame_no); + if (frame_no == 0) { frame_no = buffer_no - 1; } else { frame_no = frame_no - 1; } + hx_drv_jpeg_get_EncOutRealMEMSize(®_val); hx_drv_jpeg_get_FillFileSizeToMem(frame_no, (uint32_t)_jpegsize_baseaddr, &mem_val); hx_drv_jpeg_get_MemAddrByFrameNo(frame_no, _wdma2_baseaddr, &_jpeg.data); + _jpeg.size = mem_val == reg_val ? mem_val : reg_val; + hx_InvalidateDCache_by_Addr((volatile void*)_jpeg.data, _jpeg.size); + return _jpeg; } diff --git a/porting/himax/we2/drivers/drv_ov5647.c b/porting/himax/we2/drivers/drv_ov5647.c index ac45f0ac..49043a72 100644 --- a/porting/himax/we2/drivers/drv_ov5647.c +++ b/porting/himax/we2/drivers/drv_ov5647.c @@ -1,5 +1,8 @@ #include "drv_ov5647.h" +#include "drv_common.h" +#include "drv_shared_cfg.h" + static HX_CIS_SensorSetting_t OV5647_init_setting[] = { #if (OV5647_MIPI_MODE == OV5647_MIPI_640X480) #include "OV5647_mipi_2lane_640x480.i" @@ -23,55 +26,34 @@ static HX_CIS_SensorSetting_t OV5647_stream_off[] = { static volatile bool _frame_ready = false; static volatile uint32_t _frame_count = 0; -static volatile uint32_t _wdma1_baseaddr = 0x36000000; -static volatile uint32_t _wdma2_baseaddr = 0; -static volatile uint32_t _wdma3_baseaddr = 0; -static volatile uint32_t _jpegsize_baseaddr = 0; +static volatile uint32_t _wdma1_baseaddr = HW1_ADDR_BASE; +static volatile uint32_t _wdma2_baseaddr = JPEG_BASE_ADDR; +static volatile uint32_t _wdma3_baseaddr = YUV422_BASE_ADDR; +static volatile uint32_t _jpegsize_baseaddr = JPEG_SZ_BASE_ADDR; static el_img_t _frame, _jpeg; -el_res_t _drv_ov5647_fit_res(uint16_t width, uint16_t height) { - el_res_t res; - if (width > 320 || height > 240) { - res.width = 640; - res.height = 480; - } else if (width > 160 || height > 120) { - res.width = 320; - res.height = 240; - } else { - res.width = 160; - res.height = 120; - } - // if (width > 480 || height > 320) { - // res.width = 960; - // res.height = 540; - // } else if (width > 240 || height > 160) { - // res.width = 480; - // res.height = 270; - // } else { - // res.width = 240; - // res.height = 135; - // } - EL_LOGD("fit width: %d height: %d", res.width, res.height); - - return res; +static void memset_fb() { + memset((void*)_wdma1_baseaddr, 0, HW1_ADDR_SIZE); + memset((void*)_wdma2_baseaddr, 0, JPEG_SIZE_MAX); + memset((void*)_wdma3_baseaddr, 0, YUV422_SIZE_MAX); + memset((void*)_jpegsize_baseaddr, 0, JPEG_SZ_SIZE); } -void drv_ov5647_cb(SENSORDPLIB_STATUS_E event) { - // EL_LOGD("Event: %d", event); +static void drv_ov5647_cb(SENSORDPLIB_STATUS_E event) { + EL_LOGD("Event: %d", event); + switch (event) { case SENSORDPLIB_STATUS_XDMA_FRAME_READY: _frame_ready = true; _frame_count++; break; default: - el_printf("Unkonw event:%d", event); - + EL_LOGW("Unkonw event: %d", event); break; } - return; } -void set_mipi_csirx_enable() { +static void set_mipi_csirx_enable() { uint32_t mipi_pixel_clk = 96; hx_drv_scu_get_freq(SCU_CLK_FREQ_TYPE_HSC_MIPI_RXCLK, &mipi_pixel_clk); @@ -227,6 +209,7 @@ el_err_code_t drv_ov5647_init(uint16_t width, uint16_t height) { EL_LOGD("hx_drv_cis_set_slaveID(0x%02X)", CIS_I2C_ID); el_sleep(3); + // off stream if (hx_drv_cis_setRegTable(OV5647_stream_off, HX_CIS_SIZE_N(OV5647_stream_off, HX_CIS_SensorSetting_t)) != HX_CIS_NO_ERROR) { @@ -251,7 +234,7 @@ el_err_code_t drv_ov5647_init(uint16_t width, uint16_t height) { goto err; } - res = _drv_ov5647_fit_res(width, height); + res = _drv_fit_res(width, height); start_x = (res.width - width) / 2; start_y = (res.height - height) / 2; @@ -260,39 +243,20 @@ el_err_code_t drv_ov5647_init(uint16_t width, uint16_t height) { set_mipi_csirx_enable(); - _frame.height = height; _frame.width = width; + _frame.height = height; _frame.rotate = EL_PIXEL_ROTATE_0; _frame.format = EL_PIXEL_FORMAT_YUV422; _frame.size = width * height * 3 / 2; - _jpeg.height = height; _jpeg.width = width; + _jpeg.height = height; _jpeg.rotate = EL_PIXEL_ROTATE_0; _jpeg.format = EL_PIXEL_FORMAT_JPEG; _jpeg.size = width * height / 4; // DMA - if (!_jpegsize_baseaddr) _jpegsize_baseaddr = (uint32_t)el_aligned_malloc_once(32, 64); - if (_jpegsize_baseaddr == 0) { - ret = EL_ENOMEM; - goto err; - } - - { - size_t bs = (((623 + (size_t)(res.width / 16) * (size_t)(res.height / 16) * 128 + 35) >> 2) << 2); - if (!_wdma1_baseaddr) _wdma1_baseaddr = (uint32_t)el_aligned_malloc_once(32, bs); // JPEG - } - if (_wdma1_baseaddr == 0) { - ret = EL_ENOMEM; - goto err; - } - _wdma2_baseaddr = _wdma1_baseaddr; - if (!_wdma3_baseaddr) _wdma3_baseaddr = (uint32_t)el_aligned_malloc_once(32, res.width * res.height * 3 / 2); - if (_wdma3_baseaddr == 0) { - ret = EL_ENOMEM; - goto err; - } + memset_fb(); _frame.data = _wdma3_baseaddr; _jpeg.data = _wdma2_baseaddr; @@ -321,6 +285,7 @@ el_err_code_t drv_ov5647_init(uint16_t width, uint16_t height) { crop, OV5647_BINNING_0); break; + case 320: sensordplib_set_sensorctrl_inp_wi_crop_bin(SENSORDPLIB_SENSOR_OV5647, SENSORDPLIB_STREAM_NONEAOS, @@ -330,6 +295,7 @@ el_err_code_t drv_ov5647_init(uint16_t width, uint16_t height) { crop, OV5647_BINNING_1); break; + case 160: sensordplib_set_sensorctrl_inp_wi_crop_bin(SENSORDPLIB_SENSOR_OV5647, SENSORDPLIB_STREAM_NONEAOS, @@ -386,19 +352,6 @@ el_err_code_t drv_ov5647_init(uint16_t width, uint16_t height) { hx_drv_sensorctrl_set_xSleep(0); - // if (_jpegsize_baseaddr != 0) { - // el_free(_jpegsize_baseaddr); - // _jpegsize_baseaddr = 0; - // } - // if (_wdma3_baseaddr != 0) { - // el_free(_wdma3_baseaddr); - // _wdma3_baseaddr = 0; - // } - // if (_wdma1_baseaddr) { - // el_free(_wdma3_baseaddr); - // _wdma1_baseaddr = 0; - // _wdma2_baseaddr = 0; - // } return ret; } @@ -414,18 +367,21 @@ el_err_code_t drv_ov5647_deinit() { return EL_EIO; } set_mipi_csirx_disable(); + // power off hx_drv_sensorctrl_set_xSleep(1); + return EL_OK; } el_err_code_t drv_ov5647_capture(uint32_t timeout) { uint32_t time = el_get_time_ms(); + while (!_frame_ready) { if (el_get_time_ms() - time >= timeout) { return EL_ETIMOUT; } - el_sleep(1); + el_sleep(5); } return EL_OK; @@ -443,18 +399,25 @@ el_img_t drv_ov5647_get_frame() { return _frame; } el_img_t drv_ov5647_get_jpeg() { uint8_t frame_no, buffer_no = 0; uint32_t reg_val = 0, mem_val = 0; + hx_drv_xdma_get_WDMA2_bufferNo(&buffer_no); hx_drv_xdma_get_WDMA2NextFrameIdx(&frame_no); + if (frame_no == 0) { frame_no = buffer_no - 1; } else { frame_no = frame_no - 1; } + hx_drv_jpeg_get_EncOutRealMEMSize(®_val); hx_drv_jpeg_get_FillFileSizeToMem(frame_no, (uint32_t)_jpegsize_baseaddr, &mem_val); hx_drv_jpeg_get_MemAddrByFrameNo(frame_no, _wdma2_baseaddr, &_jpeg.data); + _jpeg.size = mem_val == reg_val ? mem_val : reg_val; + hx_InvalidateDCache_by_Addr((volatile void*)_jpeg.data, _jpeg.size); + EL_LOGD("JPEG size: %d", _jpeg.size); + return _jpeg; } diff --git a/porting/himax/we2/drivers/drv_ov5647.h b/porting/himax/we2/drivers/drv_ov5647.h index 9218c090..0cfc5e83 100644 --- a/porting/himax/we2/drivers/drv_ov5647.h +++ b/porting/himax/we2/drivers/drv_ov5647.h @@ -76,12 +76,12 @@ #define OV5647_MIPI_MODE OV5647_MIPI_1296X972 #if (OV5647_MIPI_MODE == OV5647_MIPI_640X480) - #define OV5647_SENSOR_WIDTH 640 - #define OV5647_SENSOR_HEIGHT 480 - #define OV5647_SUB_SAMPLE INP_SUBSAMPLE_DISABLE - #define OV5647_BINNING_0 INP_BINNING_DISABLE - #define OV5647_BINNING_1 INP_BINNING_4TO2_B - #define OV5647_BINNING_2 INP_BINNING_8TO2_B + #define OV5647_SENSOR_WIDTH 640 + #define OV5647_SENSOR_HEIGHT 480 + #define OV5647_SUB_SAMPLE INP_SUBSAMPLE_DISABLE + #define OV5647_BINNING_0 INP_BINNING_DISABLE + #define OV5647_BINNING_1 INP_BINNING_4TO2_B + #define OV5647_BINNING_2 INP_BINNING_8TO2_B #elif (OV5647_MIPI_MODE == OV5647_MIPI_2592X1944) #define OV5647_SENSOR_WIDTH 2592 #define OV5647_SENSOR_HEIGHT 1944 diff --git a/porting/himax/we2/drivers/drv_shared_cfg.h b/porting/himax/we2/drivers/drv_shared_cfg.h new file mode 100644 index 00000000..87d0b9fc --- /dev/null +++ b/porting/himax/we2/drivers/drv_shared_cfg.h @@ -0,0 +1,21 @@ +#ifndef _DRV_SHARED_CFG_H_ +#define _DRV_SHARED_CFG_H_ + +#define FRAME_WIDTH_MAX 640 +#define FRAME_HEIGHT_MAX 480 + +#define HW1_ADDR_BASE 0x36000000 +#define HW1_ADDR_SIZE 0 + +#define JPEG_10X_SIZE_EXP(w, h) (((623 + (size_t)(w / 16) * (size_t)(h / 16) * 128 + 35) >> 2) << 2) +#define JPEG_BASE_ADDR (HW1_ADDR_BASE + HW1_ADDR_SIZE) +#define JPEG_SIZE_MAX JPEG_10X_SIZE_EXP(FRAME_WIDTH_MAX, FRAME_HEIGHT_MAX) // 150KB + +#define JPEG_SZ_BASE_ADDR (JPEG_BASE_ADDR + JPEG_SIZE_MAX) +#define JPEG_SZ_SIZE 0x1000 // 4KB + +#define YUV422_SIZE_EXP(w, h) (w * h * 3 / 2) +#define YUV422_BASE_ADDR 0x3418F800 +#define YUV422_SIZE_MAX YUV422_SIZE_EXP(FRAME_WIDTH_MAX, FRAME_HEIGHT_MAX) // 450KB + +#endif diff --git a/porting/himax/we2/el_camera_hm0360.cpp b/porting/himax/we2/el_camera_hm0360.cpp deleted file mode 100644 index c95c2247..00000000 --- a/porting/himax/we2/el_camera_hm0360.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2023 Hongtai Liu (Seeed Technology Inc.) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "el_camera_hm0360.h" - -extern "C" { -#include -#include -} - -namespace edgelab { - -el_err_code_t CameraHM0360::init(size_t width, size_t height) { - EL_ASSERT(!this->_is_present); - auto ret = drv_hm0360_init(width, height); - this->_is_present = ret == EL_OK; - return ret; -} - -el_err_code_t CameraHM0360::deinit() { - auto ret = drv_hm0360_deinit(); - this->_is_present = false; - return ret; -} - -el_err_code_t CameraHM0360::start_stream() { - this->_is_streaming = true; - return drv_hm0360_capture(2000); -} - -el_err_code_t CameraHM0360::stop_stream() { - if (this->_is_streaming) { - this->_is_streaming = false; - return drv_hm0360_capture_stop(); - } - return EL_OK; -} - -el_err_code_t CameraHM0360::get_frame(el_img_t* img) { - if (!this->_is_streaming) { - return EL_EIO; - } - *img = drv_hm0360_get_frame(); - el_printf("frame:%08x, size: %d\n", img->data, img->size); - return EL_OK; -} - -el_err_code_t CameraHM0360::get_processed_frame(el_img_t* img) { - if (!this->_is_streaming) { - return EL_EIO; - } - *img = drv_hm0360_get_jpeg(); - el_printf("jpeg:%08x, size: %d\n", img->data, img->size); - return EL_OK; -} - -} // namespace edgelab diff --git a/porting/himax/we2/el_camera_ov5647.cpp b/porting/himax/we2/el_camera_ov5647.cpp deleted file mode 100644 index e4c10a7e..00000000 --- a/porting/himax/we2/el_camera_ov5647.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2023 Hongtai Liu (Seeed Technology Inc.) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#include "el_camera_ov5647.h" - -extern "C" { -#include -#include -} - -namespace edgelab { - -el_err_code_t CameraOV5647::init(size_t width, size_t height) { - EL_ASSERT(!this->_is_present); - auto ret = drv_ov5647_init(width, height); - this->_is_present = ret == EL_OK; - return ret; -} - -el_err_code_t CameraOV5647::deinit() { - auto ret = drv_ov5647_deinit(); - this->_is_present = false; - return ret; -} - -el_err_code_t CameraOV5647::start_stream() { - this->_is_streaming = true; - return drv_ov5647_capture(2000); -} - -el_err_code_t CameraOV5647::stop_stream() { - if (this->_is_streaming) { - this->_is_streaming = false; - return drv_ov5647_capture_stop(); - } - return EL_OK; -} - -el_err_code_t CameraOV5647::get_frame(el_img_t* img) { - if (!this->_is_streaming) [[likely]] { - return EL_EIO; - } - *img = drv_ov5647_get_frame(); - return EL_OK; -} - -el_err_code_t CameraOV5647::get_processed_frame(el_img_t* img) { - if (!this->_is_streaming) [[likely]] { - return EL_EIO; - } - *img = drv_ov5647_get_jpeg(); - return EL_OK; -} - -} // namespace edgelab diff --git a/porting/himax/we2/el_camera_ov5647.h b/porting/himax/we2/el_camera_ov5647.h deleted file mode 100644 index 60d1d4ae..00000000 --- a/porting/himax/we2/el_camera_ov5647.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2023 Hongtai Liu (Seeed Technology Inc.) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ - -#ifndef _EL_CAMERA_OV5647_H_ -#define _EL_CAMERA_OV5647_H_ - -#include "core/el_types.h" -#include "porting/el_camera.h" - -namespace edgelab { - -class CameraOV5647 final : public Camera { - public: - CameraOV5647() = default; - ~CameraOV5647() = default; - - el_err_code_t init(size_t width, size_t height) override; - el_err_code_t deinit() override; - - el_err_code_t start_stream() override; - el_err_code_t stop_stream() override; - - el_err_code_t get_frame(el_img_t* img) override; - el_err_code_t get_processed_frame(el_img_t* img) override; -}; - -} // namespace edgelab - -#endif diff --git a/porting/himax/we2/el_camera_we2.cpp b/porting/himax/we2/el_camera_we2.cpp new file mode 100644 index 00000000..889e2e31 --- /dev/null +++ b/porting/himax/we2/el_camera_we2.cpp @@ -0,0 +1,136 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2023 nullptr (Seeed Technology Inc.) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +#include "el_camera_we2.h" + +extern "C" { +#include +#include +} + +namespace edgelab { + +CameraWE2::CameraWE2() : Camera(0b00000111) {} + +el_err_code_t CameraWE2::init(SensorOptIdType opt_id) { + if (this->_is_present) [[unlikely]] { + return EL_OK; + } + + auto ret = EL_OK; + switch (opt_id) { + case 0: + ret = drv_ov5647_init(240, 240); + this->_current_opt_id = 0; + break; + case 1: + ret = drv_ov5647_init(480, 480); + this->_current_opt_id = 1; + break; + case 2: + ret = drv_ov5647_init(640, 480); + this->_current_opt_id = 2; + break; + default: + ret = EL_EINVAL; + } + + if (ret == EL_OK) [[likely]] { + this->_is_present = true; + } + + return ret; +} + +el_err_code_t CameraWE2::deinit() { + if (!this->_is_present) [[unlikely]] { + return EL_OK; + } + + + auto ret = drv_ov5647_deinit(); + + if (ret == EL_OK) [[likely]] { + this->_is_present = false; + } + + return ret; +} + +el_err_code_t CameraWE2::start_stream() { + if (this->_is_streaming) [[unlikely]] { + return EL_EBUSY; + } else { + if (!this->_is_present) [[unlikely]] { + return EL_EPERM; + } + } + + auto ret = drv_ov5647_capture(2000); + + if (ret == EL_OK) [[likely]] { + this->_is_streaming = true; + } + + return ret; +} + +el_err_code_t CameraWE2::stop_stream() { + if (!this->_is_streaming) [[unlikely]] { + return EL_OK; // only ensure the camera is not streaming + } + + auto ret = drv_ov5647_capture_stop(); + + if (ret == EL_OK) [[likely]] { + this->_is_streaming = false; + } + + return ret; +} + +el_err_code_t CameraWE2::get_frame(el_img_t* img) { + if (!this->_is_streaming) [[unlikely]] { + return EL_EPERM; + } + + *img = drv_ov5647_get_frame(); + // just assign, not sure whether the img is valid + + return EL_OK; +} + +el_err_code_t CameraWE2::get_processed_frame(el_img_t* img) { + if (!this->_is_streaming) [[unlikely]] { + return EL_EPERM; + } + + *img = drv_ov5647_get_jpeg(); + // just assign, not sure whether the img is valid + + return EL_OK; +} + +} // namespace edgelab diff --git a/porting/himax/we2/el_camera_hm0360.h b/porting/himax/we2/el_camera_we2.h similarity index 84% rename from porting/himax/we2/el_camera_hm0360.h rename to porting/himax/we2/el_camera_we2.h index 47cdca53..1322e83d 100644 --- a/porting/himax/we2/el_camera_hm0360.h +++ b/porting/himax/we2/el_camera_we2.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2023 Hongtai Liu (Seeed Technology Inc.) + * Copyright (c) 2023 Seeed Technology Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,20 +23,20 @@ * */ -#ifndef _EL_CAMERA_HM0360_H_ -#define _EL_CAMERA_HM0360_H_ +#ifndef _EL_CAMERA_WE2_H_ +#define _EL_CAMERA_WE2_H_ #include "core/el_types.h" #include "porting/el_camera.h" namespace edgelab { -class CameraHM0360 : public Camera { +class CameraWE2 final : public Camera { public: - CameraHM0360() = default; - ~CameraHM0360() = default; + CameraWE2(); + ~CameraWE2() = default; - el_err_code_t init(size_t width, size_t height) override; + el_err_code_t init(SensorOptIdType opt_id) override; el_err_code_t deinit() override; el_err_code_t start_stream() override; diff --git a/porting/himax/we2/el_config_porting.h b/porting/himax/we2/el_config_porting.h index ad317771..c3afafff 100644 --- a/porting/himax/we2/el_config_porting.h +++ b/porting/himax/we2/el_config_porting.h @@ -43,7 +43,7 @@ #endif #define CONFIG_EL_DEBUG 3 -// #define CONFIG_EL_DEBUG_COLOR 1 +#define CONFIG_EL_DEBUG_COLOR 0 #define CONFIG_EL_HAS_FREERTOS_SUPPORT 1 #define SSCMA_REPL_EXECUTOR_PRIO 2 #define CONFIG_SSCMA_TENSOR_ARENA_SIZE (1060 * 1024) @@ -129,6 +129,10 @@ extern const struct fal_flash_dev _el_flash_db_nor_flash0; #endif extern void __on_algo_preprocess_done(); -#define EL_ON_ALGO_PREPROCESS_DONE __on_algo_preprocess_done(); +#define EL_ON_ALGO_PREPROCESS_DONE __on_algo_preprocess_done(); + +#define SSCMA_SHARED_BASE64_BUFFER 1 +#define SSCMA_SHARED_BASE64_BUFFER_BASE (0x36000000 + (150 * 1024)) // (JPEG_BASE_ADDR + JPEG_SIZE_MAX) +#define SSCMA_SHARED_BASE64_BUFFER_SIZE (200 * 1024) #endif diff --git a/porting/himax/we2/el_device_we2.cpp b/porting/himax/we2/el_device_we2.cpp index dd38f017..33d8a7da 100644 --- a/porting/himax/we2/el_device_we2.cpp +++ b/porting/himax/we2/el_device_we2.cpp @@ -37,7 +37,7 @@ extern "C" { #include #include "core/el_debug.h" -#include "el_camera_ov5647.h" +#include "el_camera_we2.h" #include "el_config_porting.h" #include "el_serial_we2.h" #include "el_wire_we2.h" @@ -140,7 +140,7 @@ void DeviceWE2::init() { static uint8_t sensor_id = 0; - static CameraOV5647 camera{}; + static CameraWE2 camera{}; this->_camera = &camera; this->_registered_sensors.emplace_front(el_sensor_info_t{ .id = ++sensor_id, .type = el_sensor_type_t::EL_SENSOR_TYPE_CAM, .state = el_sensor_state_t::EL_SENSOR_STA_REG}); @@ -165,4 +165,5 @@ Device* Device::get_device() { } // namespace edgelab +// current implementation does not support multiple cameras void __on_algo_preprocess_done() { edgelab::DeviceWE2::get_device()->get_camera()->stop_stream(); } diff --git a/porting/himax/we2/el_misc_we2.cpp b/porting/himax/we2/el_misc_we2.cpp index 5bca064e..21386c6c 100644 --- a/porting/himax/we2/el_misc_we2.cpp +++ b/porting/himax/we2/el_misc_we2.cpp @@ -84,7 +84,7 @@ EL_ATTR_WEAK void* el_malloc(size_t size) { } EL_ATTR_WEAK void* el_aligned_malloc_once(size_t align, size_t size) { - constexpr static const size_t elHeapSize = 1548 * 1024; + constexpr static const size_t elHeapSize = 1098 * 1024; static uint8_t elHeap[elHeapSize]{}; static uint8_t* cp = elHeap; size_t pv = reinterpret_cast(cp); @@ -128,7 +128,6 @@ EL_ATTR_WEAK void el_status_led(bool on) { } #if CONFIG_EL_HAS_FREERTOS_SUPPORT - EL_ATTR_WEAK void* operator new[](size_t size) { return pvPortMalloc(size); } EL_ATTR_WEAK void operator delete[](void* p) { vPortFree(p); } @@ -136,5 +135,4 @@ EL_ATTR_WEAK void operator delete[](void* p) { vPortFree(p); } EL_ATTR_WEAK void* operator new(size_t size) { return pvPortMalloc(size); } EL_ATTR_WEAK void operator delete(void* p) { vPortFree(p); } - #endif diff --git a/sscma/callback/invoke.hpp b/sscma/callback/invoke.hpp index 7ec3fe8b..718373e5 100644 --- a/sscma/callback/invoke.hpp +++ b/sscma/callback/invoke.hpp @@ -24,7 +24,7 @@ class Invoke final : public std::enable_shared_from_this { std::shared_ptr getptr() { return shared_from_this(); } [[nodiscard]] static std::shared_ptr create( - std::string cmd, std::size_t n_times, bool differed, bool results_only, void* caller) { + std::string cmd, int32_t n_times, bool differed, bool results_only, void* caller) { return std::shared_ptr{ new Invoke{std::move(cmd), n_times, differed, results_only, caller} }; @@ -38,7 +38,7 @@ class Invoke final : public std::enable_shared_from_this { inline void run() { prepare(); } protected: - Invoke(std::string cmd, std::size_t n_times, bool differed, bool results_only, void* caller) + Invoke(std::string cmd, int32_t n_times, bool differed, bool results_only, void* caller) : _cmd{cmd}, _n_times{n_times}, _differed{differed}, @@ -141,7 +141,7 @@ class Invoke final : public std::enable_shared_from_this { ", \"algorithm\": ", algorithm_config, ", \"sensor\": ", - sensor_info_2_json_str(_sensor_info), + sensor_info_2_json_str(_sensor_info, static_resource->device), "}}\n")}; static_cast(_caller)->send_bytes(ss.c_str(), ss.size()); } @@ -341,7 +341,7 @@ class Invoke final : public std::enable_shared_from_this { template void event_loop_cam(std::shared_ptr algorithm, ResultsFilter results_filter) { - if (_times++ == _n_times) [[unlikely]] + if ((_n_times >= 0) & (_times++ >= _n_times)) [[unlikely]] return; if (static_resource->current_task_id.load(std::memory_order_seq_cst) != _task_id) [[unlikely]] return; @@ -468,7 +468,7 @@ class Invoke final : public std::enable_shared_from_this { private: std::string _cmd; - std::size_t _n_times; + int32_t _n_times; bool _differed; bool _results_only; void* _caller; @@ -478,7 +478,7 @@ class Invoke final : public std::enable_shared_from_this { el_model_info_t _model_info; el_algorithm_info_t _algorithm_info; - std::size_t _times; + int32_t _times; el_err_code_t _ret; uint16_t _action_hash; diff --git a/sscma/callback/sample.hpp b/sscma/callback/sample.hpp index 07a03e37..505c252d 100644 --- a/sscma/callback/sample.hpp +++ b/sscma/callback/sample.hpp @@ -16,7 +16,7 @@ class Sample final : public std::enable_shared_from_this { public: std::shared_ptr getptr() { return shared_from_this(); } - [[nodiscard]] static std::shared_ptr create(std::string cmd, std::size_t n_times, void* caller) { + [[nodiscard]] static std::shared_ptr create(std::string cmd, int32_t n_times, void* caller) { return std::shared_ptr{ new Sample{std::move(cmd), n_times, caller} }; @@ -27,7 +27,7 @@ class Sample final : public std::enable_shared_from_this { inline void run() { prepare(); } protected: - Sample(std::string cmd, std::size_t n_times, void* caller) + Sample(std::string cmd, int32_t n_times, void* caller) : _cmd{cmd}, _n_times{n_times}, _caller{caller}, @@ -71,7 +71,7 @@ class Sample final : public std::enable_shared_from_this { "\", \"code\": ", std::to_string(_ret), ", \"data\": {\"sensor\": ", - sensor_info_2_json_str(_sensor_info), + sensor_info_2_json_str(_sensor_info, static_resource->device), "}}\n")}; static_cast(_caller)->send_bytes(ss.c_str(), ss.size()); } @@ -100,7 +100,7 @@ class Sample final : public std::enable_shared_from_this { } void event_loop_cam() { - if (_times++ == _n_times) [[unlikely]] + if ((_n_times >= 0) & (_times++ >= _n_times)) [[unlikely]] return; if (static_resource->current_task_id.load(std::memory_order_seq_cst) != _task_id) [[unlikely]] return; @@ -145,12 +145,12 @@ class Sample final : public std::enable_shared_from_this { private: std::string _cmd; - std::size_t _n_times; + int32_t _n_times; void* _caller; std::size_t _task_id; el_sensor_info_t _sensor_info; - std::size_t _times; + int32_t _times; el_err_code_t _ret; }; diff --git a/sscma/callback/sensor.hpp b/sscma/callback/sensor.hpp index 8b0dfc97..efe8f15b 100644 --- a/sscma/callback/sensor.hpp +++ b/sscma/callback/sensor.hpp @@ -19,7 +19,7 @@ void get_available_sensors(const std::string& cmd, void* caller) { concat_strings("\r{\"type\": 0, \"name\": \"", cmd, "\", \"code\": ", std::to_string(EL_OK), ", \"data\": [")}; for (const auto& i : registered_sensors) { - ss += concat_strings(delim, sensor_info_2_json_str(i)); + ss += concat_strings(delim, sensor_info_2_json_str(i, static_resource->device, true)); delim = ", "; } ss += "]}\n"; @@ -27,7 +27,8 @@ void get_available_sensors(const std::string& cmd, void* caller) { static_cast(caller)->send_bytes(ss.c_str(), ss.size()); } -void set_sensor(const std::string& cmd, uint8_t sensor_id, bool enable, void* caller, bool called_by_event = false) { +void set_sensor( + const std::string& cmd, uint8_t sensor_id, bool enable, uint8_t opt_id, void* caller, bool called_by_event = false) { auto sensor_info = static_resource->device->get_sensor_info(sensor_id); // a valid sensor id should always > 0 @@ -49,7 +50,7 @@ void set_sensor(const std::string& cmd, uint8_t sensor_id, bool enable, void* ca // if enable is true, init the camera if (enable) { - ret = camera->init(480, 480); // TODO: custom resolution + ret = camera->init(opt_id); // TODO: custom resolution if (ret != EL_OK) [[unlikely]] goto SensorError; } @@ -85,7 +86,7 @@ void set_sensor(const std::string& cmd, uint8_t sensor_id, bool enable, void* ca "\", \"code\": ", std::to_string(ret), ", \"data\": {\"sensor\": ", - sensor_info_2_json_str(sensor_info), + sensor_info_2_json_str(sensor_info, static_resource->device), "}}\n")}; static_cast(caller)->send_bytes(ss.c_str(), ss.size()); } @@ -98,7 +99,7 @@ void get_sensor_info(const std::string& cmd, void* caller) { "\", \"code\": ", std::to_string(EL_OK), ", \"data\": ", - sensor_info_2_json_str(sensor_info), + sensor_info_2_json_str(sensor_info, static_resource->device), "}\n")}; static_cast(caller)->send_bytes(ss.c_str(), ss.size()); } diff --git a/sscma/definations.hpp b/sscma/definations.hpp index 483fe76e..2148b57c 100644 --- a/sscma/definations.hpp +++ b/sscma/definations.hpp @@ -24,6 +24,14 @@ #define SSCMA_HAS_NATIVE_NETWORKING 0 #endif +#ifndef SSCMA_SHARED_BASE64_BUFFER + #define SSCMA_SHARED_BASE64_BUFFER 0 +#else + #ifndef SSCMA_SHARED_BASE64_BUFFER_BASE or SSCMA_SHARED_BASE64_BUFFER_SIZE + #error "Please specify base and size for shared base64 buffer" + #endif +#endif + #define SSCMA_REPL_HISTORY_MAX 8 #define SSCMA_AT_API_MAJOR_VERSION "v0" diff --git a/sscma/hooks.hpp b/sscma/hooks.hpp index 712fa984..76549911 100644 --- a/sscma/hooks.hpp +++ b/sscma/hooks.hpp @@ -40,8 +40,12 @@ void init_model_hook(std::string cmd) { void init_sensor_hook(std::string cmd) { if (static_resource->current_sensor_id) [[likely]] - set_sensor( - cmd + "@SENSOR", static_resource->current_sensor_id, true, static_cast(static_resource->serial), true); + set_sensor(cmd + "@SENSOR", + static_resource->current_sensor_id, + true, + 0, + static_cast(static_resource->serial), + true); } void init_action_hook(std::string cmd) { diff --git a/sscma/main_task.hpp b/sscma/main_task.hpp index ec115d49..b2d90a19 100644 --- a/sscma/main_task.hpp +++ b/sscma/main_task.hpp @@ -179,21 +179,24 @@ void register_commands() { return EL_OK; }); - static_resource->instance->register_cmd( - "SENSOR", - "Set a default sensor by sensor ID", - "SENSOR_ID,ENABLE/DISABLE", - [](std::vector argv, void* caller) { - uint8_t sensor_id = std::atoi(argv[1].c_str()); - bool enable = std::atoi(argv[2].c_str()) ? true : false; - static_resource->executor->add_task( - [cmd = std::move(argv[0]), sensor_id = std::move(sensor_id), enable = std::move(enable), caller]( - const std::atomic&) { - static_resource->current_task_id.fetch_add(1, std::memory_order_seq_cst); - set_sensor(cmd, sensor_id, enable, caller); - }); - return EL_OK; - }); + static_resource->instance->register_cmd("SENSOR", + "Set a default sensor by sensor ID", + "SENSOR_ID,ENABLE/DISABLE,OPT_ID", + [](std::vector argv, void* caller) { + uint8_t sensor_id = std::atoi(argv[1].c_str()); + bool enable = std::atoi(argv[2].c_str()) ? true : false; + uint8_t opt_id = std::atoi(argv[3].c_str()); + static_resource->executor->add_task([cmd = std::move(argv[0]), + sensor_id = std::move(sensor_id), + enable = std::move(enable), + opt_id = std::move(opt_id), + caller](const std::atomic&) { + static_resource->current_task_id.fetch_add( + 1, std::memory_order_seq_cst); + set_sensor(cmd, sensor_id, enable, opt_id, caller); + }); + return EL_OK; + }); static_resource->instance->register_cmd( "SENSOR?", "Get current sensor info", "", [](std::vector argv, void* caller) { diff --git a/sscma/utility.hpp b/sscma/utility.hpp index 1ec11aeb..cdcc5aaf 100644 --- a/sscma/utility.hpp +++ b/sscma/utility.hpp @@ -115,13 +115,38 @@ decltype(auto) model_info_2_json_str(const el_model_info_t& model_info) { "}"); } -decltype(auto) sensor_info_2_json_str(const el_sensor_info_t& sensor_info) { +decltype(auto) sensor_info_2_json_str(const el_sensor_info_t& sensor_info, Device* device, bool all_opts = false) { + std::string opts; + + switch (sensor_info.type) { + case EL_SENSOR_TYPE_CAM: { + auto camera = device->get_camera(); // currently only support single camera + auto opt_id = camera->current_opt_id(); + opts += concat_strings( + "\"opt_id\": ", std::to_string(opt_id), ", \"opt_detail\": \"", camera->current_opt_detail(), "\""); + const char* delim = ""; + if (all_opts) { + opts += ", \"opts\": {"; + for (const auto& opt : camera->supported_opts()) { + opts += concat_strings(delim, quoted(std::to_string(opt.id)), ": ", quoted(opt.details)); + delim = ", "; + } + opts += "}"; + } + } break; + + default: + opts = "\"opt_id\": -1, \"opt_detail\": \"Unknown\", \"opts\": {}"; + } + return concat_strings("{\"id\": ", std::to_string(sensor_info.id), ", \"type\": ", std::to_string(sensor_info.type), ", \"state\": ", std::to_string(sensor_info.state), + ", ", + std::move(opts), "}"); } @@ -244,9 +269,18 @@ inline decltype(auto) img_2_json_str(const el_img_t* img) { if (!img || !img->data || !img->size) [[unlikely]] return std::string("\"image\": \"\""); - static std::size_t size = 0; - static std::size_t buffer_size = 0; +#if SSCMA_SHARED_BASE64_BUFFER + static char* buffer = reinterpret_cast(SSCMA_SHARED_BASE64_BUFFER_BASE); + static std::size_t buffer_size = SSCMA_SHARED_BASE64_BUFFER_SIZE; + + if ((((img->size + 2u) / 3u) << 2u) + 1u > buffer_size) { + EL_LOGW("Error: shared base64 buffer exhausted"); + return std::string{"\"image\": \"\""}; + } +#else static char* buffer = nullptr; + static std::size_t buffer_size = 0; + static std::size_t size = 0; // only reallcate memory when buffer size is not enough if (img->size > size) [[unlikely]] { @@ -257,6 +291,7 @@ inline decltype(auto) img_2_json_str(const el_img_t* img) { delete[] buffer; buffer = new char[buffer_size]{}; } +#endif std::memset(buffer, 0, buffer_size); el_base64_encode(img->data, img->size, buffer);