/
nrf5x_utils.c
203 lines (168 loc) · 6.79 KB
/
nrf5x_utils.c
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/* Copyright (c) 2012 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include "nrf5x_utils.h"
#include "nrf.h"
#include "nrf_gpio.h"
#include "nrf_gpiote.h"
#include "nrf_uart.h"
#include "nrf_error.h"
#include "nrf_nvmc.h"
#include "nrf_timer.h"
#include "nrf_drv_gpiote.h"
#include "nrf_drv_ppi.h"
#include "jsparse.h"
unsigned int nrf_utils_get_baud_enum(int baud) {
// https://devzone.nordicsemi.com/f/nordic-q-a/391/uart-baudrate-register-values#post-id-1194
uint64_t br = (((uint64_t)baud) * (1<<25)) / 125000;
if (br > 0xFFFFFFFF) return 0;
return ((uint32_t)br + 0x800) & 0xFFFFF000;
}
// Configure the low frequency clock to use the external 32.768 kHz crystal as a source. Start this clock.
void nrf_utils_lfclk_config_and_start()
{
// Select the preferred clock source.
#ifdef ESPR_LSE_ENABLE
NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos;
#else
NRF_CLOCK->LFCLKSRC = CLOCK_LFCLKSRC_SRC_RC << CLOCK_LFCLKSRC_SRC_Pos;
#endif
// Start the 32 kHz clock, and wait for the start up to complete
NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
NRF_CLOCK->TASKS_LFCLKSTART = 1;
while(NRF_CLOCK->EVENTS_LFCLKSTARTED == 0);
/*
// wait until the clock is running - Xtal only?
while (((NRF_CLOCK->LFCLKSTAT & CLOCK_LFCLKSTAT_STATE_Msk) != ((CLOCK_LFCLKSTAT_STATE_Running << CLOCK_LFCLKSTAT_STATE_Pos) & CLOCK_LFCLKSTAT_STATE_Msk)))
{
// Do nothing...
}*/
}
unsigned int nrf_utils_cap_sense(int capSenseTxPin, int capSenseRxPin) {
#ifdef NRF5DDD
uint32_t err_code;
nrf_drv_gpiote_in_config_t rxconfig = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
nrf_drv_gpiote_in_init(capSenseRxPin, &rxconfig, 0);
nrf_drv_gpiote_in_event_enable(capSenseRxPin, false /* no interrupt */);
//
nrf_drv_gpiote_out_config_t txconfig = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
nrf_drv_gpiote_out_init(capSenseTxPin, &txconfig);
nrf_drv_gpiote_out_task_enable(capSenseTxPin);
//;
nrf_timer_mode_set(NRF_TIMER2, TIMER_MODE_MODE_Timer);
nrf_timer_bit_width_set(NRF_TIMER2, NRF_TIMER_BIT_WIDTH_16);
nrf_timer_frequency_set(NRF_TIMER2, NRF_TIMER_FREQ_16MHz);
nrf_timer_cc_write(NRF_TIMER2, 0, 0);
nrf_timer_cc_write(NRF_TIMER2, 1, 2047);
nrf_timer_cc_write(NRF_TIMER2, 3, 4095);
nrf_timer_shorts_enable(NRF_TIMER2, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK);
nrf_ppi_channel_t ppi_channel1, ppi_channel2, ppi_channel3;
// 1: When RX pin goes low->high, capture it in the timer
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(ppi_channel1,
nrf_drv_gpiote_in_event_addr_get(capSenseRxPin),
nrf_timer_task_address_get(NRF_TIMER2, NRF_TIMER_TASK_CAPTURE2));
APP_ERROR_CHECK(err_code);
// 2: When timer is at Compare0, toggle
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel2);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(ppi_channel2,
nrf_timer_event_address_get(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE0),
nrf_drv_gpiote_out_task_addr_get(capSenseTxPin));
APP_ERROR_CHECK(err_code);
// 3: When timer is at Compare1, toggle
err_code = nrf_drv_ppi_channel_alloc(&ppi_channel3);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_assign(ppi_channel3,
nrf_timer_event_address_get(NRF_TIMER2, NRF_TIMER_EVENT_COMPARE1),
nrf_drv_gpiote_out_task_addr_get(capSenseTxPin));
APP_ERROR_CHECK(err_code);
// Enable both configured PPI channels
err_code = nrf_drv_ppi_channel_enable(ppi_channel1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(ppi_channel2);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_ppi_channel_enable(ppi_channel3);
APP_ERROR_CHECK(err_code);
// start timer
NRF_TIMER2->CC[2] = 0;
nrf_timer_task_trigger(NRF_TIMER2, NRF_TIMER_TASK_START);
nrf_gpio_cfg_input(capSenseRxPin, NRF_GPIO_PIN_NOPULL);
nrf_gpio_cfg_output(capSenseTxPin);
//
unsigned int sum = 0;
NRF_TIMER2->EVENTS_COMPARE[1] = 0;
int i;
for (i=0;i<50;i++) {
unsigned int timeout = 100000;
while (!NRF_TIMER2->EVENTS_COMPARE[1] && --timeout);
NRF_TIMER2->EVENTS_COMPARE[1] = 0;
sum += NRF_TIMER2->CC[2];
if (jspIsInterrupted()) break;
}
nrf_gpio_cfg_input(capSenseTxPin, NRF_GPIO_PIN_NOPULL);
nrf_timer_task_trigger(NRF_TIMER2, NRF_TIMER_TASK_STOP);
nrf_timer_shorts_disable(NRF_TIMER2, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK);
nrf_drv_ppi_channel_disable(ppi_channel3);
nrf_drv_ppi_channel_disable(ppi_channel2);
nrf_drv_ppi_channel_disable(ppi_channel1);
nrf_drv_ppi_channel_free(ppi_channel3);
nrf_drv_ppi_channel_free(ppi_channel2);
nrf_drv_ppi_channel_free(ppi_channel1);
nrf_drv_gpiote_in_uninit(capSenseTxPin);
nrf_drv_gpiote_in_uninit(capSenseRxPin);
return sum;
#else
unsigned int sum = 0;
int i;
unsigned int mask = 1<<capSenseRxPin;
nrf_gpio_cfg_input(capSenseRxPin, NRF_GPIO_PIN_NOPULL);
nrf_gpio_pin_clear(capSenseTxPin);
nrf_gpio_cfg_output(capSenseTxPin);
for (i=0;i<100;i++) {
const unsigned int CTR_MAX = 100000;
unsigned int ctr = CTR_MAX;
nrf_gpio_pin_set(capSenseTxPin);
while (!(NRF_GPIO->IN & mask) && ctr--);
sum += CTR_MAX-ctr;
nrf_gpio_pin_clear(capSenseTxPin);
while (NRF_GPIO->IN & mask && ctr--);
sum += CTR_MAX-ctr;
if (jspIsInterrupted()) break;
}
nrf_gpio_cfg_input(capSenseTxPin, NRF_GPIO_PIN_NOPULL);
return sum;
#endif
}
/// Ensure UICR flags are set correctly for the current device
void nrf_configure_uicr_flags(void) {
#if defined (NRF52840_XXAA) && !defined(ESPR_REGOUT0_1_8V)
// Ensure that GPIO output voltage is 3.3v (not 1.8v) if powered via regulator
// Configure UICR_REGOUT0 register only if it is set to default value.
if ((NRF_UICR->REGOUT0 & UICR_REGOUT0_VOUT_Msk) ==
(UICR_REGOUT0_VOUT_DEFAULT << UICR_REGOUT0_VOUT_Pos))
{
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
NRF_UICR->REGOUT0 = (NRF_UICR->REGOUT0 & ~((uint32_t)UICR_REGOUT0_VOUT_Msk)) |
(UICR_REGOUT0_VOUT_3V3 << UICR_REGOUT0_VOUT_Pos);
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren;
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
// System reset is needed to update UICR registers.
NVIC_SystemReset();
}
#endif
}