PWM: added workaround for Edison's problem with 0% duty
As described in issue #91, on Edison setting 0% duty doesn't disable the PWM on a pin completely. Therefore we add a couple of Edison-specific _pre functions and an internal PWM state variable, which we use to toggle PWM enabled/disabled based on what duty is set for the pin. Closes #91. Signed-off-by: Alex Tereschenko <alext.mkrs@gmail.com> Signed-off-by: Brendan Le Foll <brendan.le.foll@intel.com>
This commit is contained in:
committed by
Brendan Le Foll
parent
c413a43d5a
commit
8af6843566
@@ -87,7 +87,9 @@ typedef struct {
|
||||
mraa_result_t (*pwm_period_replace) (mraa_pwm_context dev, int period);
|
||||
float (*pwm_read_replace) (mraa_pwm_context dev);
|
||||
mraa_result_t (*pwm_write_replace) (mraa_pwm_context dev, float duty);
|
||||
mraa_result_t (*pwm_write_pre) (mraa_pwm_context dev, float percentage);
|
||||
mraa_result_t (*pwm_enable_replace) (mraa_pwm_context dev, int enable);
|
||||
mraa_result_t (*pwm_enable_pre) (mraa_pwm_context dev, int enable);
|
||||
|
||||
mraa_result_t (*spi_init_pre) (int bus);
|
||||
mraa_result_t (*spi_init_post) (mraa_spi_context spi);
|
||||
|
||||
@@ -340,6 +340,13 @@ mraa_pwm_write(mraa_pwm_context dev, float percentage)
|
||||
return MRAA_ERROR_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
if (IS_FUNC_DEFINED(dev, pwm_write_pre)) {
|
||||
if (dev->advance_func->pwm_write_pre(dev, percentage) != MRAA_SUCCESS) {
|
||||
syslog(LOG_ERR, "mraa_pwm_write (pwm%i): pwm_write_pre failed, see syslog", dev->pin);
|
||||
return MRAA_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->period == -1) {
|
||||
if (mraa_pwm_read_period(dev) <= 0)
|
||||
return MRAA_ERROR_NO_DATA_AVAILABLE;
|
||||
@@ -433,6 +440,13 @@ mraa_pwm_enable(mraa_pwm_context dev, int enable)
|
||||
return dev->advance_func->pwm_enable_replace(dev, enable);
|
||||
}
|
||||
|
||||
if (IS_FUNC_DEFINED(dev, pwm_enable_pre)) {
|
||||
if (dev->advance_func->pwm_enable_pre(dev, enable) != MRAA_SUCCESS) {
|
||||
syslog(LOG_ERR, "mraa_pwm_enable (pwm%i): pwm_enable_pre failed, see syslog", dev->pin);
|
||||
return MRAA_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
char bu[MAX_SIZE];
|
||||
snprintf(bu, MAX_SIZE, "/sys/class/pwm/pwmchip%d/pwm%d/enable", dev->chipid, dev->pin);
|
||||
|
||||
|
||||
@@ -76,6 +76,9 @@ static int mmap_fd = 0;
|
||||
static int mmap_size;
|
||||
static unsigned int mmap_count = 0;
|
||||
|
||||
// PWM 0% duty workaround state array
|
||||
static int pwm_disabled[4] = { 0 };
|
||||
|
||||
mraa_result_t
|
||||
mraa_intel_edison_spi_lsbmode_replace(mraa_spi_context dev, mraa_boolean_t lsb)
|
||||
{
|
||||
@@ -367,6 +370,30 @@ mraa_intel_edison_aio_init_post(mraa_aio_context dev)
|
||||
return mraa_gpio_write(tristate, 1);
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_intel_edison_pwm_enable_pre(mraa_pwm_context dev, int enable) {
|
||||
// PWM 0% duty workaround: update state array
|
||||
// if someone first ran write(0) and then enable(1).
|
||||
if ((pwm_disabled[dev->pin] == 1) && (enable == 1)) { pwm_disabled[dev->pin] = 0; }
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_intel_edison_pwm_write_pre(mraa_pwm_context dev, float percentage) {
|
||||
// PWM 0% duty workaround: set the state array and enable/disable pin accordingly
|
||||
if (percentage == 0.0f) {
|
||||
syslog(LOG_INFO, "edison_pwm_write_pre (pwm%i): requested zero duty cycle, disabling PWM on the pin", dev->pin);
|
||||
pwm_disabled[dev->pin] = 1;
|
||||
return mraa_pwm_enable(dev, 0);
|
||||
} else if (pwm_disabled[dev->pin] == 1) {
|
||||
syslog(LOG_INFO, "edison_pwm_write_pre (pwm%i): Re-enabling the pin after setting non-zero duty", dev->pin);
|
||||
pwm_disabled[dev->pin] = 0;
|
||||
return mraa_pwm_enable(dev, 1);
|
||||
}
|
||||
|
||||
return MRAA_SUCCESS;
|
||||
}
|
||||
|
||||
mraa_result_t
|
||||
mraa_intel_edison_pwm_init_pre(int pin)
|
||||
{
|
||||
@@ -414,6 +441,7 @@ mraa_intel_edison_pwm_init_pre(int pin)
|
||||
mraa_result_t
|
||||
mraa_intel_edison_pwm_init_post(mraa_pwm_context pwm)
|
||||
{
|
||||
pwm_disabled[pwm->pin] = 0;
|
||||
return mraa_gpio_write(tristate, 1);
|
||||
}
|
||||
|
||||
@@ -802,6 +830,8 @@ mraa_intel_edison_miniboard(mraa_board_t* b)
|
||||
}
|
||||
b->adv_func->gpio_init_post = &mraa_intel_edison_gpio_init_post;
|
||||
b->adv_func->pwm_init_pre = &mraa_intel_edison_pwm_init_pre;
|
||||
b->adv_func->pwm_enable_pre = &mraa_intel_edison_pwm_enable_pre;
|
||||
b->adv_func->pwm_write_pre = &mraa_intel_edison_pwm_write_pre;
|
||||
b->adv_func->i2c_init_pre = &mraa_intel_edison_i2c_init_pre;
|
||||
b->adv_func->i2c_set_frequency_replace = &mraa_intel_edison_i2c_freq;
|
||||
b->adv_func->spi_init_pre = &mraa_intel_edison_spi_init_pre;
|
||||
@@ -1259,6 +1289,8 @@ mraa_intel_edison_fab_c()
|
||||
b->adv_func->aio_init_post = &mraa_intel_edison_aio_init_post;
|
||||
b->adv_func->pwm_init_pre = &mraa_intel_edison_pwm_init_pre;
|
||||
b->adv_func->pwm_init_post = &mraa_intel_edison_pwm_init_post;
|
||||
b->adv_func->pwm_enable_pre = &mraa_intel_edison_pwm_enable_pre;
|
||||
b->adv_func->pwm_write_pre = &mraa_intel_edison_pwm_write_pre;
|
||||
b->adv_func->spi_init_pre = &mraa_intel_edison_spi_init_pre;
|
||||
b->adv_func->spi_init_post = &mraa_intel_edison_spi_init_post;
|
||||
b->adv_func->gpio_mode_replace = &mraa_intel_edison_gpio_mode_replace;
|
||||
|
||||
Reference in New Issue
Block a user