Skip to content

Commit 8de419c

Browse files
authored
Merge pull request #10 from nvlsianpu/nordic_sdk_integration
Analog Input for nRF51 rework + PWM fix
2 parents f21ca34 + 1c262e3 commit 8de419c

File tree

7 files changed

+1075
-34
lines changed

7 files changed

+1075
-34
lines changed

hal/targets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,7 @@
13751375
"supported_form_factors": ["ARDUINO"],
13761376
"inherits": ["MCU_NRF51_32K"],
13771377
"progen": {"target": "nrf51-dk"},
1378-
"device_has": ["ERROR_PATTERN", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH"]
1378+
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "INTERRUPTIN", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH"]
13791379
},
13801380
"NRF51_DK_BOOT": {
13811381
"supported_form_factors": ["ARDUINO"],

hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF51822/analogin_api.c

Lines changed: 27 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,18 @@
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
15-
*/
15+
*/
1616
#include "mbed_assert.h"
1717
#include "analogin_api.h"
1818
#include "cmsis.h"
1919
#include "pinmap.h"
20+
#include "nrf_drv_adc.h"
2021

2122
#ifdef DEVICE_ANALOGIN
2223

23-
#define ANALOGIN_MEDIAN_FILTER 1
24-
#define ADC_10BIT_RANGE 0x3FF
25-
#define ADC_RANGE ADC_10BIT_RANGE
24+
25+
#define ADC_10BIT_RANGE 0x3FF
26+
#define ADC_RANGE ADC_10BIT_RANGE
2627

2728
static const PinMap PinMap_ADC[] = {
2829
{p1, ADC0_0, 4},
@@ -38,47 +39,42 @@ static const PinMap PinMap_ADC[] = {
3839
{NC, NC, 0}
3940
};
4041

42+
4143
void analogin_init(analogin_t *obj, PinName pin)
4244
{
43-
int analogInputPin = 0;
44-
const PinMap *map = PinMap_ADC;
45-
46-
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC); //(NRF_ADC_Type *)
45+
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
4746
MBED_ASSERT(obj->adc != (ADCName)NC);
4847

49-
while (map->pin != NC) {
50-
if (map->pin == pin) {
51-
analogInputPin = map->function;
52-
break;
53-
}
54-
map++;
55-
}
56-
obj->adc_pin = (uint8_t)analogInputPin;
57-
58-
NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
59-
NRF_ADC->CONFIG = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos) |
60-
(ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) |
61-
(ADC_CONFIG_REFSEL_SupplyOneThirdPrescaling << ADC_CONFIG_REFSEL_Pos) |
62-
(analogInputPin << ADC_CONFIG_PSEL_Pos) |
63-
(ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos);
48+
uint32_t pinFunc = pinmap_function(pin, PinMap_ADC);
49+
MBED_ASSERT(pinFunc != (uint32_t)NC);
50+
51+
obj->adc_pin = pinFunc;
52+
53+
ret_code_t ret_code;
54+
// p_config, event_handler
55+
ret_code = nrf_drv_adc_init(NULL , NULL); // select blocking mode
56+
MBED_ASSERT(ret_code == NRF_SUCCESS);
6457
}
6558

6659
uint16_t analogin_read_u16(analogin_t *obj)
6760
{
68-
NRF_ADC->CONFIG &= ~ADC_CONFIG_PSEL_Msk;
69-
NRF_ADC->CONFIG |= obj->adc_pin << ADC_CONFIG_PSEL_Pos;
70-
NRF_ADC->EVENTS_END = 0;
71-
NRF_ADC->TASKS_START = 1;
72-
73-
while (!NRF_ADC->EVENTS_END) {
74-
}
61+
nrf_adc_value_t adc_value;
62+
63+
nrf_drv_adc_channel_t adc_channel = NRF_DRV_ADC_DEFAULT_CHANNEL(obj->adc_pin);
64+
7565

76-
return (uint16_t)NRF_ADC->RESULT; // 10 bit
66+
ret_code_t ret_code;
67+
68+
ret_code = nrf_drv_adc_sample_convert( &adc_channel, &adc_value);
69+
MBED_ASSERT(ret_code == NRF_SUCCESS);
70+
71+
return adc_value;
7772
}
7873

7974
float analogin_read(analogin_t *obj)
8075
{
8176
uint16_t value = analogin_read_u16(obj);
77+
8278
return (float)value * (1.0f / (float)ADC_RANGE);
8379
}
8480

hal/targets/hal/TARGET_NORDIC/TARGET_NRF5/TARGET_MCU_NRF51822/pwmout_api.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ void pwmout_init(pwmout_t *obj, PinName pin)
138138

139139
void pwmout_free(pwmout_t *obj)
140140
{
141-
MBED_ASSERT(obj->pwm != (PWMName)NC);
141+
MBED_ASSERT(obj->pwm_name != (PWMName)NC);
142142
MBED_ASSERT(obj->pwm_channel < PWM_CHANNELS_PER_INSTANCE);
143143

144144
pwm_t * pwm = (pwm_t *) obj->pwm_struct;
@@ -160,7 +160,8 @@ void pwmout_write(pwmout_t *obj, float value)
160160
if (value > 1.0f) {
161161
value = 1.0f;
162162
}
163-
uint16_t ticks = (uint16_t)((float)app_pwm_cycle_ticks_get(pwm->instance) * value);
163+
164+
app_pwm_channel_duty_set(pwm->instance, obj->pwm_channel, (app_pwm_duty_t)(value * 100.0f) );
164165
}
165166

166167
float pwmout_read(pwmout_t *obj)
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
/* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
2+
*
3+
* The information contained herein is property of Nordic Semiconductor ASA.
4+
* Terms and conditions of usage are described in detail in NORDIC
5+
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
6+
*
7+
* Licensees are granted free, non-transferable use of the information. NO
8+
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
9+
* the file.
10+
*
11+
*/
12+
13+
#include "nrf_drv_adc.h"
14+
#include "nrf_drv_common.h"
15+
#include "nrf_assert.h"
16+
#include "app_util_platform.h"
17+
#include "app_util.h"
18+
19+
typedef struct
20+
{
21+
nrf_drv_adc_event_handler_t event_handler;
22+
nrf_drv_adc_channel_t * p_head;
23+
nrf_drv_adc_channel_t * p_current_conv;
24+
nrf_adc_value_t * p_buffer;
25+
uint8_t size;
26+
uint8_t idx;
27+
nrf_drv_state_t state;
28+
} adc_cb_t;
29+
30+
static adc_cb_t m_cb;
31+
static const nrf_drv_adc_config_t m_default_config = NRF_DRV_ADC_DEFAULT_CONFIG;
32+
33+
ret_code_t nrf_drv_adc_init(nrf_drv_adc_config_t const * p_config,
34+
nrf_drv_adc_event_handler_t event_handler)
35+
{
36+
if (m_cb.state != NRF_DRV_STATE_UNINITIALIZED)
37+
{
38+
return NRF_ERROR_INVALID_STATE;
39+
}
40+
41+
nrf_adc_event_clear(NRF_ADC_EVENT_END);
42+
if (event_handler)
43+
{
44+
if (!p_config)
45+
{
46+
p_config = (nrf_drv_adc_config_t *)&m_default_config;
47+
}
48+
nrf_drv_common_irq_enable(ADC_IRQn, p_config->interrupt_priority);
49+
}
50+
m_cb.event_handler = event_handler;
51+
m_cb.state = NRF_DRV_STATE_INITIALIZED;
52+
53+
return NRF_SUCCESS;
54+
}
55+
56+
void nrf_drv_adc_uninit(void)
57+
{
58+
m_cb.p_head = NULL;
59+
nrf_drv_common_irq_disable(ADC_IRQn);
60+
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
61+
nrf_adc_task_trigger(NRF_ADC_TASK_STOP);
62+
63+
m_cb.state = NRF_DRV_STATE_UNINITIALIZED;
64+
}
65+
66+
void nrf_drv_adc_channel_enable(nrf_drv_adc_channel_t * const p_channel)
67+
{
68+
ASSERT(mp_state == NRF_DRV_STATE_INITIALIZED);
69+
ASSERT(!is_address_from_stack(p_channel));
70+
71+
p_channel->p_next = NULL;
72+
if (m_cb.p_head == NULL)
73+
{
74+
m_cb.p_head = p_channel;
75+
}
76+
else
77+
{
78+
nrf_drv_adc_channel_t * p_curr_channel = m_cb.p_head;
79+
while (p_curr_channel->p_next != NULL)
80+
{
81+
ASSERT(p_channel != p_curr_channel);
82+
p_curr_channel = p_curr_channel->p_next;
83+
}
84+
p_curr_channel->p_next = p_channel;
85+
}
86+
}
87+
88+
void nrf_drv_adc_channel_disable(nrf_drv_adc_channel_t * const p_channel)
89+
{
90+
ASSERT(mp_state == NRF_DRV_STATE_INITIALIZED);
91+
ASSERT(m_cb.p_head);
92+
93+
nrf_drv_adc_channel_t * p_curr_channel = m_cb.p_head;
94+
nrf_drv_adc_channel_t * p_prev_channel = NULL;
95+
while(p_curr_channel != p_channel)
96+
{
97+
p_prev_channel = p_curr_channel;
98+
p_curr_channel = p_curr_channel->p_next;
99+
ASSERT(p_curr_channel == NULL);
100+
}
101+
if (p_prev_channel)
102+
{
103+
p_prev_channel->p_next = p_curr_channel->p_next;
104+
}
105+
else
106+
{
107+
m_cb.p_head = p_curr_channel->p_next;
108+
}
109+
}
110+
111+
void nrf_drv_adc_sample(void)
112+
{
113+
ASSERT(mp_state != NRF_DRV_STATE_UNINITIALIZED);
114+
ASSERT(!nrf_adc_is_busy());
115+
nrf_adc_start();
116+
}
117+
118+
ret_code_t nrf_drv_adc_sample_convert(nrf_drv_adc_channel_t const * const p_channel,
119+
nrf_adc_value_t * p_value)
120+
{
121+
ASSERT(mp_state != NRF_DRV_STATE_UNINITIALIZED);
122+
if(m_cb.state == NRF_DRV_STATE_POWERED_ON)
123+
{
124+
return NRF_ERROR_BUSY;
125+
}
126+
else
127+
{
128+
m_cb.state = NRF_DRV_STATE_POWERED_ON;
129+
130+
nrf_adc_config_set(p_channel->config.data);
131+
nrf_adc_enable();
132+
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
133+
nrf_adc_start();
134+
if (p_value)
135+
{
136+
while(!nrf_adc_event_check(NRF_ADC_EVENT_END)) {}
137+
nrf_adc_event_clear(NRF_ADC_EVENT_END);
138+
*p_value = (nrf_adc_value_t)nrf_adc_result_get();
139+
nrf_adc_disable();
140+
141+
m_cb.state = NRF_DRV_STATE_INITIALIZED;
142+
}
143+
else
144+
{
145+
ASSERT(m_cb.event_handler);
146+
m_cb.p_buffer = NULL;
147+
nrf_adc_int_enable(NRF_ADC_INT_END_MASK);
148+
}
149+
return NRF_SUCCESS;
150+
}
151+
}
152+
153+
static bool adc_sample_process()
154+
{
155+
nrf_adc_event_clear(NRF_ADC_EVENT_END);
156+
nrf_adc_disable();
157+
m_cb.p_buffer[m_cb.idx] = (nrf_adc_value_t)nrf_adc_result_get();
158+
m_cb.idx++;
159+
if (m_cb.idx < m_cb.size)
160+
{
161+
bool task_trigger = false;
162+
if (m_cb.p_current_conv->p_next == NULL)
163+
{
164+
m_cb.p_current_conv = m_cb.p_head;
165+
}
166+
else
167+
{
168+
m_cb.p_current_conv = m_cb.p_current_conv->p_next;
169+
task_trigger = true;
170+
}
171+
nrf_adc_config_set(m_cb.p_current_conv->config.data);
172+
nrf_adc_enable();
173+
if (task_trigger)
174+
{
175+
//nrf_adc_start();
176+
nrf_adc_task_trigger(NRF_ADC_TASK_START);
177+
}
178+
return false;
179+
}
180+
else
181+
{
182+
return true;
183+
}
184+
}
185+
186+
ret_code_t nrf_drv_adc_buffer_convert(nrf_adc_value_t * buffer, uint16_t size)
187+
{
188+
ASSERT(mp_state != NRF_DRV_STATE_UNINITIALIZED);
189+
if(m_cb.state == NRF_DRV_STATE_POWERED_ON)
190+
{
191+
return NRF_ERROR_BUSY;
192+
}
193+
else
194+
{
195+
m_cb.state = NRF_DRV_STATE_POWERED_ON;
196+
m_cb.p_current_conv = m_cb.p_head;
197+
m_cb.size = size;
198+
m_cb.idx = 0;
199+
m_cb.p_buffer = buffer;
200+
nrf_adc_config_set(m_cb.p_current_conv->config.data);
201+
nrf_adc_event_clear(NRF_ADC_EVENT_END);
202+
nrf_adc_enable();
203+
if (m_cb.event_handler)
204+
{
205+
nrf_adc_int_enable(NRF_ADC_INT_END_MASK);
206+
}
207+
else
208+
{
209+
while(1)
210+
{
211+
while(!nrf_adc_event_check(NRF_ADC_EVENT_END)){}
212+
213+
if (adc_sample_process())
214+
{
215+
m_cb.state = NRF_DRV_STATE_INITIALIZED;
216+
break;
217+
}
218+
}
219+
}
220+
return NRF_SUCCESS;
221+
}
222+
}
223+
224+
bool nrf_drv_adc_is_busy(void)
225+
{
226+
ASSERT(mp_state != NRF_DRV_STATE_UNINITIALIZED);
227+
return (m_cb.state == NRF_DRV_STATE_POWERED_ON) ? true : false;
228+
}
229+
230+
void ADC_IRQHandler(void)
231+
{
232+
if (m_cb.p_buffer == NULL)
233+
{
234+
nrf_adc_event_clear(NRF_ADC_EVENT_END);
235+
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
236+
nrf_adc_disable();
237+
nrf_drv_adc_evt_t evt;
238+
evt.type = NRF_DRV_ADC_EVT_SAMPLE;
239+
evt.data.sample.sample = (nrf_adc_value_t)nrf_adc_result_get();
240+
m_cb.state = NRF_DRV_STATE_INITIALIZED;
241+
m_cb.event_handler(&evt);
242+
}
243+
else if (adc_sample_process())
244+
{
245+
nrf_adc_int_disable(NRF_ADC_INT_END_MASK);
246+
nrf_drv_adc_evt_t evt;
247+
evt.type = NRF_DRV_ADC_EVT_DONE;
248+
evt.data.done.p_buffer = m_cb.p_buffer;
249+
evt.data.done.size = m_cb.size;
250+
m_cb.state = NRF_DRV_STATE_INITIALIZED;
251+
m_cb.event_handler(&evt);
252+
}
253+
}

0 commit comments

Comments
 (0)