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.

Werwolf

Hello Les,
I am using LLCC64 and SX1268 with PIC16F15Q40 (modules E220-400MM22S and E22-400MM22S). I didn't have any problems with SPI, but there was a problem with the initialization of the modules (SPI bus responses were similar to yours). The problem was that all the examples state that CTXO is used, not standard quartz resonator (what is used in these modules). The problem was solved when the following procedure was unchecked during initialization (sorry for the C language, BASIC version at home):

void Ebyte_E22x_SetDio3AsTcxoCtrl( RadioTcxoCtrlVoltage_t tcxoVoltage, uint32e_t timeout )
{
    uint8e_t buf[4];

    buf[0] = tcxoVoltage & 0x07;
    buf[1] = ( uint8e_t )( ( timeout >> 16 ) & 0xFF );
    buf[2] = ( uint8e_t )( ( timeout >> 8 ) & 0xFF );
    buf[3] = ( uint8e_t )( timeout & 0xFF );

    Ebyte_E22x_WriteCommand( RADIO_SET_TCXOMODE, buf, 4 );
}

Best Regards
Alvydas

top204

#4
Many thanks.

I am still having problems with the SX1268 devices I have, and no code I create seems to work on them.

Trastikata, I changed your code so that the BUSY pin was set as a input and not an output, and added debug mechanisms in place, but still no luck.

I am starting to pull my hair out over this and nothing seems to make sense with the devices any more! The SX127x devices were very straightforward to get working as a USART, and they work nicely, but at the wrong frequencies and power, so it has to be the SX126x series.

Regards
Les

trastikata

Quote from: top204 on Dec 18, 2024, 11:54 AMThe SX127x devices were very straightforward to get working as a USART, and they work nicely, but at the wrong frequencies and power, so it has to be the SX126x series.

What do you mean by that Les? I've never had any troubles setting the power and frequency output on SX1278?

SX1278 requires 32 MHz clock source, however 32 MHz TCXOs are quite expensive where 26 MHz TCXO are quite ubiquitous and I've built bunch of tracking devices with 26 MHz TCXOs. Calculating the output frequency register is straightforward - just replacing 32 MHz with 26 MHz and the output frequency is correct.

However one drawback is that the bandwidth is a function of the reference clock and SX1278 devices set using the same settings, same output frequency, same bandwidth etc but different clock sources can't decode messages sent from one to the other.

Is it possible that in your device they used the non-standard TCXO?   

Les, this weekend I'll dig out an old SX1268 device which I left for testing some day and will see if I can do something about the settings.

Werwolf

The same formulae as for SX1278 cannot be used to calculate the frequency of SX1268 and LLCC64 because of the difference in the division factor.

trastikata

#7
Hello Les,

I found the SX1262 transmitter and receiver set I built in the past, but I'll have to rebuild the receiver because it seems I used it for something else and it will have to wait until the weekend. However the transmitter was complete and I did some coding.

In my code/device Symbol SW = PORTA.3 is the switch between TX and RX paths, so this pin not might not be relevant in your case.

This is working code for the SX1262 transmitter:

Device = 18F25J50

Config_Start
  WDTEN = OFF    ;Disabled - Controlled by SWDTEN bit
  PLLDIV = 5    ;Divide by 5 (20 MHz oscillator input)
  STVREN = On    ;Enabled
  XINST = OFF    ;Disabled
  Debug = OFF    ;Disabled
  CPUDIV = OSC1
  Cp0 = OFF    ;Program memory is not code-protected
  OSC = HSPLL    ;HS+PLL, USB-HS+PLL
  T1DIG = OFF    ;Secondary Oscillator clock source may not be selected
  LPT1OSC = OFF    ;High-power operation
  FCMEN = On    ;Disabled
  IESO = On    ;Disabled
  WDTPS = 32768    ;1:32768
  DSWDTOSC = INTOSCREF    ;DSWDT uses INTRC
  RTCOSC = T1OSCREF    ;RTCC uses T1OSC/T1CKI
  DSBOREN = On    ;Enabled
  DSWDTEN = OFF    ;Disabled
  DSWDTPS = G2    ;1:2,147,483,648 (25.7 days)
  IOL1WAY = OFF    ;The IOLOCK bit (PPSCON<0>) can be set and cleared as needed
  MSSP7B_EN = MSK7    ;7 Bit address masking mode
  WPFP = PAGE_31    ;Write Protect Program Flash Page 31
  WPEND = PAGE_WPFP    ;Page WPFP<5:0> through Configuration Words erase/write protected
  WPCFG = OFF    ;Configuration Words page not erase/write-protected
  WPDIS = OFF    ;WPFP<5:0>/WPEND region ignored
Config_End

Declare Xtal = 48

Declare Auto_Variable_Bank_Cross = On
Declare FSR_CONTEXT_SAVE = On
Declare LABEL_BANK_RESETS = On
Declare Optimiser_Level = 3
Declare Dead_Code_Remove = On
Declare Float_Display_Type = Large


Symbol DIO1 = PORTA.2
Input DIO1
Symbol MOSI = PORTA.5
Output MOSI
Symbol CS = PORTB.0
Output CS
Symbol MODEM_RESET = PORTB.1
Output MODEM_RESET
Symbol SCLK = PORTB.2
Output SCLK
Symbol MISO = PORTB.3
Input MISO
Symbol LED = PORTC.2
Output LED
Symbol SW = PORTA.3
Output SW
Symbol DIO0 = PORTA.1
Input DIO0

'======================================= 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

Dim baPayload[64] As Byte
Dim bPacketLen As Byte


Main:
    Clear
    Low LED : High CS : Low SCLK : High SW
    OSCTUNE.6 = 1 : DelayMS 500
    ANCON0 = %11111110 : ANCON1 = %00011111

    InitLoRa(435.321, 41.67, 11, 14, 16, 26, 0x64, 64)

    While 1 = 1
        ContructMessage()
        SendMessage()
        DelayMS 5000
    Wend


'fFrequency = Frequency in MHz (Ex: 430.8)
'fBandwidth = Standard LoRa BW (Ex: 31.25)
'bSpreadingFactor = LoRa spreading factor (Ex: 10)
'bPout = Power output (Ex: 14)
'bPreambleLength = Preamble length (Ex: 16)
'bSyncByte = LoRa sync word Byte0 (Ex: 0x64)
'bPacketLength = Packet length in bytes
Proc InitLoRa(fFrequency As Float, fBandwidth As Float, bSpreadingFactor As Byte, bPout As Byte, bPreambleLength As Byte, bCrystalFreq As Byte, bSyncByte As Byte, bPacketLength As Byte)
    Dim fTemp As Float
    Dim dTemp As Dword
    Dim CAL_IMG_FRQ1 As Byte
    Dim CAL_IMG_FRQ2 As Byte
       
    bPacketLen = bPacketLength
   
    'Reset chip
    Low MODEM_RESET : DelayMS 200 : High MODEM_RESET
   
    'Wait for SX126x to boot
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Set power mode to LDO + DC
    Low CS
        SpiSend(CMD_SET_REGULATOR_MODE)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Start calibration
    Low CS
        SpiSend(CMD_CALIBRATE)
        SpiSend(%01111111)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Start image calibration over the band Freq - 4 / Freq + 4 MHz
    fTemp = (fFrequency - 4) / 4
    CAL_IMG_FRQ1 = fTemp
    fTemp = (fFrequency + 7) / 4
    CAL_IMG_FRQ2 = fTemp
    Low CS
        SpiSend(CMD_CALIBRATE_IMAGE)
        SpiSend(CAL_IMG_FRQ1)
        SpiSend(CAL_IMG_FRQ2)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Go to Standby - STDBY_XOSC mode
    Low CS
        SpiSend(CMD_SET_STANDBY)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the protocol as LoRa 
    Low CS
        SpiSend(CMD_SET_PACKET_TYPE)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the RF frequency as RFfrequency=(RFFreq*FXTAL)/2^25
    fTemp = 33554432 / bCrystalFreq
    fTemp = fTemp * fFrequency
    dTemp = fTemp
    Low CS
        SpiSend(CMD_SET_RF_FREQUENCY)
        SpiSend(dTemp.Byte3)
        SpiSend(dTemp.Byte2)
        SpiSend(dTemp.Byte1)
        SpiSend(dTemp.Byte0)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the modulation parameter
    'Mod Param1 --> bSpreadingFactor
    'Mod Param2 --> Bandwidth
    'Mod Param3 --> CR = 4/8
    'Mod Param4 --> LowDataRateOptimize = ON
    Low CS
        SpiSend(CMD_SET_MODULATION_PARAMS)
        Select bSpreadingFactor
            Case 12
                SpiSend(0x0C)    '12
            Case 11
                SpiSend(0x0B)    '11
            Case 10
                SpiSend(0x0A)    '10
            Case 9
                SpiSend(0x09)    '9
            Case 8
                SpiSend(0x08)    '8
            Case 7
                SpiSend(0x07)    '7
            Case 6
                SpiSend(0x06)    '6
            Case 5
                SpiSend(0x05)    '5
        EndSelect
        Select fBandwidth
            Case 500
                SpiSend(0x06)    '500 
            Case 250
                SpiSend(0x05)    '250
            Case 125
                SpiSend(0x04)    '125
            Case 62.5
                SpiSend(0x03)    '62.5
            Case 41.67
                SpiSend(0x0A)    '41.7
            Case 31.25
                SpiSend(0x02)    '31.25
            Case 20.83
                SpiSend(0x09)    '20.8
            Case 15.63
                SpiSend(0x01)    '15.6
            Case 10.42
                SpiSend(0x08)    '10.4
            Case 7.81
                SpiSend(0x00)    '7.8
        EndSelect
        SpiSend(0x04)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the packet format
    'Pack Param1 --> PreambleLength (15:8) = 0
    'Pack Param2 --> PreambleLength (7:0) = bPreambleLength
    'Pack Param3 --> HeaderType = Fixed length packet (implicit header)
    'Pack Param4 --> bPacketLength
    'Pack Param5 --> CRC = ON
    'Pack Param6 --> InvertIQ = Standard IQ setup
    Low CS
        SpiSend(CMD_SET_PACKET_PARAMS)
        SpiSend(0x00)
        SpiSend(bPreambleLength)
        SpiSend(0x01)
        SpiSend(bPacketLength)
        SpiSend(0x01)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define Sync Word value and write in Sync Word Byte 0 
    Low CS
        SpiSend(CMD_WRITE_REGISTER )
        SpiSend(REG_LORA_SYNC_WORD_MSB.Byte1)
        SpiSend(REG_LORA_SYNC_WORD_MSB.Byte0)
        SpiSend(bSyncByte)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    '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
    Low CS
        SpiSend(CMD_SET_BUFFER_BASE_ADDRESS)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the Power Amplifier configuration for +22 dBm
    Low CS
        SpiSend(CMD_SET_PA_CONFIG)
        SpiSend(0x04)
        SpiSend(0x07)
        SpiSend(0x00)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define output power +22 dBm and ramping time 80uS
    Low CS
        SpiSend(CMD_SET_TX_PARAMS)
        Select bPout
            Case 15
                SpiSend(22)       'Set pout 15
            Case 14
                SpiSend(21)       'Set pout 14
            Case 13
                SpiSend(19)       'Set pout 13
            Case 12
                SpiSend(17)       'Set pout 12
            Case 11
                SpiSend(15)       'Set pout 11
            Case 10
                SpiSend(14)       'Set pout 10
            Case 9
                SpiSend(12)       'Set pout 9
            Case 8
                SpiSend(10)       'Set pout 8
            Case 7
                SpiSend(9)        'Set pout 7
            Case 6
                SpiSend(8)        'Set pout 6
            Case 5
                SpiSend(7)        'Set pout 5
            Case 4
                SpiSend(6)        'Set pout 4
            Case 3
                SpiSend(5)        'Set pout 3
            Case 2
                SpiSend(3)        'Set pout 2
            Case 1
                SpiSend(1)        'Set pout 1
            Case 0
                SpiSend(0)        'Set pout 0
        EndSelect
        SpiSend(0x03)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Set Over Current Protection to 140mA
    Low CS
        SpiSend(CMD_WRITE_REGISTER )
        SpiSend(REG_OCP_CONFIGURATION.Byte1)
        SpiSend(REG_OCP_CONFIGURATION.Byte0)
        SpiSend(0x38)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Modify TxClampConfig
    Low CS
        SpiSend(CMD_WRITE_REGISTER)
        SpiSend(0x08)
        SpiSend(0xD8)
        SpiSend(0xDE)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend

   
    'Configure DIO and IRQ --> TxDone IRQ mapped To DIO1
    Low CS
        SpiSend(CMD_SET_DIO_IRQ_PARAMS)
        SpiSend(0x00)
        SpiSend(0x01)
        SpiSend(0x00)
        SpiSend(0x01)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    ClearIrq()
EndProc

Proc ClearIrq()
    Low CS
        SpiSend(CMD_CLEAR_IRQ_STATUS)
        SpiSend(0xFF)
        SpiSend(0xFF)
    High CS
    While DIO0 = 1 : Wend
    DelayMS 10
EndProc

Proc ContructMessage()
    Clear baPayload
    baPayload = "Hello!"
EndProc

Proc SendMessage()
    Dim bCounter As Byte
   
    High LED
    If DIO1 = 1 Then
        ClearIrq()
    EndIf
   
    'Send data from the Byte Array to the TX buffer at offset 0
    Low CS
        SpiSend(CMD_WRITE_BUFFER) 
        SpiSend(0x00)                          
        For bCounter = 0 To bPacketLen - 1
            SpiSend(baPayload[bCounter])
        Next
    High CS
    DelayMS 20
   
    'set the device in transmit mode
    Low CS
        SpiSend(CMD_SET_TX)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS

    DelayMS 10
    While DIO1 = 0 : Wend
    DelayMS 10    
    ClearIrq()
    Low LED
EndProc



Proc SpiSend(spi_byte As Byte)
    MOSI = spi_byte.7 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.6 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.5 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.4 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.3 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.2 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.1 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.0 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
EndProc

I think at the time I put all those delays for a reason, but can't remember why. Anyway start with this code and clean up the delays if not needed.

Look at the SDR screens, first screen is initiated with InitLoRa(430.8, 20.83, 10, 14, 16, 26, 0x64, 64) - look at my code for comments, and second is InitLoRa(435.321, 41.67, 11, 14, 16, 26, 0x64, 64) - thus changing settings works.

This weekend I'll do the receiver part and post the code here. Hope it helps.

430_8_20_83_10.jpg

435_321_41_67_11.jpg

top204

Many thanks All.

Werwolf and Trastikata, you have been so kind and thoughtful sharing your codes, and I cannot thank you both enough.

I'll get back into the SX units today, but now with fresh eyes.

Best regards
Les

trastikata

#9
Hello Les,

this is a working code for Transmitter and Receiver parts. The program sends "HELLO " + Str$(Dec bGlobalCounter) which is incremented after each transmission and the received packet is displayed on a screen.

There is either something wrong with the power settings and calibration parameters, or I suspect there might be a problem with the RF switch on that TX module because the signal is weaker than SX1278 with similar settings. However basic TX-RX code works as shown on the video.

This is the TX and RX code, for the RX code I've cut the display part.

Device = 18F25J50

Config_Start
  WDTEN = OFF    ;Disabled - Controlled by SWDTEN bit
  PLLDIV = 5    ;Divide by 5 (20 MHz oscillator input)
  STVREN = On    ;Enabled
  XINST = OFF    ;Disabled
  Debug = OFF    ;Disabled
  CPUDIV = OSC1
  Cp0 = OFF    ;Program memory is not code-protected
  OSC = HSPLL    ;HS+PLL, USB-HS+PLL
  T1DIG = OFF    ;Secondary Oscillator clock source may not be selected
  LPT1OSC = OFF    ;High-power operation
  FCMEN = On    ;Disabled
  IESO = On    ;Disabled
  WDTPS = 32768    ;1:32768
  DSWDTOSC = INTOSCREF    ;DSWDT uses INTRC
  RTCOSC = T1OSCREF    ;RTCC uses T1OSC/T1CKI
  DSBOREN = On    ;Enabled
  DSWDTEN = OFF    ;Disabled
  DSWDTPS = G2    ;1:2,147,483,648 (25.7 days)
  IOL1WAY = OFF    ;The IOLOCK bit (PPSCON<0>) can be set and cleared as needed
  MSSP7B_EN = MSK7    ;7 Bit address masking mode
  WPFP = PAGE_31    ;Write Protect Program Flash Page 31
  WPEND = PAGE_WPFP    ;Page WPFP<5:0> through Configuration Words erase/write protected
  WPCFG = OFF    ;Configuration Words page not erase/write-protected
  WPDIS = OFF    ;WPFP<5:0>/WPEND region ignored
Config_End

Declare Xtal = 48

Declare Auto_Variable_Bank_Cross = On
Declare FSR_CONTEXT_SAVE = On
Declare LABEL_BANK_RESETS = On
Declare Optimiser_Level = 3
Declare Dead_Code_Remove = On
Declare Float_Display_Type = Large


Symbol DIO1 = PORTA.2
Input DIO1
Symbol MOSI = PORTA.5
Output MOSI
Symbol CS = PORTB.0
Output CS
Symbol MODEM_RESET = PORTB.1
Output MODEM_RESET
Symbol SCLK = PORTB.2
Output SCLK
Symbol MISO = PORTB.3
Input MISO
Symbol LED = PORTC.2
Output LED
Symbol SW = PORTA.3
Output SW
Symbol DIO0 = PORTA.1
Input DIO0

'======================================= 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

Dim baPayload[64] As Byte
Dim bPacketLen As Byte
Dim bGlobalCounter As Byte


Main:
    Clear
    Low LED : High CS : Low SCLK : High SW
    OSCTUNE.6 = 1 : DelayMS 500
    ANCON0 = %11111110 : ANCON1 = %00011111

    InitLoRa(435.321, 125, 10, 14, 16, 26, 0x64, 64)

    While 1 = 1
        ContructMessage()
        SendMessage()
        DelayMS 1000
    Wend


'fFrequency = Frequency in MHz (Ex: 430.8)
'fBandwidth = Standard LoRa BW (Ex: 31.25)
'bSpreadingFactor = LoRa spreading factor (Ex: 10)
'bPout = Power output (Ex: 14)
'bPreambleLength = Preamble length (Ex: 16)
'bSyncByte = LoRa sync word Byte0 (Ex: 0x64)
'bPacketLength = Packet length in bytes
Proc InitLoRa(fFrequency As Float, fBandwidth As Float, bSpreadingFactor As Byte, bPout As Byte, bPreambleLength As Byte, bCrystalFreq As Byte, bSyncByte As Byte, bPacketLength As Byte)
    Dim fTemp As Float
    Dim dTemp As Dword
    Dim CAL_IMG_FRQ1 As Byte
    Dim CAL_IMG_FRQ2 As Byte
       
    bPacketLen = bPacketLength
   
    'Reset chip
    Low MODEM_RESET : DelayMS 200 : High MODEM_RESET
   
    'Wait for SX126x to boot
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Set power mode to LDO + DC
    Low CS
        SpiSend(CMD_SET_REGULATOR_MODE)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Start calibration
    Low CS
        SpiSend(CMD_CALIBRATE)
        SpiSend(%01111111)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Start image calibration over the band Freq - 4 / Freq + 4 MHz
    fTemp = (fFrequency - 4) / 4
    CAL_IMG_FRQ1 = fTemp
    fTemp = (fFrequency + 7) / 4
    CAL_IMG_FRQ2 = fTemp
    Low CS
        SpiSend(CMD_CALIBRATE_IMAGE)
        SpiSend(CAL_IMG_FRQ1)
        SpiSend(CAL_IMG_FRQ2)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Go to Standby - STDBY_XOSC mode
    Low CS
        SpiSend(CMD_SET_STANDBY)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the protocol as LoRa 
    Low CS
        SpiSend(CMD_SET_PACKET_TYPE)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the RF frequency as RFfrequency=(RFFreq*FXTAL)/2^25
    fTemp = 33554432 / bCrystalFreq
    fTemp = fTemp * fFrequency
    dTemp = fTemp
    Low CS
        SpiSend(CMD_SET_RF_FREQUENCY)
        SpiSend(dTemp.Byte3)
        SpiSend(dTemp.Byte2)
        SpiSend(dTemp.Byte1)
        SpiSend(dTemp.Byte0)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the modulation parameter
    'Mod Param1 --> bSpreadingFactor
    'Mod Param2 --> Bandwidth
    'Mod Param3 --> CR = 4/8
    'Mod Param4 --> LowDataRateOptimize = ON
    Low CS
        SpiSend(CMD_SET_MODULATION_PARAMS)
        Select bSpreadingFactor
            Case 12
                SpiSend(0x0C)    '12
            Case 11
                SpiSend(0x0B)    '11
            Case 10
                SpiSend(0x0A)    '10
            Case 9
                SpiSend(0x09)    '9
            Case 8
                SpiSend(0x08)    '8
            Case 7
                SpiSend(0x07)    '7
            Case 6
                SpiSend(0x06)    '6
            Case 5
                SpiSend(0x05)    '5
        EndSelect
        Select fBandwidth
            Case 500
                SpiSend(0x06)    '500 
            Case 250
                SpiSend(0x05)    '250
            Case 125
                SpiSend(0x04)    '125
            Case 62.5
                SpiSend(0x03)    '62.5
            Case 41.67
                SpiSend(0x0A)    '41.7
            Case 31.25
                SpiSend(0x02)    '31.25
            Case 20.83
                SpiSend(0x09)    '20.8
            Case 15.63
                SpiSend(0x01)    '15.6
            Case 10.42
                SpiSend(0x08)    '10.4
            Case 7.81
                SpiSend(0x00)    '7.8
        EndSelect
        SpiSend(0x04)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the packet format
    'Pack Param1 --> PreambleLength (15:8) = 0
    'Pack Param2 --> PreambleLength (7:0) = bPreambleLength
    'Pack Param3 --> HeaderType = Fixed length packet (implicit header)
    'Pack Param4 --> bPacketLength
    'Pack Param5 --> CRC = ON
    'Pack Param6 --> InvertIQ = Standard IQ setup
    Low CS
        SpiSend(CMD_SET_PACKET_PARAMS)
        SpiSend(0x00)
        SpiSend(bPreambleLength)
        SpiSend(0x01)
        SpiSend(bPacketLength)
        SpiSend(0x01)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define Sync Word value and write in Sync Word Byte 0 
    Low CS
        SpiSend(CMD_WRITE_REGISTER )
        SpiSend(REG_LORA_SYNC_WORD_MSB.Byte1)
        SpiSend(REG_LORA_SYNC_WORD_MSB.Byte0)
        SpiSend(bSyncByte)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    '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
    Low CS
        SpiSend(CMD_SET_BUFFER_BASE_ADDRESS)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the Power Amplifier configuration for +22 dBm
    Low CS
        SpiSend(CMD_SET_PA_CONFIG)
        SpiSend(0x04)
        SpiSend(0x07)
        SpiSend(0x00)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define output power +22 dBm and ramping time 80uS
    Low CS
        SpiSend(CMD_SET_TX_PARAMS)
        Select bPout
            Case 15
                SpiSend(22)       'Set pout 15
            Case 14
                SpiSend(21)       'Set pout 14
            Case 13
                SpiSend(19)       'Set pout 13
            Case 12
                SpiSend(17)       'Set pout 12
            Case 11
                SpiSend(15)       'Set pout 11
            Case 10
                SpiSend(14)       'Set pout 10
            Case 9
                SpiSend(12)       'Set pout 9
            Case 8
                SpiSend(10)       'Set pout 8
            Case 7
                SpiSend(9)        'Set pout 7
            Case 6
                SpiSend(8)        'Set pout 6
            Case 5
                SpiSend(7)        'Set pout 5
            Case 4
                SpiSend(6)        'Set pout 4
            Case 3
                SpiSend(5)        'Set pout 3
            Case 2
                SpiSend(3)        'Set pout 2
            Case 1
                SpiSend(1)        'Set pout 1
            Case 0
                SpiSend(0)        'Set pout 0
        EndSelect
        SpiSend(0x03)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Set Over Current Protection to 140mA
    Low CS
        SpiSend(CMD_WRITE_REGISTER )
        SpiSend(REG_OCP_CONFIGURATION.Byte1)
        SpiSend(REG_OCP_CONFIGURATION.Byte0)
        SpiSend(0x38)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Modify TxClampConfig
    Low CS
        SpiSend(CMD_WRITE_REGISTER)
        SpiSend(0x08)
        SpiSend(0xD8)
        SpiSend(0xDE)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend

   
    'Configure DIO and IRQ --> TxDone IRQ mapped To DIO1
    Low CS
        SpiSend(CMD_SET_DIO_IRQ_PARAMS)
        SpiSend(0x00)
        SpiSend(0x01)
        SpiSend(0x00)
        SpiSend(0x01)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    ClearIrq()
EndProc

Proc ClearIrq()
    Low CS
        SpiSend(CMD_CLEAR_IRQ_STATUS)
        SpiSend(0xFF)
        SpiSend(0xFF)
    High CS
    While DIO0 = 1 : Wend
    DelayMS 10
EndProc

Proc ContructMessage()
    Dim sTempString As String * 8
    Clear baPayload
   
    sTempString = "HELLO " + Str$(Dec bGlobalCounter)
    baPayload = sTempString
    Inc bGlobalCounter
EndProc

Proc SendMessage()
    Dim bCounter As Byte
   
    High LED
    If DIO1 = 1 Then
        ClearIrq()
    EndIf
   
    'Send data from the Byte Array to the TX buffer at offset 0
    Low CS
        SpiSend(CMD_WRITE_BUFFER) 
        SpiSend(0x00)                          
        For bCounter = 0 To bPacketLen - 1
            SpiSend(baPayload[bCounter])
        Next
    High CS
    DelayMS 20
   
    'set the device in transmit mode
    Low CS
        SpiSend(CMD_SET_TX)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS

    DelayMS 10
    While DIO1 = 0 : Wend
    DelayMS 10    
    ClearIrq()
    Low LED
EndProc



Proc SpiSend(spi_byte As Byte)
    MOSI = spi_byte.7 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.6 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.5 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.4 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.3 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.2 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.1 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.0 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
EndProc

Device = 18F26J50

Config_Start
  WDTEN = OFF    ;Disabled - Controlled by SWDTEN bit
  PLLDIV = 5    ;Divide by 5 (20 MHz oscillator input)
  STVREN = On    ;Enabled
  XINST = OFF    ;Disabled
  Debug = OFF    ;Disabled
  CPUDIV = OSC1
  Cp0 = OFF    ;Program memory is not code-protected
  OSC = HSPLL    ;HS+PLL, USB-HS+PLL
  T1DIG = OFF    ;Secondary Oscillator clock source may not be selected
  LPT1OSC = OFF    ;High-power operation
  FCMEN = On    ;Disabled
  IESO = On    ;Disabled
  WDTPS = 32768    ;1:32768
  DSWDTOSC = INTOSCREF    ;DSWDT uses INTRC
  RTCOSC = T1OSCREF    ;RTCC uses T1OSC/T1CKI
  DSBOREN = On    ;Enabled
  DSWDTEN = OFF    ;Disabled
  DSWDTPS = G2    ;1:2,147,483,648 (25.7 days)
  IOL1WAY = OFF    ;The IOLOCK bit (PPSCON<0>) can be set and cleared as needed
  MSSP7B_EN = MSK7    ;7 Bit address masking mode
  WPFP = PAGE_31    ;Write Protect Program Flash Page 31
  WPEND = PAGE_WPFP    ;Page WPFP<5:0> through Configuration Words erase/write protected
  WPCFG = OFF    ;Configuration Words page not erase/write-protected
  WPDIS = OFF    ;WPFP<5:0>/WPEND region ignored
Config_End

Declare Xtal = 48

Declare Auto_Variable_Bank_Cross = On
Declare FSR_CONTEXT_SAVE = On
Declare LABEL_BANK_RESETS = On
Declare Optimiser_Level = 3
Declare Dead_Code_Remove = On
Declare Float_Display_Type = Large
Declare Hbus_Bitrate = 400
Declare HSDA_Pin = PORTB.5
Declare HSCL_Pin = PORTB.4
Declare Slow_Bus = On


Symbol DIO0 = PORTA.1
Input DIO0
Symbol DIO1 = PORTA.2
Input DIO1
Symbol SCLK = PORTA.5
Output SCLK
Symbol MISO = PORTB.0
Input MISO
Symbol MOSI = PORTB.1
Output MOSI
Symbol MODEM_RESET = PORTB.2
Output MODEM_RESET
Symbol CS = PORTB.3
Output CS
Symbol SW = PORTA.3
Output SW

Symbol SSD1306 = $3C << 1
Symbol ControlByteCMD  = %10000000         ;Co bit set = Command follows
Symbol ControlByteData = %01000000         ;D/C# bit set = GDRAM byte follows


'======================================= 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

Dim baPayload[64] As Byte
Dim bPacketLen As Byte
Dim bCounter As Byte


Main:
    Clear
    High CS : Low SCLK : Low SW
    OSCTUNE.6 = 1 : DelayMS 500
    ANCON0 = %11111110 : ANCON1 = %00011111
   
    GoSub INITIALIZE_LCD
    GoSub LCD_ON
    GoSub LCD_NORMAL
    GoSub LCD_CLEAR
   
    InitLoRa(435.321, 125, 10, 14, 16, 26, 0x64, 64)
    SetRX()
   
    While 1 = 1
        While RxPacket() = 0 : Wend
        For bCounter = 0 To 8
            CH_string[bCounter] = baPayload[bCounter]
        Next
        row = 4 : pos = 0 : GoSub Print_GLCD_LINE
    Wend


'fFrequency = Frequency in MHz (Ex: 430.8)
'fBandwidth = Standard LoRa BW (Ex: 31.25)
'bSpreadingFactor = LoRa spreading factor (Ex: 10)
'bPout = Power output (Ex: 14)
'bPreambleLength = Preamble length (Ex: 16)
'bSyncByte = LoRa sync word Byte0 (Ex: 0x64)
'bPacketLength = Packet length in bytes
Proc InitLoRa(fFrequency As Float, fBandwidth As Float, bSpreadingFactor As Byte, bPout As Byte, bPreambleLength As Byte, bCrystalFreq As Byte, bSyncByte As Byte, bPacketLength As Byte)
    Dim fTemp As Float
    Dim dTemp As Dword
    Dim CAL_IMG_FRQ1 As Byte
    Dim CAL_IMG_FRQ2 As Byte
       
    bPacketLen = bPacketLength
   
    'Reset chip
    Low MODEM_RESET : DelayMS 200 : High MODEM_RESET
   
    'Wait for SX126x to boot
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Set power mode to LDO + DC
    Low CS
        SpiSend(CMD_SET_REGULATOR_MODE)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Start calibration
    Low CS
        SpiSend(CMD_CALIBRATE)
        SpiSend(%01111111)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Start image calibration over the band Freq - 4 / Freq + 4 MHz
    fTemp = (fFrequency - 4) / 4
    CAL_IMG_FRQ1 = fTemp
    fTemp = (fFrequency + 7) / 4
    CAL_IMG_FRQ2 = fTemp
    Low CS
        SpiSend(CMD_CALIBRATE_IMAGE)
        SpiSend(CAL_IMG_FRQ1)
        SpiSend(CAL_IMG_FRQ2)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Go to Standby - STDBY_XOSC mode
    Low CS
        SpiSend(CMD_SET_STANDBY)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the protocol as LoRa 
    Low CS
        SpiSend(CMD_SET_PACKET_TYPE)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the RF frequency as RFfrequency=(RFFreq*FXTAL)/2^25
    fTemp = 33554432 / bCrystalFreq
    fTemp = fTemp * fFrequency
    dTemp = fTemp
    Low CS
        SpiSend(CMD_SET_RF_FREQUENCY)
        SpiSend(dTemp.Byte3)
        SpiSend(dTemp.Byte2)
        SpiSend(dTemp.Byte1)
        SpiSend(dTemp.Byte0)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the modulation parameter
    'Mod Param1 --> bSpreadingFactor
    'Mod Param2 --> Bandwidth
    'Mod Param3 --> CR = 4/8
    'Mod Param4 --> LowDataRateOptimize = ON
    Low CS
        SpiSend(CMD_SET_MODULATION_PARAMS)
        Select bSpreadingFactor
            Case 12
                SpiSend(0x0C)    '12
            Case 11
                SpiSend(0x0B)    '11
            Case 10
                SpiSend(0x0A)    '10
            Case 9
                SpiSend(0x09)    '9
            Case 8
                SpiSend(0x08)    '8
            Case 7
                SpiSend(0x07)    '7
            Case 6
                SpiSend(0x06)    '6
            Case 5
                SpiSend(0x05)    '5
        EndSelect
        Select fBandwidth
            Case 500
                SpiSend(0x06)    '500 
            Case 250
                SpiSend(0x05)    '250
            Case 125
                SpiSend(0x04)    '125
            Case 62.5
                SpiSend(0x03)    '62.5
            Case 41.67
                SpiSend(0x0A)    '41.7
            Case 31.25
                SpiSend(0x02)    '31.25
            Case 20.83
                SpiSend(0x09)    '20.8
            Case 15.63
                SpiSend(0x01)    '15.6
            Case 10.42
                SpiSend(0x08)    '10.4
            Case 7.81
                SpiSend(0x00)    '7.8
        EndSelect
        SpiSend(0x04)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define the packet format
    'Pack Param1 --> PreambleLength (15:8) = 0
    'Pack Param2 --> PreambleLength (7:0) = bPreambleLength
    'Pack Param3 --> HeaderType = Fixed length packet (implicit header)
    'Pack Param4 --> bPacketLength
    'Pack Param5 --> CRC = ON
    'Pack Param6 --> InvertIQ = Standard IQ setup
    Low CS
        SpiSend(CMD_SET_PACKET_PARAMS)
        SpiSend(0x00)
        SpiSend(bPreambleLength)
        SpiSend(0x01)
        SpiSend(bPacketLength)
        SpiSend(0x01)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Define Sync Word value and write in Sync Word Byte 0 
    Low CS
        SpiSend(CMD_WRITE_REGISTER )
        SpiSend(REG_LORA_SYNC_WORD_MSB.Byte1)
        SpiSend(REG_LORA_SYNC_WORD_MSB.Byte0)
        SpiSend(bSyncByte)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    '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
    Low CS
        SpiSend(CMD_SET_BUFFER_BASE_ADDRESS)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Rx Gain Configuration to Rx Boosted gain
    Low CS
        SpiSend(REG_RX_GAIN)
        SpiSend(0x96)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    'Configure DIO and IRQ --> RxDone IRQ mapped To DIO1
    Low CS
        SpiSend(CMD_SET_DIO_IRQ_PARAMS)
        SpiSend(0x00)
        SpiSend(0x02)
        SpiSend(0x00)
        SpiSend(0x01)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend
   
    ClearIrq()
EndProc

Proc ClearIrq()
    Low CS
        SpiSend(CMD_CLEAR_IRQ_STATUS)
        SpiSend(0xFF)
        SpiSend(0xFF)
    High CS
    While DIO0 = 1 : Wend
    DelayMS 10
EndProc

'Set receiver mode with no timeout
Proc SetRX()
    Low CS
        SpiSend(CMD_SET_RX)
        SpiSend(0x00)
        SpiSend(0x00)
        SpiSend(0x00)
    High CS
    While DIO0 = 1 : Wend
    DelayMS 10
EndProc

Proc RxPacket(), Byte
    Dim bCounter As Byte
   
    Result = 0
   
    'Wait for IRQ on RXDone
    While DIO1 = 0 : Wend
    DelayMS 10
   
    'Clear the IRQ
    ClearIrq()
   
    'Read data from the RX buffer at offset 0, NOP, and place it in the Byte Array
    Low CS
        SpiSend(CMD_READ_BUFFER)  
        SpiSend(0x00)
        SpiSend(0x00)
        For bCounter = 0 To 63
            baPayload[bCounter] = SpiReceive()
        Next
    High CS
   
    SetRX()
   
    Result = 1
EndProc   

Proc SpiSend(spi_byte As Byte)
    MOSI = spi_byte.7 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.6 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.5 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.4 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.3 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.2 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.1 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
    MOSI = spi_byte.0 : DelayCS 6 : High SCLK : DelayCS 6 : Low SCLK : DelayCS 6
EndProc

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



top204

#10
I cannot thank you enough, and I will be running the code later this afternoon to see where I have been going wrong in my code.

I really like your SDR! What type is it, because I have never used SDR before? I've seen SDR used many times, but never owned or used one myself because they were too expensive.

Best regards
Les

trastikata

Hello Les,

I am using an inexpensive RTL2832U USB SDR dongle. I've bought mine couple of years ago from Aliexpress for about 20 USD, should not be much different now.

I'm using it with HDSDR or SDRsharp - I can't say it is a good SDR dongle - probably the more expensive ones around 50$ would have been better, but it does the job for basic RF debugging and it was only 20$, probably cheaper now.

About the SX1262/SX1268 chips, comes to mind two things:

1. That those have a two power schemes - LDO only and LDO + DC-DC converter. Thus if there's no inductor in the module, the DC-DC converter won't work, so try with LDO only  in the power supply register:

'Set power mode to LDO + DC
    Low CS
        SpiSend(CMD_SET_REGULATOR_MODE)
        SpiSend(0x01)
    High CS
    DelayMS 20
    While DIO0 = 1 : Wend

2. In my custom modules there's a TCXO of 26 MHz, standard inexpensive modules have a 32 MHz Crystal or more expensive ones a 32 MHz TCXO, so you'd have to take that in consideration if this would be the case with your modules.
- If there's a crystal in yours, adjust the code to work with crystals.
- When initiating the module in my code I use 26 MHz, change it to 32 MHz in yours.