x393_sens_cmprs.py 143 KB
Newer Older
1 2 3 4 5
from __future__ import division
from __future__ import print_function

'''
# Copyright (C) 2015, Elphel.inc.
6
# Class to control image acquisition and compression functionality
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
# 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
37 38 39 40 41 42 43
import x393_camsync
import x393_gpio
import x393_cmprs_afi
import x393_cmprs
import x393_frame_sequencer
import x393_sensor
import x393_rtc
44
import x393_mcntrl_membridge
45 46
import x393_utils

47
import time
48
import vrlg
49 50
import x393_mcntrl

51
from verilog_utils import hx
52 53


54
PAGE_SIZE =           4096
55 56 57 58 59 60 61
#SI5338_PATH =         '/sys/devices/amba.0/e0004000.ps7-i2c/i2c-0/0-0070'
#POWER393_PATH =       '/sys/devices/elphel393-pwr.1'
#MEM_PATH =            '/sys/devices/elphel393-mem.2/'

SI5338_PATH =         '/sys/devices/soc0/amba@0/e0004000.ps7-i2c/i2c-0/0-0070'
POWER393_PATH =       '/sys/devices/soc0/elphel393-pwr@0'
MEM_PATH =            '/sys/devices/soc0/elphel393-mem@0/'
62 63 64 65
EYESIS_POWER_PATH=    '/sys/devices/soc0/elphel393-pwr@0/gpio_10389'
EYESIS_POWER_ON=      '0x101'
EYESIS_POWER_OFF=     '0x100'

66

Andrey Filippov's avatar
Andrey Filippov committed
67
BUFFER_ADDRESS_NAME = 'buffer_address'
68 69 70
BUFFER_PAGES_NAME =   'buffer_pages'
BUFFER_ADDRESS =      None # in bytes
BUFFER_LEN =          None # in bytes
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
BUFFER_ADDRESS_NAME =       'buffer_address'
BUFFER_PAGES_NAME =         'buffer_pages'
BUFFER_H2D_ADDRESS_NAME =   'buffer_address_h2d'
BUFFER_H2D_PAGES_NAME =     'buffer_pages_h2d'
BUFFER_D2H_ADDRESS_NAME =   'buffer_address_d2h'
BUFFER_D2H_PAGES_NAME =     'buffer_pages_d2h'
BUFFER_BIDIR_ADDRESS_NAME = 'buffer_address_bidir'
BUFFER_BIDIR_PAGES_NAME =   'buffer_pages_bidir'

BUFFER_FOR_CPU =             'sync_for_cpu' # add suffix
BUFFER_FOR_DEVICE =          'sync_for_device' # add suffix

BUFFER_FOR_CPU_H2D =         'sync_for_cpu_h2d'
BUFFER_FOR_DEVICE_H2D =      'sync_for_device_h2d'

BUFFER_FOR_CPU_D2H =         'sync_for_cpu_d2h'
BUFFER_FOR_DEVICE_D2H =      'sync_for_device_d2h'

BUFFER_FOR_CPU_BIDIR =       'sync_for_cpu_bidir'
BUFFER_FOR_DEVICE_BIDIR =    'sync_for_device_bidir'

92

93 94
GLBL_CIRCBUF_CHN_SIZE = None
GLBL_CIRCBUF_STARTS =   None
95
GLBL_CIRCBUF_ENDS =   None
96
GLBL_CIRCBUF_END =      None
97

98 99
GLBL_MEMBRIDGE_START =  None
GLBL_MEMBRIDGE_END =    None
100 101 102 103 104 105 106

GLBL_MEMBRIDGE_H2D_START =  None
GLBL_MEMBRIDGE_H2D_END =    None

GLBL_MEMBRIDGE_D2H_START =  None
GLBL_MEMBRIDGE_D2H_END =    None

107 108 109
GLBL_BUFFER_END =       None
GLBL_WINDOW =           None

110 111 112 113 114 115 116 117 118 119 120 121
BUFFER_ADDRESS =          None # in bytes
BUFFER_LEN =              None # in bytes

BUFFER_ADDRESS_H2D =      None # in bytes
BUFFER_LEN_H2D =          None # in bytes

BUFFER_ADDRESS_D2H =      None # in bytes
BUFFER_LEN_D2H =          None # in bytes

BUFFER_ADDRESS_BIDIR =    None # in bytes
BUFFER_LEN_BIDIR =        None # in bytes

122 123 124 125 126 127
# old value was 0x200 (of 128-bit bursts), which equals to
# 8-bit mode:  8192 px per row
# 16-bit mode: 4096 px per row (not fit for mt9f002 4384x3288)
# new value 0x400
FRAME_FULL_WIDTH        = 0x400
FRAME_START_ADDRESS_INC = 0x80000
128

129 130
#SENSOR_INTERFACE_PARALLEL = "PAR12"
#SENSOR_INTERFACE_HISPI =    "HISPI"
131
# for now - single sensor type per interface
132
SENSOR_INTERFACES={x393_sensor.SENSOR_INTERFACE_PARALLEL: {"mv":2800, "freq":24.0,   "iface":"2V5_LVDS"},
133
                   x393_sensor.SENSOR_INTERFACE_HISPI:    {"mv":1820, "freq":24.444, "iface":"1V8_LVDS"},
134
                   x393_sensor.SENSOR_INTERFACE_VOSPI:    {"mv":2800, "freq":24.0,   "iface":"2V5_LVDS"}}
135
#                   x393_sensor.SENSOR_INTERFACE_HISPI:    {"mv":2500, "freq":24.444, "iface":"1V8_LVDS"}}
136
#slave is 7 bit
137 138
SENSOR_DEFAULTS= { x393_sensor.SENSOR_INTERFACE_PARALLEL: {"width":2592, "height":1944, "top":0, "left":0, "slave":0x48, "i2c_delay":100, "bayer":3},
                   x393_sensor.SENSOR_INTERFACE_HISPI:    {"width":4384, "height":3288, "top":0, "left":0, "slave":0x10, "i2c_delay":100, "bayer":2},
139 140
#                   x393_sensor.SENSOR_INTERFACE_VOSPI:     {"width":160,  "height":120,  "top":0, "left":0, "slave":0x2a, "i2c_delay":100, "bayer":2}}
                   x393_sensor.SENSOR_INTERFACE_VOSPI:    {"width":160,  "height":122,  "top":0, "left":0, "slave":0x2a, "i2c_delay":100, "bayer":2}}
141

142 143
#SENSOR_DEFAULTS_SIMULATION= {x393_sensor.SENSOR_INTERFACE_PARALLEL: {"width":2592, "height":1944, "top":0, "left":0, "slave":0x48, "i2c_delay":100, "bayer":3},
#                             x393_sensor.SENSOR_INTERFACE_HISPI:   {"width":4384, "height":3288, "top":0, "left":0, "slave":0x10, "i2c_delay":100, "bayer":2}}
144
class X393SensCmprs(object):
145 146 147 148 149 150 151 152 153 154 155 156 157 158
    DRY_MODE =           True # True
    DEBUG_MODE =         1
    x393_mem =           None
    x393_axi_tasks =     None #x393X393AxiControlStatus
    x393_utils =         None
    verbose =            1

    x393Camsync =        None
    x393GPIO =           None
    x393CmprsAfi =       None
    x393Cmprs =          None
    x393FrameSequencer = None
    x393Sensor =         None
    x393Rtc =            None
159
    x393Membridge =      None
160

161
    def __init__(self, debug_mode=1,dry_mode=True, saveFileName=None, nomargins = True): # False):
162 163
#        global BUFFER_ADDRESS, BUFFER_LEN
        global BUFFER_ADDRESS, BUFFER_LEN, COMMAND_ADDRESS, DATAIN_ADDRESS, DATAOUT_ADDRESS
164
        global BUFFER_ADDRESS_H2D, BUFFER_LEN_H2D, BUFFER_ADDRESS_D2H, BUFFER_LEN_D2H, BUFFER_ADDRESS_BIDIR, BUFFER_LEN_BIDIR
165
#        global SENSOR_DEFAULTS_SIMULATION
166
        print ("X393SensCmprs.__init__: dry_mode=",dry_mode)
167 168 169 170 171 172 173 174 175 176 177 178
        if (dry_mode):
            try:
                if ":" in dry_mode:
                    print ("X393SensCmprs.__init__: setting SENSOR_DEFAULTS")
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["width"]=  vrlg.WOI_WIDTH + 2 # 4
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["height"]= vrlg.WOI_HEIGHT + 4
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["top"]=    0
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["left"]=   0
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["width"]=     vrlg.WOI_WIDTH + 2 #4
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["height"]=    vrlg.WOI_HEIGHT + 4
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["top"]=       0
                    SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["left"]=      0
179
                    # keep settings from Python program
180 181 182 183 184
                    #SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_VOSPI]["width"]=     vrlg.WOI_WIDTH #4
                    #SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_VOSPI]["height"]=    vrlg.WOI_HEIGHT
                    #SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_VOSPI]["top"]=       0
                    #SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_VOSPI]["left"]=      0
                    # do not update VOSPI defaults !!!
185 186 187 188 189 190 191
                    if nomargins:
                        SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["width"]=  vrlg.WOI_WIDTH + 0 # 4
                        SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["height"]= vrlg.WOI_HEIGHT + 0
                        SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["width"]=     vrlg.WOI_WIDTH + 0 #4
                        SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["height"]=    vrlg.WOI_HEIGHT + 0
                    
                    
192
                    print ("Using simulation size sensor defaults ",SENSOR_DEFAULTS)
193

194
            except:
195 196
                print ("No simulation server is used, just running in dry mode")

197 198 199 200 201
        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
202

203 204 205 206 207 208 209
        self.x393Camsync =        x393_camsync.X393Camsync(debug_mode,dry_mode, saveFileName)
        self.x393GPIO =           x393_gpio.X393GPIO(debug_mode,dry_mode, saveFileName)
        self.x393CmprsAfi =       x393_cmprs_afi.X393CmprsAfi(debug_mode,dry_mode, saveFileName)
        self.x393Cmprs =          x393_cmprs.X393Cmprs(debug_mode,dry_mode, saveFileName)
        self.x393FrameSequencer = x393_frame_sequencer.X393FrameSequencer(debug_mode,dry_mode, saveFileName)
        self.x393Sensor =         x393_sensor.X393Sensor(debug_mode,dry_mode, saveFileName)
        self.x393Rtc =            x393_rtc.X393Rtc(debug_mode,dry_mode, saveFileName)
210
        self.x393Membridge =      x393_mcntrl_membridge.X393McntrlMembridge(debug_mode,dry_mode)
211 212 213 214
        try:
            self.verbose=vrlg.VERBOSE
        except:
            pass
215
        if dry_mode:
216
            """
217 218 219 220 221 222 223 224
            BUFFER_ADDRESS =       0x38100000
            BUFFER_LEN =           0x06400000
            BUFFER_ADDRESS_H2D =   0x38100000
            BUFFER_LEN_H2D =       0x06400000
            BUFFER_ADDRESS_D2H =   0x38100000
            BUFFER_LEN_D2H =       0x06400000
            BUFFER_ADDRESS_BIDIR = 0x38100000
            BUFFER_LEN_BIDIR =     0x06400000
225 226 227 228 229 230 231 232 233 234 235
            """

            BUFFER_ADDRESS =       0x25500000
            BUFFER_LEN =           0x19000000
            BUFFER_ADDRESS_H2D =   0x25500000
            BUFFER_LEN_H2D =       0x19000000
            BUFFER_ADDRESS_D2H =   0x25500000
            BUFFER_LEN_D2H =       0x19000000
            BUFFER_ADDRESS_BIDIR = 0x25500000
            BUFFER_LEN_BIDIR =     0x19000000

236 237


238 239 240
            print ("Running in simulated mode, using hard-coded addresses:")
        else:
            try:
Andrey Filippov's avatar
Andrey Filippov committed
241
                with open(MEM_PATH + BUFFER_ADDRESS_NAME) as sysfile:
242 243 244 245 246
                    BUFFER_ADDRESS = int(sysfile.read(),0)
                with open(MEM_PATH + BUFFER_PAGES_NAME) as sysfile:
                    BUFFER_LEN = PAGE_SIZE * int(sysfile.read(),0)
            except:
                print("Failed to get reserved physical memory range")
247 248
                print('BUFFER_ADDRESS=', BUFFER_ADDRESS)
                print('BUFFER_LEN=', BUFFER_LEN)
249
                return
250 251 252 253 254 255 256 257

            try:
                with open(MEM_PATH + BUFFER_H2D_ADDRESS_NAME) as sysfile:
                    BUFFER_ADDRESS_H2D=int(sysfile.read(),0)
                with open(MEM_PATH+BUFFER_H2D_PAGES_NAME) as sysfile:
                    BUFFER_LEN_H2D=PAGE_SIZE*int(sysfile.read(),0)
            except:
                print("Failed to get reserved physical memory range")
258 259
                print('BUFFER_ADDRESS_H2D=',BUFFER_ADDRESS_H2D)
                print('BUFFER_LEN_H2D=',BUFFER_LEN_H2D)
260
                return
261

262 263 264 265 266 267 268
            try:
                with open(MEM_PATH + BUFFER_D2H_ADDRESS_NAME) as sysfile:
                    BUFFER_ADDRESS_D2H=int(sysfile.read(),0)
                with open(MEM_PATH+BUFFER_D2H_PAGES_NAME) as sysfile:
                    BUFFER_LEN_D2H=PAGE_SIZE*int(sysfile.read(),0)
            except:
                print("Failed to get reserved physical memory range")
269 270
                print('BUFFER_ADDRESS_D2H=',BUFFER_ADDRESS_D2H)
                print('BUFFER_LEN_D2H=',BUFFER_LEN_D2H)
271
                return
272

273 274 275 276 277 278 279
            try:
                with open(MEM_PATH + BUFFER_BIDIR_ADDRESS_NAME) as sysfile:
                    BUFFER_ADDRESS_BIDIR=int(sysfile.read(),0)
                with open(MEM_PATH+BUFFER_BIDIR_PAGES_NAME) as sysfile:
                    BUFFER_LEN_BIDIR=PAGE_SIZE*int(sysfile.read(),0)
            except:
                print("Failed to get reserved physical memory range")
280 281
                print('BUFFER_ADDRESS_BIDIR=',BUFFER_ADDRESS_BIDIR)
                print('BUFFER_LEN_BIDIR=',BUFFER_LEN_BIDIR)
282
                return
283 284 285


        print('X393SensCmprs: BUFFER_ADDRESS=0x%x'%(BUFFER_ADDRESS))
286 287 288 289 290 291
        print('X393SensCmprs: BUFFER_LEN=0x%x'%(BUFFER_LEN))
    def get_histogram_byte_start(self): # should be 4KB page aligned
        global BUFFER_ADDRESS
        return BUFFER_ADDRESS
    def get_circbuf_byte_start(self): # should be 4KB page aligned
        global BUFFER_ADDRESS
292
        return BUFFER_ADDRESS + 4096* (1 << vrlg.NUM_FRAME_BITS)* 16 # 16 subchannels
293 294 295
    def get_circbuf_byte_end(self): # should be 4KB page aligned
        global BUFFER_ADDRESS, BUFFER_LEN
        return BUFFER_ADDRESS + BUFFER_LEN
Andrey Filippov's avatar
Andrey Filippov committed
296 297 298 299
    def sleep_ms(self, time_ms):
        """
        Sleep for specified number of milliseconds
        @param time_ms - sleep time in milliseconds
300
        """
301
        if (time_ms):
302
            time.sleep(0.001*time_ms)
303
    def setSensorClock(self, freq_MHz = 24.0, iface = "2V5_LVDS", quiet = 0):
304
        """
305
        Set up external clock for sensor-synchronous circuitry (and sensor(s) themselves.
306
        Currently required clock frequency is 1/4 of the sensor clock, so it is 24MHz for 96MHz sensor
307 308
        @param freq_MHz - input clock frequency (MHz). Currently for 96MHZ sensor clock it should be 24.0
        @param iface - one of the supported interfaces
309
               (see ls /sys/devices/soc0/amba@0/e0004000.ps7-i2c/i2c-0/0-0070/output_drivers)
310
        @param quiet - reduce output
311
        """
312 313 314
        if self.DRY_MODE:
            print ("Not defined for simulation mode")
            return
315
        with open ( SI5338_PATH + "/output_drivers/" + iface,      "w") as f:
316 317
            print("2", file = f)
        with open ( SI5338_PATH + "/output_clocks/out2_freq_fract","w") as f:
318
            print("%d"%(round(1000000*freq_MHz)), file = f )
319
        if quiet == 0:
320
            print ("Set sensor clock to %f MHz, driver type \"%s\""%(freq_MHz,iface))
321
    def setSensorPower(self, sub_pair=0, power_on=0, quiet=0):
322
        """
323 324 325
        @param sub_pair - pair of the sensors: 0 - sensors 1 and 2, 1 - sensors 3 and 4
        @param power_on - 1 - power on, 0 - power off (both sensor power and interface/FPGA bank voltage)
        @param quiet - reduce output
326
        """
327
        if quiet == 0:
328
            print (("vcc_sens01 vp33sens01", "vcc_sens23 vp33sens23")[sub_pair]+" -> "+POWER393_PATH + "/channels_"+ ("dis","en")[power_on])
329 330
        with open (POWER393_PATH + "/channels_"+ ("dis","en")[power_on],"w") as f:
            print(("vcc_sens01 vp33sens01", "vcc_sens23 vp33sens23")[sub_pair], file = f)
331

332 333
    def setSensorIfaceVoltage(self, sub_pair, voltage_mv, quiet = 0):
        """
334 335 336 337
        Set interface voltage (should be done before power is on)
        @param sub_pair - pair of the sensors: 0 - sensors 1 and 2, 1 - sensors 3 and 4
        @param voltage_mv - desired interface voltage (1800..2800 mv)
        @param quiet - reduce output
338 339 340 341
        """
        with open (POWER393_PATH + "/voltages_mv/"+ ("vcc_sens01", "vcc_sens23")[sub_pair],"w") as f:
            print(voltage_mv, file = f)
        if quiet == 0:
342
            print ("Set sensors %s interface voltage to %d mV"%(("0, 1","2, 3")[sub_pair],voltage_mv))
343
        time.sleep(0.1)
344

345 346 347 348 349 350
    def setEyesisPower (self, en, dly_ms=0):
        """
        Turn on/off external power supply for Eyesis sensor ports. At startup stupid GPIO system
        interface "thinks" it is off, but it is actually on. So to turn off after boot On-Off sequence
        is needed
        @param en True or 1 - turn power on, False or 0 - turn off
351
        @param dly_ms - delay in ms after turning power on or off
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
        """
        if self.DRY_MODE:
            print ("setEyesisPower() is not defined for simulation mode")
            return
        with open (EYESIS_POWER_PATH,      "w") as f:
            print((EYESIS_POWER_OFF,EYESIS_POWER_ON)[en], file = f)
        self.sleep_ms(dly_ms)

    def setupEyesisPower (self, dly1_ms = 50, dly2_ms=100):
        """
        1. Turn off external power supply for Eyesis sensor ports (it is on after boot),
        2. Set interface voltage (should be with power off)
        3. Turn on power
        @param dly1_ms - delay time in ms after interface voltage
        @param dly2_ms - delay time in ms after external power on/off
        """
        voltage_mv = SENSOR_INTERFACES['PAR12']["mv"]
        if self.DRY_MODE:
            print ("setupEyesisPower() is not defined for simulation mode")
            return
372 373
        #turn off external sensor power
        self.setEyesisPower (True,  0) # stupid GPIO after reset will not turn off if it thinks it is off
374 375 376 377 378 379 380 381 382 383 384
        self.setEyesisPower (False, dly2_ms)
        #Turn off on-board sensor power (just in case)
        for sub_pair in (0,1):
            self.setSensorPower(sub_pair = sub_pair, power_on = 0)
        for sub_pair in (0,1):
            self.setSensorIfaceVoltage(sub_pair=sub_pair, voltage_mv = voltage_mv)
            self.sleep_ms(dly1_ms)
        self.setEyesisPower (True, dly2_ms)
        #Turn on-board sensor power (just in case)
        for sub_pair in (0,1):
            self.setSensorPower(sub_pair = sub_pair, power_on = 0)
385

386
    def setupSensorsPower(self, ifaceType,  pairs = "all", quiet=0, dly=0.0):
Andrey Filippov's avatar
Andrey Filippov committed
387 388
        """
        Set interface voltage and turn on power for interface and the sensors
389
        according to sensor type
390 391 392 393
        @param ifaceType "PAR12" or "HISPI"
        @param pairs - 'all' or list/tuple of pairs of the sensors: 0 - sensors 1 and 2, 1 - sensors 3 and 4
        @param quiet - reduce output
        @param dly - debug feature: step delay in sec
Andrey Filippov's avatar
Andrey Filippov committed
394
        """
395 396 397 398 399 400 401
        try:
            if (pairs == all) or (pairs[0].upper() == "A"): #all is a built-in function
                pairs = (0,1)
        except:
            pass
        if not isinstance(pairs,(list,tuple)):
            pairs = (pairs,)
402
        for pair in pairs:
Andrey Filippov's avatar
Andrey Filippov committed
403 404 405 406
            self.setSensorIfaceVoltagePower(sub_pair =   pair,
                                            voltage_mv = SENSOR_INTERFACES[ifaceType]["mv"],
                                            quiet =      quiet,
                                            dly =        dly)
407

408
    def setSensorIfaceVoltagePower(self, sub_pair, voltage_mv, quiet=0, dly=0.0):
409
        """
410 411 412 413 414
        Set interface voltage and turn on power for interface and the sensors
        @param sub_pair - pair of the sensors: 0 - sensors 1 and 2, 1 - sensors 3 and 4
        @param voltage_mv - desired interface voltage (1800..2800 mv)
        @param quiet - reduce output
        @param dly - debug feature: step delay in sec
415 416
        """
        self.setSensorPower(sub_pair = sub_pair, power_on = 0)
Andrey Filippov's avatar
Andrey Filippov committed
417
        time.sleep(2*dly)
418
        self.setSensorIfaceVoltage(sub_pair=sub_pair, voltage_mv = voltage_mv)
Andrey Filippov's avatar
Andrey Filippov committed
419
        time.sleep(2*dly)
420 421 422
        if self.DRY_MODE:
            print ("Not defined for simulation mode")
            return
423
        if quiet == 0:
424
            print ("Turning on interface power %f V for sensors %s"%(voltage_mv*0.001,("0, 1","2, 3")[sub_pair]))
Andrey Filippov's avatar
Andrey Filippov committed
425
        time.sleep(3*dly)
426 427 428
        with open (POWER393_PATH + "/channels_en","w") as f:
            print(("vcc_sens01", "vcc_sens23")[sub_pair], file = f)
        if quiet == 0:
429
            print ("Turned on interface power %f V for sensors %s"%(voltage_mv*0.001,("0, 1","2, 3")[sub_pair]))
Andrey Filippov's avatar
Andrey Filippov committed
430
        time.sleep(3*dly)
431 432 433
        with open (POWER393_PATH + "/channels_en","w") as f:
            print(("vp33sens01", "vp33sens23")[sub_pair], file = f)
        if quiet == 0:
434
            print ("Turned on +3.3V power for sensors %s"%(("0, 1","2, 3")[sub_pair]))
Andrey Filippov's avatar
Andrey Filippov committed
435
        time.sleep(2*dly)
436

437 438

    def setupSensorsPowerClock(self, setPower=False, quiet=0):
439 440 441
        """
        Set interface voltage for all sensors, clock for frequency and sensor power
        for the interface matching bitstream file
442
        Not possible for diff. termination - power should be set before the bitstream
443
        """
444
        ifaceType = self.x393Sensor.getSensorInterfaceType();
445 446
        if setPower:
            if quiet == 0:
447
                print ("Configuring sensor ports for interface type: \"%s\""%(ifaceType))
448 449
            for sub_pair in (0,1):
                self.setSensorIfaceVoltagePower(sub_pair, SENSOR_INTERFACES[ifaceType]["mv"])
450 451
        self.setSensorClock(freq_MHz = SENSOR_INTERFACES[ifaceType]["freq"], iface = SENSOR_INTERFACES[ifaceType]["iface"])

452 453
#    def setSensorClock(self, freq_MHz = 24.0, iface = "2V5_LVDS"):

454
    def setup_sensor_channel (self,
455 456 457 458
                              exit_step =                 None,
                              num_sensor =                0,
#                              histogram_start_phys_page, # Calculate from?
#                              frame_full_width, # 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
459 460 461 462
                              window_width =              None, # 2592,   # 2592
                              window_height =             None, # 1944,   # 1944
                              window_left =               None, # 0,     # 0
                              window_top =                None, # 0, # 0? 1?
463
#                              compressor_left_margin =    0, #0?`1?
464 465 466
#                              frame_start_address, # calculate through num_sensor, num frames, frame size and start addr?
#                              frame_start_address_inc,
                              last_buf_frame =            1,  #  - just 2-frame buffer
467
                              cmode =                     0, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
468
                              colorsat_blue =             0x120,     # 0x90 fo 1x
469 470
                              colorsat_red =              0x16c,     # 0xb6 for x1
                              clk_sel =                   1,         # 1
471 472 473 474
                              histogram_left =            None, # 0,
                              histogram_top =             None, # 0,
                              histogram_width_m1 =        None, # 2559, #0,
                              histogram_height_m1 =       None, # 1935, #0,
Andrey Filippov's avatar
Andrey Filippov committed
475
                              bits16 =                    False,
476 477
                              verbose =                   1
                              ):
478 479
        """
        Setup one sensor+compressor channel (for one sub-channel only)
480 481 482 483 484 485 486 487 488 489 490
        @param exit_step -         exit after executing specified step:
                                 10 - just after printing calculated values
                                 11 - after programming status
                                 12 - after setup_sensor_memory
                                 13 - after enabling memory controller for the sensor channel
                                 14 - after setup_compressor_channel
                                 15 - after setup_compressor_memory
                                 16 - after compressor run
                                 17 - removing MRST from the sensor
                                 18 - after vignetting, gamma and histograms setup
                                 19 - enabling sensor memory controller (histograms in not yet)
491 492 493 494 495 496
        @param num_sensor - sensor port number (0..3)
        @param window_width -      (here - in pixels)
        @param window_height -     16-bit window height in scan lines
        @param window_left -       left margin of the window (here - in pixels)
        @param window_top -        top margin of the window (16 bit)
        @param last_buf_frame) -   16-bit number of the last frame in a buffer
497 498 499 500 501 502 503 504 505 506 507 508 509 510
        @param cmode -       color mode:
                                CMPRS_CBIT_CMODE_JPEG18 =          0 - color 4:2:0
                                CMPRS_CBIT_CMODE_MONO6 =           1 - mono 4:2:0 (6 blocks)
                                CMPRS_CBIT_CMODE_JP46 =            2 - jp4, 6 blocks, original
                                CMPRS_CBIT_CMODE_JP46DC =          3 - jp4, 6 blocks, dc -improved
                                CMPRS_CBIT_CMODE_JPEG20 =          4 - mono, 4 blocks (but still not actual monochrome JPEG as the blocks are scanned in 2x2 macroblocks)
                                CMPRS_CBIT_CMODE_JP4 =             5 - jp4,  4 blocks, dc-improved
                                CMPRS_CBIT_CMODE_JP4DC =           6 - jp4,  4 blocks, dc-improved
                                CMPRS_CBIT_CMODE_JP4DIFF =         7 - jp4,  4 blocks, differential
                                CMPRS_CBIT_CMODE_JP4DIFFHDR =      8 - jp4,  4 blocks, differential, hdr
                                CMPRS_CBIT_CMODE_JP4DIFFDIV2 =     9 - jp4,  4 blocks, differential, divide by 2
                                CMPRS_CBIT_CMODE_JP4DIFFHDRDIV2 = 10 - jp4,  4 blocks, differential, hdr,divide by 2
                                CMPRS_CBIT_CMODE_MONO1 =          11 -  mono JPEG (not yet implemented)
                                CMPRS_CBIT_CMODE_MONO4 =          14 -  mono 4 blocks
511 512 513 514 515 516 517
        @param colorsat_blue - color saturation for blue (10 bits), 0x90 for 100%
        @param colorsat_red -  color saturation for red (10 bits), 0xb6 for 100%
        @param clk_sel - True - use pixel clock from the sensor, False - use internal clock (provided to the sensor), None - no chnage
        @param histogram_left -      histogram window left margin
        @param histogram_top -       histogram window top margin
        @param histogram_width_m1 -  one less than window width. If 0 - use frame right margin (end of HACT)
        @param histogram_height_m1 - one less than window height. If 0 - use frame bottom margin (end of VACT)
518

519
        ???
520
        @param verbose - verbose level
521
        @return True if all done, False if exited prematurely through exit_step
522
        """
523
#        @param compressor_left_margin - 0..31 - left margin for compressor (to the nearest 32-byte column)
524 525 526

        global FRAME_FULL_WIDTH, FRAME_START_ADDRESS_INC

527
        sensorType = self.x393Sensor.getSensorInterfaceType()
528 529
        if verbose > 0 :
            print ("Sensor port %d interface type: %s"%(num_sensor, sensorType))
530 531
#            print ("setup_sensor_channel(): window_width['width']=",window_width)

532 533 534 535
        window = self.specify_window (window_width =  window_width,
                                      window_height = window_height,
                                      window_left =   window_left,
                                      window_top =    window_top,
536 537
#                                      cmode =         None, # will use 0
                                      cmode =         cmode, # will use 0
538 539 540 541 542 543 544
                                      verbose =       0)
        window_width =   window["width"]
        window_height =  window["height"]
        window_left =    window["left"]
        window_top =     window["top"]
        """
        cmode =          window["cmode"]
545 546 547 548 549 550 551 552
        if window_width is None:
            window_width = SENSOR_DEFAULTS[sensorType]["width"]
        if window_height is None:
            window_height = SENSOR_DEFAULTS[sensorType]["height"]
        if window_left is None:
            window_left = SENSOR_DEFAULTS[sensorType]["left"]
        if window_top is None:
            window_top = SENSOR_DEFAULTS[sensorType]["top"]
553
        """
554

555
        #setting up histogram window, same for parallel, similar for serial
556

557 558 559 560 561 562 563 564 565
        if histogram_left is None:
            histogram_left = 0
        if histogram_top is None:
            histogram_top = 0
        if histogram_width_m1 is None:
            histogram_width_m1 = window_width - 33
        if histogram_height_m1 is None:
            histogram_height_m1 = window_height - 9

566

567 568 569 570
        align_to_bursts = 64 # align full width to multiple of align_to_bursts. 64 is the size of memory access
        width_in_bursts = window_width >> 4
        if (window_width & 0xf):
            width_in_bursts += 1
571
        compressor_left_margin = window_left % 32
572

573 574 575 576 577 578
        num_burst_in_line = (window_left >> 4) + width_in_bursts
        num_pages_in_line = num_burst_in_line // align_to_bursts;
        if num_burst_in_line % align_to_bursts:
            num_pages_in_line += 1
#        frame_full_width -  13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
#        frame_start_address_inc - 22-bit frame start address increment  ((3 CA LSBs==0. BA==0)
579 580 581 582
##        frame_full_width =  num_pages_in_line * align_to_bursts
        """
        Changing frame full width and size to fixed values (normally read from sysfs)
                frame_full_width =  num_pages_in_line * align_to_bursts
583

584
        """
585

586
        frame_full_width =  FRAME_FULL_WIDTH # Made it fixed width
587 588 589



590 591 592
        num8rows=   (window_top + window_height) // 8
        if (window_top + window_height) % 8:
            num8rows += 1
593
        """
594
        frame_start_address_inc = num8rows * frame_full_width
595
        """
596
        frame_start_address_inc = FRAME_START_ADDRESS_INC #Fixed size
597

598
        """ TODO: Calculate tiles and move to initial print """
599 600 601 602 603 604 605 606
        num_macro_cols_m1 = (window_width >> 4) - 1
        num_macro_rows_m1 = (window_height >> 4) - 1

#       frame_start_address, # calculate through num_sensor, num frames, frame size and start addr?
#        rame_start_address - 22-bit frame start address ((3 CA LSBs==0. BA==0)
        frame_start_address = (last_buf_frame + 1) * frame_start_address_inc * num_sensor
#       histogram_start_phys_page - system memory 4K page number to start histogram

607
        histogram_start_phys_page = self.get_histogram_byte_start() // 4096
608

609
        if verbose >0 :
610
            print ("setup_sensor_channel, type=",sensorType)
611 612 613 614 615 616 617 618 619 620
            print ("num_sensor =                ", num_sensor)
            print ("frame_full_width =          ", frame_full_width)
            print ("window_width =              ", window_width)
            print ("window_height =             ", window_height)
            print ("window_left =               ", window_left)
            print ("window_top =                ", window_top)
            print ("frame_start_address =       0x%x"%(frame_start_address))
            print ("frame_start_address_inc =   0x%x"%(frame_start_address_inc))
            print ("histogram_start_phys_page = 0x%x"%(histogram_start_phys_page))
            print ("histogram start address =   0x%x"%(histogram_start_phys_page * 4096))
621 622 623 624
            print ("width_in_bursts =           %d(0x%x)"%(width_in_bursts,width_in_bursts))
            print ("num_burst_in_line =         %d(0x%x)"%(num_burst_in_line,num_burst_in_line))
            print ("num_pages_in_line =         %d(0x%x)"%(num_pages_in_line,num_pages_in_line))
            print ("num8rows =                  %d(0x%x)"%(num8rows,num8rows))
625 626 627
            print ("last_buf_frame =            ", last_buf_frame)
            print ("num_macro_cols_m1 =         ", num_macro_cols_m1)
            print ("num_macro_rows_m1 =         ", num_macro_rows_m1)
628
            print ("cmode =                     ", cmode)
629
            print ("bits16 =                    ", bits16)
630
            print ("verbose =                   ", verbose)
631
        if exit_step == 10: return False
632

633 634 635 636 637 638 639 640 641 642
        self.x393Sensor.program_status_sensor_i2c(
            num_sensor = num_sensor,  # input [1:0] num_sensor;
            mode =       3,           # input [1:0] mode;
            seq_num =    0);          # input [5:0] seq_num;
        self.x393Sensor.program_status_sensor_io(
            num_sensor = num_sensor,  # input [1:0] num_sensor;
            mode =       3,           # input [1:0] mode;
            seq_num =    0);          # input [5:0] seq_num;

        self.x393Cmprs.program_status_compressor(
643
            cmprs_chn =  num_sensor,  # input [1:0] num_sensor;
644 645
            mode =       3,           # input [1:0] mode;
            seq_num =    0);          # input [5:0] seq_num;
646
        if exit_step == 11: return False
647

648
    # moved before camsync to have a valid timestamo w/o special waiting
649
        if verbose >0 :
650
            print ("===================== MEMORY_SENSOR =========================, mode= %d"%(cmode))
651

652
        window_height_memory = window_height
653 654
#        if (cmode==vrlg.CMPRS_CBIT_CMODE_JP4) or (cmode==15): # vrlg.CMPRS_CBIT_CMODE_RAW):
        if (cmode==vrlg.CMPRS_CBIT_CMODE_JP4): # vrlg.CMPRS_CBIT_CMODE_RAW): # RAW may be any umber of lines
655
            window_height_memory &= 0xfff0 # do not need extra margins
656
            num_burst_in_line &= 0xfffe    # make even (assuming left=0)
657 658
#            print ("===================== Mode is JP4 or raw =========================")
            print ("===================== Mode is JP4 =========================")
659
        else:
660 661
#            print ("===================== Mode is neither JP4 nor raw =========================")
            print ("===================== Mode is not JP4 =========================")
662 663 664 665
        if (bits16):
            num_burst_in_line *= 2    
            if verbose >0 :
                print ("Doubling line width for 16-bit mode")
666

667 668 669 670 671 672
        self.x393Sensor.setup_sensor_memory (
            num_sensor =       num_sensor,              # input  [1:0] num_sensor;
            frame_sa =         frame_start_address,     # input [31:0] frame_sa;         # 22-bit frame start address ((3 CA LSBs==0. BA==0)
            frame_sa_inc =     frame_start_address_inc, # input [31:0] frame_sa_inc;     # 22-bit frame start address increment  ((3 CA LSBs==0. BA==0)
            last_frame_num =   last_buf_frame,          # input [31:0] last_frame_num;   # 16-bit number of the last frame in a buffer
            frame_full_width = frame_full_width,        # input [31:0] frame_full_width; # 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
673
            window_width =     num_burst_in_line,       # input [31:0] window_width;     # 13 bit - in 8*16=128 bit bursts
674 675
#            window_height =    window_height,           # input [31:0] window_height;    # 16 bit
            window_height =    window_height_memory,   # input [31:0] window_height;    # 16 bit
676 677 678
            window_left =      window_left >> 4,        # input [31:0] window_left;
            window_top =       window_top);             # input [31:0] window_top;
    # Enable arbitration of sensor-to-memory controller
679 680
        if exit_step == 12: return False

681
        self.x393_axi_tasks.enable_memcntrl_en_dis(8 + num_sensor, True);
682 683
        if exit_step == 13: return False

684 685 686
        self.x393Cmprs.compressor_control(chn =  num_sensor,
                                          run_mode = 0) # reset compressor
        #TODO: Calculate from the image size?
687 688 689
        # replacing with setup compressor:
        self.setup_compressor(chn =  num_sensor,
                               cmode =          cmode,
690
                               bits16 =         bits16,
691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
                               qbank =          0,
                               dc_sub =         True,
                               multi_frame =    True,
                               bayer =          0,
                               focus_mode =     0,
                               coring =         0,
                               window_width =   window_width, # 2592,   # 2592
                               window_height =  window_height, # 1944,   # 1944
                               window_left =    window_left, # 0,     # 0
                               window_top =     window_top, # 0, # 0? 1?
                               last_buf_frame = last_buf_frame,  #  - just 2-frame buffer
                               colorsat_blue =  colorsat_blue, #0x120     # 0x90 for 1x
                               colorsat_red =   colorsat_red, #0x16c,     # 0xb6 for x1
                               verbose =        verbose)

706 707

        if exit_step == 15: return False
708

709
        self.x393Cmprs.compressor_control(
710
                       chn = num_sensor,
711
                       run_mode =  0) #  3)  # run repetitive mode
712 713

        if exit_step == 16: return False
714
        #Set up delays separately, outside of this method
715
        """
716 717
        if verbose >0 :
            print ("===================== DELAYS_SETUP =========================")
718

719 720 721 722 723 724 725 726 727
        self.x393Sensor.set_sensor_io_dly (
                           num_sensor = num_sensor,
                           mmcm_phase = 0,
                           iclk_dly =   0,
                           vact_dly =   0,
                           hact_dly =   0,
                           pxd_dly =    0)
        self.x393Sensor.set_sensor_io_ctl (
                           quadrants =  vrlg.QUADRANTS_PXD_HACT_VACT)
728 729

        """
730
        if verbose >0 :
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
            print ("===================== IO_SETUP, sensorType=",sensorType," =========================")
        if sensorType ==  x393_sensor.SENSOR_INTERFACE_PARALLEL:
            self.x393Sensor.set_sensor_io_width(
                num_sensor = num_sensor, # input    [1:0] num_sensor;
                width =      0) # Or use 0 for sensor-generated HACT input   [15:0] width; # 0 - use HACT, >0 - generate HACT from start to specified width
            self.x393Sensor.set_sensor_io_ctl (
                               num_sensor = num_sensor,
                               mrst =       False,
                               arst =       False,
                               aro  =       False,
                               mmcm_rst =   True,   #reset mmcm
                               clk_sel =    None,   #Dealing with Unisims bug: "Error: [Unisim MMCME2_ADV-4] Input clock can only be switched when..."
                               set_delays = False,
                               quadrants =  None)
            #Wait 200 us in real system
            self.x393Sensor.set_sensor_io_ctl (
                               num_sensor = num_sensor,
                               mrst =       False,
                               arst =       False,
                               aro  =       False,
                               mmcm_rst =   True,   #reset mmcm
                               clk_sel =    clk_sel,
                               set_delays = False,
                               quadrants =  None)
    
            self.x393Sensor.set_sensor_io_ctl (
                               num_sensor = num_sensor,
                               mmcm_rst =   False, # release MMCM reset (maybe wait longer?
                               clk_sel =    clk_sel,
                               set_delays = False,
                               quadrants =  None)
            
763
        elif sensorType ==  x393_sensor.SENSOR_INTERFACE_VOSPI:
764 765
            self.x393Sensor.set_sensor_io_ctl_lwir (
                               num_sensor = num_sensor,
766 767
                               rst  =       2, #  mrst, no power down
                               # TODO - use rst_seq instead?
768 769 770 771 772 773 774
                               mclk  =      True, # None,
                               spi_en =     1, #None, # 1 - reset+disable, 2 - noreset, disable, 3 - noreset, enable
                               segm_zero =  True, #None,
                               out_en =     None,
                               out_single = False,
                               reset_crc =  True,
                               spi_clk =    False) #None)
775
            print ("self.DRY_MODE=",self.DRY_MODE, " resetting VOSPI sensor")
776 777 778
            if  self.DRY_MODE:
                self.x393Sensor.set_sensor_io_ctl_lwir (
                                   num_sensor = num_sensor,
779
                                   rst  =       3) #  no mrst, no power down
780 781 782 783 784 785 786 787 788 789 790
                self.x393Sensor.set_sensor_io_ctl_lwir (
                                   num_sensor = num_sensor,
                                   spi_en =     2) #None, # 1 - reset+disable, 2 - noreset, disable, 3 - noreset, enable
                self.x393Sensor.set_sensor_io_ctl_lwir (
                                   num_sensor = num_sensor,
                                   spi_en =     3, #None, # 1 - reset+disable, 2 - noreset, disable, 3 - noreset, enable
                                   out_en =     True)
            else:    
                self.sleep_ms(0.2) # 1 ms. TODO: For real camera turn off all channels simultaneously ***
                self.x393Sensor.set_sensor_io_ctl_lwir (
                                   num_sensor = num_sensor,
791
                                   rst  =       3, #  no mrst, no power down
792 793
                                   spi_en =     3, #None, # 1 - reset+disable, 2 - noreset, disable, 3 - noreset, enable
                                   out_en =     True)
794 795 796

        if exit_step == 17: return False

797 798 799 800 801 802
        """
        if verbose >0 :
            print ("===================== I2C_TEST =========================")
        self.x393Sensor.test_i2c_353() # test soft/sequencer i2c
        """
        if verbose >0 :
803 804
            print ("===================== LENS_FLAT_SETUP ========================= num_sensor=",num_sensor)
        self.x393Sensor.set_sensor_lens_flat_heights (
805 806 807 808 809 810 811 812 813 814 815
                                      num_sensor = num_sensor,
                                      height0_m1 = 0xffff,
                                      height1_m1 = None,
                                      height2_m1 = None)
        self.x393Sensor.set_sensor_lens_flat_parameters (
                                         num_sensor = num_sensor,
                                         num_sub_sensor = 0,
                                         AX = 0, # 0x20000,
                                         AY = 0, # 0x20000
                                         BX = 0, # 0x180000
                                         BY = 0, # 0x180000
816
                                         C =  0x8000,
817 818 819 820 821 822 823 824 825 826
                                         scales0 =        0x8000,
                                         scales1 =        0x8000,
                                         scales2 =        0x8000,
                                         scales3 =        0x8000,
                                         fatzero_in =     0,
                                         fatzero_out =    0,
                                         post_scale =     1)
        if verbose >0 :
            print ("===================== GAMMA_SETUP =========================")

827
        self.x393Sensor.set_sensor_gamma_heights (
828 829 830 831
                                  num_sensor = num_sensor,
                                  height0_m1 = 0xffff,
                                  height1_m1 = 0,
                                  height2_m1 = 0)
832

833 834 835 836 837
        # Configure histograms
        if verbose >0 :
            print ("===================== HISTOGRAMS_SETUP =========================")
        self.x393Sensor.set_sensor_histogram_window ( # 353 did it using command sequencer)
                                    num_sensor =     num_sensor,
838
                                    subchannel =     0,
839 840 841 842 843 844 845 846
                                    left =           histogram_left,
                                    top =            histogram_top,
                                    width_m1 =       histogram_width_m1,
                                    height_m1 =      histogram_height_m1)

        self.x393Sensor.set_sensor_histogram_saxi_addr (
                                    num_sensor = num_sensor,
                                    subchannel = 0,
847
                                    page = histogram_start_phys_page) # for the channel/subchannel = 0/0
848

849 850 851
        self.x393Sensor.set_sensor_histogram_saxi (
                                   en = True,
                                   nrst = True,
852
                                   confirm_write = False, # True,
853 854
                                   cache_mode = 3)

855 856
        if exit_step == 18: return False

857 858 859
        # Run after histogram channel is set up?
        if verbose >0 :
            print ("===================== SENSOR_SETUP =========================")
860

861 862 863
        self.x393Sensor.set_sensor_mode (
            num_sensor = num_sensor,
            hist_en =    1, # bitmask, only first subchannel
864 865
            hist_nrst =  1, # bitmask, only first subchannel
            chn_en =     True,
Andrey Filippov's avatar
Andrey Filippov committed
866
            bits16 =     bits16) #False)
867 868 869 870 871 872

        if verbose >0 :
            print ("===================== CMPRS_EN_ARBIT =========================")
    # just temporarily - enable channel immediately
        self.x393_axi_tasks.enable_memcntrl_en_dis(12 + num_sensor, True);

873 874
        if exit_step == 19: return False

875 876
        if verbose >0 :
            print ("===================== GAMMA_CTL =========================")
877
        self.x393Sensor.set_sensor_gamma_ctl (# doing last to enable sensor data when everything else is set up
878 879 880 881 882 883
            num_sensor = num_sensor, # input   [1:0] num_sensor; # sensor channel number (0..3)
            bayer =      0,
            table_page = 0,
            en_input =   True,
            repet_mode = True, #  Normal mode, single trigger - just for debugging  TODO: re-assign?
            trig = False)
884
        return True
885

886
    def specify_window (self,
887 888
                        window_width =              None, # 2592
                        window_height =             None, # 1944
889 890
                        window_left =               None,     # 0
                        window_top =                None, # 0? 1?
891
                        cmode =                     None,
892 893 894 895 896
                        bayer =                     None,
                        y_quality =                 None,
                        c_quality =                 None, # use "same" to save None
                        portrait =                  None,
                        gamma =                     None,
897
                        black =                     None, # 0.04
898
                        colorsat_blue =             None, # colorsat_blue, #0x120     # 0x90 for 1x
899
                        colorsat_red =              None, # colorsat_red, #0x16c,     # 0xb6 for x1
900
                        verbose =                   1
901
                        ):
902 903 904
        
        
        
905 906 907
        global GLBL_WINDOW
        if GLBL_WINDOW is None:
            GLBL_WINDOW = {}
908
        sensorType = self.x393Sensor.getSensorInterfaceType()
909 910 911
        if verbose > 0 :
            print ("Sensor interface type: %s"%(sensorType))
        if window_width is None:
912 913 914 915
            try:
                window_width = GLBL_WINDOW["width"]
            except:
                window_width = SENSOR_DEFAULTS[sensorType]["width"]
916
#        print ("specify_window()1.: window_width['width']=",window_width) #256
917
        if window_height is None:
918 919 920 921
            try:
                window_height = GLBL_WINDOW["height"]
            except:
                window_height = SENSOR_DEFAULTS[sensorType]["height"]
922
        if window_left is None:
923 924 925 926
            try:
                window_left = GLBL_WINDOW["left"]
            except:
                window_left = SENSOR_DEFAULTS[sensorType]["left"]
927
        if window_top is None:
928 929 930 931 932 933 934 935 936
            try:
                window_top = GLBL_WINDOW["top"]
            except:
                window_top = SENSOR_DEFAULTS[sensorType]["top"]
        if cmode is None:
            try:
                cmode = GLBL_WINDOW["cmode"]
            except:
                cmode = 0
937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955

        if bayer is None:
            try:
                bayer = GLBL_WINDOW["bayer"]
            except:
                bayer = SENSOR_DEFAULTS[sensorType]["bayer"]

        if y_quality is None:
            try:
                y_quality = GLBL_WINDOW["y_quality"]
            except:
                y_quality = 100

        if c_quality is None:
            try:
                c_quality = GLBL_WINDOW["c_quality"]
            except:
                c_quality = "same"
        if c_quality == "same": # to save as None, not to not save
956 957
                c_quality = None

958 959 960 961 962
        if portrait is None:
            try:
                portrait = GLBL_WINDOW["portrait"]
            except:
                portrait = False
963

964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
        if gamma is None:
            try:
                gamma = GLBL_WINDOW["gamma"]
            except:
                gamma = 0.57

        if black is None:
            try:
                black = GLBL_WINDOW["black"]
            except:
                black = 0.04

        if colorsat_blue is None:
            try:
                colorsat_blue = GLBL_WINDOW["colorsat_blue"]
            except:
                colorsat_blue = 2.0 # *0x90

        if colorsat_red is None:
            try:
                colorsat_red = GLBL_WINDOW["colorsat_red"]
            except:
                colorsat_red = 2.0 #  *0xb6
987

988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005
        GLBL_WINDOW = {"width":         window_width,
                       "height":        window_height,
                       "left":          window_left,
                       "top":           window_top,
                       "cmode":         cmode,
                       "bayer":         bayer,
                       "y_quality":     y_quality,
                       "c_quality":     c_quality,
                       "portrait":      portrait,
                       "gamma":         gamma,
                       "black":         black,
                       "colorsat_blue": colorsat_blue,
                       "colorsat_red":  colorsat_red,
                       }
        if verbose > 1:
            print("GLBL_WINDOW:")
            for k in GLBL_WINDOW.keys():
                print ("%15s:%s"%(k,str(GLBL_WINDOW[k])))
1006
        return GLBL_WINDOW
1007 1008


1009
    def specify_phys_memory(self,
Oleg Dzhimiev's avatar
Oleg Dzhimiev committed
1010
                            circbuf_chn_size= 0x4000000,
1011 1012 1013 1014
                            verbose =         1):
        """
        @param circbuf_chn_size - circular buffer size for each channel, in bytes
        """
1015 1016 1017
        global GLBL_CIRCBUF_CHN_SIZE, GLBL_CIRCBUF_STARTS, GLBL_CIRCBUF_ENDS, GLBL_CIRCBUF_END, GLBL_MEMBRIDGE_START, GLBL_MEMBRIDGE_END, GLBL_BUFFER_END
        global GLBL_MEMBRIDGE_H2D_START, GLBL_MEMBRIDGE_H2D_END, GLBL_MEMBRIDGE_D2H_START, GLBL_MEMBRIDGE_D2H_END
        global BUFFER_ADDRESS_H2D, BUFFER_LEN_H2D, BUFFER_ADDRESS_D2H, BUFFER_LEN_D2H
1018

1019 1020 1021 1022
        circbuf_start =   self.get_circbuf_byte_start()
        GLBL_BUFFER_END=  self.get_circbuf_byte_end()
        GLBL_CIRCBUF_CHN_SIZE = circbuf_chn_size
        GLBL_CIRCBUF_STARTS=[]
1023
        GLBL_CIRCBUF_ENDS=[]
1024 1025
        for i in range(16):
            GLBL_CIRCBUF_STARTS.append(circbuf_start + i*circbuf_chn_size)
1026
            GLBL_CIRCBUF_ENDS.append(circbuf_start + (i+1)*circbuf_chn_size)
1027 1028 1029
        GLBL_CIRCBUF_END =     circbuf_start + 4*GLBL_CIRCBUF_CHN_SIZE
        GLBL_MEMBRIDGE_START = GLBL_CIRCBUF_END
        GLBL_MEMBRIDGE_END =   GLBL_BUFFER_END
1030 1031 1032 1033 1034 1035

        GLBL_MEMBRIDGE_H2D_START = BUFFER_ADDRESS_H2D
        GLBL_MEMBRIDGE_H2D_END =   BUFFER_ADDRESS_H2D + BUFFER_LEN_H2D

        GLBL_MEMBRIDGE_D2H_START = BUFFER_ADDRESS_D2H
        GLBL_MEMBRIDGE_D2H_END =   BUFFER_ADDRESS_D2H + BUFFER_LEN_D2H
1036

1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
        if verbose >0 :
            print ("compressor system memory buffers:")
            print ("circbuf start 0 =           0x%x"%(GLBL_CIRCBUF_STARTS[0]))
            print ("circbuf start 1 =           0x%x"%(GLBL_CIRCBUF_STARTS[1]))
            print ("circbuf start 2 =           0x%x"%(GLBL_CIRCBUF_STARTS[2]))
            print ("circbuf start 3 =           0x%x"%(GLBL_CIRCBUF_STARTS[3]))
            print ("circbuf end =               0x%x"%(GLBL_BUFFER_END))
            print ("membridge start =           0x%x"%(GLBL_MEMBRIDGE_START))
            print ("membridge end =             0x%x"%(GLBL_MEMBRIDGE_END))
            print ("membridge size =            %d bytes"%(GLBL_MEMBRIDGE_END - GLBL_MEMBRIDGE_START))
1047 1048 1049 1050 1051 1052
            print ("membridge h2d_start =       0x%x"%(GLBL_MEMBRIDGE_H2D_START))
            print ("membridge h2d end =         0x%x"%(GLBL_MEMBRIDGE_H2D_END))
            print ("membridge h2d size =        %d bytes"%(GLBL_MEMBRIDGE_H2D_END - GLBL_MEMBRIDGE_H2D_START))
            print ("membridge h2d start =       0x%x"%(GLBL_MEMBRIDGE_D2H_START))
            print ("membridge h2d end =         0x%x"%(GLBL_MEMBRIDGE_D2H_END))
            print ("membridge h2d size =        %d bytes"%(GLBL_MEMBRIDGE_D2H_END - GLBL_MEMBRIDGE_D2H_START))
1053
            print ("memory buffer end =         0x%x"%(GLBL_BUFFER_END))
1054 1055 1056 1057 1058
    def setup_cmdmux (self):
        #Will report frame number for each channel
        """
        Configure status report for command sequencer to report 4 LSB of each channel frame number
        with get_frame_numbers()
1059
        """
1060
        self.x393_axi_tasks.program_status( # also takes snapshot
Andrey Filippov's avatar
Andrey Filippov committed
1061 1062 1063 1064
                                           base_addr =    vrlg.CMDSEQMUX_ADDR,
                                           reg_addr =     0,
                                           mode =         3,     # input [1:0] mode;
                                           seq_number =   0)     #input [5:0] seq_num;
1065 1066 1067 1068 1069 1070 1071 1072 1073
    def get_frame_numbers(self):
        """
        @return list of 4-bit frame numbers, per channel
        """
        status =   self.x393_axi_tasks.read_status(address = vrlg.CMDSEQMUX_STATUS)
        frames = []
        for i in range(4):
            frames.append (int((status >> (4*i)) & 0xf))
        return frames
1074 1075 1076 1077 1078 1079 1080
    def get_frame_number(self,
                         channel=0):
        """
        @return frame number of the sequencer for the specified channel (4 bits)
        """
        status =   self.x393_axi_tasks.read_status(address = vrlg.CMDSEQMUX_STATUS)
        return int((status >> (4*channel)) & 0xf)
1081

1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
    def get_frame_number_i2c(self,
                             channel=0):
        """
        @return frame number of the i2c sequencer for the specified channel
        """
        try:
            if (channel == all) or (channel[0].upper() == "A"): #all is a built-in function
                frames=[]
                for channel in range(4):
                    frames.append(self.get_frame_number_i2c(channel = channel))
1092
                return frames
1093
        except:
1094
            pass
1095 1096 1097
        status = self.x393_axi_tasks.read_status(
                    address = vrlg.SENSI2C_STATUS_REG_BASE + channel * vrlg.SENSI2C_STATUS_REG_INC + vrlg.SENSI2C_STATUS_REG_REL)
        return int((status >> 12) & 0xf)
1098

1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
    def skip_frame(self,
                   channel_mask,
                   loop_delay = 0.01,
                   timeout = 2.0):
        old_frames = self.get_frame_numbers()
        timeout_time = time.time() + timeout
        frameno = -1
        while time.time() < timeout_time :
            new_frames = self.get_frame_numbers()
            all_new=True
            for chn in range(4):
                if ((channel_mask >> chn) & 1):
                    if (old_frames[chn] == new_frames[chn]):
                        all_new = False
                        break
                    else:
                        frameno = new_frames[chn]
            if all_new:
                break;
1118
        return frameno # Frame number of the last  new frame checked
1119

1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
    def wait_frame(self,
                   channel = 0,
                   frame =      0,
                   loop_delay = 0.01,
                   timeout = 2.0):
        timeout_time = time.time() + timeout
        frameno = -1
        while time.time() < timeout_time :
            frameno = self.get_frame_number(channel)
            if frameno == (frame & 15):
                return frameno
1131
        return frameno # Frame number of the last  new frame checked
1132

1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
    def skip_frame_i2c(self,
                   channel_mask,
                   loop_delay = 0.01,
                   timeout = 2.0):
        old_frames = self.get_frame_number_i2c("all")
        timeout_time = time.time() + timeout
        frameno = -1
        while time.time() < timeout_time :
            new_frames = self.get_frame_number_i2c("all")
            all_new=True
            for chn in range(4):
                if ((channel_mask >> chn) & 1):
                    if (old_frames[chn] == new_frames[chn]):
                        all_new = False
                        break
                    else:
                        frameno = new_frames[chn]
            if all_new:
                break;
1152 1153
        return frameno # Frame number of the last  new frame checked

1154 1155
    def setup_compressor(self,
                          chn,
1156
                          cmode =            0, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
1157
                          bits16 =           0,
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
                          bayer =            0,
                          qbank =            0,
                          dc_sub =           1,
                          multi_frame =      1,
                          focus_mode =       0,
                          coring =           0,
                          window_width =     None, # 2592,   # 2592
                          window_height =    None, # 1944,   # 1944
                          window_left =      None, # 0,     # 0
                          window_top =       None, # 0, # 0? 1?
                          last_buf_frame =   1,  #  - just 2-frame buffer
1169
                          colorsat_blue =    0x120,     # 0x90 for 1x
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
                          colorsat_red =     0x16c,     # 0xb6 for x1
                          verbose =          1):
        """
        @param chn -         compressor channel (0..3)
        @param cmode -       color mode:
                                CMPRS_CBIT_CMODE_JPEG18 =          0 - color 4:2:0
                                CMPRS_CBIT_CMODE_MONO6 =           1 - mono 4:2:0 (6 blocks)
                                CMPRS_CBIT_CMODE_JP46 =            2 - jp4, 6 blocks, original
                                CMPRS_CBIT_CMODE_JP46DC =          3 - jp4, 6 blocks, dc -improved
                                CMPRS_CBIT_CMODE_JPEG20 =          4 - mono, 4 blocks (but still not actual monochrome JPEG as the blocks are scanned in 2x2 macroblocks)
                                CMPRS_CBIT_CMODE_JP4 =             5 - jp4,  4 blocks, dc-improved
                                CMPRS_CBIT_CMODE_JP4DC =           6 - jp4,  4 blocks, dc-improved
                                CMPRS_CBIT_CMODE_JP4DIFF =         7 - jp4,  4 blocks, differential
                                CMPRS_CBIT_CMODE_JP4DIFFHDR =      8 - jp4,  4 blocks, differential, hdr
                                CMPRS_CBIT_CMODE_JP4DIFFDIV2 =     9 - jp4,  4 blocks, differential, divide by 2
                                CMPRS_CBIT_CMODE_JP4DIFFHDRDIV2 = 10 - jp4,  4 blocks, differential, hdr,divide by 2
                                CMPRS_CBIT_CMODE_MONO1 =          11 -  mono JPEG (not yet implemented)
                                CMPRS_CBIT_CMODE_MONO4 =          14 -  mono 4 blocks
1188
                                CMPRS_CBIT_CMODE_RAW =            15 -  raw (uncompressed) mode
1189
        @param bits16 -       16-bit (2 bytes per pixel) mode                                
1190 1191 1192 1193
        @param qbank -       quantization table page (0..15)
        @param dc_sub -      True - subtract DC before running DCT, False - no subtraction, convert as is,
        @param multi_frame -  False - single-frame buffer, True - multi-frame video memory buffer,
        @param bayer -        Bayer shift (0..3)
1194
        @param focus_mode -   focus mode - how to combine image with "focus quality" in the result image
1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
        @param coring - coring value
        @param window_width -      (here - in pixels)
        @param window_height -     16-bit window height in scan lines
        @param window_left -       left margin of the window (here - in pixels)
        @param window_top -        top margin of the window (16 bit)
        @param last_buf_frame) -   16-bit number of the last frame in a buffer
        @param colorsat_blue - color saturation for blue (10 bits), 0x90 for 100%
        @param colorsat_red -  color saturation for red (10 bits), 0xb6 for 100%
        @param verbose - verbose level
        """
1205 1206 1207

        global FRAME_FULL_WIDTH, FRAME_START_ADDRESS_INC

1208 1209 1210
        try:
            if (chn == all) or (chn[0].upper() == "A"): #all is a built-in function
                for chn in range(4):
1211
                    self. setup_compressor( #self,
1212 1213
                                           chn =            chn,
                                           cmode =          cmode,
1214
                                           bits16 =          bits16,
1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225
                                           qbank =          qbank,
                                           dc_sub =         dc_sub,
                                           multi_frame =    multi_frame,
                                           bayer =          bayer,
                                           focus_mode =     focus_mode,
                                           coring =         coring,
                                           window_width =   None, # 2592,   # 2592
                                           window_height =  None, # 1944,   # 1944
                                           window_left =    None, # 0,     # 0
                                           window_top =     None, # 0, # 0? 1?
                                           last_buf_frame = last_buf_frame,  #  - just 2-frame buffer
1226
                                           colorsat_blue =  colorsat_blue, #0x120     # 0x90 for 1x
1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242
                                           colorsat_red =   colorsat_red, #0x16c,     # 0xb6 for x1
                                           verbose =        verbose)
                return
        except:
            pass
        window = self.specify_window (window_width =  window_width,
                                      window_height = window_height,
                                      window_left =   window_left,
                                      window_top =    window_top,
                                      cmode =         cmode, # will use 0
                                      verbose =       0)
        window_width =   window["width"]
        window_height =  window["height"]
        window_left =    window["left"]
        window_top =     window["top"]
        cmode =          window["cmode"]
1243
        COLOR_MARGINS = 2
1244
        num_sensor = chn # 1:1 sensor - compressor
1245

1246
        align_to_bursts = 64 # align full width to multiple of align_to_bursts. 64 is the size of memory access
1247

1248 1249 1250 1251
        width_in_bursts = window_width >> 4
        if (window_width & 0xf):
            width_in_bursts += 1
        compressor_left_margin = window_left % 32
1252

1253 1254 1255 1256
        num_burst_in_line = (window_left >> 4) + width_in_bursts
        num_pages_in_line = num_burst_in_line // align_to_bursts;
        if num_burst_in_line % align_to_bursts:
            num_pages_in_line += 1
1257 1258 1259
        """
        Changing frame full width and size to fixed values (normally read from sysfs)
                frame_full_width =  num_pages_in_line * align_to_bursts
1260

1261
        """
1262

1263
        frame_full_width =  FRAME_FULL_WIDTH # Made it fixed width
1264 1265 1266
        num8rows=   (window_top + window_height) // 8
        if (window_top + window_height) % 8:
            num8rows += 1
1267
        """
1268
        frame_start_address_inc = num8rows * frame_full_width
1269
        """
1270
        frame_start_address_inc = FRAME_START_ADDRESS_INC #Fixed size
1271 1272

        num_macro_cols_m1 = (window_width >> 4) - 1
1273
        
1274
        if (cmode == vrlg.CMPRS_CBIT_CMODE_RAW) and (bits16):
1275 1276 1277 1278 1279
            num_macro_cols_m1 = ((window_width >> 4) << 1) - 1
        else:
            num_macro_cols_m1 = (window_width >> 4) - 1
            
        if (cmode == vrlg.CMPRS_CBIT_CMODE_RAW):
1280
            num_macro_rows_m1 = (window_height -1) >> 4
1281
            cmprs_mem_height = window_height
1282 1283
            if (verbose > 0) :
                print ("num_macro_rows_m1 =       ", num_macro_rows_m1, " (raw mode, cmode=",cmode,")")
1284
        else:
1285
            num_macro_rows_m1 = (window_height >> 4) - 1
1286
            cmprs_mem_height = window_height & 0xfff0
1287 1288 1289
            if (verbose > 0) :
                print ("num_macro_rows_m1 =       ", num_macro_rows_m1, " (not raw mode, cmode=",cmode,")")
            
1290
            
1291
        frame_start_address = (last_buf_frame + 1) * frame_start_address_inc * num_sensor
1292

1293 1294 1295 1296 1297
        self.x393Cmprs.setup_compressor_channel (
                                  chn =               chn,
                                  qbank =             qbank,
                                  dc_sub =            dc_sub,
                                  cmode =             cmode, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
1298
                                  bits16 =             bits16,
1299 1300 1301 1302 1303
                                  multi_frame =       True,
                                  bayer       =       bayer,
                                  focus_mode  =       focus_mode,
                                  num_macro_cols_m1 = num_macro_cols_m1,
                                  num_macro_rows_m1 = num_macro_rows_m1,
1304
                                  row_lsb_raw =       (window_height -1) & 0xf,
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
                                  left_margin =       compressor_left_margin,
                                  colorsat_blue =     colorsat_blue,
                                  colorsat_red =      colorsat_red,
                                  coring =            0,
                                  verbose =           verbose)
    # TODO: calculate widths correctly!
        if cmode == vrlg.CMPRS_CBIT_CMODE_JPEG18:
            tile_margin = 2 # 18x18 instead of 16x16
            tile_width =  2
            extra_pages = 1
1315

1316 1317 1318 1319
        else: # actually other modes should be parsed here, now considering just JP4 flavors
            tile_margin = 0 # 18x18 instead of 16x16
            tile_width =  4
#            extra_pages = (0,1)[(compressor_left_margin % 16) != 0] # memory access block border does not cut macroblocks
1320
            extra_pages = 0 #  1 # just testing, 0 should be OK  here
1321 1322 1323 1324 1325 1326
        tile_vstep = 16
        tile_height = tile_vstep + tile_margin

        left_tiles32 = window_left // 32
        last_tile32 = (window_left + ((num_macro_cols_m1 + 1) * 16) + tile_margin - 1) // 32
        width32 = last_tile32 - left_tiles32 + 1 # number of 32-wide tiles needed in each row
1327
        comp_mem_linear = (0,1)[cmode == vrlg.CMPRS_CBIT_CMODE_RAW]
1328 1329 1330 1331 1332
#        Already done
#        if (bits16):
#            width32 *= 2    
#            if verbose >0 :
#                print ("Doubling line width for 16-bit mode")
1333

1334 1335 1336 1337 1338 1339 1340
        if (verbose > 0) :
            print ("setup_compressor_memory:")
            print ("num_sensor =       ", num_sensor)
            print ("frame_sa =         0x%x"%(frame_start_address))
            print ("frame_sa_inc =     0x%x"%(frame_start_address_inc))
            print ("last_frame_num =   0x%x"%(last_buf_frame))
            print ("frame_full_width = 0x%x"%(frame_full_width))
1341
            print ("window_width =     0x%x (in 16 - bursts, made even)"%(width32 * 2 )) # window_width >> 4)) # width in 16 - bursts, made even
1342
            print ("window_height =    0x%x"%(cmprs_mem_height)) # window_height & 0xfffffff0))
1343 1344 1345
            print ("window_left =      0x%x"%(left_tiles32 * 2)) # window_left >> 4)) # left in 16-byte bursts, made even
            print ("window_top =       0x%x"%(window_top))
            print ("byte32 =           1")
1346
            print ("linear =           ",comp_mem_linear)
1347 1348 1349 1350 1351
            print ("tile_width =       0x%x"%(tile_width))
            print ("tile_vstep =       0x%x"%(tile_vstep))
            print ("tile_height =      0x%x"%(tile_height))
            print ("extra_pages =      0x%x"%(extra_pages))
            print ("disable_need =     1")
1352
            print ("abort_late =       0")
1353 1354 1355 1356 1357 1358 1359 1360

        self.x393Cmprs.setup_compressor_memory (
            num_sensor =       num_sensor,
            frame_sa =         frame_start_address,         # input [31:0] frame_sa;         # 22-bit frame start address ((3 CA LSBs==0. BA==0)
            frame_sa_inc =     frame_start_address_inc,     # input [31:0] frame_sa_inc;     # 22-bit frame start address increment  ((3 CA LSBs==0. BA==0)
            last_frame_num =   last_buf_frame,              # input [31:0] last_frame_num;   # 16-bit number of the last frame in a buffer
            frame_full_width = frame_full_width,            # input [31:0] frame_full_width; # 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
            window_width =     (width32 * 2 ),              # input [31:0] window_width;     # 13 bit - in 8*16=128 bit bursts
1361 1362 1363

            window_height =    cmprs_mem_height, #  window_height & 0xfffffff0,  # input [31:0] window_height;    # 16 bit

1364 1365 1366
            window_left =      left_tiles32 * 2,            # input [31:0] window_left;
            window_top =       window_top,                  # input [31:0] window_top;
            byte32 =           1,
1367
            linear =           comp_mem_linear,
1368 1369 1370 1371
            tile_width =       tile_width,
            tile_vstep =       tile_vstep,
            tile_height =      tile_height,
            extra_pages =      extra_pages,
1372 1373 1374
            disable_need =     1,
            abort_late =       False)

1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389
    def reset_channels(self,
                       sensor_mask = 0x1,
                       reset_mask =  0xf):
        """
        Reset channels before re-programming
        @param sensor_mask -       bitmap of the selected channels (1 - only channel 0, 0xf - all channels)
        @param reset_mask -        +1 - reset sensor(s) (MRST and internal),
                                   +2 - reset compressor(s)
                                   +4 - reset sensor-to-memory modules
                                   +8 - reset memory-to-compressor modules
        """
        MASK_SENSOR =        1
        MASK_COMPRESSOR =    2
        MASK_MEMSENSOR =     4
        MASK_MEMCOMPRESSOR = 8
1390

1391 1392 1393 1394 1395
        for chn in range (4):
            if sensor_mask & (1 << chn):
                if reset_mask & MASK_COMPRESSOR:
                    self.x393Cmprs.compressor_control        (chn =      chn,
                                                              run_mode = 1) # stop after frame done
1396

1397 1398 1399
                if reset_mask & MASK_MEMSENSOR:
                    self.x393Sensor.control_sensor_memory    (num_sensor = chn,
                                                              command = 'stop')
1400

1401 1402 1403
                if reset_mask & MASK_MEMCOMPRESSOR:
                    self.x393Cmprs.control_compressor_memory (num_sensor = chn,
                                                              command = 'stop')
1404 1405

        self.sleep_ms(200)
1406 1407 1408 1409 1410 1411 1412 1413
        for chn in range (4):
            if sensor_mask & (1 << chn):
                if reset_mask & MASK_COMPRESSOR:
                    self.x393Cmprs.compressor_control        (chn =      chn,
                                                              run_mode = 0)  # reset, 'kill -9'
                if reset_mask & MASK_MEMSENSOR:
                    self.x393Sensor.control_sensor_memory    (num_sensor = chn,
                                                              command = 'reset')
1414

1415 1416 1417 1418 1419 1420 1421 1422
                if reset_mask & MASK_MEMCOMPRESSOR:
                    self.x393Cmprs.control_compressor_memory (num_sensor = chn,
                                                              command = 'reset')

                if reset_mask & MASK_SENSOR:
                    self.x393Sensor.set_sensor_io_ctl        (num_sensor =  chn,
                                                              mrst =        True)

1423

1424
    def setup_all_sensors (self,
1425
                              setup_membridge =           False,
1426 1427 1428
                              exit_step =                 None,
                              sensor_mask =               0x1, # channel 0 only
                              gamma_load =                False,
1429 1430 1431 1432
                              window_width =              None, # 2592,   # 2592
                              window_height =             None, # 1944,   # 1944
                              window_left =               None, # 0,     # 0
                              window_top =                None, # 0, # 0? 1?
1433
                              compressor_left_margin =    0, #0?`1?