/* Correction du TP 1 (partie 1, sans OS) -- extraits de Core/Src/main.c.
 *
 * Chaque bloc va entre les commentaires USER CODE indiques ; tout le reste de
 * main.c est celui genere par CubeMX (LED_1..LED_4 en sortie, SW1 en entree
 * sans tirage, SYS Debug = Serial Wire, horloge HSI par defaut).
 */

/* ===== USER CODE BEGIN PD ===================================================
 * Etape 6 : periode d'echantillonnage du bouton. */
#define DEBOUNCE_MS 20u
/* USER CODE END PD */

/* ===== USER CODE BEGIN PV ===================================================
 * Etape 4 : les quatre LED dans un tableau. */
typedef struct { GPIO_TypeDef *port; uint16_t pin; } led_t;

static const led_t leds[4] = {
    { LED_1_GPIO_Port, LED_1_Pin },
    { LED_2_GPIO_Port, LED_2_Pin },
    { LED_3_GPIO_Port, LED_3_Pin },
    { LED_4_GPIO_Port, LED_4_Pin },
};
/* USER CODE END PV */

/* ===== USER CODE BEGIN 0 ==================================================== */
/* N'allume que la LED d'indice i (0..3). */
static void leds_show_one(uint32_t i)
{
    for (uint32_t k = 0u; k < 4u; k++)
    {
        HAL_GPIO_WritePin(leds[k].port, leds[k].pin,
                          (k == i) ? GPIO_PIN_SET : GPIO_PIN_RESET);
    }
}

/* Etape 6 : etat stable du bouton, mis a jour toutes les DEBOUNCE_MS.
 * Renvoie 1 au front montant de l'etat stable (un appui), 0 sinon. */
static uint32_t sw1_pressed(void)
{
    static uint32_t       last_sample_ms = 0u;
    static GPIO_PinState  previous_read  = GPIO_PIN_RESET;
    static GPIO_PinState  stable         = GPIO_PIN_RESET;
    uint32_t              now            = HAL_GetTick();
    uint32_t              edge           = 0u;

    if ((now - last_sample_ms) >= DEBOUNCE_MS)
    {
        GPIO_PinState read = HAL_GPIO_ReadPin(SW1_GPIO_Port, SW1_Pin);

        last_sample_ms = now;
        /* deux lectures successives concordantes : l'etat est stable */
        if ((read == previous_read) && (read != stable))
        {
            stable = read;
            edge   = (stable == GPIO_PIN_SET) ? 1u : 0u;
        }
        previous_read = read;
    }
    return edge;
}
/* USER CODE END 0 */

/* ===== Dans while (1), USER CODE BEGIN 3 ====================================
 * Une seule des variantes ci-dessous a la fois. */

/* Etape 3 : clignotement a 2 Hz (periode 500 ms). */
#if 0
    HAL_GPIO_TogglePin(LED_1_GPIO_Port, LED_1_Pin);
    HAL_Delay(250);
#endif

/* Etape 4 : chenillard, une LED toutes les 200 ms. */
#if 0
    {
        static uint32_t i = 0u;
        leds_show_one(i);
        i = (i + 1u) % 4u;
        HAL_Delay(200);
    }
#endif

/* Etape 5 : LED_1 suit SW1. */
#if 0
    HAL_GPIO_WritePin(LED_1_GPIO_Port, LED_1_Pin,
                      HAL_GPIO_ReadPin(SW1_GPIO_Port, SW1_Pin));
#endif

/* Etape 6, premiere version : front montant SANS anti-rebond. Le chenillard
 * avance de plusieurs LED pour un appui, et pas toujours du meme nombre. */
#if 0
    {
        static GPIO_PinState previous = GPIO_PIN_RESET;
        static uint32_t      i        = 0u;
        GPIO_PinState        now      = HAL_GPIO_ReadPin(SW1_GPIO_Port, SW1_Pin);

        if ((previous == GPIO_PIN_RESET) && (now == GPIO_PIN_SET))
        {
            i = (i + 1u) % 4u;
        }
        previous = now;
        leds_show_one(i);
    }
#endif

/* Etape 6, avec anti-rebond : une LED par appui. Sans HAL_Delay, la boucle
 * reste libre pour autre chose (question 9). */
#if 1
    {
        static uint32_t i = 0u;

        if (sw1_pressed())
        {
            i = (i + 1u) % 4u;
        }
        leds_show_one(i);
    }
#endif
/* USER CODE END 3 */

/* Reponses attendues aux questions :
 *  1. 500 ms : 250 ms allumee, 250 ms eteinte (toggle toutes les 250 ms).
 *  2. La LED parait allumee en permanence, un peu moins lumineuse : 500 Hz,
 *     trop rapide pour l'oeil (persistance retinienne).
 *  3. Le code reste juste si la LED change de broche dans CubeMX ; il se lit.
 *  4. A constater sur la carte (ordre attendu : PD4, PD3, PD2, PC7).
 *  5. Toutes allumees : une LED absente ou une broche coupee se voit ; toutes
 *     eteintes : une sortie collee a l'etat haut se voit.
 *  6. La resistance de 10 kOhm est sur la carte. Sans elle, broche en l'air :
 *     lecture indeterminee (0 ou 1 au hasard, bruit).
 *  7. Plus de dix, variable d'un essai a l'autre : le rebond n'est pas
 *     reproductible.
 *  8. Le rebond dure quelques ms : 1 ms ne le filtre pas ; 500 ms rate les
 *     appuis rapides et rend le bouton paresseux.
 *  9. Comparer HAL_GetTick() a l'instant de la derniere action (voir
 *     sw1_pressed) au lieu de bloquer dans HAL_Delay.
 */
