/*
 * LEIGH:plc
 * Copyright 2022 Alex Leigh
 *
 * This program is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <math.h>
#include "driver/ledc.h"
#include "esp_err.h"

#ifdef BOARD_WESP32
#define CH1_PIN GPIO_NUM_15
#define CH2_PIN GPIO_NUM_4
#define CH3_PIN GPIO_NUM_13
#define CH4_PIN GPIO_NUM_18
#elif BOARD_ESPRESSIF_DEV
// These are wrong
#define CH1_PIN GPIO_NUM_15
#define CH2_PIN GPIO_NUM_4
#define CH3_PIN GPIO_NUM_13
#define CH4_PIN GPIO_NUM_18
#endif

void pwmFinit(void)
{
    ledc_channel_config_t ch1 = {0}, ch2 = {0}, ch3 = {0}, ch4 = {0};

    ch1.gpio_num = CH1_PIN;
    ch1.speed_mode = LEDC_HIGH_SPEED_MODE;
    ch1.channel = LEDC_CHANNEL_1;
    ch1.intr_type = LEDC_INTR_DISABLE;
    ch1.timer_sel = LEDC_TIMER_1;
    ch1.duty = 0;

    ch2.gpio_num = CH2_PIN;
    ch2.speed_mode = LEDC_HIGH_SPEED_MODE;
    ch2.channel = LEDC_CHANNEL_2;
    ch2.intr_type = LEDC_INTR_DISABLE;
    ch2.timer_sel = LEDC_TIMER_1;
    ch2.duty = 0;

    ch3.gpio_num = CH3_PIN;
    ch3.speed_mode = LEDC_HIGH_SPEED_MODE;
    ch3.channel = LEDC_CHANNEL_3;
    ch3.intr_type = LEDC_INTR_DISABLE;
    ch3.timer_sel = LEDC_TIMER_1;
    ch3.duty = 0;

    ch4.gpio_num = CH4_PIN;
    ch4.speed_mode = LEDC_HIGH_SPEED_MODE;
    ch4.channel = LEDC_CHANNEL_4;
    ch4.intr_type = LEDC_INTR_DISABLE;
    ch4.timer_sel = LEDC_TIMER_1;
    ch4.duty = 0;

    ledc_timer_config_t ledc_timer = {0};
    ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_timer.duty_resolution = LEDC_TIMER_8_BIT;
    ledc_timer.timer_num = LEDC_TIMER_1;
    ledc_timer.freq_hz = 25000;

    ESP_ERROR_CHECK(ledc_channel_config(&ch1));
    ESP_ERROR_CHECK(ledc_channel_config(&ch2));
    ESP_ERROR_CHECK(ledc_channel_config(&ch3));
    ESP_ERROR_CHECK(ledc_channel_config(&ch4));
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
}

void pwmFset(uint8_t ch1_fraction, uint8_t ch2_fraction, uint8_t ch3_fraction, uint8_t ch4_fraction)
{
    uint8_t duty = ch1_fraction;
    duty = 255 - ch1_fraction;
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1, duty));
    duty = 255 - ch2_fraction;
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2, duty));
    duty = 255 - ch2_fraction;
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3, duty));
    duty = 255 - ch2_fraction;
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_4, duty));

    ESP_ERROR_CHECK(ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_1));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_2));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_3));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_4));
}