#include <math.h>

// Define the phase pins
const int phaseA = 9;
const int phaseB = 10;
const int phaseC = 11;

// Define the maximum PWM value
const int maxPWM = 255;

// Define the frequency of the PWM signal in Hz
float frequency = 50.0;

// Define the amplitude of the sine wave
float amplitude = 1.0;

// Define the number of samples in the sine wave
const int numSamples = 128;

// Define the lookup table for the sine wave
float sinTable[numSamples];

void setup() {
  // Initialize the serial port for debugging
  Serial.begin(9600);

  // Generate the sine wave lookup table
  for (int i = 0; i < numSamples; i++) {
    sinTable[i] = amplitude * sin(2.0 * PI * i / numSamples);
  }

  // Set the pins as outputs
  pinMode(phaseA, OUTPUT);
  pinMode(phaseB, OUTPUT);
  pinMode(phaseC, OUTPUT);

  // Set up Timer1 for phaseA (Pin 9)
  TCCR1A = _BV(COM1A1) | _BV(WGM11); // Non-inverting mode, Fast PWM
  TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10); // No prescaler
  ICR1 = (16000000 / (frequency * 2)) - 1; // Set the PWM frequency

  // Set up Timer2 for phaseB (Pin 10)
  TCCR2A = _BV(COM2A1) | _BV(WGM21) | _BV(WGM20); // Non-inverting mode, Fast PWM
  TCCR2B = _BV(CS20); // No prescaler
  OCR2A = (255 / (frequency * 2)) - 1; // Set the PWM frequency

  // Start with phase A high
  analogWrite(phaseA, maxPWM / 2);
  analogWrite(phaseB, 0);
  analogWrite(phaseC, 0);
}

void loop() {
  // Read the frequency and amplitude from the serial port
  if (Serial.available() > 0) {
    float newFrequency = Serial.parseFloat();
    float newAmplitude = Serial.parseFloat();

    // Update the frequency and amplitude if valid values were received
    if (newFrequency > 0 && newAmplitude >= 0) {
      frequency = newFrequency;
      amplitude = newAmplitude;

      // Update the PWM frequency for the phase pins
      ICR1 = (16000000 / (frequency * 2)) - 1;
      OCR2A = (255 / (frequency * 2)) - 1;

      // Update the sine wave lookup table
      for (int i = 0; i < numSamples; i++) {
        sinTable[i] = amplitude * sin(2.0 * PI * i / numSamples);
      }
    }
  }

  // Calculate the current time in seconds
  float time = millis() / 1000.0;

  // Calculate the phase angle for each phase
  float angleA = 2.0 * PI * frequency * time;
  float angleB = angleA + (2.0 * PI / 3.0);
  float angleC = angleA + (4.0 * PI / 3.0);

  // Calculate the PWM values for each phase
  int pwmA = (maxPWM / 2) * (1 + amplitude * sin(angleA));
  int pwmB = (maxPWM / 2) * (1 + amplitude * sin(angleB));
  int pwmC = (maxPWM / 2) * (1 + amplitude * sin(angleC));

  // Write the PWM values to the phase pins
  analogWrite(phaseA, pwmA);
  analogWrite(phaseB, pwmB);
  analogWrite(phaseC, pwmC);

  // Debugging output
  Serial.print("Frequency: ");
  Serial.print(frequency);
  Serial.print(" Amplitude: ");
  Serial.print(amplitude);
  Serial.print(" PWM A: ");
  Serial.print(pwmA);
  Serial.print(" PWM B: ");
  Serial.print(pwmB);
  Serial.print(" PWM C: ");
  Serial.println(pwmC);

  delay(10); // Short delay to prevent overwhelming the serial output
}