Skip to content

Commit 07ce12f

Browse files
committed
nrf52 PwmOut in progress.
1 parent 0d9dc1e commit 07ce12f

File tree

6 files changed

+1647
-6
lines changed

6 files changed

+1647
-6
lines changed

hal/targets.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,6 @@
17731773
"NRF52_PAN_62",
17741774
"NRF52_PAN_63"
17751775
],
1776-
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"]
1776+
"device_has": ["ANALOGIN", "ERROR_PATTERN", "I2C", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_ASYNCH", "SLEEP", "SPI", "SPI_ASYNCH", "SPISLAVE"]
17771777
}
17781778
}

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

Lines changed: 203 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,49 +44,249 @@
4444

4545
#if DEVICE_PWMOUT
4646

47-
// TODO - provide an implementation.
47+
#include "app_util_platform.h"
48+
#include "nrf_drv_pwm.h"
4849

49-
//#include "nrf_pwm.h"
50+
#define PWM_INSTANCE_COUNT 3
5051

52+
static nrf_drv_pwm_t m_pwm_driver[PWM_INSTANCE_COUNT] =
53+
{
54+
NRF_DRV_PWM_INSTANCE(0),
55+
NRF_DRV_PWM_INSTANCE(1),
56+
NRF_DRV_PWM_INSTANCE(2)
57+
};
58+
59+
typedef struct
60+
{
61+
uint32_t period_us;
62+
uint32_t duty_us;
63+
} pwm_signal_t;
64+
65+
typedef struct
66+
{
67+
nrf_drv_pwm_t * p_pwm_driver;
68+
pwm_signal_t signal;
69+
} pwm_t;
70+
71+
static pwm_t m_pwm[PWM_INSTANCE_COUNT] =
72+
{
73+
{.p_pwm_driver = NULL},
74+
{.p_pwm_driver = NULL},
75+
{.p_pwm_driver = NULL}
76+
};
77+
78+
typedef struct
79+
{
80+
uint16_t period;
81+
uint16_t duty;
82+
nrf_pwm_clk_t pwm_clk;
83+
} pulsewidth_set_t;
84+
85+
86+
static void internal_pwmout_exe(pwmout_t *obj);
87+
5188
void pwmout_init(pwmout_t *obj, PinName pin)
5289
{
90+
uint32_t i;
91+
92+
for (i = 0; PWM_INSTANCE_COUNT; i++)
93+
{
94+
if (m_pwm[i].p_pwm_driver == NULL) // a driver instance not assigned to the obj?
95+
{
96+
obj->pin = pin;
97+
/// @todo obj->pwm_name =
98+
obj->pwm_channel = i;
99+
100+
m_pwm[i].p_pwm_driver = &m_pwm_driver[i];
101+
m_pwm[i].signal.period_us = 200000; // 0.02 s
102+
m_pwm[i].signal.duty_us = 100000;
103+
104+
obj->pwm_struct = &m_pwm[i];
105+
106+
internal_pwmout_exe(obj);
107+
break;
108+
}
109+
}
110+
111+
MBED_ASSERT(i != PWM_INSTANCE_COUNT); // assert if free instance was not found.
53112
}
54113

55114
void pwmout_free(pwmout_t *obj)
56115
{
116+
nrf_drv_pwm_uninit( (nrf_drv_pwm_t*) obj->pwm_struct );
117+
118+
m_pwm[obj->pwm_channel].p_pwm_driver = NULL;
119+
/// @todo release gpio
57120
}
58121

59122
void pwmout_write(pwmout_t *obj, float percent)
60123
{
124+
125+
if (percent < 0)
126+
{
127+
percent = 0;
128+
}
129+
else if (percent > 100)
130+
{
131+
percent = 100;
132+
}
133+
134+
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
135+
136+
int us = (((int)p_pwm_signal->period_us) * percent) / 100;
137+
138+
pwmout_pulsewidth_us(obj, us);
61139
}
62140

63141
float pwmout_read(pwmout_t *obj)
64142
{
65-
return 0.0f;
143+
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
144+
145+
return (float)p_pwm_signal->duty_us / (float)p_pwm_signal->period_us * 100;
66146
}
67147

68148
void pwmout_period(pwmout_t *obj, float seconds)
69149
{
150+
// @todo saturation
151+
int us = seconds * 1000000;
152+
153+
pwmout_period_us(obj, us);
70154
}
71155

72156
void pwmout_period_ms(pwmout_t *obj, int ms)
73157
{
158+
int us = ms * 1000;
159+
160+
pwmout_period_us(obj, us);
74161
}
75162

76163
void pwmout_period_us(pwmout_t *obj, int us)
77164
{
165+
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
166+
167+
p_pwm_signal->period_us = us;
168+
169+
internal_pwmout_exe(obj);
78170
}
79171

80172
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
81173
{
174+
// @todo saturation
175+
int us = seconds * 1000000;
176+
177+
pwmout_pulsewidth_us(obj,us);
82178
}
83179

84180
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
85181
{
182+
// @todo saturation
183+
int us = ms * 1000;
184+
185+
pwmout_pulsewidth_us(obj,us);
86186
}
87187

88188
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
89189
{
190+
// @todo saturation
191+
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
192+
193+
p_pwm_signal->duty_us = us;
194+
195+
internal_pwmout_exe(obj);
196+
}
197+
198+
199+
200+
201+
202+
203+
static ret_code_t pulsewidth_us_set_get(int period_us, int duty_us, pulsewidth_set_t * const p_settings)
204+
{
205+
uint16_t div;
206+
nrf_pwm_clk_t pwm_clk = NRF_PWM_CLK_16MHz;
207+
208+
for(div = 1; div <= 128 ; div <<= 1)
209+
{
210+
if (0xFFFF >= period_us)
211+
{
212+
p_settings->period = period_us; // unit [us * div]
213+
p_settings->duty = duty_us; // unit [us * div]
214+
p_settings->pwm_clk = pwm_clk;
215+
216+
return NRF_SUCCESS;
217+
}
218+
219+
period_us >>= 1;
220+
duty_us >>= 1;
221+
pwm_clk++;
222+
}
223+
224+
return NRF_ERROR_INVALID_PARAM;
225+
}
226+
227+
static nrf_pwm_values_common_t seq_values[1];
228+
229+
static nrf_pwm_sequence_t const seq =
230+
{
231+
.values.p_common = seq_values,
232+
.length = NRF_PWM_VALUES_LENGTH(seq_values),
233+
.repeats = 0,
234+
.end_delay = 0
235+
};
236+
237+
static void internal_pwmout_exe(pwmout_t *obj)
238+
{
239+
pulsewidth_set_t pulsewidth_set;
240+
pwm_signal_t * p_pwm_signal;
241+
nrf_drv_pwm_t *p_pwm_driver;
242+
ret_code_t ret_code;
243+
244+
p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
245+
246+
if (NRF_SUCCESS == pulsewidth_us_set_get(p_pwm_signal->period_us,
247+
p_pwm_signal->duty_us,
248+
&pulsewidth_set))
249+
{
250+
//@todo apply pulsewidth_set
251+
p_pwm_driver = (((pwm_t*)obj->pwm_struct)->p_pwm_driver);
252+
253+
nrf_drv_pwm_config_t config0 =
254+
{
255+
.output_pins =
256+
{
257+
obj->pin, // channel 0
258+
NRF_DRV_PWM_PIN_NOT_USED, // channel 1
259+
NRF_DRV_PWM_PIN_NOT_USED, // channel 2
260+
NRF_DRV_PWM_PIN_NOT_USED, // channel 3
261+
},
262+
.irq_priority = APP_IRQ_PRIORITY_LOW,
263+
.base_clock = pulsewidth_set.pwm_clk,
264+
.count_mode = NRF_PWM_MODE_UP,
265+
.top_value = pulsewidth_set.period,
266+
.load_mode = NRF_PWM_LOAD_COMMON,
267+
.step_mode = NRF_PWM_STEP_AUTO
268+
};
269+
270+
271+
//printf("clock = %d, top = %d\r\n", pulsewidth_set.pwm_clk, pulsewidth_set.period);
272+
273+
nrf_drv_pwm_uninit(p_pwm_driver);
274+
275+
ret_code = nrf_drv_pwm_init( p_pwm_driver, &config0, NULL);
276+
277+
MBED_ASSERT(ret_code == NRF_SUCCESS); // assert if free instance was not found.
278+
279+
seq_values[0] = pulsewidth_set.duty;
280+
281+
nrf_drv_pwm_simple_playback(p_pwm_driver, &seq, 3, NRF_DRV_PWM_FLAG_LOOP);
282+
283+
284+
}
285+
else
286+
{
287+
MBED_ASSERT(0); // force assertion
288+
}
289+
90290
}
91291

92292
#endif // DEVICE_PWMOUT

0 commit comments

Comments
 (0)