Commit cf4af6f5 authored by Andrey Filippov's avatar Andrey Filippov

More editing

parent 804b8db1
......@@ -76,7 +76,7 @@
/** Wait queue for the processes waiting for a new frame to appear in the circular buffer */
wait_queue_head_t circbuf_wait_queue;
struct circbuf_priv_t circbuf_priv[IMAGE_CHN_NUM];
struct circbuf_priv_t circbuf_priv[SENSOR_PORTS];
struct circbuf_priv_t *circbuf_priv_ptr = circbuf_priv;
static struct device *g_dev_ptr;
......@@ -109,7 +109,7 @@ int init_ccam_dma_buf_ptr(struct platform_device *pdev)
// set circular buffer size in bytes
set_globalParam(G_CIRCBUFSIZE, CCAM_DMA_SIZE);
for (i = 0; i < IMAGE_CHN_NUM; i++) {
for (i = 0; i < SENSOR_PORTS; i++) {
circbuf_priv[i].buf_ptr = ccam_dma_buf_ptr + BYTE2DW(CIRCBUF_START_OFFSET + i * CCAM_DMA_SIZE);
circbuf_priv[i].phys_addr = dma_handle + CIRCBUF_START_OFFSET + i * CCAM_DMA_SIZE;
}
......@@ -572,10 +572,10 @@ ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t *
/* debug code follows*/
switch (buf[0] - 0x30) {
case 0:
camera_interrupts(0);
compressor_interrupts(0,chn);
break;
case 1:
camera_interrupts(1);
compressor_interrupts(1,chn);
break;
}
/* debug code end */
......
......@@ -753,10 +753,10 @@ ssize_t circbuf_write(struct file *file, const char *buf, size_t count, loff_t *
/* debug code follows*/
switch (buf[0] - 0x30) {
case 0:
camera_interrupts(0);
compressor_interrupts(0,chn);
break;
case 1:
camera_interrupts(1);
compressor_interrupts(1,chn);
break;
case 3:
/* update image quality */
......
......@@ -60,25 +60,29 @@ struct sensor_name_t {
const char * name;
u32 code;
int type; ///< +1 - applicable to sensors, +2 - applicable to multiplexers
sens_iface_t iface;
};
//typedef enum {NONE,PARALLEL12,HISPI} sens_iface_t; ///< Sensor port interface type
const struct sensor_name_t sensor_names[] ={
{.name="detect", .type=3, .code = 0}, // to be automatically detected
{.name="none", .type=3, .code = SENSOR_NONE}, // no device attached
{.name="mux10359", .type=2, .code = SENSOR_MUX_10359}, // no device attached
{.name="zr32112", .type=1, .code = SENSOR_ZR32112}, // Zoran ZR32112
{.name="zr32212", .type=1, .code = SENSOR_ZR32212}, // Zoran ZR32212
{.name="kac1310", .type=1, .code = SENSOR_KAC1310}, // Kodak KAC1310
{.name="kac5000", .type=1, .code = SENSOR_KAC5000}, // Kodak KAC5000
{.name="mi1300", .type=1, .code = SENSOR_MI1300}, // Micron MI1300
{.name="mt9m001", .type=1, .code = SENSOR_MT9M001}, // MT9M001
{.name="mt9d001", .type=1, .code = SENSOR_MT9D001}, // MT9D001
{.name="mt9t001", .type=1, .code = SENSOR_MT9T001}, // MT9T001
{.name="mt9p006", .type=1, .code = SENSOR_MT9P006}, // MT9P006
{.name="mt9f002", .type=1, .code = SENSOR_MT9F002}, // MT9F002
{.name="ibis51300", .type=1, .code = SENSOR_IBIS51300}, // FillFactory IBIS51300
{.name="kai11002", .type=1, .code = SENSOR_KAI11000}, // Kodak KAI11002
{.name=NULL, .type=0, .code = 0} // end of list
{.name="detect", .type=3, .iface=NONE, .code = 0}, // to be automatically detected
{.name="none", .type=3, .iface=NONE, .code = SENSOR_NONE}, // no device attached
{.name="mux10359", .type=2, .iface=PARALLEL12, .code = SENSOR_MUX_10359}, // no device attached
{.name="zr32112", .type=1, .iface=PARALLEL12, .code = SENSOR_ZR32112}, // Zoran ZR32112
{.name="zr32212", .type=1, .iface=PARALLEL12, .code = SENSOR_ZR32212}, // Zoran ZR32212
{.name="kac1310", .type=1, .iface=PARALLEL12, .code = SENSOR_KAC1310}, // Kodak KAC1310
{.name="kac5000", .type=1, .iface=PARALLEL12, .code = SENSOR_KAC5000}, // Kodak KAC5000
{.name="mi1300", .type=1, .iface=PARALLEL12, .code = SENSOR_MI1300}, // Micron MI1300
{.name="mt9m001", .type=1, .iface=PARALLEL12, .code = SENSOR_MT9M001}, // MT9M001
{.name="mt9d001", .type=1, .iface=PARALLEL12, .code = SENSOR_MT9D001}, // MT9D001
{.name="mt9t001", .type=1, .iface=PARALLEL12, .code = SENSOR_MT9T001}, // MT9T001
{.name="mt9p006", .type=1, .iface=PARALLEL12, .code = SENSOR_MT9P006}, // MT9P006
{.name="mt9f002", .type=1, .iface=HISPI4, .code = SENSOR_MT9F002}, // MT9F002
{.name="ibis51300", .type=1, .iface=PARALLEL12, .code = SENSOR_IBIS51300}, // FillFactory IBIS51300
{.name="kai11002", .type=1, .iface=PARALLEL12, .code = SENSOR_KAI11000}, // Kodak KAI11002
{.name=NULL, .type=0, .iface=NONE, .code = 0} // end of list
};
static sens_iface_t port_iface[SENSOR_PORTS];
//#define DETECT_SENSOR 1 ///< Include sensors, May be OR-ed when looking for sensor/multiplexer code/name
//#define DETECT_MUX 2 ///< Include multiplexers, May be OR-ed when looking for sensor/multiplexer code/name
......@@ -111,6 +115,20 @@ const char * get_name_by_code(int code, ///< sensor code
return NULL;
}
/** Get sensor/multiplexer interface type by code */
sens_iface_t get_iface_by_code(int code, ///< sensor code
int type) ///< valid type [DETECT_SENSOR]|[DETECT_MUX]
///< @return sensor name or NULL for invalid code
{
int i;
for (i = 0; sensor_names[i].name; i++){
if ((sensor_names[i].type & type) && (sensor_names[i].code == code)){
return sensor_names[i].iface;
}
}
return NONE;
}
/** Get sensor port multiplexer type */
int get_detected_mux_code(int port) ///< Sensor port number (0..3)
......@@ -120,12 +138,59 @@ int get_detected_mux_code(int port) ///< Sensor port number (0..3)
}
/** Get sensor type */
int get_detected_sensor_code(int port, ///< Sensor port number (0..3)
int sub_chn) ///< Sensor subchannel (0..3)
int sub_chn) ///< Sensor subchannel (0..3), -1 - use first defined sub channel
///< @return sensor code (SENSOR_DETECT, SENSOR_NONE, or SENSOR_*)
{
return sensorPortConfig[port&3].sensor[sub_chn & 3];
int nchn,code;
port &= 3;
if (sub_chn >= 0)
return sensorPortConfig[port].sensor[sub_chn & 3];
// Negative sensor - find first defined
nchn = (get_detected_mux_code(port) == SENSOR_NONE)? 1: MAX_SENSORS;
for (sub_chn = 0; sub_chn < nchn; sub_chn++){
code = sensorPortConfig[port].sensor[sub_chn];
if ((code != SENSOR_DETECT) && (code != SENSOR_NONE))
return code;
}
return SENSOR_NONE;
}
/** Gert configured sensorport subchannels */
int get_subchannels(int port) ///< Sensor port
///< @return bitmask of available channels
{
int sub_chn, chn_mask = 0;
int nchn = (get_detected_mux_code(port) == SENSOR_NONE)? 1: MAX_SENSORS;
for (sub_chn = 0; sub_chn < nchn; sub_chn++){
if ((sensorPortConfig[port].sensor[sub_chn]!= SENSOR_DETECT) && (sensorPortConfig[port].sensor[sub_chn] != SENSOR_NONE)) {
chn_mask |= 1 << sub_chn;
}
}
return chn_mask;
}
/** Update per-port interface type after changing sensor/multiplexer */
void update_port_iface(int port) ///< Sensor port number (0..3)
{
sens_iface_t iface = get_iface_by_code(get_detected_mux_code(port), DETECT_MUX);
if (iface != NONE) {
port_iface[port] = iface;
return;
}
port_iface[port] = get_iface_by_code(get_detected_sensor_code(port,-1), DETECT_MUX); // '-1' - any subchannel
}
/** Get per-port interface type */
sens_iface_t get_port_interface(int port) ///< Sensor port number (0..3)
///< @ return interface type (none, parallel12, hispi4
{
return port_iface[port];
}
/** Set sensor port multiplexer type */
int set_detected_mux_code(int port, ///< Sensor port number (0..3)
int mux_type) ///< Sensor multiplexer type (SENSOR_DETECT, SENSOR_MUX_10359 or SENSOR_NONE)
......@@ -138,6 +203,7 @@ int set_detected_mux_code(int port, ///< Sensor port number (0..3)
return -EINVAL;
}
sensorPortConfig[port & 3].mux = mux_type;
update_port_iface(port);
return 0;
}
......@@ -154,6 +220,7 @@ int set_detected_sensor_code(int port, ///< Sensor port number (0..3)
return -EINVAL;
}
sensorPortConfig[port & 3].sensor[sub_chn] = sens_type;
update_port_iface(port);
return 0;
}
......@@ -182,7 +249,7 @@ static int get_channel_sub_from_name(struct device_attribute *attr) ///< Linux k
static ssize_t show_port_mux(struct device *dev, struct device_attribute *attr, char *buf)
{
int i;
const char * name = get_name_by_code(sensorPortConfig[get_channel_from_name(attr)].mux, DETECT_MUX);
const char * name = get_name_by_code(get_detected_mux_code(get_channel_from_name(attr)), DETECT_MUX);
if (name) return sprintf(buf,"%s\n", name);
// Should never get here
return sprintf(buf,"0x%x\n", sensorPortConfig[get_channel_from_name(attr)].mux);
......@@ -193,7 +260,7 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *attr, ch
int psch = get_channel_sub_from_name(attr);
int port = (psch>>4) &3;
int sub_chn = psch &3;
const char * name = get_name_by_code(sensorPortConfig[port].sensor[sub_chn], DETECT_SENSOR);
const char * name = get_name_by_code(get_detected_sensor_code(port,sub_chn), DETECT_SENSOR);
if (name) return sprintf(buf,"%s\n", name);
// Should never get here
return sprintf(buf,"0x%x\n", sensorPortConfig[(psch>>4) & 3].sensor[psch & 3]);
......
......@@ -20,9 +20,15 @@
#define DETECT_SENSOR 1 ///< Include sensors, May be OR-ed when looking for sensor/multiplexer code/name
#define DETECT_MUX 2 ///< Include multiplexers, May be OR-ed when looking for sensor/multiplexer code/name
typedef enum {NONE,PARALLEL12,HISPI4} sens_iface_t; ///< Sensor port interface type
int get_code_by_name(const char * name, int type);
const char * get_name_by_code(int code, int type);
sens_iface_t get_iface_by_code(int code, int type);
int get_detected_mux_code(int port);
int get_detected_sensor_code(int port, int sub_chn);
int get_subchannels(int port);
int set_detected_mux_code(int port, int mux_type);
int set_detected_sensor_code(int port, int sub_chn, int mux_type);
sens_iface_t get_port_interface(int port);
......@@ -146,7 +146,7 @@ wait_queue_head_t aframepars_wait_queue[SENSOR_PORTS];// used to wait for
/* Remove after compilation OK */
struct sensorproc_t * sensorproc = NULL;
//void camera_interrupts (int on) {}
//void compressor_interrupts (int on) {}
#if 0
#define wait_event_interruptible(wq, condition) \
({ \
......@@ -353,6 +353,16 @@ inline unsigned long get_imageParamsPrev(int sensor_port, int n)
return aframepars[sensor_port][(thisFrameNumber(sensor_port) - 1) & PARS_FRAMES_MASK].pars[n];
}
/** Reads past parameters (small subset of all) fro absolute frame number */
inline unsigned long get_imageParamsPast(int sensor_port, ///< sensor port (0..3)
int n, ///< parameter index (should be 128..143)
int frame) ///< absolute frame number
{
return apastpars[sensor_port][frame & PASTPARS_SAVE_ENTRIES_MASK].past_pars[n-PARS_SAVE_FROM];
}
/**
* @brief writes read-only parameter to the current frame (does not propagate to next frames as setFramePar() does)
* In most cases you really need to use setFramePar() instead;
......@@ -1181,11 +1191,12 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
break;
case LSEEK_INTERRUPT_OFF: // disable camera interrupts
MDF2(printk("LSEEK_INTERRUPT_OFF\n"));
camera_interrupts(0);
// compressor_interrupts(0,sensor_port);
sensor_interrupts(0,sensor_port);
break;
case LSEEK_INTERRUPT_ON: // enable camera interrupts
MDF2(printk("LSEEK_INTERRUPT_ON\n"));
camera_interrupts(1);
// MDF2(printk("LSEEK_INTERRUPT_ON\n"));
sensor_interrupts(1,sensor_port);
break;
}
}
......
......@@ -21,6 +21,8 @@ void resetFrameNumber (int sensor_port); /// reset this frame number (called fr
unsigned long get_imageParamsThis (int sensor_port, int n);
unsigned long get_imageParamsPrev (int sensor_port, int n);
unsigned long get_imageParamsPast(int sensor_port, int n, int frame);
void set_imageParamsThis (int sensor_port, int n, unsigned long d);
unsigned long get_globalParam (int sensor_port, int n);
......
......@@ -113,8 +113,6 @@
//#include "fpga_io.h"//fpga_table_write_nice
#include "framepars.h" // for debug mask
#include <elphel/elphel393-mem.h>
#include "legacy_defines.h" // temporarily
//#include "cc3x3.h"
#include "x393.h"
#include "histograms.h"
......
......@@ -55,8 +55,6 @@
#include "imu_log393.h"
#include "x393.h"
#include "cci2c.h"
//#include "legacy_defines.h" // temporarily
#if 0
#define D(x) x
......
......@@ -350,8 +350,7 @@
#include "framepars.h" // parameters manipulation
#include "sensor_common.h"
#include "pgm_functions.h"
//#include "x3x3.h" // hardware definitions
#include "legacy_defines.h" // temporarily
#include "x393.h"
#include "sensor_i2c.h"
......@@ -647,16 +646,16 @@ static unsigned short mt9p001_multiregs[]=
};
int mt9x001_pgm_detectsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_initsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_window (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_window_safe (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_window_common(int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_limitfps (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_exposure (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_gains (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_triggermode (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_sensorregs (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame8);
int mt9x001_pgm_detectsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_initsensor (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_window (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_window_safe (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_window_common(int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_limitfps (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_exposure (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_gains (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_triggermode (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int mt9x001_pgm_sensorregs (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
// @brief read 2 bytes from i2c
#ifdef NC353
#define I2C_READ_DATA16(x) ((i2c_read_data[(x)<<1]<<8)+i2c_read_data[((x)<<1)+1])
......@@ -691,23 +690,24 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
int sensor_subtype=0;
int i;
struct sensor_t * psensor; // current sensor
MDF4(printk(" frame8=%d\n",frame8));
x393_sensio_ctl_t sensio_ctl = {.d32=0};
MDF4(printk(" frame16=%d\n",frame16));
// MDD1(printk("sensor=0x%x\n", (int)sensor));
if (thispars->pars[P_SENSOR]!=0) { ///already initialized - called second time after common pgm_detectsensor(), first time is inside pgm_detectsensor()
MDF1(printk(" sensor 0x%x already detected, exiting\n",(int) thispars->pars[P_SENSOR]));
return sensor->sensorType;
}
// try MT9P001 first
psensor= &mt9p001;
#ifdef NC353
// set control lines
CCAM_NEGRST; ///set negative MRST polarity
CCAM_TRIG_INT;
CCAM_MRST_OFF;
CCAM_ARST_OFF;
udelay (100);
// try MT9P001 first
psensor= &mt9p001;
#ifdef NC353
local_irq_save(flags); // IRQ Off
i2c_stop_wait();
i2c_writeData(0, (psensor->i2c_addr) & 0xfe, &chipver_reg, 1, 0); // no stop before read (cxi2c.c)
......@@ -718,6 +718,22 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
sensor_subtype=MT9P_TYP; //1;
}
#else
// set control lines
sensio_ctl.mrst = 1;
sensio_ctl.mrst_set = 1;
sensio_ctl.arst = 1;
sensio_ctl.arst_set = 1;
sensio_ctl.aro = 1;
sensio_ctl.aro_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
sensio_ctl.d32=0;
// reset mmcm
sensio_ctl.mmcm_rst = 1;
sensio_ctl.mmcm_rst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
sensio_ctl.mmcm_rst = 0;
x393_sensio_ctrl(sensio_ctl,sensor_port);
udelay(50); // is it needed?
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw);
if (((i2c_read_dataw ^ MT9P001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9P001 2592x1944 sensor, chip ID=%x\n",i2c_read_dataw);
......@@ -727,7 +743,7 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
// printk("sensor id= 0x%x\r\n",i2c_read_data[0]);
// MDD1(printk("sensor=0x%x\n", (int)sensor));
if (sensor_subtype ==0) { // not a 5MPix chip
CCAM_ARST_ON;
// CCAM_ARST_ON; // Why was it here
psensor= &mt9m001; //address the same for all others
#ifdef NC353
local_irq_save(flags); // IRQ Off
......@@ -823,8 +839,12 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
for (i=0;i<8;i++) {
// MDF(printk("i=%d, m=0x%lx\n",i,GLOBALPARS(G_MULTI_REGSM+i)));
}
// CCAM_ARO_ON ; //set Does it need to be set here? Not earlier (as it is now set for NC393
MDF4(printk(" set ARO (TRIGGER) line HIGH\n"));
CCAM_ARO_ON ; //set
sensio_ctl.d32=0;
sensio_ctl.aro = 1;
sensio_ctl.aro_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
return sensor->sensorType;
//NOTE 353: hardware i2c is turned off (not needed in 393)
}
......@@ -844,9 +864,11 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
struct frameparspair_t pars_to_update[258+(MAX_SENSORS * P_MULTI_NUMREGS )]; // for all the sensor registers. Other P_* values will reuse the same ones
int first_sensor_i2c;
unsigned short * sensor_register_overwrites;
MDF4(printk(" frame8=%d\n",frame8));
x393_sensio_ctl_t sensio_ctl = {.d32=0};
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= 0) return -1; // should be ASAP
// int fpga_addr=(frame8 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame8);
// int fpga_addr=(frame16 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame16);
// unsigned char i2c_read_data[512]; // each two bytes - one short word, big endian
u32 i2c_read_data_dw[256];
int nupdate=0;
......@@ -854,6 +876,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
int regval, regnum, mreg, j;
printk("Resetting MT9X001 sensor\r\n");
// reset sensor by applying MRST (low):
#ifdef NC353
CCAM_MRST_ON;
udelay (100);
CCAM_MRST_OFF;
......@@ -863,7 +886,6 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
if (GLOBALPARS(sensor_port, G_SENS_AVAIL)) {
first_sensor_i2c+= I2C359_INC * ((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 1)?1:((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 2)?2:3));
}
#ifdef NC353
i2c_read_data[0]=0;
local_irq_save(flags); // IRQ Off (rather long - all 256 registers through i2c, but there is no hurry - sensor is off)
i2c_stop_wait();
......@@ -884,7 +906,23 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
}
}
#else
for (i=0; i<256; i++) { // rdead all registers, one at a time (slower than in 353)
// CCAM_MRST_ON;
sensio_ctl.mrst = 0;
sensio_ctl.mrst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
udelay (100);
// CCAM_MRST_OFF;
sensio_ctl.mrst = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
sensio_ctl.d32=0;
// NC393: both sequencers started in pgm_detectsensor
udelay (100);
printk("Reading sensor registers to the shadows:\r\n");
first_sensor_i2c=sensor->i2c_addr;
if (GLOBALPARS(sensor_port, G_SENS_AVAIL)) {
first_sensor_i2c+= I2C359_INC * ((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 1)?1:((GLOBALPARS(sensor_port, G_SENS_AVAIL) & 2)?2:3));
}
for (i=0; i<256; i++) { // read all registers, one at a time (slower than in 353)
X3X3_I2C_RCV2(sensor_port, first_sensor_i2c, i, &(i2c_read_data_dw[i]));
}
for (i=0; i<256; i++) { // possible to modify register range to save (that is why nupdate is separate from i)
......@@ -927,8 +965,6 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
X3X3_SEQ_RUN;
local_irq_restore(flags); // IRQ restore
#else
X3X3_SEQ_RUN;
i2c_run();
#endif
nupdate=0; // Second pass over the registers to set
//#define SET_SENSOR_MBPAR(p,f,s,r,v)
......@@ -1038,11 +1074,11 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
// flip margins for mirrored images (except oversized, not to rely on sensor->clearWidth/sensor->clearHeight
if (!thispars->pars[P_OVERSIZE]) {
if(flipX) {
wl = sensor->clearWidth - ww - wl - X313_MARGINS * dh;
wl = sensor->clearWidth - ww - wl - (2 * COLOR_MARGINS) * dh;
if(wl < 0) wl = 0;
}
if(flipY) {
wt = sensor->clearHeight - wh - wt - X313_MARGINS * dv;
wt = sensor->clearHeight - wh - wt - (2 * COLOR_MARGINS) * dv;
if(wt < 0) wt = 0;
}
// apply clearTop/clearLeft
......@@ -1160,7 +1196,7 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
uint64_t ull_fp1000s;
#endif
int target_virt_width=(thispars->pars[P_VIRT_KEEP])?(thispars->pars[P_VIRT_WIDTH]):0;
MDF4(printk(" frame8=%d\n",frame8));
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
switch(styp) {
case MT9P_TYP: //page 16
......@@ -1925,7 +1961,7 @@ int mt9x001_pgm_sensorregs (int sensor_port, ///< sensor port
///< @return 0 - OK, negative - error
{
MDF4(printk(" frame8=%d\n",frame8));
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// send all parameters marked as "needed to be processed" to the sensor, clear those flags
// mask out all non sensor pars
......
......@@ -114,17 +114,15 @@
#include "framepars.h" // parameters manipulation
#include "sensor_common.h"
#include "pgm_functions.h"
//#include "x3x3.h" // hardware definitions
#include "legacy_defines.h" // temporarily
#include "sensor_i2c.h"
#include "clock10359.h"
#include "x393.h"
/**
* \def D(x) optional debug output
*/
#define X313_MARGINS 4
#if ELPHEL_DEBUG
#define MDF(x) {printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);x ;}
......@@ -384,7 +382,7 @@ inline int sensor_wl(int wl, ///< Specified window left margin
int i,d;
if (!oversize) {
if(flipX) {
wl = sensor->clearWidth - ww - wl - X313_MARGINS * dh;
wl = sensor->clearWidth - ww - wl - (2 * COLOR_MARGINS) * dh;
if(wl < 0) wl = 0;
}
// apply clearTop/clearLeft
......@@ -427,7 +425,7 @@ inline int sensor_wt(int wt, ///< Specified window top margin
{
if (!oversize) {
if(flipY) {
wt = sensor->clearHeight - wh - wt - X313_MARGINS * dv;
wt = sensor->clearHeight - wh - wt - (2 * COLOR_MARGINS) * dv;
if(wt < 0) wt = 0;
}
// apply clearTop/clearLeft
......@@ -500,7 +498,7 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
bh= thispars->pars[P_BIN_HOR];
bv= thispars->pars[P_BIN_VERT];
ww= thispars->pars[P_SENSOR_PIXH] * dh;
// SETFRAMEPARS_SET(P_SENSOR_PIXV, height+X313_MARGINS); // full height for the sensor (after decimation), including margins
// SETFRAMEPARS_SET(P_SENSOR_PIXV, height+(2 * COLOR_MARGINS)); // full height for the sensor (after decimation), including margins
wh= thispars->pars[P_SENSOR_PIXV] * dv; // number of scan lines read from the sensor multipled by decimation
d = 2 * bh * (ww / (2 * bh));
if (unlikely(d != ww)) { // correct window width if needed
......@@ -526,12 +524,12 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
sequence = (sequence<<2) | (i & 3);
}
// Now sequence may be opposite to that of the P_MULTI_SEQUENCE
// wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0] += X313_MARGINS*dv; // include margins into individual sensor WOI-sizes
// wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1] += X313_MARGINS*dv;
// wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] += X313_MARGINS*dv;
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0] = (((wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0]/dv) & ~1)+ X313_MARGINS)*dv; // include margins into individual sensor WOI-sizes, make even number of output lines
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1] = (((wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1]/dv) & ~1)+ X313_MARGINS)*dv;
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] = (((wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2]/dv) & ~1)+ X313_MARGINS)*dv;
// wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0] += (2 * COLOR_MARGINS)*dv; // include margins into individual sensor WOI-sizes
// wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1] += (2 * COLOR_MARGINS)*dv;
// wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] += (2 * COLOR_MARGINS)*dv;
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0] = (((wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+0]/dv) & ~1)+ (2 * COLOR_MARGINS))*dv; // include margins into individual sensor WOI-sizes, make even number of output lines
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1] = (((wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+1]/dv) & ~1)+ (2 * COLOR_MARGINS))*dv;
wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2] = (((wois[(P_MULTI_HEIGHT1-P_MULTI_WOI)+2]/dv) & ~1)+ (2 * COLOR_MARGINS))*dv;
......@@ -545,11 +543,11 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
// Modify sequence if one or 2 frames is skipped from top because of P_WOI_TOP
// Margins
if (flipX) {
wl= (thispars->pars[P_SENSOR_WIDTH]+dh*X313_MARGINS)-ww-wl; // simplified (ww includes margins*dh)
wl= (thispars->pars[P_SENSOR_WIDTH]+dh*(2 * COLOR_MARGINS))-ww-wl; // simplified (ww includes margins*dh)
if(wl < 0) wl = 0;
}
if (flipY) {
wt= (thispars->pars[P_SENSOR_HEIGHT]+dv*X313_MARGINS)-wh-wt; // simplified (wh includes margins*dv)
wt= (thispars->pars[P_SENSOR_HEIGHT]+dv*(2 * COLOR_MARGINS))-wh-wt; // simplified (wh includes margins*dv)
if(wt < 0) wt = 0;
}
if ((wt>height1) && (sequence >>2)) { // only skip if anything is left
......@@ -690,13 +688,13 @@ int multisensor_pgm_window_common (int sensor_port, ///< sensor p
if (flipY) multi_mode_flips ^= 0x2a;
MDF25(printk("sequence=0x%x flipX=%x flipY=%x multi_mode_flips=0x%x \n",sequence,flipX,flipY,multi_mode_flips ));
SETFRAMEPARS_COND(P_MULTI_MODE_FLIPS, multi_mode_flips);
// subtract X313_MARGINS from the first and last frame
// subtract (2 * COLOR_MARGINS) from the first and last frame
// SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK1, ((height1 - (X313_MARGINS>>1)*(((height2==0) && (height3==0))?2:1)) & 0xffff) | (vblank2<<16));
// SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK2, ((height2 - (X313_MARGINS>>1)*(((height2 >0) && (height3==0))?1:0)) & 0xffff) | (vblank3<<16));
// Currently X313_MARGINS (4 pixels) are subtracted from the very last sub-frame only
SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK1, ((height1 - X313_MARGINS*(((height2==0) && (height3==0))?1:0)) & 0xffff) | (vblank2<<16));
SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK2, ((height2 - X313_MARGINS*(((height2 >0) && (height3==0))?1:0)) & 0xffff) | (vblank3<<16));
// SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK1, ((height1 - ((2 * COLOR_MARGINS)>>1)*(((height2==0) && (height3==0))?2:1)) & 0xffff) | (vblank2<<16));
// SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK2, ((height2 - ((2 * COLOR_MARGINS)>>1)*(((height2 >0) && (height3==0))?1:0)) & 0xffff) | (vblank3<<16));
// Currently (2 * COLOR_MARGINS) (4 pixels) are subtracted from the very last sub-frame only
SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK1, ((height1 - (2 * COLOR_MARGINS)*(((height2==0) && (height3==0))?1:0)) & 0xffff) | (vblank2<<16));
SETFRAMEPARS_COND(P_MULTI_HEIGHT_BLANK2, ((height2 - (2 * COLOR_MARGINS)*(((height2 >0) && (height3==0))?1:0)) & 0xffff) | (vblank3<<16));
if (GLOBALPARS(sensor_port, G_MULTI_CFG) & (1 <<G_MULTI_CFG_BEFORE)) {
//TODO: Program 10359 registers here
......@@ -935,6 +933,8 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
{
struct frameparspair_t pars_to_update[64]; // so far 39 actually needed
int nupdate=0;
x393_sensio_ctl_t sensio_ctl = {.d32=0};
x393_camsync_mode_t camsync_mode = {.d32=0};
unsigned long bitstream_version;
unsigned long sensor_id[MAX_SENSORS];
......@@ -943,7 +943,7 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
int this_sensor_type;
// .hact_delay = -2500, // -2.5ns delay in ps
// .sensorDelay = 2460, // Delay from sensor clock at FPGA output to pixel data transition (FPGA input), short cable (ps)
multi_unitialized=0; // reset this static variable - it will prevent copying individual flips to multiple until copmosite mode is used
multi_unitialized=0; // reset this static variable - it will prevent copying individual flips to multiple until composite mode is used
MDF3(printk(" frame16=%d\n",frame16));
GLOBALPARS(sensor_port,G_SENS_AVAIL)=0; // no 10359A board present
if (frame16 >= 0) return -1; // can only work in ASAP mode
......@@ -975,8 +975,13 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
printk("10353 sensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
udelay (100);// 0.0001 sec to stabilize clocks
X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset
X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also
// X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset
// X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also
// NC393 reset mmcm - is it needed? Clock was not changed yet
sensio_ctl.mmcm_rst = 1;
sensio_ctl.mmcm_rst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
// reset system and SDRAM DCMs on 10359
MULTISENSOR_WRITE_I2C16(sensor_port,I2C359_DCM_SYSTEM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
MULTISENSOR_WRITE_I2C16(sensor_port,I2C359_DCM_SDRAM, I2C359_DCM_RESET | I2C359_DCM_RESET90);
......@@ -1005,10 +1010,15 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
// Try to read chip version from each of the 3 possible sensors
printk("removing MRST from the sensor\n");
//
CCAM_NEGRST; // set negative MRST polarity
CCAM_TRIG_INT;
CCAM_MRST_OFF;
CCAM_ARST_OFF;
sensio_ctl.d32 = 0;
sensio_ctl.mrst = 1;
sensio_ctl.mrst_set = 1;
sensio_ctl.arst = 1;
sensio_ctl.arst_set = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
camsync_mode.trig = 0;
camsync_mode.trig_set = 1;
x393_camsync_mode (camsync_mode);
udelay (100);
GLOBALPARS(sensor_port,G_SENS_AVAIL) |= 1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)); // temporary to indicate sensor detection functions that they need to initialize multisensor registers
......@@ -1142,9 +1152,10 @@ Now overwrite sensor functions with it's own (originals (physical sensor ones) a
SETFRAMEPARS_SET(P_MULTI_HEIGHT2, 1940);
SETFRAMEPARS_SET(P_MULTI_HEIGHT3, 1940);
#ifdef NC353
CCAM_RESET_MCONTR_ON ; // Set mode that resets memory controller pointers after each frame sync. TODO: Later - make it work without?
CCAM_ENDFRAMES_EN ; // Enable ending frame being compressed if no more data will be available (frame ended before specified number of blocks compressed)
#endif
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return this_sensor_type;
}
......@@ -1295,7 +1306,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
int multi_frame=0;
if (composite && SENSOR_IN_SEQ_EN(1,sequence,sensor_mask)) { // specified in sequence is enabled
multi_frame=1;
total_height+=(vblank+X313_MARGINS)*dv;
total_height+=(vblank+(2 * COLOR_MARGINS))*dv;
MDF25(printk(" total_height=0x%x\n",total_height));
if (!height2) height2=sensor->imageHeight;
if (height2 < sensor->minHeight) height2=sensor->minHeight;
......@@ -1305,7 +1316,7 @@ int multisensor_pgm_multisens (int sensor_port, ///< sensor port n
total_height+=height2;
MDF25(printk(" total_height=0x%x\n",total_height));
if (SENSOR_IN_SEQ_EN(2,sequence,sensor_mask)) {
total_height+=(vblank+X313_MARGINS)*dv;
total_height+=(vblank+(2 * COLOR_MARGINS))*dv;
MDF25(printk(" total_height=0x%x\n",total_height));
if (!height3) height3=sensor->imageHeight;
if (height3 < sensor->minHeight) height3=sensor->minHeight;
......
......@@ -24,6 +24,7 @@
*/
#define I2C359_CLK_NUMBER 4 ///< OK with NC393, clock is ANDed with 3
//multisensor.h
//#define I2C359_INC 2 //< slave address increment between sensors in 10359A board (broadcast, 1,2,3) (7 bits SA) moved to sensor_common
......
......@@ -210,17 +210,9 @@
#include "pgm_functions.h"
#include "jpeghead.h" // to program FPGA Huffman tables
#include "x393.h"
// #include "legacy_defines.h" // temporarily
#include "sensor_i2c.h"
#include "x393_videomem.h"
#define COLOR_MARGINS 2 // add this many pixels each side
#define X313_TIMESTAMPLEN 28 // pixels used for timestamp (in linescan mode added after the line)
#define X393_TILEHOR 16
#define X393_TILEVERT 16
#define X393_MAXWIDTH 65536 // 4096 // multiple of 128
#define X393_MAXHEIGHT 65536 // 16384 // multiple of 16 - unsafe - not enough room for black level subtraction
#define X393_MAXHEIGHT_SAFE 65536 // 4096 // multiple of 16 OK for black level subtraction TODO: disable black level if unsafe
#include "detect_sensors.h"
/**
* @brief optional debug output macros
......@@ -345,172 +337,238 @@ int add_sensor_proc(int index, int (*sens_func)(int sensor_port, struct sensor_t
* - set sensor structure (capabilities),
* - set function pointers (by directly calling sensor specific \b *_pgm_detectsensor */
int pgm_detectsensor (int sensor_port, ///< sensor port number (0..3)
struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters
struct framepars_t * prevpars, ///< sensor previous parameters (not used here)
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
struct sensor_t * sensor, ///< sensor static parameters (capabilities)
struct framepars_t * thispars, ///< sensor current parameters
struct framepars_t * prevpars, ///< sensor previous parameters (not used here)
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
int was_sensor_freq;
int qperiod;
int i2cbytes;
int phase;
x393_camsync_mode_t camsync_mode = {.d32=0};
int was_sensor_freq;
int qperiod;
int i2cbytes;
int phase;
int mux;
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= 0) return -1; // can only work in ASAP mode
if (thispars->pars[P_SENSOR]) return 0; // Sensor is already detected - do not bother (to re-detect it P_SENSOR should be set to 0)
// no other initializations, just the sensor-related stuff (starting with lowest sensor clock)
// stop hardware i2c controller, so it will not get stuck when waiting for !busy
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= 0) return -1; // can only work in ASAP mode
if (thispars->pars[P_SENSOR]) return 0; // Sensor is already detected - do not bother (to re-detect it P_SENSOR should be set to 0)
// no other initializations, just the sensor-related stuff (starting with lowest sensor clock)
// stop hardware i2c controller, so it will not get stuck when waiting for !busy
#ifndef NC353
// NC393 - nothing to do here - use a separate module for sensor setup: DT, sysfs, something else (add pin pullup/down)
return 0;
#else
// NC393 - nothing to do here - use a separate module for sensor setup: DT, sysfs, something else (add pin pullup/down)
// currently assign same sensor to all subchannles (first present)
thispars->pars[P_SENSOR] = get_detected_sensor_code(sensor_port, -1); // "-1" - first detected sensor
GLOBALPARS(sensor_port, G_SUBCHANNELS) = get_subchannels(sensor_port);
mux = get_detected_mux_code(sensor_port); // none/detect/10359
if ((mux == SENSOR_NONE) && (thispars->pars[P_SENSOR] == SENSOR_NONE))
return 0; // no sensor/mux enabled on this port
//TODO NC393: turn on both sequencers why MRST is active, then i2c frame will definitely match ? Or is it already done in FPGA?
sequencer_stop_run_reset(sensor_port, SEQ_CMD_RESET);
sequencer_stop_run_reset(sensor_port, SEQ_CMD_RUN); // also programs status update
i2c_stop_run_reset (sensor_port, I2C_CMD_RESET);
i2c_drive_mode (sensor_port, SDA_DRIVE_HIGH, SDA_RELEASE);
i2c_stop_run_reset (sensor_port, I2C_CMD_RUN); // also programs status update
camsync_mode.trig = 0;
camsync_mode.trig_set = 1;
camsync_mode.ext = 1; // use external timestamp (default)
camsync_mode.ext_set = 1;
x393_camsync_mode (camsync_mode);
// NOTE: disabling interrupts here !!!
camera_interrupts (0);
MDF1(printk("Disabled camera interrupts\n"));
// This 3 initialization commands were not here, trying to temporarily fix problem when WP was 8/16 words higher than actual data in DMA buffer
if (GLOBALPARS(sensor_port, G_TEST_CTL_BITS) & (1<< G_TEST_CTL_BITS_RESET_DMA_COMPRESSOR )) {
MDF1(printk("x313_dma_stop()\n"));
/// x313_dma_stop();
MDF1(printk("x313_dma_init()\n"));
/// x313_dma_init();
MDF1(printk("reset_compressor()\n"));
reset_compressor(sensor_port);
}
// printk("trying MT9P001\n");
// mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
if (mux != SENSOR_NONE) {
// try multisensor here (before removing MRST)
multisensor_pgm_detectsensor (sensor_port, sensor, thispars, prevpars, frame16); // multisensor
}
if (thispars->pars[P_SENSOR]==0) { // multisensor not detected
printk("removing MRST from the sensor\n");
// CCAM_MRST_OFF;
printk("trying MT9P001\n");
mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
}
if (thispars->pars[P_SENSOR] == SENSOR_DETECT) {
sensor->sensorType=SENSOR_NONE; // to prevent from initializing again
printk("No image sensor found\r\n");
}
setFramePar(sensor_port, thispars, P_SENSOR_WIDTH, sensor->imageWidth); // Maybe get rid of duplicates?
setFramePar(sensor_port, thispars, P_SENSOR_HEIGHT, sensor->imageHeight); // Maybe get rid of duplicates?
if (sensor->i2c_period==0) sensor->i2c_period=2500; // SCL period in ns, (standard i2c - 2500)
qperiod=thispars->pars[P_I2C_QPERIOD];
if (qperiod==0) qperiod=(sensor->i2c_period * (thispars->pars[P_CLK_FPGA]/1000))/4000000;
setFramePar(sensor_port, thispars, P_I2C_QPERIOD | FRAMEPAIR_FORCE_NEWPROC, qperiod); // force i2c
i2cbytes=thispars->pars[P_I2C_BYTES];
if (i2cbytes==0) i2cbytes=sensor->i2c_bytes;
setFramePar(sensor_port, thispars, P_I2C_BYTES | FRAMEPAIR_FORCE_NEWPROC, i2cbytes); // force i2c
// restore/set sensor clock
if ((was_sensor_freq < sensor->minClockFreq) || (was_sensor_freq > sensor->maxClockFreq)) was_sensor_freq=sensor->nomClockFreq;
setFramePar(sensor_port, thispars, P_CLK_SENSOR | FRAMEPAIR_FORCE_NEWPROC, was_sensor_freq); // will schedule clock/phase adjustment
phase=thispars->pars[P_SENSOR_PHASE];
// TODO: remove phase adjustment from here
if (phase==0) {
phase= 0x40000;
setFramePar(sensor_port, thispars, P_SENSOR_PHASE | FRAMEPAIR_FORCE_NEWPROC, phase); // will schedule clock/phase adjustment
}
setFramePar(sensor_port, thispars, P_IRQ_SMART | FRAMEPAIR_FORCE_NEWPROC, 3); // smart IRQ mode programming (and enable interrupts)
// NOTE: sensor detected - enabling camera interrupts here (actual interrupts will start later)
// Here interrupts are disabled - with compressor_interrupts (0) earlier in this function)
compressor_interrupts (1,sensor_port);
sensor_interrupts (1,sensor_port);
return 0;
#else
// TODO: Add 10347 detection here // if (IS_KAI11000) return init_KAI11000();
// Need to set slow clock
// f1=imageParamsR[P_CLK_SENSOR]=20000000; setClockFreq(1, imageParamsR[P_CLK_SENSOR]); X3X3_RSTSENSDCM;
was_sensor_freq=getClockFreq(1); // using clock driver data, not thispars
setFramePar(sensor_port, thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(sensor_port, thispars, P_CLK_SENSOR, 48000000);
setClockFreq(1, thispars->pars[P_CLK_SENSOR]);
printk("\nsensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
udelay (100);// 0.0001 sec to stabilize clocks
X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset
X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also
mdelay (50);// 0.05 sec to stabilize clocks
// setting reasonable state of the control signals
CCAM_DCLK_ON;
CCAM_CNVEN_OFF;
CCAM_NEGRST; ///set negative MRST polarity
CCAM_MRST_ON;
CCAM_TRIG_INT;
CCAM_EXTERNALTS_EN; // Maybe use default as enabled - yes, it will not be active if not available
udelay (100); // apply clock before removing MRS
// first trying MT9P001 that does not need converter
// try multisensor here (before removing MRST)
if (thispars->pars[P_SENSOR]==0) multisensor_pgm_detectsensor (sensor_port, sensor, thispars, prevpars, frame16); // multisensor
if (thispars->pars[P_SENSOR]==0) {
printk("removing MRST from the sensor\n");
CCAM_MRST_OFF;
}
if (thispars->pars[P_SENSOR]==0) {
mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
printk("trying MT9P001\n");
}
// temporary - disabling old sensors
// NOTE: disabling interrupts here !!!
compressor_interrupts (0);
MDF1(printk("Disabled camera interrupts\n"));
// This 3 initialization commands were not here, trying to temporarily fix problem when WP was 8/16 words higher than actual data in DMA buffer
if (GLOBALPARS(sensor_port, G_TEST_CTL_BITS) & (1<< G_TEST_CTL_BITS_RESET_DMA_COMPRESSOR )) {
MDF1(printk("x313_dma_stop()\n"));
/// x313_dma_stop();
MDF1(printk("x313_dma_init()\n"));
/// x313_dma_init();
MDF1(printk("reset_compressor()\n"));
reset_compressor(sensor_port);
}
// TODO: Add 10347 detection here // if (IS_KAI11000) return init_KAI11000();
// Need to set slow clock
// f1=imageParamsR[P_CLK_SENSOR]=20000000; setClockFreq(1, imageParamsR[P_CLK_SENSOR]); X3X3_RSTSENSDCM;
was_sensor_freq=getClockFreq(1); // using clock driver data, not thispars
setFramePar(sensor_port, thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(sensor_port, thispars, P_CLK_SENSOR, 48000000);
setClockFreq(1, thispars->pars[P_CLK_SENSOR]);
printk("\nsensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
udelay (100);// 0.0001 sec to stabilize clocks
X3X3_RSTSENSDCM; // FPGA DCM can fail after clock change, needs to be reset
X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also
mdelay (50);// 0.05 sec to stabilize clocks
// setting reasonable state of the control signals
CCAM_DCLK_ON;
CCAM_CNVEN_OFF;
CCAM_NEGRST; ///set negative MRST polarity
CCAM_MRST_ON;
CCAM_TRIG_INT;
CCAM_EXTERNALTS_EN; // Maybe use default as enabled - yes, it will not be active if not available
udelay (100); // apply clock before removing MRS
// first trying MT9P001 that does not need converter
// try multisensor here (before removing MRST)
if (thispars->pars[P_SENSOR]==0) multisensor_pgm_detectsensor (sensor_port, sensor, thispars, prevpars, frame16); // multisensor
if (thispars->pars[P_SENSOR]==0) {
printk("removing MRST from the sensor\n");
CCAM_MRST_OFF;
}
if (thispars->pars[P_SENSOR]==0) {
mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
printk("trying MT9P001\n");
}
// temporary - disabling old sensors
#define ENABLE_OLD_SENSORS 1
#ifdef ENABLE_OLD_SENSORS
if (thispars->pars[P_SENSOR]==0) { // no - it is not MT9P001)
printk("trying other MT9X001\n");
CCAM_CNVEN_ON;
// CCAM_ARST_ON; ///MT9P001 expects ARST==0 (STANDBY) - done inside mt9x001.c
// enable output for power converter signals
// This should be done first!!!
// printk ("Will Turn DC power for the sensor after 1 sec delay...\n"); udelay (1000000);
// turning on DC-DC converter may cause system to reboot because of a power spike, so start slow
if (thispars->pars[P_SENSOR]==0) { // no - it is not MT9P001)
printk("trying other MT9X001\n");
CCAM_CNVEN_ON;
// CCAM_ARST_ON; ///MT9P001 expects ARST==0 (STANDBY) - done inside mt9x001.c
// enable output for power converter signals
// This should be done first!!!
// printk ("Will Turn DC power for the sensor after 1 sec delay...\n"); udelay (1000000);
// turning on DC-DC converter may cause system to reboot because of a power spike, so start slow
#ifdef NC353
port_csp0_addr[X313_WA_DCDC] = 0x44; // 48 - enough, 41 - ok - was 0x61; //
printk ("sensor power set low\r\n ");
mdelay (10); // Wait voltage to come up (~10 ms)
mdelay (10); // Wait voltage to come up (~10 ms)
printk ("will set to 0x41\r\n");
mdelay (10); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x41; //
printk ("will set to 0x30\r\n");
mdelay (10); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x30; //
printk ("will set to 0x28\r\n");
mdelay (10); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x28; //
printk ("will set to 0x24\r\n");
mdelay (10); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x24; //
printk ("will set to 0x22\r\n");
mdelay (10); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x22; //
mdelay (10); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x10; // now - full frequency (same as 0x21). Slow that down if the sensor clock is above 20MHz (i.e.0x22 for 40MHz)
printk (".. full\r\n");
mdelay (10); // Wait voltage to stabilize
CCAM_POSRST; //set positive MRST polarity (default)
udelay (100); // apply clock before removing MRST
CCAM_MRST_OFF;
mdelay (10); // Wait voltage to stabilize
CCAM_POSRST; //set positive MRST polarity (default)
udelay (100); // apply clock before removing MRST
CCAM_MRST_OFF;
#endif
}
}
#ifdef CONFIG_ETRAX_ELPHEL_KAC1310
if (thispars->pars[P_SENSOR]==0) kac1310_pgm_detectsensor(sensor, thispars, prevpars, frame16); // try KAC-1310 (does not exist anymore)
if (thispars->pars[P_SENSOR]==0) kac1310_pgm_detectsensor(sensor, thispars, prevpars, frame16); // try KAC-1310 (does not exist anymore)
#endif
#ifdef CONFIG_ETRAX_ELPHEL_IBIS51300
if (thispars->pars[P_SENSOR]==0) ibis1300_pgm_detectsensor(sensor, thispars, prevpars, frame16); // try IBIS5-1300 (software dead)
if (thispars->pars[P_SENSOR]==0) ibis1300_pgm_detectsensor(sensor, thispars, prevpars, frame16); // try IBIS5-1300 (software dead)
#endif
// invert MRST for other sensors
if (thispars->pars[P_SENSOR]==0) {
CCAM_NEGRST; //set negative MRST polarity
printk ("Inverted MRST\n");
udelay (100);
}
// invert MRST for other sensors
if (thispars->pars[P_SENSOR]==0) {
CCAM_NEGRST; //set negative MRST polarity
printk ("Inverted MRST\n");
udelay (100);
}
#ifdef CONFIG_ETRAX_ELPHEL_MT9X001
if (thispars->pars[P_SENSOR]==0) printk("trying MT9X001\n");
if (thispars->pars[P_SENSOR]==0) mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 1.3/2.0/3.0 Mpixel
if (thispars->pars[P_SENSOR]==0) printk("trying MT9X001\n");
if (thispars->pars[P_SENSOR]==0) mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 1.3/2.0/3.0 Mpixel
#endif
#ifdef CONFIG_ETRAX_ELPHEL_KAC1310
if (thispars->pars[P_SENSOR]==0) kac5000_pgm_detectsensor(sensorsensor_port, sensor, thispars, prevpars, frame16); // try KAC-5000
if (thispars->pars[P_SENSOR]==0) kac5000_pgm_detectsensor(sensorsensor_port, sensor, thispars, prevpars, frame16); // try KAC-5000
#endif
#ifdef CONFIG_ETRAX_ELPHEL_ZR32112
if (thispars->pars[P_SENSOR]==0) zr32112_pgm_detectsensor(sensorsensor_port, sensor, thispars, prevpars, frame16); // try ZR32112
if (thispars->pars[P_SENSOR]==0) zr32112_pgm_detectsensor(sensorsensor_port, sensor, thispars, prevpars, frame16); // try ZR32112
#endif
#ifdef CONFIG_ETRAX_ELPHEL_ZR32212
if (thispars->pars[P_SENSOR]==0) zr32212_pgm_detectsensor(sensorsensor_port, sensor, thispars, prevpars, frame16); // try ZR32212
if (thispars->pars[P_SENSOR]==0) zr32212_pgm_detectsensor(sensorsensor_port, sensor, thispars, prevpars, frame16); // try ZR32212
#endif
#endif // ENABLE_OLD_SENSORS *************** temporary disabling other sensors ********************
if (thispars->pars[P_SENSOR]==0) {
sensor->sensorType=SENSOR_NONE; // to prevent from initializing again
printk("No image sensor found\r\n");
}
setFramePar(sensor_port, thispars, P_SENSOR_WIDTH, sensor->imageWidth); // Maybe get rid of duplicates?
setFramePar(sensor_port, thispars, P_SENSOR_HEIGHT, sensor->imageHeight); // Maybe get rid of duplicates?
if (sensor->i2c_period==0) sensor->i2c_period=2500; // SCL period in ns, (standard i2c - 2500)
qperiod=thispars->pars[P_I2C_QPERIOD];
if (qperiod==0) qperiod=(sensor->i2c_period * (thispars->pars[P_CLK_FPGA]/1000))/4000000;
setFramePar(sensor_port, thispars, P_I2C_QPERIOD | FRAMEPAIR_FORCE_NEWPROC, qperiod); // force i2c
i2cbytes=thispars->pars[P_I2C_BYTES];
if (i2cbytes==0) i2cbytes=sensor->i2c_bytes;
setFramePar(sensor_port, thispars, P_I2C_BYTES | FRAMEPAIR_FORCE_NEWPROC, i2cbytes); // force i2c
// restore/set sensor clock
if ((was_sensor_freq < sensor->minClockFreq) || (was_sensor_freq > sensor->maxClockFreq)) was_sensor_freq=sensor->nomClockFreq;
setFramePar(sensor_port, thispars, P_CLK_SENSOR | FRAMEPAIR_FORCE_NEWPROC, was_sensor_freq); // will schedule clock/phase adjustment
phase=thispars->pars[P_SENSOR_PHASE];
// TODO: remove phase adjustment from here
if (phase==0) {
phase= 0x40000;
setFramePar(sensor_port, thispars, P_SENSOR_PHASE | FRAMEPAIR_FORCE_NEWPROC, phase); // will schedule clock/phase adjustment
}
setFramePar(sensor_port, thispars, P_IRQ_SMART | FRAMEPAIR_FORCE_NEWPROC, 3); // smart IRQ mode programming (and enable interrupts)
// NOTE: sensor detected - enabling camera interrupts here (actual interrupts will start later)
// Here interrupts are disabled - with camera_interrupts (0) earlier in this function)
camera_interrupts (1);
return 0;
if (thispars->pars[P_SENSOR]==0) {
sensor->sensorType=SENSOR_NONE; // to prevent from initializing again
printk("No image sensor found\r\n");
}
setFramePar(sensor_port, thispars, P_SENSOR_WIDTH, sensor->imageWidth); // Maybe get rid of duplicates?
setFramePar(sensor_port, thispars, P_SENSOR_HEIGHT, sensor->imageHeight); // Maybe get rid of duplicates?
if (sensor->i2c_period==0) sensor->i2c_period=2500; // SCL period in ns, (standard i2c - 2500)
qperiod=thispars->pars[P_I2C_QPERIOD];
if (qperiod==0) qperiod=(sensor->i2c_period * (thispars->pars[P_CLK_FPGA]/1000))/4000000;
setFramePar(sensor_port, thispars, P_I2C_QPERIOD | FRAMEPAIR_FORCE_NEWPROC, qperiod); // force i2c
i2cbytes=thispars->pars[P_I2C_BYTES];
if (i2cbytes==0) i2cbytes=sensor->i2c_bytes;
setFramePar(sensor_port, thispars, P_I2C_BYTES | FRAMEPAIR_FORCE_NEWPROC, i2cbytes); // force i2c
// restore/set sensor clock
if ((was_sensor_freq < sensor->minClockFreq) || (was_sensor_freq > sensor->maxClockFreq)) was_sensor_freq=sensor->nomClockFreq;
setFramePar(sensor_port, thispars, P_CLK_SENSOR | FRAMEPAIR_FORCE_NEWPROC, was_sensor_freq); // will schedule clock/phase adjustment
phase=thispars->pars[P_SENSOR_PHASE];
// TODO: remove phase adjustment from here
if (phase==0) {
phase= 0x40000;
setFramePar(sensor_port, thispars, P_SENSOR_PHASE | FRAMEPAIR_FORCE_NEWPROC, phase); // will schedule clock/phase adjustment
}
setFramePar(sensor_port, thispars, P_IRQ_SMART | FRAMEPAIR_FORCE_NEWPROC, 3); // smart IRQ mode programming (and enable interrupts)
// NOTE: sensor detected - enabling camera interrupts here (actual interrupts will start later)
// Here interrupts are disabled - with compressor_interrupts (0) earlier in this function)
compressor_interrupts (1);
return 0;
#endif
}
......@@ -616,6 +674,7 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
{
#ifndef NC353
x393_sensio_ctl_t sensio_ctl = {.d32=0};
x393_sensio_tim0_t sensio_tim0 = {.d32=0};
x393_sensio_tim1_t sensio_tim1 = {.d32=0};
x393_sensio_tim2_t sensio_tim2 = {.d32=0};
......@@ -626,6 +685,7 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
sensio_tim0.d32 = thispars->pars[P_SENSOR_IFACE_TIM0];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim0, sensio_tim0);
set_x393_sensio_tim0 (sensio_tim0, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
MDF3(printk(" X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim0, 0x%x)\n", sensor_port, frame16, sensio_tim0.d32));
}
......@@ -633,21 +693,35 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
sensio_tim1.d32 = thispars->pars[P_SENSOR_IFACE_TIM1];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim1, sensio_tim1);
set_x393_sensio_tim1 (sensio_tim1, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
MDF3(printk(" X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim1, 0x%x)\n", sensor_port, frame16, sensio_tim1 .d32));
}
if (FRAMEPAR_MODIFIED(P_SENSOR_IFACE_TIM2)) {
sensio_tim2.d32 = thispars->pars[P_SENSOR_IFACE_TIM2];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim2, sensio_tim2);
set_x393_sensio_tim2 (sensio_tim2, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
MDF3(printk(" X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim2, 0x%x)\n", sensor_port, frame16, sensio_tim2.d32));
}
if (FRAMEPAR_MODIFIED(P_SENSOR_IFACE_TIM3)) {
sensio_tim3.d32 = thispars->pars[P_SENSOR_IFACE_TIM3];
// X393_SEQ_SEND1 (sensor_port, frame16, x393_sensio_tim3, sensio_tim3);
set_x393_sensio_tim3 (sensio_tim3, sensor_port); // write directly, sequencer may be not operational
sensio_ctl.set_dly = 1;
MDF3(printk(" X393_SEQ_SEND1(0x%x, 0x%x, x393_sensio_tim3, 0x%x)\n", sensor_port, frame16, sensio_tim3.d32));
}
if (get_port_interface == PARALLEL12){
if (FRAMEPAR_MODIFIED(P_SENSOR_PHASE)) { // for parallel sensor it means quadrants: 90-degree shifts for data [1:0], hact [3:2] and vact [5:4]
sensio_ctl.quadrants = thispars->pars[P_SENSOR_PHASE] & 0x3f;
sensio_ctl.quadrants_set = 1;
}
if (sensio_ctl.d32)
x393_sensio_ctrl(sensio_ctl, sensor_port);
} else {
/* TODO 393: Add HISPI code */
}
return 0;
#else
......
......@@ -17,6 +17,13 @@
*******************************************************************************/
#include "sensor_i2c.h"
#define COLOR_MARGINS 2 // add this many pixels each side
#define X313_TIMESTAMPLEN 28 // pixels used for timestamp (in linescan mode added after the line)
#define X393_TILEHOR 16
#define X393_TILEVERT 16
#define X393_MAXWIDTH 65536 // 4096 // multiple of 128
#define X393_MAXHEIGHT 65536 // 16384 // multiple of 16 - unsafe - not enough room for black level subtraction
#define X393_MAXHEIGHT_SAFE 65536 // 4096 // multiple of 16 OK for black level subtraction TODO: disable black level if unsafe
int init_pgm_proc(void);
int add_sensor_proc(int index, int (*sens_func)(int sensor_port, struct sensor_t * , struct framepars_t * , struct framepars_t *, int ));
......
......@@ -60,6 +60,7 @@
/** @brief Contains read and write pointers along with IRQ number for a single channel*/
struct jpeg_ptr_t {
volatile u32 frame; ///< Absolute frame number
volatile int jpeg_wp; ///< JPEG write pointer in 32 bit words
volatile int jpeg_rp; ///< JPEG read pointer in 32 bit words
volatile int fpga_cntr_prev; ///< This field contains previous value of the FPGA transfer counter which is used to find out if it has changed. This pointer is in 32 bit words.
......@@ -252,7 +253,10 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
void *virt_addr;
// int prev_dword;
int xferred; // number of 32-byte chunks transferred since compressor was reset
x393_cmdseqmux_status_t cmdseqmux_status;
x393_afimux_status_t stat = x393_afimux0_status(jptr->chn_num);
int frame16;
u32 aframe = GLOBALPARS(jptr->chn_num,G_THIS_FRAME); // thisFrameNumber(jptr->chn_num); // current absolute frame number
xferred = stat.offset256 - (jptr->fpga_cntr_prev >> 3);
if (xferred == 0)
......@@ -262,6 +266,18 @@ static inline int updateIRQJPEG_wp(struct jpeg_ptr_t *jptr)
jptr->fpga_cntr_prev = jptr->jpeg_wp;
jptr->jpeg_wp = (stat.offset256 << 3);
// Find absolute frame number just compressed
cmdseqmux_status = x393_cmdseqmux_status(); // CMDSEQMUX status data (frame numbers and interrupts
switch (jptr->chn_num){
case 0: frame16 =cmdseqmux_status.frame_num0; break;
case 1: frame16 =cmdseqmux_status.frame_num1; break;
case 2: frame16 =cmdseqmux_status.frame_num2; break;
default: frame16 =cmdseqmux_status.frame_num3;
}
if (frame16 > (aframe & PARS_FRAMES_MASK))
aframe += 16;
jptr->frame = (aframe & ~PARS_FRAMES_MASK) | frame16; // This is absolute compressed frame number, may lag behind current one
/* debug code follows */
frame_counter[jptr->chn_num] += 1;
if (jptr->jpeg_wp == 0) {
......@@ -416,12 +432,15 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
return interframe;
}
/**
* @brief Fill exif data with the current frame data, save pointer to Exif page in the interframe area
* @param jptr pointer to jpeg_ptr_t structure with read/write image pointers
* @param interframe pointer to interframe parameters structure
/** Fill exif data with the current frame data, save pointer to Exif page in the interframe area
*
* TODO NC393: Allow lag between current frame and compressor frame, use only previous parameters (among those copied)
*
*
*/
inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, struct interframe_params_t* interframe) {
inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, ///< pointer to jpeg_ptr_t structure with read/write image pointers
struct interframe_params_t* interframe) ///< pointer to interframe parameters structure
{
unsigned char short_buff[2];
unsigned int sensor_port = jptr->chn_num;
int index_time = jptr->jpeg_wp - 11;
......@@ -431,6 +450,12 @@ inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, struct interframe_params_t*
unsigned char orientations[]="1638274545273816";
unsigned char orientation_short[2];
int maker_offset;
u32 frame = jptr->frame;
int frame_index = frame & PASTPARS_SAVE_ENTRIES_MASK;
// [P_FRAME-PARS_SAVE_FROM
// Now find if parameters are still available or need pastpars (that may switch at any time or should we use pastpars already as they were copied
// at the start of the frame ?
//get_imageParamsThis
if (index_time<0) index_time+=get_globalParam (sensor_port, G_CIRCBUFSIZE)>>2;
// struct exif_datetime_t
......@@ -439,18 +464,18 @@ inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, struct interframe_params_t*
// may be split in datetime/subsec - now it will not notice missing subseq field in template
write_meta_irq(sensor_port, exif_meta_time_string, &meta_offsets.Photo_DateTimeOriginal, Exif_Photo_DateTimeOriginal, 27);
write_meta_irq(sensor_port, exif_meta_time_string, &meta_offsets.Image_DateTime, Exif_Image_DateTime, 20); // may use 27 if room is provided
putlong_meta_irq(sensor_port, get_imageParamsThis(sensor_port, P_EXPOS), &meta_offsets.Photo_ExposureTime, Exif_Photo_ExposureTime);
putlong_meta_irq(sensor_port, get_imageParamsThis(sensor_port, P_FRAME), &meta_offsets.Image_ImageNumber, Exif_Image_ImageNumber);
putlong_meta_irq(sensor_port, get_imageParamsPast(sensor_port, P_EXPOS, frame), &meta_offsets.Photo_ExposureTime, Exif_Photo_ExposureTime);
putlong_meta_irq(sensor_port, frame, &meta_offsets.Image_ImageNumber, Exif_Image_ImageNumber);
//Exif_Photo_MakerNote
global_flips=(get_imageParamsThis(sensor_port, P_FLIPH) & 1) | ((get_imageParamsThis(sensor_port, P_FLIPV)<<1) & 2);
global_flips=(get_imageParamsPast(sensor_port, P_FLIPH, frame) & 1) | ((get_imageParamsPast(sensor_port, P_FLIPV, frame)<<1) & 2);
extra_flips=0;
if (get_imageParamsThis(sensor_port, P_MULTI_MODE)!=0) {
extra_flips=get_imageParamsThis(sensor_port, P_MULTI_MODE_FLIPS);
if (get_imageParamsThis(sensor_port, P_MULTI_MODE)!=0) { // No past!
extra_flips=get_imageParamsThis(sensor_port, P_MULTI_MODE_FLIPS); // No past!
global_flips=extra_flips & 3;
}
orientation_short[0]=0;
orientation_short[1]=0xf & orientations[(get_imageParamsThis(sensor_port, P_PORTRAIT)&3) | (global_flips<<2)];
orientation_short[1]=0xf & orientations[(get_imageParamsThis(sensor_port, P_PORTRAIT)&3) | (global_flips<<2)]; // No past!
write_meta_irq(sensor_port, orientation_short, &meta_offsets.Image_Orientation, Exif_Image_Orientation, 2);
// write sensor number
......@@ -460,36 +485,37 @@ inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, struct interframe_params_t*
write_meta_irq(sensor_port, short_buff, &meta_offsets.PageNumber, Exif_Image_PageNumber, 2);
//TODO - use memcpy
maker_offset=putlong_meta_irq(sensor_port, get_imageParamsThis(sensor_port, P_GAINR), &meta_offsets.Photo_MakerNote, Exif_Photo_MakerNote);
maker_offset=putlong_meta_irq(sensor_port, get_imageParamsPast(sensor_port, P_GAINR,frame), &meta_offsets.Photo_MakerNote, Exif_Photo_MakerNote);
if (maker_offset>0) {
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GAING), maker_offset+4);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GAINGB), maker_offset+8);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GAINB), maker_offset+12);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GTAB_R), maker_offset+16);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GTAB_G), maker_offset+20);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GTAB_GB), maker_offset+24);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_GTAB_B), maker_offset+28);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_WOI_LEFT) | (get_imageParamsThis(sensor_port, P_WOI_WIDTH)<<16), maker_offset+32);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_WOI_TOP) | (get_imageParamsThis(sensor_port, P_WOI_HEIGHT)<<16), maker_offset+36);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_GAING,frame), maker_offset+4);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_GAINGB,frame), maker_offset+8);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_GAINB,frame), maker_offset+12);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_GTAB_R,frame), maker_offset+16);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_GTAB_G,frame), maker_offset+20);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_GTAB_GB,frame), maker_offset+24);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_GTAB_B,frame), maker_offset+28);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_WOI_LEFT) | (get_imageParamsThis(sensor_port, P_WOI_WIDTH)<<16), maker_offset+32); //No Past
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_WOI_TOP) | (get_imageParamsThis(sensor_port, P_WOI_HEIGHT)<<16), maker_offset+36); //No Past
putlong_meta_raw_irq(sensor_port, global_flips |
((get_imageParamsThis(sensor_port, P_BAYER)<<2) & 0xc) |
((get_imageParamsThis(sensor_port, P_COLOR)<<4) & 0xF0) |
((get_imageParamsThis(sensor_port, P_DCM_HOR)<<8) & 0xF00) |
((get_imageParamsThis(sensor_port, P_DCM_VERT)<<12) & 0xF000) |
((get_imageParamsThis(sensor_port, P_BIN_HOR)<<16) & 0xF0000) |
((get_imageParamsThis(sensor_port, P_BIN_VERT)<<20) & 0xF00000) |
((get_imageParamsThis(sensor_port, P_BAYER)<<2) & 0xc) | // No past!
((get_imageParamsPast(sensor_port, P_COLOR, frame)<<4) & 0xF0) |
((get_imageParamsThis(sensor_port, P_DCM_HOR)<<8) & 0xF00) | // No past!
((get_imageParamsThis(sensor_port, P_DCM_VERT)<<12) & 0xF000) | // No past!
((get_imageParamsThis(sensor_port, P_BIN_HOR)<<16) & 0xF0000) | // No past!
((get_imageParamsThis(sensor_port, P_BIN_VERT)<<20) & 0xF00000) | // No past!
(extra_flips <<24) , maker_offset+40);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_MULTI_HEIGHT_BLANK1), maker_offset+44);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_MULTI_HEIGHT_BLANK2), maker_offset+48);
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_MULTI_HEIGHT_BLANK1), maker_offset+44); // No past!
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_MULTI_HEIGHT_BLANK2), maker_offset+48); // No past!
// putlong_meta_raw_irq(0x1234567, maker_offset+52); // just testing
putlong_meta_raw_irq(sensor_port, get_imageParamsThis(sensor_port, P_QUALITY) | ((get_imageParamsThis(sensor_port, P_PORTRAIT)&1)<<7) | (get_imageParamsThis(sensor_port, P_CORING_INDEX)<<16), maker_offset+52);
putlong_meta_raw_irq(sensor_port, get_globalParam(sensor_port, G_TEMPERATURE01), maker_offset+56); // data should be provided by a running daemon
putlong_meta_raw_irq(sensor_port, get_globalParam(sensor_port, G_TEMPERATURE23), maker_offset+60);
putlong_meta_raw_irq(sensor_port, get_imageParamsPast(sensor_port, P_QUALITY, frame) |
((get_imageParamsThis(sensor_port, P_PORTRAIT)&1)<<7) | // No past!
(get_imageParamsThis(sensor_port, P_CORING_INDEX)<<16), maker_offset+52); // No past!
putlong_meta_raw_irq(sensor_port, get_globalParam(sensor_port, G_TEMPERATURE01), maker_offset+56); // data should be provided by a running daemon // No past!
putlong_meta_raw_irq(sensor_port, get_globalParam(sensor_port, G_TEMPERATURE23), maker_offset+60); // No past!
//get_globalParam(G_TASKLET_CTL)
// left 1 long spare (+44)
}
interframe->meta_index=store_meta(sensor_port);
}
......@@ -580,7 +606,6 @@ static irqreturn_t compressor_irq_handler(int irq, void *dev_id)
irq_ctrl.interrupt_cmd = IRQ_CLEAR;
x393_cmprs_interrupts(irq_ctrl, jptr->chn_num);
local_irq_restore(flag);
return IRQ_HANDLED;
}
......@@ -777,15 +802,14 @@ void reset_compressor(unsigned int chn)
local_irq_restore(flags);
}
/**
* @brief Camera interrupts on/off (currently both in the FPGA and in the CPU)
* @param on 1 - enable, 0 - disable interrupts
*/
void camera_interrupts (int on) {
/** Camera compressor interrupts on/off */
void compressor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt enable
int chn) ///< compressor channel (0..3)
{
int i;
x393_cmprs_interrupts_t irq_ctrl;
x393_cmprs_interrupts_t irq_ctrl = {.d32=0};
//MDF2(printk ("camera_interrupts(%d)\n",on));
//MDF2(printk ("compressor_interrupts(%d)\n",on));
dev_dbg(NULL, "set camera interrupts status: %d\n", on);
#ifdef TEST_DISABLE_CODE
if (on) {
......@@ -802,10 +826,65 @@ void camera_interrupts (int on) {
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
#endif /* TEST_DISABLE_CODE */
irq_ctrl.interrupt_cmd = on ? IRQ_ENABLE : IRQ_DISABLE;
for (i = 0; i < SENSOR_PORTS; i++) {
x393_cmprs_interrupts(irq_ctrl, i);
}
//
irq_ctrl.interrupt_cmd = on ? IRQ_ENABLE : IRQ_DISABLE;
x393_cmprs_interrupts(irq_ctrl, chn);
}
/** Camera sensor (frame sequencer) compressor interrupts on/off */
void sensor_interrupts (int on, ///< 0 -interrupt disable, 1 - interrupt enable
int chn) ///< compressor channel (0..3)
{
int i;
x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32=0};
//MDF2(printk ("compressor_interrupts(%d)\n",on));
dev_dbg(NULL, "set sensor interrupts status: %d\n", on);
#ifdef TEST_DISABLE_CODE
if (on) {
EN_INTERRUPT(SMART);
} else {
DIS_INTERRUPTS;
}
// clear smart interrupt circuitry in any case
port_csp0_addr[X313_WA_SMART_IRQ]=0x8000;
reg_intr_vect_rw_mask intr_mask;
intr_mask = REG_RD(intr_vect, regi_irq, rw_mask);
intr_mask.ext = on ? 1 : 0;
REG_WR(intr_vect, regi_irq, rw_mask, intr_mask);
#endif /* TEST_DISABLE_CODE */
//
cmdframeseq_mode.interrupt_cmd = on ? IRQ_ENABLE : IRQ_DISABLE;
x393_cmdframeseq_ctrl(cmdframeseq_mode, chn);
}
int sequencer_stop_run_reset(int chn, ///< Sensor port
int cmd) ///< Command: SEQ_CMD_STOP=0 - stop, SEQ_CMD_RUN=1 - run, SEQ_CMD_RESET=2 - reset
///< @return always 0
{
x393_cmdframeseq_mode_t cmdframeseq_mode = {.d32 = 0};
x393_status_ctrl_t status_ctrl = {.d32=0};
switch (cmd){
case SEQ_CMD_STOP:
cmdframeseq_mode.run_cmd = 2;
break;
case SEQ_CMD_RUN:
cmdframeseq_mode.run_cmd = 3;
status_ctrl.mode = 3; // autoupdate, is anyway set to it when reading i2c
break;
case SEQ_CMD_RESET:
cmdframeseq_mode.reset = 1;
}
if (cmdframeseq_mode.d32)
x393_cmdframeseq_ctrl (cmdframeseq_mode, chn);
if (cmd == SEQ_CMD_RESET)
udelay(1);
if (status_ctrl.mode)
set_x393_cmdseqmux_status_ctrl(status_ctrl);
return 0;
}
/**
......
......@@ -15,6 +15,11 @@ extern struct sensorproc_t * sensorproc;
#ifdef CONFIG_ETRAX_ELPHEL_MT9X001
#include "mt9x001.h"
#endif
#define SEQ_CMD_STOP 0 ///< Sequencer command stop
#define SEQ_CMD_RUN 1 ///< Sequencer command run
#define SEQ_CMD_RESET 2 ///< Sequencer command reset
//#include "multisensor.h"
//int camSeqGetJPEG_wp(void);
//int camSeqGetJPEG_rp(void);
......@@ -36,7 +41,9 @@ extern unsigned long * ccam_dma_buf_ptr[SENSOR_PORTS];
//int init_FPGA(void); /// can be initialized only after FPGA is configured, not at module init (NOTE was static??)
///can be verified with if (!X313_IS_SDRAM_ON)
void reset_compressor(unsigned int chn);
void camera_interrupts (int on);
void compressor_interrupts (int on, int chn);
void sensor_interrupts (int on, int chn);
int sequencer_stop_run_reset(int chn, int cmd);
struct sensorproc_t * copy_sensorproc (int sensor_port, struct sensorproc_t * copy);
///NOTE: If profiling is enabled (TASKLET_CTL_ENPROF is set in G_TASKLET_CTL) - save current time in 2 of the 32-bit locations that can be read as pastpars (i.e. from PHP)
......
......@@ -76,6 +76,50 @@ static int sysfs_page[4]; ///< when positive - page locked for exclus
static struct device *sdev = NULL; ///< store this device here
static u32 i2c_read_data[4]; ///< last data read from i2c device
/** I2C sequencer stop/run/reset (also programs status if run)*/
int i2c_stop_run_reset(int chn, ///< Sensor port
int cmd) ///< Command: I2C_CMD_STOP=0 - stop, I2C_CMD_RUN=1 - run, I2C_CMD_RESET=2 - reset
///< @return always 0
{
x393_i2c_ctltbl_t i2c_ctl = {.d32=0};
x393_status_ctrl_t status_ctrl = {.d32=0};
switch (cmd){
case I2C_CMD_STOP:
i2c_ctl.cmd_run = 2;
break;
case I2C_CMD_RUN:
i2c_ctl.cmd_run = 3;
status_ctrl.mode = 3; // autoupdate, is anyway set to it when reading i2c
break;
case I2C_CMD_RESET:
i2c_ctl.reset = 1;
}
if (i2c_ctl.d32)
x393_sensi2c_ctrl (i2c_ctl, chn);
if (cmd == I2C_CMD_RESET)
udelay(1);
if (status_ctrl.mode)
set_x393_sensi2c_status_ctrl(status_ctrl, chn);
return 0;
}
EXPORT_SYMBOL_GPL(i2c_stop_run_reset);
/** I2C sequencer drive mode */
int i2c_drive_mode(int chn, ///< Sensor port
int sda_drive_high, ///< Actively drive SDA=1 during second half of SCL=1
int sda_release) ///< Release SDA early if next bit is SDA=1
///< @return always 0
{
x393_i2c_ctltbl_t i2c_ctl = {.d32=0};
i2c_ctl.sda_drive_high = sda_drive_high;
i2c_ctl.sda_release = sda_release;
i2c_ctl.drive_ctl = 1;
x393_sensi2c_ctrl (i2c_ctl, chn);
return 0;
}
EXPORT_SYMBOL_GPL(i2c_drive_mode);
/** Mark all i2c pages for each channel as free */
void i2c_page_alloc_init(void)
{
......
......@@ -17,6 +17,14 @@
#ifndef SENSOR_I2C_H
#define SENSOR_I2C_H
#define I2C_CMD_STOP 0
#define I2C_CMD_RUN 1
#define I2C_CMD_RESET 2
#define SDA_DRIVE_HIGH 1
#define SDA_RELEASE 1
/** I2C device description to be used with i2c sequencer*/
typedef struct{
char name[32]; ///< Device class name (up to 31 characters)
......@@ -27,136 +35,29 @@ typedef struct{
int scl_khz; ///< maximal SCL frequency in KHz (currently limited by 200KHz slowest)
} x393_i2c_device_t;
/** Reserve i2c page (1 of 256) for a sensor port
* @param chn sensor port number (0..3) */
int i2c_page_alloc(int chn);
/* Register specific page, can be used with legacy software to register page equal to slave address,
* and use 0xff for reading. Works with 1byhte addresses and 16-bit data */
int i2c_page_register(int chn, // Sensor port
int page); // page to register (for legacy software, use 7-bit slave address
// @return 0 on success, -ENOMEM if page is already registered
/* Free i2c page */
void i2c_page_free(int chn, int page);
/* Find device list entry by device class name */
x393_i2c_device_t * xi2c_dev_get(const char * name); // Device class name as string
/* Set i2c table entry to raw data (will just overwrite tbl_mode = 2)*/
void set_xi2c_raw(int chn,
int page, // index in lookup table
u32 data); // Bit delay - number of mclk periods in 1/4 of the SCL period
/* Set i2c table entry for write operation */
void set_xi2c_wr(int chn, // sensor port
int page, // index in lookup table
int sa7, // slave address (7 bit)
int rah, // High byte of the i2c register address
int num_bytes, // Number of bytes to write (1..10)
int bit_delay); // Bit delay - number of mclk periods in 1/4 of the SCL period
/*
* Set i2c table entry for write operation using known devices
* Get device with xi2c_dev_get(), copy and modify, if needed to
* offset slave address or change number of bytes to write, SCL frequency
*/
void set_xi2c_wrc( x393_i2c_device_t * dc, // device class
int chn, // sensor port
int page, // index in lookup table
int rah); // High byte of the i2c register address
/*
* Set i2c table entry for read operation using known devices
* Get device with xi2c_dev_get(), copy and modify, if needed to
* offset slave address or change number of bytes to write, SCL frequency
*/
void set_xi2c_rdc(x393_i2c_device_t * dc, // device class
int chn, // sensor port
int page); // index in lookup table
/* Set i2c table entry for read operation */
void set_xi2c_rd(int chn,
int page, // index in lookup table
int two_byte_addr, // Number of address bytes (0 - one byte, 1 - two bytes)
int num_bytes, // Number of bytes to read (1..8, 0 means 8)
int bit_delay); // Bit delay - number of mclk periods in 1/4 of the SCL period
/* Write one or multiple DWORDs to i2c relative (modulo16) address. Use offs = 0 for immediate (ASAP) command */
/* Length of data is determined by the page data already preset */
int write_xi2c_rel (int chn,
int offs, // 4 bits
u32 * data);
int i2c_stop_run_reset(int chn, int cmd);
int i2c_drive_mode (int chn, int sda_drive_high, int sda_release);
int write_xi2c_abs (int chn,
int offs, // 4 bits
u32 * data);
/* Write sensor 16 bit (or 8 bit as programmed in the table) data in immediate mode */
void write_xi2c_reg16 (int chn,
int page, // page (8 bits)
int addr, // low 8 bits
u32 data); // 16 or 8-bit data (LSB aligned)
/* Write sensor 16 bit (or 8 bit as programmed in the table) data in immediate mode */
void write_xi2c_reg16_rel (int chn, // sensor port
int page, // index in the table (8 bits)
int frame, // relative frame number modulo PARS_FRAMES
int addr, // low byte of the register address (high is in the table), 8 bits
u32 data); ///< 16 or 8-bit data (LSB aligned)
/* Write sensor 16 bit (or 8 bit as programmed in the table) data in immediate mode */
void write_xi2c_reg16_abs (int chn, // sensor port
int page, // index in the table (8 bits)
int frame, // absolute frame number modulo PARS_FRAMES
int addr, // low byte of the register address (high is in the table), 8 bits
u32 data); //16 or 8-bit data (LSB aligned)
/* Compatibility with the legacy code: frame <0 - ASAP, >=0 - absolute
* Write sensor 16 bit (or 8 bit as programmed in the table) data in immediate mode */
void write_xi2c_reg16_abs_asap (int chn, // sensor port
int page, // index in the table (8 bits)
int frame, // absolute frame number modulo PARS_FRAMES
int addr, // low byte of the register address (high is in the table), 8 bits
u32 data); // 16 or 8-bit data (LSB aligned)
/* Initiate sensor i2c read in immediate mode (data itself has to be read from FIFO with read_xi2c_fifo)
* Use slave address from provided class structure. */
void read_xi2c (x393_i2c_device_t * dc, // device class
int chn,
int page, // page (8 bits)
int addr); // 8/16 bit address
/* Initiate sensor i2c read in immediate mode (data itself has to be read from FIFO with read_xi2c_fifo)*/
void read_xi2c_sa7 (int chn,
int page, // page (8 bits)
int sa7, // 7-bit i2c slave address
int addr); // 8/16 bit address
/* Read next byte from the channel i2c FIFO. Return byte or -1 if no data available */
/* Sensor channel status should be in auto update mode (3) */
int read_xi2c_fifo(int chn);
/* Handling classes of i2c devices */
int i2c_page_alloc (int chn);
int i2c_page_register(int chn, int page);
void i2c_page_free (int chn, int page);
x393_i2c_device_t * xi2c_dev_get(const char * name);
/* Single-command i2c write/read register using pre-defined device classes */
int x393_xi2c_write_reg(const char * cname, // device class name
int chn, // sensor port number
int sa7_offs, // slave address (7-bit) offset from the class defined slave address
int reg_addr, // register address (width is defined by class)
int data); // data to write (width is defined by class)
int x393_xi2c_read_reg( const char * cname, // device class name
int chn, // sensor port number
int sa7_offs, // slave address (7-bit) offset from the class defined slave address
int reg_addr, // register address (width is defined by class)
int * datap); // pointer to a data receiver (read data width is defined by class)
int legacy_read_i2c_reg(int chn, // sensor port number
int page, // i2c table page registerd for read operation
int sa7, // slave address (7-bit) of the device
// Offset is non-zero when multiple devices of the same class are present.
int reg_addr, // register address (width is defined by class)
int len, // number of bytes to read.
int * datap); // pointer to a data receiver (read data width is defined by class)
// @return 0 on success, < 0 - error (ETIMEDOUT)
void set_xi2c_raw (int chn, int page, u32 data);
void set_xi2c_wr (int chn,int page, int sa7, int rah, int num_bytes, int bit_delay);
void set_xi2c_wrc (x393_i2c_device_t * dc, int chn, int page, int rah);
void set_xi2c_rdc (x393_i2c_device_t * dc, int chn, int page);
void set_xi2c_rd (int chn, int page, int two_byte_addr, int num_bytes, int bit_delay);
int write_xi2c_rel (int chn, int offs, u32 * data);
int write_xi2c_abs (int chn, int offs, u32 * data);
void write_xi2c_reg16 (int chn, int page, int addr, u32 data);
void write_xi2c_reg16_rel (int chn, int page, int frame, int addr, u32 data);
void write_xi2c_reg16_abs (int chn, int page, int frame, int addr, u32 data);
void write_xi2c_reg16_abs_asap (int chn, int page, int frame, int addr, u32 data);
void read_xi2c (x393_i2c_device_t * dc, int chn, int page, int addr);
void read_xi2c_sa7 (int chn, int page, int sa7, int addr);
int read_xi2c_fifo (int chn);
x393_i2c_device_t * xi2c_dev_get(const char * name);
int x393_xi2c_write_reg(const char * cname, int chn, int sa7_offs, int reg_addr, int data);
int x393_xi2c_read_reg (const char * cname, int chn, int sa7_offs, int reg_addr, int * datap);
int legacy_read_i2c_reg(int chn, int page, int sa7, int reg_addr, int len, int * datap);
#endif
......@@ -18,3 +18,7 @@
#include "x393_fpga_functions.h"
int init_command_sequencer(int sensor_port)
{
return 0;
}
......@@ -387,6 +387,7 @@
#define P_HISTRQ 72 ///< per-frame enabling of histogram calculation - bit 0 - Y (G), bit 2 - C (R,G2,B)
#define P_TILES 73 ///< Number of 16x16 (20x20) tiles in a compressed frame // 393: Still needed?
#define P_SENSOR_PHASE 74 ///< packed, low 16 bit - signed fine phase, bits [18:17] - 90-degrees shift
///< NC393 parallel12: 6 LSBs mean quadrants: 90-degree shifts for data [1:0], hact [3:2] and vact [5:4]
#define P_TEMPERATURE_PERIOD 75 ///< period of temperature measurements, ms (normally - multiple seconds)
#define P_AUTOEXP_ON 76 ///< Autoexposure control (unsigned long on)
// relative histogram (autoexposure) window (changed from % to 1/0x10000)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment