예제 #1
0
 def init_pru(self):
     '''
     creates interface for pruss and irq
     '''
     self.IRQ = 2
     self.pruss = Icss('/dev/uio/pruss/module')
     self.irq = Uio("/dev/uio/pruss/irq%d" % self.IRQ, blocking=False)
     self.pruss.initialize(fill_memories=True)
예제 #2
0
파일: pwmss.py 프로젝트: silver2row/py-uio
 def qep(self):
     if not self._qep:
         self.regs.clkreq.qep = 1
         if self.regs.clkack.qep != 1:
             raise RuntimeError("submodule clock failure?")
         uio = Uio(self.path.parent / 'qep', parent=self)
         self._qep = uio.map(EQep)
         self._qep.irq.uio = uio
     return self._qep
예제 #3
0
파일: pwmss.py 프로젝트: silver2row/py-uio
 def cap(self):
     if not self._cap:
         self.regs.clkreq.cap = 1
         if self.regs.clkack.cap != 1:
             raise RuntimeError("submodule clock failure?")
         uio = Uio(self.path.parent / 'cap', parent=self)
         self._cap = uio.map(ECap)
         self._cap.irq.uio = uio
     return self._cap
예제 #4
0
    def _add_submodule(self, name, Module, offset):
        module = None

        path = self.path / name
        if path.exists():
            uio = Uio(path, parent=self)
            assert uio.region().address == self.region().address + offset

            module = uio.map(Module)
            module._uio = uio

            module.irq.uio = uio

        setattr(self, name, module)

        if module is None:
            # fallback, mainly for debugging:
            module = self.map(Module, offset)

        setattr(self, '_' + name, module)
예제 #5
0
#!/usr/bin/python3

from uio.ti.icss import Icss
from uio.device import Uio
import ctypes
import asyncio

loop = asyncio.get_event_loop()

EVENT0 = 16 # range 16..31
EVENT1 = 17 # range 16..31
IRQ = 2     # range 2..9

pruss = Icss( "/dev/uio/pruss/module" )
irq = Uio( "/dev/uio/pruss/irq%d" % IRQ )
intc = pruss.intc
(core0, core1) = pruss.cores

pruss.initialize()

# clear and enable events and route them to our irq
for event in EVENT0, EVENT1:
    intc.ev_ch[ event ] = IRQ
    intc.ev_clear_one( event )
    intc.ev_enable_one( event )

# load program onto both cores
core0.load( 'fw/intc-test.bin' )
core1.load( 'fw/intc-test.bin' )

# map and set parameters
예제 #6
0
#!/usr/bin/python3

import asyncio
from uio.device import Uio

loop = asyncio.get_event_loop()

pin = Uio("/dev/uio/gpio-irq", blocking=False)
pin.irq_enable()


def irq_callback():
    pin.irq_recv()
    print("Ping!")

    # If the irq is level-triggered instead of edge-triggered, you should
    # ensure that it is no longer asserted before reenabling it, otherwise
    # it will just immediately trigger again.
    pin.irq_enable()


loop.add_reader(pin.fileno(), irq_callback)

loop.run_forever()
예제 #7
0
#!/usr/bin/python3

from uio.device import Uio

pin = Uio("/dev/uio/gpio-irq")
pin.irq_enable()

while True:
    pin.irq_recv()
    print("Ping!")

    # If the irq is level-triggered instead of edge-triggered, you should
    # ensure that it is no longer asserted before reenabling it, otherwise
    # it will just immediately trigger again.
    pin.irq_enable()
예제 #8
0
#!/usr/bin/python3

from uio.ti.icss import Icss
from uio.device import Uio
import ctypes
import os

EVENT0 = 16  # range 16..31
EVENT1 = 17  # range 16..31
IRQ = 2  # range 2..9

pruss = Icss("/dev/uio/pruss/module")
irq = Uio("/dev/uio/pruss/irq%d" % IRQ)
intc = pruss.intc
(core0, core1) = pruss.cores

pruss.initialize()

# clear and enable events and route them to our irq
for event in EVENT0, EVENT1:
    intc.ev_ch[event] = IRQ
    intc.ev_clear_one(event)
    intc.ev_enable_one(event)

# load program onto both cores
core0.load('fw/intc-test.bin')
core1.load('fw/intc-test.bin')


# map and set parameters
class Params(ctypes.Structure):
예제 #9
0
#!/usr/bin/python3

from uio.ti.icss import Icss
from uio.device import Uio
import ctypes

EVENT0 = 16  # range 16..31
EVENT1 = 17  # range 16..31
IRQ = 2  # range 2..9

pruss = Icss("/dev/uio/pruss/module")
irq = Uio("/dev/uio/pruss/irq%d" % IRQ)
intc = pruss.intc
(core0, core1) = pruss.cores

pruss.initialize()

# clear and enable events and route them to our irq
for event in EVENT0, EVENT1:
    intc.ev_ch[event] = IRQ
    intc.ev_clear_one(event)
    intc.ev_enable_one(event)

# load program onto both cores
core0.load('fw/intc-test.bin')
core1.load('fw/intc-test.bin')


# map and set parameters
class Params(ctypes.Structure):
    _fields_ = [
예제 #10
0
파일: l3-sn-test.py 프로젝트: mvduin/py-uio
#!/usr/bin/python3

from uio.device import Uio
import ctypes
from ctypes import c_uint32 as uint


########## L3 interconnect service network #####################################
#
# Welcome to the most fussy register space on the SoC!
# Only single word access allowed. Byte/halfword/multi-word access = bus error.

l3_sn = Uio( "/dev/uio/l3-sn" )

class ComponentID( ctypes.Structure ):
    _fields_ = [
            ("vendor",  uint, 16),  # 1 = Arteris
            ("type",    uint, 16),
            ("hash",    uint, 24),
            ("version", uint,  8),
        ]

class FlagOutput( ctypes.Structure ):
    src_t = uint  # one bit per input

    _fields_ = [
            ("enabled", src_t),  #rw
            ("pending", src_t),  #r-
        ]

class FaultCombiner( ctypes.Structure ):
예제 #11
0
class Machine:
    def __init__(self, stepper=True, camera = False):
        if camera:
            from camera import Camera
            self.camera = Camera()
        self.loadconstants()
        self.position = [0, 0, 0]
        self.pindictionary()
        self.init_pru()
        self.currentdir = dirname(realpath(__file__))
        self.bin_folder = join(self.currentdir, 'binaries')
        self.laserchannels = 0
        self.configure_pins()
        if stepper:
            self.motor_spi = [self.init_stepper(label) for label in ['x','y','z']] 
        # digipot is used to set laser power
        self.digipot = I2C.get_i2c_device(0x28, busnum=2)


    def configure_pins(self):
        '''
        pins are configured via config-pin -f pinfile.bbio

        This relies on cape-universal. Cape-universal allows pins to be
        changed on the fly without reboot.
        '''
        path = join(self.currentdir, 'config-pin', 'firestarter.bbio')
        MyOut = subprocess.Popen(['config-pin', '-f', path ],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.STDOUT)
        stdout, stderr = MyOut.communicate()
        if stdout or stderr:
            raise Exception("Configuring pins via config-pin failed")


    @property
    def laser_power(self):
        '''
        gets power set for laser driver chip can be in range [0-255] 
        '''
        return abs(self.digipot.readU8(0))


    @laser_power.setter
    def laser_power(self, value):
        '''
        set laser power to given value in range [0-255]
        for the laser driver chip. This does not turn on or off the laser.

        The laser power can be changed in two ways.
        First by using one or two channels. Second by settings a value between
        0-255 at the laser driver chip.
        '''
        if value < 0 or value > 255:
            raise Exception('Invalid laser power')
        self.digipot.write8(0, value)


    @property
    def laserchannels(self):
        '''
        returns the number of laser channels turned on

        channels can be [0,1,2]
        '''
        return self._laserchannels


    @laserchannels.setter
    def laserchannels(self, channels):
        '''
        sets 0, 1 or 2 channels on.
        
        The laser power can be changed in two ways.
        First by using one or two channels. Second by setting a value in 
        range [0-255] at the laser driver chip. Here the amount of channels 
        used is set.
        :param channels: number of channels to be turned max is 2. 
        '''
        channels = int(round(channels))
        if channels<0 or channels>2:
            raise Exception("Channels is not within set [0,1,2]")

        self.pruss.core0.load(join(self.bin_folder,
            'switch_laser.bin'))

        class Params( Structure ):
            _fields_ = [
                    ("power", c_uint32)
        ]
        variables = self.pruss.core0.dram.map(Params)
        variables.power = int(round(channels))
        self.pruss.core0.run()
        while not self.pruss.core0.halted:
            pass
        self._laserchannels = int(round(channels))


    def test_photodiode(self):
        """
        The laser is turned on. The polygon is spun at a rate of 1000 Hz
        for 5 seconds. The photodiode is measured for three seconds, if 
        high within these three seconds test is succesfull, otherwise 
        unsuccesfull. The laser is turned off.
        """
        GPIO.output(self.pins['prism_enable'], GPIO.LOW)
        self.pruss.core0.load(join(self.bin_folder,
                        'photodiodetest.bin'))
        self.pruss.core0.run()
        print("Waiting for core to halt")
        while not self.pruss.core0.halted:
            pass
        byte0 = self.pruss.core0.dram.map(c_uint32)
        return_value = int(byte0.value)
        if return_value == 0:
            print("Laser detected with photodiode, test successfull")
        elif return_value == 1:
            print("Photo diode connected but no signal")
        else:
            print("Photo diode not connected")
        GPIO.output(self.pins['prism_enable'], GPIO.HIGH)


    def test_polygonmotor(self):
        """
        spins the polygon at a rate of x Hz for 5 seconds
        """
        GPIO.output(self.pins['prism_enable'], GPIO.LOW)
        self.pruss.core0.load(join(self.bin_folder,
                        'spinpolygon.bin'))
        self.pruss.core0.run()
        print("Spinning polygon for 5 seconds")
        while not self.pruss.core0.halted:
            pass
        GPIO.output(self.pins['prism_enable'], GPIO.HIGH)


    def test_createline(self):
        """
        spins the polygon at a rate of x Hz for 5 seconds
        while laser channel 1 is enabled.
        As such a line is created without a phase lock loop.
        """
        GPIO.output(self.pins['prism_enable'], GPIO.LOW)
        self.pruss.core0.load(join(self.bin_folder,
                        'createline.bin'))
        self.pruss.core0.run()
        print("Turning on channel 1 and spinning polygon for 5 seconds")
        while not self.pruss.core0.halted:
            pass
        GPIO.output(self.pins['prism_enable'], GPIO.HIGH)


    def loadconstants(self):
        '''
        loads COMMANDS and Errors
        '''
        # commands accepted by scanhead also defined in laserscribe constants
        self.COMMANDS = ['CMD_EMPTY',
                'CMD_SCAN_DATA', 'CMD_SCAN_DATA_NO_SLED']
        self.COMMANDS += ['CMD_EXIT', 'CMD_DONE']
        self.COMMANDS = bidict(enumerate(self.COMMANDS))
        # errors accepted by scanhead also defined in laserscribe constants
        self.ERRORS = ['ERROR_NONE',
                'ERROR_DEBUG_BREAK', 'ERROR_MIRROR_SYNC']
        self.ERRORS += ['ERROR_TIME_OVERRUN']
        self.ERRORS = bidict(enumerate(self.ERRORS))

        #TODO: place this in a dictionary or a named tuple

        # key variables
        self.RPM = 2400                           # revolutions per minute 
        self.TICK_DELAY = 100                # cpu cycles in loop
        PRU_SPEED = 200E6                    # cpu cycles per second
        self.FACETS = 4                           # number of sides of prism
        self.TICKS_START = 4375              # laser starts in off state
        self.SCANLINE_DATA_SIZE = 790        # there are 8 pixels per byte 
                                             # so TICKS = 8*SCANLINE_DATA_SIZE
        # dependent variables
        self.TICKS_PER_PRISM_FACET = round(PRU_SPEED//  # ticks per prism facet
        (self.TICK_DELAY*(self.RPM*self.FACETS)/60)) 
        # time in seconds used to spinup prism
        self.SPINUP_TICKS = round(1.5 * PRU_SPEED / self.TICK_DELAY) 
        # time in seconds waited for laser stabilization
        self.MAX_WAIT_STABLE_TICKS = round(1.125 * PRU_SPEED / self.TICK_DELAY) 
        # ticks per half period of prism motor
        self.TICKS_HALF_PERIOD_MOTOR=int(round((self.TICKS_PER_PRISM_FACET*self.FACETS/6)/2))
        self.SCANLINE_HEADER_SIZE = 1        # each line starts with a self.COMMAND
        self.START_RINGBUFFER = 1            # the zero byte is an error code, ringbuffer starts at 1
        self.QUEUE_LEN = 8                   # length of the ringbuffer
        # length of an item in the ringbuffer in bytes
        self.SCANLINE_ITEM_SIZE = self.SCANLINE_HEADER_SIZE + self.SCANLINE_DATA_SIZE
        # the prism is spin up, it is determined if the jitter per prism is within a certain threshold
        self.JITTER_THRESH = round(self.TICKS_PER_PRISM_FACET / 400 )
        # after spinup the jitter allow is set smaller this leads to better results
        self.JITTER_ALLOW = round(self.TICKS_PER_PRISM_FACET / 3000 )

        self.STEPSPERMM = {'x': 76.2, 'y': 76.2, 'z': 1600}
        # These things are needed in interpolator
        self.SLED_SPEED = 1/self.STEPSPERMM['y']*(self.RPM*self.FACETS/60)
        #print("Sled speed is fixed at {} mm/s".format(SLED_SPEED))
        #print("Laser freq is {} Hz".format(200e6/TICK_DELAY))
        


    def init_stepper(self, drive='x', mA=600, microsteps=16, stealthchop=True):
        '''
        connects to stepper motor with current in miliamperes, number of microsteps
        and steatlchop, drive can be x, y or z.
        '''
        GPIO_0_BASE = 0x44E07000
        # pins order is x,y,z
        pindict = {'x':GPIO_0_BASE | 5,'y':GPIO_0_BASE | 30, 'z': GPIO_0_BASE | 26} 
        try:
            motor = steppers.TMC2130(pindict[drive])
        except KeyError:
            raise Exception("Invalid drive value")
        motor.begin()
        if motor.test_connection():
            raise Exception("Failed to connent to {} motor".format(drive))
        motor.rms_current(mA)
        motor.microsteps(microsteps)
        motor.toff(3)
        motor.stealthChop(stealthchop)
        return motor


    def init_pru(self):
        '''
        creates interface for pruss and irq
        '''
        self.IRQ = 2
        self.pruss = Icss('/dev/uio/pruss/module')
        self.irq = Uio("/dev/uio/pruss/irq%d" % self.IRQ, blocking=False)
        self.pruss.initialize(fill_memories=True)


    def pindictionary(self):
        '''
        creates dictionary for motor pins
        '''
        self.pins = {'x_dir': "P9_42",
                     'y_dir': "P8_15",
                     'z_dir': "P8_17",
                     'step_enable': "P9_12",
                     'prism_enable': "P9_23"}

        for key, value in self.pins.items():
            GPIO.setup(value, GPIO.OUT)


    def write_params(self, axis, distance, speed, core=0):
        '''
        writes parameters to pru0

        in moving distance defines a length
        in homing distance defines a limit

        :param axis; can be 'x', 'y' or 'z' used to determine steps per mm
        :param distance; distance in mm
        :param speed; speed in mm/s
        :param core; pru core map parameters to
        '''
        try:
            steps_per_mm = self.STEPSPERMM[axis]
        except KeyError:
            raise Exception("Axis {} invalid".format(axis))

        class Params( Structure ):
            _fields_ = [                         #1 steps moved in case of move
                    ("steps", c_uint32),         #1 max amount steps moved for home
                    ("halfperiodstep", c_uint32) #2 speed
        ]
        if core == 0:
            params = self.pruss.core0.dram.map(Params)
        else:
            params = self.pruss.core1.dram.map(Params)
        # round(np.float64(3.0)) -> 3.0, round(3.0) -> 3
        params.steps = int(round(distance * steps_per_mm))
        CPU_SPEED = 200E6
        INST_PER_LOOP = 2
        params.halfperiodstep = int(round(CPU_SPEED
            /(2*speed*steps_per_mm*INST_PER_LOOP)))


    def enable_steppers(self):
        '''
        enables stepper motors by setting enable pin to low
        '''
        GPIO.output(self.pins['step_enable'], GPIO.LOW)


    def disable_steppers(self):
        '''
        disables stepper motors by setting enable pin to high
        '''
        GPIO.output(self.pins['step_enable'], GPIO.HIGH)


    def home(self, direction='x', speed = 2):
        '''
        homes axis in direction at given speed
        
        :param direction; homing direction, x or y
        :param speed; homing speed in mm/s
        '''
        if direction == 'x':
            self.write_params('x', 300, speed, core=1)
            GPIO.output(self.pins['x_dir'], GPIO.LOW)
            self.pruss.core1.load(join(self.bin_folder,
                'home_x.bin'))
            self.pruss.core1.run()
            while not self.pruss.core1.halted:
                pass
            if self.pruss.core1.r10:
                raise Exception("Homing x failed")
        elif direction == 'y':
            self.write_params('y', 300, speed, core=0)
            GPIO.output(self.pins['y_dir'], GPIO.LOW)
            self.pruss.core0.load(join(self.bin_folder,
                'home_y.bin'))
            self.pruss.core0.run()
            while not self.pruss.core0.halted:
                pass
            if self.pruss.core0.r2:
                raise Exception("Homing y failed")
        elif direction == 'z':
            self.write_params('z', 300, speed, core=1)
            # home in the down direction
            GPIO.output(self.pins['z_dir'], GPIO.HIGH)
            self.pruss.core1.load(join(self.bin_folder,
                'home_z.bin'))
            self.pruss.core1.run()
            while not self.pruss.core1.halted:
                pass
            if self.pruss.core1.r10:
                raise Exception("Homing z failed")
        else:
            raise Exception("Direction invalid")
        # update current position, move so homing switch is disabled
        if direction == 'x':
            self.position[0] = 0
            self.move([40, self.position[1], self.position[2]], 4)
            self.position[0] = 0
        elif direction == 'y':
            self.position[1] = 0
            self.move([self.position[0], 10, self.position[2]], 4)
            self.position[1] = 0
        else: # must be z exception already cared in homing procedure
            self.position[2] = 0
            self.move([self.position[0], self.position[2], 10], 4)  
            self.position[2] = 0


    def move(self, target_position, speed = 2):
        '''
        moves axis into position at given speed

        :param target position; list, [x, y, z] in mm
        :param speed; homing speed in mm/s
        '''
        if target_position[0] < 0 or target_position[0] > 200:
            raise Exception('Target out of bounds')
        elif target_position[1] < 0 or target_position[1] > 200:
            raise Exception('Target out of bounds')
        elif target_position[2] < 0 or target_position[2] > 200:
            raise Exception('Target out of bounds')
        displacement = np.array(target_position) - np.array(self.position)
        
        if displacement[0]:
            direction = GPIO.HIGH if displacement[0] > 0 else GPIO.LOW
            GPIO.output(self.pins['x_dir'], direction)
            self.write_params('x', abs(displacement[0]), speed, core=1)
            self.pruss.core1.load(join(self.bin_folder, 'move_x.bin'))
            self.pruss.core1.run()
            while not self.pruss.core1.halted:
                pass

        if displacement[1]:
            direction = GPIO.HIGH if displacement[1] > 0 else GPIO.LOW
            GPIO.output(self.pins['y_dir'], direction)
            self.write_params('y', abs(displacement[1]), speed, core=0)
            self.pruss.core0.load(join(self.bin_folder, 'move_y.bin'))
            self.pruss.core0.run()
            while not self.pruss.core0.halted:
                pass

        if displacement[2]:
            direction = GPIO.LOW if displacement[2] > 0 else GPIO.HIGH
            GPIO.output(self.pins['z_dir'], direction)
            self.write_params('z', abs(displacement[2]), speed, core=1)
            self.pruss.core1.load(join(self.bin_folder, 'move_z.bin'))
            self.pruss.core1.run()
            while not self.pruss.core1.halted:
                pass

        self.position = target_position


    def enable_scanhead(self, singlefacet=False):
        '''
        enables scanhead, ensure scanhead is not above substrate
        :param singlefacet; if true singlefacet exposure enabled
        '''
        GPIO.output(self.pins['prism_enable'], GPIO.LOW)
        PRU0_ARM_INTERRUPT = 19
        self.pruss.intc.ev_ch[PRU0_ARM_INTERRUPT] = self.IRQ
        self.pruss.intc.ev_clear_one(PRU0_ARM_INTERRUPT)
        self.pruss.intc.ev_enable_one(PRU0_ARM_INTERRUPT)
        self.pruss.core0.load(join(self.bin_folder, './stabilizer.bin'))
        # map and set parameters
        class Variables( Structure ):
            _fields_ = [
                    ("ringbuffer_size", c_uint32),  
                    ("item_size", c_uint32),
                    ("start_sync_after", c_uint32),
                    ("global_time", c_uint32),
                    ("polygon_time", c_uint32),
                    ("wait_countdown", c_uint32),
                    ("hsync_time", c_uint32),
                    ("item_start", c_uint32),
                    ("item_pos", c_uint32),
                    ("state", c_uint16),
                    ("bit_loop", c_uint8),
                    ("last_hsync_bit", c_uint8),
                    ("single_facet", c_uint8),
                    ("current_facet", c_uint8),
                    ("ticks_half_period_motor", c_uint16),
                    ("low_thresh_prism", c_uint16),
                    ("high_thresh_prism", c_uint16),
                    ("ticks_start", c_uint16),
                    ("tick_delay", c_uint16),
                    ("spinup_ticks", c_uint32),
                    ("max_wait_stable_ticks", c_uint32)
                ]
        variables = self.pruss.core0.dram.map(Variables)
        if singlefacet:
            variables.single_facet = 1
        else:
            variables.single_facet = 0
        variables.item_size = self.SCANLINE_ITEM_SIZE
        variables.ringbuffer_size = self.SCANLINE_ITEM_SIZE * self.QUEUE_LEN
        variables.start_sync_after = self.TICKS_PER_PRISM_FACET - self.JITTER_ALLOW - 1
        variables.ticks_half_period_motor = self.TICKS_HALF_PERIOD_MOTOR
        variables.low_thresh_prism = self.TICKS_PER_PRISM_FACET - self.JITTER_THRESH
        variables.high_thresh_prism = self.TICKS_PER_PRISM_FACET + self.JITTER_THRESH
        variables.ticks_start = self.TICKS_START
        variables.tick_delay = self.TICK_DELAY
        variables.max_wait_stable_ticks = self.MAX_WAIT_STABLE_TICKS
        variables.spinup_ticks = self.SPINUP_TICKS
        self.pruss.core0.run()
        #TODO: add check polygon is enabled and stable
        # if you can't disable does not work
        sleep(4)


    def receive_command(self, byte = None, check = False):
        '''
        receives command at given offset

        :param byte; byte to read after trigger is received this is the command
        :param check; check wether the command equals command empty
        '''
        if byte == None:
            byte = self.START_RINGBUFFER

        self.pruss.intc.out_enable_one(self.IRQ) 
        # while loop is used in case irc_recv call is non-blocking
        while True:
            result = self.irq.irq_recv()
            if result:
                break
            else:
                sleep(1E-3)
        self.pruss.intc.ev_clear_one(self.pruss.intc.out_event[self.IRQ])
        self.pruss.intc.out_enable_one(self.IRQ)
        [command_index] = self.pruss.core0.dram.map(length = 1,
                                    offset = byte)

        if check:
            received_command = self.COMMANDS[command_index]
            if  received_command != 'CMD_EMPTY':
                error = ('Command not empty but {} '.format(received_command) +
                         'you could overwrite line not written to substrate yet.')
                raise Exception(error)
        
        return command_index


    def disable_scanhead(self):
        '''
        disables scanhead

        function sleeps to offset is START_RINGBUFFER
        '''
    
        data = [self.COMMANDS.inv['CMD_EXIT']]
        self.pruss.core0.dram.write(data, offset = self.START_RINGBUFFER)
        while not self.pruss.core0.halted:
            pass
        GPIO.output(self.pins['prism_enable'], GPIO.HIGH)


    def error_received(self):
        '''
        prints errors received and returns error index

        can be used to read out errors from the laser scanner
        '''
        ERROR_RESULT_POS = 0
        error_index = self.pruss.core0.dram.map(length = 1,
                offset = ERROR_RESULT_POS)[0]
        if error_index:
            try:
                print("Error received; {}".format(
                    self.ERRORS[error_index]))
            except IndexError:
                print("Error, error out of index")
        return error_index


    def expose(self, line_data, direction = True,
            multiplier = 1, move = False, takepicture = False):
        '''
        expose given line_data to substrate in given direction
        each line is exposed multiplier times.
        returns result of takepicture

        :param line_data; data to write to scanner, uint8
        :param multiplier; amount of times a line is exposed
        :param direction; direction of exposure,
                          True is postive y (away from home)
        :param move; if enabled moves stage
        :param takepicture; if enabled takes picture
        '''
        if line_data.dtype != np.uint8:
            raise Exception('Dtype must be uint8')
        if len(line_data) % self.SCANLINE_DATA_SIZE:
            raise Exception('Data invalid, length should be multilple'
                            + ' of scanline size')
        if (line_data.max() < 1 or line_data.max() > 255):
            raise Exception('Data invalid, values out of range.')
        if move:
            self.enable_steppers()
        else:
            self.disable_steppers()

        if direction:
            GPIO.output(self.pins['y_dir'], GPIO.HIGH)
        else:
            GPIO.output(self.pins['y_dir'], GPIO.LOW)
        
        byte = self.START_RINGBUFFER

        for scanline in range(0, len(line_data)//self.SCANLINE_DATA_SIZE):
            for counter in range(0, multiplier):
                self.receive_command(byte, True)
                # you start the picture where the laser is just off again
                if scanline == self.QUEUE_LEN and takepicture:
                    self.camera.get_spotinfo(wait=False)
                extra_data = list(line_data[scanline*self.SCANLINE_DATA_SIZE
                    :(scanline+1)*self.SCANLINE_DATA_SIZE])
                if counter == 0:
                    write_data = ([self.COMMANDS.inv['CMD_SCAN_DATA']] 
                    + extra_data)
                else:
                    write_data = ([self.COMMANDS.inv['CMD_SCAN_DATA_NO_SLED']] 
                    + extra_data)
                self.pruss.core0.dram.write(write_data, offset = byte)
                byte += self.SCANLINE_ITEM_SIZE
                if byte > self.SCANLINE_DATA_SIZE * self.QUEUE_LEN:
                    byte = self.START_RINGBUFFER

        if takepicture: 
            return self.camera.get_answer()
        
        return byte
예제 #12
0
#!/usr/bin/python3

import asyncio
from uio.device import Uio

loop = asyncio.get_event_loop()

pin = Uio( "/dev/uio/gpio-irq", blocking=False )
pin.irq_enable()

def irq_callback():
    pin.irq_recv()
    print( "Ping!" )

    # If the irq is level-triggered instead of edge-triggered, you should
    # ensure that it is no longer asserted before reenabling it, otherwise
    # it will just immediately trigger again.
    pin.irq_enable()

loop.add_reader( pin.fileno(), irq_callback )

loop.run_forever()
예제 #13
0
#!/usr/bin/python3

from uio.device import Uio
import ctypes
from ctypes import c_uint32 as uint

########## L3 interconnect service network #####################################
#
# Welcome to the most fussy register space on the SoC!
# Only single word access allowed. Byte/halfword/multi-word access = bus error.

l3_sn = Uio("/dev/uio/l3-sn")


class ComponentID(ctypes.Structure):
    _fields_ = [
        ("vendor", uint, 16),  # 1 = Arteris
        ("type", uint, 16),
        ("hash", uint, 24),
        ("version", uint, 8),
    ]


class FlagOutput(ctypes.Structure):
    src_t = uint  # one bit per input

    _fields_ = [
        ("enabled", src_t),  #rw
        ("pending", src_t),  #r-
    ]
예제 #14
0
#!/usr/bin/python3

from uio.device import Uio
from uio.ti.subarctic.lcdc import Lcdc, lcdc_fck
from time import sleep

uio = Uio( "/dev/uio/lcdc" )
lcdc = uio.map( Lcdc )

# lcdc functional clock rate
fck = lcdc_fck()
print( "lcdc_fck = %f MHz" % (fck/1e6) )

# global config
lcdc.clock_div = 6  # FIXME pick suitable value
lcdc.pinmux = 0     # rfb

# memory clock rate
mck = fck / lcdc.clock_div
print( "lcdc_mck = %f MHz  (1 cycle = %f ns)" % (mck/1e6, 1e9/mck) )

# sanity checks
if fck > 252000000:
    raise RuntimeError('lcdc functional clock exceeds max spec')
if mck > 126000000:
    raise RuntimeError('lcdc memory clock exceeds max spec')
elif mck > 42000000 and lcdc.pinmux == 0:
    raise RuntimeError('lcdc memory clock exceeds max spec for rfb mode')

rfb = lcdc.rfb
rfb.protocol = 4    # hd44780
예제 #15
0
if TOTAL_LINES <= QUEUE_LEN:
    raise Exception("Less than {} lines!".format(QUEUE_LEN))

# DATA to send before PRU start
data = [ERRORS.inv['ERROR_NONE']] + [0]*4
data += ([COMMANDS.inv['CMD_SCAN_DATA']] + LINE)* QUEUE_LEN

# ENABLE polygon motor
polygon_enable = "P9_23"
GPIO.setup(polygon_enable, GPIO.OUT)
GPIO.output(polygon_enable, GPIO.LOW)


pruss = Icss("/dev/uio/pruss/module")
irq = Uio("/dev/uio/pruss/irq%d" % IRQ, blocking=False)

pruss.initialize()

pruss.intc.ev_ch[PRU0_ARM_INTERRUPT] = IRQ
pruss.intc.ev_clear_one(PRU0_ARM_INTERRUPT)
pruss.intc.ev_enable_one(PRU0_ARM_INTERRUPT)

pruss.core0.load('./determinefacettime.bin')
pruss.core0.dram.write(data)
pruss.core0.run()
print("running core and uploaded data")

byte = START_RINGBUFFER # increased scanline size each loop
response = 1
# you read through ring buffer, it is extended by one to read out hsync time
예제 #16
0
#!/usr/bin/python3

from uio.ti.icss import Icss
from uio.device import Uio
import ctypes
import asyncio

loop = asyncio.get_event_loop()

EVENT0 = 16  # range 16..31
EVENT1 = 17  # range 16..31
IRQ = 2  # range 2..9

pruss = Icss("/dev/uio/pruss/module")
irq = Uio("/dev/uio/pruss/irq%d" % IRQ)
intc = pruss.intc
(core0, core1) = pruss.cores

pruss.initialize()

# clear and enable events and route them to our irq
for event in EVENT0, EVENT1:
    intc.ev_ch[event] = IRQ
    intc.ev_clear_one(event)
    intc.ev_enable_one(event)

# load program onto both cores
core0.load('fw/intc-test.bin')
core1.load('fw/intc-test.bin')

예제 #17
0
파일: gpio-irq.py 프로젝트: mvduin/py-uio
#!/usr/bin/python3

from uio.device import Uio

pin = Uio( "/dev/uio/gpio-irq" )
pin.irq_enable()

while True:
    pin.irq_recv()
    print( "Ping!" )

    # If the irq is level-triggered instead of edge-triggered, you should
    # ensure that it is no longer asserted before reenabling it, otherwise
    # it will just immediately trigger again.
    pin.irq_enable()