NRF52 series PWM reimplementation for SDK 14.2

Driver uses new API in SDK 14.2
pull/6547/head
Marcus Chang 2018-03-07 15:17:18 -08:00
parent f9b371fc0f
commit d11f74cb4c
7 changed files with 412 additions and 328 deletions

View File

@ -30,3 +30,10 @@ MBED_WEAK const PinMapI2C PinMap_I2C[1] = {
MBED_WEAK const PinMapSPI PinMap_SPI[1] = {
{NC, NC, NC, NC}
};
/* Default mapping between PWM pins and PWM instance.
* Can be overwritten by user.
*/
MBED_WEAK const PinMapPWM PinMap_PWM[1] = {
{NC, NC}
};

View File

@ -2266,14 +2266,14 @@
#ifndef PWM1_ENABLED
#define PWM1_ENABLED 0
#define PWM1_ENABLED 1
#endif
// <q> PWM2_ENABLED - Enable PWM2 instance
#ifndef PWM2_ENABLED
#define PWM2_ENABLED 0
#define PWM2_ENABLED 1
#endif
// <q> PWM3_ENABLED - Enable PWM3 instance

View File

@ -2266,21 +2266,21 @@
#ifndef PWM1_ENABLED
#define PWM1_ENABLED 0
#define PWM1_ENABLED 1
#endif
// <q> PWM2_ENABLED - Enable PWM2 instance
#ifndef PWM2_ENABLED
#define PWM2_ENABLED 0
#define PWM2_ENABLED 1
#endif
// <q> PWM3_ENABLED - Enable PWM3 instance
#ifndef PWM3_ENABLED
#define PWM3_ENABLED 0
#define PWM3_ENABLED 1
#endif
// </e>

View File

@ -44,6 +44,8 @@
#include "PeripheralNames.h"
#include "PinNames.h"
#include "nrf_pwm.h"
#ifdef __cplusplus
extern "C" {
#endif
@ -62,10 +64,12 @@ struct port_s {
};
struct pwmout_s {
PWMName pwm_name;
int instance;
PinName pin;
uint8_t pwm_channel;
void * pwm_struct;
nrf_pwm_values_common_t pulse;
uint16_t period;
float percent;
nrf_pwm_sequence_t sequence;
};
struct i2c_s {

View File

@ -31,6 +31,7 @@
/* Define number of instances */
#define NORDIC_TWI_COUNT TWI_COUNT
#define NORDIC_SPI_COUNT SPI_COUNT
#define NORDIC_PWM_COUNT PWM_COUNT
/* Define which instance to return when there are no free instances left.
* The Mbed HAL API doesn't provide a way for signaling initialization errors
@ -38,7 +39,20 @@
* by the driver implementation.
*/
#define DEFAULT_I2C_INSTANCE 0 // SPI counts down, choose instance furthest away
#define DEFAULT_SPI_INSTANCE (SPI_COUNT - 1) // I2C counts up, choose instance furthers away
#define DEFAULT_SPI_INSTANCE (NORDIC_SPI_COUNT - 1) // I2C counts up, choose instance furthers away
#define DEFAULT_PWM_INSTANCE (NORDIC_PWM_COUNT - 1)
/***
* _____ _____ _____ ___ _____
* / ____| __ \_ _|__ \ / ____|
* | (___ | |__) || | ) | |
* \___ \| ___/ | | / /| |
* ____) | | _| |_ / /_| |____
* |_____/|_| |_____|____|\_____|
*
*
*/
/* Internal data structure shared between SPI and I2C to keep track of allocated
* instances. The data structure is shared to reflect the hardware sharing.
@ -246,3 +260,108 @@ int pin_instance_spi(PinName mosi, PinName miso, PinName clk)
return instance;
}
/***
* _______ ____ __
* | __ \ \ / / \/ |
* | |__) \ \ /\ / /| \ / |
* | ___/ \ \/ \/ / | |\/| |
* | | \ /\ / | | | |
* |_| \/ \/ |_| |_|
*
*
*/
/* Internal data structure to keep track of allocated instances.
*/
static PinName nordic_internal_pwm[NORDIC_PWM_COUNT] = {
NC,
NC,
NC,
#if (NORDIC_PWM_COUNT == 4)
NC,
#endif
};
/**
* Brief Find hardware instance for the provided PWM pin.
*
* The function will search the PeripheralPin map for a pre-allocated
* assignment. If none is found the allocation map will be searched
* to see if the same pins have been assigned an instance before.
*
* If no assignement is found and there is an empty slot left in the
* map, the pins are stored in the map and the hardware instance is
* returned.
*
* If no free instances are available, the default instance is returned.
*
* Parameter pwm pwm pin.
*
* Return Hardware instance associated with provided pins.
*/
int pin_instance_pwm(PinName pwm)
{
int instance = NC;
/* Search pin map for pre-allocated instance */
for (size_t index = 0; (PinMap_PWM[index].pwm != NC); index++) {
/* Compare pins to entry. */
if (PinMap_PWM[index].pwm == pwm) {
DEBUG_PRINTF("found: %d %d\r\n", pwm, PinMap_PWM[index].instance);
/* Instance found, save result. */
instance = PinMap_PWM[index].instance;
/* Lock out entry in map. */
nordic_internal_pwm[instance] = pwm;
break;
}
}
/* No instance was found in static map. */
if (instance == NC) {
/* Search dynamic map for entry. */
for (size_t index = 0; index < NORDIC_PWM_COUNT; index++) {
/* Pins match previous dynamic allocation, return instance. */
if (nordic_internal_pwm[index] == pwm) {
instance = index;
break;
}
}
}
/* No instance was found in dynamic map. */
if (instance == NC) {
/* Search dynamic map for empty slot. */
for (size_t index = 0; index < NORDIC_PWM_COUNT; index++) {
/* Empty slot found, reserve slot by storing pins. */
if (nordic_internal_pwm[index] == NC) {
nordic_internal_pwm[index] = pwm;
instance = index;
break;
}
}
}
#if defined(DEFAULT_PWM_INSTANCE)
/* Exhausted all options. Return default value. */
if (instance == NC) {
instance = DEFAULT_PWM_INSTANCE;
}
#endif
DEBUG_PRINTF("PWM: %d %d\r\n", pwm, instance);
return instance;
}

View File

@ -42,6 +42,14 @@ typedef struct {
extern const PinMapSPI PinMap_SPI[];
/* Data structure for pre-allocated PWM instances. */
typedef struct {
PinName pwm;
int instance;
} PinMapPWM;
extern const PinMapPWM PinMap_PWM[];
/**
* @brief Find hardware instance for the provided I2C pins.
*
@ -83,6 +91,25 @@ int pin_instance_i2c(PinName sda, PinName scl);
*/
int pin_instance_spi(PinName mosi, PinName miso, PinName clk);
/**
* @brief Find hardware instance for the provided PWM pins.
*
* The function will search the PeripheralPin map for a pre-allocated
* assignment. If none is found the allocation map will be searched
* to see if the same pins have been assigned an instance before.
*
* If no assignement is found and there is an empty slot left in the
* map, the pins are stored in the map and the hardware instance is
* returned.
*
* If no free instances are available, the default instance is returned.
*
* @param[in] pwm pwm pin.
*
* @return Hardware instance associated with provided pins.
*/
int pin_instance_pwm(PinName pwm);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013 Nordic Semiconductor ASA
* Copyright (c) 2018 Nordic Semiconductor ASA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
@ -36,36 +36,29 @@
*
*/
#warning arm porting pending
#ifndef TARGET_MCU_NRF51822
#include "mbed_assert.h"
#include "mbed_error.h"
#include "cmsis.h"
#include "pinmap.h"
#include "sdk_config.h"
#if DEVICE_PWMOUT
#include "app_util_platform.h"
#include "hal/pwmout_api.h"
#include "pinmap_ex.h"
#include "nrf_drv_pwm.h"
#include "pwmout_api.h"
#include "irq_handlers_hw.h"
#if 0
#define DEBUG_PRINTF(...) do { printf(__VA_ARGS__); } while(0)
#else
#define DEBUG_PRINTF(...) {}
#endif
#define MAX_PWM_COUNTERTOP (0x7FFF) // 0x7FFF is the max of COUNTERTOP value for the PWM peripherial of the nRF52.
#define MAX_PWM_PERIOD_US (MAX_PWM_COUNTERTOP * 8) // PWM hw is driven by 16 MHz clock, hence the tick is 1_us/16,
// and 128 is the max prescaler value.
#define MAX_PWM_PERIOD_MS ((MAX_PWM_PERIOD_US / 1000) + 1) // approximations advance
#define MAX_PWM_PERIOD_S ((MAX_PWM_PERIOD_US / 1000000) + 1) // approximations advance
/* 0x7FFF is the max of COUNTERTOP pulse for the PWM peripherial of the nRF52. */
#define MAX_PWM_COUNTERTOP (0x7FFF)
/* The PWM is driven by a 1 MHz clock to fit the 1 us resolution expected by the API. */
#define MAX_PWM_PERIOD_US (MAX_PWM_COUNTERTOP)
#define MAX_PWM_PERIOD_MS (MAX_PWM_PERIOD_US / 1000)
#define MAX_PWM_PERIOD_S ((float) MAX_PWM_PERIOD_US / 1000000.0f)
#define PWM_INSTANCE_COUNT (PWM_COUNT) // import from the nrf_drv_config.h file
///> instances of nRF52 PWM driver
static const nrf_drv_pwm_t m_pwm_driver[PWM_INSTANCE_COUNT] =
{
/* Allocate PWM instances. */
static nrf_drv_pwm_t nordic_nrf5_pwm_instance[] = {
#if PWM0_ENABLED
NRF_DRV_PWM_INSTANCE(0),
#endif
@ -73,339 +66,273 @@ static const nrf_drv_pwm_t m_pwm_driver[PWM_INSTANCE_COUNT] =
NRF_DRV_PWM_INSTANCE(1),
#endif
#if PWM2_ENABLED
NRF_DRV_PWM_INSTANCE(2)
NRF_DRV_PWM_INSTANCE(2),
#endif
#if PWM3_ENABLED
NRF_DRV_PWM_INSTANCE(3),
#endif
};
typedef struct
/* Helper function for (re)initializing the PWM instance.
*/
static void nordic_pwm_init(pwmout_t *obj)
{
uint32_t period_us;
uint32_t duty_us;
float duty;
} pwm_signal_t; /// PWM signal description type
typedef struct
{
nrf_drv_pwm_t * p_pwm_driver;
pwm_signal_t signal;
volatile nrf_pwm_values_common_t seq_values[1];
} pwm_t; /// internal PWM instance support type
static pwm_t m_pwm[PWM_INSTANCE_COUNT] =
{
#if PWM0_ENABLED
{.p_pwm_driver = NULL},
#endif
#if PWM1_ENABLED
{.p_pwm_driver = NULL},
#endif
#if PWM2_ENABLED
{.p_pwm_driver = NULL}
#endif
}; /// Array of internal PWM instances.
typedef struct
{
uint16_t period_hwu; // unit related to pwm_clk
uint16_t duty_hwu; // unit related to pwm_clk
nrf_pwm_clk_t pwm_clk;
} pulsewidth_set_t; /// helper type for timing calculations
static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization);
// extern PWM nIRQ handler implementations
void PWM0_IRQHandler(void);
void PWM1_IRQHandler(void);
void PWM2_IRQHandler(void);
static const peripheral_handler_desc_t pwm_handlers[PWM_INSTANCE_COUNT] =
{
{
PWM0_IRQn,
(uint32_t)PWM0_IRQHandler
},
#warning
#if 0
{
PWM1_IRQn,
(uint32_t)PWM1_IRQHandler
},
{
PWM2_IRQn,
(uint32_t)PWM2_IRQHandler
}
#endif
};
void pwmout_init(pwmout_t *obj, PinName pin)
{
uint32_t i;
for (i = 0; PWM_INSTANCE_COUNT; i++)
{
if (m_pwm[i].p_pwm_driver == NULL) // a driver instance not assigned to the obj?
{
NVIC_SetVector(pwm_handlers[i].IRQn, pwm_handlers[i].vector);
obj->pin = pin;
obj->pwm_channel = i;
m_pwm[i].p_pwm_driver = (nrf_drv_pwm_t *) &m_pwm_driver[i];
m_pwm[i].signal.period_us = 200000; // 0.02 s
m_pwm[i].signal.duty_us = 100000;
m_pwm[i].signal.duty = 0.5f;
obj->pwm_struct = &m_pwm[i];
internal_pwmout_exe(obj, true, true);
break;
}
}
MBED_ASSERT(i != PWM_INSTANCE_COUNT); // assert if free instance was not found.
}
void pwmout_free(pwmout_t *obj)
{
nrf_drv_pwm_uninit( (nrf_drv_pwm_t*) obj->pwm_struct );
m_pwm[obj->pwm_channel].p_pwm_driver = NULL;
}
void pwmout_write(pwmout_t *obj, float percent)
{
if (percent < 0)
{
percent = 0;
}
else if (percent > 1)
{
percent = 1;
}
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
p_pwm_signal->duty = percent;
int us = (((int)p_pwm_signal->period_us) * percent);
pwmout_pulsewidth_us(obj, us);
}
float pwmout_read(pwmout_t *obj)
{
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
return (float)p_pwm_signal->duty_us / (float)p_pwm_signal->period_us;
}
void pwmout_period(pwmout_t *obj, float seconds)
{
// raught saturation < 0, quasi-max>
if (seconds > MAX_PWM_PERIOD_S)
{
seconds = MAX_PWM_PERIOD_S;
}
else if (seconds < 0)
{
seconds = 0; // f. pwmout_period_us will set period to min. value
}
int us = seconds * 1000000;
pwmout_period_us(obj, us);
}
void pwmout_period_ms(pwmout_t *obj, int ms)
{
// reught saturation < 0, quasi-max>
if (ms > MAX_PWM_PERIOD_MS)
{
ms = MAX_PWM_PERIOD_MS;
}
else if (ms < 0)
{
ms = 0; // f. pwmout_period_us will set period to min. value
}
int us = ms * 1000;
pwmout_period_us(obj, us);
}
void pwmout_period_us(pwmout_t *obj, int us)
{
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
// saturation <1, real-max>
if (us > MAX_PWM_PERIOD_US)
{
us = MAX_PWM_PERIOD_US;
}
else if (us < 1)
{
us = 1;
}
p_pwm_signal->duty_us = (int)((float)us * p_pwm_signal->duty);
p_pwm_signal->period_us = us;
internal_pwmout_exe(obj, true, false);
}
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
{
// raught saturation < 0, quasi-max>
if (seconds > MAX_PWM_PERIOD_S)
{
seconds = MAX_PWM_PERIOD_S;
}
else if (seconds < 0)
{
seconds = 0;
}
int us = seconds * 1000000;
pwmout_pulsewidth_us(obj,us);
}
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
{
// raught saturation < 0, quasi-max>
if (ms > MAX_PWM_PERIOD_MS)
{
ms = MAX_PWM_PERIOD_MS;
}
else if (ms < 0)
{
ms = 0;
}
int us = ms * 1000;
pwmout_pulsewidth_us(obj, us);
}
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
{
// saturation <0, real-max>
if (us > MAX_PWM_PERIOD_US)
{
us = MAX_PWM_PERIOD_US;
}
else if (us < 0)
{
us = 0;
}
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
p_pwm_signal->duty_us = us;
p_pwm_signal->duty = us / p_pwm_signal->period_us;
internal_pwmout_exe(obj, false, false);
}
static ret_code_t pulsewidth_us_set_get(int period_hwu, int duty_hwu, pulsewidth_set_t * p_settings)
{
uint16_t div;
nrf_pwm_clk_t pwm_clk = NRF_PWM_CLK_16MHz;
for(div = 1; div <= 128 ; div <<= 1) // 128 is the maximum of clock prescaler for PWM peripherial
{
if (MAX_PWM_COUNTERTOP >= period_hwu)
{
p_settings->period_hwu = period_hwu; // unit [us/16 * div]
p_settings->duty_hwu = duty_hwu; // unit [us/16 * div]
p_settings->pwm_clk = pwm_clk;
return NRF_SUCCESS;
}
period_hwu >>= 1;
duty_hwu >>= 1;
pwm_clk++;
}
return NRF_ERROR_INVALID_PARAM;
}
static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization)
{
pulsewidth_set_t pulsewidth_set;
pwm_signal_t * p_pwm_signal;
nrf_drv_pwm_t * p_pwm_driver;
ret_code_t ret_code;
p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
if (NRF_SUCCESS == pulsewidth_us_set_get(p_pwm_signal->period_us * 16, // base clk for PWM is 16 MHz
p_pwm_signal->duty_us * 16, // base clk for PWM is 16 MHz
&pulsewidth_set))
{
p_pwm_driver = (((pwm_t*)obj->pwm_struct)->p_pwm_driver);
const nrf_pwm_sequence_t seq =
{
.values.p_common = (nrf_pwm_values_common_t*) (((pwm_t*)obj->pwm_struct)->seq_values),
.length = 1,
.repeats = 0,
.end_delay = 0
};
(((pwm_t*)obj->pwm_struct)->seq_values)[0] = pulsewidth_set.duty_hwu | 0x8000;
if (new_period)
{
nrf_drv_pwm_config_t config0 =
{
.output_pins =
{
obj->pin | NRF_DRV_PWM_PIN_INVERTED, // channel 0
NRF_DRV_PWM_PIN_NOT_USED, // channel 1
NRF_DRV_PWM_PIN_NOT_USED, // channel 2
NRF_DRV_PWM_PIN_NOT_USED, // channel 3
MBED_ASSERT(obj);
/* Default configuration:
* 1 pin per instance, otherwise they would share base count.
* 1 MHz clock source to match the 1 us resolution.
*/
nrf_drv_pwm_config_t config = {
.output_pins = {
obj->pin,
NRF_DRV_PWM_PIN_NOT_USED,
NRF_DRV_PWM_PIN_NOT_USED,
NRF_DRV_PWM_PIN_NOT_USED,
},
.irq_priority = PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
.base_clock = pulsewidth_set.pwm_clk,
.base_clock = NRF_PWM_CLK_1MHz,
.count_mode = NRF_PWM_MODE_UP,
.top_value = pulsewidth_set.period_hwu,
.top_value = obj->period,
.load_mode = NRF_PWM_LOAD_COMMON,
.step_mode = NRF_PWM_STEP_AUTO
.step_mode = NRF_PWM_STEP_AUTO,
};
if (!initialization)
/* Make sure PWM instance is not running before making changes. */
nrf_drv_pwm_uninit(&nordic_nrf5_pwm_instance[obj->instance]);
/* Initialize instance with new configuration. */
ret_code_t result = nrf_drv_pwm_init(&nordic_nrf5_pwm_instance[obj->instance],
&config,
NULL);
MBED_ASSERT(result == NRF_SUCCESS);
}
/* Helper function for reinitializing the PWM instance and setting the duty-cycle. */
static void nordic_pwm_restart(pwmout_t *obj)
{
nrf_drv_pwm_uninit(p_pwm_driver);
MBED_ASSERT(obj);
/* (Re)initialize PWM instance. */
nordic_pwm_init(obj);
/* Set duty-cycle from object. */
ret_code_t result = nrf_drv_pwm_simple_playback(&nordic_nrf5_pwm_instance[obj->instance],
&obj->sequence,
1,
NRF_DRV_PWM_FLAG_LOOP);
MBED_ASSERT(result == NRF_SUCCESS);
}
ret_code = nrf_drv_pwm_init( p_pwm_driver, &config0, NULL);
MBED_ASSERT(ret_code == NRF_SUCCESS); // assert if free instance was not found.
}
nrf_drv_pwm_simple_playback(p_pwm_driver, &seq, 0, NRF_DRV_PWM_FLAG_LOOP);
}
else
/** Initialize the pwm out peripheral and configure the pin
*
* Parameter obj The pwmout object to initialize
* Parameter pin The pwmout pin to initialize
*/
void pwmout_init(pwmout_t *obj, PinName pin)
{
MBED_ASSERT(0); // force assertion
DEBUG_PRINTF("pwmout_init: %d\r\n", pin);
MBED_ASSERT(obj);
/* Get hardware instance from pinmap. */
int instance = pin_instance_pwm(pin);
MBED_ASSERT(instance < (int)(sizeof(nordic_nrf5_pwm_instance) / sizeof(nrf_drv_pwm_t)));
/* Populate PWM object with default values. */
obj->instance = instance;
obj->pin = pin;
obj->pulse = 0;
obj->period = MAX_PWM_COUNTERTOP;
obj->percent = 0;
obj->sequence.values.p_common = &obj->pulse;
obj->sequence.length = NRF_PWM_VALUES_LENGTH(obj->pulse);
obj->sequence.repeats = 0;
obj->sequence.end_delay = 0;
/* Initialize PWM instance. */
nordic_pwm_init(obj);
}
/** Deinitialize the pwmout object
*
* Parameter obj The pwmout object
*/
void pwmout_free(pwmout_t *obj)
{
DEBUG_PRINTF("pwmout_free\r\n");
MBED_ASSERT(obj);
/* Uninitialize PWM instance. */
nrf_drv_pwm_uninit(&nordic_nrf5_pwm_instance[obj->instance]);
}
/** Set the output duty-cycle in range <0.0f, 1.0f>
*
* pulse 0.0f represents 0 percentage, 1.0f represents 100 percent.
* Parameter obj The pwmout object
* Parameter percent The floating-point percentage number
*/
void pwmout_write(pwmout_t *obj, float percent)
{
DEBUG_PRINTF("pwmout_write: %f\r\n", percent);
/* Find counts based on period. */
uint16_t pulse = obj->period * percent;
/* Ensure we don't overcount. */
obj->pulse = (pulse > MAX_PWM_COUNTERTOP) ? MAX_PWM_COUNTERTOP : pulse;
/* Store actual percentage passed as parameter to avoid floating point rounding errors. */
obj->percent = percent;
/* Set new duty-cycle. */
ret_code_t result = nrf_drv_pwm_simple_playback(&nordic_nrf5_pwm_instance[obj->instance],
&obj->sequence,
1,
NRF_DRV_PWM_FLAG_LOOP);
MBED_ASSERT(result == NRF_SUCCESS);
}
/** Read the current float-point output duty-cycle
*
* Parameter obj The pwmout object
* Return A floating-point output duty-cycle
*/
float pwmout_read(pwmout_t *obj)
{
DEBUG_PRINTF("pwmout_read: %f\r\n", obj->percent);
/* Return percentage stored in object instead of calculating the value.
* This prevents floating point rounding errors.
*/
return obj->percent;
}
/** Set the PWM period specified in seconds, keeping the duty cycle the same
*
* Periods smaller than microseconds (the lowest resolution) are set to zero.
* Parameter obj The pwmout object
* Parameter seconds The floating-point seconds period
*/
void pwmout_period(pwmout_t *obj, float period)
{
DEBUG_PRINTF("pwmout_period: %f\r\n", period);
/* Cap period if too large. */
if (period > MAX_PWM_PERIOD_S) {
period = MAX_PWM_PERIOD_S;
}
/* Set new period. */
pwmout_period_us(obj, period * 1000000);
}
/** Set the PWM period specified in miliseconds, keeping the duty cycle the same
*
* Parameter obj The pwmout object
* Parameter ms The milisecond period
*/
void pwmout_period_ms(pwmout_t *obj, int period)
{
DEBUG_PRINTF("pwmout_period_ms: %d\r\n", period);
/* Cap period if too large. */
if (period > MAX_PWM_PERIOD_MS) {
period = MAX_PWM_PERIOD_MS;
}
/* Set new period. */
pwmout_period_us(obj, period * 1000);
}
/** Set the PWM period specified in microseconds, keeping the duty cycle the same
*
* Parameter obj The pwmout object
* Parameter us The microsecond period
*/
void pwmout_period_us(pwmout_t *obj, int period)
{
DEBUG_PRINTF("pwmout_period_us: %d\r\n", period);
/* Cap period if too large. */
if (period > MAX_PWM_PERIOD_US) {
period = MAX_PWM_PERIOD_US;
}
/* Scale new count based on stored duty-cycle and new period. */
uint32_t pulse = (period * obj->pulse) / obj->period;
/* Store new values in object. */
obj->pulse = pulse;
obj->period = period;
obj->percent = (float) pulse / (float) period;
/* Restart instance with new values. */
nordic_pwm_restart(obj);
}
/** Set the PWM pulsewidth specified in seconds, keeping the period the same.
*
* Parameter obj The pwmout object
* Parameter seconds The floating-point pulsewidth in seconds
*/
void pwmout_pulsewidth(pwmout_t *obj, float pulse)
{
DEBUG_PRINTF("pwmout_pulsewidt: %f\r\n", pulse);
/* Cap pulsewidth to period before setting it. */
if ((pulse * 1000000) > (float) obj->pulse) {
obj->pulse = obj->period;
pwmout_pulsewidth_us(obj, obj->pulse);
} else {
pwmout_pulsewidth_us(obj, pulse * 1000000);
}
}
/** Set the PWM pulsewidth specified in miliseconds, keeping the period the same.
*
* Parameter obj The pwmout object
* Parameter ms The floating-point pulsewidth in miliseconds
*/
void pwmout_pulsewidth_ms(pwmout_t *obj, int pulse)
{
DEBUG_PRINTF("pwmout_pulsewidth_ms: %d\r\n", ms);
/* Cap pulsewidth to period before setting it. */
if ((pulse * 1000) > (int) obj->period) {
obj->pulse = obj->period;
pwmout_pulsewidth_us(obj, obj->pulse);
} else {
pwmout_pulsewidth_us(obj, pulse * 1000);
}
}
/** Set the PWM pulsewidth specified in microseconds, keeping the period the same.
*
* Parameter obj The pwmout object
* Parameter us The floating-point pulsewidth in microseconds
*/
void pwmout_pulsewidth_us(pwmout_t *obj, int pulse)
{
DEBUG_PRINTF("pwmout_pulsewidth_us: %d\r\n", pulse);
/* Cap pulsewidth to period. */
if (pulse > obj->period) {
pulse = obj->period;
}
/* Store new values in object. */
obj->pulse = pulse;
obj->percent = (float) pulse / (float) obj->period;
/* Restart instance with new values. */
nordic_pwm_restart(obj);
}
#endif // DEVICE_PWMOUT
#endif