/*
    parking access is demo application born to show a state 
    machine implementation.
   
        Copyright (C) 2022 Maurilio Pizzurro 
        
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 1, or (at your option)
   any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/


/* 
    Parking access application
    Pulsante verde per simulare la barriera IR
    https://www.adafruit.com/product/2168
    https://www.adafruit.com/product/2167

    IR Break Beam Sensor with Premium Wire Header Ends - 5mm LEDs
*/

#include <IRremote.h>
#include <LiquidCrystal.h>
#include <Servo.h>

#define PIN_RECEIVER 2   // Signal Pin of IR receiver

IRrecv receiver(PIN_RECEIVER);
Servo RCservo;

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

/* SERVO_UP servo in posizione verticale */
#define SERVO_UP      180
/* SERVO_UP servo in posizione orizzontale */
#define SERVO_DOWN    90

/* PIN_IR_BARRIER contatto pulito relay IR RX */
const byte PIN_IR_BARRIER   = 4;

// g_state è la variabile di stato
uint8_t   g_state       = 0;
uint32_t  g_saveMillis  = 0;
uint8_t   g_servoPos    = SERVO_DOWN;

/* S_XXX stati della macchina a stati g_state */
#define S_START         0
#define S_INOPENING     1
#define S_ISUP          2
#define S_INCLOSING     3

#define IRCMD_PLAY  168

void setup() {
    Serial.begin(115200);
    pinMode(PIN_IR_BARRIER, INPUT_PULLUP);
    
    receiver.enableIRIn(); // Start the receiver

    lcd.begin(16, 2);

    lcd.print("Press play");
    
    RCservo.attach(5);
    RCservo.write(g_servoPos);
}


void loop() {

    uint8_t command = 0;

    if (receiver.decode()) {
        command = receiver.decodedIRData.command;
        receiver.resume();  // Receive the next value
    }

    switch (g_state) {
        
        case S_START:
            if (command == IRCMD_PLAY) {
                /* CHANGE STATE */
                g_state = S_INOPENING;     
            }      
            break;

        case S_INOPENING:
            
            if (millis() - g_saveMillis > 35) {
                g_saveMillis = millis();
                
                if (g_servoPos <= SERVO_UP) {
                    g_servoPos++;
                    RCservo.write(g_servoPos);
                } 
                if (g_servoPos == SERVO_UP) {
                    /* CHANGE STATE */
                    g_state = S_ISUP;
                    g_saveMillis = millis();
                }
                
            }
            break;

        case S_ISUP:
            if (millis() - g_saveMillis > 2000) {
                /* CHANGE STATE */
                g_state = S_INCLOSING;
            }
            /* CHECK IR BARRIER */
            if (digitalRead(PIN_IR_BARRIER) == LOW) {
                /* RESTART TIMER */
                g_saveMillis = millis();
            }
            break;

        case S_INCLOSING:
            if (millis() - g_saveMillis > 50) {
                g_saveMillis = millis();
                  
                if (g_servoPos >= SERVO_DOWN) {
                    g_servoPos--;
                    RCservo.write(g_servoPos);
                } 
                if (g_servoPos == SERVO_DOWN) {
                    /* CHANGE STATE */
                    g_state = S_START;
                }
            }
            /* CHECK IR BARRIER */
            if (digitalRead(PIN_IR_BARRIER) == LOW) {
                /* CHANGE STATE */
                g_state = S_INOPENING;
            }
            break;
    } // end switch
} // end loop()

nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
lcd:VSS
lcd:VDD
lcd:V0
lcd:RS
lcd:RW
lcd:E
lcd:D0
lcd:D1
lcd:D2
lcd:D3
lcd:D4
lcd:D5
lcd:D6
lcd:D7
lcd:A
lcd:K
r1:1
r1:2
ir:GND
ir:VCC
ir:DAT
servo1:GND
servo1:V+
servo1:PWM
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r