Source code for wni.txrx_spi

"""
Set the LO on the radar frontend board to the correct frequency.  The LO is
controlled via SPI.
"""


import os
import struct
import time


[docs]class HMC807(object): REG_ID = 0x0 REG_RST = 0x1 REG_REFDIV = 0x2 REG_FREQ_INT = 0x3 REG_FREQ_FRAC = 0x4 REG_SEED = 0x5 REG_SD_CFG = 0x6 REG_LKD_CSP = 0x7 # lock detect / cycle slip prevention REG_ANALOG_EN = 0x8 REG_CP = 0x9 # charge pump REG_CP_OPAMP = 0xA # Charge Pump Internal Op-Amp bias REG_PFD = 0xB # phase frequency detector REG_VCO = 0xC # Voltage controlled oscillator REG_GPO = 0xD # General purpose output register (multiplexer select) REG_LD_STATE = 0xF # Lock detect state def __init__(self, bus, device): import spidev self._frequency_mult = None self.spi = spidev.SpiDev(bus, device) self.spi.mode = 0 @classmethod def _format_read(cls, reg): """Return the bytes that need to be sent to read a register.""" tx = [0] * 4 tx[0] = (0x80 | ((0x3F & reg) << 1)) & 0xFE return tx
[docs] @classmethod def from_chardev(cls, path): """Instantiate an HMC807 device given a path to SPI device in /dev""" basename = os.path.basename(path) bus, dev = basename.split('.') bus = int(bus[len('spidev'):]) dev = int(dev) return cls(bus, dev)
@classmethod def _format_write(cls, reg, val): """Return the bytes that need to be sent to write `val` to `reg`""" tx = [None] * 4 data = [None] * 3 data[0] = val >> 16 data[1] = (val >> 8) & 0xFF data[2] = val & 0xFF # the hmc is the worst and has one 7-bit word at the beginning. # so everything else has to be bitshifted lots. tx[0] = (0x00 | ((0x3F & reg) << 1)) | ((data[0] >> 7) & 0x01) tx[1] = ((data[0] << 1) & 0xFE) | ((data[1] >> 7) & 0x01); tx[2] = ((data[1] << 1) & 0xFE) | ((data[2] >> 7) & 0x01); tx[3] = ((data[2] << 1) & 0xFE); return tx
[docs] def read_reg(self, reg): tx = self._format_read(reg) rx = self.spi.xfer(tx) b = bytearray(rx) value, = struct.unpack('>I', b) # The first seven bits are not part of the value. # _Probably_ we should count the first bit as well, but we're not going to. # This means that the MSB won't get counted, I think. value = value & 0xFFFFFF return value
[docs] def write_reg(self, reg, data): tx = self._format_write(reg, data) self.spi.writebytes(tx)
def _display_registers(self): """Displays the registers in self.default_addr""" for addr in range(0x10): val = self.read_reg(addr) print("HMC Reg 0x%02X: 0x%06X" % (addr, val))
[docs] def init_registers(self): """Initialize the registers with values we like.""" self.reset() self.write_reg(self.REG_RST, 1) # enable external CE self.write_reg(self.REG_REFDIV, 1) # bypass reference clk divider self.frequency_mult = 125 # multiply reference clk by 125 self.write_reg(self.REG_FREQ_FRAC, 0) # no fractional part self.write_reg(self.REG_SEED , 0x50894C) self.write_reg(self.REG_SD_CFG , 0x703387) self.write_reg(self.REG_LKD_CSP, 0x04FA) # Disable CSP self.write_reg(self.REG_ANALOG_EN, 0x31DF) self.write_reg(self.REG_CP, 0x900000) self.write_reg(self.REG_PFD, 0x72) self.write_reg(self.REG_GPO, 0xD)
@property def id(self): return '{:x}'.format(self.read_reg(0)) @property def frequency_mult(self): """Get and set the reference frequency multiplier.""" return self._frequency_mult return self.read_reg(self.REG_FREQ_INT) @frequency_mult.setter def frequency_mult(self, value): self._frequency_mult = value self.write_reg(self.REG_FREQ_INT, value)
[docs] def reset(self): """Reset all registers to default values.""" self.write_reg(0, 1)