wayne roberts / sx126x

Dependents:   alarm_slave iq_sx126x sx126x_simple_TX_shield_2020a sx126x_simple_RX_shield_2020a ... more

Files at this revision

API Documentation at this revision

Comitter:
Wayne Roberts
Date:
Mon Jun 11 11:15:18 2018 -0700
Parent:
1:497af0bd9e53
Child:
3:f6f2f8adcd22
Commit message:
send 0 value for NOP to radio chip

Changed in this revision

sx126x.cpp Show annotated file Show diff for this revision Revisions of this file
sx12xx.h Show annotated file Show diff for this revision Revisions of this file
--- a/sx126x.cpp	Tue May 22 14:26:32 2018 -0700
+++ b/sx126x.cpp	Mon Jun 11 11:15:18 2018 -0700
@@ -32,7 +32,7 @@
     buf[5] = 0; // dio2
     buf[6] = 0; // dio3
     buf[7] = 0; // dio3
-    xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, buf);
+    xfer(OPCODE_SET_DIO_IRQ_PARAMS, 8, 0, buf);
 
 }
 
@@ -61,17 +61,18 @@
     printf("\r\n");
 }
 
+extern RawSerial pc;
 void SX126x::service()
 {
-    //unsigned n = 0;
     IrqFlags_t irqFlags, clearIrqFlags;
     uint8_t buf[4];
 
-    if (busy)
+    if (busy) {
         return;
+    }
 
     while (dio1) {
-        xfer(OPCODE_GET_IRQ_STATUS, 3, buf);
+        xfer(OPCODE_GET_IRQ_STATUS, 0, 3, buf);
         irqFlags.word = buf[1] << 8;
         irqFlags.word |= buf[2];
         clearIrqFlags.word = 0;
@@ -86,10 +87,10 @@
                 uint8_t len;
                 float snr, rssi;
                 int8_t s;
-                xfer(OPCODE_GET_RX_BUFFER_STATUS, 3, buf);
+                xfer(OPCODE_GET_RX_BUFFER_STATUS, 0, 3, buf);
                 len = buf[1];
-                ReadBuffer(len);
-                xfer(OPCODE_GET_PACKET_STATUS, 4, buf);
+                ReadBuffer(len, buf[2]);
+                xfer(OPCODE_GET_PACKET_STATUS, 0, 4, buf);
                 rssi = -buf[1] / 2.0;   // TODO FSK
                 s = buf[2];
                 snr = s / 4.0;
@@ -109,36 +110,47 @@
         if (clearIrqFlags.word != 0) {
             buf[0] = clearIrqFlags.word >> 8;
             buf[1] = (uint8_t)clearIrqFlags.word;
-            xfer(OPCODE_CLEAR_IRQ_STATUS, 2, buf);
+            xfer(OPCODE_CLEAR_IRQ_STATUS, 2, 0, buf);
         }
 
     } // ...while (dio1)
 
 } // ..service()
 
-void SX126x::xfer(uint8_t opcode, uint8_t len, uint8_t* ptr)
+void SX126x::xfer(uint8_t opcode, uint8_t wlen, uint8_t rlen, uint8_t* ptr)
 {
+    const uint8_t* stopPtr;
+    const uint8_t* wstop;
+    const uint8_t* rstop;
+    uint8_t nop = 0;
+
     if (sleeping) {
         nss = 0;
         while (busy)
             ;
         sleeping = false;
     } else {
-        //unsigned n = 0;
-        while (busy) {
-            /*wait_us(0.002);
-            if (++n > 200) {
-                return -1;
-            }*/
-        }
+        while (busy)
+            ;
         nss = 0;
     }
 
     spi.write(opcode);
-    while (len > 0) {
-        *ptr = spi.write(*ptr);
-        len--;
-        ptr++;
+
+    wstop = ptr + wlen;
+    rstop = ptr + rlen;
+    if (rlen > wlen)
+        stopPtr = rstop;
+    else
+        stopPtr = wstop;
+
+    for (; ptr < stopPtr; ptr++) {
+        if (ptr < wstop && ptr < rstop)
+            *ptr = spi.write(*ptr);
+        else if (ptr < wstop)
+            spi.write(*ptr);
+        else
+            *ptr = spi.write(nop);    // n >= write length: send NOP
     }
 
     nss = 1;
@@ -170,7 +182,7 @@
     buf[0] = 0x40;
     buf[1] = 0x00;
     buf[2] = 0x00;
-    xfer(OPCODE_SET_TX, 3, buf);
+    xfer(OPCODE_SET_TX, 3, 0, buf);
 
     chipMode = CHIPMODE_TX;
 }
@@ -182,12 +194,11 @@
     buf[0] = timeout >> 16;
     buf[1] = timeout >> 8;
     buf[2] = timeout;
-    xfer(OPCODE_SET_RX, 3, buf);
+    xfer(OPCODE_SET_RX, 3, 0, buf);
 
     chipMode = CHIPMODE_RX;
 }
 
-#define MHZ_TO_FRF      1048576 // = (1<<25) / Fxtal_MHz
 uint8_t SX126x::setMHz(float MHz)
 {
     unsigned frf = MHz * MHZ_TO_FRF;
@@ -197,21 +208,27 @@
     buf[1] = frf >> 16;
     buf[2] = frf >> 8;
     buf[3] = frf;
-    xfer(OPCODE_SET_RF_FREQUENCY, 4, buf);
+    xfer(OPCODE_SET_RF_FREQUENCY, 4, 0, buf);
     return buf[3];
 }
 
+float SX126x::getMHz()
+{
+    uint32_t frf = readReg(REG_ADDR_RFFREQ, 4);
+    return frf / (float)MHZ_TO_FRF;
+}
+
 void SX126x::setPacketType(uint8_t type)
 {
-    xfer(OPCODE_SET_PACKET_TYPE, 1, &type);
+    xfer(OPCODE_SET_PACKET_TYPE, 1, 0, &type);
 }
 
 void SX126x::SetDIO2AsRfSwitchCtrl(uint8_t en)
 {
-    xfer(OPCODE_SET_DIO2_AS_RFSWITCH, 1, &en);
+    xfer(OPCODE_SET_DIO2_AS_RFSWITCH, 1, 0, &en);
 }
 
-void SX126x::ReadBuffer(uint8_t size)
+void SX126x::ReadBuffer(uint8_t size, uint8_t offset)
 {
     unsigned i;
     while (busy)
@@ -220,7 +237,7 @@
     nss = 0;
 
     spi.write(OPCODE_READ_BUFFER);
-    spi.write(0);   // offset
+    spi.write(offset);
     spi.write(0);   // NOP
     i = 0;
     for (i = 0; i < size; i++) {
@@ -258,7 +275,7 @@
         else if (dbm < -3)
             dbm = -3;
     }
-    xfer(OPCODE_SET_PA_CONFIG, 4, buf);
+    xfer(OPCODE_SET_PA_CONFIG, 4, 0, buf);
 
     if (is1262 && dbm > 18) {
         /* OCP is set by chip whenever SetPaConfig() is called */
@@ -269,7 +286,7 @@
     buf[0] = dbm;
     //if (opt == 0) txco
     buf[1] = SET_RAMP_200U;
-    xfer(OPCODE_SET_TX_PARAMS, 2, buf);
+    xfer(OPCODE_SET_TX_PARAMS, 2, 0, buf);
 }
 
 void SX126x::writeReg(uint16_t addr, uint32_t data, uint8_t len)
@@ -282,13 +299,13 @@
         buf[n+1] = (uint8_t)data;
         data >>= 8;
     }
-    xfer(OPCODE_WRITE_REGISTER, 2+len, buf);
+    xfer(OPCODE_WRITE_REGISTER, 2+len, 2+len, buf);
 }
 
 void SX126x::setStandby(stby_t stby)
 {
     uint8_t octet = stby;
-    xfer(OPCODE_SET_STANDBY, 1, &octet);
+    xfer(OPCODE_SET_STANDBY, 1, 0, &octet);
 
     chipMode = CHIPMODE_NONE;
 }
@@ -300,7 +317,7 @@
     sc.octet = 0;
     sc.bits.rtcWakeup = rtcWakeup;
     sc.bits.warmStart = warmStart;
-    xfer(OPCODE_SET_SLEEP, 1, &sc.octet);
+    xfer(OPCODE_SET_SLEEP, 1, 0, &sc.octet);
 
     chipMode = CHIPMODE_NONE;
 }
@@ -327,7 +344,7 @@
     uint8_t buf[7];
     buf[0] = addr >> 8;
     buf[1] = (uint8_t)addr;
-    xfer(OPCODE_READ_REGISTER, 3+len, buf);
+    xfer(OPCODE_READ_REGISTER, 2, 3+len, buf);
     for (i = 0; i < len; i++) {
         ret <<= 8;
         ret |= buf[i+3];
--- a/sx12xx.h	Tue May 22 14:26:32 2018 -0700
+++ b/sx12xx.h	Mon Jun 11 11:15:18 2018 -0700
@@ -5,9 +5,11 @@
 #define RC_TICKS_PER_MS         0.015625    /* 64KHz */
 #define RC_TICKS_PER_US         15.625    /* 64KHz */
 
-#define XTAL_FREQ               32000000
+#define XTAL_FREQ_HZ            32000000
 #define FREQ_DIV                33554432
 #define FREQ_STEP               0.95367431640625 // ( ( double )( XTAL_FREQ / ( double )FREQ_DIV ) )
+#define MHZ_TO_FRF              1048576 // = (1<<25) / Fxtal_MHz
+#define KHZ_TO_FRF              1048.576
 
 /***************************************************************/
 #define OPCODE_CLEAR_IRQ_STATUS         0x02
@@ -55,12 +57,42 @@
 #define INVERTED_IQ                     1
 
 /* direct register access */
-#define REG_ADDR_LORA_CONFIG0    0x0703 // 8bit  bw/sf
-#define REG_ADDR_LORA_IRQ_MASK   0x070a // 24bit
-#define REG_ADDR_LORA_SYNC       0x0740 // config22, config23: frame sync peak position
-#define REG_ADDR_RANDOM          0x0819
-#define REG_ADDR_OCP             0x08e7
-#define REG_ADDR_
+#define REG_ADDR_IRQ_STATUS            0x58a // 16bit
+#define REG_ADDR_IRQ_MASK              0x58c // 16bit
+#define REG_ADDR_MODCFG                0x680 // 8bit
+#define REG_ADDR_BITRATE               0x6a1 // 24bit fsk
+#define REG_ADDR_FREQDEV               0x6a4 // 18bit fsk
+#define REG_ADDR_SHAPECFG              0x6a7 // 5bit
+#define REG_ADDR_FSK_PKTCTRL0          0x6b3 // 8bit
+#define REG_ADDR_FSK_PKTCTRL1          0x6b4 // 3bit
+#define REG_ADDR_FSK_PREAMBLE_TXLEN    0x6b5 // 16bit
+#define REG_ADDR_FSK_SYNC_LEN          0x6b7 // 7bit
+#define REG_ADDR_FSK_PKTCTRL2          0x6ba // 8bit
+#define REG_ADDR_FSK_PAYLOAD_LEN       0x6bb // 8bit
+#define REG_ADDR_SYNCADDR              0x6c0 // 64bit fsk
+#define REG_ADDR_NODEADDR              0x6cd // 8bit fsk
+#define REG_ADDR_NODEADDRCOMP          0x6cf // 2bit fsk
+
+#define REG_ADDR_LORA_TXPKTLEN         0x702 // 8bit
+#define REG_ADDR_LORA_CONFIG0          0x703 // 8bit  bw/sf
+#define REG_ADDR_LORA_CONFIG1          0x704 // 8bit  ppm_offset, fixlen, invertiq, cr
+#define REG_ADDR_LORA_CONFIG2          0x705 // 8bit  crcType
+#define REG_ADDR_LORA_IRQ_MASK         0x70a // 24bit
+#define REG_ADDR_LORA_PREAMBLE_SYMBNB  0x73a // 16bit
+#define REG_ADDR_LORA_SYNC             0x740 // config22, config23: frame sync peak position
+
+#define REG_ADDR_DIGFECTL              0x804 // 6bits
+#define REG_ADDR_BWSEL                 0x807 // 5bits
+#define REG_ADDR_RANDOM                0x819 //        ro
+#define REG_ADDR_RFFREQ                0x88b // 31bits
+#define REG_ADDR_FREQ_OFFSET           0x88f // 19bits
+#define REG_ADDR_ANACTRL6              0x8d7 // 6bits
+#define REG_ADDR_ANACTRL7              0x8d8 // 6bits
+#define REG_ADDR_ANACTRL15             0x8e1 // 7bits
+#define REG_ADDR_OCP                   0x8e7
+#define REG_ADDR_                      0x
+
+/**********************************************/
 
 #define SET_RAMP_10U        0x00
 #define SET_RAMP_20U        0x01
@@ -101,6 +133,7 @@
         uint8_t PacketType;             // param6
         uint8_t PayloadLength;          // param7
         uint8_t CRCType;                // param8
+        uint8_t Whitening;              // param9
     } gfsk;
     uint8_t buf[8];
 } PacketParams_t;
@@ -128,6 +161,9 @@
 #define GFSK_PREAMBLE_DETECTOR_LENGTH_24BITS        0x06
 #define GFSK_PREAMBLE_DETECTOR_LENGTH_32BITS        0x07
 
+#define GFSK_WHITENING_OFF      0
+#define GFSK_WHITENING_ON       1
+
 #define GFSK_CRC_OFF            0x01
 #define GFSK_CRC_1_BYTE         0x00
 #define GFSK_CRC_2_BYTE         0x02
@@ -167,6 +203,152 @@
     STBY_XOSC
 } stby_t;
 
+#define MOD_TYPE_IQ      0
+#define MOD_TYPE_FSK     1
+#define MOD_TYPE_MSK     2
+#define MOD_TYPE_LORA    3
+typedef union {
+    struct {
+        uint8_t mod_order :  2; // 0,1   modulation size      2points to 16points
+        uint8_t mod_type  :  2; // 2,3   IQ, FSK, MSK, LoRa
+        uint8_t data_src  :  1; // 4     
+        uint8_t clk_src   :  2; // 5,6
+        uint8_t mod_en    :  1; // 7
+    } bits;
+    uint8_t octet;
+} modCfg_t;  // at 0x680  fsk
+
+typedef union {
+    struct {
+        uint8_t bt           :  2; // 0,1    0=BT1.0   1=BT0.5   2=BT0.3
+        uint8_t double_rate  :  1; // 2      double oversampling rate
+        uint8_t pulse_shape  :  2; // 3,4    0=noFilter  1=gaussian   2=RRC
+        uint8_t res          :  3; // 5,6,7
+    } bits;
+    uint8_t octet;
+} shapeCfg_t;  // at 0x6a7 fsk
+
+typedef union {
+    struct {
+        uint8_t pkt_start_p    :  1; // 0   ros1
+        uint8_t pkt_abort_p    :  1; // 1   ros1
+        uint8_t pkt_sw_clr_p   :  1; // 2   ros1
+        uint8_t crl_status_p   :  1; // 3   ros1
+        uint8_t clk_en         :  1; // 4   ro
+        uint8_t pkt_rx_ntx     :  1; // 5
+        uint8_t pkt_len_format :  1; // 6
+        uint8_t cont_rx        :  1; // 7
+    } bits;
+    uint8_t octet;
+} pktCtrl0_t;  // at 0x6b3 fsk
+
+typedef union {
+    struct {
+        uint8_t preamble_len_rx    :  2; // 0,1   number of preamble bits detected
+        uint8_t preamble_det_on    :  1; // 2   enable rx-sde preamble detector   
+        uint8_t res        :  1; // 7
+    } bits;
+    uint8_t octet;
+} pktCtrl1_t;  // at 0x6b4 fsk
+
+typedef union {
+    struct {
+        uint8_t crc_disable    :  1; // 0
+        uint8_t crc_len        :  1; // 1     0=1byte  1=2byte
+        uint8_t crc_inv        :  1; // 2
+        uint8_t crc_in_fifo    :  1; // 3
+        uint8_t whit_enable    :  1; // 4
+        uint8_t manchester_en  :  1; // 5
+        uint8_t rssi_mode      :  2; // 6,7
+    } bits;
+    uint8_t octet;
+} pktCtrl2_t;  // at 0x6ba fsk
+
+
+typedef union {
+    struct {
+        uint8_t modem_sf:  4; // 0,1,2,3
+        uint8_t modem_bw:  4; // 4,5,6,7
+    } bits;
+    uint8_t octet;
+} loraConfig0_t;  // at 0x703
+
+typedef union {
+    struct {
+        uint8_t tx_coding_rate :  3; // 0,1,2
+        uint8_t ppm_offset      : 2; // 3,4     aka long range mode
+        uint8_t tx_mode         : 1; // 5
+        uint8_t rx_invert_iq    : 1; // 6
+        uint8_t implicit_header : 1; // 7     0=variable length packet
+    } bits;
+    uint8_t octet;
+} loraConfig1_t;  // at 0x704
+
+typedef union {
+    struct {
+        uint8_t cad_rxtx               :  2; // 0,1
+        uint8_t tx_payload_crc16_en    :  1; // 2
+        uint8_t cont_rx                :  1; // 3
+        uint8_t freeze_dagc_upon_synch :  2; // 4,5
+        uint8_t fine_sync_en           :  1; // 6
+        uint8_t res                    :  1; // 7
+    } bits;
+    uint8_t octet;
+} loraConfig2_t;  // at 0x705
+
+typedef union {
+    struct {
+        uint8_t inv_edge        : 1; // 0
+        uint8_t swap_iq         : 1; // 1
+        uint8_t dig_fe_clear    : 1; // 2
+        uint8_t lora_ngfsk      : 1; // 3   data buffer selection lora/gfsk
+        uint8_t adc_from_dio    : 1; // 4
+        uint8_t lora_pre_cf_en  : 1; // 5
+        uint8_t res             : 2; // 6,7
+    } bits;
+    uint8_t octet;
+} digFeCtrl_t;  // at 0x804
+
+typedef union {
+    struct {
+        uint8_t exp  : 3; // 0,1,2
+        uint8_t mant : 2; // 3,4
+        uint8_t res  : 3; // 5,6,7
+    } bits;
+    uint8_t octet;
+} bwSel_t;  // at 0x807   rx_bw
+
+typedef union {
+    struct {
+        uint8_t pa_hp_ena_ana        : 1; // 0
+        uint8_t tx_ena_bat           : 1; // 1
+        uint8_t pa_dctrim_select_ana : 4; // 2,3,4,5
+        uint8_t res                  : 2; // 6,7
+    } bits;
+    uint8_t octet;
+} AnaCtrl6_t;  // at 0x8d7
+
+typedef union {
+    struct {
+        uint8_t pa_lp_ena_ana         : 1; // 0
+        uint8_t pa_clamp_code_bat     : 3; // 1,2,3
+        uint8_t pa_clamp_override_bat : 1; // 4
+        uint8_t pa_hp_sel_ana         : 1; // 5,6,7
+    } bits;
+    uint8_t octet;
+} AnaCtrl7_t;  // at 0x8d8
+
+typedef union {
+    struct {
+        uint8_t reg_pa_comp_poarity_ana  : 1; // 0
+        uint8_t reg_pa_comp_en_ana       : 1; // 1
+        uint8_t fir_dac_sign_ana         : 2; // 2,3
+        uint8_t fir_dac_pole_ana         : 3; // 4,5,6
+        uint8_t res                      : 1; // 7
+    } bits;
+    uint8_t octet;
+} AnaCtrl15_t;  // at 0x8e1
+
 typedef union {
     struct {
         uint8_t spreadingFactor; // param1
@@ -179,10 +361,10 @@
         uint8_t bitrateMid; // param2
         uint8_t bitrateLo;  // param3
         uint8_t PulseShape; // param4
-        uint8_t bandwith;   // param5
-        uint8_t fdevHi; // param6
+        uint8_t bandwidth;  // param5
+        uint8_t fdevHi;     // param6
         uint8_t fdevMid;    // param7
-        uint8_t fdevLo; // param8
+        uint8_t fdevLo;     // param8
     } gfsk;
     uint8_t buf[8];
 } ModulationParams_t;
@@ -225,9 +407,10 @@
 
 
         void hw_reset(PinName nrst);
-        void xfer(uint8_t opcode, uint8_t len, uint8_t* buf);
+        void xfer(uint8_t opcode, uint8_t writeLen, uint8_t readLen, uint8_t* buf);
         void setPacketType(uint8_t);
         uint8_t setMHz(float);
+        float getMHz(void);
 
         /* start_tx and start_rx assumes DIO1 is connected, and only pin used to generate radio interrupt */
         void start_tx(uint8_t pktLen);  // tx_buf must be filled prior to calling
@@ -236,7 +419,7 @@
 #define RX_TIMEOUT_CONTINUOUS     0xffffff  /* keep RXing */
         void start_rx(unsigned);
 
-        void ReadBuffer(uint8_t size);
+        void ReadBuffer(uint8_t size, uint8_t offset);
         void SetDIO2AsRfSwitchCtrl(uint8_t);
         void set_tx_dbm(bool is1262, int8_t dbm);
         uint32_t readReg(uint16_t addr, uint8_t len);
@@ -260,7 +443,6 @@
          */
         inline bool getDIO1(void) { return dio1.read(); }
         void PrintChipStatus(status_t);
-        //bool txing;
         chipMote_e chipMode;
 
     private: