def setup_swapchain_depth_stencil(recreate=False): global depth_format, depth_stencil, depth_alloc, depth_view if recreate: hvk.destroy_image_view(api, device, depth_view) hvk.destroy_image(api, device, depth_stencil) hvk.free_memory(api, device, depth_alloc) width, height = window.dimensions() # Depth stencil attachment setup depth_format = None depth_formats = (vk.FORMAT_D32_SFLOAT_S8_UINT, vk.FORMAT_D24_UNORM_S8_UINT, vk.FORMAT_D16_UNORM_S8_UINT) for fmt in depth_formats: prop = hvk.physical_device_format_properties(api, physical_device, fmt) if IntFlag(vk.FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) in IntFlag( prop.optimal_tiling_features): depth_format = fmt break if depth_format is None: raise RuntimeError("Failed to find a suitable depth stencil format.") # Depth stencil image creation depth_stencil = hvk.create_image( api, device, hvk.image_create_info(format=depth_format, extent=vk.Extent3D(width=width, height=height, depth=1), usage=vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk.IMAGE_USAGE_TRANSFER_SRC_BIT)) # Depth stencil image memory image_memreq = hvk.image_memory_requirements(api, device, depth_stencil) mt_index = find_memory_type(vk.MEMORY_HEAP_DEVICE_LOCAL_BIT, vk.MEMORY_PROPERTY_DEVICE_LOCAL_BIT) depth_stencil_size = image_memreq.size * 2 depth_alloc = hvk.allocate_memory( api, device, hvk.memory_allocate_info(allocation_size=depth_stencil_size, memory_type_index=mt_index)) hvk.bind_image_memory(api, device, depth_stencil, depth_alloc) # Depth stencil image view depth_view = hvk.create_image_view( api, device, hvk.image_view_create_info( image=depth_stencil, format=depth_format, subresource_range=hvk.image_subresource_range( aspect_mask=vk.IMAGE_ASPECT_DEPTH_BIT | vk.IMAGE_ASPECT_STENCIL_BIT)))
class Tag(NameMixin, CreatedAtMixin, OrderedMixin, LikeMixin, IconMixin): TARGET_TYPE = IntFlag('Tag.TARGET_TYPE', 'FOLDER RESOURCE SKILL') ANY_TARGET = TARGET_TYPE.FOLDER | TARGET_TYPE.RESOURCE | TARGET_TYPE.SKILL color = ColorField( verbose_name='Цвет', null=True, blank=True, ) target_type = IntFlagField( verbose_name='Тип цели', enum=TARGET_TYPE, default=int(ANY_TARGET), ) class Meta: verbose_name = 'Метка' verbose_name_plural = 'Метки' default_related_name = 'tags' def save(self, *args, **kwargs): is_new = self._state.adding super().save(*args, **kwargs) if is_new: self.values.create(is_default=True)
def generate_compound(name, bitnames, null=False, sep='', maxbits=None, offset=0): for s in bitnames: if len(s) > 1: sep = '+' break nbits = {} s2i = dict([(s, i + offset) for i, s in enumerate(bitnames)]) d = [] if null: d.append(('null', 0)) nbits['null'] = 0 nbits[0] = 0 for s in bitnames: v = 1 << s2i[s] d.append((s, v)) nbits[s] = 1 nbits[v] = 1 for i in range(2, len(bitnames) + 1): if maxbits and i > maxbits: continue for c in combinations(bitnames, i): s = sep.join(c) j = 0 for x in c: j |= 1 << s2i[x] d.append((s, j)) nbits[s] = i nbits[j] = i states = IntFlag(name, d) return states, nbits
def create_device(): global physical_device, render_queue_family, device # Device selection (use the first available) physical_devices = hvk.list_physical_devices(api, instance) physical_device = physical_devices[0] # Queues setup (A single graphic queue) queue_families = hvk.list_queue_families(api, physical_device) render_queue_family = next(qf for qf in queue_families if IntFlag( vk.QUEUE_GRAPHICS_BIT) in IntFlag(qf.properties.queue_flags)) render_queue_create_info = hvk.queue_create_info( queue_family_index=render_queue_family.index, queue_count=1) # Device creation extensions = ("VK_KHR_swapchain", ) device = hvk.create_device(api, physical_device, extensions, (render_queue_create_info, ))
def generate_from_graph(name, bitnames, g, null=True, sep='', maxbits=None): ''' calculate the set of "contiguous" compound states with maximum size `maxbits` from the given graph of simple states ''' # http://stackoverflow.com/questions # /15658245/efficiently-find-all-connected-subgraphs for s in bitnames: if len(s) > 1: sep = '+' break nbits = {} results = [] if null: results.append(('null', 0)) nbits['null'] = 0 nbits[0] = 0 for i, s in enumerate(bitnames): j = 1 << i results.append((s, j)) nbits[s] = 1 nbits[j] = 1 def gsg(nodes, subset, neighbors): if not subset: candidates = nodes else: candidates = nodes.intersection(neighbors) if not candidates: nb = len(subset) if 2 <= nb <= maxbits: s = sep.join([ bitnames[x.index] for x in sorted(subset, key=lambda e: e.index) ]) j = 0 for x in subset: j |= 1 << x.index results.append((s, j)) nbits[s] = nb nbits[j] = nb else: n = next(iter(candidates)) sn = set([n]) nmsn = nodes - sn gsg(nmsn, subset, neighbors) gsg(nmsn, subset.union(sn), neighbors.union(n.neighbors())) gsg(set(g.vs()), set(), set()) states = IntFlag(name, results) return states, nbits
def generate_simple(name, bitnames, null=False, offset=0): flags = [] if null: flags.append(('null', 0)) for i, s in enumerate(bitnames): i += offset flags.append((s, 1 << i)) states = IntFlag(name, flags) nbits = {} for state in states: nbits[state.name] = 1 nbits[state.value] = 1 return states, nbits
def __init__(self, name, msgdef, options=None): self.size = types['u32'].size self.name = name self.enumtype = 'u32' self.msgdef = msgdef e_hash = {} for f in msgdef: if type(f) is dict and 'enumtype' in f: if f['enumtype'] != 'u32': self.size = types[f['enumtype']].size self.enumtype = f['enumtype'] continue ename, evalue = f e_hash[ename] = evalue self.enum = IntFlag(name, e_hash) types[name] = self class_types[name] = VPPEnumType self.options = options
from enum import IntFlag ResetLevels = IntFlag('ResetLevels', 'all allButID allButIDDR')
############################################## # The MIT License (MIT) # Copyright (c) 2016 Kevin Walchko # see LICENSE for full details ############################################## import attr from math import cos, sin, pi, atan2, asin, sqrt from squaternion import Quaternion from ins_nav.utils import rad2deg from ins_nav.utils import normalize3 from enum import IntFlag Angle = IntFlag("Angle", "degrees radians quaternion") @attr.s(slots=True) class TiltCompensatedCompass(object): """ A tilt compensated compass is basically just taking the magnetometer readings and adjusting them based of how the sensor is oriented (tilted). We use the accelerometer to determine the orientation relative to the ground. Obviously, if the sensor is under some sort of gravity loading, say movng fast (falling), then this won't work correctly. Also, the in sensor inputs are expected to have already been adjusted for biases and other issues (hard/soft iron errors). """ angle_units = attr.ib(default=Angle.degrees) # def __init__(self, angle_units=Angle.degrees):
class FtdiEeprom: """FTDI EEPROM management """ _PROPS = namedtuple('PROPS', 'size user dynoff') """Properties for each FTDI device release.""" _PROPERTIES = { 0x0200: _PROPS(0, None, 0x94), # FT232AM 0x0400: _PROPS(256, 0x14, 0x94), # FT232BM 0x0500: _PROPS(256, 0x16, 0x96), # FT2232D 0x0600: _PROPS(128, None, 0x98), # FT232R 0x0700: _PROPS(256, 0x1A, 0x9A), # FT2232H 0x0800: _PROPS(256, 0x1A, 0x9A), # FT4232H 0x0900: _PROPS(256, 0x1A, 0xA0), # FT232H 0x1000: _PROPS(1024, 0x1A, 0xA0), # FT230X/FT231X/FT234X } """EEPROM properties.""" CBUS = IntEnum('CBUS', 'TXDEN PWREN RXLED TXLED TXRXLED SLEEP CLK48 CLK24 CLK12 ' 'CLK6 IOMODE BB_WR BB_R', start=0) """Alternate features for legacy FT232R devices.""" CBUSH = IntEnum('CBUSH', 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 ' 'IOMODE TXDEN CLK30 CLK15 CLK7_5', start=0) """Alternate features for FT232H/FT2232H/FT4232H devices.""" CBUSX = IntEnum('CBUSX', 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 ' 'IOMODE TXDEN CLK24 CLK12 CLK6 BAT_DETECT BAT_DETECT_NEG ' 'I2C_TXE I2C_RXF VBUS_SENSE BB_WR BB_RD TIME_STAMP AWAKE', start=0) """Alternate features for FT230X devices.""" INVERT = IntFlag('INVERT', 'TXD RXD RTS CTS DTR DSR DCD RI') """Inversion flags for FT232R devices.""" CHANNEL = IntFlag('CHANNEL', 'FIFO OPTO CPU FT128 RS485') """Alternate port mode.""" DRIVE = IntEnum('DRIVE', 'LOW HIGH SLOW_SLEW SCHMITT _10 _20 _40 PWRSAVE_DIS') """Driver options for I/O pins.""" CFG1 = IntFlag('CFG1', 'CLK_IDLE_STATE DATA_LSB FLOW_CONTROL _08 ' 'HIGH_CURRENTDRIVE _20 _40 SUSPEND_DBUS7') """Configuration bits stored @ 0x01.""" VAR_STRINGS = ('manufacturer', 'product', 'serial') """EEPROM strings with variable length.""" def __init__(self): self.log = getLogger('pyftdi.eeprom') self._ftdi = Ftdi() self._eeprom = bytearray() self._dev_ver = 0 self._valid = False self._config = OrderedDict() self._dirty = set() def __getattr__(self, name): if name in self._config: return self._config[name] raise AttributeError('No such attribute: %s' % name) def open(self, device: Union[str, UsbDevice], ignore: bool = False) -> None: """Open a new connection to the FTDI USB device. :param device: the device URL or a USB device instance. :param ignore: whether to ignore existing content """ if self._ftdi.is_connected: raise FtdiError('Already open') if isinstance(device, str): self._ftdi.open_from_url(device) else: self._ftdi.open_from_device(device) if not ignore: self._read_eeprom() if self._valid: self._decode_eeprom() def close(self) -> None: """Close the current connection to the FTDI USB device, """ if self._ftdi.is_connected: self._ftdi.close() self._eeprom = bytearray() self._dev_ver = 0 self._config.clear() def connect(self, ftdi: Ftdi, ignore: bool = False) -> None: """Connect a FTDI EEPROM to an existing Ftdi instance. :param ftdi: the Ftdi instance to use :param ignore: whether to ignore existing content """ self._ftdi = ftdi self._eeprom = bytearray() self._dev_ver = 0 self._valid = False self._config = OrderedDict() self._dirty = set() if not ignore: self._read_eeprom() if self._valid: self._decode_eeprom() @property def device_version(self) -> int: """Report the version of the FTDI device. :return: the release """ if not self._dev_ver: if not self._ftdi.is_connected: raise FtdiError('Not connected') self._dev_ver = self._ftdi.device_version return self._dev_ver @property def size(self) -> int: """Report the EEPROM size. The physical EEPROM size may be greater. :return: the size in bytes """ try: eeprom_size = self._PROPERTIES[self.device_version].size except (AttributeError, KeyError): raise FtdiError('No EEPROM') return eeprom_size @property def data(self) -> bytes: """Returns the content of the EEPROM. :return: the content as bytes. """ self._sync_eeprom() return bytes(self._eeprom) @property def properties(self) -> Set[str]: """Returns the supported properties for the current device. :return: the supported properies. """ props = set(self._config.keys()) props -= set(self.VAR_STRINGS) return props @property def is_empty(self) -> bool: """Reports whether the EEPROM has been erased, or no EEPROM is connected to the FTDI EEPROM port. :return: True if no content is detected """ if len(self._eeprom) != self._PROPERTIES[self.device_version].size: return False for byte in self._eeprom: if byte != 0xFF: return False return True @property def cbus_pins(self) -> List[int]: """Return the list of CBUS pins configured as GPIO, if any :return: list of CBUS pins """ pins = [pin for pin in range(0, 10) if self._config.get('cbus_func_%d' % pin, '') == 'IOMODE'] return pins @property def cbus_mask(self) -> int: """Return the bitmask of CBUS pins configured as GPIO. The bitmap contains four bits, ordered in natural order. :return: CBUS mask """ if self.device_version == 0x900: # FT232H cbus = [5, 6, 8, 9] else: cbus = list(range(4)) mask = 0 for bix, pin in enumerate(cbus): if self._config.get('cbus_func_%d' % pin, '') == 'IOMODE': mask |= 1 << bix return mask def save_config(self, file: TextIO) -> None: """Save the EEPROM content as an INI stream. :param file: output stream """ self._sync_eeprom() cfg = ConfigParser() cfg.add_section('values') for name, value in self._config.items(): cfg.set('values', name, str(value)) cfg.add_section('raw') length = 16 for i in range(0, len(self._eeprom), length): chunk = self._eeprom[i:i+length] hexa = hexlify(chunk).decode() cfg.set('raw', '@%02x' % i, hexa) cfg.write(file) def set_serial_number(self, serial: str) -> None: """Define a new serial number.""" self._validate_string(serial) self._update_var_string('serial', serial) self.set_property('has_serial', True) def set_manufacturer_name(self, manufacturer: str) -> None: """Define a new manufacturer string.""" self._validate_string(manufacturer) self._update_var_string('manufacturer', manufacturer) def set_product_name(self, product: str) -> None: """Define a new product name.""" self._validate_string(product) self._update_var_string('product', product) def set_property(self, name: str, value: Union[str, int, bool], out: Optional[TextIO] = None) -> None: """Change the value of a stored property. :see: :py:meth:`properties` for a list of valid property names. Note that for now, only a small subset of properties can be changed. :param name: the property to change :param value: the new value (supported values depend on property) :param out: optional output stream to report hints """ mobj = match(r'cbus_func_(\d)', name) if mobj: if not isinstance(value, str): raise ValueError("'%s' should be specified as a string" % name) self._set_cbus_func(int(mobj.group(1)), value, out) self._dirty.add(name) return hwords = { 'vendor_id': 0x02, 'product_id': 0x04, 'type': 0x06, 'usb_version': 0x0c } if name in hwords: val = to_int(value) if not 0 <= val <= 0xFFFF: raise ValueError('Invalid value for %s' % name) offset = hwords[name] self._eeprom[offset:offset+2] = spack('<H', val) return confs = { 'remote_wakeup': (0, 5), 'self_powered': (0, 6), 'in_isochronous': (2, 0), 'out_isochronous': (2, 1), 'suspend_pull_down': (2, 2), 'has_serial': (2, 3), 'has_usb_version': (2, 4), } if name in confs: val = to_bool(value, permissive=False, allow_int=True) offset, bit = confs[name] mask = 1 << bit if val: self._eeprom[0x08+offset] |= mask else: self._eeprom[0x0a+offset] &= ~mask return if name == 'power_max': val = to_int(value) >> 1 self._eeprom[0x09] = val return if name in self.properties: raise NotImplementedError("Change to '%s' is not yet supported" % name) raise ValueError("Unknown property '%s'" % name) def erase(self) -> None: """Erase the whole EEPROM.""" self._eeprom = bytearray([0x00] * self.size) self._config.clear() def initialize(self) -> None: """Initialize the EEPROM with some default sensible values. """ dev_ver = self.device_version dev_name = Ftdi.DEVICE_NAMES[dev_ver] vid = Ftdi.FTDI_VENDOR pid = Ftdi.PRODUCT_IDS[vid][dev_name] self.set_manufacturer_name('FTDI') self.set_product_name(dev_name.upper()) sernum = ''.join([chr(randint(ord('A'), ord('Z'))) for _ in range(5)]) self.set_serial_number('FT%d%s' % (randint(0, 9), sernum)) self.set_property('vendor_id', vid) self.set_property('product_id', pid) self.set_property('type', dev_ver) self.set_property('usb_version', 0x200) self.set_property('power_max', 150) self._sync_eeprom() def sync(self) -> None: """Force re-evaluation of configuration after some changes. This API is not useful for regular usage, but might help for testing when the EEPROM does not go through a full save/load cycle """ self._sync_eeprom() def dump_config(self, file: Optional[BinaryIO] = None) -> None: """Dump the configuration to a file. :param file: the output file, default to stdout """ if self._dirty: self._decode_eeprom() for name, value in self._config.items(): print('%s: %s' % (name, value), file=file or sys.stdout) def commit(self, dry_run: bool = True) -> bool: """Commit any changes to the EEPROM. :param dry_run: log what should be written, do not actually change the EEPROM content :return: True if some changes have been committed to the EEPROM """ if not self._dirty: self.log.info('No change to commit') return False self.log.info('Changes to commit: %s', ', '.join(sorted(self._dirty))) self._sync_eeprom() self._ftdi.overwrite_eeprom(self._eeprom, dry_run=dry_run) return dry_run @classmethod def _validate_string(cls, string): for invchr in ':/': # do not accept characters which are interpreted as URL seperators if invchr in string: raise ValueError("Invalid character '%s' in string" % invchr) def _update_var_string(self, name: str, value: str) -> None: if name not in self.VAR_STRINGS: raise ValueError('%s is not a variable string' % name) try: if value == self._config[name]: return except KeyError: # not yet defined pass self._config[name] = value self._dirty.add(name) def _generate_var_strings(self, fill=True) -> None: stream = bytearray() dynpos = self._PROPERTIES[self.device_version].dynoff data_pos = dynpos tbl_pos = 0x0e for name in self.VAR_STRINGS: try: ustr = self._config[name].encode('utf-16le') except KeyError: ustr = '' length = len(ustr)+2 stream.append(length) stream.append(0x03) # string descriptor stream.extend(ustr) self._eeprom[tbl_pos] = data_pos tbl_pos += 1 self._eeprom[tbl_pos] = length tbl_pos += 1 data_pos += length self._eeprom[dynpos:dynpos+len(stream)] = stream crc_size = scalc('<H') if fill: mtp = self._ftdi.device_version == 0x1000 crc_pos = 0x100 if mtp else len(self._eeprom) crc_pos -= crc_size rem = len(self._eeprom) - (dynpos + len(stream)) - crc_size self._eeprom[dynpos+len(stream):crc_pos] = bytes(rem) def _sync_eeprom(self): if not self._dirty: return if any([x in self._dirty for x in self.VAR_STRINGS]): self._generate_var_strings() for varstr in self.VAR_STRINGS: self._dirty.discard(varstr) self._update_crc() self._decode_eeprom() self._dirty.clear() def _compute_crc(self, check=False): mtp = self._ftdi.device_version == 0x1000 crc_pos = 0x100 if mtp else len(self._eeprom) crc_size = scalc('<H') if not check: # check mode: add CRC itself, so that result should be zero crc_pos -= crc_size crc = self._ftdi.calc_eeprom_checksum(self._eeprom[:crc_pos]) return crc, crc_pos, crc_size def _update_crc(self): crc, crc_pos, crc_size = self._compute_crc() self._eeprom[crc_pos:crc_pos+crc_size] = spack('<H', crc) def _read_eeprom(self): buf = self._ftdi.read_eeprom(0, eeprom_size=self.size) self._eeprom = bytearray(buf) crc = self._compute_crc(True)[0] if crc: if self.is_empty: self.log.info('No EEPROM or EEPROM erased') else: self.log.error('Invalid CRC or EEPROM content') self._valid = not bool(crc) def _decode_eeprom(self): cfg = self._config cfg.clear() cfg['vendor_id'] = Hex4Int(sunpack('<H', self._eeprom[0x02:0x04])[0]) cfg['product_id'] = Hex4Int(sunpack('<H', self._eeprom[0x04:0x06])[0]) cfg['type'] = Hex4Int(sunpack('<H', self._eeprom[0x06:0x08])[0]) power_supply, power_max, conf = sunpack('<3B', self._eeprom[0x08:0x0b]) cfg['self_powered'] = bool(power_supply & (1 << 6)) cfg['remote_wakeup'] = bool(power_supply & (1 << 5)) cfg['power_max'] = power_max << 1 cfg['has_usb_version'] = bool(conf & (1 << 4)) cfg['has_serial'] = bool(conf & (1 << 3)) cfg['suspend_pull_down'] = bool(conf & (1 << 2)) cfg['out_isochronous'] = bool(conf & (1 << 1)) cfg['in_isochronous'] = bool(conf & (1 << 0)) cfg['usb_version'] = Hex4Int(sunpack('<H', self._eeprom[0x0c:0x0e])[0]) cfg['manufacturer'] = self._decode_string(0x0e) cfg['product'] = self._decode_string(0x10) cfg['serial'] = self._decode_string(0x12) try: name = Ftdi.DEVICE_NAMES[cfg['type']] func = getattr(self, '_decode_%s' % name[2:]) except (KeyError, AttributeError): pass else: func() def _decode_string(self, offset): str_offset, str_size = sunpack('<BB', self._eeprom[offset:offset+2]) if str_size: str_offset &= self.size - 1 str_size -= scalc('<H') str_offset += scalc('<H') manufacturer = self._eeprom[str_offset:str_offset+str_size] return manufacturer.decode('utf16', errors='ignore') return '' def _set_cbus_func(self, cpin: int, value: str, out: Optional[TextIO]) -> None: cmap = {0x600: (self.CBUS, 5, 0x14, 4), # FT232R 0x900: (self.CBUSH, 10, 0x18, 4), # FT232H 0x1000: (self.CBUSX, 4, 0x1A, 8)} # FT230X/FT231X/FT234X try: cbus, count, offset, width = cmap[self.device_version] except KeyError: raise ValueError('This property is not supported on this device') if value == '?' and out: print(', '.join(sorted([item.name for item in cbus])), file=out) return if not 0 <= cpin < count: raise ValueError("Unsupported CBUS pin '%d'" % cpin) try: code = cbus[value.upper()] except KeyError: raise ValueError("CBUS pin %d does not have function '%s'" % (cpin, value)) addr = offset + (cpin*width)//8 if width == 4: bitoff = 4 if cpin & 0x1 else 0 mask = 0x0F << bitoff else: bitoff = 0 mask = 0xFF old = self._eeprom[addr] self._eeprom[addr] &= ~mask self._eeprom[addr] |= code << bitoff self.log.debug('Cpin %d, addr 0x%02x, value 0x%02x->0x%02x', cpin, addr, old, self._eeprom[addr]) def _decode_230x(self): cfg = self._config misc, = sunpack('<H', self._eeprom[0x00:0x02]) cfg['channel_a_driver'] = 'VCP' if misc & (1 << 7) else 'D2XX' for bit in self.INVERT: value = self._eeprom[0x0B] cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit) max_drive = self.DRIVE.LOW | self.DRIVE.HIGH value = self._eeprom[0x0c] for grp in range(2): conf = value &0xF cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive) cfg['group_%d_schmitt' % grp] = conf & self.DRIVE.SCHMITT cfg['group_%d_slew' % grp] = conf & self.DRIVE.SLOW_SLEW value >>= 4 for bix in range(4): value = self._eeprom[0x1A + bix] cfg['cbus_func_%d' % bix] = self.CBUSX(value).name cfg['chip'] = Hex2Int(self._eeprom[0x1E]) def _decode_232h(self): cfg = self._config cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_type'] = cfg0 & 0x0F cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 4)) else 'D2XX' cfg['clock_polarity'] = 'high' if (cfg1 & self.CFG1.CLK_IDLE_STATE) \ else 'low' cfg['lsb_data'] = bool(cfg1 & self.CFG1.DATA_LSB) cfg['flow_control'] = 'on' if (cfg1 & self.CFG1.FLOW_CONTROL) \ else 'off' cfg['powersave'] = bool(cfg1 & self.DRIVE.PWRSAVE_DIS) max_drive = self.DRIVE.LOW | self.DRIVE.HIGH for grp in range(2): conf = self._eeprom[0x0c+grp] cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive) cfg['group_%d_schmitt' % grp] = conf & self.DRIVE.SCHMITT cfg['group_%d_slew' % grp] = conf & self.DRIVE.SLOW_SLEW for bix in range(5): value = self._eeprom[0x18 + bix] low, high = value & 0x0F, value >> 4 cfg['cbus_func_%d' % ((2*bix)+0)] = self.CBUSH(low).name cfg['cbus_func_%d' % ((2*bix)+1)] = self.CBUSH(high).name cfg['chip'] = Hex2Int(self._eeprom[0x1E]) def _decode_232r(self): cfg = self._config cfg0 = self._eeprom[0x00] cfg['channel_a_driver'] = 'VCP' if (~cfg0 & (1 << 3)) else '' cfg['high_current'] = bool(~cfg0 & (1 << 2)) cfg['external_oscillator'] = cfg0 & 0x02 for bit in self.INVERT: value = self._eeprom[0x0B] cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit) bix = 0 while True: value = self._eeprom[0x14 + bix] low, high = value & 0x0F, value >> 4 cfg['cbus_func_%d' % ((2*bix)+0)] = self.CBUS(low).name if bix == 2: break cfg['cbus_func_%d' % ((2*bix)+1)] = self.CBUS(high).name bix += 1 def _decode_2232h(self): cfg = self._config self._decode_x232h(cfg) cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_type'] = self.CHANNEL(cfg0 & 0x7).name or 'UART' cfg['channel_b_type'] = self.CHANNEL(cfg1 & 0x7).name or 'UART' cfg['suspend_dbus7'] = cfg1 & self.CFG1.SUSPEND_DBUS7 def _decode_4232h(self): cfg = self._config self._decode_x232h(cfg) cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_c_driver'] = 'VCP' if ((cfg0 >> 4) & (1 << 3)) else 'D2XX' cfg['channel_d_driver'] = 'VCP' if ((cfg1 >> 4) & (1 << 3)) else 'D2XX' conf = self._eeprom[0x0B] rs485 = self.CHANNEL.RS485 for chix in range(4): cfg['channel_%x_rs485' % (0xa+chix)] = bool(conf & (rs485 << chix)) def _decode_x232h(self, cfg): # common code for2232h and 4232h cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 3)) else 'D2XX' cfg['channel_b_driver'] = 'VCP' if (cfg1 & (1 << 3)) else 'D2XX' max_drive = self.DRIVE.LOW | self.DRIVE.HIGH for bix in range(4): if not bix & 1: val = self._eeprom[0x0c + bix//2] else: val >>= 4 cfg['group_%d_drive' % bix] = bool(val & max_drive) cfg['group_%d_schmitt' % bix] = bool(val & self.DRIVE.SCHMITT) cfg['group_%d_slew' % bix] = bool(val & self.DRIVE.SLOW_SLEW) cfg['chip'] = Hex2Int(self._eeprom[0x18])
] __all__.extend(os._get_exports_list(_socket)) # Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for # nicer string representations. # Note that _socket only knows about the integer values. The public interface # in this module understands the enums and translates them back from integers # where needed (e.g. .family property of a socket object). IntEnum._convert_("AddressFamily", __name__, lambda C: C.isupper() and C.startswith("AF_")) IntEnum._convert_("SocketKind", __name__, lambda C: C.isupper() and C.startswith("SOCK_")) IntFlag._convert_("MsgFlag", __name__, lambda C: C.isupper() and C.startswith("MSG_")) IntFlag._convert_("AddressInfo", __name__, lambda C: C.isupper() and C.startswith("AI_")) _LOCALHOST = "127.0.0.1" _LOCALHOST_V6 = "::1" def _intenum_converter(value, enum_klass): """Convert a numeric family value to an IntEnum member. If it's not a known member, return the numeric value itself. """ try: return enum_klass(value)
import attr from collections import namedtuple from enum import IntFlag import numpy as np # type: ignore np.set_printoptions(suppress=True) from colorama import Fore JointType = IntFlag('JointType', 'revolute prismatic revolute_theda revolute_alpha') mdh_params = namedtuple("mdh_params", "alpha a theta d ") from math import pi rad2deg = 180 / pi deg2rad = pi / 180 @attr.s(slots=True) class RevoluteLink: """ RevoluteLink about theta. All other parameters (alpha, a, d) are fixed and cannot be changed once the link is created. """ _alpha = attr.ib() _a = attr.ib() theta = attr.ib() _d = attr.ib() min = attr.ib(default=-np.pi / 2) max = attr.ib(default=np.pi / 2) @max.validator def max_check(self, attribute, value):
def __new__(metacls, name, bases, d): flags = [(i.name, i.value) for i in AmpelFlags] for k, v in d.items(): if not k.endswith('__'): flags.append((k, v)) return IntFlag(name, flags, module=d['__module__'])
from enum import IntFlag from itertools import chain from msdsalgs.security_types.access_mask import AccessMask from msdsalgs.utils import Mask # TODO: Add standard user rights? class RegsamFlag(IntFlag): KEY_QUERY_VALUE = 0x00000001 KEY_SET_VALUE = 0x00000002 KEY_CREATE_SUB_KEY = 0x00000004 KEY_ENUMERATE_SUB_KEYS = 0x00000008 KEY_CREATE_LINK = 0x00000020 KEY_WOW64_64KEY = 0x00000100 KEY_WOW64_32KEY = 0x00000200 Regsam = Mask.make_class(int_flag_class=IntFlag('Regsam', ( (enum_entry.name, enum_entry.value) for enum_entry in chain(AccessMask, RegsamFlag))))
def __str__(self): """Provides just the name representation of enum.""" return IntFlag.__str__(self)[len(self.__class__.__name__) + 1:]
class FtdiEeprom: """FTDI EEPROM management """ _PROPS = namedtuple('PROPS', 'size user dynoff') """Properties for each FTDI device release.""" _PROPERTIES = { 0x0200: _PROPS(0, None, 0x94), # FT232AM 0x0400: _PROPS(256, 0x14, 0x94), # FT232BM 0x0500: _PROPS(256, 0x16, 0x96), # FT2232D 0x0600: _PROPS(128, None, 0x98), # FT232R 0x0700: _PROPS(256, 0x1A, 0x9A), # FT2232H 0x0800: _PROPS(256, 0x1A, 0x9A), # FT4232H 0x0900: _PROPS(256, 0x1A, 0xA0), # FT232H 0x1000: _PROPS(256, 0x1A, 0xA0), # FT230X } """EEPROM properties.""" _CBUS = IntEnum('CBUS', 'TXDEN PWREN RXLED TXLED TXRXLED SLEEP CLK48 CLK24 CLK12 ' 'CLK6 IOMODE BB_WR BB_R', start=0) """Alternate features for legacy FT232R devices.""" _CBUSH = IntEnum('CBUSH', 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 ' 'IOMODE TXDEN CLK30 CLK15 CLK7_5', start=0) """Alternate features for FT232H/FT2232H/FT4232H devices.""" _CBUSX = IntEnum('CBUSX', 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 ' 'IOMODE TXDEN CLK24 CLK12 CLK6 BAT_DETECT BAT_DETECT_NEG ' 'I2C_TXE I2C_RXF VBUS_SENSE BB_WR BB_RD TIME_STAMP AWAKE', start=0) """Alternate features for FT230X devices.""" _INVERT = IntFlag('INVERT', 'TXD RXD RTS CTS DTR DSR DCD RI') """Inversion flags for FT232R devices.""" _CHANNEL = IntFlag('CHANNEL', 'FIFO OPTO CPU FT128 RS485') """Alternate port mode.""" _DRIVE = IntEnum('DRIVE', 'LOW HIGH SLOW_SLEW SCHMITT _10 _20 _40 PWRSAVE_DIS') """Driver options for I/O pins.""" _CFG1 = IntFlag( 'CFG1', 'CLK_IDLE_STATE DATA_LSB FLOW_CONTROL _08 ' 'HIGH_CURRENT_DRIVE _20 _40 SUSPEND_DBUS7') """Configuration bits stored @ 0x01.""" VAR_STRINGS = ('manufacturer', 'product', 'serial') """EEPROM strings with variable length.""" def __init__(self): self.log = getLogger('pyftdi.eeprom') self._ftdi = Ftdi() self._eeprom = bytearray() self._dev_ver = 0 self._valid = False self._config = OrderedDict() self._dirty = set() def __getattr__(self, name): if name in self._config: return self._config[name] raise AttributeError('No such attribute: %s' % name) def open(self, device: Union[str, UsbDevice]) -> None: """Open a new connection to the FTDI USB device. :param device: the device URL or a USB device instance. """ if self._ftdi.is_connected: raise FtdiError('Already open') if isinstance(device, str): self._ftdi.open_from_url(device) else: self._ftdi.open_from_device(device) self._read_eeprom() if self._valid: self._decode_eeprom() def close(self) -> None: """Close the current connection to the FTDI USB device, """ if self._ftdi.is_connected: self._ftdi.close() self._eeprom = bytearray() self._dev_ver = 0 self._config.clear() @property def device_version(self) -> int: """Report the version of the FTDI device. :return: the release """ if not self._dev_ver: if not self._ftdi.is_connected: raise FtdiError('Not connected') self._dev_ver = self._ftdi.device_version return self._dev_ver @property def size(self) -> int: """Report the EEPROM size. The physical EEPROM size may be greater. :return: the size in bytes """ try: eeprom_size = self._PROPERTIES[self.device_version].size except (AttributeError, KeyError): raise FtdiError('No EEPROM') return eeprom_size @property def data(self) -> bytes: """Returns the content of the EEPROM. :return: the content as bytes. """ return bytes(self._eeprom) @property def is_empty(self) -> bool: """Reports whether the EEPROM has been erased, or no EEPROM is connected to the FTDI EEPROM port. :return: True if no content is detected """ if len(self._eeprom) != self._PROPERTIES[self.device_version].size: return False for byte in self._eeprom: if byte != 0xFF: return False return True def save_config(self, file: TextIO) -> None: """Save the EEPROM content as an INI stream. :param file: output stream """ cfg = ConfigParser() cfg.add_section('values') for name, value in self._config.items(): cfg.set('values', name, str(value)) cfg.add_section('raw') length = 16 for i in range(0, len(self._eeprom), length): chunk = self._eeprom[i:i + length] hexa = hexlify(chunk).decode() cfg.set('raw', '@%02x' % i, hexa) cfg.write(file) def set_serial_number(self, serial: str) -> None: """Define a new serial number.""" self._update_var_string('serial', serial) def set_manufacturer_name(self, manufacturer: str) -> None: """Define a new manufacturer string.""" self._update_var_string('manufacturer', manufacturer) def set_product_name(self, product: str) -> None: """Define a new product name.""" self._update_var_string('product', product) def erase(self) -> None: """Erase the whole EEPROM.""" self._eeprom = bytearray([0xFF] * self.size) self._config.clear() def dump_config(self, file: Optional[BinaryIO] = None) -> None: """Dump the configuration to a file. :param file: the output file, default to stdout """ for name, value in self._config.items(): print('%s: %s' % (name, value), file=file or stdout) def commit(self, dry_run: bool = True) -> bool: """Commit any changes to the EEPROM. :param dry_run: log what should be written, do not actually change the EEPROM content :return: True if some changes have been committed to the EEPROM """ if not self._dirty: self.log.info('No change to commit') return False self.log.info('Changes to commit: %s', ', '.join(sorted(self._dirty))) if any([x in self._dirty for x in self.VAR_STRINGS]): self._generate_var_strings() self._ftdi.overwrite_eeprom(self._eeprom, dry_run=dry_run) return dry_run def _update_var_string(self, name: str, value: str) -> None: if name not in self.VAR_STRINGS: raise ValueError('%s is not a variable string' % name) if value == self._config[name]: return self._config[name] = value self._dirty.add(name) def _generate_var_strings(self, fill=True) -> None: stream = bytearray() dynpos = self._PROPERTIES[self.device_version].dynoff data_pos = dynpos tbl_pos = 0x0e for name in self.VAR_STRINGS: ustr = self._config[name].encode('utf-16le') length = len(ustr) + 2 stream.append(length) stream.append(0x03) # no idea what this constant means stream.extend(ustr) self._eeprom[tbl_pos] = data_pos tbl_pos += 1 self._eeprom[tbl_pos] = length tbl_pos += 1 data_pos += length self._eeprom[dynpos:dynpos + len(stream)] = stream crc_size = scalc('<H') if fill: rem = len(self._eeprom) - (dynpos + len(stream)) - crc_size self._eeprom[dynpos + len(stream):-crc_size] = bytes(rem) crc = self._ftdi.calc_eeprom_checksum(self._eeprom[:-crc_size]) self._eeprom[-crc_size:] = spack('<H', crc) def _read_eeprom(self): self._eeprom = bytearray( self._ftdi.read_eeprom(0, eeprom_size=self.size)) crc = self._ftdi.calc_eeprom_checksum(self._eeprom) if crc: if self.is_empty: self.log.info('No EEPROM or EEPROM erased') else: self.log.error('Invalid CRC or EEPROM content') self._valid = not bool(crc) def _decode_eeprom(self): cfg = self._config cfg.clear() cfg['vendor_id'] = Hex4Int(sunpack('<H', self._eeprom[0x02:0x04])[0]) cfg['product_id'] = Hex4Int(sunpack('<H', self._eeprom[0x04:0x06])[0]) cfg['type'] = Hex4Int(sunpack('<H', self._eeprom[0x06:0x08])[0]) power_supply, power_max, conf = sunpack('<3B', self._eeprom[0x08:0x0b]) cfg['self_powered'] = bool(power_supply & (1 << 6)) cfg['remote_wakeup'] = bool(power_supply & (1 << 5)) cfg['power_max'] = power_max << 1 cfg['has_usb_version'] = bool(conf & (1 << 4)) cfg['has_serial'] = bool(conf & (1 << 3)) cfg['suspend_pull_down'] = bool(conf & (1 << 2)) cfg['out_isochronous'] = bool(conf & (1 << 1)) cfg['in_isochronous'] = bool(conf & (1 << 0)) cfg['usb_version'] = Hex4Int(sunpack('<H', self._eeprom[0x0c:0x0e])[0]) cfg['manufacturer'] = self._decode_string(0x0e) cfg['product'] = self._decode_string(0x10) cfg['serial'] = self._decode_string(0x12) try: name = Ftdi.DEVICE_NAMES[cfg['type']] func = getattr(self, '_decode_%s' % name[2:]) except (KeyError, AttributeError): pass else: func() def _decode_string(self, offset): str_offset, str_size = sunpack('<BB', self._eeprom[offset:offset + 2]) if str_size: str_offset &= self.size - 1 str_size -= scalc('<H') str_offset += scalc('<H') manufacturer = self._eeprom[str_offset:str_offset + str_size] return manufacturer.decode('utf16', errors='ignore') return '' def _decode_230x(self): cfg = self._config cfg['channel_a_driver'] = 'VCP' for bit in self.INVERT: value = self._eeprom[0x0B] cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit) max_drive = self._DRIVE.LOW | self._DRIVE.HIGH value = self._eeprom[0x0c] for grp in range(2): conf = value & 0xF cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive) cfg['group_%d_schmitt' % grp] = conf & self._DRIVE.SCHMITT cfg['group_%d_slew' % grp] = conf & self._DRIVE.SLOW_SLEW value >>= 4 for bix in range(4): value = self._eeprom[0x1A + bix] cfg['cbus_func_%d' % bix] = self._CBUSX(value).name cfg['chip'] = Hex2Int(self._eeprom[0x1E]) def _decode_232h(self): cfg = self._config cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_type'] = cfg0 & 0x0F cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 4)) else '' cfg['clock_polarity'] = 'high' if (cfg1 & self._CFG1.CLK_IDLE_STATE) \ else 'low' cfg['lsb_data'] = bool(cfg1 & self._CFG1.DATA_LSB) cfg['flow_control'] = 'on' if (cfg1 & self._CFG1.FLOW_CONTROL) \ else 'off' cfg['powersave'] = bool(cfg1 & self._DRIVE.PWRSAVE_DIS) max_drive = self._DRIVE.LOW | self._DRIVE.HIGH for grp in range(2): conf = self._eeprom[0x0c + grp] cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive) cfg['group_%d_schmitt' % grp] = conf & self._DRIVE.SCHMITT cfg['group_%d_slew' % grp] = conf & self._DRIVE.SLOW_SLEW for bix in range(5): value = self._eeprom[0x18 + bix] low, high = value & 0x0F, value >> 4 cfg['cbus_func_%d' % ((2 * bix) + 0)] = self._CBUSH(low).name cfg['cbus_func_%d' % ((2 * bix) + 1)] = self._CBUSH(high).name cfg['chip'] = Hex2Int(self._eeprom[0x1E]) def _decode_232r(self): cfg = self._config cfg0 = self._eeprom[0x00] cfg['channel_a_driver'] = 'VCP' if (~cfg0 & (1 << 3)) else '' cfg['high_current'] = bool(~cfg0 & (1 << 2)) cfg['external_oscillator'] = cfg0 & 0x02 for bit in self.INVERT: value = self._eeprom[0x0B] cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit) bix = 0 while True: value = self._eeprom[0x14 + bix] low, high = value & 0x0F, value >> 4 cfg['cbus_func_%d' % ((2 * bix) + 0)] = self._CBUS(low).name if bix == 2: break cfg['cbus_func_%d' % ((2 * bix) + 1)] = self._CBUS(high).name bix += 1 def _decode_2232h(self): cfg = self._config self._decode_x232h(cfg) cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_type'] = self._CHANNEL(cfg0 & 0x7).name or 'UART' cfg['channel_b_type'] = self._CHANNEL(cfg1 & 0x7).name or 'UART' cfg['suspend_dbus7'] = cfg1 & self._CFG1.SUSPEND_DBUS7 def _decode_4232h(self): cfg = self._config self._decode_x232h(cfg) cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_c_driver'] = 'VCP' if ((cfg0 >> 4) & (1 << 3)) else '' cfg['channel_d_driver'] = 'VCP' if ((cfg1 >> 4) & (1 << 3)) else '' conf = self._eeprom[0x0B] rs485 = self._CHANNEL.RS485 for chix in range(4): cfg['channel_%x_rs485' % (0xa + chix)] = bool(conf & (rs485 << chix)) def _decode_x232h(self, cfg): # common code for2232h and 4232h cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 3)) else '' cfg['channel_b_driver'] = 'VCP' if (cfg1 & (1 << 3)) else '' max_drive = self._DRIVE.LOW | self._DRIVE.HIGH for bix in range(4): if not bix & 1: val = self._eeprom[0x0c + bix // 2] else: val >>= 4 cfg['group_%d_drive' % bix] = bool(val & max_drive) cfg['group_%d_schmitt' % bix] = bool(val & self._DRIVE.SCHMITT) cfg['group_%d_slew' % bix] = bool(val & self._DRIVE.SLOW_SLEW) cfg['chip'] = Hex2Int(self._eeprom[0x18])
if TYPE_CHECKING: from utils.rpg.dungeon.game import Dungeon, Movement Condition = IntFlag( "Condition", [ "BLINDED", "DEAFENED", "GRAPPLED", "INCAPACITATED", "INVISIBLE", "PARALYZED", "PETRIFIED", "POISONED", "PRONE", "RESTRAINED", "STUNNED", "UNCONSCIOUS", "DEAD", "EXHAUSTED_1", "EXHAUSTED_2", "EXHAUSTED_3", "EXHAUSTED_4", "EXHAUSTED_5", ], ) Relation = Enum("Relation", ["CHARMED", "FRIGHTENED"]) IMMOBILE = (Condition.GRAPPLED
import itertools from collections import deque from enum import IntFlag from random import randint import numpy as np Dir = IntFlag("Dir", ["N", "S", "W", "E"]) DirAll = Dir.N | Dir.S | Dir.W | Dir.E class Maze: def __init__(self, width, height): self.new_maze(width, height) # {'┌', '╴', '┤', '│', '┐', '╷', '╵', '┬', '└', '╶', '├', '┼', ' ', '┘', '─', '┴'} def __str__(self): def vert_str(row): return f"+{'+'.join('--' if x else ' ' for x in row)}+" def horz_str(row): return f"{' '.join('|' if x else ' ' for x in row)}" vert_rows = [vert_str(row & Dir.N) for row in self.maze] + [ vert_str(self.maze[-1] & Dir.S) ] horz_rows = [ horz_str(itertools.chain(row & Dir.W, [row[-1] & Dir.E])) for row in self.maze ]
############################################## # The MIT License (MIT) # Copyright (c) 2018 Kevin Walchko # see LICENSE for full details ############################################## # These are IntFlags, so you can compare them to ints. They # start with 1 and go to N. # ZmqType.pub == 1 # ZmqType.sub == 2 # from enum import IntFlag Status = IntFlag( 'Status', 'ok error topic_not_found core_not_found multiple_pub_error invalid_zmq_type' ) ZmqType = IntFlag('ZmqType', 'pub sub req rep')
EWOULDBLOCK = getattr(errno, "EWOULDBLOCK", 11) __all__ = ["fromfd", "getfqdn", "create_connection", "AddressFamily", "SocketKind"] __all__.extend(os._get_exports_list(_socket)) # Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for # nicer string representations. # Note that _socket only knows about the integer values. The public interface # in this module understands the enums and translates them back from integers # where needed (e.g. .family property of a socket object). IntEnum._convert("AddressFamily", __name__, lambda C: C.isupper() and C.startswith("AF_")) IntEnum._convert("SocketKind", __name__, lambda C: C.isupper() and C.startswith("SOCK_")) IntFlag._convert("MsgFlag", __name__, lambda C: C.isupper() and C.startswith("MSG_")) IntFlag._convert("AddressInfo", __name__, lambda C: C.isupper() and C.startswith("AI_")) _LOCALHOST = "127.0.0.1" _LOCALHOST_V6 = "::1" def _intenum_converter(value, enum_klass): """Convert a numeric family value to an IntEnum member. If it's not a known member, return the numeric value itself. """ try: return enum_klass(value) except ValueError:
# Note that _socket only knows about the integer values. The public interface # in this module understands the enums and translates them back from integers # where needed (e.g. .family property of a socket object). IntEnum._convert( 'AddressFamily', __name__, lambda C: C.isupper() and C.startswith('AF_')) IntEnum._convert( 'SocketKind', __name__, lambda C: C.isupper() and C.startswith('SOCK_')) IntFlag._convert( 'MsgFlag', __name__, lambda C: C.isupper() and C.startswith('MSG_')) IntFlag._convert( 'AddressInfo', __name__, lambda C: C.isupper() and C.startswith('AI_')) _LOCALHOST = '127.0.0.1' _LOCALHOST_V6 = '::1' def _intenum_converter(value, enum_klass): """Convert a numeric family value to an IntEnum member. If it's not a known member, return the numeric value itself.
class FtdiEeprom: """FTDI EEPROM management """ _PROPS = namedtuple('PROPS', 'size user dynoff') """Properties for each FTDI device release. * size is the size in bytes of the EEPROM storage area * user is the size in bytes of the user storage area, if any/supported * dynoff is the offset in EEPROM of the first bytes to store strings """ _PROPERTIES = { 0x0200: _PROPS(0, None, 0), # FT232AM 0x0400: _PROPS(256, 0x14, 0x94), # FT232BM 0x0500: _PROPS(256, 0x16, 0x96), # FT2232D 0x0600: _PROPS(128, None, 0x18), # FT232R 0x0700: _PROPS(256, 0x1A, 0x9A), # FT2232H 0x0800: _PROPS(256, 0x1A, 0x9A), # FT4232H 0x0900: _PROPS(256, 0x1A, 0xA0), # FT232H 0x1000: _PROPS(1024, 0x1A, 0xA0), # FT230X/FT231X/FT234X } """EEPROM properties.""" CBUS = IntEnum('CBus', 'TXDEN PWREN TXLED RXLED TXRXLED SLEEP CLK48 CLK24 CLK12 ' 'CLK6 GPIO BB_WR BB_RD', start=0) """Alternate features for legacy FT232R devices.""" CBUSH = IntEnum('CBusH', 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 ' 'GPIO TXDEN CLK30 CLK15 CLK7_5', start=0) """Alternate features for FT232H/FT2232H/FT4232H devices.""" CBUSX = IntEnum('CBusX', 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 ' 'GPIO TXDEN CLK24 CLK12 CLK6 BAT_DETECT BAT_NDETECT ' 'I2C_TXE I2C_RXF VBUS_SENSE BB_WR BB_RD TIMESTAMP AWAKE', start=0) """Alternate features for FT230X devices.""" UART_BITS = IntFlag('UartBits', 'TXD RXD RTS CTS DTR DSR DCD RI') """Inversion flags for FT232R and FT-X devices.""" CHANNEL = IntFlag('Channel', 'FIFO OPTO CPU FT128 RS485') """Alternate port mode.""" DRIVE = IntFlag('Drive', 'LOW HIGH SLOW_SLEW SCHMITT _10 _20 _40 PWRSAVE_DIS') """Driver options for I/O pins.""" CFG1 = IntFlag( 'Cfg1', 'CLK_IDLE_STATE DATA_LSB FLOW_CONTROL _08 ' 'HIGH_CURRENTDRIVE _20 _40 SUSPEND_DBUS7') """Configuration bits stored @ 0x01.""" VAR_STRINGS = ('manufacturer', 'product', 'serial') """EEPROM strings with variable length.""" def __init__(self): self.log = getLogger('pyftdi.eeprom') self._ftdi = Ftdi() self._eeprom = bytearray() self._dev_ver = 0 self._valid = False self._config = OrderedDict() self._dirty = set() self._modified = False def __getattr__(self, name): if name in self._config: return self._config[name] raise AttributeError('No such attribute: %s' % name) def open(self, device: Union[str, UsbDevice], ignore: bool = False) -> None: """Open a new connection to the FTDI USB device. :param device: the device URL or a USB device instance. :param ignore: whether to ignore existing content """ if self._ftdi.is_connected: raise FtdiError('Already open') if isinstance(device, str): self._ftdi.open_from_url(device) else: self._ftdi.open_from_device(device) if not ignore: self._eeprom = self._read_eeprom() if self._valid: self._decode_eeprom() def close(self) -> None: """Close the current connection to the FTDI USB device, """ if self._ftdi.is_connected: self._ftdi.close() self._eeprom = bytearray() self._dev_ver = 0 self._config.clear() def connect(self, ftdi: Ftdi, ignore: bool = False) -> None: """Connect a FTDI EEPROM to an existing Ftdi instance. :param ftdi: the Ftdi instance to use :param ignore: whether to ignore existing content """ self._ftdi = ftdi self._eeprom = bytearray() self._dev_ver = 0 self._valid = False self._config = OrderedDict() self._dirty = set() if not ignore: self._eeprom = self._read_eeprom() if self._valid: self._decode_eeprom() self._decode_eeprom() @property def device_version(self) -> int: """Report the version of the FTDI device. :return: the release """ if not self._dev_ver: if not self._ftdi.is_connected: raise FtdiError('Not connected') self._dev_ver = self._ftdi.device_version return self._dev_ver @property def size(self) -> int: """Report the EEPROM size. The physical EEPROM size may be greater. :return: the size in bytes """ try: eeprom_size = self._PROPERTIES[self.device_version].size except (AttributeError, KeyError): raise FtdiError('No EEPROM') return eeprom_size @property def data(self) -> bytes: """Returns the content of the EEPROM. :return: the content as bytes. """ self._sync_eeprom() return bytes(self._eeprom) @property def properties(self) -> Set[str]: """Returns the supported properties for the current device. :return: the supported properies. """ props = set(self._config.keys()) props -= set(self.VAR_STRINGS) return props @property def is_empty(self) -> bool: """Reports whether the EEPROM has been erased, or no EEPROM is connected to the FTDI EEPROM port. :return: True if no content is detected """ if len(self._eeprom) != self._PROPERTIES[self.device_version].size: return False for byte in self._eeprom: if byte != 0xFF: return False return True @property def cbus_pins(self) -> List[int]: """Return the list of CBUS pins configured as GPIO, if any :return: list of CBUS pins """ pins = [ pin for pin in range(0, 10) if self._config.get('cbus_func_%d' % pin, '') == 'GPIO' ] return pins @property def cbus_mask(self) -> int: """Return the bitmask of CBUS pins configured as GPIO. The bitmap contains four bits, ordered in natural order. :return: CBUS mask """ if self.device_version == 0x900: # FT232H cbus = [5, 6, 8, 9] else: cbus = list(range(4)) mask = 0 for bix, pin in enumerate(cbus): if self._config.get('cbus_func_%d' % pin, '') == 'GPIO': mask |= 1 << bix return mask def save_config(self, file: TextIO) -> None: """Save the EEPROM content as an INI stream. :param file: output stream """ self._sync_eeprom() cfg = ConfigParser() cfg.add_section('values') for name, value in self._config.items(): cfg.set('values', name, str(value)) cfg.add_section('raw') length = 16 for i in range(0, len(self._eeprom), length): chunk = self._eeprom[i:i + length] hexa = hexlify(chunk).decode() cfg.set('raw', '@%02x' % i, hexa) cfg.write(file) def load_config(self, file: TextIO, section: Optional[str] = None) -> None: """Load the EEPROM content from an INI stream. The ``section`` argument selects which section(s) to load: * ``raw`` only loads the raw data (hexabytes) from a previous dump * ``values`` only loads the values section, that is the human readable configuration. * ``all``, which is the default section selection, load the raw section, then overwrite part of it with any configuration value from the ``values`` section. This provides a handy way to use an existing dump from a valid EEPROM content, while customizing some parameters, such as the serial number. :param file: input stream :paran section: which section to load from the ini file """ self._sync_eeprom() cfg = ConfigParser() cfg.read_file(file) loaded = False sect = 'raw' if section in (None, 'all', sect, ''): if not cfg.has_section(sect): raise FtdiEepromError("No '%s' section in INI file" % sect) options = cfg.options(sect) try: for opt in options: if not opt.startswith('@'): raise ValueError() address = int(opt[1:], 16) hexval = cfg.get(sect, opt).strip() buf = unhexlify(hexval) self._eeprom[address:address + len(buf)] = buf except IndexError: raise ValueError("Invalid address in '%s'' section" % sect) except ValueError: raise ValueError("Invalid line in '%s'' section" % sect) self._compute_crc(self._eeprom, True) if not self._valid: raise ValueError('Loaded RAW section is invalid (CRC mismatch') loaded = True sect = 'values' vmap = { 'manufacturer': 'manufacturer_name', 'product': 'product_name', 'serial': 'serial_number' } if section in (None, 'all', sect, ''): if not cfg.has_section(sect): raise FtdiEepromError("No '%s' section in INI file" % sect) options = cfg.options(sect) for opt in options: value = cfg.get(sect, opt).strip() if opt in vmap: func = getattr(self, 'set_%s' % vmap[opt]) func(value) else: try: self.set_property(opt, value) except ValueError: self.log.warning( "Ignoring setting '%s': " "not implemented", opt) loaded = True if not loaded: raise ValueError('Invalid section: %s' % section) self._sync_eeprom() def set_serial_number(self, serial: str) -> None: """Define a new serial number.""" self._validate_string(serial) self._update_var_string('serial', serial) self.set_property('has_serial', True) def set_manufacturer_name(self, manufacturer: str) -> None: """Define a new manufacturer string.""" self._validate_string(manufacturer) self._update_var_string('manufacturer', manufacturer) def set_product_name(self, product: str) -> None: """Define a new product name.""" self._validate_string(product) self._update_var_string('product', product) def set_property(self, name: str, value: Union[str, int, bool], out: Optional[TextIO] = None) -> None: """Change the value of a stored property. :see: :py:meth:`properties` for a list of valid property names. Note that for now, only a small subset of properties can be changed. :param name: the property to change :param value: the new value (supported values depend on property) :param out: optional output stream to report hints """ mobj = match(r'cbus_func_(\d)', name) if mobj: if not isinstance(value, str): raise ValueError("'%s' should be specified as a string" % name) self._set_cbus_func(int(mobj.group(1)), value, out) self._dirty.add(name) return mobj = match(r'([abcd])bus_(drive|slow_slew|schmitt)', name) if mobj: self._set_bus_control(mobj.group(1), mobj.group(2), value, out) self._dirty.add(name) return hwords = { 'vendor_id': 0x02, 'product_id': 0x04, 'type': 0x06, 'usb_version': 0x0c } if name in hwords: val = to_int(value) if not 0 <= val <= 0xFFFF: raise ValueError('Invalid value for %s' % name) offset = hwords[name] self._eeprom[offset:offset + 2] = spack('<H', val) return confs = { 'remote_wakeup': (0, 5), 'self_powered': (0, 6), 'in_isochronous': (2, 0), 'out_isochronous': (2, 1), 'suspend_pull_down': (2, 2), 'has_serial': (2, 3), } if name in confs: val = to_bool(value, permissive=False, allow_int=True) offset, bit = confs[name] mask = 1 << bit if val: self._eeprom[0x08 + offset] |= mask else: self._eeprom[0x0a + offset] &= ~mask return if name == 'power_max': val = to_int(value) >> 1 self._eeprom[0x09] = val return if name.startswith('invert_'): if not self.device_version in (0x600, 0x1000): raise ValueError('UART control line inversion not available ' 'with this device') self._set_invert(name[len('invert_'):], value, out) self._dirty.add(name) return if name in self.properties: raise NotImplementedError("Change to '%s' is not yet supported" % name) raise ValueError("Unknown property '%s'" % name) def erase(self) -> None: """Erase the whole EEPROM.""" self._eeprom = bytearray([0xFF] * self.size) self._config.clear() self._dirty.add('eeprom') def initialize(self) -> None: """Initialize the EEPROM with some default sensible values. """ dev_ver = self.device_version dev_name = Ftdi.DEVICE_NAMES[dev_ver] vid = Ftdi.FTDI_VENDOR pid = Ftdi.PRODUCT_IDS[vid][dev_name] self.set_manufacturer_name('FTDI') self.set_product_name(dev_name.upper()) sernum = ''.join([chr(randint(ord('A'), ord('Z'))) for _ in range(5)]) self.set_serial_number('FT%d%s' % (randint(0, 9), sernum)) self.set_property('vendor_id', vid) self.set_property('product_id', pid) self.set_property('type', dev_ver) self.set_property('usb_version', 0x200) self.set_property('power_max', 150) self._sync_eeprom() def sync(self) -> None: """Force re-evaluation of configuration after some changes. This API is not useful for regular usage, but might help for testing when the EEPROM does not go through a full save/load cycle """ self._sync_eeprom() def dump_config(self, file: Optional[BinaryIO] = None) -> None: """Dump the configuration to a file. :param file: the output file, default to stdout """ if self._dirty: self._decode_eeprom() for name, value in self._config.items(): print('%s: %s' % (name, value), file=file or sys.stdout) def commit(self, dry_run: bool = True) -> bool: """Commit any changes to the EEPROM. :param dry_run: log what should be written, do not actually change the EEPROM content :return: True if some changes have been committed to the EEPROM """ self._sync_eeprom() if not self._modified: self.log.warning('No change to commit, EEPROM not modified') return False self._ftdi.overwrite_eeprom(self._eeprom, dry_run=dry_run) if not dry_run: eeprom = self._read_eeprom() if eeprom != self._eeprom: pos = 0 for pos, (old, new) in enumerate(zip(self._eeprom, eeprom)): if old != new: break pos &= ~0x1 raise FtdiEepromError('Write to EEPROM failed @ 0x%02x' % pos) self._modified = False return dry_run def reset_device(self): """Execute a USB device reset.""" self._ftdi.reset(usb_reset=True) @classmethod def _validate_string(cls, string): for invchr in ':/': # do not accept characters which are interpreted as URL seperators if invchr in string: raise ValueError("Invalid character '%s' in string" % invchr) def _update_var_string(self, name: str, value: str) -> None: if name not in self.VAR_STRINGS: raise ValueError('%s is not a variable string' % name) try: if value == self._config[name]: return except KeyError: # not yet defined pass self._config[name] = value self._dirty.add(name) def _generate_var_strings(self, fill=True) -> None: stream = bytearray() dynpos = self._PROPERTIES[self.device_version].dynoff data_pos = dynpos tbl_pos = 0x0e for name in self.VAR_STRINGS: try: ustr = self._config[name].encode('utf-16le') except KeyError: ustr = '' length = len(ustr) + 2 stream.append(length) stream.append(0x03) # string descriptor stream.extend(ustr) self._eeprom[tbl_pos] = data_pos tbl_pos += 1 self._eeprom[tbl_pos] = length tbl_pos += 1 data_pos += length self._eeprom[dynpos:dynpos + len(stream)] = stream crc_size = scalc('<H') if fill: mtp = self._ftdi.device_version == 0x1000 crc_pos = 0x100 if mtp else len(self._eeprom) crc_pos -= crc_size rem = len(self._eeprom) - (dynpos + len(stream)) - crc_size self._eeprom[dynpos + len(stream):crc_pos] = bytes(rem) def _sync_eeprom(self): if not self._dirty: self.log.debug('No change detected for EEPROM content') return if any([x in self._dirty for x in self.VAR_STRINGS]): self._generate_var_strings() for varstr in self.VAR_STRINGS: self._dirty.discard(varstr) self._update_crc() self._decode_eeprom() self._dirty.clear() self._modified = True self.log.debug('EEPROM content regenerated (not yet committed)') def _compute_crc(self, eeprom: Union[bytes, bytearray], check=False): mtp = self._ftdi.device_version == 0x1000 crc_pos = 0x100 if mtp else len(eeprom) crc_size = scalc('<H') if not check: # check mode: add CRC itself, so that result should be zero crc_pos -= crc_size crc = self._ftdi.calc_eeprom_checksum(eeprom[:crc_pos]) if check: self._valid = not bool(crc) if not self._valid: self.log.debug('CRC is now 0x%04x', crc) else: self.log.debug('CRC OK') return crc, crc_pos, crc_size def _update_crc(self): crc, crc_pos, crc_size = self._compute_crc(self._eeprom, False) self._eeprom[crc_pos:crc_pos + crc_size] = spack('<H', crc) def _read_eeprom(self) -> bytes: buf = self._ftdi.read_eeprom(0, eeprom_size=self.size) eeprom = bytearray(buf) crc = self._compute_crc(eeprom, True)[0] if crc: if self.is_empty: self.log.info('No EEPROM or EEPROM erased') else: self.log.error('Invalid CRC or EEPROM content') return eeprom def _decode_eeprom(self): cfg = self._config cfg.clear() cfg['vendor_id'] = Hex4Int(sunpack('<H', self._eeprom[0x02:0x04])[0]) cfg['product_id'] = Hex4Int(sunpack('<H', self._eeprom[0x04:0x06])[0]) cfg['type'] = Hex4Int(sunpack('<H', self._eeprom[0x06:0x08])[0]) power_supply, power_max, conf = sunpack('<3B', self._eeprom[0x08:0x0b]) cfg['self_powered'] = bool(power_supply & (1 << 6)) cfg['remote_wakeup'] = bool(power_supply & (1 << 5)) cfg['power_max'] = power_max << 1 cfg['has_serial'] = bool(conf & (1 << 3)) cfg['suspend_pull_down'] = bool(conf & (1 << 2)) cfg['out_isochronous'] = bool(conf & (1 << 1)) cfg['in_isochronous'] = bool(conf & (1 << 0)) cfg['usb_version'] = Hex4Int(sunpack('<H', self._eeprom[0x0c:0x0e])[0]) cfg['manufacturer'] = self._decode_string(0x0e) cfg['product'] = self._decode_string(0x10) cfg['serial'] = self._decode_string(0x12) name = None try: name = Ftdi.DEVICE_NAMES[cfg['type']].replace('-', '') if name.startswith('ft'): name = name[2:] func = getattr(self, '_decode_%s' % name) except (KeyError, AttributeError): self.log.warning('No EEPROM decoder for device %s', name or '?') else: func() def _decode_string(self, offset): str_offset, str_size = sunpack('<BB', self._eeprom[offset:offset + 2]) if str_size: str_offset &= self.size - 1 str_size -= scalc('<H') str_offset += scalc('<H') manufacturer = self._eeprom[str_offset:str_offset + str_size] return manufacturer.decode('utf16', errors='ignore') return '' def _set_cbus_func(self, cpin: int, value: str, out: Optional[TextIO]) -> None: cmap = { 0x600: (self.CBUS, 5, 0x14, 4), # FT232R 0x900: (self.CBUSH, 10, 0x18, 4), # FT232H 0x1000: (self.CBUSX, 4, 0x1A, 8) } # FT230X/FT231X/FT234X try: cbus, count, offset, width = cmap[self.device_version] except KeyError: raise ValueError('This property is not supported on this device') pin_filter = getattr(self, '_filter_cbus_func_x%x' % self.device_version, None) if value == '?' and out: items = {item.name for item in cbus} if pin_filter: items = {val for val in items if pin_filter(cpin, val)} print(', '.join(sorted(items)) if items else '(none)', file=out) return if not 0 <= cpin < count: raise ValueError("Unsupported CBUS pin '%d'" % cpin) try: code = cbus[value.upper()].value except KeyError: raise ValueError("CBUS pin %d does not have function '%s'" % (cpin, value)) if pin_filter and not pin_filter(cpin, value.upper()): raise ValueError("Unsupported CBUS function '%s' for pin '%d'" % (value, cpin)) addr = offset + (cpin * width) // 8 if width == 4: bitoff = 4 if cpin & 0x1 else 0 mask = 0x0F << bitoff else: bitoff = 0 mask = 0xFF old = self._eeprom[addr] self._eeprom[addr] &= ~mask self._eeprom[addr] |= code << bitoff self.log.debug('Cpin %d, addr 0x%02x, value 0x%02x->0x%02x', cpin, addr, old, self._eeprom[addr]) @classmethod def _filter_cbus_func_x900(cls, cpin: int, value: str): if cpin == 7: # nothing can be assigned to ACBUS7 return False if value in 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0'.split(): # any pin can be assigned these functions return True if cpin in (5, 6, 8, 9): # any function can be assigned to ACBUS5, ACBUS6, ACBUS8, ACBUS9 return True if cpin == 0: return value != 'GPIO' return False @classmethod def _filter_cbus_func_x600(cls, cpin: int, value: str): if value == 'BB_WR': # this signal is only available on CBUS0, CBUS1 return cpin < 2 return True def _set_bus_control(self, bus: str, control: str, value: Union[str, int, bool], out: Optional[TextIO]) -> None: if self.device_version == 0x1000: self._set_bus_control_230x(bus, control, value, out) return # for now, only support FT-X devices raise ValueError('Bus control not implemented for this device') def _set_bus_control_230x(self, bus: str, control: str, value: Union[str, int, bool], out: Optional[TextIO]) -> None: if bus not in 'cd': raise ValueError('Invalid bus: %s' % bus) try: if control == 'drive': candidates = (4, 8, 12, 16) if value == '?' and out: print(', '.join([str(v) for v in candidates]), file=out) return value = int(value) if value not in candidates: raise ValueError('Invalid drive current: %d mA' % value) value //= 4 value -= 1 elif control in ('slow_slew', 'schmitt'): if value == '?' and out: print('off, on', file=out) return value = int(to_bool(value)) else: raise ValueError('Unsupported control: %s' % control) except (ValueError, TypeError): raise ValueError('Invalid %s value: %s' % (control, value)) config = self._eeprom[0x0c] if bus == 'd': conf = config & 0x0F config &= 0xF0 cshift = 0 else: conf = config >> 4 config &= 0x0F cshift = 4 if control == 'drive': conf &= 0b1100 conf |= value elif control == 'slow_slew': conf &= 0b1011 conf |= value << 2 elif control == 'schmitt': conf &= 0b0111 conf |= value << 3 else: raise RuntimeError('Internal error') config |= conf << cshift self._eeprom[0x0c] = config def _set_invert(self, name, value, out): if value == '?' and out: print('off, on', file=out) return if name.upper() not in self.UART_BITS.__members__: raise ValueError('Unknown property: %s' % name) value = to_bool(value, permissive=False) code = getattr(self.UART_BITS, name.upper()) invert = self._eeprom[0x0B] if value: invert |= code else: invert &= ~code self._eeprom[0x0B] = invert def _decode_x(self): # FT-X series cfg = self._config misc, = sunpack('<H', self._eeprom[0x00:0x02]) cfg['channel_a_driver'] = 'VCP' if misc & (1 << 7) else 'D2XX' for bit in self.UART_BITS: value = self._eeprom[0x0B] cfg['invert_%s' % self.UART_BITS(bit).name] = bool(value & bit) max_drive = self.DRIVE.LOW | self.DRIVE.HIGH value = self._eeprom[0x0c] for grp in range(2): conf = value & 0xF bus = 'c' if grp else 'd' cfg['%sbus_drive' % bus] = 4 * (1 + (conf & max_drive)) cfg['%sbus_schmitt' % bus] = bool(conf & self.DRIVE.SCHMITT) cfg['%sbus_slow_slew' % bus] = bool(conf & self.DRIVE.SLOW_SLEW) value >>= 4 for bix in range(4): value = self._eeprom[0x1A + bix] try: cfg['cbus_func_%d' % bix] = self.CBUSX(value).name except ValueError: pass cfg['chip'] = Hex2Int(self._eeprom[0x1E]) def _decode_232h(self): cfg = self._config cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_type'] = cfg0 & 0x0F cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 4)) else 'D2XX' cfg['clock_polarity'] = 'high' if (cfg1 & self.CFG1.CLK_IDLE_STATE) \ else 'low' cfg['lsb_data'] = bool(cfg1 & self.CFG1.DATA_LSB) cfg['flow_control'] = 'on' if (cfg1 & self.CFG1.FLOW_CONTROL) \ else 'off' cfg['powersave'] = bool(cfg1 & self.DRIVE.PWRSAVE_DIS) max_drive = self.DRIVE.LOW | self.DRIVE.HIGH for grp in range(2): conf = self._eeprom[0x0c + grp] cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive) cfg['group_%d_schmitt' % grp] = conf & self.DRIVE.SCHMITT cfg['group_%d_slew' % grp] = conf & self.DRIVE.SLOW_SLEW for bix in range(5): value = self._eeprom[0x18 + bix] low, high = value & 0x0F, value >> 4 try: cfg['cbus_func_%d' % ((2 * bix) + 0)] = self.CBUSH(low).name except ValueError: pass try: cfg['cbus_func_%d' % ((2 * bix) + 1)] = self.CBUSH(high).name except ValueError: pass cfg['chip'] = Hex2Int(self._eeprom[0x1E]) def _decode_232r(self): cfg = self._config cfg0 = self._eeprom[0x00] cfg['channel_a_driver'] = 'VCP' if (~cfg0 & (1 << 3)) else '' cfg['high_current'] = bool(~cfg0 & (1 << 2)) cfg['external_oscillator'] = cfg0 & 0x02 for bit in self.UART_BITS: value = self._eeprom[0x0B] cfg['invert_%s' % self.UART_BITS(bit).name] = bool(value & bit) bix = 0 while True: value = self._eeprom[0x14 + bix] low, high = value & 0x0F, value >> 4 try: cfg['cbus_func_%d' % ((2 * bix) + 0)] = self.CBUS(low).name except ValueError: pass if bix == 2: break try: cfg['cbus_func_%d' % ((2 * bix) + 1)] = self.CBUS(high).name except ValueError: pass bix += 1 def _decode_2232h(self): cfg = self._config self._decode_x232h(cfg) cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_type'] = self.CHANNEL(cfg0 & 0x7).name or 'UART' cfg['channel_b_type'] = self.CHANNEL(cfg1 & 0x7).name or 'UART' cfg['suspend_dbus7'] = cfg1 & self.CFG1.SUSPEND_DBUS7 def _decode_4232h(self): cfg = self._config self._decode_x232h(cfg) cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_c_driver'] = 'VCP' if ((cfg0 >> 4) & (1 << 3)) else 'D2XX' cfg['channel_d_driver'] = 'VCP' if ((cfg1 >> 4) & (1 << 3)) else 'D2XX' conf = self._eeprom[0x0B] rs485 = self.CHANNEL.RS485 for chix in range(4): cfg['channel_%x_rs485' % (0xa + chix)] = bool(conf & (rs485 << chix)) def _decode_x232h(self, cfg): # common code for2232h and 4232h cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01] cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 3)) else 'D2XX' cfg['channel_b_driver'] = 'VCP' if (cfg1 & (1 << 3)) else 'D2XX' max_drive = self.DRIVE.LOW | self.DRIVE.HIGH for bix in range(4): if not bix & 1: val = self._eeprom[0x0c + bix // 2] else: val >>= 4 cfg['group_%d_drive' % bix] = bool(val & max_drive) cfg['group_%d_schmitt' % bix] = bool(val & self.DRIVE.SCHMITT) cfg['group_%d_slew' % bix] = bool(val & self.DRIVE.SLOW_SLEW) cfg['chip'] = Hex2Int(self._eeprom[0x18])
from _ssl import RAND_egd except ImportError: # LibreSSL does not provide RAND_egd pass from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1, HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3 from _ssl import _DEFAULT_CIPHERS, _OPENSSL_API_VERSION _IntEnum._convert( "_SSLMethod", __name__, lambda name: name.startswith("PROTOCOL_") and name != "PROTOCOL_SSLv23", source=_ssl) _IntFlag._convert("Options", __name__, lambda name: name.startswith("OP_"), source=_ssl) _IntEnum._convert("AlertDescription", __name__, lambda name: name.startswith("ALERT_DESCRIPTION_"), source=_ssl) _IntEnum._convert("SSLErrorNumber", __name__, lambda name: name.startswith("SSL_ERROR_"), source=_ssl) _IntFlag._convert("VerifyFlags", __name__, lambda name: name.startswith("VERIFY_"),
from _ssl import RAND_egd except ImportError: # LibreSSL does not provide RAND_egd pass from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3 from _ssl import _OPENSSL_API_VERSION _IntEnum._convert( '_SSLMethod', __name__, lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23', source=_ssl) _IntFlag._convert('Options', __name__, lambda name: name.startswith('OP_'), source=_ssl) _IntEnum._convert('AlertDescription', __name__, lambda name: name.startswith('ALERT_DESCRIPTION_'), source=_ssl) _IntEnum._convert('SSLErrorNumber', __name__, lambda name: name.startswith('SSL_ERROR_'), source=_ssl) _IntFlag._convert('VerifyFlags', __name__, lambda name: name.startswith('VERIFY_'),
from math import pi, pow from datetime import datetime, timedelta, timezone from doop.constants import Earth from collections import namedtuple from enum import IntFlag ID = namedtuple("ID", "launch_year launch_number piece") Object = namedtuple("Object", "name number classification") EphemerisType = IntFlag("EphemerisType", "SGP SGP4 SDP4 SGP8 SDP8") TLE = namedtuple( "TLE", 'object ' 'id ' 'coe ' 'ballistic_coeffecient ' 'bstar ' 'line1 line2') OE = namedtuple("OE", "a e i raan w v") def fix_classification(x): if x == "U": return "Unclassified" elif x == "C": return "Classified" elif x == "S": return "Secret" raise Exception(f"Invalid classification: {x}")
# Copyright (c) 2014 Kevin Walchko # see LICENSE for full details ############################################## # -*- coding: utf-8 -* from colorama import Fore import io from threading import Thread #, Lock import time from slurm.rate import Rate import numpy as np import cv2 from enum import IntFlag import attr # 1 2 3 4 ColorSpace = IntFlag("ColorSpace", "bgr rgb hsv gray") @attr.s(slots=True) class ThreadedCamera: """ https://www.raspberrypi.org/documentation/hardware/camera/ Raspberry Pi v2: resolution: 3280 x 2464 pixels sensor area: 3.68 mm x 2.76 mm pixel size: 1.12 um x 1.12 um video modes:1080p30, 720p60 and 640x480p60/90 optical size: 1/4" driver: V4L2 driver c = ThreadedCamera()
except ImportError: # LibreSSL does not provide RAND_egd pass from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN from _ssl import _OPENSSL_API_VERSION _IntEnum._convert( '_SSLMethod', __name__, lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23', source=_ssl) _IntFlag._convert( 'Options', __name__, lambda name: name.startswith('OP_'), source=_ssl) _IntEnum._convert( 'AlertDescription', __name__, lambda name: name.startswith('ALERT_DESCRIPTION_'), source=_ssl) _IntEnum._convert( 'SSLErrorNumber', __name__, lambda name: name.startswith('SSL_ERROR_'), source=_ssl) _IntFlag._convert( 'VerifyFlags', __name__, lambda name: name.startswith('VERIFY_'),
def create_swapchain(): global swapchain_image_format, swapchain # Swapchain Setup caps = hvk.physical_device_surface_capabilities(api, physical_device, surface) formats = hvk.physical_device_surface_formats(api, physical_device, surface) present_modes = hvk.physical_device_surface_present_modes( api, physical_device, surface) if not hvk.get_physical_device_surface_support( api, physical_device, surface, render_queue.family.index): raise RuntimeError( "Main rendering queue cannot present images to the surface") # Swapchain Format format_values = tuple(vkf.format for vkf in formats) required_formats = [vk.FORMAT_B8G8R8A8_SRGB, vk.FORMAT_B8G8R8A8_UNORM] for i, required_format in enumerate(required_formats): if required_format in format_values: required_formats[i] = format_values.index(required_format) else: required_formats[i] = None selected_format = next( (formats[i] for i in required_formats if i is not None), None) if selected_format is None: raise RuntimeError("Required swapchain image format not supported") # Swapchain Extent extent = caps.current_extent if extent.width == -1 or extent.height == -1: width, height = window.dimensions() extent.width = width extent.height = height # Min image count min_image_count = 2 if caps.max_image_count != 0 and caps.max_image_count < min_image_count: raise RuntimeError("Minimum image count not met") elif caps.min_image_count > min_image_count: min_image_count = caps.min_image_count # Present mode present_mode = vk.PRESENT_MODE_FIFO_KHR if vk.PRESENT_MODE_MAILBOX_KHR in present_modes: present_mode = vk.PRESENT_MODE_MAILBOX_KHR elif vk.PRESENT_MODE_IMMEDIATE_KHR in present_modes: present_mode = vk.PRESENT_MODE_IMMEDIATE_KHR # Default image transformation transform = caps.current_transform if IntFlag(vk.SURFACE_TRANSFORM_IDENTITY_BIT_KHR) in IntFlag( caps.supported_transforms): transform = vk.SURFACE_TRANSFORM_IDENTITY_BIT_KHR # Swapchain creation swapchain_image_format = selected_format.format swapchain = hvk.create_swapchain( api, device, hvk.swapchain_create_info( surface=surface, image_format=swapchain_image_format, image_color_space=selected_format.color_space, image_extent=extent, min_image_count=min_image_count, present_mode=present_mode, pre_transform=transform, old_swapchain=0))
from functools import partialmethod from itertools import accumulate from opcode import ( EXTENDED_ARG, HAVE_ARGUMENT, cmp_op, hascompare, hasconst, hasfree, haslocal, hasname, opname, ) from types import CodeType CompilerFlags = IntFlag("CompilerFlags", " ".join(COMPILER_FLAG_NAMES.values())) MakeFunctionFlags = IntFlag( "MakeFunctionFlags", " ".join(flag.upper() for flag in MAKE_FUNCTION_FLAGS)) class CodeBuilderBase: def __init__(self): self.consts = {None: 0} self.names = {} self.varnames = {} self.cellvars = {} self.freevars = {} def ascode(self, func_name: str, argcount: int) -> CodeType: code = bytes(self)
# Note that _socket only knows about the integer values. The public interface # in this module understands the enums and translates them back from integers # where needed (e.g. .family property of a socket object). IntEnum._convert_( 'AddressFamily', __name__, lambda C: C.isupper() and C.startswith('AF_')) IntEnum._convert_( 'SocketKind', __name__, lambda C: C.isupper() and C.startswith('SOCK_')) IntFlag._convert_( 'MsgFlag', __name__, lambda C: C.isupper() and C.startswith('MSG_')) IntFlag._convert_( 'AddressInfo', __name__, lambda C: C.isupper() and C.startswith('AI_')) _LOCALHOST = '127.0.0.1' _LOCALHOST_V6 = '::1' def _intenum_converter(value, enum_klass): """Convert a numeric family value to an IntEnum member. If it's not a known member, return the numeric value itself.
def _setup_device(self): api, instance = self.api, self.instance conf = self.configuration queues_conf = conf.get("QUEUES", DEFAULT_ENGINE_CONFIGURATION["QUEUES"]) # Device selection failure_reasons, all_good = [], False physical_devices = hvk.list_physical_devices(api, instance) for index, physical_device in enumerate(physical_devices): # Features supported_features = hvk.physical_device_features(api, physical_device) if not "texture_compression_BC" in supported_features: failure_reasons.append(f"BC compressed textures are not supported on your machine on device #{index}") continue # Queues queue_families = hvk.list_queue_families(api, physical_device) queue_create_infos = [] mapped_queue_configurations = {} render_queue_data = None bad_queues = False for qconf in queues_conf: queue_family = None # Find a matching queue family for qf in queue_families: if qconf.type in IntFlag(qf.properties.queue_flags): queue_family = qf # Go to the next device if a required queue configuration could not be found if qconf.required and queue_family is None: bad_queues = True failure_reasons.append(f"No queue family matches the required configuration {qconf} on device #{index}") break # Update the queue create info array new_info = {"queue_family_index": queue_family.index, "queue_count": 0} queue_create_info = next((qc for qc in queue_create_infos if qc["queue_family_index"] == queue_family.index), new_info) queue_create_infos.append(queue_create_info) queue_local_index = queue_create_info["queue_count"] queue_create_info["queue_count"] += 1 # Save the index of the required graphics queue that will be used by the renderer if render_queue_data is None and QueueType.Graphics in qconf.type: render_queue_data = (queue_family, queue_local_index) # Associate the queue configuration with the family and the local index for queue handle fetching mapped_queue_configurations[qconf] = (queue_family, queue_local_index) if bad_queues: continue all_good = True break if not all_good: raise RuntimeError(failure_reasons) if render_queue_data is None: raise RuntimeError("No graphics queue was specified in the engine queues configuration. Protip: use \"QueueConf.Default\" ") # Device creation queue_create_infos = [hvk.queue_create_info(**args) for args in queue_create_infos] extensions = ("VK_KHR_swapchain",) features = vk.PhysicalDeviceFeatures(texture_compression_BC = 1) device = hvk.create_device(api, physical_device, extensions, queue_create_infos, features) # Fetching queues # First, fetch the render queue render_queue_family, render_family_local_index = render_queue_data render_queue_handle = hvk.get_queue(api, device, render_queue_family.index, render_family_local_index) render_queue = Queue(render_queue_handle, render_queue_family) # Second, fetch all the queues (yes, the render queue is fetched twice) queues = {} for queue_conf, queue_data in mapped_queue_configurations.items(): queue_family, local_index = queue_data queue_handle = hvk.get_queue(api, device, queue_family.index, local_index) queues[queue_conf.name] = Queue(queue_handle, queue_family) self.physical_device = physical_device self.device = device self.render_queue = render_queue self.queues = queues
from enum import IntFlag from random import choice, random from time import sleep def chance(percent): return random() < percent def rand_char(): return choice('█ ') WALL, AIR, FLOOR, RANDOM = IntFlag('TileType', 'WALL AIR FLOOR RANDOM') NEXT_TILETYPE = { WALL: lambda: WALL if chance(.8) else AIR, AIR: lambda: AIR if chance(.4) else RANDOM, FLOOR: lambda: RANDOM, RANDOM: lambda: choice((WALL, AIR, FLOOR)) } TILETYPE_TO_CHARACTER = { WALL: lambda: '█', AIR: lambda: ' ', FLOOR: lambda: '_', RANDOM: lambda: rand_char(), } def run(row, *, delay=.5):
#!/usr/bin/env python3 import threading import time from mbeacon import BeaconServer, BeaconFinder # from collections import namedtuple from enum import Enum, IntFlag # Pub_t = namedtuple('Pub_t', 'key topic pid funcname') # Sub_t = namedtuple('Sub_t', 'key topic pid funcname') # Perf_t = namedtuple('Perf_t', 'key nummsg msgrate datarate funcname') # Connect_t = namedtuple('Connect_t', 'topic ip') MsgsIPC = Enum('MsgsIPC', 'Pub Sub Resp Perf') TTL = IntFlag('TTL', {'host': 0, 'subnet': 1, 'site': 31}) class IPC: def __init__(self, key, kind, topic, pid, funcname): self.msg = ( key, kind, topic, pid, funcname, ) class PubIPC(IPC): def __init__(self, key, topic, pid, funcname): IPC.__init__(