Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
sx1232.cpp@1:67a841d57890, 2013-05-01 (annotated)
- Committer:
- dudmuck
- Date:
- Wed May 01 23:42:35 2013 +0000
- Revision:
- 1:67a841d57890
- Parent:
- 0:06cc2cd9f340
- Child:
- 2:8717baf6e00a
apache license
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dudmuck | 0:06cc2cd9f340 | 1 | #include "sx1232.h" |
dudmuck | 0:06cc2cd9f340 | 2 | |
dudmuck | 1:67a841d57890 | 3 | /* SX1232 driver |
dudmuck | 1:67a841d57890 | 4 | * Copyright (c) 2013 Semtech |
dudmuck | 1:67a841d57890 | 5 | * |
dudmuck | 1:67a841d57890 | 6 | * Licensed under the Apache License, Version 2.0 (the "License"); |
dudmuck | 1:67a841d57890 | 7 | * you may not use this file except in compliance with the License. |
dudmuck | 1:67a841d57890 | 8 | * You may obtain a copy of the License at |
dudmuck | 1:67a841d57890 | 9 | * |
dudmuck | 1:67a841d57890 | 10 | * http://www.apache.org/licenses/LICENSE-2.0 |
dudmuck | 1:67a841d57890 | 11 | * |
dudmuck | 1:67a841d57890 | 12 | * Unless required by applicable law or agreed to in writing, software |
dudmuck | 1:67a841d57890 | 13 | * distributed under the License is distributed on an "AS IS" BASIS, |
dudmuck | 1:67a841d57890 | 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
dudmuck | 1:67a841d57890 | 15 | * See the License for the specific language governing permissions and |
dudmuck | 1:67a841d57890 | 16 | * limitations under the License. |
dudmuck | 1:67a841d57890 | 17 | */ |
dudmuck | 1:67a841d57890 | 18 | |
dudmuck | 0:06cc2cd9f340 | 19 | SX1232::SX1232(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName rst, PinName dio_0) : m_spi(mosi, miso, sclk), m_cs(cs), reset_pin(rst), dio0(dio_0) |
dudmuck | 0:06cc2cd9f340 | 20 | { |
dudmuck | 0:06cc2cd9f340 | 21 | dio0.rise(this, &SX1232::dio0_callback); |
dudmuck | 0:06cc2cd9f340 | 22 | reset_pin.input(); |
dudmuck | 0:06cc2cd9f340 | 23 | m_cs = 1; |
dudmuck | 0:06cc2cd9f340 | 24 | m_spi.format(8, 0); |
dudmuck | 0:06cc2cd9f340 | 25 | m_spi.frequency(1000000); |
dudmuck | 0:06cc2cd9f340 | 26 | |
dudmuck | 0:06cc2cd9f340 | 27 | init(); |
dudmuck | 0:06cc2cd9f340 | 28 | service_action = SERVICE_NONE; |
dudmuck | 0:06cc2cd9f340 | 29 | } |
dudmuck | 0:06cc2cd9f340 | 30 | |
dudmuck | 0:06cc2cd9f340 | 31 | SX1232::~SX1232() |
dudmuck | 0:06cc2cd9f340 | 32 | { |
dudmuck | 0:06cc2cd9f340 | 33 | set_opmode(RF_OPMODE_SLEEP); |
dudmuck | 0:06cc2cd9f340 | 34 | } |
dudmuck | 0:06cc2cd9f340 | 35 | |
dudmuck | 0:06cc2cd9f340 | 36 | void SX1232::init() |
dudmuck | 0:06cc2cd9f340 | 37 | { |
dudmuck | 0:06cc2cd9f340 | 38 | RegOpMode.octet = read_reg(REG_OPMODE); |
dudmuck | 0:06cc2cd9f340 | 39 | RegPktConfig1.octet = read_reg(REG_PACKETCONFIG1); |
dudmuck | 0:06cc2cd9f340 | 40 | RegPktConfig2.octet = read_reg(REG_PACKETCONFIG2); |
dudmuck | 0:06cc2cd9f340 | 41 | RegDioMapping1.octet = read_reg(REG_DIOMAPPING1); |
dudmuck | 0:06cc2cd9f340 | 42 | RegDioMapping2.octet = read_reg(REG_DIOMAPPING2); |
dudmuck | 0:06cc2cd9f340 | 43 | RegPayloadLength = read_reg(REG_PAYLOADLENGTH); |
dudmuck | 0:06cc2cd9f340 | 44 | RegPaConfig.octet = read_reg(REG_PACONFIG); |
dudmuck | 0:06cc2cd9f340 | 45 | RegOokPeak.octet = read_reg(REG_OOKPEAK); |
dudmuck | 0:06cc2cd9f340 | 46 | RegRxConfig.octet = read_reg(REG_RXCONFIG); |
dudmuck | 0:06cc2cd9f340 | 47 | RegLna.octet = read_reg(REG_LNA); |
dudmuck | 0:06cc2cd9f340 | 48 | RegTimerResol.octet = read_reg(REG_TIMERRESOL); |
dudmuck | 0:06cc2cd9f340 | 49 | RegSeqConfig1.octet = read_reg(REG_SEQCONFIG1); |
dudmuck | 0:06cc2cd9f340 | 50 | RegSeqConfig2.octet = read_reg(REG_SEQCONFIG2); |
dudmuck | 0:06cc2cd9f340 | 51 | RegAfcFei.octet = read_reg(REG_AFCFEI); |
dudmuck | 0:06cc2cd9f340 | 52 | |
dudmuck | 0:06cc2cd9f340 | 53 | RegPreambleDetect.octet = read_reg(REG_PREAMBLEDETECT); |
dudmuck | 0:06cc2cd9f340 | 54 | if (RegPreambleDetect.octet != 0xaa) { |
dudmuck | 0:06cc2cd9f340 | 55 | RegPreambleDetect.octet = 0xaa; |
dudmuck | 0:06cc2cd9f340 | 56 | write_reg(REG_PREAMBLEDETECT, RegPreambleDetect.octet); |
dudmuck | 0:06cc2cd9f340 | 57 | } |
dudmuck | 0:06cc2cd9f340 | 58 | |
dudmuck | 0:06cc2cd9f340 | 59 | RegSyncConfig.octet = read_reg(REG_SYNCCONFIG); |
dudmuck | 0:06cc2cd9f340 | 60 | RegSyncConfig.bits.SyncSize = 2; // actual size is this+1 |
dudmuck | 0:06cc2cd9f340 | 61 | RegSyncConfig.bits.AutoRestartRxMode = 1; // restart Rx after fifo emptied. 2 is for frequency hopping |
dudmuck | 0:06cc2cd9f340 | 62 | write_reg(REG_SYNCCONFIG, RegSyncConfig.octet); |
dudmuck | 0:06cc2cd9f340 | 63 | write_reg(REG_SYNCVALUE1, 0xaa); |
dudmuck | 0:06cc2cd9f340 | 64 | write_reg(REG_SYNCVALUE1, 0x90); // 802.15.4g examples: 0x7bc9, 0x904e, 0xc9c2, 0x7a0e |
dudmuck | 0:06cc2cd9f340 | 65 | write_reg(REG_SYNCVALUE2, 0x4e); |
dudmuck | 0:06cc2cd9f340 | 66 | |
dudmuck | 0:06cc2cd9f340 | 67 | RegFifoThreshold.octet = read_reg(REG_FIFOTHRESH); |
dudmuck | 0:06cc2cd9f340 | 68 | if (!RegFifoThreshold.bits.TxStartCondition) { // is start condition at fifoThreshold? |
dudmuck | 0:06cc2cd9f340 | 69 | RegFifoThreshold.bits.TxStartCondition = 1; // make it start tx on FifoNotEmpty |
dudmuck | 0:06cc2cd9f340 | 70 | write_reg(REG_FIFOTHRESH, RegFifoThreshold.octet); |
dudmuck | 0:06cc2cd9f340 | 71 | } |
dudmuck | 0:06cc2cd9f340 | 72 | } |
dudmuck | 0:06cc2cd9f340 | 73 | |
dudmuck | 0:06cc2cd9f340 | 74 | void SX1232::hw_reset() |
dudmuck | 0:06cc2cd9f340 | 75 | { |
dudmuck | 0:06cc2cd9f340 | 76 | /* only a french-swiss design would have hi-Z deassert */ |
dudmuck | 0:06cc2cd9f340 | 77 | reset_pin.output(); |
dudmuck | 0:06cc2cd9f340 | 78 | reset_pin.write(1); |
dudmuck | 0:06cc2cd9f340 | 79 | wait(0.05); |
dudmuck | 0:06cc2cd9f340 | 80 | reset_pin.input(); |
dudmuck | 0:06cc2cd9f340 | 81 | wait(0.05); |
dudmuck | 0:06cc2cd9f340 | 82 | } |
dudmuck | 0:06cc2cd9f340 | 83 | |
dudmuck | 0:06cc2cd9f340 | 84 | // variable-length pkt is only 255byte max |
dudmuck | 0:06cc2cd9f340 | 85 | // fixed-length packet could be larger than 255 bytes |
dudmuck | 0:06cc2cd9f340 | 86 | int SX1232::read_fifo() |
dudmuck | 0:06cc2cd9f340 | 87 | { |
dudmuck | 0:06cc2cd9f340 | 88 | /* no blocking code or printf in an ISR */ |
dudmuck | 0:06cc2cd9f340 | 89 | int i, len; |
dudmuck | 0:06cc2cd9f340 | 90 | |
dudmuck | 0:06cc2cd9f340 | 91 | if (RegPktConfig1.bits.PacketFormatVariable) { |
dudmuck | 0:06cc2cd9f340 | 92 | m_cs = 0; |
dudmuck | 0:06cc2cd9f340 | 93 | m_spi.write(REG_FIFO); // bit7 is low for reading from radio |
dudmuck | 0:06cc2cd9f340 | 94 | len = m_spi.write(0); |
dudmuck | 0:06cc2cd9f340 | 95 | m_cs = 1; |
dudmuck | 0:06cc2cd9f340 | 96 | } else |
dudmuck | 0:06cc2cd9f340 | 97 | len = get_PayloadLength(); |
dudmuck | 0:06cc2cd9f340 | 98 | |
dudmuck | 0:06cc2cd9f340 | 99 | m_cs = 0; |
dudmuck | 0:06cc2cd9f340 | 100 | m_spi.write(REG_FIFO); // bit7 is low for reading from radio |
dudmuck | 0:06cc2cd9f340 | 101 | for (i = 0; i < len; i++) { |
dudmuck | 0:06cc2cd9f340 | 102 | // todo: flow control for pkt bigger than fifo (need ISR on FifoTreshold) |
dudmuck | 0:06cc2cd9f340 | 103 | rx_buf[i] = m_spi.write(0); |
dudmuck | 0:06cc2cd9f340 | 104 | } |
dudmuck | 0:06cc2cd9f340 | 105 | m_cs = 1; |
dudmuck | 0:06cc2cd9f340 | 106 | //_callback_rx.call(); |
dudmuck | 0:06cc2cd9f340 | 107 | return len; |
dudmuck | 0:06cc2cd9f340 | 108 | } |
dudmuck | 0:06cc2cd9f340 | 109 | |
dudmuck | 0:06cc2cd9f340 | 110 | void SX1232::dio0_callback() |
dudmuck | 0:06cc2cd9f340 | 111 | { |
dudmuck | 0:06cc2cd9f340 | 112 | /* no printf allowed here in ISR */ |
dudmuck | 0:06cc2cd9f340 | 113 | switch (RegDioMapping1.bits.Dio0Mapping) { |
dudmuck | 0:06cc2cd9f340 | 114 | case 0: |
dudmuck | 0:06cc2cd9f340 | 115 | if (RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) { |
dudmuck | 0:06cc2cd9f340 | 116 | service_action = SERVICE_READ_FIFO; |
dudmuck | 0:06cc2cd9f340 | 117 | } else if (RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER) { |
dudmuck | 0:06cc2cd9f340 | 118 | set_opmode(RF_OPMODE_STANDBY); // this should be quick enough for ISR |
dudmuck | 0:06cc2cd9f340 | 119 | } |
dudmuck | 0:06cc2cd9f340 | 120 | break; |
dudmuck | 0:06cc2cd9f340 | 121 | case 1: |
dudmuck | 0:06cc2cd9f340 | 122 | service_action = SERVICE_READ_FIFO; |
dudmuck | 0:06cc2cd9f340 | 123 | break; |
dudmuck | 0:06cc2cd9f340 | 124 | default: |
dudmuck | 0:06cc2cd9f340 | 125 | service_action = SERVICE_ERROR; |
dudmuck | 0:06cc2cd9f340 | 126 | break; |
dudmuck | 0:06cc2cd9f340 | 127 | } |
dudmuck | 0:06cc2cd9f340 | 128 | |
dudmuck | 0:06cc2cd9f340 | 129 | } |
dudmuck | 0:06cc2cd9f340 | 130 | |
dudmuck | 0:06cc2cd9f340 | 131 | void SX1232::set_opmode(chip_mode_e mode) |
dudmuck | 0:06cc2cd9f340 | 132 | { |
dudmuck | 0:06cc2cd9f340 | 133 | RegOpMode.bits.Mode = mode; |
dudmuck | 0:06cc2cd9f340 | 134 | write_reg(REG_OPMODE, RegOpMode.octet); |
dudmuck | 0:06cc2cd9f340 | 135 | } |
dudmuck | 0:06cc2cd9f340 | 136 | |
dudmuck | 0:06cc2cd9f340 | 137 | float SX1232::get_frf_MHz(void) |
dudmuck | 0:06cc2cd9f340 | 138 | { |
dudmuck | 0:06cc2cd9f340 | 139 | uint32_t frf; |
dudmuck | 0:06cc2cd9f340 | 140 | uint8_t lsb, mid, msb; |
dudmuck | 0:06cc2cd9f340 | 141 | msb = read_reg(REG_FRFMSB); |
dudmuck | 0:06cc2cd9f340 | 142 | mid = read_reg(REG_FRFMID); |
dudmuck | 0:06cc2cd9f340 | 143 | lsb = read_reg(REG_FRFLSB); |
dudmuck | 0:06cc2cd9f340 | 144 | frf = msb; |
dudmuck | 0:06cc2cd9f340 | 145 | frf <<= 8; |
dudmuck | 0:06cc2cd9f340 | 146 | frf += mid; |
dudmuck | 0:06cc2cd9f340 | 147 | frf <<= 8; |
dudmuck | 0:06cc2cd9f340 | 148 | frf += lsb; |
dudmuck | 0:06cc2cd9f340 | 149 | return frf * FREQ_STEP_MHZ; |
dudmuck | 0:06cc2cd9f340 | 150 | } |
dudmuck | 0:06cc2cd9f340 | 151 | |
dudmuck | 0:06cc2cd9f340 | 152 | void SX1232::set_bitrate(uint32_t bps) |
dudmuck | 0:06cc2cd9f340 | 153 | { |
dudmuck | 0:06cc2cd9f340 | 154 | uint8_t lsb, msb; |
dudmuck | 0:06cc2cd9f340 | 155 | uint16_t br = XTAL_FREQ / bps; |
dudmuck | 0:06cc2cd9f340 | 156 | msb = br >> 8; |
dudmuck | 0:06cc2cd9f340 | 157 | lsb = br & 0xff; |
dudmuck | 0:06cc2cd9f340 | 158 | write_reg(REG_BITRATEMSB, msb); |
dudmuck | 0:06cc2cd9f340 | 159 | write_reg(REG_BITRATELSB, lsb); |
dudmuck | 0:06cc2cd9f340 | 160 | } |
dudmuck | 0:06cc2cd9f340 | 161 | |
dudmuck | 0:06cc2cd9f340 | 162 | uint32_t SX1232::get_bitrate() |
dudmuck | 0:06cc2cd9f340 | 163 | { |
dudmuck | 0:06cc2cd9f340 | 164 | uint16_t br; |
dudmuck | 0:06cc2cd9f340 | 165 | |
dudmuck | 0:06cc2cd9f340 | 166 | br = read_reg(REG_BITRATEMSB); |
dudmuck | 0:06cc2cd9f340 | 167 | br <<= 8; |
dudmuck | 0:06cc2cd9f340 | 168 | br += read_reg(REG_BITRATELSB); |
dudmuck | 0:06cc2cd9f340 | 169 | |
dudmuck | 0:06cc2cd9f340 | 170 | return XTAL_FREQ / br; |
dudmuck | 0:06cc2cd9f340 | 171 | } |
dudmuck | 0:06cc2cd9f340 | 172 | |
dudmuck | 0:06cc2cd9f340 | 173 | void SX1232::set_tx_fdev_hz(uint32_t hz) |
dudmuck | 0:06cc2cd9f340 | 174 | { |
dudmuck | 0:06cc2cd9f340 | 175 | uint16_t fdev = hz / FREQ_STEP_HZ; |
dudmuck | 0:06cc2cd9f340 | 176 | uint8_t lsb, msb; |
dudmuck | 0:06cc2cd9f340 | 177 | msb = fdev >> 8; |
dudmuck | 0:06cc2cd9f340 | 178 | lsb = fdev & 0xff; |
dudmuck | 0:06cc2cd9f340 | 179 | write_reg(REG_FDEVMSB, msb); |
dudmuck | 0:06cc2cd9f340 | 180 | write_reg(REG_FDEVLSB, lsb); |
dudmuck | 0:06cc2cd9f340 | 181 | } |
dudmuck | 0:06cc2cd9f340 | 182 | |
dudmuck | 0:06cc2cd9f340 | 183 | uint32_t SX1232::get_tx_fdev_hz(void) |
dudmuck | 0:06cc2cd9f340 | 184 | { |
dudmuck | 0:06cc2cd9f340 | 185 | uint16_t fdev; |
dudmuck | 0:06cc2cd9f340 | 186 | |
dudmuck | 0:06cc2cd9f340 | 187 | fdev = read_reg(REG_FDEVMSB); |
dudmuck | 0:06cc2cd9f340 | 188 | fdev <<= 8; |
dudmuck | 0:06cc2cd9f340 | 189 | fdev += read_reg(REG_FDEVLSB); |
dudmuck | 0:06cc2cd9f340 | 190 | |
dudmuck | 0:06cc2cd9f340 | 191 | return fdev * FREQ_STEP_HZ; |
dudmuck | 0:06cc2cd9f340 | 192 | } |
dudmuck | 0:06cc2cd9f340 | 193 | |
dudmuck | 0:06cc2cd9f340 | 194 | void SX1232::set_frf_MHz( float MHz ) |
dudmuck | 0:06cc2cd9f340 | 195 | { |
dudmuck | 0:06cc2cd9f340 | 196 | uint32_t frf; |
dudmuck | 0:06cc2cd9f340 | 197 | uint8_t lsb, mid, msb; |
dudmuck | 0:06cc2cd9f340 | 198 | |
dudmuck | 0:06cc2cd9f340 | 199 | frf = MHz / FREQ_STEP_MHZ; |
dudmuck | 0:06cc2cd9f340 | 200 | msb = frf >> 16; |
dudmuck | 0:06cc2cd9f340 | 201 | mid = (frf >> 8) & 0xff; |
dudmuck | 0:06cc2cd9f340 | 202 | lsb = frf & 0xff; |
dudmuck | 0:06cc2cd9f340 | 203 | write_reg(REG_FRFMSB, msb); |
dudmuck | 0:06cc2cd9f340 | 204 | write_reg(REG_FRFMID, mid); |
dudmuck | 0:06cc2cd9f340 | 205 | write_reg(REG_FRFLSB, lsb); |
dudmuck | 0:06cc2cd9f340 | 206 | } |
dudmuck | 0:06cc2cd9f340 | 207 | |
dudmuck | 0:06cc2cd9f340 | 208 | void SX1232::ComputeRxBwMantExp( uint32_t rxBwValue, uint8_t* mantisse, uint8_t* exponent ) |
dudmuck | 0:06cc2cd9f340 | 209 | { |
dudmuck | 0:06cc2cd9f340 | 210 | uint8_t tmpExp, tmpMant; |
dudmuck | 0:06cc2cd9f340 | 211 | double tmpRxBw; |
dudmuck | 0:06cc2cd9f340 | 212 | double rxBwMin = 10e6; |
dudmuck | 0:06cc2cd9f340 | 213 | |
dudmuck | 0:06cc2cd9f340 | 214 | for( tmpExp = 0; tmpExp < 8; tmpExp++ ) { |
dudmuck | 0:06cc2cd9f340 | 215 | for( tmpMant = 16; tmpMant <= 24; tmpMant += 4 ) { |
dudmuck | 0:06cc2cd9f340 | 216 | tmpRxBw = ComputeRxBw(tmpMant, tmpExp); |
dudmuck | 0:06cc2cd9f340 | 217 | if( fabs( tmpRxBw - rxBwValue ) < rxBwMin ) { |
dudmuck | 0:06cc2cd9f340 | 218 | rxBwMin = fabs( tmpRxBw - rxBwValue ); |
dudmuck | 0:06cc2cd9f340 | 219 | *mantisse = tmpMant; |
dudmuck | 0:06cc2cd9f340 | 220 | *exponent = tmpExp; |
dudmuck | 0:06cc2cd9f340 | 221 | } |
dudmuck | 0:06cc2cd9f340 | 222 | } |
dudmuck | 0:06cc2cd9f340 | 223 | } |
dudmuck | 0:06cc2cd9f340 | 224 | } |
dudmuck | 0:06cc2cd9f340 | 225 | |
dudmuck | 0:06cc2cd9f340 | 226 | uint32_t SX1232::ComputeRxBw( uint8_t mantisse, uint8_t exponent ) { |
dudmuck | 0:06cc2cd9f340 | 227 | // rxBw |
dudmuck | 0:06cc2cd9f340 | 228 | if (RegOpMode.bits.ModulationType == 0) |
dudmuck | 0:06cc2cd9f340 | 229 | return XTAL_FREQ / (mantisse * (1 << exponent+2)); |
dudmuck | 0:06cc2cd9f340 | 230 | else |
dudmuck | 0:06cc2cd9f340 | 231 | return XTAL_FREQ / (mantisse * (1 << exponent+3)); |
dudmuck | 0:06cc2cd9f340 | 232 | } |
dudmuck | 0:06cc2cd9f340 | 233 | |
dudmuck | 0:06cc2cd9f340 | 234 | void SX1232::set_rx_dcc_bw_hz(uint32_t dccValue, uint32_t bw_hz ) |
dudmuck | 0:06cc2cd9f340 | 235 | { |
dudmuck | 0:06cc2cd9f340 | 236 | uint8_t mantisse = 0; |
dudmuck | 0:06cc2cd9f340 | 237 | uint8_t exponent = 0; |
dudmuck | 0:06cc2cd9f340 | 238 | uint8_t reg; |
dudmuck | 0:06cc2cd9f340 | 239 | |
dudmuck | 0:06cc2cd9f340 | 240 | reg = ( uint8_t )dccValue & 0x60; |
dudmuck | 0:06cc2cd9f340 | 241 | ComputeRxBwMantExp( bw_hz, &mantisse, &exponent ); |
dudmuck | 0:06cc2cd9f340 | 242 | switch( mantisse ) { |
dudmuck | 0:06cc2cd9f340 | 243 | case 16: |
dudmuck | 0:06cc2cd9f340 | 244 | reg |= ( uint8_t )( 0x00 | ( exponent & 0x07 ) ); |
dudmuck | 0:06cc2cd9f340 | 245 | break; |
dudmuck | 0:06cc2cd9f340 | 246 | case 20: |
dudmuck | 0:06cc2cd9f340 | 247 | reg |= ( uint8_t )( 0x08 | ( exponent & 0x07 ) ); |
dudmuck | 0:06cc2cd9f340 | 248 | break; |
dudmuck | 0:06cc2cd9f340 | 249 | case 24: |
dudmuck | 0:06cc2cd9f340 | 250 | reg |= ( uint8_t )( 0x10 | ( exponent & 0x07 ) ); |
dudmuck | 0:06cc2cd9f340 | 251 | break; |
dudmuck | 0:06cc2cd9f340 | 252 | default: |
dudmuck | 0:06cc2cd9f340 | 253 | // Something went terribely wrong |
dudmuck | 0:06cc2cd9f340 | 254 | printf("maintisse:%d\r\n", mantisse); |
dudmuck | 0:06cc2cd9f340 | 255 | break; |
dudmuck | 0:06cc2cd9f340 | 256 | } |
dudmuck | 0:06cc2cd9f340 | 257 | |
dudmuck | 0:06cc2cd9f340 | 258 | write_reg(REG_RXBW, reg); |
dudmuck | 0:06cc2cd9f340 | 259 | } |
dudmuck | 0:06cc2cd9f340 | 260 | |
dudmuck | 0:06cc2cd9f340 | 261 | uint32_t SX1232::get_rx_bw_hz(uint8_t addr) |
dudmuck | 0:06cc2cd9f340 | 262 | { |
dudmuck | 0:06cc2cd9f340 | 263 | uint8_t mantisse = 0; |
dudmuck | 0:06cc2cd9f340 | 264 | uint8_t reg = read_reg(REG_RXBW); |
dudmuck | 0:06cc2cd9f340 | 265 | switch( ( reg & 0x18 ) >> 3 ) |
dudmuck | 0:06cc2cd9f340 | 266 | { |
dudmuck | 0:06cc2cd9f340 | 267 | case 0: |
dudmuck | 0:06cc2cd9f340 | 268 | mantisse = 16; |
dudmuck | 0:06cc2cd9f340 | 269 | break; |
dudmuck | 0:06cc2cd9f340 | 270 | case 1: |
dudmuck | 0:06cc2cd9f340 | 271 | mantisse = 20; |
dudmuck | 0:06cc2cd9f340 | 272 | break; |
dudmuck | 0:06cc2cd9f340 | 273 | case 2: |
dudmuck | 0:06cc2cd9f340 | 274 | mantisse = 24; |
dudmuck | 0:06cc2cd9f340 | 275 | break; |
dudmuck | 0:06cc2cd9f340 | 276 | default: |
dudmuck | 0:06cc2cd9f340 | 277 | break; |
dudmuck | 0:06cc2cd9f340 | 278 | } |
dudmuck | 0:06cc2cd9f340 | 279 | return ComputeRxBw( mantisse, ( uint8_t )reg & 0x07 ); |
dudmuck | 0:06cc2cd9f340 | 280 | } |
dudmuck | 0:06cc2cd9f340 | 281 | |
dudmuck | 0:06cc2cd9f340 | 282 | uint16_t SX1232::get_PayloadLength() |
dudmuck | 0:06cc2cd9f340 | 283 | { |
dudmuck | 0:06cc2cd9f340 | 284 | uint16_t ret; |
dudmuck | 0:06cc2cd9f340 | 285 | |
dudmuck | 0:06cc2cd9f340 | 286 | RegPktConfig2.octet = read_reg(REG_PACKETCONFIG2); |
dudmuck | 0:06cc2cd9f340 | 287 | RegPayloadLength = read_reg(REG_PAYLOADLENGTH); |
dudmuck | 0:06cc2cd9f340 | 288 | |
dudmuck | 0:06cc2cd9f340 | 289 | ret = RegPktConfig2.bits.PayloadLengthHi; |
dudmuck | 0:06cc2cd9f340 | 290 | ret <<= 8; |
dudmuck | 0:06cc2cd9f340 | 291 | ret += RegPayloadLength; |
dudmuck | 0:06cc2cd9f340 | 292 | |
dudmuck | 0:06cc2cd9f340 | 293 | return ret; |
dudmuck | 0:06cc2cd9f340 | 294 | } |
dudmuck | 0:06cc2cd9f340 | 295 | |
dudmuck | 0:06cc2cd9f340 | 296 | void SX1232::set_RegPayloadLength(uint16_t len) |
dudmuck | 0:06cc2cd9f340 | 297 | { |
dudmuck | 0:06cc2cd9f340 | 298 | RegPktConfig2.bits.PayloadLengthHi = len >> 8; |
dudmuck | 0:06cc2cd9f340 | 299 | write_reg(REG_PACKETCONFIG2, RegPktConfig2.octet); |
dudmuck | 0:06cc2cd9f340 | 300 | RegPayloadLength = len & 0xff; |
dudmuck | 0:06cc2cd9f340 | 301 | write_reg(REG_PAYLOADLENGTH, RegPayloadLength); |
dudmuck | 0:06cc2cd9f340 | 302 | } |
dudmuck | 0:06cc2cd9f340 | 303 | |
dudmuck | 0:06cc2cd9f340 | 304 | void SX1232::enable_afc(char en) |
dudmuck | 0:06cc2cd9f340 | 305 | { |
dudmuck | 0:06cc2cd9f340 | 306 | if (en) { |
dudmuck | 0:06cc2cd9f340 | 307 | RegRxConfig.bits.AfcAutoOn = 1; |
dudmuck | 0:06cc2cd9f340 | 308 | RegRxConfig.bits.RxTrigger = 6; // 6: trigger on preamble detect |
dudmuck | 0:06cc2cd9f340 | 309 | |
dudmuck | 0:06cc2cd9f340 | 310 | if (RegSyncConfig.bits.AutoRestartRxMode != 1) { |
dudmuck | 0:06cc2cd9f340 | 311 | // 2 is for frequency hopping application |
dudmuck | 0:06cc2cd9f340 | 312 | // if 0 then manual RestartRx in RxConfig required |
dudmuck | 0:06cc2cd9f340 | 313 | RegSyncConfig.bits.AutoRestartRxMode = 1; |
dudmuck | 0:06cc2cd9f340 | 314 | } |
dudmuck | 0:06cc2cd9f340 | 315 | // preamble detector triggers AFC |
dudmuck | 0:06cc2cd9f340 | 316 | if (!RegPreambleDetect.bits.PreambleDetectorOn) { |
dudmuck | 0:06cc2cd9f340 | 317 | RegPreambleDetect.bits.PreambleDetectorOn = 1; |
dudmuck | 0:06cc2cd9f340 | 318 | RegPreambleDetect.bits.PreambleDetectorTol = 10; // chips |
dudmuck | 0:06cc2cd9f340 | 319 | RegPreambleDetect.bits.PreambleDetectorSize = 1; // bytes |
dudmuck | 0:06cc2cd9f340 | 320 | write_reg(REG_PREAMBLEDETECT, RegPreambleDetect.octet); |
dudmuck | 0:06cc2cd9f340 | 321 | } |
dudmuck | 0:06cc2cd9f340 | 322 | // set DIO4 output. not required, only for monitoring |
dudmuck | 0:06cc2cd9f340 | 323 | if ((RegDioMapping2.bits.Dio4Mapping != 3) || !RegDioMapping2.bits.MapPreambleDetect) { |
dudmuck | 0:06cc2cd9f340 | 324 | RegDioMapping2.bits.Dio4Mapping = 3; |
dudmuck | 0:06cc2cd9f340 | 325 | RegDioMapping2.bits.MapPreambleDetect = 1; |
dudmuck | 0:06cc2cd9f340 | 326 | write_reg(REG_DIOMAPPING2, RegDioMapping2.octet); |
dudmuck | 0:06cc2cd9f340 | 327 | } |
dudmuck | 0:06cc2cd9f340 | 328 | } else { |
dudmuck | 0:06cc2cd9f340 | 329 | RegRxConfig.bits.AfcAutoOn = 0; |
dudmuck | 0:06cc2cd9f340 | 330 | RegRxConfig.bits.RxTrigger = 0; |
dudmuck | 0:06cc2cd9f340 | 331 | } |
dudmuck | 0:06cc2cd9f340 | 332 | write_reg(REG_RXCONFIG, RegRxConfig.octet); |
dudmuck | 0:06cc2cd9f340 | 333 | } |
dudmuck | 0:06cc2cd9f340 | 334 | |
dudmuck | 0:06cc2cd9f340 | 335 | int16_t SX1232::read_reg_s16(uint8_t addr) |
dudmuck | 0:06cc2cd9f340 | 336 | { |
dudmuck | 0:06cc2cd9f340 | 337 | int16_t ret; |
dudmuck | 0:06cc2cd9f340 | 338 | // Select the device by seting chip select low |
dudmuck | 0:06cc2cd9f340 | 339 | m_cs = 0; |
dudmuck | 0:06cc2cd9f340 | 340 | |
dudmuck | 0:06cc2cd9f340 | 341 | m_spi.write(addr); // bit7 is low for reading from radio |
dudmuck | 0:06cc2cd9f340 | 342 | |
dudmuck | 0:06cc2cd9f340 | 343 | // Send a dummy byte to receive the contents of the WHOAMI register |
dudmuck | 0:06cc2cd9f340 | 344 | ret = m_spi.write(0x00); |
dudmuck | 0:06cc2cd9f340 | 345 | ret <<= 8; |
dudmuck | 0:06cc2cd9f340 | 346 | ret += m_spi.write(0x00); |
dudmuck | 0:06cc2cd9f340 | 347 | |
dudmuck | 0:06cc2cd9f340 | 348 | // Deselect the device |
dudmuck | 0:06cc2cd9f340 | 349 | m_cs = 1; |
dudmuck | 0:06cc2cd9f340 | 350 | |
dudmuck | 0:06cc2cd9f340 | 351 | return ret; |
dudmuck | 0:06cc2cd9f340 | 352 | } |
dudmuck | 0:06cc2cd9f340 | 353 | |
dudmuck | 0:06cc2cd9f340 | 354 | uint8_t SX1232::read_reg(uint8_t addr) |
dudmuck | 0:06cc2cd9f340 | 355 | { |
dudmuck | 0:06cc2cd9f340 | 356 | uint8_t ret; |
dudmuck | 0:06cc2cd9f340 | 357 | // Select the device by seting chip select low |
dudmuck | 0:06cc2cd9f340 | 358 | m_cs = 0; |
dudmuck | 0:06cc2cd9f340 | 359 | |
dudmuck | 0:06cc2cd9f340 | 360 | m_spi.write(addr); // bit7 is low for reading from radio |
dudmuck | 0:06cc2cd9f340 | 361 | |
dudmuck | 0:06cc2cd9f340 | 362 | // Send a dummy byte to receive the contents of the WHOAMI register |
dudmuck | 0:06cc2cd9f340 | 363 | ret = m_spi.write(0x00); |
dudmuck | 0:06cc2cd9f340 | 364 | |
dudmuck | 0:06cc2cd9f340 | 365 | // Deselect the device |
dudmuck | 0:06cc2cd9f340 | 366 | m_cs = 1; |
dudmuck | 0:06cc2cd9f340 | 367 | |
dudmuck | 0:06cc2cd9f340 | 368 | return ret; |
dudmuck | 0:06cc2cd9f340 | 369 | } |
dudmuck | 0:06cc2cd9f340 | 370 | |
dudmuck | 0:06cc2cd9f340 | 371 | void SX1232::write_reg(uint8_t addr, uint8_t data) |
dudmuck | 0:06cc2cd9f340 | 372 | { |
dudmuck | 0:06cc2cd9f340 | 373 | m_cs = 0; // Select the device by seting chip select low |
dudmuck | 0:06cc2cd9f340 | 374 | |
dudmuck | 0:06cc2cd9f340 | 375 | m_spi.write(addr | 0x80); // bit7 is high for writing to radio |
dudmuck | 0:06cc2cd9f340 | 376 | |
dudmuck | 0:06cc2cd9f340 | 377 | // Send a dummy byte to receive the contents of the WHOAMI register |
dudmuck | 0:06cc2cd9f340 | 378 | m_spi.write(data); |
dudmuck | 0:06cc2cd9f340 | 379 | |
dudmuck | 0:06cc2cd9f340 | 380 | m_cs = 1; // Deselect the device |
dudmuck | 0:06cc2cd9f340 | 381 | } |
dudmuck | 0:06cc2cd9f340 | 382 | |
dudmuck | 0:06cc2cd9f340 | 383 | // variable-length pkt is only 255byte max |
dudmuck | 0:06cc2cd9f340 | 384 | void SX1232::write_fifo__varlen(uint8_t len) |
dudmuck | 0:06cc2cd9f340 | 385 | { |
dudmuck | 0:06cc2cd9f340 | 386 | int i; |
dudmuck | 0:06cc2cd9f340 | 387 | |
dudmuck | 0:06cc2cd9f340 | 388 | m_cs = 0; |
dudmuck | 0:06cc2cd9f340 | 389 | m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio |
dudmuck | 0:06cc2cd9f340 | 390 | m_spi.write(len); |
dudmuck | 0:06cc2cd9f340 | 391 | for (i = 0; i < len; i++) { |
dudmuck | 0:06cc2cd9f340 | 392 | // todo: flow control for pkt bigger than fifo |
dudmuck | 0:06cc2cd9f340 | 393 | m_spi.write(tx_buf[i]); |
dudmuck | 0:06cc2cd9f340 | 394 | } |
dudmuck | 0:06cc2cd9f340 | 395 | m_cs = 1; |
dudmuck | 0:06cc2cd9f340 | 396 | } |
dudmuck | 0:06cc2cd9f340 | 397 | |
dudmuck | 0:06cc2cd9f340 | 398 | // fixed-length packet could be larger than 255 bytes |
dudmuck | 0:06cc2cd9f340 | 399 | void SX1232::write_fifo__fixedlen(void) |
dudmuck | 0:06cc2cd9f340 | 400 | { |
dudmuck | 0:06cc2cd9f340 | 401 | int i, len = get_PayloadLength(); |
dudmuck | 0:06cc2cd9f340 | 402 | m_cs = 0; |
dudmuck | 0:06cc2cd9f340 | 403 | m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio |
dudmuck | 0:06cc2cd9f340 | 404 | for (i = 0; i < len; i++) { |
dudmuck | 0:06cc2cd9f340 | 405 | // todo: flow control for pkt bigger than fifo |
dudmuck | 0:06cc2cd9f340 | 406 | m_spi.write(tx_buf[i]); |
dudmuck | 0:06cc2cd9f340 | 407 | } |
dudmuck | 0:06cc2cd9f340 | 408 | m_cs = 1; |
dudmuck | 0:06cc2cd9f340 | 409 | } |
dudmuck | 0:06cc2cd9f340 | 410 | |
dudmuck | 0:06cc2cd9f340 | 411 | // arg only for variable-length |
dudmuck | 0:06cc2cd9f340 | 412 | void SX1232::start_tx(uint8_t len) |
dudmuck | 0:06cc2cd9f340 | 413 | { |
dudmuck | 0:06cc2cd9f340 | 414 | if (RegOpMode.bits.Mode > RF_OPMODE_STANDBY) { |
dudmuck | 0:06cc2cd9f340 | 415 | RegIrqFlags1_t RegIrqFlags1; |
dudmuck | 0:06cc2cd9f340 | 416 | set_opmode(RF_OPMODE_STANDBY); // unwise fill fifo in RX |
dudmuck | 0:06cc2cd9f340 | 417 | wait(0.01); |
dudmuck | 0:06cc2cd9f340 | 418 | RegIrqFlags1.octet = read_reg(REG_IRQFLAGS1); |
dudmuck | 0:06cc2cd9f340 | 419 | while (!RegIrqFlags1.bits.ModeReady) { |
dudmuck | 0:06cc2cd9f340 | 420 | //printf("to stby:%02x\r\n", RegIrqFlags1.octet); |
dudmuck | 0:06cc2cd9f340 | 421 | wait(0.01); |
dudmuck | 0:06cc2cd9f340 | 422 | RegIrqFlags1.octet = read_reg(REG_IRQFLAGS1); |
dudmuck | 0:06cc2cd9f340 | 423 | } |
dudmuck | 0:06cc2cd9f340 | 424 | } |
dudmuck | 0:06cc2cd9f340 | 425 | |
dudmuck | 0:06cc2cd9f340 | 426 | // DIO0 to PacketSent |
dudmuck | 0:06cc2cd9f340 | 427 | if (RegDioMapping1.bits.Dio0Mapping != 0) { |
dudmuck | 0:06cc2cd9f340 | 428 | RegDioMapping1.bits.Dio0Mapping = 0; |
dudmuck | 0:06cc2cd9f340 | 429 | write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); |
dudmuck | 0:06cc2cd9f340 | 430 | } |
dudmuck | 0:06cc2cd9f340 | 431 | |
dudmuck | 0:06cc2cd9f340 | 432 | if (RegPktConfig1.bits.PacketFormatVariable) |
dudmuck | 0:06cc2cd9f340 | 433 | write_fifo__varlen(len); |
dudmuck | 0:06cc2cd9f340 | 434 | else |
dudmuck | 0:06cc2cd9f340 | 435 | write_fifo__fixedlen(); |
dudmuck | 0:06cc2cd9f340 | 436 | |
dudmuck | 0:06cc2cd9f340 | 437 | set_opmode(RF_OPMODE_TRANSMITTER); |
dudmuck | 0:06cc2cd9f340 | 438 | } |
dudmuck | 0:06cc2cd9f340 | 439 | |
dudmuck | 0:06cc2cd9f340 | 440 | void SX1232::start_rx() |
dudmuck | 0:06cc2cd9f340 | 441 | { |
dudmuck | 0:06cc2cd9f340 | 442 | if (RegPktConfig1.bits.CrcOn) { // DIO0 to CrcOk |
dudmuck | 0:06cc2cd9f340 | 443 | if (RegDioMapping1.bits.Dio0Mapping != 1) { |
dudmuck | 0:06cc2cd9f340 | 444 | RegDioMapping1.bits.Dio0Mapping = 1; |
dudmuck | 0:06cc2cd9f340 | 445 | write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); |
dudmuck | 0:06cc2cd9f340 | 446 | } |
dudmuck | 0:06cc2cd9f340 | 447 | } else { // DIO0 to PayloadReady |
dudmuck | 0:06cc2cd9f340 | 448 | if (RegDioMapping1.bits.Dio0Mapping != 0) { |
dudmuck | 0:06cc2cd9f340 | 449 | RegDioMapping1.bits.Dio0Mapping = 0; |
dudmuck | 0:06cc2cd9f340 | 450 | write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); |
dudmuck | 0:06cc2cd9f340 | 451 | } |
dudmuck | 0:06cc2cd9f340 | 452 | } |
dudmuck | 0:06cc2cd9f340 | 453 | |
dudmuck | 0:06cc2cd9f340 | 454 | set_opmode(RF_OPMODE_RECEIVER); |
dudmuck | 0:06cc2cd9f340 | 455 | } |