
// ----------------------------------------------------------------------

void calcFgrAng(long zVal) {
  // calculate the Finger angle value from the calibration limits  
  FgrVal = zVal;
  FgrAng = ((servoFgrMax - FgrVal)* 68)/(servoFgrMax - servoFgrTap);
}

// ----------------------------------------------------------------------

void calcFgrVal(long zAng) {
  // calculate the Finger microsecond value from the calibration limits  
  FgrAng = zAng;
  FgrVal = servoFgrMax - (((servoFgrMax - servoFgrTap) * zAng)/68);
}

// ----------------------------------------------------------------------

void doMainTask() {
  // main task scheduler, called every 10 ms
  readSwitch(); readSwitch(); // debounce switch read
  switch (mainTask) {
    case 0:
      // waiting for something to happen
      if (switchState > 0) {
        // switch press detected so switch it OFF
        pressCnt++; // count switch presses
        if (subTask < 10) {subTask++;}
        switch (subTask) {
          case 1: delay(3000); fingerAct50(); break;
          case 2: delay(2700); fingerAct51(); break;
          case 3: delay(2500); fingerAct52(); break;
          case 4: delay(2200); fingerAct53(); break;
          case 5: delay(2000); fingerAct00(); break;
          case 6: delay(1000); fingerAct01(); break;
          case 7: delay(1000); fingerAct02(); break;
          case 8: delay(500); fingerAct03(); break;
          case 9: delay(500); fingerAct04(); break;
          case 10:
            delay(random (100, 500)); actionTask = random(0,5);
            switch (actionTask) {
              case 0: fingerAct00(); break;
              case 1: fingerAct01(); break;
              case 2: fingerAct02(); break;
              case 3: fingerAct03(); break;
              case 4: fingerAct04(); break;
            }break;
        }
        mainCnt = 0; // zero task counter as something has happened
        mainWake = random(3500, 30000); sleepEn = 0;
        wakeTask= 0; wakeMinTime = 0;
      }
      break;
    case 1:
      // performing a 'wake up' action and increase sleep - wake period
      if (wakeTask < 5) {wakeTask++;}
      switch (wakeTask) {
        case 1: fingerAct90(); wakeMinTime = 30000; break;
        case 2: fingerAct91(); wakeMinTime = 60000; break;
        case 3: fingerAct92(); wakeMinTime = 120000; break;
        case 4: fingerAct93(); wakeMinTime = 240000; break;
        case 5: fingerAct94(); wakeMinTime = 480000; break;
      } mainTask = 0; break;
  }
  // pause or sleep for 1 second
  if (sleepEn > 0) {
    // powering down for 1 second
    Serial.print("z"); delay(1);
    LowPower.powerDown(SLEEP_1S, ADC_OFF, BOD_OFF);
    mainCnt = mainCnt+ 100; // don't lose count due to sleeping
  } else {mainCnt++;}
//  Serial.print("mainCnt = "); Serial.println(mainCnt);
  if (mainCnt == 3000) {
    // no recent activity so enable power saving sleep mode
    Serial.println("\nQuiet for 30s!");
    pressCnt = 0; subTask = 0; sleepEn = 1;
  }
  if (mainCnt >= mainWake) {
    // lift lid if no switch actions every now and again
    Serial.println("\nWaking up...");
    mainWake = mainCnt + wakeMinTime + random(3000, 30000); mainTask = 1;
  }
  if (mainCnt < 0) {
    // test for overflow?
    Serial.println("\nOverflow!");
    mainCnt = 0;
    mainWake = mainCnt + wakeMinTime + random(3000, 30000);
  }
  nextMicros = micros() + interval; // re-initialise loop timer
  switchState = -1; // set switch state as open
}

// ----------------------------------------------------------------------

void fingerAct00 () {
  // turn switch OFF as fast as possible
  Serial.println("Action 00");
  attachServos();
  SetLidVal(servoLidClr); delay(100);
  SetFgrVal(servoFgrMax); delay(400); // press switch OFF
  SetFgrToRest(); delay(100);
  SetLidToRest(); delayLidAng(45);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct01 () {
  // first touch switch then turn switch OFF as fast as possible
  Serial.println("Action 01");
  attachServos();
  SetLidVal(servoLidClr); delay(100); // raise lid
  SetFgrVal(servoFgrTch); delay(random(1000,2000)); // touch switch
  SetFgrVal(servoFgrTap); delay(200); // recoil
  SetFgrVal(servoFgrMax); delay(400); // press switch OFF
  SetFgrToRest(); delay(100);
  SetLidToRest(); delayLidAng(45);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct02 () {
  // first touch switch twice then turn switch OFF as fast as possible
  Serial.println("Action 02");
  attachServos();
  SetLidVal(servoLidClr); delay(100); // raise lid
  SetFgrVal(servoFgrTch); delay(random(1000,2000)); // touch switch
  SetFgrVal(servoFgrTch - 200); delay(random(750,1500)); // recoil slightly
  SetFgrVal(servoFgrTch); delay(random(750,1500)); // touch switch
  SetFgrVal(servoFgrTap); delay(200); // recoil
  SetFgrVal(servoFgrMax); delay(400); // press switch OFF
  SetFgrToRest(); delay(100);
  SetLidToRest(); delayLidAng(45);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct03 () {
  // turn switch OFF as fast as possible, then bang lid
  Serial.println("Action 03");
  attachServos();
  SetLidVal(servoLidClr); delay(100);
  SetFgrVal(servoFgrMax); delay(400); // press switch OFF
  SetFgrToRest(); delay(100);
  SetLidToRest(); delayLidAng(45);
  // bang lid
  detachDel(random(500,750));
  for (int zP=0; zP < random(3, 6); zP++) {
    SetLidVal(servoLidTap + 150); delay(100);
    SetLidVal(servoLidTap - 50); delay(100);
  }
  SetLidToRest(); delayLidAng(45);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct04 () {
  // bang lid, then turn switch OFF as fast as possible
  Serial.println("Action 04");
  attachServos();
  // bang lid
  for (int zP=0; zP < random(3, 6); zP++) {
    SetLidVal(servoLidTap + 150); delay(100);
    SetLidVal(servoLidTap - 50); delay(100);
  }
  detachDel(random(500,750));
  SetLidVal(servoLidClr); delay(100);
  SetFgrVal(servoFgrMax); delay(400); // press switch OFF
  SetFgrToRest(); delay(100);
  SetLidToRest(); delayLidAng(45);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct50 () {
  // turn switch OFF very cautiously and quickly
  Serial.println("Action 50");
  attachServos();
  // look around once
  calcLidAng(servoLidTap); attachServos();
  SetLidAngle(LidAng); delayLidAng(5); // get ready to open lid
  // partially raise the lid
  MoveLidAngle(LidAng - random(18, 24),80);
  detachDel(random(750, 2000)); // pause unpowered, looking around
  SetLidToRest(); delay(200);
  detachDel(random(100, 3000)); // pause unpowered
  // press switch OFF
  fingerAct00();
}

// ----------------------------------------------------------------------

void fingerAct51 () {
  // turn switch OFF very cautiously and quickly
  Serial.println("Action 51");
  attachServos();
  // look around once
  calcLidAng(servoLidTap); attachServos();
  SetLidAngle(LidAng); delayLidAng(5); // get ready to open lid
  // partially raise the lid
  MoveLidAngle(LidAng - random(20, 26),80);
  detachDel(random(750, 2000)); // pause unpowered, looking around
  // partially close lid
  MoveLidAngle(LidAng + 10, 50);
  detachDel(random(750, 2000)); // pause unpowered, looking around
  // close lid
  SetLidToRest(); delay(200);
  detachDel(random(100, 3000)); // pause unpowered
  // press switch OFF
  fingerAct00();
}

// ----------------------------------------------------------------------

void fingerAct52 () {
  // turn switch OFF very cautiously and quickly
  Serial.println("Action 52");
  attachServos();
  // look around once
  calcLidAng(servoLidTap); attachServos();
  SetLidAngle(LidAng); delayLidAng(5); // get ready to open lid
  // partially raise the lid
  MoveLidAngle(LidAng - random(20, 26),80);
  detachDel(random(750, 2000)); // pause unpowered, looking around
  // partially close lid
  MoveLidAngle(LidAng + 12, 50);
  detachDel(random(750, 2000)); // pause unpowered, looking around
  // partrially raise lid
  MoveLidAngle(LidAng - 8, 40);
  detachDel(random(750, 2000)); // pause unpowered, looking around
  // close lid
  SetLidToRest(); delay(200);
  detachDel(random(100, 3000)); // pause unpowered
  // press switch OFF
  fingerAct00();
}

// ----------------------------------------------------------------------

void fingerAct53 () {
  // turn switch OFF very cautiously and quickly
  Serial.println("Action 53");
  attachServos();
  // look around once
  calcLidAng(servoLidTap); attachServos();
  SetLidAngle(LidAng); delayLidAng(5); // get ready to open lid
  // partially raise the lid
  MoveLidAngle(LidAng - 15,80);
  detachDel(random(750, 2000)); // pause unpowered, looking around
  // press switch OFF
  fingerAct00();
}

// ----------------------------------------------------------------------

void fingerAct90 () {
  // awaken cautiously with a single tap
  Serial.println("Action 90");
  attachServos();
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidVal(servoLidTap - 50);  delay(100);
  SetLidToRest(); delayLidAng(45);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct91 () {
  // awaken cautiously with a tap,....tap
  Serial.println("Action 91");
  attachServos();
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(100);
  detachDel(900);
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(100);
  detachDel(100);
  SetLidToRest(); delayLidAng(20);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct92 () {
  // awaken cautiously with a tap,....tap,tap
  Serial.println("Action 92");
  attachServos();
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(900);
  detachDel(900);
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(100);
  detachDel(100);
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(100);
  detachDel(100);
  SetLidToRest(); delayLidAng(20);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct93 () {
  // awaken cautiously with a tap,..tap,..tap
  Serial.println("Action 93");
  attachServos();
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(100);
  detachDel(900);
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(100);
  detachDel(900);
  SetLidVal(servoLidTap + 150); delay(100);
  SetLidToRest();  delay(100);
  detachDel(900);
  SetLidToRest(); delayLidAng(20);
  detachServos();
}

// ----------------------------------------------------------------------

void fingerAct94 () {
  // awaken cautiously with multi-taps
  Serial.println("Action 94");
  attachServos();
  for (int zT=0; zT < random(1, 4); zT++) {
    for (int zP=0; zP < random(1, 4); zP++) {
      SetLidVal(servoLidTap + 150); delay(100);
      SetLidToRest();  delay(100);
      detachDel(random(100,750));
    } detachDel(random(500,2500));
  }
  SetLidToRest(); delayLidAng(45);
  detachServos();
}

// ----------------------------------------------------------------------

void SetFgrAngle(long zAng) {
  // move the Finger to the angle position immediately
  calcFgrVal(zAng); servoFgr.writeMicroseconds(FgrVal);
}

// ----------------------------------------------------------------------

void SetFgrVal(long zVal) {
  // move the Finger to the Microsecond position immediately
  calcFgrAng(zVal); servoFgr.writeMicroseconds(FgrVal);
}

// ----------------------------------------------------------------------

void SetFgrToRest() {
  // move the Finger to the Rest position immediately
  SetFgrAngle(80);
}

// ----------------------------------------------------------------------

void SetFgrToTap() {
  // move the Finger to the Tap position immediately
  SetFgrVal(servoFgrTap);
}

// ----------------------------------------------------------------------

