/*-----------------------------------------------------------------------------------------
 *  This software is in the public domain, furnished "as is", without technical
 *  support, and with no warranty, express or implied, as to its usefulness for
 *  any purpose.
 *
 *  Strawap38MVF_ESP.ino:
 *
 *  ESP32-WROOM-32 microcontroller software project to implement functionality for a
 *  two wheel driven RC amphi-tank (Strawap38MFV).
 *  This is the main control loop to trigger the below listed functions.
 *
 *  - RCPWMRead.ino: reading PWM signals from RC receiver and signal quality checks.
 *    The functions based on the RC engine sound & LED controller for Arduino ESP32
 *    written by TheDIYGuy999 and migrated functionality from pwmread_rcfailsafe.ino
 *    written by Kelvin Nelson.
 *
 *  - DualDriveMix3CH.ino: control of 2 motorshilds (BTS7960) to drive and steer the
 *    amphi-tank with two different modes
 *
 *  - Multiswitch.ino: 4 times multiswitch decoder to trigger different functions of
 *    the tank. Hardware design of encoder was taken from www.rc-bastelbu.de YaMS
 *    implementation of Dirk Wiedemann
 *
 *  - LED.ino: control of a RGB-LED to show the different driving states, failsave
 *    or wateralert
 *
 *  - Sound.ino: sound controller for engine, sirene, gun and wateralert based on the
 *    RC engine sound & LED controller for Arduino ESP32 written by TheDIYGuy999
 *
 *  - Watersensor.ino: reading of digital humidity sensor as wateralert implementation
 *
 *  Author: Volker Frauenstein
 *  Date: 03/03/2021 Version 2.1: functions x_RCpwmRange for easy RC signal calibration
 *                                and RC interrupt performance optimisation added
 *                                Global definitions outsourced to new Strawap38MVF_ESP.h
 *
 *  Date: 29/01/2021 Version 2.0: documentation completed and blinking function to RGB-LED added
 *  Date: 08/01/2021 Version 1.3: RGB-LED function adapted
 *  Date: 06/01/2021 Version 1.2: migration of sound functions added
 *  Date: 05/01/2021 Version 1.1: RGB-LED, Multiswitch and wateralert function added
 *  Date: 02/01/2021 Version 1.0: migration of RC signal readings to ESP32 microcontroller
 */

// SW version definition
String Strawap = "StrawapMFV38 - SW Version 2.1 (for ESP32 WROOM DEV)";

// include for function and datstructur definitions
#include "Strawap38MVF_ESP.h"

// generig definitions
//#define DEBUG_M 1                              // set activ if debuging for main loop is needed

#ifdef DEBUG_M
 unsigned long lastloop = 0;
#endif

// =======================================================================================================
// SETUP FUNCTIONS
// =======================================================================================================
void setup() {

    // Serial setup
    Serial.begin(115200);                     // USB serial (for DEBUG)
    Serial.print(" Start up of ");Serial.println(Strawap);

    setupRCpwm();                             // setup read of RC PWM signals of defined channels
    close_DualDrive();                        // disable motorshilds and motors for start up
    setup_MultiSwitch();                      // define multiswitch Pinout
    close_MultiSwitch();                      // and close states at startup
    setup_LEDstate();                         // setup RGB-LED
    sound_setup();                            // setup for sound
    setup_watersensor();                      // setup for water alarm
}

// =======================================================================================================
// MAIN LOOP, RUNNING ON CORE 1
// =======================================================================================================
void loop() {

     if (pwmRCcycle > PWM_CHANNELS_NUM) {     // new pwm signals measured on all GIO Pins
       #ifdef DEBUG_M
        unsigned long looptime = millis();
        Serial.print("RC pwm duration: ");Serial.print(looptime - lastloop);Serial.print("ms");
        lastloop = looptime;
       #endif

       readPwmSignals();                      // collect and normalise RC pwm input

       pwmRCcycle = 1;                        // prepare for next RC signal cycle (every 20 ms)
       pwm_cycle = true;                      // trigger RC loop on Core 0

       // old RC systems can have scattering on pwm signal, therefor the out of bound check will not do the job
       failed_now = RCpwmScattering();        // check RC signal scattering

       if ( failed_before > 0 ) {             // failsafe for scattering reasons is activ
        if ( !failed_now ) {                  // check if signal quality is now good againg
          if ( count_good > 10 ) {
            start_DualDriveMix();             // signal was 10 times good, enable motors againg
            failed_before = false;            // and clean up for next check
            count_good = 0;
            set_LEDstate(6);                  // LED off
            #ifdef DEBUG_M
             Serial.print(" Start ");
            #endif
          }
          else {
            count_good = count_good + 1;      // signal is good -> count good time
            set_LEDstate(0);                  // LED set to red
            #ifdef DEBUG_M
             Serial.print(" Wait ");
            #endif
          }
        }
        else {                                // signal is still or againg bad
          count_good = 0;                     // reset good time counter
          #ifdef DEBUG_M
           Serial.print(" Reset ");
          #endif
        }
       }
       else {                                 // RC signal was good
        if ( !failed_now ) {                  // check if it is still good
          run_DualDrive(0, 1, 2);             // Mix the drives with RC channels 1, 2 and 4 (RC_in[0],RC_in[1],RC_in[2])
          run_MultiSwitch(3);                 // check state of Multiswitch on channel 6 (RC_in[3] and handle pinout
          // triggering switchable sounds
          engineOnOff(switchOn[0]);           // Switch engine on or off
          triggerSiren(switchOn[1]);          // sound for combat siren depending on switch b
          triggerSound1(switchOn[2]);         // sound for MG fire depending on switch c
          count_good = 0;
          #ifdef DEBUG_M
           Serial.print(" Run ");
          #endif
        }
        else {                                // RC signal has gone bad now, do failsafe and disable motors and Multiswitch
          close_DualDrive();                  // disable motors
          close_MultiSwitch();                // and Multiswitch
          failed_before = true;               // prepare for next check
          set_LEDstate(0);                    // LED set to red
          // shutoff sounds
          engineOnOff(false);                 // Switch engine on or off
          triggerSiren(false);                // sound for combat siren depending on switch b
          triggerSound1(false);               // sound for MG fire depending on switch c
          count_good = 0;
          #ifdef DEBUG_M
           Serial.print(" Stop ");
          #endif
        }
       }                                      // end failsafe check for old RCs

       mapThrottle(power);                    // Map pulsewidth to throttle
       triggerHorn(checkwater());             // check for wateralarm and trigger horn if needed

      #ifdef DEBUG_M                          // show debug data if needed
       looptime = millis() - looptime;
       Serial.print(", Mainloop runtime: ");Serial.print(looptime);Serial.println("ms");
      #endif
     }                                        // end loop on RC signal detection
}                                            // end Loop

// =======================================================================================================
// 1st MAIN TASK, RUNNING ON CORE 0 (Interrupts are running on this core as well)
// =======================================================================================================

void Task1code(void *pvParameters) {
  for (;;) {

    dacOffsetFade();                          // DAC offset fader for sounds

    if (pwm_cycle) {                          // RC Signal needed for update of functions

      pwm_cycle = false;                      // prepare for next RC signal cycle (every 20 ms)

      engineMassSimulation();                 // Simulate engine mass, generate RPM signal
      automaticGearSelector();                // call gear selector
      DriveState();                           // set Drivestate for engine sound simulation
    }
  }
}