Removed locking mechanism for I2C

Develop
Sven Steudte 2017-08-19 04:38:41 +02:00
rodzic f14d1f35ff
commit 851a399db6
6 zmienionych plików z 123 dodań i 220 usunięć

Wyświetl plik

@ -282,7 +282,7 @@ void start_user_modules(void)
chsnprintf(config[5].ssdv_conf.callsign, 7, "DL7AD2"); // SSDV Callsign chsnprintf(config[5].ssdv_conf.callsign, 7, "DL7AD2"); // SSDV Callsign
config[5].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer config[5].ssdv_conf.ram_buffer = ssdv_buffer; // Camera buffer
config[5].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size config[5].ssdv_conf.ram_size = sizeof(ssdv_buffer); // Buffer size
config[5].ssdv_conf.res = RES_XGA; // Resolution XGA config[5].ssdv_conf.res = RES_VGA; // Resolution XGA
//config[5].ssdv_conf.redundantTx = true; // Transmit packets twice //config[5].ssdv_conf.redundantTx = true; // Transmit packets twice
start_image_thread(&config[5]); start_image_thread(&config[5]);

Wyświetl plik

@ -36,22 +36,22 @@ void BME280_Init(bme280_t *handle, uint8_t address)
handle->address = address; handle->address = address;
I2C_read16_LE(address, BME280_REGISTER_DIG_T1, &handle->calib.dig_T1); I2C_read16_LE(address, BME280_REGISTER_DIG_T1, (uint16_t*)&handle->calib.dig_T1);
I2C_readS16_LE(address, BME280_REGISTER_DIG_T2, &handle->calib.dig_T2); I2C_read16_LE(address, BME280_REGISTER_DIG_T2, (uint16_t*)&handle->calib.dig_T2);
I2C_readS16_LE(address, BME280_REGISTER_DIG_T3, &handle->calib.dig_T3); I2C_read16_LE(address, BME280_REGISTER_DIG_T3, (uint16_t*)&handle->calib.dig_T3);
I2C_read16_LE(address, BME280_REGISTER_DIG_P1, &handle->calib.dig_P1); I2C_read16_LE(address, BME280_REGISTER_DIG_P1, (uint16_t*)&handle->calib.dig_P1);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P2, &handle->calib.dig_P2); I2C_read16_LE(address, BME280_REGISTER_DIG_P2, (uint16_t*)&handle->calib.dig_P2);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P3, &handle->calib.dig_P3); I2C_read16_LE(address, BME280_REGISTER_DIG_P3, (uint16_t*)&handle->calib.dig_P3);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P4, &handle->calib.dig_P4); I2C_read16_LE(address, BME280_REGISTER_DIG_P4, (uint16_t*)&handle->calib.dig_P4);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P5, &handle->calib.dig_P5); I2C_read16_LE(address, BME280_REGISTER_DIG_P5, (uint16_t*)&handle->calib.dig_P5);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P6, &handle->calib.dig_P6); I2C_read16_LE(address, BME280_REGISTER_DIG_P6, (uint16_t*)&handle->calib.dig_P6);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P7, &handle->calib.dig_P7); I2C_read16_LE(address, BME280_REGISTER_DIG_P7, (uint16_t*)&handle->calib.dig_P7);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P8, &handle->calib.dig_P8); I2C_read16_LE(address, BME280_REGISTER_DIG_P8, (uint16_t*)&handle->calib.dig_P8);
I2C_readS16_LE(address, BME280_REGISTER_DIG_P9, &handle->calib.dig_P9); I2C_read16_LE(address, BME280_REGISTER_DIG_P9, (uint16_t*)&handle->calib.dig_P9);
I2C_read8(address, BME280_REGISTER_DIG_H1, &handle->calib.dig_H1); I2C_read8(address, BME280_REGISTER_DIG_H1, &handle->calib.dig_H1);
I2C_readS16_LE(address, BME280_REGISTER_DIG_H2, &handle->calib.dig_H2); I2C_read16_LE(address, BME280_REGISTER_DIG_H2, (uint16_t*)&handle->calib.dig_H2);
I2C_read8(address, BME280_REGISTER_DIG_H3, &handle->calib.dig_H3); I2C_read8(address, BME280_REGISTER_DIG_H3, &handle->calib.dig_H3);
I2C_read8(address, BME280_REGISTER_DIG_H4, &tmp1); I2C_read8(address, BME280_REGISTER_DIG_H4, &tmp1);

Wyświetl plik

@ -712,64 +712,61 @@ void OV2640_InitGPIO(void)
void OV2640_TransmitConfig(void) void OV2640_TransmitConfig(void)
{ {
// Set to page 1 // Set to page 1
I2C_write8_locked(OV2640_I2C_ADR, 0xff, 0x01); I2C_write8(OV2640_I2C_ADR, 0xff, 0x01);
I2C_write8_locked(OV2640_I2C_ADR, 0x12, 0x80); I2C_write8(OV2640_I2C_ADR, 0x12, 0x80);
chThdSleepMilliseconds(50); chThdSleepMilliseconds(50);
/* Write selected arrays to the camera to initialize it and set the /* Write selected arrays to the camera to initialize it and set the
* desired output format. */ * desired output format. */
for(uint32_t i=0; (ov2640_init_regs[i].reg != 0xff) || (ov2640_init_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_init_regs[i].reg != 0xff) || (ov2640_init_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_init_regs[i].reg, ov2640_init_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_init_regs[i].reg, ov2640_init_regs[i].val);
for(uint32_t i=0; (ov2640_size_change_preamble_regs[i].reg != 0xff) || (ov2640_size_change_preamble_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_size_change_preamble_regs[i].reg != 0xff) || (ov2640_size_change_preamble_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_size_change_preamble_regs[i].reg, ov2640_size_change_preamble_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_size_change_preamble_regs[i].reg, ov2640_size_change_preamble_regs[i].val);
switch(ov2640_conf->res) { switch(ov2640_conf->res) {
case RES_QCIF: case RES_QCIF:
for(uint32_t i=0; (ov2640_qcif_regs[i].reg != 0xff) || (ov2640_qcif_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_qcif_regs[i].reg != 0xff) || (ov2640_qcif_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_qcif_regs[i].reg, ov2640_qcif_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_qcif_regs[i].reg, ov2640_qcif_regs[i].val);
break; break;
case RES_QVGA: case RES_QVGA:
for(uint32_t i=0; (ov2640_qvga_regs[i].reg != 0xff) || (ov2640_qvga_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_qvga_regs[i].reg != 0xff) || (ov2640_qvga_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_qvga_regs[i].reg, ov2640_qvga_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_qvga_regs[i].reg, ov2640_qvga_regs[i].val);
break; break;
case RES_VGA: case RES_VGA:
for(uint32_t i=0; (ov2640_vga_regs[i].reg != 0xff) || (ov2640_vga_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_vga_regs[i].reg != 0xff) || (ov2640_vga_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_vga_regs[i].reg, ov2640_vga_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_vga_regs[i].reg, ov2640_vga_regs[i].val);
break; break;
case RES_XGA: case RES_XGA:
for(uint32_t i=0; (ov2640_xga_regs[i].reg != 0xff) || (ov2640_xga_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_xga_regs[i].reg != 0xff) || (ov2640_xga_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_xga_regs[i].reg, ov2640_xga_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_xga_regs[i].reg, ov2640_xga_regs[i].val);
break; break;
case RES_UXGA: case RES_UXGA:
for(uint32_t i=0; (ov2640_uxga_regs[i].reg != 0xff) || (ov2640_uxga_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_uxga_regs[i].reg != 0xff) || (ov2640_uxga_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_uxga_regs[i].reg, ov2640_uxga_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_uxga_regs[i].reg, ov2640_uxga_regs[i].val);
break; break;
default: // Default QVGA default: // Default QVGA
for(uint32_t i=0; (ov2640_qvga_regs[i].reg != 0xff) || (ov2640_qvga_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_qvga_regs[i].reg != 0xff) || (ov2640_qvga_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_qvga_regs[i].reg, ov2640_qvga_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_qvga_regs[i].reg, ov2640_qvga_regs[i].val);
} }
for(uint32_t i=0; (ov2640_format_change_preamble_regs[i].reg != 0xff) || (ov2640_format_change_preamble_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_format_change_preamble_regs[i].reg != 0xff) || (ov2640_format_change_preamble_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_format_change_preamble_regs[i].reg, ov2640_format_change_preamble_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_format_change_preamble_regs[i].reg, ov2640_format_change_preamble_regs[i].val);
for(uint32_t i=0; (ov2640_yuyv_regs[i].reg != 0xff) || (ov2640_yuyv_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_yuyv_regs[i].reg != 0xff) || (ov2640_yuyv_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_yuyv_regs[i].reg, ov2640_yuyv_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_yuyv_regs[i].reg, ov2640_yuyv_regs[i].val);
for(uint32_t i=0; (ov2640_jpeg_regs[i].reg != 0xff) || (ov2640_jpeg_regs[i].val != 0xff); i++) for(uint32_t i=0; (ov2640_jpeg_regs[i].reg != 0xff) || (ov2640_jpeg_regs[i].val != 0xff); i++)
I2C_write8_locked(OV2640_I2C_ADR, ov2640_jpeg_regs[i].reg, ov2640_jpeg_regs[i].val); I2C_write8(OV2640_I2C_ADR, ov2640_jpeg_regs[i].reg, ov2640_jpeg_regs[i].val);
} }
void OV2640_init(ssdv_conf_t *config) { void OV2640_init(ssdv_conf_t *config) {
ov2640_conf = config; ov2640_conf = config;
// Take I2C (due to silicon bug of OV2640, it interferes if byte 0x30 transmitted on I2C bus)
I2C_lock();
// Clearing buffer // Clearing buffer
uint32_t i; uint32_t i;
for(i=0; i<ov2640_conf->ram_size; i++) for(i=0; i<ov2640_conf->ram_size; i++)
@ -810,15 +807,10 @@ void OV2640_deinit(void) {
palSetLineMode(LINE_CAM_EN, PAL_MODE_INPUT); palSetLineMode(LINE_CAM_EN, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT); palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT);
// Release I2C (due to silicon bug of OV2640, it interferes if byte 0x30 transmitted on I2C bus)
I2C_unlock();
} }
bool OV2640_isAvailable(void) bool OV2640_isAvailable(void)
{ {
I2C_lock();
// Configure pins // Configure pins
OV2640_InitGPIO(); OV2640_InitGPIO();
@ -830,14 +822,13 @@ bool OV2640_isAvailable(void)
uint16_t val; uint16_t val;
bool ret; bool ret;
if(I2C_read16_locked(OV2640_I2C_ADR, 0x0A, &val)) if(I2C_read16(OV2640_I2C_ADR, 0x0A, &val))
ret = val == PID_OV2640; ret = val == PID_OV2640;
else else
ret = false; ret = false;
palClearLine(LINE_CAM_EN); // Switch off camera palClearLine(LINE_CAM_EN); // Switch off camera
palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT); // CAM_RESET palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT); // CAM_RESET
I2C_unlock();
return ret; return ret;
} }

Wyświetl plik

@ -1,3 +1,8 @@
/*
* Registers by Arducam https://github.com/ArduCAM/Arduino/blob/master/ArduCAM/ov5640_regs.h
* https://github.com/ArduCAM/Arduino/blob/master/ArduCAM/ArduCAM.cpp
*/
#include "ch.h" #include "ch.h"
#include "hal.h" #include "hal.h"
#include "ov5640.h" #include "ov5640.h"
@ -9,14 +14,11 @@
#define OV5640_I2C_ADR 0x3C #define OV5640_I2C_ADR 0x3C
struct regval_list { struct regval_list {
uint16_t reg; uint16_t reg;
uint8_t val; uint8_t val;
}; };
static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] = static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] =
{ {
{ 0x4740, 0x24 }, { 0x4740, 0x24 },
@ -1025,110 +1027,107 @@ void OV5640_InitGPIO(void)
void OV5640_TransmitConfig(void) void OV5640_TransmitConfig(void)
{ {
chThdSleepMilliseconds(1000); chThdSleepMilliseconds(1000);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3103, 0x11); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3103, 0x11);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3008, 0x82); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3008, 0x82);
chThdSleepMilliseconds(100); chThdSleepMilliseconds(100);
for(uint32_t i=0; (OV5640YUV_Sensor_Dvp_Init[i].reg != 0xffff) || (OV5640YUV_Sensor_Dvp_Init[i].val != 0xff); i++) for(uint32_t i=0; (OV5640YUV_Sensor_Dvp_Init[i].reg != 0xffff) || (OV5640YUV_Sensor_Dvp_Init[i].val != 0xff); i++)
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, OV5640YUV_Sensor_Dvp_Init[i].reg, OV5640YUV_Sensor_Dvp_Init[i].val); I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640YUV_Sensor_Dvp_Init[i].reg, OV5640YUV_Sensor_Dvp_Init[i].val);
chThdSleepMilliseconds(500); chThdSleepMilliseconds(500);
for(uint32_t i=0; (OV5640_JPEG_QSXGA[i].reg != 0xffff) || (OV5640_JPEG_QSXGA[i].val != 0xff); i++) for(uint32_t i=0; (OV5640_JPEG_QSXGA[i].reg != 0xffff) || (OV5640_JPEG_QSXGA[i].val != 0xff); i++)
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, OV5640_JPEG_QSXGA[i].reg, OV5640_JPEG_QSXGA[i].val); I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_JPEG_QSXGA[i].reg, OV5640_JPEG_QSXGA[i].val);
switch(ov5640_conf->res) { switch(ov5640_conf->res) {
case RES_QVGA: case RES_QVGA:
for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++) for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++)
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val); I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val);
break; break;
case RES_VGA: case RES_VGA:
for(uint32_t i=0; (OV5640_QSXGA2VGA[i].reg != 0xffff) || (OV5640_QSXGA2VGA[i].val != 0xff); i++) for(uint32_t i=0; (OV5640_QSXGA2VGA[i].reg != 0xffff) || (OV5640_QSXGA2VGA[i].val != 0xff); i++)
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, OV5640_QSXGA2VGA[i].reg, OV5640_QSXGA2VGA[i].val); I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2VGA[i].reg, OV5640_QSXGA2VGA[i].val);
break; break;
case RES_XGA: case RES_XGA:
for(uint32_t i=0; (OV5640_QSXGA2XGA[i].reg != 0xffff) || (OV5640_QSXGA2XGA[i].val != 0xff); i++) for(uint32_t i=0; (OV5640_QSXGA2XGA[i].reg != 0xffff) || (OV5640_QSXGA2XGA[i].val != 0xff); i++)
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, OV5640_QSXGA2XGA[i].reg, OV5640_QSXGA2XGA[i].val); I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2XGA[i].reg, OV5640_QSXGA2XGA[i].val);
break; break;
case RES_UXGA: case RES_UXGA:
for(uint32_t i=0; (OV5640_QSXGA2UXGA[i].reg != 0xffff) || (OV5640_QSXGA2UXGA[i].val != 0xff); i++) for(uint32_t i=0; (OV5640_QSXGA2UXGA[i].reg != 0xffff) || (OV5640_QSXGA2UXGA[i].val != 0xff); i++)
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, OV5640_QSXGA2UXGA[i].reg, OV5640_QSXGA2UXGA[i].val); I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2UXGA[i].reg, OV5640_QSXGA2UXGA[i].val);
break; break;
default: // Default QVGA default: // Default QVGA
for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++) for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++)
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val); I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val);
} }
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x4407, 0x04); // Quantization scale I2C_write8_16bitreg(OV5640_I2C_ADR, 0x4407, 0x04); // Quantization scale
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3406, 0x00); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3406, 0x00);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3400, 0x04); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3400, 0x04);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3401, 0x00); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3401, 0x00);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3402, 0x04); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3402, 0x04);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3403, 0x00); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3403, 0x00);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3404, 0x04); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3404, 0x04);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3405, 0x00); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3405, 0x00);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0xa3); // lanuch group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0xa3); // lanuch group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5183 ,0x0 ); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5183 ,0x0 );
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5381, 0x1c); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5381, 0x1c);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5382, 0x5a); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5382, 0x5a);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5383, 0x06); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5383, 0x06);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5384, 0x1a); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5384, 0x1a);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5385, 0x66); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5385, 0x66);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5386, 0x80); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5386, 0x80);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5387, 0x82); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5387, 0x82);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5388, 0x80); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5388, 0x80);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5389, 0x02); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5389, 0x02);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x538b, 0x98); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x538b, 0x98);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x538a, 0x01); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x538a, 0x01);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5587, 0x00); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5587, 0x00);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5588, 0x01); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5588, 0x01);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5586, 0x20); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5586, 0x20);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5585, 0x00); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5585, 0x00);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5580, 0x06); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5580, 0x06);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5583, 0x40); // sat U I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5583, 0x40); // sat U
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5584, 0x10); // sat V I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5584, 0x10); // sat V
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x5003, 0x08); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x5003, 0x08);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x13); // end group 3
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3a0f, 0x38); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3a0f, 0x38);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3a10, 0x30); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3a10, 0x30);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3a11, 0x61); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3a11, 0x61);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3a1b, 0x38); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3a1b, 0x38);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3a1e, 0x30); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3a1e, 0x30);
I2C_write8_16bitreg_locked(OV5640_I2C_ADR, 0x3a1f, 0x10); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3a1f, 0x10);
} }
void OV5640_init(ssdv_conf_t *config) { void OV5640_init(ssdv_conf_t *config) {
ov5640_conf = config; ov5640_conf = config;
// Take I2C (due to silicon bug of OV5640, it interferes if byte 0x30 transmitted on I2C bus)
I2C_lock();
// Clearing buffer // Clearing buffer
uint32_t i; uint32_t i;
for(i=0; i<ov5640_conf->ram_size; i++) for(i=0; i<ov5640_conf->ram_size; i++)
@ -1169,15 +1168,10 @@ void OV5640_deinit(void) {
palSetLineMode(LINE_CAM_EN, PAL_MODE_INPUT); palSetLineMode(LINE_CAM_EN, PAL_MODE_INPUT);
palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT); palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT);
// Release I2C (due to silicon bug of OV5640, it interferes if byte 0x30 transmitted on I2C bus)
I2C_unlock();
} }
bool OV5640_isAvailable(void) bool OV5640_isAvailable(void)
{ {
I2C_lock();
// Configure pins // Configure pins
OV5640_InitGPIO(); OV5640_InitGPIO();
@ -1190,7 +1184,7 @@ bool OV5640_isAvailable(void)
uint8_t val, val2; uint8_t val, val2;
bool ret; bool ret;
if(I2C_read8_16bitreg_locked(OV5640_I2C_ADR, 0x300A, &val) && I2C_read8_16bitreg_locked(OV5640_I2C_ADR, 0x300B, &val2)) { if(I2C_read8_16bitreg(OV5640_I2C_ADR, 0x300A, &val) && I2C_read8_16bitreg(OV5640_I2C_ADR, 0x300B, &val2)) {
ret = val == 0x56 && val2 == 0x40; ret = val == 0x56 && val2 == 0x40;
} else { } else {
ret = false; ret = false;
@ -1198,7 +1192,6 @@ bool OV5640_isAvailable(void)
palClearLine(LINE_CAM_EN); // Switch off camera palClearLine(LINE_CAM_EN); // Switch off camera
palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT); // CAM_RESET palSetLineMode(LINE_CAM_RESET, PAL_MODE_INPUT); // CAM_RESET
I2C_unlock();
return ret; return ret;
} }

Wyświetl plik

@ -6,33 +6,28 @@
#include "hal.h" #include "hal.h"
#include "pi2c.h" #include "pi2c.h"
#define I2C_DRIVER (&I2CD1)
const I2CConfig _i2cfg = { const I2CConfig _i2cfg = {
OPMODE_I2C, OPMODE_I2C,
50000, 50000,
STD_DUTY_CYCLE, STD_DUTY_CYCLE,
}; };
mutex_t pi2c_mtx; static bool I2C_transmit(I2CDriver *driver, uint8_t addr, uint8_t *txbuf, uint32_t txbytes, uint8_t *rxbuf, uint32_t rxbytes, systime_t timeout) {
bool i2cSendDriver(I2CDriver *driver, uint8_t addr, uint8_t *txbuf, uint32_t txbytes, uint8_t *rxbuf, uint32_t rxbytes, systime_t timeout) {
i2cAcquireBus(driver); i2cAcquireBus(driver);
msg_t i2c_status = i2cMasterTransmitTimeout(driver, addr, txbuf, txbytes, rxbuf, rxbytes, timeout); msg_t i2c_status = i2cMasterTransmitTimeout(driver, addr, txbuf, txbytes, rxbuf, rxbytes, timeout);
if(i2c_status == MSG_TIMEOUT) { // Restart I2C at timeout if(i2c_status == MSG_TIMEOUT) { // Restart I2C at timeout
TRACE_ERROR("I2C > TIMEOUT > RESTART (ADDR 0x%02x)", addr); TRACE_ERROR("I2C > TIMEOUT > RESTART (ADDR 0x%02x)", addr);
i2cStop(driver); i2cStop(driver);
i2cStart(driver, &_i2cfg); i2cStart(driver, &_i2cfg);
} else if(i2c_status == MSG_RESET && addr != 0x4C) { // Prevent PAC1720 to produce message while it doesnt work below 2.5V } else if(i2c_status == MSG_RESET) {
TRACE_ERROR("I2C > RESET (ADDR 0x%02x)", addr); TRACE_ERROR("I2C > RESET (ADDR 0x%02x)", addr);
} }
i2cReleaseBus(driver); i2cReleaseBus(driver);
return i2c_status == MSG_OK; return i2c_status == MSG_OK;
} }
bool I2C_send(uint8_t addr, uint8_t *txbuf, uint32_t txbytes, uint8_t *rxbuf, uint32_t rxbytes, systime_t timeout)
{
return i2cSendDriver(&I2CD1, addr, txbuf, txbytes, rxbuf, rxbytes, timeout);
}
void pi2cInit(void) void pi2cInit(void)
{ {
TRACE_INFO("I2C > Initialize I2C"); TRACE_INFO("I2C > Initialize I2C");
@ -41,119 +36,55 @@ void pi2cInit(void)
palSetLineMode(LINE_I2C_SCL, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_OTYPE_OPENDRAIN); // SCL palSetLineMode(LINE_I2C_SCL, PAL_MODE_ALTERNATE(4) | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_OTYPE_OPENDRAIN); // SCL
i2cStart(&I2CD1, &_i2cfg); i2cStart(&I2CD1, &_i2cfg);
chMtxObjectInit(&pi2c_mtx);
} }
// I2C Mutex locked access functions
bool I2C_write8_locked(uint8_t address, uint8_t reg, uint8_t value)
{
uint8_t txbuf[] = {reg, value};
return I2C_send(address, txbuf, 2, NULL, 0, MS2ST(100));
}
bool I2C_write8_16bitreg_locked(uint8_t address, uint16_t reg, uint8_t value) // 16bit register (for OV5640)
{
uint8_t txbuf[] = {reg >> 8, reg & 0xFF, value};
return I2C_send(address, txbuf, 3, NULL, 0, MS2ST(100));
}
bool I2C_writeN_locked(uint8_t address, uint8_t *txbuf, uint32_t length)
{
return I2C_send(address, txbuf, length, NULL, 0, MS2ST(100));
}
bool I2C_read8_locked(uint8_t address, uint8_t reg, uint8_t *val)
{
uint8_t txbuf[] = {reg};
uint8_t rxbuf[1];
bool ret = I2C_send(address, txbuf, 1, rxbuf, 1, MS2ST(100));
*val = rxbuf[0];
return ret;
}
bool I2C_read8_16bitreg_locked(uint8_t address, uint16_t reg, uint8_t *val) // 16bit register (for OV5640)
{
uint8_t txbuf[] = {reg >> 8, reg & 0xFF};
uint8_t rxbuf[1];
bool ret = I2C_send(address, txbuf, 2, rxbuf, 1, MS2ST(100));
*val = rxbuf[0];
return ret;
}
bool I2C_read16_locked(uint8_t address, uint8_t reg, uint16_t *val)
{
uint8_t txbuf[] = {reg};
uint8_t rxbuf[2];
bool ret = I2C_send(address, txbuf, 1, rxbuf, 2, MS2ST(100));
*val = (rxbuf[0] << 8) | rxbuf[1];
return ret;
}
// I2C Mutex unlocked access functions
bool I2C_write8(uint8_t address, uint8_t reg, uint8_t value) bool I2C_write8(uint8_t address, uint8_t reg, uint8_t value)
{ {
I2C_lock(); uint8_t txbuf[] = {reg, value};
bool ret = I2C_write8_locked(address, reg, value); return I2C_transmit(I2C_DRIVER, address, txbuf, 2, NULL, 0, MS2ST(100));
chMtxUnlock(&pi2c_mtx);
return ret;
} }
bool I2C_writeN(uint8_t address, uint8_t *txbuf, uint32_t length) bool I2C_writeN(uint8_t address, uint8_t *txbuf, uint32_t length)
{ {
I2C_lock(); return I2C_transmit(I2C_DRIVER, address, txbuf, length, NULL, 0, MS2ST(100));
bool ret = I2C_writeN_locked(address, txbuf, length);
I2C_unlock();
return ret;
} }
bool I2C_read8(uint8_t address, uint8_t reg, uint8_t *val) bool I2C_read8(uint8_t address, uint8_t reg, uint8_t *val)
{ {
I2C_lock(); uint8_t txbuf[] = {reg};
bool ret = I2C_read8_locked(address, reg, val); uint8_t rxbuf[1];
I2C_unlock(); bool ret = I2C_transmit(I2C_DRIVER, address, txbuf, 1, rxbuf, 1, MS2ST(100));
*val = rxbuf[0];
return ret; return ret;
} }
bool I2C_read16(uint8_t address, uint8_t reg, uint16_t *val) bool I2C_read16(uint8_t address, uint8_t reg, uint16_t *val)
{ {
I2C_lock(); uint8_t txbuf[] = {reg};
bool ret = I2C_read16_locked(address, reg, val); uint8_t rxbuf[2];
I2C_unlock(); bool ret = I2C_transmit(I2C_DRIVER, address, txbuf, 1, rxbuf, 2, MS2ST(100));
*val = (rxbuf[0] << 8) | rxbuf[1];
return ret; return ret;
} }
bool I2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val) { bool I2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val) {
bool ret = I2C_read16_locked(address, reg, val); bool ret = I2C_read16(address, reg, val);
*val = (*val >> 8) | (*val << 8); *val = (*val >> 8) | (*val << 8);
return ret; return ret;
} }
bool I2C_readS16(uint8_t address, uint8_t reg, int16_t *val)
bool I2C_read8_16bitreg(uint8_t address, uint16_t reg, uint8_t *val) // 16bit register (for OV5640)
{ {
return I2C_read16(address, reg, (uint16_t*)val); uint8_t txbuf[] = {reg >> 8, reg & 0xFF};
uint8_t rxbuf[1];
bool ret = I2C_transmit(I2C_DRIVER, address, txbuf, 2, rxbuf, 1, MS2ST(100));
*val = rxbuf[0];
return ret;
} }
bool I2C_readS16_LE(uint8_t address, uint8_t reg, int16_t* val) bool I2C_write8_16bitreg(uint8_t address, uint16_t reg, uint8_t value) // 16bit register (for OV5640)
{ {
return I2C_read16_LE(address, reg, (uint16_t*)val); uint8_t txbuf[] = {reg >> 8, reg & 0xFF, value};
} return I2C_transmit(I2C_DRIVER, address, txbuf, 3, NULL, 0, MS2ST(100));
/**
* Locks all other I2C threads to access I2C
*/
void I2C_lock(void)
{
chMtxLock(&pi2c_mtx);
}
/**
* Unlocks all other I2C threads to access I2C
*/
void I2C_unlock(void)
{
chMtxUnlock(&pi2c_mtx);
} }

Wyświetl plik

@ -13,27 +13,15 @@
void pi2cInit(void); void pi2cInit(void);
// I2C Mutex locked access functions (Access only if I2C has been locked with I2C_lock())
bool I2C_write8_locked(uint8_t address, uint8_t reg, uint8_t value);
bool I2C_writeN_locked(uint8_t address, uint8_t *txbuf, uint32_t length);
bool I2C_read8_locked(uint8_t address, uint8_t reg, uint8_t *val);
bool I2C_read16_locked(uint8_t address, uint8_t reg, uint16_t *val);
bool I2C_write8_16bitreg_locked(uint8_t address, uint16_t reg, uint8_t value); // 16bit register (for OV5640)
bool I2C_read8_16bitreg_locked(uint8_t address, uint16_t reg, uint8_t *val); // 16bit register (for OV5640)
// I2C Mutex unlocked access functions
bool I2C_write8(uint8_t address, uint8_t reg, uint8_t value); bool I2C_write8(uint8_t address, uint8_t reg, uint8_t value);
bool I2C_writeN(uint8_t address, uint8_t *txbuf, uint32_t length); bool I2C_writeN(uint8_t address, uint8_t *txbuf, uint32_t length);
bool I2C_read8(uint8_t address, uint8_t reg, uint8_t *val); bool I2C_read8(uint8_t address, uint8_t reg, uint8_t *val);
bool I2C_read16(uint8_t address, uint8_t reg, uint16_t *val); bool I2C_read16(uint8_t address, uint8_t reg, uint16_t *val);
bool I2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val);
bool I2C_readS16(uint8_t address, uint8_t reg, int16_t *val);
bool I2C_readS16_LE(uint8_t address, uint8_t reg, int16_t* val);
// I2C locking and unlocking bool I2C_write8_16bitreg(uint8_t address, uint16_t reg, uint8_t value); // 16bit register (for OV5640)
void I2C_lock(void); bool I2C_read8_16bitreg(uint8_t address, uint16_t reg, uint8_t *val); // 16bit register (for OV5640)
void I2C_unlock(void);
bool I2C_read16_LE(uint8_t address, uint8_t reg, uint16_t *val);
#endif #endif