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
00001 #include "sx1232.h" 00002 00003 /* SX1232 driver 00004 * Copyright (c) 2013 Semtech 00005 * 00006 * Licensed under the Apache License, Version 2.0 (the "License"); 00007 * you may not use this file except in compliance with the License. 00008 * You may obtain a copy of the License at 00009 * 00010 * http://www.apache.org/licenses/LICENSE-2.0 00011 * 00012 * Unless required by applicable law or agreed to in writing, software 00013 * distributed under the License is distributed on an "AS IS" BASIS, 00014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 * See the License for the specific language governing permissions and 00016 * limitations under the License. 00017 */ 00018 00019 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) 00020 { 00021 dio0.rise(this, &SX1232::dio0_callback); 00022 reset_pin.input(); 00023 m_cs = 1; 00024 m_spi.format(8, 0); 00025 m_spi.frequency(1000000); 00026 00027 init(); 00028 service_action = SERVICE_NONE; 00029 } 00030 00031 SX1232::~SX1232() 00032 { 00033 set_opmode(RF_OPMODE_SLEEP); 00034 } 00035 00036 void SX1232::init() 00037 { 00038 RegOpMode.octet = read_reg(REG_OPMODE); 00039 RegPktConfig1.octet = read_reg(REG_PACKETCONFIG1); 00040 RegPktConfig2.octet = read_reg(REG_PACKETCONFIG2); 00041 RegDioMapping1.octet = read_reg(REG_DIOMAPPING1); 00042 RegDioMapping2.octet = read_reg(REG_DIOMAPPING2); 00043 RegPayloadLength = read_reg(REG_PAYLOADLENGTH); 00044 RegPaConfig.octet = read_reg(REG_PACONFIG); 00045 RegOokPeak.octet = read_reg(REG_OOKPEAK); 00046 RegRxConfig.octet = read_reg(REG_RXCONFIG); 00047 RegLna.octet = read_reg(REG_LNA); 00048 RegTimerResol.octet = read_reg(REG_TIMERRESOL); 00049 RegSeqConfig1.octet = read_reg(REG_SEQCONFIG1); 00050 RegSeqConfig2.octet = read_reg(REG_SEQCONFIG2); 00051 RegAfcFei.octet = read_reg(REG_AFCFEI); 00052 00053 RegPreambleDetect.octet = read_reg(REG_PREAMBLEDETECT); 00054 if (RegPreambleDetect.octet != 0xaa) { 00055 RegPreambleDetect.octet = 0xaa; 00056 write_reg(REG_PREAMBLEDETECT, RegPreambleDetect.octet); 00057 } 00058 00059 RegSyncConfig.octet = read_reg(REG_SYNCCONFIG); 00060 RegSyncConfig.bits.SyncSize = 2; // actual size is this+1 00061 RegSyncConfig.bits.AutoRestartRxMode = 1; // restart Rx after fifo emptied. 2 is for frequency hopping 00062 write_reg(REG_SYNCCONFIG, RegSyncConfig.octet); 00063 write_reg(REG_SYNCVALUE1, 0xaa); 00064 write_reg(REG_SYNCVALUE1, 0x90); // 802.15.4g examples: 0x7bc9, 0x904e, 0xc9c2, 0x7a0e 00065 write_reg(REG_SYNCVALUE2, 0x4e); 00066 00067 RegFifoThreshold.octet = read_reg(REG_FIFOTHRESH); 00068 if (!RegFifoThreshold.bits.TxStartCondition) { // is start condition at fifoThreshold? 00069 RegFifoThreshold.bits.TxStartCondition = 1; // make it start tx on FifoNotEmpty 00070 write_reg(REG_FIFOTHRESH, RegFifoThreshold.octet); 00071 } 00072 } 00073 00074 void SX1232::hw_reset() 00075 { 00076 /* only a french-swiss design would have hi-Z deassert */ 00077 reset_pin.output(); 00078 reset_pin.write(1); 00079 wait(0.05); 00080 reset_pin.input(); 00081 wait(0.05); 00082 } 00083 00084 // variable-length pkt is only 255byte max 00085 // fixed-length packet could be larger than 255 bytes 00086 int SX1232::read_fifo() 00087 { 00088 /* no blocking code or printf in an ISR */ 00089 int i, len; 00090 00091 if (RegPktConfig1.bits.PacketFormatVariable) { 00092 m_cs = 0; 00093 m_spi.write(REG_FIFO); // bit7 is low for reading from radio 00094 len = m_spi.write(0); 00095 m_cs = 1; 00096 } else 00097 len = get_PayloadLength(); 00098 00099 m_cs = 0; 00100 m_spi.write(REG_FIFO); // bit7 is low for reading from radio 00101 for (i = 0; i < len; i++) { 00102 // todo: flow control for pkt bigger than fifo (need ISR on FifoTreshold) 00103 rx_buf[i] = m_spi.write(0); 00104 } 00105 m_cs = 1; 00106 //_callback_rx.call(); 00107 return len; 00108 } 00109 00110 void SX1232::dio0_callback() 00111 { 00112 /* no printf allowed here in ISR */ 00113 switch (RegDioMapping1.bits.Dio0Mapping) { 00114 case 0: 00115 if (RegOpMode.bits.Mode == RF_OPMODE_RECEIVER) { 00116 service_action = SERVICE_READ_FIFO; 00117 } else if (RegOpMode.bits.Mode == RF_OPMODE_TRANSMITTER) { 00118 set_opmode(RF_OPMODE_STANDBY); // this should be quick enough for ISR 00119 service_action = SERVICE_TX_DONE; 00120 } 00121 break; 00122 case 1: 00123 service_action = SERVICE_READ_FIFO; 00124 break; 00125 default: 00126 service_action = SERVICE_ERROR; 00127 break; 00128 } 00129 00130 } 00131 00132 void SX1232::set_opmode(chip_mode_e mode) 00133 { 00134 RegOpMode.bits.Mode = mode; 00135 write_reg(REG_OPMODE, RegOpMode.octet); 00136 } 00137 00138 float SX1232::get_frf_MHz(void) 00139 { 00140 uint32_t frf; 00141 uint8_t lsb, mid, msb; 00142 msb = read_reg(REG_FRFMSB); 00143 mid = read_reg(REG_FRFMID); 00144 lsb = read_reg(REG_FRFLSB); 00145 frf = msb; 00146 frf <<= 8; 00147 frf += mid; 00148 frf <<= 8; 00149 frf += lsb; 00150 return frf * FREQ_STEP_MHZ; 00151 } 00152 00153 void SX1232::set_bitrate(uint32_t bps) 00154 { 00155 uint8_t lsb, msb; 00156 uint16_t br = XTAL_FREQ / bps; 00157 msb = br >> 8; 00158 lsb = br & 0xff; 00159 write_reg(REG_BITRATEMSB, msb); 00160 write_reg(REG_BITRATELSB, lsb); 00161 } 00162 00163 uint32_t SX1232::get_bitrate() 00164 { 00165 uint16_t br; 00166 00167 br = read_reg(REG_BITRATEMSB); 00168 br <<= 8; 00169 br += read_reg(REG_BITRATELSB); 00170 00171 return XTAL_FREQ / br; 00172 } 00173 00174 void SX1232::set_tx_fdev_hz(uint32_t hz) 00175 { 00176 uint16_t fdev = hz / FREQ_STEP_HZ; 00177 uint8_t lsb, msb; 00178 msb = fdev >> 8; 00179 lsb = fdev & 0xff; 00180 write_reg(REG_FDEVMSB, msb); 00181 write_reg(REG_FDEVLSB, lsb); 00182 } 00183 00184 uint32_t SX1232::get_tx_fdev_hz(void) 00185 { 00186 uint16_t fdev; 00187 00188 fdev = read_reg(REG_FDEVMSB); 00189 fdev <<= 8; 00190 fdev += read_reg(REG_FDEVLSB); 00191 00192 return fdev * FREQ_STEP_HZ; 00193 } 00194 00195 void SX1232::set_frf_MHz( float MHz ) 00196 { 00197 uint32_t frf; 00198 uint8_t lsb, mid, msb; 00199 00200 frf = MHz / FREQ_STEP_MHZ; 00201 msb = frf >> 16; 00202 mid = (frf >> 8) & 0xff; 00203 lsb = frf & 0xff; 00204 write_reg(REG_FRFMSB, msb); 00205 write_reg(REG_FRFMID, mid); 00206 write_reg(REG_FRFLSB, lsb); 00207 } 00208 00209 void SX1232::ComputeRxBwMantExp( uint32_t rxBwValue, uint8_t* mantisse, uint8_t* exponent ) 00210 { 00211 uint8_t tmpExp, tmpMant; 00212 double tmpRxBw; 00213 double rxBwMin = 10e6; 00214 00215 for( tmpExp = 0; tmpExp < 8; tmpExp++ ) { 00216 for( tmpMant = 16; tmpMant <= 24; tmpMant += 4 ) { 00217 tmpRxBw = ComputeRxBw(tmpMant, tmpExp); 00218 if( fabs( tmpRxBw - rxBwValue ) < rxBwMin ) { 00219 rxBwMin = fabs( tmpRxBw - rxBwValue ); 00220 *mantisse = tmpMant; 00221 *exponent = tmpExp; 00222 } 00223 } 00224 } 00225 } 00226 00227 uint32_t SX1232::ComputeRxBw( uint8_t mantisse, uint8_t exponent ) { 00228 // rxBw 00229 if (RegOpMode.bits.ModulationType == 0) 00230 return XTAL_FREQ / (mantisse * (1 << exponent+2)); 00231 else 00232 return XTAL_FREQ / (mantisse * (1 << exponent+3)); 00233 } 00234 00235 void SX1232::set_rx_dcc_bw_hz(uint32_t dccValue, uint32_t bw_hz ) 00236 { 00237 uint8_t mantisse = 0; 00238 uint8_t exponent = 0; 00239 uint8_t reg; 00240 00241 reg = ( uint8_t )dccValue & 0x60; 00242 ComputeRxBwMantExp( bw_hz, &mantisse, &exponent ); 00243 switch( mantisse ) { 00244 case 16: 00245 reg |= ( uint8_t )( 0x00 | ( exponent & 0x07 ) ); 00246 break; 00247 case 20: 00248 reg |= ( uint8_t )( 0x08 | ( exponent & 0x07 ) ); 00249 break; 00250 case 24: 00251 reg |= ( uint8_t )( 0x10 | ( exponent & 0x07 ) ); 00252 break; 00253 default: 00254 // Something went terribely wrong 00255 printf("maintisse:%d\r\n", mantisse); 00256 break; 00257 } 00258 00259 write_reg(REG_RXBW, reg); 00260 } 00261 00262 uint32_t SX1232::get_rx_bw_hz(uint8_t addr) 00263 { 00264 uint8_t mantisse = 0; 00265 uint8_t reg = read_reg(REG_RXBW); 00266 switch( ( reg & 0x18 ) >> 3 ) 00267 { 00268 case 0: 00269 mantisse = 16; 00270 break; 00271 case 1: 00272 mantisse = 20; 00273 break; 00274 case 2: 00275 mantisse = 24; 00276 break; 00277 default: 00278 break; 00279 } 00280 return ComputeRxBw( mantisse, ( uint8_t )reg & 0x07 ); 00281 } 00282 00283 uint16_t SX1232::get_PayloadLength() 00284 { 00285 uint16_t ret; 00286 00287 RegPktConfig2.octet = read_reg(REG_PACKETCONFIG2); 00288 RegPayloadLength = read_reg(REG_PAYLOADLENGTH); 00289 00290 ret = RegPktConfig2.bits.PayloadLengthHi; 00291 ret <<= 8; 00292 ret += RegPayloadLength; 00293 00294 return ret; 00295 } 00296 00297 void SX1232::set_RegPayloadLength(uint16_t len) 00298 { 00299 RegPktConfig2.bits.PayloadLengthHi = len >> 8; 00300 write_reg(REG_PACKETCONFIG2, RegPktConfig2.octet); 00301 RegPayloadLength = len & 0xff; 00302 write_reg(REG_PAYLOADLENGTH, RegPayloadLength); 00303 } 00304 00305 void SX1232::enable_afc(char en) 00306 { 00307 if (en) { 00308 RegRxConfig.bits.AfcAutoOn = 1; 00309 RegRxConfig.bits.RxTrigger = 6; // 6: trigger on preamble detect 00310 00311 if (RegSyncConfig.bits.AutoRestartRxMode != 1) { 00312 // 2 is for frequency hopping application 00313 // if 0 then manual RestartRx in RxConfig required 00314 RegSyncConfig.bits.AutoRestartRxMode = 1; 00315 } 00316 // preamble detector triggers AFC 00317 if (!RegPreambleDetect.bits.PreambleDetectorOn) { 00318 RegPreambleDetect.bits.PreambleDetectorOn = 1; 00319 RegPreambleDetect.bits.PreambleDetectorTol = 10; // chips 00320 RegPreambleDetect.bits.PreambleDetectorSize = 1; // bytes 00321 write_reg(REG_PREAMBLEDETECT, RegPreambleDetect.octet); 00322 } 00323 // set DIO4 output. not required, only for monitoring 00324 if ((RegDioMapping2.bits.Dio4Mapping != 3) || !RegDioMapping2.bits.MapPreambleDetect) { 00325 RegDioMapping2.bits.Dio4Mapping = 3; 00326 RegDioMapping2.bits.MapPreambleDetect = 1; 00327 write_reg(REG_DIOMAPPING2, RegDioMapping2.octet); 00328 } 00329 } else { 00330 RegRxConfig.bits.AfcAutoOn = 0; 00331 RegRxConfig.bits.RxTrigger = 0; 00332 } 00333 write_reg(REG_RXCONFIG, RegRxConfig.octet); 00334 } 00335 00336 int16_t SX1232::read_reg_s16(uint8_t addr) 00337 { 00338 int16_t ret; 00339 // Select the device by seting chip select low 00340 m_cs = 0; 00341 00342 m_spi.write(addr); // bit7 is low for reading from radio 00343 00344 // Send a dummy byte to receive the contents of the WHOAMI register 00345 ret = m_spi.write(0x00); 00346 ret <<= 8; 00347 ret += m_spi.write(0x00); 00348 00349 // Deselect the device 00350 m_cs = 1; 00351 00352 return ret; 00353 } 00354 00355 uint8_t SX1232::read_reg(uint8_t addr) 00356 { 00357 uint8_t ret; 00358 // Select the device by seting chip select low 00359 m_cs = 0; 00360 00361 m_spi.write(addr); // bit7 is low for reading from radio 00362 00363 // Send a dummy byte to receive the contents of the WHOAMI register 00364 ret = m_spi.write(0x00); 00365 00366 // Deselect the device 00367 m_cs = 1; 00368 00369 return ret; 00370 } 00371 00372 void SX1232::write_reg(uint8_t addr, uint8_t data) 00373 { 00374 m_cs = 0; // Select the device by seting chip select low 00375 00376 m_spi.write(addr | 0x80); // bit7 is high for writing to radio 00377 00378 // Send a dummy byte to receive the contents of the WHOAMI register 00379 m_spi.write(data); 00380 00381 m_cs = 1; // Deselect the device 00382 } 00383 00384 // variable-length pkt is only 255byte max 00385 void SX1232::write_fifo__varlen(uint8_t len) 00386 { 00387 int i; 00388 00389 m_cs = 0; 00390 m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio 00391 m_spi.write(len); 00392 for (i = 0; i < len; i++) { 00393 // todo: flow control for pkt bigger than fifo 00394 m_spi.write(tx_buf[i]); 00395 } 00396 m_cs = 1; 00397 } 00398 00399 // fixed-length packet could be larger than 255 bytes 00400 void SX1232::write_fifo__fixedlen(void) 00401 { 00402 int i, len = get_PayloadLength(); 00403 m_cs = 0; 00404 m_spi.write(REG_FIFO | 0x80); // bit7 is high for writing to radio 00405 for (i = 0; i < len; i++) { 00406 // todo: flow control for pkt bigger than fifo 00407 m_spi.write(tx_buf[i]); 00408 } 00409 m_cs = 1; 00410 } 00411 00412 // arg only for variable-length 00413 void SX1232::start_tx(uint8_t len) 00414 { 00415 if (RegOpMode.bits.Mode > RF_OPMODE_STANDBY) { 00416 RegIrqFlags1_t RegIrqFlags1; 00417 set_opmode(RF_OPMODE_STANDBY); // unwise fill fifo in RX 00418 wait(0.01); 00419 RegIrqFlags1.octet = read_reg(REG_IRQFLAGS1); 00420 while (!RegIrqFlags1.bits.ModeReady) { 00421 //printf("to stby:%02x\r\n", RegIrqFlags1.octet); 00422 wait(0.01); 00423 RegIrqFlags1.octet = read_reg(REG_IRQFLAGS1); 00424 } 00425 } 00426 00427 // DIO0 to PacketSent 00428 if (RegDioMapping1.bits.Dio0Mapping != 0) { 00429 RegDioMapping1.bits.Dio0Mapping = 0; 00430 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); 00431 } 00432 00433 if (RegPktConfig1.bits.PacketFormatVariable) 00434 write_fifo__varlen(len); 00435 else 00436 write_fifo__fixedlen(); 00437 00438 set_opmode(RF_OPMODE_TRANSMITTER); 00439 } 00440 00441 void SX1232::start_rx() 00442 { 00443 if (RegPktConfig1.bits.CrcOn) { // DIO0 to CrcOk 00444 if (RegDioMapping1.bits.Dio0Mapping != 1) { 00445 RegDioMapping1.bits.Dio0Mapping = 1; 00446 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); 00447 } 00448 } else { // DIO0 to PayloadReady 00449 if (RegDioMapping1.bits.Dio0Mapping != 0) { 00450 RegDioMapping1.bits.Dio0Mapping = 0; 00451 write_reg(REG_DIOMAPPING1, RegDioMapping1.octet); 00452 } 00453 } 00454 00455 set_opmode(RF_OPMODE_RECEIVER); 00456 }
Generated on Thu Jul 21 2022 17:07:21 by
1.7.2