Commit 3c106d1d authored by Andrey Filippov's avatar Andrey Filippov

Making driver files compile

parent 581d1d2f
......@@ -23,3 +23,9 @@ obj-$(CONFIG_ELPHEL393) += quantization_tables.o
obj-$(CONFIG_ELPHEL393) += circbuf.o
obj-$(CONFIG_ELPHEL393) += jpeghead.o
obj-$(CONFIG_ELPHEL393) += gamma_tables.o
obj-$(CONFIG_ELPHEL393) += histograms.o
obj-$(CONFIG_ELPHEL393) += pgm_functions.o
obj-$(CONFIG_ELPHEL393) += mt9x001.o
obj-$(CONFIG_ELPHEL393) += multi10359.o
......@@ -187,7 +187,8 @@ int x393_getClockFreq(int sensor_port, int nclock) {
EXPORT_SYMBOL_GPL(x393_getClockFreq);
int x393_setClockFreq(int sensor_port, int nclock, int freq) { // freq now in Hz
int x393_setClockFreq(int sensor_port, int nclock, int freq)
{ // freq now in Hz
int err=0;
sensor_port &= 3;
nclock &= 3;
......
......@@ -550,10 +550,10 @@ inline void processParsASAP(int sensor_port, struct sensorproc_t * sensorproc, i
framepars[4].functions, framepars[5].functions, framepars[6].functions, framepars[7].functions));
if (sensorproc->pgm_func[i]) {
rslt = sensorproc->pgm_func[i] ( &(sensorproc->sensor), procpars, prevpars, -1);
rslt = sensorproc->pgm_func[i] (sensor_port, &(sensorproc->sensor), procpars, prevpars, -1);
} else rslt = 0; // only sensor-specific function, nothing to do common to all sensors
if ((rslt >= 0) && (sensorproc->pgm_func[i + 32])) { // sensor - specific functions, called after the main ones
rslt = sensorproc->pgm_func[i + 32] ( &(sensorproc->sensor), procpars, prevpars, -1);
rslt = sensorproc->pgm_func[i + 32] (sensor_port, &(sensorproc->sensor), procpars, prevpars, -1);
}
// Nothing to do with errors here - just report?
if (rslt < 0) printk("%s:%d:%s - error=%d", __FILE__, __LINE__, __FUNCTION__, rslt);
......@@ -627,10 +627,10 @@ inline void processParsSeq(int sensor_port, struct sensorproc_t * sensorproc, in
if (sensorproc->pgm_func[i]) {
// NOTE: Was (frame8+job_ahead +1) & PARS_FRAMES_MASK
rslt = sensorproc->pgm_func[i] ( &(sensorproc->sensor), procpars, prevpars, seq_frame);
rslt = sensorproc->pgm_func[i] (sensor_port, &(sensorproc->sensor), procpars, prevpars, seq_frame);
} else rslt = 0; // only sensor-specific function, nothing to do common to all sensors
if ((rslt >= 0) && (sensorproc->pgm_func[i + 32])) { // sensor - specific functions, called after the main ones
rslt = sensorproc->pgm_func[i + 32] ( &(sensorproc->sensor), procpars, prevpars, seq_frame);
rslt = sensorproc->pgm_func[i + 32] (sensor_port, &(sensorproc->sensor), procpars, prevpars, seq_frame);
}
if (rslt >= 0) {
procpars->functions &= ~mask; // mark it done
......@@ -1113,7 +1113,7 @@ loff_t framepars_lseek(struct file * file, loff_t offset, int orig)
unsigned long target_frame;
struct framepars_pd * privData = (struct framepars_pd*) file -> private_data;
int sensor_port = privData -> minor - CMOSCAM_MINOR_FRAMEPARS_CHN_0;
struct framepars_t *framepars = aframepars[sensor_port];
// struct framepars_t *framepars = aframepars[sensor_port];
MDF1(printk(" offset=0x%x, orig=0x%x, sensor_port = %d\n", (int)offset, (int)orig, sensor_port));
switch (orig) {
case SEEK_SET:
......
......@@ -7,11 +7,11 @@ int is_gamma_current (unsigned short hash16, unsigned short scale, int index);
int is_gamma_valid (unsigned short hash16, unsigned short scale, int index);
// int prev_locked_color[4];
int unlock_gamma_node (int color); /// NOTE: Not needed anymore
int unlock_gamma_node (int color, int sensor_port, int sensor_subchn); /// NOTE: Not needed anymore
///
/// return a pointer to the gamma table (single color) encoded in FPGA format (NULL if there is to table ready)
///
unsigned long * get_gamma_fpga(int color);
unsigned long * get_gamma_fpga(int color, int sensor_port, int sensor_subchn);
int gamma_new_node(void);
void gamma_encode_fpga(unsigned short * gamma_in, unsigned long * gamma_out);///Hardware-dependent encoding of the FPGA "gamma" table. Converts unsigned short array of 257 16-bit values (only 10 msb-s are used) to 256 unsigned long words to be written to FPGA
......@@ -27,5 +27,6 @@ void gamma_calc_reverse(unsigned short * gamma_in, unsigned char * gamma_out);/
// #define GAMMA_MODE_HARDWARE 4 // the table is needed to program FPGA: fpga-encoded table will be calculated (if not yet), node will be locked for specified
// color/frame pair
int set_gamma_table (unsigned short hash16, unsigned short scale, unsigned short * gamma_proto, unsigned char mode, int color, int sensor_port, int sensor_subchn);
unsigned long get_locked_hash32(int color);
unsigned long get_locked_hash32(int color, int sensor_port,int sensor_subchn);
#endif
......@@ -102,7 +102,9 @@
#include <asm/outercache.h>
#include <asm/cacheflush.h>
#include <linux/dma-mapping.h>
#include <linux/dma-direction.h>
// ##include <asm/dma-mapping.h>
#include <elphel/driver_numbers.h>
#include <elphel/c313a.h>
......@@ -130,6 +132,8 @@
#define MDF22(x)
#endif
//u32 (*fpga_hist_data)[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
//u32 *fpga_hist_data[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
u32 (*fpga_hist_data)[SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]; ///< Array of histogram data, mapped to the memory wheer FPGA sends data
dma_addr_t fpga_hist_phys; // physical address of the start of the received histogram data
......@@ -144,6 +148,7 @@ static int numHistChn = 0;
/** Variable-length array (length is the total number of active sensors <=16), each being the same as in 353:
* consisting of SENSOR_PORTS histogram_stuct_t structures */
struct histogram_stuct_t (*histograms)[HISTOGRAM_CACHE_NUMBER];
//struct histogram_stuct_t *histograms;
dma_addr_t histograms_phys; ///< likely not needed, saved during allocation
......@@ -193,7 +198,8 @@ int histograms_init_hardware(void)
{
int port, chn;
x393_hist_saxi_addr_t saxi_addr;
fpga_hist_data = (u32 [SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]) pElphel_buf->d2h_vaddr; // must be page-aligned!
// fpga_hist_data = (u32 [SENSOR_PORTS][MAX_SENSORS][PARS_FRAMES][4][256]) pElphel_buf->d2h_vaddr; // must be page-aligned!
fpga_hist_data = (u32 *) pElphel_buf->d2h_vaddr; // must be page-aligned!
fpga_hist_phys = pElphel_buf->d2h_paddr;
for (port=0; port<SENSOR_PORTS; port++) for (chn=0; chn < MAX_SENSORS; chn++) {
saxi_addr.page=(fpga_hist_phys >> PAGE_SHIFT)+ PARS_FRAMES * (chn + MAX_SENSORS *port);// table for 4 colors is exactly 1 page;
......@@ -225,24 +231,29 @@ void init_histograms(int chn_mask) ///< combined subchannels and ports Save mask
unsigned long flags;
int p,s,i, sz,pages;
numHistChn = 0; //__builtin_popcount (chn_mask & 0xffff);
if (sz & (PAGE_SIZE-1)) pages++;
for (p=0; p< SENSOR_PORTS; p++) for (s=0;s <MAX_SENSORS;s++) {
i = p * SENSOR_PORTS + s;
if (chn_mask & (1 << i)){
histograms_map = numHistChn++;
histograms_map[p][s] = numHistChn++;
GLOBALPARS(p, G_HIST_LAST_INDEX + s) =0; // mark as valid
GLOBALPARS(p, G_SUBCHANNELS) |= 1 << s;
} else {
histograms_map = -1;
histograms_map[p][s] = -1;
GLOBALPARS(p, G_HIST_LAST_INDEX + s) =0xffffffff; // mark as invalid
GLOBALPARS(p, G_SUBCHANNELS) &= ~(1 << s);
}
}
//G_SUBCHANNELS
sz = numHistChn * HISTOGRAM_CACHE_NUMBER * sizeof(struct histogram_stuct_t);
if (sz & (PAGE_SIZE-1)) pages++;
pages = sz >> PAGE_SHIFT;
// When device == NULL, dma_alloc_coherent just allocates notmal memory, page aligned, CMA if available
histograms = (struct histogram_stuct_t*[HISTOGRAM_CACHE_NUMBER]) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
// histograms = (struct histogram_stuct_t* [HISTOGRAM_CACHE_NUMBER]) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
// histograms = (struct histogram_stuct_t[HISTOGRAM_CACHE_NUMBER] * ) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
// histograms = (struct histogram_stuct_t[HISTOGRAM_CACHE_NUMBER]) * dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL);
histograms = dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL); // OK
// histograms = (struct histogram_stuct_t * ) dma_alloc_coherent(NULL,(sz * PAGE_SIZE),&histograms_phys,GFP_KERNEL); //<<<assignment from incompatible pointer type [-Wincompatible-pointer-types]>>>
BUG_ON(!histograms);
histograms_p= (struct histogram_stuct_t *) histograms;
MDF21(printk("\n"));
......@@ -284,12 +295,12 @@ int set_histograms (int sensor_port, ///< sensor port number (0..3)
int i, color_start, hist_indx, hist_frame;
hist_indx=get_hist_index(sensor_port,sensor_chn);
if (hist_indx <0 ) return -EINVAL;
if (histograms[GLOBALPARS(sensor_port,G_HIST_LAST_INDEX+sensor_chn)].frame!=frame) {
if (histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX+sensor_chn)].frame!=frame) {
GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)=(GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)+1) & (HISTOGRAM_CACHE_NUMBER-1);
histograms[hist_indx][GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)].valid=0; // overwrite all
histograms[hist_indx][GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn)].frame=frame; // add to existent
if (framep) memcpy (&(histograms[GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].frame), framep, 32); // copy provided frame, gains,expos,vexpos, focus
if (gammaHash) memcpy (&(histograms[GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].gtab_r), gammaHash, 16); // copy provided 4 hash32 values
if (framep) memcpy (&(histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].frame), framep, 32); // copy provided frame, gains,expos,vexpos, focus
if (gammaHash) memcpy (&(histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].gtab_r), gammaHash, 16); // copy provided 4 hash32 values
} else {
needed &= ~histograms[hist_indx][GLOBALPARS(sensor_port,G_HIST_LAST_INDEX)].valid; // remove those that are already available from the request
}
......@@ -337,9 +348,10 @@ int get_histograms(int sensor_port, ///< sensor port number (0..3)
{
int i, color_start, index;
int hist_indx=get_hist_index(sensor_port,sensor_chn);
int raw_needed;
if (hist_indx <0 ) return -EINVAL;
index=GLOBALPARS(sensor_port, G_HIST_LAST_INDEX+sensor_chn);
int raw_needed=(needed | (needed>>4) | needed>>8) & 0xf;
raw_needed=(needed | (needed>>4) | needed>>8) & 0xf;
for (i=0;i<HISTOGRAM_CACHE_NUMBER;i++) {
MDF21(printk("index=%d, needed=0x%x\n",index,needed));
if ((histograms[hist_indx][index].frame <= frame) && ((histograms[hist_indx][index].valid & raw_needed)==raw_needed)) break;
......@@ -403,12 +415,12 @@ inline void histogram_calc_percentiles (unsigned long * cumul_hist, ///< [IN]
unsigned long v256=0; // running value to be compared against cumulative histogram (it is 256 larger than cumul_hist)
unsigned long inc_v256=cumul_hist[255]; // step of v256 increment
int shiftl=8;
int p=0; // current value of percentile
int x=0; // current percentile index
while (inc_v256>0xffffff) { // to protect from unlikely overflow at 16MPix - in the future)
inc_v256 >>= 1;
shiftl--;
}
int p=0; // current value of percentile
int x=0; // current percentile index
while ((p<256) && (x<256)) {
percentile[x]=p;
if ((p<255) && ( (cumul_hist[p] << shiftl) <= v256)) {
......@@ -547,24 +559,24 @@ loff_t histograms_lseek (struct file * file,
else reqFrame=offset;
}
if ((offset < reqFrame) && // if the requested frame is in the past - try to get it first before requesting a new
(((privData->frame_index = get_histograms (offset, privData->needed))) >=0)) {
(((privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed))) >=0)) {
// file->f_pos=privData->frame_index;
file->f_pos=privData->frame_index + HISTOGRAM_CACHE_NUMBER * get_hist_index(privData->port, privData->subchannel);
return file->f_pos;
}
// request histogram(s)
// setFramePar(&framepars[reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(&aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][reqFrame & PARS_FRAMES_MASK], reqAddr, 1);
// make sure (harmful) interrupt did not happen since getThisFrameNumber()
if (reqFrame < getThisFrameNumber(privData->port)) {
// setFramePar(&framepars[getThisFrameNumber() & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(&aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
setFramePar(privData->port, &aframepars[privData->port][getThisFrameNumber(privData->port) & PARS_FRAMES_MASK], reqAddr, 1);
}
}
if (privData-> wait_mode) wait_event_interruptible (hist_c_wait_queue,GLOBALPARS(privData->port,G_HIST_C_FRAME + privData->subchannel)>=offset);
else wait_event_interruptible (hist_y_wait_queue,GLOBALPARS(privData->port,G_HIST_Y_FRAME + privData->subchannel)>=offset);
privData->frame_index = get_histograms (offset, privData->needed);
privData->frame_index = get_histograms (privData->port, privData->subchannel, offset, privData->needed);
if (privData->frame_index <0) {
return -EFAULT;
} else {
......@@ -605,12 +617,12 @@ loff_t histograms_lseek (struct file * file,
default:
switch (offset & ~0x1f) {
case LSEEK_DAEMON_HIST_Y: // wait for daemon enabled and histograms Y ready
MDF21(printk("wait_event_interruptible (hist_y_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(P_DAEMON_EN) & (1<<(offset & 0x1f)));
MDF21(printk("wait_event_interruptible (hist_y_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
wait_event_interruptible (hist_y_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break;
case LSEEK_DAEMON_HIST_C: // wait for daemon enabled and histograms Y ready
MDF21(printk("wait_event_interruptible (hist_c_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(P_DAEMON_EN) & (1<<(offset & 0x1f)));
MDF21(printk("wait_event_interruptible (hist_c_wait_queue,0x%x & 0x%x)\n",(int) get_imageParamsThis(privData->port, P_DAEMON_EN), (int) (1<<(offset & 0x1f))));
wait_event_interruptible (hist_c_wait_queue, get_imageParamsThis(privData->port, P_DAEMON_EN) & (1<<(offset & 0x1f)));
break;
default:
return -EINVAL;
......
......@@ -26,7 +26,7 @@ int get_hist_index (int sensor_port, int sensor_chn);
int set_histograms (int sensor_port, int sensor_chn, unsigned long frame, int needed, unsigned long * gammaHash, unsigned long * framep);
int get_histograms (unsigned long frame, int needed);
int get_histograms (int sensor_port, int sensor_chn, unsigned long frame, int needed);
int histograms_init_hardware(void);
void histograms_dma_ctrl(int mode); // 0 - reset, 1 - disable, 2 - enable
/*!***************************************************************************
*! FILE NAME : imu_log353.c
*! DESCRIPTION: reading IMU log fifo
*! Copyright (C) 2011 Elphel, Inc.
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*! -----------------------------------------------------------------------------**
*! $Log: imu_log353.c,v $
*! Revision 1.5 2012/04/14 03:53:48 elphel
*! bug fix in the driver (was producing errors in 3-4 hours)
*!
*! Revision 1.3 2011/08/13 00:54:08 elphel
*! added /dev/imu_ctl where it is possible to read current logger settings
*!
*! Revision 1.2 2011/07/30 23:22:54 elphel
*! Modified to enable simultaneous access to IMU logger,
*! fixed bug noticed by Lemay
*!
*! Revision 1.1 2011/05/20 03:33:48 elphel
*! IMU/GPS logger driver, initial commit
*!
*/
/****************** INCLUDE FILES SECTION ***********************************/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/autoconf.h>
#include <asm/system.h>
#include <asm/arch/memmap.h>
//#include <asm/svinto.h>
#include <asm/io.h>
#include <asm/arch/dma.h>
#include <asm/arch/hwregs/dma_defs.h>
#include <asm/arch/hwregs/dma.h>
#include <asm/arch/hwregs/reg_map.h>
#include <asm/arch/hwregs/bif_dma_defs.h>
#include <asm/irq.h>
#include <asm/fasttimer.h>
#include <asm/atomic.h>
#include <asm/delay.h>
#include <asm/uaccess.h>
#include <asm/arch/cache.h>
#include <asm/elphel/driver_numbers.h>
#include <asm/elphel/c313a.h>
#include <asm/elphel/fpgaconfa.h>
#include "fpgactrl.h"
//#include "fpga_sdram.h"
#include "imu_log353.h"
#include "x3x3.h"
#include "cci2c.h" // i2c to enable CS for the IMU
#if 0
#define D(x) x
#define D0(x) x
#define MD7(x) printk("%s:%d:",__FILE__,__LINE__);x
#define MD8(x) printk("%s:%d:",__FILE__,__LINE__);x
#define MD12(x) printk("%s:%d:",__FILE__,__LINE__);x
#else
#define D(x)
#define D0(x)
#define MD7(x)
#define MD8(x)
#define MD12(x)
#endif
#define D1(x) x
#define IS_103695_REV_A 1
#define EXT_DMA_1_START \
do { reg_bif_dma_rw_ch1_start c = {.run=1};\
REG_WR(bif_dma, regi_bif_dma, rw_ch1_start, (reg_bif_dma_rw_ch1_start) c); } while( 0 )
#define EXT_DMA_1_STOP \
do { reg_bif_dma_rw_ch1_start c = {.run=0};\
REG_WR(bif_dma, regi_bif_dma, rw_ch1_start, (reg_bif_dma_rw_ch1_start) c); } while( 0 )
#define bytePtrMask ((CCAM_DMA1_SIZE << 2)-1) // and byte pointer in the dma buffer to get index in the array
#define XCLK_RATE 80000000
#define RS232_RATE 19200
#define IMU_MODULE_DESCRIPTION "IMU logger for 10365 ext. board"
#define IMU_DRIVER_NAME "imu_logger"
#define IMU_MAXMINOR 10
#define X313_WA_IOPINS 0x70 // bits [31:24] - enable channels (channel 0 -software, enabled at FPGA init)
#define X313_WA_IOPINS_EN_IMU 0xc0000000
#define X313_WA_IOPINS_DIS_IMU 0x80000000
#define X313_WA_IMU_DATA 0x7e
#define X313_WA_IMU_CTRL 0x7f
// #define X313_RA_IMU_DATA 0x7e // use csp4
// #define X313_RA_IMU_STATUS 0x7f // use csp4
#define IMU_COUNT_OVERFLOW 0x1000000 // number of records written is modulo IMU_COUNT_OVERFLOW
#define X313_RA_IMU_COUNT 0x7e // number of 64-byte samples recorded (24 bit counter)
#define X313_IMU_PERIOD_ADDR 0x0 // request period for IMU (in SPI bit periods)
#define X313_IMU_DIVISOR_ADDR 0x1 // xclk (80MHz) clock divisor for half SPI bit period
#define X313_IMU_RS232DIV_ADDR 0x2 // serial gps bit duration in xclk (80MHz) periods - 16 bits
#define X313_IMU_CONFIGURE_ADDR 0x3 // IMU logger configuration
#define IMU_CONF(x,y) (((((y) & ((1 << IMUCR__##x##__WIDTH)-1))) | (1 << IMUCR__##x##__WIDTH) ) << IMUCR__##x##__BITNM)
#define IMUCR__IMU_SLOT__BITNM 0 // slot, where 103695 (imu) bnoard is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11)
#define IMUCR__IMU_SLOT__WIDTH 2
#define IMUCR__GPS_CONF__BITNM 3 // slot, where 103695 (imu) bnoard is connected: 0 - none, 1 - J9, 2 - J10, 3 - J11)
#define IMUCR__GPS_CONF__WIDTH 4 // bits 0,1 - slot #, same as for IMU_SLOT, bits 2,3:
// 0 - ext pulse, leading edge,
// 1 - ext pulse, trailing edge
// 2 - start of the first rs232 character after pause
// 3 - start of the last "$" character (start of each NMEA sentence)
#define IMUCR__MSG_CONF__BITNM 8 // source of external pulses to log:
#define IMUCR__MSG_CONF__WIDTH 5 // bits 0-3 - number of fpga GPIO input 0..11 (i.e. 0x0a - external optoisolated sync input (J15)
// 0x0f - disable MSG module
// bit 4 - invert polarity: 0 - timestamp leading edge, log at trailing edge, 1 - opposite
// software may set (up to 56 bytes) log message before trailing end of the pulse
#define IMUCR__SYN_CONF__BITNM 14 // logging frame time stamps (may be synchronized by another camera and have timestamp of that camera)
#define IMUCR__SYN_CONF__WIDTH 1 // 0 - disable, 1 - enable
#define IMUCR__RST_CONF__BITNM 16 // reset module
#define IMUCR__RST_CONF__WIDTH 1 // 0 - enable, 1 -reset (needs resettimng DMA address in ETRAX also)
#define IMUCR__DBG_CONF__BITNM 18 // several axtra IMU configuration bits
#define IMUCR__DBG_CONF__WIDTH 4 // 0 - config_long_sda_en, 1 -config_late_clk, 2 - config_single_wire, should be set for 103695 rev "A"
#define X313_IMU_REGISTERS_ADDR 0x4
#define X313_IMU_NMEA_FORMAT_ADDR 0x20
#define X313_IMU_MESSAGE_ADDR 0x40 // 40..4f, only first 0xe visible
// offsets in the file (during write)
#define X313_IMU_PERIOD_OFFS 0x0
#define X313_IMU_DIVISOR_OFFS 0x4
#define X313_IMU_RS232DIV_OFFS 0x8
#define X313_IMU_CONFIGURE_OFFS 0xc
#define X313_IMU_SLEEP_OFFS 0x10
#define X313_IMU_REGISTERS_OFFS 0x14 // .. 0x2f
#define X313_IMU_NMEA_FORMAT_OFFS 0x30
#define X313_IMU_MESSAGE_OFFS 0xB0 // 0xB0..0xE7
#define PCA9500_PP_ADDR 0x40 // PCA9500 i2c slave addr for the parallel port (read will be 0x41)
#define DFLT_SLAVE_ADDR 3 // i2c slave addr modifier (0..7) for the IMU (103695) board
#define DFLT_SCLK_FREQ 5000000 // SCLK frequency
#define DFLT_DIVISOR ( XCLK_RATE / DFLT_SCLK_FREQ /2 )
#define DFLT_STALL_USEC 2 // stall time in usec
#define DFLT_STALL (( DFLT_STALL_USEC * ( XCLK_RATE / DFLT_DIVISOR )) / 1000000 ) // stall time in usec
#define DFLT_SLEEP 30000 // usec, sleep if not ready
//#define DFLT_FEQ 300
//#define DFLT_PERIOD ( XCLK_RATE / DFLT_DIVISOR / DFLT_FEQ ) // fixed scan period
#define DFLT_PERIOD 0xFFFFFFFF // read IMU when it is ready
#define DFLT_RS232DIV ( XCLK_RATE / 2 / RS232_RATE )
#if IS_103695_REV_A
#define EXTRA_CONF 0x4
#else
#define EXTRA_CONF 0x0
#endif
#define SLOW_SPI 0 // set to 1 for slower SPI (not ADIS-16375), it will increase SCLK period that does not end CS active
#define DFLT_CONFIG ( IMU_CONF(IMU_SLOT,1) | \
IMU_CONF(GPS_CONF, ( 2 | 8) ) | \
IMU_CONF(MSG_CONF,10) | \
IMU_CONF(SYN_CONF, 1) | \
IMU_CONF(DBG_CONF, EXTRA_CONF) | \
((SLOW_SPI & 1)<<23) | \
(DFLT_SLAVE_ADDR << 24))
#define WHICH_INIT 1
#define WHICH_RESET 2
#define WHICH_RESET_SPI 4
#define WHICH_DIVISOR 8
#define WHICH_RS232DIV 16
#define WHICH_NMEA 32
#define WHICH_CONFIG 64
#define WHICH_REGISTERS 128
#define WHICH_MESSAGE 256
#define WHICH_PERIOD 512
#define WHICH_EN_DMA 1024
#define WHICH_EN_LOGGER 2048
#define LSEEK_IMU_NEW 1 // start from the new data, discard buffer
#define LSEEK_IMU_STOP 2 // stop DMA1 and IMU
#define LSEEK_IMU_START 3 // start IMU and DMA1 (do not modify parameters)
static unsigned char dflt_wbuf[]=
{ DFLT_PERIOD & 0xff, ( DFLT_PERIOD >> 8 ) & 0xff, ( DFLT_PERIOD >> 16) & 0xff, ( DFLT_PERIOD >> 24 ) & 0xff,
// {0,0,0,0, // period - off
DFLT_DIVISOR, DFLT_STALL, 0,0, // clock divisor
DFLT_RS232DIV & 0xff, ( DFLT_RS232DIV >> 8 ) & 0xff, ( DFLT_RS232DIV >> 16) & 0xff, ( DFLT_RS232DIV >> 24 ) & 0xff,
DFLT_CONFIG & 0xff, ( DFLT_CONFIG >> 8 ) & 0xff, ( DFLT_CONFIG >> 16) & 0xff, ( DFLT_CONFIG >> 24 ) & 0xff,
DFLT_SLEEP & 0xff, ( DFLT_SLEEP >> 8 ) & 0xff, ( DFLT_SLEEP >> 16) & 0xff, ( DFLT_SLEEP >> 24 ) & 0xff,
0x10, // x gyro low
0x12, // x gyro high
0x14, // y gyro low
0x16, // y gyro high
0x18, // z gyro low
0x1a, // z gyro high
0x1c, // x accel low
0x1e, // x accel high
0x20, // y accel low
0x22, // y accel high
0x24, // z accel low
0x26, // z accel high
0x40, // x delta angle low
0x42, // x delta angle high
0x44, // y delta angle low
0x46, // y delta angle high
0x48, // z delta angle low
0x4a, // z delta angle high
0x4c, // x delta velocity low
0x4e, // x delta velocity high
0x50, // y delta velocity low
0x52, // y delta velocity high
0x54, // z delta velocity low
0x56, // z delta velocity high
0x0e, // temperature
0x70, // time m/s
0x72, // time d/h
0x74,// time y/m
/// NMEA sentences
/// first three letters - sentence to log (letters after "$GP"). next "n"/"b" (up to 24 total) - "n" number (will be encoded 4 digits/byte, follwed by "0xF"
/// "b" - byte - all but last will have MSB 0 (& 0x7f), the last one - with MSB set (| 0x80). If there are no characters in the field 0xff will be output
'R','M','C','n','b','n','b','n','b','n','n','n','n','b', 0, 0, 0, 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
'G','G','A','n','n','b','n','b','n','n','n','n','b','n','b','b','b', 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
'G','S','A','b','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n','n', 0,0,0,0, 0,0,0,0, 0,0,0,0,
'V','T','G','n','b','n','b','n','b','n','b', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
// Message - up to 56 bytes
'O', 'd', 'o', 'm', 'e', 't', 'e', 'r', ' ', 'm', 'e', 's', 's', 'a', 'g', 'e',
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
};
static unsigned char wbuf[sizeof(dflt_wbuf)];
//static unsigned char brbuf[8192]; /// twice the FPGA FIFO size
//static unsigned long * rbuf= (unsigned long *) brbuf;
/*
#define IMU_MAJOR 141
#define IMU_MINOR 1
*/
static const char fpga_name[] = "imu_control";
static int imu_open (struct inode *inode, struct file *filp);
static int imu_release(struct inode *inode, struct file *filp);
//static int imu_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
static ssize_t imu_write (struct file * file, const char * buf, size_t count, loff_t *off);
static loff_t imu_lseek (struct file * file, loff_t offset, int orig);
static ssize_t imu_read (struct file * file, char * buf, size_t count, loff_t *off);
//static loff_t fpga_lseek(struct file * file, loff_t offset, int orig);
//static ssize_t fpga_read(struct file * file, char * buf, size_t count, loff_t *off);
//static int __init fpga_init(void);
#define IMU_MAXMINOR 10
//static int minors[IMU_MAXMINOR+1]; // each minor can be opened only once
//static int num_reads; // number of fifo reads (does not advance file position)
//static int numRecordsRead=0; // number of 64-byte log records read (24 bit, same format as FPGA write counter)
static loff_t numBytesRead=0; // totalnumber of bytes read from the imu - global pointer (modified when open in write mode)
static loff_t numBytesWritten=0; // totalnumber of bytes writtent to the IMU buffer since it was started/restarted
static int lastFPGABytes=0; // last read FPGA counter (24 bits) << 6
static unsigned long ccam_dma1_buf[CCAM_DMA1_SIZE + (PAGE_SIZE>>2)] __attribute__ ((aligned (PAGE_SIZE)));
//!Without "static" system hangs after "Uncompressing Linux...
unsigned long * ccam_dma1_buf_ptr = NULL;
//unsigned long * ccam_dma1 = NULL; //! still used in autoexposure or something - why is in needed there?
void init_ccam_dma1_buf_ptr(void) {
ccam_dma1_buf_ptr = ccam_dma1_buf;
// ccam_dma1 = ccam_dma1_buf; //&ccam_dma_buf[0]; Use in autoexposure
}
void updateNumBytesWritten(void){
int thisFPGABytes=(int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
int delta=(thisFPGABytes-lastFPGABytes);
lastFPGABytes=thisFPGABytes;
if (delta<0) delta+=(IMU_COUNT_OVERFLOW<<6);
numBytesWritten+=delta; // long long
}
static struct file_operations imu_fops = {
owner: THIS_MODULE,
open: imu_open,
release: imu_release,
// ioctl: umu_ioctl,
llseek: imu_lseek,
read: imu_read,
write: imu_write
};
static void set_logger_params(int which){ // 1 - program IOPINS, 2 - reset first, 4 - set divisor, 8 set regs, 16 - set period
// IMU should be enable through i2c before opening
D(int i2c_err=0;)
int i,j,b,f,n;
int nmea_sel[16];
int nmea_fpga_frmt[16];
unsigned long d;
unsigned long * period= (unsigned long *) &wbuf[X313_IMU_PERIOD_OFFS];
unsigned long * divisor= (unsigned long *) &wbuf[X313_IMU_DIVISOR_OFFS];
unsigned long * rs232_div= (unsigned long *) &wbuf[X313_IMU_RS232DIV_OFFS];
unsigned long * config= (unsigned long *) &wbuf[X313_IMU_CONFIGURE_OFFS];
unsigned long * message= (unsigned long *) &wbuf[X313_IMU_MESSAGE_OFFS];
char * nmea_format= (char *) &wbuf[X313_IMU_NMEA_FORMAT_OFFS];
D(for (i=0; i< sizeof (wbuf); i++ ) { if ((i & 0x1f)==0) printk("\n %03x",i); printk(" %02x",(int) wbuf[i]); });
/*
if (which & WHICH_INIT) {
D(printk("Enabling I/O pins for IMU, written 0x%x to 0x%x\n", (int) X313_WA_IOPINS_EN_IMU, (int) X313_WA_IOPINS));
port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_EN_IMU;
///TODO: add enabling via i2c (bus=1&raw=0x2300&data=0xfe)
}
*/
if (which & WHICH_RESET) {
if (x313_is_dma1_on()!=0) {
D(printk("Stopping DMA\n"));
x313_dma1_stop();
}
D(printk("Resetting logger\n"));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_CONFIGURE_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = IMU_CONF(RST_CONF,1);
}
if (which & WHICH_INIT) {
D(printk("Enabling I/O pins for IMU, written 0x%x to 0x%x\n", (int) X313_WA_IOPINS_EN_IMU, (int) X313_WA_IOPINS));
port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_EN_IMU;
///TODO: add enabling via i2c (bus=1&raw=0x2300&data=0xfe)
//PCA9500_PP_ADDR
unsigned char i2c_sa= PCA9500_PP_ADDR+((config[0]>>23) & 0xe);
unsigned char enable_IMU=0xfe; // maybe we need to reset it here? bit [1]
#if IS_103695_REV_A
enable_IMU=(((config[0]>>23) & 1)?0xfd:0xff); // bit[0] - reset IMU
#else
enable_IMU=0xfe; // maybe we need to reset it here? bit [1]
#endif
i2c_writeData(1, // int n - bus (0 - to the sensor)
i2c_sa, // unsigned char theSlave,
&enable_IMU, //unsigned char *theData,
1, // int size,
1); // int stop (send stop in the end)
D(printk("Sent i2c command in raw mode - address=0x%x, data=0x%x, result=0x%x\n",(int)i2c_sa, (int) enable_IMU, i2c_err));
}
if (which & WHICH_RESET_SPI) {
D(printk("stopped IMU logger (set period=0)\n"));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_PERIOD_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = 0; // reset IMU
}
if (which & WHICH_DIVISOR) {
D(printk("IMU clock divisor= %ld\n", divisor[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_DIVISOR_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = divisor[0]-1;
}
if (which & WHICH_RS232DIV) {
D(printk("RS232 clock divisor= %ld\n", rs232_div[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_RS232DIV_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = rs232_div[0]-1;
}
if (which & WHICH_NMEA) {
for (i=0;i<16;i++) {
nmea_sel[i]=0;
nmea_fpga_frmt[i]=0;
}
for (n=0;n<4;n++) {
nmea_format[32*n+27]=0; // just in case
D(printk("Setting NMEA sentence format for $GP%s\n", &nmea_format[32*n]));
D(printk("(0x%x, 0x%x, 0x%x\n",(int) nmea_format[32*n],(int) nmea_format[32*n+1],(int) nmea_format[32*n+2]));
f=0;
for (i=2;i>=0;i--) {
b=nmea_format[32*n+i]; /// first 3 letters in each sentence
D(printk("n=%d, i=%d, b=0x%x\n", n,i,b));
for (j=4; j>=0; j--) {
f<<=1;
if ((b & (1<<j))!=0) f++;
}
}
D(printk("n=%d, f=0x%x\n", n,f));
for (i=0;i<15;i++) if ((f & (1<<i))!=0) nmea_sel[i] |= (1<<n);
f=0;
nmea_fpga_frmt[n*4]=0;
for (i=0; (i<24) && (nmea_format[32*n+3+i]!=0);i++ ) {
b=nmea_format[32*n+3+i];
if ((b=='b') || (b=='B')) f|=(1<<i);
nmea_fpga_frmt[n*4]++;
}
nmea_fpga_frmt[n*4+1]=f & 0xff;
nmea_fpga_frmt[n*4+2]=(f>> 8)&0xff;
nmea_fpga_frmt[n*4+3]=(f>>16)&0xff;
}
D(printk("Selection data is %x%x%x%x%x%x%x%x%x%x%x%x%x%x%x\n", nmea_sel[0],nmea_sel[1],nmea_sel[2],
nmea_sel[3],nmea_sel[4],nmea_sel[5],nmea_sel[6],nmea_sel[7],nmea_sel[8],nmea_sel[9],
nmea_sel[10],nmea_sel[11],nmea_sel[12],nmea_sel[13],nmea_sel[14]));
D(printk("Format data for sentence 1 is %02x %02x %02x %02x\n", nmea_fpga_frmt[ 0],nmea_fpga_frmt[ 1],nmea_fpga_frmt[ 2],nmea_fpga_frmt[ 3]));
D(printk("Format data for sentence 2 is %02x %02x %02x %02x\n", nmea_fpga_frmt[ 4],nmea_fpga_frmt[ 5],nmea_fpga_frmt[ 6],nmea_fpga_frmt[ 7]));
D(printk("Format data for sentence 3 is %02x %02x %02x %02x\n", nmea_fpga_frmt[ 8],nmea_fpga_frmt[ 9],nmea_fpga_frmt[10],nmea_fpga_frmt[11]));
D(printk("Format data for sentence 4 is %02x %02x %02x %02x\n", nmea_fpga_frmt[12],nmea_fpga_frmt[13],nmea_fpga_frmt[14],nmea_fpga_frmt[15]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_NMEA_FORMAT_ADDR;
for (i=0;i<16;i++) {
port_csp0_addr[X313_WA_IMU_DATA] = nmea_sel[i];
D(printk("Loading imu fpga register 0x%x with 0x%x\n", X313_IMU_NMEA_FORMAT_ADDR+i, nmea_sel[i] ));
}
for (i=0;i<16;i++) {
port_csp0_addr[X313_WA_IMU_DATA] = nmea_fpga_frmt[i];
D(printk("Loading imu fpga register 0x%x with 0x%x\n", X313_IMU_NMEA_FORMAT_ADDR+i+16, nmea_fpga_frmt[i] ));
}
}
if (which & WHICH_CONFIG) {
D(printk("Setting configuration= 0x%lx\n", config[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_CONFIGURE_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] =(config[0] & 0xffffff); // MSB used for the i2c slave addr of the 10365
}
if (which & WHICH_REGISTERS) {
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_REGISTERS_ADDR;
for (i=X313_IMU_REGISTERS_OFFS; i< X313_IMU_NMEA_FORMAT_OFFS ;i++) {
d=wbuf[i];
D(printk("%d: logging IMU register with 0x%lx\n", (i-X313_IMU_REGISTERS_OFFS+1),d));
port_csp0_addr[X313_WA_IMU_DATA] = d;
}
}
if (which & WHICH_MESSAGE) {
D(printk("Setting odometer message %56s\n", (char *) message));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_MESSAGE_ADDR;
for (i=0; i<(((sizeof(wbuf)-X313_IMU_MESSAGE_OFFS))>>2);i++) {
D(printk("%d: message 4 bytes= 0x%x\n", i+1,(int) message[i]));
port_csp0_addr[X313_WA_IMU_DATA] = message[i];
}
}
// setting IMU SPI period, turning it on
if (which & WHICH_PERIOD) {
D(printk("IMU cycle period= %ld\n", period[0]));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_PERIOD_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = period[0];
}
if (which & WHICH_EN_DMA) {
D(printk("Enabling DMA\n"));
/*!
TODO: (re)start DMA1 here !
*/
/// for now - init everything again?
if (x313_is_dma1_on()!=0) {
D(printk("Stopping DMA\n"));
x313_dma1_stop();
}
x313_dma1_init();
x313_dma1_start();
}
if (which & WHICH_EN_LOGGER) {
D(printk("Enabling logger\n"));
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_CONFIGURE_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = IMU_CONF(RST_CONF,0);
}
}
//filp->f_mode & FMODE_WRITE
static int imu_open(struct inode *inode, struct file *filp) {
int p= MINOR(inode->i_rdev);
// int res;
int i;
// loff_t numBytesWritten;
D(printk("imu_open: minor=%x\r\n",p) );
D(printk("filp=%lx\r\n",(unsigned long)filp) );
switch ( p ) {
case IMU_CTL_MINOR:
D1(printk(KERN_NOTICE "IMU_ctl_open\n"));
inode->i_size=sizeof(wbuf);
// nothing more here, after writeing parameters should start imu (and dma), otherwise will use defaults on next open of /dev/imu
break;
case IMU_MINOR :
{
D1(printk(KERN_NOTICE "IMU_open\n"));
inode->i_size=sizeof(wbuf); // only in write mode
/// See if initialization is needed
if (x313_is_dma1_on()==0) {
/// copy defaults
D1(printk(KERN_NOTICE "Initializing IMU\n"));
for (i=0;i<sizeof(wbuf);i++) wbuf[i]=dflt_wbuf[i];
set_logger_params(WHICH_INIT |
WHICH_RESET |
WHICH_RESET_SPI |
WHICH_DIVISOR |
WHICH_RS232DIV |
WHICH_NMEA |
WHICH_CONFIG |
WHICH_REGISTERS |
WHICH_MESSAGE |
WHICH_PERIOD |
WHICH_EN_DMA |
WHICH_EN_LOGGER );
numBytesRead=0;
} else {
D1(printk(KERN_NOTICE "Skipping IMU initialization\n"));
updateNumBytesWritten();
// numBytesWritten= (int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
if (filp->f_mode & FMODE_WRITE) { // write mode, use global read pointer
// if ((numBytesWritten < numBytesRead) || (numBytesWritten - numBytesRead)>=(CCAM_DMA1_SIZE<<2)) {
if ((numBytesWritten - numBytesRead)>=(CCAM_DMA1_SIZE<<2)) { // there is still a chance to read as much as possible using lseek
// alternatively - open at lower pointer?
D1(printk(KERN_ERR "DMA1 buffer overrun (numBytesWritten=0x%llx, numBytesRead=0x%llx, resetting numBytesRead\n", numBytesWritten, numBytesRead));
numBytesRead=numBytesWritten;
}
//printk("imu opened in R/W mode, (numBytesWritten=0x%x, numBytesRead=0x%x\n", numBytesWritten, numBytesRead);
} else { // read mode, use file pointer as read pointer, start from the latest data
filp->f_pos=numBytesWritten; // there is still a chance to lseek to an earlier position - reopening at the position of the total number of bytes written to the buffer
//printk("imu opened in RDONLY mode, (numBytesWritten=0x%x, numBytesRead=0x%x\n", numBytesWritten, numBytesRead);
}
}
break;
}
default: return -EINVAL;
}
// minors[p]=p;
// filp->private_data = &minors[p];
filp->private_data = (int *) p; // store just minor there
return 0;
}
static int imu_release(struct inode *inode, struct file *filp) {
// int res=0;
int p = MINOR(inode->i_rdev);
switch ( p ) {
case IMU_MINOR :
case IMU_CTL_MINOR:
printk(KERN_NOTICE "Closing IMU device, numBytesWritten=0x%llx, numBytesRead=0x%llx (only global pointer, does not include files opened in read mode)\n", numBytesWritten, numBytesRead);
/*
port_csp0_addr[X313_WA_IMU_CTRL] = X313_IMU_PERIOD_ADDR;
port_csp0_addr[X313_WA_IMU_DATA] = 0; // reset IMU
port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_DIS_IMU;
*/
// minors[p]=0;
break;
default: return -EINVAL;
}
D(printk("imu_release: done\r\n"));
return 0;
}
/*
static int imu_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { // switch by minor
// int res=0;
D(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
switch (((int *)filp->private_data)[0]) {
case FPGACONF_MINOR_IORW : {// read write FPGA registers
D(printk("fpga_ioctl cmd= %x, arg= %x\n\r",cmd,(int) arg));
if(_IOC_TYPE(cmd) == FPGACONF_GETSTATE) {
return fpga_state;
}
return fpga_io_ioctl (inode, filp, cmd, arg);
}
default:return -EINVAL;
}
}
*/
static ssize_t imu_write(struct file * file, const char * buf, size_t count, loff_t *off) {
unsigned long p=*off;
unsigned long left;
int which=0;
// D(printk("imu_write: ((int *)file->private_data)[0]= %x\r\n",((int *)file->private_data)[0]));
D(printk("imu_write: (int)file->private_data)= %x\r\n",((int)file->private_data)));
// switch (((int *)file->private_data)[0]) {
switch ((int) file->private_data) {
case IMU_MINOR :
case IMU_CTL_MINOR:
if (!file->f_mode & FMODE_WRITE) {
return -EINVAL; // readonly
}
if (p >= sizeof(wbuf)) return -EINVAL; // bigger than all
if( (p + count) > sizeof(wbuf)) { // truncate count
count = sizeof(wbuf) - p;
}
left=count;
if (left==0) return 0;
if (copy_from_user(&wbuf[p], buf, count)) return -EFAULT;
if (p<(X313_IMU_PERIOD_OFFS+4)) which |= WHICH_PERIOD;
if ((p<(X313_IMU_DIVISOR_OFFS+4)) && ((p+count)>X313_IMU_DIVISOR_OFFS)) which |= WHICH_DIVISOR;
if ((p<(X313_IMU_RS232DIV_OFFS+4)) && ((p+count)>X313_IMU_RS232DIV_OFFS)) which |= WHICH_RS232DIV;
// if ((p<(X313_IMU_CONFIGURE_OFFS+4)) && ((p+count)>X313_IMU_CONFIGURE_OFFS)) which |= WHICH_CONFIG;
if ((p<(X313_IMU_CONFIGURE_OFFS+4)) && ((p+count)>X313_IMU_CONFIGURE_OFFS)) which |= WHICH_CONFIG | WHICH_INIT;
if ((p<(X313_IMU_NMEA_FORMAT_OFFS)) && ((p+count)>X313_IMU_REGISTERS_OFFS)) which |= WHICH_REGISTERS;
if ((p<(X313_IMU_MESSAGE_OFFS)) && ((p+count)>X313_IMU_NMEA_FORMAT_OFFS)) which |= WHICH_NMEA;
if ((p+count)>X313_IMU_MESSAGE_OFFS) which |= WHICH_MESSAGE;
// will not add automatic restarts here
set_logger_params(which);
// if (which & WHICH_PERIOD) num_reads=0;
*off+=count;
return count;
default: return -EINVAL;
}
}
static loff_t imu_lseek(struct file * file, loff_t offset, int orig) {
D(printk (" file=%x, offset=%llx (%d), orig=%x\r\n", (int) file, offset,(int) offset, (int) orig));
int p=(int)file->private_data;
switch (p) {
case IMU_MINOR:
case IMU_CTL_MINOR:
switch (orig) {
case SEEK_SET:
file->f_pos = offset;
break;
case SEEK_CUR:
file->f_pos += offset;
break;
case SEEK_END:
//!overload later?
if (offset<=0) {
file->f_pos = sizeof(wbuf) + offset;
} else {
switch (offset) {
case LSEEK_IMU_NEW: // sets file pointer to the last written data TODO: add lseeking to the earliest data?
updateNumBytesWritten();
// numBytesRead=(int) port_csp0_addr[X313_RA_IMU_COUNT]<<6; //numBytesWritten
return file->f_pos;
case LSEEK_IMU_STOP:
D(printk("got LSEEK_IMU_STOP\n"));
set_logger_params(WHICH_RESET |
WHICH_RESET_SPI);
numBytesRead=0;
return file->f_pos;
case LSEEK_IMU_START:
D(printk("got LSEEK_IMU_START\n"));
set_logger_params(WHICH_RESET |
WHICH_RESET_SPI |
WHICH_PERIOD |
WHICH_EN_DMA |
WHICH_EN_LOGGER );
return file->f_pos;
}
/// Add stuff later?
}
break;
default:
printk(KERN_ERR "lseek: invalid orig=%d\n", orig);
return -EINVAL;
}
break;
default:
printk(KERN_ERR "lseek: invalid minor=%d\n", p);
return -EINVAL;
/*
#define LSEEK_IMU_STOP 1 // stop DMA1 and IMU
#define LSEEK_IMU_START 2 // start IMU and DMA1 (do not modify parameters)
*/
}
/** truncate position */
if (file->f_pos < 0) {
printk(KERN_ERR "negative position: minor=%d, file->f_pos=0x%llx\n", p, file->f_pos);
file->f_pos = 0;
return (-EOVERFLOW);
}
/** enable seeking beyond buffer - it now is absolute position in the data stream*/
if ((p==IMU_CTL_MINOR) && (file->f_pos > sizeof(wbuf))) {
printk(KERN_ERR "beyond end: minor=%d, file->f_pos=0x%llx\n", p, file->f_pos);
file->f_pos = sizeof(wbuf);
return (-EOVERFLOW);
}
return (file->f_pos);
}
static ssize_t imu_read(struct file * file, char * buf, size_t count, loff_t *off) {
int err;
unsigned long * sleep;
char *charDMABuf;
int idbg;
// loff_t numBytesWritten; - it is global now, made absolute from the IMU start
loff_t thisNumBytesRead;
reg_dma_rw_stat stat;
reg_bif_dma_r_ch1_stat ch1_stat;
// REG_WR(bif_dma, regi_bif_dma, rw_ch1_addr, exdma_addr);
// switch (((int *)file->private_data)[0]) {
switch ((int)file->private_data) {
case IMU_CTL_MINOR:
// if (*off >= sizeof(wbuf)) return -EINVAL; // bigger than all
if (*off >= sizeof(wbuf)) return 0; // bigger than all
if( (*off + count) > sizeof(wbuf)) { // truncate count
count = sizeof(wbuf) - *off;
}
if (count==0) return 0;
err=copy_to_user(buf, &wbuf[*off], count);
if (err) {
printk(KERN_ERR "0. tried to copy 0x%x bytes to offset 0x%llx, result=0x%x\n", count, *off,err);
return -EFAULT;
}
*off+=count;
return count;
break;
case IMU_MINOR :
updateNumBytesWritten();
thisNumBytesRead=(file->f_mode & FMODE_WRITE)?numBytesRead:*off; // is that needed ("write mode") ?
charDMABuf = (char *) ccam_dma1_buf_ptr;
sleep= (unsigned long *) &wbuf[X313_IMU_SLEEP_OFFS];
// numBytesWritten= (int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
// if ( thisNumBytesRead > numBytesWritten) thisNumBytesRead-= (IMU_COUNT_OVERFLOW<<6); // may become negative here
/// should we wait for data?
idbg=0;
while ((sleep[0]!=0) && ((numBytesWritten-thisNumBytesRead)<= 64)) { /// last 32 bytes can get stuck in ETRAX dma channel
schedule_usleep(*sleep);
updateNumBytesWritten();
// numBytesWritten= (int) port_csp0_addr[X313_RA_IMU_COUNT]<<6;
// if ( thisNumBytesRead > numBytesWritten) thisNumBytesRead-= (IMU_COUNT_OVERFLOW<<6); // may become negative here
idbg++;
}
if (idbg>0) {
D(printk ("slept %d times (%d usec)\n", idbg, (int) (*sleep * idbg)));
}
//! now read what is available (and required), roll over the buffer (if needed), copy data and advance numReadBytes
int byteIndexRead=thisNumBytesRead & bytePtrMask;
int byteIndexValid=(numBytesWritten-64) & bytePtrMask; // one record less to mitigate data hidden in ETRAX dma buffer
if (byteIndexValid<byteIndexRead) byteIndexValid += (CCAM_DMA1_SIZE<<2);
if (count>(byteIndexValid-byteIndexRead)) count = (byteIndexValid-byteIndexRead);
int leftToRead=count;
int pe=byteIndexRead+leftToRead;
if (pe>(CCAM_DMA1_SIZE<<2)) pe=(CCAM_DMA1_SIZE<<2);
/// copy all (or first part)
err=copy_to_user(buf, &charDMABuf[byteIndexRead], (pe-byteIndexRead));
if (err) {
printk(KERN_ERR "1. tried to copy 0x%x bytes to offset 0x%llx, result=0x%x\n", count, *off,err);
return -EFAULT;
}
// advance pointers
leftToRead -= (pe-byteIndexRead);
thisNumBytesRead+= (pe-byteIndexRead);
///Do we need to copy from the beginning of the buffer?
if (leftToRead>0) {
// err=copy_to_user(buf, &charDMABuf[0], leftToRead);
err=copy_to_user(&buf[pe-byteIndexRead], &charDMABuf[0], leftToRead);
byteIndexRead=0;
}
if (err) {
printk(KERN_ERR "2. tried to copy 0x%x bytes to offset 0x%llx, result=0x%x\n", count, *off,err);
return -EFAULT;
}
thisNumBytesRead+=leftToRead;
stat = REG_RD(dma, regi_dma7, rw_stat);
ch1_stat= REG_RD(bif_dma, regi_bif_dma, r_ch1_stat);
// reg_bif_dma_r_ch1_stat ch1_stat;
// REG_WR(bif_dma, regi_bif_dma, rw_ch1_addr, exdma_addr);
D(printk ("count=0x%x, thisNumBytesRead=0x%llx, numBytesWritten=0x%llx, stat.buf=0x%x, stat.mode=%x, ch1.run=%x ch1.cnt=0x%x\n", (int) count, thisNumBytesRead, numBytesWritten, (int) stat.buf,(int) stat.mode, (int) ch1_stat.run, (int) ch1_stat.cnt ));
//printk(" file->f_mode & FMODE_WRITE=0x%d\n",file->f_mode & FMODE_WRITE);
if (file->f_mode & FMODE_WRITE) numBytesRead=thisNumBytesRead;
// else *off=thisNumBytesRead;
*off=thisNumBytesRead; // always update
if (count<0) {
printk(KERN_ERR "Count is negative ( 0x%x)\n", count);
}
return count;
default:
//printk(" Wrong minor=0x%x\n",((int *)file->private_data)[0]);
printk(KERN_ERR " Wrong minor=0x%x\n",(int)file->private_data);
return -EINVAL;
}
}
static int __init
imu_init(void)
{
// int i;
int res;
res = register_chrdev(IMU_MAJOR, IMU_DRIVER_NAME, &imu_fops);
if(res < 0) {
printk(KERN_ERR "\nimu_init: couldn't get a major number %d.\n ",IMU_MAJOR);
return res;
}
printk(IMU_DRIVER_NAME"- %d\n",IMU_MAJOR);
// for (i=0;i<=IMU_MAXMINOR;i++) minors[i]=0;
init_ccam_dma1_buf_ptr();
return 0;
}
///TODO: it seems we could use a single data descriptor (in LX data segment was limited to 16KB), but let's have minimal changes
//#define DMA_CHUNK 0x4000 // 32-bit words - may increase??
//#define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE / DMA_CHUNK) +1 ) // number of data descriptors
#define CCAM_DESCR1_DATA_NUM (( CCAM_DMA1_SIZE / DMA_CHUNK) +1 ) // number of data descriptors
static dma_descr_data ccam_dma1_descr_data [CCAM_DESCR1_DATA_NUM] __attribute__ ((__aligned__(16)));
static dma_descr_context ccam_dma1_descr_context __attribute__ ((__aligned__(32)));
static int dma1_on=0;
int x313_setDMA1Buffer(void);
unsigned long x313_DMA1_size (void);
/**
* @brief tests if ETRAX DMA1 is running
* @return 1 - DMA is on, 0 - DMA is off
*/
int x313_is_dma1_on(void) {
return dma1_on;
}
/**
* @brief Stop ETRAX DMA1
* @return 0
*/
int x313_dma1_stop(void) {
dma1_on=0;
MD12(printk("==========x313_dma1_stop\n"));
port_csp0_addr[X313_WA_DMACR] = 0x20; // disable DMA1, dot't modify DMA0
EXT_DMA_1_STOP ; /// for testing - no reset DMA after acquisition
udelay(10) ; //?
DMA_RESET( regi_dma7 );
// put here restoring of the .after pointer ?
return 0;
}
/**
* @brief Start ETRAX DMA for the IMU
*/
void x313_dma1_start(void) {
unsigned long dai;
int i = 0;
MD12(printk("----------x313_dma1_start\n"));
DMA_RESET(regi_dma7);
/// need to restore pointers after previous stop DMA - maybe later move there?
for(dai = 0; dai < CCAM_DMA1_SIZE; dai += DMA_CHUNK) { /// DMA_CHUNK==0x4000
if(dai + DMA_CHUNK >= CCAM_DMA1_SIZE) /// last descriptor
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[CCAM_DMA1_SIZE]);
else /// not the last one
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[dai + DMA_CHUNK]);
//!TODO: does flush here IS IT STILL NEEDED HERE?
flush_dma_descr( & ccam_dma1_descr_data[i], 0);
i++;
}
DMA_ENABLE(regi_dma7);
port_csp0_addr[X313_WA_DMACR] = 0x20; // disable DMA1, don't modify DMA0
/// NOTE: needs to be here (not in x313_dma1_init) - word width is reset by channel reset !!!
DMA_WR_CMD(regi_dma7, regk_dma_set_w_size4); ///32-bit transfers
/// point to the beginning of the buffer?
ccam_dma1_descr_context.saved_data = (dma_descr_data*)virt_to_phys(&ccam_dma1_descr_data[0]);
ccam_dma1_descr_context.saved_data_buf = ccam_dma1_descr_data[0].buf;
//! need this also?
flush_dma_descr((dma_descr_data*) & ccam_dma1_descr_context, 0);
DMA_START_CONTEXT(regi_dma7, virt_to_phys(&ccam_dma1_descr_context));
EXT_DMA_1_START ;
port_csp0_addr[X313_WA_DMACR] = 0x28; // enable DMA1, don't modify DMA0
dma1_on=1;
}
/*
#define DMA_CHUNK 0x4000 // 32-bit words - may increase??
#define CCAM_DESCR_DATA_NUM (( CCAM_DMA_SIZE / DMA_CHUNK) +1 ) // number of data descriptors
#define CCAM_BYTES_PER_CHUNK (1<<16) // dma buffer bytes per descriptor
#define CCAM_DESCR_PER_CHUNK 1
#define CCAM_CHUNK_PER_DMABUF 302 // no. of 64Kbyte chunks per buffer
#define CCAM_WORDS_PER_DMABUF (CCAM_CHUNK_PER_DMABUF<<14) //32bit words
#define CCAM_BYTES_PER_DMABUF (CCAM_CHUNK_PER_DMABUF<<16)
#define CCAM_DMA_SIZE CCAM_WORDS_PER_DMABUF
#define CCAM_CHUNK_PER_DMA1BUF 16 // no. of 64Kbyte chunks per buffer
#define CCAM_WORDS_PER_DMA1BUF (CCAM_CHUNK_PER_DMA1BUF<<14) //32bit words
#define CCAM_BYTES_PER_DMA1BUF (CCAM_CHUNK_PER_DMA1BUF<<16)
#define CCAM_DMA1_SIZE CCAM_WORDS_PER_DMA1BUF
*/
///dma0 is using external dma 3 (input) with dma channel 9
///dma1 (this) is using external dma 1 (input) with dma channel 7 (shared with async. serial 0, so do not use DMA there!)
unsigned long x313_dma1_init(void) {
dma1_on=0;
int rslt;
reg_dma_rw_cfg cfg = {.en = regk_dma_yes}; // if disabled - will be busy and hang on attemt of DMA_WR_CMD
reg_bif_dma_rw_ch1_ctrl exdma_ctrl = {
.bw = regk_bif_dma_bw32,
.burst_len = regk_bif_dma_burst8, // changed - updated FPGA to use 8-word bursts
.cont = 1, // continuous transfer mode (probably - don't care)
.end_discard = 0, // discard end of burst date (don't care)
.cnt = 0, // transfer counter ignored
.dreq_pin = 2, // use hsh2
.dreq_mode = regk_bif_dma_norm, // normal - active high DREQ from pin (see above)
.tc_in_pin = 0, // don't care - tc pin number
.tc_in_mode = 0, // no tc pin
.bus_mode = regk_bif_dma_master, // bus mode - master
.rate_en = 0 // no rate limiting
};
reg_bif_dma_rw_ch1_addr exdma_addr = {.addr = ( MEM_CSR0_START + 4 ) | MEM_NON_CACHEABLE}; // fpga register 1
reg_bif_dma_rw_pin2_cfg exdma_pin2 = {
.master_ch = 0, // don't care
.master_mode = regk_bif_dma_off, // off
.slave_ch = 0, // don't care
.slave_mode = regk_bif_dma_off // off
};
reg_bif_dma_rw_pin3_cfg exdma_pin3 = {
.master_ch = 1, // ext DMA channel #
.master_mode = regk_bif_dma_dack, // use DACK, active high
.slave_ch = 1, // don't care
.slave_mode = regk_bif_dma_off // off
};
// just in case - free DMA channel (we are only using it here)
crisv32_free_dma(EXTDMA1_RX_DMA_NBR);
printk("Initializing DMA registers for EXTDMA1\n");
MD7(printk("x313_dma1_init(void)"));
D0(printk ("before crisv32_request_dma\n"); udelay (500000));
rslt = crisv32_request_dma(EXTDMA1_RX_DMA_NBR,
"imu data in from fpga",
DMA_VERBOSE_ON_ERROR,
0,
dma_ext1);
D0(printk ("after crisv32_request_dma - result=%d\n",rslt); udelay(500000));
if(rslt) {
printk("failed\n");
crisv32_free_dma(EXTDMA1_RX_DMA_NBR);
printk(KERN_CRIT "Can't allocate external dma port for compressed data in from fpga");
} else { /// dma channel 7 allocated for ext dma 1
/// setup source of hsh2, hsh3
REG_WR(bif_dma, regi_bif_dma, rw_pin2_cfg, exdma_pin2); /// just in case - turn hsh2 off
REG_WR(bif_dma, regi_bif_dma, rw_pin3_cfg, exdma_pin3); /// make hsh3 DACK
/// Configure ext DMA 3
REG_WR(bif_dma, regi_bif_dma, rw_ch1_ctrl, exdma_ctrl);
REG_WR(bif_dma, regi_bif_dma, rw_ch1_addr, exdma_addr);
REG_WR(dma, regi_dma7, rw_cfg, cfg); /// DMA configuration (bit 0 - enable, bit 1 - stop) - stopped
}
/// DMABufferLength = 0;
x313_setDMA1Buffer();
return ((unsigned long)virt_to_phys(ccam_dma1_buf_ptr)) | 0x80000000;
}
int x313_setDMA1Buffer(void) {
unsigned long dai;
int i = 0;
EXT_DMA_1_STOP; /// Stop DMA1 (just in case)
for(dai = 0; dai < CCAM_DMA1_SIZE; dai += DMA_CHUNK) { /// DMA_CHUNK==0x4000
ccam_dma1_descr_data[i].buf = (char *)virt_to_phys(&ccam_dma1_buf_ptr[dai]);
ccam_dma1_descr_data[i].intr = 0;
ccam_dma1_descr_data[i].wait = 0;
ccam_dma1_descr_data[i].eol = 0; /// we probably do not need to use eol as the descriptors are linked in a loop anyway
if(dai + DMA_CHUNK >= CCAM_DMA1_SIZE) { ///last descriptor
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[CCAM_DMA1_SIZE]);
ccam_dma1_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma1_descr_data[0]);
} else { /// not the last one
ccam_dma1_descr_data[i].after = (char *)virt_to_phys(&ccam_dma1_buf_ptr[dai + DMA_CHUNK]);
ccam_dma1_descr_data[i].next = (dma_descr_data*)virt_to_phys(&ccam_dma1_descr_data[i + 1]);
}
flush_dma_descr( & ccam_dma1_descr_data[i], 0);
i++;
}
// TODO: make new global parameter?
// set_globalParam (G_CIRCBUFSIZE,CCAM_DMA_SIZE<<2); /// make it adjustable? TODO: initialize with others?
//*********************** TEMPORARY ********************************
MD8(printk ("filling DMA1 buffer with natural numbers - just test \n"));
for(dai = 0; dai < CCAM_DMA1_SIZE; dai++) ccam_dma1_buf_ptr[dai] = dai;
return 0;
}
module_init(imu_init);
MODULE_LICENSE("GPLv3");
MODULE_AUTHOR("Andrey Filippov <andrey@elphel.com>.");
MODULE_DESCRIPTION(IMU_MODULE_DESCRIPTION);
void x313_dma1_start(void);
int x313_dma1_stop(void);
int x313_is_dma1_on(void);
unsigned long x313_dma1_init(void);
......@@ -72,12 +72,12 @@
#define CONFIG_ETRAX_ELPHEL_MT9X001 1
void x313_dma_stop() {}
void x313_dma_init() {}
void reset_compressor() {}
void i2c_run(void) {}
void i2c_stop_wait(void){}
//pgm_functions:pgm_detect_sensor
// void x313_dma_stop() {}
// void x313_dma_init() {}
// void reset_compressor() {} // available in sensor_common (make sure it does it all
void i2c_run(void);
void i2c_stop_wait(void);
// if ((gtable= get_gamma_fpga(color))) fpga_table_write_nice (CX313_FPGA_TABLES_GAMMA + (color * 256), 256, gtable);
......
......@@ -682,12 +682,12 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
///< @return 0 - OK, negative - error
{
unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
// unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
// unsigned char i2c_read_data[2]; // each two bytes - one short word, big endian
u32 i2c_read_dataw;
u8 * i2c_read_data = (u8*)& i2c_read_dataw; // each two bytes - one short word, big endian
// u8 * i2c_read_data = (u8*)& i2c_read_dataw; // each two bytes - one short word, big endian
// unsigned char chipver_reg=P_MT9X001_CHIPVER;
u32 chipver_reg=P_MT9X001_CHIPVER;
// u32 chipver_reg=P_MT9X001_CHIPVER;
int sensor_subtype=0;
int i;
struct sensor_t * psensor; // current sensor
......@@ -753,15 +753,15 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
#else
X3X3_I2C_RCV2(sensor_port, psensor->i2c_addr, P_MT9X001_CHIPVER, &i2c_read_dataw);
if (((i2c_read_dataw ^MT9M001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9M001 1280x1024 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
printk("Found MT9M001 1280x1024 sensor, chip ID=%x\r\n",i2c_read_dataw);
psensor= &mt9m001;
sensor_subtype=MT9M_TYP; //1;
} else if (((i2c_read_dataw ^ MT9D001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9D001 1600x1200 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
printk("Found MT9D001 1600x1200 sensor, chip ID=%x\r\n",i2c_read_dataw);
psensor= &mt9d001;
sensor_subtype=MT9D_TYP; //2;
} else if (((i2c_read_dataw ^ MT9T001_PARTID) & MT9X001_PARTIDMASK)==0) {
printk("Found MT9T001 2048x1536 sensor, chip ID=%x\r\n",I2C_READ_DATA16(0));
printk("Found MT9T001 2048x1536 sensor, chip ID=%x\r\n",i2c_read_dataw);
psensor= &mt9t001;
sensor_subtype=MT9T_TYP; //3;
// if(d[2] == 0x01) - MT9T001 chip rev 01 - color gains had a bug
......@@ -785,7 +785,7 @@ int mt9x001_pgm_detectsensor (int sensor_port, ///< sensor port
add_sensor_proc(onchange_triggermode, &mt9x001_pgm_triggermode); // program sensor trigger mode
add_sensor_proc(onchange_sensorregs, &mt9x001_pgm_sensorregs); // write sensor registers (only changed from outside the driver as they may have different latencies)?
// MDD1(printk("sensor->sensorType=0x%lx\n", sensor->sensorType));
setFramePar(thispars, P_SENSOR, sensor->sensorType); // was so
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType); // was so
// setFramePar(thispars, P_SENSOR | FRAMEPAIR_FORCE_NEWPROC, sensor->sensorType); // force actions
// MDD1(printk("\n"));
///TODO: Fill G_MULTI_REGSM+i - which registers need individual values in multi-sensor applications
......@@ -840,11 +840,13 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
// unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
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));
if (frame16 >= 0) return -1; // should be ASAP
// int fpga_addr=(frame8 <0) ? X313_I2C_ASAP : (X313_I2C_FRAME0+frame8);
unsigned long flags; // this function uses software i2c operations - they need to have interrupts (and hardware i2c off)
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
// unsigned char i2c_read_data[512]; // each two bytes - one short word, big endian
u32 i2c_read_data_dw[256];
int nupdate=0;
......@@ -857,7 +859,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
CCAM_MRST_OFF;
udelay (100);
printk("Reading sensor registers to the shadows:\r\n");
int first_sensor_i2c=sensor->i2c_addr;
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));
}
......@@ -895,9 +897,7 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
}
#endif
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
printk("Initializing MT9X001 registers with default values:\r\n");
unsigned short * sensor_register_overwrites;
int sensor_register_overwrites_number;
int sensor_subtype=sensor->sensorType - SENSOR_MT9X001;
switch (sensor_subtype) {
......@@ -933,7 +933,11 @@ int mt9x001_pgm_initsensor (int sensor_port, ///< sensor port
nupdate=0; // Second pass over the registers to set
//#define SET_SENSOR_MBPAR(p,f,s,r,v)
for (i=0; i<sensor_register_overwrites_number;i++ ) { // unconditionally set those registers NOTE: Should be < 63 of them!
SET_SENSOR_MBPAR(sensor_port,frame16,sensor->i2c_addr, sensor_register_overwrites[2*i], sensor_register_overwrites[2*i+1]);
SET_SENSOR_MBPAR(sensor_port,
frame16,
sensor->i2c_addr,
sensor_register_overwrites[2*i],\
sensor_register_overwrites[2*i+1]);
MDF4(printk(" SET_SENSOR_MBPAR(0x%x,0x%x,0x%x, 0x%x, 0x%x)\n", sensor_port, frame16, (int) sensor->i2c_addr, (int) sensor_register_overwrites[2*i], (int) sensor_register_overwrites[2*i+1]));
}
......@@ -979,7 +983,7 @@ int mt9x001_pgm_window_safe (int sensor_port, ///< sensor port num
///< @return 0 - OK, negative - error
{
MDF4(printk(" frame16=%d\n",frame16));
return mt9x001_pgm_window_common (sensor, thispars, prevpars, frame16);
return mt9x001_pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
/** PCommon part of programming sensor WOI */
......@@ -991,11 +995,11 @@ int mt9x001_pgm_window_common (int sensor_port, ///< sensor port
///< be applied to, negative - ASAP
///< @return 0 - OK, negative - error
{
int i,dv,dh,bv,bh,ww,wh,wl,wt,flip,flipX,flipY,d, v;
struct frameparspair_t pars_to_update[29];
int nupdate=0;
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int i,dv,dh,bv,bh,ww,wh,wl,wt,flip,flipX,flipY,d, v;
int styp = sensor->sensorType & 7;
dh= thispars->pars[P_DCM_HOR];
dv= thispars->pars[P_DCM_VERT];
......@@ -1143,8 +1147,6 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
{
struct frameparspair_t pars_to_update[16]; // maximum 7 registers updated (need to recount)
int nupdate=0;
MDF4(printk(" frame8=%d\n",frame8));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int dh= thispars->pars[P_DCM_HOR];
int ww= thispars->pars[P_SENSOR_PIXH] * dh;
int binning_cost = 0;
......@@ -1158,6 +1160,8 @@ 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));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
switch(styp) {
case MT9P_TYP: //page 16
width = 2 * ww / (2 * dh);
......@@ -1310,7 +1314,12 @@ int mt9x001_pgm_limitfps (int sensor_port, ///< sensor port numb
sclk=thispars->pars[P_CLK_SENSOR] ; ///pixel clock, in Hz
#if USELONGLONG
ull_fp1000s=((long long) 1000)* ((long long) sclk);
#ifdef __div64_32
__div64_32(&ull_fp1000s,pix_period);
#else
do_div(ull_fp1000s,pix_period);
// ull_fp1000s /= pix_period;
#endif
fp1000s= ull_fp1000s;
// fp1000s= ((long long) 1000)* ((long long)sclk) /pix_period;
#else
......@@ -1367,7 +1376,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
MDF1(printk(" exposure=%d (0x%x), video_exposure=%d (0x%x)\n", (int) thispars->pars[P_VEXPOS], (int) thispars->pars[P_VEXPOS], (int) video_exposure, (int) video_exposure));
#if USELONGLONG
ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) * ((long long) 1000000);
#ifdef __div64_32
__div64_32(&ull_exposure, sclk);
#else
do_div(ull_exposure, sclk);
// ull_exposure /= sclk;
#endif
exposure= ull_exposure;
#else
exposure = (100*video_exposure * row_time_in_pixels) / (sclk/10000); // in microseconds
......@@ -1377,8 +1391,15 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
exposure = thispars->pars[P_EXPOS];
#if USELONGLONG
ull_video_exposure= (long long) exposure * (long long) sclk;
#ifdef __div64_32
__div64_32(&ull_video_exposure, row_time_in_pixels);
__div64_32(&ull_video_exposure, 1000000);
#else
do_div(ull_video_exposure, row_time_in_pixels);
do_div(ull_video_exposure, 1000000);
// ull_video_exposure /= row_time_in_pixels;
// ull_video_exposure /= 1000000;
#endif
video_exposure= ull_video_exposure;
#else
///TODO - use shifts, not division where possible?
......@@ -1401,7 +1422,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
video_exposure=sensor->maxShutter;
#if USELONGLONG
ull_exposure= ((long long)(video_exposure * row_time_in_pixels)) *((long long) 1000000);
#ifdef __div64_32
__div64_32(&ull_exposure, sclk);
#else
do_div(ull_exposure, sclk);
// ull_exposure /= sclk;
#endif
exposure= ull_exposure;
#else
exposure = (100*video_exposure * row_time_in_pixels) / (sclk/10000); // in microseconds
......@@ -1415,7 +1441,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
video_exposure=thispars->pars[P_PERIOD_MAX]/row_time_in_pixels;
#if USELONGLONG
ull_exposure= (((long long) thispars->pars[P_PERIOD_MAX]) *((long long) 1000000));
#ifdef __div64_32
__div64_32(&ull_exposure, sclk);
#else
do_div(ull_exposure, sclk);
// ull_exposure /= sclk;
#endif
exposure= ull_exposure;
#else
exposure = (thispars->pars[P_PERIOD_MAX] * 100) / (sclk/10000); // in microseconds
......@@ -1431,7 +1462,12 @@ int mt9x001_pgm_exposure (int sensor_port, ///< sensor port
// schedule updating P_FP1000S if it changed
#if USELONGLONG
ull_fp1000s=((long long) 1000)* ((long long) sclk);
#ifdef __div64_32
__div64_32(&ull_fp1000s,pix_period);
#else
do_div(ull_fp1000s,pix_period);
// ull_fp1000s /= pix_period;
#endif
fp1000s= ull_fp1000s;
#else
fp1000s= 10*sclk/(pix_period/100);
......@@ -1517,14 +1553,19 @@ unsigned long gain_ajust_mt9x001(
MDF4(printk("*newRegGain=0x%lx\n",*newRegGain));
// now divide gains
ull_gain =((long long) gain) << 16;
#ifdef __div64_32
__div64_32(&ull_gain, gainTab[gainIndex]);
#else
do_div(ull_gain, gainTab[gainIndex]);
// ull_gain /= gainTab[gainIndex];
#endif
MDF4(printk("((unsigned long) ull_gain)=0x%lx\n",((unsigned long) ull_gain)));
return ((unsigned long) ull_gain) >> SHIFT_DGAIN;
}
/** Calculates hardware specific analog gains.
* Changed to rounding (was truncaiting)*/
* Changed to rounding (was truncating)*/
inline int gain_mt9x001(int g, ///< gain value (integer, 256 for unity gain)
int maxGain256) ///< maximal supported gain (integer, 256 for unity gain)
///< @return hardware gain value
......@@ -1567,7 +1608,12 @@ inline unsigned long getScale16 (unsigned long nominator, ///< 32-bit nominato
unsigned long * l_result= (unsigned long *) &ull_result;
#endif
MDF4(printk("l_result[1]=0x%lx, l_result[0]=0x%lx\n",l_result[1],l_result[0]));
#ifdef __div64_32
__div64_32(&ull_result, denominator);
#else
do_div(ull_result, denominator);
// ull_result /= denominator;
#endif
MDF4(printk("l_result[1]=0x%lx, l_result[0]=0x%lx\n",l_result[1],l_result[0]));
return (unsigned long) ull_result;
}
......@@ -1594,8 +1640,6 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
{
struct frameparspair_t pars_to_update[38]; // 22+12 needed
int nupdate=0;
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
unsigned long newRegGain,digitalGain, testmode;
unsigned long anaGainEn= (thispars->pars[P_GAIN_CTRL]>> GAIN_BIT_ENABLE) & 1;
unsigned long minAnaGain=thispars->pars[P_GAIN_MIN];
......@@ -1603,6 +1647,8 @@ int mt9x001_pgm_gains (int sensor_port, ///< sensor port numb
unsigned long maxGain;
int limitsModified=0;
int gaingModified=FRAMEPAR_MODIFIED(P_GAING);
MDF4(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
///make sure limits are OK
if (FRAMEPAR_MODIFIED(P_GAIN_MIN)) {
limitsModified=1;
......
......@@ -99,7 +99,8 @@
#include <asm/irq.h>
#include <asm/delay.h>
//#include <asm/delay.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <elphel/c313a.h>
......@@ -116,6 +117,7 @@
//#include "x3x3.h" // hardware definitions
#include "legacy_defines.h" // temporarily
#include "sensor_i2c.h"
#include "clock10359.h"
/**
* \def D(x) optional debug output
......@@ -226,12 +228,12 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
{rslt |= multisensor_write_i2c((port),(name),(offs),(ra),(v)) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x, 0x%x) -> %d\n",(int)(port),name,int(offs),(int)(ra),(int)(v),rslt));}
#define MULTISENSOR_WRITE_I2C16(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),(ra),(v)) ; \
{rslt |= multisensor_write_i2c((port),(name_10359),0,(ra),(v)) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",(int)(port),name_10359,(int)(ra),(int)(v),rslt));}
#define MULTISENSOR_WRITE_I2C32(port,ra,v) \
{rslt |= multisensor_write_i2c((port),(name_10359),(I2C359_MSW),(v)>>16) ; \
{rslt |= multisensor_write_i2c((port),(name_10359),0,(I2C359_MSW),(v)>>16) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",(int)(port),name_10359,I2C359_MSW,(int)(v)>>16,rslt)); \
rslt |= multisensor_write_i2c((I2C359_SLAVEADDR),(ra),(v) & 0xffff,2) ; \
rslt |= multisensor_write_i2c((port),(name_10359),0,(ra), (v) & 0xffff) ; \
MDF1(printk(" multisensor_write_i2c(%d, %s, 0x%x, 0x%x) -> %d\n",(int)(port),name_10359,(int)(ra),(int)(v)&0xffff,2,rslt)); \
}
#endif
......@@ -306,9 +308,9 @@ int setup_i2c_pages(int ports) ///< bitmask of the sensor ports to use
//int multisensor_read_i2c(unsigned char theSlave, unsigned char theRegister, unsigned long *theData, int size);
int multisensor_read_i2c(int sensor_port, const char * class_name, int sa7_offs, u32 reg_addr, u32 * reg_datap);
int multisensor_read_i2c (int sensor_port, const char * class_name, int sa7_offs, u32 reg_addr, u32 * reg_datap);
//int multisensor_write_i2c(unsigned char theSlave, unsigned char theRegister, unsigned long theData, int size);
int multisensor_write_i2c(int sensor_port, const char * class_name,int sa7_offs, u32 reg_addr, u32 reg_data);
int multisensor_write_i2c (int sensor_port, const char * class_name,int sa7_offs, u32 reg_addr, u32 reg_data);
int multisensor_pgm_multisens (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int multisensor_pgm_sensorphase (int sensor_port, struct sensor_t * sensor, struct framepars_t * thispars, struct framepars_t * prevpars, int frame16);
int multisensor_set_freq (int sensor_port, int first, struct framepars_t * thispars);
......@@ -960,37 +962,43 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
if ((((bitstream_version ^ I2C359_MINVERSION) & 0xffff0000)!=0) || ((bitstream_version & 0xffff) < (I2C359_MINVERSION & 0xffff))) {
printk ("invalid 10359 bitstream version, found 0x%08lx, required >= 0x%08x\n",bitstream_version, I2C359_MINVERSION );
setFramePar(thispars, P_SENSOR, sensor->sensorType);
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
return -1;
}
printk("10359 bitstream version =0x%08lx\n",bitstream_version);
// now set sensor clock in both system board and 10359A to 96MHz - currently we support only 5MPix in thias mode
setFramePar(thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(thispars, P_CLK_SENSOR, 96000000);
setClockFreq(1, thispars->pars[P_CLK_SENSOR]);
#ifdef NC353
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, 96000000);
setClockFreq(sensor_port, 1, thispars->pars[P_CLK_SENSOR]);
#endif
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
// 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);
multisensor_initSDRAM(thispars); // init 10359 SDRAM
multisensor_initSDRAM(sensor_port, thispars); // init 10359 SDRAM
rslt=0;
// TODO: read other?
// MULTISENSOR_WRITE_I2C16_SHADOW(I2C359_I2CMUX, I2C359_I2CMUX_2MEM);
//TODO: Is it needed for NC393?
#ifdef NC353
if (rslt!=0) { // select memory/clock i2c bus
printk ("10359A did not respond after changing 10353 sensor clock frequency to 96MHz\n");
setFramePar(thispars, P_CLK_SENSOR, 20000000);
setFramePar(sensor_port, thispars, P_CLK_SENSOR, 20000000);
setClockFreq(1, thispars->pars[P_CLK_SENSOR]);
printk("10353 sensor clock set to %d\n",(int) thispars->pars[P_CLK_SENSOR]);
udelay (50000);// 0.05 sec to stabilize clocks
setFramePar(thispars, P_SENSOR, sensor->sensorType);
mdelay (50);// 0.05 sec to stabilize clocks
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return -1;
}
rslt=multisensor_set_freq (1, thispars); // first time (1)
#endif
rslt=multisensor_set_freq (sensor_port, 1, thispars); // first time (1)
if (rslt>0) printk("10359A sensor clock set to %d\n", rslt);
else if (rslt==0) printk("10359A sensors are using 10353 system clock, as set in configuration\n");
else printk("10359 sensor clock failure, will use system clock from 10353 board\n");
......@@ -1031,21 +1039,21 @@ int multisensor_pgm_detectsensor (int sensor_port, ///< sensor p
GLOBALPARS(sensor_port,G_SENS_AVAIL) &= (1<< (GLOBALPARS(sensor_port,G_SENS_AVAIL)))-1; // remove flag used to indicate sensor detection functions that they need to initialize multisesnor registers
if (GLOBALPARS(sensor_port,G_SENS_AVAIL)==0) {
printk ("No supported sensors connected to 10359A board\n");
setFramePar(thispars, P_SENSOR, sensor->sensorType);
setFramePar(sensor_port, thispars, P_SENSOR, sensor->sensorType);
if (nupdate) setFramePars(sensor_port,thispars, nupdate, pars_to_update); // save changes to sensor register shadows
return 0;
}
printk ("Setting internal HACT generation\n");
MULTISENSOR_WRITE_I2C16_SHADOW(sensor_port, I2C359_HACT_MODE, 7);
// At least one MT9P0X1 sensor found, initializing them in broadcast mode (will still need to modify phases - both 10353 and 10359
this_sensor_type=mt9x001_pgm_detectsensor(sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
this_sensor_type=mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
// for (i=0;i<8;i++) {
// MDF(printk("i=%d, m=0x%lx\n",i,GLOBALPARS(G_MULTI_REGSM+i)));
// }
initMultiPars(); // this time the registors that need to have individual shadows are known, initialize the corresponding data structures
initMultiPars(sensor_port); // this time the registors that need to have individual shadows are known, initialize the corresponding data structures
// memcpy(psensor, sensor, sizeof(struct sensor_t)); // copy physical sensor definitions to the save area (so some can be replaced by modified ones)
// MDF24(printk(" before: sensorproc_phys->sensor.sensorDelay=0x%x\n", sensorproc_phys->sensor.sensorDelay));
copy_sensorproc(sensorproc_phys); // save physical sensor functions
copy_sensorproc(sensor_port, sensorproc_phys); // save physical sensor functions
// MDF24(printk(" after: sensorproc_phys->sensor.sensorDelay=0x%x\n", sensorproc_phys->sensor.sensorDelay));
// Now calculate phases, swap ones from the sensor
......@@ -1397,16 +1405,19 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
int thisPhase1= thispars->pars[P_MULTI_PHASE1];
int thisPhase2= thispars->pars[P_MULTI_PHASE2];
int thisPhase3= thispars->pars[P_MULTI_PHASE3];
uint64_t ull_result = 1000000000000LL;
if (frame16 >= 0) return -1; // can only work in ASAP mode
//changed (just set) clock frequency initiates calculation of phase settings
if (!multi_phases_initialized || (thispars->pars[P_CLK_SENSOR] != prevpars->pars[P_CLK_SENSOR])) { // system clock is already set to the new frequency
if (thispars->pars[P_CLK_SENSOR] == prevpars->pars[P_CLK_SENSOR]) {
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__); printk ("WARNING: ((thispars->pars[P_CLK_SENSOR] == prevpars->pars[P_CLK_SENSOR])) but multi_phases_initialized is not yet set (re-init?)\n");
}
multisensor_set_freq (0, thispars); // not the first time. Assuming no clock chip if clock4 is not set
multisensor_set_freq (sensor_port, 0, thispars); // not the first time. Assuming no clock chip if clock4 is not set
reset=1;
// TODO: put here calculation of the sensor phases in 10359 from bitstream data and clock rate
clk_period= 1000000000000.0/thispars->pars[P_CLK_SENSOR]; // period in ps
// clk_period= 1000000000000.0f/thispars->pars[P_CLK_SENSOR]; // period in ps
do_div(ull_result,thispars->pars[P_CLK_SENSOR]);
clk_period= ull_result;
// Now for each of 3 sensor ports of the 10359
cableDelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_C1);
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_DLY359_P1);
......@@ -1431,7 +1442,7 @@ int multisensor_pgm_sensorphase(int sensor_port, ///< sensor port
if (reset) {
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);
multisensor_initSDRAM(thispars); // init 10359 SDRAM
multisensor_initSDRAM(sensor_port, thispars); // init 10359 SDRAM
}
if ((thisPhaseSDRAM != prevpars->pars[P_MULTI_PHASE_SDRAM]) || adjustSDRAMNeed) {
if (adjustSDRAMNeed || (thisPhaseSDRAM & 0x200000)) { // at boot, after frequency change or manually requested (0x200000)
......@@ -1508,15 +1519,15 @@ int multisensor_set_freq (int sensor_port, ///< sensor port numb
int was_sensor_freq=0;
if (!(GLOBALPARS(sensor_port, G_MULTI_CFG) && (1<<G_MULTI_CFG_SYSCLK))) { // skip local clock if disabled in configuration
// was_sensor_freq=getClockFreq(I2C359_CLK_NUMBER);
was_sensor_freq=x393_getClockFreq(I2C359_CLK_NUMBER & 3); // clock 0
was_sensor_freq=x393_getClockFreq(sensor_port, I2C359_CLK_NUMBER & 3); // clock 0
if (first || (was_sensor_freq !=0)) { // Otherwise it is likely rev 0 - no clock
// was_sensor_freq=getClockFreq(1);
was_sensor_freq=90000000; // TODO: Find out how to read actual clock frequency for sensor ports
// i=setClockFreq(I2C359_CLK_NUMBER, was_sensor_freq);
i=x393_setClockFreq(I2C359_CLK_NUMBER & 3, was_sensor_freq);
i=x393_setClockFreq(sensor_port, I2C359_CLK_NUMBER & 3, was_sensor_freq);
if (i>0) {
MULTISENSOR_WRITE_I2C16_SHADOW(sensor_port, I2C359_CLKSRC, I2C359_CLKSRC_LOCAL);
udelay (50000); // 0.05 sec to stabilize clocks - will miss multiple frames
mdelay (50); // 0.05 sec to stabilize clocks - will miss multiple frames
} else {
was_sensor_freq=-1; // error
}
......@@ -1713,7 +1724,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
int results90 [4];
int i;
int oldPhase=0;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, 0, oldPhase); // reset SDRAM phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, 0, oldPhase); // reset SDRAM phase
if (oldPhase<0) return oldPhase; // failed to reset
int needReset=0;
int ok90=0;
......@@ -1722,7 +1733,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
int high90=-1;
int low_l, low_h, high_l,high_h;
for (i=0; i<4; i++) {
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, i<<16, oldPhase); // do not reset SDRAM phase - no fine tuning
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i<<16, oldPhase); // do not reset SDRAM phase - no fine tuning
if (oldPhase<0) return oldPhase; // any error is fatal here
results90 [i]=multisensor_memphase (sensor_port,&centroids90[i]);
if (results90 [i]==0) {
......@@ -1777,12 +1788,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
#define I2C359_DCM_ERR_OVFL 3
#define I2C359_DCM_ERR_NODONE 4
#define I2C359_DCM_ERR_NOLOCKED 5*/
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((low_h-low_l)>1) {
i=(low_l+low_h)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1802,12 +1813,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
high_l= 0;
high_h= maxAdjust;
}
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((high_h-high_l)>1) {
i=(high_h+high_l)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1823,7 +1834,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
if (high90==low90) { // 0,1 OK phases
if (high_l>low_h) { // 0,1 OK phases
i= (high90<<16) | (((high_l+low_h)>>1) & 0xffff);
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
if (oldPhase<0) return oldPhase;
// Verify that final phase is OK
if (multisensor_memphase (sensor_port,NULL)==0) return i;
......@@ -1844,12 +1855,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
low90=high90;
low_l= -maxAdjust;
low_h= 0;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (low90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((low_h-low_l)>1) {
i=(low_l+low_h)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (low90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1865,12 +1876,12 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
high90=low90;
high_l= 0;
high_h= maxAdjust;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, 1, (high90<<16), oldPhase); // reset dcm, set 90-degree phase
if (oldPhase<0) return oldPhase; // any error is fatal here - fine phase is 0
needReset=0;
while ((high_h-high_l)>1) {
i=(high_h+high_l)/2;
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, (high90<<16) | (i & 0xffff), oldPhase); // try middle phase, no DCM reset
if (oldPhase<0) {
MDF24 (printk(" DCM error=%d\n",-oldPhase));
needReset=1;
......@@ -1886,7 +1897,7 @@ int multisensor_adjustSDRAM (int sensor_port, ///< sensor_port Sensor port (0..
MDF24 (printk("Re-measured to the same 90-degree phase low90=%d, low=%d, high90=%d, high=%d\n",low90,low_h,high90,high_l));
if (high_l>low_h) { // 0,1 OK phases
i= (high90<<16) | (((high_l+low_h)>>1) & 0xffff);
oldPhase= multisensor_set_phase_verify (I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
oldPhase= multisensor_set_phase_verify (sensor_port, I2C359_DCM_SDRAM, needReset, i, oldPhase); // middle phase, same 90-degree
return oldPhase; // (both >=0 or error (<0)
} else { // something strange - should not get here
printk("%s:%d:%s ",__FILE__,__LINE__,__FUNCTION__);
......@@ -2041,7 +2052,7 @@ int multisensor_pgm_sensorregs (int sensor_port, ///< sensor port
thispars->mod32=0;
}
// Now proceed with physical sensor(s) i2c registers - both broadcast and individual
if (sensorproc_phys->pgm_func[onchange_sensorregs+32]) return sensorproc_phys->pgm_func[onchange_sensorregs+32] (sensor, thispars, prevpars, frame16);
if (sensorproc_phys->pgm_func[onchange_sensorregs+32]) return sensorproc_phys->pgm_func[onchange_sensorregs+32] (sensor_port, sensor, thispars, prevpars, frame16);
return 0; // physical sensor function does not exist
}
......
......@@ -199,8 +199,8 @@
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/delay.h>
#include <linux/delay.h>
//#include <asm/delay.h>
#include <asm/uaccess.h>
#include <elphel/c313a.h>
//#include <asm/elphel/exifa.h>
......@@ -212,6 +212,8 @@
//#include "x3x3.h" // hardware definitions
#include "framepars.h"
#include "sensor_common.h"
#include "multi10359.h"
#include "mt9x001.h"
#include "gamma_tables.h"
#include "quantization_tables.h"
#include "latency.h"
......@@ -288,7 +290,8 @@
/** Initialize array of functions that program different acquisition parameters (some are sensor dependent)
* @return always 0 */
int init_pgm_proc(void) {
int init_pgm_proc(void)
{
int i;
MDF1(printk("\n"));
for (i=0;i<64;i++) sensorproc->pgm_func[i]=NULL;
......@@ -325,7 +328,7 @@ int init_pgm_proc(void) {
sensorproc->pgm_func[onchange_sensorregs]= &pgm_sensorregs; // write sensor registers (only changed from outside the driver as they may have different latencies)?
sensorproc->pgm_func[onchange_prescal]= &pgm_prescal; // change scales for per-color digital gains, apply vignetting correction
return 0;
return 0;
}
/**
......@@ -333,10 +336,11 @@ return 0;
* @param index function index (internally 32 is added to distinguish from the common (not sensor-specific) functions
* @param sens_func pointer to a sensor-specific function
* @return always 0 */
int add_sensor_proc(int index, int (*sens_func)(int sensor_port, struct sensor_t * , struct framepars_t * , struct framepars_t *, int )) {
int add_sensor_proc(int index, int (*sens_func)(int sensor_port, struct sensor_t * , struct framepars_t * , struct framepars_t *, int ))
{
MDF1(printk("index=0x%x\n",index));
sensorproc->pgm_func[32+(index & 0x1f)]= sens_func;
return 0;
return 0;
}
/** Detect and initialize sensor and related data structures
......@@ -352,6 +356,11 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
///< @return OK - 0, <0 - error
{
int was_sensor_freq;
int qperiod;
int i2cbytes;
int phase;
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)
......@@ -366,26 +375,28 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
// 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();
/// x313_dma_stop();
MDF1(printk("x313_dma_init()\n"));
x313_dma_init();
/// x313_dma_init();
MDF1(printk("reset_compressor()\n"));
reset_compressor();
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;
int was_sensor_freq=getClockFreq(1); // using clock driver data, not thispars
setFramePar(thispars, P_CLK_FPGA, getClockFreq(0)); // just in case - read the actual fpga clock frequency and store it (no actions)
setFramePar(thispars, P_CLK_SENSOR, 48000000);
#ifdef NC353
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]);
#endif
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
udelay (50000);// 0.05 sec to stabilize clocks
mdelay (50);// 0.05 sec to stabilize clocks
// setting reasonable state of the control signals
CCAM_DCLK_ON;
CCAM_CNVEN_OFF;
......@@ -396,14 +407,14 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
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, thispars, prevpars, frame16); // multisensor
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;
}
#ifdef CONFIG_ETRAX_ELPHEL_MT9X001
if (thispars->pars[P_SENSOR]==0) {
mt9x001_pgm_detectsensor(sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
mt9x001_pgm_detectsensor(sensor_port, sensor, thispars, prevpars, frame16); // try Micron 5.0 Mpixel - should return sensor type
printk("trying MT9P001\n");
}
#endif
......@@ -421,26 +432,26 @@ int pgm_detectsensor (int sensor_port, ///< sensor port number (
#ifdef NC353
port_csp0_addr[X313_WA_DCDC] = 0x44; // 48 - enough, 41 - ok - was 0x61; //
printk ("sensor power set low\r\n ");
udelay (10000); // Wait voltage to come up (~10 ms)
mdelay (10); // Wait voltage to come up (~10 ms)
printk ("will set to 0x41\r\n");
udelay (10000); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x41; //
printk ("will set to 0x30\r\n");
udelay (10000); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x30; //
printk ("will set to 0x28\r\n");
udelay (10000); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x28; //
printk ("will set to 0x24\r\n");
udelay (10000); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x24; //
printk ("will set to 0x22\r\n");
udelay (10000); // to find the problem
mdelay (10); // to find the problem
port_csp0_addr[X313_WA_DCDC] = 0x22; //
udelay (100000); // 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");
udelay (10000); // Wait voltage to stabilize
mdelay (10); // Wait voltage to stabilize
CCAM_POSRST; //set positive MRST polarity (default)
udelay (100); // apply clock before removing MRST
CCAM_MRST_OFF;
......@@ -461,16 +472,16 @@ printk ("Inverted MRST\n");
}
#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, thispars, prevpars, frame16); // try Micron 1.3/2.0/3.0 Mpixel
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(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(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(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 ********************
......@@ -478,25 +489,25 @@ printk ("Inverted MRST\n");
sensor->sensorType=SENSOR_NONE; // to prevent from initializing again
printk("No image sensor found\r\n");
}
setFramePar(thispars, P_SENSOR_WIDTH, sensor->imageWidth); // Maybe get rid of duplicates?
setFramePar(thispars, P_SENSOR_HEIGHT, sensor->imageHeight); // Maybe get rid of duplicates?
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)
int qperiod=thispars->pars[P_I2C_QPERIOD];
qperiod=thispars->pars[P_I2C_QPERIOD];
if (qperiod==0) qperiod=(sensor->i2c_period * (thispars->pars[P_CLK_FPGA]/1000))/4000000;
setFramePar(thispars, P_I2C_QPERIOD | FRAMEPAIR_FORCE_NEWPROC, qperiod); // force i2c
int i2cbytes=thispars->pars[P_I2C_BYTES];
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(thispars, P_I2C_BYTES | FRAMEPAIR_FORCE_NEWPROC, i2cbytes); // force i2c
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(thispars, P_CLK_SENSOR | FRAMEPAIR_FORCE_NEWPROC, was_sensor_freq); // will schedule clock/phase adjustment
int phase=thispars->pars[P_SENSOR_PHASE];
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(thispars, P_SENSOR_PHASE | FRAMEPAIR_FORCE_NEWPROC, phase); // will schedule clock/phase adjustment
setFramePar(sensor_port, thispars, P_SENSOR_PHASE | FRAMEPAIR_FORCE_NEWPROC, phase); // will schedule clock/phase adjustment
}
setFramePar(thispars, P_IRQ_SMART | FRAMEPAIR_FORCE_NEWPROC, 3); // smart IRQ mode programming (and enable interrupts)
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)
......@@ -541,10 +552,10 @@ int pgm_afterinit (int sensor_port, ///< sensor port number (
struct frameparspair_t pars_to_update[24]; // 20 needed, increase if more entries will be added
int nupdate=0;
MDF3(printk(" frame16=%d\n",frame16));
// If this is a multisensor camera, update composite sensor dimensions (will trigger other related changes)
// For single sensors sensor size is updated only after initialization, with composite it needs to be updated after vertical gap or number of active sesnors is changed
// if (GLOBALPARS(G_SENS_AVAIL) ) multisensor_pgm_afterinit0 (sensor, thispars, prevpars,frame16);
// Setup WOI. If size is zero - use maximal that sensor can, in non-zero - just refresh so appropriate actions will be scheduled on chnange
// If this is a multisensor camera, update composite sensor dimensions (will trigger other related changes)
// For single sensors sensor size is updated only after initialization, with composite it needs to be updated after vertical gap or number of active sesnors is changed
// if (GLOBALPARS(G_SENS_AVAIL) ) multisensor_pgm_afterinit0 (sensor, thispars, prevpars,frame16);
// Setup WOI. If size is zero - use maximal that sensor can, in non-zero - just refresh so appropriate actions will be scheduled on chnange
int woi_width=thispars->pars[P_WOI_WIDTH];
int woi_height=thispars->pars[P_WOI_HEIGHT];
if ((woi_width == 0) || (woi_height == 0)) { ///were zeroes
......@@ -567,19 +578,19 @@ int pgm_afterinit (int sensor_port, ///< sensor port number (
SETFRAMEPARS_UPDATE_SET(P_DCM_VERT | FRAMEPAIR_FORCE_NEW, 1);
SETFRAMEPARS_UPDATE_SET(P_BIN_HOR | FRAMEPAIR_FORCE_NEW, 1);
SETFRAMEPARS_UPDATE_SET(P_BIN_VERT | FRAMEPAIR_FORCE_NEW, 1);
// Set analog gains to 1.0 if not set otherwise
// FIXME: Without those 3 lines it is not initialaized (or immediately reset) from the parameters in autocampars.xml. GAING=0x10000, all the rest - 0
/*
// Set analog gains to 1.0 if not set otherwise
// FIXME: Without those 3 lines it is not initialaized (or immediately reset) from the parameters in autocampars.xml. GAING=0x10000, all the rest - 0
/*
if (!(GLOBALPARS(G_DEBUG) & (1 <<28))) { // debugging here ! ***********************************
SETFRAMEPARS_UPDATE_SET(P_GAINR | FRAMEPAIR_FORCE_NEW, 0x20000); ///gain ==1.0
SETFRAMEPARS_UPDATE_SET(P_GAING | FRAMEPAIR_FORCE_NEW, 0x20000); ///gain ==1.0
SETFRAMEPARS_UPDATE_SET(P_GAINB | FRAMEPAIR_FORCE_NEW, 0x20000); ///gain ==1.0
SETFRAMEPARS_UPDATE_SET(P_GAINGB | FRAMEPAIR_FORCE_NEW,0x20000); ///gain ==1.0
}
*/
*/
SETFRAMEPARS_UPDATE(P_BAYER | FRAMEPAIR_FORCE_NEW);
// Exposure use non-zero P_EXPOS, then P_VEXPOS, then P_EXPOS=10ms
// Exposure use non-zero P_EXPOS, then P_VEXPOS, then P_EXPOS=10ms
if (thispars->pars[P_EXPOS]) {
SETFRAMEPARS_UPDATE(P_EXPOS | FRAMEPAIR_FORCE_NEW);
} else if (thispars->pars[P_VEXPOS]) {
......@@ -588,9 +599,9 @@ int pgm_afterinit (int sensor_port, ///< sensor port number (
SETFRAMEPARS_SET(P_EXPOS | FRAMEPAIR_FORCE_NEW, 10000); // set exposure to 0.01 sec
}
SETFRAMEPARS_UPDATE(P_TRIG | FRAMEPAIR_FORCE_NEW); // set trigger mode (or should it alway be internal after init?)
// something else to add? NOTE: Only sensor parameters, erased when it is reset - other parameters should not chnage here
// NOTE: increase pars_to_update[24] size if needed
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); // save changes, schedule functions
// something else to add? NOTE: Only sensor parameters, erased when it is reset - other parameters should not chnage here
// NOTE: increase pars_to_update[24] size if needed
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
return 0;
}
......@@ -600,8 +611,8 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
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 always 0
///< be applied to, negative - ASAP
///< @return always 0
{
struct frameparspair_t pars_to_update[5]; // ??? needed, increase if more entries will be added
......@@ -614,27 +625,41 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
int diff_phase;
int diff_phase90;
int new_freq= thispars->pars[P_CLK_SENSOR];
MDF3(printk(" frame16=%d\n",frame16));
int thisPhase=thispars->pars[P_SENSOR_PHASE];
int was_sensor_freq = new_freq; // bypassing for nc393
int hact_shift;
long * cableDelay;
long * FPGADelay;
int clk_period; // period in ps
int px_delay;
int px_delay90;
uint64_t ull_result = 1000000000000LL;
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= 0) return -1; // can only work in ASAP mode
//Can not change sensor frequency
#ifdef NC353
int was_sensor_freq=getClockFreq(1); // using clock driver data, not thispars
if (unlikely(new_freq > sensor->maxClockFreq)) {
new_freq= sensor->maxClockFreq;
SETFRAMEPARS_SET(P_CLK_SENSOR, new_freq);
}
#endif
if ((new_freq != was_sensor_freq) || (thisPhase & 0x40000)) { // 0x40000 reprogram clock even if it did not change
#ifdef NC353
if (unlikely(setClockFreq(1, thispars->pars[P_CLK_SENSOR])<0)) { // if it failed to setup frequency - use the old one
new_freq=was_sensor_freq;
setClockFreq(1, was_sensor_freq);
SETFRAMEPARS_SET(P_CLK_SENSOR, new_freq);
}
#endif
X3X3_RSTSENSDCM; // Make Xilinx Spartan DCM happy (it does not like changing input clock)
X3X3_SENSDCM_CLK2X_RESET; // reset pclk2x DCM also
if (sensor->needReset & SENSOR_NEED_RESET_CLK) schedule_this_pgm_func(thispars, onchange_initsensor);
// set HACT PHASE here - 90 deg. increment - seems like a bug in MT9P001 sensors - horisontal (and vert.) sync has different phase than data
// Update (program) hact_shift only when the frequency is changed, not when just the phase is
// adjustment range is 270 early to 360 late
int hact_shift= 0.004 * (((int)sensor->hact_delay)/(1000000000.0/new_freq)) + 4.5;
if (sensor->needReset & SENSOR_NEED_RESET_CLK) schedule_this_pgm_func(sensor_port, thispars, onchange_initsensor);
// set HACT PHASE here - 90 deg. increment - seems like a bug in MT9P001 sensors - horisontal (and vert.) sync has different phase than data
// Update (program) hact_shift only when the frequency is changed, not when just the phase is
// adjustment range is 270 early to 360 late
hact_shift= 0.004f * (((int)sensor->hact_delay)/(1000000000.0f/new_freq)) + 4.5f;
MDF16(printk ("hact_shift=%d-4\r\n",hact_shift));
hact_shift-=4;
MDF16(printk ("hact_shift=%d\r\n",hact_shift));
......@@ -647,14 +672,18 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
else if (hact_shift<0) for (i=0; i < -hact_shift; i++) {
X3X3_SENSDCM_HACT_EARLY90;
}
// Calculate and set sensor phase (only initially and when clock frequency is chnaged)
long * cableDelay= (long *) &GLOBALPARS(sensor_port, G_CABLE_TIM );
long * FPGADelay= (long *) &GLOBALPARS(sensor_port, G_FPGA_TIM0 );
int clk_period= 1000000000000.0/new_freq; // period in ps
// Calculate and set sensor phase (only initially and when clock frequency is chnaged)
cableDelay= (long *) &GLOBALPARS(sensor_port, G_CABLE_TIM );
FPGADelay= (long *) &GLOBALPARS(sensor_port, G_FPGA_TIM0 );
// clk_period= 1000000000000.0f/new_freq; // period in ps
// clk_period= 1.0E12f/new_freq; // period in ps
do_div(ull_result,new_freq);
clk_period= ull_result;
MDF16(printk ("cableDelay=%ld, FPGADelay=%ld, clk_period=%d\r\n",cableDelay[0], FPGADelay[0], clk_period));
int px_delay=-(clk_period/2 - FPGADelay[0]- cableDelay[0] - ((int) sensor->sensorDelay)) ;
px_delay=-(clk_period/2 - FPGADelay[0]- cableDelay[0] - ((int) sensor->sensorDelay)) ;
MDF16(printk ("px_delay=%d\r\n",px_delay));
int px_delay90=(4*px_delay+clk_period/2)/clk_period;
px_delay90=(4*px_delay+clk_period/2)/clk_period;
px_delay -= (px_delay90*clk_period)/4; // -clk_period/8<= now px_delay <= +clk_period/8
MDF16(printk ("px_delay=%d, px_delay90=%d\r\n",px_delay,px_delay90));
px_delay/= FPGA_DCM_STEP; // in DCM steps
......@@ -686,7 +715,7 @@ int pgm_sensorphase (int sensor_port, ///< sensor port number (
SETFRAMEPARS_SET(P_SENSOR_PHASE, thisPhase & 0x3ffff);
}
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); // save changes, schedule functions
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
return 0;
}
......@@ -719,8 +748,8 @@ int pgm_i2c (int sensor_port, ///< sensor port number (0..3
X3X3_SEQ_SEND1(fpga_addr, X313_I2C_CMD, X3X3_SET_I2C_BYTES(thispars->pars[P_I2C_BYTES]+1) |
X3X3_SET_I2C_DLY (thispars->pars[P_I2C_QPERIOD]));
#endif
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_I2C_CMD, (int) (X3X3_SET_I2C_BYTES(thispars->pars[P_I2C_BYTES]+1) | X3X3_SET_I2C_DLY (thispars->pars[P_I2C_QPERIOD])) ));
return 0;
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_I2C_CMD, (int) (X3X3_SET_I2C_BYTES(thispars->pars[P_I2C_BYTES]+1) | X3X3_SET_I2C_DLY (thispars->pars[P_I2C_QPERIOD])) ));
return 0;
}
/** Program sensor WOI and mirroring
......@@ -737,7 +766,7 @@ int pgm_window (int sensor_port, ///< sensor port number (0..3
{
MDF3(printk(" frame16=%d\n",frame16));
return pgm_window_common (sensor, thispars, prevpars, frame16);
return pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
/** Program sensor WOI and mirroring, safe mode. Does the same as pgm_window, at least not sensor-specific */
......@@ -751,7 +780,7 @@ int pgm_window_safe (int sensor_port, ///< sensor port number (0..
{
MDF3(printk(" frame16=%d\n",frame16));
return pgm_window_common (sensor, thispars, prevpars, frame16);
return pgm_window_common (sensor_port, sensor, thispars, prevpars, frame16);
}
//** Common (not sensor-specific) part of processing WOI parameters*/
......@@ -764,23 +793,25 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
///< @return always 0
{
int dv,dh,bv,bh,width,height,timestamp_len,oversize,pfh,pf_stripes,ah, left,top,is_color;
int sensor_width;
int sensor_height;
struct frameparspair_t pars_to_update[18]; // 15 needed, increase if more entries will be added
int nupdate=0;
MDF3(printk(" frame16=%d\n",frame16));
MDF23(printk("thispars->pars[P_WOI_HEIGHT]=%lx thispars->pars[P_WOI_WIDTH]=%lx\n",thispars->pars[P_WOI_HEIGHT], thispars->pars[P_WOI_WIDTH]));
// if (GLOBALPARS(G_SENS_AVAIL) ) multisensor_pgm_window_common0 (sensor, thispars, prevpars, frame16);
// if (GLOBALPARS(G_SENS_AVAIL) ) multisensor_pgm_window_common0 (sensor, thispars, prevpars, frame16);
int sensor_width= thispars->pars[P_SENSOR_WIDTH];
int sensor_height=thispars->pars[P_SENSOR_HEIGHT];
sensor_width= thispars->pars[P_SENSOR_WIDTH];
sensor_height=thispars->pars[P_SENSOR_HEIGHT];
oversize=thispars->pars[P_OVERSIZE];
is_color=1;
struct frameparspair_t pars_to_update[18]; // 15 needed, increase if more entries will be added
int nupdate=0;
switch (thispars->pars[P_COLOR] & 0x0f){
case COLORMODE_MONO6:
case COLORMODE_MONO4:
is_color=0;
}
// flips changed?
// flips changed?
if (FRAMEPAR_MODIFIED(P_FLIPH)) {
if (unlikely((thispars->pars[P_FLIPH] & sensor->flips & 1)!=thispars->pars[P_FLIPH])) { // remove unsupoported flips
SETFRAMEPARS_SET(P_FLIPH, (thispars->pars[P_FLIPH] & sensor->flips & 1));
......@@ -791,28 +822,28 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
SETFRAMEPARS_SET(P_FLIPV, (thispars->pars[P_FLIPV] & (sensor->flips >> 1 ) & 1));
}
}
// dh (decimation changed)?
// dh (decimation changed)?
dh = thispars->pars[P_DCM_HOR];
if (FRAMEPAR_MODIFIED(P_DCM_HOR)) {
if (dh<1) dh=1; else if (dh>32) dh=32;
while ((dh>1) && !(sensor->dcmHor & (1 << (dh-1)))) dh--; // adjust decimation to maximal supported (if requested is not supported)
if (unlikely(dh!=thispars->pars[P_DCM_HOR])) SETFRAMEPARS_SET(P_DCM_HOR, dh);
}
// dv (decimation changed)?
// dv (decimation changed)?
dv = thispars->pars[P_DCM_VERT];
if (FRAMEPAR_MODIFIED(P_DCM_VERT)) {
if (dv<1) dv=1; else if (dv>32) dv=32;
while ((dv>1) && !(sensor->dcmVert & (1 << (dv-1)))) dv--; // adjust decimation to maximal supported (if requested is not supported)
if (unlikely(dv!=thispars->pars[P_DCM_HOR])) SETFRAMEPARS_SET(P_DCM_VERT, dv);
}
// bh (binning changed)?
// bh (binning changed)?
bh = thispars->pars[P_BIN_HOR];
if (FRAMEPAR_MODIFIED(P_BIN_HOR)) {
if (bh<1) bh=1; else if (bh>dh) bh=dh;
while ((bh>1) && !(sensor->binHor & (1 << (bh-1)))) bh--; // adjust binning to maximal supported (if requested is not supported)
if (unlikely(bh!=thispars->pars[P_BIN_HOR])) SETFRAMEPARS_SET(P_DCM_HOR, bh);
}
// bv (binning changed)?
// bv (binning changed)?
bv = thispars->pars[P_BIN_VERT];
if (FRAMEPAR_MODIFIED(P_BIN_VERT)) {
if (bv<1) bv=1; else if (bv>dv) bv=dv;
......@@ -820,17 +851,17 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
if (unlikely(bv!=thispars->pars[P_BIN_VERT])) SETFRAMEPARS_SET(P_DCM_VERT, bv);
}
// any other binning adjustmens needed?
// adjustP_WOI_WIDTH, P_ACTUAL_WIDTH, P_SENSOR_PIXH - depends on decimation, photofinish mode
// adjustP_WOI_WIDTH, P_ACTUAL_WIDTH, P_SENSOR_PIXH - depends on decimation, photofinish mode
timestamp_len = (((thispars->pars[P_PF_HEIGHT] >> 16) & 3)==2)? X313_TIMESTAMPLEN*dh : 0;
// adjust width/height first, then adjust left top
// adjust width/height first, then adjust left top
width=thispars->pars[P_WOI_WIDTH];
// if ((!oversize) && (width > sensor->imageWidth)) width= sensor->imageWidth;
// if ((!oversize) && (width > sensor_width)) width= sensor_width;
// if ((!oversize) && (width > sensor->imageWidth)) width= sensor->imageWidth;
// if ((!oversize) && (width > sensor_width)) width= sensor_width;
if ((!oversize) && (width > sensor_width)) width= sensor_width;
// make width to be multiple of the compressor tile (before adding margins of 4 pixels)
// make width to be multiple of the compressor tile (before adding margins of 4 pixels)
width= (((width/dh) + timestamp_len)/X313_TILEHOR)*X313_TILEHOR-timestamp_len; // divided by dh
// suppose minimal width refers to decimated output
// suppose minimal width refers to decimated output
while (width < sensor->minWidth) width+=X313_TILEHOR;
if (unlikely(thispars->pars[P_ACTUAL_WIDTH] != (width+timestamp_len))) {
SETFRAMEPARS_SET(P_ACTUAL_WIDTH, width+timestamp_len); ///full width for the compressor, including timestamp, but excluding margins
......@@ -840,10 +871,10 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
width*=dh;
if (unlikely(thispars->pars[P_WOI_WIDTH] != width))
SETFRAMEPARS_SET(P_WOI_WIDTH, width); // WOI width, as specified (corrected for the sensor if needed)
// adjustP_WOI_HEIGHT, P_ACTUAL_HEIGHT, P_SENSOR_PIXV - depends on decimation, photofinish mode
// adjustP_WOI_HEIGHT, P_ACTUAL_HEIGHT, P_SENSOR_PIXV - depends on decimation, photofinish mode
pfh = (thispars->pars[P_PF_HEIGHT] & 0xffff);
height=thispars->pars[P_WOI_HEIGHT];
// pf_stripes;
// pf_stripes;
if(pfh > 0) {
if (pfh < sensor->minHeight) pfh = sensor->minHeight;
if (pfh & 1) pfh++;
......@@ -857,7 +888,7 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
} else {
if ((!oversize ) && (height > sensor_height)) height=sensor_height;
height= ((height/dv)/X313_TILEVERT) * X313_TILEVERT; // divided by dv (before multisensor options)
// suppose minimal height refers to decimated output
// suppose minimal height refers to decimated output
while (height < sensor->minHeight) height+=X313_TILEVERT;
if (unlikely(thispars->pars[P_SENSOR_PIXV] != height+X313_MARGINS))
SETFRAMEPARS_SET(P_SENSOR_PIXV, height+X313_MARGINS); ///full height for the sensor (after decimation), including margins
......@@ -870,18 +901,18 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
MDF23(printk(" SETFRAMEPARS_SET(P_PF_HEIGHT, 0x%x)\n",(int) ((thispars->pars[P_PF_HEIGHT] & 0xffff0000 ) | pfh)));
SETFRAMEPARS_SET(P_PF_HEIGHT, (thispars->pars[P_PF_HEIGHT] & 0xffff0000 ) | pfh );
}
// update WOI height [P_WOI_HEIGHT
// update WOI height [P_WOI_HEIGHT
if (unlikely(thispars->pars[P_WOI_HEIGHT] != height)) {
MDF23(printk(" SETFRAMEPARS_SET(P_WOI_HEIGHT, 0x%x)\n",height));
SETFRAMEPARS_SET(P_WOI_HEIGHT, height); ///full height for the compressor (excluding margins)
}
// update P_ACTUAL_HEIGHT
// update P_ACTUAL_HEIGHT
ah=height/dv;
if (unlikely(thispars->pars[P_ACTUAL_HEIGHT] != ah)) {
MDF23(printk(" SETFRAMEPARS_SET(P_ACTUAL_HEIGHT, 0x%x)\n",ah));
SETFRAMEPARS_SET(P_ACTUAL_HEIGHT, ah); ///full height for the compressor (excluding margins)
}
// left margin
// left margin
left = thispars->pars[P_WOI_LEFT];
if (!oversize) { // in oversize mode let user to specify any margin, including odd ones (bayer shifted)
if (is_color) left &= 0xfffe;
......@@ -891,13 +922,13 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
}
if (left & 0x8000) left = 0;
}
// update P_WOI_LEFT
// update P_WOI_LEFT
if (unlikely(thispars->pars[P_WOI_LEFT] != left)) {
MDF23(printk(" SETFRAMEPARS_SET(P_WOI_LEFT, 0x%x)\n",left));
SETFRAMEPARS_SET(P_WOI_LEFT, left);
}
// top margin
// top margin
top = thispars->pars[P_WOI_TOP];
int clearHeight=(sensor->clearHeight-sensor->imageHeight) + thispars->pars[P_SENSOR_HEIGHT];
if (!oversize) { // in oversize mode let user to specify any margin, including odd ones (bayer shifted)
......@@ -908,12 +939,12 @@ int pgm_window_common (int sensor_port, ///< sensor port number (
}
if (top & 0x8000) top = 0;
}
// update P_WOI_TOP
// update P_WOI_TOP
if (unlikely(thispars->pars[P_WOI_TOP] != top)) {
MDF23(printk(" SETFRAMEPARS_SET(P_WOI_TOP, 0x%x)\n",top));
SETFRAMEPARS_SET(P_WOI_TOP, top);
}
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); // save changes, schedule functions
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
return 0;
}
......@@ -933,7 +964,7 @@ int pgm_limitfps (int sensor_port, ///< sensor port number (0..3
///< @return always 0
{
// Calculate minimal frame period compressor can handle, apply requested fps, limit/program the sequencer
// Calculate minimal frame period compressor can handle, apply requested fps, limit/program the sequencer
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
struct frameparspair_t pars_to_update[8]; // 4 needed, increase if more entries will be added
......@@ -942,12 +973,15 @@ int pgm_limitfps (int sensor_port, ///< sensor port number (0..3
int cycles; // number of FPGA clock cycles per frame;
int min_period; // number of pixel clock periods needed for the compressor (or user limit)
int period=0;
cycles=thispars->pars[P_TILES]; // number of tiles
int pfh;
int n_stripes;
#if USELONGLONG
uint64_t ull_min_period;
uint64_t ull_period;
#endif
// MDF9(printk(" tiles=%d(0x%x)\n",cycles,cycles));
cycles=thispars->pars[P_TILES]; // number of tiles
// MDF9(printk(" tiles=%d(0x%x)\n",cycles,cycles));
switch (thispars->pars[P_COLOR] & 0x0f){
case COLORMODE_MONO6:
case COLORMODE_COLOR:
......@@ -963,15 +997,20 @@ int pgm_limitfps (int sensor_port, ///< sensor port number (0..3
MDF9(printk(" cycles=%d(0x%x)\n",cycles,cycles));
cycles += thispars->pars[P_FPGA_XTRA]; // extra cycles needed for the compressor to start/finish the frame;
MDF9(printk(" cycles with P_FPGA_XTRA =%d(0x%x)\n",cycles,cycles));
// #define P_CLK_FPGA, #define P_CLK_SENSOR 27-28 bits, cycles - 24-25 bits
// TODO: fix long long
// #define P_CLK_FPGA, #define P_CLK_SENSOR 27-28 bits, cycles - 24-25 bits
// TODO: fix long long
#if USELONGLONG
ull_min_period=(((long long) cycles) * ((long long) thispars->pars[P_CLK_SENSOR]));
#ifdef __div64_32
__div64_32(&ull_min_period, thispars->pars[P_CLK_FPGA]);
#else
do_div(ull_min_period, thispars->pars[P_CLK_FPGA]);
// ull_min_period/=thispars->pars[P_CLK_FPGA];
#endif
min_period= ull_min_period;
MDF9(printk("min_period =%d(0x%x)\n",min_period,min_period));
// min_period = (((long long) cycles) * ((long long) thispars->pars[P_CLK_SENSOR])) / ((long long) thispars->pars[P_CLK_FPGA]);
// min_period = (((long long) cycles) * ((long long) thispars->pars[P_CLK_SENSOR])) / ((long long) thispars->pars[P_CLK_FPGA]);
#else
if (cycles < (1<<16) ) {
min_period = (cycles * (thispars->pars[P_CLK_SENSOR] >> 12)) / (thispars->pars[P_CLK_FPGA]>>12);
......@@ -989,14 +1028,19 @@ int pgm_limitfps (int sensor_port, ///< sensor port number (0..3
///? fp1000s= 10*sclk/(pix_period/100);
MDF9(printk("min_period =%d(0x%x)\n",min_period,min_period));
#endif
// is there limit set for the FPS?
// is there limit set for the FPS?
if (thispars->pars[P_FPSFLAGS]) {
#if USELONGLONG
ull_period=(((long long) thispars->pars[P_CLK_SENSOR]) * (long long) 1000);
#ifdef __div64_32
__div64_32(&ull_period, thispars->pars[P_FP1000SLIM]);
#else
do_div(ull_period, thispars->pars[P_FP1000SLIM]);
// ull_period /= thispars->pars[P_FP1000SLIM];
#endif
period= ull_period;
MDF9(printk("period =%d(0x%x)\n",period,period));
// period=(((long long) thispars->pars[P_CLK_SENSOR]) * (long long) 1000)/((long long) thispars->pars[P_FP1000SLIM]);
// period=(((long long) thispars->pars[P_CLK_SENSOR]) * (long long) 1000)/((long long) thispars->pars[P_FP1000SLIM]);
#else
period=125*(( thispars->pars[P_CLK_SENSOR] << 3) / thispars->pars[P_FP1000SLIM]); // 125 <<3 = 1000
MDF9(printk("period =%d(0x%x)\n",period,period));
......@@ -1004,9 +1048,8 @@ int pgm_limitfps (int sensor_port, ///< sensor port number (0..3
}
MDF1(printk(" period=%d\n",period));
if ((thispars->pars[P_FPSFLAGS] & 1) && (period>min_period)) min_period=period;
// *********************************************************** P_PF_HEIGHT
int pfh=thispars->pars[P_PF_HEIGHT] &0xffff ;
int n_stripes;
// *********************************************************** P_PF_HEIGHT
pfh=thispars->pars[P_PF_HEIGHT] &0xffff ;
if (pfh>0) {
n_stripes=thispars->pars[P_WOI_HEIGHT]/pfh;
if (n_stripes>0) min_period/=n_stripes;
......@@ -1018,18 +1061,18 @@ int pgm_limitfps (int sensor_port, ///< sensor port number (0..3
}
if (((thispars->pars[P_FPSFLAGS] & 2)==0) || (period < min_period)) period=0x7fffffff; // no upper limit
if (period != thispars->pars[P_PERIOD_MAX]) SETFRAMEPARS_SET(P_PERIOD_MAX, period); // set it (and propagate to the later frames)
// Now see if the sequencer period needs to be adjusted
// if (async && (thispars->pars[P_TRIG_PERIOD] >=256)) { // <256 - single trig
// if (async && (thispars->pars[P_TRIG_PERIOD] !=1)) { // <256 - single trig, here only ==1 is for single
// Update period to comply even if it is not in async mode
// Now see if the sequencer period needs to be adjusted
// if (async && (thispars->pars[P_TRIG_PERIOD] >=256)) { // <256 - single trig
// if (async && (thispars->pars[P_TRIG_PERIOD] !=1)) { // <256 - single trig, here only ==1 is for single
// Update period to comply even if it is not in async mode
if (thispars->pars[P_TRIG_PERIOD] !=1) { // <256 - single trig, here only ==1 is for single
if (thispars->pars[P_TRIG_PERIOD] < min_period) SETFRAMEPARS_SET(P_TRIG_PERIOD, min_period); // set it (and propagate to the later frames)
if (async && (thispars->pars[P_FPSFLAGS] & 2) && (thispars->pars[P_TRIG_PERIOD] > period)) {
SETFRAMEPARS_SET(P_TRIG_PERIOD, period); // set it (and propagate to the later frames)
}
}
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); // save changes, schedule functions
// That's all - sensor or sequencer will be programmed later using the parameters specified here
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
// That's all - sensor or sequencer will be programmed later using the parameters specified here
return 0;
}
......@@ -1058,10 +1101,10 @@ int pgm_triggermode(int sensor_port, ///< sensor port number (0..3
///< @return OK - 0, <0 - error
{
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int fpga_addr= frame16;
int async=(thispars->pars[P_TRIG] & 4)?1:0;
// X3X3_SEQ_SEND1(frame16, X313_WA_DCR0, X353_DCR0(SENSTRIGEN,async));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// X3X3_SEQ_SEND1(frame16, X313_WA_DCR0, X353_DCR0(SENSTRIGEN,async));
return 0;
}
......@@ -1082,7 +1125,7 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
#ifdef NC353
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
// Set FPN mode (P_FPGATEST - currently only LSB is processed)
// Set FPN mode (P_FPGATEST - currently only LSB is processed)
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SENSFPN, X313_SENSFPN_D( \
(thispars->pars[P_FPGATEST]), \
(thispars->pars[P_FPNS]), \
......@@ -1099,13 +1142,13 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
int n_scan_lines, n_ph_lines, n_pixels;
// New - writing WOI width for internally generated HACT
// New - writing WOI width for internally generated HACT
n_pixels=((thispars->pars[P_ACTUAL_WIDTH]+X313_MARGINS) & 0x3fff) | 0x4000;
X3X3_SEQ_SEND1 (fpga_addr, X313_WA_NLINES, n_pixels);
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_NLINES, (int) n_pixels));
// Program number of scan lines to acquire
// Is PhotoFinish mode enabled? // **************** TODO: use ACTUAL_HEIGHT (and update it) not WOI_HEIGHT
// Program number of scan lines to acquire
// Is PhotoFinish mode enabled? // **************** TODO: use ACTUAL_HEIGHT (and update it) not WOI_HEIGHT
if (((thispars->pars[P_PF_HEIGHT] & 0xffff)>0) && (thispars->pars[P_PF_HEIGHT]<=thispars->pars[P_ACTUAL_HEIGHT])){
n_ph_lines= thispars->pars[P_ACTUAL_HEIGHT]/(thispars->pars[P_PF_HEIGHT] & 0x3fff);
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_NLINES, (int) (n_ph_lines-1) | 0x8000));
......@@ -1114,7 +1157,7 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
n_scan_lines= thispars->pars[P_ACTUAL_HEIGHT]; // no margins here
} else {
// temporary hack trying to disable PH mode earlier
// temporary hack trying to disable PH mode earlier
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", X313_SEQ_ASAP, X313_WA_NLINES, 0x8000));
X3X3_SEQ_SEND1 (X313_SEQ_ASAP, X313_WA_NLINES, 0x8000);
......@@ -1124,7 +1167,7 @@ int pgm_sensorin (int sensor_port, ///< sensor port number (0..3
n_scan_lines&=0x3fff;
X3X3_SEQ_SEND1 (fpga_addr, X313_WA_NLINES, n_scan_lines);
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_NLINES, (int) n_scan_lines));
// Bayer phase changed?
// Bayer phase changed?
int flips=(thispars->pars[P_FLIPH] & 1) | ((thispars->pars[P_FLIPV] & 1)<<1);
int bayer_modified=FRAMEPAR_MODIFIED(P_BAYER) || FRAMEPAR_MODIFIED(P_FLIPH) || FRAMEPAR_MODIFIED(P_FLIPV) || FRAMEPAR_MODIFIED(P_MULTI_MODE);
......@@ -1157,9 +1200,9 @@ int pgm_sensorrun (int sensor_port, ///< sensor port number (0..3
///< @return OK - 0, <0 - error
{
int fpga_data=0;
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int fpga_data=0;
switch (thispars->pars[P_SENSOR_RUN] & 3) {
case 1: fpga_data=4; break;
case 2:
......@@ -1167,7 +1210,7 @@ int pgm_sensorrun (int sensor_port, ///< sensor port number (0..3
}
#if NC353
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
// only start/single, stopping will be handled by the pgm_sensorstop
// only start/single, stopping will be handled by the pgm_sensorstop
if (fpga_data) {
X3X3_SEQ_SEND1(fpga_addr, X313_WA_TRIG, fpga_data);
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_TRIG, (int) fpga_data));
......@@ -1187,9 +1230,9 @@ int pgm_sensorstop (int sensor_port, ///< sensor port number (0..3
///< @return OK - 0, <0 - error
{
int fpga_data=0;
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
int fpga_data=0;
switch (thispars->pars[P_SENSOR_RUN] & 3) {
case 1: fpga_data=4; break;
case 2:
......@@ -1197,7 +1240,7 @@ int pgm_sensorstop (int sensor_port, ///< sensor port number (0..3
}
#if NC353
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
// only start/single, stopping will be handled by the pgm_sensorstop
// only start/single, stopping will be handled by the pgm_sensorstop
if ((thispars->pars[P_SENSOR_RUN] & 3)==0){
X3X3_SEQ_SEND1(fpga_addr, X313_WA_TRIG, fpga_data);
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_TRIG, (int) fpga_data));
......@@ -1209,7 +1252,7 @@ int pgm_sensorstop (int sensor_port, ///< sensor port number (0..3
/** Program gamma table
* Table with the same hash should be available in cache. It is very unlikely
* but is still possible that it can be pushed out - TODO: make it guaranteed. So normally new gamma table is
* set through a chracter device driver (with FPGA bit set to get locked?) and then pgm_gamma is activated when
* set through a charcter device driver (with FPGA bit set to get locked?) and then pgm_gamma is activated when
* the P_GTAB_R (*_G,*_GB, *_B) are updated
* The scale part of these parameters (lower 16 bits) may be modified by white balancing code without loading a new table
*
......@@ -1226,18 +1269,6 @@ int pgm_gamma (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
MDF3(printk(" frame16=%d, (getThisFrameNumber() & PARS_FRAMES_MASK)= %ld\n",frame16, getThisFrameNumber() & PARS_FRAMES_MASK));
MDF3(printk(" frame16=%d, thispars->pars[P_GTAB_*]=0x%lx 0x%lx 0x%lx 0x%lx, thispars->pars[P_FRAME]=0x%lx"
" get_locked_hash32(*)=0x%lx 0x%lx 0x%lx 0x%lx\n",
frame16, thispars->pars[P_GTAB_R],thispars->pars[P_GTAB_R+1],thispars->pars[P_GTAB_R+2],thispars->pars[P_GTAB_R+3],thispars->pars[P_FRAME],
get_locked_hash32(0),get_locked_hash32(1),get_locked_hash32(2),get_locked_hash32(3)));
MDF16(printk(" frame16=%d, thispars->pars[P_GTAB_*]=0x%lx 0x%lx 0x%lx 0x%lx, thispars->pars[P_FRAME]=0x%lx\n",frame16, thispars->pars[P_GTAB_R],thispars->pars[P_GTAB_R+1],thispars->pars[P_GTAB_R+2],thispars->pars[P_GTAB_R+3],thispars->pars[P_FRAME]));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// Not needed - now it can be done in advance (just prepare cache). Later it will be done again and actually programmed (1 frame ahead of time)
// return if too early
// TODO: still calculate FPGA table , but not load it if too early?
int color, rslt;
struct frameparspair_t pars_to_update[4]; // 4 needed
int nupdate=0;
......@@ -1246,9 +1277,23 @@ get_locked_hash32(0),get_locked_hash32(1),get_locked_hash32(2),get_locked_hash32
unsigned short hash16;
} gamma32;
unsigned long * pgamma32= (unsigned long *) & gamma32;
// TODO: Add for multi-subchannel, for now using 0
MDF3(printk(" frame16=%d, (getThisFrameNumber() & PARS_FRAMES_MASK)= %ld\n",frame16, getThisFrameNumber() & PARS_FRAMES_MASK));
MDF3(printk(" frame16=%d, thispars->pars[P_GTAB_*]=0x%lx 0x%lx 0x%lx 0x%lx, thispars->pars[P_FRAME]=0x%lx"
" get_locked_hash32(*)=0x%lx 0x%lx 0x%lx 0x%lx\n",
frame16, thispars->pars[P_GTAB_R],thispars->pars[P_GTAB_R+1],thispars->pars[P_GTAB_R+2],thispars->pars[P_GTAB_R+3],thispars->pars[P_FRAME],
get_locked_hash32(0),get_locked_hash32(1),get_locked_hash32(2),get_locked_hash32(3)));
MDF16(printk(" frame16=%d, thispars->pars[P_GTAB_*]=0x%lx 0x%lx 0x%lx 0x%lx, thispars->pars[P_FRAME]=0x%lx\n",frame16, thispars->pars[P_GTAB_R],thispars->pars[P_GTAB_R+1],thispars->pars[P_GTAB_R+2],thispars->pars[P_GTAB_R+3],thispars->pars[P_FRAME]));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// Not needed - now it can be done in advance (just prepare cache). Later it will be done again and actually programmed (1 frame ahead of time)
// return if too early
// TODO: still calculate FPGA table , but not load it if too early?
for (color=0; color<4; color++) {
if (get_locked_hash32(color)!=thispars->pars[P_GTAB_R+color]) { // modified for this color
if (get_locked_hash32(color,sensor_port,0)!=thispars->pars[P_GTAB_R+color]) { // modified for this color
*pgamma32=thispars->pars[P_GTAB_R+color];
rslt=set_gamma_table (gamma32.hash16,
gamma32.scale, NULL,
......@@ -1256,11 +1301,11 @@ get_locked_hash32(0),get_locked_hash32(1),get_locked_hash32(2),get_locked_hash32
color,
sensor_port,
0); // frame16 - one ahead of the current do not lock yet TODO 393 multisensor - split gamma tables to subchannels
if (rslt<=0) SETFRAMEPARS_SET(P_GTAB_R+color, get_locked_hash32(color)); // increases nupdate
if (rslt<=0) SETFRAMEPARS_SET(P_GTAB_R+color, get_locked_hash32(color,sensor_port, 0)); // increases nupdate
}
}
if (nupdate) {
setFramePars(thispars, nupdate, pars_to_update); // restore failed components
setFramePars(sensor_port, thispars, nupdate, pars_to_update); // restore failed components
MDF3(printk("had to restore back %d gamma tables (color components) \n",nupdate));
return -1;
}
......@@ -1294,8 +1339,8 @@ int pgm_hist (int sensor_port, ///< sensor port number (0..3
};
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
// calculate absolute window from the relative, apply limits
// int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
// calculate absolute window from the relative, apply limits
hist_setup_data.width= ((thispars->pars[P_HISTWND_RWIDTH] * thispars->pars[P_ACTUAL_WIDTH])>>16) & 0xffe;
if (hist_setup_data.width<2) hist_setup_data.width=2;
else if (hist_setup_data.width > thispars->pars[P_ACTUAL_WIDTH]) hist_setup_data.width = thispars->pars[P_ACTUAL_WIDTH];
......@@ -1312,7 +1357,7 @@ int pgm_hist (int sensor_port, ///< sensor port number (0..3
(hist_setup_data.width != thispars->pars[P_HISTWND_WIDTH]) ||
(hist_setup_data.top != thispars->pars[P_HISTWND_TOP]) ||
(hist_setup_data.height != thispars->pars[P_HISTWND_HEIGHT])) {
// set these values to FPGA
// set these values to FPGA
#ifdef NC353
X3X3_SEQ_SEND1(frame16, X313_WA_HIST_LEFT, hist_setup_data.left);
X3X3_SEQ_SEND1(frame16, X313_WA_HIST_WIDTH, hist_setup_data.width-2);
......@@ -1327,7 +1372,7 @@ int pgm_hist (int sensor_port, ///< sensor port number (0..3
pars_to_update[1].val=hist_setup_data.width;
pars_to_update[2].val=hist_setup_data.top;
pars_to_update[3].val=hist_setup_data.height;
setFramePars(thispars, 4, pars_to_update); // save intermediate/readonly parameters
setFramePars(sensor_port, thispars, 4, pars_to_update); // save intermediate/readonly parameters
}
return 0;
}
......@@ -1343,7 +1388,7 @@ int pgm_aexp (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
//TODO:
//TODO:
MDF3(printk(" frame16=%d\n",frame16));
return 0;
}
......@@ -1358,25 +1403,25 @@ int pgm_quality (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
MDF3(printk(" frame16=%d\n",frame16));
int y_coring_index;
int c_coring_index;
int composite_quality=(thispars->pars[P_QUALITY] & 0xff7f) | ((thispars->pars[P_PORTRAIT] & 1)<<7);
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
// int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
if (thispars->pars[P_CORING_INDEX]!= prevpars->pars[P_CORING_INDEX]) {
y_coring_index= thispars->pars[ P_CORING_INDEX] & 0xffff;
c_coring_index=(thispars->pars[ P_CORING_INDEX]>>16) & 0xffff;
if (c_coring_index==0) c_coring_index=y_coring_index;
set_coring_fpga(y_coring_index, 0);
set_coring_fpga(c_coring_index, 1);
set_coring_fpga(y_coring_index, 0, sensor_port);
set_coring_fpga(c_coring_index, 1, sensor_port);
}
// calculate quality tables - find already programmed FPGA page or calculates/programms a new one
// set_qtable_fpga returns table page (0..7) or -1 - invalid q
// calculate quality tables - find already programmed FPGA page or calculates/programms a new one
// set_qtable_fpga returns table page (0..7) or -1 - invalid q
if ((thispars->pars[P_COMPMOD_QTAB]=set_qtable_fpga(composite_quality))>=0) {
// X3X3_SEQ_SEND1(frame16, X313_WA_COMP_CMD, COMPCMD_QTAB(thispars->pars[P_COMPMOD_QTAB]));
if ((thispars->pars[P_COMPMOD_QTAB]=set_qtable_fpga(composite_quality, sensor_port))>=0) {
// X3X3_SEQ_SEND1(frame16, X313_WA_COMP_CMD, COMPCMD_QTAB(thispars->pars[P_COMPMOD_QTAB]));
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_COMP_CMD, (int) COMPCMD_QTAB(thispars->pars[P_COMPMOD_QTAB])));
return 0;
} else return -1;
......@@ -1398,18 +1443,18 @@ int pgm_memsensor (int sensor_port, ///< sensor port number (
#ifdef NC353
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
#endif
///programm channel1 (FPN). Will not enable if not needed (imageParamsR[P_FPN]==0)
///programm channel1 (FPN). Will not enable if not needed (imageParamsR[P_FPN]==0)
ntilex=((thispars->pars[P_ACTUAL_WIDTH]+X313_MARGINS+7)>>3);
ntiley=thispars->pars[P_ACTUAL_HEIGHT]+(((thispars->pars[P_PF_HEIGHT] & 0xffff)>0)?0:X313_MARGINS);
MDF3(printk("ntilex=0x%x ntiley=0x%x\n",ntilex,ntiley));
if ((thispars->pars[P_PF_HEIGHT] & 0xffff)==0) { // not a photofinish
if(!thispars->pars[P_BGFRAME] && ((thispars->pars[P_FPNS]!=0) || (thispars->pars[P_FPNM]!=0))) {
// program memory channel1
// program memory channel1
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SDCH1_CTL1, X313_SDCHAN_REG1(0,0,0, X313_MAP_FPN, (ntilex-1), (ntiley-1)));
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SDCH1_CTL2, X313_SDCHAN_REG2(0,0,0, X313_MAP_FPN, (ntilex-1), (ntiley-1)));
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SDCH1_CTL0, X313_SDCHAN_REG0(0,0,0, X313_MAP_FPN, (ntilex-1), (ntiley-1)));
// enable channel1 for reading SDRAM
// enable channel1 for reading SDRAM
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SD_MODE, X313_CHN_EN_D(1)); // wait ready later... ???
#endif
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_SDCH1_CTL1, (int) X313_SDCHAN_REG1(0,0,0, X313_MAP_FPN, (ntilex-1), (ntiley-1))));
......@@ -1429,12 +1474,12 @@ int pgm_memsensor (int sensor_port, ///< sensor port number (
#endif
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_SD_MODE, (int) X313_CHN_DIS_D(1)));
}
// Program channel 0 (sensor->memory)
// goodEOL=0; // last 8/16 blocks of pixels in each scanline are bad (only 2 are actually written)
// if 8-bit mode we'll need to update ntilex. fpga tries to write 2 bytes more (but not crossing the page boundaries
// GoodEOL - if image width is multiple of 512 pixels 1 extra block (16 pixels) needs to be written to memory (and padlen will be more by 512 bytes (256 words)
// due to FPGA controller implementation (it writes extra 4 pixels for the margins, but not when it crosses 512 byte boundary)
// When reading 20x20 macroblocks to the compressor, such exception is not needed, it crosses page boundaries when needed
// Program channel 0 (sensor->memory)
// goodEOL=0; // last 8/16 blocks of pixels in each scanline are bad (only 2 are actually written)
// if 8-bit mode we'll need to update ntilex. fpga tries to write 2 bytes more (but not crossing the page boundaries
// GoodEOL - if image width is multiple of 512 pixels 1 extra block (16 pixels) needs to be written to memory (and padlen will be more by 512 bytes (256 words)
// due to FPGA controller implementation (it writes extra 4 pixels for the margins, but not when it crosses 512 byte boundary)
// When reading 20x20 macroblocks to the compressor, such exception is not needed, it crosses page boundaries when needed
if ((thispars->pars[P_BITS]==8) && (!thispars->pars[P_BGFRAME])) { // in 16-bit mode ntilex will stay the same
ntilex=((thispars->pars[P_ACTUAL_WIDTH]+X313_MARGINS+15)>>4);
......@@ -1444,14 +1489,14 @@ int pgm_memsensor (int sensor_port, ///< sensor port number (
}
MDF3(printk("ntilex=0x%x ntiley=0x%x\n",ntilex,ntiley));
// if (imageParamsR[P_OVERLAP]>=(imageParamsR[P_ACTUAL_HEIGHT]+2)) imageParamsR[P_OVERLAP]=imageParamsR[P_ACTUAL_HEIGHT]+1; rotten code, left as a comment
// if (imageParamsR[P_OVERLAP]>=(imageParamsR[P_ACTUAL_HEIGHT]+2)) imageParamsR[P_OVERLAP]=imageParamsR[P_ACTUAL_HEIGHT]+1; rotten code, left as a comment
if (thispars->pars[P_OVERLAP]>0) ntiley=(ntiley<<1); // ntiley will be twice bigger for synch. mode)
padlen=((ntilex+31)>>5) << 8;
//TODO:fix it to be able to use two (or larger) frame buffer
// imgsz=((padlen * (thispars->pars[P_ACTUAL_HEIGHT]+X313_MARGINS) * thispars->pars[P_PAGE_ACQ]) << ((thispars->pars(P_TRIG) & 1)?1:0)); // mostly rotten too
//TODO:fix it to be able to use two (or larger) frame buffer
// imgsz=((padlen * (thispars->pars[P_ACTUAL_HEIGHT]+X313_MARGINS) * thispars->pars[P_PAGE_ACQ]) << ((thispars->pars(P_TRIG) & 1)?1:0)); // mostly rotten too
imgsz=padlen * ntiley;
MDF3(printk("imgsz=0x%x, padlen=0x%x\n",imgsz,padlen));
if (thispars->pars[P_IMGSZMEM]!= imgsz) setFramePar(thispars, P_IMGSZMEM, imgsz); // set it (and propagate to the later frames)
if (thispars->pars[P_IMGSZMEM]!= imgsz) setFramePar(sensor_port, thispars, P_IMGSZMEM, imgsz); // set it (and propagate to the later frames)
#ifdef NC353
sa=X313_MAP_FRAME + (imgsz * thispars->pars[P_PAGE_ACQ]); // now - always X313_MAP_FRAME
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SDCH0_CTL1, X313_SDCHAN_REG1(0,1,1, sa, (ntilex-1), (ntiley-1)));
......@@ -1463,7 +1508,7 @@ int pgm_memsensor (int sensor_port, ///< sensor port number (
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SD_MODE, X313_CHN_EN_D(0));
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_SD_MODE, (int) X313_CHN_EN_D(0) ));
#endif
// number of scan lines to read from sensor - program in pgm_sensorin
// number of scan lines to read from sensor - program in pgm_sensorin
return 0;
}
......@@ -1480,8 +1525,10 @@ int pgm_memcompressor (int sensor_port, ///< sensor port number (
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
//TODO: redo for nc393
#ifdef NC353
int ntilex,ntiley,sa,pf;
// struct frameparspair_t * pars_to_update[4]={
// struct frameparspair_t * pars_to_update[4]={
struct frameparspair_t pars_to_update[4]={
{P_SDRAM_CHN20, 0},
{P_SDRAM_CHN21, 0},
......@@ -1490,7 +1537,7 @@ int pgm_memcompressor (int sensor_port, ///< sensor port number (
};
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
// int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
ntilex=((thispars->pars[P_ACTUAL_WIDTH]+X313_MARGINS-1)>>4);
ntiley=thispars->pars[P_ACTUAL_HEIGHT]; // number of lines it the whole frame
#ifdef NC353
......@@ -1499,14 +1546,15 @@ int pgm_memcompressor (int sensor_port, ///< sensor port number (
pf=((thispars->pars[P_PF_HEIGHT] & 0xffff)>0)?1:0; // when mode==1, wnr means "photofinish" in fpga
int depend=((thispars->pars[P_SENSOR_RUN] & 3)==SENSOR_RUN_STOP) ? 0 : 1;
MDF23(printk("ntilex=0x%x ntiley=0x%x sa=0x%x pf=0x%x depend=%x\n",ntilex,ntiley,sa,pf,depend));
// will be programmed with "depend==1", so it will not be possible to re-read from memory this way
// will be programmed with "depend==1", so it will not be possible to re-read from memory this way
MDF9(printk(" thispars->pars[P_SENSOR_RUN]=0x%x, depend=%d)\n", (int)thispars->pars[P_SENSOR_RUN], depend));
pars_to_update[1].val=X313_SDCHAN_REG1(1,pf,depend, sa, (ntilex-1), (ntiley-16));
pars_to_update[2].val=X313_SDCHAN_REG2(1,pf,depend, sa, (ntilex-1), (ntiley-16));
pars_to_update[0].val=X313_SDCHAN_REG0(1,pf,depend, sa, (ntilex-1), (ntiley-16));
pars_to_update[3].val=ntilex*(ntiley>>4);
setFramePars(thispars, 4, pars_to_update);
setFramePars(sensor_port, thispars, 4, pars_to_update);
#endif
return 0;
}
......@@ -1521,18 +1569,14 @@ int pgm_compmode (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
MDF3(printk(" frame16=%d\n",frame16));
if (!jpeg_htable_is_programmed()) jpeg_htable_fpga_pgm ();
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
#ifdef NC353
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
#endif
int comp_cmd=0;
struct frameparspair_t pars_to_update[4]; // 2 needed, increase if more entries will be added
int nupdate=0;
// QTAB is programmed separately
// demosaic mode - is it changed?
MDF3(printk(" frame16=%d\n",frame16));
if (!jpeg_htable_is_programmed(sensor_port)) jpeg_htable_fpga_pgm (sensor_port);
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// QTAB is programmed separately
// demosaic mode - is it changed?
if (FRAMEPAR_MODIFIED(P_COLOR)) {
switch (thispars->pars[P_COLOR] & 0x0f){
case COLORMODE_MONO6: comp_cmd |= COMPCMD_DEMOS(DEMOS_MONO6); break;
......@@ -1549,29 +1593,31 @@ int pgm_compmode (int sensor_port, ///< sensor port number (0..3
case COLORMODE_MONO4: comp_cmd |= COMPCMD_DEMOS(DEMOS_MONO4); break;
}
}
// TODO: Redo for NC393
#ifdef NC353
MDF3(printk("comp_cmd=0x%x\n",comp_cmd));
// Bayer shift changed? (additional bayer shift, separate from the gamma-tables one)
// Bayer shift changed? (additional bayer shift, separate from the gamma-tables one)
if (FRAMEPAR_MODIFIED(P_COMPMOD_BYRSH)) {
comp_cmd |= COMPCMD_BAYERSHIFT(thispars->pars[P_COMPMOD_BYRSH]);
}
// Tile shift changed? (position of the 16x16, 18x8 or 20x20 inside 20x20 overlapping tile - dx==dy (diagonal), 0..4)
// Tile shift changed? (position of the 16x16, 18x8 or 20x20 inside 20x20 overlapping tile - dx==dy (diagonal), 0..4)
if (FRAMEPAR_MODIFIED(P_COMPMOD_TILSH)) {
comp_cmd |= COMPCMD_TILESHIFT(thispars->pars[P_COMPMOD_TILSH]);
}
// DC subtraction modse changed? (mostly FPGA debug feature, normally should be on - average block level to bypass DCT conversion)
// DC subtraction modse changed? (mostly FPGA debug feature, normally should be on - average block level to bypass DCT conversion)
if (FRAMEPAR_MODIFIED(P_COMPMOD_DCSUB)) {
comp_cmd |= COMPCMD_DCSUB(thispars->pars[P_COMPMOD_DCSUB]);
}
// Did focus show mode change? (do it here, not with other focus parameters that can not be set through the sequencer (writing tables
// could break writing gamma/quntization/whatever tables
// Did focus show mode change? (do it here, not with other focus parameters that can not be set through the sequencer (writing tables
// could break writing gamma/quntization/whatever tables
if (FRAMEPAR_MODIFIED(P_FOCUS_SHOW)) {
comp_cmd |= COMPCMD_FOCUS(thispars->pars[ P_FOCUS_SHOW]);
}
// enqueue it for the compressor
// enqueue it for the compressor
if (comp_cmd) {
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_COMP_CMD, comp_cmd);
......@@ -1580,7 +1626,7 @@ int pgm_compmode (int sensor_port, ///< sensor port number (0..3
} else {
MDF3(printk(" comp_cmd==0, does not need to be sent\n"));
}
// color saturation changed?
// color saturation changed?
if (FRAMEPAR_MODIFIED(P_COLOR_SATURATION_BLUE) || FRAMEPAR_MODIFIED(P_COLOR_SATURATION_RED)) {
int csb=(thispars->pars[P_COLOR_SATURATION_BLUE]* DEFAULT_COLOR_SATURATION_BLUE)/100;
int csr=(thispars->pars[P_COLOR_SATURATION_RED] * DEFAULT_COLOR_SATURATION_RED)/100;
......@@ -1600,8 +1646,8 @@ int pgm_compmode (int sensor_port, ///< sensor port number (0..3
}
// compressor quantizer zero bin mode changed?
// Quantizer tuning - bits 0..7 - zero bin, 15:8 - quantizer bias
// compressor quantizer zero bin mode changed?
// Quantizer tuning - bits 0..7 - zero bin, 15:8 - quantizer bias
if (FRAMEPAR_MODIFIED(P_CORING_PAGE)) {
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_QUANTIZER_MODE,thispars->pars[P_CORING_PAGE]);
......@@ -1609,7 +1655,8 @@ int pgm_compmode (int sensor_port, ///< sensor port number (0..3
MDF9(printk(" X3X3_SEQ_SEND1(0x%x, 0x%x, 0x%x)\n", (int)fpga_addr, (int)X313_WA_QUANTIZER_MODE, (int)thispars->pars[P_CORING_PAGE]));
}
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); // save changes, schedule functions
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
#endif
return 0;
}
......@@ -1633,7 +1680,7 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
long filter_no;
long show1;
} focus_setup_data;
// struct frameparspair_t * pars_to_update[5]={
// struct frameparspair_t * pars_to_update[5]={
struct frameparspair_t pars_to_update[5]={
{P_FOCUS_TOTWIDTH, 0},
{P_FOCUS_LEFT, 0},
......@@ -1645,7 +1692,7 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
if (frame16 >= 0) return -1; // now can only programm in immediate mode by writing the table
focus_setup_data.totalwidth=(thispars->pars[P_ACTUAL_WIDTH]& 0xfff0) -0x10; // anyway should be 16x
focus_setup_data.show1= thispars->pars[P_FOCUS_SHOW1];
// calculate absolute window from the relative, apply limits
// calculate absolute window from the relative, apply limits
focus_setup_data.left= ((((thispars->pars[P_RFOCUS_LEFT] * (0x10000-thispars->pars[P_RFOCUS_WIDTH])) >>16)* thispars->pars[P_ACTUAL_WIDTH])>>16) & 0xff8;
focus_setup_data.right=(focus_setup_data.left+((thispars->pars[P_RFOCUS_WIDTH]*thispars->pars[P_ACTUAL_WIDTH])>>16) -8);
if (focus_setup_data.right<0) {
......@@ -1669,14 +1716,17 @@ int pgm_focusmode (int sensor_port, ///< sensor port number (0..3
(focus_setup_data.bottom != (focus_setup_data.top+thispars->pars[P_FOCUS_HEIGHT] -8)) ||
FRAMEPAR_MODIFIED(P_FOCUS_FILTER) ||
FRAMEPAR_MODIFIED(P_FOCUS_SHOW1) ) {
// TODO: Redo for nc393
#ifdef NC353
fpga_table_write_nice (CX313_FPGA_TABLES_FOCUSPARS, sizeof(focus_setup_data)/sizeof(focus_setup_data.left), (unsigned long *) &focus_setup_data);
#endif
pars_to_update[0].val=focus_setup_data.totalwidth;
pars_to_update[1].val=focus_setup_data.left;
pars_to_update[2].val=focus_setup_data.right-focus_setup_data.left+8;
pars_to_update[3].val=focus_setup_data.top;
pars_to_update[4].val=focus_setup_data.bottom-focus_setup_data.top+8;
setFramePars(thispars, 5, pars_to_update); // save intermediate/readonly parameters
setFramePars(sensor_port, thispars, 5, pars_to_update); // save intermediate/readonly parameters
}
return 0;
}
......@@ -1688,8 +1738,8 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
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
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
struct frameparspair_t pars_to_update[10]; // ??? needed, increase if more entries will be added
int nupdate=0;
......@@ -1697,21 +1747,21 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
if (frame16 >= 0) return -1; // ASAP only mode
// Trigger condition changed? (0 - internal sequencer)
// Trigger condition changed? (0 - internal sequencer)
if (FRAMEPAR_MODIFIED(P_TRIG_CONDITION)) {
#ifdef NC353
port_csp0_addr[X313_WA_CAMSYNCTRIG] = thispars->pars[P_TRIG_CONDITION];
#endif
MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_CAMSYNCTRIG, (int)thispars->pars[P_TRIG_CONDITION]));
}
// Trigger delay changed?
// Trigger delay changed?
if (FRAMEPAR_MODIFIED(P_TRIG_DELAY)) {
#ifdef NC353
port_csp0_addr[X313_WA_CAMSYNCDLY] = thispars->pars[P_TRIG_DELAY];
#endif
MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_CAMSYNCDLY, (int) thispars->pars[P_TRIG_DELAY]));
}
// Sequencer output word changed? (to which outputs it is sent and what polarity)
// Sequencer output word changed? (to which outputs it is sent and what polarity)
if (FRAMEPAR_MODIFIED(P_TRIG_OUT)) {
#ifdef NC353
port_csp0_addr[X313_WA_CAMSYNCOUT] = thispars->pars[P_TRIG_OUT];
......@@ -1724,12 +1774,12 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
#endif
MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_IOPINS, (int) X313_WA_IOPINS_EN_TRIG_OUT));
} else {
// Not needed, I think
// port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_DIS_TRIG_OUT;
// MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_IOPINS, (int) X313_WA_IOPINS_DIS_TRIG_OUT));
// Not needed, I think
// port_csp0_addr[X313_WA_IOPINS] = X313_WA_IOPINS_DIS_TRIG_OUT;
// MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_IOPINS, (int) X313_WA_IOPINS_DIS_TRIG_OUT));
}
}
// Sequencer period changed? (0 - stopped, 1 - single trigger, >=256 - start repetitive)
// Sequencer period changed? (0 - stopped, 1 - single trigger, >=256 - start repetitive)
if (FRAMEPAR_MODIFIED(P_TRIG_PERIOD)) {
if (unlikely((thispars->pars[P_TRIG_PERIOD] > 1) && (thispars->pars[P_TRIG_PERIOD] < 256))) { // Wrong value, restore old one
SETFRAMEPARS_SET(P_TRIG_PERIOD,prevpars->pars[P_TRIG_PERIOD]);
......@@ -1740,7 +1790,7 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_CAMSYNCPER, (int)thispars->pars[P_TRIG_PERIOD]));
}
}
// Bit length changed or not yet initialized?
// Bit length changed or not yet initialized?
if (FRAMEPAR_MODIFIED(P_TRIG_BITLENGTH) || (thispars->pars[P_TRIG_BITLENGTH]==0)) {
d=thispars->pars[P_TRIG_BITLENGTH];
if (unlikely((d<2) || (d>255))) { // Wrong value, restore old one
......@@ -1752,21 +1802,21 @@ int pgm_trigseq (int sensor_port, ///< sensor port number (0..3
#endif
MDF3(printk("writing bit length-1: port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_CAMSYNCPER, d));
}
// P_EXTERN_TIMESTAMP changed? (0 - internal sequencer)
// P_EXTERN_TIMESTAMP changed? (0 - internal sequencer)
if (FRAMEPAR_MODIFIED(P_EXTERN_TIMESTAMP)) {
#ifdef NC353
port_csp0_addr[X313_WA_DCR1]=X353_DCR1(EXTERNALTS,thispars->pars[P_EXTERN_TIMESTAMP]?1:0);
#endif
MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_DCR1, (int)X353_DCR1(EXTERNALTS,thispars->pars[P_EXTERN_TIMESTAMP]?1:0)));
}
// P_XMIT_TIMESTAMP changed? (0 - internal sequencer)
// P_XMIT_TIMESTAMP changed? (0 - internal sequencer)
if (FRAMEPAR_MODIFIED(P_XMIT_TIMESTAMP)) {
#ifdef NC353
port_csp0_addr[X313_WA_DCR1]=X353_DCR1(OUTPUTTS,thispars->pars[P_XMIT_TIMESTAMP]?1:0);
#endif
MDF3(printk(" port_csp0_addr[0x%x]=0x%x\n", (int) X313_WA_DCR1, (int)X353_DCR1(OUTPUTTS,thispars->pars[P_XMIT_TIMESTAMP]?1:0)));
}
if (nupdate) setFramePars(thispars, nupdate, pars_to_update); // save changes, schedule functions
if (nupdate) setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
return 0;
}
......@@ -1785,10 +1835,10 @@ int pgm_irq (int sensor_port, ///< sensor port number (0..3)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
#ifdef NC353
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
/** temporary make "smart" IRQ always enabled (otherwise FPGA bug fix needed)
/** temporary make "smart" IRQ always enabled (otherwise FPGA bug fix needed)
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SMART_IRQ, (2 | ((thispars->pars[P_IRQ_SMART] & 1)?1:0)) | \
(8 | ((thispars->pars[P_IRQ_SMART] & 2)?4:0)));
*/
*/
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SMART_IRQ, (2 | ((thispars->pars[P_IRQ_SMART] & 1)?1:0)) | \
(8 | ((thispars->pars[P_IRQ_SMART] & 2)?4:0)));
......@@ -1834,7 +1884,7 @@ int pgm_recalcseq (int sensor_port, ///< sensor port number (0..3
for (i=2; i>=0; i--) {
pars[i].val |= pars[i+1].val;
}
// moved all these parameters to "frame zero" (static)
// moved all these parameters to "frame zero" (static)
GLOBALPARS(sensor_port, G_CALLNEXT+1)=pars[0].val;
GLOBALPARS(sensor_port, G_CALLNEXT+2)=pars[1].val;
GLOBALPARS(sensor_port, G_CALLNEXT+3)=pars[2].val;
......@@ -1858,7 +1908,7 @@ int pgm_comprestart(int sensor_port, ///< sensor port number (0..3
{
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
// does it need to be be started (nothing do be done to stop)
// does it need to be be started (nothing do be done to stop)
if (thispars->pars[P_COMPRESSOR_RUN]==0) return 0; // does not need comporessor to be started
#ifdef NC353
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
......@@ -1873,17 +1923,17 @@ int pgm_comprestart(int sensor_port, ///< sensor port number (0..3
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_SDCH2_CTL2, (int) thispars->pars[P_SDRAM_CHN22]));
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_SDCH2_CTL0, (int) thispars->pars[P_SDRAM_CHN20]));
// enable memory channel2
// enable memory channel2
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SD_MODE, X313_CHN_EN_D(0));
#endif
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_SD_MODE, (int) X313_CHN_EN_D(0)));
// set number of tiles to compressor
// set number of tiles to compressor
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_MCUNUM, thispars->pars[P_TILES]-1);
#endif
MDF3(printk(" X3X3_SEQ_SEND1(0x%x,0x%x, 0x%x)\n", fpga_addr, (int) X313_WA_MCUNUM, (int) thispars->pars[P_TILES]-1));
// start the compressor
// start the compressor
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_COMP_CMD, (thispars->pars[P_COMPRESSOR_RUN]==2) ? COMPCMD_RUN : COMPCMD_SINGLE);
#endif
......@@ -1891,8 +1941,7 @@ int pgm_comprestart(int sensor_port, ///< sensor port number (0..3
return 0;
}
/**
* @brief stop compressor when changing geometry
/** Stop compressor when changing geometry
* TODO: 353 - reimplement
*/
int pgm_compstop (int sensor_port, ///< sensor port number (0..3)
......@@ -1907,7 +1956,7 @@ int pgm_compstop (int sensor_port, ///< sensor port number (0..3
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
#endif
MDF3(printk(" frame16=%d\n",frame16));
// if (frame16 & ~PARS_FRAMES_MASK) return -1; // wrong frame (can be only -1 or 0..7)
// if (frame16 & ~PARS_FRAMES_MASK) return -1; // wrong frame (can be only -1 or 0..7)
if (frame16 >= PARS_FRAMES) return -1; // wrong frame (can be only -1 or 0..7)
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_COMP_CMD, COMPCMD_STOP);
......@@ -1932,18 +1981,18 @@ int pgm_compctl (int sensor_port, ///< sensor port number (0..3
int fpga_addr=(frame16 <0) ? X313_SEQ_ASAP : (X313_SEQ_FRAME0+frame16);
#endif
if ((prevpars->pars[P_COMPRESSOR_RUN]==0) && (thispars->pars[P_COMPRESSOR_RUN]!=0)) { // just started
// reset memory controller for the channel2 to the start of the frame
// reset memory controller for the channel2 to the start of the frame
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SDCH2_CTL1, thispars->pars[P_SDRAM_CHN21]);
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SDCH2_CTL2, thispars->pars[P_SDRAM_CHN22]);
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SDCH2_CTL0, thispars->pars[P_SDRAM_CHN20]);
#endif
// enable memory channel2 (NOTE: wnen is it disabled? does it need to be disabled?)
// enable memory channel2 (NOTE: wnen is it disabled? does it need to be disabled?)
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_SD_MODE, X313_CHN_EN_D(2));
#endif
// set number of tiles to compressor
// set number of tiles to compressor
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_MCUNUM, thispars->pars[P_TILES]-1);
#endif
......@@ -1965,14 +2014,19 @@ int pgm_compctl (int sensor_port, ///< sensor port number (0..3
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_COMP_CMD, COMPCMD_SINGLE);
#endif
//TODO: Update for NC393
#ifdef NC353
if (!x313_is_dma_on()) x313_dma_start();
#endif
MDF9(printk(" X3X3_SEQ_SEND1(0x%x, 0x%x, 0x%x)\n", (int)fpga_addr, (int) X313_WA_COMP_CMD, (int) COMPCMD_SINGLE));
break;
case COMPRESSOR_RUN_CONT:
#ifdef NC353
X3X3_SEQ_SEND1(fpga_addr, X313_WA_COMP_CMD, COMPCMD_RUN);
#endif
#ifdef NC353
if (!x313_is_dma_on()) x313_dma_start();
#endif
MDF9(printk(" X3X3_SEQ_SEND1(0x%x, 0x%x, 0x%x)\n", (int)fpga_addr, (int) X313_WA_COMP_CMD, (int) COMPCMD_RUN));
break;
}
......@@ -1991,6 +2045,7 @@ int pgm_gammaload (int sensor_port, ///< sensor port number (0..3
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
//TODO: make multi-subchannel, for now using the same gamma for all
struct frameparspair_t pars_to_update[4]; // 4 needed, increase if more entries will be added
int nupdate=0;
MDF3(printk(" frame16=%d, (getThisFrameNumber() & PARS_FRAMES_MASK)= %ld, thispars->pars[P_GTAB_R]=0x%lx, thispars->pars[P_FRAME]=0x%lx\n",frame16, getThisFrameNumber() & PARS_FRAMES_MASK, thispars->pars[P_GTAB_R],thispars->pars[P_FRAME]));
......@@ -2000,7 +2055,7 @@ int pgm_gammaload (int sensor_port, ///< sensor port number (0..3
#endif
MDF3(printk(" nextframe=%d, nextsparsd, nextspars->pars[P_GTAB_R]=0x%lx, nextspars->pars[P_FRAME]=0x%lx\n",(int) ((thispars->pars[P_FRAME]+1) & PARS_FRAMES_MASK), nextspars->pars[P_GTAB_R], nextspars->pars[P_FRAME]));
MDF16(printk(" nextframe=%d, nextspars->pars[P_GTAB_R]=0x%lx, nextspars->pars[P_FRAME]=0x%lx\n",(int) ((thispars->pars[P_FRAME]+1) & PARS_FRAMES_MASK), nextspars->pars[P_GTAB_R], nextspars->pars[P_FRAME]));
///NOTE: Yes, ASAP, but - 1 frame ahead
///NOTE: Yes, ASAP, but - 1 frame ahead
if (frame16 >= 0) return -1; // only can work in ASAP mode
int color, rslt;
struct {
......@@ -2010,12 +2065,12 @@ int pgm_gammaload (int sensor_port, ///< sensor port number (0..3
unsigned long * pgamma32= (unsigned long *) & gamma32;
unsigned long *gtable;
int need_pgm=0;
for (color=0; color<4; color++) if (get_locked_hash32(color)!=thispars->pars[P_GTAB_R+color]) need_pgm++;
// code currently does not allow to overwrite just 1 table - only all 4
for (color=0; color<4; color++) if (get_locked_hash32(color,sensor_port, 0)!=thispars->pars[P_GTAB_R+color]) need_pgm++;
// code currently does not allow to overwrite just 1 table - only all 4
if (need_pgm) {
for (color=0; color<4; color++) {
*pgamma32=thispars->pars[P_GTAB_R+color];
// Normally, nothing will be calculated in the next set_gamma_table() call
// Normally, nothing will be calculated in the next set_gamma_table() call
rslt=set_gamma_table (gamma32.hash16,
gamma32.scale,
NULL,
......@@ -2023,14 +2078,17 @@ int pgm_gammaload (int sensor_port, ///< sensor port number (0..3
color,
sensor_port,
0); // frame16 - one ahead of the current TODO 393 multisensor - split gamma tables to subchannels
// now gtable will be old one if result <=0 get_gamma_fpga(color) can return 0 only if nothing yet was programmed
// now gtable will be old one if result <=0 get_gamma_fpga(color) can return 0 only if nothing yet was programmed
//TODO: Update for NC393
#ifdef NC353
if ((gtable= get_gamma_fpga(color))) fpga_table_write_nice (CX313_FPGA_TABLES_GAMMA + (color * 256), 256, gtable);
if (rslt <= 0) SETFRAMEPARS_SET(P_GTAB_R+color, get_locked_hash32(color)); // restore to the locked table
#endif
if (rslt <= 0) SETFRAMEPARS_SET(P_GTAB_R+color, get_locked_hash32(color,sensor_port,0)); // restore to the locked table
}
MDF3(printk("need_pgm=%d, get_locked_hash32(*)=0x%lx 0x%lx 0x%lx 0x%lx\n",need_pgm,get_locked_hash32(0),get_locked_hash32(1),get_locked_hash32(2),get_locked_hash32(3)));
}
if (nupdate) {
setFramePars(thispars, nupdate, pars_to_update); // save changes, schedule functions
setFramePars(sensor_port, thispars, nupdate, pars_to_update); // save changes, schedule functions
MDF3(printk("had to restore back %d gamma tables (color components) \n",nupdate));
return -1;
}
......@@ -2060,10 +2118,10 @@ int pgm_sensorregs (int sensor_port, ///< sensor port number (0..3
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
{
MDF3(printk("frame16=%d\n",frame16)); // nothing here, all in multisensor.c
return 0;
}
}
......@@ -2079,7 +2137,7 @@ int pgm_prescal (int sensor_port, ///< sensor port number (
int frame16) ///< 4-bit (hardware) frame number parameters should
///< be applied to, negative - ASAP
///< @return OK - 0, <0 - error
{
{
MDF3(printk(" frame16=%d\n",frame16));
if (frame16 >= PARS_FRAMES) return -1; // wrong frame
#ifdef NC353
......
......@@ -40,16 +40,18 @@
#include "framepars.h"
#include "sensor_common.h"
//#include "pgm_functions.h"
#include "pgm_functions.h"
#include "circbuf.h"
#include "exif393.h"
//#include "histograms.h"
//#include "gamma_tables.h"
#include "histograms.h"
#include "gamma_tables.h"
#include "quantization_tables.h"
#include "x393_macro.h"
//#include "x393.h"
#include "x393.h"
#include "x393_helpers.h"
#include <asm/delay.h> // just for usleep1000()
/** @brief Driver name to display in log messages.*/
#define IMAGEACQ_DRIVER_NAME "Elphel (R) Model 393 Image Acquisition device driver"
......@@ -67,6 +69,18 @@ struct jpeg_ptr_t {
volatile unsigned int flags;
};
// just temporarily
void i2c_run(void) {}
void i2c_stop_wait(void){}
void udelay1000(int ms)
{
int i;
for (i=0;i<ms;i++) udelay(1000);
}
/** @brief Contains private data for the image acquisition driver */
struct image_acq_pd_t {
int minor; ///< Driver minor number
......@@ -410,26 +424,31 @@ inline struct interframe_params_t* updateIRQ_interframe(struct jpeg_ptr_t *jptr)
inline void updateIRQ_Exif(struct jpeg_ptr_t *jptr, struct interframe_params_t* interframe) {
unsigned char short_buff[2];
unsigned int sensor_port = jptr->chn_num;
int index_time = jptr->jpeg_wp - 11; if (index_time<0) index_time+=get_globalParam (sensor_port, G_CIRCBUFSIZE)>>2;
int index_time = jptr->jpeg_wp - 11;
char time_buff[27];
char * exif_meta_time_string;
int global_flips, extra_flips;
unsigned char orientations[]="1638274545273816";
unsigned char orientation_short[2];
int maker_offset;
if (index_time<0) index_time+=get_globalParam (sensor_port, G_CIRCBUFSIZE)>>2;
// struct exif_datetime_t
// calculates datetime([20] and subsec[7], returns pointer to char[27]
char time_buff[27];
char * 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]);
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]);
// 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);
//Exif_Photo_MakerNote
int global_flips=(get_imageParamsThis(sensor_port, P_FLIPH) & 1) | ((get_imageParamsThis(sensor_port, P_FLIPV)<<1) & 2);
int extra_flips=0;
global_flips=(get_imageParamsThis(sensor_port, P_FLIPH) & 1) | ((get_imageParamsThis(sensor_port, P_FLIPV)<<1) & 2);
extra_flips=0;
if (get_imageParamsThis(sensor_port, P_MULTI_MODE)!=0) {
extra_flips=get_imageParamsThis(sensor_port, P_MULTI_MODE_FLIPS);
global_flips=extra_flips & 3;
}
unsigned char orientations[]="1638274545273816";
unsigned char orientation_short[2];
orientation_short[0]=0;
orientation_short[1]=0xf & orientations[(get_imageParamsThis(sensor_port, P_PORTRAIT)&3) | (global_flips<<2)];
write_meta_irq(sensor_port, orientation_short, &meta_offsets.Image_Orientation, Exif_Image_Orientation, 2);
......@@ -441,7 +460,6 @@ 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
int maker_offset;
maker_offset=putlong_meta_irq(sensor_port, get_imageParamsThis(sensor_port, P_GAINR), &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);
......@@ -660,8 +678,8 @@ void tasklet_fpga_function(unsigned long arg) {
subchn,
prevFrameNumber,
(1 << COLOR_Y_NUMBER),
hash32p+hist_indx*16*(sizeof u32),
framep+hist_indx*32*(sizeof u32)); // 0x2 Green1
hash32p+hist_indx*16*sizeof (u32),
framep+hist_indx*32*sizeof (u32)); // 0x2 Green1
} else {
set_histograms (sensor_port, subchn, prevFrameNumber, (1 << COLOR_Y_NUMBER), hash32p, framep); // 0x2 Green1
}
......@@ -723,8 +741,8 @@ if (hist_en) {
subchn,
prevFrameNumber,
0xf, // all colors
hash32p+hist_indx*16*(sizeof u32),
framep+hist_indx*32*(sizeof u32)); // 0x2 Green1
hash32p+hist_indx*16*sizeof (u32),
framep+hist_indx*32*sizeof (u32)); // 0x2 Green1
} else {
set_histograms (sensor_port, subchn, prevFrameNumber, 0xf, hash32p, framep); // 0x2 Green1
}
......@@ -809,10 +827,10 @@ void camera_interrupts (int on) {
int image_acq_init(struct platform_device *pdev)
{
int i;
int res;
// int res;
unsigned int irq;
struct device *dev = &pdev->dev;
const struct of_device_id *match;
// const struct of_device_id *match;
const char *frame_sync_irq_names[4] = {"frame_sync_irq_0", "frame_sync_irq_1",
"frame_sync_irq_2", "frame_sync_irq_3"};
const char *compressor_irq_names[4] = {"compr_irq_0", "compr_irq_1",
......@@ -915,10 +933,10 @@ int legacy_i2c(int ports) ///< bitmask of the sensor ports to use
set_xi2c_wrc(&dev_sensor, sensor_port, dev_sensor.slave7, 0);
}
// Now register one page for reading 10359 and the sensor using sensor speed data
memcpy(&dev_sensor, class_sensor, sizeof(class_sensor));
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2, 0);
dev_sensor->data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4, 0);
memcpy(&dev_sensor, class_sensor, sizeof(dev_sensor));
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE2);
dev_sensor.data_bytes=4; // for reading 10359 in 32-bit mode
set_xi2c_rdc(&dev_sensor, sensor_port, LEGACY_READ_PAGE4);
}
return 0;
}
......
......@@ -121,6 +121,6 @@ long long get_frame_pos(unsigned int chn, unsigned int pos);
#define X3X3_I2C_RCV4(port,sa7,reg,datap) legacy_read_i2c_reg((port),(LEGACY_READ_PAGE4),(sa7),(reg),4,(datap))
int legacy_i2c (int ports);
void udelay1000(int ms);
#endif
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