News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

SX1268 or LLCC68 LoRA device help.

Started by top204, Dec 15, 2024, 12:46 PM

Previous topic - Next topic

top204

Hello

Has anyone used an SX1268 or LLCC68 LoRa device with Positron or Proton?

I am having difficulties getting them working.

I wrote code for the SX1278 LoRa devices acting as a USART no problem, but the 68 devices seem to be a bit more different for standard LoRa operating as a USART, and I just cannot get my head around it.

The interface is standard Mode 0-0 SPI using a software mechanism to make sure it is operating as it should, but I am not getting the correct responses when writing and reading the SX1268 registers?

All pins have been checked and all CS (NSS in the SX devices), clock, and MOSI/MISO pulses are OK, but all I get from the device is the same value of either $C8 or $A5. There is a sequence to read or write the registers which I am sure I have followed correctly with the op-code then register value etc, but still get no results?.

I know, once I find the problem it is going to be one of those "Of Course" moments, but until then I am in "cannot see the forest bacause of the trees" mode.

Looking at the C++ code available, it is all over-bloated gibberish for a straightforware SPI interface and mechanism, and it even confuses the heck out me, so it is really hard to follow it. It also uses the device peripherals for the SPI, but in the form of streams and handles and indirect pointers to buffers instead of just sending a command value, and all of that rubbish on the bloated object oriented languages.

Thanks
Les

trastikata

Hello Les,

This is a code I wrote some time ago for a friend who wanted to use SX1268 instead the SX1278. However I did not have any devices at hand by the time and just wrote it as I thought it should be without being able to test it.

With something minor to correct (I think it was the frequency calculation or order to send but I am not 100% sure), the code worked and he had built his device. Here's the code:

Device = 18F27Q43

Declare Xtal = 4

'======================================= Ports declared =======================================
Symbol NCS = PORTA.0
Output NCS
Symbol BUSY = PORTA.1
Output BUSY
Symbol NRESET = PORTA.2
Output NRESET
Symbol SCLK = PORTA.3
Output SCLK
Symbol MOSI = PORTA.4
Output MOSI
Symbol MISO = PORTB.0
Input MISO
Symbol DIO1 = PORTB.1
Input DIO1

'======================================= Variables declared =======================================
Dim ModemMode As Bit        'Select TX or RX
Dim ByteArray[20] As Byte   'Create a 20 byte array
Dim bTemp As Byte           'Create a byte temporary variable

'======================================= Aliases =======================================
'SX126X SPI commands
' operational modes commands
Symbol CMD_NOP                               = 0x00
Symbol CMD_SET_SLEEP                         = 0x84
Symbol CMD_SET_STANDBY                       = 0x80
Symbol CMD_SET_FS                            = 0xC1
Symbol CMD_SET_TX                            = 0x83
Symbol CMD_SET_RX                            = 0x82
Symbol CMD_STOP_TIMER_ON_PREAMBLE            = 0x9F
Symbol CMD_SET_RX_DUTY_CYCLE                 = 0x94
Symbol CMD_SET_CAD                           = 0xC5
Symbol CMD_SET_TX_CONTINUOUS_WAVE            = 0xD1
Symbol CMD_SET_TX_INFINITE_PREAMBLE          = 0xD2
Symbol CMD_SET_REGULATOR_MODE                = 0x96
Symbol CMD_CALIBRATE                         = 0x89
Symbol CMD_CALIBRATE_IMAGE                   = 0x98
Symbol CMD_SET_PA_CONFIG                     = 0x95
Symbol CMD_SET_RX_TX_FALLBACK_MODE           = 0x93

'register and buffer access commands
Symbol CMD_WRITE_REGISTER                    = 0x0D
Symbol CMD_READ_REGISTER                     = 0x1D
Symbol CMD_WRITE_BUFFER                      = 0x0E
Symbol CMD_READ_BUFFER                       = 0x1E

'DIO and IRQ control
Symbol CMD_SET_DIO_IRQ_PARAMS                = 0x08
Symbol CMD_GET_IRQ_STATUS                    = 0x12
Symbol CMD_CLEAR_IRQ_STATUS                  = 0x02
Symbol CMD_SET_DIO2_AS_RF_SWITCH_CTRL        = 0x9D
Symbol CMD_SET_DIO3_AS_TCXO_CTRL             = 0x97

'RF, modulation and packet commands
Symbol CMD_SET_RF_FREQUENCY                  = 0x86
Symbol CMD_SET_PACKET_TYPE                   = 0x8A
Symbol CMD_GET_PACKET_TYPE                   = 0x11
Symbol CMD_SET_TX_PARAMS                     = 0x8E
Symbol CMD_SET_MODULATION_PARAMS             = 0x8B
Symbol CMD_SET_PACKET_PARAMS                 = 0x8C
Symbol CMD_SET_CAD_PARAMS                    = 0x88
Symbol CMD_SET_BUFFER_BASE_ADDRESS           = 0x8F
Symbol CMD_SET_LORA_SYMB_NUM_TIMEOUT         = 0xA0

Symbol PA_CONFIG_SX1261                      = 0x01
Symbol PA_CONFIG_SX1262                      = 0x00

'status commands
Symbol CMD_GET_STATUS                        = 0xC0
Symbol CMD_GET_RSSI_INST                     = 0x15
Symbol CMD_GET_RX_BUFFER_STATUS              = 0x13
Symbol CMD_GET_PACKET_STATUS                 = 0x14
Symbol CMD_GET_DEVICE_ERRORS                 = 0x17
Symbol CMD_CLEAR_DEVICE_ERRORS               = 0x07
Symbol CMD_GET_STATS                         = 0x10
Symbol CMD_RESET_STATS                       = 0x00


'SX126X register map
Symbol REG_WHITENING_INITIAL_MSB             = 0x06B8
Symbol REG_WHITENING_INITIAL_LSB             = 0x06B9
Symbol REG_CRC_INITIAL_MSB                   = 0x06BC
Symbol REG_CRC_INITIAL_LSB                   = 0x06BD
Symbol REG_CRC_POLYNOMIAL_MSB                = 0x06BE
Symbol REG_CRC_POLYNOMIAL_LSB                = 0x06BF
Symbol REG_SYNC_WORD_0                       = 0x06C0
Symbol REG_SYNC_WORD_1                       = 0x06C1
Symbol REG_SYNC_WORD_2                       = 0x06C2
Symbol REG_SYNC_WORD_3                       = 0x06C3
Symbol REG_SYNC_WORD_4                       = 0x06C4
Symbol REG_SYNC_WORD_5                       = 0x06C5
Symbol REG_SYNC_WORD_6                       = 0x06C6
Symbol REG_SYNC_WORD_7                       = 0x06C7
Symbol REG_NODE_ADDRESS                      = 0x06CD
Symbol REG_BROADCAST_ADDRESS                 = 0x06CE
Symbol REG_LORA_SYNC_WORD_MSB                = 0x0740
Symbol REG_LORA_SYNC_WORD_LSB                = 0x0741
Symbol REG_RANDOM_NUMBER_0                   = 0x0819
Symbol REG_RANDOM_NUMBER_1                   = 0x081A
Symbol REG_RANDOM_NUMBER_2                   = 0x081B
Symbol REG_RANDOM_NUMBER_3                   = 0x081C
Symbol REG_RX_GAIN                           = 0x08AC
Symbol REG_OCP_CONFIGURATION                 = 0x08E7
Symbol REG_XTA_TRIM                          = 0x0911
Symbol REG_XTB_TRIM                          = 0x0912

'CMD_CALIBRATE_IMAGE
Symbol CAL_IMG_430_MHZ_1                     = 0x6B
Symbol CAL_IMG_430_MHZ_2                     = 0x6F
Symbol CAL_IMG_470_MHZ_1                     = 0x75
Symbol CAL_IMG_470_MHZ_2                     = 0x81
Symbol CAL_IMG_779_MHZ_1                     = 0xC1
Symbol CAL_IMG_779_MHZ_2                     = 0xC5
Symbol CAL_IMG_863_MHZ_1                     = 0xD7
Symbol CAL_IMG_863_MHZ_2                     = 0xDB
Symbol CAL_IMG_902_MHZ_1                     = 0xE1
Symbol CAL_IMG_902_MHZ_2                     = 0xE9


'======================================= MAIN PROGRAM =======================================
Main:
'Reset chip
    Low NRESET : DelayMS 100 : High NRESET

'Wait for SX126x to boot
    While BUSY = 1 : Wend

'Set chip common operational mode parameters
    SetLoraSx1268Common()   

'Select settings for RX or TX and go to the corresponding sub routine
    If ModemMode = 1 Then
        RxSettings()     'Use Receiver specific settings 
        GoTo RxPacket   
    Else
        TxSettings()     'Use Transmitter specific settings 
        GoTo TxPacket 
    EndIf
       

'Transmit a packet of 20 bytes array   
TxPacket:
    'Fill the byte array with data 0 to 19
    For bTemp = 0 To 19
        ByteArray[bTemp] = bTemp
    Next
   
    'Send data from the Byte Array to the TX buffer at offset 0
    Low NCS : DelayCS 4
        SpiSend(CMD_WRITE_BUFFER)   
        SpiSend(0x00)                             
        For bTemp = 0 To 19
            SpiSend(ByteArray[bTemp])
        Next
    High NCS : DelayCS 4
   
    'set the device in transmit mode
    SetTX()
   
    'Wait for IRQ on TXDone
    While DIO1 = 0 : Wend
   
    'Clear the IRQ
    ClearIrq()
   
    GoTo EndOfProgram

'Receive a packet of 20 bytes array   
RxPacket: 
    'Wait for IRQ on RXDone
    While DIO1 = 0 : Wend
   
    'Clear the IRQ
    ClearIrq()
   
    'Read data from the RX buffer at offset 0, NOP, and place it in the Byte Array
    Low NCS : DelayCS 4
        SpiSend(CMD_READ_BUFFER)   
        SpiSend(0x00)
        SpiSend(0x00)
        For bTemp = 0 To 19
            ByteArray[bTemp] = SpiReceive()
        Next
    High NCS : DelayCS 4
   
    GoTo EndOfProgram         

'End of program = perpetual loop
EndOfProgram:
    While 1 = 1 : Wend

   



'======================================= Procedures and commands =======================================   

'Receiver specific settings
Proc RxSettings()
    'Rx Gain Configuration to Rx Boosted gain
    WriteReg1Byte(REG_RX_GAIN, 0x96)
    WaitForNotBusy()
   
    'Configure DIO and IRQ --> RxDone IRQ mapped To DIO1
    SpiWrite1Byte4Word(CMD_SET_DIO_IRQ_PARAMS, 0x0002, 0x0002, 0x0000, 0x0000)
    WaitForNotBusy()
   
    'Clear the IRQ if any
    ClearIrq()
   
    'Set device in receiver mode with no timeout
    SetRX()
EndProc

'Transmitter specific settings
Proc TxSettings()
    'Define the Power Amplifier configuration for +22 dBm
    SpiWrite1Byte4Byte(CMD_SET_PA_CONFIG , 0x04, 0x07, 0x00, 0x01)
    WaitForNotBusy() 
   
    'Define output power +22 dBm and ramping time 80uS
    SpiWrite1Byte2Byte(CMD_SET_TX_PARAMS, 0x16, 0x03)
    WaitForNotBusy()
   
    'Set Over Current Protection to 140mA
    WriteReg1Byte(REG_OCP_CONFIGURATION, 0x38)
    WaitForNotBusy()
   
    'Configure DIO and IRQ --> TxDone IRQ mapped To DIO1
    SpiWrite1Byte4Word(CMD_SET_DIO_IRQ_PARAMS, 0x0001, 0x0001, 0x0000, 0x0000)
    WaitForNotBusy()
   
    'Clear the IRQ if any
    ClearIrq()
EndProc


'Common LoRa settings
Proc SetLoraSx1268Common()
    'Start image calibration over the band 430-440 MHz
    SpiWrite1Byte2Byte(CMD_CALIBRATE_IMAGE, CAL_IMG_430_MHZ_1, CAL_IMG_470_MHZ_2)
    WaitForNotBusy() 
   
    'Go to Standby - STDBY_XOSC mode
    SpiWrite1Byte1Byte(CMD_SET_STANDBY, 0x01)
    WaitForNotBusy()
   
    'Define the protocol as LoRa 
    SpiWrite1Byte1Byte(CMD_SET_PACKET_TYPE, 0x01)
    WaitForNotBusy()
   
    'Define the RF frequency as RFfrequency=(RFFreq*FXTAL)/2^25
    '433Mhz, 32MHz crystal --> RFfrequency=(433000000*32000000)/(2^25) = 33554432
    SpiWrite1Byte1DWord(CMD_SET_RF_FREQUENCY, 33554432)
    WaitForNotBusy() 
   
    'Define the modulation parameter
    'Mod Param1 --> SF = 11
    'Mod Param2 --> BW = 62.50 kHz
    'Mod Param3 --> CR = 4/8
    'Mod Param4 --> LowDataRateOptimize = ON
    SpiWrite1Byte4Byte(CMD_SET_MODULATION_PARAMS, 0x0B, 0x03, 0x04, 0x01)
    WaitForNotBusy()
   
    'Define the packet format
    'Pack Param1 --> PreambleLength (15:8) = 0
    'Pack Param2 --> PreambleLength (7:0) = 15
    'Pack Param3 --> HeaderType = Fixed length packet (implicit header)
    'Pack Param4 --> PayloadLength = 20 bytes (14 hex)
    'Pack Param5 --> CRC = ON
    'Pack Param6 --> InvertIQ = Standard IQ setup
    SpiWrite1Byte6Byte(CMD_SET_PACKET_PARAMS, 0x00, 0x0F, 0x01, 0x14, 0x01, 0x00)
    WaitForNotBusy()
   
    'Define Sync Word value to 0x79 and write in Sync Word Byte 0 
    WriteReg1Byte(REG_SYNC_WORD_0, 0x79)
    WaitForNotBusy()
   
    'Define where the data payload will be stored in buffer
    'For maximum capacity TX and RX will use the same address of 0 and will have 256 bytes space
    SpiWrite1Byte2Byte(CMD_SET_BUFFER_BASE_ADDRESS, 0x00, 0x00)
    WaitForNotBusy()
EndProc

'Write to register XXXX 1 data byte
Proc WriteReg1Byte(SpiAddress As Word, SpiData1 As Byte)
    Low NCS : DelayCS 4
        SpiSend(CMD_WRITE_REGISTER)
        SpiSend(SpiAddress.Byte1)
        SpiSend(SpiAddress.Byte0)
        SpiSend(SpiData1)
    High NCS : DelayCS 4
EndProc

'Send one address/command as byte and one parameter DWord(32bit)
Proc SpiWrite1Byte1DWord(SpiAddress As Byte, SpiData As Dword)
    Low NCS : DelayCS 4
        SpiSend(SpiAddress)
        SpiSend(SpiData.Byte3)
        SpiSend(SpiData.Byte2)
        SpiSend(SpiData.Byte1)
        SpiSend(SpiData.Byte0)
    High NCS : DelayCS 4
EndProc

'Send one address/command as byte and one 4 parameter Word(16bit)
Proc SpiWrite1Byte4Word(SpiAddress As Byte, SpiData1 As Word, SpiData2 As Word, SpiData3 As Word, SpiData4 As Word)
    Low NCS : DelayCS 4
        SpiSend(SpiAddress)
        SpiSend(SpiData1.Byte1)
        SpiSend(SpiData1.Byte0)
        SpiSend(SpiData2.Byte1)
        SpiSend(SpiData2.Byte0)
        SpiSend(SpiData3.Byte1)
        SpiSend(SpiData3.Byte0)
        SpiSend(SpiData4.Byte1)
        SpiSend(SpiData4.Byte0)
    High NCS : DelayCS 4
EndProc

'Send one address/command as byte and one parameter byte
Proc SpiWrite1Byte1Byte(SpiAddress As Byte, SpiData1 As Byte)
    Low NCS : DelayCS 4
        SpiSend(SpiAddress)
        SpiSend(SpiData1)
    High NCS : DelayCS 4
EndProc

'Send one address/command as byte and two parameter bytes
Proc SpiWrite1Byte2Byte(SpiAddress As Byte, SpiData1 As Byte, SpiData2 As Byte)
    Low NCS : DelayCS 4
        SpiSend(SpiAddress)
        SpiSend(SpiData1)
        SpiSend(SpiData2)
    High NCS : DelayCS 4
EndProc

'Send one address/command as byte and four parameter bytes
Proc SpiWrite1Byte4Byte(SpiAddress As Byte, SpiData1 As Byte, SpiData2 As Byte, SpiData3 As Byte, SpiData4 As Byte)
    Low NCS : DelayCS 4
        SpiSend(SpiAddress)
        SpiSend(SpiData1)
        SpiSend(SpiData2)
        SpiSend(SpiData3)
        SpiSend(SpiData4)
    High NCS : DelayCS 4
EndProc

'Send one address/command as byte and six parameter bytes
Proc SpiWrite1Byte6Byte(SpiAddress As Byte, SpiData1 As Byte, SpiData2 As Byte, SpiData3 As Byte, SpiData4 As Byte, SpiData5 As Byte, SpiData6 As Byte)
    Low NCS : DelayCS 4
        SpiSend(SpiAddress)
        SpiSend(SpiData1)
        SpiSend(SpiData2)
        SpiSend(SpiData3)
        SpiSend(SpiData4)
        SpiSend(SpiData5)
        SpiSend(SpiData6)
    High NCS : DelayCS 4
EndProc

'Wait until ready to receive ne command
Proc WaitForNotBusy()
    While BUSY = 1 : Wend
EndProc

'Clear IRQ
Proc ClearIrq()
    Low NCS : DelayCS 4
        SpiSend(CMD_CLEAR_IRQ_STATUS)
        SpiSend(0xFF)
        SpiSend(0xFF)
    High NCS : DelayCS 4
    WaitForNotBusy()
EndProc

'Set receiver mode with no timeout
Proc SetRX()
    Low NCS : DelayCS 4
        SpiSend(CMD_SET_RX)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High NCS : DelayCS 4
EndProc

'Set transmitter mode with no timeout
Proc SetTX()
    Low NCS : DelayCS 4
        SpiSend(CMD_SET_TX)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High NCS : DelayCS 4
EndProc

'Software SPI send
Proc SpiSend(SpiData As Byte)
    MOSI = SpiData.7 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
    MOSI = SpiData.6 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
    MOSI = SpiData.5 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
    MOSI = SpiData.4 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
    MOSI = SpiData.3 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
    MOSI = SpiData.2 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
    MOSI = SpiData.1 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
    MOSI = SpiData.0 : DelayCS 4 : High SCLK : DelayCS 4 : Low SCLK : DelayCS 4
EndProc   

'Software SPI receive
Proc SpiReceive(), Byte
    High SCLK : DelayCS 4 : Result.7 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
    High SCLK : DelayCS 4 : Result.6 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
    High SCLK : DelayCS 4 : Result.5 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
    High SCLK : DelayCS 4 : Result.4 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
    High SCLK : DelayCS 4 : Result.3 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
    High SCLK : DelayCS 4 : Result.2 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
    High SCLK : DelayCS 4 : Result.1 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
    High SCLK : DelayCS 4 : Result.0 = MISO : DelayCS 4 : Low SCLK : DelayCS 4
EndProc   



top204

Many thanks Dyanko, I'll give it a try later this morning.

The mechanisms for reading and writing registers looks just like what I have been doing without success, but one never knows until one tries. :-)

I once created SPI read and write routines using Pin Setting and Clearing and Reading inline like yous, many years ago, to make it fast to talk to other devices, when the SPI peripheral was set as slave so it could not easily be used to talk to other slaves as a master as well.