wayne roberts / SX1232

Dependents:   chat_sx1232

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sx1232.cpp Source File

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 }