#ifndef _MY_BOARD_H
#define _MY_BOARD_H

#include <stdint.h>
#include "my_buttons.h"


#define S3MODULEKIT 0

//*************************

#define BoardLED1     17
#define BoardLED2     18

#define Set_Status_LED1(x) digitalWrite(BoardLED1, x)
#define Set_Status_LED2(x) digitalWrite(BoardLED2, x)

//************************

#define Button1_Pin   8
#define Button2_Pin   19
#define Button3_Pin   0

#define Button1_State digitalRead(Button1_Pin)
#define Button2_State digitalRead(Button2_Pin)
#define Button3_State digitalRead(Button3_Pin)

//***********************

#define I2C_SDA1_Pin    1
#define I2C_SCL1_Pin    2

#define Buzzer_Pin      37

#if S3MODULEKIT == 1
  #define RGBLED1_Pin   48
#else
  #define RGBLED1_Pin   3
#endif
  #define RGBLED2_Pin   46

#define RX433_Pin       16
#define TX433_Pin       38

#define VIN_12V_Pin     20

#define RELAY_RES       12
#define RELAY1_Pin      45
#define RELAY2_Pin      48
#define RELAY3_Pin      47
#define RELAY4_Pin      21
#define RELAY5_Pin      35 /* test*/

#define FanIndex        3

#define TMP102_ADDR     72

#define buzzerCh        4 /* 0-7chs available, 0-3 used by pwm outputs */

#define TOUCH1_Pin      9
#define TOUCH2_Pin      10
#define TOUCH3_Pin      11
#define TOUCH4_Pin      12
#define TOUCH5_Pin      13
#define TOUCH_SHIELD_Pin  9

#define EXT1_Pin        35
#define EXT2_Pin        36

#define OLED_DC       7
#define OLED_RST      6
#define OLED_MOSI     5
#define OLED_SCK      4
#define OLED_CS       15


int linearizeLED(float inp);

#define SetRelay(c,val) ledcWrite(c, val);
#define SetFrontLightCorr(val) ledcWrite(FrontConstLightCh,linearizeLED(val))
#define SetRearLightCorr(val) ledcWrite(RearConstLightCh,linearizeLED(val))
#define SetFrontLight(val) ledcWrite(FrontConstLightCh, val)
#define SetRearLight(val) ledcWrite(RearConstLightCh,val)

void Init_Board_Pins(void);

void Init_PWM_Outputs(void);

struct _relay
{
  int freq;
  bool linCorr;
  int max;
  int min;
};

struct PWMOUT{
  float max;
  bool visionCorrected;
  int resolution;
  int frequency;
};

class PWM_Output {
  public:
    float currDuty;
    bool visionCorrected;
    PWM_Output(uint8_t pin, uint8_t ch, int res, uint32_t freq, float maxDuty, bool visionCorrected=false);
    void setOutput(float duty);
    void setFreq(uint32_t fq);

    float getMaxDuty() const {
      return maxDuty;
    }
    void setMaxDuty(float duty) {
      // add any validation or constraints here
      if(duty < 0) {duty = 0.0;}
      else{if(duty > 100.0) {duty = 100.0;}}
      maxDuty = duty;
    }

  private:
    uint8_t ch;
    uint32_t freq;
    uint8_t res;
    uint8_t currOutVal;
    float maxDuty;
    int msecRampRate;

};

extern PWM_Output *pwmOut[4];


// Push button Ramp Up/Down Logic for Lights
class RAMP_Output {
  public:
    TimerHandle_t timerHandle;
    RAMP_Output(PWM_Output *output, OneButton *button, int rampTime, int steps, float min, float max);
    ~RAMP_Output();
    void IncrementTick(void);
    void SwitchDirection(void);
    void ClickOnOff(void);
    static void TimerCallback(TimerHandle_t xTimer);
    static RAMP_Output *instance; // Static member variable to store an instance
  private:
    PWM_Output *Output;
    OneButton *Button;
    int steps;
    int rampTime;
    float min;
    float max;
    float stepSize;
    bool dirFwd = true;
    float lastDuty;
    bool IsOn = true;

};

void Initialize_Rear_Control(int relayIndex, int buttonIndex, int rampTime, int steps, float min, float max);

#endif
