Commit d9f09d9d authored by Andrey Filippov's avatar Andrey Filippov

added more Python modules to control hardware, some bug fixes

parent b13c86d4
......@@ -45,7 +45,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
*/
parameter CMPRS_AFIMUX_SA_LEN= 'h8, // .. 'hf
/*
27-bit "chunk" addresses and lengths. 1 chunk = 32 bytes, so 27 bit covers all 2^32 adderss range
27-bit "chunk" addresses and lengths. 1 chunk = 32 bytes, so 27 bit covers all 2^32 address range
8 .. 11 - per-channel start adddresses,
12 .. 15 - per-channel buffer lengths (will roll over to start address)
(0..3 - start addresses, 4..7 - lengths)
......
......@@ -127,7 +127,7 @@ module mult_saxi_wr #(
wire [127:0] data_in;
wire [3:0] pre_valid;
reg [3:0] valid;
reg [BRAM_A_WDTH-1:0] buf_wa; // multiplexed buffer write adderss
reg [BRAM_A_WDTH-1:0] buf_wa; // multiplexed buffer write address
reg [31:0] buf_wd; // multiplexed buffer write data
reg buf_we; // multiplexed buffer write enable
......@@ -136,7 +136,7 @@ module mult_saxi_wr #(
wire en_out_arb;
wire [1:0] re_cur_chn;
reg [BRAM_A_WDTH-1:0] buf_ra; // multiplexed buffer write adderss
reg [BRAM_A_WDTH-1:0] buf_ra; // multiplexed buffer write address
wire [31:0] inter_buf_data; // multiplexed buffer write data
reg [2:0] buf_re; // multiplexed buffer write enable
......
......@@ -228,7 +228,7 @@ module jp_channel#(
// wire [11:0] buf_ra; // buffer read address (2 MSB - page number)
wire [ 1:0] buf_rd; // buf {regen, re}
wire [ 7:0] buf_pxd; // 8-bit pixel data from the memory buffer
wire [11:0] buf_ra; // Memory buffer read adderss
wire [11:0] buf_ra; // Memory buffer read address
// signals connecting modules: chn_rd_buf_i and ???:
wire [ 7:0] mb_data_out; // Macroblock data out in scanline order
wire mb_pre_first_out; // Macroblock data out strobe - 1 cycle just before data valid
......
......@@ -85,8 +85,8 @@ def print_params(data,out_file_name):
print (", .INITP_%02X (256'h%064X)"%(i,v), file=out_file)
#print ('Number of arguments: %d'%(len(sys.argv)))
#print ('Argument List:%s'%(str(sys.argv)))
with open(sys.argv[1]) as file:
tokens=file.read().split()
with open(sys.argv[1]) as f:
tokens=f.read().split()
# print(lines)
#print (lines.split())
values=[]
......
......@@ -630,7 +630,7 @@
parameter RTC_ADDR= 'h704, // 'h707
parameter CAMSYNC_ADDR = 'h708, // 'h70f
parameter RTC_STATUS_REG_ADDR = 'h31, // (1 loc) address where status can be read out (currently just sequence # and alternating bit)
parameter RTC_SEC_USEC_ADDR = 'h32, // ..'h33 address where seconds of the snapshot can be read (microseconds - next adderss)
parameter RTC_SEC_USEC_ADDR = 'h32, // ..'h33 address where seconds of the snapshot can be read (microseconds - next address)
parameter RTC_MASK = 'h7fc,
parameter CAMSYNC_MASK = 'h7f8,
parameter CAMSYNC_MODE = 'h0,
......
......@@ -62,7 +62,8 @@ import x393_camsync
import x393_gpio
import x393_cmprs_afi
import x393_cmprs
import x393_frame_sequencer
import x393_sensor
import vrlg
__all__ = []
__version__ = 0.1
......@@ -328,21 +329,23 @@ USAGE
print("vrlg.VERBOSE__TYPE="+str(vrlg.VERBOSE__TYPE))
print("vrlg.VERBOSE__RAW="+str(vrlg.VERBOSE__RAW))
x393mem= x393_mem.X393Mem(verbose,args.simulated) #add dry run parameter
x393utils= x393_utils.X393Utils(verbose,args.simulated,args.localparams)
x393tasks= x393_axi_control_status.X393AxiControlStatus(verbose,args.simulated)
x393Pio= x393_pio_sequences.X393PIOSequences(verbose,args.simulated)
x393Timing= x393_mcntrl_timing.X393McntrlTiming(verbose,args.simulated)
x393Buffers= x393_mcntrl_buffers.X393McntrlBuffers(verbose,args.simulated)
x393Tests= x393_mcntrl_tests.X393McntrlTests(verbose,args.simulated)
x393Eyepatterns= x393_mcntrl_eyepatterns.X393McntrlEyepattern(verbose,args.simulated)
x393Adjust= x393_mcntrl_adjust.X393McntrlAdjust(verbose,args.simulated,args.localparams)
X393Membridge= x393_mcntrl_membridge.X393McntrlMembridge(verbose,args.simulated)
x393SensCmprs= x393_sens_cmprs.X393SensCmprs(verbose,args.simulated,args.localparams)
x393Camsync= x393_camsync.X393Camsync(verbose,args.simulated,args.localparams)
x393GPIO= x393_gpio.X393GPIO(verbose,args.simulated,args.localparams)
x393CmprsAfi= x393_cmprs_afi.X393CmprsAfi(verbose,args.simulated,args.localparams)
x393Cmprs= x393_cmprs.X393Cmprs(verbose,args.simulated,args.localparams)
x393mem = x393_mem.X393Mem(verbose,args.simulated) #add dry run parameter
x393utils = x393_utils.X393Utils(verbose,args.simulated,args.localparams)
x393tasks = x393_axi_control_status.X393AxiControlStatus(verbose,args.simulated)
x393Pio = x393_pio_sequences.X393PIOSequences(verbose,args.simulated)
x393Timing = x393_mcntrl_timing.X393McntrlTiming(verbose,args.simulated)
x393Buffers = x393_mcntrl_buffers.X393McntrlBuffers(verbose,args.simulated)
x393Tests = x393_mcntrl_tests.X393McntrlTests(verbose,args.simulated)
x393Eyepatterns = x393_mcntrl_eyepatterns.X393McntrlEyepattern(verbose,args.simulated)
x393Adjust = x393_mcntrl_adjust.X393McntrlAdjust(verbose,args.simulated,args.localparams)
X393Membridge = x393_mcntrl_membridge.X393McntrlMembridge(verbose,args.simulated)
x393SensCmprs = x393_sens_cmprs.X393SensCmprs(verbose,args.simulated,args.localparams)
x393Camsync = x393_camsync.X393Camsync(verbose,args.simulated,args.localparams)
x393GPIO = x393_gpio.X393GPIO(verbose,args.simulated,args.localparams)
x393CmprsAfi = x393_cmprs_afi.X393CmprsAfi(verbose,args.simulated,args.localparams)
x393Cmprs = x393_cmprs.X393Cmprs(verbose,args.simulated,args.localparams)
x393FrameSequencer = x393_frame_sequencer.X393FrameSequencer(verbose,args.simulated,args.localparams)
x393Sensor = x393_sensor.X393Sensor(verbose,args.simulated,args.localparams)
'''
print ("----------------------")
print("x393_mem.__dict__="+str(x393_mem.__dict__))
......@@ -372,6 +375,8 @@ USAGE
extractTasks(x393_gpio.X393GPIO, x393GPIO)
extractTasks(x393_cmprs_afi.X393CmprsAfi, x393CmprsAfi)
extractTasks(x393_cmprs.X393Cmprs, x393Cmprs)
extractTasks(x393_frame_sequencer.X393FrameSequencer, x393FrameSequencer)
extractTasks(x393_sensor.X393Sensor, x393Sensor)
for cmdLine in commands:
print ('Running task: '+str(cmdLine))
......
......@@ -318,85 +318,6 @@ class X393AxiControlStatus(object):
self.program_status (vrlg.MCNTRL_TEST01_ADDR, vrlg.MCNTRL_TEST01_CHN4_STATUS_CNTRL,mode,seq_num)#; //MCNTRL_TEST01_STATUS_REG_CHN4_ADDR= 'h3e,
self.program_status (vrlg.MEMBRIDGE_ADDR, vrlg.MEMBRIDGE_STATUS_CNTRL, mode,seq_num)#; //MCNTRL_TEST01_STATUS_REG_CHN4_ADDR= 'h3e,
def program_status_sensor_i2c( self,
num_sensor,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for selected sensor port i2c control
@param num_sensor - number of the sensor port (0..3)
@param mode - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
@param seq_number - 6-bit sequence number of the status message to be sent
"""
self.program_status (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC + vrlg.SENSI2C_CTRL_RADDR,
vrlg.SENSI2C_STATUS,
mode,
seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
def program_status_sensor_io( self,
num_sensor,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for selected sensor port io subsystem
@param num_sensor - number of the sensor port (0..3)
@param mode - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
@param seq_number - 6-bit sequence number of the status message to be sent
"""
self.program_status (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC + vrlg.SENSIO_RADDR,
vrlg.SENSIO_STATUS,
mode,
seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
def program_status_compressor(self,
cmprs_chn,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for selected compressor channel
@param cmprs_chn - number of the compressor channel (0..3)
@param mode - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
@param seq_number - 6-bit sequence number of the status message to be sent
"""
self.program_status (vrlg.CMPRS_GROUP_ADDR + cmprs_chn * vrlg.CMPRS_BASE_INC,
vrlg.CMPRS_STATUS_CNTRL,
mode,
seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
'''
def program_status_gpio(self,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for GPIO port
@param mode - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
@param seq_number - 6-bit sequence number of the status message to be sent
"""
self.program_status (vrlg.GPIO_ADDR,
vrlg.GPIO_SET_STATUS,
mode,
seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
'''
def enable_cmda(self,
en): # input en;
"""
......
......@@ -57,6 +57,26 @@ class X393Cmprs(object):
except:
pass
def program_status_compressor(self,
cmprs_chn,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for selected compressor channel
@param cmprs_chn - number of the compressor channel (0..3)
@param mode - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
@param seq_number - 6-bit sequence number of the status message to be sent
"""
self.x393_axi_tasks.program_status (
vrlg.CMPRS_GROUP_ADDR + cmprs_chn * vrlg.CMPRS_BASE_INC,
vrlg.CMPRS_STATUS_CNTRL,
mode,
seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
def func_compressor_format (self,
num_macro_cols_m1,
num_macro_rows_m1,
......
from __future__ import division
from __future__ import print_function
'''
# Copyright (C) 2015, Elphel.inc.
# Class to control 10393 Frame sequencer that allows storing and applying
# register writes synchronized by the sensors frame sync
# 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/>.
@author: Andrey Filippov
@copyright: 2015 Elphel, Inc.
@license: GPLv3.0+
@contact: andrey@elphel.coml
@deffield updated: Updated
'''
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2015, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
#import sys
#import pickle
from x393_mem import X393Mem
import x393_axi_control_status
import x393_utils
#import time
import vrlg
class X393FrameSequencer(object):
DRY_MODE= True # True
DEBUG_MODE=1
x393_mem=None
x393_axi_tasks=None #x393X393AxiControlStatus
x393_utils=None
verbose=1
def __init__(self, debug_mode=1,dry_mode=True, saveFileName=None):
self.DEBUG_MODE= debug_mode
self.DRY_MODE= dry_mode
self.x393_mem= X393Mem(debug_mode,dry_mode)
self.x393_axi_tasks= x393_axi_control_status.X393AxiControlStatus(debug_mode,dry_mode)
self.x393_utils= x393_utils.X393Utils(debug_mode,dry_mode, saveFileName) # should not overwrite save file path
try:
self.verbose=vrlg.VERBOSE
except:
pass
def ctrl_cmd_frame_sequencer (self,
num_sensor,
reset = False,
start = False,
stop = False):
"""
Control frame sequence
@param num_sensor - sensor channel number
@param reset - reset sequencer (also stops)
@param start - start sequencer
@param stop - stop sequencer
"""
data = 0;
if reset:
data |= 1 << vrlg.CMDFRAMESEQ_RST_BIT
if start:
data |= 1 << (vrlg.CMDFRAMESEQ_RUN_BIT -1)
if start or stop:
data |= 1 << vrlg.CMDFRAMESEQ_RUN_BIT
self.x393_axi_tasks.write_contol_register(
vrlg.CMDFRAMESEQ_ADDR_BASE + num_sensor * vrlg.CMDFRAMESEQ_ADDR_INC + vrlg.CMDFRAMESEQ_CTRL,
data)
def write_cmd_frame_sequencer (self,
num_sensor,
relative,
frame_addr,
addr,
data):
"""
Schedule/execute frame sequence command (register write)
@param num_sensor - sensor channel number
@param relative - False - use absolute address (0..15), True - use relative (to current frame) address - 0..14
writes to relative address 0 are considered ASAP and do not wait for the frame sync
@param frame_addr - 4-bit frame address (relative or absolute), relative must be < 15
@param addr; // command address (register to which command should be applied), 32 word (not byte) address, relative to maxi0 space
@param data; // command data to write
"""
frame_addr &= 0xf
if relative and (frame_addr == 0xf):
raise Exception ("task write_cmd_frame_sequencer(): relative address 0xf is invalid, it is reserved for module control")
reg_addr = vrlg.CMDFRAMESEQ_ADDR_BASE + num_sensor * vrlg.CMDFRAMESEQ_ADDR_INC + (vrlg.CMDFRAMESEQ_ABS,vrlg.CMDFRAMESEQ_REL)[relative] + frame_addr
self.x393_axi_tasks.write_contol_register( reg_addr, addr) # two writes to the same location - first is the register address
self.x393_axi_tasks.write_contol_register( reg_addr, data) # second is data to write to that register
......@@ -125,9 +125,9 @@ class X393GPIO(object):
data = 0
for i, e in enumerate (ext):
if not e is None:
if (e == 0) or (e.upper() == "0") or (e.upper() == "L"):
if (e is False) or (e == 0) or (e.upper() == "0") or (e.upper() == "L"):
data |= 1 << (2*i)
elif (e == 1) or (e.upper() == "1") or (e.upper() == "H"):
elif (e is True) or (e == 1) or (e.upper() == "1") or (e.upper() == "H"):
data |= 2 << (2*i)
elif e.upper() == "I":
data |= 3 << (2*i)
......
......@@ -3763,7 +3763,7 @@ class X393McntrlAdjust(object):
else:
raise Exception ("set_delays_with_reinit failed to read with safe delays for phase=%d after re-initializing device, wl_rslt=%s"%
(phase,str(wl_rslt)))
return cmda_odly_early[phase] # safe command/adderss delay
return cmda_odly_early[phase] # safe command/address delay
def cmd_phase_step(phase):
def measure_block(dly,
......
......@@ -182,7 +182,7 @@ class X393McntrlMembridge(object):
def membridge_setup (self,
len64, # input [28:0] len64; # number of 64-bit words to transfer
width64, # input [28:0] width64; # frame width in 64-bit words
start64, # input [28:0] start64; # relative start adderss of the transfer (set to 0 when writing lo_addr64)
start64, # input [28:0] start64; # relative start address of the transfer (set to 0 when writing lo_addr64)
lo_addr64 = None, # input [28:0] lo_addr64; # low address of the system memory range, in 64-bit words
size64 = None, # input [28:0] size64; # size of the system memory range in 64-bit words
cache = 0x3,
......
......@@ -129,7 +129,7 @@ class X393PIOSequences(object):
x393_mcontr_encode_cmd
'''
def func_encode_cmd(self, # function [31:0]
addr, # input [14:0] addr; // 15-bit row/column adderss
addr, # input [14:0] addr; // 15-bit row/column address
bank, # input [2:0] bank; // bank (here OK to be any)
rcw, # input [2:0] rcw; // RAS/CAS/WE, positive logic
odt_en, # input odt_en; // enable ODT
......@@ -145,7 +145,7 @@ class X393PIOSequences(object):
buf_rst): # input buf_rst; // connect to external buffer (but only if not paused)
"""
Encode data into memory controller sequencer word
<addr> 15-bit row/column adderss
<addr> 15-bit row/column address
<bank> 3-bit bank address
<rcw> 3-bit combined {RAS,CAS,WE}, positive logic
<odt_en> enable ODT
......@@ -161,7 +161,7 @@ class X393PIOSequences(object):
<buf_rst> reset external buffer page address to 0, increment page number
"""
return (
((addr & 0x7fff) << 17) | # addr[14:0], // 15-bit row/column adderss
((addr & 0x7fff) << 17) | # addr[14:0], // 15-bit row/column address
((bank & 0x7) << 14) | # bank [2:0], // bank
((rcw & 0x7) << 11) | # rcw[2:0], // RAS/CAS/WE
((0,1)[odt_en] << 10) | # odt_en, // enable ODT
......@@ -829,7 +829,7 @@ class X393PIOSequences(object):
reset_dll, # input reset_dll;
verbose=0):
"""
Setup sequence (at paramter-defined adderss) to write MR0, MR1, MR2 and MR3 mode registers of DDR3 memory
Setup sequence (at paramter-defined address) to write MR0, MR1, MR2 and MR3 mode registers of DDR3 memory
<reset_dll> reset memory DLL when running this sequence
<verbose> print data being written (default: False)
"""
......
from __future__ import division
from __future__ import print_function
'''
# Copyright (C) 2015, Elphel.inc.
# Class to control 10393 sensor-to-memory channel (including histograms)
# 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/>.
@author: Andrey Filippov
@copyright: 2015 Elphel, Inc.
@license: GPLv3.0+
@contact: andrey@elphel.coml
@deffield updated: Updated
'''
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2015, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
#import sys
#import pickle
from x393_mem import X393Mem
import x393_axi_control_status
import x393_utils
#import time
import vrlg
class X393Sensor(object):
DRY_MODE= True # True
DEBUG_MODE=1
x393_mem=None
x393_axi_tasks=None #x393X393AxiControlStatus
x393_utils=None
verbose=1
def __init__(self, debug_mode=1,dry_mode=True, saveFileName=None):
self.DEBUG_MODE= debug_mode
self.DRY_MODE= dry_mode
self.x393_mem= X393Mem(debug_mode,dry_mode)
self.x393_axi_tasks= x393_axi_control_status.X393AxiControlStatus(debug_mode,dry_mode)
self.x393_utils= x393_utils.X393Utils(debug_mode,dry_mode, saveFileName) # should not overwrite save file path
try:
self.verbose=vrlg.VERBOSE
except:
pass
def program_status_sensor_i2c( self,
num_sensor,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for selected sensor port i2c control
@param num_sensor - number of the sensor port (0..3)
@param mode - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
@param seq_number - 6-bit sequence number of the status message to be sent
"""
self.program_status (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC + vrlg.SENSI2C_CTRL_RADDR,
vrlg.SENSI2C_STATUS,
mode,
seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
def program_status_sensor_io( self,
num_sensor,
mode, # input [1:0] mode;
seq_num): # input [5:0] seq_num;
"""
Set status generation mode for selected sensor port io subsystem
@param num_sensor - number of the sensor port (0..3)
@param mode - status generation mode:
0: disable status generation,
1: single status request,
2: auto status, keep specified seq number,
4: auto, inc sequence number
@param seq_number - 6-bit sequence number of the status message to be sent
"""
self.x393_axi_tasks.program_status (
vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC + vrlg.SENSIO_RADDR,
vrlg.SENSIO_STATUS,
mode,
seq_num)# //MCONTR_PHY_STATUS_REG_ADDR= 'h0,
# Functions used by sensor-related tasks
def func_sensor_mode (self,
hist_en,
hist_nrst,
chn_en,
bits16):
"""
Combine parameters into sensor mode control word
@param hist_en - bit mask to enable histogram sub-modules, when 0 - disable after processing
the started frame
@param hist_nrst - bit mask to immediately reset histogram sub-module (if 0)
@param chn_en - enable sensor channel (False - reset)
@param bits16) - True - 16 bpp mode, false - 8 bpp mode (bypass gamma). Gamma-processed data
is still used for histograms
@return: sensor mode control word
"""
rslt = 0;
rslt |= (hist_en & 0xf) << vrlg.SENSOR_HIST_EN_BITS
rslt |= (hist_nrst & 0xf) << vrlg.SENSOR_HIST_NRST_BITS
rslt |= ((0,1)[chn_en]) << vrlg.SENSOR_CHN_EN_BIT
rslt |= ((0,1)[bits16]) << vrlg.SENSOR_16BIT_BIT
return rslt
def func_sensor_i2c_command (self,
rst_cmd = False,
run_cmd = None,
num_bytes = None,
dly = None,
scl_ctl = None,
sda_ctl = None):
"""
@param rst_cmd - reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
@param run_cmd - True - run i2c, False - stop i2c (needed before software i2c), None - no change
@param num_bytes - set number of i2c bytes after slave address (0..3), None - no change
@param dly - set duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA??? obsolete)
@param scl_ctl - directly control SCL line: None - NOP, 'Z' - high Z, 0/False/'L' - low level,
1/True/'H' - high level
@param sda_ctl - directly control SDA line: None - NOP, 'Z' - high Z, 0/False/'L' - low level,
1/True/'H' - high level
@return: i2c control word
"""
rslt = 0
rslt |= (0,1)[rst_cmd] << vrlg.SENSI2C_CMD_RESET
if not run_cmd is None:
rslt |= 1 << vrlg.SENSI2C_CMD_RUN
rslt |= (0,1)[run_cmd] << (vrlg.SENSI2C_CMD_RUN - vrlg.SENSI2C_CMD_RUN_PBITS)
if not num_bytes is None:
num_bytes &= (1 << vrlg.SENSI2C_CMD_BYTES_PBITS) -1
rslt |= 1 << vrlg.SENSI2C_CMD_BYTES
rslt |= num_bytes << (vrlg.SENSI2C_CMD_BYTES - vrlg.SENSI2C_CMD_BYTES_PBITS)
if not dly is None:
dly &= (1 << vrlg.SENSI2C_CMD_BYTES_PBITS) -1
rslt |= 1 << vrlg.SENSI2C_CMD_BYTES
rslt |= dly << (vrlg.SENSI2C_CMD_BYTES - vrlg.SENSI2C_CMD_BYTES_PBITS)
scl=0
if not scl_ctl is None:
if (scl_ctl is False) or (scl_ctl == 0) or (scl_ctl == "0") or (scl_ctl.upper() == "L"):
scl = 1
elif (scl_ctl is True) or (scl_ctl == 1) or (scl_ctl == "1") or (scl_ctl.upper() == "H"):
scl = 2
elif scl_ctl.upper() == "Z":
scl = 3
rslt |= scl << vrlg.SENSI2C_CMD_SCL
sda=0
if not sda_ctl is None:
if (sda_ctl is False) or (sda_ctl == 0) or (sda_ctl == "0") or (sda_ctl.upper() == "L"):
sda = 1
elif (sda_ctl is True) or (sda_ctl == 1) or (sda_ctl == "1") or (sda_ctl.upper() == "H"):
sda = 2
elif sda_ctl.upper() == "Z":
sda = 3
rslt |= sda << vrlg.SENSI2C_CMD_SDA
return rslt
def func_sensor_io_ctl (self,
mrst = None,
arst = None,
aro = None,
mmcm_rst = None,
clk_sel = None,
set_delays = False,
quadrants = None):
"""
Combine sensor I/O control parameters into a control word
@param mrst - True - activate MRST signal (low), False - deactivate MRST (high), None - no change
@param arst - True - activate ARST signal (low), False - deactivate ARST (high), None - no change
@param aro - True - activate ARO signal (low), False - deactivate ARO (high), None - no change
@param mmcm_rst - True - activate MMCM reset, False - deactivate MMCM reset, None - no change (needed after clock change/interruption)
@param clk_sel - True - use pixel clock from the sensor, False - use internal clock (provided to the sensor), None - no chnage
@param set_delays - (self-clearing) load all pre-programmed delays for the sensor pad inputs
@param quadrants - 90-degree shifts for data [1:0], hact [3:2] and vact [5:4] (6'h01), None - no change
@return sensor i/o control word
"""
rslt = 0
if not mrst is None:
rslt |= (2,3)[mrst] << vrlg.SENS_CTRL_MRST
if not arst is None:
rslt |= (2,3)[arst] << vrlg.SENS_CTRL_ARST
if not aro is None:
rslt |= (2,3)[aro] << vrlg.SENS_CTRL_ARO
if not mmcm_rst is None:
rslt |= (2,3)[mmcm_rst] << vrlg.SENS_CTRL_RST_MMCM
if not clk_sel is None:
rslt |= (2,3)[clk_sel] << vrlg.SENS_CTRL_EXT_CLK
rslt |= (0,1)[set_delays] << vrlg.SENS_CTRL_LD_DLY
if not quadrants is None:
rslt |= 1 << vrlg.SENS_CTRL_QUADRANTS_EN
rslt |= (quadrants & ((1 << vrlg.SENS_CTRL_QUADRANTS_WIDTH) - 1)) << vrlg.SENS_CTRL_QUADRANTS
return rslt
def func_sensor_jtag_ctl(self,
pgmen = None, # <2: keep PGMEN, 2 - PGMEN low (inactive), 3 - high (active) enable JTAG control
prog = None, # <2: keep prog, 2 - prog low (active), 3 - high (inactive) ("program" pin control)
tck = None, # <2: keep TCK, 2 - set TCK low, 3 - set TCK high
tms = None, # <2: keep TMS, 2 - set TMS low, 3 - set TMS high
tdi = None): # <2: keep TDI, 2 - set TDI low, 3 - set TDI high
"""
JTAG interface for programming external sensor multiplexer using shared signal lines on the sensor ports
@param pgmen - False PGMEN low (inactive), True - high (active) enable JTAG control, None - keep previous value
@param prog - False prog low (active), True - high (inactive) ("program" pin control), None - keep previous value
@param tck = False - set TCK low, True - set TCK high, None - keep previous value
@param tms = False - set TMS low, True - set TMS high, None - keep previous value
@param tdi = False - set TDI low, True - set TDI high, None - keep previous value
@return combined control word
"""
rslt = 0
if not pgmen is None:
rslt |= (2,3)[pgmen] << vrlg.SENS_JTAG_PGMEN
if not prog is None:
rslt |= (2,3)[prog] << vrlg.SENS_JTAG_PROG
if not tck is None:
rslt |= (2,3)[tck] << vrlg.SENS_JTAG_TCK
if not tms is None:
rslt |= (2,3)[tms] << vrlg.SENS_JTAG_TMS
if not tdi is None:
rslt |= (2,3)[tdi] << vrlg.SENS_JTAG_TDI
return rslt
def func_sensor_gamma_ctl(self,
bayer = 0,
table_page = 0,
en_input = True,
repet_mode = True, # Normal mode, single trigger - just for debugging TODO: re-assign?
trig = False):
"""
@param bayer - Bayer shift (0..3)
@param table_page - Gamma table page
@param en_input - Enable input
@param repet_mode - Repetitive (normal) mode. Set False for debugging, then use trig for single frame trigger
@param trig - single trigger (when repet_mode is False), debug feature
@return combined control word
"""
rslt = 0
rslt |= (bayer & 3) << vrlg.SENS_GAMMA_MODE_BAYER
rslt |= (0,1)[table_page] << vrlg.SENS_GAMMA_MODE_PAGE
rslt |= (0,1)[en_input] << vrlg.SENS_GAMMA_MODE_EN
rslt |= (0,1)[repet_mode] << vrlg.SENS_GAMMA_MODE_REPET
rslt |= (0,1)[trig] << vrlg.SENS_GAMMA_MODE_TRIG
return rslt
def func_status_addr_sensor_i2c(self,
num_sensor):
"""
@param num_sensor - sensor port number (0..3)
@return status register address for i2c for selected sensor port
"""
return (vrlg.SENSI2C_STATUS_REG_BASE + num_sensor * vrlg.SENSI2C_STATUS_REG_INC + vrlg.SENSI2C_STATUS_REG_REL);
def func_status_addr_sensor_io(self,
num_sensor):
"""
@param num_sensor - sensor port number (0..3)
@return status register address for I/O for selected sensor port
"""
return (vrlg.SENSI2C_STATUS_REG_BASE + num_sensor * vrlg.SENSI2C_STATUS_REG_INC + vrlg.SENSIO_STATUS_REG_REL);
def set_sensor_mode (self,
num_sensor,
hist_en,
hist_nrst,
chn_en,
bits16):
"""
Set sensor mode
@param num_sensor - sensor port number (0..3)
@param hist_en - bit mask to enable histogram sub-modules, when 0 - disable after processing
the started frame
@param hist_nrst - bit mask to immediately reset histogram sub-module (if 0)
@param chn_en - enable sensor channel (False - reset)
@param bits16) - True - 16 bpp mode, false - 8 bpp mode (bypass gamma). Gamma-processed data
is still used for histograms
"""
self.x393_axi_tasks.write_contol_register(vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC + vrlg.SENSOR_CTRL_RADDR,
self.func_sensor_mode(
hist_en = hist_en,
hist_nrst = hist_nrst,
chn_en = chn_en,
bits16 = bits16))
def set_sensor_i2c_command (self,
num_sensor,
rst_cmd = False,
run_cmd = None,
num_bytes = None,
dly = None,
scl_ctl = None,
sda_ctl = None):
"""
@param rst_cmd - reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
@param run_cmd - True - run i2c, False - stop i2c (needed before software i2c), None - no change
@param num_bytes - set number of i2c bytes after slave address (0..3), None - no change
@param dly - set duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA??? obsolete)
@param scl_ctl - directly control SCL line: None - NOP, 'Z' - high Z, 0/False/'L' - low level,
1/True/'H' - high level
@param sda_ctl - directly control SDA line: None - NOP, 'Z' - high Z, 0/False/'L' - low level,
1/True/'H' - high level
@return: i2c control word
"""
self.x393_axi_tasks.write_contol_register(vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC + vrlg.SENSI2C_CTRL_RADDR,
self.func_sensor_i2c_command(
rst_cmd = rst_cmd,
run_cmd = run_cmd,
num_bytes = num_bytes,
dly = dly,
scl_ctl = scl_ctl,
sda_ctl = sda_ctl))
def write_sensor_i2c (self,
num_sensor,
rel_addr,
addr,
data):
"""
Write i2c command to the i2c command sequencer
@param num_sensor - sensor port number (0..3)
@param rel_addr - True - relative frame address, False - absolute frame address
@param addr - frame address (0..15)
@param data - Combine slave address/register address/ register data for the i2c command
"""
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC)
reg_addr += ((vrlg.SENSI2C_ABS_RADDR,vrlg.SENSI2C_REL_RADDR)[rel_addr] )
reg_addr += (addr & ~vrlg.SENSI2C_ADDR_MASK);
self.x393_axi_tasks.write_contol_register(reg_addr, data)
def set_sensor_io_ctl (self,
num_sensor,
mrst = None,
arst = None,
aro = None,
mmcm_rst = None,
clk_sel = None,
set_delays = False,
quadrants = None):
"""
Set sensor I/O controls, including I/O signals
@param num_sensor - sensor port number (0..3)
@param mrst - True - activate MRST signal (low), False - deactivate MRST (high), None - no change
@param arst - True - activate ARST signal (low), False - deactivate ARST (high), None - no change
@param aro - True - activate ARO signal (low), False - deactivate ARO (high), None - no change
@param mmcm_rst - True - activate MMCM reset, False - deactivate MMCM reset, None - no change (needed after clock change/interruption)
@param clk_sel - True - use pixel clock from the sensor, False - use internal clock (provided to the sensor), None - no chnage
@param set_delays - (self-clearing) load all pre-programmed delays for the sensor pad inputs
@param quadrants - 90-degree shifts for data [1:0], hact [3:2] and vact [5:4] (6'h01), None - no change
"""
data = self.func_sensor_io_ctl (
mrst = mrst,
arst = arst,
aro = aro,
mmcm_rst = mmcm_rst,
clk_sel = clk_sel,
set_delays = set_delays,
quadrants = quadrants)
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENSIO_RADDR + vrlg.SENSIO_CTRL;
self.x393_axi_tasks.write_contol_register(reg_addr, data)
def set_sensor_io_dly (self,
num_sensor,
mmcm_phase,
iclk_dly,
vact_dly,
hact_dly,
pxd_dly):
"""
Set sensor port input delays and mmcm phase
@param num_sensor - sensor port number (0..3)
@param mmcm_phase - MMCM clock phase
@param iclk_dly - delay in the input clock line (3 LSB are not used)
@param vact_dly - delay in the VACT line (3 LSB are not used)
@param hact_dly - delay in the HACT line (3 LSB are not used)
@param pxd_dly - list of data line delays (12 elements, 3 LSB are not used)
"""
dlys=((pxd_dly[0] & 0xff) | ((pxd_dly[1] & 0xff) << 8) | ((pxd_dly[ 2] & 0xff) << 16) | ((pxd_dly[ 3] & 0xff) << 24),
(pxd_dly[4] & 0xff) | ((pxd_dly[5] & 0xff) << 8) | ((pxd_dly[ 6] & 0xff) << 16) | ((pxd_dly[ 7] & 0xff) << 24),
(pxd_dly[8] & 0xff) | ((pxd_dly[9] & 0xff) << 8) | ((pxd_dly[10] & 0xff) << 16) | ((pxd_dly[11] & 0xff) << 24),
(hact_dly & 0xff) | ((vact_dly & 0xff) << 8) | ((iclk_dly & 0xff) << 16) | ((mmcm_phase & 0xff) << 24))
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENSIO_RADDR + vrlg.SENSIO_DELAYS;
self.x393_axi_tasks.write_contol_register(reg_addr + 0, dlys[0]) # {pxd3, pxd2, pxd1, pxd0}
self.x393_axi_tasks.write_contol_register(reg_addr + 1, dlys[1]) # {pxd7, pxd6, pxd5, pxd4}
self.x393_axi_tasks.write_contol_register(reg_addr + 2, dlys[2]) # {pxd11, pxd10, pxd9, pxd8}
self.x393_axi_tasks.write_contol_register(reg_addr + 3, dlys[3]) # {mmcm_phase, bpf, vact, hact}
self.set_sensor_io_ctl (num_sensor = num_sensor,
set_delays = True)
def set_sensor_io_jtag (self,
num_sensor,
pgmen = None, # <2: keep PGMEN, 2 - PGMEN low (inactive), 3 - high (active) enable JTAG control
prog = None, # <2: keep prog, 2 - prog low (active), 3 - high (inactive) ("program" pin control)
tck = None, # <2: keep TCK, 2 - set TCK low, 3 - set TCK high
tms = None, # <2: keep TMS, 2 - set TMS low, 3 - set TMS high
tdi = None): # <2: keep TDI, 2 - set TDI low, 3 - set TDI high
"""
JTAG interface for programming external sensor multiplexer using shared signal lines on the sensor ports
@param num_sensor - sensor port number (0..3)
@param pgmen - False PGMEN low (inactive), True - high (active) enable JTAG control, None - keep previous value
@param prog - False prog low (active), True - high (inactive) ("program" pin control), None - keep previous value
@param tck = False - set TCK low, True - set TCK high, None - keep previous value
@param tms = False - set TMS low, True - set TMS high, None - keep previous value
@param tdi = False - set TDI low, True - set TDI high, None - keep previous value
"""
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENSIO_RADDR + vrlg.SENSIO_JTAG;
data = self.func_sensor_jtag_ctl (
pgmen = pgmen,
prog = prog,
tck = tck,
tms = tms,
tdi = tdi)
self.x393_axi_tasks.write_contol_register(reg_addr, data)
def set_sensor_io_width (
self,
num_sensor,
width): # 0 - use HACT, >0 - generate HACT from start to specified width
"""
Set sensor frame width
@param num_sensor - sensor port number (0..3)
@param width - sensor 16-bit frame width (0 - use sensor HACT signal)
"""
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENSIO_RADDR + vrlg.SENSIO_WIDTH;
self.x393_axi_tasks.write_contol_register(reg_addr, width)
def set_sensor_lens_flat_heights (self,
num_sensor,
height0_m1 = None,
height1_m1 = None,
height2_m1 = None):
"""
Set division of the composite frame into sub-frames for the vignetting correction module
@param num_sensor - sensor port number (0..3)
@param height0_m1 - height of the first sub-frame minus 1
@param height1_m1 - height of the second sub-frame minus 1
@param height2_m1 - height of the third sub-frame minus 1
(No need for the 4-th, as it will just go until end of the composite frame)
"""
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENS_LENS_RADDR;
if not height0_m1 is None:
self.x393_axi_tasks.write_contol_register(reg_addr + 0, height0_m1)
if not height1_m1 is None:
self.x393_axi_tasks.write_contol_register(reg_addr + 1, height1_m1)
if not height2_m1 is None:
self.x393_axi_tasks.write_contol_register(reg_addr + 2, height2_m1)
def set_sensor_lens_flat_parameters (self,
num_sensor,
num_sub_sensor,
# add mode "DIRECT", "ASAP", "RELATIVE", "ABSOLUTE" and frame number
AX = None,
AY = None,
BX = None,
BY = None,
C = None,
scales0 = None,
scales1 = None,
scales2 = None,
scales3 = None,
fatzero_in = None,
fatzero_out = None,
post_scale = None):
"""
Program vignetting correction and per-color scale
@param num_sensor - sensor port number (0..3)
@param num_sub_sensor - sub-sensor attached to the same port through multiplexer (0..3)
TODO: add mode "DIRECT", "ASAP", "RELATIVE", "ABSOLUTE" and frame number for sequencer
All the next parameters can be None - will not be set
@param AX (19 bits)
@param AY (19 bits)
@param BX (21 bits)
@param BY (21 bits)
@param C (19 bits)
@param scales0 (17 bits) - color channel 0 scale
@param scales1 (17 bits) - color channel 1 scale
@param scales2 (17 bits) - color channel 2 scale
@param scales3 (17 bits) - color channel 3 scale
@param fatzero_in (16 bits)
@param fatzero_out (16 bits)
@param post_scale (4 bits) - shift of the result
"""
def func_lens_data (self,
num_sensor,
addr,
data,
width):
return ((num_sensor & 3) << 24) | ((addr & 0xff) << 16) | (data & ((1 << width) - 1))
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENS_LENS_RADDR + vrlg.SENS_LENS_COEFF
if not AX is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_AX, AX, 19))
if not AY is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_AY, AY, 19))
if not BX is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_BX, BX, 21))
if not BY is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_BY, BY, 21))
if not C is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_C, C, 19))
if not scales0 is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_SCALES + 0, scales0, 17))
if not scales1 is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_SCALES + 2, scales1, 17))
if not scales2 is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_SCALES + 4, scales2, 17))
if not scales3 is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_SCALES + 6, scales3, 17))
if not fatzero_in is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_FAT0_IN, fatzero_in, 16))
if not fatzero_out is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_FAT0_OUT, fatzero_out, 16))
if not post_scale is None:
self.x393_axi_tasks.write_contol_register(reg_addr, func_lens_data(num_sub_sensor, vrlg.SENS_LENS_POST_SCALE, post_scale, 4))
def program_curves (self,
num_sensor,
sub_channel,
curves_data,
page = 0):
"""
Program gamma tables for specified sensor port and subchannel
@param num_sensor - sensor port number (0..3)
@param num_sub_sensor - sub-sensor attached to the same port through multiplexer (0..3)
@param curves_data - either 1028-element list (257 per color component) or a file path
with the same data, same as for Verilog $readmemh
@param page - gammma table page number (only used if SENS_GAMMA_BUFFER > 0
"""
def set_sensor_gamma_table_addr (
num_sensor,
sub_channel,
color,
page = 0): # only used if SENS_GAMMA_BUFFER != 0
data = (1 << 20) | ((color & 3) <<8)
if (vrlg.SENS_GAMMA_BUFFER):
data |= (sub_channel & 3) << 11 # [12:11]
data |= page << 10
else:
data |= (sub_channel & 3) << 10 # [11:10]
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENS_GAMMA_RADDR + vrlg.SENS_GAMMA_ADDR_DATA
self.x393_axi_tasks.write_contol_register(reg_addr, data)
def set_sensor_gamma_table_data ( #; // need 256 for a single color data
num_sensor,
data18): # ; // 18-bit table data
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENS_GAMMA_RADDR + vrlg.SENS_GAMMA_ADDR_DATA;
self.x393_axi_tasks.write_contol_register(reg_addr, data18 & ((1 << 18) - 1))
if isinstance(curves_data, unicode):
with open(curves_data) as f:
tokens=f.read().split()
curves_data = []
for w in tokens:
curves_data.append(int(w,16))
set_sensor_gamma_table_addr (
num_sensor = num_sensor,
sub_channel = sub_channel,
color = 0,
page = page)
for n in range(4):
for i in range(256):
base =curves_data[257*n+i];
diff =curves_data[257*n+i+1]-curves_data[257*n+i];
diff1=curves_data[257*n+i+1]-curves_data[257*n+i]+8;
# $display ("%x %x %x %x %x %x",n,i,curves_data[257*n+i], base, diff, diff1);
#1;
if ((diff > 63) or (diff < -64)):
data18 = (1 << 17) | (base & 0x3ff) | (((diff1 >> 4) & 0x7f) << 10) # {1'b1,diff1[10:4],base[9:0]};
else:
data18 = (base & 0x3ff) | (( diff & 0x7f) << 10) # {1'b0,diff [ 6:0],base[9:0]};
set_sensor_gamma_table_data (
num_sensor = num_sensor,
data18 = data18)
def set_sensor_gamma_heights (self,
num_sensor,
height0_m1,
height1_m1,
height2_m1):
"""
Set division of the composite frame into sub-frames for gamma correction (separate for each subframe
@param num_sensor - sensor port number (0..3)
@param height0_m1 - height of the first sub-frame minus 1
@param height1_m1 - height of the second sub-frame minus 1
@param height2_m1 - height of the third sub-frame minus 1
(No need for the 4-th, as it will just go until end of the composite frame)
"""
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENS_GAMMA_RADDR + vrlg.SENS_GAMMA_HEIGHT01
self.x393_axi_tasks.write_contol_register(reg_addr, (height0_m1 & 0xffff) | ((height1_m1 & 0xffff) << 16));
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENS_GAMMA_RADDR + vrlg.SENS_GAMMA_HEIGHT2;
self.x393_axi_tasks.write_contol_register(reg_addr, height2_m1 & 0xffff);
def set_sensor_gamma_ctl (self,
num_sensor,
bayer = 0,
table_page = 0,
en_input = True,
repet_mode = True, # Normal mode, single trigger - just for debugging TODO: re-assign?
trig = False):
"""
Setup sensor gamma correction
@param num_sensor - sensor port number (0..3)
@param bayer - Bayer shift (0..3)
@param table_page - Gamma table page
@param en_input - Enable input
@param repet_mode - Repetitive (normal) mode. Set False for debugging, then use trig for single frame trigger
@param trig - single trigger (when repet_mode is False), debug feature
"""
data = self.func_sensor_gamma_ctl (
bayer = bayer,
table_page = table_page,
en_input = en_input,
repet_mode = repet_mode,
trig = trig)
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + vrlg.SENS_GAMMA_RADDR + vrlg.SENS_GAMMA_CTRL;
self.x393_axi_tasks.write_contol_register(reg_addr, data);
def set_sensor_histogram_window (self,
num_sensor,
subchannel,
left,
top,
width_m1,
height_m1):
"""
Program histogram window
@param num_sensor - sensor port number (0..3)
@param num_sub_sensor - sub-sensor attached to the same port through multiplexer (0..3)
@param left - histogram window left margin
@param top - histogram window top margin
@param width_m1 - one less than window width. If 0 - use frame right margin (end of HACT)
@param height_m1 - one less than window height. If 0 - use frame bottom margin (end of VACT)
"""
raddr = (vrlg.HISTOGRAM_RADDR0, vrlg.HISTOGRAM_RADDR1, vrlg.HISTOGRAM_RADDR2, vrlg.HISTOGRAM_RADDR3)
reg_addr = (vrlg.SENSOR_GROUP_ADDR + num_sensor * vrlg.SENSOR_BASE_INC) + raddr[subchannel & 3]
self.x393_axi_tasks.write_contol_register(reg_addr + vrlg.HISTOGRAM_LEFT_TOP, ((top & 0xffff) << 16) | (left & 0xff))
self.x393_axi_tasks.write_contol_register(reg_addr + vrlg.HISTOGRAM_WIDTH_HEIGHT, ((height_m1 & 0xffff) << 16) | (width_m1 & 0xff))
def set_sensor_histogram_saxi (self,
en,
nrst,
confirm_write,
cache_mode = 3):
"""
Setup SAXI GP channel to transfer histograms (16 pages, up to 16 sensors) to the system memory
@param en - enable transfers
@param nrst - negated reset False - immediate reset, True - normal run;
@param confirm_write - wait for the write confirmed (over B channel) before switching channels
@param cache_mode AXI cache mode, default should be 4'h3
"""
data = 0;
data |= (0,1)[en] << vrlg.HIST_SAXI_EN
data |= (0,1)[nrst] << vrlg.HIST_SAXI_NRESET
data |= (0,1)[confirm_write] << vrlg.HIST_CONFIRM_WRITE
data |= (cache_mode & 0xf) << vrlg.HIST_SAXI_AWCACHE
self.x393_axi_tasks.write_contol_register(vrlg.SENSOR_GROUP_ADDR + vrlg.HIST_SAXI_MODE_ADDR_REL, data)
def set_sensor_histogram_saxi_addr (self,
num_sensor,
subchannel,
page):
"""
Setup SAXI GP start address in 4KB pages (1 page - 1 subchannel histogram)
@param num_sensor - sensor port number (0..3)
@param num_sub_sensor - sub-sensor attached to the same port through multiplexer (0..3)
@param page - system memory page address (in 4KB units)
"""
channel = ((num_sensor & 3) << 2) + (subchannel & 3)
self.x393_axi_tasks.write_contol_register(vrlg.SENSOR_GROUP_ADDR + vrlg.HIST_SAXI_ADDR_REL + channel,page)
......@@ -25,7 +25,7 @@
module rtc393 #(
parameter RTC_ADDR = 'h704, //..'h707
parameter RTC_STATUS_REG_ADDR = 'h31, // address where status can be read out (currently just sequence # and alternating bit)
parameter RTC_SEC_USEC_ADDR = 'h32, //'h33 address where seconds of the snapshot can be read (microseconds - next adderss)
parameter RTC_SEC_USEC_ADDR = 'h32, //'h33 address where seconds of the snapshot can be read (microseconds - next address)
parameter RTC_MASK = 'h7fc,
parameter RTC_MHZ = 25, // RTC input clock in MHz (should be interger number)
......
......@@ -24,7 +24,7 @@ module timing393 #(
parameter RTC_ADDR= 'h704, // 'h707
parameter CAMSYNC_ADDR = 'h708, // 'h70f
parameter RTC_STATUS_REG_ADDR = 'h31, // (1 loc) address where status can be read out (currently just sequence # and alternating bit)
parameter RTC_SEC_USEC_ADDR = 'h32, // ..'h33 address where seconds of the snapshot can be read (microseconds - next adderss)
parameter RTC_SEC_USEC_ADDR = 'h32, // ..'h33 address where seconds of the snapshot can be read (microseconds - next address)
parameter RTC_MASK = 'h7fc,
parameter CAMSYNC_MASK = 'h7f8,
parameter CAMSYNC_MODE = 'h0,
......
......@@ -285,7 +285,7 @@ module x393 #(
wire status_compressor_start; //
// TODO: Add sequencer status (16+2) bits of current frame number. Ose 'h31 as the adderss, 'h702 (701..703 were empty) to program
// TODO: Add sequencer status (16+2) bits of current frame number. Ose 'h31 as the address, 'h702 (701..703 were empty) to program
wire [7:0] status_sequencer_ad; // Other status byte-wide address/data
wire status_sequencer_rq; // Other status request
wire status_sequencer_start; // S uppressThisWarning VEditor ****** Other status packet transfer start (currently with 0 latency from status_root_rq)
......
......@@ -2391,7 +2391,7 @@ task setup_sensor_channel;
set_sensor_histogram_saxi (
1'b1, // input en;
1'b1, // input nrst;
1'b1, // input confirm_write; // wait for the write confirmed befoer swicthing channels
1'b1, // input confirm_write; // wait for the write confirmed before switching channels
4'h3); // input [3:0] cache_mode; // default should be 4'h3
/*
......@@ -2812,7 +2812,7 @@ task test_i2c_353;
1'b1, // input set_bytes; // [11] if 1, use bytes (below), 0 - nop
2'h3, // input [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes; // [10:9] set command bytes to send after slave address (0..3)
1'b1, // input set_dly; // [8] if 1, use dly (0 - ignore)
8'h0a, // input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
8'h0a, // input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
2'b0, // input [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl; // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
2'b0); // input [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl; // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA
repeat (10) @ (posedge CLK); // wait for initialization to be done TODO: use status
......@@ -2848,7 +2848,7 @@ task test_i2c_353;
endtask
//x393_axi_control_status.py
//x393_sensor.py
task program_status_sensor_i2c;
input [1:0] num_sensor;
input [1:0] mode;
......@@ -2861,7 +2861,7 @@ task program_status_sensor_i2c;
end
endtask
//x393_axi_control_status.py
//x393_sensor.py
task program_status_sensor_io;
input [1:0] num_sensor;
input [1:0] mode;
......@@ -2874,7 +2874,7 @@ task program_status_sensor_io;
end
endtask
//x393_axi_control_status.py
//x393_cmprs.py
task program_status_compressor;
input [1:0] num_sensor;
input [1:0] mode;
......@@ -2968,7 +2968,7 @@ task set_sensor_i2c_command;
input set_bytes; // [11] if 1, use bytes (below), 0 - nop
input [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes; // [10:9] set command bytes to send after slave address (0..3)
input set_dly; // [8] if 1, use dly (0 - ignore)
input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
input [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl; // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
input [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl; // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA
......@@ -3299,7 +3299,7 @@ endtask
task set_sensor_histogram_saxi;
input en;
input nrst;
input confirm_write; // wait for the write confirmed befoer swicthing channels
input confirm_write; // wait for the write confirmed before switching channels
input [3:0] cache_mode; // default should be 4'h3
reg [31:0] data;
begin
......@@ -3373,7 +3373,7 @@ function [STATUS_DEPTH-1:0] func_status_addr_rtc_usec; // sec is in the next add
endfunction
*/
// camsync tasks
//x393_camsync.py
// x393_camsync.py
task set_camsync_mode;
input en; // 1 - enable, 0 - reset module
input [1:0] en_snd; // <2 - NOP, 2 - disable, 3 - enable sending timestamp with sync pulse
......@@ -3394,7 +3394,7 @@ task set_camsync_mode;
end
endtask
//x393_camsync.py
// x393_camsync.py
task set_camsync_inout; // set specified input bit, keep other ones
input is_out; // 0 - input selection, 1 - output selection
input integer bit_number; // 0..9 - bit to use
......@@ -3408,6 +3408,7 @@ task set_camsync_inout; // set specified input bit, keep other ones
end
endtask
// x393_camsync.py
task reset_camsync_inout; // disable all inputs
input is_out; // 0 - input selection, 1 - output selection
begin
......@@ -3416,6 +3417,7 @@ task reset_camsync_inout; // disable all inputs
end
endtask
// x393_camsync.py
task set_camsync_period;
input [31:0] period; // 0 - input selection, 1 - output selection
begin
......@@ -3423,6 +3425,7 @@ task set_camsync_period;
end
endtask
// x393_camsync.py
task set_camsync_delay;
input [1:0] sub_chn;
input [31:0] dly; // 0 - input selection, 1 - output selection
......@@ -3433,6 +3436,7 @@ endtask
// command sequencer control
// Functions used by sensor-related tasks
// x393_frame_sequencer.py
task ctrl_cmd_frame_sequencer;
input [1:0] num_sensor; // sensor channel number
input reset; // reset sequencer (also stops)
......@@ -3450,16 +3454,17 @@ task ctrl_cmd_frame_sequencer;
end
endtask
// x393_frame_sequencer.py
task write_cmd_frame_sequencer;
input [1:0] num_sensor; // sensor channel number
input relative; // 0 - absolute (address = 0..f), 1 - relative (address= 0..e)
input [3:0] frame_addr; // frame address (relative ort absolute)
input [3:0] frame_addr; // frame address (relative or absolute)
input [AXI_WR_ADDR_BITS-1:0] addr; // command address (register to which command should be applied)
input [31:0] data; // command data
reg [29:0] reg_addr;
begin
if (relative && (&frame_addr)) $display("task write_cmd_frame_sequencer(): relative adderss 'hf is invalid, it is reserved for module control");
if (relative && (&frame_addr)) $display("task write_cmd_frame_sequencer(): relative address 'hf is invalid, it is reserved for module control");
else begin
reg_addr = CMDFRAMESEQ_ADDR_BASE + num_sensor * CMDFRAMESEQ_ADDR_INC + (relative ? CMDFRAMESEQ_REL : CMDFRAMESEQ_ABS) + frame_addr;
write_contol_register(reg_addr, {{32-AXI_WR_ADDR_BITS{1'b0}}, addr});
......@@ -3467,7 +3472,7 @@ task write_cmd_frame_sequencer;
end
end
endtask
// x393_sensor.py
function [SENSOR_MODE_WIDTH-1:0] func_sensor_mode;
input [3:0] hist_en; // [0..3] 1 - enable histogram modules, disable after processing the started frame
input [3:0] hist_nrst; // [4..7] 0 - immediately reset histogram module
......@@ -3485,13 +3490,14 @@ function [SENSOR_MODE_WIDTH-1:0] func_sensor_mode;
endfunction
// x393_sensor.py
function [31 : 0] func_sensor_i2c_command;
input rst_cmd; // [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
input [SENSI2C_CMD_RUN_PBITS : 0] run_cmd; // [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
input set_bytes; // [11] if 1, use bytes (below), 0 - nop
input [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes; // [10:9] set command bytes to send after slave address (0..3)
input set_dly; // [8] if 1, use dly (0 - ignore)
input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quarter i2c cycle (if 0, [3:0] control SCL+SDA)
input [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl; // [17:16] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
input [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl; // [19:18] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA
......@@ -3513,6 +3519,7 @@ endfunction
// x393_sensor.py
function [31 : 0] func_sensor_io_ctl;
input [1:0] mrst; // <2: keep MRST, 2 - MRST low (active), 3 - high (inactive)
input [1:0] arst; // <2: keep ARST, 2 - ARST low (active), 3 - high (inactive)
......@@ -3533,11 +3540,12 @@ function [31 : 0] func_sensor_io_ctl;
tmp [SENS_CTRL_EXT_CLK +: 2] = clk_sel;
tmp [SENS_CTRL_LD_DLY] = set_delays;
tmp [SENS_CTRL_QUADRANTS_EN] = set_guadrants;
tmp [SENS_CTRL_EXT_CLK +: SENS_CTRL_QUADRANTS_WIDTH] = quadrants;
tmp [SENS_CTRL_QUADRANTS +: SENS_CTRL_QUADRANTS_WIDTH] = quadrants;
func_sensor_io_ctl = tmp;
end
endfunction
// x393_sensor.py
function [31 : 0] func_sensor_jtag_ctl;
input [1:0] pgmen; // <2: keep PGMEN, 2 - PGMEN low (inactive), 3 - high (active) enable JTAG control
input [1:0] prog; // <2: keep prog, 2 - prog low (active), 3 - high (inactive) ("program" pin control)
......@@ -3548,16 +3556,16 @@ function [31 : 0] func_sensor_jtag_ctl;
reg [31 : 0] tmp;
begin
tmp = 0;
tmp [SENS_JTAG_TDI +: 2] = pgmen;
tmp [SENS_JTAG_TMS +: 2] = prog;
tmp [SENS_JTAG_TCK +: 2] = tck;
tmp [SENS_JTAG_TMS +: 2] = tms;
tmp [SENS_JTAG_TDI +: 2] = tdi;
tmp [SENS_JTAG_PGMEN +: 2] = pgmen;
tmp [SENS_JTAG_PROG +: 2] = prog;
tmp [SENS_JTAG_TCK +: 2] = tck;
tmp [SENS_JTAG_TMS +: 2] = tms;
tmp [SENS_JTAG_TDI +: 2] = tdi;
func_sensor_jtag_ctl = tmp;
end
endfunction
// x393_sensor.py
function [31 : 0] func_sensor_gamma_ctl;
input [1:0] bayer;
input table_page;
......
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