x393_camsync.py 8.32 KB
Newer Older
1 2 3 4 5 6 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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
from __future__ import division
from __future__ import print_function

'''
# Copyright (C) 2015, Elphel.inc.
# Class to control camsync (inter-camera synchronization) module  
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http:#www.gnu.org/licenses/>.

@author:     Andrey Filippov
@copyright:  2015 Elphel, Inc.
@license:    GPLv3.0+
@contact:    andrey@elphel.coml
@deffield    updated: Updated
'''
__author__ = "Andrey Filippov"
__copyright__ = "Copyright 2015, Elphel, Inc."
__license__ = "GPL"
__version__ = "3.0+"
__maintainer__ = "Andrey Filippov"
__email__ = "andrey@elphel.com"
__status__ = "Development"
#import sys
#import pickle
from x393_mem                import X393Mem
import x393_axi_control_status
import x393_gpio

import x393_utils

#import time
import vrlg

#  parameter SYNC_BIT_LENGTH=8-1; /// 7 pixel clock pulses
SYNC_BIT_LENGTH=8-1 # 7 pixel clock pulses

class X393Camsync(object):
    DRY_MODE= True # True
    DEBUG_MODE=1
    x393_mem=None
    x393_axi_tasks=None #x393X393AxiControlStatus
    X393_gpio=None
    x393_utils=None
    verbose=1
    def __init__(self, debug_mode=1,dry_mode=True, saveFileName=None):
        self.DEBUG_MODE=  debug_mode
        self.DRY_MODE=    dry_mode
        self.x393_mem=            X393Mem(debug_mode,dry_mode)
        self.x393_axi_tasks=      x393_axi_control_status.X393AxiControlStatus(debug_mode,dry_mode)
        self.x393_utils=          x393_utils.X393Utils(debug_mode,dry_mode, saveFileName) # should not overwrite save file path
        self.X393_gpio =          x393_gpio.X393GPIO(debug_mode,dry_mode, saveFileName)
        try:
            self.verbose=vrlg.VERBOSE
        except:
            pass
    def set_camsync_mode (self,
                          en =             True,
                          en_snd =         None,
                          en_ts_external = None,
                          triggered_mode = None,
                          master_chn =     None,
                          chn_en =         None):
        """
        Control camsync operational mode (None means "keep current value")
        set_camsync_mode (0) 
        @param en True - enable, False - reset module
        @param en_snd  - enable sending timestamp with the sync pulse
        @param en_ts_external - True - use received timestamp in the image file, False - use local timestamp 
        @param triggered_mode - False - async (free running) sensor mode, True - triggered (global reset) sensor mode
        @param master_chn -     sensor channel used as a synchronization source (delay used for flash in internal triggered mode)
        @param chn_en -         bitmask of enabled channels
        """
        data = 0
        if en:
            data |= 1 << vrlg.CAMSYNC_EN_BIT     
        if not en_snd is None:
            data |= (2,3)[en_snd] << (vrlg.CAMSYNC_SNDEN_BIT - 1)
        if not en_ts_external is None:
            data |= (2,3)[en_ts_external] << (vrlg.CAMSYNC_EXTERNAL_BIT - 1)
        if not triggered_mode is None:
            data |= (2,3)[triggered_mode] << (vrlg.CAMSYNC_TRIGGERED_BIT - 1)
        if not master_chn is None:
            data |=  (4 | (master_chn & 3)) << (vrlg.CAMSYNC_MASTER_BIT - 2)
        if not chn_en is None:
            data |=  (0x10 | (chn_en & 0xf)) << (vrlg.CAMSYNC_CHN_EN_BIT - 4)
        self.x393_axi_tasks.write_contol_register(vrlg.CAMSYNC_ADDR + vrlg.CAMSYNC_MODE, data);
        
    def set_camsync_inout(self,
                          is_out,
                          bit_number,
                          active_positive):
        """
        Setup camsync input or output
        @param is_out - True for outputs, False for inputs
        @param bit_number - number ogf GPIO (ext)
        @param active_positive - True for active-high signals, False for active low ones. None - inactive I/O
        """
        data = 0x55555
        db = 0
        if not active_positive is None:
            db=(2,3)[active_positive]
        data &= ~(3 << (2 * bit_number))
        data |=  (db << (2 * bit_number))   
        self.x393_axi_tasks.write_contol_register(vrlg.CAMSYNC_ADDR +
                                                 (vrlg.CAMSYNC_TRIG_SRC,vrlg.CAMSYNC_TRIG_DST)[is_out], data)
            
    def reset_camsync_inout(self,
                          is_out):
        """
        Reset camsync inputs or outputs to inactive/don't care state
        @param is_out - True for outputs, False for inputs
        """
        self.x393_axi_tasks.write_contol_register(vrlg.CAMSYNC_ADDR +
                                                 (vrlg.CAMSYNC_TRIG_SRC,vrlg.CAMSYNC_TRIG_DST)[is_out], 0)

    def set_camsync_period(self,
                          period):
        """
        Set camsync period
        @param period - period value in 10 ns steps - max 42.95 sec
        """
        self.x393_axi_tasks.write_contol_register(vrlg.CAMSYNC_ADDR + vrlg.CAMSYNC_TRIG_PERIOD, period)
            
    def set_camsync_delay(self,
                          sub_chn,
                          delay):
        """
        Set camsync delay for selected channel (in internal mode master channel is used for flash delay)
        @param sub_chn - sensor channel (0..3)
        @param delay -   delay value in 10 ns steps - max 42.95 sec
        """
        self.x393_axi_tasks.write_contol_register(vrlg.CAMSYNC_ADDR + vrlg.CAMSYNC_TRIG_PERIOD, delay)
    
    def camsync_setup(self,
                      sensor_mask =        None,
                      trigger_mode =       None,
                      ext_trigger_mode =   None,
                      external_timestamp = None,
                      camsync_period =     None,
                      camsync_delay =      None):
        """
        @param sensor_mask -        bitmask of enabled channels
        @param triggered_mode -     False - async (free running) sensor mode, True - triggered (global reset) sensor mode
        @param ext_trigger_mode -   True - external trigger source, 0 - local FPGA trigger source
        @param external_timestamp - True - use received timestamp in the image file, False - use local timestamp 
        @param period -             period value in 10 ns steps - max 42.95 sec
        @param delay -              delay value in 10 ns steps - max 42.95 sec (or list/tuple if different for channels)
        """
        self.set_camsync_period  (0) # reset circuitry
        self.set_gpio_ports (port_a = True)
        self.set_camsync_mode (
                               en = True,
                               snd_en = True,
                               en_ts_external = external_timestamp,
                               triggered_mode = trigger_mode,
                               master_chn =     0,
                               chn_en = sensor_mask)
        # setting I/Os after camsync is enabled
        self.reset_camsync_inout (is_out = 0)        # reset input selection
        if ext_trigger_mode :
            self.set_camsync_inout(is_out = 0,
                                   bit_number = 7,
                                   active_positive = 1) # set input selection - ext[7], active high
            
        self.reset_camsync_inout (is_out = 1)        # reset output selection
        self.set_camsync_inout   (is_out = 1,
                                  bit_number = 6,
                                  active_positive = 1) # set output selection - ext[6], active high
        self.set_camsync_period  (SYNC_BIT_LENGTH) #set (bit_length -1) (should be 2..255), not the period
        if not isinstance(camsync_delay,list) or isinstance(camsync_delay,tuple):
            camsync_delay = (camsync_delay, camsync_delay, camsync_delay, camsync_delay)
            for i, dly in enumerate (camsync_delay): 
                self.set_camsync_delay(sub_chn = i, delay = dly)

        self.set_camsync_period  (period = camsync_period) # set period (start generating) - in 353 was after everything else was set