/*********************************************************************
                    GM detector tube tester ver.3.35
    Oled display pulse counter with interrupt, can be started with a start button,
                    with a measurement time of 10 seconds.
                Created by Steve Barth BME-NTI May 2022
            https://wokwi.com/projects/349037427655967315

        RAM:   [===       ]  40.2% (used   823 bytes from  2048 bytes)
        Flash: [========  ]  85.2% (used 26162 bytes from 30720 bytes)

                            2022.11.25. used, final version

*********************************************************************/

//* declaration
#include <Arduino.h>                                   // only for VS Code
#include <Adafruit_SH110X.h>                           // oled driver library
#include <Adafruit_GFX.h>                              // GFX library
#include <SPI.h>                                       // Serial Peripheral Interface (SPI) library
#include <Wire.h>                                      // TWI/I2C library
#include <Fonts/FreeSansBold9pt7b.h>                   // use font
#include <Fonts/FreeSans9pt7b.h>                       // use font
#include <Fonts/FreeSansBoldOblique9pt7b.h>            // use font

/* Uncomment the initialize the I2C address , uncomment only one, If you get a totally blank screen try the other*/
// #define i2c_Address 0x3c            // initialize with the I2C addr 0x3C Typically eBay OLED's
// #define i2c_Address 0x3d            //initialize with the I2C addr 0x3D Typically Adafruit OLED's

// #define SCREEN_WIDTH 128            // OLED display width, in pixels
// #define SCREEN_HEIGHT 64            // OLED display height, in pixels
#define OLED_RESET -1            //   QT-PY / XIAO
Adafruit_SH1106G oled = Adafruit_SH1106G(128, 64, &Wire, OLED_RESET);

//* connected
#define v_ref 2.329            // external reference voltage LM336 2.48V,   internal v_ref=1.100V
#define sound 5                // sound output
#define start_Sw 10            // connect start switch

//* data type
long startTime;               // data type for starting time
int timerMode = 0;            // start state for timer mode

unsigned int currentTime;             // for time now
unsigned int STBYTime = 0;            // for display standby time

unsigned volatile long pulse = 0;
unsigned long new_pulse = 0;
unsigned long nowpulse = 0;

float Vbuff = 0;
float voltage = 0;

//* Void's

void voltmeter()
{
    for (int i = 0; i < 200; i++)            // read it 200 times for more stable results
    {
        Vbuff = Vbuff + analogRead(A0);            // reading buffer
        delayMicroseconds(100);                    // delay
    }
    Vbuff = Vbuff / 200;                         // average calculation
    voltage = (Vbuff * v_ref) / 1023;            // converting that reading to voltage, which is based off the reference voltage
}

void count()
{
    pulse = pulse + 1;
}

//****************************   Setup   *************************************//

void setup()
{
    //* SERIAL MONITOR & Vref SETTINGS
    Serial.begin(115200);                 // serial monitor set
    analogReference(EXTERNAL);            // external voltage reference Wokwi Reverse!
    // analogReference(INTERNAL);           // internal voltage reference 1,1V

    //* PIN SETTINGS
    pinMode(start_Sw, INPUT_PULLUP);            // start switch input pin
    pinMode(sound, OUTPUT);                     // set sound output
    pinMode(2, INPUT_PULLUP);                   // set interrupt pin

    //* INTERRUPT
    attachInterrupt(digitalPinToInterrupt(2), count, FALLING);            // 0 interrupt channel number input from GM tube pulse GPIO2  \_

    //* OLED DISPLAY SETTINGS
    delay(100);            // wait for the OLED to power up
    oled.setRotation(0);
    oled.begin(0x3c, true);            // Address 0x3C default
    oled.clearDisplay();               // Clear the buffer.

    //* SOUND MUTE
    noTone(5);            // sound off

    //* START DISPLAY
    oled.drawRoundRect(2, 0, 124, 62, 5, SH110X_WHITE);            // white frame
    oled.setTextColor(SH110X_WHITE);                               // set text color
    oled.setFont(&FreeSansBold9pt7b);                              // set font type
    oled.setTextSize(1);                                           // set font size
    oled.setCursor(12, 18);                                        // cursor position
    oled.print("GM detector");                                     // text on the display
    oled.setCursor(5, 36);                                         // cursor position
    oled.print("pulse counter");                                   // text on the display
    oled.display();                                                // display on the screen
    delay(800);                                                    // pause
    oled.setFont();                                                // set font default
    oled.setTextSize(1);                                           // set font size
    oled.setCursor(8, 46);                                         // cursor position
    oled.print("Made by Steve Barth");                             // text on the display
    oled.display();                                                // display on the screen
    delay(1400);                                                   // pause
    oled.clearDisplay();                                           // screen clear
    oled.setFont(&FreeSans9pt7b);                                  // set font type
    oled.setTextSize(1);                                           // set text size
    oled.setCursor(27, 20);                                        // cursor position
    oled.print("BME-NTI");                                         // text on the display
    oled.display();                                                // display on the screen
    delay(500);                                                    // pause
    oled.setCursor(43, 41);                                        // cursor position
    oled.print("2022");                                            // text on the display
    oled.display();                                                // display on the screen
    delay(750);                                                    // pause
    oled.setFont();                                                // set font default
    oled.setTextSize(1);                                           // set font size
    oled.setCursor(29, 50);                                        // cursor position
    oled.print("SW ver. 3.35");                                    // text on the display
    oled.display();                                                // display on the screen
    delay(1000);                                                   // pause
    oled.clearDisplay();                                           // screen clear
}

//*********************************   Loop   **********************************//

void loop()
{

    //*  STAND-BY STATE   */

    //* first page display
    if (timerMode == 0)            // if timermode "0" status
    {
        pulse = 0;                                                     // all detected pulse reset
        oled.clearDisplay();                                           // screen clear
        oled.drawRoundRect(2, 0, 124, 62, 5, SH110X_WHITE);            // create frame
        oled.setTextColor(SH110X_WHITE);                               // set text color
        oled.setFont(&FreeSansBoldOblique9pt7b);                       // set font type
        oled.setTextSize(1);                                           // set font size
        oled.setCursor(23, 18);                                        // cursor position
        oled.print("Press the");                                       // text on the display
        oled.setCursor(12, 36);                                        // cursor position
        oled.print("start button");                                    // text on the display
        oled.setFont();                                                // set font default
        oled.setTextSize(1);                                           // set font size
        oled.drawLine(7, 42, 120, 42, SH110X_WHITE);                   // create line

        //* display voltmeter on standby-state
        {
            voltmeter();
            oled.setCursor(10, 48);                           // cursor position
            oled.print("High Voltage:");                      // text on the display
            oled.setCursor(88, 48);                           // cursor position
            char string[6];                                   // string max 6 digit (0000.0)
            dtostrf(voltage * 1000, 5, 0, string);            // convert data to string (0000), dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER)
            oled.print(string);                               // screen data
            Serial.println(voltage * 1000);
            oled.print("V");            // text on the display
            oled.display();             // display on the screen
        }
    }

    //*  START TIME OF THE MEASUREMENT   *//

    //* push the start button
    if (digitalRead(start_Sw) == LOW)            // if start switch impuls (high-low-high)
    {
        tone(5, 980, 150);               // sound output 5 pin 980Hz 250ms
        delay(150);                      // pause 0,05s
        noTone(5);                       // sound off
        startTime = millis();            // starttime settings
        timerMode++;                     // increase the timermode status
    }

    //* detecting pulses
    nowpulse = pulse;
    if (nowpulse != new_pulse)
    {
        new_pulse = nowpulse;
        // delayMicroseconds(10);
    }

    //* second page display
    if (timerMode == 1)            // if timermode status 1
    {
        //* time display
        oled.clearDisplay();                                                   // screen clear
        oled.drawRoundRect(4, 1, 120, 45, 4, SH110X_WHITE);                    // create frame
        oled.setFont();                                                        // set font default
        oled.setTextSize(1);                                                   // set font size
        oled.setCursor(20, 5);                                                 // cursor position
        oled.print("THE MEASUREMENT");                                         // text on the display
        oled.setCursor(52, 16);                                                // cursor position
        oled.print("TIME:");                                                   // text on the display
        oled.setFont(&FreeSansBold9pt7b);                                      // set font type
        oled.setTextSize(1);                                                   // set font size
        oled.setCursor(30, 39);                                                // cursor position
        char stringTime[4];                                                    // string max 4 digit (00.0)
        dtostrf((millis() - startTime) / 1000.0, 4, 1, stringTime);            // convert data dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER)
        oled.print(stringTime);                                                // time on the display format 00.0 s
        Serial.println(stringTime);
        oled.setCursor(70, 39);            // cursor position
        oled.print("sec.");                // text on the display

        //* measurement time setting
        if ((millis() - startTime) >= 9999)            // stoptime max.: 10 sec
        {
            timerMode++;            // increase the timermode status
        }

        //* display counting pulse on measurement
        oled.setFont();                    // set font default
        oled.setTextSize(1);               // set font size
        oled.setCursor(15, 52);            // cursor position
        oled.print("pulse:  ");            // text on the display
        Serial.print("pulse:  ");
        Serial.println(pulse);
        oled.print(pulse);            // text on the display
        oled.display();               // display on the screen
    }

    //*   MEASUREMENT RESULT   *//

    //* third page display
    if (timerMode > 1)            // if timermode status bigger 1
    {
        //* counting pulse result
        oled.clearDisplay();                                            // screen clear
        oled.setFont(&FreeSansBold9pt7b);                               // set font type
        oled.setTextSize(1);                                            // set font size
        oled.setCursor(16, 20);                                         // cursor position 32,31
        oled.print("All counts:");                                      // text on the display
        oled.fillRoundRect(4, 30, 120, 23, 4, SH110X_WHITE);            // 4,39,120,23,4,WHITE
        oled.setTextColor(SH110X_BLACK);                                // set text color
        oled.setCursor(28, 47);                                         // cursor position
        char string[8];                                                 // max 6 digit wide string
        dtostrf((pulse), 7, 0, string);                                 // counts convering string (_//_ = 2 counts !!)
        oled.print(string);                                             // data string on the display
        //* ending signal
        tone(5, 980, 50);             // sound output 5 pin 980Hz
        delay(100);                   // pause 0,1s
        tone(5, 980, 50);             // sound output 5 pin 980Hz
        delay(100);                   // pause 0,1s
        tone(5, 980, 350);            // sound output 5 pin 980Hz
        delay(350);                   // pause 0,35s
        noTone(5);                    // sound off
        // delay(250);                                                     // pause
        Serial.print("all pulse: ");
        Serial.println(string);
        oled.display();            // display on the screen
        delay(3500);               // pause
        timerMode = 0;             // set timermode status 0
    }

    Vbuff = 0;

    //******************** End of loop ******************************
}