Commit cc6a8f22 authored by Andrey Filippov's avatar Andrey Filippov

synchronizing cameras

parent 567a278f
......@@ -385,7 +385,7 @@ int drp_read_reg (int sensor_port, u8 daddr);
int drp_write_reg (int sensor_port, int daddr, u16 data,u16 mask);
u8* drp_phase_addr (int clk_out);
int drp_read_clock_phase (int sensor_port, int clk_out);
int drp_write_clock_phase (int sensor_port, int clk_out, u8 phase);
int drp_write_clock_phase (int sensor_port, int clk_out, u16 phase); // 0..1ff
// SysFS interface functions
static int get_channel_from_name(struct device_attribute *attr);
......@@ -822,7 +822,7 @@ int drp_read_clock_phase (int sensor_port, int clk_out){
int data1, data2;
if ((data1 = drp_read_reg (sensor_port, addr_pair[0])) < 0) return data1;
if ((data2 = drp_read_reg (sensor_port, addr_pair[1])) < 0) return data2;
return ((data1 >> 13) & 7) | ((data2 & 0x1f) << 3);
return ((data1 >> 13) & 7) | ((data2 & 0x3f) << 3);
}
/**
......@@ -833,14 +833,14 @@ int drp_read_clock_phase (int sensor_port, int clk_out){
* @param phase 8-bit phase shift in 1/8 VCO periods or -ETIMEOUT
* @return 0-OK, <0 - error (-ETIMEOUT)
*/
int drp_write_clock_phase (int sensor_port, int clk_out, u8 phase)
int drp_write_clock_phase (int sensor_port, int clk_out, u16 phase)
{
u8* addr_pair = drp_phase_addr(clk_out);
int data1, data2, rslt;
data1 = (phase & 7) << 13;
data2 = (phase >> 3) & 0x1f;
data2 = (phase >> 3) & 0x3f;
if ((rslt = drp_write_reg(sensor_port, addr_pair[0], data1, 0xe000)) < 0) return rslt;
if ((rslt = drp_write_reg(sensor_port, addr_pair[1], data2, 0x001f)) < 0) return rslt;
if ((rslt = drp_write_reg(sensor_port, addr_pair[1], data2, 0x003f)) < 0) return rslt;
return 0;
}
......@@ -1039,26 +1039,29 @@ int set_initial_phase(int sensor_port,
{
// just setting clock and 3 lanes delays (5 MSBs 3 LSB are not used)
x393_sensio_tim2_t tim2 ={.d32=0};
x393_sensio_tim3_t tim3 ={.d32=0};
// x393_sensio_tim3_t tim3 ={.d32=0};
x393_sensio_ctl_t sensio_ctl = {.d32=0};
u8 initial_delays[] = {0x10, 0x00, 0x00, 0x00, // clock, lane0, lanel, lane2
0xe0, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30,
0xf8, 0x40, 0x38, 0xd0};
tim2.dly_lane0 = initial_delays[4*sensor_port + 1];
tim2.dly_lane1 = initial_delays[4*sensor_port + 2];
tim2.dly_lane2 = initial_delays[4*sensor_port + 3];
tim3.phase_h = initial_delays[4*sensor_port + 0];
u8 initial_delays[] = {0x00, 0x80, 0x80, 0x80, 0x80, // clock, lane0, lanel, lane2
0x00, 0x80, 0x80, 0x80, 0x80,
0x00, 0x80, 0x80, 0x80, 0x80,
0x00, 0x80, 0x80, 0x88, 0x80};
tim2.dly_lane0 = initial_delays[5*sensor_port + 1];
tim2.dly_lane1 = initial_delays[5*sensor_port + 2];
tim2.dly_lane2 = initial_delays[5*sensor_port + 3];
tim2.dly_lane3 = initial_delays[5*sensor_port + 4]; // not available in rev 0, added for revA
// tim3.phase_h = initial_delays[4*sensor_port + 0]; // may be restored for revA - it is 9 bits for MMCM phase
// Will use DRP (immediate mode only, not through tghe sequencer)
set_x393_sensio_tim2(tim2, sensor_port);
set_x393_sensio_tim3(tim3, sensor_port);
// set_x393_sensio_tim3(tim3, sensor_port);
sensio_ctl.set_dly = 1;
x393_sensio_ctrl(sensio_ctl,sensor_port);
dev_info(g_dev_ptr,"**set_initial_phase**: {%d} setting delays tim2 = 0x%x tim3 = 0x%x \n",sensor_port, tim2.d32, tim3.d32);
// dev_info(g_dev_ptr,"**set_initial_phase**: {%d} setting delays tim2 = 0x%x tim3 = 0x%x \n",sensor_port, tim2.d32, tim3.d32);
dev_info(g_dev_ptr,"**set_initial_phase**: {%d} setting delays tim2 = 0x%x \n",sensor_port, tim2.d32);
//P_SENSOR_IFACE_TIM2
setFramePar(sensor_port, thispars, P_SENSOR_IFACE_TIM2, tim2.d32);
setFramePar(sensor_port, thispars, P_SENSOR_IFACE_TIM3, tim3.d32);
// setFramePar(sensor_port, thispars, P_SENSOR_IFACE_TIM3, tim3.d32);
return 0;
}
......@@ -1481,8 +1484,9 @@ int boson640_pgm_window_common (int sensor_port, ///< sensor port
if (unlikely(thispars->pars[P_SENSOR_REGS + P_BOSON_TELEMETRY] != need_telemetry)) {
SETFRAMEPARS_SET(P_SENSOR_PIXV, wh); // probably already set by pgm_window_common
SETFRAMEPARS_SET(P_WOI_HEIGHT, wh); // probably already set by pgm_window_common
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_TELEMETRY, need_telemetry); // set sensor register and parameter
dev_dbg(g_dev_ptr,"boson640_pgm_window_common() SET_SENSOR_MBPAR_LUT(%d, %d, P_BOSON_TELEMETRY, %d)\n",sensor_port, frame16, need_telemetry);
// SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_TELEMETRY, need_telemetry); // set sensor register and parameter
SET_SENSOR_PAR_LUT (sensor_port, frame16, P_BOSON_TELEMETRY, need_telemetry); // set sensor register and parameter
dev_dbg(g_dev_ptr,"boson640_pgm_window_common() SET_SENSOR_PAR_LUT(%d, %d, P_BOSON_TELEMETRY, %d)\n",sensor_port, frame16, need_telemetry);
}
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(exit): {%d} thispars->pars[P_WOI_HEIGHT]=%lx thispars->pars[P_WOI_WIDTH]=%lx\n", sensor_port,thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]);
dev_dbg(g_dev_ptr,"boson640_pgm_window_common(exit): {%d} thispars->pars[P_SENSOR_PIXV]=%lx thispars->pars[P_SENSOR_PIXH]=%lx\n", sensor_port,thispars->pars[P_SENSOR_PIXV], thispars->pars[P_SENSOR_PIXH]);
......@@ -1616,6 +1620,7 @@ int boson640_pgm_triggermode (int sensor_port, ///< sensor
return -1; // Not yet fully booted.
}
if (thispars->pars[P_TRIG] & 4) { // turn external
dev_dbg(g_dev_ptr,"boson640_pgm_triggermode(): {%d} frame16=%d frame=%ld TURN EXTERNAL (%ld)\n",sensor_port,frame16,getThisFrameNumber(sensor_port),thispars->pars[P_TRIG]);
// always apply P_BOSON_DVO_DISPLAY_MODE
// if (thispars->pars[P_SENSOR_REGS + P_BOSON_DVO_DISPLAY_MODE] != 1){
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_DVO_DISPLAY_MODE, 1);
......@@ -1624,6 +1629,7 @@ int boson640_pgm_triggermode (int sensor_port, ///< sensor
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_BOSON_EXT_SYNC_MODE, 2);
}
} else { // turn internal
dev_dbg(g_dev_ptr,"boson640_pgm_triggermode(): {%d} frame16=%d frame=%ld TURN INTERNAL (%ld)\n",sensor_port,frame16,getThisFrameNumber(sensor_port),thispars->pars[P_TRIG]);
if (thispars->pars[P_SENSOR_REGS + P_BOSON_BOSON_EXT_SYNC_MODE] != 0){
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, P_BOSON_BOSON_EXT_SYNC_MODE, 0);
}
......@@ -1651,14 +1657,16 @@ int boson640_pgm_sensorregs (int sensor_port, ///< sensor port
unsigned long bmask32= ((thispars->mod32) >> (P_SENSOR_REGS>>5)) & (( 1 << (P_SENSOR_NUMREGS >> 5))-1) ;
unsigned long mask;
int index,index32, reg_index;
int I, ADDR;
struct frameparspair_t pars_to_update[sizeof(boson640_par2addr)/sizeof(short)/2]; ///
int nupdate=0;
int nupdate=0; // No need to update any parameter w/o multiplexer !
dev_dbg(g_dev_ptr,"boson640_pgm_sensorregs(): {%d} frame16=%d frame=%ld\n",sensor_port,frame16,getThisFrameNumber(sensor_port));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
if (boson640_is_booted (sensor_port, thispars) < 2){ // not yet booted
return -1; // Not yet fully booted.
}
dev_dbg(g_dev_ptr,"{%d} bmask32=0x%lx, thispars->mod32=0x%lx, P_SENSOR_REGS=0x%x, P_SENSOR_NUMREGS=0x%x\n",sensor_port,bmask32,thispars->mod32,P_SENSOR_REGS,P_SENSOR_NUMREGS);
// dev_info(g_dev_ptr,"{%d} bmask32=0x%lx, thispars->mod32=0x%lx, P_SENSOR_REGS=0x%x, P_SENSOR_NUMREGS=0x%x\n",sensor_port,bmask32,thispars->mod32,P_SENSOR_REGS,P_SENSOR_NUMREGS);
if (bmask32) {
for (index32=(P_SENSOR_REGS>>5); bmask32; index32++, bmask32 >>= 1) {
dev_dbg(g_dev_ptr,"{%d} index32=0x%x, bmask32=0x%lx\n",sensor_port,index32,bmask32);
......@@ -1668,20 +1676,16 @@ int boson640_pgm_sensorregs (int sensor_port, ///< sensor port
for (index=(index32<<5); mask; index++, mask >>= 1) {
reg_index = (index-P_SENSOR_REGS);
if (mask & 1) {
X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
dev_dbg(g_dev_ptr,"Boson640 {%d} X3X3_I2C_SEND2(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",sensor_port,sensor_port, frame16,sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
/*// from lepton (disabled)
if (reg_index >= FIRST_BOSON640_INT) {
// X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,reg_index,thispars->pars[index]);
SET_BOSON640_PAR_NOWAIT(sensor_port, frame16, reg_index, thispars->pars[index]);
dev_dbg(g_dev_ptr,"{%d} SET_BOSON640_PAR_NOWAIT(0x%x, 0x%x, 0x%lx,0x%lx)\n",
sensor_port,sensor_port, frame16,reg_index,thispars->pars[index]);
}else {
X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,reg_index,thispars->pars[index]);
dev_dbg(g_dev_ptr,"{%d} X3X3_I2C_SEND2(0x%x, 0x%x, 0x%lx,0x%x,0x%lx)\n",sensor_port,sensor_port, frame16,sensor->i2c_addr,reg_index,thispars->pars[index]);
}
*/
dev_dbg(g_dev_ptr,"Boson640 {%d} X3X3_I2C_SEND2_LUT(0x%x, 0x%x, 0, 0x%lx,0x%x,0x%lx)\n",sensor_port,sensor_port, frame16,sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
// dev_info(g_dev_ptr,"Boson640 {%d} X3X3_I2C_SEND2_LUT(0x%x, 0x%x, 0, 0x%lx,0x%x,0x%lx)\n",sensor_port,sensor_port, frame16,sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
// X3X3_I2C_SEND2(sensor_port, frame16, sensor->i2c_addr,(index-P_SENSOR_REGS),thispars->pars[index]);
// X3X3_I2C_SEND2_LUT(sensor_port,frame16,0,(index-P_SENSOR_REGS),thispars->pars[index]);
I = pSensorPortConfig[sensor_port].broadcast_addr;
ADDR = pSensorPortConfig[sensor_port].par2addr[I][(index-P_SENSOR_REGS)];\
dev_dbg(g_dev_ptr,"Boson640 {%d} pSensorPortConfig[sensor_port].broadcast_addr=0x%x \n",sensor_port, I);
dev_dbg(g_dev_ptr,"Boson640 {%d} pSensorPortConfig[(p)].par2addr[_I][(r)] = 0x%x \n",sensor_port,ADDR);
SET_SENSOR_MBPAR_LUT(sensor_port, frame16, (index-P_SENSOR_REGS), thispars->pars[index]); // set sensor register and parameter
}
}
thispars->mod[index32]=0;
......@@ -1689,14 +1693,12 @@ int boson640_pgm_sensorregs (int sensor_port, ///< sensor port
}
thispars->mod32=0;
}
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
// if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // No need to update anything w/o multiplexer and broadcast
// send all parameters marked as "needed to be processed" to the sensor, clear those flags
// mask out all non sensor pars
// unsigned long bmask32= ((thispars->mod32) >> (P_SENSOR_REGS>>5)) & (P_SENSOR_NUMREGS-1) ;
// It will be the first for the frame (before automatic sensor changes).
// Add testing for programmed sensor and move values to later frames (not here butin the pgm_functions)
// nothing to do here now, use similar approach to program non-i2c Lepton registers
return 0;
}
......
......@@ -24,6 +24,8 @@
//#define DEBUG // should be before linux/module.h - enables dev_dbg at boot in this file (needs "debug" in bootarg)
#include <linux/types.h> // div for 64
#include <asm/div64.h> // div for 64
#include <linux/math64.h> // newer divisions https://mymusing.co/division-functions-in-linux-kernel/
#include <linux/module.h>
#include <linux/mm.h>
......@@ -66,7 +68,7 @@
//#include "cci2c.h" // to use void i2c_reset_wait(void), reset shadow static 'i2c_hardware_on'
#include "x393_macro.h"
#include "x393.h"
#include "sensor_i2c.h" // read_xi2c_frame()
#include "sensor_i2c.h" // read_xi2c_frame(), i2c_stop_run_reset
#include "klogger_393.h"
/**
......@@ -183,13 +185,17 @@ static const int framepars_minor[] = {
static struct class *framepars_dev_class;
static int hardware_initialized = 0;
static u64 master_ts = 0; // Stores timestamp in microseconds converted from frame number
static u32 master_frame = 0; // stores ts converted to frame (for master channel)
/* 393: sFrameParsAll is an array of 4per-port structures */
static struct framepars_all_t sFrameParsAll[SENSOR_PORTS] __attribute__ ((aligned(PAGE_SIZE))); ///< Sensor Parameters, currently 16 pages all and 2048 pages some, static struct
unsigned int frameParsInitialized[SENSOR_PORTS]; // set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
#define thisFrameNumber(p) GLOBALPARS(p,G_THIS_FRAME) // Current frame number (may lag from the hardware)
#define thisCompressorFrameNumber(p) GLOBALPARS(p,G_COMPRESSOR_FRAME) // Current compressed frame number (lags from thisFrameNumber)
//#define thisFrameNumber(p) GLOBALPARS(p,G_THIS_FRAME) // Current frame number (may lag from the hardware)
//#define thisCompressorFrameNumber(p) GLOBALPARS(p,G_COMPRESSOR_FRAME) // Current compressed frame number (lags from thisFrameNumber)
//#define thisCompressorTimestamp_sec(p) GLOBALPARS(p,G_COMPRESSOR_SEC) // Current compressed frame timestamp seconds
//#define thisCompressorTimestamp_usec(p) GLOBALPARS(p,G_COMPRESSOR_USEC) // Current compressed frame timestamp microseconds seconds
#ifdef NC353
struct framepars_all_t *frameparsall = NULL; // - will be mmap-ed
......@@ -386,7 +392,6 @@ void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3
x393_cmdframeseq_ctrl(cmdframeseq_mode, sensor_port);
dev_dbg(g_devfp_ptr,"Reset command sequencer (all channels !): port= %d, thisFrameNumber=0x%lx\n", sensor_port, thisFrameNumber(sensor_port));
}
/* Check if the status update mode for command sequencer is not 3 (auto), set/wait if needed */
stat_ctrl = get_x393_cmdseqmux_status_ctrl();
if (stat_ctrl.mode !=3) {
......@@ -399,7 +404,7 @@ void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3
if (likely(stat.seq_num == stat_ctrl.seq_num))
break;
}
} else {
} else { // correct frame numbers should be set after resetting frame number (first call to x393_cmdframeseq_ctrl())
stat = x393_cmdseqmux_status();
}
switch (sensor_port) {
......@@ -410,7 +415,8 @@ void resetFrameNumber(int sensor_port, ///< sensor_port sensor port number (0..3
default:
frame16 = stat.frame_num3; break;
}
thisFrameNumber(sensor_port) = (aframe & PARS_FRAMES_MASK) | frame16;
// thisFrameNumber(sensor_port) = (aframe & PARS_FRAMES_MASK) | frame16; // OLD BUG???
thisFrameNumber(sensor_port) = (aframe & ~PARS_FRAMES_MASK) | frame16;
#ifdef NC353
thisFrameNumber(sensor_port) = X3X3_I2C_FRAME;
#endif
......@@ -1839,6 +1845,7 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
}
while (first < count) {
while ((first < count) && ((pars[first].num & 0xff00) == 0xff00)) { // process special instructions
dev_dbg(g_devfp_ptr, "sensor_port = %d this_frame = 0x%lx\n",sensor_port, getThisFrameNumber(sensor_port));
dev_dbg(g_devfp_ptr, "pars[%d].num = 0x%lx pars[%d].val = 0x%lx\n",first,pars[first].num, first,pars[first].val);
switch (pars[first].num & 0xff0f) {
#if 0
......@@ -1867,7 +1874,7 @@ ssize_t framepars_write(struct file * file, const char * buf, size_t count, loff
case FRAMEPARS_SETFRAME:
frame = pars[first].val;
port_mask = (pars[first].num >> 4) & ((1 << SENSOR_PORTS) - 1);
// No correction - frames should be exctly synchronized to work this way, otherwise use relative
// No correction - frames should be exactly synchronized to work this way, otherwise use relative
if (port_mask){
int ii;
for (ii =0; ii < SENSOR_PORTS; ii++) if (port_mask & (1 << ii)){
......@@ -1989,6 +1996,7 @@ static int get_channel_from_name(struct device_attribute *attr) ///< Linux kerne
return reg;
}
static ssize_t show_this_frame(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%u\n", (int) GLOBALPARS(get_channel_from_name(attr), G_THIS_FRAME));
......@@ -2072,6 +2080,69 @@ static ssize_t store_fpga_time(struct device *dev, struct device_attribute *attr
}
return count;
}
/**
* Reset frame numbers for command and i2c sequencers, if specified frame < PARS_FRAMES - reset hardware sequencers
* 2^15 @60Hz - 414 days, so assuming there is no overflow
* treat number of frames: :
* frame <= -PARS_FRAMES - wait for absolute frame number (-frame), then hardware reset and reset frame to zero
* -PARS_FRAMES < frame < 0 : skip -frame frames, then hardware reset and reset frame to zero
* 0 >= frame < PARS_FRAMES : no wait, hardware reset and reset frame to zero (treat as frame == 0)
* PARS_FRAMES <frame: no hardware reset, set only high order bits, keep low 4 bits from the hardware
* @param dev
* @param attr
* @param buf
* @param count
* @return
*/
static ssize_t store_all_frames(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int chn, mchn;
u32 aframe, wframe;
int sframe;
int skip=0;
FLAGS_IBH;
if (sscanf(buf, "%d", &sframe) > 0) {
aframe = (sframe > 0) ? sframe: 0;
skip = -sframe;
}
if (!common_pars){
dev_err(g_devfp_ptr,"*** common_pars not found, can not set frames! ***\n");
return -ENXIO;
}
// get master channel
mchn = common_pars->master_chn;
if (skip > 0){
wframe = getThisFrameNumber(mchn);
if (skip >= PARS_FRAMES) {
if (wframe < skip){ // do not try to wait if it is too late
wframe = skip + 1; // Skip 1 frame?
}
} else {
wframe += skip;
}
dev_dbg(g_devfp_ptr,"master port= %d, now frame=%d, wait frame %ld\n", mchn, wframe, getThisFrameNumber(mchn));
waitFrame(mchn, aframe);
}
// Do next chn iteration with IRQ disabled ? Lock with master channel lock. Or should each channel be locked (reset channel is not thread safe anyway)
LOCK_IBH(framepars_locks[common_pars->master_chn]);
for (chn = 0; chn < SENSOR_PORTS; chn++){
resetFrameNumber(chn,
aframe,
(aframe < PARS_FRAMES)?1:0); // reset hardware if aframe is small
}
UNLOCK_IBH(framepars_locks[common_pars->master_chn]);
// nothing to do with i2c sequencers if hardware command sequencers are not reset
if (aframe < PARS_FRAMES){ // reset hardware sequencers and copy to i2c sequencers
for (chn = 0; chn < SENSOR_PORTS; chn++){
i2c_stop_run_reset (chn, I2C_CMD_RESET);
i2c_stop_run_reset (chn, I2C_CMD_RUN);
}
}
return count;
}
static ssize_t show_all_frames(struct device *dev, struct device_attribute *attr, char *buf)
{
......@@ -2111,6 +2182,112 @@ static ssize_t show_all_frames(struct device *dev, struct device_attribute *attr
buf += sprintf(buf,"\n");
return buf-buf0;
}
/**
* Convert frame number into a timestamp (a pair of seconds, microseconds)
* @param dev
* @param attr
* @param buf
* @param count
* @return
*/
static ssize_t store_frame2ts(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
int mchn;
u32 aframe=0;
u32 period10ns; // trigger period in 10 ns increments
u32 ts_pair[2];
s64 delta_ts;
int delta_frame;
sscanf(buf, "%u", &aframe);
if (!common_pars){
dev_err(g_devfp_ptr,"*** common_pars not found, can not set frames! ***\n");
return -ENXIO;
}
// get master channel
mchn = common_pars->master_chn;
// get last compressed frame number and timestamp
master_frame = thisCompressorFrameNumber(mchn);
ts_pair[1] = thisCompressorTimestamp_sec(mchn);
ts_pair[0] = thisCompressorTimestamp_usec(mchn);
if (master_frame != thisCompressorFrameNumber(mchn)) { // updated in ISR -> retry once
master_frame = thisCompressorFrameNumber(mchn);
ts_pair[1] = thisCompressorTimestamp_sec(mchn);
ts_pair[0] = thisCompressorTimestamp_usec(mchn);
}
master_ts = ((long long) ts_pair[1]) * 1000000 + ts_pair[0]; // timestamp in microseconds
if (aframe > 0) { // if 0 - keep last ts to be read
period10ns = aframepars[mchn][thisFrameNumber(mchn) & PARS_FRAMES_MASK].pars[P_TRIG_PERIOD];
delta_frame = aframe - master_frame;
delta_ts = ((long long) period10ns) * delta_frame * 2 + 1; // to round afrter division by 100
dev_info(g_devfp_ptr,"delta_frame = %d, delta_ts = %lld us, period10ns=%d\n", delta_frame, delta_ts,period10ns);
// do_div(delta_ts, 200); // 64 by 32, delta_ts now in microseconds
// s64 div_s64(s64 dividend, s32 divisor) : Signed division of 64-bit dividend by 32-bit divisor.
delta_ts = div_s64(delta_ts,200); // linux/math64.h
dev_info(g_devfp_ptr,"delta_ts = %lld us\n", delta_ts);
master_ts += delta_ts;
}
return count;
}
static ssize_t show_frame2ts(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%lld", master_ts);
}
static ssize_t store_ts2frame(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
u64 ts = 0;
u32 ts_pair[2];
int mchn;
u32 period10ns; // trigger period in 10 ns increments
s64 delta_ts;
s32 delta_frame;
sscanf(buf, "%llu", &ts);
if (!common_pars){
dev_err(g_devfp_ptr,"*** common_pars not found, can not set frames! ***\n");
return -ENXIO;
}
// get master channel
mchn = common_pars->master_chn;
// get last compressed frame number and timestamp
master_frame = thisCompressorFrameNumber(mchn);
ts_pair[1] = thisCompressorTimestamp_sec(mchn);
ts_pair[0] = thisCompressorTimestamp_usec(mchn);
if (master_frame != thisCompressorFrameNumber(mchn)) { // updated in ISR -> retry once
master_frame = thisCompressorFrameNumber(mchn);
ts_pair[1] = thisCompressorTimestamp_sec(mchn);
ts_pair[0] = thisCompressorTimestamp_usec(mchn);
}
master_ts = ((long long) ts_pair[1]) * 1000000 + ts_pair[0]; // timestamp in microseconds
if (ts) { // if ts 0 (or not specified, e.g. echo "" > ... , then keep last comprfessed frame and timestamp to be read out
period10ns = aframepars[mchn][thisFrameNumber(mchn) & PARS_FRAMES_MASK].pars[P_TRIG_PERIOD];
delta_ts = 100*(ts - master_ts) + (period10ns/2); // for rounding
// do_div(delta_ts, period10ns);
// delta_ts /= period10ns;
delta_frame = div_s64(delta_ts, period10ns); // linux/math64.h
master_frame += delta_frame;
dev_info(g_devfp_ptr,"delta_frame = %d, delta_ts = %lld us, period10ns=%d\n", delta_frame, delta_ts, period10ns);
}
return count;
}
static ssize_t show_ts2frame(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%d", master_frame);
}
/*
aframepars[sensor_port][(i+frame16) & PARS_FRAMES_MASK].pars[P_FRAME] = thisFrameNumber(sensor_port) + i;#define thisCompressorFrameNumber(p) GLOBALPARS(p,G_COMPRESSOR_FRAME) // Current compressed frame number (lags from thisFrameNumber)
#define thisCompressorTimestamp_sec(p) GLOBALPARS(p,G_COMPRESSOR_SEC) // Current compressed frame timestamp seconds
#define thisCompressorTimestamp_usec(p) GLOBALPARS(p,G_COMPRESSOR_USEC) // Current compressed frame timestamp microseconds seconds
static u64 master_ts = 0; // Stores timestamp in microseconds converted from frame number
static u32 master_frame = 0; // stores ts converted to frame (for master channel)
static u32 master_ts[2]; // [0] - microseconds, [1] - seconds. Stores timestamp pair converted from frame number
static u32 master_frame = 0; // stores ts converted to frame (for master channel)
*/
static DEVICE_ATTR(this_frame0, SYSFS_PERMISSIONS, show_this_frame, store_this_frame);
static DEVICE_ATTR(this_frame1, SYSFS_PERMISSIONS, show_this_frame, store_this_frame);
......@@ -2120,15 +2297,14 @@ static DEVICE_ATTR(chn_en0, SYSFS_PERMISSIONS, NULL,
static DEVICE_ATTR(chn_en1, SYSFS_PERMISSIONS, NULL, store_endis_chn);
static DEVICE_ATTR(chn_en2, SYSFS_PERMISSIONS, NULL, store_endis_chn);
static DEVICE_ATTR(chn_en3, SYSFS_PERMISSIONS, NULL, store_endis_chn);
//static DEVICE_ATTR(chn_en0, SYSFS_WRITEONLY, NULL, store_endis_chn);
//static DEVICE_ATTR(chn_en1, SYSFS_WRITEONLY, NULL, store_endis_chn);
//static DEVICE_ATTR(chn_en2, SYSFS_WRITEONLY, NULL, store_endis_chn);
//static DEVICE_ATTR(chn_en3, SYSFS_WRITEONLY, NULL, store_endis_chn);
static DEVICE_ATTR(all_frames, SYSFS_READONLY, show_all_frames, NULL);
static DEVICE_ATTR(all_frames, SYSFS_PERMISSIONS, show_all_frames, store_all_frames);
static DEVICE_ATTR(fpga_time, SYSFS_PERMISSIONS, show_fpga_time, store_fpga_time);
static DEVICE_ATTR(fpga_version, SYSFS_READONLY, show_fpga_version, NULL);
static DEVICE_ATTR(fpga_sensor_interface, SYSFS_READONLY, show_fpga_sensor_interface, NULL);
static DEVICE_ATTR(frame2ts, SYSFS_PERMISSIONS, show_frame2ts, store_frame2ts);
static DEVICE_ATTR(ts2frame, SYSFS_PERMISSIONS, show_ts2frame, store_ts2frame);
static struct attribute *root_dev_attrs[] = {
&dev_attr_this_frame0.attr,
......@@ -2143,6 +2319,8 @@ static struct attribute *root_dev_attrs[] = {
&dev_attr_chn_en3.attr,
&dev_attr_fpga_version.attr,
&dev_attr_fpga_sensor_interface.attr,
&dev_attr_frame2ts.attr,
&dev_attr_ts2frame.attr,
NULL
};
......
......@@ -10,6 +10,10 @@ extern struct common_pars_t *common_pars;
extern unsigned long *aglobalPars[SENSOR_PORTS];
extern unsigned long *amultiSensIndex[SENSOR_PORTS];
extern unsigned long *amultiSensRvrsIndex[SENSOR_PORTS];
#define thisFrameNumber(p) GLOBALPARS(p,G_THIS_FRAME) // Current frame number (may lag from the hardware)
#define thisCompressorFrameNumber(p) GLOBALPARS(p,G_COMPRESSOR_FRAME) // Current compressed frame number (lags from thisFrameNumber)
#define thisCompressorTimestamp_sec(p) GLOBALPARS(p,G_COMPRESSOR_SEC) // Current compressed frame timestamp seconds
#define thisCompressorTimestamp_usec(p) GLOBALPARS(p,G_COMPRESSOR_USEC) // Current compressed frame timestamp microseconds seconds
extern wait_queue_head_t aframepars_wait_queue[SENSOR_PORTS];
///TODO: init framepars (zero parameters) before initscripts (not when detecting the sensors) - then initscript will be able to overwrite some
void init_framepars_ptr(int sensor_port);
......
......@@ -364,6 +364,7 @@ loff_t jpeghead_lseek(struct file *file, loff_t offset, int orig,
file->f_pos = jpeghead_priv[chn].jpeg_h_sz + offset;
} else {
file->f_pos = 0; // reset it to 0 anyway
// frame_length = timestamp_sec (same field). Should it be fixed below?
if ((fp->signffff != MARKER_FFFF) || // signature is overwritten
((fp->timestamp_sec) & X313_LENGTH_MASK)) return -EINVAL; //! acquisition of this frame is not done yet - length word high byte is non-zero
if ((offset & 0x1f) == 0x2)
......
......@@ -1348,7 +1348,7 @@ int pgm_triggermode(int sensor_port, ///< sensor port number (0..3
x393_camsync_mode_t camsync_mode = {.d32=0};
int is_master = (thispars->pars[P_TRIG_MASTER] == sensor_port)? 1 : 0;
dev_dbg(g_dev_ptr,"{%d} frame16=%d, is_master=%d\n",sensor_port,frame16, is_master);
dev_dbg(g_dev_ptr,"{%d} frame16=%d, is_master=%d, this_frame=%ld\n",sensor_port,frame16, is_master, getThisFrameNumber(sensor_port));
MDP(DBGB_PSFN, sensor_port,"frame16=%d\n",frame16)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
camsync_mode.trig = (thispars->pars[P_TRIG] & 4)?1:0;
......@@ -1382,6 +1382,8 @@ int pgm_triggermode(int sensor_port, ///< sensor port number (0..3
for (i=0; i<SENSOR_PORTS; i++) if (i != sensor_port) {
common_pars->updated[i] = 1;
}
} else {
dev_dbg(g_dev_ptr,"{%d} No change to common trigger mode, old=0x%lx, new=0x%lx\n",sensor_port,common_pars->trig_mode,thispars->pars[P_TRIG]);
}
return 0;
......
......@@ -516,6 +516,9 @@ inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, ///< pointer
// int frame_index = frame & PASTPARS_SAVE_ENTRIES_MASK;
// NC393: current parameters are valid at compressor done interrupt (after frame sync interrupts latest valid is new frame number - 2
if (index_time<0) index_time+=get_globalParam (sensor_port, G_CIRCBUFSIZE)>>2;
thisCompressorTimestamp_sec(sensor_port) = ccam_dma_buf_ptr[sensor_port][index_time];
thisCompressorTimestamp_usec(sensor_port) = ccam_dma_buf_ptr[sensor_port][index_time+1];
// struct exif_datetime_t
// calculates datetime([20] and subsec[7], returns pointer to char[27]
exif_meta_time_string=encode_time(time_buff, ccam_dma_buf_ptr[sensor_port][index_time], ccam_dma_buf_ptr[sensor_port][index_time+1]);
......
......@@ -802,7 +802,11 @@
#define G_HIST_Y_FRAME (FRAMEPAR_GLOBALS + 102) ///< last frame for which Y histogram was calculated (uses 4 locations)
#define G_HIST_C_FRAME (FRAMEPAR_GLOBALS + 106) ///< last frame for which C histograms were calculated (uses 4 locations)
#define G_HIST_SHIFT (FRAMEPAR_GLOBALS + 107) ///< debug feature - add 0..15 to the histogram frame to read DMA memory
// FIXME: overlap?
//#define G_HIST_SHIFT (FRAMEPAR_GLOBALS + 107) ///< debug feature - add 0..15 to the histogram frame to read DMA memory
#define G_COMPRESSOR_SEC (FRAMEPAR_GLOBALS + 110) ///< last compressed frame timestamp seconds (use with G_COMPRESSOR_FRAME)
#define G_COMPRESSOR_USEC (FRAMEPAR_GLOBALS + 111) ///< last compressed frame timestamp microseconds
#define G_HIST_SHIFT (FRAMEPAR_GLOBALS + 112) ///< debug feature - add 0..15 to the histogram frame to read DMA memory
#define G_SENSOR_CALIB (FRAMEPAR_GLOBALS + 1024) ///< 1024 Array of sensor calibration data, sensor dependent.For Micron it is 256*4 actual gains in 8.16 format
///< Only first 96 for each color are used
......@@ -1397,10 +1401,13 @@ struct p_names_t {
G_NAME_ENTRY(PROFILING_EN), \
G_NAME_ENTRY(TEMPERATURE01), \
G_NAME_ENTRY(TEMPERATURE23), \
G_NAME_ENTRY(COMPRESSOR_SEC), \
G_NAME_ENTRY(COMPRESSOR_USEC), \
G_NAME_ENTRY(SENSOR_CALIB), \
G_NAME_ENTRY(HIST_SHIFT) \
};
#define ONCHANGE_NAME_ENTRY(y) { onchange_##y, #y }
#define DEFINE_ONCHANGE_NAMES(x) struct p_names_t x[]= { \
ONCHANGE_NAME_ENTRY(recalcseq), \
......
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