Pokaż plik/*
    0 - zarezerwowany
    1 - zarezerwowany
    2 - czujnik obrotów koła
    3 - czujnik obrotów silnika
    4 - stan lewego kierunkowskazu
    5 - stan świateł mijania
    6 - stan świateł drogowych
    7 - stan prawego kierunkowskazu
    8 - przycisk lewego kierunkowskazu
    9 - przycisk prawego kierunkowskazu
    10 - przycisk biegu wstecznego
    11 - sygnał PWM dla sterownika silnika
    12 - kierunek obrotów silnika (kanał A)
    13 - kierunek obrotów silnika (kanał B)

    A0 - puste
    A1 - puste
    A2 - odczyt natężenia prądu
    A3 - odczyt napięcia prądu
    A4 - potencjometr manetki do sygnału PWM
    A5 - odczyt natężenia prądu silnika (ze sterownika silnika)
*/
#pragma region defines
    #pragma region digital
        #pragma region uart
            #define pin_Rx 0
            #define pin_Tx 1
        #pragma endregion
        #pragma region interrupt_pins
            #define pin_kolo 2
            #define pin_silnik 3
        #pragma region swiatla
            #define pin_left_blinker 4
            #define pin_low_beam 5
            #define pin_traffic_lights 6
            #define pin_right_blinker 7
        #pragma endregion
        #pragma region buttons
            #define btn_left_blinker 8
            #define btn_right_blinker 9
            #define btn_reverse 10
        #pragma endregion
        #pragma region engine
            #define pin_enginePWM 11
            #define pin_inA 12
            #define pin_inB 13
        #pragma endregion
    #pragma endregion
    #pragma region analog
        #define pin_prad A2
        #define pin_napiecie A3
        #define pin_manetka A4
        #define pin_cs A5
    #pragma endregion
#pragma endregion
#pragma region includes
    #include <SoftwareSerial.h>
    #include <stdlib.h>
#pragma endregion
#pragma region variables
    volatile int obroty_kola = 0;
    volatile int obroty_silnika = 0;

    int k_lewy = 0;
    int mijania = 0;
    int drogowe = 0;
    int k_prawy = 0;
    int polozenie_manetki = 0;
    
    bool prawy = false;
    bool lewy = false;
    
    unsigned long aktualnyCzas = 0;
    unsigned long zapamietanyCzas = 0;
    unsigned long ostatniaWysylka = 0;

    float prad = 0;
    float napiecie = 0;
#pragma endregion
#pragma region setup
    void setup() {
        Serial.begin(9600);
        #pragma region OUTPUT
            pinMode(pin_enginePWM, OUTPUT);
            pinMode(pin_inA, OUTPUT);
            pinMode(pin_inB, OUTPUT);

            pinMode(pin_left_blinker, OUTPUT);
            pinMode(pin_right_blinker, OUTPUT);
        #pragma endregion
        #pragma region INPUT
            pinMode(pin_low_beam, INPUT);
            pinMode(pin_traffic_lights, INPUT);
        #pragma endregion
        #pragma region INPUT_PULLUP
            pinMode(pin_kolo, INPUT_PULLUP);
            pinMode(pin_silnik, INPUT_PULLUP);
            pinMode(btn_left_blinker, INPUT_PULLUP);
            pinMode(btn_right_blinker, INPUT_PULLUP);
            pinMode(btn_reverse, INPUT_PULLUP);
        #pragma endregion
        #pragma region interrupts
            attachInterrupt(digitalPinToInterrupt(pin_kolo), dodaj_obrot_kola, RISING);
            attachInterrupt(digitalPinToInterrupt(pin_silnik), dodaj_obrot_silnika, RISING);
        #pragma endregion

        Serial.println("Device is ready!");
    }
#pragma endregion
#pragma region loop
    void loop() {
        // Reset liczników obrotów
        obroty_kola = 0;
        obroty_silnika = 0;
        #pragma region analogRead
            polozenie_manetki = analogRead(pin_manetka);
            // pomiar pradu baterii bez dodatkowego modułu jest niewykonalny, więc odczytany będzie prąd silnika
            // prad = analogRead(pin_prad) * (5.0 / 1024.0 / 10);
            prad = analogRead(pin_cs);
            napiecie = analogRead(pin_napiecie) * (12.0 / 1024.0);
        #pragma endregion
        #pragma region wsteczny
            if (digitalRead(btn_reverse) == LOW) {
                digitalWrite(pin_inA, LOW);
                digitalWrite(pin_inB, HIGH);
            } else {
                digitalWrite(pin_inA, HIGH);
                digitalWrite(pin_inB, LOW);
            }
        #pragma endregion
        #pragma region kierunkowskazy
            if (digitalRead(btn_left_blinker) == LOW) {
                if (lewy) {
                    aktualnyCzas = millis();
                    if (aktualnyCzas - zapamietanyCzas >= 400UL) {
                        lewy = false;
                    }
                } else {
                    zapamietanyCzas = 0;
                    lewy = true;
                    prawy = false;
                }
            }
            
            if (digitalRead(btn_right_blinker) == LOW) {
                if (prawy) {
                    aktualnyCzas = millis();
                    if (aktualnyCzas - zapamietanyCzas >= 400UL) {
                        prawy = false;
                    }
                } else {
                    zapamietanyCzas = 0;
                    lewy = false;
                    prawy = true;
                }
            }
            
            if (lewy) {
                digitalWrite(pin_left_blinker, !digitalRead(pin_left_blinker));
            } else {
                digitalWrite(pin_left_blinker, LOW);
            }

            if (prawy) {
                digitalWrite(pin_right_blinker, !digitalRead(pin_right_blinker));
            } else {
                digitalWrite(pin_right_blinker, LOW);
            }
        #pragma endregion
        #pragma region obroty_kola
            analogWrite(pin_enginePWM, polozenie_manetki/2);
        #pragma endregion

        #pragma region wysyłka danych
            send_data(obroty_kola, obroty_silnika, prad, napiecie, digitalRead(pin_left_blinker), digitalRead(pin_low_beam), digitalRead(pin_traffic_lights), digitalRead(pin_right_blinker));
        #pragma endregion

    }
#pragma endregion
#pragma region functions
    void send_data(int _obroty_kola, int _obroty_silnika, float _prad, float _napiecie, int _k_lewy, int _mijania, int _drogowe, int _k_prawy) {
        // Format danych
        // ^ obroty_kola | obroty_silnika | prad | napiecie | kierunkowskaz_lewy | mijania | drogowe | kierunkowskaz_prawy $
        if (millis() - ostatniaWysylka >= 100UL) {
            ostatniaWysylka = millis();
            Serial.println("^"+String(_obroty_kola)+"|"+String(_obroty_silnika / 10)+"|"+String(_prad, 2)+"|"+String(_napiecie, 2)+"|"+String(_k_lewy)+"|"+String(_mijania)+"|"+String(_drogowe)+"|"+String(_k_prawy)+"$");
        }
    }

    #pragma region interrupt_functions
        void dodaj_obrot_kola() {
            obroty_kola++;
        }

        void dodaj_obrot_silnika() {
            obroty_silnika++;
        }
    #pragma endregion
#pragma endregion