x393_sens_cmprs.py 139 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 122
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


123 124
#SENSOR_INTERFACE_PARALLEL = "PAR12"
#SENSOR_INTERFACE_HISPI =    "HISPI"
125
# for now - single sensor type per interface
126 127
SENSOR_INTERFACES={x393_sensor.SENSOR_INTERFACE_PARALLEL: {"mv":2800, "freq":24.0,   "iface":"2V5_LVDS"},
                   x393_sensor.SENSOR_INTERFACE_HISPI:    {"mv":1820, "freq":24.444, "iface":"1V8_LVDS"}}
128
#                   x393_sensor.SENSOR_INTERFACE_HISPI:    {"mv":2500, "freq":24.444, "iface":"1V8_LVDS"}}
129

130 131
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}}
132

133 134
#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}}
135
class X393SensCmprs(object):
136 137 138 139 140 141 142 143 144 145 146 147 148 149
    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
150
    x393Membridge =      None
151

152
    def __init__(self, debug_mode=1,dry_mode=True, saveFileName=None):
153 154
#        global BUFFER_ADDRESS, BUFFER_LEN
        global BUFFER_ADDRESS, BUFFER_LEN, COMMAND_ADDRESS, DATAIN_ADDRESS, DATAOUT_ADDRESS
155
        global BUFFER_ADDRESS_H2D, BUFFER_LEN_H2D, BUFFER_ADDRESS_D2H, BUFFER_LEN_D2H, BUFFER_ADDRESS_BIDIR, BUFFER_LEN_BIDIR
156
#        global SENSOR_DEFAULTS_SIMULATION
157
        print ("X393SensCmprs.__init__: dry_mode=",dry_mode)
158 159 160 161 162 163 164 165 166 167 168 169 170
        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
                    print ("Using simulation size sensor defaults ",SENSOR_DEFAULTS)
171

172
            except:
173 174
                print ("No simulation server is used, just running in dry mode")

175 176 177 178 179
        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
180

181 182 183 184 185 186 187
        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)
188
        self.x393Membridge =      x393_mcntrl_membridge.X393McntrlMembridge(debug_mode,dry_mode)
189 190 191 192
        try:
            self.verbose=vrlg.VERBOSE
        except:
            pass
193
        if dry_mode:
194
            """
195 196 197 198 199 200 201 202
            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
203 204 205 206 207 208 209 210 211 212 213
            """

            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

214 215


216 217 218
            print ("Running in simulated mode, using hard-coded addresses:")
        else:
            try:
Andrey Filippov's avatar
Andrey Filippov committed
219
                with open(MEM_PATH + BUFFER_ADDRESS_NAME) as sysfile:
220 221 222 223 224
                    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")
225 226
                print('BUFFER_ADDRESS=', BUFFER_ADDRESS)
                print('BUFFER_LEN=', BUFFER_LEN)
227
                return
228 229 230 231 232 233 234 235

            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")
236 237
                print('BUFFER_ADDRESS_H2D=',BUFFER_ADDRESS_H2D)
                print('BUFFER_LEN_H2D=',BUFFER_LEN_H2D)
238
                return
239

240 241 242 243 244 245 246
            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")
247 248
                print('BUFFER_ADDRESS_D2H=',BUFFER_ADDRESS_D2H)
                print('BUFFER_LEN_D2H=',BUFFER_LEN_D2H)
249
                return
250

251 252 253 254 255 256 257
            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")
258 259
                print('BUFFER_ADDRESS_BIDIR=',BUFFER_ADDRESS_BIDIR)
                print('BUFFER_LEN_BIDIR=',BUFFER_LEN_BIDIR)
260
                return
261 262 263


        print('X393SensCmprs: BUFFER_ADDRESS=0x%x'%(BUFFER_ADDRESS))
264 265 266 267 268 269
        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
270
        return BUFFER_ADDRESS + 4096* (1 << vrlg.NUM_FRAME_BITS)* 16 # 16 subchannels
271 272 273
    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
274 275 276 277
    def sleep_ms(self, time_ms):
        """
        Sleep for specified number of milliseconds
        @param time_ms - sleep time in milliseconds
278
        """
279
        if (time_ms):
280
            time.sleep(0.001*time_ms)
281
    def setSensorClock(self, freq_MHz = 24.0, iface = "2V5_LVDS", quiet = 0):
282
        """
283
        Set up external clock for sensor-synchronous circuitry (and sensor(s) themselves.
284
        Currently required clock frequency is 1/4 of the sensor clock, so it is 24MHz for 96MHz sensor
285 286
        @param freq_MHz - input clock frequency (MHz). Currently for 96MHZ sensor clock it should be 24.0
        @param iface - one of the supported interfaces
287
               (see ls /sys/devices/soc0/amba@0/e0004000.ps7-i2c/i2c-0/0-0070/output_drivers)
288
        @param quiet - reduce output
289
        """
290 291 292
        if self.DRY_MODE:
            print ("Not defined for simulation mode")
            return
293
        with open ( SI5338_PATH + "/output_drivers/" + iface,      "w") as f:
294 295
            print("2", file = f)
        with open ( SI5338_PATH + "/output_clocks/out2_freq_fract","w") as f:
296
            print("%d"%(round(1000000*freq_MHz)), file = f )
297
        if quiet == 0:
298
            print ("Set sensor clock to %f MHz, driver type \"%s\""%(freq_MHz,iface))
299
    def setSensorPower(self, sub_pair=0, power_on=0, quiet=0):
300
        """
301 302 303
        @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
304
        """
305
        if quiet == 0:
306
            print (("vcc_sens01 vp33sens01", "vcc_sens23 vp33sens23")[sub_pair]+" -> "+POWER393_PATH + "/channels_"+ ("dis","en")[power_on])
307 308
        with open (POWER393_PATH + "/channels_"+ ("dis","en")[power_on],"w") as f:
            print(("vcc_sens01 vp33sens01", "vcc_sens23 vp33sens23")[sub_pair], file = f)
309

310 311
    def setSensorIfaceVoltage(self, sub_pair, voltage_mv, quiet = 0):
        """
312 313 314 315
        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
316 317 318 319
        """
        with open (POWER393_PATH + "/voltages_mv/"+ ("vcc_sens01", "vcc_sens23")[sub_pair],"w") as f:
            print(voltage_mv, file = f)
        if quiet == 0:
320
            print ("Set sensors %s interface voltage to %d mV"%(("0, 1","2, 3")[sub_pair],voltage_mv))
321
        time.sleep(0.1)
322

323 324 325 326 327 328
    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
329
        @param dly_ms - delay in ms after turning power on or off
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
        """
        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
350 351
        #turn off external sensor power
        self.setEyesisPower (True,  0) # stupid GPIO after reset will not turn off if it thinks it is off
352 353 354 355 356 357 358 359 360 361 362
        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)
363

364
    def setupSensorsPower(self, ifaceType,  pairs = "all", quiet=0, dly=0.0):
Andrey Filippov's avatar
Andrey Filippov committed
365 366
        """
        Set interface voltage and turn on power for interface and the sensors
367
        according to sensor type
368 369 370 371
        @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
372
        """
373 374 375 376 377 378 379
        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,)
380
        for pair in pairs:
Andrey Filippov's avatar
Andrey Filippov committed
381 382 383 384
            self.setSensorIfaceVoltagePower(sub_pair =   pair,
                                            voltage_mv = SENSOR_INTERFACES[ifaceType]["mv"],
                                            quiet =      quiet,
                                            dly =        dly)
385

386
    def setSensorIfaceVoltagePower(self, sub_pair, voltage_mv, quiet=0, dly=0.0):
387
        """
388 389 390 391 392
        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
393 394
        """
        self.setSensorPower(sub_pair = sub_pair, power_on = 0)
Andrey Filippov's avatar
Andrey Filippov committed
395
        time.sleep(2*dly)
396
        self.setSensorIfaceVoltage(sub_pair=sub_pair, voltage_mv = voltage_mv)
Andrey Filippov's avatar
Andrey Filippov committed
397
        time.sleep(2*dly)
398 399 400
        if self.DRY_MODE:
            print ("Not defined for simulation mode")
            return
401
        if quiet == 0:
402
            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
403
        time.sleep(3*dly)
404 405 406
        with open (POWER393_PATH + "/channels_en","w") as f:
            print(("vcc_sens01", "vcc_sens23")[sub_pair], file = f)
        if quiet == 0:
407
            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
408
        time.sleep(3*dly)
409 410 411
        with open (POWER393_PATH + "/channels_en","w") as f:
            print(("vp33sens01", "vp33sens23")[sub_pair], file = f)
        if quiet == 0:
412
            print ("Turned on +3.3V power for sensors %s"%(("0, 1","2, 3")[sub_pair]))
Andrey Filippov's avatar
Andrey Filippov committed
413
        time.sleep(2*dly)
414

415 416

    def setupSensorsPowerClock(self, setPower=False, quiet=0):
417 418 419
        """
        Set interface voltage for all sensors, clock for frequency and sensor power
        for the interface matching bitstream file
420
        Not possible for diff. termination - power should be set before the bitstream
421
        """
422
        ifaceType = self.x393Sensor.getSensorInterfaceType();
423 424
        if setPower:
            if quiet == 0:
425
                print ("Configuring sensor ports for interface type: \"%s\""%(ifaceType))
426 427
            for sub_pair in (0,1):
                self.setSensorIfaceVoltagePower(sub_pair, SENSOR_INTERFACES[ifaceType]["mv"])
428 429
        self.setSensorClock(freq_MHz = SENSOR_INTERFACES[ifaceType]["freq"], iface = SENSOR_INTERFACES[ifaceType]["iface"])

430 431
#    def setSensorClock(self, freq_MHz = 24.0, iface = "2V5_LVDS"):

432
    def setup_sensor_channel (self,
433 434 435 436
                              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)
437 438 439 440
                              window_width =              None, # 2592,   # 2592
                              window_height =             None, # 1944,   # 1944
                              window_left =               None, # 0,     # 0
                              window_top =                None, # 0, # 0? 1?
441
#                              compressor_left_margin =    0, #0?`1?
442 443 444
#                              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
445
                              cmode =                     0, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
446
                              colorsat_blue =             0x120,     # 0x90 fo 1x
447 448
                              colorsat_red =              0x16c,     # 0xb6 for x1
                              clk_sel =                   1,         # 1
449 450 451 452
                              histogram_left =            None, # 0,
                              histogram_top =             None, # 0,
                              histogram_width_m1 =        None, # 2559, #0,
                              histogram_height_m1 =       None, # 1935, #0,
453 454
                              verbose =                   1
                              ):
455 456
        """
        Setup one sensor+compressor channel (for one sub-channel only)
457 458 459 460 461 462 463 464 465 466 467
        @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)
468 469 470 471 472 473
        @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
474 475 476 477 478 479 480 481 482 483 484 485 486 487
        @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
488 489 490 491 492 493 494
        @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)
495

496
        ???
497
        @param verbose - verbose level
498
        @return True if all done, False if exited prematurely through exit_step
499
        """
500
#        @param compressor_left_margin - 0..31 - left margin for compressor (to the nearest 32-byte column)
501
        sensorType = self.x393Sensor.getSensorInterfaceType()
502 503
        if verbose > 0 :
            print ("Sensor port %d interface type: %s"%(num_sensor, sensorType))
504 505 506 507
        window = self.specify_window (window_width =  window_width,
                                      window_height = window_height,
                                      window_left =   window_left,
                                      window_top =    window_top,
508 509
#                                      cmode =         None, # will use 0
                                      cmode =         cmode, # will use 0
510 511 512 513 514 515 516
                                      verbose =       0)
        window_width =   window["width"]
        window_height =  window["height"]
        window_left =    window["left"]
        window_top =     window["top"]
        """
        cmode =          window["cmode"]
517 518 519 520 521 522 523 524
        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"]
525
        """
526

527
        #setting up histogram window, same for parallel, similar for serial
528

529 530 531 532 533 534 535 536 537
        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

538

539 540 541 542
        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
543
        compressor_left_margin = window_left % 32
544

545 546 547 548 549 550
        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)
551 552 553 554
##        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
555

556
        """
557

558
        frame_full_width =  0x200 # Made it fixed width
559 560 561



562 563 564
        num8rows=   (window_top + window_height) // 8
        if (window_top + window_height) % 8:
            num8rows += 1
565
        """
566
        frame_start_address_inc = num8rows * frame_full_width
567 568
        """
        frame_start_address_inc = 0x80000 #Fixed size
569

570
        """ TODO: Calculate tiles and move to initial print """
571 572 573 574 575 576 577 578
        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

579
        histogram_start_phys_page = self.get_histogram_byte_start() // 4096
580

581 582
        if verbose >0 :
            print ("setup_sensor_channel:")
583 584 585 586 587 588 589 590 591 592
            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))
593 594 595 596
            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))
597 598 599
            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)
600
            print ("cmode =                     ", cmode)
601
            print ("verbose =                   ", verbose)
602
        if exit_step == 10: return False
603

604 605 606 607 608 609 610 611 612 613
        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(
614
            cmprs_chn =  num_sensor,  # input [1:0] num_sensor;
615 616
            mode =       3,           # input [1:0] mode;
            seq_num =    0);          # input [5:0] seq_num;
617
        if exit_step == 11: return False
618

619
    # moved before camsync to have a valid timestamo w/o special waiting
620 621
        if verbose >0 :
            print ("===================== MEMORY_SENSOR =========================")
622

623 624 625
        window_height_memory = window_height
        if cmode==vrlg.CMPRS_CBIT_CMODE_JP4:
            window_height_memory &= 0xfff0 # do not need extra margins
626 627
            num_burst_in_line &= 0xfffe    # make even (assuming left=0)

628 629 630 631 632 633
        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)
634 635
#            window_width =     window_width >> 4,        # input [31:0] window_width;     # 13 bit - in 8*16=128 bit bursts
            window_width =     num_burst_in_line,       # input [31:0] window_width;     # 13 bit - in 8*16=128 bit bursts
636 637
#            window_height =    window_height,           # input [31:0] window_height;    # 16 bit
            window_height =    window_height_memory,   # input [31:0] window_height;    # 16 bit
638 639 640
            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
641 642
        if exit_step == 12: return False

643
        self.x393_axi_tasks.enable_memcntrl_en_dis(8 + num_sensor, True);
644 645
        if exit_step == 13: return False

646 647 648
        self.x393Cmprs.compressor_control(chn =  num_sensor,
                                          run_mode = 0) # reset compressor
        #TODO: Calculate from the image size?
649
        """
650
        #How it was
651
        self.x393Cmprs.setup_compressor_channel (
652
                                  chn =               num_sensor,
653 654 655
                                  qbank =             0,
                                  dc_sub =            True,
                                  cmode =             vrlg.CMPRS_CBIT_CMODE_JPEG18,
656
#                                  cmode =             vrlg.CMPRS_CBIT_CMODE_JP4,
657 658 659 660 661
                                  multi_frame =       True,
                                  bayer       =       0,
                                  focus_mode  =       0,
                                  num_macro_cols_m1 = num_macro_cols_m1,
                                  num_macro_rows_m1 = num_macro_rows_m1,
662
                                  left_margin =       compressor_left_margin,
663 664 665 666 667
                                  colorsat_blue =     colorsat_blue,
                                  colorsat_red =      colorsat_red,
                                  coring =            0,
                                  verbose =           verbose)
    # TODO: calculate widths correctly!
668
        if exit_step == 14: return False
669 670 671 672 673
        tile_margin = 2 # 18x18 instead of 16x16
        left_tiles32 = window_left // 32
#        last_tile32 = (window_left + (window_width & ~0xf) + tile_margin - 1) // 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
674

675 676 677 678 679 680 681 682 683
        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))
            print ("window_width =     0x%x"%(width32 * 2 )) # window_width >> 4)) # width in 16 - bursts, made evem
            print ("window_height =    0x%x"%(window_height & 0xfffffff0))
684
            print ("window_left =      0x%x"%(left_tiles32 * 2)) # window_left >> 4)) # left in 16-byte bursts, made even
685 686 687
            print ("window_top =       0x%x"%(window_top))
            print ("byte32 =           1")
            print ("tile_width =       2")
688 689
            print ("tile_vstep =      16")
            print ("tile_height =     18")
690 691
            print ("extra_pages =      1")
            print ("disable_need =     1")
692
            print ("abort_late =       0")
693

694 695
        self.x393Cmprs.setup_compressor_memory (
            num_sensor =       num_sensor,
696 697 698 699 700 701 702 703
            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
            window_height =    window_height & 0xfffffff0,  # input [31:0] window_height;    # 16 bit
            window_left =      left_tiles32 * 2,            # input [31:0] window_left;
            window_top =       window_top,                  # input [31:0] window_top;
704 705
            byte32 =           1,
            tile_width =       2,
706 707
            tile_vstep =      16,
            tile_height =     18,
708
            extra_pages =      1,
709 710
            disable_need =     1,
            abort_late =       False)
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
        """
        # replacing with setup compressor:
        self.setup_compressor(chn =  num_sensor,
                               cmode =          cmode,
                               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)

730 731

        if exit_step == 15: return False
732

733
        self.x393Cmprs.compressor_control(
734
                       chn = num_sensor,
735
                       run_mode =  0) #  3)  # run repetitive mode
736 737

        if exit_step == 16: return False
738
        #Set up delays separately, outside of this method
739
        """
740 741
        if verbose >0 :
            print ("===================== DELAYS_SETUP =========================")
742

743 744 745 746 747 748 749 750 751
        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)
752 753

        """
754 755 756 757 758
        if verbose >0 :
            print ("===================== IO_SETUP =========================")
        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
759 760 761 762 763
        self.x393Sensor.set_sensor_io_ctl (
                           num_sensor = num_sensor,
                           mrst =       False,
                           arst =       False,
                           aro  =       False,
764
                           mmcm_rst =   True,   #reset mmcm
765 766 767 768
                           clk_sel =    None,   #Dealing with Unisims bug: "Error: [Unisim MMCME2_ADV-4] Input clock can only be switched when..."
                           set_delays = False,
                           quadrants =  None)

769 770 771 772 773
        self.x393Sensor.set_sensor_io_ctl (
                           num_sensor = num_sensor,
                           mrst =       False,
                           arst =       False,
                           aro  =       False,
774
                           mmcm_rst =   True,   #reset mmcm
775 776 777 778 779 780 781 782 783 784
                           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)
785 786 787

        if exit_step == 17: return False

788 789 790 791 792 793
        """
        if verbose >0 :
            print ("===================== I2C_TEST =========================")
        self.x393Sensor.test_i2c_353() # test soft/sequencer i2c
        """
        if verbose >0 :
794 795
            print ("===================== LENS_FLAT_SETUP ========================= num_sensor=",num_sensor)
        self.x393Sensor.set_sensor_lens_flat_heights (
796 797 798 799 800 801 802 803 804 805 806
                                      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
807
                                         C =  0x8000,
808 809 810 811 812 813 814 815 816 817
                                         scales0 =        0x8000,
                                         scales1 =        0x8000,
                                         scales2 =        0x8000,
                                         scales3 =        0x8000,
                                         fatzero_in =     0,
                                         fatzero_out =    0,
                                         post_scale =     1)
        if verbose >0 :
            print ("===================== GAMMA_SETUP =========================")

818
        self.x393Sensor.set_sensor_gamma_heights (
819 820 821 822
                                  num_sensor = num_sensor,
                                  height0_m1 = 0xffff,
                                  height1_m1 = 0,
                                  height2_m1 = 0)
823

824 825 826 827 828
        # Configure histograms
        if verbose >0 :
            print ("===================== HISTOGRAMS_SETUP =========================")
        self.x393Sensor.set_sensor_histogram_window ( # 353 did it using command sequencer)
                                    num_sensor =     num_sensor,
829
                                    subchannel =     0,
830 831 832 833 834 835 836 837
                                    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,
838
                                    page = histogram_start_phys_page) # for the channel/subchannel = 0/0
839

840 841 842
        self.x393Sensor.set_sensor_histogram_saxi (
                                   en = True,
                                   nrst = True,
843
                                   confirm_write = False, # True,
844 845
                                   cache_mode = 3)

846 847
        if exit_step == 18: return False

848 849 850
        # Run after histogram channel is set up?
        if verbose >0 :
            print ("===================== SENSOR_SETUP =========================")
851

852 853 854
        self.x393Sensor.set_sensor_mode (
            num_sensor = num_sensor,
            hist_en =    1, # bitmask, only first subchannel
855 856
            hist_nrst =  1, # bitmask, only first subchannel
            chn_en =     True,
857 858 859 860 861 862 863
            bits16 =     False)

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

864 865
        if exit_step == 19: return False

866 867
        if verbose >0 :
            print ("===================== GAMMA_CTL =========================")
868
        self.x393Sensor.set_sensor_gamma_ctl (# doing last to enable sensor data when everything else is set up
869 870 871 872 873 874
            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)
875
        return True
876

877
    def specify_window (self,
878 879
                        window_width =              None, # 2592
                        window_height =             None, # 1944
880 881
                        window_left =               None,     # 0
                        window_top =                None, # 0? 1?
882
                        cmode =                     None,
883 884 885 886 887
                        bayer =                     None,
                        y_quality =                 None,
                        c_quality =                 None, # use "same" to save None
                        portrait =                  None,
                        gamma =                     None,
888
                        black =                     None, # 0.04
889
                        colorsat_blue =             None, # colorsat_blue, #0x120     # 0x90 for 1x
890
                        colorsat_red =              None, # colorsat_red, #0x16c,     # 0xb6 for x1
891
                        verbose =                   1
892
                        ):
893

894 895 896
        global GLBL_WINDOW
        if GLBL_WINDOW is None:
            GLBL_WINDOW = {}
897
        sensorType = self.x393Sensor.getSensorInterfaceType()
898 899 900
        if verbose > 0 :
            print ("Sensor interface type: %s"%(sensorType))
        if window_width is None:
901 902 903 904
            try:
                window_width = GLBL_WINDOW["width"]
            except:
                window_width = SENSOR_DEFAULTS[sensorType]["width"]
905
        if window_height is None:
906 907 908 909
            try:
                window_height = GLBL_WINDOW["height"]
            except:
                window_height = SENSOR_DEFAULTS[sensorType]["height"]
910
        if window_left is None:
911 912 913 914
            try:
                window_left = GLBL_WINDOW["left"]
            except:
                window_left = SENSOR_DEFAULTS[sensorType]["left"]
915
        if window_top is None:
916 917 918 919 920 921 922 923 924
            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
925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943

        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
944 945
                c_quality = None

946 947 948 949 950
        if portrait is None:
            try:
                portrait = GLBL_WINDOW["portrait"]
            except:
                portrait = False
951

952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974
        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
975

976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993
        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])))
994
        return GLBL_WINDOW
995 996


997
    def specify_phys_memory(self,
Oleg Dzhimiev's avatar
Oleg Dzhimiev committed
998
                            circbuf_chn_size= 0x4000000,
999 1000 1001 1002
                            verbose =         1):
        """
        @param circbuf_chn_size - circular buffer size for each channel, in bytes
        """
1003 1004 1005
        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
1006

1007 1008 1009 1010
        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=[]
1011
        GLBL_CIRCBUF_ENDS=[]
1012 1013
        for i in range(16):
            GLBL_CIRCBUF_STARTS.append(circbuf_start + i*circbuf_chn_size)
1014
            GLBL_CIRCBUF_ENDS.append(circbuf_start + (i+1)*circbuf_chn_size)
1015 1016 1017
        GLBL_CIRCBUF_END =     circbuf_start + 4*GLBL_CIRCBUF_CHN_SIZE
        GLBL_MEMBRIDGE_START = GLBL_CIRCBUF_END
        GLBL_MEMBRIDGE_END =   GLBL_BUFFER_END
1018 1019 1020 1021 1022 1023

        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
1024

1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
        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))
1035 1036 1037 1038 1039 1040
            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))
1041
            print ("memory buffer end =         0x%x"%(GLBL_BUFFER_END))
1042 1043 1044 1045 1046
    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()
1047
        """
1048
        self.x393_axi_tasks.program_status( # also takes snapshot
Andrey Filippov's avatar
Andrey Filippov committed
1049 1050 1051 1052
                                           base_addr =    vrlg.CMDSEQMUX_ADDR,
                                           reg_addr =     0,
                                           mode =         3,     # input [1:0] mode;
                                           seq_number =   0)     #input [5:0] seq_num;
1053 1054 1055 1056 1057 1058 1059 1060 1061
    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
1062 1063 1064 1065 1066 1067 1068
    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)
1069

1070 1071 1072 1073 1074 1075 1076 1077 1078 1079
    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))
1080
                return frames
1081
        except:
1082
            pass
1083 1084 1085
        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)
1086

1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
    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;
1106
        return frameno # Frame number of the last  new frame checked
1107

1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
    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
1119
        return frameno # Frame number of the last  new frame checked
1120

1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
    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;
1140 1141
        return frameno # Frame number of the last  new frame checked

1142 1143
    def setup_compressor(self,
                          chn,
1144
                          cmode =            0, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
                          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
1156
                          colorsat_blue =    0x120,     # 0x90 for 1x
1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178
                          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
        @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)
1179
        @param focus_mode -   focus mode - how to combine image with "focus quality" in the result image
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
        @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
        """
        try:
            if (chn == all) or (chn[0].upper() == "A"): #all is a built-in function
                for chn in range(4):
1193
                    self. setup_compressor( #self,
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
                                           chn =            chn,
                                           cmode =          cmode,
                                           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
1207
                                           colorsat_blue =  colorsat_blue, #0x120     # 0x90 for 1x
1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
                                           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"]
1224
        COLOR_MARGINS = 2
1225
        num_sensor = chn # 1:1 sensor - compressor
1226

1227
        align_to_bursts = 64 # align full width to multiple of align_to_bursts. 64 is the size of memory access
1228 1229 1230 1231 1232 1233 1234 1235
        """
        overlap = 0    # tile overlap (total - 2 for JPEG18, 4 - for JPEG20, 0 otherwise
        cmprs_top = 0  # 1 for JPEG18 only, 0 for others (also is used for compressor left)
        if cmode ==  vrlg.CMPRS_CBIT_CMODE_JPEG18:
            overlap = 2
            cmprs_top = 1
        elif cmode ==  vrlg.CMPRS_CBIT_CMODE_JPEG20:
            overlap = 4
1236

1237 1238 1239 1240 1241 1242 1243
        if overlap:
            window_width +=  (2 * COLOR_MARGINS)
            window_height += (2 * COLOR_MARGINS)
            tile_width = 2
        else:
            tile_width = 4
#        cmprs_frame_format.left_margin = cmprs_top; // same as top - only for 18x18 tiles to keep Bayer shift (0/1)
1244

1245 1246 1247 1248 1249 1250 1251 1252
        width_bursts = window_width >> 4
        if  window_width & 0xf:
            width_bursts += 1
        # Adjusting for tile width. TODO: probably not needed, handled in FPGA - verify (and remove 2 next lines)
        if width_bursts & 1:
            width_bursts += 1
        if (tile_width > 2) and (width_bursts & 2):
             width_bursts += 2
1253

1254 1255
        tile_height = 16 + overlap;
        """
1256 1257


1258 1259 1260 1261
        width_in_bursts = window_width >> 4
        if (window_width & 0xf):
            width_in_bursts += 1
        compressor_left_margin = window_left % 32
1262

1263 1264 1265 1266
        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
1267 1268 1269
        """
        Changing frame full width and size to fixed values (normally read from sysfs)
                frame_full_width =  num_pages_in_line * align_to_bursts
1270

1271
        """
1272

1273
        frame_full_width =  0x200 # Made it fixed width
1274 1275 1276
        num8rows=   (window_top + window_height) // 8
        if (window_top + window_height) % 8:
            num8rows += 1
1277
        """
1278
        frame_start_address_inc = num8rows * frame_full_width
1279 1280
        """
        frame_start_address_inc = 0x80000 #Fixed size
1281 1282 1283 1284

        num_macro_cols_m1 = (window_width >> 4) - 1
        num_macro_rows_m1 = (window_height >> 4) - 1
        frame_start_address = (last_buf_frame + 1) * frame_start_address_inc * num_sensor
1285

1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305
        self.x393Cmprs.setup_compressor_channel (
                                  chn =               chn,
                                  qbank =             qbank,
                                  dc_sub =            dc_sub,
                                  cmode =             cmode, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
                                  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,
                                  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
1306

1307 1308 1309 1310
        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
1311
            extra_pages = 0 #  1 # just testing, 0 should be OK  here
1312 1313 1314 1315 1316 1317
        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
1318

1319 1320 1321 1322 1323 1324 1325
        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))
1326
            print ("window_width =     0x%x (in 16 - bursts, made even)"%(width32 * 2 )) # window_width >> 4)) # width in 16 - bursts, made even
1327 1328 1329 1330 1331 1332 1333 1334 1335
            print ("window_height =    0x%x"%(window_height & 0xfffffff0))
            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")
            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")
1336
            print ("abort_late =       0")
1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352

        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
            window_height =    window_height & 0xfffffff0,  # input [31:0] window_height;    # 16 bit
            window_left =      left_tiles32 * 2,            # input [31:0] window_left;
            window_top =       window_top,                  # input [31:0] window_top;
            byte32 =           1,
            tile_width =       tile_width,
            tile_vstep =       tile_vstep,
            tile_height =      tile_height,
            extra_pages =      extra_pages,
1353 1354 1355
            disable_need =     1,
            abort_late =       False)

1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
    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
1371

1372 1373 1374 1375 1376
        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
1377

1378 1379 1380
                if reset_mask & MASK_MEMSENSOR:
                    self.x393Sensor.control_sensor_memory    (num_sensor = chn,
                                                              command = 'stop')
1381

1382 1383 1384
                if reset_mask & MASK_MEMCOMPRESSOR:
                    self.x393Cmprs.control_compressor_memory (num_sensor = chn,
                                                              command = 'stop')
1385 1386

        self.sleep_ms(200)
1387 1388 1389 1390 1391 1392 1393 1394
        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')
1395

1396 1397 1398 1399 1400 1401 1402 1403
                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)

1404

1405
    def setup_all_sensors (self,
1406
                              setup_membridge =           False,
1407 1408 1409
                              exit_step =                 None,
                              sensor_mask =               0x1, # channel 0 only
                              gamma_load =                False,
1410 1411 1412 1413
                              window_width =              None, # 2592,   # 2592
                              window_height =             None, # 1944,   # 1944
                              window_left =               None, # 0,     # 0
                              window_top =                None, # 0, # 0? 1?
1414
                              compressor_left_margin =    0, #0?`1?
1415
                              last_buf_frame =            1,  #  - just 2-frame buffer
1416
                              cmode =                     0, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
1417
                              colorsat_blue =             0x120,     # 0x90 fo 1x
1418 1419
                              colorsat_red =              0x16c,     # 0xb6 for x1
                              clk_sel =                   1,         # 1
1420 1421 1422 1423
                              histogram_left =            None,
                              histogram_top =             None,
                              histogram_width_m1 =        None, # 2559, #0,
                              histogram_height_m1 =       None, # 799, #0,
1424
                              circbuf_chn_size=           0x4000000, # 64 Mib - all 4 channels?
1425
                              reset_afi =                 False, # reset AFI multiplexer
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
                              verbose =                   1):
        """
        Setup one sensor+compressor channel (for one sub-channel only)
        @param exit_step -         exit after executing specified step:
                                1 - after power and clock
                                2 - exit after GPIO setup
                                3 - exit after RTC setup
                                10..19 - exit from setup_sensor_channel:
                                   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)
                                20 - after setup_sensor_channel
                                21 - after afi_mux_setup
        @param sensor_mask -       bitmap of the selected channels (1 - only channel 0, 0xf - all channels)
        @param gamma_load -        load gamma table TODO: Change to calculate and load table
        @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 compressor_left_margin - 0..31 - left margin for compressor (to the nearest 32-byte column)
        @param last_buf_frame) -   16-bit number of the last frame in a buffer
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467
        @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
1468 1469
        @param colorsat_blue - color saturation for blue (10 bits), 0x90 for 100%
        @param colorsat_red -  color saturation for red (10 bits), 0xb6 for 100%
1470
        @param clk_sel - True - use pixel clock from the sensor, False - use internal clock (provided to the sensor), None - no change
1471 1472 1473 1474
        @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)
1475 1476 1477 1478 1479
        @param reset_afi            Reset AFI multiplexer when initializing

        2018/01/02: the buffer sizes and addresses can be read from sysfs.
                    /sys/devices/soc0/elphel393-mem@0/buffer_address_circbuf_chn0..3, buffer_address_raw_chn0..3
                    buffer_pages_circbuf_chn0..3,   buffer_pages_raw_chn0..3, page size is 4096
1480

1481
        @param circbuf_chn_size - circular buffer size for each channel, in bytes
1482

1483
        @param verbose - verbose level
1484 1485
        @return True if all done, False if exited prematurely by  exit_step
        """
1486 1487
        global GLBL_CIRCBUF_CHN_SIZE, GLBL_CIRCBUF_STARTS, GLBL_CIRCBUF_ENDS, GLBL_CIRCBUF_END, GLBL_MEMBRIDGE_START, GLBL_MEMBRIDGE_END, GLBL_BUFFER_END, GLBL_WINDOW
        global GLBL_MEMBRIDGE_H2D_START, GLBL_MEMBRIDGE_H2D_END, GLBL_MEMBRIDGE_D2H_START, GLBL_MEMBRIDGE_D2H_END
1488

1489
        sensorType = self.x393Sensor.getSensorInterfaceType()
1490 1491
        if verbose > 0 :
            print ("Sensor interface type: %s"%(sensorType))
1492 1493 1494 1495
        window = self.specify_window (window_width =  window_width,
                                      window_height = window_height,
                                      window_left =   window_left,
                                      window_top =    window_top,