# include <Wire.h>

# include <Adafruit_GFX.h>
# include <Adafruit_SSD1306.h>

// #include <LiquidCrystal_I2C.h> 		//从库管理器添加1602I2C库

# include <SPI.h>

# define LOG_PERIOD 1000    //Logging period in milliseconds, recommended value 15000-60000.
# define MAX_PERIOD 60000   //Maximum logging period 
 
 # define RED_LED	5		      // danger led
 # define YELLOW_LED 4		  // warning led
// # define Foot_SW 3		  //foot switch interrupt for reset counts
# define pin_Tick 2

unsigned long counts;           // GM 变量
unsigned long cpm;              // CPM 变量
unsigned int multiplier;        //设置换算变量
unsigned long previousMillis;   //测量时间
int conversion_factor;

float usv;

// LiquidCrystal_I2C lcd(0x27, 16, 2); 	//设置LCD地址为 0x27 (1602显示器)

#define OLED_RESET 13
Adafruit_SSD1306 display(128, 32, & Wire, OLED_RESET);


void tick()      	// GM tube impulse
{ 
  counts++;
}

//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
};

static const unsigned char PROGMEM NTI [] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x2D, 0xFF, 0xFF, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x11, 0x8F, 0x3C, 0xE6, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xA7, 0x3E, 0xDB, 0x7B, 0x40, 0x00, 0x00, 0xFF, 0xF8, 0x3E, 0x00, 0xF8, 0xFF, 0xF8,
0x00, 0x01, 0xEF, 0x7F, 0xFF, 0xBF, 0xE0, 0x00, 0x00, 0x30, 0x1C, 0x0F, 0x00, 0xE0, 0x30, 0x1C,
0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x30, 0x0E, 0x0F, 0x01, 0xE0, 0x30, 0x04,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x30, 0x0E, 0x0B, 0x81, 0x60, 0x30, 0x44,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x30, 0x0C, 0x0D, 0x83, 0x60, 0x30, 0xC0,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x30, 0x38, 0x0D, 0xC2, 0x60, 0x30, 0xC0,
0x00, 0x2F, 0x7F, 0xFF, 0xFF, 0xFF, 0xBA, 0x00, 0x00, 0x3F, 0xF8, 0x0C, 0xC6, 0x60, 0x3F, 0xC0,
0x00, 0x2D, 0x3F, 0xFF, 0xFF, 0xFF, 0x6D, 0x00, 0x00, 0x30, 0x0C, 0x0C, 0xC4, 0x60, 0x30, 0xC0,
0x00, 0x7B, 0xB8, 0x7E, 0x3F, 0x87, 0x77, 0x80, 0x00, 0x30, 0x06, 0x0C, 0x6C, 0x60, 0x30, 0x40,
0x00, 0x77, 0xE0, 0x3C, 0x0F, 0x03, 0xFB, 0x80, 0x00, 0x30, 0x06, 0x0C, 0x6C, 0x60, 0x30, 0x02,
0x00, 0x3F, 0xF0, 0x38, 0x06, 0x03, 0xFB, 0x00, 0x00, 0x30, 0x0E, 0x0C, 0x78, 0x60, 0x30, 0x06,
0x01, 0x1F, 0xFF, 0x10, 0x06, 0x3F, 0xFE, 0x00, 0x00, 0x30, 0x1E, 0x0C, 0x38, 0x60, 0x30, 0x1C,
0x5E, 0x07, 0xBF, 0xFF, 0xFF, 0xFF, 0xF8, 0x0C, 0x00, 0xFF, 0xF8, 0x3E, 0x31, 0xF8, 0xFF, 0xFC,
0x60, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x0C, 0x07, 0xFF, 0xFF, 0xF8, 0x18, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1C, 0x09, 0x80, 0x00, 0x00, 0x00, 0x06, 0x0E, 0x00, 0x00, 0x08, 0x04, 0x08, 0x00, 0x00, 0x00,
0x0F, 0x02, 0x00, 0xC0, 0x00, 0x20, 0x00, 0x3C, 0x00, 0x82, 0x6A, 0x45, 0xAD, 0x92, 0x12, 0xD5,
0x03, 0xE0, 0x00, 0x80, 0x00, 0xD0, 0x01, 0xF0, 0x00, 0x4A, 0x42, 0xA5, 0x00, 0x16, 0x12, 0x88,
0x00, 0xFE, 0x01, 0x80, 0x01, 0x08, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};



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


void setup() 
{
  Serial.begin(9600);

    // pins settings

    pinMode(RED_LED, OUTPUT); 
    pinMode(YELLOW_LED, OUTPUT);
//  pinMode(Foot_SW, INPUT_PULLUP);
    pinMode(pin_Tick, INPUT_PULLUP);

		//  OLED setting 

  delay(400);  // This delay is needed to let the display to initialize
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);	// OLED display initialize

  
    // basic settings

  counts = 0;
  cpm = 0;    				                      	//计数
  multiplier = MAX_PERIOD / LOG_PERIOD;      	//计算乘数,取决于周期
  
  attachInterrupt(0, tick, FALLING);  	      //中断为下降沿触发

  conversion_factor = 151;                    // setting GM tube conversion factor

      // OLED boot screen

    display.display();
    display.clearDisplay();
    display.drawBitmap(0, 0, NTI, 128, 32, WHITE);
    delay(1500);



/*		// LCD boot animation

  lcd.init();                     
  lcd.backlight();
  lcd.setCursor(5, 0);
  lcd.print("Boot..."); 
  lcd.setCursor(0, 1);
  for(int i=0;i<16;i++)
  {
  lcd.write(0xff);
  delay(250);
  }

*/

}


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


void loop()
{

  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(RED_LED, LOW);

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > LOG_PERIOD) 
 {
    previousMillis = currentMillis;
    cpm = counts * multiplier;			//得出技术次数
    usv = float(cpm) / conversion_factor;			//带入公式计算出辐射强度

/*      //  1602 LCD display

    lcd.clear();
    lcd.print("CPM=");
    lcd.print(cpm);				//输出cpm值
    lcd.setCursor(0, 1);			//第二行
    lcd.print(usv);
    lcd.print(" uSv/h");			//输出强度值
    counts = 0;					// only uSv range display 复位

*/
    display.display();
    display.clearDisplay();
    display.drawRoundRect(72,0,55,32,3,WHITE);
    display.setTextColor(WHITE);
    display.setTextSize(1);

    display.setCursor(1, 1);
    display.print("count:");
    display.print(counts);

    display.setCursor(1, 13);
    display.print("CPM:");
    display.print(cpm);				//输出cpm值

    display.setCursor(1, 24);			//第二行
    display.print(usv);
    display.print("uSv/h");			//输出强度值
//    counts = 0;					// only uSv range display 复位

/*
		    //  (uSv, LCD) normal, warning, danger range display setting 

    if (usv >= 10)
  {
      lcd.setCursor(9, 0);
      lcd.print("Danger!");//如果辐射大于10则显示危险
      delay(0.1);
  }

    else if (usv < 10 && usv >= 0.52)
  {
        lcd.setCursor(10, 0);
        lcd.print("Unsafe");//在0.52-10这个范围显示不安全
        delay(0.1);
  }

      else if (usv < 0.52)

  {
          lcd.setCursor(10, 0);
          lcd.print("Safety");//在这个值以下显示安全
          delay(0.1);
  }

*/

/*
      //  (counts, OLED) normal, warning, danger range display setting 

    if (counts >= 600)
  {
     // display.invertDisplay(true);
         display.fillRoundRect(72,0,55,32,6,WHITE);
         display.setTextColor(BLACK);
      display.setTextSize(1);
      display.setCursor(80,12);
      display.print("DANGER!");		//如果辐射大于10则显示危险
      delay(0.1);
      
  }

    else if (counts < 600 && counts >= 300)
  {
    //display.invertDisplay(false);
        display.drawRoundRect(72,0,55,32,6,WHITE);
      display.setTextSize(1);
      display.setCursor(80,12);
      display.print("warning");		//如果辐射大于10则显示危险
      delay(0.1);

  }

      else if (counts < 300)

  {
    //display.invertDisplay(false);
        display.drawRoundRect(72,0,55,32,6,WHITE);
      display.setTextSize(1);
      display.setCursor(82,12);
      display.print("safety");		//如果辐射大于10则显示危险
      delay(0.1);
  }
	counts = 0;					// only OLED range display 复位

*/
     //  (CPM, OLED) normal, warning, danger range display setting 

    if (cpm >= 400)
  {
      //display.fillRoundRect(72,0,55,32,6,WHITE);
      display.drawBitmap(83, 0, radiation_bmp, 32, 32, WHITE);
      //display.setTextColor(BLACK);
      //display.setTextSize(1);
      //display.setCursor(80,12);
      //display.print("DANGER!");	
      digitalWrite(RED_LED, HIGH);	
      delay(100);
  }

    else if (cpm < 400 && cpm >= 200)
  {
    
      //display.drawRoundRect(72,0,55,32,6,WHITE);
      display.setTextSize(1);
      display.setCursor(80,12);
      digitalWrite(YELLOW_LED, HIGH);
      display.print("warning");		
      delay(100);
  }

      else if (cpm < 200)
  {   
      //display.drawRoundRect(72,0,55,32,6,WHITE);
      display.setTextSize(1);
      display.setCursor(82,12);
      display.print("safety");		
      //delay(0.1);
  }
	counts = 0;					// only OLED range display

  

/*

      //  (counts, led) normal, warning, danger display 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;					// only led range display 复位
*/

 }
}