// Corrigé perçeuse avec arrêt d'urgence
//
// EPFL, Microinformatique pour GM, 2021, Pierre-Yves Rochat, pyr@pyr.ch

#include <msp430.h>
#include <stdint.h>

// *****************************************************************
// Vous n'avez pas besoin de comprendre cette partie :
// ce sera le sujet de la suite du semestre !
// Votre procédure loop() pourra simplement utiliser
// les définitions suivantes, pour utiliser les LED et les poussoirs.

#define Pous1On (!(P1IN & (1<<7)))
#define Pous2On (!(P2IN & (1<<2)))
#define Pous3On (!(P4IN & (1<<5)))

#define LedRougeOn P1OUT |= (1<<0)
#define LedRougeOff P1OUT &=~(1<<0)
#define LedOrangeOn P8OUT |= (1<<1)
#define LedOrangeOff P8OUT &=~(1<<1)
#define LedVerteOn P8OUT |= (1<<2)
#define LedVerteOff P8OUT &=~(1<<2)

void loop(); // prototype
void setup();

void delay(uint32_t duree) { // attente en milliseconde
    volatile uint16_t i;
    while(duree-- >0) {
        for (i=113; i>0; i--){ // attente active
        }
    }
}

void Test3Pous() {
    if (Pous1On) { LedVerteOn; } else { LedVerteOff; }
    if (Pous2On) { LedOrangeOn; } else { LedOrangeOff; }
    if (Pous3On) { LedRougeOn; } else { LedRougeOff; }
}

int main(void) {
    WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer
    P8SEL = 0;
    P1DIR |= (1<<0); P1OUT &=~(1<<0); // LED rouge en sortie, mise à 0
    P8DIR |= (1<<1); P8OUT &=~(1<<1); // LED orange
    P8DIR |= (1<<2); P8OUT &=~(1<<2); // LED verte
    P1OUT |= (1<<7); P1REN |= (1<<7); // Poussoir S1 en entrée avec pull-up
    P2OUT |= (1<<2); P2REN |= (1<<2); // Poussoir S2
    P4OUT |= (1<<5); P4REN |= (1<<5); // Poussoir ajouté

    setup();
    while(1) {
        loop();
    }
}
// Fin de la partie que vous n'avez pas besoin de comprendre !
// *****************************************************************

#define Start Pous3On
#define Haut Pous2On
#define Bas Pous1On

enum {Arret, DescenteAttRel, Descente, MonteeAttRel, Montee, UrgenceAttRel, Urgence };

uint16_t etat;

void setup() {
    etat = Arret;
}

void loop() {
    switch (etat) {
    case Arret : LedRougeOff; LedVerteOff; LedOrangeOff;
        if (Start) { etat = DescenteAttRel; }
        break;
    case DescenteAttRel : LedRougeOn; LedVerteOff; // Descente, Attente Start relâché
        if (!Start) { etat = Descente; }
        if (Bas) { etat = Montee; }
        break;
    case Descente : LedRougeOn; LedVerteOff; // Descente, Start comme bouton d'urgence
        if (Start) { etat = UrgenceAttRel; }
        if (Bas) { etat = MonteeAttRel; }
        break;
    case MonteeAttRel : LedRougeOff; LedVerteOn;
    if (!Start) { etat = Montee; }
        if (Haut) { etat = Arret; }
        break;
    case Montee : LedRougeOff; LedVerteOn;
        if (Start) { etat = UrgenceAttRel; }
        if (Haut) { etat = Arret; }
    break;
    case UrgenceAttRel : LedRougeOff; LedVerteOff; LedOrangeOn; // Montre l'urgence
        if (!Start) { etat = Urgence; }
        break;
    case Urgence : LedRougeOff; LedVerteOff; LedOrangeOn;
        if (Start) { etat = MonteeAttRel; }
        break;
    }
    delay(20); // suppression des rebonds
}

