This could work. Modify the ConvertToHalfCycleTime() function for your desired mapping. It takes the microseconds between rising edges on the input and returns the microseconds in a half-cycle of the output. To have the output track the input, return inputCycleTime / 2.
const byte InputPin = 2;
const byte OutputPin = 3;
volatile unsigned long PreviousInterruptTime = 0;
volatile unsigned long InputCycleTime = 0;
void setup()
{
pinMode(InputPin, INPUT);
pinMode(OutputPin, OUTPUT);
attachInterrupt(digitalPinToInterrupt(InputPin), InputISR, RISING);
}
void InputISR()
{
unsigned long thisInterruptTime = micros();
InputCycleTime = thisInterruptTime - PreviousInterruptTime;
PreviousInterruptTime = thisInterruptTime;
}
unsigned long ConvertToHalfCycleTime(unsigned long inputCycleTime)
{
return inputCycleTime * 1.3333; // Remember, going from full cycles to half cycles
}
void loop()
{
unsigned long currentMicros = micros();
static unsigned long lastOutputChangeTime = 0;
noInterrupts();
unsigned long ict = InputCycleTime;
unsigned long pit = PreviousInterruptTime;
interrupts();
// Only pulse output if the time since the last interrupt is less than one second.
if (currentMicros - pit < 1000000ul)
{
unsigned long outputHalfCycleTime = ConvertToHalfCycleTime(ict);
if (currentMicros - lastOutputChangeTime >= outputHalfCycleTime)
{
lastOutputChangeTime = currentMicros;
digitalWrite(OutputPin, !digitalRead(OutputPin)); // Toggle each half cycle
}
}
}