Code for Technion Formula car sensors reader
Dependencies: mbed Buffer FATFileSystem
Fork of SX1272PingPong by
This is code is part of a Technion course project in advanced IoT, implementing a device to read and transmit sensors data from a Formula racing car built by students at Technion - Israel Institute of Technology.
How to install
- Create an account on Mbed: https://os.mbed.com/account/signup/
- Import project into Compiler
- In the Program Workspace select "Formula_Nucleo_Reader"
- Select a Platform like so:
- Click button at top-left
- Add Board
- Search "NUCLEO F103RB" and then "Add to your Mbed Compiler"
- Finally click "Compile", if the build was successful, the binary would download automatically
- To install it on device simply plug it in to a PC, open device drive and drag then drop binary file in it
Revision 15:2e0d977dbb31, committed 2018-05-17
- Comitter:
- wardm
- Date:
- Thu May 17 20:37:41 2018 +0000
- Parent:
- 14:ab6eecd44b7a
- Commit message:
- V1.0.0
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferedSerial/Buffer.lib Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,1 @@ +https://mbed.org/users/sam_grove/code/Buffer/#89564915f2a7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferedSerial/BufferedSerial.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,158 @@ +/** + * @file BufferedSerial.cpp + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "BufferedSerial.h" +#include <stdarg.h> + +BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name) + : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size)) +{ + RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq); + this->_buf_size = buf_size; + this->_tx_multiple = tx_multiple; + return; +} + +BufferedSerial::~BufferedSerial(void) +{ + RawSerial::attach(NULL, RawSerial::RxIrq); + RawSerial::attach(NULL, RawSerial::TxIrq); + + return; +} + +int BufferedSerial::readable(void) +{ + return _rxbuf.available(); // note: look if things are in the buffer +} + +int BufferedSerial::writeable(void) +{ + return 1; // buffer allows overwriting by design, always true +} + +int BufferedSerial::getc(void) +{ + return _rxbuf; +} + +int BufferedSerial::putc(int c) +{ + _txbuf = (char)c; + BufferedSerial::prime(); + + return c; +} + +int BufferedSerial::puts(const char *s) +{ + if (s != NULL) { + const char* ptr = s; + + while(*(ptr) != 0) { + _txbuf = *(ptr++); + } + _txbuf = '\n'; // done per puts definition + BufferedSerial::prime(); + + return (ptr - s) + 1; + } + return 0; +} + +int BufferedSerial::printf(const char* format, ...) +{ + char buffer[this->_buf_size]; + memset(buffer,0,this->_buf_size); + int r = 0; + + va_list arg; + va_start(arg, format); + r = vsprintf(buffer, format, arg); + // this may not hit the heap but should alert the user anyways + if(r > this->_buf_size) { + error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__,this->_buf_size,r); + va_end(arg); + return 0; + } + va_end(arg); + r = BufferedSerial::write(buffer, r); + + return r; +} + +ssize_t BufferedSerial::write(const void *s, size_t length) +{ + if (s != NULL && length > 0) { + const char* ptr = (const char*)s; + const char* end = ptr + length; + + while (ptr != end) { + _txbuf = *(ptr++); + } + BufferedSerial::prime(); + + return ptr - (const char*)s; + } + return 0; +} + + +void BufferedSerial::rxIrq(void) +{ + // read from the peripheral and make sure something is available + if(serial_readable(&_serial)) { + _rxbuf = serial_getc(&_serial); // if so load them into a buffer + } + + return; +} + +void BufferedSerial::txIrq(void) +{ + // see if there is room in the hardware fifo and if something is in the software fifo + while(serial_writable(&_serial)) { + if(_txbuf.available()) { + serial_putc(&_serial, (int)_txbuf.get()); + } else { + // disable the TX interrupt when there is nothing left to send + RawSerial::attach(NULL, RawSerial::TxIrq); + break; + } + } + + return; +} + +void BufferedSerial::prime(void) +{ + // if already busy then the irq will pick this up + if(serial_writable(&_serial)) { + RawSerial::attach(NULL, RawSerial::TxIrq); // make sure not to cause contention in the irq + BufferedSerial::txIrq(); // only write to hardware in one place + RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq); + } + + return; +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BufferedSerial/BufferedSerial.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,140 @@ + +/** + * @file BufferedSerial.h + * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX + * @author sam grove + * @version 1.0 + * @see + * + * Copyright (c) 2013 + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BUFFEREDSERIAL_H +#define BUFFEREDSERIAL_H + +#include "mbed.h" +#include "MyBuffer.h" + +/** A serial port (UART) for communication with other serial devices + * + * Can be used for Full Duplex communication, or Simplex by specifying + * one pin as NC (Not Connected) + * + * Example: + * @code + * #include "mbed.h" + * #include "BufferedSerial.h" + * + * BufferedSerial pc(USBTX, USBRX); + * + * int main() + * { + * while(1) + * { + * Timer s; + * + * s.start(); + * pc.printf("Hello World - buffered\n"); + * int buffered_time = s.read_us(); + * wait(0.1f); // give time for the buffer to empty + * + * s.reset(); + * printf("Hello World - blocking\n"); + * int polled_time = s.read_us(); + * s.stop(); + * wait(0.1f); // give time for the buffer to empty + * + * pc.printf("printf buffered took %d us\n", buffered_time); + * pc.printf("printf blocking took %d us\n", polled_time); + * wait(0.5f); + * } + * } + * @endcode + */ + +/** + * @class BufferedSerial + * @brief Software buffers and interrupt driven tx and rx for Serial + */ +class BufferedSerial : public RawSerial +{ +private: + MyBuffer <char> _rxbuf; + MyBuffer <char> _txbuf; + uint32_t _buf_size; + uint32_t _tx_multiple; + + void rxIrq(void); + void txIrq(void); + void prime(void); + +public: + /** Create a BufferedSerial port, connected to the specified transmit and receive pins + * @param tx Transmit pin + * @param rx Receive pin + * @param buf_size printf() buffer size + * @param tx_multiple amount of max printf() present in the internal ring buffer at one time + * @param name optional name + * @note Either tx or rx may be specified as NC if unused + */ + BufferedSerial(PinName tx, PinName rx, uint32_t buf_size = 256, uint32_t tx_multiple = 4,const char* name=NULL); + + /** Destroy a BufferedSerial port + */ + virtual ~BufferedSerial(void); + + /** Check on how many bytes are in the rx buffer + * @return 1 if something exists, 0 otherwise + */ + virtual int readable(void); + + /** Check to see if the tx buffer has room + * @return 1 always has room and can overwrite previous content if too small / slow + */ + virtual int writeable(void); + + /** Get a single byte from the BufferedSerial Port. + * Should check readable() before calling this. + * @return A byte that came in on the Serial Port + */ + virtual int getc(void); + + /** Write a single byte to the BufferedSerial Port. + * @param c The byte to write to the Serial Port + * @return The byte that was written to the Serial Port Buffer + */ + virtual int putc(int c); + + /** Write a string to the BufferedSerial Port. Must be NULL terminated + * @param s The string to write to the Serial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int puts(const char *s); + + /** Write a formatted string to the BufferedSerial Port. + * @param format The string + format specifiers to write to the Serial Port + * @return The number of bytes written to the Serial Port Buffer + */ + virtual int printf(const char* format, ...); + + /** Write data to the Buffered Serial Port + * @param s A pointer to data to send + * @param length The amount of data being pointed to + * @return The number of bytes written to the Serial Port Buffer + */ + virtual ssize_t write(const void *s, std::size_t length); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DS3231/DS3231.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,138 @@ +#include "DS3231.h" + +DS3231::DS3231(PinName sda, PinName scl) : i2c(sda, scl) + { + } + + +// BCD to decimal conversion +int DS3231::bcd2dec(int k) + {return(((k&0xF0)>>4)*10+(k&0x0F));} + + +// decimal to BCD conversion +int DS3231::dec2bcd(int k) + {return((k/10)*16+(k%10));} + +void DS3231::setI2Cfrequency(int frequency) + {i2c.frequency(frequency); + } + +// read temperature from DS3231 +float DS3231::readTemp() + {char buf[2]; + buf[0]=DS3231_MSB_Temp; + int w=i2c.write(DS3231_Address,buf,1); + int r=i2c.read(DS3231_Address,buf,2); + error=((w!=0)||(r!=0)); + return(buf[0]+buf[1]/256.0);} + +// force temperatue conversion +void DS3231::convertTemperature() + {int Control=readRegister(DS3231_Control)|DS3231_bit_CONV; + writeRegister(DS3231_Control,Control); + } + +// decode time registers +void DS3231::decodeTime(int regHours, int regMinutes, int regSeconds,int *Hours, int *Minutes, int *Seconds) + {*Hours=bcd2dec(regHours); + *Minutes=bcd2dec(regMinutes); + *Seconds=bcd2dec(regSeconds); + } + + +// read time registers dand decode them to decimal +void DS3231::readTime(int *hours, int *minutes, int *seconds) + {char buf[3]; + buf[0]=DS3231_Seconds; + int w=i2c.write(DS3231_Address,buf,1); + int r=i2c.read(DS3231_Address,buf,3); + decodeTime(buf[2],buf[1],buf[0],hours,minutes,seconds); + error=((w!=0)||(r!=0)); + } + +// set time register +void DS3231::setTime(int hours, int minutes, int seconds) + {writeRegister(DS3231_Seconds,dec2bcd(seconds)); + writeRegister(DS3231_Minutes,dec2bcd(minutes)); + writeRegister(DS3231_Hours,dec2bcd(hours)); + } + +// decode date registers +void DS3231::decodeDate(int regDate,int regMonth, int regYear, int *date, int *month, int *year) + {*date=bcd2dec(regDate); + int century=regMonth&128; + *month=bcd2dec(regMonth&127); + *year=bcd2dec(regYear); + if (century==0) // only XXth and XXIst centuries allowed + {*year=*year+1900;} + else + {*year=*year+2000;} + } + +// read date registers +void DS3231::readDate(int *date, int *month, int *year) + {char buf[3]; + buf[0]=DS3231_Date; + int w=i2c.write(DS3231_Address,buf,1); + int r=i2c.read(DS3231_Address,buf,3); + decodeDate(buf[0],buf[1],buf[2],date,month,year); + error=((w!=0)||(r!=0)); + } + +// set the date registers +void DS3231::setDate(int dayOfWeek, int date, int month, int year) + {writeRegister(DS3231_Date,dec2bcd(date)); + writeRegister(DS3231_Day,dayOfWeek); + int century=0; // only XXth and XXIst centuries allowed + if (year<1900){year=1900;} + if (year>2099){year=2099;} + if (year<2000) + {year=year-1900;} + else + {year=year-2000;century=1;} + writeRegister(DS3231_Month_Century,dec2bcd(month)+128*century); + writeRegister(DS3231_Year,dec2bcd(year)); + } + +// read date and time registers +void DS3231::readDateTime(int *dayOfWeek, int *date, int *month, int *year, int *hours, int *minutes, int *seconds) + {char buf[7]; + buf[0]=DS3231_Seconds; + int w=i2c.write(DS3231_Address,buf,1); + int r=i2c.read(DS3231_Address,buf,7); + decodeTime(buf[2],buf[1],buf[0],hours,minutes,seconds); + *dayOfWeek=buf[3]; + decodeDate(buf[4],buf[5],buf[6],date,month,year); + error=((w!=0)||(r!=0)); + } + +// read a register +int DS3231::readRegister(char reg) + {char buf[1]; + buf[0]=reg; + int w=i2c.write(DS3231_Address,buf,1); + int r=i2c.read(DS3231_Address,buf,1); + error=((w!=0)||(r!=0)); + return(buf[0]); + } + +// write a register +void DS3231::writeRegister(int reg,char byte) + {char buf[2]; + buf[0]=reg; + buf[1]=byte; + int w=i2c.write(DS3231_Address,buf,2); + error=(w!=0); + } + +void DS3231::eraseOSF() + {int reg=readRegister(DS3231_Control_Status); + reg=reg&0x7F; + writeRegister(DS3231_Control_Status,reg); + } + +bool DS3231::OSF() + {int reg=readRegister(DS3231_Control_Status); + return(reg&DS3231_bit_OSF); + } \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DS3231/DS3231.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,222 @@ +/** mbded library for driving the PMAXIM DS3231 Real Time Clock +* datasheet link : http://datasheets.maximintegrated.com/en/ds/DS3231.pdf +* breakout : MACETECH ChronoDot V2.1 High Precision RTC +* remi cormier 2012 +* WARNING : sda and sdl should be pulled up with 2.2k resistor +*/ + +/** Example code +* @code +// DS3231 Library test program +// remi cormier 2012 + +#include "mbed.h" +#include "DS3231.h" + +Serial pc(USBTX, USBRX); + +int hour; +int minute; +int second; + +int dayOfWeek; +int date; +int month; +int year; + +DS3231 RTC(p28,p27); + + +int main() + {printf("\r\n\nDS3231 Library test program\r\nremi cormier 2012\r\n\n"); + + RTC.setI2Cfrequency(400000); + + //RTC.writeRegister(DS3231_Aging_Offset,0); // uncomment to set Aging Offset 1LSB = approx. 0.1 ppm according from datasheet = 0.05 ppm @ 21 °C from my measurments + + RTC.convertTemperature(); + + int reg=RTC.readRegister(DS3231_Aging_Offset); + if (reg>127) + {reg=reg-256;} + pc.printf("Aging offset : %i\r\n",reg); + + pc.printf("OSF flag : %i",RTC.OSF()); + pc.printf("\r\n"); + + RTC.readDate(&date,&month,&year); + pc.printf("date : %02i-%02i-%02i",date,month,year); + pc.printf("\r\n"); + + //RTC.setTime(19,48,45); // uncomment to set time + + RTC.readTime(&hour,&minute,&second); + pc.printf("time : %02i:%02i:%02i",hour,minute,second); + pc.printf("\r\n"); + + //RTC.setDate(6,22,12,2012); // uncomment to set date + + RTC.readDateTime(&dayOfWeek,&date,&month,&year,&hour,&minute,&second); + pc.printf("date time : %i / %02i-%02i-%02i %02i:%02i:%02i",dayOfWeek,date,month,year,hour,minute,second); + pc.printf("\r\n"); + + pc.printf("temperature :%6.2f",RTC.readTemp()); + pc.printf("\r\n"); + } +* @endcode +*/ + + +#include "mbed.h" + +#ifndef MBED_DS3231_H +#define MBED_DS3231_H + +//DS3231 8 bit adress +#define DS3231_Address 0xD0 + +//DS3231 registers +#define DS3231_Seconds 0x00 +#define DS3231_Minutes 0x01 +#define DS3231_Hours 0x02 +// DS3231 Hours bits +#define DS3231_bit_AM_PM 0x20 +#define DS3231_bit_12_24 0x40 + +#define DS3231_Day 0x03 +#define DS3231_Date 0x04 +#define DS3231_Month_Century 0x05 +#define DS3231_Year 0x06 +#define DS3231_Alarm1_Seconds 0x07 +#define DS3231_Alarm1_Minutes 0x08 +#define DS3231_Alarm1_Hours 0x09 +#define DS3231_Alarm1_Day_Date 0x0A +#define DS3231_Alarm2_Minutes 0x0B +#define DS3231_Alarm2_Hours 0x0C +#define DS3231_Alarm_2_Day_Date 0x0D + +#define DS3231_Control 0x0E +// DS3231 Control bits +#define DS3231_bit_A1IE 1 +#define DS3231_bit_A2IE 2 +#define DS3231_bit_INTCN 4 +#define DS3231_bit_SQW_1Hz 0 +#define DS3231_bit_SQW_1024Hz 8 +#define DS3231_bit_SQW_4096Hz 16 +#define DS3231_bit_SQW_8192Hz 24 +#define DS3231_bit_CONV 32 +#define DS3231_bit_BBSQW 64 +#define DS3231_bit_EOSCb 128 + + +#define DS3231_Control_Status 0x0F +// DS3231 Control/Status bits +#define DS3231_bit_BSY 0x04 +#define DS3231_bit_EN32kHz 0x08 +#define DS3231_bit_OSF 0x80 + +#define DS3231_Aging_Offset 0x10 +#define DS3231_MSB_Temp 0x11 +#define DS3231_LSB_Temp 0x12 + +/* Interface to MAXIM DS3231 RTC */ +class DS3231 + {public : + /** Create an instance of the DS3231 connected to specfied I2C pins + * + * @param sda The I2C data pin + * @param scl The I2C clock pin + */ + DS3231(PinName sda, PinName scl); + + /** set I2C bus speed + * @param frequency : I2C clocl frequenct (Hz) + */ + void setI2Cfrequency(int frequency); + + /** Read the temperature + * + * @return The temperature + */ + float readTemp(); + + /** Read the time registers + * @param hours + * @param minutes + * @param seconds + */ + void readTime(int *hours, int *minutes, int *seconds); + + /** force temperature conversion + * + */ + void convertTemperature(); + + /** Set the time registers + * @param hours + * @param minutes + * @param seconds + */ + void setTime(int hours, int minutes, int seconds); + + /** Read the date registers + * @param date + * @param month + * @param year + */ + void readDate(int *date, int *month, int *year); + + /** Set the date registers + * @param dayOfWeek : day of week + * @param date + * @param month + * @param year + */ + void setDate(int dayOfWeek, int date, int month, int year); + + /** Read the date and time registers + * @param dayOfWeek : day of week + * @param date + * @param month + * @param year + * @param hours + * @param minutes + * @param seconds + */ + void readDateTime(int *dayOfWeek, int *date, int *month, int *year, int *hours, int *minutes, int *seconds); + + /** Read a register + * @param reg : register address + * @return The register content + */ + int readRegister(char reg); + + /** Write to a register + * @param reg : register address + * @param The register content + */ + void writeRegister(int reg,char byte); + + /** set OSF (Oscillator Stop Flag) bit to 0 in Control Status register + * should be done just after power up DS3231 + * OSF bit is automaticaly set to 1 when on power up or when the DS3231 oscillator stops + */ + void eraseOSF(); + + /** Return OSF bit. If true the oscillator stopped or the DS3231 just powered up + * @return The OSF bit + */ + bool OSF(); + + bool error; + + private : + I2C i2c; + int bcd2dec(int k); // bcd to decimal conversion + int dec2bcd(int k); // decimal to bcd conversion + void decodeTime(int regHours, int regMinutes, int regSeconds,int *Hours, int *Minutes, int *Seconds); + void decodeDate(int regDate,int regMonth, int regYear, int *date, int *month, int *year); + }; + + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LSM303DLHC/LSM303DLHC.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,196 @@ +#include "mbed.h" +#include "LSM303DLHC.h" + +LSM303DLHC::LSM303DLHC(PinName sda, PinName scl) : i2c(sda, scl){ + i2c.frequency(400000); + + // HERE GIVES DEVICE DEFAULT + ACtrl(LP_OFF); // ACC Normal Power Mode + ACtrl(ADR3); // ACC ON and Date Rate 25Hz + ACtrl(XYZ); // ACC XYZ Axis Enable + ACtrl(HPF_ON); // ACC internal HPF IN USE + ACtrl(HPF_CF0); // ACC HPF Cutoff Freq = option 0 + ACtrl(HPF_NORM_R); // ACC HPF Model = Normal + ACtrl(BDU_CONT); // ACC data continuous + ACtrl(G4); // ACC Range +/-4g + ACtrl(HIGH_R); // ACC in High Prec + MCtrl(MDR4); // MAG DR 15Hz + MCtrl(GN4); // MAG GN 4.0Gauss + MCtrl(MD_CONT); // MAG ON and MD Continuous + TCtrl(TEMP_ON); // TEMP ON + + // DEFAULT CALIBRATION PARAMETER + acc_offset[0] = 0; + acc_offset[1] = 0; + acc_offset[2] = 0; + acc_scale[0] = 1; + acc_scale[1] = 1; + acc_scale[2] = 1; + + mag_offset[0] = 0; + mag_offset[1] = 0; + mag_offset[2] = 0; + mag_scale[0] = 1; + mag_scale[1] = 1; + mag_scale[2] = 1; + + temp_offset[0] = 0; + temp_scale[0] = 1; +} + +void LSM303DLHC::GetAcc(float arr[3]){ + data[0] = OUT_X_L_A | (1 << 7); // MSB=1 to read multiple bytes + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, data, 6); + + arr[0] = acc_scale[0]*(acc_offset[0]+((short)(data[1]<<8 | data[0])>>4)); + arr[1] = acc_scale[1]*(acc_offset[1]+((short)(data[3]<<8 | data[2])>>4)); + arr[2] = acc_scale[2]*(acc_offset[2]+((short)(data[5]<<8 | data[4])>>4)); +} + +void LSM303DLHC::GetMag(float arr[3]){ + data[0] = OUT_X_H_M; + i2c.write(MAG_ADDRESS, data, 1); + i2c.read(MAG_ADDRESS, data, 6); + arr[0] = mag_scale[0]*(mag_offset[0]+(short)(data[0]<<8 | data[1])); + arr[1] = mag_scale[1]*(mag_offset[1]+(short)(data[4]<<8 | data[5])); + arr[2] = mag_scale[2]*(mag_offset[2]+(short)(data[2]<<8 | data[3])); +} + +void LSM303DLHC::GetTemp(float arr[1]){ + data[0] = TEMP_OUT_H_M; + i2c.write(MAG_ADDRESS, data, 1); + i2c.read(MAG_ADDRESS, data, 2); + arr[0] = temp_scale[0]*(temp_offset[0]+((short)(data[0]<<8 | data[1])>>4)); +} + +void LSM303DLHC::ACtrl(ACC_ODR cmd){ + data[0] = CTRL_REG1_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b00001111) | (cmd<<4); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_LPen cmd){ + data[0] = CTRL_REG1_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11110111) | (cmd<<3); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_AXIS cmd){ + data[0] = CTRL_REG1_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11111000) | (cmd<<0); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_HPM cmd){ + data[0] = CTRL_REG2_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b00111111) | (cmd<<6); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_HPCF cmd){ + data[0] = CTRL_REG2_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11001111) | (cmd<<4); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_FDS cmd){ + data[0] = CTRL_REG2_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11110111) | (cmd<<3); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_BDU cmd){ + data[0] = CTRL_REG4_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b01111111) | (cmd<<7); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_FS cmd){ + data[0] = CTRL_REG4_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11001111) | (cmd<<4); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::ACtrl(ACC_HR cmd){ + data[0] = CTRL_REG4_A; + i2c.write(ACC_ADDRESS, data, 1); + i2c.read(ACC_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11110111) | (cmd<<3); + i2c.write(ACC_ADDRESS, data, 2); +} + +void LSM303DLHC::TCtrl(TEMP_EN cmd){ + data[0] = CRA_REG_M; + i2c.write(MAG_ADDRESS, data, 1); + i2c.read(MAG_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b01111111) | (cmd<<7); + i2c.write(MAG_ADDRESS, data, 2); +} + +void LSM303DLHC::MCtrl(MAG_DR cmd){ + data[0] = CRA_REG_M; + i2c.write(MAG_ADDRESS, data, 1); + i2c.read(MAG_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11100011) | (cmd<<2); + i2c.write(MAG_ADDRESS, data, 2); +} + +void LSM303DLHC::MCtrl(MAG_GN cmd){ + data[0] = CRB_REG_M; + i2c.write(MAG_ADDRESS, data, 1); + i2c.read(MAG_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b00011111) | (cmd<<5); + i2c.write(MAG_ADDRESS, data, 2); +} + +void LSM303DLHC::MCtrl(MAG_MD cmd){ + data[0] = MR_REG_M; + i2c.write(MAG_ADDRESS, data, 1); + i2c.read(MAG_ADDRESS, &data[1], 1); + data[1] = data[1] & (0b11111100) | (cmd<<0); + i2c.write(MAG_ADDRESS, data, 2); +} + +void LSM303DLHC::WriteReg(int sad, char d[2]){ + i2c.write(sad, d, 2); +} + +void LSM303DLHC::ACal(float offset[3], float scale[3]){ + acc_offset[0] = offset[0]; + acc_offset[1] = offset[1]; + acc_offset[2] = offset[2]; + acc_scale[0] = scale[0]; + acc_scale[1] = scale[1]; + acc_scale[2] = scale[2]; +} + +void LSM303DLHC::MCal(float offset[3], float scale[3]){ + mag_offset[0] = offset[0]; + mag_offset[1] = offset[1]; + mag_offset[2] = offset[2]; + mag_scale[0] = scale[0]; + mag_scale[1] = scale[1]; + mag_scale[2] = scale[2]; +} + +void LSM303DLHC::TCal(float offset[1], float scale[1]){ + temp_offset[0] = offset[0]; + temp_scale[0] = scale[0]; +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LSM303DLHC/LSM303DLHC.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,171 @@ +/* COMPACT USER INSTRUCTION OF LSM303DLHC + +-- ACCELEROMETER PART +void GetAcc( float arr[3] ) // Get Acceleration Value + arr[3] is the xyz-axis acc data + // default range from -2048 to +2047 with step=1 (12bit high prec) or step=4 (10bit normal prec) + // and roughly 1000/g(+/-2g) 500/g(+/-4g) 200/g(+/-8g) 80/g(+/-16g) depend on your device and ACC_FS + // note your calibration setting will change the range +void ACtrl( enum cmd ) e.g. ACtrl(LSM303DLHC::LP_ON) + enum ACC_LPen {LP_OFF,LP_ON} // to ctrl acc power mode + enum ACC_ODR {PW_D,ADR1,ADR2,ADR3,ADR4,ADR5,ADR6,ADR7,ADR8,ADR9} // to ctrl acc data rate + enum ACC_AXIS {NONE,X,Y,XY,Z,XZ,YZ,XYZ} // to sel the acc data of axis you want + enum ACC_HPM {HPF_NORM_R,HPF_REF,HPF_NORM,HPF_AUTO} // to sel acc internal HPF model + enum ACC_HPCF {HPF_CF0,HPF_CF1,HPF_CF2,HPF_CF3} // to switch acc internal HPF cutoff freq + enum ACC_FDS {HPF_OFF,HPF_ON} // to switch on/off acc internal HPF for output + enum ACC_BDU {BDU_CONT,BDU_HOLD} // to sel acc data update mode + enum ACC_FS {G2,G4,G8,G16} // to sel acc full scale of data + enum ACC_HR {LOW_R,HIGH_R} // to sel acc output data precision +void ACal( float offset[3], float scale[3] ); // Acc Calibration Setting + // affect data of GetAcc() by output = scale * ( offset + original ) + // but if internal HPF enable then output = scale * original + // note linear acc has no offset + +-- MAGNETOMETER PART +void GetMag( float arr[3] ); // Get magnetic flux density + arr[3] is the xyz-axis mag data + // default range from -2048 to +2047 with step=1 + // note your calibration setting will change the range +void MCtrl( enum cmd ) e.g. MCtrl(LSM303DLHC::MDR3); + enum MAG_DR {MDR0,MDR1,MDR2,MDR3,MDR4,MDR5,MDR6,MDR7} // to ctrl mag data rate + enum MAG_GN {GN1,GN2,GN3,GN4,GN5,GN6,GN7) // to ctrl mag full scale of data + enum MAG_MD {MD_CONT,MD_SING,MD_SLP,MD_SLP2}; +void MCal(float offset[3], float scale[3]); // Mag Calibration + // affect data of GetMag() by output = scale * ( offset + original ) + +-- TEMPERATURE METER PART +void GetTemp( float arr[1] ); // Get temperature + arr[1] is the temperture + // default range from -2048 to +2047 +void TCal( enum cmd ) + enum TEMP_EN{TEMP_OFF,TEMP_ON}; // to switch on/off TEMP +void TempCal(float offset[1], float scale[1]); // Mag Calibration + //affect data of GetMag() by output = scale * ( offset + original ) + +-- DIRECT WRITE REG +void WriteReg(int sad, char d[2]); // Write value to reg + sad = ACC_ADDRESS or MAG_ADDRESS + d[0] = Register Address + d[1] = Register Value + CAUTION: THE FUNTION USES UNFRIENDLY ASSIGN + CAUTION: WRITING TO RESERVED REG MAY CAUSE PERMANENT DAMAGE + PLEASE FOLLOW DATASHEET RIGIDLY +*/ + + +#ifndef LSM303DLHC_H +#define LSM303DLHC_H +#include "mbed.h" +#include "LSM303DLHC_REG.h" + +class LSM303DLHC { + public: + //// PORT + LSM303DLHC(PinName sda, PinName scl); + + //// REG CTRL + // modify the default in LSM303DLHC.cpp + + //// CTRL_REG1_A (20h) + // ACC Low Power Mode ON/OFF + enum ACC_LPen { LP_OFF = 0, LP_ON = 1} ; + void ACtrl(ACC_LPen cmd); + // ACC Data Rate NOTE: ACC SWITCH IS HERE + enum ACC_ODR { PW_D = 0, ADR1 = 1, ADR2 = 2, ADR3 = 3, ADR4 = 4, ADR5 = 5, ADR6 = 6, ADR7 = 7, ADR8 = 8, ADR9 = 9}; + // PW Down 1Hz 10Hz 25Hz 50Hz 100Hz 200Hz 400Hz 1620Hz@LP 1344Hz@NM/5376HZ@LP + void ACtrl(ACC_ODR cmd); + // ACC AXIS SEL + enum ACC_AXIS { NONE = 0, X = 1, Y = 2, XY = 3, Z = 4, XZ = 5, YZ = 6, XYZ = 7 }; + void ACtrl(ACC_AXIS cmd); + + //// CTRL_REG2_A (21h) + // ACC HPF Mode + enum ACC_HPM { HPF_NORM_R = 0, HPF_REF = 1, HPF_NORM = 2, HPF_AUTO = 3 }; + void ACtrl(ACC_HPM cmd); + // ACC HPF Cutoff Freq + enum ACC_HPCF { HPF_CF0 = 0, HPF_CF1 = 1, HPF_CF2 = 2, HPF_CF3 = 3}; + void ACtrl(ACC_HPCF cmd); + // ACC HPF ON/OFF for output + enum ACC_FDS { HPF_OFF = 0, HPF_ON = 1 }; + void ACtrl(ACC_FDS cmd); + + //// CTRL_REG4_A (23h) + // ACC Block Date Update Mode + enum ACC_BDU { BDU_CONT = 0, BDU_HOLD = 1 }; + void ACtrl(ACC_BDU cmd); + // ACC Output Full-Scale SEL + enum ACC_FS {G2 = 0b00, G4 = 0b01, G8 = 0b10, G16= 0b11 }; + // +/-2g +/-4g +/-8g +/-16g + void ACtrl(ACC_FS cmd); + // ACC Output in High/Low Resolution (Precision SEL) + enum ACC_HR { LOW_R = 0, HIGH_R = 1 }; + // 10bit 12bit + void ACtrl(ACC_HR cmd); + + //// CRA_REG_M (00h) + // TEMP Sensor En NOTE: TEMP SWITCH IS HERE + enum TEMP_EN { TEMP_OFF = 0, TEMP_ON = 1}; + void TCtrl(TEMP_EN cmd); + // MAG Data Rate (Note: MAG_DR determines DRDY pin) + enum MAG_DR { MDR0 = 0, MDR1 = 1, MDR2 = 2, MDR3 = 3, MDR4 = 4, MDR5 = 5, MDR6 = 6, MDR7 = 7}; + // 0.75Hz 1.5Hz 3Hz 7.5Hz 15Hz 30Hz 75Hz 220Hz + void MCtrl(MAG_DR cmd); // MAG Date Rate + + //// CRB_REG_M (01h) + // MAG Gain (Range SEL) + enum MAG_GN { GN1 = 1, GN2 = 2, GN3 = 3, GN4 = 4, GN5 = 5, GN6 = 6, GN7 = 7}; + // 1.3 1.9 2.5 4.0 4.7 5.6 8.1 (+/- Gauss) + void MCtrl(MAG_GN cmd); // MAG Measure Range + + //// MR_REG_M (02h) + // MAG Mode NOTE: MAG SWITCH IS HERE + enum MAG_MD { MD_CONT = 0, MD_SING = 1, MD_SLP = 2, MD_SLP2 = 3}; + // Continuous single-conv sleep-mode sleep-mode + void MCtrl(MAG_MD cmd); + + //// Change more regs + void WriteReg(int sad, char d[2]); // Write value to reg + // sad = ACC_ADDRESS or MAG_ADDRESS + // d[0] = Register Address and d[1] = Register Value + // CAUTION: THE FUNTION USES UNFRIENDLY ASSIGN AND WRITING TO RESERVED REG MAY CAUSE PERMANENT DAMAGE + // PLEASE FOLLOW DATASHEET RIGIDLY + + //// Get Data + // please refer to the top: COMPACT USER INSTRUCTION + void GetAcc(float arr[3]); // Get acc + void GetMag(float arr[3]); // Get mag + void GetTemp(float arr[1]); // Get temp + + //// sensor reading calibration + // please refer to the top: COMPACT USER INSTRUCTION + void ACal(float offset[3], float scale[3]); // Acc Calibration + void MCal(float offset[3], float scale[3]); // Mag Calibration + void TCal(float offset[1], float scale[1]); // Mag Calibration + + + //// Not implemented function + bool isAccRdy(); // Check if acc has new data + // one way is to use high freq ticker to check STATUS_REG_A (27h) + // I2C@400kHz just enough to check Max Normal Mode Data Rate (1344Hz) + // or someone to teach me how to use CTRL_REG6_A THX THX THX (: + bool isMagRdy(); // check if mag has new data + // one way is to use InterruptIn to trigger from DRDY pin + // DRDY pin freq defined by MAG_DR + + private: + I2C i2c; + + char data[6]; // used as main data exchange + + // use offset to calibrate zero reading + float acc_offset[3]; + float mag_offset[3]; + float temp_offset[1]; + + //use scale to adjust the range to required + float acc_scale[3]; + float mag_scale[3]; + float temp_scale[1]; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LSM303DLHC/LSM303DLHC_REG.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,60 @@ +#ifndef LSM303DLHC_REG_H +#define LSM303DLHC_REG_H + +// ACC SAD +#define ACC_ADDRESS 0x32 +// ACC CTRL SUB +#define CTRL_REG1_A 0x20 //RW ODR(4) LPen Zen Yen Xen +#define CTRL_REG2_A 0x21 //RW HPM(2) HPCF(2) FDS HPCLICK HPIS2 HPIS1 +#define CTRL_REG3_A 0x22 //RW I1_CLICK I1_AOI1 I1_AOI2 I1_DRDY1 I1_DRDY2 I1_WTM I1_OVERRUN - +#define CTRL_REG4_A 0x23 //RW BDU BLE FS1 FS0 HR 0(2) SIM +#define CTRL_REG5_A 0x24 //RW BOOT FIFO_EN - - LIR_INT1 D4D_INT1 LIR_INT2 D4D_INT2 +#define CTRL_REG6_A 0x25 //RW I2_CLICKen I2_INT1 I2_INT2 BOOT_I1 P2_ACT - H_LACTIVE - +#define REFERENCE_A 0x26 //RW Ref7 Ref6 Ref5 Ref4 Ref3 Ref2 Ref1 Ref0 +#define STATUS_REG_A 0x27 //R ZYXOR ZOR YOR XOR ZYXDA ZDA YDA XDA +// ACC OUT SUB +#define OUT_X_L_A 0x28 //R MSB(8) +#define OUT_X_H_A 0x29 //R LSB(4) 0(4) +#define OUT_Y_L_A 0x2A //R ditto +#define OUT_Y_H_A 0x2B //R ditto +#define OUT_Z_L_A 0x2C //R ditto +#define OUT_Z_H_A 0x2D //R ditto +// ACC INT SUB +#define INT1_CFG_A 0x30 +#define INT1_SRC_A 0x31 +#define INT1_THS_A 0x32 +#define INT1_DURATION_A 0x33 +#define INT2_CFG_A 0x34 +#define INT2_SRC_A 0x35 +#define INT2_THS_A 0x36 +#define INT2_DURATION_A 0x37 +// ACC CLICK SUB +#define CLICK_CFG_A 0x38 +#define CLICK_SRC_A 0x39 +#define CLICK_THS_A 0x3A +#define TIME_LIMIT_A 0x3B +#define TIME_LATENCY_A 0x3C +#define TIME_WINDOW_A 0x3D + +// MAG SAD +#define MAG_ADDRESS 0x3C +// MAG CTRL SUB +#define CRA_REG_M 0x00 //RW TEMP_EN 0(2) DR(3) 0(2) +#define CRB_REG_M 0x01 //RW GN(3) 0(5) +#define MR_REG_M 0x02 //RW 0(6) MD(2) +// MAG OUT SUB +#define OUT_X_H_M 0x03 //R LSB(8) +#define OUT_X_L_M 0x04 //R 0(4) MSB(4) +#define OUT_Z_H_M 0x05 //R ditto +#define OUT_Z_L_M 0x06 //R ditto +#define OUT_Y_H_M 0x07 //R ditto +#define OUT_Y_L_M 0x08 //R ditto +#define SR_REG_M 0x09 //R -(6) LOCK DRDY +#define IRA_REG_M 0x0A //R +#define IRB_REG_M 0x0B //R +#define IRC_REG_M 0x0C //R +// Temprature OUT SUB +#define TEMP_OUT_H_M 0x31 //R MSB(8) +#define TEMP_OUT_L_M 0x32 //R LSB(4) 0(4) + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LSM303DLHC/mbed.bld Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/7130f322cb7e \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem/FATFileSystem.lib Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/mbed-official/code/FATFileSystem/#28e685e5ff7f
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem/SDCRC.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,119 @@ +/* SD/MMC File System Library + * Copyright (c) 2016 Neil Thiessen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SDCRC.h" + +namespace SDCRC +{ + +namespace +{ +const char m_Crc7Table[] = { + 0x00, 0x09, 0x12, 0x1B, 0x24, 0x2D, 0x36, 0x3F, + 0x48, 0x41, 0x5A, 0x53, 0x6C, 0x65, 0x7E, 0x77, + 0x19, 0x10, 0x0B, 0x02, 0x3D, 0x34, 0x2F, 0x26, + 0x51, 0x58, 0x43, 0x4A, 0x75, 0x7C, 0x67, 0x6E, + 0x32, 0x3B, 0x20, 0x29, 0x16, 0x1F, 0x04, 0x0D, + 0x7A, 0x73, 0x68, 0x61, 0x5E, 0x57, 0x4C, 0x45, + 0x2B, 0x22, 0x39, 0x30, 0x0F, 0x06, 0x1D, 0x14, + 0x63, 0x6A, 0x71, 0x78, 0x47, 0x4E, 0x55, 0x5C, + 0x64, 0x6D, 0x76, 0x7F, 0x40, 0x49, 0x52, 0x5B, + 0x2C, 0x25, 0x3E, 0x37, 0x08, 0x01, 0x1A, 0x13, + 0x7D, 0x74, 0x6F, 0x66, 0x59, 0x50, 0x4B, 0x42, + 0x35, 0x3C, 0x27, 0x2E, 0x11, 0x18, 0x03, 0x0A, + 0x56, 0x5F, 0x44, 0x4D, 0x72, 0x7B, 0x60, 0x69, + 0x1E, 0x17, 0x0C, 0x05, 0x3A, 0x33, 0x28, 0x21, + 0x4F, 0x46, 0x5D, 0x54, 0x6B, 0x62, 0x79, 0x70, + 0x07, 0x0E, 0x15, 0x1C, 0x23, 0x2A, 0x31, 0x38, + 0x41, 0x48, 0x53, 0x5A, 0x65, 0x6C, 0x77, 0x7E, + 0x09, 0x00, 0x1B, 0x12, 0x2D, 0x24, 0x3F, 0x36, + 0x58, 0x51, 0x4A, 0x43, 0x7C, 0x75, 0x6E, 0x67, + 0x10, 0x19, 0x02, 0x0B, 0x34, 0x3D, 0x26, 0x2F, + 0x73, 0x7A, 0x61, 0x68, 0x57, 0x5E, 0x45, 0x4C, + 0x3B, 0x32, 0x29, 0x20, 0x1F, 0x16, 0x0D, 0x04, + 0x6A, 0x63, 0x78, 0x71, 0x4E, 0x47, 0x5C, 0x55, + 0x22, 0x2B, 0x30, 0x39, 0x06, 0x0F, 0x14, 0x1D, + 0x25, 0x2C, 0x37, 0x3E, 0x01, 0x08, 0x13, 0x1A, + 0x6D, 0x64, 0x7F, 0x76, 0x49, 0x40, 0x5B, 0x52, + 0x3C, 0x35, 0x2E, 0x27, 0x18, 0x11, 0x0A, 0x03, + 0x74, 0x7D, 0x66, 0x6F, 0x50, 0x59, 0x42, 0x4B, + 0x17, 0x1E, 0x05, 0x0C, 0x33, 0x3A, 0x21, 0x28, + 0x5F, 0x56, 0x4D, 0x44, 0x7B, 0x72, 0x69, 0x60, + 0x0E, 0x07, 0x1C, 0x15, 0x2A, 0x23, 0x38, 0x31, + 0x46, 0x4F, 0x54, 0x5D, 0x62, 0x6B, 0x70, 0x79 +}; + +const unsigned short m_Crc16Table[256] = { + 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, + 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, + 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, + 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, + 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, + 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, + 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, + 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, + 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, + 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, + 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, + 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, + 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, + 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, + 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, + 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, + 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, + 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, + 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, + 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, + 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, + 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, + 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, + 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, + 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, + 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, + 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, + 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, + 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, + 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, + 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, + 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0 +}; +} + +char crc7(const char* data, int length) +{ + //Calculate the CRC7 checksum for the specified data block + char crc = 0; + for (int i = 0; i < length; i++) { + crc = m_Crc7Table[(crc << 1) ^ data[i]]; + } + + //Return the calculated checksum + return crc; +} + +unsigned short crc16(const char* data, int length) +{ + //Calculate the CRC16 checksum for the specified data block + unsigned short crc = 0; + for (int i = 0; i < length; i++) { + crc = (crc << 8) ^ m_Crc16Table[((crc >> 8) ^ data[i]) & 0x00FF]; + } + + //Return the calculated checksum + return crc; +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem/SDCRC.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,30 @@ +/* SD/MMC File System Library + * Copyright (c) 2016 Neil Thiessen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SD_CRC_H +#define SD_CRC_H + +#include "mbed.h" + +namespace SDCRC +{ + +char crc7(const char* data, int length); +unsigned short crc16(const char* data, int length); + +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem/SDFileSystem.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,934 @@ +/* SD/MMC File System Library + * Copyright (c) 2016 Neil Thiessen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "SDFileSystem.h" +#include "diskio.h" +#include "pinmap.h" +#include "SDCRC.h" + +SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype, int hz) + : FATFileSystem(name), + m_Spi(mosi, miso, sclk), + m_Cs(cs, 1), + m_Cd(cd), + m_FREQ(hz) +{ + //Initialize the member variables + m_CardType = CARD_NONE; + m_Crc = true; + m_LargeFrames = false; + m_WriteValidation = true; + m_Status = STA_NOINIT; + + //Enable the internal pull-up resistor on MISO + pin_mode(miso, PullUp); + + //Configure the SPI bus + m_Spi.format(8, 0); + + //Configure the card detect pin + if (cdtype == SWITCH_POS_NO) { + m_Cd.mode(PullDown); + m_CdAssert = 1; + m_Cd.fall(this, &SDFileSystem::onCardRemoval); + } else if (cdtype == SWITCH_POS_NC) { + m_Cd.mode(PullDown); + m_CdAssert = 0; + m_Cd.rise(this, &SDFileSystem::onCardRemoval); + } else if (cdtype == SWITCH_NEG_NO) { + m_Cd.mode(PullUp); + m_CdAssert = 0; + m_Cd.rise(this, &SDFileSystem::onCardRemoval); + } else if (cdtype == SWITCH_NEG_NC) { + m_Cd.mode(PullUp); + m_CdAssert = 1; + m_Cd.fall(this, &SDFileSystem::onCardRemoval); + } else { + m_CdAssert = -1; + } +} + +bool SDFileSystem::card_present() +{ + //Check the card socket + checkSocket(); + + //Return whether or not a card is present + return !(m_Status & STA_NODISK); +} + +SDFileSystem::CardType SDFileSystem::card_type() +{ + //Check the card socket + checkSocket(); + + //Return the card type + return m_CardType; +} + +bool SDFileSystem::crc() +{ + //Return whether or not CRC is enabled + return m_Crc; +} + +void SDFileSystem::crc(bool enabled) +{ + //Check the card socket + checkSocket(); + + //Just update the member variable if the card isn't initialized + if (m_Status & STA_NOINIT) { + m_Crc = enabled; + return; + } + + //Enable or disable CRC + if (enabled && !m_Crc) { + //Send CMD59(0x00000001) to enable CRC + m_Crc = true; + commandTransaction(CMD59, 0x00000001); + } else if (!enabled && m_Crc) { + //Send CMD59(0x00000000) to disable CRC + commandTransaction(CMD59, 0x00000000); + m_Crc = false; + } +} + +bool SDFileSystem::large_frames() +{ + //Return whether or not 16-bit frames are enabled + return m_LargeFrames; +} + +void SDFileSystem::large_frames(bool enabled) +{ + //Set whether or not 16-bit frames are enabled + m_LargeFrames = enabled; +} + +bool SDFileSystem::write_validation() +{ + //Return whether or not write validation is enabled + return m_WriteValidation; +} + +void SDFileSystem::write_validation(bool enabled) +{ + //Set whether or not write validation is enabled + m_WriteValidation = enabled; +} + +int SDFileSystem::unmount() +{ + //Unmount the filesystem + FATFileSystem::unmount(); + + //Change the status to not initialized, and the card type to unknown + m_Status |= STA_NOINIT; + m_CardType = CARD_UNKNOWN; + + //Always succeeds + return 0; +} + +int SDFileSystem::disk_initialize() +{ + char token; + unsigned int resp; + Timer timer; + + //Make sure there's a card in the socket before proceeding + checkSocket(); + if (m_Status & STA_NODISK) + return m_Status; + + //Make sure we're not already initialized before proceeding + if (!(m_Status & STA_NOINIT)) + return m_Status; + + //Set the SPI frequency to 400kHz for initialization + m_Spi.frequency(400000); + + //Try to reset the card up to 3 times + for (int f = 0; f < 3; f++) { + //Send 80 dummy clocks with /CS deasserted and DI held high + m_Cs = 1; + for (int i = 0; i < 10; i++) { + m_Spi.write(0xFF); + } + + //Send CMD0(0x00000000) to reset the card + token = commandTransaction(CMD0, 0x00000000); + if (token == 0x01) { + break; + } + } + + //Check if the card reset + if (token != 0x01) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + + //Send CMD59(0x00000001) to enable CRC if necessary + if (m_Crc) { + if (commandTransaction(CMD59, 0x00000001) != 0x01) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + } + + //Send CMD8(0x000001AA) to see if this is an SDCv2 card + if (commandTransaction(CMD8, 0x000001AA, &resp) == 0x01) { + //This is an SDCv2 card, get the 32-bit return value and verify the voltage range/check pattern + if ((resp & 0xFFF) != 0x1AA) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + + //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V + if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + + //Try to initialize the card using ACMD41(0x40100000) for up to 2 seconds + timer.start(); + do { + token = commandTransaction(ACMD41, 0x40100000); + } while (token == 0x01 && timer.read_ms() < 2000); + timer.stop(); + timer.reset(); + + //Check if the card initialized + if (token != 0x00) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + + //Send CMD58(0x00000000) to read the OCR + if (commandTransaction(CMD58, 0x00000000, &resp) == 0x00) { + //Check the CCS bit to determine if this is a high capacity card + if (resp & (1 << 30)) + m_CardType = CARD_SDHC; + else + m_CardType = CARD_SD; + + //Increase the SPI frequency to full speed (up to 50MHz for SDCv2) + if (m_FREQ > 25000000) { + if (enableHighSpeedMode()) { + if (m_FREQ > 50000000) { + m_Spi.frequency(50000000); + } else { + m_Spi.frequency(m_FREQ); + } + } else { + m_Spi.frequency(25000000); + } + } else { + m_Spi.frequency(m_FREQ); + } + } else { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + } else { + //Didn't respond or illegal command, this is either an SDCv1 or MMC card + //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V + if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + + //Try to initialize the card using ACMD41(0x40100000) for up to 2 seconds + timer.start(); + do { + token = commandTransaction(ACMD41, 0x40100000); + } while (token == 0x01 && timer.read_ms() < 2000); + timer.stop(); + timer.reset(); + + //Check if the card initialized + if (token == 0x00) { + //This is an SDCv1 standard capacity card + m_CardType = CARD_SD; + + //Increase the SPI frequency to full speed (up to 25MHz for SDCv1) + if (m_FREQ > 25000000) + m_Spi.frequency(25000000); + else + m_Spi.frequency(m_FREQ); + } else { + //Try to initialize the card using CMD1(0x00100000) for up to 2 seconds + timer.start(); + do { + token = commandTransaction(CMD1, 0x00100000); + } while (token == 0x01 && timer.read_ms() < 2000); + timer.stop(); + timer.reset(); + + //Check if the card initialized + if (token == 0x00) { + //This is an MMCv3 card + m_CardType = CARD_MMC; + + //Increase the SPI frequency to full speed (up to 20MHz for MMCv3) + if (m_FREQ > 20000000) + m_Spi.frequency(20000000); + else + m_Spi.frequency(m_FREQ); + } else { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + } + } + + //Send ACMD42(0x00000000) to disconnect the internal pull-up resistor on pin 1 if necessary + if (m_CardType != CARD_MMC) { + if (commandTransaction(ACMD42, 0x00000000) != 0x00) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + } + + //Send CMD16(0x00000200) to force the block size to 512B if necessary + if (m_CardType != CARD_SDHC) { + if (commandTransaction(CMD16, 0x00000200) != 0x00) { + //Initialization failed + m_CardType = CARD_UNKNOWN; + return m_Status; + } + } + + //The card is now initialized + m_Status &= ~STA_NOINIT; + + //Return the disk status + return m_Status; +} + +int SDFileSystem::disk_status() +{ + //Check the card socket + checkSocket(); + + //Return the disk status + return m_Status; +} + +int SDFileSystem::disk_read(uint8_t* buffer, uint32_t sector, uint32_t count) +{ + //Make sure the card is initialized before proceeding + if (m_Status & STA_NOINIT) + return RES_NOTRDY; + + //Read a single block, or multiple blocks + if (count > 1) { + return readBlocks((char*)buffer, sector, count) ? RES_OK : RES_ERROR; + } else { + return readBlock((char*)buffer, sector) ? RES_OK : RES_ERROR; + } +} + +int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t sector, uint32_t count) +{ + //Make sure the card is initialized before proceeding + if (m_Status & STA_NOINIT) + return RES_NOTRDY; + + //Make sure the card isn't write protected before proceeding + if (m_Status & STA_PROTECT) + return RES_WRPRT; + + //Write a single block, or multiple blocks + if (count > 1) { + return writeBlocks((const char*)buffer, sector, count) ? RES_OK : RES_ERROR; + } else { + return writeBlock((const char*)buffer, sector) ? RES_OK : RES_ERROR; + } +} + +int SDFileSystem::disk_sync() +{ + //Select the card so we're forced to wait for the end of any internal write processes + if (select()) { + deselect(); + return RES_OK; + } else { + return RES_ERROR; + } +} + +uint32_t SDFileSystem::disk_sectors() +{ + //Make sure the card is initialized before proceeding + if (m_Status & STA_NOINIT) + return 0; + + //Try to read the CSD register up to 3 times + for (int f = 0; f < 3; f++) { + //Select the card, and wait for ready + if(!select()) + break; + + //Send CMD9(0x00000000) to read the CSD register + if (writeCommand(CMD9, 0x00000000) == 0x00) { + //Read the 16B CSD data block + char csd[16]; + bool success = readData(csd, 16); + deselect(); + if (success) { + //Calculate the sector count based on the card type + if ((csd[0] >> 6) == 0x01) { + //Calculate the sector count for a high capacity card + unsigned int size = (((csd[7] & 0x3F) << 16) | (csd[8] << 8) | csd[9]) + 1; + return size << 10; + } else { + //Calculate the sector count for a standard capacity card + unsigned int size = (((csd[6] & 0x03) << 10) | (csd[7] << 2) | ((csd[8] & 0xC0) >> 6)) + 1; + size <<= ((((csd[9] & 0x03) << 1) | ((csd[10] & 0x80) >> 7)) + 2); + size <<= (csd[5] & 0x0F); + return size >> 9; + } + } + } else { + //The command failed, get out + break; + } + } + + //The read operation failed 3 times + deselect(); + return 0; +} + +void SDFileSystem::onCardRemoval() +{ + //Check the card socket + checkSocket(); +} + +inline void SDFileSystem::checkSocket() +{ + //Use the card detect switch (if available) to determine if the socket is occupied + if (m_CdAssert != -1) { + if (m_Status & STA_NODISK) { + if (m_Cd == m_CdAssert) { + //The socket is now occupied + m_Status &= ~STA_NODISK; + m_CardType = CARD_UNKNOWN; + } + } else { + if (m_Cd != m_CdAssert) { + //The socket is now empty + m_Status |= (STA_NODISK | STA_NOINIT); + m_CardType = CARD_NONE; + } + } + } +} + +inline bool SDFileSystem::waitReady(int timeout) +{ + char resp; + + //Keep sending dummy clocks with DI held high until the card releases the DO line + m_Timer.start(); + do { + resp = m_Spi.write(0xFF); + } while (resp == 0x00 && m_Timer.read_ms() < timeout); + m_Timer.stop(); + m_Timer.reset(); + + //Return success/failure + return (resp > 0x00); +} + +inline bool SDFileSystem::select() +{ + //Assert /CS + m_Cs = 0; + + //Send 8 dummy clocks with DI held high to enable DO + m_Spi.write(0xFF); + + //Wait for up to 500ms for the card to become ready + if (waitReady(500)) { + return true; + } else { + //We timed out, deselect and return false + deselect(); + return false; + } +} + +inline void SDFileSystem::deselect() +{ + //Deassert /CS + m_Cs = 1; + + //Send 8 dummy clocks with DI held high to disable DO + m_Spi.write(0xFF); +} + +inline char SDFileSystem::commandTransaction(char cmd, unsigned int arg, unsigned int* resp) +{ + //Select the card, and wait for ready + if(!select()) + return 0xFF; + + //Perform the command transaction + char token = writeCommand(cmd, arg, resp); + + //Deselect the card, and return the R1 response token + deselect(); + return token; +} + +char SDFileSystem::writeCommand(char cmd, unsigned int arg, unsigned int* resp) +{ + char token; + + //Try to send the command up to 3 times + for (int f = 0; f < 3; f++) { + //Send CMD55(0x00000000) prior to an application specific command + if (cmd == ACMD22 || cmd == ACMD23 || cmd == ACMD41 || cmd == ACMD42) { + token = writeCommand(CMD55, 0x00000000); + if (token > 0x01) + return token; + + //Deselect and reselect the card between CMD55 and an ACMD + deselect(); + if(!select()) + return 0xFF; + } + + //Prepare the command packet + char cmdPacket[6]; + cmdPacket[0] = cmd; + cmdPacket[1] = arg >> 24; + cmdPacket[2] = arg >> 16; + cmdPacket[3] = arg >> 8; + cmdPacket[4] = arg; + if (m_Crc || cmd == CMD0 || cmd == CMD8) + cmdPacket[5] = (SDCRC::crc7(cmdPacket, 5) << 1) | 0x01; + else + cmdPacket[5] = 0x01; + + //Send the command packet + for (int i = 0; i < 6; i++) + m_Spi.write(cmdPacket[i]); + + //Discard the stuff byte immediately following CMD12 + if (cmd == CMD12) + m_Spi.write(0xFF); + + //Allow up to 8 bytes of delay for the R1 response token + for (int i = 0; i < 9; i++) { + token = m_Spi.write(0xFF); + if (!(token & 0x80)) + break; + } + + //Verify the R1 response token + if (token == 0xFF) { + //No data was received, get out early + break; + } else if (token & (1 << 3)) { + //There was a CRC error, try again + continue; + } else if (token > 0x01) { + //An error occured, get out early + break; + } + + //Handle R2 and R3/R7 response tokens + if (cmd == CMD13 && resp != NULL) { + //Read the R2 response value + *resp = m_Spi.write(0xFF); + } else if ((cmd == CMD8 || cmd == CMD58) && resp != NULL) { + //Read the R3/R7 response value + *resp = (m_Spi.write(0xFF) << 24); + *resp |= (m_Spi.write(0xFF) << 16); + *resp |= (m_Spi.write(0xFF) << 8); + *resp |= m_Spi.write(0xFF); + } + + //The command was successful + break; + } + + //Return the R1 response token + return token; +} + +bool SDFileSystem::readData(char* buffer, int length) +{ + char token; + unsigned short crc; + + //Wait for up to 500ms for a token to arrive + m_Timer.start(); + do { + token = m_Spi.write(0xFF); + } while (token == 0xFF && m_Timer.read_ms() < 500); + m_Timer.stop(); + m_Timer.reset(); + + //Check if a valid start block token was received + if (token != 0xFE) + return false; + + //Check if large frames are enabled or not + if (m_LargeFrames) { + //Switch to 16-bit frames for better performance + m_Spi.format(16, 0); + + //Read the data block into the buffer + unsigned short dataWord; + for (int i = 0; i < length; i += 2) { + dataWord = m_Spi.write(0xFFFF); + buffer[i] = dataWord >> 8; + buffer[i + 1] = dataWord; + } + + //Read the CRC16 checksum for the data block + crc = m_Spi.write(0xFFFF); + + //Switch back to 8-bit frames + m_Spi.format(8, 0); + } else { + //Read the data into the buffer + for (int i = 0; i < length; i++) + buffer[i] = m_Spi.write(0xFF); + + //Read the CRC16 checksum for the data block + crc = (m_Spi.write(0xFF) << 8); + crc |= m_Spi.write(0xFF); + } + + //Return the validity of the CRC16 checksum (if enabled) + return (!m_Crc || crc == SDCRC::crc16(buffer, length)); +} + +char SDFileSystem::writeData(const char* buffer, char token) +{ + //Calculate the CRC16 checksum for the data block (if enabled) + unsigned short crc = (m_Crc) ? SDCRC::crc16(buffer, 512) : 0xFFFF; + + //Wait for up to 500ms for the card to become ready + if (!waitReady(500)) + return false; + + //Send the start block token + m_Spi.write(token); + + //Check if large frames are enabled or not + if (m_LargeFrames) { + //Switch to 16-bit frames for better performance + m_Spi.format(16, 0); + + //Write the data block from the buffer + for (int i = 0; i < 512; i += 2) + m_Spi.write((buffer[i] << 8) | buffer[i + 1]); + + //Send the CRC16 checksum for the data block + m_Spi.write(crc); + + //Switch back to 8-bit frames + m_Spi.format(8, 0); + } else { + //Write the data block from the buffer + for (int i = 0; i < 512; i++) + m_Spi.write(buffer[i]); + + //Send the CRC16 checksum for the data block + m_Spi.write(crc >> 8); + m_Spi.write(crc); + } + + //Return the data response token + return (m_Spi.write(0xFF) & 0x1F); +} + +inline bool SDFileSystem::readBlock(char* buffer, unsigned int lba) +{ + //Try to read the block up to 3 times + for (int f = 0; f < 3; f++) { + //Select the card, and wait for ready + if(!select()) + break; + + //Send CMD17(block) to read a single block + if (writeCommand(CMD17, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) { + //Try to read the block, and deselect the card + bool success = readData(buffer, 512); + deselect(); + + //Return if successful + if (success) + return true; + } else { + //The command failed, get out + break; + } + } + + //The single block read failed + deselect(); + return false; +} + +inline bool SDFileSystem::readBlocks(char* buffer, unsigned int lba, unsigned int count) +{ + //Try to read each block up to 3 times + for (int f = 0; f < 3;) { + //Select the card, and wait for ready + if(!select()) + break; + + //Send CMD18(block) to read multiple blocks + if (writeCommand(CMD18, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) { + //Try to read all of the data blocks + do { + //Read the next block, and break on errors + if (!readData(buffer, 512)) { + f++; + break; + } + + //Update the variables + lba++; + buffer += 512; + f = 0; + } while (--count); + + //Send CMD12(0x00000000) to stop the transmission + if (writeCommand(CMD12, 0x00000000) != 0x00) { + //The command failed, get out + break; + } + + //Deselect the card, and return if successful + deselect(); + if (count == 0) + return true; + } else { + //The command failed, get out + break; + } + } + + //The multiple block read failed + deselect(); + return false; +} + +inline bool SDFileSystem::writeBlock(const char* buffer, unsigned int lba) +{ + //Try to write the block up to 3 times + for (int f = 0; f < 3; f++) { + //Select the card, and wait for ready + if(!select()) + break; + + //Send CMD24(block) to write a single block + if (writeCommand(CMD24, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) { + //Try to write the block, and deselect the card + char token = writeData(buffer, 0xFE); + deselect(); + + //Check the data response token + if (token == 0x0A) { + //A CRC error occured, try again + continue; + } else if (token == 0x0C) { + //A write error occured, get out + break; + } + + //Send CMD13(0x00000000) to verify that the programming was successful if enabled + if (m_WriteValidation) { + unsigned int resp; + if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) { + //Some manner of unrecoverable write error occured during programming, get out + break; + } + } + + //The data was written successfully + return true; + } else { + //The command failed, get out + break; + } + } + + //The single block write failed + deselect(); + return false; +} + +inline bool SDFileSystem::writeBlocks(const char* buffer, unsigned int lba, unsigned int count) +{ + char token; + const char* currentBuffer = buffer; + unsigned int currentLba = lba; + int currentCount = count; + + //Try to write each block up to 3 times + for (int f = 0; f < 3;) { + //If this is an SD card, send ACMD23(count) to set the number of blocks to pre-erase + if (m_CardType != CARD_MMC) { + if (commandTransaction(ACMD23, currentCount) != 0x00) { + //The command failed, get out + break; + } + } + + //Select the card, and wait for ready + if(!select()) + break; + + //Send CMD25(block) to write multiple blocks + if (writeCommand(CMD25, (m_CardType == CARD_SDHC) ? currentLba : currentLba << 9) == 0x00) { + //Try to write all of the data blocks + do { + //Write the next block and break on errors + token = writeData(currentBuffer, 0xFC); + if (token != 0x05) { + f++; + break; + } + + //Update the variables + currentBuffer += 512; + f = 0; + } while (--currentCount); + + //Wait for up to 500ms for the card to finish processing the last block + if (!waitReady(500)) + break; + + //Finalize the transmission + if (currentCount == 0) { + //Send the stop tran token, and deselect the card + m_Spi.write(0xFD); + deselect(); + + //Send CMD13(0x00000000) to verify that the programming was successful if enabled + if (m_WriteValidation) { + unsigned int resp; + if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) { + //Some manner of unrecoverable write error occured during programming, get out + break; + } + } + + //The data was written successfully + return true; + } else { + //Send CMD12(0x00000000) to abort the transmission + if (writeCommand(CMD12, 0x00000000) != 0x00) { + //The command failed, get out + break; + } + + //Deselect the card + deselect(); + + //Check the error token + if (token == 0x0A) { + //Determine the number of well written blocks if possible + unsigned int writtenBlocks = 0; + if (m_CardType != CARD_MMC && select()) { + //Send ACMD22(0x00000000) to get the number of well written blocks + if (writeCommand(ACMD22, 0x00000000) == 0x00) { + //Read the data + char acmdData[4]; + if (readData(acmdData, 4)) { + //Extract the number of well written blocks + writtenBlocks = acmdData[0] << 24; + writtenBlocks |= acmdData[1] << 16; + writtenBlocks |= acmdData[2] << 8; + writtenBlocks |= acmdData[3]; + } + } + deselect(); + } + + //Roll back the variables based on the number of well written blocks + currentBuffer = buffer + (writtenBlocks << 9); + currentLba = lba + writtenBlocks; + currentCount = count - writtenBlocks; + + //Try again + continue; + } else { + //A write error occured, get out + break; + } + } + } else { + //The command failed, get out + break; + } + } + + //The multiple block write failed + deselect(); + return false; +} + +bool SDFileSystem::enableHighSpeedMode() +{ + //Try to issue CMD6 up to 3 times + for (int f = 0; f < 3; f++) { + //Select the card, and wait for ready + if(!select()) + break; + + //Send CMD6(0x80FFFFF1) to change the access mode to high speed + if (writeCommand(CMD6, 0x80FFFFF1) == 0x00) { + //Read the 64B status data block + char status[64]; + bool success = readData(status, 64); + deselect(); + if (success) { + //Return whether or not the operation was successful + return ((status[16] & 0x0F) == 0x1); + } + } else { + //The command failed, get out + break; + } + } + + //The operation failed 3 times + deselect(); + return false; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem/SDFileSystem.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,225 @@ +/* SD/MMC File System Library + * Copyright (c) 2016 Neil Thiessen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SD_FILE_SYSTEM_H +#define SD_FILE_SYSTEM_H + +#include "mbed.h" +#include "FATFileSystem.h" + +/** SDFileSystem class. + * Used for creating a virtual file system for accessing SD/MMC cards via SPI. + * + * Example: + * @code + * #include "mbed.h" + * #include "SDFileSystem.h" + * + * //Create an SDFileSystem object + * SDFileSystem sd(p5, p6, p7, p20, "sd"); + * + * int main() + * { + * //Mount the filesystem + * sd.mount(); + * + * //Perform a write test + * printf("\nWriting to SD card..."); + * FILE *fp = fopen("/sd/sdtest.txt", "w"); + * if (fp != NULL) { + * fprintf(fp, "We're writing to an SD card!"); + * fclose(fp); + * printf("success!\n"); + * } else { + * printf("failed!\n"); + * } + * + * //Perform a read test + * printf("Reading from SD card..."); + * fp = fopen("/sd/sdtest.txt", "r"); + * if (fp != NULL) { + * char c = fgetc(fp); + * if (c == 'W') + * printf("success!\n"); + * else + * printf("incorrect char (%c)!\n", c); + * fclose(fp); + * } else { + * printf("failed!\n"); + * } + * + * //Unmount the filesystem + * sd.unmount(); + * } + * @endcode + */ +class SDFileSystem : public FATFileSystem +{ +public: + /** Represents the different card detect switch types + */ + enum SwitchType { + SWITCH_NONE, /**< No card detect switch (assumes socket is always occupied) */ + SWITCH_POS_NO, /**< Switch shorts to VDD when the socket is occupied (positive logic, normally open) */ + SWITCH_POS_NC, /**< Switch shorts to VDD when the socket is empty (positive logic, normally closed) */ + SWITCH_NEG_NO, /**< Switch shorts to GND when the socket is occupied (negative logic, normally open) */ + SWITCH_NEG_NC /**< Switch shorts to GND when the socket is empty (negative logic, normally closed) */ + }; + + /** Represents the different SD/MMC card types + */ + enum CardType { + CARD_NONE, /**< No card is present */ + CARD_MMC, /**< MMC card */ + CARD_SD, /**< Standard capacity SD card */ + CARD_SDHC, /**< High capacity SD card */ + CARD_UNKNOWN /**< Unknown or unsupported card */ + }; + + /** Create a virtual file system for accessing SD/MMC cards via SPI + * + * @param mosi The SPI data out pin. + * @param miso The SPI data in pin. + * @param sclk The SPI clock pin. + * @param cs The SPI chip select pin. + * @param name The name used to access the virtual filesystem. + * @param cd The card detect pin. + * @param cdtype The type of card detect switch. + * @param hz The SPI bus frequency (defaults to 1MHz). + */ + SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd = NC, SwitchType cdtype = SWITCH_NONE, int hz = 1000000); + + /** Determine whether or not a card is present + * + * @returns + * 'true' if a card is present, + * 'false' if no card is present. + */ + bool card_present(); + + /** Get the detected SD/MMC card type + * + * @returns The detected card type as a CardType enum. + * + * @note Valid after the filesystem has been mounted. + */ + SDFileSystem::CardType card_type(); + + /** Get whether or not CRC is enabled for commands and data + * + * @returns + * 'true' if CRC is enabled for commands and data, + * 'false' if CRC is disabled for commands and data. + */ + bool crc(); + + /** Set whether or not CRC is enabled for commands and data + * + * @param enabled Whether or not to enable CRC for commands and data. + */ + void crc(bool enabled); + + /** Get whether or not 16-bit frames are enabled for data read/write operations + * + * @returns + * 'true' if 16-bit frames will be used during data read/write operations, + * 'false' if 8-bit frames will be used during data read/write operations. + */ + bool large_frames(); + + /** Set whether or not 16-bit frames are enabled for data read/write operations + * + * @param enabled Whether or not 16-bit frames are enabled for data read/write operations. + */ + void large_frames(bool enabled); + + /** Get whether or not write validation is enabled for data write operations + * + * @returns + * 'true' if data writes will be verified using CMD13, + * 'false' if data writes will not be verified. + */ + bool write_validation(); + + /** Set whether or not write validation is enabled for data write operations + * + * @param enabled Whether or not write validation is enabled for data write operations. + */ + void write_validation(bool enabled); + + virtual int unmount(); + virtual int disk_initialize(); + virtual int disk_status(); + virtual int disk_read(uint8_t* buffer, uint32_t sector, uint32_t count); + virtual int disk_write(const uint8_t* buffer, uint32_t sector, uint32_t count); + virtual int disk_sync(); + virtual uint32_t disk_sectors(); + +private: + //Commands + enum Command { + CMD0 = (0x40 | 0), /**< GO_IDLE_STATE */ + CMD1 = (0x40 | 1), /**< SEND_OP_COND */ + CMD6 = (0x40 | 6), /**< SWITCH_FUNC */ + CMD8 = (0x40 | 8), /**< SEND_IF_COND */ + CMD9 = (0x40 | 9), /**< SEND_CSD */ + CMD12 = (0x40 | 12), /**< STOP_TRANSMISSION */ + CMD13 = (0x40 | 13), /**< SEND_STATUS */ + CMD16 = (0x40 | 16), /**< SET_BLOCKLEN */ + CMD17 = (0x40 | 17), /**< READ_SINGLE_BLOCK */ + CMD18 = (0x40 | 18), /**< READ_MULTIPLE_BLOCK */ + ACMD22 = (0x40 | 22), /**< SEND_NUM_WR_BLOCKS */ + ACMD23 = (0x40 | 23), /**< SET_WR_BLK_ERASE_COUNT */ + CMD24 = (0x40 | 24), /**< WRITE_BLOCK */ + CMD25 = (0x40 | 25), /**< WRITE_MULTIPLE_BLOCK */ + ACMD41 = (0x40 | 41), /**< SD_SEND_OP_COND */ + ACMD42 = (0x40 | 42), /**< SET_CLR_CARD_DETECT */ + CMD55 = (0x40 | 55), /**< APP_CMD */ + CMD58 = (0x40 | 58), /**< READ_OCR */ + CMD59 = (0x40 | 59) /**< CRC_ON_OFF */ + }; + + //Member variables + Timer m_Timer; + SPI m_Spi; + DigitalOut m_Cs; + InterruptIn m_Cd; + int m_CdAssert; + const int m_FREQ; + SDFileSystem::CardType m_CardType; + bool m_Crc; + bool m_LargeFrames; + bool m_WriteValidation; + int m_Status; + + //Internal methods + void onCardRemoval(); + void checkSocket(); + bool waitReady(int timeout); + bool select(); + void deselect(); + char commandTransaction(char cmd, unsigned int arg, unsigned int* resp = NULL); + char writeCommand(char cmd, unsigned int arg, unsigned int* resp = NULL); + bool readData(char* buffer, int length); + char writeData(const char* buffer, char token); + bool readBlock(char* buffer, unsigned int lba); + bool readBlocks(char* buffer, unsigned int lba, unsigned int count); + bool writeBlock(const char* buffer, unsigned int lba); + bool writeBlocks(const char* buffer, unsigned int lba, unsigned int count); + bool enableHighSpeedMode(); +}; + +#endif
--- a/SX1272Lib.lib Mon Apr 24 09:29:13 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/teams/Semtech/code/SX1272Lib/#b988b60083a1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/LICENSE.txt Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,25 @@ +--- Revised BSD License --- +Copyright (c) 2013, SEMTECH S.A. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Semtech corporation nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL SEMTECH S.A. BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/debug/debug.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,61 @@ +/* Copyright (c) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef DEBUG_H +#define DEBUG_H + +/** @file debug.h */ + +#ifndef NDEBUG + +#include <stdarg.h> +#include <stdio.h> + +/** Output a debug message + * + * @param format printf-style format string, followed by variables + */ +static inline void debug(const char *format, ...) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); +} + +/** Conditionally output a debug message + * + * @param condition output only if condition is true + * @param format printf-style format string, followed by variables + */ +static inline void debug_if(bool condition, const char *format, ...) { + if(condition) { + va_list args; + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + } +} + +#else + +static inline void debug(const char *format, ...) {} +static inline void debug(bool condition, const char *format, ...) {} + +#endif + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/enums/enums.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,133 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + ( C )2015 Semtech + +Description: - + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#ifndef __ENUMS_H__ +#define __ENUMS_H__ + +/*! + * Radio driver internal state machine states definition + */ +typedef enum RadioState +{ + RF_IDLE = 0, + RF_RX_RUNNING, + RF_TX_RUNNING, + RF_CAD, +}RadioState_t; + +/*! + * Type of the modem. [LORA / FSK] + */ +typedef enum ModemType +{ + MODEM_FSK = 0, + MODEM_LORA +}RadioModems_t; + +/*! + * Type of the supported board. + */ +typedef enum BoardType +{ + SX1272MB2XAS = 0, + SX1272MB1DCS, + NA_MOTE_72, + MDOT_F411RE, + UNKNOWN +}BoardType_t; + +/*! + * Radio FSK modem parameters + */ +typedef struct +{ + int8_t Power; + uint32_t Fdev; + uint32_t Bandwidth; + uint32_t BandwidthAfc; + uint32_t Datarate; + uint16_t PreambleLen; + bool FixLen; + uint8_t PayloadLen; + bool CrcOn; + bool IqInverted; + bool RxContinuous; + uint32_t TxTimeout; + uint32_t RxSingleTimeout; +}RadioFskSettings_t; + +/*! + * Radio FSK packet handler state + */ +typedef struct +{ + uint8_t PreambleDetected; + uint8_t SyncWordDetected; + int8_t RssiValue; + int32_t AfcValue; + uint8_t RxGain; + uint16_t Size; + uint16_t NbBytes; + uint8_t FifoThresh; + uint8_t ChunkSize; +}RadioFskPacketHandler_t; + +/*! + * Radio LoRa modem parameters + */ +typedef struct +{ + int8_t Power; + uint32_t Bandwidth; + uint32_t Datarate; + bool LowDatarateOptimize; + uint8_t Coderate; + uint16_t PreambleLen; + bool FixLen; + uint8_t PayloadLen; + bool CrcOn; + bool FreqHopOn; + uint8_t HopPeriod; + bool IqInverted; + bool RxContinuous; + uint32_t TxTimeout; + bool PublicNetwork; +}RadioLoRaSettings_t; + +/*! + * Radio LoRa packet handler state + */ +typedef struct +{ + int8_t SnrValue; + int8_t RssiValue; + uint8_t Size; +}RadioLoRaPacketHandler_t; + +/*! + * Radio Settings + */ +typedef struct +{ + RadioState State; + ModemType Modem; + uint32_t Channel; + RadioFskSettings_t Fsk; + RadioFskPacketHandler_t FskPacketHandler; + RadioLoRaSettings_t LoRa; + RadioLoRaPacketHandler_t LoRaPacketHandler; +}RadioSettings_t; + + +#endif //__ENUMS_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/radio/radio.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,20 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: Interface for the radios, contains the main functions that a radio needs, and 5 callback functions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#include "radio.h" + +Radio::Radio( RadioEvents_t *events ) +{ + this->RadioEvents = events; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/radio/radio.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,337 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: Interface for the radios, contains the main functions that a radio needs, and 5 callback functions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#ifndef __RADIO_H__ +#define __RADIO_H__ + +#include "mbed.h" + +#include "./enums/enums.h" + +/*! + * @brief Radio driver callback functions + */ +typedef struct +{ + /*! + * @brief Tx Done callback prototype. + */ + void ( *TxDone )( void ); + /*! + * @brief Tx Timeout callback prototype. + */ + void ( *TxTimeout )( void ); + /*! + * @brief Rx Done callback prototype. + * + * @param [IN] payload Received buffer pointer + * @param [IN] size Received buffer size + * @param [IN] rssi RSSI value computed while receiving the frame [dBm] + * @param [IN] snr Raw SNR value given by the radio hardware + * FSK : N/A ( set to 0 ) + * LoRa: SNR value in dB + */ + void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); + /*! + * @brief Rx Timeout callback prototype. + */ + void ( *RxTimeout )( void ); + /*! + * @brief Rx Error callback prototype. + */ + void ( *RxError )( void ); + /*! + * \brief FHSS Change Channel callback prototype. + * + * \param [IN] currentChannel Index number of the current channel + */ + void ( *FhssChangeChannel )( uint8_t currentChannel ); + /*! + * @brief CAD Done callback prototype. + * + * @param [IN] channelDetected Channel Activity detected during the CAD + */ + void ( *CadDone ) ( bool channelActivityDetected ); +}RadioEvents_t; + +/*! + * Interface for the radios, contains the main functions that a radio needs, and 5 callback functions + */ +class Radio +{ +protected: + RadioEvents_t* RadioEvents; + +public: + //------------------------------------------------------------------------- + // Constructor + //------------------------------------------------------------------------- + /*! + * @brief Constructor of the radio object, the parameters are the callback functions described in the header. + * + * @param [IN] events Structure containing the driver callback functions + */ + Radio( RadioEvents_t *events ); + virtual ~Radio( ) {}; + + //------------------------------------------------------------------------- + // Pure virtual functions + //------------------------------------------------------------------------- + /*! + * @brief Initializes the radio + * + * @param [IN] events Structure containing the driver callback functions + */ + virtual void Init( RadioEvents_t *events ) = 0; + /*! + * @brief Return current radio status + * + * @param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] + */ + virtual RadioState GetStatus( void ) = 0; + /*! + * @brief Configures the radio with the given modem + * + * @param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ + virtual void SetModem( RadioModems_t modem ) = 0; + /*! + * @brief Sets the channel frequency + * + * @param [IN] freq Channel RF frequency + */ + virtual void SetChannel( uint32_t freq ) = 0; + /*! + * @brief Sets the channels configuration + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] freq Channel RF frequency + * @param [IN] rssiThresh RSSI threshold + * + * @retval isFree [true: Channel is free, false: Channel is not free] + */ + virtual bool IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ) = 0; + /*! + * @brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * @retval randomValue 32 bits random value + */ + virtual uint32_t Random( void )= 0; + /*! + * @brief Sets the reception parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] bandwidthAfc Sets the AFC Bandwidth ( FSK only ) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * @param [IN] preambleLen Sets the Preamble length ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: Length in symbols ( the hardware adds 4 more symbols ) + * @param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout number of bytes + * LoRa: timeout in symbols + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] payloadLen Sets payload length when fixed lenght is used + * @param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ + virtual void SetRxConfig ( RadioModems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) = 0; + /*! + * @brief Sets the transmission parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] power Sets the output power [dBm] + * @param [IN] fdev Sets the frequency deviation ( FSK only ) + * FSK : [Hz] + * LoRa: 0 + * @param [IN] bandwidth Sets the bandwidth ( LoRa only ) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] preambleLen Sets the preamble length + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] timeout Transmission timeout [us] + */ + virtual void SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) = 0; + /*! + * @brief Checks if the given RF frequency is supported by the hardware + * + * @param [IN] frequency RF frequency to be checked + * @retval isSupported [true: supported, false: unsupported] + */ + virtual bool CheckRfFrequency( uint32_t frequency ) = 0; + /*! + * @brief Computes the packet time on air for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] pktLen Packet payload length + * + * @retval airTime Computed airTime for the given packet payload length + */ + virtual uint32_t TimeOnAir ( RadioModems_t modem, uint8_t pktLen ) = 0; + /*! + * @brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * @param [IN]: buffer Buffer pointer + * @param [IN]: size Buffer size + */ + virtual void Send( uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Sets the radio in sleep mode + */ + virtual void Sleep( void ) = 0; + /*! + * @brief Sets the radio in standby mode + */ + virtual void Standby( void ) = 0; + /*! + * @brief Sets the radio in CAD mode + */ + virtual void StartCad( void ) = 0; + /*! + * @brief Sets the radio in reception mode for the given time + * @param [IN] timeout Reception timeout [us] + * [0: continuous, others timeout] + */ + virtual void Rx( uint32_t timeout ) = 0; + /*! + * @brief Sets the radio in transmission mode for the given time + * @param [IN] timeout Transmission timeout [us] + * [0: continuous, others timeout] + */ + virtual void Tx( uint32_t timeout ) = 0; + /*! + * @brief Sets the radio in continuous wave transmission mode + * + * @param [IN]: freq Channel RF frequency + * @param [IN]: power Sets the output power [dBm] + * @param [IN]: time Transmission mode timeout [s] + */ + virtual void SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ) = 0; + /*! + * @brief Reads the current RSSI value + * + * @retval rssiValue Current RSSI value in [dBm] + */ + virtual int16_t GetRssi ( RadioModems_t modem ) = 0; + /*! + * @brief Writes the radio register at the specified address + * + * @param [IN]: addr Register address + * @param [IN]: data New register value + */ + virtual void Write ( uint8_t addr, uint8_t data ) = 0; + /*! + * @brief Reads the radio register at the specified address + * + * @param [IN]: addr Register address + * @retval data Register value + */ + virtual uint8_t Read ( uint8_t addr ) = 0; + /*! + * @brief Writes multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [IN] buffer Buffer containing the new register's values + * @param [IN] size Number of registers to be written + */ + virtual void Write( uint8_t addr, uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Reads multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [OUT] buffer Buffer where to copy the registers data + * @param [IN] size Number of registers to be read + */ + virtual void Read ( uint8_t addr, uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Writes the buffer contents to the Radio FIFO + * + * @param [IN] buffer Buffer containing data to be put on the FIFO. + * @param [IN] size Number of bytes to be written to the FIFO + */ + virtual void WriteFifo( uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Reads the contents of the Radio FIFO + * + * @param [OUT] buffer Buffer where to copy the FIFO read data. + * @param [IN] size Number of bytes to be read from the FIFO + */ + virtual void ReadFifo( uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Sets the maximum payload length. + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] max Maximum payload length in bytes + */ + virtual void SetMaxPayloadLength( RadioModems_t modem, uint8_t max ) = 0; + /*! + * @brief Sets the network to public or private. Updates the sync byte. + * + * @remark Applies to LoRa modem only + * + * @param [IN] enable if true, it enables a public network + */ + virtual void SetPublicNetwork( bool enable ) = 0; +}; + +#endif // __RADIO_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/registers/sx1272Regs-Fsk.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,1134 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: SX1272 FSK modem registers and bits definitions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __SX1272_REGS_FSK_H__ +#define __SX1272_REGS_FSK_H__ + +/*! + * ============================================================================ + * SX1272 Internal registers Address + * ============================================================================ + */ +#define REG_FIFO 0x00 +// Common settings +#define REG_OPMODE 0x01 +#define REG_BITRATEMSB 0x02 +#define REG_BITRATELSB 0x03 +#define REG_FDEVMSB 0x04 +#define REG_FDEVLSB 0x05 +#define REG_FRFMSB 0x06 +#define REG_FRFMID 0x07 +#define REG_FRFLSB 0x08 +// Tx settings +#define REG_PACONFIG 0x09 +#define REG_PARAMP 0x0A +#define REG_OCP 0x0B +// Rx settings +#define REG_LNA 0x0C +#define REG_RXCONFIG 0x0D +#define REG_RSSICONFIG 0x0E +#define REG_RSSICOLLISION 0x0F +#define REG_RSSITHRESH 0x10 +#define REG_RSSIVALUE 0x11 +#define REG_RXBW 0x12 +#define REG_AFCBW 0x13 +#define REG_OOKPEAK 0x14 +#define REG_OOKFIX 0x15 +#define REG_OOKAVG 0x16 +#define REG_RES17 0x17 +#define REG_RES18 0x18 +#define REG_RES19 0x19 +#define REG_AFCFEI 0x1A +#define REG_AFCMSB 0x1B +#define REG_AFCLSB 0x1C +#define REG_FEIMSB 0x1D +#define REG_FEILSB 0x1E +#define REG_PREAMBLEDETECT 0x1F +#define REG_RXTIMEOUT1 0x20 +#define REG_RXTIMEOUT2 0x21 +#define REG_RXTIMEOUT3 0x22 +#define REG_RXDELAY 0x23 +// Oscillator settings +#define REG_OSC 0x24 +// Packet handler settings +#define REG_PREAMBLEMSB 0x25 +#define REG_PREAMBLELSB 0x26 +#define REG_SYNCCONFIG 0x27 +#define REG_SYNCVALUE1 0x28 +#define REG_SYNCVALUE2 0x29 +#define REG_SYNCVALUE3 0x2A +#define REG_SYNCVALUE4 0x2B +#define REG_SYNCVALUE5 0x2C +#define REG_SYNCVALUE6 0x2D +#define REG_SYNCVALUE7 0x2E +#define REG_SYNCVALUE8 0x2F +#define REG_PACKETCONFIG1 0x30 +#define REG_PACKETCONFIG2 0x31 +#define REG_PAYLOADLENGTH 0x32 +#define REG_NODEADRS 0x33 +#define REG_BROADCASTADRS 0x34 +#define REG_FIFOTHRESH 0x35 +// SM settings +#define REG_SEQCONFIG1 0x36 +#define REG_SEQCONFIG2 0x37 +#define REG_TIMERRESOL 0x38 +#define REG_TIMER1COEF 0x39 +#define REG_TIMER2COEF 0x3A +// Service settings +#define REG_IMAGECAL 0x3B +#define REG_TEMP 0x3C +#define REG_LOWBAT 0x3D +// Status +#define REG_IRQFLAGS1 0x3E +#define REG_IRQFLAGS2 0x3F +// I/O settings +#define REG_DIOMAPPING1 0x40 +#define REG_DIOMAPPING2 0x41 +// Version +#define REG_VERSION 0x42 +// Additional settings +#define REG_AGCREF 0x43 +#define REG_AGCTHRESH1 0x44 +#define REG_AGCTHRESH2 0x45 +#define REG_AGCTHRESH3 0x46 +#define REG_PLLHOP 0x4B +#define REG_TCXO 0x58 +#define REG_PADAC 0x5A +#define REG_PLL 0x5C +#define REG_PLLLOWPN 0x5E +#define REG_FORMERTEMP 0x6C +#define REG_BITRATEFRAC 0x70 + +/*! + * ============================================================================ + * SX1272 FSK bits control definition + * ============================================================================ + */ + +/*! + * RegFifo + */ + +/*! + * RegOpMode + */ +#define RF_OPMODE_LONGRANGEMODE_MASK 0x7F +#define RF_OPMODE_LONGRANGEMODE_OFF 0x00 +#define RF_OPMODE_LONGRANGEMODE_ON 0x80 + +#define RF_OPMODE_MODULATIONTYPE_MASK 0x9F +#define RF_OPMODE_MODULATIONTYPE_FSK 0x00 // Default +#define RF_OPMODE_MODULATIONTYPE_OOK 0x20 + +#define RF_OPMODE_MODULATIONSHAPING_MASK 0xE7 +#define RF_OPMODE_MODULATIONSHAPING_00 0x00 // Default +#define RF_OPMODE_MODULATIONSHAPING_01 0x08 +#define RF_OPMODE_MODULATIONSHAPING_10 0x10 +#define RF_OPMODE_MODULATIONSHAPING_11 0x18 + +#define RF_OPMODE_MASK 0xF8 +#define RF_OPMODE_SLEEP 0x00 +#define RF_OPMODE_STANDBY 0x01 // Default +#define RF_OPMODE_SYNTHESIZER_TX 0x02 +#define RF_OPMODE_TRANSMITTER 0x03 +#define RF_OPMODE_SYNTHESIZER_RX 0x04 +#define RF_OPMODE_RECEIVER 0x05 + +/*! + * RegBitRate (bits/sec) + */ +#define RF_BITRATEMSB_1200_BPS 0x68 +#define RF_BITRATELSB_1200_BPS 0x2B +#define RF_BITRATEMSB_2400_BPS 0x34 +#define RF_BITRATELSB_2400_BPS 0x15 +#define RF_BITRATEMSB_4800_BPS 0x1A // Default +#define RF_BITRATELSB_4800_BPS 0x0B // Default +#define RF_BITRATEMSB_9600_BPS 0x0D +#define RF_BITRATELSB_9600_BPS 0x05 +#define RF_BITRATEMSB_15000_BPS 0x08 +#define RF_BITRATELSB_15000_BPS 0x55 +#define RF_BITRATEMSB_19200_BPS 0x06 +#define RF_BITRATELSB_19200_BPS 0x83 +#define RF_BITRATEMSB_38400_BPS 0x03 +#define RF_BITRATELSB_38400_BPS 0x41 +#define RF_BITRATEMSB_76800_BPS 0x01 +#define RF_BITRATELSB_76800_BPS 0xA1 +#define RF_BITRATEMSB_153600_BPS 0x00 +#define RF_BITRATELSB_153600_BPS 0xD0 +#define RF_BITRATEMSB_57600_BPS 0x02 +#define RF_BITRATELSB_57600_BPS 0x2C +#define RF_BITRATEMSB_115200_BPS 0x01 +#define RF_BITRATELSB_115200_BPS 0x16 +#define RF_BITRATEMSB_12500_BPS 0x0A +#define RF_BITRATELSB_12500_BPS 0x00 +#define RF_BITRATEMSB_25000_BPS 0x05 +#define RF_BITRATELSB_25000_BPS 0x00 +#define RF_BITRATEMSB_50000_BPS 0x02 +#define RF_BITRATELSB_50000_BPS 0x80 +#define RF_BITRATEMSB_100000_BPS 0x01 +#define RF_BITRATELSB_100000_BPS 0x40 +#define RF_BITRATEMSB_150000_BPS 0x00 +#define RF_BITRATELSB_150000_BPS 0xD5 +#define RF_BITRATEMSB_200000_BPS 0x00 +#define RF_BITRATELSB_200000_BPS 0xA0 +#define RF_BITRATEMSB_250000_BPS 0x00 +#define RF_BITRATELSB_250000_BPS 0x80 +#define RF_BITRATEMSB_32768_BPS 0x03 +#define RF_BITRATELSB_32768_BPS 0xD1 + +/*! + * RegFdev (Hz) + */ +#define RF_FDEVMSB_2000_HZ 0x00 +#define RF_FDEVLSB_2000_HZ 0x21 +#define RF_FDEVMSB_5000_HZ 0x00 // Default +#define RF_FDEVLSB_5000_HZ 0x52 // Default +#define RF_FDEVMSB_10000_HZ 0x00 +#define RF_FDEVLSB_10000_HZ 0xA4 +#define RF_FDEVMSB_15000_HZ 0x00 +#define RF_FDEVLSB_15000_HZ 0xF6 +#define RF_FDEVMSB_20000_HZ 0x01 +#define RF_FDEVLSB_20000_HZ 0x48 +#define RF_FDEVMSB_25000_HZ 0x01 +#define RF_FDEVLSB_25000_HZ 0x9A +#define RF_FDEVMSB_30000_HZ 0x01 +#define RF_FDEVLSB_30000_HZ 0xEC +#define RF_FDEVMSB_35000_HZ 0x02 +#define RF_FDEVLSB_35000_HZ 0x3D +#define RF_FDEVMSB_40000_HZ 0x02 +#define RF_FDEVLSB_40000_HZ 0x8F +#define RF_FDEVMSB_45000_HZ 0x02 +#define RF_FDEVLSB_45000_HZ 0xE1 +#define RF_FDEVMSB_50000_HZ 0x03 +#define RF_FDEVLSB_50000_HZ 0x33 +#define RF_FDEVMSB_55000_HZ 0x03 +#define RF_FDEVLSB_55000_HZ 0x85 +#define RF_FDEVMSB_60000_HZ 0x03 +#define RF_FDEVLSB_60000_HZ 0xD7 +#define RF_FDEVMSB_65000_HZ 0x04 +#define RF_FDEVLSB_65000_HZ 0x29 +#define RF_FDEVMSB_70000_HZ 0x04 +#define RF_FDEVLSB_70000_HZ 0x7B +#define RF_FDEVMSB_75000_HZ 0x04 +#define RF_FDEVLSB_75000_HZ 0xCD +#define RF_FDEVMSB_80000_HZ 0x05 +#define RF_FDEVLSB_80000_HZ 0x1F +#define RF_FDEVMSB_85000_HZ 0x05 +#define RF_FDEVLSB_85000_HZ 0x71 +#define RF_FDEVMSB_90000_HZ 0x05 +#define RF_FDEVLSB_90000_HZ 0xC3 +#define RF_FDEVMSB_95000_HZ 0x06 +#define RF_FDEVLSB_95000_HZ 0x14 +#define RF_FDEVMSB_100000_HZ 0x06 +#define RF_FDEVLSB_100000_HZ 0x66 +#define RF_FDEVMSB_110000_HZ 0x07 +#define RF_FDEVLSB_110000_HZ 0x0A +#define RF_FDEVMSB_120000_HZ 0x07 +#define RF_FDEVLSB_120000_HZ 0xAE +#define RF_FDEVMSB_130000_HZ 0x08 +#define RF_FDEVLSB_130000_HZ 0x52 +#define RF_FDEVMSB_140000_HZ 0x08 +#define RF_FDEVLSB_140000_HZ 0xF6 +#define RF_FDEVMSB_150000_HZ 0x09 +#define RF_FDEVLSB_150000_HZ 0x9A +#define RF_FDEVMSB_160000_HZ 0x0A +#define RF_FDEVLSB_160000_HZ 0x3D +#define RF_FDEVMSB_170000_HZ 0x0A +#define RF_FDEVLSB_170000_HZ 0xE1 +#define RF_FDEVMSB_180000_HZ 0x0B +#define RF_FDEVLSB_180000_HZ 0x85 +#define RF_FDEVMSB_190000_HZ 0x0C +#define RF_FDEVLSB_190000_HZ 0x29 +#define RF_FDEVMSB_200000_HZ 0x0C +#define RF_FDEVLSB_200000_HZ 0xCD + +/*! + * RegFrf (MHz) + */ +#define RF_FRFMSB_863_MHZ 0xD7 +#define RF_FRFMID_863_MHZ 0xC0 +#define RF_FRFLSB_863_MHZ 0x00 +#define RF_FRFMSB_864_MHZ 0xD8 +#define RF_FRFMID_864_MHZ 0x00 +#define RF_FRFLSB_864_MHZ 0x00 +#define RF_FRFMSB_865_MHZ 0xD8 +#define RF_FRFMID_865_MHZ 0x40 +#define RF_FRFLSB_865_MHZ 0x00 +#define RF_FRFMSB_866_MHZ 0xD8 +#define RF_FRFMID_866_MHZ 0x80 +#define RF_FRFLSB_866_MHZ 0x00 +#define RF_FRFMSB_867_MHZ 0xD8 +#define RF_FRFMID_867_MHZ 0xC0 +#define RF_FRFLSB_867_MHZ 0x00 +#define RF_FRFMSB_868_MHZ 0xD9 +#define RF_FRFMID_868_MHZ 0x00 +#define RF_FRFLSB_868_MHZ 0x00 +#define RF_FRFMSB_869_MHZ 0xD9 +#define RF_FRFMID_869_MHZ 0x40 +#define RF_FRFLSB_869_MHZ 0x00 +#define RF_FRFMSB_870_MHZ 0xD9 +#define RF_FRFMID_870_MHZ 0x80 +#define RF_FRFLSB_870_MHZ 0x00 + +#define RF_FRFMSB_902_MHZ 0xE1 +#define RF_FRFMID_902_MHZ 0x80 +#define RF_FRFLSB_902_MHZ 0x00 +#define RF_FRFMSB_903_MHZ 0xE1 +#define RF_FRFMID_903_MHZ 0xC0 +#define RF_FRFLSB_903_MHZ 0x00 +#define RF_FRFMSB_904_MHZ 0xE2 +#define RF_FRFMID_904_MHZ 0x00 +#define RF_FRFLSB_904_MHZ 0x00 +#define RF_FRFMSB_905_MHZ 0xE2 +#define RF_FRFMID_905_MHZ 0x40 +#define RF_FRFLSB_905_MHZ 0x00 +#define RF_FRFMSB_906_MHZ 0xE2 +#define RF_FRFMID_906_MHZ 0x80 +#define RF_FRFLSB_906_MHZ 0x00 +#define RF_FRFMSB_907_MHZ 0xE2 +#define RF_FRFMID_907_MHZ 0xC0 +#define RF_FRFLSB_907_MHZ 0x00 +#define RF_FRFMSB_908_MHZ 0xE3 +#define RF_FRFMID_908_MHZ 0x00 +#define RF_FRFLSB_908_MHZ 0x00 +#define RF_FRFMSB_909_MHZ 0xE3 +#define RF_FRFMID_909_MHZ 0x40 +#define RF_FRFLSB_909_MHZ 0x00 +#define RF_FRFMSB_910_MHZ 0xE3 +#define RF_FRFMID_910_MHZ 0x80 +#define RF_FRFLSB_910_MHZ 0x00 +#define RF_FRFMSB_911_MHZ 0xE3 +#define RF_FRFMID_911_MHZ 0xC0 +#define RF_FRFLSB_911_MHZ 0x00 +#define RF_FRFMSB_912_MHZ 0xE4 +#define RF_FRFMID_912_MHZ 0x00 +#define RF_FRFLSB_912_MHZ 0x00 +#define RF_FRFMSB_913_MHZ 0xE4 +#define RF_FRFMID_913_MHZ 0x40 +#define RF_FRFLSB_913_MHZ 0x00 +#define RF_FRFMSB_914_MHZ 0xE4 +#define RF_FRFMID_914_MHZ 0x80 +#define RF_FRFLSB_914_MHZ 0x00 +#define RF_FRFMSB_915_MHZ 0xE4 // Default +#define RF_FRFMID_915_MHZ 0xC0 // Default +#define RF_FRFLSB_915_MHZ 0x00 // Default +#define RF_FRFMSB_916_MHZ 0xE5 +#define RF_FRFMID_916_MHZ 0x00 +#define RF_FRFLSB_916_MHZ 0x00 +#define RF_FRFMSB_917_MHZ 0xE5 +#define RF_FRFMID_917_MHZ 0x40 +#define RF_FRFLSB_917_MHZ 0x00 +#define RF_FRFMSB_918_MHZ 0xE5 +#define RF_FRFMID_918_MHZ 0x80 +#define RF_FRFLSB_918_MHZ 0x00 +#define RF_FRFMSB_919_MHZ 0xE5 +#define RF_FRFMID_919_MHZ 0xC0 +#define RF_FRFLSB_919_MHZ 0x00 +#define RF_FRFMSB_920_MHZ 0xE6 +#define RF_FRFMID_920_MHZ 0x00 +#define RF_FRFLSB_920_MHZ 0x00 +#define RF_FRFMSB_921_MHZ 0xE6 +#define RF_FRFMID_921_MHZ 0x40 +#define RF_FRFLSB_921_MHZ 0x00 +#define RF_FRFMSB_922_MHZ 0xE6 +#define RF_FRFMID_922_MHZ 0x80 +#define RF_FRFLSB_922_MHZ 0x00 +#define RF_FRFMSB_923_MHZ 0xE6 +#define RF_FRFMID_923_MHZ 0xC0 +#define RF_FRFLSB_923_MHZ 0x00 +#define RF_FRFMSB_924_MHZ 0xE7 +#define RF_FRFMID_924_MHZ 0x00 +#define RF_FRFLSB_924_MHZ 0x00 +#define RF_FRFMSB_925_MHZ 0xE7 +#define RF_FRFMID_925_MHZ 0x40 +#define RF_FRFLSB_925_MHZ 0x00 +#define RF_FRFMSB_926_MHZ 0xE7 +#define RF_FRFMID_926_MHZ 0x80 +#define RF_FRFLSB_926_MHZ 0x00 +#define RF_FRFMSB_927_MHZ 0xE7 +#define RF_FRFMID_927_MHZ 0xC0 +#define RF_FRFLSB_927_MHZ 0x00 +#define RF_FRFMSB_928_MHZ 0xE8 +#define RF_FRFMID_928_MHZ 0x00 +#define RF_FRFLSB_928_MHZ 0x00 + +/*! + * RegPaConfig + */ +#define RF_PACONFIG_PASELECT_MASK 0x7F +#define RF_PACONFIG_PASELECT_PABOOST 0x80 +#define RF_PACONFIG_PASELECT_RFO 0x00 // Default + +#define RF_PACONFIG_OUTPUTPOWER_MASK 0xF0 + +/*! + * RegPaRamp + */ +#define RF_PARAMP_LOWPNTXPLL_MASK 0xEF +#define RF_PARAMP_LOWPNTXPLL_OFF 0x10 // Default +#define RF_PARAMP_LOWPNTXPLL_ON 0x00 + +#define RF_PARAMP_MASK 0xF0 +#define RF_PARAMP_3400_US 0x00 +#define RF_PARAMP_2000_US 0x01 +#define RF_PARAMP_1000_US 0x02 +#define RF_PARAMP_0500_US 0x03 +#define RF_PARAMP_0250_US 0x04 +#define RF_PARAMP_0125_US 0x05 +#define RF_PARAMP_0100_US 0x06 +#define RF_PARAMP_0062_US 0x07 +#define RF_PARAMP_0050_US 0x08 +#define RF_PARAMP_0040_US 0x09 // Default +#define RF_PARAMP_0031_US 0x0A +#define RF_PARAMP_0025_US 0x0B +#define RF_PARAMP_0020_US 0x0C +#define RF_PARAMP_0015_US 0x0D +#define RF_PARAMP_0012_US 0x0E +#define RF_PARAMP_0010_US 0x0F + +/*! + * RegOcp + */ +#define RF_OCP_MASK 0xDF +#define RF_OCP_ON 0x20 // Default +#define RF_OCP_OFF 0x00 + +#define RF_OCP_TRIM_MASK 0xE0 +#define RF_OCP_TRIM_045_MA 0x00 +#define RF_OCP_TRIM_050_MA 0x01 +#define RF_OCP_TRIM_055_MA 0x02 +#define RF_OCP_TRIM_060_MA 0x03 +#define RF_OCP_TRIM_065_MA 0x04 +#define RF_OCP_TRIM_070_MA 0x05 +#define RF_OCP_TRIM_075_MA 0x06 +#define RF_OCP_TRIM_080_MA 0x07 +#define RF_OCP_TRIM_085_MA 0x08 +#define RF_OCP_TRIM_090_MA 0x09 +#define RF_OCP_TRIM_095_MA 0x0A +#define RF_OCP_TRIM_100_MA 0x0B // Default +#define RF_OCP_TRIM_105_MA 0x0C +#define RF_OCP_TRIM_110_MA 0x0D +#define RF_OCP_TRIM_115_MA 0x0E +#define RF_OCP_TRIM_120_MA 0x0F +#define RF_OCP_TRIM_130_MA 0x10 +#define RF_OCP_TRIM_140_MA 0x11 +#define RF_OCP_TRIM_150_MA 0x12 +#define RF_OCP_TRIM_160_MA 0x13 +#define RF_OCP_TRIM_170_MA 0x14 +#define RF_OCP_TRIM_180_MA 0x15 +#define RF_OCP_TRIM_190_MA 0x16 +#define RF_OCP_TRIM_200_MA 0x17 +#define RF_OCP_TRIM_210_MA 0x18 +#define RF_OCP_TRIM_220_MA 0x19 +#define RF_OCP_TRIM_230_MA 0x1A +#define RF_OCP_TRIM_240_MA 0x1B + +/*! + * RegLna + */ +#define RF_LNA_GAIN_MASK 0x1F +#define RF_LNA_GAIN_G1 0x20 // Default +#define RF_LNA_GAIN_G2 0x40 +#define RF_LNA_GAIN_G3 0x60 +#define RF_LNA_GAIN_G4 0x80 +#define RF_LNA_GAIN_G5 0xA0 +#define RF_LNA_GAIN_G6 0xC0 + +#define RF_LNA_BOOST_MASK 0xFC +#define RF_LNA_BOOST_OFF 0x00 // Default +#define RF_LNA_BOOST_ON 0x03 + +/*! + * RegRxConfig + */ +#define RF_RXCONFIG_RESTARTRXONCOLLISION_MASK 0x7F +#define RF_RXCONFIG_RESTARTRXONCOLLISION_ON 0x80 +#define RF_RXCONFIG_RESTARTRXONCOLLISION_OFF 0x00 // Default + +#define RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK 0x40 // Write only + +#define RF_RXCONFIG_RESTARTRXWITHPLLLOCK 0x20 // Write only + +#define RF_RXCONFIG_AFCAUTO_MASK 0xEF +#define RF_RXCONFIG_AFCAUTO_ON 0x10 +#define RF_RXCONFIG_AFCAUTO_OFF 0x00 // Default + +#define RF_RXCONFIG_AGCAUTO_MASK 0xF7 +#define RF_RXCONFIG_AGCAUTO_ON 0x08 // Default +#define RF_RXCONFIG_AGCAUTO_OFF 0x00 + +#define RF_RXCONFIG_RXTRIGER_MASK 0xF8 +#define RF_RXCONFIG_RXTRIGER_OFF 0x00 +#define RF_RXCONFIG_RXTRIGER_RSSI 0x01 +#define RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT 0x06 // Default +#define RF_RXCONFIG_RXTRIGER_RSSI_PREAMBLEDETECT 0x07 + +/*! + * RegRssiConfig + */ +#define RF_RSSICONFIG_OFFSET_MASK 0x07 +#define RF_RSSICONFIG_OFFSET_P_00_DB 0x00 // Default +#define RF_RSSICONFIG_OFFSET_P_01_DB 0x08 +#define RF_RSSICONFIG_OFFSET_P_02_DB 0x10 +#define RF_RSSICONFIG_OFFSET_P_03_DB 0x18 +#define RF_RSSICONFIG_OFFSET_P_04_DB 0x20 +#define RF_RSSICONFIG_OFFSET_P_05_DB 0x28 +#define RF_RSSICONFIG_OFFSET_P_06_DB 0x30 +#define RF_RSSICONFIG_OFFSET_P_07_DB 0x38 +#define RF_RSSICONFIG_OFFSET_P_08_DB 0x40 +#define RF_RSSICONFIG_OFFSET_P_09_DB 0x48 +#define RF_RSSICONFIG_OFFSET_P_10_DB 0x50 +#define RF_RSSICONFIG_OFFSET_P_11_DB 0x58 +#define RF_RSSICONFIG_OFFSET_P_12_DB 0x60 +#define RF_RSSICONFIG_OFFSET_P_13_DB 0x68 +#define RF_RSSICONFIG_OFFSET_P_14_DB 0x70 +#define RF_RSSICONFIG_OFFSET_P_15_DB 0x78 +#define RF_RSSICONFIG_OFFSET_M_16_DB 0x80 +#define RF_RSSICONFIG_OFFSET_M_15_DB 0x88 +#define RF_RSSICONFIG_OFFSET_M_14_DB 0x90 +#define RF_RSSICONFIG_OFFSET_M_13_DB 0x98 +#define RF_RSSICONFIG_OFFSET_M_12_DB 0xA0 +#define RF_RSSICONFIG_OFFSET_M_11_DB 0xA8 +#define RF_RSSICONFIG_OFFSET_M_10_DB 0xB0 +#define RF_RSSICONFIG_OFFSET_M_09_DB 0xB8 +#define RF_RSSICONFIG_OFFSET_M_08_DB 0xC0 +#define RF_RSSICONFIG_OFFSET_M_07_DB 0xC8 +#define RF_RSSICONFIG_OFFSET_M_06_DB 0xD0 +#define RF_RSSICONFIG_OFFSET_M_05_DB 0xD8 +#define RF_RSSICONFIG_OFFSET_M_04_DB 0xE0 +#define RF_RSSICONFIG_OFFSET_M_03_DB 0xE8 +#define RF_RSSICONFIG_OFFSET_M_02_DB 0xF0 +#define RF_RSSICONFIG_OFFSET_M_01_DB 0xF8 + +#define RF_RSSICONFIG_SMOOTHING_MASK 0xF8 +#define RF_RSSICONFIG_SMOOTHING_2 0x00 +#define RF_RSSICONFIG_SMOOTHING_4 0x01 +#define RF_RSSICONFIG_SMOOTHING_8 0x02 // Default +#define RF_RSSICONFIG_SMOOTHING_16 0x03 +#define RF_RSSICONFIG_SMOOTHING_32 0x04 +#define RF_RSSICONFIG_SMOOTHING_64 0x05 +#define RF_RSSICONFIG_SMOOTHING_128 0x06 +#define RF_RSSICONFIG_SMOOTHING_256 0x07 + +/*! + * RegRssiCollision + */ +#define RF_RSSICOLISION_THRESHOLD 0x0A // Default + +/*! + * RegRssiThresh + */ +#define RF_RSSITHRESH_THRESHOLD 0xFF // Default + +/*! + * RegRssiValue (Read Only) + */ + +/*! + * RegRxBw + */ +#define RF_RXBW_MANT_MASK 0xE7 +#define RF_RXBW_MANT_16 0x00 +#define RF_RXBW_MANT_20 0x08 +#define RF_RXBW_MANT_24 0x10 // Default + +#define RF_RXBW_EXP_MASK 0xF8 +#define RF_RXBW_EXP_0 0x00 +#define RF_RXBW_EXP_1 0x01 +#define RF_RXBW_EXP_2 0x02 +#define RF_RXBW_EXP_3 0x03 +#define RF_RXBW_EXP_4 0x04 +#define RF_RXBW_EXP_5 0x05 // Default +#define RF_RXBW_EXP_6 0x06 +#define RF_RXBW_EXP_7 0x07 + +/*! + * RegAfcBw + */ +#define RF_AFCBW_MANTAFC_MASK 0xE7 +#define RF_AFCBW_MANTAFC_16 0x00 +#define RF_AFCBW_MANTAFC_20 0x08 // Default +#define RF_AFCBW_MANTAFC_24 0x10 + +#define RF_AFCBW_EXPAFC_MASK 0xF8 +#define RF_AFCBW_EXPAFC_0 0x00 +#define RF_AFCBW_EXPAFC_1 0x01 +#define RF_AFCBW_EXPAFC_2 0x02 +#define RF_AFCBW_EXPAFC_3 0x03 // Default +#define RF_AFCBW_EXPAFC_4 0x04 +#define RF_AFCBW_EXPAFC_5 0x05 +#define RF_AFCBW_EXPAFC_6 0x06 +#define RF_AFCBW_EXPAFC_7 0x07 + +/*! + * RegOokPeak + */ +#define RF_OOKPEAK_BITSYNC_MASK 0xDF // Default +#define RF_OOKPEAK_BITSYNC_ON 0x20 // Default +#define RF_OOKPEAK_BITSYNC_OFF 0x00 + +#define RF_OOKPEAK_OOKTHRESHTYPE_MASK 0xE7 +#define RF_OOKPEAK_OOKTHRESHTYPE_FIXED 0x00 +#define RF_OOKPEAK_OOKTHRESHTYPE_PEAK 0x08 // Default +#define RF_OOKPEAK_OOKTHRESHTYPE_AVERAGE 0x10 + +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_MASK 0xF8 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_0_5_DB 0x00 // Default +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_0_DB 0x01 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_1_5_DB 0x02 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_2_0_DB 0x03 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_3_0_DB 0x04 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_4_0_DB 0x05 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_5_0_DB 0x06 +#define RF_OOKPEAK_OOKPEAKTHRESHSTEP_6_0_DB 0x07 + +/*! + * RegOokFix + */ +#define RF_OOKFIX_OOKFIXEDTHRESHOLD 0x0C // Default + +/*! + * RegOokAvg + */ +#define RF_OOKAVG_OOKPEAKTHRESHDEC_MASK 0x1F +#define RF_OOKAVG_OOKPEAKTHRESHDEC_000 0x00 // Default +#define RF_OOKAVG_OOKPEAKTHRESHDEC_001 0x20 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_010 0x40 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_011 0x60 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_100 0x80 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_101 0xA0 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_110 0xC0 +#define RF_OOKAVG_OOKPEAKTHRESHDEC_111 0xE0 + +#define RF_OOKAVG_AVERAGEOFFSET_MASK 0xF3 +#define RF_OOKAVG_AVERAGEOFFSET_0_DB 0x00 // Default +#define RF_OOKAVG_AVERAGEOFFSET_2_DB 0x04 +#define RF_OOKAVG_AVERAGEOFFSET_4_DB 0x08 +#define RF_OOKAVG_AVERAGEOFFSET_6_DB 0x0C + +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_MASK 0xFC +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_00 0x00 +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_01 0x01 +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_10 0x02 // Default +#define RF_OOKAVG_OOKAVERAGETHRESHFILT_11 0x03 + +/*! + * RegAfcFei + */ +#define RF_AFCFEI_AGCSTART 0x10 + +#define RF_AFCFEI_AFCCLEAR 0x02 + +#define RF_AFCFEI_AFCAUTOCLEAR_MASK 0xFE +#define RF_AFCFEI_AFCAUTOCLEAR_ON 0x01 +#define RF_AFCFEI_AFCAUTOCLEAR_OFF 0x00 // Default + +/*! + * RegAfcMsb (Read Only) + */ + +/*! + * RegAfcLsb (Read Only) + */ + +/*! + * RegFeiMsb (Read Only) + */ + +/*! + * RegFeiLsb (Read Only) + */ + +/*! + * RegPreambleDetect + */ +#define RF_PREAMBLEDETECT_DETECTOR_MASK 0x7F +#define RF_PREAMBLEDETECT_DETECTOR_ON 0x80 // Default +#define RF_PREAMBLEDETECT_DETECTOR_OFF 0x00 + +#define RF_PREAMBLEDETECT_DETECTORSIZE_MASK 0x9F +#define RF_PREAMBLEDETECT_DETECTORSIZE_1 0x00 +#define RF_PREAMBLEDETECT_DETECTORSIZE_2 0x20 // Default +#define RF_PREAMBLEDETECT_DETECTORSIZE_3 0x40 +#define RF_PREAMBLEDETECT_DETECTORSIZE_4 0x60 + +#define RF_PREAMBLEDETECT_DETECTORTOL_MASK 0xE0 +#define RF_PREAMBLEDETECT_DETECTORTOL_0 0x00 +#define RF_PREAMBLEDETECT_DETECTORTOL_1 0x01 +#define RF_PREAMBLEDETECT_DETECTORTOL_2 0x02 +#define RF_PREAMBLEDETECT_DETECTORTOL_3 0x03 +#define RF_PREAMBLEDETECT_DETECTORTOL_4 0x04 +#define RF_PREAMBLEDETECT_DETECTORTOL_5 0x05 +#define RF_PREAMBLEDETECT_DETECTORTOL_6 0x06 +#define RF_PREAMBLEDETECT_DETECTORTOL_7 0x07 +#define RF_PREAMBLEDETECT_DETECTORTOL_8 0x08 +#define RF_PREAMBLEDETECT_DETECTORTOL_9 0x09 +#define RF_PREAMBLEDETECT_DETECTORTOL_10 0x0A // Default +#define RF_PREAMBLEDETECT_DETECTORTOL_11 0x0B +#define RF_PREAMBLEDETECT_DETECTORTOL_12 0x0C +#define RF_PREAMBLEDETECT_DETECTORTOL_13 0x0D +#define RF_PREAMBLEDETECT_DETECTORTOL_14 0x0E +#define RF_PREAMBLEDETECT_DETECTORTOL_15 0x0F +#define RF_PREAMBLEDETECT_DETECTORTOL_16 0x10 +#define RF_PREAMBLEDETECT_DETECTORTOL_17 0x11 +#define RF_PREAMBLEDETECT_DETECTORTOL_18 0x12 +#define RF_PREAMBLEDETECT_DETECTORTOL_19 0x13 +#define RF_PREAMBLEDETECT_DETECTORTOL_20 0x14 +#define RF_PREAMBLEDETECT_DETECTORTOL_21 0x15 +#define RF_PREAMBLEDETECT_DETECTORTOL_22 0x16 +#define RF_PREAMBLEDETECT_DETECTORTOL_23 0x17 +#define RF_PREAMBLEDETECT_DETECTORTOL_24 0x18 +#define RF_PREAMBLEDETECT_DETECTORTOL_25 0x19 +#define RF_PREAMBLEDETECT_DETECTORTOL_26 0x1A +#define RF_PREAMBLEDETECT_DETECTORTOL_27 0x1B +#define RF_PREAMBLEDETECT_DETECTORTOL_28 0x1C +#define RF_PREAMBLEDETECT_DETECTORTOL_29 0x1D +#define RF_PREAMBLEDETECT_DETECTORTOL_30 0x1E +#define RF_PREAMBLEDETECT_DETECTORTOL_31 0x1F + +/*! + * RegRxTimeout1 + */ +#define RF_RXTIMEOUT1_TIMEOUTRXRSSI 0x00 // Default + +/*! + * RegRxTimeout2 + */ +#define RF_RXTIMEOUT2_TIMEOUTRXPREAMBLE 0x00 // Default + +/*! + * RegRxTimeout3 + */ +#define RF_RXTIMEOUT3_TIMEOUTSIGNALSYNC 0x00 // Default + +/*! + * RegRxDelay + */ +#define RF_RXDELAY_INTERPACKETRXDELAY 0x00 // Default + +/*! + * RegOsc + */ +#define RF_OSC_RCCALSTART 0x08 + +#define RF_OSC_CLKOUT_MASK 0xF8 +#define RF_OSC_CLKOUT_32_MHZ 0x00 +#define RF_OSC_CLKOUT_16_MHZ 0x01 +#define RF_OSC_CLKOUT_8_MHZ 0x02 +#define RF_OSC_CLKOUT_4_MHZ 0x03 +#define RF_OSC_CLKOUT_2_MHZ 0x04 +#define RF_OSC_CLKOUT_1_MHZ 0x05 +#define RF_OSC_CLKOUT_RC 0x06 +#define RF_OSC_CLKOUT_OFF 0x07 // Default + +/*! + * RegPreambleMsb/RegPreambleLsb + */ +#define RF_PREAMBLEMSB_SIZE 0x00 // Default +#define RF_PREAMBLELSB_SIZE 0x03 // Default + +/*! + * RegSyncConfig + */ +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_MASK 0x3F +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_ON 0x80 // Default +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_WAITPLL_OFF 0x40 +#define RF_SYNCCONFIG_AUTORESTARTRXMODE_OFF 0x00 + + +#define RF_SYNCCONFIG_PREAMBLEPOLARITY_MASK 0xDF +#define RF_SYNCCONFIG_PREAMBLEPOLARITY_55 0x20 +#define RF_SYNCCONFIG_PREAMBLEPOLARITY_AA 0x00 // Default + +#define RF_SYNCCONFIG_SYNC_MASK 0xEF +#define RF_SYNCCONFIG_SYNC_ON 0x10 // Default +#define RF_SYNCCONFIG_SYNC_OFF 0x00 + +#define RF_SYNCCONFIG_FIFOFILLCONDITION_MASK 0xF7 +#define RF_SYNCCONFIG_FIFOFILLCONDITION_AUTO 0x00 // Default +#define RF_SYNCCONFIG_FIFOFILLCONDITION_MANUAL 0x08 + +#define RF_SYNCCONFIG_SYNCSIZE_MASK 0xF8 +#define RF_SYNCCONFIG_SYNCSIZE_1 0x00 +#define RF_SYNCCONFIG_SYNCSIZE_2 0x01 +#define RF_SYNCCONFIG_SYNCSIZE_3 0x02 +#define RF_SYNCCONFIG_SYNCSIZE_4 0x03 // Default +#define RF_SYNCCONFIG_SYNCSIZE_5 0x04 +#define RF_SYNCCONFIG_SYNCSIZE_6 0x05 +#define RF_SYNCCONFIG_SYNCSIZE_7 0x06 +#define RF_SYNCCONFIG_SYNCSIZE_8 0x07 + +/*! + * RegSyncValue1-8 + */ +#define RF_SYNCVALUE1_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE2_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE3_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE4_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE5_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE6_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE7_SYNCVALUE 0x01 // Default +#define RF_SYNCVALUE8_SYNCVALUE 0x01 // Default + +/*! + * RegPacketConfig1 + */ +#define RF_PACKETCONFIG1_PACKETFORMAT_MASK 0x7F +#define RF_PACKETCONFIG1_PACKETFORMAT_FIXED 0x00 +#define RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE 0x80 // Default + +#define RF_PACKETCONFIG1_DCFREE_MASK 0x9F +#define RF_PACKETCONFIG1_DCFREE_OFF 0x00 // Default +#define RF_PACKETCONFIG1_DCFREE_MANCHESTER 0x20 +#define RF_PACKETCONFIG1_DCFREE_WHITENING 0x40 + +#define RF_PACKETCONFIG1_CRC_MASK 0xEF +#define RF_PACKETCONFIG1_CRC_ON 0x10 // Default +#define RF_PACKETCONFIG1_CRC_OFF 0x00 + +#define RF_PACKETCONFIG1_CRCAUTOCLEAR_MASK 0xF7 +#define RF_PACKETCONFIG1_CRCAUTOCLEAR_ON 0x00 // Default +#define RF_PACKETCONFIG1_CRCAUTOCLEAR_OFF 0x08 + +#define RF_PACKETCONFIG1_ADDRSFILTERING_MASK 0xF9 +#define RF_PACKETCONFIG1_ADDRSFILTERING_OFF 0x00 // Default +#define RF_PACKETCONFIG1_ADDRSFILTERING_NODE 0x02 +#define RF_PACKETCONFIG1_ADDRSFILTERING_NODEBROADCAST 0x04 + +#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_MASK 0xFE +#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_CCITT 0x00 // Default +#define RF_PACKETCONFIG1_CRCWHITENINGTYPE_IBM 0x01 + +/*! + * RegPacketConfig2 + */ +#define RF_PACKETCONFIG2_DATAMODE_MASK 0xBF +#define RF_PACKETCONFIG2_DATAMODE_CONTINUOUS 0x00 +#define RF_PACKETCONFIG2_DATAMODE_PACKET 0x40 // Default + +#define RF_PACKETCONFIG2_IOHOME_MASK 0xDF +#define RF_PACKETCONFIG2_IOHOME_ON 0x20 +#define RF_PACKETCONFIG2_IOHOME_OFF 0x00 // Default + +#define RF_PACKETCONFIG2_BEACON_MASK 0xF7 +#define RF_PACKETCONFIG2_BEACON_ON 0x08 +#define RF_PACKETCONFIG2_BEACON_OFF 0x00 // Default + +#define RF_PACKETCONFIG2_PAYLOADLENGTH_MSB_MASK 0xF8 + +/*! + * RegPayloadLength + */ +#define RF_PAYLOADLENGTH_LENGTH 0x40 // Default + +/*! + * RegNodeAdrs + */ +#define RF_NODEADDRESS_ADDRESS 0x00 + +/*! + * RegBroadcastAdrs + */ +#define RF_BROADCASTADDRESS_ADDRESS 0x00 + +/*! + * RegFifoThresh + */ +#define RF_FIFOTHRESH_TXSTARTCONDITION_MASK 0x7F +#define RF_FIFOTHRESH_TXSTARTCONDITION_FIFOTHRESH 0x00 +#define RF_FIFOTHRESH_TXSTARTCONDITION_FIFONOTEMPTY 0x80 // Default + +#define RF_FIFOTHRESH_FIFOTHRESHOLD_MASK 0xC0 +#define RF_FIFOTHRESH_FIFOTHRESHOLD_THRESHOLD 0x0F // Default + +/*! + * RegSeqConfig1 + */ +#define RF_SEQCONFIG1_SEQUENCER_START 0x80 + +#define RF_SEQCONFIG1_SEQUENCER_STOP 0x40 + +#define RF_SEQCONFIG1_IDLEMODE_MASK 0xDF +#define RF_SEQCONFIG1_IDLEMODE_SLEEP 0x20 +#define RF_SEQCONFIG1_IDLEMODE_STANDBY 0x00 // Default + +#define RF_SEQCONFIG1_FROMSTART_MASK 0xE7 +#define RF_SEQCONFIG1_FROMSTART_TOLPS 0x00 // Default +#define RF_SEQCONFIG1_FROMSTART_TORX 0x08 +#define RF_SEQCONFIG1_FROMSTART_TOTX 0x10 +#define RF_SEQCONFIG1_FROMSTART_TOTX_ONFIFOLEVEL 0x18 + +#define RF_SEQCONFIG1_LPS_MASK 0xFB +#define RF_SEQCONFIG1_LPS_SEQUENCER_OFF 0x00 // Default +#define RF_SEQCONFIG1_LPS_IDLE 0x04 + +#define RF_SEQCONFIG1_FROMIDLE_MASK 0xFD +#define RF_SEQCONFIG1_FROMIDLE_TOTX 0x00 // Default +#define RF_SEQCONFIG1_FROMIDLE_TORX 0x02 + +#define RF_SEQCONFIG1_FROMTX_MASK 0xFE +#define RF_SEQCONFIG1_FROMTX_TOLPS 0x00 // Default +#define RF_SEQCONFIG1_FROMTX_TORX 0x01 + +/*! + * RegSeqConfig2 + */ +#define RF_SEQCONFIG2_FROMRX_MASK 0x1F +#define RF_SEQCONFIG2_FROMRX_TOUNUSED_000 0x00 // Default +#define RF_SEQCONFIG2_FROMRX_TORXPKT_ONPLDRDY 0x20 +#define RF_SEQCONFIG2_FROMRX_TOLPS_ONPLDRDY 0x40 +#define RF_SEQCONFIG2_FROMRX_TORXPKT_ONCRCOK 0x60 +#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONRSSI 0x80 +#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONSYNC 0xA0 +#define RF_SEQCONFIG2_FROMRX_TOSEQUENCEROFF_ONPREAMBLE 0xC0 +#define RF_SEQCONFIG2_FROMRX_TOUNUSED_111 0xE0 + +#define RF_SEQCONFIG2_FROMRXTIMEOUT_MASK 0xE7 +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TORXRESTART 0x00 // Default +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOTX 0x08 +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOLPS 0x10 +#define RF_SEQCONFIG2_FROMRXTIMEOUT_TOSEQUENCEROFF 0x18 + +#define RF_SEQCONFIG2_FROMRXPKT_MASK 0xF8 +#define RF_SEQCONFIG2_FROMRXPKT_TOSEQUENCEROFF 0x00 // Default +#define RF_SEQCONFIG2_FROMRXPKT_TOTX_ONFIFOEMPTY 0x01 +#define RF_SEQCONFIG2_FROMRXPKT_TOLPS 0x02 +#define RF_SEQCONFIG2_FROMRXPKT_TOSYNTHESIZERRX 0x03 +#define RF_SEQCONFIG2_FROMRXPKT_TORX 0x04 + +/*! + * RegTimerResol + */ +#define RF_TIMERRESOL_TIMER1RESOL_MASK 0xF3 +#define RF_TIMERRESOL_TIMER1RESOL_OFF 0x00 // Default +#define RF_TIMERRESOL_TIMER1RESOL_000064_US 0x04 +#define RF_TIMERRESOL_TIMER1RESOL_004100_US 0x08 +#define RF_TIMERRESOL_TIMER1RESOL_262000_US 0x0C + +#define RF_TIMERRESOL_TIMER2RESOL_MASK 0xFC +#define RF_TIMERRESOL_TIMER2RESOL_OFF 0x00 // Default +#define RF_TIMERRESOL_TIMER2RESOL_000064_US 0x01 +#define RF_TIMERRESOL_TIMER2RESOL_004100_US 0x02 +#define RF_TIMERRESOL_TIMER2RESOL_262000_US 0x03 + +/*! + * RegTimer1Coef + */ +#define RF_TIMER1COEF_TIMER1COEFFICIENT 0xF5 // Default + +/*! + * RegTimer2Coef + */ +#define RF_TIMER2COEF_TIMER2COEFFICIENT 0x20 // Default + +/*! + * RegImageCal + */ +#define RF_IMAGECAL_AUTOIMAGECAL_MASK 0x7F +#define RF_IMAGECAL_AUTOIMAGECAL_ON 0x80 +#define RF_IMAGECAL_AUTOIMAGECAL_OFF 0x00 // Default + +#define RF_IMAGECAL_IMAGECAL_MASK 0xBF +#define RF_IMAGECAL_IMAGECAL_START 0x40 + +#define RF_IMAGECAL_IMAGECAL_RUNNING 0x20 +#define RF_IMAGECAL_IMAGECAL_DONE 0x00 // Default + +#define RF_IMAGECAL_TEMPCHANGE_HIGHER 0x08 +#define RF_IMAGECAL_TEMPCHANGE_LOWER 0x00 + +#define RF_IMAGECAL_TEMPTHRESHOLD_MASK 0xF9 +#define RF_IMAGECAL_TEMPTHRESHOLD_05 0x00 +#define RF_IMAGECAL_TEMPTHRESHOLD_10 0x02 // Default +#define RF_IMAGECAL_TEMPTHRESHOLD_15 0x04 +#define RF_IMAGECAL_TEMPTHRESHOLD_20 0x06 + +#define RF_IMAGECAL_TEMPMONITOR_MASK 0xFE +#define RF_IMAGECAL_TEMPMONITOR_ON 0x00 // Default +#define RF_IMAGECAL_TEMPMONITOR_OFF 0x01 + +/*! + * RegTemp (Read Only) + */ + +/*! + * RegLowBat + */ +#define RF_LOWBAT_MASK 0xF7 +#define RF_LOWBAT_ON 0x08 +#define RF_LOWBAT_OFF 0x00 // Default + +#define RF_LOWBAT_TRIM_MASK 0xF8 +#define RF_LOWBAT_TRIM_1695 0x00 +#define RF_LOWBAT_TRIM_1764 0x01 +#define RF_LOWBAT_TRIM_1835 0x02 // Default +#define RF_LOWBAT_TRIM_1905 0x03 +#define RF_LOWBAT_TRIM_1976 0x04 +#define RF_LOWBAT_TRIM_2045 0x05 +#define RF_LOWBAT_TRIM_2116 0x06 +#define RF_LOWBAT_TRIM_2185 0x07 + +/*! + * RegIrqFlags1 + */ +#define RF_IRQFLAGS1_MODEREADY 0x80 + +#define RF_IRQFLAGS1_RXREADY 0x40 + +#define RF_IRQFLAGS1_TXREADY 0x20 + +#define RF_IRQFLAGS1_PLLLOCK 0x10 + +#define RF_IRQFLAGS1_RSSI 0x08 + +#define RF_IRQFLAGS1_TIMEOUT 0x04 + +#define RF_IRQFLAGS1_PREAMBLEDETECT 0x02 + +#define RF_IRQFLAGS1_SYNCADDRESSMATCH 0x01 + +/*! + * RegIrqFlags2 + */ +#define RF_IRQFLAGS2_FIFOFULL 0x80 + +#define RF_IRQFLAGS2_FIFOEMPTY 0x40 + +#define RF_IRQFLAGS2_FIFOLEVEL 0x20 + +#define RF_IRQFLAGS2_FIFOOVERRUN 0x10 + +#define RF_IRQFLAGS2_PACKETSENT 0x08 + +#define RF_IRQFLAGS2_PAYLOADREADY 0x04 + +#define RF_IRQFLAGS2_CRCOK 0x02 + +#define RF_IRQFLAGS2_LOWBAT 0x01 + +/*! + * RegDioMapping1 + */ +#define RF_DIOMAPPING1_DIO0_MASK 0x3F +#define RF_DIOMAPPING1_DIO0_00 0x00 // Default +#define RF_DIOMAPPING1_DIO0_01 0x40 +#define RF_DIOMAPPING1_DIO0_10 0x80 +#define RF_DIOMAPPING1_DIO0_11 0xC0 + +#define RF_DIOMAPPING1_DIO1_MASK 0xCF +#define RF_DIOMAPPING1_DIO1_00 0x00 // Default +#define RF_DIOMAPPING1_DIO1_01 0x10 +#define RF_DIOMAPPING1_DIO1_10 0x20 +#define RF_DIOMAPPING1_DIO1_11 0x30 + +#define RF_DIOMAPPING1_DIO2_MASK 0xF3 +#define RF_DIOMAPPING1_DIO2_00 0x00 // Default +#define RF_DIOMAPPING1_DIO2_01 0x04 +#define RF_DIOMAPPING1_DIO2_10 0x08 +#define RF_DIOMAPPING1_DIO2_11 0x0C + +#define RF_DIOMAPPING1_DIO3_MASK 0xFC +#define RF_DIOMAPPING1_DIO3_00 0x00 // Default +#define RF_DIOMAPPING1_DIO3_01 0x01 +#define RF_DIOMAPPING1_DIO3_10 0x02 +#define RF_DIOMAPPING1_DIO3_11 0x03 + +/*! + * RegDioMapping2 + */ +#define RF_DIOMAPPING2_DIO4_MASK 0x3F +#define RF_DIOMAPPING2_DIO4_00 0x00 // Default +#define RF_DIOMAPPING2_DIO4_01 0x40 +#define RF_DIOMAPPING2_DIO4_10 0x80 +#define RF_DIOMAPPING2_DIO4_11 0xC0 + +#define RF_DIOMAPPING2_DIO5_MASK 0xCF +#define RF_DIOMAPPING2_DIO5_00 0x00 // Default +#define RF_DIOMAPPING2_DIO5_01 0x10 +#define RF_DIOMAPPING2_DIO5_10 0x20 +#define RF_DIOMAPPING2_DIO5_11 0x30 + +#define RF_DIOMAPPING2_MAP_MASK 0xFE +#define RF_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01 +#define RF_DIOMAPPING2_MAP_RSSI 0x00 // Default + +/*! + * RegVersion (Read Only) + */ + +/*! + * RegAgcRef + */ + +/*! + * RegAgcThresh1 + */ + +/*! + * RegAgcThresh2 + */ + +/*! + * RegAgcThresh3 + */ + +/*! + * RegPllHop + */ +#define RF_PLLHOP_FASTHOP_MASK 0x7F +#define RF_PLLHOP_FASTHOP_ON 0x80 +#define RF_PLLHOP_FASTHOP_OFF 0x00 // Default + +/*! + * RegTcxo + */ +#define RF_TCXO_TCXOINPUT_MASK 0xEF +#define RF_TCXO_TCXOINPUT_ON 0x10 +#define RF_TCXO_TCXOINPUT_OFF 0x00 // Default + +/*! + * RegPaDac + */ +#define RF_PADAC_20DBM_MASK 0xF8 +#define RF_PADAC_20DBM_ON 0x07 +#define RF_PADAC_20DBM_OFF 0x04 // Default + +/*! + * RegPll + */ +#define RF_PLL_BANDWIDTH_MASK 0x3F +#define RF_PLL_BANDWIDTH_75 0x00 +#define RF_PLL_BANDWIDTH_150 0x40 +#define RF_PLL_BANDWIDTH_225 0x80 +#define RF_PLL_BANDWIDTH_300 0xC0 // Default + +/*! + * RegPllLowPn + */ +#define RF_PLLLOWPN_BANDWIDTH_MASK 0x3F +#define RF_PLLLOWPN_BANDWIDTH_75 0x00 +#define RF_PLLLOWPN_BANDWIDTH_150 0x40 +#define RF_PLLLOWPN_BANDWIDTH_225 0x80 +#define RF_PLLLOWPN_BANDWIDTH_300 0xC0 // Default + +/*! + * RegFormerTemp + */ + +/*! + * RegBitrateFrac + */ +#define RF_BITRATEFRAC_MASK 0xF0 + +#endif // __SX1272_REGS_FSK_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/registers/sx1272Regs-LoRa.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,545 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: SX1272 LoRa modem registers and bits definitions + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainer: Miguel Luis and Gregory Cristian +*/ +#ifndef __SX1272_REGS_LORA_H__ +#define __SX1272_REGS_LORA_H__ + +/*! + * ============================================================================ + * SX1272 Internal registers Address + * ============================================================================ + */ +#define REG_LR_FIFO 0x00 +// Common settings +#define REG_LR_OPMODE 0x01 +#define REG_LR_FRFMSB 0x06 +#define REG_LR_FRFMID 0x07 +#define REG_LR_FRFLSB 0x08 +// Tx settings +#define REG_LR_PACONFIG 0x09 +#define REG_LR_PARAMP 0x0A +#define REG_LR_OCP 0x0B +// Rx settings +#define REG_LR_LNA 0x0C +// LoRa registers +#define REG_LR_FIFOADDRPTR 0x0D +#define REG_LR_FIFOTXBASEADDR 0x0E +#define REG_LR_FIFORXBASEADDR 0x0F +#define REG_LR_FIFORXCURRENTADDR 0x10 +#define REG_LR_IRQFLAGSMASK 0x11 +#define REG_LR_IRQFLAGS 0x12 +#define REG_LR_RXNBBYTES 0x13 +#define REG_LR_RXHEADERCNTVALUEMSB 0x14 +#define REG_LR_RXHEADERCNTVALUELSB 0x15 +#define REG_LR_RXPACKETCNTVALUEMSB 0x16 +#define REG_LR_RXPACKETCNTVALUELSB 0x17 +#define REG_LR_MODEMSTAT 0x18 +#define REG_LR_PKTSNRVALUE 0x19 +#define REG_LR_PKTRSSIVALUE 0x1A +#define REG_LR_RSSIVALUE 0x1B +#define REG_LR_HOPCHANNEL 0x1C +#define REG_LR_MODEMCONFIG1 0x1D +#define REG_LR_MODEMCONFIG2 0x1E +#define REG_LR_SYMBTIMEOUTLSB 0x1F +#define REG_LR_PREAMBLEMSB 0x20 +#define REG_LR_PREAMBLELSB 0x21 +#define REG_LR_PAYLOADLENGTH 0x22 +#define REG_LR_PAYLOADMAXLENGTH 0x23 +#define REG_LR_HOPPERIOD 0x24 +#define REG_LR_FIFORXBYTEADDR 0x25 +#define REG_LR_FEIMSB 0x28 +#define REG_LR_FEIMID 0x29 +#define REG_LR_FEILSB 0x2A +#define REG_LR_RSSIWIDEBAND 0x2C +#define REG_LR_DETECTOPTIMIZE 0x31 +#define REG_LR_INVERTIQ 0x33 +#define REG_LR_DETECTIONTHRESHOLD 0x37 +#define REG_LR_SYNCWORD 0x39 +#define REG_LR_INVERTIQ2 0x3B + +// end of documented register in datasheet +// I/O settings +#define REG_LR_DIOMAPPING1 0x40 +#define REG_LR_DIOMAPPING2 0x41 +// Version +#define REG_LR_VERSION 0x42 +// Additional settings +#define REG_LR_AGCREF 0x43 +#define REG_LR_AGCTHRESH1 0x44 +#define REG_LR_AGCTHRESH2 0x45 +#define REG_LR_AGCTHRESH3 0x46 +#define REG_LR_PLLHOP 0x4B +#define REG_LR_TCXO 0x58 +#define REG_LR_PADAC 0x5A +#define REG_LR_PLL 0x5C +#define REG_LR_PLLLOWPN 0x5E +#define REG_LR_FORMERTEMP 0x6C + +/*! + * ============================================================================ + * SX1272 LoRa bits control definition + * ============================================================================ + */ + +/*! + * RegFifo + */ + +/*! + * RegOpMode + */ +#define RFLR_OPMODE_LONGRANGEMODE_MASK 0x7F +#define RFLR_OPMODE_LONGRANGEMODE_OFF 0x00 // Default +#define RFLR_OPMODE_LONGRANGEMODE_ON 0x80 + +#define RFLR_OPMODE_ACCESSSHAREDREG_MASK 0xBF +#define RFLR_OPMODE_ACCESSSHAREDREG_ENABLE 0x40 +#define RFLR_OPMODE_ACCESSSHAREDREG_DISABLE 0x00 // Default + +#define RFLR_OPMODE_MASK 0xF8 +#define RFLR_OPMODE_SLEEP 0x00 +#define RFLR_OPMODE_STANDBY 0x01 // Default +#define RFLR_OPMODE_SYNTHESIZER_TX 0x02 +#define RFLR_OPMODE_TRANSMITTER 0x03 +#define RFLR_OPMODE_SYNTHESIZER_RX 0x04 +#define RFLR_OPMODE_RECEIVER 0x05 +// LoRa specific modes +#define RFLR_OPMODE_RECEIVER_SINGLE 0x06 +#define RFLR_OPMODE_CAD 0x07 + +/*! + * RegFrf (MHz) + */ +#define RFLR_FRFMSB_915_MHZ 0xE4 // Default +#define RFLR_FRFMID_915_MHZ 0xC0 // Default +#define RFLR_FRFLSB_915_MHZ 0x00 // Default + +/*! + * RegPaConfig + */ +#define RFLR_PACONFIG_PASELECT_MASK 0x7F +#define RFLR_PACONFIG_PASELECT_PABOOST 0x80 +#define RFLR_PACONFIG_PASELECT_RFO 0x00 // Default + +#define RFLR_PACONFIG_OUTPUTPOWER_MASK 0xF0 + +/*! + * RegPaRamp + */ +#define RFLR_PARAMP_LOWPNTXPLL_MASK 0xE0 +#define RFLR_PARAMP_LOWPNTXPLL_OFF 0x10 // Default +#define RFLR_PARAMP_LOWPNTXPLL_ON 0x00 + +#define RFLR_PARAMP_MASK 0xF0 +#define RFLR_PARAMP_3400_US 0x00 +#define RFLR_PARAMP_2000_US 0x01 +#define RFLR_PARAMP_1000_US 0x02 +#define RFLR_PARAMP_0500_US 0x03 +#define RFLR_PARAMP_0250_US 0x04 +#define RFLR_PARAMP_0125_US 0x05 +#define RFLR_PARAMP_0100_US 0x06 +#define RFLR_PARAMP_0062_US 0x07 +#define RFLR_PARAMP_0050_US 0x08 +#define RFLR_PARAMP_0040_US 0x09 // Default +#define RFLR_PARAMP_0031_US 0x0A +#define RFLR_PARAMP_0025_US 0x0B +#define RFLR_PARAMP_0020_US 0x0C +#define RFLR_PARAMP_0015_US 0x0D +#define RFLR_PARAMP_0012_US 0x0E +#define RFLR_PARAMP_0010_US 0x0F + +/*! + * RegOcp + */ +#define RFLR_OCP_MASK 0xDF +#define RFLR_OCP_ON 0x20 // Default +#define RFLR_OCP_OFF 0x00 + +#define RFLR_OCP_TRIM_MASK 0xE0 +#define RFLR_OCP_TRIM_045_MA 0x00 +#define RFLR_OCP_TRIM_050_MA 0x01 +#define RFLR_OCP_TRIM_055_MA 0x02 +#define RFLR_OCP_TRIM_060_MA 0x03 +#define RFLR_OCP_TRIM_065_MA 0x04 +#define RFLR_OCP_TRIM_070_MA 0x05 +#define RFLR_OCP_TRIM_075_MA 0x06 +#define RFLR_OCP_TRIM_080_MA 0x07 +#define RFLR_OCP_TRIM_085_MA 0x08 +#define RFLR_OCP_TRIM_090_MA 0x09 +#define RFLR_OCP_TRIM_095_MA 0x0A +#define RFLR_OCP_TRIM_100_MA 0x0B // Default +#define RFLR_OCP_TRIM_105_MA 0x0C +#define RFLR_OCP_TRIM_110_MA 0x0D +#define RFLR_OCP_TRIM_115_MA 0x0E +#define RFLR_OCP_TRIM_120_MA 0x0F +#define RFLR_OCP_TRIM_130_MA 0x10 +#define RFLR_OCP_TRIM_140_MA 0x11 +#define RFLR_OCP_TRIM_150_MA 0x12 +#define RFLR_OCP_TRIM_160_MA 0x13 +#define RFLR_OCP_TRIM_170_MA 0x14 +#define RFLR_OCP_TRIM_180_MA 0x15 +#define RFLR_OCP_TRIM_190_MA 0x16 +#define RFLR_OCP_TRIM_200_MA 0x17 +#define RFLR_OCP_TRIM_210_MA 0x18 +#define RFLR_OCP_TRIM_220_MA 0x19 +#define RFLR_OCP_TRIM_230_MA 0x1A +#define RFLR_OCP_TRIM_240_MA 0x1B + +/*! + * RegLna + */ +#define RFLR_LNA_GAIN_MASK 0x1F +#define RFLR_LNA_GAIN_G1 0x20 // Default +#define RFLR_LNA_GAIN_G2 0x40 +#define RFLR_LNA_GAIN_G3 0x60 +#define RFLR_LNA_GAIN_G4 0x80 +#define RFLR_LNA_GAIN_G5 0xA0 +#define RFLR_LNA_GAIN_G6 0xC0 + +#define RFLR_LNA_BOOST_MASK 0xFC +#define RFLR_LNA_BOOST_OFF 0x00 // Default +#define RFLR_LNA_BOOST_ON 0x03 + +/*! + * RegFifoAddrPtr + */ +#define RFLR_FIFOADDRPTR 0x00 // Default + +/*! + * RegFifoTxBaseAddr + */ +#define RFLR_FIFOTXBASEADDR 0x80 // Default + +/*! + * RegFifoTxBaseAddr + */ +#define RFLR_FIFORXBASEADDR 0x00 // Default + +/*! + * RegFifoRxCurrentAddr (Read Only) + */ + +/*! + * RegIrqFlagsMask + */ +#define RFLR_IRQFLAGS_RXTIMEOUT_MASK 0x80 +#define RFLR_IRQFLAGS_RXDONE_MASK 0x40 +#define RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK 0x20 +#define RFLR_IRQFLAGS_VALIDHEADER_MASK 0x10 +#define RFLR_IRQFLAGS_TXDONE_MASK 0x08 +#define RFLR_IRQFLAGS_CADDONE_MASK 0x04 +#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK 0x02 +#define RFLR_IRQFLAGS_CADDETECTED_MASK 0x01 + +/*! + * RegIrqFlags + */ +#define RFLR_IRQFLAGS_RXTIMEOUT 0x80 +#define RFLR_IRQFLAGS_RXDONE 0x40 +#define RFLR_IRQFLAGS_PAYLOADCRCERROR 0x20 +#define RFLR_IRQFLAGS_VALIDHEADER 0x10 +#define RFLR_IRQFLAGS_TXDONE 0x08 +#define RFLR_IRQFLAGS_CADDONE 0x04 +#define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL 0x02 +#define RFLR_IRQFLAGS_CADDETECTED 0x01 + +/*! + * RegFifoRxNbBytes (Read Only) + */ + +/*! + * RegRxHeaderCntValueMsb (Read Only) + */ + +/*! + * RegRxHeaderCntValueLsb (Read Only) + */ + +/*! + * RegRxPacketCntValueMsb (Read Only) + */ + +/*! + * RegRxPacketCntValueLsb (Read Only) + */ + +/*! + * RegModemStat (Read Only) + */ +#define RFLR_MODEMSTAT_RX_CR_MASK 0x1F +#define RFLR_MODEMSTAT_MODEM_STATUS_MASK 0xE0 + +/*! + * RegPktSnrValue (Read Only) + */ + +/*! + * RegPktRssiValue (Read Only) + */ + +/*! + * RegRssiValue (Read Only) + */ + +/*! + * RegHopChannel (Read Only) + */ +#define RFLR_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK 0x7F +#define RFLR_HOPCHANNEL_PLL_LOCK_FAIL 0x80 +#define RFLR_HOPCHANNEL_PLL_LOCK_SUCCEED 0x00 // Default + +#define RFLR_HOPCHANNEL_CRCONPAYLOAD_MASK 0xBF +#define RFLR_HOPCHANNEL_CRCONPAYLOAD_ON 0x40 +#define RFLR_HOPCHANNEL_CRCONPAYLOAD_OFF 0x00 // Default + +#define RFLR_HOPCHANNEL_CHANNEL_MASK 0x3F + +/*! + * RegModemConfig1 + */ +#define RFLR_MODEMCONFIG1_BW_MASK 0x3F +#define RFLR_MODEMCONFIG1_BW_125_KHZ 0x00 // Default +#define RFLR_MODEMCONFIG1_BW_250_KHZ 0x40 +#define RFLR_MODEMCONFIG1_BW_500_KHZ 0x80 + +#define RFLR_MODEMCONFIG1_CODINGRATE_MASK 0xC7 +#define RFLR_MODEMCONFIG1_CODINGRATE_4_5 0x08 +#define RFLR_MODEMCONFIG1_CODINGRATE_4_6 0x10 // Default +#define RFLR_MODEMCONFIG1_CODINGRATE_4_7 0x18 +#define RFLR_MODEMCONFIG1_CODINGRATE_4_8 0x20 + +#define RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK 0xFB +#define RFLR_MODEMCONFIG1_IMPLICITHEADER_ON 0x04 +#define RFLR_MODEMCONFIG1_IMPLICITHEADER_OFF 0x00 // Default + +#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_MASK 0xFD +#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_ON 0x02 +#define RFLR_MODEMCONFIG1_RXPAYLOADCRC_OFF 0x00 // Default + +#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_MASK 0xFE +#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_ON 0x01 +#define RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_OFF 0x00 // Default + +/*! + * RegModemConfig2 + */ +#define RFLR_MODEMCONFIG2_SF_MASK 0x0F +#define RFLR_MODEMCONFIG2_SF_6 0x60 +#define RFLR_MODEMCONFIG2_SF_7 0x70 // Default +#define RFLR_MODEMCONFIG2_SF_8 0x80 +#define RFLR_MODEMCONFIG2_SF_9 0x90 +#define RFLR_MODEMCONFIG2_SF_10 0xA0 +#define RFLR_MODEMCONFIG2_SF_11 0xB0 +#define RFLR_MODEMCONFIG2_SF_12 0xC0 + +#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_MASK 0xF7 +#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_ON 0x08 +#define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_OFF 0x00 + +#define RFLR_MODEMCONFIG2_AGCAUTO_MASK 0xFB +#define RFLR_MODEMCONFIG2_AGCAUTO_ON 0x04 // Default +#define RFLR_MODEMCONFIG2_AGCAUTO_OFF 0x00 + +#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK 0xFC +#define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB 0x00 // Default + +/*! + * RegSymbTimeoutLsb + */ +#define RFLR_SYMBTIMEOUTLSB_SYMBTIMEOUT 0x64 // Default + +/*! + * RegPreambleLengthMsb + */ +#define RFLR_PREAMBLELENGTHMSB 0x00 // Default + +/*! + * RegPreambleLengthLsb + */ +#define RFLR_PREAMBLELENGTHLSB 0x08 // Default + +/*! + * RegPayloadLength + */ +#define RFLR_PAYLOADLENGTH 0x0E // Default + +/*! + * RegPayloadMaxLength + */ +#define RFLR_PAYLOADMAXLENGTH 0xFF // Default + +/*! + * RegHopPeriod + */ +#define RFLR_HOPPERIOD_FREQFOPPINGPERIOD 0x00 // Default + +/*! + * RegFifoRxByteAddr (Read Only) + */ + +/*! + * RegFeiMsb (Read Only) + */ + +/*! + * RegFeiMid (Read Only) + */ + +/*! + * RegFeiLsb (Read Only) + */ + +/*! + * RegRssiWideband (Read Only) + */ + +/*! + * RegDetectOptimize + */ +#define RFLR_DETECTIONOPTIMIZE_MASK 0xF8 +#define RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 0x03 // Default +#define RFLR_DETECTIONOPTIMIZE_SF6 0x05 + +/*! + * RegInvertIQ + */ +#define RFLR_INVERTIQ_RX_MASK 0xBF +#define RFLR_INVERTIQ_RX_OFF 0x00 +#define RFLR_INVERTIQ_RX_ON 0x40 +#define RFLR_INVERTIQ_TX_MASK 0xFE +#define RFLR_INVERTIQ_TX_OFF 0x01 +#define RFLR_INVERTIQ_TX_ON 0x00 + +/*! + * RegDetectionThreshold + */ +#define RFLR_DETECTIONTHRESH_SF7_TO_SF12 0x0A // Default +#define RFLR_DETECTIONTHRESH_SF6 0x0C + +/*! + * RegInvertIQ2 + */ +#define RFLR_INVERTIQ2_ON 0x19 +#define RFLR_INVERTIQ2_OFF 0x1D + +/*! + * RegDioMapping1 + */ +#define RFLR_DIOMAPPING1_DIO0_MASK 0x3F +#define RFLR_DIOMAPPING1_DIO0_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO0_01 0x40 +#define RFLR_DIOMAPPING1_DIO0_10 0x80 +#define RFLR_DIOMAPPING1_DIO0_11 0xC0 + +#define RFLR_DIOMAPPING1_DIO1_MASK 0xCF +#define RFLR_DIOMAPPING1_DIO1_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO1_01 0x10 +#define RFLR_DIOMAPPING1_DIO1_10 0x20 +#define RFLR_DIOMAPPING1_DIO1_11 0x30 + +#define RFLR_DIOMAPPING1_DIO2_MASK 0xF3 +#define RFLR_DIOMAPPING1_DIO2_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO2_01 0x04 +#define RFLR_DIOMAPPING1_DIO2_10 0x08 +#define RFLR_DIOMAPPING1_DIO2_11 0x0C + +#define RFLR_DIOMAPPING1_DIO3_MASK 0xFC +#define RFLR_DIOMAPPING1_DIO3_00 0x00 // Default +#define RFLR_DIOMAPPING1_DIO3_01 0x01 +#define RFLR_DIOMAPPING1_DIO3_10 0x02 +#define RFLR_DIOMAPPING1_DIO3_11 0x03 + +/*! + * RegDioMapping2 + */ +#define RFLR_DIOMAPPING2_DIO4_MASK 0x3F +#define RFLR_DIOMAPPING2_DIO4_00 0x00 // Default +#define RFLR_DIOMAPPING2_DIO4_01 0x40 +#define RFLR_DIOMAPPING2_DIO4_10 0x80 +#define RFLR_DIOMAPPING2_DIO4_11 0xC0 + +#define RFLR_DIOMAPPING2_DIO5_MASK 0xCF +#define RFLR_DIOMAPPING2_DIO5_00 0x00 // Default +#define RFLR_DIOMAPPING2_DIO5_01 0x10 +#define RFLR_DIOMAPPING2_DIO5_10 0x20 +#define RFLR_DIOMAPPING2_DIO5_11 0x30 + +#define RFLR_DIOMAPPING2_MAP_MASK 0xFE +#define RFLR_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01 +#define RFLR_DIOMAPPING2_MAP_RSSI 0x00 // Default + +/*! + * RegVersion (Read Only) + */ + +/*! + * RegAgcRef + */ + +/*! + * RegAgcThresh1 + */ + +/*! + * RegAgcThresh2 + */ + +/*! + * RegAgcThresh3 + */ + +/*! + * RegPllHop + */ +#define RFLR_PLLHOP_FASTHOP_MASK 0x7F +#define RFLR_PLLHOP_FASTHOP_ON 0x80 +#define RFLR_PLLHOP_FASTHOP_OFF 0x00 // Default + +/*! + * RegTcxo + */ +#define RFLR_TCXO_TCXOINPUT_MASK 0xEF +#define RFLR_TCXO_TCXOINPUT_ON 0x10 +#define RFLR_TCXO_TCXOINPUT_OFF 0x00 // Default + +/*! + * RegPaDac + */ +#define RFLR_PADAC_20DBM_MASK 0xF8 +#define RFLR_PADAC_20DBM_ON 0x07 +#define RFLR_PADAC_20DBM_OFF 0x04 // Default + +/*! + * RegPll + */ +#define RFLR_PLL_BANDWIDTH_MASK 0x3F +#define RFLR_PLL_BANDWIDTH_75 0x00 +#define RFLR_PLL_BANDWIDTH_150 0x40 +#define RFLR_PLL_BANDWIDTH_225 0x80 +#define RFLR_PLL_BANDWIDTH_300 0xC0 // Default + +/*! + * RegPllLowPn + */ +#define RFLR_PLLLOWPN_BANDWIDTH_MASK 0x3F +#define RFLR_PLLLOWPN_BANDWIDTH_75 0x00 +#define RFLR_PLLLOWPN_BANDWIDTH_150 0x40 +#define RFLR_PLLLOWPN_BANDWIDTH_225 0x80 +#define RFLR_PLLLOWPN_BANDWIDTH_300 0xC0 // Default + +/*! + * RegFormerTemp + */ + +#endif // __SX1272_REGS_LORA_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/sx1272/sx1272-hal.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,459 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: - + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#include "sx1272-hal.h" + +#if defined ( TARGET_MOTE_L152RC ) +/* + PD_2=0 PD_2=1 +op PaB rfo rfo +0 4.6 18.5 27.0 +1 5.6 21.1 28.1 +2 6.7 23.3 29.1 +3 7.7 25.3 30.1 +4 8.8 26.2 30.7 +5 9.8 27.3 31.2 +6 10.7 28.1 31.6 +7 11.7 28.6 32.2 +8 12.8 29.2 32.4 +9 13.7 29.9 32.9 +10 14.7 30.5 33.1 +11 15.6 30.8 33.4 +12 16.4 30.9 33.6 +13 17.1 31.0 33.7 +14 17.8 31.1 33.7 +15 18.4 31.1 33.7 +*/ +// txpow: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 +static const uint8_t PaBTable[20] = { 0, 0, 0, 0, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15 }; + +// txpow: 20 21 22 23 24 25 26 27 28 29 30 +static const uint8_t RfoTable[11] = { 1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9 }; + +#endif + +const RadioRegisters_t SX1272MB2xAS::RadioRegsInit[] = RADIO_INIT_REGISTERS_VALUE; + +SX1272MB2xAS::SX1272MB2xAS( RadioEvents_t *events, + PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, + PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5, +#if defined ( TARGET_MOTE_L152RC ) + PinName rfSwitchCntr1, PinName rfSwitchCntr2 ) +#elif defined ( TARGET_MTS_MDOT_F411RE ) + PinName txctl, PinName rxctl ) +#else + PinName antSwitch ) +#endif + : SX1272( events, mosi, miso, sclk, nss, reset, dio0, dio1, dio2, dio3, dio4, dio5 ), +#if defined ( TARGET_MOTE_L152RC ) + RfSwitchCntr1( rfSwitchCntr1 ), + RfSwitchCntr2( rfSwitchCntr2 ), + PwrAmpCntr( PD_2 ) +#elif defined ( TARGET_MTS_MDOT_F411RE ) + TxCtl ( txctl ), + RxCtl ( rxctl ) +#else + AntSwitch( antSwitch ), + #if( defined ( TARGET_NUCLEO_L152RE ) ) || defined ( TARGET_NUCLEO_L476RG ) + Fake( D8 ) + #else + Fake( A3 ) + #endif +#endif +{ + this->RadioEvents = events; + + Reset( ); + + IoInit( ); + + SetOpMode( RF_OPMODE_SLEEP ); + + IoIrqInit( dioIrq ); + + RadioRegistersInit( ); + + SetModem( MODEM_FSK ); + + this->settings.State = RF_IDLE ; +} + +SX1272MB2xAS::SX1272MB2xAS( RadioEvents_t *events ) + #if defined ( TARGET_NUCLEO_L152RE ) || defined ( TARGET_NUCLEO_L476RG ) + : SX1272( events, D11, D12, D13, D10, A0, D2, D3, D4, D5, A3, D9 ), // For NUCLEO L152RE dio4 is on port A3 + AntSwitch( A4 ), + Fake( D8 ) + #elif defined ( TARGET_MOTE_L152RC ) + : SX1272( events, PB_15, PB_14, PB_13, PB_12, PC_2, PC_6, PC_10, PC_11, PC_8, PC_9, PC_12 ), + RfSwitchCntr1( PC_4 ), + RfSwitchCntr2( PC_13 ), + PwrAmpCntr( PD_2 ) + #elif defined ( TARGET_MTS_MDOT_F411RE ) + : SX1272( events, LORA_MOSI, LORA_MISO, LORA_SCK, LORA_NSS, LORA_RESET, LORA_DIO0, LORA_DIO1, LORA_DIO2, LORA_DIO3, LORA_DIO4, LORA_DIO5 ), + TxCtl( LORA_TXCTL ), + RxCtl( LORA_RXCTL ) + #else + : SX1272( events, D11, D12, D13, D10, A0, D2, D3, D4, D5, D8, D9 ), + AntSwitch( A4 ), + Fake( A3 ) + #endif +{ + this->RadioEvents = events; + + Reset( ); + + boardConnected = UNKNOWN; + + DetectBoardType( ); + + IoInit( ); + + SetOpMode( RF_OPMODE_SLEEP ); + IoIrqInit( dioIrq ); + + RadioRegistersInit( ); + + SetModem( MODEM_FSK ); + + this->settings.State = RF_IDLE ; +} + +//------------------------------------------------------------------------- +// Board relative functions +//------------------------------------------------------------------------- +uint8_t SX1272MB2xAS::DetectBoardType( void ) +{ + if( boardConnected == UNKNOWN ) + { +#if defined ( TARGET_MOTE_L152RC ) + boardConnected = NA_MOTE_72; +#elif defined ( TARGET_MTS_MDOT_F411RE ) + boardConnected = MDOT_F411RE; +#else + this->AntSwitch.input( ); + wait_ms( 1 ); + if( this->AntSwitch == 1 ) + { + boardConnected = SX1272MB1DCS; + } + else + { + boardConnected = SX1272MB2XAS; + } + this->AntSwitch.output( ); + wait_ms( 1 ); +#endif + } + return ( boardConnected ); +} + +void SX1272MB2xAS::IoInit( void ) +{ + AntSwInit( ); + SpiInit( ); +} + +void SX1272MB2xAS::RadioRegistersInit( ) +{ + uint8_t i = 0; + for( i = 0; i < sizeof( RadioRegsInit ) / sizeof( RadioRegisters_t ); i++ ) + { + SetModem( RadioRegsInit[i].Modem ); + Write( RadioRegsInit[i].Addr, RadioRegsInit[i].Value ); + } +} + +void SX1272MB2xAS::SpiInit( void ) +{ + nss = 1; + spi.format( 8,0 ); + uint32_t frequencyToSet = 8000000; + #if( defined ( TARGET_NUCLEO_L152RE ) || defined ( TARGET_MOTE_L152RC ) || defined ( TARGET_NUCLEO_L476RG ) || defined ( TARGET_LPC11U6X ) || defined ( TARGET_MTS_MDOT_F411RE ) ) + spi.frequency( frequencyToSet ); + #elif( defined ( TARGET_KL25Z ) ) //busclock frequency is halved -> double the spi frequency to compensate + spi.frequency( frequencyToSet * 2 ); + #else + #warning "Check the board's SPI frequency" + #endif + wait(0.1); +} + +void SX1272MB2xAS::IoIrqInit( DioIrqHandler *irqHandlers ) +{ +#if( defined ( TARGET_NUCLEO_L152RE ) || defined ( TARGET_MOTE_L152RC ) || defined ( TARGET_NUCLEO_L476RG ) || defined ( TARGET_NUCLEO_L476RG ) || defined ( TARGET_LPC11U6X ) ) + dio0.mode( PullDown ); + dio1.mode( PullDown ); + dio2.mode( PullDown ); + dio3.mode( PullDown ); + dio4.mode( PullDown ); +#endif + dio0.rise( mbed::callback( this, static_cast< TriggerMB2xAS > ( irqHandlers[0] ) ) ); + dio1.rise( mbed::callback( this, static_cast< TriggerMB2xAS > ( irqHandlers[1] ) ) ); + dio2.rise( mbed::callback( this, static_cast< TriggerMB2xAS > ( irqHandlers[2] ) ) ); + dio3.rise( mbed::callback( this, static_cast< TriggerMB2xAS > ( irqHandlers[3] ) ) ); + dio4.rise( mbed::callback( this, static_cast< TriggerMB2xAS > ( irqHandlers[4] ) ) ); +} + +void SX1272MB2xAS::IoDeInit( void ) +{ + //nothing +} + +void SX1272MB2xAS::SetRfTxPower( int8_t power ) +{ + uint8_t paConfig = 0; + uint8_t paDac = 0; + + paConfig = Read( REG_PACONFIG ); + paDac = Read( REG_PADAC ); + +#if defined ( TARGET_MOTE_L152RC ) + if( power > 19 ) + { + paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_RFO; + paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | RfoTable[power - 20]; + } + else + { + paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | RF_PACONFIG_PASELECT_PABOOST; + paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | PaBTable[power]; + } +#else + paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | GetPaSelect( this->settings.Channel ); + + if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST ) + { + if( power > 17 ) + { + paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON; + } + else + { + paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF; + } + if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON ) + { + if( power < 5 ) + { + power = 5; + } + if( power > 20 ) + { + power = 20; + } + paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F ); + } + else + { + if( power < 2 ) + { + power = 2; + } + if( power > 17 ) + { + power = 17; + } + paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F ); + } + } + else + { + if( power < -1 ) + { + power = -1; + } + if( power > 14 ) + { + power = 14; + } + paConfig = ( paConfig & RFLR_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F ); + } +#endif + Write( REG_PACONFIG, paConfig ); + Write( REG_PADAC, paDac ); +} + +uint8_t SX1272MB2xAS::GetPaSelect( uint32_t channel ) +{ + if( boardConnected == SX1272MB1DCS || boardConnected == MDOT_F411RE ) + { + return RF_PACONFIG_PASELECT_PABOOST; + } + else + { + return RF_PACONFIG_PASELECT_RFO; + } +} + +void SX1272MB2xAS::SetAntSwLowPower( bool status ) +{ + if( isRadioActive != status ) + { + isRadioActive = status; + + if( status == false ) + { + AntSwInit( ); + } + else + { + AntSwDeInit( ); + } + } +} + +void SX1272MB2xAS::AntSwInit( void ) +{ +#if defined ( TARGET_MOTE_L152RC ) + this->RfSwitchCntr1 = 0; + this->RfSwitchCntr2 = 0; + this->PwrAmpCntr = 0; +#elif defined ( TARGET_MTS_MDOT_F411RE ) + this->TxCtl = 0; + this->RxCtl = 0; +#else + this->AntSwitch = 0; +#endif +} + +void SX1272MB2xAS::AntSwDeInit( void ) +{ +#if defined ( TARGET_MOTE_L152RC ) + this->RfSwitchCntr1 = 0; + this->RfSwitchCntr2 = 0; + this->PwrAmpCntr = 0; +#elif defined ( TARGET_MTS_MDOT_F411RE ) + this->TxCtl = 0; + this->RxCtl = 0; +#else + this->AntSwitch = 0; +#endif +} + +void SX1272MB2xAS::SetAntSw( uint8_t opMode ) +{ + switch( opMode ) + { + case RFLR_OPMODE_TRANSMITTER: +#if defined ( TARGET_MOTE_L152RC ) + if( ( Read( REG_PACONFIG ) & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST ) + { + this->RfSwitchCntr1 = 1; + this->RfSwitchCntr2 = 0; + } + else + { + this->RfSwitchCntr1 = 0; + this->RfSwitchCntr2 = 1; + } +#elif defined ( TARGET_MTS_MDOT_F411RE ) + /* SKY13350 */ + this->TxCtl = 1; + this->RxCtl = 0; +#else + this->AntSwitch = 1; +#endif + break; + case RFLR_OPMODE_RECEIVER: + case RFLR_OPMODE_RECEIVER_SINGLE: + case RFLR_OPMODE_CAD: +#if defined ( TARGET_MOTE_L152RC ) + this->RfSwitchCntr1 = 1; + this->RfSwitchCntr2 = 1; +#elif defined ( TARGET_MTS_MDOT_F411RE ) + /* SKY13350 */ + this->TxCtl = 0; + this->RxCtl = 1; +#else + this->AntSwitch = 0; +#endif + break; + default: +#if defined ( TARGET_MOTE_L152RC ) + this->RfSwitchCntr1 = 0; + this->RfSwitchCntr2 = 0; + this->PwrAmpCntr = 0; +#elif defined ( TARGET_MTS_MDOT_F411RE ) + /* SKY13350 */ + this->TxCtl = 0; + this->RxCtl = 0; +#else + this->AntSwitch = 0; +#endif + break; + } +} + +bool SX1272MB2xAS::CheckRfFrequency( uint32_t frequency ) +{ + // Implement check. Currently all frequencies are supported + return true; +} + +void SX1272MB2xAS::Reset( void ) +{ + reset.output( ); + reset = 0; + wait_ms( 1 ); + reset.input( ); + wait_ms( 6 ); +} + +void SX1272MB2xAS::Write( uint8_t addr, uint8_t data ) +{ + Write( addr, &data, 1 ); +} + +uint8_t SX1272MB2xAS::Read( uint8_t addr ) +{ + uint8_t data; + Read( addr, &data, 1 ); + return data; +} + +void SX1272MB2xAS::Write( uint8_t addr, uint8_t *buffer, uint8_t size ) +{ + uint8_t i; + + nss = 0; + spi.write( addr | 0x80 ); + for( i = 0; i < size; i++ ) + { + spi.write( buffer[i] ); + } + nss = 1; +} + +void SX1272MB2xAS::Read( uint8_t addr, uint8_t *buffer, uint8_t size ) +{ + uint8_t i; + + nss = 0; + spi.write( addr & 0x7F ); + for( i = 0; i < size; i++ ) + { + buffer[i] = spi.write( 0 ); + } + nss = 1; +} + +void SX1272MB2xAS::WriteFifo( uint8_t *buffer, uint8_t size ) +{ + Write( 0, buffer, size ); +} + +void SX1272MB2xAS::ReadFifo( uint8_t *buffer, uint8_t size ) +{ + Read( 0, buffer, size ); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/sx1272/sx1272-hal.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,228 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: - + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#ifndef __SX1272_HAL_H__ +#define __SX1272_HAL_H__ +#include "sx1272.h" + +/*! + * @brief Radio hardware registers initialization definition + * + * @remark Can be automatically generated by the SX1272 GUI (not yet implemented) + */ +#define RADIO_INIT_REGISTERS_VALUE \ +{ \ + { MODEM_FSK , REG_LNA , 0x23 },\ + { MODEM_FSK , REG_RXCONFIG , 0x1E },\ + { MODEM_FSK , REG_RSSICONFIG , 0xD2 },\ + { MODEM_FSK , REG_AFCFEI , 0x01 },\ + { MODEM_FSK , REG_PREAMBLEDETECT , 0xAA },\ + { MODEM_FSK , REG_OSC , 0x07 },\ + { MODEM_FSK , REG_SYNCCONFIG , 0x12 },\ + { MODEM_FSK , REG_SYNCVALUE1 , 0xC1 },\ + { MODEM_FSK , REG_SYNCVALUE2 , 0x94 },\ + { MODEM_FSK , REG_SYNCVALUE3 , 0xC1 },\ + { MODEM_FSK , REG_PACKETCONFIG1 , 0xD8 },\ + { MODEM_FSK , REG_FIFOTHRESH , 0x8F },\ + { MODEM_FSK , REG_IMAGECAL , 0x02 },\ + { MODEM_FSK , REG_DIOMAPPING1 , 0x00 },\ + { MODEM_FSK , REG_DIOMAPPING2 , 0x30 },\ + { MODEM_LORA, REG_LR_DETECTOPTIMIZE , 0x43 },\ + { MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 },\ +} \ + +/*! + * Actual implementation of a SX1272 radio, includes some modifications to make it compatible with the MB1 LAS board + */ +class SX1272MB2xAS : public SX1272 +{ +protected: + /*! + * Antenna switch GPIO pins objects + */ +#if defined ( TARGET_MOTE_L152RC ) + DigitalOut RfSwitchCntr1; + DigitalOut RfSwitchCntr2; + DigitalOut PwrAmpCntr; +#elif defined ( TARGET_MTS_MDOT_F411RE ) + DigitalOut TxCtl; + DigitalOut RxCtl; +#else + DigitalInOut AntSwitch; + DigitalIn Fake; +#endif + +private: + static const RadioRegisters_t RadioRegsInit[]; + +public: + SX1272MB2xAS( RadioEvents_t *events, + PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, + PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5, +#if defined ( TARGET_MOTE_L152RC ) + PinName rfSwitchCntr1, PinName rfSwitchCntr2 ); +#elif defined ( TARGET_MTS_MDOT_F411RE ) + PinName txctl, PinName rxctl ); +#else + PinName antSwitch ); +#endif + + SX1272MB2xAS( RadioEvents_t *events ); + + virtual ~SX1272MB2xAS( ) { }; + +protected: + /*! + * @brief Initializes the radio I/Os pins interface + */ + virtual void IoInit( void ); + + /*! + * @brief Initializes the radio registers + */ + virtual void RadioRegistersInit( ); + + /*! + * @brief Initializes the radio SPI + */ + virtual void SpiInit( void ); + + /*! + * @brief Initializes DIO IRQ handlers + * + * @param [IN] irqHandlers Array containing the IRQ callback functions + */ + virtual void IoIrqInit( DioIrqHandler *irqHandlers ); + + /*! + * @brief De-initializes the radio I/Os pins interface. + * + * \remark Useful when going in MCU lowpower modes + */ + virtual void IoDeInit( void ); + + /*! + * \brief Sets the radio output power. + * + * @param [IN] power Sets the RF output power + */ + virtual void SetRfTxPower( int8_t power ); + + /*! + * @brief Gets the board PA selection configuration + * + * @param [IN] channel Channel frequency in Hz + * @retval PaSelect RegPaConfig PaSelect value + */ + virtual uint8_t GetPaSelect( uint32_t channel ); + + /*! + * @brief Set the RF Switch I/Os pins in Low Power mode + * + * @param [IN] status enable or disable + */ + virtual void SetAntSwLowPower( bool status ); + + /*! + * @brief Initializes the RF Switch I/Os pins interface + */ + virtual void AntSwInit( void ); + + /*! + * @brief De-initializes the RF Switch I/Os pins interface + * + * @remark Needed to decrease the power consumption in MCU lowpower modes + */ + virtual void AntSwDeInit( void ); + + /*! + * @brief Controls the antena switch if necessary. + * + * @remark see errata note + * + * @param [IN] opMode Current radio operating mode + */ + virtual void SetAntSw( uint8_t opMode ); + +public: + /*! + * @brief Detect the board connected by reading the value of the antenna switch pin + */ + virtual uint8_t DetectBoardType( void ); + + /*! + * @brief Checks if the given RF frequency is supported by the hardware + * + * @param [IN] frequency RF frequency to be checked + * @retval isSupported [true: supported, false: unsupported] + */ + virtual bool CheckRfFrequency( uint32_t frequency ); + + /*! + * @brief Writes the radio register at the specified address + * + * @param [IN]: addr Register address + * @param [IN]: data New register value + */ + virtual void Write ( uint8_t addr, uint8_t data ) ; + + /*! + * @brief Reads the radio register at the specified address + * + * @param [IN]: addr Register address + * @retval data Register value + */ + virtual uint8_t Read ( uint8_t addr ) ; + + /*! + * @brief Writes multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [IN] buffer Buffer containing the new register's values + * @param [IN] size Number of registers to be written + */ + virtual void Write( uint8_t addr, uint8_t *buffer, uint8_t size ) ; + + /*! + * @brief Reads multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [OUT] buffer Buffer where to copy the registers data + * @param [IN] size Number of registers to be read + */ + virtual void Read ( uint8_t addr, uint8_t *buffer, uint8_t size ) ; + + /*! + * @brief Writes the buffer contents to the SX1272 FIFO + * + * @param [IN] buffer Buffer containing data to be put on the FIFO. + * @param [IN] size Number of bytes to be written to the FIFO + */ + virtual void WriteFifo( uint8_t *buffer, uint8_t size ) ; + + /*! + * @brief Reads the contents of the SX1272 FIFO + * + * @param [OUT] buffer Buffer where to copy the FIFO read data. + * @param [IN] size Number of bytes to be read from the FIFO + */ + virtual void ReadFifo( uint8_t *buffer, uint8_t size ) ; + + /*! + * @brief Reset the SX1272 + */ + virtual void Reset( void ); +}; + +#endif // __SX1272_HAL_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/sx1272/sx1272.cpp Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,1393 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: Actual implementation of a SX1272 radio, inherits Radio + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#include "sx1272.h" + +const FskBandwidth_t SX1272::FskBandwidths[] = +{ + { 2600 , 0x17 }, + { 3100 , 0x0F }, + { 3900 , 0x07 }, + { 5200 , 0x16 }, + { 6300 , 0x0E }, + { 7800 , 0x06 }, + { 10400 , 0x15 }, + { 12500 , 0x0D }, + { 15600 , 0x05 }, + { 20800 , 0x14 }, + { 25000 , 0x0C }, + { 31300 , 0x04 }, + { 41700 , 0x13 }, + { 50000 , 0x0B }, + { 62500 , 0x03 }, + { 83333 , 0x12 }, + { 100000, 0x0A }, + { 125000, 0x02 }, + { 166700, 0x11 }, + { 200000, 0x09 }, + { 250000, 0x01 }, + { 300000, 0x00 }, // Invalid Bandwidth +}; + + +SX1272::SX1272( RadioEvents_t *events, + PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, + PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5 ) + : Radio( events ), + spi( mosi, miso, sclk ), + nss( nss ), + reset( reset ), + dio0( dio0 ), dio1( dio1 ), dio2( dio2 ), dio3( dio3 ), dio4( dio4 ), dio5( dio5 ), + isRadioActive( false ) +{ + wait_ms( 10 ); + this->rxtxBuffer = new uint8_t[RX_BUFFER_SIZE]; + + this->RadioEvents = events; + + this->dioIrq = new DioIrqHandler[6]; + + this->dioIrq[0] = &SX1272::OnDio0Irq; + this->dioIrq[1] = &SX1272::OnDio1Irq; + this->dioIrq[2] = &SX1272::OnDio2Irq; + this->dioIrq[3] = &SX1272::OnDio3Irq; + this->dioIrq[4] = &SX1272::OnDio4Irq; + this->dioIrq[5] = NULL; + + this->settings.State = RF_IDLE; +} + +SX1272::~SX1272( ) +{ + delete this->rxtxBuffer; + delete this->dioIrq; +} + +void SX1272::Init( RadioEvents_t *events ) +{ + this->RadioEvents = events; +} + +RadioState SX1272::GetStatus( void ) +{ + return this->settings.State; +} + +void SX1272::SetChannel( uint32_t freq ) +{ + this->settings.Channel = freq; + freq = ( uint32_t )( ( double )freq / ( double )FREQ_STEP ); + Write( REG_FRFMSB, ( uint8_t )( ( freq >> 16 ) & 0xFF ) ); + Write( REG_FRFMID, ( uint8_t )( ( freq >> 8 ) & 0xFF ) ); + Write( REG_FRFLSB, ( uint8_t )( freq & 0xFF ) ); +} + +bool SX1272::IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ) +{ + int16_t rssi = 0; + + SetModem( modem ); + + SetChannel( freq ); + + SetOpMode( RF_OPMODE_RECEIVER ); + + wait_ms( 1 ); + + rssi = GetRssi( modem ); + + Sleep( ); + + if( rssi > rssiThresh ) + { + return false; + } + return true; +} + +uint32_t SX1272::Random( void ) +{ + uint8_t i; + uint32_t rnd = 0; + + /* + * Radio setup for random number generation + */ + // Set LoRa modem ON + SetModem( MODEM_LORA ); + + // Disable LoRa modem interrupts + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // Set radio in continuous reception + SetOpMode( RF_OPMODE_RECEIVER ); + + for( i = 0; i < 32; i++ ) + { + wait_ms( 1 ); + // Unfiltered RSSI value reading. Only takes the LSB value + rnd |= ( ( uint32_t )Read( REG_LR_RSSIWIDEBAND ) & 0x01 ) << i; + } + + Sleep( ); + + return rnd; +} + +/*! + * Returns the known FSK bandwidth registers value + * + * \param [IN] bandwidth Bandwidth value in Hz + * \retval regValue Bandwidth register value. + */ +uint8_t SX1272::GetFskBandwidthRegValue( uint32_t bandwidth ) +{ + uint8_t i; + + for( i = 0; i < ( sizeof( FskBandwidths ) / sizeof( FskBandwidth_t ) ) - 1; i++ ) + { + if( ( bandwidth >= FskBandwidths[i].bandwidth ) && ( bandwidth < FskBandwidths[i + 1].bandwidth ) ) + { + return FskBandwidths[i].RegValue; + } + } + // ERROR: Value not found + while( 1 ); +} + +void SX1272::SetRxConfig( RadioModems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ) +{ + SetModem( modem ); + + switch( modem ) + { + case MODEM_FSK: + { + this->settings.Fsk.Bandwidth = bandwidth; + this->settings.Fsk.Datarate = datarate; + this->settings.Fsk.BandwidthAfc = bandwidthAfc; + this->settings.Fsk.FixLen = fixLen; + this->settings.Fsk.PayloadLen = payloadLen; + this->settings.Fsk.CrcOn = crcOn; + this->settings.Fsk.IqInverted = iqInverted; + this->settings.Fsk.RxContinuous = rxContinuous; + this->settings.Fsk.PreambleLen = preambleLen; + this->settings.Fsk.RxSingleTimeout = symbTimeout * ( ( 1.0 / ( double )datarate ) * 8.0 ) * 1e3; + + datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate ); + Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) ); + Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) ); + + Write( REG_RXBW, GetFskBandwidthRegValue( bandwidth ) ); + Write( REG_AFCBW, GetFskBandwidthRegValue( bandwidthAfc ) ); + + Write( REG_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); + Write( REG_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + + if( fixLen == 1 ) + { + Write( REG_PAYLOADLENGTH, payloadLen ); + } + else + { + Write( REG_PAYLOADLENGTH, 0xFF ); // Set payload length to the maximum + } + + Write( REG_PACKETCONFIG1, + ( Read( REG_PACKETCONFIG1 ) & + RF_PACKETCONFIG1_CRC_MASK & + RF_PACKETCONFIG1_PACKETFORMAT_MASK ) | + ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) | + ( crcOn << 4 ) ); + Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) ); + } + break; + case MODEM_LORA: + { + this->settings.LoRa.Bandwidth = bandwidth; + this->settings.LoRa.Datarate = datarate; + this->settings.LoRa.Coderate = coderate; + this->settings.LoRa.PreambleLen = preambleLen; + this->settings.LoRa.FixLen = fixLen; + this->settings.LoRa.PayloadLen = payloadLen; + this->settings.LoRa.CrcOn = crcOn; + this->settings.LoRa.FreqHopOn = freqHopOn; + this->settings.LoRa.HopPeriod = hopPeriod; + this->settings.LoRa.IqInverted = iqInverted; + this->settings.LoRa.RxContinuous = rxContinuous; + + if( datarate > 12 ) + { + datarate = 12; + } + else if( datarate < 6 ) + { + datarate = 6; + } + + if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) || + ( ( bandwidth == 1 ) && ( datarate == 12 ) ) ) + { + this->settings.LoRa.LowDatarateOptimize = 0x01; + } + else + { + this->settings.LoRa.LowDatarateOptimize = 0x00; + } + + Write( REG_LR_MODEMCONFIG1, + ( Read( REG_LR_MODEMCONFIG1 ) & + RFLR_MODEMCONFIG1_BW_MASK & + RFLR_MODEMCONFIG1_CODINGRATE_MASK & + RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK & + RFLR_MODEMCONFIG1_RXPAYLOADCRC_MASK & + RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_MASK ) | + ( bandwidth << 6 ) | ( coderate << 3 ) | + ( fixLen << 2 ) | ( crcOn << 1 ) | + this->settings.LoRa.LowDatarateOptimize ); + + Write( REG_LR_MODEMCONFIG2, + ( Read( REG_LR_MODEMCONFIG2 ) & + RFLR_MODEMCONFIG2_SF_MASK & + RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) | + ( datarate << 4 ) | + ( ( symbTimeout >> 8 ) & ~RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK ) ); + + Write( REG_LR_SYMBTIMEOUTLSB, ( uint8_t )( symbTimeout & 0xFF ) ); + + Write( REG_LR_PREAMBLEMSB, ( uint8_t )( ( preambleLen >> 8 ) & 0xFF ) ); + Write( REG_LR_PREAMBLELSB, ( uint8_t )( preambleLen & 0xFF ) ); + + if( fixLen == 1 ) + { + Write( REG_LR_PAYLOADLENGTH, payloadLen ); + } + + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_PLLHOP, ( Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + Write( REG_LR_HOPPERIOD, this->settings.LoRa.HopPeriod ); + } + + if( datarate == 6 ) + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF6 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF6 ); + } + else + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); + } + } + break; + } +} + +void SX1272::SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ) +{ + SetModem( modem ); + + SetRfTxPower( power ); + + switch( modem ) + { + case MODEM_FSK: + { + this->settings.Fsk.Power = power; + this->settings.Fsk.Fdev = fdev; + this->settings.Fsk.Bandwidth = bandwidth; + this->settings.Fsk.Datarate = datarate; + this->settings.Fsk.PreambleLen = preambleLen; + this->settings.Fsk.FixLen = fixLen; + this->settings.Fsk.CrcOn = crcOn; + this->settings.Fsk.IqInverted = iqInverted; + this->settings.Fsk.TxTimeout = timeout; + + fdev = ( uint16_t )( ( double )fdev / ( double )FREQ_STEP ); + Write( REG_FDEVMSB, ( uint8_t )( fdev >> 8 ) ); + Write( REG_FDEVLSB, ( uint8_t )( fdev & 0xFF ) ); + + datarate = ( uint16_t )( ( double )XTAL_FREQ / ( double )datarate ); + Write( REG_BITRATEMSB, ( uint8_t )( datarate >> 8 ) ); + Write( REG_BITRATELSB, ( uint8_t )( datarate & 0xFF ) ); + + Write( REG_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF ); + Write( REG_PREAMBLELSB, preambleLen & 0xFF ); + + Write( REG_PACKETCONFIG1, + ( Read( REG_PACKETCONFIG1 ) & + RF_PACKETCONFIG1_CRC_MASK & + RF_PACKETCONFIG1_PACKETFORMAT_MASK ) | + ( ( fixLen == 1 ) ? RF_PACKETCONFIG1_PACKETFORMAT_FIXED : RF_PACKETCONFIG1_PACKETFORMAT_VARIABLE ) | + ( crcOn << 4 ) ); + Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) | RF_PACKETCONFIG2_DATAMODE_PACKET ) ); + } + break; + case MODEM_LORA: + { + this->settings.LoRa.Power = power; + this->settings.LoRa.Bandwidth = bandwidth; + this->settings.LoRa.Datarate = datarate; + this->settings.LoRa.Coderate = coderate; + this->settings.LoRa.PreambleLen = preambleLen; + this->settings.LoRa.FixLen = fixLen; + this->settings.LoRa.FreqHopOn = freqHopOn; + this->settings.LoRa.HopPeriod = hopPeriod; + this->settings.LoRa.CrcOn = crcOn; + this->settings.LoRa.IqInverted = iqInverted; + this->settings.LoRa.TxTimeout = timeout; + + if( datarate > 12 ) + { + datarate = 12; + } + else if( datarate < 6 ) + { + datarate = 6; + } + if( ( ( bandwidth == 0 ) && ( ( datarate == 11 ) || ( datarate == 12 ) ) ) || + ( ( bandwidth == 1 ) && ( datarate == 12 ) ) ) + { + this->settings.LoRa.LowDatarateOptimize = 0x01; + } + else + { + this->settings.LoRa.LowDatarateOptimize = 0x00; + } + + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_PLLHOP, ( Read( REG_LR_PLLHOP ) & RFLR_PLLHOP_FASTHOP_MASK ) | RFLR_PLLHOP_FASTHOP_ON ); + Write( REG_LR_HOPPERIOD, this->settings.LoRa.HopPeriod ); + } + + Write( REG_LR_MODEMCONFIG1, + ( Read( REG_LR_MODEMCONFIG1 ) & + RFLR_MODEMCONFIG1_BW_MASK & + RFLR_MODEMCONFIG1_CODINGRATE_MASK & + RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK & + RFLR_MODEMCONFIG1_RXPAYLOADCRC_MASK & + RFLR_MODEMCONFIG1_LOWDATARATEOPTIMIZE_MASK ) | + ( bandwidth << 6 ) | ( coderate << 3 ) | + ( fixLen << 2 ) | ( crcOn << 1 ) | + this->settings.LoRa.LowDatarateOptimize ); + + Write( REG_LR_MODEMCONFIG2, + ( Read( REG_LR_MODEMCONFIG2 ) & + RFLR_MODEMCONFIG2_SF_MASK ) | + ( datarate << 4 ) ); + + + Write( REG_LR_PREAMBLEMSB, ( preambleLen >> 8 ) & 0x00FF ); + Write( REG_LR_PREAMBLELSB, preambleLen & 0xFF ); + + if( datarate == 6 ) + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF6 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF6 ); + } + else + { + Write( REG_LR_DETECTOPTIMIZE, + ( Read( REG_LR_DETECTOPTIMIZE ) & + RFLR_DETECTIONOPTIMIZE_MASK ) | + RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 ); + Write( REG_LR_DETECTIONTHRESHOLD, + RFLR_DETECTIONTHRESH_SF7_TO_SF12 ); + } + } + break; + } +} + +uint32_t SX1272::TimeOnAir( RadioModems_t modem, uint8_t pktLen ) +{ + uint32_t airTime = 0; + + switch( modem ) + { + case MODEM_FSK: + { + airTime = rint( ( 8 * ( this->settings.Fsk.PreambleLen + + ( ( Read( REG_SYNCCONFIG ) & ~RF_SYNCCONFIG_SYNCSIZE_MASK ) + 1 ) + + ( ( this->settings.Fsk.FixLen == 0x01 ) ? 0.0 : 1.0 ) + + ( ( ( Read( REG_PACKETCONFIG1 ) & ~RF_PACKETCONFIG1_ADDRSFILTERING_MASK ) != 0x00 ) ? 1.0 : 0 ) + + pktLen + + ( ( this->settings.Fsk.CrcOn == 0x01 ) ? 2.0 : 0 ) ) / + this->settings.Fsk.Datarate ) * 1e3 ); + } + break; + case MODEM_LORA: + { + double bw = 0.0; + switch( this->settings.LoRa.Bandwidth ) + { + case 0: // 125 kHz + bw = 125e3; + break; + case 1: // 250 kHz + bw = 250e3; + break; + case 2: // 500 kHz + bw = 500e3; + break; + } + + // Symbol rate : time for one symbol (secs) + double rs = bw / ( 1 << this->settings.LoRa.Datarate ); + double ts = 1 / rs; + // time of preamble + double tPreamble = ( this->settings.LoRa.PreambleLen + 4.25 ) * ts; + // Symbol length of payload and time + double tmp = ceil( ( 8 * pktLen - 4 * this->settings.LoRa.Datarate + + 28 + 16 * this->settings.LoRa.CrcOn - + ( this->settings.LoRa.FixLen ? 20 : 0 ) ) / + ( double )( 4 * ( this->settings.LoRa.Datarate - + ( ( this->settings.LoRa.LowDatarateOptimize > 0 ) ? 2 : 0 ) ) ) ) * + ( this->settings.LoRa.Coderate + 4 ); + double nPayload = 8 + ( ( tmp > 0 ) ? tmp : 0 ); + double tPayload = nPayload * ts; + // Time on air + double tOnAir = tPreamble + tPayload; + // return ms secs + airTime = floor( tOnAir * 1e3 + 0.999 ); + } + break; + } + return airTime; +} + +void SX1272::Send( uint8_t *buffer, uint8_t size ) +{ + uint32_t txTimeout = 0; + + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = size; + + if( this->settings.Fsk.FixLen == false ) + { + WriteFifo( ( uint8_t* )&size, 1 ); + } + else + { + Write( REG_PAYLOADLENGTH, size ); + } + + if( ( size > 0 ) && ( size <= 64 ) ) + { + this->settings.FskPacketHandler.ChunkSize = size; + } + else + { + memcpy( rxtxBuffer, buffer, size ); + this->settings.FskPacketHandler.ChunkSize = 32; + } + + // Write payload buffer + WriteFifo( buffer, this->settings.FskPacketHandler.ChunkSize ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.ChunkSize; + txTimeout = this->settings.Fsk.TxTimeout; + } + break; + case MODEM_LORA: + { + if( this->settings.LoRa.IqInverted == true ) + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_ON ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON ); + } + else + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF ); + } + + this->settings.LoRaPacketHandler.Size = size; + + // Initializes the payload size + Write( REG_LR_PAYLOADLENGTH, size ); + + // Full buffer used for Tx + Write( REG_LR_FIFOTXBASEADDR, 0 ); + Write( REG_LR_FIFOADDRPTR, 0 ); + + // FIFO operations can not take place in Sleep mode + if( ( Read( REG_OPMODE ) & ~RF_OPMODE_MASK ) == RF_OPMODE_SLEEP ) + { + Standby( ); + wait_ms( 1 ); + } + // Write payload buffer + WriteFifo( buffer, size ); + txTimeout = this->settings.LoRa.TxTimeout; + } + break; + } + + Tx( txTimeout ); +} + +void SX1272::Sleep( void ) +{ + txTimeoutTimer.detach( ); + rxTimeoutTimer.detach( ); + + SetOpMode( RF_OPMODE_SLEEP ); + this->settings.State = RF_IDLE; +} + +void SX1272::Standby( void ) +{ + txTimeoutTimer.detach( ); + rxTimeoutTimer.detach( ); + + SetOpMode( RF_OPMODE_STANDBY ); + this->settings.State = RF_IDLE; +} + +void SX1272::Rx( uint32_t timeout ) +{ + bool rxContinuous = false; + + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + rxContinuous = this->settings.Fsk.RxContinuous; + + // DIO0=PayloadReady + // DIO1=FifoLevel + // DIO2=SyncAddr + // DIO3=FifoEmpty + // DIO4=Preamble + // DIO5=ModeReady + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK & + RF_DIOMAPPING1_DIO1_MASK & + RF_DIOMAPPING1_DIO2_MASK ) | + RF_DIOMAPPING1_DIO0_00 | + RF_DIOMAPPING1_DIO1_00 | + RF_DIOMAPPING1_DIO2_11 ); + + Write( REG_DIOMAPPING2, ( Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK & + RF_DIOMAPPING2_MAP_MASK ) | + RF_DIOMAPPING2_DIO4_11 | + RF_DIOMAPPING2_MAP_PREAMBLEDETECT ); + + this->settings.FskPacketHandler.FifoThresh = Read( REG_FIFOTHRESH ) & 0x3F; + + Write( REG_RXCONFIG, RF_RXCONFIG_AFCAUTO_ON | RF_RXCONFIG_AGCAUTO_ON | RF_RXCONFIG_RXTRIGER_PREAMBLEDETECT ); + + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + } + break; + case MODEM_LORA: + { + if( this->settings.LoRa.IqInverted == true ) + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_ON | RFLR_INVERTIQ_TX_OFF ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_ON ); + } + else + { + Write( REG_LR_INVERTIQ, ( ( Read( REG_LR_INVERTIQ ) & RFLR_INVERTIQ_TX_MASK & RFLR_INVERTIQ_RX_MASK ) | RFLR_INVERTIQ_RX_OFF | RFLR_INVERTIQ_TX_OFF ) ); + Write( REG_LR_INVERTIQ2, RFLR_INVERTIQ2_OFF ); + } + + rxContinuous = this->settings.LoRa.RxContinuous; + + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone, DIO2=FhssChangeChannel + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_00 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + Write( REG_LR_IRQFLAGSMASK, //RFLR_IRQFLAGS_RXTIMEOUT | + //RFLR_IRQFLAGS_RXDONE | + //RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=RxDone + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_00 ); + } + Write( REG_LR_FIFORXBASEADDR, 0 ); + Write( REG_LR_FIFOADDRPTR, 0 ); + } + break; + } + + memset( rxtxBuffer, 0, ( size_t )RX_BUFFER_SIZE ); + + this->settings.State = RF_RX_RUNNING; + if( timeout != 0 ) + { + rxTimeoutTimer.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), timeout * 1e3 ); + } + + if( this->settings.Modem == MODEM_FSK ) + { + SetOpMode( RF_OPMODE_RECEIVER ); + + if( rxContinuous == false ) + { + rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), + this->settings.Fsk.RxSingleTimeout * 1e3 ); + } + } + else + { + if( rxContinuous == true ) + { + SetOpMode( RFLR_OPMODE_RECEIVER ); + } + else + { + SetOpMode( RFLR_OPMODE_RECEIVER_SINGLE ); + } + } +} + +void SX1272::Tx( uint32_t timeout ) +{ + + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + // DIO0=PacketSent + // DIO1=FifoEmpty + // DIO2=FifoFull + // DIO3=FifoEmpty + // DIO4=LowBat + // DIO5=ModeReady + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RF_DIOMAPPING1_DIO0_MASK & + RF_DIOMAPPING1_DIO1_MASK & + RF_DIOMAPPING1_DIO2_MASK ) | + RF_DIOMAPPING1_DIO1_01 ); + + Write( REG_DIOMAPPING2, ( Read( REG_DIOMAPPING2 ) & RF_DIOMAPPING2_DIO4_MASK & + RF_DIOMAPPING2_MAP_MASK ) ); + this->settings.FskPacketHandler.FifoThresh = Read( REG_FIFOTHRESH ) & 0x3F; + } + break; + case MODEM_LORA: + { + if( this->settings.LoRa.FreqHopOn == true ) + { + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + //RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone, DIO2=FhssChangeChannel + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK & RFLR_DIOMAPPING1_DIO2_MASK ) | RFLR_DIOMAPPING1_DIO0_01 | RFLR_DIOMAPPING1_DIO2_00 ); + } + else + { + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + //RFLR_IRQFLAGS_TXDONE | + RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL | + RFLR_IRQFLAGS_CADDETECTED ); + + // DIO0=TxDone + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO0_MASK ) | RFLR_DIOMAPPING1_DIO0_01 ); + } + } + break; + } + + this->settings.State = RF_TX_RUNNING; + txTimeoutTimer.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), timeout * 1e3 ); + SetOpMode( RF_OPMODE_TRANSMITTER ); +} + +void SX1272::StartCad( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + + } + break; + case MODEM_LORA: + { + Write( REG_LR_IRQFLAGSMASK, RFLR_IRQFLAGS_RXTIMEOUT | + RFLR_IRQFLAGS_RXDONE | + RFLR_IRQFLAGS_PAYLOADCRCERROR | + RFLR_IRQFLAGS_VALIDHEADER | + RFLR_IRQFLAGS_TXDONE | + //RFLR_IRQFLAGS_CADDONE | + RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL // | + //RFLR_IRQFLAGS_CADDETECTED + ); + + // DIO3=CADDone + Write( REG_DIOMAPPING1, ( Read( REG_DIOMAPPING1 ) & RFLR_DIOMAPPING1_DIO3_MASK ) | RFLR_DIOMAPPING1_DIO3_00 ); + + this->settings.State = RF_CAD; + SetOpMode( RFLR_OPMODE_CAD ); + } + break; + default: + break; + } +} + +void SX1272::SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ) +{ + uint32_t timeout = ( uint32_t )( time * 1e6 ); + + SetChannel( freq ); + + SetTxConfig( MODEM_FSK, power, 0, 0, 4800, 0, 5, false, false, 0, 0, 0, timeout ); + + Write( REG_PACKETCONFIG2, ( Read( REG_PACKETCONFIG2 ) & RF_PACKETCONFIG2_DATAMODE_MASK ) ); + // Disable radio interrupts + Write( REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_11 | RF_DIOMAPPING1_DIO1_11 ); + Write( REG_DIOMAPPING2, RF_DIOMAPPING2_DIO4_10 | RF_DIOMAPPING2_DIO5_10 ); + + this->settings.State = RF_TX_RUNNING; + txTimeoutTimer.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), timeout ); + SetOpMode( RF_OPMODE_TRANSMITTER ); +} + +int16_t SX1272::GetRssi( RadioModems_t modem ) +{ + int16_t rssi = 0; + + switch( modem ) + { + case MODEM_FSK: + rssi = -( Read( REG_RSSIVALUE ) >> 1 ); + break; + case MODEM_LORA: + rssi = RSSI_OFFSET + Read( REG_LR_RSSIVALUE ); + break; + default: + rssi = -1; + break; + } + return rssi; +} + +void SX1272::SetOpMode( uint8_t opMode ) +{ + if( opMode == RF_OPMODE_SLEEP ) + { + SetAntSwLowPower( true ); + } + else + { + SetAntSwLowPower( false ); + SetAntSw( opMode ); + } + Write( REG_OPMODE, ( Read( REG_OPMODE ) & RF_OPMODE_MASK ) | opMode ); +} + +void SX1272::SetModem( RadioModems_t modem ) +{ + if( ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_ON ) != 0 ) + { + this->settings.Modem = MODEM_LORA; + } + else + { + this->settings.Modem = MODEM_FSK; + } + + if( this->settings.Modem == modem ) + { + return; + } + + this->settings.Modem = modem; + switch( this->settings.Modem ) + { + default: + case MODEM_FSK: + Sleep( ); + Write( REG_OPMODE, ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_OFF ); + + Write( REG_DIOMAPPING1, 0x00 ); + Write( REG_DIOMAPPING2, 0x30 ); // DIO5=ModeReady + break; + case MODEM_LORA: + Sleep( ); + Write( REG_OPMODE, ( Read( REG_OPMODE ) & RFLR_OPMODE_LONGRANGEMODE_MASK ) | RFLR_OPMODE_LONGRANGEMODE_ON ); + + Write( REG_DIOMAPPING1, 0x00 ); + Write( REG_DIOMAPPING2, 0x00 ); + break; + } +} + +void SX1272::SetMaxPayloadLength( RadioModems_t modem, uint8_t max ) +{ + this->SetModem( modem ); + + switch( modem ) + { + case MODEM_FSK: + if( this->settings.Fsk.FixLen == false ) + { + this->Write( REG_PAYLOADLENGTH, max ); + } + break; + case MODEM_LORA: + this->Write( REG_LR_PAYLOADMAXLENGTH, max ); + break; + } +} + +void SX1272::SetPublicNetwork( bool enable ) +{ + SetModem( MODEM_LORA ); + this->settings.LoRa.PublicNetwork = enable; + if( enable == true ) + { + // Change LoRa modem SyncWord + Write( REG_LR_SYNCWORD, LORA_MAC_PUBLIC_SYNCWORD ); + } + else + { + // Change LoRa modem SyncWord + Write( REG_LR_SYNCWORD, LORA_MAC_PRIVATE_SYNCWORD ); + } +} + +void SX1272::OnTimeoutIrq( void ) +{ + switch( this->settings.State ) + { + case RF_RX_RUNNING: + if( this->settings.Modem == MODEM_FSK ) + { + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + + // Clear Irqs + Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | + RF_IRQFLAGS1_PREAMBLEDETECT | + RF_IRQFLAGS1_SYNCADDRESSMATCH ); + Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN ); + + if( this->settings.Fsk.RxContinuous == true ) + { + // Continuous mode restart Rx chain + Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); + rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), + this->settings.Fsk.RxSingleTimeout * 1e3 ); + } + else + { + this->settings.State = RF_IDLE; + rxTimeoutSyncWord.detach( ); + } + } + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxTimeout != NULL ) ) + { + this->RadioEvents->RxTimeout( ); + } + break; + case RF_TX_RUNNING: + // Tx timeout shouldn't happen. + // But it has been observed that when it happens it is a result of a corrupted SPI transfer + // it depends on the platform design. + // + // The workaround is to put the radio in a known state. Thus, we re-initialize it. + + // BEGIN WORKAROUND + + // Reset the radio + Reset( ); + + // Initialize radio default values + SetOpMode( RF_OPMODE_SLEEP ); + + RadioRegistersInit( ); + + SetModem( MODEM_FSK ); + + // Restore previous network type setting. + SetPublicNetwork( this->settings.LoRa.PublicNetwork ); + // END WORKAROUND + + this->settings.State = RF_IDLE; + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->TxTimeout != NULL ) ) + { + this->RadioEvents->TxTimeout( ); + } + break; + default: + break; + } +} + +void SX1272::OnDio0Irq( void ) +{ + volatile uint8_t irqFlags = 0; + + switch( this->settings.State ) + { + case RF_RX_RUNNING: + //TimerStop( &RxTimeoutTimer ); + // RxDone interrupt + switch( this->settings.Modem ) + { + case MODEM_FSK: + if( this->settings.Fsk.CrcOn == true ) + { + irqFlags = Read( REG_IRQFLAGS2 ); + if( ( irqFlags & RF_IRQFLAGS2_CRCOK ) != RF_IRQFLAGS2_CRCOK ) + { + // Clear Irqs + Write( REG_IRQFLAGS1, RF_IRQFLAGS1_RSSI | + RF_IRQFLAGS1_PREAMBLEDETECT | + RF_IRQFLAGS1_SYNCADDRESSMATCH ); + Write( REG_IRQFLAGS2, RF_IRQFLAGS2_FIFOOVERRUN ); + + rxTimeoutTimer.detach( ); + + if( this->settings.Fsk.RxContinuous == false ) + { + rxTimeoutSyncWord.detach( ); + this->settings.State = RF_IDLE; + } + else + { + // Continuous mode restart Rx chain + Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); + rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), + this->settings.Fsk.RxSingleTimeout * 1e3 ); + } + + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxError != NULL ) ) + { + this->RadioEvents->RxError( ); + } + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + break; + } + } + + // Read received packet size + if( ( this->settings.FskPacketHandler.Size == 0 ) && ( this->settings.FskPacketHandler.NbBytes == 0 ) ) + { + if( this->settings.Fsk.FixLen == false ) + { + ReadFifo( ( uint8_t* )&this->settings.FskPacketHandler.Size, 1 ); + } + else + { + this->settings.FskPacketHandler.Size = Read( REG_PAYLOADLENGTH ); + } + ReadFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + } + else + { + ReadFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + } + + rxTimeoutTimer.detach( ); + + if( this->settings.Fsk.RxContinuous == false ) + { + this->settings.State = RF_IDLE; + rxTimeoutSyncWord.detach( ); + } + else + { + // Continuous mode restart Rx chain + Write( REG_RXCONFIG, Read( REG_RXCONFIG ) | RF_RXCONFIG_RESTARTRXWITHOUTPLLLOCK ); + rxTimeoutSyncWord.attach_us( mbed::callback( this, &SX1272::OnTimeoutIrq ), + this->settings.Fsk.RxSingleTimeout * 1e3 ); + } + + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxDone != NULL ) ) + { + this->RadioEvents->RxDone( rxtxBuffer, this->settings.FskPacketHandler.Size, this->settings.FskPacketHandler.RssiValue, 0 ); + } + this->settings.FskPacketHandler.PreambleDetected = false; + this->settings.FskPacketHandler.SyncWordDetected = false; + this->settings.FskPacketHandler.NbBytes = 0; + this->settings.FskPacketHandler.Size = 0; + break; + case MODEM_LORA: + { + int8_t snr = 0; + + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXDONE ); + + irqFlags = Read( REG_LR_IRQFLAGS ); + if( ( irqFlags & RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK ) == RFLR_IRQFLAGS_PAYLOADCRCERROR ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_PAYLOADCRCERROR ); + + if( this->settings.LoRa.RxContinuous == false ) + { + this->settings.State = RF_IDLE; + } + rxTimeoutTimer.detach( ); + + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxError != NULL ) ) + { + this->RadioEvents->RxError( ); + } + break; + } + + this->settings.LoRaPacketHandler.SnrValue = Read( REG_LR_PKTSNRVALUE ); + if( this->settings.LoRaPacketHandler.SnrValue & 0x80 ) // The SNR sign bit is 1 + { + // Invert and divide by 4 + snr = ( ( ~this->settings.LoRaPacketHandler.SnrValue + 1 ) & 0xFF ) >> 2; + snr = -snr; + } + else + { + // Divide by 4 + snr = ( this->settings.LoRaPacketHandler.SnrValue & 0xFF ) >> 2; + } + + int16_t rssi = Read( REG_LR_PKTRSSIVALUE ); + if( snr < 0 ) + { + this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET + rssi + ( rssi >> 4 ) + + snr; + } + else + { + this->settings.LoRaPacketHandler.RssiValue = RSSI_OFFSET + rssi + ( rssi >> 4 ); + } + + this->settings.LoRaPacketHandler.Size = Read( REG_LR_RXNBBYTES ); + ReadFifo( rxtxBuffer, this->settings.LoRaPacketHandler.Size ); + + if( this->settings.LoRa.RxContinuous == false ) + { + this->settings.State = RF_IDLE; + } + rxTimeoutTimer.detach( ); + + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxDone != NULL ) ) + { + this->RadioEvents->RxDone( rxtxBuffer, this->settings.LoRaPacketHandler.Size, this->settings.LoRaPacketHandler.RssiValue, this->settings.LoRaPacketHandler.SnrValue ); + } + } + break; + default: + break; + } + break; + case RF_TX_RUNNING: + txTimeoutTimer.detach( ); + // TxDone interrupt + switch( this->settings.Modem ) + { + case MODEM_LORA: + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_TXDONE ); + // Intentional fall through + case MODEM_FSK: + default: + this->settings.State = RF_IDLE; + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->TxDone != NULL ) ) + { + this->RadioEvents->TxDone( ); + } + break; + } + break; + default: + break; + } +} + +void SX1272::OnDio1Irq( void ) +{ + switch( this->settings.State ) + { + case RF_RX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + // FifoLevel interrupt + // Read received packet size + if( ( this->settings.FskPacketHandler.Size == 0 ) && ( this->settings.FskPacketHandler.NbBytes == 0 ) ) + { + if( this->settings.Fsk.FixLen == false ) + { + ReadFifo( ( uint8_t* )&this->settings.FskPacketHandler.Size, 1 ); + } + else + { + this->settings.FskPacketHandler.Size = Read( REG_PAYLOADLENGTH ); + } + } + + if( ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ) > this->settings.FskPacketHandler.FifoThresh ) + { + ReadFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.FifoThresh ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.FifoThresh; + } + else + { + ReadFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + } + break; + case MODEM_LORA: + // Sync time out + rxTimeoutTimer.detach( ); + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_RXTIMEOUT ); + + this->settings.State = RF_IDLE; + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->RxTimeout != NULL ) ) + { + this->RadioEvents->RxTimeout( ); + } + break; + default: + break; + } + break; + case RF_TX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + // FifoEmpty interrupt + if( ( this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ) > this->settings.FskPacketHandler.ChunkSize ) + { + WriteFifo( ( rxtxBuffer + this->settings.FskPacketHandler.NbBytes ), this->settings.FskPacketHandler.ChunkSize ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.ChunkSize; + } + else + { + // Write the last chunk of data + WriteFifo( rxtxBuffer + this->settings.FskPacketHandler.NbBytes, this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes ); + this->settings.FskPacketHandler.NbBytes += this->settings.FskPacketHandler.Size - this->settings.FskPacketHandler.NbBytes; + } + break; + case MODEM_LORA: + break; + default: + break; + } + break; + default: + break; + } +} + +void SX1272::OnDio2Irq( void ) +{ + switch( this->settings.State ) + { + case RF_RX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + // Checks if DIO4 is connected. If it is not PreambleDtected is set to true. + if( this->dioIrq[4] == NULL ) + { + this->settings.FskPacketHandler.PreambleDetected = true; + } + + if( ( this->settings.FskPacketHandler.PreambleDetected == true ) && ( this->settings.FskPacketHandler.SyncWordDetected == false ) ) + { + rxTimeoutSyncWord.detach( ); + + this->settings.FskPacketHandler.SyncWordDetected = true; + + this->settings.FskPacketHandler.RssiValue = -( Read( REG_RSSIVALUE ) >> 1 ); + + this->settings.FskPacketHandler.AfcValue = ( int32_t )( double )( ( ( uint16_t )Read( REG_AFCMSB ) << 8 ) | + ( uint16_t )Read( REG_AFCLSB ) ) * + ( double )FREQ_STEP; + this->settings.FskPacketHandler.RxGain = ( Read( REG_LNA ) >> 5 ) & 0x07; + } + break; + case MODEM_LORA: + if( this->settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->FhssChangeChannel != NULL ) ) + { + this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } + break; + default: + break; + } + break; + case RF_TX_RUNNING: + switch( this->settings.Modem ) + { + case MODEM_FSK: + break; + case MODEM_LORA: + if( this->settings.LoRa.FreqHopOn == true ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL ); + + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->FhssChangeChannel != NULL ) ) + { + this->RadioEvents->FhssChangeChannel( ( Read( REG_LR_HOPCHANNEL ) & RFLR_HOPCHANNEL_CHANNEL_MASK ) ); + } + } + break; + default: + break; + } + break; + default: + break; + } +} + +void SX1272::OnDio3Irq( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + break; + case MODEM_LORA: + if( ( Read( REG_LR_IRQFLAGS ) & RFLR_IRQFLAGS_CADDETECTED ) == RFLR_IRQFLAGS_CADDETECTED ) + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDETECTED | RFLR_IRQFLAGS_CADDONE ); + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->CadDone != NULL ) ) + { + this->RadioEvents->CadDone( true ); + } + } + else + { + // Clear Irq + Write( REG_LR_IRQFLAGS, RFLR_IRQFLAGS_CADDONE ); + if( ( this->RadioEvents != NULL ) && ( this->RadioEvents->CadDone != NULL ) ) + { + this->RadioEvents->CadDone( false ); + } + } + break; + default: + break; + } +} + +void SX1272::OnDio4Irq( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + { + if( this->settings.FskPacketHandler.PreambleDetected == false ) + { + this->settings.FskPacketHandler.PreambleDetected = true; + } + } + break; + case MODEM_LORA: + break; + default: + break; + } +} + +void SX1272::OnDio5Irq( void ) +{ + switch( this->settings.Modem ) + { + case MODEM_FSK: + break; + case MODEM_LORA: + break; + default: + break; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/sx1272/sx1272.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,503 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: Actual implementation of a SX1272 radio, inherits Radio + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#ifndef __SX1272_H__ +#define __SX1272_H__ + +#include "radio.h" +#include "./registers/sx1272Regs-Fsk.h" +#include "./registers/sx1272Regs-LoRa.h" +#include "./typedefs/typedefs.h" + +/*! + * Radio wake-up time from sleep + */ +#define RADIO_WAKEUP_TIME 1 // [ms] + +/*! + * Sync word for Private LoRa networks + */ +#define LORA_MAC_PRIVATE_SYNCWORD 0x12 + +/*! + * Sync word for Public LoRa networks + */ +#define LORA_MAC_PUBLIC_SYNCWORD 0x34 + + +/*! + * SX1272 definitions + */ +#define XTAL_FREQ 32000000 +#define FREQ_STEP 61.03515625 + +#define RX_BUFFER_SIZE 256 + +/*! + * Constant values need to compute the RSSI value + */ +#define RSSI_OFFSET -139 + +/*! + * Actual implementation of a SX1272 radio, inherits Radio + */ +class SX1272 : public Radio +{ +protected: + /*! + * SPI Interface + */ + SPI spi; // mosi, miso, sclk + DigitalOut nss; + + /*! + * SX1272 Reset pin + */ + DigitalInOut reset; + + /*! + * SX1272 DIO pins + */ + InterruptIn dio0; + InterruptIn dio1; + InterruptIn dio2; + InterruptIn dio3; + InterruptIn dio4; + DigitalIn dio5; + + bool isRadioActive; + + uint8_t boardConnected; //1 = SX1272MB1DCS; 0 = SX1272MB1DAS + + uint8_t *rxtxBuffer; + + /*! + * Hardware DIO IRQ functions + */ + DioIrqHandler *dioIrq; + + /*! + * Tx and Rx timers + */ + Timeout txTimeoutTimer; + Timeout rxTimeoutTimer; + Timeout rxTimeoutSyncWord; + + RadioSettings_t settings; + + static const FskBandwidth_t FskBandwidths[]; +protected: + + /*! + * Performs the Rx chain calibration for LF and HF bands + * \remark Must be called just after the reset so all registers are at their + * default values + */ + void RxChainCalibration( void ); + +public: + SX1272( RadioEvents_t *events, + PinName mosi, PinName miso, PinName sclk, PinName nss, PinName reset, + PinName dio0, PinName dio1, PinName dio2, PinName dio3, PinName dio4, PinName dio5 ); + SX1272( RadioEvents_t *events ); + virtual ~SX1272( ); + + //------------------------------------------------------------------------- + // Redefined Radio functions + //------------------------------------------------------------------------- + /*! + * @brief Initializes the radio + * + * @param [IN] events Structure containing the driver callback functions + */ + virtual void Init( RadioEvents_t *events ); + /*! + * Return current radio status + * + * @param status Radio status. [RF_IDLE, RX_RUNNING, TX_RUNNING] + */ + virtual RadioState GetStatus( void ); + /*! + * @brief Configures the SX1272 with the given modem + * + * @param [IN] modem Modem to be used [0: FSK, 1: LoRa] + */ + virtual void SetModem( RadioModems_t modem ); + /*! + * @brief Sets the channel frequency + * + * @param [IN] freq Channel RF frequency + */ + virtual void SetChannel( uint32_t freq ); + /*! + * @brief Sets the channels configuration + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] freq Channel RF frequency + * @param [IN] rssiThresh RSSI threshold + * + * @retval isFree [true: Channel is free, false: Channel is not free] + */ + virtual bool IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ); + /*! + * @brief Generates a 32 bits random value based on the RSSI readings + * + * \remark This function sets the radio in LoRa modem mode and disables + * all interrupts. + * After calling this function either Radio.SetRxConfig or + * Radio.SetTxConfig functions must be called. + * + * @retval randomValue 32 bits random value + */ + virtual uint32_t Random( void ); + /*! + * @brief Sets the reception parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] bandwidth Sets the bandwidth + * FSK : >= 2600 and <= 250000 Hz + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] bandwidthAfc Sets the AFC Bandwidth ( FSK only ) + * FSK : >= 2600 and <= 250000 Hz + * LoRa: N/A ( set to 0 ) + * @param [IN] preambleLen Sets the Preamble length ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: Length in symbols ( the hardware adds 4 more symbols ) + * @param [IN] symbTimeout Sets the RxSingle timeout value + * FSK : timeout number of bytes + * LoRa: timeout in symbols + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] payloadLen Sets payload length when fixed lenght is used + * @param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] rxContinuous Sets the reception in continuous mode + * [false: single mode, true: continuous mode] + */ + virtual void SetRxConfig ( RadioModems_t modem, uint32_t bandwidth, + uint32_t datarate, uint8_t coderate, + uint32_t bandwidthAfc, uint16_t preambleLen, + uint16_t symbTimeout, bool fixLen, + uint8_t payloadLen, + bool crcOn, bool freqHopOn, uint8_t hopPeriod, + bool iqInverted, bool rxContinuous ); + /*! + * @brief Sets the transmission parameters + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] power Sets the output power [dBm] + * @param [IN] fdev Sets the frequency deviation ( FSK only ) + * FSK : [Hz] + * LoRa: 0 + * @param [IN] bandwidth Sets the bandwidth ( LoRa only ) + * FSK : 0 + * LoRa: [0: 125 kHz, 1: 250 kHz, + * 2: 500 kHz, 3: Reserved] + * @param [IN] datarate Sets the Datarate + * FSK : 600..300000 bits/s + * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, + * 10: 1024, 11: 2048, 12: 4096 chips] + * @param [IN] coderate Sets the coding rate ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] + * @param [IN] preambleLen Sets the preamble length + * @param [IN] fixLen Fixed length packets [0: variable, 1: fixed] + * @param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] + * @param [IN] freqHopOn Enables disables the intra-packet frequency hopping [0: OFF, 1: ON] (LoRa only) + * @param [IN] hopPeriod Number of symbols bewteen each hop (LoRa only) + * @param [IN] iqInverted Inverts IQ signals ( LoRa only ) + * FSK : N/A ( set to 0 ) + * LoRa: [0: not inverted, 1: inverted] + * @param [IN] timeout Transmission timeout [ms] + */ + virtual void SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, + uint32_t bandwidth, uint32_t datarate, + uint8_t coderate, uint16_t preambleLen, + bool fixLen, bool crcOn, bool freqHopOn, + uint8_t hopPeriod, bool iqInverted, uint32_t timeout ); + /*! + * @brief Checks if the given RF frequency is supported by the hardware + * + * @param [IN] frequency RF frequency to be checked + * @retval isSupported [true: supported, false: unsupported] + */ + virtual bool CheckRfFrequency( uint32_t frequency ) = 0; + /*! + * @brief Computes the packet time on air for the given payload + * + * \Remark Can only be called once SetRxConfig or SetTxConfig have been called + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] pktLen Packet payload length + * + * @retval airTime Computed airTime for the given packet payload length + */ + virtual uint32_t TimeOnAir ( RadioModems_t modem, uint8_t pktLen ); + /*! + * @brief Sends the buffer of size. Prepares the packet to be sent and sets + * the radio in transmission + * + * @param [IN]: buffer Buffer pointer + * @param [IN]: size Buffer size + */ + virtual void Send( uint8_t *buffer, uint8_t size ); + /*! + * @brief Sets the radio in sleep mode + */ + virtual void Sleep( void ); + /*! + * @brief Sets the radio in standby mode + */ + virtual void Standby( void ); + /*! + * @brief Sets the radio in CAD mode + */ + virtual void StartCad( void ); + /*! + * @brief Sets the radio in reception mode for the given time + * @param [IN] timeout Reception timeout [ms] + * [0: continuous, others timeout] + */ + virtual void Rx( uint32_t timeout ); + /*! + * @brief Sets the radio in transmission mode for the given time + * @param [IN] timeout Transmission timeout [ms] + * [0: continuous, others timeout] + */ + virtual void Tx( uint32_t timeout ); + /*! + * @brief Sets the radio in continuous wave transmission mode + * + * @param [IN]: freq Channel RF frequency + * @param [IN]: power Sets the output power [dBm] + * @param [IN]: time Transmission mode timeout [s] + */ + virtual void SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ); + /*! + * @brief Reads the current RSSI value + * + * @retval rssiValue Current RSSI value in [dBm] + */ + virtual int16_t GetRssi ( RadioModems_t modem ); + /*! + * @brief Writes the radio register at the specified address + * + * @param [IN]: addr Register address + * @param [IN]: data New register value + */ + virtual void Write ( uint8_t addr, uint8_t data ) = 0; + /*! + * @brief Reads the radio register at the specified address + * + * @param [IN]: addr Register address + * @retval data Register value + */ + virtual uint8_t Read ( uint8_t addr ) = 0; + /*! + * @brief Writes multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [IN] buffer Buffer containing the new register's values + * @param [IN] size Number of registers to be written + */ + virtual void Write( uint8_t addr, uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Reads multiple radio registers starting at address + * + * @param [IN] addr First Radio register address + * @param [OUT] buffer Buffer where to copy the registers data + * @param [IN] size Number of registers to be read + */ + virtual void Read ( uint8_t addr, uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Writes the buffer contents to the SX1272 FIFO + * + * @param [IN] buffer Buffer containing data to be put on the FIFO. + * @param [IN] size Number of bytes to be written to the FIFO + */ + virtual void WriteFifo( uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Reads the contents of the SX1272 FIFO + * + * @param [OUT] buffer Buffer where to copy the FIFO read data. + * @param [IN] size Number of bytes to be read from the FIFO + */ + virtual void ReadFifo( uint8_t *buffer, uint8_t size ) = 0; + /*! + * @brief Resets the SX1272 + */ + virtual void Reset( void ) = 0; + + /*! + * @brief Sets the maximum payload length. + * + * @param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] + * @param [IN] max Maximum payload length in bytes + */ + virtual void SetMaxPayloadLength( RadioModems_t modem, uint8_t max ); + + /*! + * \brief Sets the network to public or private. Updates the sync byte. + * + * \remark Applies to LoRa modem only + * + * \param [IN] enable if true, it enables a public network + */ + virtual void SetPublicNetwork( bool enable ); + + //------------------------------------------------------------------------- + // Board relative functions + //------------------------------------------------------------------------- + +protected: + /*! + * @brief Initializes the radio I/Os pins interface + */ + virtual void IoInit( void ) = 0; + + /*! + * @brief Initializes the radio registers + */ + virtual void RadioRegistersInit( ) = 0; + + /*! + * @brief Initializes the radio SPI + */ + virtual void SpiInit( void ) = 0; + + /*! + * @brief Initializes DIO IRQ handlers + * + * @param [IN] irqHandlers Array containing the IRQ callback functions + */ + virtual void IoIrqInit( DioIrqHandler *irqHandlers ) = 0; + + /*! + * @brief De-initializes the radio I/Os pins interface. + * + * \remark Useful when going in MCU lowpower modes + */ + virtual void IoDeInit( void ) = 0; + + /*! + * @brief Sets the radio output power. + * + * @param [IN] power Sets the RF output power + */ + virtual void SetRfTxPower( int8_t power ) = 0; + + /*! + * @brief Gets the board PA selection configuration + * + * @param [IN] channel Channel frequency in Hz + * @retval PaSelect RegPaConfig PaSelect value + */ + virtual uint8_t GetPaSelect( uint32_t channel ) = 0; + + /*! + * @brief Set the RF Switch I/Os pins in Low Power mode + * + * @param [IN] status enable or disable + */ + virtual void SetAntSwLowPower( bool status ) = 0; + + /*! + * @brief Initializes the RF Switch I/Os pins interface + */ + virtual void AntSwInit( void ) = 0; + + /*! + * @brief De-initializes the RF Switch I/Os pins interface + * + * \remark Needed to decrease the power consumption in MCU lowpower modes + */ + virtual void AntSwDeInit( void ) = 0; + + /*! + * @brief Controls the antenna switch if necessary. + * + * \remark see errata note + * + * @param [IN] opMode Current radio operating mode + */ + virtual void SetAntSw( uint8_t opMode ) = 0; +protected: + + /*! + * @brief Sets the SX1272 operating mode + * + * @param [IN] opMode New operating mode + */ + virtual void SetOpMode( uint8_t opMode ); + + /* + * SX1272 DIO IRQ callback functions prototype + */ + + /*! + * @brief DIO 0 IRQ callback + */ + virtual void OnDio0Irq( void ); + + /*! + * @brief DIO 1 IRQ callback + */ + virtual void OnDio1Irq( void ); + + /*! + * @brief DIO 2 IRQ callback + */ + virtual void OnDio2Irq( void ); + + /*! + * @brief DIO 3 IRQ callback + */ + virtual void OnDio3Irq( void ); + + /*! + * @brief DIO 4 IRQ callback + */ + virtual void OnDio4Irq( void ); + + /*! + * @brief DIO 5 IRQ callback + */ + virtual void OnDio5Irq( void ); + + /*! + * @brief Tx & Rx timeout timer callback + */ + virtual void OnTimeoutIrq( void ); + + /*! + * Returns the known FSK bandwidth registers value + * + * \param [IN] bandwidth Bandwidth value in Hz + * \retval regValue Bandwidth register value. + */ + static uint8_t GetFskBandwidthRegValue( uint32_t bandwidth ); +}; + +#endif // __SX1272_H__
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SX1272Lib/typedefs/typedefs.h Thu May 17 20:37:41 2018 +0000 @@ -0,0 +1,53 @@ +/* + / _____) _ | | +( (____ _____ ____ _| |_ _____ ____| |__ + \____ \| ___ | (_ _) ___ |/ ___) _ \ + _____) ) ____| | | || |_| ____( (___| | | | +(______/|_____)_|_|_| \__)_____)\____)_| |_| + (C) 2015 Semtech + +Description: - + +License: Revised BSD License, see LICENSE.TXT file include in the project + +Maintainers: Miguel Luis, Gregory Cristian and Nicolas Huguenin +*/ +#ifndef __TYPEDEFS_H__ +#define __TYPEDEFS_H__ + +#include "mbed.h" +#include "./enums/enums.h" + +class SX1272; +class SX1272MB2xAS; +/*! + * Hardware IO IRQ callback function definition + */ +typedef void ( SX1272::*DioIrqHandler )( void ); + +/*! + * triggers definition + */ +typedef void ( SX1272::*Trigger )( void ); +typedef void ( SX1272MB2xAS::*TriggerMB2xAS )( void ); + +/*! + * FSK bandwidth definition + */ +typedef struct +{ + uint32_t bandwidth; + uint8_t RegValue; +}FskBandwidth_t; + +/*! + * Radio registers definition + */ +typedef struct +{ + ModemType Modem; + uint8_t Addr; + uint8_t Value; +}RadioRegisters_t; + +#endif //__TYPEDEFS_H__
--- a/main.cpp Mon Apr 24 09:29:13 2017 +0000 +++ b/main.cpp Thu May 17 20:37:41 2018 +0000 @@ -1,52 +1,20 @@ #include "mbed.h" #include "main.h" +#include "string.h" #include "sx1272-hal.h" -#include "debug.h" +#include "DS3231.h" +#include "LSM303DLHC.h" +#include "SDFileSystem.h" +// #include "EncoderCounter.h" + +/* + * Technion - Formula Car Telemetry + * Part 1: Reading data signals from the car sensors and broadcasting them + */ /* Set this flag to '1' to display debug messages on the console */ #define DEBUG_MESSAGE 1 -/* Set this flag to '1' to use the LoRa modulation or to '0' to use FSK modulation */ -#define USE_MODEM_LORA 1 -#define USE_MODEM_FSK !USE_MODEM_LORA - -#define RF_FREQUENCY 868000000 // Hz -#define TX_OUTPUT_POWER 14 // 14 dBm - -#if USE_MODEM_LORA == 1 - - #define LORA_BANDWIDTH 2 // [0: 125 kHz, - // 1: 250 kHz, - // 2: 500 kHz, - // 3: Reserved] - #define LORA_SPREADING_FACTOR 7 // [SF7..SF12] - #define LORA_CODINGRATE 1 // [1: 4/5, - // 2: 4/6, - // 3: 4/7, - // 4: 4/8] - #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx - #define LORA_SYMBOL_TIMEOUT 5 // Symbols - #define LORA_FIX_LENGTH_PAYLOAD_ON false - #define LORA_FHSS_ENABLED false - #define LORA_NB_SYMB_HOP 4 - #define LORA_IQ_INVERSION_ON false - #define LORA_CRC_ENABLED true - -#elif USE_MODEM_FSK == 1 - - #define FSK_FDEV 25000 // Hz - #define FSK_DATARATE 19200 // bps - #define FSK_BANDWIDTH 50000 // Hz - #define FSK_AFC_BANDWIDTH 83333 // Hz - #define FSK_PREAMBLE_LENGTH 5 // Same for Tx and Rx - #define FSK_FIX_LENGTH_PAYLOAD_ON false - #define FSK_CRC_ENABLED true - -#else - #error "Please define a modem in the compiler options." -#endif - -#define RX_TIMEOUT_VALUE 3500 // in ms #define BUFFER_SIZE 32 // Define the payload size here #if( defined ( TARGET_KL25Z ) || defined ( TARGET_LPC11U6X ) ) @@ -55,292 +23,52 @@ DigitalOut led( LED1 ); #endif -/* - * Global variables declarations - */ -typedef enum -{ - LOWPOWER = 0, - IDLE, - - RX, - RX_TIMEOUT, - RX_ERROR, - - TX, - TX_TIMEOUT, - - CAD, - CAD_DONE -}AppStates_t; - -volatile AppStates_t State = LOWPOWER; - -/*! - * Radio events function pointer - */ -static RadioEvents_t RadioEvents; - -/* - * Global variables declarations - */ -SX1272MB2xAS Radio( NULL ); - -const uint8_t PingMsg[] = "PING"; -const uint8_t PongMsg[] = "PONG"; - -uint16_t BufferSize = BUFFER_SIZE; -uint8_t Buffer[BUFFER_SIZE]; - -int16_t RssiValue = 0.0; -int8_t SnrValue = 0.0; - int main( void ) { - uint8_t i; - bool isMaster = true; - - debug( "\n\n\r SX1272 Ping Pong Demo Application \n\n\r" ); - - // Initialize Radio driver - RadioEvents.TxDone = OnTxDone; - RadioEvents.RxDone = OnRxDone; - RadioEvents.RxError = OnRxError; - RadioEvents.TxTimeout = OnTxTimeout; - RadioEvents.RxTimeout = OnRxTimeout; - Radio.Init( &RadioEvents ); - - // verify the connection with the board - while( Radio.Read( REG_VERSION ) == 0x00 ) - { - debug( "Radio could not be detected!\n\r", NULL ); - wait( 1 ); +// ENCODER enc(1); +// int x = enc.XAxisGetCount(); + AnalogIn sus_rf(PA_0); + AnalogIn sus_rr(PA_1); + AnalogIn sus_lf(PA_4); // check if connected + AnalogIn sus_lr(PB_0); + AnalogIn wheel_ang(PC_1); + AnalogIn front_brake(PC_0); + AnalogIn rear_brake(PC_3); // check if connected + DS3231 TC(PB_7,PB_6); + + //PinName mosi, PinName miso, PinName sclk, PinName cs + SDFileSystem sd(PB_15, PB_14, PB_13, PB_12, "sd"); + sd.mount(); + + FILE *fp = fopen("/sd/formola_run.csv", "w"); + + LSM303DLHC lsm303(PB_11, PB_10); + + // Real Time Clock + int year = 0, month = 0, dayOfWeek = 0, date = 0, hours = 0, min = 0, sec = 0; + TC.readDateTime(&dayOfWeek, &date, &month, &year, &hours, &min, &sec); + + BufferedSerial* ser = new BufferedSerial(USBTX,USBRX); + ser->baud(115200*2); + ser->format(8); + + fprintf(fp, "dayOfWeek: %d,date %d,month: %d,year: %d,hours: %d,minutes: %d,sec: %d\r\n", dayOfWeek,date,month,year,hours,min,sec); + ser->printf("dayOfWeek: %d,date %d,month: %d,year: %d,hours: %d,minutes: %d,sec: %d\r\n", dayOfWeek,date,month,year,hours,min,sec); + + fprintf(fp, "sus_rf,sus_rr,sus_lf,sus_lr,wheel_ang,front_brake,accx,accy \r\n"); + ser->printf("sus_rf,sus_rr,sus_lf,sus_lr,wheel_ang,front_brake,accx,accy \r\n"); + + + + while(1){ + float accelReading[3] = {0.0, 0.0, 0.0}; + lsm303.GetAcc(accelReading); + + ser->printf("%f,%f,%f,%f,%f,%f,%f,%f\n", sus_rf.read(), sus_rr.read(), + sus_lf.read(), sus_lr.read(), wheel_ang.read(), front_brake.read(), + rear_brake.read(), accelReading[0], accelReading[1]); + + wait(1); } - - debug_if( ( DEBUG_MESSAGE & ( Radio.DetectBoardType( ) == SX1272MB2XAS ) ), "\n\r > Board Type: SX1272MB2xAS < \n\r" ); - - Radio.SetChannel( RF_FREQUENCY ); - -#if USE_MODEM_LORA == 1 - - debug_if( LORA_FHSS_ENABLED, "\n\n\r > LORA FHSS Mode < \n\n\r" ); - debug_if( !LORA_FHSS_ENABLED, "\n\n\r > LORA Mode < \n\n\r" ); - - Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH, - LORA_SPREADING_FACTOR, LORA_CODINGRATE, - LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON, - LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, - LORA_IQ_INVERSION_ON, 2000 ); - - Radio.SetRxConfig( MODEM_LORA, LORA_BANDWIDTH, LORA_SPREADING_FACTOR, - LORA_CODINGRATE, 0, LORA_PREAMBLE_LENGTH, - LORA_SYMBOL_TIMEOUT, LORA_FIX_LENGTH_PAYLOAD_ON, 0, - LORA_CRC_ENABLED, LORA_FHSS_ENABLED, LORA_NB_SYMB_HOP, - LORA_IQ_INVERSION_ON, true ); - -#elif USE_MODEM_FSK == 1 - - debug("\n\n\r > FSK Mode < \n\n\r" ); - Radio.SetTxConfig( MODEM_FSK, TX_OUTPUT_POWER, FSK_FDEV, 0, - FSK_DATARATE, 0, - FSK_PREAMBLE_LENGTH, FSK_FIX_LENGTH_PAYLOAD_ON, - FSK_CRC_ENABLED, 0, 0, 0, 2000 ); - - Radio.SetRxConfig( MODEM_FSK, FSK_BANDWIDTH, FSK_DATARATE, - 0, FSK_AFC_BANDWIDTH, FSK_PREAMBLE_LENGTH, - 0, FSK_FIX_LENGTH_PAYLOAD_ON, 0, FSK_CRC_ENABLED, - 0, 0, false, true ); - -#else - -#error "Please define a modem in the compiler options." - -#endif - - debug_if( DEBUG_MESSAGE, "Starting Ping-Pong loop\r\n" ); - - led = 0; - - Radio.Rx( RX_TIMEOUT_VALUE ); - - while( 1 ) - { - switch( State ) - { - case RX: - if( isMaster == true ) - { - if( BufferSize > 0 ) - { - if( strncmp( ( const char* )Buffer, ( const char* )PongMsg, 4 ) == 0 ) - { - led = !led; - debug( "...Pong\r\n" ); - // Send the next PING frame - strcpy( ( char* )Buffer, ( char* )PingMsg ); - // We fill the buffer with numbers for the payload - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) - { // A master already exists then become a slave - debug( "...Ping\r\n" ); - led = !led; - isMaster = false; - // Send the next PONG frame - strcpy( ( char* )Buffer, ( char* )PongMsg ); - // We fill the buffer with numbers for the payload - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else // valid reception but neither a PING or a PONG message - { // Set device as master ans start again - isMaster = true; - Radio.Rx( RX_TIMEOUT_VALUE ); - } - } - } - else - { - if( BufferSize > 0 ) - { - if( strncmp( ( const char* )Buffer, ( const char* )PingMsg, 4 ) == 0 ) - { - led = !led; - debug( "...Ping\r\n" ); - // Send the reply to the PING string - strcpy( ( char* )Buffer, ( char* )PongMsg ); - // We fill the buffer with numbers for the payload - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else // valid reception but not a PING as expected - { // Set device as master and start again - isMaster = true; - Radio.Rx( RX_TIMEOUT_VALUE ); - } - } - } - State = LOWPOWER; - break; - case TX: - led = !led; - if( isMaster == true ) - { - debug( "Ping...\r\n" ); - } - else - { - debug( "Pong...\r\n" ); - } - Radio.Rx( RX_TIMEOUT_VALUE ); - State = LOWPOWER; - break; - case RX_TIMEOUT: - if( isMaster == true ) - { - // Send the next PING frame - strcpy( ( char* )Buffer, ( char* )PingMsg ); - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else - { - Radio.Rx( RX_TIMEOUT_VALUE ); - } - State = LOWPOWER; - break; - case RX_ERROR: - // We have received a Packet with a CRC error, send reply as if packet was correct - if( isMaster == true ) - { - // Send the next PING frame - strcpy( ( char* )Buffer, ( char* )PingMsg ); - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - else - { - // Send the next PONG frame - strcpy( ( char* )Buffer, ( char* )PongMsg ); - for( i = 4; i < BufferSize; i++ ) - { - Buffer[i] = i - 4; - } - wait_ms( 10 ); - Radio.Send( Buffer, BufferSize ); - } - State = LOWPOWER; - break; - case TX_TIMEOUT: - Radio.Rx( RX_TIMEOUT_VALUE ); - State = LOWPOWER; - break; - case LOWPOWER: - break; - default: - State = LOWPOWER; - break; - } - } + } - -void OnTxDone( void ) -{ - Radio.Sleep( ); - State = TX; - debug_if( DEBUG_MESSAGE, "> OnTxDone\n\r" ); -} - -void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ) -{ - Radio.Sleep( ); - BufferSize = size; - memcpy( Buffer, payload, BufferSize ); - RssiValue = rssi; - SnrValue = snr; - State = RX; - debug_if( DEBUG_MESSAGE, "> OnRxDone\n\r" ); -} - -void OnTxTimeout( void ) -{ - Radio.Sleep( ); - State = TX_TIMEOUT; - debug_if( DEBUG_MESSAGE, "> OnTxTimeout\n\r" ); -} - -void OnRxTimeout( void ) -{ - Radio.Sleep( ); - Buffer[BufferSize] = 0; - State = RX_TIMEOUT; - debug_if( DEBUG_MESSAGE, "> OnRxTimeout\n\r" ); -} - -void OnRxError( void ) -{ - Radio.Sleep( ); - State = RX_ERROR; - debug_if( DEBUG_MESSAGE, "> OnRxError\n\r" ); -}
--- a/main.h Mon Apr 24 09:29:13 2017 +0000 +++ b/main.h Thu May 17 20:37:41 2018 +0000 @@ -1,56 +1,6 @@ -/* - / _____) _ | | -( (____ _____ ____ _| |_ _____ ____| |__ - \____ \| ___ | (_ _) ___ |/ ___) _ \ - _____) ) ____| | | || |_| ____( (___| | | | -(______/|_____)_|_|_| \__)_____)\____)_| |_| - ( C )2014 Semtech -Description: Contains the callbacks for the IRQs and any application related details - -License: Revised BSD License, see LICENSE.TXT file include in the project - -Maintainer: Miguel Luis and Gregory Cristian -*/ #ifndef __MAIN_H__ #define __MAIN_H__ - -/* - * Callback functions prototypes - */ -/*! - * @brief Function to be executed on Radio Tx Done event - */ -void OnTxDone( void ); - -/*! - * @brief Function to be executed on Radio Rx Done event - */ -void OnRxDone( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); - -/*! - * @brief Function executed on Radio Tx Timeout event - */ -void OnTxTimeout( void ); - -/*! - * @brief Function executed on Radio Rx Timeout event - */ -void OnRxTimeout( void ); - -/*! - * @brief Function executed on Radio Rx Error event - */ -void OnRxError( void ); - -/*! - * @brief Function executed on Radio Fhss Change Channel event - */ -void OnFhssChangeChannel( uint8_t channelIndex ); - -/*! - * @brief Function executed on CAD Done event - */ -void OnCadDone( void ); - +#include "mbed.h" +#include "BufferedSerial.h" #endif // __MAIN_H__