/**
 * @file Functions.h
 * @author Lukas Chytil (xchyti13@vutbr.cz)
 * @brief A file declaring functions for the main program.
 * @date 2023-05-02
 *
 * @copyright Copyright (c) 2023
 *
 */
#ifndef FUNCTIONS
#define FUNCTIONS

#include <Arduino.h>

/**
 * @brief This main function determines the state of the vehicle and decides what sound will be played. \n
 * Detects braking, controller off, ensures engine start. \n
 * It calls the functions that ensure the sound system of the car.
 *
 */
void sound_creator();


/**
 * @brief A function that regulates engine revolutions depending on the potentiometer for the engine power. \n
 * Creates smooth acceleration and deceleration effect. Based on the timeon value from receiver and the acceleration, \n
 * it gradually modifies the engine revolutions in the timeon_function_sound variable
 *
 * @param timeon PWM signal from receiver in ON position in microseconds.
 */
void timeon_regulator(long timeon);

/**
 * @brief This function is responsible for playing the sounds of the vehicle when it is moving forward. \n
 * First, it will be evaluated whether a sharp acceleration has occurred. \n
 * If the acceleration is moderate, a accelerate soundtrack adequate for the given speed level is played. If there is no change in speed, the song is played for constant engine revolutions at the given speed \n
 * When slowing down, a decelerate soundtrack will be played for the corresponding speed.
 *
 */
void driving_forward();


/**
 * @brief This function is responsible for playing the sounds of the vehicle when it is moving backwards. \n
 * First, it will be evaluated whether a sharp acceleration has occurred. \n
 * If the acceleration is moderate, a accelerate soundtrack adequate for the given speed level is played. If there is no change in speed, the song is played for constant engine revolutions at the given speed \n
 * When slowing down, a decelerate soundtrack will be played for the corresponding speed.
 *
 */
void driving_backwards();


/**
 * @brief This function is called once per signal period. \n
 * It stores the previous TIMEON values used for braking and determines the difference between the values \n
 * Prints the value of TIMEON for each period.
 *
 */
void signal_analyses();


/**
 * @brief Function ensuring the playback of engine sound at neutral speed
 *
 */
void neutral_engine_rpm();


/**
 * @brief The function ensuring the start of the engine at the beginning of the program.
 *
 * @return true - When the engine is starting.
 * @return false - When the engine is already started.
 */
bool starting_engine();

/**
 * @brief Braking detection function. Built-in LED indicates braking. If it lights up, the brake is activated. Otherwise the LED will turn off.
 *
 * @param timeon_function_begin PWM signal width in ON position in microseconds.
 * @return true - If braking is activated and the controller is in the brake position.
 * @return false - if braking is not activated or the controller has returned from the braking position.
 */
bool braking(long timeon_function_begin);


/**
 * @brief This function is called on an interrupt basis. Filters invalid values ​​and stores TIMEON value in a global time_on_value variable. \n
 * Stored value is in microseconds.
 *
 */
void pulse_width();


/**
 * @brief This function will end the playback of the mixer, whitch is used for playing engine sound mixed with beep sound.
 *
 */
void stop_playing_mixer_sound();


/**
 * @brief This function is used to play engine sounds from ESP32 memory.
 *
 * @param track_num Number of the engine track in PROGMEM to be played.
 */
void play_wav_from_PROGMEM(int track_num);



/**
 * @brief This function plays and mixes the sound of the engine and the reversing ultrasonic sensor from PROGMEM. \n
 * The function is only used if it is enabled (ULTRASONIC_ENABLE == 1) and the vehicle is moving slowly backwards.
 *
 * @param channel Select the channel to be used for playback. Channel 1 is used to play the sound of the motor. Channel 0 is used to play beep sound of reverse sensor.
 */
void play_wav_from_PROGMEM_mixer(int channel);


/**
 * @brief This function is called to play the engine record. \n
 * Decides whether it is necessary to play another song.
 *
 * @param track_num Track number to be played.
 */
void rpm_function(int track_num);


/**
 * @brief The task of this function is to play the sound of the engine that played last before silence. \n
 * Silence occurs to eliminate indecisive switching between the two tracks around the switching threshold. \n
 * For example: engine_01.wav is played to a width of 1520 milliseconds, engine_02.wav is played from width of 1530 milliseconds,
 * The length of the space between tracks is modified by the REMOVE_EDGE variable.
 */
void play_last_if_silence();


/**
 * @brief Distance measurement using an ultrasonic sensor. Dinstance is measured and stored in global variable in centimeters.
 *
 */
void measure_distance();


/**
 * @brief When reversing, the distance behind the vehicle is measured every 40 milliseconds using an ultrasonic sensor. \n
 * If the distance is less than 40 centimeters, a beeping sound is added to the engine audio track. \n
 * The smaller the distance, the more often the beep track is played
 *
 */
void reverse_distance_sensor();


/**
 * @brief Set the up audio players object. Playback from ESP32 memory, \n
 * playback from PROGMEM for the mixer.
 *
 */
void setup_audio_players();


/**
 * @brief The function periodically checks the signal width. \n
 * If the transmitter is not connected to the receiver, an error tone will be played after 2 seconds.
 *
 * @param time_on PWM signal width in ON position in microseconds
 * @return true IF the transmitter is connected and PWM width in NOT 0 microseconds.
 * @return false IF the transmitter is NOT connected and PWM width in greater than 0 microseconds.
 */
bool transmitter_signal_check(long time_on);

/**
 * @brief The function returns the length of the song based on the argument
 *
 * @param track_num the number of the song whose length I want to know
 * @return song length in milliseconds
 */
int track_length(int track_num);

/**
 * @brief The function loads a track from memory. The playback field has a new source.
 *
 * @param track_num the number of the track that should be given to the audio output.
 */
void open_audio_file(int track_num);


/**
 * @brief Function used to change the audio volume using a potentiometer. \n
 * Converts the voltage to a flaot value in the interval <0.1,3.99> \n
 * The smallest step of change is a tenth. \n
 * Prevents the volume from changing on the edge of two levels.
 *
 */
void audio_volume();


/**
 * @brief Function used to change the engine power using a potentiometer. \n
 * Converts the voltage to a int value. A higher value means a slower onset of performance\n
 * The smallest step of change is one. \n
 * Prevents the power from changing on the edge of two levels.
 *
 */
void power_adjust();

#endif //FUNCTIONS