Skip to content

Instantly share code, notes, and snippets.

@mattytrentini
Created May 23, 2024 23:53
Show Gist options
  • Save mattytrentini/689dd83810a58e78170382fc754fc54d to your computer and use it in GitHub Desktop.
Save mattytrentini/689dd83810a58e78170382fc754fc54d to your computer and use it in GitHub Desktop.
Example MicroPython code to interact with an AD5592r chip
# The microcontroller used was a SeeedStudio XIAO RP2040.
# Modify `spi` and `cs` appropriately to work on any other micro.
from machine import Pin, SPI
spi = SPI(0, baudrate=20_000_000) # Initialise SPI at 20MHz. Note that on RP2040 due to clock configurations this is closer to 15MHz.
cs = Pin.board.CSn
cs.init(Pin.OUT, value=1) # Initialise CS high, ie no transmission
def send(spi, cs, reg):
""" Send reg as two-byte data """
buf = bytearray(2)
buf[0] = (reg & 0xff00) >> 8
buf[1] = reg & 0x00ff
cs.off()
spi.write(buf)
cs.on()
def get_register(spi, cs, reg):
""" Send a CONFIG_READ_AND_LDAC with the appropriate register details, read back the value of the register. """
buf = bytearray(2)
regdata = bytearray(2)
# 0b0_0111_0000_1_1000_00 # Retrieve GPIO register
buf[0] = 0b0_0111_000 # Read, Read register, Reserved
buf[1] = 0b0_1_0000_00 # Reserved continued, Read enabled, register, LDAC
buf[1] |= (reg & 0xf) << 2
cs.off()
spi.write(buf)
cs.on()
cs.off()
spi.readinto(regdata)
cs.on()
return (regdata[0] << 8) + regdata[1]
def read_data(spi, cs, send=0):
""" Read 16-bit ADC response, return the ADC channel and data """
data = bytearray(2)
buf = bytearray(2)
buf[0] = (send & 0xff00) >> 8
buf[1] = send & 0x00ff
cs.off()
spi.write_readinto(buf, data)
cs.on()
adc_addr = data[0] >> 4
adc_data = ((data[0] & 0xf) << 8) + data[1]
return adc_addr, adc_data
def get_adc_values(spi, cs, channels):
""" Send ADC_SEQ (not repeating) to initialise ADC reads. Read the ADC data for each channel requested.
Return a list of tuples where each tuple is a pair of ADC channel ID's and the corresponding ADC data.
"""
seq = (0b0_0010_0_0_0 << 8) + (channels & 0xff)
print(bin(seq))
send(spi, cs, seq)
# Datasheet suggests this next spi operation is necessary but data was inconsistent when it was added.
# Working theory is that CS toggling was slow enough (10's of us) in MicroPython that the ADC conversion
# would occur before the toggle.
# Could approach native speeds by toggling with register access but seems adequate as-is for now.
#send(spi, cs, 0)
num_reads = bin(channels).count("1")
data = [read_data(spi, cs) for _ in range(num_reads)]
return data
def print_all_registers(spi, cs):
""" Print all of the registers in a neat table.
Skips over CONFIG_READ_AND_LDAC since it's the register used to read each register and is modified during the read!
"""
reg_names = ["NOP", "DAC_RD", "ADC_SEQ", "GEN_CTRL_REG", "ADC_CONFIG",
"DAC_CONFIG", "PULLDWN_CONFIG", #"CONFIG_READ_AND_LDAC",
"GPIO_CONFIG", "GPIO_OUTPUT", "GPIO_INPUT", "PD_REF_CTRL",
"GPIO_OPENDRAIN_CONFIG", "IO_TS_CONFIG"]
longest_len = len(max(reg_names, key = len))
for reg_id in range(0xd):
print(f"{reg_names[reg_id]:<{longest_len}} {reg_id:#06b} {get_register(spi, cs, reg_id):#018b}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment