diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..9e4a950 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "files.associations": { + "**/debian/*.install": "plain", + "charconv": "cpp", + "chrono": "cpp", + "optional": "cpp", + "format": "cpp", + "ratio": "cpp", + "system_error": "cpp", + "array": "cpp", + "functional": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "__bit_reference": "cpp", + "__node_handle": "cpp", + "deque": "cpp", + "limits": "cpp", + "locale": "cpp", + "vector": "cpp", + "algorithm": "cpp" + } +} \ No newline at end of file diff --git a/EmbeddedCAM.ino b/EmbeddedCAM.ino index 854f2aa..4f58df6 100644 --- a/EmbeddedCAM.ino +++ b/EmbeddedCAM.ino @@ -28,27 +28,26 @@ // =================== // Select camera model // =================== -//#define CAMERA_MODEL_WROVER_KIT // Has PSRAM -//#define CAMERA_MODEL_ESP_EYE // Has PSRAM +// #define CAMERA_MODEL_WROVER_KIT // Has PSRAM +// #define CAMERA_MODEL_ESP_EYE // Has PSRAM #define CAMERA_MODEL_ESP32S3_EYE // Has PSRAM -//#define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM -//#define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM -//#define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM -//#define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM -//#define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM -//#define CAMERA_MODEL_M5STACK_CAMS3_UNIT // Has PSRAM -//#define CAMERA_MODEL_AI_THINKER // Has PSRAM -//#define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM -//#define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM -// ** Espressif Internal Boards ** -//#define CAMERA_MODEL_ESP32_CAM_BOARD -//#define CAMERA_MODEL_ESP32S2_CAM_BOARD -//#define CAMERA_MODEL_ESP32S3_CAM_LCD -//#define CAMERA_MODEL_DFRobot_FireBeetle2_ESP32S3 // Has PSRAM -//#define CAMERA_MODEL_DFRobot_Romeo_ESP32S3 // Has PSRAM +// #define CAMERA_MODEL_M5STACK_PSRAM // Has PSRAM +// #define CAMERA_MODEL_M5STACK_V2_PSRAM // M5Camera version B Has PSRAM +// #define CAMERA_MODEL_M5STACK_WIDE // Has PSRAM +// #define CAMERA_MODEL_M5STACK_ESP32CAM // No PSRAM +// #define CAMERA_MODEL_M5STACK_UNITCAM // No PSRAM +// #define CAMERA_MODEL_M5STACK_CAMS3_UNIT // Has PSRAM +// #define CAMERA_MODEL_AI_THINKER // Has PSRAM +// #define CAMERA_MODEL_TTGO_T_JOURNAL // No PSRAM +// #define CAMERA_MODEL_XIAO_ESP32S3 // Has PSRAM +// ** Espressif Internal Boards ** +// #define CAMERA_MODEL_ESP32_CAM_BOARD +// #define CAMERA_MODEL_ESP32S2_CAM_BOARD +// #define CAMERA_MODEL_ESP32S3_CAM_LCD +// #define CAMERA_MODEL_DFRobot_FireBeetle2_ESP32S3 // Has PSRAM +// #define CAMERA_MODEL_DFRobot_Romeo_ESP32S3 // Has PSRAM #include "camera_pins.h" - // // LEP Task constants // @@ -69,7 +68,6 @@ int64_t vsyncDetectedUsec; WiFiServer lipSrv(8078); - // =========================== // Enter your WiFi credentials // =========================== @@ -79,15 +77,16 @@ const char *password = "plechovka"; void startCameraServer(); void setupLedFlash(int pin); -void setup() { +void setup() +{ gpio_config_t usb_phy_conf = { - .pin_bit_mask = (1ULL << 19) | (1ULL << 20), - .mode = GPIO_MODE_OUTPUT, - .pull_up_en = GPIO_PULLUP_ENABLE, - .pull_down_en = GPIO_PULLDOWN_DISABLE, - .intr_type = GPIO_INTR_DISABLE, -}; -gpio_config(&usb_phy_conf); + .pin_bit_mask = (1ULL << 19) | (1ULL << 20), + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&usb_phy_conf); printf("[MAIN] Start task\n"); @@ -166,8 +165,8 @@ gpio_config(&usb_phy_conf); config.pin_reset = RESET_GPIO_NUM; config.xclk_freq_hz = 20000000; config.frame_size = FRAMESIZE_UXGA; - config.pixel_format = PIXFORMAT_JPEG; // for streaming - //config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition + config.pixel_format = PIXFORMAT_JPEG; // for streaming + // config.pixel_format = PIXFORMAT_RGB565; // for face detection/recognition config.grab_mode = CAMERA_GRAB_WHEN_EMPTY; config.fb_location = CAMERA_FB_IN_PSRAM; config.jpeg_quality = 12; @@ -175,17 +174,23 @@ gpio_config(&usb_phy_conf); // if PSRAM IC present, init with UXGA resolution and higher JPEG quality // for larger pre-allocated frame buffer. - if (config.pixel_format == PIXFORMAT_JPEG) { - if (psramFound()) { + if (config.pixel_format == PIXFORMAT_JPEG) + { + if (psramFound()) + { config.jpeg_quality = 10; config.fb_count = 2; config.grab_mode = CAMERA_GRAB_LATEST; - } else { + } + else + { // Limit the frame size when PSRAM is not available config.frame_size = FRAMESIZE_SVGA; config.fb_location = CAMERA_FB_IN_DRAM; } - } else { + } + else + { // Best option for face detection/recognition config.frame_size = FRAMESIZE_240X240; #if CONFIG_IDF_TARGET_ESP32S3 @@ -200,20 +205,23 @@ gpio_config(&usb_phy_conf); // camera init esp_err_t err = esp_camera_init(&config); - if (err != ESP_OK) { + if (err != ESP_OK) + { printf("Camera init failed with error 0x%x", err); return; } sensor_t *s = esp_camera_sensor_get(); // initial sensors are flipped vertically and colors are a bit saturated - if (s->id.PID == OV3660_PID) { - s->set_vflip(s, 1); // flip it back - s->set_brightness(s, 1); // up the brightness just a bit - s->set_saturation(s, -2); // lower the saturation + if (s->id.PID == OV3660_PID) + { + s->set_vflip(s, 1); // flip it back + s->set_brightness(s, 1); // up the brightness just a bit + s->set_saturation(s, -2); // lower the saturation } // drop down frame size for higher initial frame rate - if (config.pixel_format == PIXFORMAT_JPEG) { + if (config.pixel_format == PIXFORMAT_JPEG) + { s->set_framesize(s, FRAMESIZE_QVGA); } @@ -235,7 +243,8 @@ gpio_config(&usb_phy_conf); WiFi.setSleep(false); printf("WiFi connecting\n"); - while (WiFi.status() != WL_CONNECTED) { + while (WiFi.status() != WL_CONNECTED) + { delay(500); printf("."); } @@ -250,7 +259,6 @@ gpio_config(&usb_phy_conf); printf("' to connect\n"); } - uint8_t *take_picture() { digitalWrite(LEP_CSN_PIN, 0); @@ -314,12 +322,12 @@ void lepton_restart() { delay(LEP_RESET_FAIL_RETRY_SECS * 1000); printf("LEPRESET\n\a"); - - #ifdef LEP_RESET_PIN + +#ifdef LEP_RESET_PIN digitalWrite(LEP_RESET_PIN, LEP_RESET_ON); delay(10); digitalWrite(LEP_RESET_PIN, LEP_RESET_OFF); - #endif +#endif // Delay for Lepton internal initialization (max 950 mSec) delay(1000); diff --git a/src/lipton/cci.cpp b/src/lipton/cci.cpp index 734e360..9559271 100644 --- a/src/lipton/cci.cpp +++ b/src/lipton/cci.cpp @@ -645,7 +645,7 @@ static int cci_write_burst(uint16_t start, uint16_t word_len, uint16_t *buf) int i; size_t bufSize = sizeof(*buf) * (1 + word_len); - buffer = malloc(bufSize); + unsigned char *buffer = (unsigned char *)malloc(bufSize); // Create the i2c transaction buffer buffer[0] = start >> 8; @@ -656,15 +656,16 @@ static int cci_write_burst(uint16_t start, uint16_t word_len, uint16_t *buf) buffer[i * 2 + 1] = *buf++ & 0xFF; } - esp_err_t ret = i2c_master_transmit(LEPTON_DEV_HANDLE, buffer, sizeof(buffer), I2C_TIMEOUT_MS_VALUE); + esp_err_t ret = i2c_master_transmit(LEPTON_DEV_HANDLE, buffer, bufSize, I2C_TIMEOUT_MS_VALUE); + free(buffer); if (ret == ESP_OK) { - ESP_LOGV(TAG_CCI, "Burst write to register 0x%04X successful (Value: 0x%04X)", reg_addr, value); + ESP_LOGV(TAG_CCI, "Burst write to register 0x%04X successful", start); return 1; } else { - ESP_LOGE(TAG_CCI, "Burst write to register 0x%04X failed: %s", reg_addr, esp_err_to_name(ret)); + ESP_LOGE(TAG_CCI, "Burst write to register 0x%04X failed: %s", start, esp_err_to_name(ret)); return -1; } } @@ -684,11 +685,12 @@ uint16_t cci_read_register(uint16_t reg_addr) { uint8_t buffer[2]; - esp_err_t ret = i2c_master_transmit_receive(LEPTON_DEV_HANDLE, ®_addr, sizeof(reg_addr), buffer, sizeof(buffer), I2C_TIMEOUT_MS_VALUE); + esp_err_t ret = i2c_master_transmit_receive(LEPTON_DEV_HANDLE, (uint8_t *)®_addr, sizeof(reg_addr), buffer, sizeof(buffer), I2C_TIMEOUT_MS_VALUE); if (ret == ESP_OK) { - ESP_LOGV(TAG_CCI, "Read from register 0x%04X successful (Value: 0x%04X)", reg_addr, *value); - return (((uint16_t)(buffer[0] & 0xFF)) << 8) | (buffer[1] & 0xFF); + uint16_t value = (((uint16_t)(buffer[0] & 0xFF)) << 8) | (buffer[1] & 0xFF); + ESP_LOGV(TAG_CCI, "Read from register 0x%04X successful (Value: 0x%04X)", reg_addr, value); + return value; } else { @@ -713,24 +715,30 @@ int cci_read_burst(uint16_t start, uint16_t word_len, uint16_t *buf) return -1; } size_t bufSize = word_len * sizeof(*buf); - buffer = malloc(bufSize); - esp_err_t ret = i2c_master_transmit_receive(LEPTON_DEV_HANDLE, ®_addr, sizeof(reg_addr), buffer, bufSize, I2C_TIMEOUT_MS_VALUE); + unsigned char *buffer = (unsigned char *)malloc(bufSize); + esp_err_t ret = i2c_master_transmit_receive(LEPTON_DEV_HANDLE, (uint8_t *)&start, sizeof(start), buffer, bufSize, I2C_TIMEOUT_MS_VALUE); if (ret == ESP_OK) { - ESP_LOGV(TAG_CCI, "Read from register 0x%04X successful (Value: 0x%04X)", reg_addr, *value); + ESP_LOGV(TAG_CCI, "Read from register 0x%04X successful", start); for (int i = 0; i < word_len; i++) { // CHECK IF THIS IS NEEDED *buf++ = buffer[i * 2] << 8 | buffer[i * 2 + 1]; } + free(buffer); return 1; } else { - ESP_LOGE(TAG_CCI, "Read from register 0x%04X failed: %s", reg_addr, esp_err_to_name(ret)); + ESP_LOGE(TAG_CCI, "Read from register 0x%04X failed: %s", start, esp_err_to_name(ret)); return -1; } } +/** + * Wait for busy to be clear in the status register + * Returns the 16-bit STATUS + * Returns 0x00010000 if there is a communication failure + */ /** * Wait for busy to be clear in the status register * Returns the 16-bit STATUS @@ -739,12 +747,13 @@ int cci_read_burst(uint16_t start, uint16_t word_len, uint16_t *buf) static uint32_t cci_wait_busy_clear() { bool err = false; - uint8_t buf[2] = {0x00, 0x07}; + uint8_t tx_buf[2]; // Register address to read from + uint8_t rx_buf[2]; // Value buffer - int t = 0; // maximum tick count + uint16_t reg_addr = 0x0002; // STATUS register + int t = 0; - // Wait for booted, not busy - while (((buf[1] & 0x07) != 0x06) && !err) + while (!err) { if (t++ >= CCI_MAX_WAIT_TICKS) { @@ -752,32 +761,33 @@ static uint32_t cci_wait_busy_clear() break; } - // Write STATUS register address - buf[0] = 0x00; - buf[1] = 0x02; + // Prepare register address in big-endian + tx_buf[0] = (reg_addr >> 8) & 0xFF; + tx_buf[1] = reg_addr & 0xFF; - esp_err_t ret = i2c_master_transmit_receive(LEPTON_DEV_HANDLE, ®_addr, sizeof(reg_addr), buf, sizeof(buf), I2C_TIMEOUT_MS_VALUE); - if (ret == ESP_OK) + esp_err_t ret = i2c_master_transmit_receive(LEPTON_DEV_HANDLE, tx_buf, sizeof(tx_buf), rx_buf, sizeof(rx_buf), I2C_TIMEOUT_MS_VALUE); + if (ret != ESP_OK) { - ESP_LOGV(TAG_CCI, "Read from register 0x%04X successful (Value: 0x%04X)", reg_addr, *value); + ESP_LOGE(TAG_CCI, "Failed to read STATUS register: %s", esp_err_to_name(ret)); + return 0x00010000; } - else + + uint16_t status = ((uint16_t)rx_buf[0] << 8) | rx_buf[1]; + + ESP_LOGV(TAG_CCI, "STATUS register read: 0x%04X", status); + + // Check bits [2:0] == 0b110 (0x06) + if ((rx_buf[1] & 0x07) == 0x06) { - ESP_LOGE(TAG_CCI, "Read from register 0x%04X failed: %s", reg_addr, esp_err_to_name(ret)); - return -1; + return status; } } - if (err) - { - return 0x00010000; - } - else - { - return (buf[0] << 8) | buf[1]; - } + // Timed out + return 0x00010000; } + /** * Wait for busy to be clear in the status register and check the result * printing an error if detected diff --git a/src/lipton/i2c.cpp b/src/lipton/i2c.cpp index b95eb7d..ef21c66 100644 --- a/src/lipton/i2c.cpp +++ b/src/lipton/i2c.cpp @@ -29,6 +29,9 @@ // #include "freertos/FreeRTOS.h" // #include "freertos/semphr.h" +i2c_master_bus_handle_t i2c0_bus_hdl; // migrate to newer +i2c_master_dev_handle_t LEPTON_DEV_HANDLE; + // // I2C API // @@ -36,20 +39,55 @@ /** * i2c master initialization */ + +esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle) +{ + const uint16_t probe_timeout_ms = 50; // timeout in milliseconds + uint8_t address; + bool found_any = false; + + printf("Scanning I2C bus...\n"); + + for (int i = 0; i < 128; i++) + { + fflush(stdout); + address = i; + + esp_err_t ret = i2c_master_probe(handle, address, probe_timeout_ms); + + if (ret == ESP_OK) + { + printf("Found device at 0x%02X\n", address); + found_any = true; + } + } + + if (!found_any) + { + printf("No I2C devices found.\n"); + } + + return ESP_OK; +} + esp_err_t i2c_master_init(gpio_num_t scl_pin, gpio_num_t sda_pin) { - - i2c_master_bus_config_t i2c0_bus_cfg = { .i2c_port = I2C_MASTER_NUM, .sda_io_num = sda_pin, .scl_io_num = scl_pin, .clk_source = I2C_CLK_SRC_DEFAULT, .glitch_ignore_cnt = 7, -}; + .flags = { + .enable_internal_pullup = true, + .allow_pd = false, + } + }; ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl)); + i2c_master_bus_detect_devices(i2c0_bus_hdl); + i2c_device_config_t LEPTON_DEV_CFG = { .dev_addr_length = I2C_ADDR_BIT_LEN_7, .device_address = CCI_ADDRESS, diff --git a/src/lipton/i2c.h b/src/lipton/i2c.h index 7c86025..905a8f1 100644 --- a/src/lipton/i2c.h +++ b/src/lipton/i2c.h @@ -22,7 +22,9 @@ * along with tCam. If not, see . * */ -#pragma once + +#ifndef TCAM_I2C +#define TCAM_I2C #include #include "esp_system.h" @@ -41,10 +43,11 @@ #define ACK_VAL (i2c_ack_type_t)0x0 #define NACK_VAL (i2c_ack_type_t)0x1 -i2c_master_bus_handle_t i2c0_bus_hdl; //migrate to newer -i2c_master_dev_handle_t LEPTON_DEV_HANDLE; +extern i2c_master_bus_handle_t i2c0_bus_hdl; //migrate to newer +extern i2c_master_dev_handle_t LEPTON_DEV_HANDLE; // // I2C API // -esp_err_t i2c_master_init(gpio_num_t scl_pin, gpio_num_t sda_pin); \ No newline at end of file +esp_err_t i2c_master_init(gpio_num_t scl_pin, gpio_num_t sda_pin); +#endif \ No newline at end of file diff --git a/src/lipton/lepton_system.cpp b/src/lipton/lepton_system.cpp index 04a1de0..cc32342 100644 --- a/src/lipton/lepton_system.cpp +++ b/src/lipton/lepton_system.cpp @@ -12,7 +12,6 @@ // lepton image and telem buffer lep_buffer_t rsp_lep_buffer; - /** * Initialize the ESP32 GPIO and internal peripherals */ @@ -28,8 +27,7 @@ bool lepton_io_init() if (ret != ESP_OK) { printf("[LEP SYS] Error: I2C Master initialization failed\n"); return false; - } - + } // Attempt to initialize the SPI Master used by the lep_task memset(&spi_buscfg, 0, sizeof(spi_bus_config_t)); spi_buscfg.miso_io_num=LEP_MISO_PIN; diff --git a/src/lipton/lepton_system.h b/src/lipton/lepton_system.h index 5f1f7fa..51e94d1 100644 --- a/src/lipton/lepton_system.h +++ b/src/lipton/lepton_system.h @@ -19,10 +19,10 @@ #define LEP_CSN_PIN 14 // SPI_CS 10 #define LEP_RESET_PIN 20 // RESET_L 17 -#define I2C_TIMEOUT_MS_VALUE 20 +#define I2C_TIMEOUT_MS_VALUE 2000 -#define I2C_MASTER_SDA_PIN GPIO_NUM_4 // SDA 5 -#define I2C_MASTER_SCL_PIN GPIO_NUM_5 // SCL 8 +#define I2C_MASTER_SDA_PIN GPIO_NUM_4 // SDA +#define I2C_MASTER_SCL_PIN GPIO_NUM_5 // SCL #define CCI_ADDRESS 0x2A // I2C