diff --git a/CHANGELOG.md b/CHANGELOG.md index 786d9e8..e185cf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [v1.3](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.3) - 09 Nov 2023 + +### Added + +* Implement `RF_API_start_continuous_wave()` function for **type approval addon**. +* Add **RF frequency parameter check** in `RF_API_init()` function since it is not performed by ST driver. + +### Fixed + +* Fix **TX output power formula** in ST driver (patch file update). +* Do not close radio driver in `RF_API_error()` function. +* Add **missing pointer symbol** on HW API callback syntax. + +### Removed + +* Remove `doc` folder since images are now hosted on the GitHub wiki. + +### Known limitations + +* **LBT** not implemented. +* **External radio front-end** not supported. +* **Modulated CW** not supported for type approval addon. + ## [v1.2](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.2) - 10 Aug 2023 ### Changed diff --git a/README.md b/README.md index d2158f3..ccb760b 100644 --- a/README.md +++ b/README.md @@ -4,127 +4,208 @@ This **S2LP RF API** is a low level implementation example of the [Sigfox EP library](https://github.com/sigfox-tech-radio/sigfox-ep-lib), showing the `manuf/rf_api.c` file implementation for the [S2LP](https://www.st.com/en/wireless-connectivity/s2-lp.html) transceiver from ST-Microelectronics. -The table below shows the version compatibility with the SIGFOX_EP_LIB version. +> [!WARNING] +> The resulting radio performances of your device strongly depends on your **hardware design** (schematic, PCB routing, crystal oscillator placement, good RF practices, etc...). **Sigfox certification remains mandatory** whatever the software embedded in your device (including the Sigfox End-Point library and its implementation examples). -| **S2LP_RF_API** | **SIGFOX_EP_LIB** | -|:---------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------:| -| [v1.2](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.2) | >= [v3.2](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.2) | -| [v1.1](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.1) | >= [v3.2](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.2) | -| [v1.0](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.0) | >= [v3.2](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.2) | +The table below shows the versions compatibility between this radio example and the Sigfox End-Point library. -**Note:** the resulting radio performances of your device strongly depends on your hardware design (schematic, PCB routing, crystal oscillator placement, good RF practices, etc...). **Sigfox certification remains mandatory** whatever the software embedded in your device (including the Sigfox End-Point library and its implementation examples). +| **S2LP_RF_API** | **EP_LIB** | +|:---:|:---:| +| [v1.3](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.3) | >= [v3.4](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.4) | +| [v1.2](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.2) | [v3.2](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.2) to [v3.3](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.3) | +| [v1.1](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.1) | [v3.2](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.2) to [v3.3](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.3) | +| [v1.0](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases/tag/v1.0) | [v3.2](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.2) to [v3.3](https://github.com/sigfox-tech-radio/sigfox-ep-lib/releases/tag/v3.3) | ## Architecture

- +

-## External S2LP library +## Compilation flags for optimization -The **S2LP RF API** is based on the official [S2LP library](https://github.com/STMicroelectronics/x-cube-sfxs2lp1/tree/main/Drivers/BSP/Components/S2LP/S2LP_Library) from ST-Microelectronics. This library exposes a functional interface to configure the chip registers, which is used to perform the Sigfox uplink modulation and optional downlink reception. +This radio example inherits all the [Sigfox End-Point library flags](https://github.com/sigfox-tech-radio/sigfox-ep-lib/wiki/compilation-flags-for-optimization) and can be optimized accordingly. -## Hardware +The `LOW_LEVEL_OPEN_CLOSE` flag must be enabled to use this example. -The driver relies on **low level functions** (called board drivers) which need to be implemented to run on your specific hardware. There are divided in 2 groups: +## How to add S2LP RF API example to your project -* **MCU_Interface_template** : low level functions of the S2LP library from ST (registers access through SPI and shutdown pin management). -* **S2LP_HW_API** : additional hardware-dependent functions required to get a generic RF API implementation of the S2LP. +### Dependencies -These drivers are located in the `src/board` folder. +The **S2LP RF API** is based on the [official S2LP driver](https://github.com/STMicroelectronics/x-cube-sfxs2lp1/tree/main/Drivers/BSP/Components/S2LP/S2LP_Library) from ST-Microelectronics. This driver exposes a functional interface to configure the chip registers, which is used to perform the Sigfox uplink modulation and optional downlink reception. It relies on **low level functions** (called board drivers) which need to be implemented to run on your specific hardware. There are divided in 2 groups: -## Code optimization +* **MCU_Interface_template** : low level functions of the S2LP driver from ST (registers access through SPI and shutdown pin management). +* **S2LP_HW_API** : additional hardware dependent functions required to get a generic RF API implementation of the S2LP. -The driver inherits all the [Sigfox EP library](https://github.com/sigfox-tech-radio/sigfox-ep-lib) flags and can be optimized accordingly. +The templates are located in the `src/board` folder. -## Getting Started +### Submodule -### Cloning the repository +The best way to embed the S2LP RF API example into your project is to use a [Git submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules), in a similar way to the library. The radio driver will be seen as a sub-repository with independant history. It will be much easier to **upgrade the radio driver** or to **switch between versions** when necessary, by using the common `git pull` and `git checkout` commands within the `sigfox-ep-rf-api-st-s2lp` folder. + +In order to keep the repository clean, you will need to **exclude** the `src/board` folder from build (where the board templates are defined) and implement the functions in another location of your project. + +To add the S2LP RF API submodule, go to your project location and run the following commands: ```bash -$ git clone https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp.git +mkdir lib +cd lib/ +git submodule add https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp.git ``` -### Usage +This will clone the S2LP RF API repository. At project level, you can commit the submodule creation with the following commands: + +```bash +git commit --message "Add Sigfox S2LP RF API submodule." +git push +``` -This code can be used in 3 different ways: - * The [original source code](#original-source-code) to use the raw sources files - * The [precompiled source code](#precompiled-source-code) to remove all unused source code and have more readability. - * The [static-library](#static-library) to generate a compiled library. +With the submodule, you can easily: -### Original source code +* Update the radio driver to the **latest version**: -Sources files are available in the `inc` and `src` folders and must be copied directly in your embedded project. +```bash +cd lib/sigfox-ep-rf-api-st-s2lp/ +git pull +git checkout master +``` -### Precompiled source code +* Use a **specific release**: -#### Dependency +```bash +cd lib/sigfox-ep-rf-api-st-s2lp/ +git pull +git checkout +``` + +### Raw source code + +You can [download](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases) or clone any release of the S2LP RF API example and copy all files into your project. + +```bash +git clone https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp.git +``` -Before building process install **unifdef** and **cmake**. The unifdef tool is used to remove dead code and cmake to build. +### Precompiled source code -#### Building process +You can [download](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases) or clone any release of the S2LP RF API example and copy all files into your project. If you do not plan to change your compilation flags in the future, you can perform a **precompilation step** before copying the file in your project. The precompilation will **remove all preprocessor directives** according to your flags selection, in order to produce a more **readable code**. Then you can copy the new files into your project. -If you want to **precompile** the sources files for a given flags selection, you need to use the **cmake** commands: +```bash +git clone https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp.git +``` -Create a build folder: +To perform the precompilation, you have to install `cmake` and `unifdef` tools, and run the following commands: ```bash -$ cd sigfox-ep-rf-api-st-s2lp -$ mkdir build -$ cd build +cd sigfox-ep-rf-api-st-s2lp/ +mkdir build +cd build/ ``` -* Precompiling by reading the `inc/sigfox_ep_flags.h` file: +* Precompiling by reading the `sigfox_ep_flags.h` file: ```bash -$ cmake -DSIGFOX_EP_LIB_DIR= \ - -DUSE_SIGFOX_EP_FLAGS_H=ON .. -$ make precompil +cmake -DSIGFOX_EP_LIB_DIR= \ + -DUSE_SIGFOX_EP_FLAGS_H=ON .. +make precompil_s2lp_rf_api ``` + * Precompiling by entering the flags selection on command line: ```bash -$ cmake -DSIGFOX_EP_LIB_DIR= \ - -DUSE_SIGFOX_EP_FLAGS_H=OFF \ - -DRC1=ON \ - -DRC2=ON \ - -DRC3C=ON \ - -DRC3D=ON \ - -DRC4=ON \ - -DRC5=ON \ - -DRC6=ON \ - -DRC7=ON \ - -DAPPLICATION_MESSAGES=ON \ - -DCONTROL_KEEP_ALIVE_MESSAGE=ON \ - -DBIDIRECTIONAL=ON \ - -DASYNCHRONOUS=ON \ - -DLOW_LEVEL_OPEN_CLOSE=ON \ - -DREGULATORY=ON \ - -DLATENCY_COMPENSATION=ON \ - -DSINGLE_FRAME=ON \ - -DPARAMETERS_CHECK=ON \ - -DCERTIFICATION=ON \ - -DPUBLIC_KEY_CAPABLE=ON \ - -DVERBOSE=ON \ - -DCRC_HW=OFF \ - -DERROR_CODES=ON \ - -DUL_BIT_RATE_BPS=OFF \ - -DT_IFU_MS=OFF \ - -DT_CONF_MS=OFF \ - -DUL_PAYLOAD_SIZE=OFF \ - -DMESSAGE_COUNTER_ROLLOVER=OFF \ - -DERROR_STACK=12 .. -$ make precompil +cmake -DSIGFOX_EP_LIB_DIR= \ + -DUSE_SIGFOX_EP_FLAGS_H=OFF \ + -DRC1=ON \ + -DRC2=ON \ + -DRC3C=ON \ + -DRC3D=ON \ + -DRC4=ON \ + -DRC5=ON \ + -DRC6=ON \ + -DRC7=ON \ + -DAPPLICATION_MESSAGES=ON \ + -DCONTROL_KEEP_ALIVE_MESSAGE=ON \ + -DBIDIRECTIONAL=ON \ + -DASYNCHRONOUS=ON \ + -DLOW_LEVEL_OPEN_CLOSE=ON \ + -DREGULATORY=ON \ + -DLATENCY_COMPENSATION=ON \ + -DSINGLE_FRAME=ON \ + -DUL_BIT_RATE_BPS=OFF \ + -DTX_POWER_DBM_EIRP=OFF \ + -DT_IFU_MS=OFF \ + -DT_CONF_MS=OFF \ + -DUL_PAYLOAD_SIZE=OFF \ + -DCRC_HW=OFF \ + -DMESSAGE_COUNTER_ROLLOVER=OFF \ + -DPARAMETERS_CHECK=ON \ + -DCERTIFICATION=ON \ + -DPUBLIC_KEY_CAPABLE=ON \ + -DVERBOSE=ON \ + -DERROR_CODES=ON \ + -DERROR_STACK=12 .. +make precompil_s2lp_rf_api ``` -The precompiled files will be generated in the `build/precompil` folder. +The new files will be generated in the `build/precompil` folder. ### Static library -If you want to build a **static library**, you need to run this additionnal **cmake** command: +You can also [download](https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp/releases) or clone any release of the S2LP RF API example and build a **static library**. +```bash +git clone https://github.com/sigfox-tech-radio/sigfox-ep-rf-api-st-s2lp.git +``` + +To build a static library, you have to install `cmake` tool and run the following commands: + +```bash +cd sigfox-ep-rf-api-st-s2lp/ +mkdir build +cd build/ +``` + +* Building by reading the `sigfox_ep_flags.h` file: + +```bash +cmake -DSIGFOX_EP_LIB_DIR= \ + -DUSE_SIGFOX_EP_FLAGS_H=ON .. +make s2lp_rf_api +``` + +* Building by entering the flags selection on command line: ```bash -$ make s2lp_rf_api +cmake -DSIGFOX_EP_LIB_DIR= \ + -DUSE_SIGFOX_EP_FLAGS_H=OFF \ + -DRC1=ON \ + -DRC2=ON \ + -DRC3C=ON \ + -DRC3D=ON \ + -DRC4=ON \ + -DRC5=ON \ + -DRC6=ON \ + -DRC7=ON \ + -DAPPLICATION_MESSAGES=ON \ + -DCONTROL_KEEP_ALIVE_MESSAGE=ON \ + -DBIDIRECTIONAL=ON \ + -DASYNCHRONOUS=ON \ + -DLOW_LEVEL_OPEN_CLOSE=ON \ + -DREGULATORY=ON \ + -DLATENCY_COMPENSATION=ON \ + -DSINGLE_FRAME=ON \ + -DPARAMETERS_CHECK=ON \ + -DCERTIFICATION=ON \ + -DPUBLIC_KEY_CAPABLE=ON \ + -DVERBOSE=ON \ + -DCRC_HW=OFF \ + -DERROR_CODES=ON \ + -DUL_BIT_RATE_BPS=OFF \ + -DT_IFU_MS=OFF \ + -DT_CONF_MS=OFF \ + -DUL_PAYLOAD_SIZE=OFF \ + -DMESSAGE_COUNTER_ROLLOVER=OFF \ + -DERROR_STACK=12 .. +make s2lp_rf_api ``` The archive will be generated in the `build/lib` folder. diff --git a/cmake/s2lp.patch b/cmake/s2lp.patch index b81d7a4..056c240 100644 --- a/cmake/s2lp.patch +++ b/cmake/s2lp.patch @@ -1451,7 +1451,7 @@ index c0f189b..d5ee608 100644 } diff --git a/Drivers/BSP/Components/S2LP/S2LP_Library/src/S2LP_Radio.c b/Drivers/BSP/Components/S2LP/S2LP_Library/src/S2LP_Radio.c -index 245da9f..17ed120 100644 +index 245da9f..a1c0c91 100644 --- a/Drivers/BSP/Components/S2LP/S2LP_Library/src/S2LP_Radio.c +++ b/Drivers/BSP/Components/S2LP/S2LP_Library/src/S2LP_Radio.c @@ -24,8 +24,11 @@ @@ -1665,7 +1665,24 @@ index 245da9f..17ed120 100644 } -@@ -1219,7 +1222,7 @@ void S2LPRadioSetPALeveldBm(uint8_t cIndex, int32_t lPowerdBm) +@@ -1209,17 +1212,22 @@ void S2LPRadioSetPALeveldBm(uint8_t cIndex, int32_t lPowerdBm) + s_assert_param(IS_PA_MAX_INDEX(cIndex)); + s_assert_param(IS_PAPOWER_DBM(lPowerdBm)); + +- if(lPowerdBm> 14) ++ if(lPowerdBm >= 14) + { + paLevelValue = 1; + } + else { +- paLevelValue = (uint8_t)((int32_t)25-2*lPowerdBm); ++ if (lPowerdBm >= 11) { ++ paLevelValue = (uint8_t) ((int32_t) 15 - lPowerdBm); ++ } ++ else { ++ paLevelValue = (uint8_t) ((int32_t) 25 - 2 * lPowerdBm); ++ } + } address = PA_POWER8_ADDR + 7 - cIndex; @@ -1674,16 +1691,32 @@ index 245da9f..17ed120 100644 } -@@ -1237,7 +1240,7 @@ int32_t S2LPRadioGetPALeveldBm(uint8_t cIndex) +@@ -1232,14 +1240,22 @@ void S2LPRadioSetPALeveldBm(uint8_t cIndex, int32_t lPowerdBm) + */ + int32_t S2LPRadioGetPALeveldBm(uint8_t cIndex) + { ++ int32_t lPowerdBm = 0; + uint8_t address, paLevelValue; + s_assert_param(IS_PA_MAX_INDEX(cIndex)); address = PA_POWER8_ADDR + 7 - cIndex; - *(uint8_t*)&g_xStatus = S2LPSpiReadRegisters(address, 1, &paLevelValue); + *(S2LPStatus*)&g_xStatus = S2LPSpiReadRegisters(address, 1, &paLevelValue); ++ ++ if (paLevelValue <= 4) { ++ lPowerdBm = (int32_t) (15 - paLevelValue); ++ } ++ else { ++ lPowerdBm = (int32_t) ((25 - paLevelValue) / 2); ++ } - return ((int32_t)25-paLevelValue)/2; +- return ((int32_t)25-paLevelValue)/2; ++ return lPowerdBm; } -@@ -1256,7 +1259,7 @@ void S2LPRadioSetPALevelMaxIndex(uint8_t cIndex) + + +@@ -1256,7 +1272,7 @@ void S2LPRadioSetPALevelMaxIndex(uint8_t cIndex) S2LPSpiReadRegisters(PA_POWER0_ADDR, 1, &tmp); tmp &= (~PA_LEVEL_MAX_IDX_REGMASK); tmp |= cIndex; @@ -1692,7 +1725,7 @@ index 245da9f..17ed120 100644 } -@@ -1268,7 +1271,7 @@ void S2LPRadioSetPALevelMaxIndex(uint8_t cIndex) +@@ -1268,7 +1284,7 @@ void S2LPRadioSetPALevelMaxIndex(uint8_t cIndex) uint8_t S2LPRadioGetPALevelMaxIndex(void) { uint8_t tmp; @@ -1701,7 +1734,7 @@ index 245da9f..17ed120 100644 return (tmp & PA_LEVEL_MAX_IDX_REGMASK); } -@@ -1298,7 +1301,7 @@ void S2LPRadioSetAutoRampingMode(SFunctionalState xNewState) +@@ -1298,7 +1314,7 @@ void S2LPRadioSetAutoRampingMode(SFunctionalState xNewState) tmpBuffer[1] &= ~FIR_EN_REGMASK; } @@ -1710,7 +1743,7 @@ index 245da9f..17ed120 100644 } -@@ -1326,7 +1329,7 @@ void S2LPRadioSetManualRampingMode(SFunctionalState xNewState) +@@ -1326,7 +1342,7 @@ void S2LPRadioSetManualRampingMode(SFunctionalState xNewState) tmpBuffer[0] &= ~PA_RAMP_EN_REGMASK; } @@ -1719,7 +1752,7 @@ index 245da9f..17ed120 100644 } -@@ -1355,7 +1358,7 @@ void S2LPRadioCalibrationVco(SFunctionalState xAmplitudeCalibration, SFunctional +@@ -1355,7 +1371,7 @@ void S2LPRadioCalibrationVco(SFunctionalState xAmplitudeCalibration, SFunctional } else { tmp &= ~VCO_CALFREQ_EXT_SEL_REGMASK; } @@ -1728,7 +1761,7 @@ index 245da9f..17ed120 100644 } /** -@@ -1366,7 +1369,7 @@ void S2LPRadioCalibrationVco(SFunctionalState xAmplitudeCalibration, SFunctional +@@ -1366,7 +1382,7 @@ void S2LPRadioCalibrationVco(SFunctionalState xAmplitudeCalibration, SFunctional void S2LPRadioSetTxCalibVcoAmpWord(uint8_t value) { value <<= 4; @@ -1737,7 +1770,7 @@ index 245da9f..17ed120 100644 } /** -@@ -1377,7 +1380,7 @@ void S2LPRadioSetTxCalibVcoAmpWord(uint8_t value) +@@ -1377,7 +1393,7 @@ void S2LPRadioSetTxCalibVcoAmpWord(uint8_t value) void S2LPRadioSetRxCalibVcoAmpWord(uint8_t value) { value &= VCO_CALAMP_RX_REGMASK; @@ -1746,7 +1779,7 @@ index 245da9f..17ed120 100644 } /** -@@ -1387,7 +1390,7 @@ void S2LPRadioSetRxCalibVcoAmpWord(uint8_t value) +@@ -1387,7 +1403,7 @@ void S2LPRadioSetRxCalibVcoAmpWord(uint8_t value) */ void S2LPRadioSetTxCalibVcoFreqWord(uint8_t value) { @@ -1755,7 +1788,7 @@ index 245da9f..17ed120 100644 } /** -@@ -1397,7 +1400,7 @@ void S2LPRadioSetTxCalibVcoFreqWord(uint8_t value) +@@ -1397,7 +1413,7 @@ void S2LPRadioSetTxCalibVcoFreqWord(uint8_t value) */ void S2LPRadioSetRxCalibVcoFreqWord(uint8_t value) { @@ -1764,7 +1797,7 @@ index 245da9f..17ed120 100644 } -@@ -1445,7 +1448,7 @@ void S2LPRadioAfcInit(SAfcInit* xSAfcInit) +@@ -1445,7 +1461,7 @@ void S2LPRadioAfcInit(SAfcInit* xSAfcInit) tmpBuffer[1] = xSAfcInit->cAfcFastPeriod; tmpBuffer[2] = (xSAfcInit->cAfcFastGain<<4) | xSAfcInit->cAfcSlowGain; @@ -1773,7 +1806,7 @@ index 245da9f..17ed120 100644 } -@@ -1484,7 +1487,7 @@ void S2LPRadioSetIsiEqualizationMode(SIsiEqu xSIsiMode) +@@ -1484,7 +1500,7 @@ void S2LPRadioSetIsiEqualizationMode(SIsiEqu xSIsiMode) S2LPSpiReadRegisters(ANT_SELECT_CONF_ADDR, 1, &tmp); tmp &= ~EQU_CTRL_REGMASK; tmp |= (((uint8_t)xSIsiMode)<<5); @@ -1782,7 +1815,7 @@ index 245da9f..17ed120 100644 } -@@ -1497,7 +1500,7 @@ SIsiEqu S2LPRadioGetIsiEqualizationMode(void) +@@ -1497,7 +1513,7 @@ SIsiEqu S2LPRadioGetIsiEqualizationMode(void) { uint8_t tmp; @@ -1791,7 +1824,7 @@ index 245da9f..17ed120 100644 return (SIsiEqu)((tmp&EQU_CTRL_REGMASK)>>5); } -@@ -1532,7 +1535,7 @@ void S2LPRadioSymClkRecoverInit(SSymClkRecInit* xSSymClkRecInit) +@@ -1532,7 +1548,7 @@ void S2LPRadioSymClkRecoverInit(SSymClkRecInit* xSSymClkRecInit) tmpBuffer[1] |= xSSymClkRecInit->cClkRecIGainFast; tmpBuffer[1] |= (xSSymClkRecInit->cClkRecPGainFast<<5); diff --git a/docs/images/sigfox_ep_example_st_s2lp_architecture.png b/docs/images/sigfox_ep_example_st_s2lp_architecture.png deleted file mode 100644 index 8cb53ac..0000000 Binary files a/docs/images/sigfox_ep_example_st_s2lp_architecture.png and /dev/null differ diff --git a/inc/board/s2lp_hw_api.h b/inc/board/s2lp_hw_api.h index 3b5e4e3..8e1d241 100644 --- a/inc/board/s2lp_hw_api.h +++ b/inc/board/s2lp_hw_api.h @@ -108,7 +108,7 @@ typedef enum { * \brief S2LP driver callback functions. * \fn S2LP_HW_API_irq_cb_t To be called when a falling edge is detected on the S2LP GPIO. *******************************/ -typedef void (S2LP_HW_API_irq_cb_t)(void); +typedef void (*S2LP_HW_API_irq_cb_t)(void); /*** S2LP HW API functions ***/ diff --git a/inc/manuf/s2lp_rf_api.h b/inc/manuf/s2lp_rf_api.h index a49eaa5..41e77a1 100644 --- a/inc/manuf/s2lp_rf_api.h +++ b/inc/manuf/s2lp_rf_api.h @@ -201,13 +201,25 @@ RF_API_status_t S2LP_RF_API_carrier_sense(RF_API_carrier_sense_parameters_t *car RF_API_status_t S2LP_RF_API_get_latency(RF_API_latency_t latency_type, sfx_u32 *latency_ms); #endif +#ifdef CERTIFICATION +/*!****************************************************************** + * \fn RF_API_status_t S2LP_RF_API_start_continuous_wave(void) + * \brief Start continuous wave transmission using radio parameters given in the RF_API_init() function. + * \brief This function is only called by the type approval addon (EP-ADDON-TA). In asynchronous mode, it must not issue any completion callback. + * \param[in] none + * \param[out] none + * \retval Function execution status. + *******************************************************************/ +RF_API_status_t S2LP_RF_API_start_continuous_wave(void); +#endif + #ifdef VERBOSE /*!****************************************************************** * \fn RF_API_status_t S2LP_RF_API_get_version(sfx_u8 **version, sfx_u8 *version_size_char) * \brief Get RF driver version. * \param[in] none * \param[out] version: RF driver version. - * \param[out] version_size_char: Pointer tha will contain the string size. + * \param[out] version_size_char: Pointer that will contain the string size. * \retval Function execution status. *******************************************************************/ RF_API_status_t S2LP_RF_API_get_version(sfx_u8 **version, sfx_u8 *version_size_char); diff --git a/src/manuf/s2lp_rf_api.c b/src/manuf/s2lp_rf_api.c index abcecc4..0ef331b 100644 --- a/src/manuf/s2lp_rf_api.c +++ b/src/manuf/s2lp_rf_api.c @@ -60,6 +60,9 @@ /*** S2LP RF API local macros ***/ +#define S2LP_RF_API_FREQUENCY_MIN_HZ 826000000 +#define S2LP_RF_API_FREQUENCY_MAX_HZ 958000000 + #define S2LP_RF_API_SYMBOL_PROFILE_SIZE_BYTES 40 #define S2LP_RF_API_SYMBOL_FIFO_BUFFER_SIZE_BYTES (2 * S2LP_RF_API_SYMBOL_PROFILE_SIZE_BYTES) // Size is twice to store PA and FDEV values. @@ -79,11 +82,11 @@ #endif #ifdef VERBOSE -static const sfx_u8 S2LP_RF_API_VERSION[] = "v1.2"; +static const sfx_u8 S2LP_RF_API_VERSION[] = "v1.3"; #endif // Ramp profile table is written for ramp-down direction (reverse table for ramp up). -// Ampltude profile table contains whole bit 0 transmission. +// Amplitude profile table contains whole bit 0 transmission. #if !(defined TX_POWER_DBM_EIRP) || (TX_POWER_DBM_EIRP == 0) static const sfx_u8 S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_00_DBM[S2LP_RF_API_SYMBOL_PROFILE_SIZE_BYTES] = {23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 25, 26, 27, 28, 29, 31, 33, 35, 38, 42, 60, 220}; static const sfx_u8 S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_00_DBM[S2LP_RF_API_SYMBOL_PROFILE_SIZE_BYTES] = {23, 23, 23, 23, 23, 23, 24, 24, 25, 26, 27, 28, 29, 31, 33, 35, 38, 42, 60, 220, 220, 60, 42, 38, 35, 33, 31, 29, 28, 27, 26, 25, 24, 24, 23, 23, 23, 23, 23, 23}; @@ -177,13 +180,13 @@ static sfx_u32 S2LP_RF_API_LATENCY_MS[RF_API_LATENCY_LAST] = { 1, // TX init (600µs). 0, // Send start (depends on bit rate and will be computed during init function). 0, // Send stop (depends on bit rate and will be computed during init function). - 0, // TX de init (30µs). + 0, // TX de-init (30µs). 0, // Sleep (depends on HW latency). #ifdef BIDIRECTIONAL 1, // RX init (1.1ms). 0, // Receive start (150µs). 7, // Receive stop (6.7ms). - 0, // RX de init (30µs). + 0, // RX de-init (30µs). #endif }; #endif @@ -470,7 +473,7 @@ RF_API_status_t S2LP_RF_API_close(void) { #endif // Reset context. _reset_context(); - // De init board. + // De-init board. SdkEvalSpiDeinit(); #ifdef ERROR_CODES s2lp_hw_api_status = S2LP_HW_API_close(); @@ -569,6 +572,9 @@ RF_API_status_t S2LP_RF_API_init(RF_API_radio_parameters_t *radio_parameters) { S2LPRadioSetDigDiv(S_ENABLE); S2LPTimerCalibrationRco(S_ENABLE); // Frequency. + if (((radio_parameters -> frequency_hz) < S2LP_RF_API_FREQUENCY_MIN_HZ) || ((radio_parameters -> frequency_hz) > S2LP_RF_API_FREQUENCY_MAX_HZ)) { + EXIT_ERROR(S2LP_RF_API_ERROR_FREQUENCY); + } s2lp_status = S2LPRadioSetFrequencyBase(radio_parameters -> frequency_hz); if (s2lp_status != 0) EXIT_ERROR(S2LP_RF_API_ERROR_FREQUENCY); // Modulation and bit rate. @@ -618,73 +624,84 @@ RF_API_status_t S2LP_RF_API_init(RF_API_radio_parameters_t *radio_parameters) { // Note: SPMS configuration is performed by the TX/RX command strobe. switch (radio_parameters -> rf_mode) { case RF_API_MODE_TX: + // Configure IRQ mask. + S2LPGpioIrqConfig(TX_FIFO_ALMOST_EMPTY, S_ENABLE); + S2LPFifoMuxRxFifoIrqEnable(S_DISABLE); + // FIFO. + S2LPPacketHandlerSetTxMode(DIRECT_TX_FIFO_MODE); + S2LPFifoSetAlmostEmptyThresholdTx(S2LP_RF_API_FIFO_TX_ALMOST_EMPTY_THRESHOLD); + // PA configuration. + reg_value = 0x00; // Disable all features and select slot 0. + SdkEvalSpiWriteRegisters(PA_POWER0_ADDR, 1, ®_value); + S2LPRadioSetAutoRampingMode(S_DISABLE); + SdkEvalSpiReadRegisters(MOD1_ADDR, 1, ®_value); + reg_value |= PA_INTERP_EN_REGMASK; // Enable interpolator. + SdkEvalSpiWriteRegisters(MOD1_ADDR, 1, ®_value); + // Set output power. + if ((radio_parameters -> modulation) == RF_API_MODULATION_NONE) { + // Set fixed output power. #ifdef TX_POWER_DBM_EIRP -#if (TX_POWER_DBM_EIRP == 0) - s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_00_DBM; - s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_00_DBM; -#elif (TX_POWER_DBM_EIRP == 3) - s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_03_DBM; - s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_03_DBM; -#elif (TX_POWER_DBM_EIRP == 5) - s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_05_DBM; - s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_05_DBM; -#elif (TX_POWER_DBM_EIRP == 7) - s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_07_DBM; - s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_07_DBM; -#elif (TX_POWER_DBM_EIRP == 10) - s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_10_DBM; - s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_10_DBM; -#elif (TX_POWER_DBM_EIRP == 14) - s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_14_DBM; - s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_14_DBM; + S2LPRadioSetPALeveldBm(0, TX_POWER_DBM_EIRP); #else -#error "S2LP RF API flags error: unsupported TX_POWER_DBM_EIRP value." + S2LPRadioSetPALeveldBm(0, (radio_parameters -> tx_power_dbm_eirp)); #endif -#else /* TX_POWER_DBM_EIRP */ - // Allocate output power tables. - switch (radio_parameters -> tx_power_dbm_eirp) { - case 0: + } + else { + // Allocate output power table. +#ifdef TX_POWER_DBM_EIRP +#if (TX_POWER_DBM_EIRP == 0) s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_00_DBM; s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_00_DBM; - break; - case 3: +#elif (TX_POWER_DBM_EIRP == 3) s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_03_DBM; s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_03_DBM; - break; - case 5: +#elif (TX_POWER_DBM_EIRP == 5) s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_05_DBM; s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_05_DBM; - break; - case 7: +#elif (TX_POWER_DBM_EIRP == 7) s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_07_DBM; s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_07_DBM; - break; - case 10: +#elif (TX_POWER_DBM_EIRP == 10) s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_10_DBM; s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_10_DBM; - break; - case 14: +#elif (TX_POWER_DBM_EIRP == 14) s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_14_DBM; s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_14_DBM; - break; - default: - EXIT_ERROR(S2LP_RF_API_ERROR_TX_POWER); - break; +#else +#error "S2LP RF API flags error: unsupported TX_POWER_DBM_EIRP value." +#endif +#else /* TX_POWER_DBM_EIRP */ + switch (radio_parameters -> tx_power_dbm_eirp) { + case 0: + s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_00_DBM; + s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_00_DBM; + break; + case 3: + s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_03_DBM; + s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_03_DBM; + break; + case 5: + s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_05_DBM; + s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_05_DBM; + break; + case 7: + s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_07_DBM; + s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_07_DBM; + break; + case 10: + s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_10_DBM; + s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_10_DBM; + break; + case 14: + s2lp_rf_api_ctx.tx_ramp_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_RAMP_AMPLITUDE_PROFILE_14_DBM; + s2lp_rf_api_ctx.tx_bit_0_amplitude_profile_ptr = (sfx_u8*) S2LP_RF_API_BIT0_AMPLITUDE_PROFILE_14_DBM; + break; + default: + EXIT_ERROR(S2LP_RF_API_ERROR_TX_POWER); + break; + } } #endif /* TX_POWER_DBM_EIRP */ - // Configure IRQ mask. - S2LPGpioIrqConfig(TX_FIFO_ALMOST_EMPTY, S_ENABLE); - S2LPFifoMuxRxFifoIrqEnable(S_DISABLE); - // FIFO. - S2LPPacketHandlerSetTxMode(DIRECT_TX_FIFO_MODE); - S2LPFifoSetAlmostEmptyThresholdTx(S2LP_RF_API_FIFO_TX_ALMOST_EMPTY_THRESHOLD); - // PA configuration. - S2LPRadioSetMaxPALevel(S_DISABLE); - S2LPRadioSetManualRampingMode(S_DISABLE); - S2LPRadioSetAutoRampingMode(S_DISABLE); - SdkEvalSpiReadRegisters(MOD1_ADDR, 1, ®_value); - reg_value |= PA_INTERP_EN_REGMASK; // Enable interpolator. - SdkEvalSpiWriteRegisters(MOD1_ADDR, 1, ®_value); #if (defined TIMER_REQUIRED) && (defined LATENCY_COMPENSATION) // Start latency = 1 symbol of ramp-up. S2LP_RF_API_LATENCY_MS[RF_API_LATENCY_SEND_START] = ((1000) / ((sfx_u32) (radio_parameters -> bit_rate_bps))); @@ -708,7 +725,7 @@ RF_API_status_t S2LP_RF_API_init(RF_API_radio_parameters_t *radio_parameters) { S2LPRadioSetIsiEqualizationMode(ISI_EQUALIZATION_DISABLED); S2LPRadioAntennaSwitching(S_DISABLE); S2LPRadioCsBlanking(S_DISABLE); - // Downnlink packet structure. + // Downlink packet structure. downlink_pkt_init.xPreambleLength = S2LP_RF_API_DL_PR_SIZE_BITS; downlink_pkt_init.xSyncLength = (SIGFOX_DL_FT_SIZE_BYTES * 8); downlink_pkt_init.lSyncWords = s2lp_rf_api_ctx.sync_word_u32; @@ -957,6 +974,26 @@ RF_API_status_t S2LP_RF_API_get_latency(RF_API_latency_t latency_type, sfx_u32 * } #endif +#ifdef CERTIFICATION +/*******************************************************************/ +RF_API_status_t S2LP_RF_API_start_continuous_wave(void) { +#ifdef ERROR_CODES + RF_API_status_t status = RF_API_SUCCESS; +#endif + // Modulated CW is not supported for now. + if (S2LPRadioGetModulation() != MOD_NO_MOD) { + EXIT_ERROR(S2LP_RF_API_ERROR_MODULATION); + } + // Start radio. + S2LPCmdStrobeLockTx(); + _wait_for_s2lp_state_switch(MC_STATE_LOCKON); + S2LPCmdStrobeTx(); + _wait_for_s2lp_state_switch(MC_STATE_TX); +errors: + RETURN(); +} +#endif + #ifdef VERBOSE /*******************************************************************/ RF_API_status_t S2LP_RF_API_get_version(sfx_u8 **version, sfx_u8 *version_size_char) { @@ -974,9 +1011,6 @@ RF_API_status_t S2LP_RF_API_get_version(sfx_u8 **version, sfx_u8 *version_size_c void S2LP_RF_API_error(void) { // Turn radio off and close driver. S2LP_RF_API_sleep(); -#ifdef LOW_LEVEL_OPEN_CLOSE - S2LP_RF_API_close(); -#endif } #endif @@ -1058,6 +1092,13 @@ inline RF_API_status_t RF_API_get_latency(RF_API_latency_t latency_type, sfx_u32 } #endif +#ifdef CERTIFICATION +/*******************************************************************/ +inline RF_API_status_t RF_API_start_continuous_wave(void) { + return S2LP_RF_API_start_continuous_wave(); +} +#endif + #ifdef VERBOSE /*******************************************************************/ inline RF_API_status_t RF_API_get_version(sfx_u8 **version, sfx_u8 *version_size_char) {