├── .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 |
32 |
33 |
34 |
35 |
36 |
40 |
41 |
42 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
66 |
70 |
71 |
72 |
73 |
82 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
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 |
138 |
139 |
140 |
141 |
142 |
146 |
147 |
148 |
158 |
159 |
160 |
161 |
162 |
163 |
173 |
177 |
178 |
179 |
180 |
190 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
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 |
--------------------------------------------------------------------------------