#include <AccelStepper.h>
const int pwmPin =  4; // pin 4 used for the relay pin
const int dutyCycleAnalogIn = A0;  // Analog input- PWM duty
const int periodAnalogIn = A1;  // Analog input - period (ms)
const int speedAnalogIn = A2;  // Analog input - speed (Hz)
const int maxPeriod = 5000;   // hard coded max on time
const int maxFreq = 3;   // limit the max spot frequency (Hz)
const int minDuty = 0.2;  // min duty cycle
const int dirPin = 2;  // pin 2 used for DIR output
const int stepPin = 3;  // pin 3 used for STEP output
// Variables will change
int pwmState = LOW; //initial state for PWM output
int pwmSensorValue = 0;  // value read from the pot
int periodSensorValue = 0;
int speedValue = 0;
long plot = 0;
AccelStepper stepper1(AccelStepper::DRIVER, stepPin, dirPin); // (Type of driver: with 2 pins, STEP, DIR)
long previousMillisPwm = 0;  //last time PWM output was updated
long previousMillisPeriod = 0;
// pwmPeriod is time between spots
long pwmPeriod = 2000; //interval between spots (milliseconds)
// must be long to prevent overflow
long pwmDuration = 2000; //interval for PWM output (milliseconds)
unsigned long currentMillis = 0; // initialise
void setup() 
{
  // Core 0 is used for the stepper control
  // Set maximum speed value for the stepper:
  stepper1.setMaxSpeed(1000);
  Serial.begin(9600);
  // set pwmPin to output mode
  pinMode(pwmPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  digitalWrite(dirPin, HIGH);
  digitalWrite(pwmPin, pwmState);
  currentMillis = millis();
}
void setup1() 
{
// Core1 setup - nothing required here
}
void loop() 
{
  // Relay time / PWM control is done on Core0
  analogRead(0); // could be any channel
  periodSensorValue = analogRead(periodAnalogIn); // 0 - 1023 count
  pwmPeriod = map((maxPeriod * periodSensorValue / 1023), 0, 1023, 1000/maxFreq, 1023); // map input to pwmPeriod - time between spots
  pwmSensorValue = analogRead(dutyCycleAnalogIn); // 0 - 1023 count
  pwmDuration = map(pwmSensorValue, 0, 1023, pwmPeriod*minDuty, pwmPeriod); // map input to pwmDuration - min 20%
  currentMillis = millis(); // capture the current time
  managePwm();
  managePeriod();
  reportStatus();
}
void loop1() 
{
  // stepper speed control is done on Core1
   speedValue = map(analogRead(speedAnalogIn), 0, 4095, 400, 4095); // Define setSpeed() according to input A2
   stepper1.setSpeed(speedValue); // Step the motor with a constant speed previously set by setSpeed();
   stepper1.runSpeed();
   Serial.print("Speed ");
   Serial.println(speedValue);
}
void reportStatus() 
{
  Serial.print("Duty time is");
  Serial.print("\t");
  Serial.print(pwmDuration);
  Serial.print("\t");
  Serial.print("Period time is");
  Serial.print("\t");
  Serial.print(pwmPeriod);
  Serial.print("\t");
  Serial.print("Output");
  Serial.print("\t");
  Serial.print(pwmState);
  Serial.println("\t");
}
void managePwm() 
{
  //check if it's time to change the PWM output yet 
  if(currentMillis - previousMillisPwm > pwmDuration) 
  {
    //store the time of this change
    pwmState = LOW;
    digitalWrite(pwmPin, pwmState);
  }
}
void managePeriod() 
{
  //check if it's time to reset the output yet 
  if(currentMillis - previousMillisPeriod > pwmPeriod) 
  {
    previousMillisPeriod = currentMillis;
    previousMillisPwm = currentMillis;
    pwmState = HIGH;
    digitalWrite(pwmPin, pwmState);
  }
}