#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "stm32c0xx_hal.h"
#include <stdio.h>

ADC_HandleTypeDef hadc;
UART_HandleTypeDef huart;

QueueHandle_t sensorQueue;
SemaphoreHandle_t emergencySemaphore;
SemaphoreHandle_t thresholdMutex;

uint16_t humidityThreshold = 2000; // Valeur initiale arbitraire

typedef struct {
    int zone;
    uint16_t value;
} SensorData;

void sendUART(const char* message) {
    HAL_UART_Transmit(&huart, (uint8_t*)message, strlen(message), HAL_MAX_DELAY);
}

uint16_t readADC(uint32_t channel) {
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = channel;
    sConfig.Rank = ADC_REGULAR_RANK_1;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);
    HAL_ADC_Start(&hadc);
    HAL_ADC_PollForConversion(&hadc, HAL_MAX_DELAY);
    return HAL_ADC_GetValue(&hadc);
}

// Tâche de lecture des capteurs (PA0, PA1)
void Task_ReadHumidity(void* params) {
    SensorData data;
    while (1) {
        for (int i = 0; i < 2; i++) {
            data.zone = i;
            data.value = readADC(i == 0 ? ADC_CHANNEL_0 : ADC_CHANNEL_1);

            xSemaphoreTake(thresholdMutex, portMAX_DELAY);
            uint16_t localThreshold = humidityThreshold;
            xSemaphoreGive(thresholdMutex);

            if (data.value < localThreshold) {
                xQueueSend(sensorQueue, &data, portMAX_DELAY);
            }

            char msg[64];
            sprintf(msg, "Capteur Zone %d: %d\n", i + 1, data.value);
            sendUART(msg);
        }
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

// Tâche d’arrosage
void Task_WateringControl(void* params) {
    SensorData received;
    while (1) {
        if (xQueueReceive(sensorQueue, &received, portMAX_DELAY) == pdPASS) {
            if (xSemaphoreTake(emergencySemaphore, 0) == pdPASS) continue;

            int ledPin = received.zone == 0 ? GPIO_PIN_4 : GPIO_PIN_5;
            HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_SET);

            char msg[64];
            sprintf(msg, "Vanne %d activée\n", received.zone + 1);
            sendUART(msg);

            vTaskDelay(pdMS_TO_TICKS(10000)); // 10 sec

            HAL_GPIO_WritePin(GPIOA, ledPin, GPIO_PIN_RESET);
            sprintf(msg, "Vanne %d désactivée\n", received.zone + 1);
            sendUART(msg);
        }
    }
}

// Tâche d’urgence
void Task_Emergency(void* params) {
    while (1) {
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_3) == GPIO_PIN_SET) {
            sendUART("** Arrêt d'urgence déclenché **\n");
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4 | GPIO_PIN_5, GPIO_PIN_RESET);
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);
            xSemaphoreGive(emergencySemaphore);
            vTaskDelay(pdMS_TO_TICKS(2000)); // Anti-rebond
        }
        vTaskDelay(pdMS_TO_TICKS(200));
    }
}

// Tâche de mise à jour du seuil
void Task_UpdateThreshold(void* params) {
    while (1) {
        uint16_t newValue = readADC(ADC_CHANNEL_2);
        xSemaphoreTake(thresholdMutex, portMAX_DELAY);
        humidityThreshold = newValue;
        xSemaphoreGive(thresholdMutex);

        char msg[64];
        sprintf(msg, "Nouveau seuil humidité : %d\n", newValue);
        sendUART(msg);

        vTaskDelay(pdMS_TO_TICKS(2000));
    }
}

void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_ADC_Init(void);
void MX_USART_Init(void);

int main(void) {
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_ADC_Init();
    MX_USART_Init();

    sensorQueue = xQueueCreate(10, sizeof(SensorData));
    emergencySemaphore = xSemaphoreCreateBinary();
    thresholdMutex = xSemaphoreCreateMutex();

    xTaskCreate(Task_ReadHumidity, "ReadHumidity", 128, NULL, 2, NULL);
    xTaskCreate(Task_WateringControl, "Watering", 128, NULL, 2, NULL);
    xTaskCreate(Task_Emergency, "Emergency", 128, NULL, 3, NULL);
    xTaskCreate(Task_UpdateThreshold, "Threshold", 128, NULL, 1, NULL);

    vTaskStartScheduler();
    while (1) {}
}

// À adapter selon le simulateur Wokwi (ou init CubeMX pour vrai projet)
void MX_GPIO_Init(void) {
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    // LED vanne
    GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    // Bouton
    GPIO_InitStruct.Pin = GPIO_PIN_3;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

void MX_ADC_Init(void) {
    __HAL_RCC_ADC_CLK_ENABLE();
    hadc.Instance = ADC1;
    hadc.Init.Resolution = ADC_RESOLUTION_12B;
    hadc.Init.ContinuousConvMode = DISABLE;
    hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;
    HAL_ADC_Init(&hadc);
}

void MX_USART_Init(void) {
    __HAL_RCC_USART2_CLK_ENABLE();
    huart.Instance = USART2;
    huart.Init.BaudRate = 9600;
    huart.Init.WordLength = UART_WORDLENGTH_8B;
    huart.Init.StopBits = UART_STOPBITS_1;
    huart.Init.Parity = UART_PARITY_NONE;
    huart.Init.Mode = UART_MODE_TX_RX;
    huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    HAL_UART_Init(&huart);
}
nucleo:PD0
nucleo:PD2
nucleo:VDD
nucleo:PA14
nucleo:PA13
nucleo:PC6
nucleo:GND.1
nucleo:PC13
nucleo:PC14
nucleo:PF0
nucleo:PF1
nucleo:PB11
nucleo:PA2
nucleo:PD1
nucleo:PD2.2
nucleo:E5V
nucleo:GND.2
nucleo:IOREF.1
nucleo:NRST.1
nucleo:3V3.1
nucleo:5V.1
nucleo:GND.3
nucleo:GND.4
nucleo:VIN.1
nucleo:PA0
nucleo:PA1
nucleo:PA4
nucleo:PB1
nucleo:PA11
nucleo:PA12
nucleo:IOREF.2
nucleo:NRST.2
nucleo:3V3.2
nucleo:5V.2
nucleo:GND.5
nucleo:GND.6
nucleo:VIN.2
nucleo:A0
nucleo:A1
nucleo:A2
nucleo:A3
nucleo:A4
nucleo:A5
nucleo:5V.3
nucleo:PA3
nucleo:PC15
nucleo:PB12.1
nucleo:PB12.2
nucleo:PB2
nucleo:GND.7
nucleo:PF3
nucleo:PA8
nucleo:PB15
nucleo:PB14
nucleo:PB13
nucleo:AGND
nucleo:PB0.1
nucleo:PD3
nucleo:PB8
nucleo:PB9
nucleo:AVDD.1
nucleo:GND.8
nucleo:PA5
nucleo:PA6
nucleo:PA7
nucleo:PB0.2
nucleo:PC7
nucleo:PA9
nucleo:PA15
nucleo:PB5
nucleo:PB4
nucleo:PB10
nucleo:PB3
nucleo:PA10
nucleo:PB6
nucleo:PB7
nucleo:D15
nucleo:D14
nucleo:AVDD.2
nucleo:GND.9
nucleo:D13
nucleo:D12
nucleo:D11
nucleo:D10
nucleo:D9
nucleo:D8
nucleo:D7
nucleo:D6
nucleo:D5
nucleo:D4
nucleo:D3
nucleo:D2
nucleo:D1
nucleo:D0
led4:A
led4:C
led3:A
led3:C
led1:A
led1:C