Skip to content

Commit

Permalink
Avoid glitches on repeated analogWrite() PWM
Browse files Browse the repository at this point in the history
  • Loading branch information
GrumpyOldPizza committed Aug 12, 2018
1 parent a42d1e1 commit 1c9e497
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 24 deletions.
53 changes: 33 additions & 20 deletions cores/arduino/wiring_analog.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static stm32l0_timer_t stm32l0_pwm[PWM_INSTANCE_COUNT];

static uint8_t _channels[PWM_INSTANCE_COUNT];
static int _readResolution = 10;
static int _readPeriod = 2000;
static int _writeResolution = 8;

void analogReference(eAnalogReference reference)
Expand All @@ -51,6 +52,11 @@ void analogReadResolution(int resolution)
_readResolution = resolution;
}

void analogReadPeriod(int period)
{
_readPeriod = period;
}

static inline uint32_t mapResolution(uint32_t value, uint32_t from, uint32_t to)
{
if (from == to)
Expand Down Expand Up @@ -99,7 +105,7 @@ uint32_t __analogReadInternal(uint32_t channel, uint32_t smp)
}
else
{
return 0;
return 0;
}
}
}
Expand All @@ -125,7 +131,7 @@ uint32_t analogRead(uint32_t ulPin)

stm32l0_gpio_pin_configure(g_APinDescription[ulPin].pin, (STM32L0_GPIO_PUPD_NONE | STM32L0_GPIO_MODE_ANALOG));

input = __analogReadInternal(g_APinDescription[ulPin].adc_channel, 2000);
input = __analogReadInternal(g_APinDescription[ulPin].adc_channel, _readPeriod);

return mapResolution(input, 12, _readResolution);
}
Expand Down Expand Up @@ -160,33 +166,40 @@ void analogWrite(uint32_t ulPin, uint32_t value)
{
instance = g_APinDescription[ulPin].pwm_instance;

if (stm32l0_pwm[instance].state == STM32L0_TIMER_STATE_NONE)
if (_channels[instance] & (1u << g_APinDescription[ulPin].pwm_channel))
{
stm32l0_timer_create(&stm32l0_pwm[instance], g_PWMInstances[instance], STM32L0_PWM_IRQ_PRIORITY, 0);
stm32l0_timer_compare(&stm32l0_pwm[instance], g_APinDescription[ulPin].pwm_channel, mapResolution(value, _writeResolution, 12));
}

if (stm32l0_pwm[instance].state == STM32L0_TIMER_STATE_INIT)
else
{
carrier = 2000000;
modulus = 4095;

divider = stm32l0_timer_clock(&stm32l0_pwm[instance]) / carrier;
_channels[instance] |= (1u << g_APinDescription[ulPin].pwm_channel);

if (stm32l0_pwm[instance].state == STM32L0_TIMER_STATE_NONE)
{
stm32l0_timer_create(&stm32l0_pwm[instance], g_PWMInstances[instance], STM32L0_PWM_IRQ_PRIORITY, 0);
}

if (divider == 0)
if (stm32l0_pwm[instance].state == STM32L0_TIMER_STATE_INIT)
{
divider = 1;
carrier = 2000000;
modulus = 4095;

divider = stm32l0_timer_clock(&stm32l0_pwm[instance]) / carrier;

if (divider == 0)
{
divider = 1;
}

stm32l0_timer_enable(&stm32l0_pwm[instance], divider -1, 0, NULL, NULL, 0);
stm32l0_timer_start(&stm32l0_pwm[instance], modulus -1, false);
}

stm32l0_timer_enable(&stm32l0_pwm[instance], divider -1, 0, NULL, NULL, 0);
stm32l0_timer_start(&stm32l0_pwm[instance], modulus -1, false);
stm32l0_gpio_pin_configure(g_APinDescription[ulPin].pin, (STM32L0_GPIO_PUPD_NONE | STM32L0_GPIO_OSPEED_HIGH | STM32L0_GPIO_OTYPE_PUSHPULL | STM32L0_GPIO_MODE_ALTERNATE));

stm32l0_timer_channel(&stm32l0_pwm[instance], g_APinDescription[ulPin].pwm_channel, mapResolution(value, _writeResolution, 12), STM32L0_TIMER_CONTROL_PWM);
}

stm32l0_gpio_pin_configure(g_APinDescription[ulPin].pin, (STM32L0_GPIO_PUPD_NONE | STM32L0_GPIO_OSPEED_HIGH | STM32L0_GPIO_OTYPE_PUSHPULL | STM32L0_GPIO_MODE_ALTERNATE));

stm32l0_timer_channel(&stm32l0_pwm[instance], g_APinDescription[ulPin].pwm_channel, mapResolution(value, _writeResolution, 12), STM32L0_TIMER_CONTROL_PWM);

_channels[instance] |= (1u << g_APinDescription[ulPin].pwm_channel);

return;
}

Expand Down
15 changes: 11 additions & 4 deletions cores/arduino/wiring_analog.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,25 @@ extern uint32_t analogRead( uint32_t ulPin ) ;


/*
* \brief Set the resolution of analogRead return values. Default is 10 bits (range from 0 to 1023).
* \brief Set the resolution of analogRead return values. Default is 10 bits (range from 1 to 16).
*
* \param res
*/
extern void analogReadResolution(int res);
extern void analogReadResolution(int resolution);

/*
* \brief Set the resolution of analogWrite parameters. Default is 8 bits (range from 0 to 255).
* \brief Set the sampling period of analogRead in nanoseconds. Default is 2000 nanosceonds (range from 0 to 50000).
*
* \param res
*/
extern void analogWriteResolution(int res);
extern void analogReadPeriod(int period);

/*
* \brief Set the resolution of analogWrite parameters. Default is 8 bits (range from 1 to 16).
*
* \param res
*/
extern void analogWriteResolution(int resolution);

#ifdef __cplusplus
}
Expand Down

0 comments on commit 1c9e497

Please sign in to comment.