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

geiger counter nano OLED 1 sw 2 leds voltmeter v2.12
Created Steve Barth Hungary 2021.
arduino nano and 128*32 oled display
GM detector counts, CPM, Dose meter, voltmeter, Warning, Danger led's, oled display 

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

#include <Arduino.h>
#include <Wire.h>                    // wire library for I2C
#include <Adafruit_GFX.h>            // grafical library for OLED
#include <Adafruit_SSD1306.h>        // special library for SSD1306 driver
#include <SPI.h>

#include <Fonts/FreeSansBold9pt7b.h>
#include <Fonts/FreeSansBoldOblique9pt7b.h>


# define LOG_PERIOD 1000    // Logging period in milliseconds, recommended value 15000-60000.
# define MAX_PERIOD 60000   // Maximum logging period 
# define pin_Tick 2         // connecting GM pulse // GPIO2
# define RED_LED	5		      // danger led // GPIO5
# define YELLOW_LED 4		    // warning led // GPIO4
# define Tick_out 13         // Tick output // GPIO6
// todo only required for software testing, in practice it is sufficient to select the external or internal reference voltage
#define v_ref 1.1;  // external reference voltage LM4040 2.048V, internal v_ref=1.1V

// variables 

unsigned long counts;           // for GM pulse
unsigned long cpm;              // for CPM
unsigned int multiplier;        // for multiplier
unsigned long previousMillis;   // for time
float usv;                      // container for uSv calculating
int conversion_factor;          // GM tube special data

// OLED init

#define OLED_RESET 12           // GPIO13 (led control)
Adafruit_SSD1306 oled(128, 32, & Wire, OLED_RESET);

//const unsigned char radiation 32x32 bw logo1 pngtobmp32 [] =
static const unsigned char PROGMEM radiation_bmp[] =
{
0x00, 0x03, 0xC0, 0x00, 0x00, 0x3E, 0x7C, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x03, 0x80, 0x01, 0x80,
0x06, 0x00, 0x00, 0x60, 0x0C, 0x80, 0x03, 0x30, 0x1B, 0xC0, 0x03, 0x90, 0x13, 0xE0, 0x07, 0xC8,
0x27, 0xE0, 0x07, 0xEC, 0x2F, 0xF0, 0x0F, 0xF4, 0x4F, 0xF8, 0x1F, 0xF6, 0x5F, 0xF8, 0x1F, 0xFA,
0x5F, 0xF8, 0x3F, 0xFA, 0xDF, 0xF9, 0x9F, 0xFA, 0x9F, 0xF3, 0xCF, 0xFA, 0x9F, 0xF7, 0xEF, 0xFB,
0x80, 0x07, 0xE0, 0x03, 0xC0, 0x03, 0xC0, 0x02, 0x40, 0x01, 0x80, 0x02, 0x40, 0x00, 0x00, 0x02,
0x40, 0x07, 0xE0, 0x02, 0x60, 0x0F, 0xE0, 0x06, 0x20, 0x0F, 0xF0, 0x04, 0x30, 0x1F, 0xF8, 0x0C,
0x10, 0x1F, 0xF8, 0x08, 0x08, 0x3F, 0xFC, 0x10, 0x0C, 0x7F, 0xFE, 0x30, 0x06, 0x7F, 0xFE, 0x60,
0x01, 0x9F, 0xF9, 0x80, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x03, 0xC0, 0x00
};


// counting GM tube impulse

void tick()                   	
{ 
counts++;
}



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



void setup() 
{
  Serial.begin(9600);
  
  analogReference(EXTERNAL);  // external voltage reference
  //analogReference(INTERNAL);  // internal voltage reference 1,1V

  // pins settings

  pinMode(RED_LED, OUTPUT); 
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(Tick_out, OUTPUT);
  digitalWrite(Tick_out,LOW);
  pinMode(pin_Tick, INPUT_PULLUP);

	//  OLED setting 

  delay(50);             // This delay is needed to let the oled to initialize
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3D);	// OLED oled initialize 128x64 pixel, if 0x03C 128x32 pixel
  
  // basic settings

  counts = 0;                                 // counts reset
  cpm = 0;    				                      	// cpm reset
  multiplier = MAX_PERIOD / LOG_PERIOD;      	// Calculate the multiplier as a function of time
  
  attachInterrupt(0, tick, FALLING);  	      // interrupt from GM tube pulse 

  conversion_factor = 540;                    // setting GM tube conversion factor (151 ~ basic: SBM-19; LND 71917 ~ 540)

  // OLED boot screen

  /*
  oled.clearDisplay();
  oled.display();
  delay(200);
  oled.drawBitmap(0, 0, NTI_logo, 128, 32, WHITE);
  oled.display();
  delay(200);
  */
  oled.clearDisplay();
  delay(100);
  oled.setTextColor(WHITE);
  oled.setTextSize(1);
  oled.setCursor(34, 6);    // cursor position
  oled.print("GM counter");    // screen counts
  oled.display();
  delay(600); 
  oled.setCursor( 22, 21);    // cursor position
  oled.print("by Steve Barth");    // screen counts
  oled.display();
  delay(1500);
  oled.clearDisplay();
  delay(800);
  oled.setCursor( 30, 12);    // cursor position
  oled.print("sw ver:2.12");    // screen counts
  oled.display();
  delay(800);
  oled.clearDisplay();
  delay(500);
  oled.setCursor( 54, 24);    // cursor position
  oled.print("2022");    // screen counts
  oled.display();
  delay(600);
  oled.clearDisplay();
  delay(100);
  
}



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



void loop()
{

  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(RED_LED, LOW);
  
if (digitalRead(pin_Tick) == 0)            // read pin
    {
        digitalWrite(Tick_out, HIGH);                 // output state high
        oled.fillCircle(56, 15, 6, WHITE);            // draw circle in screen
        oled.fillCircle(56, 15, 3, BLACK);
        oled.display();
        delay(100);                                     // pause in millisecundum
        digitalWrite(Tick_out, LOW);                  // output state low
        oled.fillCircle(56, 15, 5, BLACK);            // clear circle in screen
        oled.fillCircle(56, 15, 3, WHITE);
        oled.fillCircle(56, 15, 2, BLACK);
        oled.fillCircle(56, 15, 1, WHITE);
        oled.display();
    }


  /* calculating oled data*/

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > LOG_PERIOD) 
 {
    previousMillis = currentMillis;
    cpm = counts * multiplier;			          // counts -> calculating CPM
    usv = float(cpm) / conversion_factor;			// cpm -> calculatig uSh


// ****************** screen display data ***************************//


// OLED display

/*
    // segment number display

    oled.setFont(&FreeSansBoldOblique9pt7b);
    oled.setCursor(0,14); // (0,25)
    oled.print("12unit");
    delay(0.1);
    oled.setFont();  
*/      


    oled.display();
    oled.clearDisplay();
    oled.setTextColor(WHITE);
    oled.setTextSize(1);
    

    // display counts data    // if log_period = 1000ms, else oled "cps"

    oled.setCursor(2, 1);    // cursor position
    oled.print("cps: ");    // screen counts
    oled.print(counts * 195);      // counts data   */
    
/*

    // display cpm data

    oled.setCursor(2, 13);      // cursor position
    oled.print("CPM:");        // screen cpm
    oled.print(cpm);			    	// cpm data   */


    // display uSv data
/*
    oled.setCursor(2, 12);		// cursor position
    oled.print(usv);         // uSv data
    oled.print("uSv/h");			// screen uSv   */

    // display counts data

    oled.setCursor(1, 12);      // cursor position
    oled.print("counts->");        // screen cpm
    //oled.print(cpm);			    	// cpm data   */



    // GM detector tube voltmeter
  
  int V_input=analogRead(0);  // measurment voltage A0 input reading
  float voltage = V_input * v_ref;  // converting that reading to voltage, which is based off the reference voltage
  voltage /= 1023 ;
  oled.setCursor(2,24);
  oled.print(voltage *1000); 
  oled.println(" V"); // print out the value you read:
  
  
/*
    //  if counts ->  normal, warning, danger range oled setting 

    // normal

    if (counts < 300)

  {
      oled.drawRoundRect(72,0,55,32,6,WHITE);
      oled.setTextSize(1);
      oled.setCursor(82,12);
      oled.print("safety");	
      delay(0.1);
  }

    //  Warning

    else if (counts < 600 && counts >= 300)
  {
      oled.drawRoundRect(72,0,55,32,6,WHITE);
      oled.setTextSize(1);
      oled.setCursor(80,12);
      oled.print("warning");
      delay(0.1);

  }
      // Danger!

    else if (counts >= 600)
  {
      oled.fillRoundRect(72,0,55,32,6,WHITE);
      oled.setTextColor(BLACK);
      oled.setTextSize(1);
      oled.setCursor(80,12);
      oled.print("DANGER!");
      delay(0.1); 
  }

  counts = 0;					        // counts reset

*/
//  if CPM -> normal, warning, danger range oled setting 

    if (cpm < 80)
  {   
    // SAFE oled
      oled.drawRoundRect(64,0,64,32,0,WHITE);
      oled.setFont(&FreeSansBold9pt7b);
      oled.setCursor(73,21);
      oled.print("SAFE");		
      delay(100);
      oled.setFont();
  }

    else if (cpm < 200 && cpm >= 80)
  {
    // WARNING oled
      oled.drawRoundRect(64,0,64,32,8,WHITE);
      oled.drawRoundRect(65,1,62,30,3,WHITE);
      oled.setFont(&FreeSansBoldOblique9pt7b);
      oled.setCursor(66,21);
      oled.print("WARN");
      digitalWrite(YELLOW_LED, HIGH);        // yellow led on	      		
      delay(250);
      oled.setFont();
  }

    else if (cpm >= 200)
  {
    // DANGER oled
      oled.fillRoundRect(72,0,49,32,20,WHITE);                    // or this rect
      oled.drawBitmap(81, 0, radiation_bmp, 32, 32, BLACK);      // and bitmap                       
      digitalWrite(RED_LED, HIGH);          // red led on	
      delay(250);
      oled.setFont();
  }

  counts = 0;					        // counts reset

  

/*

    //  if (OLED) Counts -> normal, warning, danger range oled setting 

    if (counts >= 10000)
  {
      pinMode(RED_LED) HIGH;			//danger red led on
      delay(0.1);
  }

    else if (counts < 10000 && counts >= 5000)
  {
      pinMode(YELLOW_LED) HIGH;			//warning yellow led on
        delay(0.1);
  }

      else if (counts < 5000)

  {
                pinMode(RED_LED) LOW;		//danger red led off
		pinMode(YELLOW_LED) LOW;	//warning yellow led off
  }

	 counts = 0;					// counts reset
*/

 }
}