AnotherSam
Posts: 14
Joined: Thu Aug 12, 2021 2:37 pm

Micropython SPI not acting as expected

Sat Sep 25, 2021 4:54 am

Hello all,

I am working on a program to control a frequency synthesizer chip through SPI. I am using a Raspberry Pi Pico to perform the SPI and I am using a PC to drive the PICO. I've gotten almost everything working but sometimes the SPI communication doesn't work quite right. I know there is a general issue with the machine.spi class that requires a dummy read to work, and have added that to the code. But this problem is very intermittent and I am having a hard time figuring out why its happening.
The pico has a main function running which imports a py file to define the Synthesizer's class, LMX2820. The main function's only other purpose to allow the user to call the LMX's functions through the serial port (USB). The first action which must be taken is initializing the chip/registers (in the main.py LMX2820Init()) I typically have to call this function 2-3 times before it works. Once it does, I have no issues after that. I can also repeat the problem by working directly with the LMX2820.py file. from LMX2820.py I usually have to call LMX2820StartUp(...) multiple times as well.
A few interesting notes on the problem: I know the chip is 100% ok because I have Texas Instruments' own programming device and it works flawlessly. When I call the LMX2820Init, or LMX2820StartUp directly, if the SPI communication doesn't work property, the chip is left in an undefined state, however, manually toggling the Chip Select (CS) line either through software or physically, will make the chip execute the command.
I feel this is all related to the dummy read problem, but perhaps someone better in Python than me can help confirm. If so, has anyone found a reliable solution to the SPI dummy write problem? The LMX2820WriteSingeRegister(spi, CS, LMX, address, NewValue): command in the LMX.py file is the function which does all the communcation.
Thanks,
Sami

Main.py on Pico

Code: Select all

from machine import Pin
import time
from LMX2820 import *

led = Pin(25, Pin.OUT)
LD = Pin(26, Pin.IN)
CEpin = machine.Pin(21, machine.Pin.OUT)
spi = machine.SPI(0, baudrate = 250000, polarity = 0, phase = 0,bits = 8,
      firstbit = machine.SPI.MSB,
      sck = machine.Pin(18),
      mosi = machine.Pin(19),
      miso = machine.Pin(16))
LMX = LMX2820(100e6, 0, 1, 1, 1, 20)
CSpin = machine.Pin(LMX.LEpin, machine.Pin.OUT)
CSpin.value(1)
dummyRead(LMX,spi,CSpin)

# Toggling LED to determine if serial port is open
def on():
    led.value(1)
def off():
    led.value(0)
#Toggling CE pin to turn on/off chip 
def ChipSelectON():
    CEpin.value(1)
def ChipSelectOFF():
    CEpin.value(0)

def LMX2820Init():
    LMX2820StartUp(LMX,spi,CSpin)
    

def LMXNewFreq(newFreq):
    LMX2820ChangeFreq(spi,CSpin,LMX,newFreq)

#OutA_Enable: 0 = PWR UP, 1 = PWR DWN
#OutA_Mux: 0 = Channel Divider, 1 = VCO output, 2=S doubled output
#OutA_PWR: 7 is max 0 is min
#OutB parameters mimic A
#BDiv  Channel B divider: 0-6 Allowed, divider value =  2^(Bdiv value+1)    
def LMXChangeOutputs(OutA_En, OutA_Mux, OutA_PWR, OutB_En, OutB_Mux, OutB_PWR,BDiv):
    LMX2820ChangeOutputSettings(spi,CSpin,LMX, OutA_En, OutA_Mux, OutA_PWR, OutB_En, OutB_Mux, OutB_PWR,BDiv)

#Toggling OutputA
def LMXToggleChannelA(OutA_En):
    LMX2820chARFOnOff(spi,CSpin,LMX,OutA_En)
    
#Toggling OutputB
def LMXToggleChannelB(OutB_En):
    LMX2820chBRFOnOff(spi,CSpin,LMX,OutB_En)
 
def LMXChangeSettings(OutA_PWR, OutB_Mux, OutB_PWR,BDiv):
    LMX2820ChangeSettings(spi,CSpin,LMX, OutA_PWR, OutB_Mux, OutB_PWR,BDiv)
LMX2820 class. 90% of the code is setting registers, those lines can be ignored

Code: Select all

from Fractions import *
from BitFunctions import *
import machine
import time

#RegFREQ is the OSCin Freq
#RefDoubler: 0 = bypassed, 1 = enabled
#Ref Multipler: 1 = bypassed, 3,5,7 only allowed
#Ref Pre-Divider: 1 = bypass max = 128
#Ref Post-Divider: 1= bypass max = 255
class LMX2820:
    def __init__(self, RefFREQ, RefDoubler, RefMultipler, PreRDiv, PostRDiv, LEpin):
        self.RefFREQ = RefFREQ
        self.RefDoubler = RefDoubler
        self.RefMultipler = RefMultipler
        self.PreRDiv = PreRDiv
        self.PostRDiv = PostRDiv
        self.LEpin = LEpin
        self.reg = [0]*123
        self.DividerLUT = [2,4,8,16,32,64,128]
        self.reg[0] = 0b0100000001110000     #Reset register PFD = 100 MHz Setting Fcal HPFD and LPFD ADJ. F_Cal is 1
        self.reg[2] = 0b1011001111101000     #Setting clock Div value
        self.reg[11] = 0b0000011000000010    #Ref doubler bypassed
        self.reg[12] = 0b0000010000001000    #Ref multiplier bypassed
        self.reg[13] = 0b0000000000111000    #Ref Post R Divider set to 1
        self.reg[14] = 0b0011000000000001    #Ref Pre R Divider set to 1
        if(self.RefDoubler != 1 and self.RefDoubler != 0):                                                     #CHekcing value of OSC_2x 
            self.RefDoubler = 0                                                                                #Ensuring only states 0 and 1 are possible
        if(self.RefMultipler!=1 and self.RefMultipler!=3 and self.RefMultipler!=5 and self.RefMultipler>7):    #Testing if requested multiplcation factor is valid
            print("Ref multiplier out of range (1,3,5,7 allowed). set to bypass, 1")
            self.RefMultipler = 1                                                                              #If value is out of range set to bypass
        if(self.PreRDiv<1 or self.PreRDiv>4095):                                                               #Testing if requested pre-divider value is valid
            print("Ref pre divider out  of range (1-128). Set to bypass, 1")
            self.PreRDiv = 1                                                                                   #If out of range, set to bypass            
        if(self.PostRDiv<1 or self.PostRDiv>255):                                                              #Checking if post divider is in valid range
            print("Ref pre divider out  of range (1-128). Set to bypass, 1")
            self.PostRDiv = 1                                                                                   #If out of range, set to bypass  
        Fpfd = self.RefFREQ * (((1+self.RefDoubler)*self.RefMultipler) / (self.PreRDiv*self.PostRDiv))          #Calculating Phase Frequency detector frequency
        if (Fpfd > 225e6 or Fpfd < 5e6):                                                                        #If Fpfd is out of range, set reference chain to bypass all
            print("Phase frequency detector frequency too high. Must be <=225 MHz and  >=5 MHz. Setting multiplier and dividres to bypass.")
            self.RefDoubler == 0
            self.RefMultipler = 1
            self.PreRDiv = 1
            self.PostRDiv = 1
        else:                                                                  #If the Fpfd is value, set the registers for the the refernece chain
            if (self.RefDoubler == 1):
                self.reg[11] = modifyBM(self.reg[11],1,4,1)                    #Adjusting register 11 accordingly for the Ref multiply by 2
            self.reg[12] = modifyBM(self.reg[12],self.RefMultipler,10,3)       #Setting new Ref Multipleir value
            self.reg[14] = modifyBM(self.reg[14],self.PreRDiv,0,12)            #Setting new Ref pre divider value
            self.reg[13] = modifyBM(self.reg[13],self.PostRDiv,5,8)            #Setting new Ref post divider value
            if(Fpfd <= 100e6):                                                 #Setting the FCal_Hpfd_ADJ according to the Fpfd
                self.reg[0] = modifyBM(self.reg[0],0,9,2)                      #
            elif(100e6 < Fpfd and Fpfd <=150e6):                               #
                self.reg[0] = modifyBM(self.reg[0],1,9,2)                      #
            elif(150e6 < Fpfd and Fpfd <=200e6):                               #
                self.reg[0] = modifyBM(self.reg[0],2,9,2)                      #
            elif(200e6 < Fpfd):                                                #
                self.reg[0] = modifyBM(self.reg[0],3,9,2)                      #
            if(Fpfd >= 10e6):                                                  #Setting FCal_Lpfd_ADJ according to Fpfd
                self.reg[0] = modifyBM(self.reg[0],0,7,2)                      #
            elif(10e6 > Fpfd and Fpfd >= 5e6):                                 #
                self.reg[0] = modifyBM(self.reg[0],1,7,2)                      #
            elif(5e6 > Fpfd and Fpfd >= 2.5e6):                                #
                self.reg[0] = modifyBM(self.reg[0],2,7,2)                      #
            elif(2.5e6 > Fpfd):                                                #
                self.reg[0] = modifyBM(self.reg[0],3,7,2)                      #
            if (self.RefFREQ <= 200e6):                                        #Setting Cal_Clk_Divider based on input reference frequency
                self.reg[2] = modifyBM(self.reg[2],0,12,3)                     #
            elif(200e6 < self.RefFREQ and self.RefFREQ <= 400e6):              #
                self.reg[2] = modifyBM(self.reg[2],1,12,3)                     #
            elif(400e6 < self.RefFREQ and self.RefFREQ <= 800e6):              #
                self.reg[2] = modifyBM(self.reg[2],2,12,3)                     #
            elif(800e6 < self.RefFREQ):                                        #
                self.reg[2] = modifyBM(self.reg[2],3,12,3)                     #

#Fucntion to intilaize the registesr for the LMX and the CE pin for SPI
#Still needs to be transmitted to chip properly
#Commented registerd get defined in class defintion
def LMX2820InitRegs(LMX):
    #LMX.reg[0] = 0b0100000001110000     #Reset register PFD = 100 MHz Setting Fcal HPFD and LPFD ADJ. 
    LMX.reg[1] = 0b0101011110100000     #Enable if doubler is engaged
    #LMX.reg[2] = 0b1011001111101000     #Setting clock Div value
    LMX.reg[3] = 0x41                   #Reserved
    LMX.reg[4] = 0x4204                 #Reserved
    LMX.reg[5] = 0x32                   #Reserved        Reset:0x3832
    LMX.reg[6] = 0xA43                  #ACAL_CMP_DLY
    LMX.reg[7] = 0x00                   #Reserved        Reset:0xC8
    LMX.reg[8] = 0xC802                 #Reserved
    LMX.reg[9] = 0x05                   #Reserved
    LMX.reg[10] = 0x00                  #Manual PFD_DLY     Reset: 0b0000011000000011
    ##LMX.reg[11] = 0b0000011000000010    #Ref doubler bypassed
    ##LMX.reg[12] = 0b0000010000001000    #Ref multiplier bypassed
    ##LMX.reg[13] = 0b0000000000111000    #Ref Post R Divider set to 1
    ##LMX.reg[14] = 0b0011000000000001    #Ref Pre R Divider set to 1
    LMX.reg[15] = 0b0010000000000001    #Setting negative polairty for PFD charge pump to nomral operation
    LMX.reg[16] = 0b0001011100011100    #Setting charge pump current   Reset: 0b0010011100011100
    LMX.reg[17] = 0b0001010111000000    #Setting lock det type to continious  Reset: 1010001000000
    LMX.reg[18] = 0x3E8                 #Lock Detect assertion delay
    LMX.reg[19] = 0b0010000100100000    #Disabling temperature sensor
    LMX.reg[20] = 0b0010011100101100    #VCO_DACISET
    LMX.reg[21] = 0x1C64                #Reserved
    LMX.reg[22] = 0xE2BF                #Seting VCO core 7 as core to Cal
    LMX.reg[23] = 0b0001000100000010    #Disabling VCO_SEL_Force
    LMX.reg[24] = 0xE34                 #Reserved
    LMX.reg[25] = 0x624                 #Reserved
    LMX.reg[26] = 0xDB0                 #Reserved
    LMX.reg[27] = 0x8001                #Reserved
    LMX.reg[28] = 0x639                 #Reserved
    LMX.reg[29] = 0x318C                #Reserved
    LMX.reg[30] = 0xB18C                #Reserved
    LMX.reg[31] = 0x401                 #Reserved
    LMX.reg[32] = 0b0001000000000001    #Setting Both Output vhannel dividers to 0 (Div by 2)
    LMX.reg[33] = 0x00                  #Reserved
    LMX.reg[34] = 0b0000000000010000    #Disabling External VCO and LoopBack
    LMX.reg[35] = 0b0011000100000000    #Enable Mash Reset and Set MASH order
    LMX.reg[36] = 60                    #Setting INT value
    LMX.reg[37] = 0x500                 #Setting PFD_DEL, only active whe PFD_DLY_MANUAL is 1, which it's NOT
    LMX.reg[38] = 0x00                  #MSBs PLL_DEN
    LMX.reg[39] = 0x3E8                 #LSBs of PLL_DEN
    LMX.reg[40] = 0x00                  #MSBs MASH seed
    LMX.reg[41] = 0x00                  #LSBs MASH seed
    LMX.reg[42] = 0x00                  #MSBs PLL_NUM
    LMX.reg[43] = 0x00                  #LSBs PLL_NUM
    LMX.reg[44] = 0x00                  #MSBs INSTCAL_PLL  2^32*(PLL_NUM/PLL_DEN)
    LMX.reg[45] = 0x00                  #LSBs INSTCAL_PLL
    LMX.reg[46] = 0x300                 #Reserved
    LMX.reg[47] = 0x300                 #Reserved
    LMX.reg[48] = 0x4180                #Reserved
    LMX.reg[49] = 0x00                  #Reserved
    LMX.reg[50] = 0x50                  #Reserved
    LMX.reg[51] = 0x203F                #Reserved
    LMX.reg[52] = 0x00                  #Reserved
    LMX.reg[53] = 0x00                  #Reserved
    LMX.reg[54] = 0x00                  #Reserved
    LMX.reg[55] = 0x02                  #Reserved
    LMX.reg[56] = 0x01                  #Reserved
    LMX.reg[57] = 0x01                  #Disabling PFDIN input
    LMX.reg[58] = 0x00                  #Reserved
    LMX.reg[59] = 0x1388                #Reserved
    LMX.reg[60] = 0x1F4                 #Reserved
    LMX.reg[61] = 0x3E8                 #Reserved
    LMX.reg[62] = 0x00                  #MSBs MASH_RST_COUNT
    LMX.reg[63] = 0xC350                #LSBs MASH_RST_COUNT
    LMX.reg[64] = 0x4080                #Disabling System REF
    LMX.reg[65] = 0x01                  #Setting System Ref divider
    LMX.reg[66] = 0x3F                  #Setting 2 of 4 JESD registers, sum of 2 registers must be equal or greater than 63
    LMX.reg[67] = 0x00                  #Setting last 2 JESD regiseres as  zero
    LMX.reg[68] = 0x00                  #Disabling Phase Sync
    LMX.reg[69] = 0x11                  #Power Down System Refoutput buffer
    LMX.reg[70] = 0x1E                  #Setting Registers as double buffered, Changes to regs will only be enabled after a write to R0
    LMX.reg[71] = 0x00                  #Reserved
    LMX.reg[72] = 0x00                  #Reserved
    LMX.reg[73] = 0x00                  #Reserved
    LMX.reg[74] = 0x00                  #Reserved
    LMX.reg[75] = 0x00                  #Reserved
    LMX.reg[76] = 0x00                  #Reserved
    LMX.reg[77] = 0b0000011000001000    #Mute Pin Polarity
    LMX.reg[78] = 0x01                  #Output A enabled and OutA Mux set to VCO
    LMX.reg[79] = 0x11E                 #Power Down B, OutB Mux set to VCO, Max power outputA
    LMX.reg[80] = 0x1C0                 #Output B max power
    LMX.reg[81] = 0x00                  #Reserved
    LMX.reg[82] = 0x00                  #Reserved
    LMX.reg[83] = 0xF00                 #Reserved
    LMX.reg[84] = 0x40                  #Reserved
    LMX.reg[85] = 0x00                  #Reserved
    LMX.reg[86] = 0x40                  #Reserved
    LMX.reg[87] = 0xFF00                #Reserved
    LMX.reg[88] = 0x3FF                 #Reserved
    LMX.reg[89] = 0x00                  #Reserved
    LMX.reg[90] = 0x00                  #Reserved
    LMX.reg[91] = 0x00                  #Reserved
    LMX.reg[92] = 0x00                  #Reserved
    LMX.reg[93] = 0x1000                #Reserved
    LMX.reg[94] = 0x00                  #Reserved
    LMX.reg[95] = 0x00                  #Reserved
    LMX.reg[96] = 0x17F8                #Reserved
    LMX.reg[97] = 0x00                  #Reserved
    LMX.reg[98] = 0x1C80                #Reserved
    LMX.reg[99] = 0x19B9                #Reserved
    LMX.reg[100] = 0x533                #Reserved
    LMX.reg[101] = 0x3E8                #Reserved
    LMX.reg[102] = 0x28                 #Reserved
    LMX.reg[103] = 0x14                 #Reserved
    LMX.reg[104] = 0x14                 #Reserved
    LMX.reg[105] = 0x0A                 #Reserved
    LMX.reg[106] = 0x00                 #Reserved
    LMX.reg[107] = 0x00                 #Reserved
    LMX.reg[108] = 0x00                 #Reserved
    LMX.reg[109] = 0x00                 #Reserved
    LMX.reg[110] = 0x1F                 #Reserved
    LMX.reg[111] = 0x00                 #Reserved
    LMX.reg[112] = 0xFFFF               #Reserved
    LMX.reg[113] = 0x00                 #Reserved
    LMX.reg[114] = 0x00                 #Reserved
    LMX.reg[115] = 0x00                 #Reserved
    LMX.reg[116] = 0x00                 #Reserved
    LMX.reg[117] = 0x00                 #Reserved
    LMX.reg[118] = 0x00                 #Reserved
    LMX.reg[119] = 0x00                 #Reserved
    LMX.reg[120] = 0x00                 #Reserved
    LMX.reg[121] = 0x00                 #Reserved
    LMX.reg[122] = 0x00                 #Reserved

#Calculating hew INT NUM and DEN values for a new frequency request within VCO range
#VCO range limits 5.65 - 11.3 GHz
def LMX2820calcIntNumDen(LMX,newFreq):
    newParams = fraction()
    Fpfd = LMX.RefFREQ * (((1+LMX.RefDoubler)*LMX.RefMultipler) / (LMX.PreRDiv*LMX.PostRDiv))    #Calculating Phase Frequency detector frequency
    #print("PFD frequency: ",Fpfd)
    if newFreq < 5.65e9 or newFreq > 11.3e9:                                                        #Testing if reqeuested frequency falls within VCO range
        INT = 60                                                                                #If not, set the output values for default frequency of 6 GHz
        NUM = 0
        DEM = 1
        print("Frequency outside VCO range")
    else:
        createdReducedFraction(newParams,newFreq/Fpfd)
        INT = newParams.WHOLE
        NUM = newParams.NUM
        DEM = newParams.DEM
    RFout = Fpfd * (INT + (NUM/DEM))                                              #Calculating the real RF frequency out
    return [INT,NUM, DEM,RFout] 

#Setting the registers for a new frequency request
#Sets dividers and mux for frequency requests down to 44.140265 MHz
#Max frequency 22.6 GHz.
def LMX2820setREGSforNewFreq(LMX,newFreq):
    outputDividerIndex = 0                                                 #Defining an index to use for output divider
    if newFreq < 44.140265e6 or newFreq > 22.6e9:                          #Making sure the requested freuqency falls withing accetable range
        realFreq = 6e9                                                     #If not, defining the real freuency as 6 GHz
        LMX.reg[78] = modifyBM(LMX.reg[78],1,0,2)                          #Setting output_A mux to VCO
        LMX.reg[1] = modifyBM(LMX.reg[1],0,1,1)                            #Setting InstaCal_2x to normal operation
    elif newFreq >= 5.65e9 and newFreq <= 11.3e9:                          #If the requested freuqnecy falls withing the VCO range, 
        realFreq = newFreq                                                 #define the real ferquency as the reqeusted frequency
        LMX.reg[78] = modifyBM(LMX.reg[78],1,0,2)                          #Setting output_A mux to VCO
        LMX.reg[1] = modifyBM(LMX.reg[1],0,1,1)                            #Setting InstaCal_2x to normal operation
    elif newFreq >11.3e9 and newFreq <= 22.6e9:                             #If the requested freuqnecy falls within 2x VCO range,
        realFreq = newFreq/2                                               #Set realFreq as half desired frequency
        LMX.reg[78] = modifyBM(LMX.reg[78],2,0,2)                          #Setting output_A mux to doubler
        LMX.reg[1] = modifyBM(LMX.reg[1],1,1,1)                            #Setting InstaCal_2x to doubler engaged operation
    else:                                                                  #If the requested freuqnecy needs the divider outputs
        LMX.reg[78] = modifyBM(LMX.reg[78],0,0,2)                          #Set output_A mux to Channel Divider
        while newFreq*LMX.DividerLUT[outputDividerIndex]<5.65e9:            #Loop through the divider lookup table to find the necessary divider to reach the VCO range
            outputDividerIndex=outputDividerIndex+1
        realFreq = newFreq*LMX.DividerLUT[outputDividerIndex]              #Define the real frequency as the requested frequency * the necessary divider
        LMX.reg[32] = modifyBM(LMX.reg[32],outputDividerIndex,6,3)         #Setting VCO divider value
        LMX.reg[1] = modifyBM(LMX.reg[1],0,1,1)                            #Setting InstaCal_2x to normal operation
    #print(newFreq,realFreq, outputDividerIndex,BMofNumber(LMX.reg[78],0,2))    #Debug
    newParams = LMX2820calcIntNumDen(LMX,realFreq)                         #Calculating new INT, NUM, DEN for the real frequency
    #print("INT, NUM, DEM, RealFreq")
    #print(newParams)                                                       #Debug
    if newParams[1] == 0:
        LMX.reg[35] = modifyBM(LMX.reg[35],0,7,2)                          #Seting Mash_Order to zero if system in is Interger mode (NUM = 0)
        LMX.reg[35] = modifyBM(LMX.reg[35],0,12,1)                          #Seting Mash_Reset to zero if system in is Interger mode (NUM = 0)
    elif newParams[2] <=7 and newParams[1] != 0:
        LMX.reg[35] = modifyBM(LMX.reg[35],1,7,2)                          #Seting MASH modulator to first order if DEN < 7
        LMX.reg[35] = modifyBM(LMX.reg[35],1,12,1)                          #Seting Mash_Reset to zero if system in is fractional mode
    elif newParams[2] >7 and newParams[1] != 0:
        LMX.reg[35] = modifyBM(LMX.reg[35],2,7,2)                          #Seting MASH modulator to second order if DEN > 7
        LMX.reg[35] = modifyBM(LMX.reg[35],1,12,1)                          #Seting Mash_Reset to zero if system in is fractional mode
    LMX.reg[42] = BMofNumber(newParams[1],16,16)                          #Setting MSBs of NUM
    LMX.reg[43] = BMofNumber(newParams[1],0,16)                           #Setting LSBs of NUM
    LMX.reg[38] = BMofNumber(newParams[2],16,16)                          #Setting MSBs of DEN
    LMX.reg[39] = BMofNumber(newParams[2],0,16)                           #Setting LSBs of DEN
    LMX.reg[36] = BMofNumber(newParams[0],0,15)                           #Setting INT
    INSTCAL_PLL = int(pow(2,32)*(newParams[1]/newParams[2]))              #calculating new INSCAL_PLL number
    LMX.reg[44] = BMofNumber(INSTCAL_PLL,16,16)                           #Setting INSTCAL MSB
    LMX.reg[45] = BMofNumber(INSTCAL_PLL,0,16)                            #Setting INSTCAL LSB
    
#Write a single register to the LMX
def LMX2820WriteSingeRegister(spi, CS, LMX, address, NewValue):
    byts2write = bytearray()
    byts2write.append(parseBytes(address,1)[0])  # Split the address into 1 byte (step seems useless, but some chips use more than 1 byte)
    parsedData = parseBytes(NewValue,2)        # Split NewValue into two bytes
    byts2write.append(parsedData[0])           # Append MSB of NewValue to bytes2Write
    byts2write.append(parsedData[1])           # Append LSB of NewValue to bytes2Write
    CS.value(0)                             # Pulling SPI Chip select low for start data
    spi.write(byts2write)                      # Write the address and new value bytes
    CS.value(1)                             # Pulling SPI CS back high   
 
def dummyRead(LMX,spi,cs):
    dummyMessage = bytearray()
    dummyMessage.append(0x80)
    cs.value(0)                             # Pulling SPI Chip enable low for start data
    spi.write(dummyMessage)                      # Write the address and new value bytes
    dummyData = spi.read(2)
    cs.value(1)

 
#Function to start up the LMX
#Initializes registers to 6 GHz and writes regs in the order described in the datasheet
def LMX2820StartUp(LMX,spi,cs):
    LMX2820InitRegs(LMX)                                        #Writting inital register values 
    LMX2820setREGSforNewFreq(LMX,6e9)                           #Setting registers to 6 GHz
    LMX.reg[0] = modifyBM(LMX.reg[0],1,1,1)                     #Writting 1 to reset register
    LMX2820WriteSingeRegister(spi,cs,LMX,0,LMX.reg[0])                 #Tramsmitting reg 0
    LMX.reg[0] = modifyBM(LMX.reg[0],0,1,1)                     #Writting 0 to reset register
    LMX2820WriteSingeRegister(spi,cs,LMX,0,LMX.reg[0])                 #Tramsmitting reg 0
    for x in range(0,117):                                      #Transmitting initizlied registers from top (112) to bottom (0)
        LMX2820WriteSingeRegister(spi,cs,LMX,116-x,LMX.reg[116-x])
    time.sleep(10e-3)                                           #Waiting 10 ms per datasheet recommendation page 40
    LMX.reg[0] = modifyBM(LMX.reg[0],1,4,1)                     #Writting a 1 in FCal_En
    LMX2820WriteSingeRegister(spi,cs,LMX,0,LMX.reg[0])                 #Tramsmitting reg 0

#Fuction to change the frequency fo the LMX
#Full frequency range allowed, 44.2 MHz to 22.6GHz
#Fucntion writes necessary registers and sends new values to the LMX
#Function ends by writting a 1 to the FCAl to lock new frequency value
def LMX2820ChangeFreq(spi,cs,LMX,newFreq):
    LMX2820setREGSforNewFreq(LMX,newFreq)
    for x in range(0,80):                       
        LMX2820WriteSingeRegister(spi,cs,LMX,79-x,LMX.reg[79-x])
    time.sleep(10e-3)
    LMX.reg[0] = modifyBM(LMX.reg[0],1,4,1)                 #Writting a 1 in FCal_En
    LMX2820WriteSingeRegister(spi,cs,LMX,0,LMX.reg[0])

#OutA_Enable: 0 = PWR UP, 1 = PWR DWN
#OutA_Mux: 0 = Channel Divider, 1 = VCO output, 2= doubled output
#OutA_PWR: 7 is max 0 is min
#OutB parameters mimic A
#BDiv  Channel B divider: 0-6 Allowed, divider value =  2^(Bdiv value+1)
def LMX2820ChangeOutputSettings(spi,cs,LMX, OutA_En=0, OutA_Mux=1, OutA_PWR=7, OutB_En=1, OutB_Mux=1, OutB_PWR=7,BDiv = 0):
    LMX.reg[78] = modifyBM(LMX.reg[78],OutA_En,4,1)
    LMX.reg[78] = modifyBM(LMX.reg[78],OutA_Mux,0,2)
    LMX.reg[79] = modifyBM(LMX.reg[79],OutA_PWR,1,3)
    LMX.reg[79] = modifyBM(LMX.reg[79],OutB_En,8,1)
    LMX.reg[79] = modifyBM(LMX.reg[79],OutB_Mux,4,2)
    LMX.reg[80] = modifyBM(LMX.reg[80],OutB_PWR,6,3)
    LMX.reg[32] = modifyBM(LMX.reg[32],BDiv,9,3)
    for x in range(0,81):                       
        LMX2820WriteSingeRegister(spi,cs,LMX,80-x,LMX.reg[80-x])

#Tuning off or on Channel A
#OutA_Enable: 0 = PWR UP, 1 = PWR DWN
def LMX2820chARFOnOff(spi,cs,LMX, OutA_En=0):
    LMX.reg[78] = modifyBM(LMX.reg[78],OutA_En,4,1)
    for x in range(0,81):                       
        LMX2820WriteSingeRegister(spi,cs,LMX,80-x,LMX.reg[80-x])

#Tuning off or on RF Channel B
#OutA_Enable: 0 = PWR UP, 1 = PWR DWN
def LMX2820chBRFOnOff(spi,cs,LMX,OutB_En=1):
    LMX.reg[79] = modifyBM(LMX.reg[79],OutB_En,8,1)
    for x in range(0,81):                       
        LMX2820WriteSingeRegister(spi,cs,LMX,80-x,LMX.reg[80-x])
        
#Change Output Powers and Channel B settings
#OutA_PWR: 7 is max 0 is min
#OutB parameters mimic A
#BDiv  Channel B divider: 0-6 Allowed, divider value =  2^(Bdiv value+1)
def LMX2820ChangeSettings(spi,cs,LMX, OutA_PWR=7, OutB_Mux=1, OutB_PWR=7,BDiv = 0):
    LMX.reg[79] = modifyBM(LMX.reg[79],OutA_PWR,1,3)
    LMX.reg[79] = modifyBM(LMX.reg[79],OutB_Mux,4,2)
    LMX.reg[80] = modifyBM(LMX.reg[80],OutB_PWR,6,3)
    LMX.reg[32] = modifyBM(LMX.reg[32],BDiv,9,3)
    for x in range(0,81):                       
        LMX2820WriteSingeRegister(spi,cs,LMX,80-x,LMX.reg[80-x])


'''
spi = machine.SPI(0, baudrate = 250000, polarity = 0, phase = 0,bits = 8,
                  firstbit = machine.SPI.MSB,
                  sck = machine.Pin(18),
                  mosi = machine.Pin(19),
                  miso = machine.Pin(16))
LMX = LMX2820(100e6, 0, 1, 1, 1, 20)
CSpin = machine.Pin(LMX.LEpin, machine.Pin.OUT)
CSpin.value(1)

dummyRead(LMX,spi,CSpin)

LMX2820StartUp(LMX,spi,CSpin)
'''

   

User avatar
OneMadGypsy
Posts: 359
Joined: Wed Apr 28, 2021 1:57 am
Location: New Orleans, Louisiana
Contact: Website

Re: Micropython SPI not acting as expected

Mon Sep 27, 2021 6:03 pm

LMX2820 class. 90% of the code is setting registers, those lines can be ignored

You should only post what is relevant in these situations. Providing a bunch of "noise" and saying "ignore it" is going to greatly reduce the amount of help you get. I'll give you undeniable proof. I had interest in helping you, stopped to write this the moment I came to that part, and I'm not going back to figure out what the 10% I should be paying attention to is. Time is precious. Help me help you by saving me as much of it as you can.

How would you format this question if you were posting it on StackOverflow? Following those guidelines would make this a good question, and you would likely get good answers. I'm hypothetically flagging this question as "needs improvement". Actually, your related question that actually is on SO was closed for similar reasons. Except, on that one you posted all of the code except for the actual part you were referring to. You got so beat up with down votes that I didn't have the heart to add one of my own.

You may also want to consider that SO was a bad place to post that question because, how do you give code with reproducible errors revolving around a part that you have to assume none of your respondents have? You were in a bit of a catch 22 with that one. You would have had to figure out a way to eliminate your part from the equation, but still reproduce the problem.
"Focus is a matter of deciding what things you're not going to do." ~ John Carmack

Return to “MicroPython”