├── .gitattributes ├── LICENSE ├── eagle ├── Gecko-Node.brd └── Gecko-Node.sch └── rf24tests ├── .cproject ├── .project ├── .settings ├── com.silabs.ss.framework.ide.project.sls.core.prefs └── org.eclipse.ltk.core.refactoring.prefs ├── CMSIS └── EFM32ZG │ ├── startup_gcc_efm32zg.s │ └── system_efm32zg.c ├── I2Cdisplay.hwconf ├── emlib ├── em_assert.c ├── em_cmu.c ├── em_emu.c ├── em_gpio.c ├── em_i2c.c ├── em_rtc.c ├── em_system.c ├── em_timer.c └── em_usart.c ├── inc ├── InitDevice.h ├── RF24.h ├── RF24_config.h ├── delay.h ├── emodes.h └── nRF24L01.h └── src ├── InitDevice.c ├── RF24.cpp ├── delay.c ├── emodes.c └── main.cpp /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /rf24tests/.cproject: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /rf24tests/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | rf24tests 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder 10 | clean,full,incremental, 11 | 12 | 13 | 14 | 15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder 16 | full,incremental, 17 | 18 | 19 | 20 | 21 | 22 | org.eclipse.cdt.core.cnature 23 | com.silabs.ss.framework.ide.project.sls.core.SLSProjectNature 24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature 25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature 26 | org.eclipse.cdt.core.ccnature 27 | 28 | 29 | -------------------------------------------------------------------------------- /rf24tests/.settings/com.silabs.ss.framework.ide.project.sls.core.prefs: -------------------------------------------------------------------------------- 1 | copiedFilesOriginState={} 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /rf24tests/.settings/org.eclipse.ltk.core.refactoring.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false 3 | -------------------------------------------------------------------------------- /rf24tests/CMSIS/EFM32ZG/startup_gcc_efm32zg.s: -------------------------------------------------------------------------------- 1 | /* @file startup_efm32zg.S 2 | * @brief startup file for Silicon Labs EFM32ZG devices. 3 | * For use with GCC for ARM Embedded Processors 4 | * @version 5.2.2 5 | * Date: 12 June 2014 6 | * 7 | */ 8 | /* Copyright (c) 2011 - 2014 ARM LIMITED 9 | 10 | All rights reserved. 11 | Redistribution and use in source and binary forms, with or without 12 | modification, are permitted provided that the following conditions are met: 13 | - Redistributions of source code must retain the above copyright 14 | notice, this list of conditions and the following disclaimer. 15 | - Redistributions in binary form must reproduce the above copyright 16 | notice, this list of conditions and the following disclaimer in the 17 | documentation and/or other materials provided with the distribution. 18 | - Neither the name of ARM nor the names of its contributors may be used 19 | to endorse or promote products derived from this software without 20 | specific prior written permission. 21 | * 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 23 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 | ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 26 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 | POSSIBILITY OF SUCH DAMAGE. 33 | ---------------------------------------------------------------------------*/ 34 | 35 | .syntax unified 36 | .arch armv6-m 37 | 38 | .section .stack 39 | .align 3 40 | #ifdef __STACK_SIZE 41 | .equ Stack_Size, __STACK_SIZE 42 | #else 43 | .equ Stack_Size, 0x00000400 44 | #endif 45 | .globl __StackTop 46 | .globl __StackLimit 47 | __StackLimit: 48 | .space Stack_Size 49 | .size __StackLimit, . - __StackLimit 50 | __StackTop: 51 | .size __StackTop, . - __StackTop 52 | 53 | .section .heap 54 | .align 3 55 | #ifdef __HEAP_SIZE 56 | .equ Heap_Size, __HEAP_SIZE 57 | #else 58 | .equ Heap_Size, 0x00000000 59 | #endif 60 | .globl __HeapBase 61 | .globl __HeapLimit 62 | __HeapBase: 63 | .if Heap_Size 64 | .space Heap_Size 65 | .endif 66 | .size __HeapBase, . - __HeapBase 67 | __HeapLimit: 68 | .size __HeapLimit, . - __HeapLimit 69 | 70 | .section .vectors 71 | .align 2 72 | .globl __Vectors 73 | __Vectors: 74 | .long __StackTop /* Top of Stack */ 75 | .long Reset_Handler /* Reset Handler */ 76 | .long NMI_Handler /* NMI Handler */ 77 | .long HardFault_Handler /* Hard Fault Handler */ 78 | .long Default_Handler /* Reserved */ 79 | .long Default_Handler /* Reserved */ 80 | .long Default_Handler /* Reserved */ 81 | .long Default_Handler /* Reserved */ 82 | .long Default_Handler /* Reserved */ 83 | .long Default_Handler /* Reserved */ 84 | .long Default_Handler /* Reserved */ 85 | .long SVC_Handler /* SVCall Handler */ 86 | .long Default_Handler /* Reserved */ 87 | .long Default_Handler /* Reserved */ 88 | .long PendSV_Handler /* PendSV Handler */ 89 | .long SysTick_Handler /* SysTick Handler */ 90 | 91 | /* External interrupts */ 92 | 93 | .long DMA_IRQHandler /* 0 - DMA */ 94 | .long GPIO_EVEN_IRQHandler /* 1 - GPIO_EVEN */ 95 | .long TIMER0_IRQHandler /* 2 - TIMER0 */ 96 | .long ACMP0_IRQHandler /* 3 - ACMP0 */ 97 | .long ADC0_IRQHandler /* 4 - ADC0 */ 98 | .long I2C0_IRQHandler /* 5 - I2C0 */ 99 | .long GPIO_ODD_IRQHandler /* 6 - GPIO_ODD */ 100 | .long TIMER1_IRQHandler /* 7 - TIMER1 */ 101 | .long USART1_RX_IRQHandler /* 8 - USART1_RX */ 102 | .long USART1_TX_IRQHandler /* 9 - USART1_TX */ 103 | .long LEUART0_IRQHandler /* 10 - LEUART0 */ 104 | .long PCNT0_IRQHandler /* 11 - PCNT0 */ 105 | .long RTC_IRQHandler /* 12 - RTC */ 106 | .long CMU_IRQHandler /* 13 - CMU */ 107 | .long VCMP_IRQHandler /* 14 - VCMP */ 108 | .long MSC_IRQHandler /* 15 - MSC */ 109 | .long AES_IRQHandler /* 16 - AES */ 110 | .long Default_Handler /* 17 - Reserved */ 111 | .long Default_Handler /* 18 - Reserved */ 112 | 113 | 114 | .size __Vectors, . - __Vectors 115 | 116 | .text 117 | .thumb 118 | .thumb_func 119 | .align 2 120 | .globl Reset_Handler 121 | .type Reset_Handler, %function 122 | Reset_Handler: 123 | #ifndef __NO_SYSTEM_INIT 124 | ldr r0, =SystemInit 125 | blx r0 126 | #endif 127 | 128 | /* Firstly it copies data from read only memory to RAM. There are two schemes 129 | * to copy. One can copy more than one sections. Another can only copy 130 | * one section. The former scheme needs more instructions and read-only 131 | * data to implement than the latter. 132 | * Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes. */ 133 | 134 | #ifdef __STARTUP_COPY_MULTIPLE 135 | /* Multiple sections scheme. 136 | * 137 | * Between symbol address __copy_table_start__ and __copy_table_end__, 138 | * there are array of triplets, each of which specify: 139 | * offset 0: LMA of start of a section to copy from 140 | * offset 4: VMA of start of a section to copy to 141 | * offset 8: size of the section to copy. Must be multiply of 4 142 | * 143 | * All addresses must be aligned to 4 bytes boundary. 144 | */ 145 | ldr r4, =__copy_table_start__ 146 | ldr r5, =__copy_table_end__ 147 | 148 | .L_loop0: 149 | cmp r4, r5 150 | bge .L_loop0_done 151 | ldr r1, [r4] 152 | ldr r2, [r4, #4] 153 | ldr r3, [r4, #8] 154 | 155 | .L_loop0_0: 156 | subs r3, #4 157 | blt .L_loop0_0_done 158 | ldr r0, [r1, r3] 159 | str r0, [r2, r3] 160 | b .L_loop0_0 161 | 162 | .L_loop0_0_done: 163 | adds r4, #12 164 | b .L_loop0 165 | 166 | .L_loop0_done: 167 | #else 168 | /* Single section scheme. 169 | * 170 | * The ranges of copy from/to are specified by following symbols 171 | * __etext: LMA of start of the section to copy from. Usually end of text 172 | * __data_start__: VMA of start of the section to copy to 173 | * __data_end__: VMA of end of the section to copy to 174 | * 175 | * All addresses must be aligned to 4 bytes boundary. 176 | */ 177 | ldr r1, =__etext 178 | ldr r2, =__data_start__ 179 | ldr r3, =__data_end__ 180 | 181 | subs r3, r2 182 | ble .L_loop1_done 183 | 184 | .L_loop1: 185 | subs r3, #4 186 | ldr r0, [r1,r3] 187 | str r0, [r2,r3] 188 | bgt .L_loop1 189 | 190 | .L_loop1_done: 191 | #endif /*__STARTUP_COPY_MULTIPLE */ 192 | 193 | /* This part of work usually is done in C library startup code. Otherwise, 194 | * define this macro to enable it in this startup. 195 | * 196 | * There are two schemes too. One can clear multiple BSS sections. Another 197 | * can only clear one section. The former is more size expensive than the 198 | * latter. 199 | * 200 | * Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former. 201 | * Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later. 202 | */ 203 | #ifdef __STARTUP_CLEAR_BSS_MULTIPLE 204 | /* Multiple sections scheme. 205 | * 206 | * Between symbol address __zero_table_start__ and __zero_table_end__, 207 | * there are array of tuples specifying: 208 | * offset 0: Start of a BSS section 209 | * offset 4: Size of this BSS section. Must be multiply of 4 210 | */ 211 | ldr r3, =__zero_table_start__ 212 | ldr r4, =__zero_table_end__ 213 | 214 | .L_loop2: 215 | cmp r3, r4 216 | bge .L_loop2_done 217 | ldr r1, [r3] 218 | ldr r2, [r3, #4] 219 | movs r0, 0 220 | 221 | .L_loop2_0: 222 | subs r2, #4 223 | blt .L_loop2_0_done 224 | str r0, [r1, r2] 225 | b .L_loop2_0 226 | .L_loop2_0_done: 227 | 228 | adds r3, #8 229 | b .L_loop2 230 | .L_loop2_done: 231 | #elif defined (__STARTUP_CLEAR_BSS) 232 | /* Single BSS section scheme. 233 | * 234 | * The BSS section is specified by following symbols 235 | * __bss_start__: start of the BSS section. 236 | * __bss_end__: end of the BSS section. 237 | * 238 | * Both addresses must be aligned to 4 bytes boundary. 239 | */ 240 | ldr r1, =__bss_start__ 241 | ldr r2, =__bss_end__ 242 | 243 | movs r0, 0 244 | subs r2, r1 245 | ble .L_loop3_done 246 | 247 | .L_loop3: 248 | subs r2, #4 249 | str r0, [r1, r2] 250 | bgt .L_loop3 251 | .L_loop3_done: 252 | #endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */ 253 | 254 | #ifndef __START 255 | #define __START _start 256 | #endif 257 | bl __START 258 | 259 | .pool 260 | .size Reset_Handler, . - Reset_Handler 261 | 262 | .align 1 263 | .thumb_func 264 | .weak Default_Handler 265 | .type Default_Handler, %function 266 | Default_Handler: 267 | b . 268 | .size Default_Handler, . - Default_Handler 269 | 270 | /* Macro to define default handlers. Default handler 271 | * will be weak symbol and just dead loops. They can be 272 | * overwritten by other handlers */ 273 | .macro def_irq_handler handler_name 274 | .weak \handler_name 275 | .set \handler_name, Default_Handler 276 | .endm 277 | 278 | def_irq_handler NMI_Handler 279 | def_irq_handler HardFault_Handler 280 | def_irq_handler SVC_Handler 281 | def_irq_handler PendSV_Handler 282 | def_irq_handler SysTick_Handler 283 | 284 | def_irq_handler DMA_IRQHandler 285 | def_irq_handler GPIO_EVEN_IRQHandler 286 | def_irq_handler TIMER0_IRQHandler 287 | def_irq_handler ACMP0_IRQHandler 288 | def_irq_handler ADC0_IRQHandler 289 | def_irq_handler I2C0_IRQHandler 290 | def_irq_handler GPIO_ODD_IRQHandler 291 | def_irq_handler TIMER1_IRQHandler 292 | def_irq_handler USART1_RX_IRQHandler 293 | def_irq_handler USART1_TX_IRQHandler 294 | def_irq_handler LEUART0_IRQHandler 295 | def_irq_handler PCNT0_IRQHandler 296 | def_irq_handler RTC_IRQHandler 297 | def_irq_handler CMU_IRQHandler 298 | def_irq_handler VCMP_IRQHandler 299 | def_irq_handler MSC_IRQHandler 300 | def_irq_handler AES_IRQHandler 301 | 302 | 303 | .end 304 | -------------------------------------------------------------------------------- /rf24tests/CMSIS/EFM32ZG/system_efm32zg.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file system_efm32zg.c 3 | * @brief CMSIS Cortex-M0+ System Layer for EFM32ZG devices. 4 | * @version 5.2.2 5 | ****************************************************************************** 6 | * # License 7 | * Copyright 2017 Silicon Laboratories, Inc. http://www.silabs.com 8 | ****************************************************************************** 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software.@n 16 | * 2. Altered source versions must be plainly marked as such, and must not be 17 | * misrepresented as being the original software.@n 18 | * 3. This notice may not be removed or altered from any source distribution. 19 | * 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Laboratories, Inc. 21 | * has no obligation to support this Software. Silicon Laboratories, Inc. is 22 | * providing the Software "AS IS", with no express or implied warranties of any 23 | * kind, including, but not limited to, any implied warranties of 24 | * merchantability or fitness for any particular purpose or warranties against 25 | * infringement of any proprietary rights of a third party. 26 | * 27 | * Silicon Laboratories, Inc. will not be liable for any consequential, 28 | * incidental, or special damages, or any other relief, or for any claim by 29 | * any third party, arising from your use of this Software. 30 | * 31 | *****************************************************************************/ 32 | 33 | #include 34 | #include "em_device.h" 35 | 36 | /******************************************************************************* 37 | ****************************** DEFINES ************************************ 38 | ******************************************************************************/ 39 | 40 | /** LFRCO frequency, tuned to below frequency during manufacturing. */ 41 | #define EFM32_LFRCO_FREQ (32768UL) 42 | /** ULFRCO frequency. */ 43 | #define EFM32_ULFRCO_FREQ (1000UL) 44 | 45 | /******************************************************************************* 46 | ************************** LOCAL VARIABLES ******************************** 47 | ******************************************************************************/ 48 | 49 | /* System oscillator frequencies. These frequencies are normally constant */ 50 | /* for a target, but they are made configurable in order to allow run-time */ 51 | /* handling of different boards. The crystal oscillator clocks can be set */ 52 | /* compile time to a non-default value by defining respective EFM32_nFXO_FREQ */ 53 | /* values according to board design. By defining the EFM32_nFXO_FREQ to 0, */ 54 | /* one indicates that the oscillator is not present, in order to save some */ 55 | /* SW footprint. */ 56 | 57 | #ifndef EFM32_HFXO_FREQ 58 | /** HFXO frequency. */ 59 | #define EFM32_HFXO_FREQ (24000000UL) 60 | #endif 61 | 62 | /** Maximum HFRCO frequency. */ 63 | #define EFM32_HFRCO_MAX_FREQ (21000000UL) 64 | 65 | /* Do not define variable if HF crystal oscillator not present */ 66 | #if (EFM32_HFXO_FREQ > 0) 67 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 68 | /** System HFXO clock. */ 69 | static uint32_t SystemHFXOClock = EFM32_HFXO_FREQ; 70 | /** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */ 71 | #endif 72 | 73 | #ifndef EFM32_LFXO_FREQ 74 | /** LFXO frequency. */ 75 | #define EFM32_LFXO_FREQ (EFM32_LFRCO_FREQ) 76 | #endif 77 | 78 | /* Do not define variable if LF crystal oscillator not present */ 79 | #if (EFM32_LFXO_FREQ > 0) 80 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 81 | /** System LFXO clock. */ 82 | static uint32_t SystemLFXOClock = EFM32_LFXO_FREQ; 83 | /** @endcond (DO_NOT_INCLUDE_WITH_DOXYGEN) */ 84 | #endif 85 | 86 | /******************************************************************************* 87 | ************************** GLOBAL VARIABLES ******************************* 88 | ******************************************************************************/ 89 | 90 | /** 91 | * @brief 92 | * System System Clock Frequency (Core Clock). 93 | * 94 | * @details 95 | * Required CMSIS global variable that must be kept up-to-date. 96 | */ 97 | uint32_t SystemCoreClock = 14000000UL; 98 | 99 | /******************************************************************************* 100 | ************************** GLOBAL FUNCTIONS ******************************* 101 | ******************************************************************************/ 102 | 103 | /***************************************************************************//** 104 | * @brief 105 | * Get the current core clock frequency. 106 | * 107 | * @details 108 | * Calculate and get the current core clock frequency based on the current 109 | * configuration. Assuming that the SystemCoreClock global variable is 110 | * maintained, the core clock frequency is stored in that variable as well. 111 | * This function will however calculate the core clock based on actual HW 112 | * configuration. It will also update the SystemCoreClock global variable. 113 | * 114 | * @note 115 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 116 | * 117 | * @return 118 | * The current core clock frequency in Hz. 119 | ******************************************************************************/ 120 | uint32_t SystemCoreClockGet(void) 121 | { 122 | uint32_t ret; 123 | 124 | ret = SystemHFClockGet(); 125 | ret >>= (CMU->HFCORECLKDIV & _CMU_HFCORECLKDIV_HFCORECLKDIV_MASK) >> 126 | _CMU_HFCORECLKDIV_HFCORECLKDIV_SHIFT; 127 | 128 | /* Keep CMSIS variable up-to-date just in case */ 129 | SystemCoreClock = ret; 130 | 131 | return ret; 132 | } 133 | 134 | 135 | /***************************************************************************//** 136 | * @brief 137 | * Get the maximum core clock frequency. 138 | * 139 | * @note 140 | * This is an EFR32 proprietary function, not part of the CMSIS definition. 141 | * 142 | * @return 143 | * The maximum core clock frequency in Hz. 144 | ******************************************************************************/ 145 | uint32_t SystemMaxCoreClockGet(void) 146 | { 147 | return (EFM32_HFRCO_MAX_FREQ > EFM32_HFXO_FREQ ? \ 148 | EFM32_HFRCO_MAX_FREQ : EFM32_HFXO_FREQ); 149 | } 150 | 151 | 152 | /***************************************************************************//** 153 | * @brief 154 | * Get the current HFCLK frequency. 155 | * 156 | * @note 157 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 158 | * 159 | * @return 160 | * The current HFCLK frequency in Hz. 161 | ******************************************************************************/ 162 | uint32_t SystemHFClockGet(void) 163 | { 164 | uint32_t ret; 165 | 166 | switch (CMU->STATUS & (CMU_STATUS_HFRCOSEL | CMU_STATUS_HFXOSEL | 167 | CMU_STATUS_LFRCOSEL | CMU_STATUS_LFXOSEL)) 168 | { 169 | case CMU_STATUS_LFXOSEL: 170 | #if (EFM32_LFXO_FREQ > 0) 171 | ret = SystemLFXOClock; 172 | #else 173 | /* We should not get here, since core should not be clocked. May */ 174 | /* be caused by a misconfiguration though. */ 175 | ret = 0; 176 | #endif 177 | break; 178 | 179 | case CMU_STATUS_LFRCOSEL: 180 | ret = EFM32_LFRCO_FREQ; 181 | break; 182 | 183 | case CMU_STATUS_HFXOSEL: 184 | #if (EFM32_HFXO_FREQ > 0) 185 | ret = SystemHFXOClock; 186 | #else 187 | /* We should not get here, since core should not be clocked. May */ 188 | /* be caused by a misconfiguration though. */ 189 | ret = 0; 190 | #endif 191 | break; 192 | 193 | default: /* CMU_STATUS_HFRCOSEL */ 194 | switch (CMU->HFRCOCTRL & _CMU_HFRCOCTRL_BAND_MASK) 195 | { 196 | case CMU_HFRCOCTRL_BAND_21MHZ: 197 | ret = 21000000; 198 | break; 199 | 200 | case CMU_HFRCOCTRL_BAND_14MHZ: 201 | ret = 14000000; 202 | break; 203 | 204 | case CMU_HFRCOCTRL_BAND_11MHZ: 205 | ret = 11000000; 206 | break; 207 | 208 | case CMU_HFRCOCTRL_BAND_7MHZ: 209 | ret = 6600000; 210 | break; 211 | 212 | case CMU_HFRCOCTRL_BAND_1MHZ: 213 | ret = 1200000; 214 | break; 215 | 216 | default: 217 | ret = 0; 218 | break; 219 | } 220 | break; 221 | } 222 | 223 | return ret; 224 | } 225 | 226 | 227 | /**************************************************************************//** 228 | * @brief 229 | * Get high frequency crystal oscillator clock frequency for target system. 230 | * 231 | * @note 232 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 233 | * 234 | * @return 235 | * HFXO frequency in Hz. 236 | *****************************************************************************/ 237 | uint32_t SystemHFXOClockGet(void) 238 | { 239 | /* External crystal oscillator present? */ 240 | #if (EFM32_HFXO_FREQ > 0) 241 | return SystemHFXOClock; 242 | #else 243 | return 0; 244 | #endif 245 | } 246 | 247 | 248 | /**************************************************************************//** 249 | * @brief 250 | * Set high frequency crystal oscillator clock frequency for target system. 251 | * 252 | * @note 253 | * This function is mainly provided for being able to handle target systems 254 | * with different HF crystal oscillator frequencies run-time. If used, it 255 | * should probably only be used once during system startup. 256 | * 257 | * @note 258 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 259 | * 260 | * @param[in] freq 261 | * HFXO frequency in Hz used for target. 262 | *****************************************************************************/ 263 | void SystemHFXOClockSet(uint32_t freq) 264 | { 265 | /* External crystal oscillator present? */ 266 | #if (EFM32_HFXO_FREQ > 0) 267 | SystemHFXOClock = freq; 268 | 269 | /* Update core clock frequency if HFXO is used to clock core */ 270 | if (CMU->STATUS & CMU_STATUS_HFXOSEL) 271 | { 272 | /* The function will update the global variable */ 273 | SystemCoreClockGet(); 274 | } 275 | #else 276 | (void)freq; /* Unused parameter */ 277 | #endif 278 | } 279 | 280 | 281 | /**************************************************************************//** 282 | * @brief 283 | * Initialize the system. 284 | * 285 | * @details 286 | * Do required generic HW system init. 287 | * 288 | * @note 289 | * This function is invoked during system init, before the main() routine 290 | * and any data has been initialized. For this reason, it cannot do any 291 | * initialization of variables etc. 292 | *****************************************************************************/ 293 | void SystemInit(void) 294 | { 295 | } 296 | 297 | 298 | /**************************************************************************//** 299 | * @brief 300 | * Get low frequency RC oscillator clock frequency for target system. 301 | * 302 | * @note 303 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 304 | * 305 | * @return 306 | * LFRCO frequency in Hz. 307 | *****************************************************************************/ 308 | uint32_t SystemLFRCOClockGet(void) 309 | { 310 | /* Currently we assume that this frequency is properly tuned during */ 311 | /* manufacturing and is not changed after reset. If future requirements */ 312 | /* for re-tuning by user, we can add support for that. */ 313 | return EFM32_LFRCO_FREQ; 314 | } 315 | 316 | 317 | /**************************************************************************//** 318 | * @brief 319 | * Get ultra low frequency RC oscillator clock frequency for target system. 320 | * 321 | * @note 322 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 323 | * 324 | * @return 325 | * ULFRCO frequency in Hz. 326 | *****************************************************************************/ 327 | uint32_t SystemULFRCOClockGet(void) 328 | { 329 | /* The ULFRCO frequency is not tuned, and can be very inaccurate */ 330 | return EFM32_ULFRCO_FREQ; 331 | } 332 | 333 | 334 | /**************************************************************************//** 335 | * @brief 336 | * Get low frequency crystal oscillator clock frequency for target system. 337 | * 338 | * @note 339 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 340 | * 341 | * @return 342 | * LFXO frequency in Hz. 343 | *****************************************************************************/ 344 | uint32_t SystemLFXOClockGet(void) 345 | { 346 | /* External crystal oscillator present? */ 347 | #if (EFM32_LFXO_FREQ > 0) 348 | return SystemLFXOClock; 349 | #else 350 | return 0; 351 | #endif 352 | } 353 | 354 | 355 | /**************************************************************************//** 356 | * @brief 357 | * Set low frequency crystal oscillator clock frequency for target system. 358 | * 359 | * @note 360 | * This function is mainly provided for being able to handle target systems 361 | * with different HF crystal oscillator frequencies run-time. If used, it 362 | * should probably only be used once during system startup. 363 | * 364 | * @note 365 | * This is an EFM32 proprietary function, not part of the CMSIS definition. 366 | * 367 | * @param[in] freq 368 | * LFXO frequency in Hz used for target. 369 | *****************************************************************************/ 370 | void SystemLFXOClockSet(uint32_t freq) 371 | { 372 | /* External crystal oscillator present? */ 373 | #if (EFM32_LFXO_FREQ > 0) 374 | SystemLFXOClock = freq; 375 | 376 | /* Update core clock frequency if LFXO is used to clock core */ 377 | if (CMU->STATUS & CMU_STATUS_LFXOSEL) 378 | { 379 | /* The function will update the global variable */ 380 | SystemCoreClockGet(); 381 | } 382 | #else 383 | (void)freq; /* Unused parameter */ 384 | #endif 385 | } 386 | -------------------------------------------------------------------------------- /rf24tests/I2Cdisplay.hwconf: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /rf24tests/emlib/em_assert.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file em_assert.c 3 | * @brief Assert API 4 | * @version 5.2.2 5 | ******************************************************************************* 6 | * # License 7 | * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com 8 | ******************************************************************************* 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. 16 | * 2. Altered source versions must be plainly marked as such, and must not be 17 | * misrepresented as being the original software. 18 | * 3. This notice may not be removed or altered from any source distribution. 19 | * 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no 21 | * obligation to support this Software. Silicon Labs is providing the 22 | * Software "AS IS", with no express or implied warranties of any kind, 23 | * including, but not limited to, any implied warranties of merchantability 24 | * or fitness for any particular purpose or warranties against infringement 25 | * of any proprietary rights of a third party. 26 | * 27 | * Silicon Labs will not be liable for any consequential, incidental, or 28 | * special damages, or any other relief, or for any claim by any third party, 29 | * arising from your use of this Software. 30 | * 31 | ******************************************************************************/ 32 | 33 | #include "em_assert.h" 34 | #include 35 | 36 | /***************************************************************************//** 37 | * @addtogroup emlib 38 | * @{ 39 | ******************************************************************************/ 40 | 41 | /***************************************************************************//** 42 | * @addtogroup ASSERT 43 | * @{ 44 | ******************************************************************************/ 45 | 46 | #if defined(DEBUG_EFM) 47 | /***************************************************************************//** 48 | * @brief 49 | * EFM internal assert handling. 50 | * 51 | * This function is invoked through EFM_ASSERT() macro usage only, it should 52 | * not be used explicitly. 53 | * 54 | * This implementation simply enters an indefinite loop, allowing 55 | * the use of a debugger to determine cause of failure. By defining 56 | * DEBUG_EFM_USER to the preprocessor for all files, a user defined version 57 | * of this function must be defined and will be invoked instead, possibly 58 | * providing output of assertion location. 59 | * 60 | * @note 61 | * This function is not used unless @ref DEBUG_EFM is defined 62 | * during preprocessing of EFM_ASSERT() usage. 63 | * 64 | * @param[in] file 65 | * Name of source file where assertion failed. 66 | * 67 | * @param[in] line 68 | * Line number in source file where assertion failed. 69 | ******************************************************************************/ 70 | void assertEFM(const char *file, int line) 71 | { 72 | (void)file; /* Unused parameter */ 73 | (void)line; /* Unused parameter */ 74 | 75 | while (true) { 76 | } 77 | } 78 | #endif /* DEBUG_EFM */ 79 | 80 | /** @} (end addtogroup ASSERT) */ 81 | /** @} (end addtogroup emlib) */ 82 | -------------------------------------------------------------------------------- /rf24tests/emlib/em_gpio.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file em_gpio.c 3 | * @brief General Purpose IO (GPIO) peripheral API 4 | * devices. 5 | * @version 5.2.2 6 | ******************************************************************************* 7 | * # License 8 | * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com 9 | ******************************************************************************* 10 | * 11 | * Permission is granted to anyone to use this software for any purpose, 12 | * including commercial applications, and to alter it and redistribute it 13 | * freely, subject to the following restrictions: 14 | * 15 | * 1. The origin of this software must not be misrepresented; you must not 16 | * claim that you wrote the original software. 17 | * 2. Altered source versions must be plainly marked as such, and must not be 18 | * misrepresented as being the original software. 19 | * 3. This notice may not be removed or altered from any source distribution. 20 | * 21 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no 22 | * obligation to support this Software. Silicon Labs is providing the 23 | * Software "AS IS", with no express or implied warranties of any kind, 24 | * including, but not limited to, any implied warranties of merchantability 25 | * or fitness for any particular purpose or warranties against infringement 26 | * of any proprietary rights of a third party. 27 | * 28 | * Silicon Labs will not be liable for any consequential, incidental, or 29 | * special damages, or any other relief, or for any claim by any third party, 30 | * arising from your use of this Software. 31 | * 32 | ******************************************************************************/ 33 | 34 | #include "em_gpio.h" 35 | 36 | #if defined(GPIO_COUNT) && (GPIO_COUNT > 0) 37 | 38 | /***************************************************************************//** 39 | * @addtogroup emlib 40 | * @{ 41 | ******************************************************************************/ 42 | 43 | /***************************************************************************//** 44 | * @addtogroup GPIO 45 | * @brief General Purpose Input/Output (GPIO) API 46 | * @details 47 | * This module contains functions to control the GPIO peripheral of Silicon 48 | * Labs 32-bit MCUs and SoCs. The GPIO peripheral is used for pin configuration 49 | * and direct pin manipulation and sensing as well as routing for peripheral 50 | * pin connections. 51 | * @{ 52 | ******************************************************************************/ 53 | 54 | /******************************************************************************* 55 | ******************************* DEFINES *********************************** 56 | ******************************************************************************/ 57 | 58 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 59 | 60 | /** Validation of pin typically usable in assert statements. */ 61 | #define GPIO_DRIVEMODE_VALID(mode) ((mode) <= 3) 62 | #define GPIO_STRENGHT_VALID(strenght) (!((strenght) \ 63 | & ~(_GPIO_P_CTRL_DRIVESTRENGTH_MASK \ 64 | | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK))) 65 | /** @endcond */ 66 | 67 | /******************************************************************************* 68 | ************************** GLOBAL FUNCTIONS ******************************* 69 | ******************************************************************************/ 70 | 71 | /***************************************************************************//** 72 | * @brief 73 | * Sets the pin location of the debug pins (Serial Wire interface). 74 | * 75 | * @note 76 | * Changing the pins used for debugging uncontrolled, may result in a lockout. 77 | * 78 | * @param[in] location 79 | * The debug pin location to use (0-3). 80 | ******************************************************************************/ 81 | void GPIO_DbgLocationSet(unsigned int location) 82 | { 83 | #if defined (_GPIO_ROUTE_SWLOCATION_MASK) 84 | EFM_ASSERT(location < AFCHANLOC_MAX); 85 | 86 | GPIO->ROUTE = (GPIO->ROUTE & ~_GPIO_ROUTE_SWLOCATION_MASK) 87 | | (location << _GPIO_ROUTE_SWLOCATION_SHIFT); 88 | #else 89 | (void)location; 90 | #endif 91 | } 92 | 93 | #if defined (_GPIO_P_CTRL_DRIVEMODE_MASK) 94 | /***************************************************************************//** 95 | * @brief 96 | * Sets the drive mode for a GPIO port. 97 | * 98 | * @param[in] port 99 | * The GPIO port to access. 100 | * 101 | * @param[in] mode 102 | * Drive mode to use for port. 103 | ******************************************************************************/ 104 | void GPIO_DriveModeSet(GPIO_Port_TypeDef port, GPIO_DriveMode_TypeDef mode) 105 | { 106 | EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_DRIVEMODE_VALID(mode)); 107 | 108 | GPIO->P[port].CTRL = (GPIO->P[port].CTRL & ~(_GPIO_P_CTRL_DRIVEMODE_MASK)) 109 | | (mode << _GPIO_P_CTRL_DRIVEMODE_SHIFT); 110 | } 111 | #endif 112 | 113 | #if defined (_GPIO_P_CTRL_DRIVESTRENGTH_MASK) 114 | /***************************************************************************//** 115 | * @brief 116 | * Sets the drive strength for a GPIO port. 117 | * 118 | * @param[in] port 119 | * The GPIO port to access. 120 | * 121 | * @param[in] strength 122 | * Drive strength to use for port. 123 | ******************************************************************************/ 124 | void GPIO_DriveStrengthSet(GPIO_Port_TypeDef port, 125 | GPIO_DriveStrength_TypeDef strength) 126 | { 127 | EFM_ASSERT(GPIO_PORT_VALID(port) && GPIO_STRENGHT_VALID(strength)); 128 | BUS_RegMaskedWrite(&GPIO->P[port].CTRL, 129 | _GPIO_P_CTRL_DRIVESTRENGTH_MASK | _GPIO_P_CTRL_DRIVESTRENGTHALT_MASK, 130 | strength); 131 | } 132 | #endif 133 | 134 | /***************************************************************************//** 135 | * @brief 136 | * Configure GPIO external pin interrupt. 137 | * 138 | * @details 139 | * If reconfiguring a GPIO interrupt that is already enabled, it is generally 140 | * recommended to disable it first, see GPIO_Disable(). 141 | * 142 | * The actual GPIO interrupt handler must be in place before enabling the 143 | * interrupt. 144 | * 145 | * Notice that any pending interrupt for the selected interrupt is cleared 146 | * by this function. 147 | * 148 | * @note 149 | * On series 0 devices the pin number parameter is not used. The 150 | * pin number used on these devices is hardwired to the interrupt with the 151 | * same number. @n 152 | * On series 1 devices, pin number can be selected freely within a group. 153 | * Interrupt numbers are divided into 4 groups (intNo / 4) and valid pin 154 | * number within the interrupt groups are: 155 | * 0: pins 0-3 156 | * 1: pins 4-7 157 | * 2: pins 8-11 158 | * 3: pins 12-15 159 | * 160 | * @param[in] port 161 | * The port to associate with @p pin. 162 | * 163 | * @param[in] pin 164 | * The pin number on the port. 165 | * 166 | * @param[in] intNo 167 | * The interrupt number to trigger. 168 | * 169 | * @param[in] risingEdge 170 | * Set to true if interrupts shall be enabled on rising edge, otherwise false. 171 | * 172 | * @param[in] fallingEdge 173 | * Set to true if interrupts shall be enabled on falling edge, otherwise false. 174 | * 175 | * @param[in] enable 176 | * Set to true if interrupt shall be enabled after configuration completed, 177 | * false to leave disabled. See GPIO_IntDisable() and GPIO_IntEnable(). 178 | ******************************************************************************/ 179 | void GPIO_ExtIntConfig(GPIO_Port_TypeDef port, 180 | unsigned int pin, 181 | unsigned int intNo, 182 | bool risingEdge, 183 | bool fallingEdge, 184 | bool enable) 185 | { 186 | uint32_t tmp = 0; 187 | #if !defined(_GPIO_EXTIPINSELL_MASK) 188 | (void)pin; 189 | #endif 190 | 191 | EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin)); 192 | #if defined(_GPIO_EXTIPINSELL_MASK) 193 | EFM_ASSERT(GPIO_INTNO_PIN_VALID(intNo, pin)); 194 | #endif 195 | 196 | /* There are two registers controlling the interrupt configuration: 197 | * The EXTIPSELL register controls pins 0-7 and EXTIPSELH controls 198 | * pins 8-15. */ 199 | if (intNo < 8) { 200 | BUS_RegMaskedWrite(&GPIO->EXTIPSELL, 201 | _GPIO_EXTIPSELL_EXTIPSEL0_MASK 202 | << (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * intNo), 203 | port << (_GPIO_EXTIPSELL_EXTIPSEL1_SHIFT * intNo)); 204 | } else { 205 | tmp = intNo - 8; 206 | BUS_RegMaskedWrite(&GPIO->EXTIPSELH, 207 | _GPIO_EXTIPSELH_EXTIPSEL8_MASK 208 | << (_GPIO_EXTIPSELH_EXTIPSEL9_SHIFT * tmp), 209 | port << (_GPIO_EXTIPSELH_EXTIPSEL9_SHIFT * tmp)); 210 | } 211 | 212 | #if defined(_GPIO_EXTIPINSELL_MASK) 213 | /* There are two registers controlling the interrupt/pin number mapping: 214 | * The EXTIPINSELL register controls interrupt 0-7 and EXTIPINSELH controls 215 | * interrupt 8-15. */ 216 | if (intNo < 8) { 217 | BUS_RegMaskedWrite(&GPIO->EXTIPINSELL, 218 | _GPIO_EXTIPINSELL_EXTIPINSEL0_MASK 219 | << (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * intNo), 220 | ((pin % 4) & _GPIO_EXTIPINSELL_EXTIPINSEL0_MASK) 221 | << (_GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * intNo)); 222 | } else { 223 | BUS_RegMaskedWrite(&GPIO->EXTIPINSELH, 224 | _GPIO_EXTIPINSELH_EXTIPINSEL8_MASK 225 | << (_GPIO_EXTIPINSELH_EXTIPINSEL9_SHIFT * tmp), 226 | ((pin % 4) & _GPIO_EXTIPINSELH_EXTIPINSEL8_MASK) 227 | << (_GPIO_EXTIPSELH_EXTIPSEL9_SHIFT * tmp)); 228 | } 229 | #endif 230 | 231 | /* Enable/disable rising edge */ 232 | BUS_RegBitWrite(&(GPIO->EXTIRISE), intNo, risingEdge); 233 | 234 | /* Enable/disable falling edge */ 235 | BUS_RegBitWrite(&(GPIO->EXTIFALL), intNo, fallingEdge); 236 | 237 | /* Clear any pending interrupt */ 238 | GPIO->IFC = 1 << intNo; 239 | 240 | /* Finally enable/disable interrupt */ 241 | BUS_RegBitWrite(&(GPIO->IEN), intNo, enable); 242 | } 243 | 244 | /***************************************************************************//** 245 | * @brief 246 | * Set the mode for a GPIO pin. 247 | * 248 | * @param[in] port 249 | * The GPIO port to access. 250 | * 251 | * @param[in] pin 252 | * The pin number in the port. 253 | * 254 | * @param[in] mode 255 | * The desired pin mode. 256 | * 257 | * @param[in] out 258 | * Value to set for pin in DOUT register. The DOUT setting is important for 259 | * even some input mode configurations, determining pull-up/down direction. 260 | ******************************************************************************/ 261 | void GPIO_PinModeSet(GPIO_Port_TypeDef port, 262 | unsigned int pin, 263 | GPIO_Mode_TypeDef mode, 264 | unsigned int out) 265 | { 266 | EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin)); 267 | 268 | /* If disabling pin, do not modify DOUT in order to reduce chance for */ 269 | /* glitch/spike (may not be sufficient precaution in all use cases) */ 270 | if (mode != gpioModeDisabled) { 271 | if (out) { 272 | GPIO_PinOutSet(port, pin); 273 | } else { 274 | GPIO_PinOutClear(port, pin); 275 | } 276 | } 277 | 278 | /* There are two registers controlling the pins for each port. The MODEL 279 | * register controls pins 0-7 and MODEH controls pins 8-15. */ 280 | if (pin < 8) { 281 | GPIO->P[port].MODEL = (GPIO->P[port].MODEL & ~(0xFu << (pin * 4))) 282 | | (mode << (pin * 4)); 283 | } else { 284 | GPIO->P[port].MODEH = (GPIO->P[port].MODEH & ~(0xFu << ((pin - 8) * 4))) 285 | | (mode << ((pin - 8) * 4)); 286 | } 287 | 288 | if (mode == gpioModeDisabled) { 289 | if (out) { 290 | GPIO_PinOutSet(port, pin); 291 | } else { 292 | GPIO_PinOutClear(port, pin); 293 | } 294 | } 295 | } 296 | 297 | /***************************************************************************//** 298 | * @brief 299 | * Get the mode for a GPIO pin. 300 | * 301 | * @param[in] port 302 | * The GPIO port to access. 303 | * 304 | * @param[in] pin 305 | * The pin number in the port. 306 | * 307 | * @return 308 | * The pin mode. 309 | ******************************************************************************/ 310 | GPIO_Mode_TypeDef GPIO_PinModeGet(GPIO_Port_TypeDef port, 311 | unsigned int pin) 312 | { 313 | EFM_ASSERT(GPIO_PORT_PIN_VALID(port, pin)); 314 | 315 | if (pin < 8) { 316 | return (GPIO_Mode_TypeDef) ((GPIO->P[port].MODEL >> (pin * 4)) & 0xF); 317 | } else { 318 | return (GPIO_Mode_TypeDef) ((GPIO->P[port].MODEH >> ((pin - 8) * 4)) & 0xF); 319 | } 320 | } 321 | 322 | #if defined(_GPIO_EM4WUEN_MASK) 323 | /**************************************************************************//** 324 | * @brief 325 | * Enable GPIO pin wake-up from EM4. When the function exits, 326 | * EM4 mode can be safely entered. 327 | * 328 | * @note 329 | * It is assumed that the GPIO pin modes are set correctly. 330 | * Valid modes are @ref gpioModeInput and @ref gpioModeInputPull. 331 | * 332 | * @param[in] pinmask 333 | * Bitmask containing the bitwise logic OR of which GPIO pin(s) to enable. 334 | * Refer to Reference Manuals for pinmask to GPIO port/pin mapping. 335 | * @param[in] polaritymask 336 | * Bitmask containing the bitwise logic OR of GPIO pin(s) wake-up polarity. 337 | * Refer to Reference Manuals for pinmask to GPIO port/pin mapping. 338 | *****************************************************************************/ 339 | void GPIO_EM4EnablePinWakeup(uint32_t pinmask, uint32_t polaritymask) 340 | { 341 | EFM_ASSERT((pinmask & ~_GPIO_EM4WUEN_MASK) == 0); 342 | 343 | #if defined(_GPIO_EM4WUPOL_MASK) 344 | EFM_ASSERT((polaritymask & ~_GPIO_EM4WUPOL_MASK) == 0); 345 | GPIO->EM4WUPOL &= ~pinmask; /* Set wakeup polarity */ 346 | GPIO->EM4WUPOL |= pinmask & polaritymask; 347 | #elif defined(_GPIO_EXTILEVEL_MASK) 348 | EFM_ASSERT((polaritymask & ~_GPIO_EXTILEVEL_MASK) == 0); 349 | GPIO->EXTILEVEL &= ~pinmask; 350 | GPIO->EXTILEVEL |= pinmask & polaritymask; 351 | #endif 352 | GPIO->EM4WUEN |= pinmask; /* Enable wakeup */ 353 | 354 | GPIO_EM4SetPinRetention(true); /* Enable pin retention */ 355 | 356 | #if defined(_GPIO_CMD_EM4WUCLR_MASK) 357 | GPIO->CMD = GPIO_CMD_EM4WUCLR; /* Clear wake-up logic */ 358 | #elif defined(_GPIO_IFC_EM4WU_MASK) 359 | GPIO_IntClear(pinmask); 360 | #endif 361 | } 362 | #endif 363 | 364 | /** @} (end addtogroup GPIO) */ 365 | /** @} (end addtogroup emlib) */ 366 | 367 | #endif /* defined(GPIO_COUNT) && (GPIO_COUNT > 0) */ 368 | -------------------------------------------------------------------------------- /rf24tests/emlib/em_i2c.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file em_i2c.c 3 | * @brief Inter-integrated Circuit (I2C) Peripheral API 4 | * @version 5.2.2 5 | ******************************************************************************* 6 | * # License 7 | * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com 8 | ******************************************************************************* 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. 16 | * 2. Altered source versions must be plainly marked as such, and must not be 17 | * misrepresented as being the original software. 18 | * 3. This notice may not be removed or altered from any source distribution. 19 | * 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no 21 | * obligation to support this Software. Silicon Labs is providing the 22 | * Software "AS IS", with no express or implied warranties of any kind, 23 | * including, but not limited to, any implied warranties of merchantability 24 | * or fitness for any particular purpose or warranties against infringement 25 | * of any proprietary rights of a third party. 26 | * 27 | * Silicon Labs will not be liable for any consequential, incidental, or 28 | * special damages, or any other relief, or for any claim by any third party, 29 | * arising from your use of this Software. 30 | * 31 | ******************************************************************************/ 32 | 33 | #include "em_i2c.h" 34 | #if defined(I2C_COUNT) && (I2C_COUNT > 0) 35 | 36 | #include "em_cmu.h" 37 | #include "em_bus.h" 38 | #include "em_assert.h" 39 | 40 | #include 41 | 42 | /***************************************************************************//** 43 | * @addtogroup emlib 44 | * @{ 45 | ******************************************************************************/ 46 | 47 | /***************************************************************************//** 48 | * @addtogroup I2C 49 | * @brief Inter-integrated Circuit (I2C) Peripheral API 50 | * @details 51 | * This module contains functions to control the I2C peripheral of Silicon 52 | * Labs 32-bit MCUs and SoCs. The I2C interface allows communication on I2C 53 | * buses with the lowest energy consumption possible. 54 | * @{ 55 | ******************************************************************************/ 56 | 57 | /******************************************************************************* 58 | ******************************* DEFINES *********************************** 59 | ******************************************************************************/ 60 | 61 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 62 | 63 | /** Validation of I2C register block pointer reference for assert statements. */ 64 | #if (I2C_COUNT == 1) 65 | #define I2C_REF_VALID(ref) ((ref) == I2C0) 66 | #elif (I2C_COUNT == 2) 67 | #define I2C_REF_VALID(ref) ((ref == I2C0) || (ref == I2C1)) 68 | #elif (I2C_COUNT == 3) 69 | #define I2C_REF_VALID(ref) ((ref == I2C0) || (ref == I2C1) || (ref == I2C2)) 70 | #endif 71 | 72 | /** Error flags indicating I2C transfer has failed somehow. */ 73 | /* Notice that I2C_IF_TXOF (transmit overflow) is not really possible with */ 74 | /* this SW supporting master mode. Likewise for I2C_IF_RXUF (receive underflow) */ 75 | /* RXUF is only likely to occur with this SW if using a debugger peeking into */ 76 | /* RXDATA register. Thus, we ignore those types of fault. */ 77 | #define I2C_IF_ERRORS (I2C_IF_BUSERR | I2C_IF_ARBLOST) 78 | 79 | /* Max I2C transmission rate constant */ 80 | #if defined(_SILICON_LABS_32B_SERIES_0) 81 | #define I2C_CR_MAX 4 82 | #elif defined(_SILICON_LABS_32B_SERIES_1) 83 | #define I2C_CR_MAX 8 84 | #else 85 | #warning "Max I2C transmission rate constant is not defined" 86 | #endif 87 | 88 | /** @endcond */ 89 | 90 | /******************************************************************************* 91 | ******************************** ENUMS ************************************ 92 | ******************************************************************************/ 93 | 94 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 95 | 96 | /** Master mode transfer states. */ 97 | typedef enum { 98 | i2cStateStartAddrSend, /**< Send start + (first part of) address. */ 99 | i2cStateAddrWFAckNack, /**< Wait for ACK/NACK on (first part of) address. */ 100 | i2cStateAddrWF2ndAckNack, /**< Wait for ACK/NACK on second part of 10 bit address. */ 101 | i2cStateRStartAddrSend, /**< Send repeated start + (first part of) address. */ 102 | i2cStateRAddrWFAckNack, /**< Wait for ACK/NACK on address sent after repeated start. */ 103 | i2cStateDataSend, /**< Send data. */ 104 | i2cStateDataWFAckNack, /**< Wait for ACK/NACK on data sent. */ 105 | i2cStateWFData, /**< Wait for data. */ 106 | i2cStateWFStopSent, /**< Wait for STOP to have been transmitted. */ 107 | i2cStateDone /**< Transfer completed successfully. */ 108 | } I2C_TransferState_TypeDef; 109 | 110 | /** @endcond */ 111 | 112 | /******************************************************************************* 113 | ******************************* STRUCTS *********************************** 114 | ******************************************************************************/ 115 | 116 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 117 | 118 | /** Structure used to store state information on an ongoing master mode transfer. */ 119 | typedef struct { 120 | /** Current state. */ 121 | I2C_TransferState_TypeDef state; 122 | 123 | /** Result return code. */ 124 | I2C_TransferReturn_TypeDef result; 125 | 126 | /** Offset in current sequence buffer. */ 127 | uint16_t offset; 128 | 129 | /* Index to current sequence buffer in use. */ 130 | uint8_t bufIndx; 131 | 132 | /** Reference to I2C transfer sequence definition provided by user. */ 133 | I2C_TransferSeq_TypeDef *seq; 134 | } I2C_Transfer_TypeDef; 135 | 136 | /** @endcond */ 137 | 138 | /******************************************************************************* 139 | ***************************** LOCAL DATA *******^************************** 140 | ******************************************************************************/ 141 | 142 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 143 | 144 | /** 145 | * Lookup table for Nlow + Nhigh setting defined by CLHR. Set undefined 146 | * index (0x3) to reflect default setting just in case. 147 | */ 148 | static const uint8_t i2cNSum[] = { 4 + 4, 6 + 3, 11 + 6, 4 + 4 }; 149 | 150 | /** Transfer state info for ongoing master mode transfer */ 151 | static I2C_Transfer_TypeDef i2cTransfer[I2C_COUNT]; 152 | 153 | /** @endcond */ 154 | 155 | /******************************************************************************* 156 | ************************** GLOBAL FUNCTIONS ******************************* 157 | ******************************************************************************/ 158 | 159 | /***************************************************************************//** 160 | * @brief 161 | * Get current configured I2C bus frequency. 162 | * 163 | * @details 164 | * This frequency is only of relevance when acting as master. 165 | * 166 | * @param[in] i2c 167 | * Pointer to I2C peripheral register block. 168 | * 169 | * @return 170 | * Current I2C frequency in Hz. 171 | ******************************************************************************/ 172 | uint32_t I2C_BusFreqGet(I2C_TypeDef *i2c) 173 | { 174 | uint32_t freqHfper; 175 | uint32_t n; 176 | 177 | /* Max frequency is given by freqScl = freqHfper/((Nlow + Nhigh)(DIV + 1) + I2C_CR_MAX) 178 | * More details can be found in the reference manual, 179 | * I2C Clock Generation chapter. */ 180 | freqHfper = CMU_ClockFreqGet(cmuClock_HFPER); 181 | /* n = Nlow + Nhigh */ 182 | n = (uint32_t)(i2cNSum[(i2c->CTRL & _I2C_CTRL_CLHR_MASK) >> _I2C_CTRL_CLHR_SHIFT]); 183 | 184 | return (freqHfper / ((n * (i2c->CLKDIV + 1)) + I2C_CR_MAX)); 185 | } 186 | 187 | /***************************************************************************//** 188 | * @brief 189 | * Set I2C bus frequency. 190 | * 191 | * @details 192 | * The bus frequency is only of relevance when acting as a master. The bus 193 | * frequency should not be set higher than the max frequency accepted by the 194 | * slowest device on the bus. 195 | * 196 | * Notice that due to asymmetric requirements on low and high I2C clock 197 | * cycles by the I2C specification, the actual max frequency allowed in order 198 | * to comply with the specification may be somewhat lower than expected. 199 | * 200 | * Please refer to the reference manual, details on I2C clock generation, 201 | * for max allowed theoretical frequencies for different modes. 202 | * 203 | * @param[in] i2c 204 | * Pointer to I2C peripheral register block. 205 | * 206 | * @param[in] freqRef 207 | * I2C reference clock frequency in Hz that will be used. If set to 0, 208 | * then HFPER clock is used. Setting it to a higher than actual configured 209 | * value only has the consequence of reducing the real I2C frequency. 210 | * 211 | * @param[in] freqScl 212 | * Bus frequency to set (actual bus speed may be lower due to integer 213 | * prescaling). Safe (according to I2C specification) max frequencies for 214 | * standard, fast and fast+ modes are available using I2C_FREQ_ defines. 215 | * (Using I2C_FREQ_ defines requires corresponding setting of @p type.) 216 | * Slowest slave device on bus must always be considered. 217 | * 218 | * @param[in] i2cMode 219 | * Clock low to high ratio type to use. If not using i2cClockHLRStandard, 220 | * make sure all devices on the bus support the specified mode. Using a 221 | * non-standard ratio is useful to achieve higher bus clock in fast and 222 | * fast+ modes. 223 | ******************************************************************************/ 224 | void I2C_BusFreqSet(I2C_TypeDef *i2c, 225 | uint32_t freqRef, 226 | uint32_t freqScl, 227 | I2C_ClockHLR_TypeDef i2cMode) 228 | { 229 | uint32_t n, minFreq; 230 | int32_t div; 231 | 232 | /* Avoid divide by 0 */ 233 | EFM_ASSERT(freqScl); 234 | if (!freqScl) { 235 | return; 236 | } 237 | 238 | /* Set the CLHR (clock low to high ratio). */ 239 | i2c->CTRL &= ~_I2C_CTRL_CLHR_MASK; 240 | BUS_RegMaskedWrite(&i2c->CTRL, 241 | _I2C_CTRL_CLHR_MASK, 242 | i2cMode << _I2C_CTRL_CLHR_SHIFT); 243 | 244 | if (!freqRef) { 245 | freqRef = CMU_ClockFreqGet(cmuClock_HFPER); 246 | } 247 | 248 | /* Check minumum HF peripheral clock */ 249 | minFreq = UINT_MAX; 250 | if (i2c->CTRL & I2C_CTRL_SLAVE) { 251 | switch (i2cMode) { 252 | case i2cClockHLRStandard: 253 | #if defined(_SILICON_LABS_32B_SERIES_0) 254 | minFreq = 4200000; break; 255 | #elif defined(_SILICON_LABS_32B_SERIES_1) 256 | minFreq = 2000000; break; 257 | #endif 258 | case i2cClockHLRAsymetric: 259 | #if defined(_SILICON_LABS_32B_SERIES_0) 260 | minFreq = 11000000; break; 261 | #elif defined(_SILICON_LABS_32B_SERIES_1) 262 | minFreq = 5000000; break; 263 | #endif 264 | case i2cClockHLRFast: 265 | #if defined(_SILICON_LABS_32B_SERIES_0) 266 | minFreq = 24400000; break; 267 | #elif defined(_SILICON_LABS_32B_SERIES_1) 268 | minFreq = 14000000; break; 269 | #endif 270 | } 271 | } else { 272 | /* For master mode, platform 1 and 2 share the same 273 | min frequencies */ 274 | switch (i2cMode) { 275 | case i2cClockHLRStandard: 276 | minFreq = 2000000; break; 277 | case i2cClockHLRAsymetric: 278 | minFreq = 9000000; break; 279 | case i2cClockHLRFast: 280 | minFreq = 20000000; break; 281 | } 282 | } 283 | 284 | /* Frequency most be larger-than */ 285 | EFM_ASSERT(freqRef > minFreq); 286 | 287 | /* SCL frequency is given by 288 | * freqScl = freqRef/((Nlow + Nhigh) * (DIV + 1) + I2C_CR_MAX) 289 | * 290 | * Thus 291 | * DIV = ((freqRef - (I2C_CR_MAX * freqScl))/((Nlow + Nhigh) * freqScl)) - 1 292 | * 293 | * More details can be found in the reference manual, 294 | * I2C Clock Generation chapter. */ 295 | 296 | /* n = Nlow + Nhigh */ 297 | n = (uint32_t)(i2cNSum[i2cMode]); 298 | div = ((freqRef - (I2C_CR_MAX * freqScl)) / (n * freqScl)) - 1; 299 | EFM_ASSERT(div >= 0); 300 | EFM_ASSERT((uint32_t)div <= _I2C_CLKDIV_DIV_MASK); 301 | 302 | /* Clock divisor must be at least 1 in slave mode according to reference */ 303 | /* manual (in which case there is normally no need to set bus frequency). */ 304 | if ((i2c->CTRL & I2C_CTRL_SLAVE) && !div) { 305 | div = 1; 306 | } 307 | i2c->CLKDIV = (uint32_t)div; 308 | } 309 | 310 | /***************************************************************************//** 311 | * @brief 312 | * Enable/disable I2C. 313 | * 314 | * @note 315 | * After enabling the I2C (from being disabled), the I2C is in BUSY state. 316 | * 317 | * @param[in] i2c 318 | * Pointer to I2C peripheral register block. 319 | * 320 | * @param[in] enable 321 | * true to enable counting, false to disable. 322 | ******************************************************************************/ 323 | void I2C_Enable(I2C_TypeDef *i2c, bool enable) 324 | { 325 | EFM_ASSERT(I2C_REF_VALID(i2c)); 326 | 327 | BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_EN_SHIFT, enable); 328 | } 329 | 330 | /***************************************************************************//** 331 | * @brief 332 | * Initialize I2C. 333 | * 334 | * @param[in] i2c 335 | * Pointer to I2C peripheral register block. 336 | * 337 | * @param[in] init 338 | * Pointer to I2C initialization structure. 339 | ******************************************************************************/ 340 | void I2C_Init(I2C_TypeDef *i2c, const I2C_Init_TypeDef *init) 341 | { 342 | EFM_ASSERT(I2C_REF_VALID(i2c)); 343 | 344 | i2c->IEN = 0; 345 | i2c->IFC = _I2C_IFC_MASK; 346 | 347 | /* Set SLAVE select mode */ 348 | BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_SLAVE_SHIFT, init->master ? 0 : 1); 349 | 350 | I2C_BusFreqSet(i2c, init->refFreq, init->freq, init->clhr); 351 | 352 | BUS_RegBitWrite(&(i2c->CTRL), _I2C_CTRL_EN_SHIFT, init->enable); 353 | } 354 | 355 | /***************************************************************************//** 356 | * @brief 357 | * Reset I2C to same state as after a HW reset. 358 | * 359 | * @note 360 | * The ROUTE register is NOT reset by this function, in order to allow for 361 | * centralized setup of this feature. 362 | * 363 | * @param[in] i2c 364 | * Pointer to I2C peripheral register block. 365 | ******************************************************************************/ 366 | void I2C_Reset(I2C_TypeDef *i2c) 367 | { 368 | i2c->CTRL = _I2C_CTRL_RESETVALUE; 369 | i2c->CLKDIV = _I2C_CLKDIV_RESETVALUE; 370 | i2c->SADDR = _I2C_SADDR_RESETVALUE; 371 | i2c->SADDRMASK = _I2C_SADDRMASK_RESETVALUE; 372 | i2c->IEN = _I2C_IEN_RESETVALUE; 373 | i2c->IFC = _I2C_IFC_MASK; 374 | /* Do not reset route register, setting should be done independently */ 375 | } 376 | 377 | /***************************************************************************//** 378 | * @brief 379 | * Continue an initiated I2C transfer (single master mode only). 380 | * 381 | * @details 382 | * This function is used repeatedly after a I2C_TransferInit() in order to 383 | * complete a transfer. It may be used in polled mode as the below example 384 | * shows: 385 | * @verbatim 386 | * I2C_TransferReturn_TypeDef ret; 387 | * 388 | * // Do a polled transfer 389 | * ret = I2C_TransferInit(I2C0, seq); 390 | * while (ret == i2cTransferInProgress) 391 | * { 392 | * ret = I2C_Transfer(I2C0); 393 | * } 394 | * @endverbatim 395 | * It may also be used in interrupt driven mode, where this function is invoked 396 | * from the interrupt handler. Notice that if used in interrupt mode, NVIC 397 | * interrupts must be configured and enabled for the I2C bus used. I2C 398 | * peripheral specific interrupts are managed by this SW. 399 | * 400 | * @note 401 | * Only single master mode is supported. 402 | * 403 | * @param[in] i2c 404 | * Pointer to I2C peripheral register block. 405 | * 406 | * @return 407 | * Returns status for ongoing transfer. 408 | * @li #i2cTransferInProgress - indicates that transfer not finished. 409 | * @li #i2cTransferDone - transfer completed successfully. 410 | * @li otherwise some sort of error has occurred. 411 | * 412 | ******************************************************************************/ 413 | I2C_TransferReturn_TypeDef I2C_Transfer(I2C_TypeDef *i2c) 414 | { 415 | uint32_t tmp; 416 | uint32_t pending; 417 | I2C_Transfer_TypeDef *transfer; 418 | I2C_TransferSeq_TypeDef *seq; 419 | 420 | EFM_ASSERT(I2C_REF_VALID(i2c)); 421 | 422 | /* Support up to 2 I2C buses */ 423 | if (i2c == I2C0) { 424 | transfer = i2cTransfer; 425 | } 426 | #if (I2C_COUNT > 1) 427 | else if (i2c == I2C1) { 428 | transfer = i2cTransfer + 1; 429 | } 430 | #endif 431 | #if (I2C_COUNT > 2) 432 | else if (i2c == I2C2) { 433 | transfer = i2cTransfer + 2; 434 | } 435 | #endif 436 | else { 437 | return i2cTransferUsageFault; 438 | } 439 | 440 | seq = transfer->seq; 441 | for (;; ) { 442 | pending = i2c->IF; 443 | 444 | /* If some sort of fault, abort transfer. */ 445 | if (pending & I2C_IF_ERRORS) { 446 | if (pending & I2C_IF_ARBLOST) { 447 | /* If arbitration fault, it indicates either a slave device */ 448 | /* not responding as expected, or other master which is not */ 449 | /* supported by this SW. */ 450 | transfer->result = i2cTransferArbLost; 451 | } else if (pending & I2C_IF_BUSERR) { 452 | /* A bus error indicates a misplaced start or stop, which should */ 453 | /* not occur in master mode controlled by this SW. */ 454 | transfer->result = i2cTransferBusErr; 455 | } 456 | 457 | /* If error situation occurred, it is difficult to know */ 458 | /* exact cause and how to resolve. It will be up to a wrapper */ 459 | /* to determine how to handle a fault/recovery if possible. */ 460 | transfer->state = i2cStateDone; 461 | goto done; 462 | } 463 | 464 | switch (transfer->state) { 465 | /***************************************************/ 466 | /* Send first start+address (first byte if 10 bit) */ 467 | /***************************************************/ 468 | case i2cStateStartAddrSend: 469 | if (seq->flags & I2C_FLAG_10BIT_ADDR) { 470 | tmp = (((uint32_t)(seq->addr) >> 8) & 0x06) | 0xf0; 471 | 472 | /* In 10 bit address mode, the address following the first */ 473 | /* start always indicate write. */ 474 | } else { 475 | tmp = (uint32_t)(seq->addr) & 0xfe; 476 | 477 | if (seq->flags & I2C_FLAG_READ) { 478 | /* Indicate read request */ 479 | tmp |= 1; 480 | } 481 | } 482 | 483 | transfer->state = i2cStateAddrWFAckNack; 484 | i2c->TXDATA = tmp;/* Data not transmitted until START sent */ 485 | i2c->CMD = I2C_CMD_START; 486 | goto done; 487 | 488 | /*******************************************************/ 489 | /* Wait for ACK/NACK on address (first byte if 10 bit) */ 490 | /*******************************************************/ 491 | case i2cStateAddrWFAckNack: 492 | if (pending & I2C_IF_NACK) { 493 | i2c->IFC = I2C_IFC_NACK; 494 | transfer->result = i2cTransferNack; 495 | transfer->state = i2cStateWFStopSent; 496 | i2c->CMD = I2C_CMD_STOP; 497 | } else if (pending & I2C_IF_ACK) { 498 | i2c->IFC = I2C_IFC_ACK; 499 | 500 | /* If 10 bit address, send 2nd byte of address. */ 501 | if (seq->flags & I2C_FLAG_10BIT_ADDR) { 502 | transfer->state = i2cStateAddrWF2ndAckNack; 503 | i2c->TXDATA = (uint32_t)(seq->addr) & 0xff; 504 | } else { 505 | /* Determine whether receiving or sending data */ 506 | if (seq->flags & I2C_FLAG_READ) { 507 | transfer->state = i2cStateWFData; 508 | if (seq->buf[transfer->bufIndx].len == 1) { 509 | i2c->CMD = I2C_CMD_NACK; 510 | } 511 | } else { 512 | transfer->state = i2cStateDataSend; 513 | continue; 514 | } 515 | } 516 | } 517 | goto done; 518 | 519 | /******************************************************/ 520 | /* Wait for ACK/NACK on second byte of 10 bit address */ 521 | /******************************************************/ 522 | case i2cStateAddrWF2ndAckNack: 523 | if (pending & I2C_IF_NACK) { 524 | i2c->IFC = I2C_IFC_NACK; 525 | transfer->result = i2cTransferNack; 526 | transfer->state = i2cStateWFStopSent; 527 | i2c->CMD = I2C_CMD_STOP; 528 | } else if (pending & I2C_IF_ACK) { 529 | i2c->IFC = I2C_IFC_ACK; 530 | 531 | /* If using plain read sequence with 10 bit address, switch to send */ 532 | /* repeated start. */ 533 | if (seq->flags & I2C_FLAG_READ) { 534 | transfer->state = i2cStateRStartAddrSend; 535 | } 536 | /* Otherwise expected to write 0 or more bytes */ 537 | else { 538 | transfer->state = i2cStateDataSend; 539 | } 540 | continue; 541 | } 542 | goto done; 543 | 544 | /*******************************/ 545 | /* Send repeated start+address */ 546 | /*******************************/ 547 | case i2cStateRStartAddrSend: 548 | if (seq->flags & I2C_FLAG_10BIT_ADDR) { 549 | tmp = ((seq->addr >> 8) & 0x06) | 0xf0; 550 | } else { 551 | tmp = seq->addr & 0xfe; 552 | } 553 | 554 | /* If this is a write+read combined sequence, then read is about to start */ 555 | if (seq->flags & I2C_FLAG_WRITE_READ) { 556 | /* Indicate read request */ 557 | tmp |= 1; 558 | } 559 | 560 | transfer->state = i2cStateRAddrWFAckNack; 561 | /* We have to write START cmd first since repeated start, otherwise */ 562 | /* data would be sent first. */ 563 | i2c->CMD = I2C_CMD_START; 564 | i2c->TXDATA = tmp; 565 | goto done; 566 | 567 | /**********************************************************************/ 568 | /* Wait for ACK/NACK on repeated start+address (first byte if 10 bit) */ 569 | /**********************************************************************/ 570 | case i2cStateRAddrWFAckNack: 571 | if (pending & I2C_IF_NACK) { 572 | i2c->IFC = I2C_IFC_NACK; 573 | transfer->result = i2cTransferNack; 574 | transfer->state = i2cStateWFStopSent; 575 | i2c->CMD = I2C_CMD_STOP; 576 | } else if (pending & I2C_IF_ACK) { 577 | i2c->IFC = I2C_IFC_ACK; 578 | 579 | /* Determine whether receiving or sending data */ 580 | if (seq->flags & I2C_FLAG_WRITE_READ) { 581 | transfer->state = i2cStateWFData; 582 | } else { 583 | transfer->state = i2cStateDataSend; 584 | continue; 585 | } 586 | } 587 | goto done; 588 | 589 | /*****************************/ 590 | /* Send a data byte to slave */ 591 | /*****************************/ 592 | case i2cStateDataSend: 593 | /* Reached end of data buffer? */ 594 | if (transfer->offset >= seq->buf[transfer->bufIndx].len) { 595 | /* Move to next message part */ 596 | transfer->offset = 0; 597 | transfer->bufIndx++; 598 | 599 | /* Send repeated start when switching to read mode on 2nd buffer */ 600 | if (seq->flags & I2C_FLAG_WRITE_READ) { 601 | transfer->state = i2cStateRStartAddrSend; 602 | continue; 603 | } 604 | 605 | /* Only writing from one buffer, or finished both buffers */ 606 | if ((seq->flags & I2C_FLAG_WRITE) || (transfer->bufIndx > 1)) { 607 | transfer->state = i2cStateWFStopSent; 608 | i2c->CMD = I2C_CMD_STOP; 609 | goto done; 610 | } 611 | 612 | /* Reprocess in case next buffer is empty */ 613 | continue; 614 | } 615 | 616 | /* Send byte */ 617 | i2c->TXDATA = (uint32_t)(seq->buf[transfer->bufIndx].data[transfer->offset++]); 618 | transfer->state = i2cStateDataWFAckNack; 619 | goto done; 620 | 621 | /*********************************************************/ 622 | /* Wait for ACK/NACK from slave after sending data to it */ 623 | /*********************************************************/ 624 | case i2cStateDataWFAckNack: 625 | if (pending & I2C_IF_NACK) { 626 | i2c->IFC = I2C_IFC_NACK; 627 | transfer->result = i2cTransferNack; 628 | transfer->state = i2cStateWFStopSent; 629 | i2c->CMD = I2C_CMD_STOP; 630 | } else if (pending & I2C_IF_ACK) { 631 | i2c->IFC = I2C_IFC_ACK; 632 | transfer->state = i2cStateDataSend; 633 | continue; 634 | } 635 | goto done; 636 | 637 | /****************************/ 638 | /* Wait for data from slave */ 639 | /****************************/ 640 | case i2cStateWFData: 641 | if (pending & I2C_IF_RXDATAV) { 642 | uint8_t data; 643 | unsigned int rxLen = seq->buf[transfer->bufIndx].len; 644 | 645 | /* Must read out data in order to not block further progress */ 646 | data = (uint8_t)(i2c->RXDATA); 647 | 648 | /* Make sure not storing beyond end of buffer just in case */ 649 | if (transfer->offset < rxLen) { 650 | seq->buf[transfer->bufIndx].data[transfer->offset++] = data; 651 | } 652 | 653 | /* If we have read all requested data, then the sequence should end */ 654 | if (transfer->offset >= rxLen) { 655 | /* If there is only one byte to receive we need to transmit the 656 | NACK now, before the stop. */ 657 | if (1 == rxLen) { 658 | i2c->CMD = I2C_CMD_NACK; 659 | } 660 | 661 | transfer->state = i2cStateWFStopSent; 662 | i2c->CMD = I2C_CMD_STOP; 663 | } else { 664 | /* Send ACK and wait for next byte */ 665 | i2c->CMD = I2C_CMD_ACK; 666 | 667 | if ( (1 < rxLen) && (transfer->offset == (rxLen - 1)) ) { 668 | /* If there is more than one byte to receive and this is the next 669 | to last byte we need to transmit the NACK now, before receiving 670 | the last byte. */ 671 | i2c->CMD = I2C_CMD_NACK; 672 | } 673 | } 674 | } 675 | goto done; 676 | 677 | /***********************************/ 678 | /* Wait for STOP to have been sent */ 679 | /***********************************/ 680 | case i2cStateWFStopSent: 681 | if (pending & I2C_IF_MSTOP) { 682 | i2c->IFC = I2C_IFC_MSTOP; 683 | transfer->state = i2cStateDone; 684 | } 685 | goto done; 686 | 687 | /******************************/ 688 | /* Unexpected state, SW fault */ 689 | /******************************/ 690 | default: 691 | transfer->result = i2cTransferSwFault; 692 | transfer->state = i2cStateDone; 693 | goto done; 694 | } 695 | } 696 | 697 | done: 698 | 699 | if (transfer->state == i2cStateDone) { 700 | /* Disable interrupt sources when done */ 701 | i2c->IEN = 0; 702 | 703 | /* Update result unless some fault already occurred */ 704 | if (transfer->result == i2cTransferInProgress) { 705 | transfer->result = i2cTransferDone; 706 | } 707 | } 708 | /* Until transfer is done keep returning i2cTransferInProgress */ 709 | else { 710 | return i2cTransferInProgress; 711 | } 712 | 713 | return transfer->result; 714 | } 715 | 716 | /***************************************************************************//** 717 | * @brief 718 | * Prepare and start an I2C transfer (single master mode only). 719 | * 720 | * @details 721 | * This function must be invoked in order to start an I2C transfer 722 | * sequence. In order to actually complete the transfer, I2C_Transfer() must 723 | * be used either in polled mode or by adding a small driver wrapper utilizing 724 | * interrupts. 725 | * 726 | * @note 727 | * Only single master mode is supported. 728 | * 729 | * @param[in] i2c 730 | * Pointer to I2C peripheral register block. 731 | * 732 | * @param[in] seq 733 | * Pointer to sequence structure defining the I2C transfer to take place. The 734 | * referenced structure must exist until the transfer has fully completed. 735 | * 736 | * @return 737 | * Returns status for ongoing transfer: 738 | * @li #i2cTransferInProgress - indicates that transfer not finished. 739 | * @li otherwise some sort of error has occurred. 740 | ******************************************************************************/ 741 | I2C_TransferReturn_TypeDef I2C_TransferInit(I2C_TypeDef *i2c, 742 | I2C_TransferSeq_TypeDef *seq) 743 | { 744 | I2C_Transfer_TypeDef *transfer; 745 | 746 | EFM_ASSERT(I2C_REF_VALID(i2c)); 747 | EFM_ASSERT(seq); 748 | 749 | /* Support up to 2 I2C buses */ 750 | if (i2c == I2C0) { 751 | transfer = i2cTransfer; 752 | } 753 | #if (I2C_COUNT > 1) 754 | else if (i2c == I2C1) { 755 | transfer = i2cTransfer + 1; 756 | } 757 | #endif 758 | #if (I2C_COUNT > 2) 759 | else if (i2c == I2C2) { 760 | transfer = i2cTransfer + 2; 761 | } 762 | #endif 763 | else { 764 | return i2cTransferUsageFault; 765 | } 766 | 767 | /* Check if in busy state. Since this SW assumes single master, we can */ 768 | /* just issue an abort. The BUSY state is normal after a reset. */ 769 | if (i2c->STATE & I2C_STATE_BUSY) { 770 | i2c->CMD = I2C_CMD_ABORT; 771 | } 772 | 773 | /* Make sure user is not trying to read 0 bytes, it is not */ 774 | /* possible according to I2C spec, since slave will always start */ 775 | /* sending first byte ACK on address. The read operation can */ 776 | /* only be stopped by NACKing a received byte, ie minimum 1 byte. */ 777 | if (((seq->flags & I2C_FLAG_READ) && !(seq->buf[0].len)) 778 | || ((seq->flags & I2C_FLAG_WRITE_READ) && !(seq->buf[1].len)) 779 | ) { 780 | return i2cTransferUsageFault; 781 | } 782 | 783 | /* Prepare for a transfer */ 784 | transfer->state = i2cStateStartAddrSend; 785 | transfer->result = i2cTransferInProgress; 786 | transfer->offset = 0; 787 | transfer->bufIndx = 0; 788 | transfer->seq = seq; 789 | 790 | /* Ensure buffers are empty */ 791 | i2c->CMD = I2C_CMD_CLEARPC | I2C_CMD_CLEARTX; 792 | if (i2c->IF & I2C_IF_RXDATAV) { 793 | (void)i2c->RXDATA; 794 | } 795 | 796 | /* Clear all pending interrupts prior to starting transfer. */ 797 | i2c->IFC = _I2C_IFC_MASK; 798 | 799 | /* Enable those interrupts we are interested in throughout transfer. */ 800 | /* Notice that the I2C interrupt must also be enabled in the NVIC, but */ 801 | /* that is left for an additional driver wrapper. */ 802 | i2c->IEN |= I2C_IF_NACK | I2C_IF_ACK | I2C_IF_MSTOP 803 | | I2C_IF_RXDATAV | I2C_IF_ERRORS; 804 | 805 | /* Start transfer */ 806 | return I2C_Transfer(i2c); 807 | } 808 | 809 | /** @} (end addtogroup I2C) */ 810 | /** @} (end addtogroup emlib) */ 811 | #endif /* defined(I2C_COUNT) && (I2C_COUNT > 0) */ 812 | -------------------------------------------------------------------------------- /rf24tests/emlib/em_rtc.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file em_rtc.c 3 | * @brief Real Time Counter (RTC) Peripheral API 4 | * @version 5.2.2 5 | ******************************************************************************* 6 | * # License 7 | * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com 8 | ******************************************************************************* 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. 16 | * 2. Altered source versions must be plainly marked as such, and must not be 17 | * misrepresented as being the original software. 18 | * 3. This notice may not be removed or altered from any source distribution. 19 | * 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no 21 | * obligation to support this Software. Silicon Labs is providing the 22 | * Software "AS IS", with no express or implied warranties of any kind, 23 | * including, but not limited to, any implied warranties of merchantability 24 | * or fitness for any particular purpose or warranties against infringement 25 | * of any proprietary rights of a third party. 26 | * 27 | * Silicon Labs will not be liable for any consequential, incidental, or 28 | * special damages, or any other relief, or for any claim by any third party, 29 | * arising from your use of this Software. 30 | * 31 | ******************************************************************************/ 32 | 33 | #include "em_rtc.h" 34 | #if defined(RTC_COUNT) && (RTC_COUNT > 0) 35 | 36 | #include "em_assert.h" 37 | #include "em_bus.h" 38 | 39 | /***************************************************************************//** 40 | * @addtogroup emlib 41 | * @{ 42 | ******************************************************************************/ 43 | 44 | /***************************************************************************//** 45 | * @addtogroup RTC 46 | * @brief Real Time Counter (RTC) Peripheral API 47 | * @details 48 | * This module contains functions to control the RTC peripheral of Silicon 49 | * Labs 32-bit MCUs and SoCs. The RTC ensures timekeeping in low energy modes. 50 | * @{ 51 | ******************************************************************************/ 52 | 53 | /******************************************************************************* 54 | ******************************* DEFINES *********************************** 55 | ******************************************************************************/ 56 | 57 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 58 | 59 | /** Validation of valid comparator register for assert statements. */ 60 | #define RTC_COMP_REG_VALID(reg) (((reg) <= 1)) 61 | 62 | /** @endcond */ 63 | 64 | /******************************************************************************* 65 | ************************** LOCAL FUNCTIONS ******************************** 66 | ******************************************************************************/ 67 | 68 | /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */ 69 | 70 | #if defined(_EFM32_GECKO_FAMILY) 71 | /***************************************************************************//** 72 | * @brief 73 | * Wait for ongoing sync of register(s) to low frequency domain to complete. 74 | * 75 | * @note 76 | * This only applies to the Gecko Family, see the reference manual 77 | * chapter about Access to Low Energy Peripherals (Asynchronos Registers) 78 | * for details. For Tiny Gecko and Giant Gecko, the RTC supports immediate 79 | * updates of registers, and will automatically hold the bus until the 80 | * register has been updated. 81 | * 82 | * @param[in] mask 83 | * Bitmask corresponding to SYNCBUSY register defined bits, indicating 84 | * registers that must complete any ongoing synchronization. 85 | ******************************************************************************/ 86 | __STATIC_INLINE void regSync(uint32_t mask) 87 | { 88 | /* Avoid deadlock if modifying the same register twice when freeze mode is */ 89 | /* activated. */ 90 | if (RTC->FREEZE & RTC_FREEZE_REGFREEZE) { 91 | return; 92 | } 93 | 94 | /* Wait for any pending previous write operation to have been completed */ 95 | /* in low frequency domain. This is only required for the Gecko Family */ 96 | while (RTC->SYNCBUSY & mask) 97 | ; 98 | } 99 | #endif 100 | 101 | /** @endcond */ 102 | 103 | /******************************************************************************* 104 | ************************** GLOBAL FUNCTIONS ******************************* 105 | ******************************************************************************/ 106 | 107 | /***************************************************************************//** 108 | * @brief 109 | * Get RTC compare register value. 110 | * 111 | * @param[in] comp 112 | * Compare register to get, either 0 or 1 113 | * 114 | * @return 115 | * Compare register value, 0 if invalid register selected. 116 | ******************************************************************************/ 117 | uint32_t RTC_CompareGet(unsigned int comp) 118 | { 119 | uint32_t ret; 120 | 121 | EFM_ASSERT(RTC_COMP_REG_VALID(comp)); 122 | 123 | #if defined(_RTC_COMP_COMP_MASK) 124 | ret = RTC->COMP[comp].COMP; 125 | #elif defined(_RTC_COMP0_MASK) 126 | /* Initialize selected compare value */ 127 | switch (comp) { 128 | case 0: 129 | ret = RTC->COMP0; 130 | break; 131 | 132 | case 1: 133 | ret = RTC->COMP1; 134 | break; 135 | 136 | default: 137 | /* Unknown compare register selected */ 138 | ret = 0; 139 | break; 140 | } 141 | #endif 142 | return ret; 143 | } 144 | 145 | /***************************************************************************//** 146 | * @brief 147 | * Set RTC compare register value. 148 | * 149 | * @note 150 | * The setting of a compare register requires synchronization into the 151 | * low frequency domain. If the same register is modified before a previous 152 | * update has completed, this function will stall until the previous 153 | * synchronization has completed. This only applies to the Gecko Family, see 154 | * comment in the regSync() internal function call. 155 | * 156 | * @param[in] comp 157 | * Compare register to set, either 0 or 1 158 | * 159 | * @param[in] value 160 | * Initialization value (<= 0x00ffffff) 161 | ******************************************************************************/ 162 | void RTC_CompareSet(unsigned int comp, uint32_t value) 163 | { 164 | volatile uint32_t *compReg; 165 | #if defined(_EFM32_GECKO_FAMILY) 166 | uint32_t syncbusy; 167 | #endif 168 | 169 | EFM_ASSERT(RTC_COMP_REG_VALID(comp)); 170 | 171 | #if defined(_RTC_COMP_COMP_COMP_MASK) 172 | EFM_ASSERT((value & ~(_RTC_COMP_COMP_COMP_MASK >> _RTC_COMP_COMP_COMP_SHIFT)) == 0); 173 | #elif defined(_RTC_COMP0_COMP0_MASK) 174 | EFM_ASSERT((value & ~(_RTC_COMP0_COMP0_MASK >> _RTC_COMP0_COMP0_SHIFT)) == 0); 175 | #endif 176 | 177 | #if defined(_RTC_COMP_COMP_MASK) 178 | compReg = &(RTC->COMP[comp].COMP); 179 | #elif defined(_RTC_COMP0_MASK) 180 | /* Initialize selected compare value */ 181 | switch (comp) { 182 | case 0: 183 | compReg = &(RTC->COMP0); 184 | #if defined(_EFM32_GECKO_FAMILY) 185 | syncbusy = RTC_SYNCBUSY_COMP0; 186 | #endif 187 | break; 188 | 189 | case 1: 190 | compReg = &(RTC->COMP1); 191 | #if defined(_EFM32_GECKO_FAMILY) 192 | syncbusy = RTC_SYNCBUSY_COMP1; 193 | #endif 194 | break; 195 | 196 | default: 197 | /* Unknown compare register selected, abort */ 198 | return; 199 | } 200 | #endif 201 | 202 | #if defined(_EFM32_GECKO_FAMILY) 203 | /* LF register about to be modified require sync. busy check */ 204 | regSync(syncbusy); 205 | #endif 206 | 207 | *compReg = value; 208 | } 209 | 210 | /***************************************************************************//** 211 | * @brief 212 | * Enable/disable RTC. 213 | * 214 | * @note 215 | * The enabling/disabling of the RTC modifies the RTC CTRL register which 216 | * requires synchronization into the low frequency domain. If this register is 217 | * modified before a previous update to the same register has completed, this 218 | * function will stall until the previous synchronization has completed. This 219 | * only applies to the Gecko Family, see comment in the regSync() internal 220 | * function call. 221 | * 222 | * @param[in] enable 223 | * true to enable counting, false to disable. 224 | ******************************************************************************/ 225 | void RTC_Enable(bool enable) 226 | { 227 | #if defined(_EFM32_GECKO_FAMILY) 228 | /* LF register about to be modified require sync. busy check */ 229 | regSync(RTC_SYNCBUSY_CTRL); 230 | #endif 231 | 232 | BUS_RegBitWrite(&(RTC->CTRL), _RTC_CTRL_EN_SHIFT, enable); 233 | 234 | #if defined(_EFM32_GECKO_FAMILY) 235 | /* Wait for CTRL to be updated before returning, because calling code may 236 | depend upon that the CTRL register is updated after this function has 237 | returned. */ 238 | regSync(RTC_SYNCBUSY_CTRL); 239 | #endif 240 | } 241 | 242 | #if defined(_RTC_FREEZE_MASK) 243 | /***************************************************************************//** 244 | * @brief 245 | * RTC register synchronization freeze control. 246 | * 247 | * @details 248 | * Some RTC registers require synchronization into the low frequency (LF) 249 | * domain. The freeze feature allows for several such registers to be 250 | * modified before passing them to the LF domain simultaneously (which 251 | * takes place when the freeze mode is disabled). 252 | * 253 | * @note 254 | * When enabling freeze mode, this function will wait for all current 255 | * ongoing RTC synchronization to LF domain to complete (Normally 256 | * synchronization will not be in progress.) However for this reason, when 257 | * using freeze mode, modifications of registers requiring LF synchronization 258 | * should be done within one freeze enable/disable block to avoid unecessary 259 | * stalling. This only applies to the Gecko Family, see the reference manual 260 | * chapter about Access to Low Energy Peripherals (Asynchronos Registers) 261 | * for details. 262 | * 263 | * @param[in] enable 264 | * @li true - enable freeze, modified registers are not propagated to the 265 | * LF domain 266 | * @li false - disables freeze, modified registers are propagated to LF 267 | * domain 268 | ******************************************************************************/ 269 | void RTC_FreezeEnable(bool enable) 270 | { 271 | if (enable) { 272 | #if defined(_EFM32_GECKO_FAMILY) 273 | /* Wait for any ongoing LF synchronization to complete. This is just to */ 274 | /* protect against the rare case when a user */ 275 | /* - modifies a register requiring LF sync */ 276 | /* - then enables freeze before LF sync completed */ 277 | /* - then modifies the same register again */ 278 | /* since modifying a register while it is in sync progress should be */ 279 | /* avoided. */ 280 | while (RTC->SYNCBUSY) 281 | ; 282 | #endif 283 | RTC->FREEZE = RTC_FREEZE_REGFREEZE; 284 | } else { 285 | RTC->FREEZE = 0; 286 | } 287 | } 288 | #endif 289 | 290 | /***************************************************************************//** 291 | * @brief 292 | * Initialize RTC. 293 | * 294 | * @details 295 | * Note that the compare values must be set separately with RTC_CompareSet(). 296 | * That should probably be done prior to the use of this function if 297 | * configuring the RTC to start when initialization is completed. 298 | * 299 | * @note 300 | * The initialization of the RTC modifies the RTC CTRL register which requires 301 | * synchronization into the low frequency domain. If this register is 302 | * modified before a previous update to the same register has completed, this 303 | * function will stall until the previous synchronization has completed. This 304 | * only applies to the Gecko Family, see comment in the regSync() internal 305 | * function call. 306 | * 307 | * @param[in] init 308 | * Pointer to RTC initialization structure. 309 | ******************************************************************************/ 310 | void RTC_Init(const RTC_Init_TypeDef *init) 311 | { 312 | uint32_t tmp; 313 | 314 | if (init->enable) { 315 | tmp = RTC_CTRL_EN; 316 | } else { 317 | tmp = 0; 318 | } 319 | 320 | /* Configure DEBUGRUN flag, sets whether or not counter should be 321 | * updated when debugger is active */ 322 | if (init->debugRun) { 323 | tmp |= RTC_CTRL_DEBUGRUN; 324 | } 325 | 326 | /* Configure COMP0TOP, this will use the COMP0 compare value as an 327 | * overflow value, instead of default 24-bit 0x00ffffff */ 328 | if (init->comp0Top) { 329 | tmp |= RTC_CTRL_COMP0TOP; 330 | } 331 | 332 | #if defined(_EFM32_GECKO_FAMILY) 333 | /* LF register about to be modified require sync. busy check */ 334 | regSync(RTC_SYNCBUSY_CTRL); 335 | #endif 336 | 337 | RTC->CTRL = tmp; 338 | } 339 | 340 | /***************************************************************************//** 341 | * @brief 342 | * Restore RTC to reset state 343 | ******************************************************************************/ 344 | void RTC_Reset(void) 345 | { 346 | /* Restore all essential RTC register to default config */ 347 | #if defined(_RTC_FREEZE_MASK) 348 | RTC->FREEZE = _RTC_FREEZE_RESETVALUE; 349 | #endif 350 | RTC->CTRL = _RTC_CTRL_RESETVALUE; 351 | #if defined(_RTC_COMP_COMP_MASK) 352 | RTC->COMP[0].COMP = _RTC_COMP_COMP_RESETVALUE; 353 | RTC->COMP[1].COMP = _RTC_COMP_COMP_RESETVALUE; 354 | #elif defined(_RTC_COMP0_MASK) 355 | RTC->COMP0 = _RTC_COMP0_RESETVALUE; 356 | RTC->COMP1 = _RTC_COMP1_RESETVALUE; 357 | #endif 358 | RTC->IEN = _RTC_IEN_RESETVALUE; 359 | RTC->IFC = _RTC_IFC_RESETVALUE; 360 | 361 | #if defined(_EFM32_GECKO_FAMILY) 362 | /* Wait for CTRL, COMP0 and COMP1 to be updated before returning, because the 363 | calling code may depend upon that the register values are updated after 364 | this function has returned. */ 365 | regSync(RTC_SYNCBUSY_CTRL | RTC_SYNCBUSY_COMP0 | RTC_SYNCBUSY_COMP1); 366 | #endif 367 | } 368 | 369 | /***************************************************************************//** 370 | * @brief 371 | * Restart RTC counter from zero 372 | ******************************************************************************/ 373 | void RTC_CounterReset(void) 374 | { 375 | /* A disable/enable sequnce will start the counter at zero */ 376 | RTC_Enable(false); 377 | RTC_Enable(true); 378 | } 379 | 380 | /** @} (end addtogroup RTC) */ 381 | /** @} (end addtogroup emlib) */ 382 | #endif /* defined(RTC_COUNT) && (RTC_COUNT > 0) */ 383 | -------------------------------------------------------------------------------- /rf24tests/emlib/em_system.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file em_system.c 3 | * @brief System Peripheral API 4 | * @version 5.2.2 5 | ******************************************************************************* 6 | * # License 7 | * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com 8 | ******************************************************************************* 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. 16 | * 2. Altered source versions must be plainly marked as such, and must not be 17 | * misrepresented as being the original software. 18 | * 3. This notice may not be removed or altered from any source distribution. 19 | * 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no 21 | * obligation to support this Software. Silicon Labs is providing the 22 | * Software "AS IS", with no express or implied warranties of any kind, 23 | * including, but not limited to, any implied warranties of merchantability 24 | * or fitness for any particular purpose or warranties against infringement 25 | * of any proprietary rights of a third party. 26 | * 27 | * Silicon Labs will not be liable for any consequential, incidental, or 28 | * special damages, or any other relief, or for any claim by any third party, 29 | * arising from your use of this Software. 30 | * 31 | ******************************************************************************/ 32 | 33 | #include "em_system.h" 34 | #include "em_assert.h" 35 | #include 36 | 37 | /***************************************************************************//** 38 | * @addtogroup emlib 39 | * @{ 40 | ******************************************************************************/ 41 | 42 | /***************************************************************************//** 43 | * @addtogroup SYSTEM 44 | * @{ 45 | ******************************************************************************/ 46 | 47 | /******************************************************************************* 48 | ************************** GLOBAL FUNCTIONS ******************************* 49 | ******************************************************************************/ 50 | 51 | /***************************************************************************//** 52 | * @brief 53 | * Get chip major/minor revision. 54 | * 55 | * @param[out] rev 56 | * Location to place chip revision info. 57 | ******************************************************************************/ 58 | void SYSTEM_ChipRevisionGet(SYSTEM_ChipRevision_TypeDef *rev) 59 | { 60 | uint8_t tmp; 61 | 62 | EFM_ASSERT(rev); 63 | 64 | /* CHIP FAMILY bit [5:2] */ 65 | tmp = (((ROMTABLE->PID1 & _ROMTABLE_PID1_FAMILYMSB_MASK) >> _ROMTABLE_PID1_FAMILYMSB_SHIFT) << 2); 66 | /* CHIP FAMILY bit [1:0] */ 67 | tmp |= ((ROMTABLE->PID0 & _ROMTABLE_PID0_FAMILYLSB_MASK) >> _ROMTABLE_PID0_FAMILYLSB_SHIFT); 68 | rev->family = tmp; 69 | 70 | /* CHIP MAJOR bit [3:0] */ 71 | rev->major = (ROMTABLE->PID0 & _ROMTABLE_PID0_REVMAJOR_MASK) >> _ROMTABLE_PID0_REVMAJOR_SHIFT; 72 | 73 | /* CHIP MINOR bit [7:4] */ 74 | tmp = (((ROMTABLE->PID2 & _ROMTABLE_PID2_REVMINORMSB_MASK) >> _ROMTABLE_PID2_REVMINORMSB_SHIFT) << 4); 75 | /* CHIP MINOR bit [3:0] */ 76 | tmp |= ((ROMTABLE->PID3 & _ROMTABLE_PID3_REVMINORLSB_MASK) >> _ROMTABLE_PID3_REVMINORLSB_SHIFT); 77 | rev->minor = tmp; 78 | } 79 | 80 | /***************************************************************************//** 81 | * @brief 82 | * Get factory calibration value for a given peripheral register. 83 | * 84 | * @param[in] regAddress 85 | * Peripheral calibration register address to get calibration value for. If 86 | * a calibration value is found then this register is updated with the 87 | * calibration value. 88 | * 89 | * @return 90 | * True if a calibration value exists, false otherwise. 91 | ******************************************************************************/ 92 | bool SYSTEM_GetCalibrationValue(volatile uint32_t *regAddress) 93 | { 94 | SYSTEM_CalAddrVal_TypeDef * p, * end; 95 | 96 | p = (SYSTEM_CalAddrVal_TypeDef *)(DEVINFO_BASE & 0xFFFFF000); 97 | end = (SYSTEM_CalAddrVal_TypeDef *)DEVINFO_BASE; 98 | 99 | for (; p < end; p++) { 100 | if (p->address == 0xFFFFFFFF) { 101 | /* Found table terminator */ 102 | return false; 103 | } 104 | if (p->address == (uint32_t)regAddress) { 105 | *regAddress = p->calValue; 106 | return true; 107 | } 108 | } 109 | /* Nothing found for regAddress */ 110 | return false; 111 | } 112 | 113 | /** @} (end addtogroup SYSTEM) */ 114 | /** @} (end addtogroup emlib) */ 115 | -------------------------------------------------------------------------------- /rf24tests/emlib/em_timer.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file em_timer.c 3 | * @brief Timer/counter (TIMER) Peripheral API 4 | * @version 5.2.2 5 | ******************************************************************************* 6 | * # License 7 | * Copyright 2016 Silicon Laboratories, Inc. http://www.silabs.com 8 | ******************************************************************************* 9 | * 10 | * Permission is granted to anyone to use this software for any purpose, 11 | * including commercial applications, and to alter it and redistribute it 12 | * freely, subject to the following restrictions: 13 | * 14 | * 1. The origin of this software must not be misrepresented; you must not 15 | * claim that you wrote the original software. 16 | * 2. Altered source versions must be plainly marked as such, and must not be 17 | * misrepresented as being the original software. 18 | * 3. This notice may not be removed or altered from any source distribution. 19 | * 20 | * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Silicon Labs has no 21 | * obligation to support this Software. Silicon Labs is providing the 22 | * Software "AS IS", with no express or implied warranties of any kind, 23 | * including, but not limited to, any implied warranties of merchantability 24 | * or fitness for any particular purpose or warranties against infringement 25 | * of any proprietary rights of a third party. 26 | * 27 | * Silicon Labs will not be liable for any consequential, incidental, or 28 | * special damages, or any other relief, or for any claim by any third party, 29 | * arising from your use of this Software. 30 | * 31 | ******************************************************************************/ 32 | 33 | #include "em_timer.h" 34 | #if defined(TIMER_COUNT) && (TIMER_COUNT > 0) 35 | 36 | #include "em_assert.h" 37 | 38 | /***************************************************************************//** 39 | * @addtogroup emlib 40 | * @{ 41 | ******************************************************************************/ 42 | 43 | /***************************************************************************//** 44 | * @addtogroup TIMER 45 | * @brief Timer/Counter (TIMER) Peripheral API 46 | * @details 47 | * The timer module consists of three main parts: 48 | * @li General timer config and enable control. 49 | * @li Compare/capture control. 50 | * @li Dead time insertion control (may not be available for all timers). 51 | * @{ 52 | ******************************************************************************/ 53 | 54 | /******************************************************************************* 55 | ************************** GLOBAL FUNCTIONS ******************************* 56 | ******************************************************************************/ 57 | 58 | /***************************************************************************//** 59 | * @brief 60 | * Initialize TIMER. 61 | * 62 | * @details 63 | * Notice that counter top must be configured separately with for instance 64 | * TIMER_TopSet(). In addition, compare/capture and dead-time insertion 65 | * init must be initialized separately if used. That should probably 66 | * be done prior to the use of this function if configuring the TIMER to 67 | * start when initialization is completed. 68 | * 69 | * @param[in] timer 70 | * Pointer to TIMER peripheral register block. 71 | * 72 | * @param[in] init 73 | * Pointer to TIMER initialization structure. 74 | ******************************************************************************/ 75 | void TIMER_Init(TIMER_TypeDef *timer, const TIMER_Init_TypeDef *init) 76 | { 77 | EFM_ASSERT(TIMER_REF_VALID(timer)); 78 | 79 | /* Stop timer if specified to be disabled (dosn't hurt if already stopped) */ 80 | if (!(init->enable)) { 81 | timer->CMD = TIMER_CMD_STOP; 82 | } 83 | 84 | /* Reset counter */ 85 | timer->CNT = _TIMER_CNT_RESETVALUE; 86 | 87 | timer->CTRL = ((uint32_t)(init->prescale) << _TIMER_CTRL_PRESC_SHIFT) 88 | | ((uint32_t)(init->clkSel) << _TIMER_CTRL_CLKSEL_SHIFT) 89 | | ((uint32_t)(init->fallAction) << _TIMER_CTRL_FALLA_SHIFT) 90 | | ((uint32_t)(init->riseAction) << _TIMER_CTRL_RISEA_SHIFT) 91 | | ((uint32_t)(init->mode) << _TIMER_CTRL_MODE_SHIFT) 92 | | (init->debugRun ? TIMER_CTRL_DEBUGRUN : 0) 93 | | (init->dmaClrAct ? TIMER_CTRL_DMACLRACT : 0) 94 | | (init->quadModeX4 ? TIMER_CTRL_QDM_X4 : 0) 95 | | (init->oneShot ? TIMER_CTRL_OSMEN : 0) 96 | 97 | #if defined(TIMER_CTRL_X2CNT) && defined(TIMER_CTRL_ATI) 98 | | (init->count2x ? TIMER_CTRL_X2CNT : 0) 99 | | (init->ati ? TIMER_CTRL_ATI : 0) 100 | #endif 101 | | (init->sync ? TIMER_CTRL_SYNC : 0); 102 | 103 | /* Start timer if specified to be enabled (dosn't hurt if already started) */ 104 | if (init->enable) { 105 | timer->CMD = TIMER_CMD_START; 106 | } 107 | } 108 | 109 | /***************************************************************************//** 110 | * @brief 111 | * Initialize TIMER compare/capture channel. 112 | * 113 | * @details 114 | * Notice that if operating channel in compare mode, the CCV and CCVB register 115 | * must be set separately as required. 116 | * 117 | * @param[in] timer 118 | * Pointer to TIMER peripheral register block. 119 | * 120 | * @param[in] ch 121 | * Compare/capture channel to init for. 122 | * 123 | * @param[in] init 124 | * Pointer to TIMER initialization structure. 125 | ******************************************************************************/ 126 | void TIMER_InitCC(TIMER_TypeDef *timer, 127 | unsigned int ch, 128 | const TIMER_InitCC_TypeDef *init) 129 | { 130 | EFM_ASSERT(TIMER_REF_VALID(timer)); 131 | EFM_ASSERT(TIMER_CH_VALID(ch)); 132 | 133 | timer->CC[ch].CTRL = 134 | ((uint32_t)(init->eventCtrl) << _TIMER_CC_CTRL_ICEVCTRL_SHIFT) 135 | | ((uint32_t)(init->edge) << _TIMER_CC_CTRL_ICEDGE_SHIFT) 136 | | ((uint32_t)(init->prsSel) << _TIMER_CC_CTRL_PRSSEL_SHIFT) 137 | | ((uint32_t)(init->cufoa) << _TIMER_CC_CTRL_CUFOA_SHIFT) 138 | | ((uint32_t)(init->cofoa) << _TIMER_CC_CTRL_COFOA_SHIFT) 139 | | ((uint32_t)(init->cmoa) << _TIMER_CC_CTRL_CMOA_SHIFT) 140 | | ((uint32_t)(init->mode) << _TIMER_CC_CTRL_MODE_SHIFT) 141 | | (init->filter ? TIMER_CC_CTRL_FILT_ENABLE : 0) 142 | | (init->prsInput ? TIMER_CC_CTRL_INSEL_PRS : 0) 143 | | (init->coist ? TIMER_CC_CTRL_COIST : 0) 144 | | (init->outInvert ? TIMER_CC_CTRL_OUTINV : 0); 145 | } 146 | 147 | #if defined(_TIMER_DTCTRL_MASK) 148 | /***************************************************************************//** 149 | * @brief 150 | * Initialize the TIMER DTI unit. 151 | * 152 | * @param[in] timer 153 | * Pointer to TIMER peripheral register block. 154 | * 155 | * @param[in] init 156 | * Pointer to TIMER DTI initialization structure. 157 | ******************************************************************************/ 158 | void TIMER_InitDTI(TIMER_TypeDef *timer, const TIMER_InitDTI_TypeDef *init) 159 | { 160 | EFM_ASSERT(TIMER0 == timer); 161 | 162 | /* Make sure the DTI unit is disabled while initializing. */ 163 | TIMER_EnableDTI(timer, false); 164 | 165 | /* Setup the DTCTRL register. 166 | The enable bit will be set at the end of the function if specified. */ 167 | timer->DTCTRL = 168 | (init->autoRestart ? TIMER_DTCTRL_DTDAS : 0) 169 | | (init->activeLowOut ? TIMER_DTCTRL_DTIPOL : 0) 170 | | (init->invertComplementaryOut ? TIMER_DTCTRL_DTCINV : 0) 171 | | (init->enablePrsSource ? TIMER_DTCTRL_DTPRSEN : 0) 172 | | ((uint32_t)(init->prsSel) << _TIMER_DTCTRL_DTPRSSEL_SHIFT); 173 | 174 | /* Setup the DTTIME register. */ 175 | timer->DTTIME = 176 | ((uint32_t)(init->prescale) << _TIMER_DTTIME_DTPRESC_SHIFT) 177 | | ((uint32_t)(init->riseTime) << _TIMER_DTTIME_DTRISET_SHIFT) 178 | | ((uint32_t)(init->fallTime) << _TIMER_DTTIME_DTFALLT_SHIFT); 179 | 180 | /* Setup the DTFC register. */ 181 | timer->DTFC = 182 | (init->enableFaultSourceCoreLockup ? TIMER_DTFC_DTLOCKUPFEN : 0) 183 | | (init->enableFaultSourceDebugger ? TIMER_DTFC_DTDBGFEN : 0) 184 | | (init->enableFaultSourcePrsSel0 ? TIMER_DTFC_DTPRS0FEN : 0) 185 | | (init->enableFaultSourcePrsSel1 ? TIMER_DTFC_DTPRS1FEN : 0) 186 | | ((uint32_t)(init->faultAction) << _TIMER_DTFC_DTFA_SHIFT) 187 | | ((uint32_t)(init->faultSourcePrsSel0) << _TIMER_DTFC_DTPRS0FSEL_SHIFT) 188 | | ((uint32_t)(init->faultSourcePrsSel1) << _TIMER_DTFC_DTPRS1FSEL_SHIFT); 189 | 190 | /* Setup the DTOGEN register. */ 191 | timer->DTOGEN = init->outputsEnableMask; 192 | 193 | /* Clear any previous DTI faults. */ 194 | TIMER_ClearDTIFault(timer, TIMER_GetDTIFault(timer)); 195 | 196 | /* Enable/disable before returning. */ 197 | TIMER_EnableDTI(timer, init->enable); 198 | } 199 | #endif 200 | 201 | /***************************************************************************//** 202 | * @brief 203 | * Reset TIMER to same state as after a HW reset. 204 | * 205 | * @note 206 | * The ROUTE register is NOT reset by this function, in order to allow for 207 | * centralized setup of this feature. 208 | * 209 | * @param[in] timer 210 | * Pointer to TIMER peripheral register block. 211 | ******************************************************************************/ 212 | void TIMER_Reset(TIMER_TypeDef *timer) 213 | { 214 | int i; 215 | 216 | EFM_ASSERT(TIMER_REF_VALID(timer)); 217 | 218 | /* Make sure disabled first, before resetting other registers */ 219 | timer->CMD = TIMER_CMD_STOP; 220 | 221 | timer->CTRL = _TIMER_CTRL_RESETVALUE; 222 | timer->IEN = _TIMER_IEN_RESETVALUE; 223 | timer->IFC = _TIMER_IFC_MASK; 224 | timer->TOPB = _TIMER_TOPB_RESETVALUE; 225 | /* Write TOP after TOPB to invalidate TOPB (clear TIMER_STATUS_TOPBV) */ 226 | timer->TOP = _TIMER_TOP_RESETVALUE; 227 | timer->CNT = _TIMER_CNT_RESETVALUE; 228 | /* Do not reset route register, setting should be done independently */ 229 | /* (Note: ROUTE register may be locked by DTLOCK register.) */ 230 | 231 | for (i = 0; TIMER_CH_VALID(i); i++) { 232 | timer->CC[i].CTRL = _TIMER_CC_CTRL_RESETVALUE; 233 | timer->CC[i].CCV = _TIMER_CC_CCV_RESETVALUE; 234 | timer->CC[i].CCVB = _TIMER_CC_CCVB_RESETVALUE; 235 | } 236 | 237 | /* Reset dead time insertion module, no effect on timers without DTI */ 238 | 239 | #if defined(TIMER_DTLOCK_LOCKKEY_UNLOCK) 240 | /* Unlock DTI registers first in case locked */ 241 | timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_UNLOCK; 242 | 243 | timer->DTCTRL = _TIMER_DTCTRL_RESETVALUE; 244 | timer->DTTIME = _TIMER_DTTIME_RESETVALUE; 245 | timer->DTFC = _TIMER_DTFC_RESETVALUE; 246 | timer->DTOGEN = _TIMER_DTOGEN_RESETVALUE; 247 | timer->DTFAULTC = _TIMER_DTFAULTC_MASK; 248 | #endif 249 | } 250 | 251 | /** @} (end addtogroup TIMER) */ 252 | /** @} (end addtogroup emlib) */ 253 | #endif /* defined(TIMER_COUNT) && (TIMER_COUNT > 0) */ 254 | -------------------------------------------------------------------------------- /rf24tests/inc/InitDevice.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | //========================================================= 5 | 6 | // inc/InitDevice.h: generated by Hardware Configurator 7 | // 8 | // This file will be regenerated when saving a document. 9 | // leave the sections inside the "$[...]" comment tags alone 10 | // or they will be overwritten! 11 | //========================================================= 12 | #ifndef __INIT_DEVICE_H__ 13 | #define __INIT_DEVICE_H__ 14 | 15 | // USER CONSTANTS 16 | // USER PROTOTYPES 17 | 18 | // $[Mode Transition Prototypes] 19 | extern void enter_DefaultMode_from_RESET(void); 20 | // [Mode Transition Prototypes]$ 21 | 22 | // $[Config(Per-Module Mode)Transition Prototypes] 23 | extern void HFXO_enter_DefaultMode_from_RESET(void); 24 | extern void LFXO_enter_DefaultMode_from_RESET(void); 25 | extern void CMU_enter_DefaultMode_from_RESET(void); 26 | extern void ADC0_enter_DefaultMode_from_RESET(void); 27 | extern void ACMP0_enter_DefaultMode_from_RESET(void); 28 | extern void IDAC0_enter_DefaultMode_from_RESET(void); 29 | extern void RTC_enter_DefaultMode_from_RESET(void); 30 | extern void USART1_enter_DefaultMode_from_RESET(void); 31 | extern void LEUART0_enter_DefaultMode_from_RESET(void); 32 | extern void VCMP_enter_DefaultMode_from_RESET(void); 33 | extern void WDOG_enter_DefaultMode_from_RESET(void); 34 | extern void I2C0_enter_DefaultMode_from_RESET(void); 35 | extern void TIMER0_enter_DefaultMode_from_RESET(void); 36 | extern void TIMER1_enter_DefaultMode_from_RESET(void); 37 | extern void PCNT0_enter_DefaultMode_from_RESET(void); 38 | extern void PRS_enter_DefaultMode_from_RESET(void); 39 | extern void PORTIO_enter_DefaultMode_from_RESET(void); 40 | // [Config(Per-Module Mode)Transition Prototypes]$ 41 | 42 | // $[User-defined pin name abstraction] 43 | 44 | #define I2C0_SCL_PIN (13) 45 | #define I2C0_SCL_PORT (gpioPortE) 46 | 47 | #define I2C0_SDA_PIN (12) 48 | #define I2C0_SDA_PORT (gpioPortE) 49 | 50 | #define LED0_PIN (11) 51 | #define LED0_PORT (gpioPortC) 52 | 53 | #define LED1_PIN (10) 54 | #define LED1_PORT (gpioPortC) 55 | 56 | #define PB0_PIN (9) 57 | #define PB0_PORT (gpioPortC) 58 | 59 | #define PB1_PIN (8) 60 | #define PB1_PORT (gpioPortC) 61 | 62 | #define RF24_CE_PIN (0) 63 | #define RF24_CE_PORT (gpioPortA) 64 | 65 | #define RF24_IRQ_PIN (11) 66 | #define RF24_IRQ_PORT (gpioPortB) 67 | 68 | #define USART1_CLK_PIN (15) 69 | #define USART1_CLK_PORT (gpioPortC) 70 | 71 | #define USART1_CS_PIN (14) 72 | #define USART1_CS_PORT (gpioPortC) 73 | 74 | #define USART1_RX_PIN (6) 75 | #define USART1_RX_PORT (gpioPortD) 76 | 77 | #define USART1_TX_PIN (7) 78 | #define USART1_TX_PORT (gpioPortD) 79 | 80 | // [User-defined pin name abstraction]$ 81 | 82 | #endif 83 | 84 | #ifdef __cplusplus 85 | } 86 | #endif 87 | -------------------------------------------------------------------------------- /rf24tests/inc/RF24.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CoretechR/Gecko-Node/c6183effcdfb11cfbb19e558acd2151d1e1f169d/rf24tests/inc/RF24.h -------------------------------------------------------------------------------- /rf24tests/inc/RF24_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | #ifndef INC_RF24_CONFIG_H_ 10 | #define INC_RF24_CONFIG_H_ 11 | 12 | 13 | /*** USER DEFINES: ***/ 14 | //#define FAILURE_HANDLING 15 | //#define SERIAL_DEBUG 16 | //#define MINIMAL 17 | //#define SPI_UART // Requires library from https://github.com/TMRh20/Sketches/tree/master/SPI_UART 18 | //#define SOFTSPI // Requires library from https://github.com/greiman/DigitalIO 19 | 20 | /**********************/ 21 | #define rf24_max(a,b) (a>b?a:b) 22 | #define rf24_min(a,b) (a 60 | 61 | // RF modules support 10 Mhz SPI bus speed 62 | const uint32_t RF24_SPI_SPEED = 10000000; 63 | 64 | #if defined (ARDUINO) && !defined (__arm__) && !defined (__ARDUINO_X86__) 65 | #if defined SPI_UART 66 | #include 67 | #define _SPI uspi 68 | #elif defined SOFTSPI 69 | // change these pins to your liking 70 | // 71 | const uint8_t SOFT_SPI_MISO_PIN = 16; 72 | const uint8_t SOFT_SPI_MOSI_PIN = 15; 73 | const uint8_t SOFT_SPI_SCK_PIN = 14; 74 | const uint8_t SPI_MODE = 0; 75 | #define _SPI spi 76 | 77 | #else 78 | #include 79 | #define _SPI SPI 80 | #endif 81 | #else 82 | // Define _BV for non-Arduino platforms and for Arduino DUE 83 | #include 84 | #include 85 | #include 86 | 87 | 88 | #if defined(__arm__) || defined (__ARDUINO_X86__) 89 | #if defined (__arm__) && defined (SPI_UART) 90 | #include 91 | #define _SPI uspi 92 | #else 93 | #include 94 | #define _SPI SPI 95 | #endif 96 | #elif !defined(__arm__) && !defined (__ARDUINO_X86__) 97 | extern HardwareSPI SPI; 98 | #endif 99 | 100 | #define _BV(x) (1<<(x)) 101 | 102 | #endif 103 | 104 | #ifdef SERIAL_DEBUG 105 | #define IF_SERIAL_DEBUG(x) ({x;}) 106 | #else 107 | #define IF_SERIAL_DEBUG(x) 108 | #if defined(RF24_TINY) 109 | #define printf_P(...) 110 | #endif 111 | #endif 112 | 113 | #if defined (__ARDUINO_X86__) 114 | #define printf_P printf 115 | #define _BV(bit) (1<<(bit)) 116 | #endif 117 | 118 | // Progmem is Arduino-specific 119 | // Arduino DUE is arm and does not include avr/pgmspace 120 | #if defined (ARDUINO_ARCH_ESP8266) 121 | 122 | #define PSTR(x) (x) 123 | #define printf Serial.printf 124 | #define sprintf(...) os_sprintf( __VA_ARGS__ ) 125 | #define printf_P printf 126 | #define strlen_P strlen 127 | #define PROGMEM 128 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 129 | #define pgm_read_word(p) (*(p)) 130 | #define PRIPSTR "%s" 131 | 132 | #elif defined(ARDUINO) && ! defined(__arm__) && !defined (__ARDUINO_X86__) || defined(XMEGA) 133 | #include 134 | #define PRIPSTR "%S" 135 | #else 136 | #if ! defined(ARDUINO) // This doesn't work on Arduino DUE 137 | typedef char const char; 138 | #else // Fill in pgm_read_byte that is used, but missing from DUE 139 | #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) 140 | #endif 141 | 142 | 143 | typedef uint16_t prog_uint16_t; 144 | #define PSTR(x) (x) 145 | #define printf_P printf 146 | #define strlen_P strlen 147 | #define PROGMEM 148 | #define pgm_read_word(p) (*(p)) 149 | 150 | #define PRIPSTR "%s" 151 | 152 | #endif 153 | 154 | #endif 155 | 156 | 157 | #endif /* INC_RF24_CONFIG_H_ */ 158 | -------------------------------------------------------------------------------- /rf24tests/inc/delay.h: -------------------------------------------------------------------------------- 1 | /* 2 | * delay.h 3 | * 4 | * Created on: 18.08.2017 5 | * Author: Maximilian 6 | */ 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif 11 | 12 | #ifndef INC_DELAY_H_ 13 | #define INC_DELAY_H_ 14 | 15 | 16 | void initDelay(void); 17 | void delay(int ms); 18 | void delayUs(int us); 19 | 20 | 21 | #endif /* INC_DELAY_H_ */ 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | -------------------------------------------------------------------------------- /rf24tests/inc/emodes.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" { 3 | #endif 4 | /* 5 | * emodes.h 6 | * 7 | * Created on: 18.08.2017 8 | * Author: Maximilian 9 | */ 10 | 11 | #ifndef INC_EMODES_H_ 12 | #define INC_EMODES_H_ 13 | 14 | /***************************************************************************//** 15 | * @file emodes.h 16 | * @brief Zero Gecko energy mode setups (See Data Sheet Table 3.3), header file 17 | * @version 5.2.2 18 | ******************************************************************************* 19 | * # License 20 | * Copyright 2016 Silicon Labs, Inc. http://www.silabs.com 21 | ******************************************************************************* 22 | * 23 | * This file is licensed under the Silabs License Agreement. See the file 24 | * "Silabs_License_Agreement.txt" for details. Before using this software for 25 | * any purpose, you must agree to the terms of that agreement. 26 | * 27 | ******************************************************************************/ 28 | 29 | #include "em_cmu.h" 30 | 31 | /* Enter energy mode functions */ 32 | void em_EM0_Hfxo(void); 33 | 34 | void em_EM0_Hfrco(CMU_HFRCOBand_TypeDef band); 35 | 36 | void em_EM1_Hfxo(void); 37 | 38 | void em_EM1_Hfrco(CMU_HFRCOBand_TypeDef band); 39 | 40 | void em_EM2_LfrcoRTC(void); 41 | 42 | void em_EM3_Ulfrco(void); 43 | 44 | void em_EM4(void); 45 | 46 | 47 | #endif /* INC_EMODES_H_ */ 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | -------------------------------------------------------------------------------- /rf24tests/inc/nRF24L01.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007 Stefan Engelke 3 | Portions Copyright (C) 2011 Greg Copeland 4 | 5 | Permission is hereby granted, free of charge, to any person 6 | obtaining a copy of this software and associated documentation 7 | files (the "Software"), to deal in the Software without 8 | restriction, including without limitation the rights to use, copy, 9 | modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | /* Memory Map */ 27 | #define NRF_CONFIG 0x00 28 | #define EN_AA 0x01 29 | #define EN_RXADDR 0x02 30 | #define SETUP_AW 0x03 31 | #define SETUP_RETR 0x04 32 | #define RF_CH 0x05 33 | #define RF_SETUP 0x06 34 | #define NRF_STATUS 0x07 35 | #define OBSERVE_TX 0x08 36 | #define CD 0x09 37 | #define RX_ADDR_P0 0x0A 38 | #define RX_ADDR_P1 0x0B 39 | #define RX_ADDR_P2 0x0C 40 | #define RX_ADDR_P3 0x0D 41 | #define RX_ADDR_P4 0x0E 42 | #define RX_ADDR_P5 0x0F 43 | #define TX_ADDR 0x10 44 | #define RX_PW_P0 0x11 45 | #define RX_PW_P1 0x12 46 | #define RX_PW_P2 0x13 47 | #define RX_PW_P3 0x14 48 | #define RX_PW_P4 0x15 49 | #define RX_PW_P5 0x16 50 | #define FIFO_STATUS 0x17 51 | #define DYNPD 0x1C 52 | #define FEATURE 0x1D 53 | 54 | /* Bit Mnemonics */ 55 | #define MASK_RX_DR 6 56 | #define MASK_TX_DS 5 57 | #define MASK_MAX_RT 4 58 | #define EN_CRC 3 59 | #define CRCO 2 60 | #define PWR_UP 1 61 | #define PRIM_RX 0 62 | #define ENAA_P5 5 63 | #define ENAA_P4 4 64 | #define ENAA_P3 3 65 | #define ENAA_P2 2 66 | #define ENAA_P1 1 67 | #define ENAA_P0 0 68 | #define ERX_P5 5 69 | #define ERX_P4 4 70 | #define ERX_P3 3 71 | #define ERX_P2 2 72 | #define ERX_P1 1 73 | #define ERX_P0 0 74 | #define AW 0 75 | #define ARD 4 76 | #define ARC 0 77 | #define PLL_LOCK 4 78 | #define RF_DR 3 79 | #define RF_PWR 6 80 | #define RX_DR 6 81 | #define TX_DS 5 82 | #define MAX_RT 4 83 | #define RX_P_NO 1 84 | #define TX_FULL 0 85 | #define PLOS_CNT 4 86 | #define ARC_CNT 0 87 | #define TX_REUSE 6 88 | #define FIFO_FULL 5 89 | #define TX_EMPTY 4 90 | #define RX_FULL 1 91 | #define RX_EMPTY 0 92 | #define DPL_P5 5 93 | #define DPL_P4 4 94 | #define DPL_P3 3 95 | #define DPL_P2 2 96 | #define DPL_P1 1 97 | #define DPL_P0 0 98 | #define EN_DPL 2 99 | #define EN_ACK_PAY 1 100 | #define EN_DYN_ACK 0 101 | 102 | /* Instruction Mnemonics */ 103 | #define R_REGISTER 0x00 104 | #define W_REGISTER 0x20 105 | #define REGISTER_MASK 0x1F 106 | #define ACTIVATE 0x50 107 | #define R_RX_PL_WID 0x60 108 | #define R_RX_PAYLOAD 0x61 109 | #define W_TX_PAYLOAD 0xA0 110 | #define W_ACK_PAYLOAD 0xA8 111 | #define FLUSH_TX 0xE1 112 | #define FLUSH_RX 0xE2 113 | #define REUSE_TX_PL 0xE3 114 | #define NOP 0xFF 115 | 116 | /* Non-P omissions */ 117 | #define LNA_HCURR 0 118 | 119 | /* P model memory Map */ 120 | #define RPD 0x09 121 | #define W_TX_PAYLOAD_NO_ACK 0xB0 122 | 123 | /* P model bit Mnemonics */ 124 | #define RF_DR_LOW 5 125 | #define RF_DR_HIGH 3 126 | #define RF_PWR_LOW 1 127 | #define RF_PWR_HIGH 2 128 | -------------------------------------------------------------------------------- /rf24tests/src/InitDevice.c: -------------------------------------------------------------------------------- 1 | // $[Library includes] 2 | #include "em_system.h" 3 | #include "em_emu.h" 4 | #include "em_cmu.h" 5 | #include "em_device.h" 6 | #include "em_chip.h" 7 | #include "em_assert.h" 8 | #include "em_gpio.h" 9 | #include "em_i2c.h" 10 | #include "em_rtc.h" 11 | #include "em_usart.h" 12 | // [Library includes]$ 13 | 14 | extern void enter_DefaultMode_from_RESET(void) { 15 | // $[Config Calls] 16 | HFXO_enter_DefaultMode_from_RESET(); 17 | LFXO_enter_DefaultMode_from_RESET(); 18 | CMU_enter_DefaultMode_from_RESET(); 19 | RTC_enter_DefaultMode_from_RESET(); 20 | USART1_enter_DefaultMode_from_RESET(); 21 | I2C0_enter_DefaultMode_from_RESET(); 22 | PORTIO_enter_DefaultMode_from_RESET(); 23 | // [Config Calls]$ 24 | } 25 | 26 | extern void HFXO_enter_DefaultMode_from_RESET(void) { 27 | 28 | // $[HFXO] 29 | CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOMODE_MASK) | CMU_CTRL_HFXOMODE_XTAL; 30 | 31 | CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_HFXOBOOST_MASK) 32 | | CMU_CTRL_HFXOBOOST_50PCENT; 33 | 34 | SystemHFXOClockSet(32000000); 35 | // [HFXO]$ 36 | 37 | } 38 | 39 | extern void LFXO_enter_DefaultMode_from_RESET(void) { 40 | 41 | // $[Use oscillator source] 42 | CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOMODE_MASK) | CMU_CTRL_LFXOMODE_XTAL; 43 | // [Use oscillator source]$ 44 | 45 | // $[LFXO Boost Percent] 46 | CMU->CTRL = (CMU->CTRL & ~_CMU_CTRL_LFXOBOOST_MASK) 47 | | CMU_CTRL_LFXOBOOST_100PCENT; 48 | // [LFXO Boost Percent]$ 49 | 50 | // $[REDLFXO Boost] 51 | // [REDLFXO Boost]$ 52 | 53 | } 54 | 55 | extern void CMU_enter_DefaultMode_from_RESET(void) { 56 | 57 | // $[LFXO enable] 58 | CMU_OscillatorEnable(cmuOsc_LFXO, true, true); 59 | // [LFXO enable]$ 60 | 61 | // $[HFXO enable] 62 | CMU_OscillatorEnable(cmuOsc_HFXO, true, true); 63 | // [HFXO enable]$ 64 | 65 | // $[LFACLK Setup] 66 | /* Select LFXO as clock source for LFACLK */ 67 | CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); 68 | 69 | // [LFACLK Setup]$ 70 | 71 | // $[High Frequency Clock select] 72 | /* Using HFXO as high frequency clock, HFCLK */ 73 | CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); 74 | 75 | /* Enable peripheral clock */ 76 | CMU_ClockEnable(cmuClock_HFPER, true); 77 | 78 | // [High Frequency Clock select]$ 79 | 80 | // $[LF clock tree setup] 81 | /* Enable LF clocks */ 82 | CMU_ClockEnable(cmuClock_CORELE, true); 83 | CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); 84 | // [LF clock tree setup]$ 85 | // $[Peripheral Clock enables] 86 | /* Enable clock for I2C0 */ 87 | CMU_ClockEnable(cmuClock_I2C0, true); 88 | 89 | /* Enable clock for RTC */ 90 | CMU_ClockEnable(cmuClock_RTC, true); 91 | 92 | /* Enable clock for USART1 */ 93 | CMU_ClockEnable(cmuClock_USART1, true); 94 | 95 | /* Enable clock for GPIO by default */ 96 | CMU_ClockEnable(cmuClock_GPIO, true); 97 | 98 | // [Peripheral Clock enables]$ 99 | 100 | } 101 | 102 | extern void ADC0_enter_DefaultMode_from_RESET(void) { 103 | 104 | // $[ADC_Init] 105 | // [ADC_Init]$ 106 | 107 | // $[ADC_InitSingle] 108 | // [ADC_InitSingle]$ 109 | 110 | // $[ADC_InitScan] 111 | // [ADC_InitScan]$ 112 | 113 | } 114 | 115 | extern void ACMP0_enter_DefaultMode_from_RESET(void) { 116 | 117 | // $[ACMP Initialization] 118 | // [ACMP Initialization]$ 119 | 120 | // $[ACMP Channel config] 121 | // [ACMP Channel config]$ 122 | 123 | } 124 | 125 | extern void IDAC0_enter_DefaultMode_from_RESET(void) { 126 | 127 | // $[IDAC Initialization] 128 | // [IDAC Initialization]$ 129 | 130 | // $[IDAC optional configurations] 131 | // [IDAC optional configurations]$ 132 | 133 | // $[IDAC enable] 134 | // [IDAC enable]$ 135 | 136 | } 137 | 138 | extern void RTC_enter_DefaultMode_from_RESET(void) { 139 | 140 | // $[RTC_Init] 141 | RTC_Init_TypeDef init = RTC_INIT_DEFAULT; 142 | 143 | init.debugRun = 0; 144 | init.comp0Top = 0; 145 | 146 | RTC_Init(&init); 147 | // [RTC_Init]$ 148 | 149 | } 150 | 151 | extern void USART1_enter_DefaultMode_from_RESET(void) { 152 | 153 | // $[USART_InitAsync] 154 | // [USART_InitAsync]$ 155 | 156 | // $[USART_InitSync] 157 | USART_InitSync_TypeDef initsync = USART_INITSYNC_DEFAULT; 158 | 159 | initsync.baudrate = 1200000; 160 | initsync.databits = usartDatabits8; 161 | initsync.master = 1; 162 | initsync.msbf = 1; 163 | initsync.clockMode = usartClockMode0; 164 | #if defined( USART_INPUT_RXPRS ) && defined( USART_TRIGCTRL_AUTOTXTEN ) 165 | initsync.prsRxEnable = 0; 166 | initsync.prsRxCh = 0; 167 | initsync.autoTx = 0; 168 | #endif 169 | 170 | USART_InitSync(USART1, &initsync); 171 | // [USART_InitSync]$ 172 | 173 | // $[USART_InitPrsTrigger] 174 | USART_PrsTriggerInit_TypeDef initprs = USART_INITPRSTRIGGER_DEFAULT; 175 | 176 | initprs.rxTriggerEnable = 0; 177 | initprs.txTriggerEnable = 0; 178 | initprs.prsTriggerChannel = usartPrsTriggerCh0; 179 | 180 | USART_InitPrsTrigger(USART1, &initprs); 181 | // [USART_InitPrsTrigger]$ 182 | 183 | } 184 | 185 | extern void LEUART0_enter_DefaultMode_from_RESET(void) { 186 | 187 | // $[LEUART0 initialization] 188 | // [LEUART0 initialization]$ 189 | 190 | } 191 | 192 | extern void VCMP_enter_DefaultMode_from_RESET(void) { 193 | 194 | // $[VCMP_Init] 195 | // [VCMP_Init]$ 196 | 197 | } 198 | 199 | extern void WDOG_enter_DefaultMode_from_RESET(void) { 200 | 201 | // $[CMU_ClockEnable] 202 | // [CMU_ClockEnable]$ 203 | 204 | // $[CMU_OscillatorEnable] 205 | // [CMU_OscillatorEnable]$ 206 | 207 | // $[WDOG_Init] 208 | // [WDOG_Init]$ 209 | 210 | } 211 | 212 | extern void I2C0_enter_DefaultMode_from_RESET(void) { 213 | 214 | // $[I2C0 initialization] 215 | I2C_Init_TypeDef init = I2C_INIT_DEFAULT; 216 | 217 | init.enable = 1; 218 | init.master = 1; 219 | init.freq = I2C_FREQ_FAST_MAX; 220 | init.clhr = i2cClockHLRAsymetric; 221 | I2C_Init(I2C0, &init); 222 | // [I2C0 initialization]$ 223 | 224 | } 225 | 226 | extern void TIMER0_enter_DefaultMode_from_RESET(void) { 227 | 228 | // $[TIMER0 initialization] 229 | // [TIMER0 initialization]$ 230 | 231 | // $[TIMER0 CC0 init] 232 | // [TIMER0 CC0 init]$ 233 | 234 | // $[TIMER0 CC1 init] 235 | // [TIMER0 CC1 init]$ 236 | 237 | // $[TIMER0 CC2 init] 238 | // [TIMER0 CC2 init]$ 239 | 240 | } 241 | 242 | extern void TIMER1_enter_DefaultMode_from_RESET(void) { 243 | 244 | // $[TIMER1 initialization] 245 | // [TIMER1 initialization]$ 246 | 247 | // $[TIMER1 CC0 init] 248 | // [TIMER1 CC0 init]$ 249 | 250 | // $[TIMER1 CC1 init] 251 | // [TIMER1 CC1 init]$ 252 | 253 | // $[TIMER1 CC2 init] 254 | // [TIMER1 CC2 init]$ 255 | 256 | } 257 | 258 | extern void PCNT0_enter_DefaultMode_from_RESET(void) { 259 | 260 | // $[PCNT0 initialization] 261 | // [PCNT0 initialization]$ 262 | 263 | } 264 | 265 | extern void PRS_enter_DefaultMode_from_RESET(void) { 266 | 267 | // $[PRS initialization] 268 | // [PRS initialization]$ 269 | 270 | } 271 | 272 | extern void PORTIO_enter_DefaultMode_from_RESET(void) { 273 | 274 | // $[Port A Configuration] 275 | 276 | /* Pin PA0 is configured to Push-pull */ 277 | GPIO->P[0].MODEL = (GPIO->P[0].MODEL & ~_GPIO_P_MODEL_MODE0_MASK) 278 | | GPIO_P_MODEL_MODE0_PUSHPULL; 279 | // [Port A Configuration]$ 280 | 281 | // $[Port B Configuration] 282 | // [Port B Configuration]$ 283 | 284 | // $[Port C Configuration] 285 | 286 | /* Pin PC8 is configured to Input enabled with filter */ 287 | GPIO->P[2].DOUT |= (1 << 8); 288 | GPIO->P[2].MODEH = (GPIO->P[2].MODEH & ~_GPIO_P_MODEH_MODE8_MASK) 289 | | GPIO_P_MODEH_MODE8_INPUT; 290 | 291 | /* Pin PC9 is configured to Input enabled with filter */ 292 | GPIO->P[2].DOUT |= (1 << 9); 293 | GPIO->P[2].MODEH = (GPIO->P[2].MODEH & ~_GPIO_P_MODEH_MODE9_MASK) 294 | | GPIO_P_MODEH_MODE9_INPUT; 295 | 296 | /* Pin PC10 is configured to Push-pull */ 297 | GPIO->P[2].MODEH = (GPIO->P[2].MODEH & ~_GPIO_P_MODEH_MODE10_MASK) 298 | | GPIO_P_MODEH_MODE10_PUSHPULL; 299 | 300 | /* Pin PC11 is configured to Push-pull */ 301 | GPIO->P[2].MODEH = (GPIO->P[2].MODEH & ~_GPIO_P_MODEH_MODE11_MASK) 302 | | GPIO_P_MODEH_MODE11_PUSHPULL; 303 | 304 | /* Pin PC14 is configured to Push-pull */ 305 | GPIO->P[2].MODEH = (GPIO->P[2].MODEH & ~_GPIO_P_MODEH_MODE14_MASK) 306 | | GPIO_P_MODEH_MODE14_PUSHPULL; 307 | 308 | /* Pin PC15 is configured to Push-pull */ 309 | GPIO->P[2].MODEH = (GPIO->P[2].MODEH & ~_GPIO_P_MODEH_MODE15_MASK) 310 | | GPIO_P_MODEH_MODE15_PUSHPULL; 311 | // [Port C Configuration]$ 312 | 313 | // $[Port D Configuration] 314 | 315 | /* Pin PD6 is configured to Input enabled */ 316 | GPIO->P[3].MODEL = (GPIO->P[3].MODEL & ~_GPIO_P_MODEL_MODE6_MASK) 317 | | GPIO_P_MODEL_MODE6_INPUT; 318 | 319 | /* Pin PD7 is configured to Push-pull */ 320 | GPIO->P[3].MODEL = (GPIO->P[3].MODEL & ~_GPIO_P_MODEL_MODE7_MASK) 321 | | GPIO_P_MODEL_MODE7_PUSHPULL; 322 | // [Port D Configuration]$ 323 | 324 | // $[Port E Configuration] 325 | 326 | /* Pin PE12 is configured to Open-drain with pull-up and filter */ 327 | GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE12_MASK) 328 | | GPIO_P_MODEH_MODE12_WIREDANDPULLUPFILTER; 329 | 330 | /* Pin PE13 is configured to Open-drain with pull-up and filter */ 331 | GPIO->P[4].MODEH = (GPIO->P[4].MODEH & ~_GPIO_P_MODEH_MODE13_MASK) 332 | | GPIO_P_MODEH_MODE13_WIREDANDPULLUPFILTER; 333 | // [Port E Configuration]$ 334 | 335 | // $[Port F Configuration] 336 | // [Port F Configuration]$ 337 | 338 | // $[Route Configuration] 339 | 340 | /* Module I2C0 is configured to location 6 */ 341 | I2C0->ROUTE = (I2C0->ROUTE & ~_I2C_ROUTE_LOCATION_MASK) 342 | | I2C_ROUTE_LOCATION_LOC6; 343 | 344 | /* Enable signals SCL, SDA */ 345 | I2C0->ROUTE |= I2C_ROUTE_SCLPEN | I2C_ROUTE_SDAPEN; 346 | 347 | /* Module USART1 is configured to location 3 */ 348 | USART1->ROUTE = (USART1->ROUTE & ~_USART_ROUTE_LOCATION_MASK) 349 | | USART_ROUTE_LOCATION_LOC3; 350 | 351 | /* Enable signals CLK, RX, TX */ 352 | USART1->ROUTE |= USART_ROUTE_CLKPEN | USART_ROUTE_RXPEN | USART_ROUTE_TXPEN; 353 | // [Route Configuration]$ 354 | 355 | } 356 | 357 | -------------------------------------------------------------------------------- /rf24tests/src/RF24.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2011 J. Coliz 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | version 2 as published by the Free Software Foundation. 7 | */ 8 | 9 | #include "em_usart.h" 10 | #include "em_gpio.h" 11 | #include "RF24.h" 12 | #include "InitDevice.h" 13 | #include "delay.h" 14 | 15 | 16 | /****************************************************************************/ 17 | 18 | uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len) 19 | { 20 | uint8_t status; 21 | 22 | beginTransaction(); 23 | status = USART_SpiTransfer(USART1, W_REGISTER | ( REGISTER_MASK & reg ) ); 24 | while ( len-- ) 25 | USART_SpiTransfer(USART1, *buf++); 26 | endTransaction(); 27 | 28 | return status; 29 | } 30 | 31 | /****************************************************************************/ 32 | 33 | uint8_t RF24::write_register(uint8_t reg, uint8_t value) 34 | { 35 | uint8_t status; 36 | 37 | beginTransaction(); 38 | status = USART_SpiTransfer(USART1, W_REGISTER | ( REGISTER_MASK & reg ) ); 39 | USART_SpiTransfer(USART1, value); 40 | endTransaction(); 41 | 42 | return status; 43 | } 44 | 45 | /****************************************************************************/ 46 | 47 | bool RF24::begin(void) 48 | { 49 | uint8_t setup=0; 50 | 51 | // Make sure CS is in high state 52 | GPIO_PinOutSet(USART1_CS_PORT, USART1_CS_PIN); 53 | 54 | // Must allow the radio time to settle else configuration bits will not necessarily stick. 55 | // This is actually only required following power up but some settling time also appears to 56 | // be required after resets too. For full coverage, we'll always assume the worst. 57 | // Enabling 16b CRC is by far the most obvious case if the wrong timing is used - or skipped. 58 | // Technically we require 4.5ms + 14us as a worst case. We'll just call it 5ms for good measure. 59 | // WARNING: Delay is based on P-variant whereby non-P *may* require different timing. 60 | delay( 5 ) ; 61 | 62 | // Reset NRF_CONFIG and enable 16-bit CRC. 63 | write_register( NRF_CONFIG, 0x0C ) ; 64 | 65 | // Set 1500uS (minimum for 32B payload in ESB@250KBPS) timeouts, to make testing a little easier 66 | // WARNING: If this is ever lowered, either 250KBS mode with AA is broken or maximum packet 67 | // sizes must never be used. See documentation for a more complete explanation. 68 | setRetries(5,15); 69 | 70 | // Reset value is MAX 71 | //setPALevel( RF24_PA_MAX ) ; 72 | 73 | // check for connected module and if this is a p nRF24l01 variant 74 | // 75 | //if( setDataRate( RF24_250KBPS ) ) 76 | //{ 77 | //p_variant = true ; 78 | //} 79 | //setup = read_register(RF_SETUP); 80 | /*if( setup == 0b00001110 ) // register default for nRF24L01P 81 | { 82 | p_variant = true ; 83 | }*/ 84 | 85 | // Then set the data rate to the slowest (and most reliable) speed supported by all 86 | // hardware. 87 | setDataRate( RF24_250KBPS ) ; 88 | 89 | // Initialize CRC and request 2-byte (16bit) CRC 90 | //setCRCLength( RF24_CRC_16 ) ; 91 | 92 | // Disable dynamic payloads, to match dynamic_payloads_enabled setting - Reset value is 0 93 | toggle_features(); 94 | write_register(FEATURE,0 ); 95 | write_register(DYNPD,0); 96 | dynamic_payloads_enabled = false; 97 | 98 | // Reset current status 99 | // Notice reset and flush is the last thing we do 100 | //write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); 101 | 102 | // Set up default configuration. Callers can always change it later. 103 | // This channel should be universally safe and not bleed over into adjacent 104 | // spectrum. 105 | setChannel(76); 106 | 107 | // Flush buffers 108 | flush_rx(); 109 | flush_tx(); 110 | 111 | powerUp(); //Power up by default when begin() is called 112 | 113 | // Enable PTX, do not write CE high so radio will remain in standby I mode ( 130us max to transition to RX or TX instead of 1500us from powerUp ) 114 | // PTX should use only 22uA of power 115 | write_register(NRF_CONFIG, ( read_register(NRF_CONFIG) ) & ~_BV(PRIM_RX) ); 116 | 117 | // if setup is 0 or ff then there was no response from module 118 | return ( setup != 0 && setup != 0xff ); 119 | } 120 | 121 | /****************************************************************************/ 122 | 123 | void RF24::setRetries(uint8_t delay, uint8_t count) 124 | { 125 | write_register(SETUP_RETR,(delay&0xf)<(&value), addr_width); 304 | write_register(TX_ADDR, reinterpret_cast(&value), addr_width); 305 | 306 | 307 | //const uint8_t max_payload_size = 32; 308 | //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); 309 | write_register(RX_PW_P0,payload_size); 310 | } 311 | 312 | /****************************************************************************/ 313 | void RF24::openWritingPipe(const uint8_t *address) 314 | { 315 | // Note that AVR 8-bit uC's store this LSB first, and the NRF24L01(+) 316 | // expects it LSB first too, so we're good. 317 | 318 | write_register(RX_ADDR_P0,address, addr_width); 319 | write_register(TX_ADDR, address, addr_width); 320 | 321 | //const uint8_t max_payload_size = 32; 322 | //write_register(RX_PW_P0,rf24_min(payload_size,max_payload_size)); 323 | write_register(RX_PW_P0,payload_size); 324 | } 325 | 326 | /******************************************************************/ 327 | 328 | //Similar to the previous write, clears the interrupt flags 329 | bool RF24::write( const void* buf, uint8_t len, const bool multicast ) 330 | { 331 | //Start Writing 332 | startFastWrite(buf,len,multicast); 333 | 334 | //Wait until complete or failed 335 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 336 | uint32_t timer = millis(); 337 | #endif 338 | 339 | while( ! ( get_status() & ( _BV(TX_DS) | _BV(MAX_RT) ))) { 340 | #if defined (FAILURE_HANDLING) || defined (RF24_LINUX) 341 | if(millis() - timer > 95){ 342 | errNotify(); 343 | #if defined (FAILURE_HANDLING) 344 | return 0; 345 | #else 346 | delay(100); 347 | #endif 348 | } 349 | #endif 350 | } 351 | 352 | GPIO_PinOutClear(RF24_CE_PORT, RF24_CE_PIN); 353 | 354 | uint8_t status = write_register(NRF_STATUS,_BV(RX_DR) | _BV(TX_DS) | _BV(MAX_RT) ); 355 | 356 | //Max retries exceeded 357 | if( status & _BV(MAX_RT)){ 358 | flush_tx(); //Only going to be 1 packet int the FIFO at a time using this method, so just flush 359 | return 0; 360 | } 361 | //TX OK 1 or 0 362 | return 1; 363 | } 364 | 365 | bool RF24::write( const void* buf, uint8_t len ){ 366 | return write(buf,len,0); 367 | } 368 | 369 | /****************************************************************************/ 370 | 371 | //Per the documentation, we want to set PTX Mode when not listening. Then all we do is write data and set CE high 372 | //In this mode, if we can keep the FIFO buffers loaded, packets will transmit immediately (no 130us delay) 373 | //Otherwise we enter Standby-II mode, which is still faster than standby mode 374 | //Also, we remove the need to keep writing the config register over and over and delaying for 150 us each time if sending a stream of data 375 | 376 | void RF24::startFastWrite( const void* buf, uint8_t len, const bool multicast, bool startTx){ //TMRh20 377 | 378 | //write_payload( buf,len); 379 | write_payload( buf, len,multicast ? W_TX_PAYLOAD_NO_ACK : W_TX_PAYLOAD ) ; 380 | if(startTx){ 381 | GPIO_PinOutSet(RF24_CE_PORT, RF24_CE_PIN); 382 | } 383 | 384 | } 385 | 386 | /****************************************************************************/ 387 | 388 | uint8_t RF24::write_payload(const void* buf, uint8_t data_len, const uint8_t writeType) 389 | { 390 | uint8_t status; 391 | const uint8_t* current = reinterpret_cast(buf); 392 | 393 | data_len = rf24_min(data_len, payload_size); 394 | uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len; 395 | 396 | #if defined (RF24_LINUX) 397 | beginTransaction(); 398 | uint8_t * prx = spi_rxbuff; 399 | uint8_t * ptx = spi_txbuff; 400 | uint8_t size; 401 | size = data_len + blank_len + 1 ; // Add register value to transmit buffer 402 | 403 | *ptx++ = writeType; 404 | while ( data_len-- ) 405 | *ptx++ = *current++; 406 | while ( blank_len-- ) 407 | *ptx++ = 0; 408 | 409 | _SPI.transfernb( (char *) spi_txbuff, (char *) spi_rxbuff, size); 410 | status = *prx; // status is 1st byte of receive buffer 411 | endTransaction(); 412 | 413 | #else 414 | 415 | beginTransaction(); 416 | status = USART_SpiTransfer(USART1, writeType ); 417 | while ( data_len-- ) { 418 | USART_SpiTransfer(USART1, *current++); 419 | } 420 | while ( blank_len-- ) { 421 | USART_SpiTransfer(USART1, 0); 422 | } 423 | endTransaction(); 424 | 425 | #endif 426 | 427 | return status; 428 | } 429 | 430 | /****************************************************************************/ 431 | 432 | uint8_t RF24::get_status(void) 433 | { 434 | return spiTrans(NOP); 435 | } 436 | -------------------------------------------------------------------------------- /rf24tests/src/delay.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* 4 | * delay.cpp 5 | * 6 | * Created on: 18.08.2017 7 | * Author: Maximilian 8 | */ 9 | 10 | 11 | #include "em_device.h" 12 | #include "em_timer.h" 13 | #include "em_cmu.h" 14 | 15 | #define RTC_FREQ 32768 16 | #define TIMER_FREQ 48000000 17 | 18 | /********************************************************** 19 | * Enables clocks used for delay functions. 20 | **********************************************************/ 21 | void initDelay(void) 22 | { 23 | CMU_ClockEnable(cmuClock_CORELE, true); 24 | CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO); 25 | CMU_ClockEnable(cmuClock_RTC, true); 26 | CMU_ClockEnable(cmuClock_TIMER0, true); 27 | } 28 | 29 | 30 | /********************************************************** 31 | * Delay a number of milliseconds 32 | **********************************************************/ 33 | void delay(int ms) 34 | { 35 | uint32_t endValue = ms * RTC_FREQ / 1000; 36 | RTC->CNT = 0; 37 | 38 | RTC->CTRL |= RTC_CTRL_EN; 39 | 40 | while ( RTC->CNT < endValue ); 41 | 42 | RTC->CTRL &= ~RTC_CTRL_EN; 43 | } 44 | 45 | /********************************************************** 46 | * Delay a number of microseconds 47 | **********************************************************/ 48 | void delayUs(int us) 49 | { 50 | uint32_t endValue = us * (TIMER_FREQ / 1000000); 51 | TIMER0->CNT = 0; 52 | 53 | TIMER0->CMD = TIMER_CMD_START; 54 | 55 | while ( TIMER0->CNT < endValue ); 56 | 57 | TIMER0->CMD = TIMER_CMD_STOP; 58 | } 59 | 60 | -------------------------------------------------------------------------------- /rf24tests/src/emodes.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | * @file emodes.c 3 | * @brief Zero Gecko energy mode setups (See Data Sheet Table 3.3) 4 | * @version 5.2.2 5 | ******************************************************************************* 6 | * # License 7 | * Copyright 2016 Silicon Labs, Inc. http://www.silabs.com 8 | ******************************************************************************* 9 | * 10 | * This file is licensed under the Silabs License Agreement. See the file 11 | * "Silabs_License_Agreement.txt" for details. Before using this software for 12 | * any purpose, you must agree to the terms of that agreement. 13 | * 14 | ******************************************************************************/ 15 | 16 | #include "emodes.h" 17 | #include "em_cmu.h" 18 | #include "em_rtc.h" 19 | #include "em_emu.h" 20 | #include 21 | #include 22 | 23 | static void disableClocks(void); 24 | static void primeCalc(void); 25 | 26 | /***************************************************************************//** 27 | * @brief 28 | * Enter EM0 with HFXO running at 24MHz. 29 | * 30 | * @details 31 | * Parameter: 32 | * EM0. No prescaling. Running prime number calculation code 33 | * from Flash (Production test condition = 14MHz).@n 34 | * Condition: 35 | * 24 MHz HFXO, all peripheral clocks disabled, VDD= 3.0V.@n 36 | * 37 | * @note 38 | * To better understand disabling clocks and oscillators for specific modes, 39 | * see Reference Manual section EMU-Energy Management Unit and Table 10.1. 40 | ******************************************************************************/ 41 | void em_EM0_Hfxo(void) 42 | { 43 | // Make sure clocks are disabled. 44 | disableClocks(); 45 | 46 | // Set HFXO for HF clock. 47 | CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); 48 | 49 | // Make sure unwanted oscillators are disabled specifically for EM0 and HFXO. 50 | CMU_OscillatorEnable(cmuOsc_HFRCO, false, true); 51 | CMU_OscillatorEnable(cmuOsc_LFXO, false, true); 52 | CMU_OscillatorEnable(cmuOsc_LFRCO, false, true); 53 | CMU_OscillatorEnable(cmuOsc_AUXHFRCO, false, true); 54 | #if defined(CMU_OSCENCMD_USHFRCOEN) 55 | CMU_OscillatorEnable(cmuOsc_USHFRCO, false, true); 56 | #endif 57 | 58 | // Calculate prime numbers forever. 59 | primeCalc(); 60 | } 61 | 62 | /***************************************************************************//** 63 | * @brief 64 | * Enter EM0 with HFRCO running at desired frequency. 65 | * 66 | * @param[in] band 67 | * HFRCO band to activate (21, 14, 11, 6.6, 1.2 MHz). 68 | * 69 | * @details 70 | * Parameter: 71 | * EM0. No prescaling. Running prime number calculation code 72 | * from Flash (Production test condition = 14MHz).@n 73 | * Condition: 74 | * Between 21 and 1.2 MHz HFRCO, all peripheral clocks disabled, VDD= 3.0V.@n 75 | * 76 | * @note 77 | * To better understand disabling clocks and oscillators for specific modes, 78 | * see Reference Manual section EMU-Energy Management Unit and Table 10.1. 79 | ******************************************************************************/ 80 | void em_EM0_Hfrco(CMU_HFRCOBand_TypeDef band) 81 | { 82 | // Make sure clocks are disabled. 83 | disableClocks(); 84 | 85 | // Set HFRCO for HF clock. 86 | CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO); 87 | 88 | // Set HFRCO frequency. 89 | CMU_HFRCOBandSet(band); 90 | 91 | // Make sure unwanted oscillators are disabled specifically for EM0 and HFRCO. 92 | CMU_OscillatorEnable(cmuOsc_HFXO, false, true); 93 | CMU_OscillatorEnable(cmuOsc_LFXO, false, true); 94 | CMU_OscillatorEnable(cmuOsc_LFRCO, false, true); 95 | CMU_OscillatorEnable(cmuOsc_AUXHFRCO, false, true); 96 | #if defined(CMU_OSCENCMD_USHFRCOEN) 97 | CMU_OscillatorEnable(cmuOsc_USHFRCO, false, true); 98 | #endif 99 | 100 | // Calculate prime numbers forever. 101 | primeCalc(); 102 | } 103 | 104 | /***************************************************************************//** 105 | * @brief 106 | * Enter EM1 with HFXO running at 24MHz. 107 | * 108 | * @details 109 | * Parameter: 110 | EM1 (Production test condition = 14 MHz).@n 111 | * Condition: 112 | * 24 MHz HFXO, all peripheral clocks disabled, VDD= 3.0 V.@n 113 | * 114 | * @note 115 | * To better understand disabling clocks and oscillators for specific modes, 116 | * see Reference Manual section EMU-Energy Management Unit and Table 10.1. 117 | ******************************************************************************/ 118 | void em_EM1_Hfxo(void) 119 | { 120 | // Make sure clocks are disabled. 121 | disableClocks(); 122 | 123 | // Set HFXO for HF clock. 124 | CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO); 125 | 126 | // Make sure unwanted oscillators are disabled specifically for EM1 and HFXO. 127 | CMU_OscillatorEnable(cmuOsc_HFRCO, false, true); 128 | CMU_OscillatorEnable(cmuOsc_LFXO, false, true); 129 | CMU_OscillatorEnable(cmuOsc_LFRCO, false, true); 130 | CMU_OscillatorEnable(cmuOsc_AUXHFRCO, false, true); 131 | #if defined(CMU_OSCENCMD_USHFRCOEN) 132 | CMU_OscillatorEnable(cmuOsc_USHFRCO, false, true); 133 | #endif 134 | 135 | // Enter EM1. 136 | EMU_EnterEM1(); 137 | } 138 | 139 | /***************************************************************************//** 140 | * @brief 141 | * Enter EM1 with HFRCO running at desired frequency. 142 | * 143 | * @param[in] band 144 | * HFRCO band to activate (21, 14, 11, 6.6, 1.2 MHz). 145 | * 146 | * @details 147 | * Parameter: 148 | * EM1 (Production test condition = 14 MHz).@n 149 | * Condition: 150 | * Between 21 and 1.2 MHz HFRCO, all peripheral clocks disabled, VDD= 3.0 V.@n 151 | * 152 | * @note 153 | * To better understand disabling clocks and oscillators for specific modes, 154 | * see Reference Manual section EMU-Energy Management Unit and Table 10.1. 155 | ******************************************************************************/ 156 | void em_EM1_Hfrco(CMU_HFRCOBand_TypeDef band) 157 | { 158 | // Make sure clocks are disabled. 159 | disableClocks(); 160 | 161 | // Set HFRCO for HF clock. 162 | CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFRCO); 163 | 164 | // Set HFRCO frequency. 165 | CMU_HFRCOBandSet(band); 166 | 167 | // Make sure unwanted oscillators are disabled specifically for EM1 and HFRCO. 168 | CMU_OscillatorEnable(cmuOsc_HFXO, false, true); 169 | CMU_OscillatorEnable(cmuOsc_LFXO, false, true); 170 | CMU_OscillatorEnable(cmuOsc_LFRCO, false, true); 171 | CMU_OscillatorEnable(cmuOsc_AUXHFRCO, false, true); 172 | #if defined(CMU_OSCENCMD_USHFRCOEN) 173 | CMU_OscillatorEnable(cmuOsc_USHFRCO, false, true); 174 | #endif 175 | 176 | // Enter EM1. 177 | EMU_EnterEM1(); 178 | } 179 | 180 | /***************************************************************************//** 181 | * @brief 182 | * Enter EM2 with RTC running with LFRCO. 183 | * 184 | * @details 185 | * Parameter: 186 | EM2.@n 187 | * Condition: 188 | * RTC prescaled to 1 Hz, 32.768 kHz LFRCO, VDD= 3.0 V.@n 189 | * 190 | * @note 191 | * To better understand disabling clocks and oscillators for specific modes, 192 | * see Reference Manual section EMU-Energy Management Unit and Table 10.1. 193 | ******************************************************************************/ 194 | void em_EM2_LfrcoRTC(void) 195 | { 196 | // Make sure clocks are disabled. 197 | disableClocks(); 198 | 199 | // Route the LFRCO clock to RTC. 200 | CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO); 201 | CMU_ClockEnable(cmuClock_RTC, true); 202 | 203 | // Configure RTC to 1Hz. 204 | CMU_ClockDivSet(cmuClock_RTC, cmuClkDiv_32768); 205 | 206 | // Enable clock to the interface with low energy modules. 207 | CMU_ClockEnable(cmuClock_CORELE, true); 208 | 209 | // Setup RTC parameters. 210 | RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; 211 | 212 | // Initialize RTC. 213 | RTC_Init(&rtcInit); 214 | 215 | // Make sure unwanted oscillators are disabled specifically for EM2 and LFRCO. 216 | CMU_OscillatorEnable(cmuOsc_LFXO, false, true); 217 | 218 | // Enter EM2. 219 | EMU_EnterEM2(false); 220 | } 221 | 222 | /***************************************************************************//** 223 | * @brief 224 | * Enter EM3. 225 | * 226 | * @details 227 | * Parameter: 228 | EM3.@n 229 | * Condition: 230 | * VDD= 3.0 V, ULFRCO enabled, LFRCO/LFXO disabled.@n 231 | * 232 | * @note 233 | * To better understand disabling clocks and oscillators for specific modes, 234 | * see Reference Manual section EMU-Energy Management Unit and Table 10.1. 235 | ******************************************************************************/ 236 | void em_EM3_Ulfrco(void) 237 | { 238 | // High and low frequency clocks are disabled in EM3. 239 | 240 | // ULFRCO is always running from EM0-EM3. 241 | 242 | // All unwanted oscillators are disabled in EM3. 243 | 244 | // Enter EM3. 245 | EMU_EnterEM3(false); 246 | } 247 | 248 | /***************************************************************************//** 249 | * @brief 250 | * Enter EM4. 251 | * 252 | * @details 253 | * Parameter: 254 | EM4. 255 | * Condition: 256 | * VDD= 3.0 V. 257 | * 258 | * @note 259 | * To better understand disabling clocks and oscillators for specific modes, 260 | * see Reference Manual section EMU-Energy Management Unit and Table 10.1. 261 | ******************************************************************************/ 262 | void em_EM4(void) 263 | { 264 | // High and low frequency clocks are disabled in EM4. 265 | 266 | // All unwanted oscillators are disabled in EM4. 267 | 268 | // Enter EM4. 269 | EMU_EnterEM4(); 270 | } 271 | 272 | /***************************************************************************//** 273 | * @brief Disable high frequency clocks 274 | ******************************************************************************/ 275 | static void disableHFClocks(void) 276 | { 277 | // Disable High Frequency Peripheral Clocks 278 | CMU_ClockEnable(cmuClock_HFPER, false); 279 | #if defined(CMU_HFPERCLKEN0_USART0) 280 | CMU_ClockEnable(cmuClock_USART0, false); 281 | #endif 282 | CMU_ClockEnable(cmuClock_USART1, false); 283 | CMU_ClockEnable(cmuClock_TIMER0, false); 284 | CMU_ClockEnable(cmuClock_TIMER1, false); 285 | #if defined(CMU_HFPERCLKEN0_TIMER2) 286 | CMU_ClockEnable(cmuClock_TIMER2, false); 287 | #endif 288 | CMU_ClockEnable(cmuClock_ACMP0, false); 289 | CMU_ClockEnable(cmuClock_PRS, false); 290 | CMU_ClockEnable(cmuClock_IDAC0, false); 291 | CMU_ClockEnable(cmuClock_GPIO, false); 292 | CMU_ClockEnable(cmuClock_VCMP, false); 293 | CMU_ClockEnable(cmuClock_ADC0, false); 294 | CMU_ClockEnable(cmuClock_I2C0, false); 295 | 296 | // Disable High Frequency Core/Bus Clocks 297 | CMU_ClockEnable(cmuClock_AES, false); 298 | CMU_ClockEnable(cmuClock_DMA, false); 299 | CMU_ClockEnable(cmuClock_HFLE, false); 300 | #if defined(CMU_HFCORECLKEN0_USB) 301 | CMU_ClockEnable(cmuClock_USB, false); 302 | #endif 303 | #if defined(CMU_HFCORECLKEN0_USBC) 304 | // Disable USBC clock by choosing unused oscillator (LFXO) 305 | CMU_ClockEnable(cmuClock_USBC, true); 306 | CMU_OscillatorEnable(cmuOsc_LFXO, true, true); 307 | CMU_ClockSelectSet(cmuClock_USBC, cmuSelect_LFXO); 308 | CMU_ClockEnable(cmuClock_USBC, false); 309 | #endif 310 | } 311 | 312 | /***************************************************************************//** 313 | * @brief Disable low frequency clocks 314 | ******************************************************************************/ 315 | static void disableLFClocks(void) 316 | { 317 | // Enable LFXO for Low Frequency Clock Disables 318 | CMU_OscillatorEnable(cmuOsc_LFXO, true, true); 319 | 320 | // Disable Low Frequency A Peripheral Clocks 321 | // Note: LFA clock must be sourced before modifying peripheral clock enables 322 | CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO); 323 | CMU_ClockEnable(cmuClock_RTC, false); 324 | CMU_ClockEnable(cmuClock_PCNT0, false); 325 | CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_Disabled); 326 | 327 | // Disable Low Frequency B Peripheral Clocks 328 | // Note: LFB clock must be sourced before modifying peripheral clock enables 329 | CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_LFXO); 330 | CMU_ClockEnable(cmuClock_LEUART0, false); 331 | CMU_ClockSelectSet(cmuClock_LFB, cmuSelect_Disabled); 332 | 333 | #if defined(_CMU_LFCCLKEN0_MASK) 334 | // Disable Low Frequency C Peripheral Clocks 335 | // Note: LFC clock must be sourced before modifying peripheral clock enables 336 | CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_LFXO); 337 | CMU_ClockEnable(cmuClock_USBLE, false); 338 | CMU_ClockSelectSet(cmuClock_LFC, cmuSelect_Disabled); 339 | #endif 340 | 341 | // Disable Low Frequency Oscillator 342 | CMU_OscillatorEnable(cmuOsc_LFXO, false, true); 343 | } 344 | 345 | /***************************************************************************//** 346 | * @brief Disable all clocks to achieve lowest current consumption numbers. 347 | ******************************************************************************/ 348 | static void disableClocks(void) 349 | { 350 | // Disable High Frequency Clocks 351 | disableHFClocks(); 352 | 353 | // Disable Low Frequency Clocks 354 | disableLFClocks(); 355 | } 356 | 357 | /***************************************************************************//** 358 | * @brief Calculate primes. 359 | ******************************************************************************/ 360 | static void primeCalc(void) 361 | { 362 | uint32_t i, d, n; 363 | uint32_t primes[64]; 364 | 365 | // Find prime numbers forever. 366 | while (1) { 367 | primes[0] = 1; 368 | for (i = 1; i < 64; ) { 369 | for (n = primes[i - 1] + 1;; n++) { 370 | for (d = 2; d <= n; d++) { 371 | if (n == d) { 372 | primes[i] = n; 373 | goto nexti; 374 | } 375 | if (n % d == 0) { 376 | break; 377 | } 378 | } 379 | } 380 | nexti: 381 | i++; 382 | } 383 | } 384 | } 385 | -------------------------------------------------------------------------------- /rf24tests/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "em_device.h" 2 | #include "em_chip.h" 3 | #include "em_cmu.h" 4 | #include "em_emu.h" 5 | #include "em_gpio.h" 6 | #include "em_i2c.h" 7 | #include "em_usart.h" 8 | #include "em_rtc.h" 9 | #include "InitDevice.h" 10 | #include "nRF24L01.h" 11 | #include "RF24.h" 12 | #include "delay.h" 13 | 14 | /* Defines*/ 15 | #define LFRCO_FREQUENCY 32768 16 | 17 | #define HDC1080_ADDRESS 0x40 18 | #define CMD_ARRAY_SIZE 1 19 | #define DATA_ARRAY_SIZE 10 20 | 21 | const uint8_t slaveAddress[5] = {'R','x','A','A','A'}; 22 | float temp = 0; 23 | 24 | 25 | // RTC Interrupt Handler, clears the flag. 26 | void RTC_IRQHandler(void) 27 | { 28 | RTC_IntClear(RTC_IFC_COMP0); // Clear interrupt source 29 | } 30 | 31 | 32 | void setupRtc(int msBetweenWakeup) 33 | { 34 | /* Starting LFRCO and waiting until it is stable */ 35 | CMU_OscillatorEnable(cmuOsc_LFRCO, true, true); 36 | 37 | /* Enabling clock to the interface of the low energy modules */ 38 | CMU_ClockEnable(cmuClock_CORELE, true); 39 | 40 | CMU_ClockSelectSet(cmuClock_LFA,cmuSelect_LFRCO); 41 | CMU_ClockEnable(cmuClock_RTC, true); 42 | 43 | 44 | RTC_Init_TypeDef rtcInit = RTC_INIT_DEFAULT; 45 | 46 | /* Setting the compare value of the RTC */ 47 | RTC_CompareSet(0, (((LFRCO_FREQUENCY * msBetweenWakeup) / 1000)-1)); 48 | 49 | /* Enabling Interrupt from RTC */ 50 | RTC_IntEnable(RTC_IEN_COMP0); 51 | NVIC_ClearPendingIRQ(RTC_IRQn); 52 | NVIC_EnableIRQ(RTC_IRQn); 53 | 54 | /* Initialize the RTC */ 55 | RTC_Init(&rtcInit); 56 | 57 | } 58 | 59 | // Globals for persistent storage 60 | uint8_t cmd_array[CMD_ARRAY_SIZE]; 61 | uint8_t data_array[DATA_ARRAY_SIZE]; 62 | 63 | // Used by the read_register and write_register functions 64 | // data_array is read data for WRITE_READ and tx2 data for WRITE_WRITE 65 | void i2c_transfer(uint16_t device_addr, uint8_t cmd_array[], uint8_t data_array[], uint16_t cmd_len, uint16_t data_len, uint8_t flag) 66 | { 67 | // Transfer structure 68 | I2C_TransferSeq_TypeDef i2cTransfer; 69 | 70 | // Initialize I2C transfer 71 | I2C_TransferReturn_TypeDef result; 72 | i2cTransfer.addr = device_addr << 1; // This shift is important!; 73 | i2cTransfer.flags = flag; 74 | i2cTransfer.buf[0].data = cmd_array; 75 | i2cTransfer.buf[0].len = cmd_len; 76 | 77 | // Note that WRITE_WRITE this is tx2 data 78 | i2cTransfer.buf[1].data = data_array; 79 | i2cTransfer.buf[1].len = data_len; 80 | 81 | // Set up the transfer 82 | result = I2C_TransferInit(I2C0, &i2cTransfer); 83 | 84 | // Do it until the transfer is done 85 | while (result != i2cTransferDone) 86 | { 87 | if (result != i2cTransferInProgress) 88 | { 89 | break; 90 | } 91 | result = I2C_Transfer(I2C0); 92 | } 93 | } 94 | 95 | struct nodeData{ 96 | float temp; 97 | float humd; 98 | char batt; 99 | char id; 100 | }; 101 | nodeData nodeSend; 102 | 103 | int main(void) 104 | { 105 | /* Chip errata */ 106 | CHIP_Init(); 107 | enter_DefaultMode_from_RESET(); 108 | 109 | 110 | RF24 radio(0, 0); 111 | 112 | //delay(3000); 113 | 114 | 115 | 116 | radio.begin(); 117 | radio.openWritingPipe(slaveAddress); 118 | 119 | /* Infinite loop */ 120 | while (1) { 121 | 122 | //GPIO_PinModeSet(LED0_PORT, LED0_PIN, gpioModePushPull, GPIO_PinInGet(PB0_PORT, PB0_PIN)); 123 | //GPIO_PinModeSet(LED1_PORT, LED1_PIN, gpioModePushPull, GPIO_PinInGet(PB1_PORT, PB1_PIN)); 124 | cmd_array[0] = 0x00; 125 | data_array[0] = 0x00; 126 | i2c_transfer(HDC1080_ADDRESS, cmd_array, data_array, 1, 0, I2C_FLAG_WRITE); 127 | setupRtc(40); 128 | EMU_EnterEM2(false); 129 | i2c_transfer(HDC1080_ADDRESS, cmd_array, data_array, 4, 0, I2C_FLAG_READ); 130 | float temp = (cmd_array[0] << 8 | cmd_array[1]) * 165.0 / 65536.0 - 40.0; 131 | float humd = 100.0*((unsigned int)(cmd_array[2] << 8 | cmd_array[3]) / 65536.0); 132 | cmd_array[0] = 0x02; 133 | i2c_transfer(HDC1080_ADDRESS, cmd_array, data_array, 1, 2, I2C_FLAG_WRITE_READ); 134 | char battBit = '0'; 135 | if((data_array[0] & 0b00010000) != 0) battBit = '1'; 136 | 137 | nodeSend.temp = temp; 138 | nodeSend.humd = humd; 139 | nodeSend.batt = battBit; 140 | nodeSend.id = 'A'; 141 | 142 | radio.powerUp(); 143 | //radio.write(&temp, sizeof(float)); 144 | radio.write(&nodeSend, sizeof(nodeSend)); 145 | 146 | 147 | radio.powerDown(); 148 | //i2c_read_register(0x00); 149 | 150 | 151 | //GPIO_PinModeSet(RF24_CE_PORT, RF24_CE_PIN, gpioModePushPull, 0); 152 | //GPIO_PinModeSet(RF24_IRQ_PORT, RF24_IRQ_PIN, gpioModeInput, 0); 153 | //GPIO_PinModeSet(LED0_PORT, LED0_PIN, gpioModePushPull, 0); 154 | //GPIO_PinModeSet(USART1_CLK_PORT, USART1_CLK_PIN, gpioModePushPull, 0); 155 | GPIO_PinModeSet(USART1_CS_PORT, USART1_CS_PIN, gpioModePushPull, 0); 156 | //GPIO_PinModeSet(USART1_RX_PORT, USART1_RX_PIN, gpioModePushPull, 0); 157 | //GPIO_PinModeSet(USART1_TX_PORT, USART1_TX_PIN, gpioModePushPull, 0); 158 | //GPIO_PinModeSet(I2C0_SCL_PORT, I2C0_SCL_PIN, gpioModePushPull, 1); 159 | //GPIO_PinModeSet(I2C0_SDA_PORT, I2C0_SDA_PIN, gpioModePushPull, 1); 160 | 161 | setupRtc(10*60000); // sleep for 10 m 162 | EMU_EnterEM2(false); 163 | /************************** Wake-up happens here *************************/ 164 | 165 | 166 | 167 | } 168 | } 169 | --------------------------------------------------------------------------------