/* Correction du TP 3 (partie 1, sans OS) -- extraits de Core/Src/main.c.
 *
 * Configuration CubeMX : PC13 = GPIO_Output (label BUZZER_ACTIF) ;
 * PB9 = TIM17_CH1, PWM Generation CH1, PSC 63, ARR 2272, Pulse 1136 ;
 * SYS Debug = Serial Wire ; horloge HSI par defaut (64 MHz, TIM17 a 64 MHz).
 */

/* ===== USER CODE BEGIN PV =================================================== */
typedef struct { uint16_t freq_hz; uint16_t duree_ms; } note_t;

/* « Au clair de la lune », premiere phrase. 0 Hz = silence. */
static const note_t melodie[] = {
    { 262, 300 }, { 262, 300 }, { 262, 300 }, { 294, 300 },
    { 330, 600 }, { 294, 600 },
    { 262, 300 }, { 330, 300 }, { 294, 300 }, { 294, 300 },
    { 262, 900 }, {   0, 600 },
};
/* USER CODE END PV */

/* ===== USER CODE BEGIN 0 ==================================================== */
/* Compteur a 1 MHz (PSC 63) : ARR = 1e6 / f - 1, CCR = (ARR + 1) / 2. */
static void note(uint32_t f)
{
    uint32_t arr = (1000000u / f) - 1u;

    __HAL_TIM_SET_AUTORELOAD(&htim17, arr);
    __HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, (arr + 1u) / 2u);
}

static void silence(void)
{
    __HAL_TIM_SET_COMPARE(&htim17, TIM_CHANNEL_1, 0u);
}

static void bip(uint32_t on_ms, uint32_t off_ms)
{
    HAL_GPIO_WritePin(BUZZER_ACTIF_GPIO_Port, BUZZER_ACTIF_Pin, GPIO_PIN_SET);
    HAL_Delay(on_ms);
    HAL_GPIO_WritePin(BUZZER_ACTIF_GPIO_Port, BUZZER_ACTIF_Pin, GPIO_PIN_RESET);
    HAL_Delay(off_ms);
}
/* USER CODE END 0 */

/* ===== USER CODE BEGIN 2 ====================================================
    HAL_TIM_PWM_Start(&htim17, TIM_CHANNEL_1);
   USER CODE END 2 */

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

/* Etape 1 : trois bips, une pause. */
#if 0
    bip(100, 100); bip(100, 100); bip(100, 100);
    HAL_Delay(1000);
#endif

/* Question 2 : SOS. Un long = trois courts (convention du morse). */
#if 0
    for (uint32_t k = 0u; k < 3u; k++) { bip(100, 100); }
    for (uint32_t k = 0u; k < 3u; k++) { bip(300, 100); }
    for (uint32_t k = 0u; k < 3u; k++) { bip(100, 100); }
    HAL_Delay(1000);
#endif

/* Etape 3 : la gamme, une note toutes les 300 ms. */
#if 0
    {
        static const uint16_t gamme[8] = { 262, 294, 330, 349, 392, 440, 494, 523 };

        for (uint32_t k = 0u; k < 8u; k++)
        {
            note(gamme[k]);
            HAL_Delay(300);
        }
        silence();
        HAL_Delay(1000);
    }
#endif

/* Etape 4 : la melodie, 25 ms de silence entre deux notes. */
#if 1
    for (uint32_t k = 0u; k < (sizeof(melodie) / sizeof(melodie[0])); k++)
    {
        if (melodie[k].freq_hz == 0u) { silence(); }
        else                          { note(melodie[k].freq_hz); }
        HAL_Delay(melodie[k].duree_ms - 25u);
        silence();
        HAL_Delay(25);
    }
#endif
/* USER CODE END 3 */

/* Reponses attendues aux questions :
 *  1. Non : son oscillateur est interne, la broche ne fait que l'alimenter.
 *  2. Voir la variante SOS ; long = 3 x court en morse.
 *  3. 64 MHz / (63 + 1) = 1 MHz ; 1 MHz / (2272 + 1) = 439,96 Hz.
 *  4. Compteur 16 bits : ARR max 65535 -> 1 MHz / 65536 = 15,3 Hz au plus
 *     bas ; au plus haut, ARR = 1 -> 500 kHz (bien au-dela de l'audible et de
 *     ce que reproduit la membrane).
 */
