#define FRAMEPARS_DRIVER_NAME "Elphel (R) Model 393 Frame Parameters device driver"
#define FRAMEPARS_DRIVER_NAME "Elphel (R) Model 393 Frame Parameters device driver"
staticstructframepars_all_tsFrameParsAll__attribute__((aligned(PAGE_SIZE)));///< Sensor Parameters, currently 8 pages all and 2048 pages some, static struct
/* 393: sFrameParsAll is an array of 4per-port structures */
staticstructframepars_all_tsFrameParsAll[SENSOR_PORTS]__attribute__((aligned(PAGE_SIZE)));///< Sensor Parameters, currently 16 pages all and 2048 pages some, static struct
unsignedlongframeParsInitialized;/// set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
unsignedlongframeParsInitialized;/// set to 0 at startup, 1 after initialization that is triggered by setParsAtomic()
#define thisFrameNumber GLOBALPARS(G_THIS_FRAME) // Current frame number (may lag from the hardware)
#define thisFrameNumber(p) GLOBALPARS(p,G_THIS_FRAME) // Current frame number (may lag from the hardware)
//#define THISFRAMENUMBER GLOBALPARS(G_THIS_FRAME) // Current frame number (may lag from the hardware)
#ifdef NC353
structframepars_all_t*frameparsall=NULL;/// - will be mmap-ed
structframepars_all_t*frameparsall=NULL;/// - will be mmap-ed
structframepars_t*framepars=NULL;///< getting rid of static to be able to use extern
structframepars_t*framepars=NULL;///< getting rid of static to be able to use extern
structframepars_past_t*pastpars=NULL;///< getting rid of static to be able to use extern
structframepars_past_t*pastpars=NULL;///< getting rid of static to be able to use extern
unsignedlong*funcs2call=NULL;/// sFrameParsAll.func2call.pars; - each parameter has a 32-bit mask of what pgm_function to call - other fields not used
unsignedlong*funcs2call=NULL;/// sFrameParsAll.func2call.pars; - each parameter has a 32-bit mask of what pgm_function to call - other fields not used
unsignedlong*globalPars=NULL;/// parameters that are not frame-related, their changes do not initiate any actions so they can be mmaped for both
unsignedlong*globalPars=NULL;/// parameters that are not frame-related, their changes do not initiate any actions so they can be mmaped for both
unsignedlong*multiSensIndex=NULL;/// index for per-sensor alternatives
unsignedlong*multiSensIndex=NULL;/// index for per-sensor alternatives
unsignedlong*multiSensRvrsIndex=NULL;/// reverse index (to parent) for the multiSensIndex
unsignedlong*multiSensRvrsIndex=NULL;/// reverse index (to parent) for the multiSensIndex
wait_queue_head_tframepars_wait_queue;/// used to wait for the frame to be acquired
wait_queue_head_tframepars_wait_queue;/// used to wait for the frame to be acquired
#endif
/* 393 : Changing to per-port */
structframepars_all_t*aframeparsall=NULL;/// - will be mmap-ed, in 393 points to an array of structures
structframepars_t*aframepars[SENSOR_PORTS];///< getting rid of static to be able to use extern
structframepars_past_t*apastpars[SENSOR_PORTS];///< getting rid of static to be able to use extern
unsignedlong*afuncs2call[SENSOR_PORTS];/// sFrameParsAll.func2call.pars; - each parameter has a 32-bit mask of what pgm_function to call - other fields not used
unsignedlong*aglobalPars[SENSOR_PORTS];/// parameters that are not frame-related, their changes do not initiate any actions so they can be mmaped for both
unsignedlong*amultiSensIndex[SENSOR_PORTS];/// index for per-sensor alternatives
unsignedlong*amultiSensRvrsIndex[SENSOR_PORTS];/// reverse index (to parent) for the multiSensIndex
wait_queue_head_taframepars_wait_queue[SENSOR_PORTS];/// used to wait for the frame to be acquired
wait_queue_head_tframepars_wait_queue;/// used to wait for the frame to be acquired
/**
/**
* @brief file private data
* @brief file private data
...
@@ -145,15 +158,16 @@ struct framepars_pd {
...
@@ -145,15 +158,16 @@ struct framepars_pd {
/**
/**
* @brief assign non-static pointers to static data to be used as extern
* @brief assign non-static pointers to static data to be used as extern
*/
*/
voidinit_framepars_ptr(void)
voidinit_framepars_ptr(intsensor_port)
{
{
frameparsall=&sFrameParsAll;/// - will be mmap-ed
// frameparsall = &sFrameParsAll; /// - will be mmap-ed
globalPars=sFrameParsAll.globalPars;/// parameters that are not frame-related, their changes do not initiate any actions so they can be mmaped for both
afuncs2call[sensor_port]=sFrameParsAll[sensor_port].func2call.pars;/// each parameter has a 32-bit mask of what pgm_function to call - other fields not used
multiSensIndex=sFrameParsAll.multiSensIndex;/// indexes of individual sensor register shadows (first of 3) - now for all parameters, not just sensor ones
aglobalPars[sensor_port]=sFrameParsAll[sensor_port].globalPars;/// parameters that are not frame-related, their changes do not initiate any actions so they can be mmaped for both
multiSensRvrsIndex=sFrameParsAll.multiSensRvrsIndex;/// reverse index (to parent) for the multiSensIndex
amultiSensIndex[sensor_port]=sFrameParsAll[sensor_port].multiSensIndex;/// indexes of individual sensor register shadows (first of 3) - now for all parameters, not just sensor ones
amultiSensRvrsIndex[sensor_port]=sFrameParsAll[sensor_port].multiSensRvrsIndex;/// reverse index (to parent) for the multiSensIndex
for(i=0;i<P_SENSOR_NUMREGS;i++)funcs2call[P_SENSOR_REGS+i]=ONCHANGE_SENSORREGS;/// by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
for(i=0;i<P_SENSOR_NUMREGS;i++)afuncs2call[sensor_port][P_SENSOR_REGS+i]=ONCHANGE_SENSORREGS;/// by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
/// Same for 10359 registers - will not change anything if there is no 10359 - these registers will not be chnaged, and if will be it wil cause no action
/// Same for 10359 registers - will not change anything if there is no 10359 - these registers will not be changed, and if will be it wil cause no action
for(i=0;i<P_M10359_NUMREGS;i++)funcs2call[P_M10359_REGS+i]=ONCHANGE_SENSORREGS;/// by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
for(i=0;i<P_M10359_NUMREGS;i++)afuncs2call[sensor_port][P_M10359_REGS+i]=ONCHANGE_SENSORREGS;/// by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
initMultiPars();/// initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called after/during sensor detection
initMultiPars();/// initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called after/during sensor detection
frameParsInitialized=1;
frameParsInitialized=1;
...
@@ -221,111 +259,120 @@ void initFramePars(void)
...
@@ -221,111 +259,120 @@ void initFramePars(void)
/**
/**
* @brief reset all global parameters, set default for debug mask (if ELPHEL_DEBUG)
* @brief reset all global parameters, set default for debug mask (if ELPHEL_DEBUG)
* @brief initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called after/during sensor detection
* @brief initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called after/during sensor detection
* @param sensor_port sensor port number (0..3)
* @return number of multi-regs
* @return number of multi-regs
*/
*/
intinitMultiPars(void)
intinitMultiPars(intsensor_port)
{
{
inti,j,n;
inti,j,n;
intireg=P_MULTI_REGS;/// multi-reg shadows start index
intireg=P_MULTI_REGS;/// multi-reg shadows start index
// remark: the line below is called from initFramePars, consider removing it
// remark: the line below is called from initFramePars, consider removing it
for(i=0;i<P_SENSOR_NUMREGS;i++)funcs2call[P_SENSOR_REGS+i]=ONCHANGE_SENSORREGS;/// by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
for(i=0;i<P_SENSOR_NUMREGS;i++)afuncs2call[sensor_port][P_SENSOR_REGS+i]=ONCHANGE_SENSORREGS;/// by default each "manual" write to any of 256 registers will trigger pgm_sensorreg function
/// Now update interframe_pars (interframe area) used to create JPEG headers. Interframe area survives exactly as long as the frames themselves (not like pastpars)
/// Now update interframe_pars (interframe area) used to create JPEG headers. Interframe area survives exactly as long as the frames themselves (not like pastpars)
if(interframe_pars){/// frame was compressed, not just vsync
if(interframe_pars){/// frame was compressed, not just vsync
///TODO: get rid of *_prev, use it for the future.
///TODO: get rid of *_prev, use it for the future.
memcpy(interframe_pars,&framepars[findex_this].pars[P_GTAB_R],24);/// will leave some gaps, but copy [P_ACTUAL_WIDTH]
memcpy(interframe_pars,&framepars[findex_this].pars[P_GTAB_R],24);/// will leave some gaps, but copy [P_ACTUAL_WIDTH]
interframe_pars->height=framepars[findex_this].pars[P_ACTUAL_HEIGHT];/// NOTE: P_ACTUAL_WIDTH,P_QUALITY copied with memcpy
interframe_pars->height=framepars[findex_this].pars[P_ACTUAL_HEIGHT];/// NOTE: P_ACTUAL_WIDTH,P_QUALITY copied with memcpy
MDF7(printk("resubmitting past due functions = 0x%lx for frame=%ld (0x%x)\n",framepars[findex_this].functions,thisFrameNumber,findex_this));
MDF7(printk("resubmitting past due functions = 0x%lx for frame=%ld (0x%x)\n",framepars[findex_this].functions,thisFrameNumber(sensor_port),findex_this));
}else{
}else{
MDF(printk("Ignored past due functions = 0x%lx for frame=%ld (0x%x)\n",framepars[findex_this].functions,thisFrameNumber,findex_this));
MDF(printk("Ignored past due functions = 0x%lx for frame=%ld (0x%x)\n",framepars[findex_this].functions,thisFrameNumber(sensor_port),findex_this));
}
}
}
}
thisFrameNumber++;
thisFrameNumber(sensor_port)++;
}
}
}
}
voidupdate_frame_pars(void)
{
printk(KERN_DEBUG"%s stub\n",__func__);
}
/**
/**
* @brief process parameters that are overdue or due in ASAP mode (not through the sequencer)
* @brief process parameters that are overdue or due in ASAP mode (not through the sequencer)
* Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?)
* Called twice from processPars - at the beginning and at the end to finish off any derivatives (needed?)
///TODO: init framepars (zero parameters) before initscripts (not when detecting the sensors) - then initscript will be able to overwrite some
///TODO: init framepars (zero parameters) before initscripts (not when detecting the sensors) - then initscript will be able to overwrite some
voidinit_framepars_ptr(void);
voidinit_framepars_ptr(intsensor_port);
voidinitSequencers(void);///Move to sensorcommon? currently it is used through frameparsall file (lseek)
voidinitSequencers(intsensor_port);///Move to sensorcommon? currently it is used through frameparsall file (lseek)
voidinitGlobalPars(void);/// resets all global parameters but debug mask (if ELPHEL_DEBUG)
voidinitGlobalPars(intsensor_port);/// resets all global parameters but debug mask (if ELPHEL_DEBUG)
intinitMultiPars(void);/// initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called aftre/during sensor detection
intinitMultiPars(intsensor_port);/// initialize structures for individual per-sensor parameters. Now only works for sensor registers using G_MULTI_REGSM. Should be called aftre/during sensor detection
voidinitFramePars(void);///initialize all parameters, set thisFrameNumber to frame8 (read from hardware, usually 0 after resetting i2c and cmd_seq)
voidinitFramePars(intsensor_port);///initialize all parameters, set thisFrameNumber to frame8 (read from hardware, usually 0 after resetting i2c and cmd_seq)
voidresetFrameNumber(void);/// reset this frame number (called from initFramePars(), also can be used to avoid frame number integer overflow)
voidresetFrameNumber(intsensor_port);/// reset this frame number (called from initFramePars(), also can be used to avoid frame number integer overflow)
voidupdateFramePars(intsensor_port,intframe8,structinterframe_params_t*frame_pars);/// called from ISR - advance thisFrameNumber to match hardware frame8, copy parameters as needed.
voidupdateFramePars(intframe8,structinterframe_params_t*frame_pars);/// called from ISR - advance thisFrameNumber to match hardware frame8, copy parameters as needed.
/// frame8 usually is just next after thisFrameNumber
/// frame8 usually is just next after thisFrameNumber
/// frame_pars - pointer to structure (between frames in the frame buffer) to save a pointer to past parameters
/// frame_pars - pointer to structure (between frames in the frame buffer) to save a pointer to past parameters
unsignedlonggetThisFrameNumber(void);/// just return current thisFrameNumber
unsignedlonggetThisFrameNumber(intsensor_port);/// just return current thisFrameNumber
/// set parameters for the frame number frameno, knowing that they should be set not less than maxLatency ahead (may be sensor - dependent)
/// set parameters for the frame number frameno, knowing that they should be set not less than maxLatency ahead (may be sensor - dependent)
/// Parameters (numPars of them) will be updated all at once, with interrupts disabled
/// Parameters (numPars of them) will be updated all at once, with interrupts disabled
/// Return - 0 if OK, -ERR_FRAMEPARS_TOOEARLY or -ERR_FRAMEPARS_TOOLATE if it is too early or too late to set parameters (numPars may be 0 to just test)
/// Return - 0 if OK, -ERR_FRAMEPARS_TOOEARLY or -ERR_FRAMEPARS_TOOLATE if it is too early or too late to set parameters (numPars may be 0 to just test)
...
@@ -42,27 +43,28 @@ unsigned long getThisFrameNumber(void); /// just return current thisFrameNumber
...
@@ -42,27 +43,28 @@ unsigned long getThisFrameNumber(void); /// just return current thisFrameNumber
/// TODO: Make (an "unlimited") future commands que based on lists and a tree frame index
/// TODO: Make (an "unlimited") future commands que based on lists and a tree frame index
/// Parameters related to multi-sensor (10359A) setup
/// Parameters related to multi-sensor (10359A) setup
#define MAX_SENSORS 3 // maximal number of sensor attached (modify some hard-wired constants below if this to be changed)
//#define MAX_SENSORS 3 // maximal number of sensor attached (modify some hard-wired constants below if this to be changed)
//! Parameters below are accessed through mmap, because of cache coherency problem it make sense to keep them compact (maybe group by 8 - cache line of 32 bytes)
/* Modified for 393 - using up to 4 sub-sensors (even as 10359 only supports 3 */
#define MAX_SENSORS 4 // maximal number of sensor attached (modify some hard-wired constants below if this to be changed)
#define SENSOR_PORTS 4 // Number of sensor ports (each has individual framepars_all_t
//! Parameters below are accessed through mmap, because of cache coherence problem it make sense to keep them compact (maybe group by 8 - cache line of 32 bytes)
#define P_SENSOR_RUN 4 // 0 - stop, 1 - single, 2 - run
#define P_SENSOR_RUN 4 // 0 - stop, 1 - single, 2 - run
//#define P_MAX_PAR 511 /// maximal # of used parameter
//#define P_MAX_PAR 511 /// maximal # of used parameter
//#define P_MAX_GPAR 1023 // maximal # of global parameter
//#define P_MAX_GPAR 1023 // maximal # of global parameter
#define P_MAX_GPAR 2047 /// maximal # of global parameter - TODO: change name to NUM_GPAR and make it 2048
//#define P_MAX_GPAR 2047 /// maximal # of global parameter - TODO: change name to NUM_GPAR and make it 2048
#define NUM_GPAR 2048 /// maximal # of global parameter - TODO: change name to NUM_GPAR and make it 2048
#define P_MAX_GPAR (NUM_GPAR - 1) /// maximal # of global parameter - TODO: change name to NUM_GPAR and make it 2048
#define PARS_SAVE_FROM 128 /// PARS_SAVE_NUM parameters starting from PARS_SAVE_FROM from "this" frame will be saved in circular buffer, PASTPARS_SAVE_ENTRIES entries
#define PARS_SAVE_FROM 128 /// PARS_SAVE_NUM parameters starting from PARS_SAVE_FROM from "this" frame will be saved in circular buffer, PASTPARS_SAVE_ENTRIES entries
#define PARS_SAVE_COPY 16 /// number of parameters copied from future (framepars) to the past (pastpars)
#define PARS_SAVE_COPY 16 /// number of parameters copied from future (framepars) to the past (pastpars)
...
@@ -617,7 +628,7 @@
...
@@ -617,7 +628,7 @@
#define GLOBALS_PRESERVE 0x20 /// number of parameters that are not erased during initGlobalPars
#define GLOBALS_PRESERVE 0x20 /// number of parameters that are not erased during initGlobalPars
/// First 32 parameter values are not erased with initGlobalPars
/// First 32 parameter values are not erased with initGlobalPars
#define GLOBALPARS(x) globalPars[(x)-FRAMEPAR_GLOBALS] // should work in drivers and applications
#define GLOBALPARS(p, x) (aglobalPars[p][(x)-FRAMEPAR_GLOBALS]) // should work in drivers and applications
#define G_DEBUG (FRAMEPAR_GLOBALS + 2) /// Each bit turns on/off some debug outputs
#define G_DEBUG (FRAMEPAR_GLOBALS + 2) /// Each bit turns on/off some debug outputs
#define G_TEST_CTL_BITS (FRAMEPAR_GLOBALS + 3) /// turn some features on/off in the drivers for debugging purposes
#define G_TEST_CTL_BITS (FRAMEPAR_GLOBALS + 3) /// turn some features on/off in the drivers for debugging purposes
...
@@ -817,10 +828,14 @@
...
@@ -817,10 +828,14 @@
/// when the 3-bit counter is combined with the software variable to get the full 32-bit frame number
/// when the 3-bit counter is combined with the software variable to get the full 32-bit frame number
/// Each parameter page includes 927 parameter registers, as well as 97 bitmasks to speed up updates between frames
/// Each parameter page includes 927 parameter registers, as well as 97 bitmasks to speed up updates between frames
/// So if no parameters are changed - nothing to be copied from page to page
/// So if no parameters are changed - nothing to be copied from page to page
#define PARS_FRAMES 8 // number of frames handled in buffer
/* Modified for 393 : 16 hardware frames, aligning framepars_all_t to PAGE_SIZE*/
#define PARS_FRAMES_MASK (PARS_FRAMES-1) // currently 7
#define PARS_FRAMES 16 // 8 // number of frames handled in buffer
unsignedlongpars[927];// parameter values (indexed by P_* constants)
unsignedlongpars[927];// parameter values (indexed by P_* constants)
unsignedlongfunctions;// each bit specifies function to be executed (triggered by some parameters change)
unsignedlongfunctions;// each bit specifies function to be executed (triggered by some parameters change)
...
@@ -893,13 +908,14 @@ struct framepars_past_t {
...
@@ -893,13 +908,14 @@ struct framepars_past_t {
unsignedlongpast_pars[PARS_SAVE_NUM];
unsignedlongpast_pars[PARS_SAVE_NUM];
};
};
// size should be PAGE_SIZE aligned
structframepars_all_t{
structframepars_all_t{
structframepars_tframePars[PARS_FRAMES];
structframepars_tframePars[PARS_FRAMES];
structframepars_tfunc2call;/// func2call.pars[] - each parameter has a 32-bit mask of what pgm_function to call - other fields not used
structframepars_tfunc2call;/// func2call.pars[] - each parameter has a 32-bit mask of what pgm_function to call - other fields not used
unsignedlongglobalPars[P_MAX_GPAR];/// parameters that are not frame-related, their changes do not initiate any actions so they can be mmaped for both R/W
unsignedlongglobalPars[NUM_GPAR];/// parameters that are not frame-related, their changes do not initiate any actions so they can be mmaped for both R/W
unsignedlongmultiSensIndex[P_MAX_PAR];/// indexes of individual sensor register shadows (first of 3) - now for all parameters, not just sensor ones
unsignedlongmultiSensIndex[P_MAX_PAR_ROUNDUP];/// indexes of individual sensor register shadows (first of 3) - now for all parameters, not just sensor ones
unsignedlongmultiSensRvrsIndex[P_MAX_PAR];/// reverse index (to parent) for the multiSensIndex in lower 16 bits, high 16 bits - sensor number
unsignedlongmultiSensRvrsIndex[P_MAX_PAR_ROUNDUP];/// reverse index (to parent) for the multiSensIndex in lower 16 bits, high 16 bits - sensor number
};
};
structframeparspair_t{
structframeparspair_t{
...
@@ -1771,7 +1787,7 @@ struct gamma_stuct_t {
...
@@ -1771,7 +1787,7 @@ struct gamma_stuct_t {
#define HISTOGRAM_TABLE_OFFSET 52 /// Histogram tables data starts 44 bytes from the histogram page structure (for PHP raw histogram)
#define HISTOGRAM_TABLE_OFFSET 52 /// Histogram tables data starts 44 bytes from the histogram page structure (for PHP raw histogram)
///TODO: Update when histogram_stuct_t is changed
///TODO: Update when histogram_stuct_t is changed
structhistogram_stuct_t{
structhistogram_stuct_t{
unsignedlongframe;/// frame number correspoding to the current histogram
unsignedlongframe;/// frame number corresponding to the current histogram