#include <Arduino_FreeRTOS.h>
#include "task.h"
#include "semphr.h"
 
#include <math.h>
 
#define SEND_GANTT  1
#define AOUT        9
#define LED_OUT     7
 
//Tasks
TaskHandle_t        ledTaskH;
TaskHandle_t        sineTaskH;
 
//Mutex
SemaphoreHandle_t   SerialMutex;
 
void sendGantt(const char *name, unsigned int stime, unsigned int etime) {
    if(xSemaphoreTake(SerialMutex, portMAX_DELAY) == pdTRUE) {  //Solicita Mutex
        Serial.print("\t\t");
        Serial.print(name);
        Serial.print(": ");
        Serial.print(stime);
        Serial.print(", ");
        Serial.println(etime);
        xSemaphoreGive(SerialMutex);                            //Libera Mutex
    }
}
 
void setup() {
    //Inicializa Serial
    Serial.begin(9600);
    Serial.print("1s is ");
    Serial.print(configTICK_RATE_HZ);
    Serial.print(" ticks at ");
    Serial.print(F_CPU);
    Serial.print(" Hz\n\n");
    #if (defined(SEND_GANTT) && (SEND_GANTT==1))
        Serial.println("gantt\n\tdateFormat x\n\ttitle A gant diagram");
    #endif
     
    SerialMutex = xSemaphoreCreateMutex();
     
    //Cria tarefa ledTask
    xTaskCreate(ledTask,            //Funcao
                "ledTask",          //Nome
                128,                //Pilha
                NULL,               //Parametro
                1,                  //Prioridade
                &ledTaskH);
     
    //Cria tarefa sineTask
    xTaskCreate(SineTask,
                "SineTask",
                128,
                NULL,
                1,
                &sineTaskH);    
}
 
void loop() {
    // Nada é feito aqui, Todas as funções são feitas em Tasks
}
 
/* LedTask
 *  Pisca Led com frequência de 1Hz
 */
void ledTask(void *arg) {
    unsigned int stime; 
    pinMode(LED_OUT, OUTPUT);
    while(1) {
        stime = millis();
        digitalWrite(LED_OUT, HIGH);                        //Liga Led
        vTaskDelay(pdMS_TO_TICKS(500));                //Espera 0.5s
        digitalWrite(LED_OUT, LOW);                         //Desliga Led
        vTaskDelay(pdMS_TO_TICKS(500));                //Espera 0.5s
        #if (defined(SEND_GANTT) && (SEND_GANTT==1))
            sendGantt("Led", stime, millis());         //Envia Informações pela Serial
        #endif
    }
    //O codigo nunca deve chegar aqui
    vTaskDelete(NULL);      //Deleta a Task atual
}
 
/* SineTask
 *  Descreve uma senoide de 2Hz na saida analogica
 */
void SineTask(void *arg) {
    unsigned int stime=0, etime=0;
    pinMode(AOUT, OUTPUT);
    unsigned int outpv = 0;
    unsigned int period = 0;
    while(1) {
        stime = millis();
        for(period = 0; period < 16; ++period){
            etime = millis();
            outpv = (unsigned int)((sin(2*PI*2*(etime - stime)*0.001)+1)*127.5);  /*Senoide = seno(2*PI*Freq*t)*/
            analogWrite(AOUT, outpv);
            vTaskDelay(pdMS_TO_TICKS(33));       //Espera 33 milisegundos (32 ms)
        }
        #if (defined(SEND_GANTT) && (SEND_GANTT==1))
            sendGantt("Sine", stime, millis());
        #endif
    }
    //O codigo nunca deve chegar aqui
    vTaskDelete(NULL);      //Deleta a Task atual
}