x393_sens_cmprs.py 140 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 133
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"}}
134
#                   x393_sensor.SENSOR_INTERFACE_HISPI:    {"mv":2500, "freq":24.444, "iface":"1V8_LVDS"}}
135

136 137
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}}
138

139 140
#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}}
141
class X393SensCmprs(object):
142 143 144 145 146 147 148 149 150 151 152 153 154 155
    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
156
    x393Membridge =      None
157

158
    def __init__(self, debug_mode=1,dry_mode=True, saveFileName=None):
159 160
#        global BUFFER_ADDRESS, BUFFER_LEN
        global BUFFER_ADDRESS, BUFFER_LEN, COMMAND_ADDRESS, DATAIN_ADDRESS, DATAOUT_ADDRESS
161
        global BUFFER_ADDRESS_H2D, BUFFER_LEN_H2D, BUFFER_ADDRESS_D2H, BUFFER_LEN_D2H, BUFFER_ADDRESS_BIDIR, BUFFER_LEN_BIDIR
162
#        global SENSOR_DEFAULTS_SIMULATION
163
        print ("X393SensCmprs.__init__: dry_mode=",dry_mode)
164 165 166 167 168 169 170 171 172 173 174 175 176
        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)
177

178
            except:
179 180
                print ("No simulation server is used, just running in dry mode")

181 182 183 184 185
        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
186

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

            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

220 221


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

            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")
242 243
                print('BUFFER_ADDRESS_H2D=',BUFFER_ADDRESS_H2D)
                print('BUFFER_LEN_H2D=',BUFFER_LEN_H2D)
244
                return
245

246 247 248 249 250 251 252
            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")
253 254
                print('BUFFER_ADDRESS_D2H=',BUFFER_ADDRESS_D2H)
                print('BUFFER_LEN_D2H=',BUFFER_LEN_D2H)
255
                return
256

257 258 259 260 261 262 263
            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")
264 265
                print('BUFFER_ADDRESS_BIDIR=',BUFFER_ADDRESS_BIDIR)
                print('BUFFER_LEN_BIDIR=',BUFFER_LEN_BIDIR)
266
                return
267 268 269


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

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

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

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

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

421 422

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

436 437
#    def setSensorClock(self, freq_MHz = 24.0, iface = "2V5_LVDS"):

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

503
        ???
504
        @param verbose - verbose level
505
        @return True if all done, False if exited prematurely through exit_step
506
        """
507
#        @param compressor_left_margin - 0..31 - left margin for compressor (to the nearest 32-byte column)
508 509 510

        global FRAME_FULL_WIDTH, FRAME_START_ADDRESS_INC

511
        sensorType = self.x393Sensor.getSensorInterfaceType()
512 513
        if verbose > 0 :
            print ("Sensor port %d interface type: %s"%(num_sensor, sensorType))
514 515 516 517
        window = self.specify_window (window_width =  window_width,
                                      window_height = window_height,
                                      window_left =   window_left,
                                      window_top =    window_top,
518 519
#                                      cmode =         None, # will use 0
                                      cmode =         cmode, # will use 0
520 521 522 523 524 525 526
                                      verbose =       0)
        window_width =   window["width"]
        window_height =  window["height"]
        window_left =    window["left"]
        window_top =     window["top"]
        """
        cmode =          window["cmode"]
527 528 529 530 531 532 533 534
        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"]
535
        """
536

537
        #setting up histogram window, same for parallel, similar for serial
538

539 540 541 542 543 544 545 546 547
        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

548

549 550 551 552
        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
553
        compressor_left_margin = window_left % 32
554

555 556 557 558 559 560
        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)
561 562 563 564
##        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
565

566
        """
567

568
        frame_full_width =  FRAME_FULL_WIDTH # Made it fixed width
569 570 571



572 573 574
        num8rows=   (window_top + window_height) // 8
        if (window_top + window_height) % 8:
            num8rows += 1
575
        """
576
        frame_start_address_inc = num8rows * frame_full_width
577
        """
578
        frame_start_address_inc = FRAME_START_ADDRESS_INC #Fixed size
579

580
        """ TODO: Calculate tiles and move to initial print """
581 582 583 584 585 586 587 588
        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

589
        histogram_start_phys_page = self.get_histogram_byte_start() // 4096
590

591 592
        if verbose >0 :
            print ("setup_sensor_channel:")
593 594 595 596 597 598 599 600 601 602
            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))
603 604 605 606
            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))
607 608 609
            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)
610
            print ("cmode =                     ", cmode)
611
            print ("verbose =                   ", verbose)
612
        if exit_step == 10: return False
613

614 615 616 617 618 619 620 621 622 623
        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(
624
            cmprs_chn =  num_sensor,  # input [1:0] num_sensor;
625 626
            mode =       3,           # input [1:0] mode;
            seq_num =    0);          # input [5:0] seq_num;
627
        if exit_step == 11: return False
628

629
    # moved before camsync to have a valid timestamo w/o special waiting
630 631
        if verbose >0 :
            print ("===================== MEMORY_SENSOR =========================")
632

633 634 635
        window_height_memory = window_height
        if cmode==vrlg.CMPRS_CBIT_CMODE_JP4:
            window_height_memory &= 0xfff0 # do not need extra margins
636 637
            num_burst_in_line &= 0xfffe    # make even (assuming left=0)

638 639 640 641 642 643
        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)
644 645
#            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
646 647
#            window_height =    window_height,           # input [31:0] window_height;    # 16 bit
            window_height =    window_height_memory,   # input [31:0] window_height;    # 16 bit
648 649 650
            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
651 652
        if exit_step == 12: return False

653
        self.x393_axi_tasks.enable_memcntrl_en_dis(8 + num_sensor, True);
654 655
        if exit_step == 13: return False

656 657 658
        self.x393Cmprs.compressor_control(chn =  num_sensor,
                                          run_mode = 0) # reset compressor
        #TODO: Calculate from the image size?
659
        """
660
        #How it was
661
        self.x393Cmprs.setup_compressor_channel (
662
                                  chn =               num_sensor,
663 664 665
                                  qbank =             0,
                                  dc_sub =            True,
                                  cmode =             vrlg.CMPRS_CBIT_CMODE_JPEG18,
666
#                                  cmode =             vrlg.CMPRS_CBIT_CMODE_JP4,
667 668 669 670 671
                                  multi_frame =       True,
                                  bayer       =       0,
                                  focus_mode  =       0,
                                  num_macro_cols_m1 = num_macro_cols_m1,
                                  num_macro_rows_m1 = num_macro_rows_m1,
672
                                  left_margin =       compressor_left_margin,
673 674 675 676 677
                                  colorsat_blue =     colorsat_blue,
                                  colorsat_red =      colorsat_red,
                                  coring =            0,
                                  verbose =           verbose)
    # TODO: calculate widths correctly!
678
        if exit_step == 14: return False
679 680 681 682 683
        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
684

685 686 687 688 689 690 691 692 693
        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))
694
            print ("window_left =      0x%x"%(left_tiles32 * 2)) # window_left >> 4)) # left in 16-byte bursts, made even
695 696 697
            print ("window_top =       0x%x"%(window_top))
            print ("byte32 =           1")
            print ("tile_width =       2")
698 699
            print ("tile_vstep =      16")
            print ("tile_height =     18")
700 701
            print ("extra_pages =      1")
            print ("disable_need =     1")
702
            print ("abort_late =       0")
703

704 705
        self.x393Cmprs.setup_compressor_memory (
            num_sensor =       num_sensor,
706 707 708 709 710 711 712 713
            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;
714 715
            byte32 =           1,
            tile_width =       2,
716 717
            tile_vstep =      16,
            tile_height =     18,
718
            extra_pages =      1,
719 720
            disable_need =     1,
            abort_late =       False)
721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739
        """
        # 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)

740 741

        if exit_step == 15: return False
742

743
        self.x393Cmprs.compressor_control(
744
                       chn = num_sensor,
745
                       run_mode =  0) #  3)  # run repetitive mode
746 747

        if exit_step == 16: return False
748
        #Set up delays separately, outside of this method
749
        """
750 751
        if verbose >0 :
            print ("===================== DELAYS_SETUP =========================")
752

753 754 755 756 757 758 759 760 761
        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)
762 763

        """
764 765 766 767 768
        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
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
                           clk_sel =    None,   #Dealing with Unisims bug: "Error: [Unisim MMCME2_ADV-4] Input clock can only be switched when..."
                           set_delays = False,
                           quadrants =  None)

779 780 781 782 783
        self.x393Sensor.set_sensor_io_ctl (
                           num_sensor = num_sensor,
                           mrst =       False,
                           arst =       False,
                           aro  =       False,
784
                           mmcm_rst =   True,   #reset mmcm
785 786 787 788 789 790 791 792 793 794
                           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)
795 796 797

        if exit_step == 17: return False

798 799 800 801 802 803
        """
        if verbose >0 :
            print ("===================== I2C_TEST =========================")
        self.x393Sensor.test_i2c_353() # test soft/sequencer i2c
        """
        if verbose >0 :
804 805
            print ("===================== LENS_FLAT_SETUP ========================= num_sensor=",num_sensor)
        self.x393Sensor.set_sensor_lens_flat_heights (
806 807 808 809 810 811 812 813 814 815 816
                                      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
817
                                         C =  0x8000,
818 819 820 821 822 823 824 825 826 827
                                         scales0 =        0x8000,
                                         scales1 =        0x8000,
                                         scales2 =        0x8000,
                                         scales3 =        0x8000,
                                         fatzero_in =     0,
                                         fatzero_out =    0,
                                         post_scale =     1)
        if verbose >0 :
            print ("===================== GAMMA_SETUP =========================")

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

834 835 836 837 838
        # Configure histograms
        if verbose >0 :
            print ("===================== HISTOGRAMS_SETUP =========================")
        self.x393Sensor.set_sensor_histogram_window ( # 353 did it using command sequencer)
                                    num_sensor =     num_sensor,
839
                                    subchannel =     0,
840 841 842 843 844 845 846 847
                                    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,
848
                                    page = histogram_start_phys_page) # for the channel/subchannel = 0/0
849

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

856 857
        if exit_step == 18: return False

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

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

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

874 875
        if exit_step == 19: return False

876 877
        if verbose >0 :
            print ("===================== GAMMA_CTL =========================")
878
        self.x393Sensor.set_sensor_gamma_ctl (# doing last to enable sensor data when everything else is set up
879 880 881 882 883 884
            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)
885
        return True
886

887
    def specify_window (self,
888 889
                        window_width =              None, # 2592
                        window_height =             None, # 1944
890 891
                        window_left =               None,     # 0
                        window_top =                None, # 0? 1?
892
                        cmode =                     None,
893 894 895 896 897
                        bayer =                     None,
                        y_quality =                 None,
                        c_quality =                 None, # use "same" to save None
                        portrait =                  None,
                        gamma =                     None,
898
                        black =                     None, # 0.04
899
                        colorsat_blue =             None, # colorsat_blue, #0x120     # 0x90 for 1x
900
                        colorsat_red =              None, # colorsat_red, #0x16c,     # 0xb6 for x1
901
                        verbose =                   1
902
                        ):
903

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

        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
954 955
                c_quality = None

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

962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984
        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
985

986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
        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])))
1004
        return GLBL_WINDOW
1005 1006


1007
    def specify_phys_memory(self,
Oleg Dzhimiev's avatar
Oleg Dzhimiev committed
1008
                            circbuf_chn_size= 0x4000000,
1009 1010 1011 1012
                            verbose =         1):
        """
        @param circbuf_chn_size - circular buffer size for each channel, in bytes
        """
1013 1014 1015
        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
1016

1017 1018 1019 1020
        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=[]
1021
        GLBL_CIRCBUF_ENDS=[]
1022 1023
        for i in range(16):
            GLBL_CIRCBUF_STARTS.append(circbuf_start + i*circbuf_chn_size)
1024
            GLBL_CIRCBUF_ENDS.append(circbuf_start + (i+1)*circbuf_chn_size)
1025 1026 1027
        GLBL_CIRCBUF_END =     circbuf_start + 4*GLBL_CIRCBUF_CHN_SIZE
        GLBL_MEMBRIDGE_START = GLBL_CIRCBUF_END
        GLBL_MEMBRIDGE_END =   GLBL_BUFFER_END
1028 1029 1030 1031 1032 1033

        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
1034

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

1080 1081 1082 1083 1084 1085 1086 1087 1088 1089
    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))
1090
                return frames
1091
        except:
1092
            pass
1093 1094 1095
        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)
1096

1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
    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;
1116
        return frameno # Frame number of the last  new frame checked
1117

1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
    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
1129
        return frameno # Frame number of the last  new frame checked
1130

1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149
    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;
1150 1151
        return frameno # Frame number of the last  new frame checked

1152 1153
    def setup_compressor(self,
                          chn,
1154
                          cmode =            0, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
                          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
1166
                          colorsat_blue =    0x120,     # 0x90 for 1x
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
                          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)
1189
        @param focus_mode -   focus mode - how to combine image with "focus quality" in the result image
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199
        @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
        """
1200 1201 1202

        global FRAME_FULL_WIDTH, FRAME_START_ADDRESS_INC

1203 1204 1205
        try:
            if (chn == all) or (chn[0].upper() == "A"): #all is a built-in function
                for chn in range(4):
1206
                    self. setup_compressor( #self,
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219
                                           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
1220
                                           colorsat_blue =  colorsat_blue, #0x120     # 0x90 for 1x
1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
                                           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"]
1237
        COLOR_MARGINS = 2
1238
        num_sensor = chn # 1:1 sensor - compressor
1239

1240
        align_to_bursts = 64 # align full width to multiple of align_to_bursts. 64 is the size of memory access
1241 1242 1243 1244 1245 1246 1247 1248
        """
        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
1249

1250 1251 1252 1253 1254 1255 1256
        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)
1257

1258 1259 1260 1261 1262 1263 1264 1265
        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
1266

1267 1268
        tile_height = 16 + overlap;
        """
1269 1270


1271 1272 1273 1274
        width_in_bursts = window_width >> 4
        if (window_width & 0xf):
            width_in_bursts += 1
        compressor_left_margin = window_left % 32
1275

1276 1277 1278 1279
        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
1280 1281 1282
        """
        Changing frame full width and size to fixed values (normally read from sysfs)
                frame_full_width =  num_pages_in_line * align_to_bursts
1283

1284
        """
1285

1286
        frame_full_width =  FRAME_FULL_WIDTH # Made it fixed width
1287 1288 1289
        num8rows=   (window_top + window_height) // 8
        if (window_top + window_height) % 8:
            num8rows += 1
1290
        """
1291
        frame_start_address_inc = num8rows * frame_full_width
1292
        """
1293
        frame_start_address_inc = FRAME_START_ADDRESS_INC #Fixed size
1294 1295 1296 1297

        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
1298

1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318
        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
1319

1320 1321 1322 1323
        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
1324
            extra_pages = 0 #  1 # just testing, 0 should be OK  here
1325 1326 1327 1328 1329 1330
        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
1331

1332 1333 1334 1335 1336 1337 1338
        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))
1339
            print ("window_width =     0x%x (in 16 - bursts, made even)"%(width32 * 2 )) # window_width >> 4)) # width in 16 - bursts, made even
1340 1341 1342 1343 1344 1345 1346 1347 1348
            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")
1349
            print ("abort_late =       0")
1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365

        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,
1366 1367 1368
            disable_need =     1,
            abort_late =       False)

1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
    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
1384

1385 1386 1387 1388 1389
        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
1390

1391 1392 1393
                if reset_mask & MASK_MEMSENSOR:
                    self.x393Sensor.control_sensor_memory    (num_sensor = chn,
                                                              command = 'stop')
1394

1395 1396 1397
                if reset_mask & MASK_MEMCOMPRESSOR:
                    self.x393Cmprs.control_compressor_memory (num_sensor = chn,
                                                              command = 'stop')
1398 1399

        self.sleep_ms(200)
1400 1401 1402 1403 1404 1405 1406 1407
        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')
1408

1409 1410 1411 1412 1413 1414 1415 1416
                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)

1417

1418
    def setup_all_sensors (self,
1419
                              setup_membridge =           False,
1420 1421 1422
                              exit_step =                 None,
                              sensor_mask =               0x1, # channel 0 only
                              gamma_load =                False,
1423 1424 1425 1426
                              window_width =              None, # 2592,   # 2592
                              window_height =             None, # 1944,   # 1944
                              window_left =               None, # 0,     # 0
                              window_top =                None, # 0, # 0? 1?
1427
                              compressor_left_margin =    0, #0?`1?
1428
                              last_buf_frame =            1,  #  - just 2-frame buffer
1429
                              cmode =                     0, # vrlg.CMPRS_CBIT_CMODE_JPEG18,
1430
                              colorsat_blue =             0x120,     # 0x90 fo 1x
1431 1432
                              colorsat_red =              0x16c,     # 0xb6 for x1
                              clk_sel =                   1,         # 1
1433 1434 1435 1436
                              histogram_left =            None,
                              histogram_top =             None,
                              histogram_width_m1 =        None, # 2559, #0,
                              histogram_height_m1 =       None, # 799, #0,
1437
                              circbuf_chn_size=           0x4000000, # 64 Mib - all 4 channels?
1438
                              reset_afi =                 False, # reset AFI multiplexer
Andrey Filippov's avatar
Andrey Filippov committed
1439
                              bits16 =                    False,
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467
                              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
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481
        @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
1482 1483
        @param colorsat_blue - color saturation for blue (10 bits), 0x90 for 100%
        @param colorsat_red -  color saturation for red (10 bits), 0xb6 for 100%
1484
        @param clk_sel - True - use pixel clock from the sensor, False - use internal clock (provided to the sensor), None - no change
1485 1486 1487 1488
        @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)
1489 1490 1491 1492 1493
        @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
1494

1495
        @param circbuf_chn_size - circular buffer size for each channel, in bytes
<