/*
Bresenham pin toggling/frequency generator
with Scope https://github.com/Dlloydev/Wokwi-Chip-Scope
and https://github.com/Dlloydev/Wokwi-Chip-PWM
Wokwi Uno https://wokwi.com/projects/390819301187622913
Wokwi Mega: https://wokwi.com/projects/390819455604080641
for https://forum.arduino.cc/t/three-square-waves/1233317/23
*/
int32_t D;
int32_t y = 0;
byte Pins[] = {12,11,10};
byte initalVal[] = {HIGH,LOW,HIGH};
const uint32_t dt = 8; // chunk time // less than 8us is unstable
// 3/2000 for toggling at 666.6666us / 750Hz
// 3/1000 for toggling at 333.333us / 1500Hz
// 300/9900 for 1515.15Hz matching tone(1500) results
// 2/2000 for toggling at 1000us / 500Hz
const int32_t dy = 300; // rise
const int32_t dx = 100000; // run
boolean bresenham(void) {
const uint32_t interval = dt;
static uint32_t last = -interval;
uint32_t now = micros();
bool retval = false;
if (now - last >= interval) {
if (D >= 0 ) {
++y;
digitalWrite(LED_BUILTIN, digitalRead(LED_BUILTIN) == HIGH ? LOW : HIGH);
if (false) { // report
Serial.print("t:");
Serial.print(now);
Serial.print(" D:");
Serial.print(D);
Serial.print(" y:");
Serial.print(y);
Serial.println();
}
D -= dx;
retval = true;
}
D += dy * dt;
last += interval; // stay phase-locked
}
return retval;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
D = -dx / 2; //phase shift -1/2 cycle
float freq = (dy)/(2*dx/1000000.0);
Serial.print("Toggle at Float ratio:");
Serial.print((1.0 * dx) / dy, 3);
Serial.print("us Bresenham ratio: ");
Serial.print(dx);
Serial.print("/");
Serial.print(dy);
Serial.print(" Frequency:");
Serial.print(freq,3);
Serial.println("Hz");
pinMode(LED_BUILTIN, OUTPUT);
byte index = 0;
for(auto &pin:Pins){
pinMode(pin,OUTPUT);
digitalWrite(pin,initalVal[index]);
++index;
}
}
void loop() {
static byte pin = 0;
// put your main code here, to run repeatedly:
if(bresenham()){ // toggle pins in round robin
digitalWrite(Pins[pin],digitalRead(Pins[pin])==HIGH?LOW:HIGH);
++pin;
if(pin >=3) pin = 0;
};
}