// https://forum.arduino.cc/t/solved-blinking-indicators/1327297
// https://wokwi.com/projects/416041824859474945

#include "proto_activities.h"

// activities

pa_activity (ButtonRecognizer, pa_ctx_tm(), int pin, bool& was_pressed, bool& was_released) {
  pinMode(pin, INPUT_PULLUP);

  pa_repeat {
    pa_await (digitalRead(pin) == LOW);
    was_pressed = true;
    pa_pause;
    was_pressed = false;
    pa_delay_ms (20); // debounce button press
    
    pa_await (digitalRead(pin) == HIGH);
    was_released = true;
    pa_pause;
    was_released = false;
    pa_delay_ms (20); // debounce button release
  }
} pa_end

pa_activity (Blink, pa_ctx_tm(), bool& show) {
  pa_every_ms (500) {
    show = !show;
  } pa_every_end
} pa_end

pa_activity (Delay_s, pa_ctx_tm(), int s) {
  pa_delay_s(s);
} pa_end

pa_activity (StateMachine, pa_ctx_tm(pa_use(Blink); pa_use(Delay_s)), bool was_pressed, bool was_released, bool& show) {
  pa_repeat {
    // Phase 1
    if (!was_pressed) {
      pa_when_abort (was_pressed, Blink, show);
    }

    // Phase 2
    show = true;
    pa_await (was_released);

    // Phase 3
    show = false;
    pa_when_abort (was_pressed, Delay_s, 3);
  }
} pa_end

pa_activity (Indicator, pa_ctx(), int pin, bool show) {
  pinMode(pin, OUTPUT);

  pa_always {
    digitalWrite(pin, show);
  } pa_always_end
} pa_end

pa_activity (Handler, pa_ctx(pa_co_res(3); pa_use(ButtonRecognizer); pa_use(StateMachine); pa_use(Indicator); bool was_pressed; bool was_released; bool show), 
                      int button, int indicator) {
  pa_co(3) {
    pa_with (ButtonRecognizer, button, pa_self.was_pressed, pa_self.was_released);
    pa_with (StateMachine, pa_self.was_pressed, pa_self.was_released, pa_self.show); 
    pa_with (Indicator, indicator, pa_self.show); 
  } pa_co_end
} pa_end

pa_activity (Main, pa_ctx(pa_co_res(2); pa_use_as(Handler, H1); pa_use_as(Handler, H2))) {
  pa_co(2) {
    pa_with_as (Handler, H1, 4, 11);
    pa_with_as (Handler, H2, 3, 10);
  } pa_co_end
} pa_end

pa_use(Main);

// setup and loop

void setup() {
  Serial.begin(115200);

  setupA7();
}

void loop() {
  pa_tick(Main);
  delay(10);  // ??

  loopA7();
}

const int indicator = A0;
const int myBuuton = A1;

//...
enum {PHASE0 = 0, PHASE1, PHASE2};
char *tags[] = {"phase zero", "phase one", "phase two", };

int thePhase = PHASE0;

bool butStateCur = true;
bool butStatePre;

bool ledOn;

unsigned long millisPre = 0;
unsigned long millisCur;
unsigned long phaseStart;
const int phaseDelay = 3000;           // delay for phase to timeout

void setupA7() {
//  Serial.begin(115200);
  Serial.println("\nJello Whirled!\n");

  pinMode(indicator, OUTPUT);
  pinMode(myBuuton, INPUT_PULLUP);

  butStatePre = digitalRead(myBuuton) == LOW;
}

void loopA7() {
  millisCur = millis();                

//... let us do our own switch handling
  bool buttonPressed = false;    // until proven otherwise
  butStateCur = digitalRead(myBuuton) == LOW;
  if (butStatePre != butStateCur) {
    if (butStateCur)
      buttonPressed = true;
    
    delay(20);    // debounce
  }

  butStatePre = butStateCur;

//...
  switch (thePhase) {
  case PHASE0 :
    ledOn = (millis() / 500) % 2;
    if (buttonPressed) {
      ledOn = true;
      thePhase = PHASE1;
    }

    break;
    
  case PHASE1 :
    if (buttonPressed) {
      ledOn = false;
      thePhase = PHASE2;
      phaseStart = millisCur;
    }

    break;

  case PHASE2 :
//    if (buttonPressed) thePhase = PHASE0;    // should the button cut short PHASE2?

    if (millisCur - phaseStart > phaseDelay) {
      thePhase = PHASE0;
    }

    break;
  }

  digitalWrite(indicator, ledOn ? HIGH : LOW);  // C/C++ ternary operator

  static int printedPhase = -1;  // no it does not!
  if (printedPhase != thePhase) {
    Serial.print("entered ");
    Serial.println(tags[thePhase]);

    printedPhase = thePhase;
  }
}
alto777