Skip to content

Commit

Permalink
bugfix(pwm): support fractional phase
Browse files Browse the repository at this point in the history
* Supports fractional phase, making the phase function produce higher precision waveforms.
* Enhanced stability
  • Loading branch information
xiongyumail committed Sep 21, 2020
1 parent ac10b42 commit 72cbf0d
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 17 deletions.
4 changes: 2 additions & 2 deletions components/esp8266/driver/ledc.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ typedef struct {
uint32_t step_01duty; // 0.1 of the duty value
uint32_t step_001duty; // 0.01 of the duty value
uint32_t gpio_num;//gpio pins
int16_t phase; //init phase
float phase; //init phase
int fade_time; // Time to duty by fade
} ledc_obj_t;

Expand Down Expand Up @@ -277,7 +277,7 @@ static void ledc_task(void* pvParameters)

esp_err_t ledc_fade_func_install(int intr_alloc_flags)
{
int16_t ledc_phase[LEDC_CHANNEL_MAX] = {0};
float ledc_phase[LEDC_CHANNEL_MAX] = {0};
uint32_t ledc_duty[LEDC_CHANNEL_MAX] = {0};
uint32_t ledc_gpio_num[LEDC_CHANNEL_MAX] = {0};

Expand Down
17 changes: 9 additions & 8 deletions components/esp8266/driver/pwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ static const char *TAG = "pwm";

typedef struct {
uint32_t duty; /*!< pwm duty for each channel */
int16_t phase; /*!< pwm phase for each channel */
float phase; /*!< pwm phase for each channel */
uint8_t io_num; /*!< pwm io_num for each channel */
} pwm_info_t;

Expand Down Expand Up @@ -113,13 +113,13 @@ static void pwm_phase_init(void)

for (i = 0; i < pwm_obj->channel_num; i++) {
if (-180 < pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase < 0) {
time_delay = 0 - ((0 - pwm_obj->pwm_info[i].phase) * pwm_obj->depth / 360);
time_delay = (int32_t)(0 - ((0 - pwm_obj->pwm_info[i].phase) * pwm_obj->depth / 360.0));
} else if (pwm_obj->pwm_info[i].phase == 0) {
continue;
} else if (180 > pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase > 0) {
time_delay = pwm_obj->pwm_info[i].phase * pwm_obj->depth / 360;
} else if (180 >= pwm_obj->pwm_info[i].phase && pwm_obj->pwm_info[i].phase > 0) {
time_delay = (int32_t)(pwm_obj->pwm_info[i].phase * pwm_obj->depth / 360.0);
} else {
ESP_LOGE(TAG, "channel[%d] phase error %d, valid ramge from (-180,180)\n", i, pwm_obj->pwm_info[i].phase);
ESP_LOGE(TAG, "channel[%d] phase error %f, valid ramge from (-180,180]\n", i, pwm_obj->pwm_info[i].phase);
continue;
}

Expand Down Expand Up @@ -224,7 +224,7 @@ esp_err_t pwm_set_period_duties(uint32_t period, uint32_t *duties)
return ESP_OK;
}

esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase)
esp_err_t pwm_set_phase(uint8_t channel_num, float phase)
{
PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG);

Expand All @@ -233,7 +233,7 @@ esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase)
return ESP_OK;
}

esp_err_t pwm_set_phases(int16_t *phases)
esp_err_t pwm_set_phases(float *phases)
{
uint8_t i;
PWM_CHECK(NULL != phases, "Pointer is empty", ESP_ERR_INVALID_ARG);
Expand All @@ -246,7 +246,7 @@ esp_err_t pwm_set_phases(int16_t *phases)
return ESP_OK;
}

esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p)
esp_err_t pwm_get_phase(uint8_t channel_num, float *phase_p)
{
PWM_CHECK(channel_num < pwm_obj->channel_num, "Channel num error", ESP_ERR_INVALID_ARG);
PWM_CHECK(NULL != phase_p, "Pointer is empty", ESP_ERR_INVALID_ARG);
Expand Down Expand Up @@ -310,6 +310,7 @@ static void IRAM_ATTR pwm_timer_intr_handler(void)
pwm_obj->this_target = AHEAD_TICKS1 + AHEAD_TICKS3;
}

REG_WRITE(WDEVTSF0TIMER_ENA, 0);
REG_WRITE(WDEVTSFSW0_LO, 0);
//WARNING, pwm_obj->this_target - AHEAD_TICKS1 should be bigger than 2
REG_WRITE(WDEVTSF0_TIMER_LO, pwm_obj->this_target - AHEAD_TICKS1);
Expand Down
8 changes: 4 additions & 4 deletions components/esp8266/include/driver/pwm.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,13 +145,13 @@ esp_err_t pwm_set_duties(uint32_t *duties);
*
* @param channel_num PWM channel number
* the channel_num cannot exceed the value initialized by pwm_init.
* @param phase The phase of this PWM channel, the phase range is (-180 ~ 180).
* @param phase The phase of this PWM channel, the phase range is (-180 ~ 180].
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase);
esp_err_t pwm_set_phase(uint8_t channel_num, float phase);

/**
* @brief Set the phase of all channels.
Expand All @@ -164,7 +164,7 @@ esp_err_t pwm_set_phase(uint8_t channel_num, int16_t phase);
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_set_phases(int16_t *phases);
esp_err_t pwm_set_phases(float *phases);

/**
* @brief Get the phase of a PWM channel.
Expand All @@ -177,7 +177,7 @@ esp_err_t pwm_set_phases(int16_t *phases);
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t pwm_get_phase(uint8_t channel_num, uint16_t *phase_p);
esp_err_t pwm_get_phase(uint8_t channel_num, float *phase_p);

/**
* @brief Set PWM period and duty of each PWM channel.
Expand Down
5 changes: 2 additions & 3 deletions examples/peripherals/pwm/main/pwm_example_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,13 @@ uint32_t duties[4] = {
};

// phase table, delay = (phase[x]/360)*PERIOD
int16_t phase[4] = {
0, 0, 90, -90,
float phase[4] = {
0, 0, 90.0, -90.0,
};

void app_main()
{
pwm_init(PWM_PERIOD, duties, 4, pin_num);
pwm_set_channel_invert(0x1 << 0);
pwm_set_phases(phase);
pwm_start();
int16_t count = 0;
Expand Down

0 comments on commit 72cbf0d

Please sign in to comment.