class LEDTest(): """Test for LED on FT232H board""" def __init__(self): self._gpio = GpioController() self._state = 0 # SW cache of the GPIO output lines def pins(self): print(self._gpio.direction) def open(self, out_pins): """Open a GPIO connection, defining which pins are configured as output and input""" out_pins &= 0xFF url = environ.get('FTDI_DEVICE', 'ftdi://ftdi:232h/1') self._gpio.open_from_url(url, direction=out_pins) def close(self): """Close the GPIO connection""" self._gpio.close() def get_gpio(self, line): """Retrieve the level of a GPIO input pin :param line: specify which GPIO to read out. :return: True for high-level, False for low-level """ value = self._gpio.read_port() print(value) return bool(value & (1 << line)) def set_gpio(self, line, on): """Set the level of a GPIO ouput pin. :param line: specify which GPIO to madify. :param on: a boolean value, True for high-level, False for low-level """ if on: state = self._state | (1 << line) else: state = self._state & ~(1 << line) self._commit_state(state) def _commit_state(self, state): """Update GPIO outputs """ self._gpio.write_port(state) # do not update cache on error self._state = state
def test(self): """Check simple GPIO write and read sequence.""" gpio = GpioController() # access to the virtual GPIO port out_pins = 0xAA gpio.configure('ftdi://:232h/1', direction=out_pins) bus, address, iface = gpio.ftdi.usb_path self.assertEqual((bus, address, iface), (4, 5, 0)) vftdi = self.loader.get_virtual_ftdi(bus, address) gpio.write_port(0xF3) self.assertEqual(vftdi.gpio, 0xAA & 0xF3) vftdi.gpio = 0x0c vio = gpio.read_port() self.assertEqual(vio, (0xAA & 0xF3) | (~0xAA & 0x0c)) gpio.close()
class GpioTest(object): """ """ def __init__(self): self._gpio = GpioController() self._state = 0 # SW cache of the GPIO output lines def open(self, out_pins): """Open a GPIO connection, defining which pins are configured as output and input""" out_pins &= 0xFF self._gpio.open(vendor=0x403, product=0x6011, interface=1, direction=out_pins) def close(self): """Close the GPIO connection""" self._gpio.close() def set_gpio(self, line, on): """Set the level of a GPIO ouput pin. :param line: specify which GPIO to madify. :param on: a boolean value, True for high-level, False for low-level """ if on: state = self._state | (1 << line) else: state = self._state & ~(1 << line) self._commit_state(state) def get_gpio(self, line): """Retrieve the level of a GPIO input pin :param line: specify which GPIO to read out. :return: True for high-level, False for low-level """ value = self._gpio.read_port() return bool(value & (1 << line)) def _commit_state(self, state): """Update GPIO outputs """ self._gpio.write_port(state) # do not update cache on error self._state = state
def _test_gpio(self): """Check simple GPIO write and read sequence.""" with open('pyftdi/tests/resources/ft232h.yaml', 'rb') as yfp: self.loader.load(yfp) gpio = GpioController() # access to the virtual GPIO port out_pins = 0xAA gpio.configure('ftdi://:232h/1', direction=out_pins) bus, address, iface = gpio.ftdi.usb_path self.assertEqual((bus, address, iface), (4, 5, 0)) vftdi = self.loader.get_virtual_ftdi(bus, address) vport = vftdi.get_port(1) gpio.write_port(0xF3) self.assertEqual(vport.gpio, 0xAA & 0xF3) vport.gpio = 0x0c vio = gpio.read_port() self.assertEqual(vio, (0xAA & 0xF3) | (~0xAA & 0x0c)) gpio.close()
class Executor(multiprocessing.Process): ''' Provides an executor - responsible for banging data onto and off of the wire - which is intended to be run in a separate process. This also handles timing and has been built to use queues to try and reduce clock jitter. This was lifted from whatabanger with slight modifications. ''' def __init__(self, req, res, clk=0x01, mosi=0x02, miso=0x04, cs=0x08): ''' Ensure a logger is setup, and access to the GPIO is possible. ''' super(Executor, self).__init__() self.log = logging.getLogger(__name__) # The initial state is everything pulled HIGH. self.state = 0xFF # Ensure the work queue is accessible - this is used for the parent # to push request to bang onto the wire. self._in = req self._out = res # Defaults are: # Pin D0 - 0x01 - OUT (CLOCK) # Pin D1 - 0x02 - OUT (MOSI) # Pin D2 - 0x04 - IN (MISO) # Pin D3 - 0x08 - OUT (CHIP SELECT) self.clk = clk self.miso = miso self.mosi = mosi self.cs = cs # Setup the clock interval. This isn't the cycle time, but half the # target cycle time. self.clock_interval = 0.0 # Setup the interface, ensuring that MISO is set to GPIO IN. self.gpio = GpioController() direction = xor(0xFF, self.miso) self.log.debug("Setting up FT2232 for GPIO (%s)", "{0:08b}".format(direction)) self.gpio.open_from_url( url='ftdi://0x0403:0x6010/1', direction=direction, ) # Set the initial GPIO state. self.gpio.write_port(self.state) self.log.debug("Set the initial GPIO state to %s", self.state) def _write_bits(self, bits): ''' Write bits onto the wire (Master to Target) communication. ''' self.log.debug("Starting banging bits (%s)", bits) for bit in bits: # Pull the clock HIGH, and drive CS low. self.state |= self.clk self.state &= ~self.cs self.gpio.write_port(self.state) time.sleep(self.clock_interval) # Check whether we need to write a HIGH or LOW for the bit to be # transmitted (where HIGH is 1). if bit == 1: self.state |= self.mosi else: self.state &= ~self.mosi # Send data via MOSI on the FALLING-edge of the clock. self.state &= ~self.clk self.gpio.write_port(self.state) time.sleep(self.clock_interval) # If there's not a Logic Analyser connected, determining when all # data has been sent is a pain. Thus, this. self.log.debug("Finished banging bits") def _read_bits(self, count): ''' Reads N bits from the wire. ''' self.log.debug("Reading %s bits", count) # This should already be the case, but ensure MISO isn't drive by # the master (us). self.gpio.set_direction(self.miso, 0x0) result = [] for _ in range(count): # Data will be banged onto the wire by the target device on the # RISING edge. self.state |= self.clk self.gpio.write_port(self.state) # Finally, read the state of MISO to determine the value sent by # the target. if (self.gpio.read() & self.miso) == self.miso: result.append(1) else: result.append(0) # Sleep and then drive the clock LOW to complete the cycle. time.sleep(self.clock_interval) self.state &= ~self.clk self.gpio.write_port(self.state) time.sleep(self.clock_interval) self.log.debug("Read %s", result) return result def _write_clock(self): ''' 'Write' a clock cycle without sending any data. ''' # Pull the clock HIGH. self.state |= self.clk self.gpio.write_port(self.state) time.sleep(self.clock_interval) # Pull the clock LOW. self.state &= ~self.clk self.gpio.write_port(self.state) time.sleep(self.clock_interval) def run(self): ''' Run the clock, and bang bits as required. ''' self.log.info("Bit banger clock and monitor started") while True: # If there's anything in the queue, bang away. if self._in.qsize() > 0: request = self._in.get() self._write_bits(request['bits']) r = 0 while r <= request['size']: result = self._read_bits(8) r += 8 self._out.put(result) else: # If no data is pending send, make sure we still drive the # clock. self._write_clock()
# do nothing, already the default pass elif args.VCC_IO1 == '2.5V': setting = setting & 0xFD elif args.VCC_IO1 == '1.8V': setting = setting & 0xFE if args.VCC_IO2 == '3.3V': # do nothing, already the default pass elif args.VCC_IO2 == '2.5V': setting = setting & 0xF7 elif args.VCC_IO2 == '1.8V': setting = setting & 0xFB gpio.write_port(setting) ''' Copyright (C) 2013-2020 Efinix Inc. All rights reserved. This document contains proprietary information which is protected by copyright. All rights are reserved. This notice refers to original work by Efinix, Inc. which may be derivitive of other work distributed under license of the authors. In the case of derivative work, nothing in this notice overrides the original author's license agreement. Where applicable, the original license agreement is included in it's original unmodified form immediately below this header. WARRANTY DISCLAIMER. THE DESIGN, CODE, OR INFORMATION ARE PROVIDED “AS IS” AND EFINIX MAKES NO WARRANTIES, EXPRESS OR IMPLIED WITH