123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- import enum
- import spidev
- class CC1101:
- # > All transfers on the SPI interface are done
- # > most significant bit first.
- # > All transactions on the SPI interface start with
- # > a header byte containing a R/W bit, a access bit (B),
- # > and a 6-bit address (A5 - A0).
- # > [...]
- # > Table 45: SPI Address Space
- _WRITE_SINGLE_BYTE = 0x00
- # > Registers with consecutive addresses can be
- # > accessed in an efficient way by setting the
- # > burst bit (B) in the header byte. The address
- # > bits (A5 - A0) set the start address in an
- # > internal address counter. This counter is
- # > incremented by one each new byte [...]
- _WRITE_BURST = 0x40
- _READ_SINGLE_BYTE = 0x80
- _READ_BURST = 0xC0
- class _SPIAddress(enum.IntEnum):
- # Table 45: SPI Address Space
- # > For register addresses in the range 0x30-0x3D,
- # > the burst bit is used to select between
- # > status registers when burst bit is one, and
- # > between command strobes when burst bit is
- # > zero. [...]
- # > Because of this, burst access is not available
- # > for status registers and they must be accessed
- # > one at a time. The status registers can only be
- # > read.
- SRES = 0x30
- PARTNUM = 0x30
- VERSION = 0x31
- MARCSTATE = 0x35
- class MainRadioControlStateMachineState(enum.IntEnum):
- """
- MARCSTATE - Main Radio Control State Machine State
- """
- IDLE = 0x01
- # 29.3 Status Register Details
- _SUPPORTED_PARTNUM = 0
- _SUPPORTED_VERSION = 0x14
- def __init__(self) -> None:
- self._spi = spidev.SpiDev()
- def _reset(self) -> None:
- assert self._spi.xfer([self._SPIAddress.SRES, 0]) == [0x0F, 0x0F]
- def _read_burst(self, register: _SPIAddress) -> int:
- response = self._spi.xfer([register | self._READ_BURST, 0])
- assert len(response) == 2, response
- assert response[0] == 0
- return response[1]
- def __enter__(self) -> "CC1101":
- # https://docs.python.org/3/reference/datamodel.html#object.__enter__
- self._spi.open(0, 0)
- self._spi.max_speed_hz = 55700 # empirical
- self._reset()
- partnum = self._read_burst(self._SPIAddress.PARTNUM)
- if partnum != self._SUPPORTED_PARTNUM:
- raise ValueError(
- "unexpected chip part number {} (expected: {})".format(
- partnum, self._SUPPORTED_PARTNUM
- )
- )
- version = self._read_burst(self._SPIAddress.VERSION)
- if version != self._SUPPORTED_VERSION:
- raise ValueError(
- "unexpected chip version number {} (expected: {})".format(
- version, self._SUPPORTED_VERSION
- )
- )
- marcstate = self.getMainRadioControlStateMachineState()
- if marcstate != self.MainRadioControlStateMachineState.IDLE:
- raise ValueError("expected marcstate idle (actual: {})".format(marcstate))
- return self
- def __exit__(self, exc_type, exc_value, traceback) -> bool:
- # https://docs.python.org/3/reference/datamodel.html#object.__exit__
- self._spi.close()
- return False
- def getMainRadioControlStateMachineState(self) -> MainRadioControlStateMachineState:
- return self.MainRadioControlStateMachineState(
- self._read_burst(self._SPIAddress.MARCSTATE)
- )
- def getMARCState(self) -> MainRadioControlStateMachineState:
- """
- alias for getMainRadioControlStateMachineState()
- """
- return self.getMainRadioControlStateMachineState()
|