import abc from typing import Optional, List, Tuple, Union import spidev from . import LowLevelHardwareInterface _RUNTIME_COMPILE = False class AbstractSpiInterface(LowLevelHardwareInterface, metaclass=abc.ABCMeta): __slots__ = () @abc.abstractmethod def send_byte(self, data: bytes) -> Optional[List[int]]: pass class HardwareImplSpiInterface(LowLevelHardwareInterface): """ **Linux driver** The default Linux driver is spi-bcm2708. The following information was valid 2014-07-05. **SPEED** The driver supports the following speeds: ======= ============ ================================= cdiv speed note ======= ============ ================================= 2 125.0 MHz 4 62.5 MHz 8 31.2 MHz 16 15.6 MHz 32 7.8 MHz cc2650 master mode max (12MHz) 64 3.9 MHz cc2650 slave mode max (4MHz) 128 1953 kHz 256 976 kHz 512 488 kHz 1024 244 kHz 2048 122 kHz 4096 61 kHz 8192 30.5 kHz 16384 15.2 kHz 32768 7629 Hz ======= ============ ================================= **required pins** *MISO*, *SCLK*, *GE0_N* """ __slots__ = ('_device', '_spi', '_spi_mode', '_spi_speed') def __init__(self, device: Tuple[int, int] = None, spi_mode=0x00, spi_speed=12_000_000): # SPI parameter if device is None: self._device = (0, 0) else: self._device = device # SPI instance self._spi = spidev.SpiDev() self._spi_mode = spi_mode self._spi_speed = spi_speed def reset(self): self._spi.open(*self._device) self._spi.mode = self._spi_mode self._spi.max_speed_hz = self._spi_speed def close(self): self._spi.close() def flush(self): pass def send_byte(self, data: Union[bytes, List[int]]) -> List[int]: if isinstance(data, bytes): return self._spi.xfer([v for v in data]) else: return self._spi.xfer(data) def recv_byte(self, size: int) -> Optional[bytes]: raise RuntimeError() class SoftwareImplSpiInterface(AbstractSpiInterface): BPS_SPI = None __slots__ = ('_spi', '_select') def __init__(self, clk: int, mosi: int, miso: Optional[int] = None, cs: Union[None, int, Tuple[int]] = None, cpol=False, cpha=True): self._check_import() self._spi = self.BPS_SPI.Bpsspi(clk, mosi, miso, cs, cpol, cpha) self._select = 0 @classmethod def _check_import(cls): if cls.BPS_SPI is None: import biopro.ext.bpsspi as bpsspi cls.BPS_SPI = bpsspi @property def select(self) -> int: return self._select @select.setter def select(self, value: int): self._select = value def reset(self): self._spi.reset() super().reset() def close(self): self._spi = None def flush(self): pass def __enter__(self): if self._spi is None: raise RuntimeError('spi has closed') self._spi.set_cs(self._select, False) return self def __exit__(self, exc_type, exc_val, exc_tb): if self._spi is not None: self._spi.set_cs(self._select, True) def send_byte(self, data: bytes) -> Optional[List[int]]: if self._spi is not None: with self: if self._spi.miso >= 0: return self.send_byte_exchange(data) else: return self.send_byte_transmit(data) return None def send_byte_transmit(self, data: bytes) -> Optional[List[int]]: if self._spi is not None: self._spi.send_byte_transmit(data) return None def send_byte_exchange(self, data: bytes) -> Optional[List[int]]: if self._spi is not None: return self._spi.send_byte_exchange(data) return None def recv_byte(self, size: int) -> Optional[bytes]: return None def _main(): from time import sleep from biopro.util.console import hex_line spi = HardwareImplSpiInterface() spi.reset() data = list(range(100)) while True: hex_line(spi.send_byte(data)) sleep(1) if __name__ == '__main__': _main()