//******* Temp and humidity for your printer***************
// By JimBo  (Although most of it was cut up from other pieces)
//*********************************************************

//****************************************************************
//  Change what is in the quotes below to name your printer in the yellow bar
//  on the top of the screen
char Printername[15] = "Shop Printer";  //<<< this.  change this to your printer name.  
//  Keep it under 15 characters
//*****************************************************************

#include "U8glib.h"             //display library
#include <BME280_Arduino_I2C.h> //BME280 Library

#define PIN_SENSE 2 //where we connected the fan sense pin. Must be an interrupt capable pin (2 or 3 on Arduino Uno)
#define DEBOUNCE 0 //0 is fine for most fans, crappy fans may require 10 or 20 to filter out noise
#define FANSTUCK_THRESHOLD 1500 //if no interrupts were received for 500ms, consider the fan as stuck and report 0 RPM
unsigned long volatile ts1=0,ts2=0;

//Fan animation images.  This is so the fan in the bottom right coner looks like it spins
// 'fanblades3i', 24x24px (original bitmap)
const unsigned char epd_bitmap_fanblades3i [] PROGMEM = {
   0x00, 0x3e, 0x00, 0x00, 0xff, 0x00, 0x01, 0xff, 0x80, 0x01, 0xff, 0xc0, 0x03, 0xff, 0xc0, 0x03, 
   0xff, 0xc0, 0x03, 0xff, 0xc0, 0x01, 0xff, 0xc0, 0x00, 0xff, 0x80, 0x00, 0x3f, 0x80, 0x00, 0x1f, 
   0x00, 0x0f, 0x1e, 0x18, 0x3f, 0xfe, 0x7c, 0x7f, 0xff, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 
   0xff, 0xc7, 0xff, 0xff, 0xc7, 0xff, 0x7f, 0xc7, 0xff, 0x7f, 0xc7, 0xfe, 0x3f, 0xc7, 0xfe, 0x3f, 
   0xc3, 0xfc, 0x1f, 0x81, 0xf8, 0x07, 0x00, 0x70
};
// 'fanblades4i', 24x24px flipped image
const unsigned char epd_bitmap_fanblades4i [] PROGMEM = {
	0x0e, 0x00, 0xe0, 0x1f, 0x81, 0xf8, 0x3f, 0xc3, 0xfc, 0x7f, 0xe3, 0xfc, 0x7f, 0xe3, 0xfe, 0xff, 
	0xe3, 0xfe, 0xff, 0xe3, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xff, 
	0xfe, 0x3e, 0x7f, 0xfc, 0x18, 0x78, 0xf0, 0x00, 0xf8, 0x00, 0x01, 0xfc, 0x00, 0x01, 0xff, 0x00, 
	0x03, 0xff, 0x80, 0x03, 0xff, 0xc0, 0x03, 0xff, 0xc0, 0x03, 0xff, 0xc0, 0x03, 0xff, 0x80, 0x01, 
	0xff, 0x80, 0x00, 0xff, 0x00, 0x00, 0x7c, 0x00
};

bool flipVertical = false; // Flag to control vertical flip of the fan animation


BME280_Arduino_I2C bme;         //calling in the bme

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);  //defining the display

char sT[8];         //Setting up strings from floats used laer
char sH[4];
char sR[4];
double cR [10];
double avcR;
int avcount = 0;

long V;        //Variable mapped to temp 10>99
//floatVf       //float of V/100.   used to set fan speed

//configure Timer 1 (pins 9,10) to output 25kHz PWM
void setupTimer1(){
    //Set PWM frequency to about 25khz on pins 9,10 (timer 1 mode 10, no prescale, count to 320)
    TCCR1A = (1 << COM1A1) | (1 << COM1B1) | (1 << WGM11);
    TCCR1B = (1 << CS10) | (1 << WGM13);
    ICR1 = 320;
    OCR1A = 0;
    OCR1B = 0;
}

//equivalent of analogWrite on pin 9
void setPWM1A(float f){
    f=f<0?0:f>1?1:f;
    OCR1A = (uint16_t)(320*f);
}


void tachISR() {
    unsigned long m=millis();
    if((m-ts2)>DEBOUNCE){
        ts1=ts2;
        ts2=m;
    }
}

//Calculates the RPM based on the timestamps of the last 2 interrupts. Can be called at any time.
unsigned long calcRPM(){
    if(millis()-ts2<FANSTUCK_THRESHOLD&&ts2!=0){
        return (60000/(ts2-ts1))/2;
    }else return 0;
}

void setup() {
    
  Serial.begin(9600);                             //Setting up Serial for troubleshooting

  u8g.setColorIndex(1);                          //Prepping the screen
  
  pinMode(9,OUTPUT); //1A  enable outputs for Timer 1
  setupTimer1();

  if (bme.begin() == 0 ) {                        //Checking if the bme is responding
    Serial.println(F("bme initialized!"));
  }
  else Serial.println(F("bme init failed!"));     //Check your wiring if you get this.  Or make sure it's in the breadboard
 
 pinMode(PIN_SENSE,INPUT_PULLUP); //set the sense pin as input with pullup resistor
    attachInterrupt(digitalPinToInterrupt(PIN_SENSE),tachISR,FALLING); //set tachISR to be triggered when the signal on the sense pin goes low
    Serial.begin(9600); //enable serial so we can see the RPM in the serial monitor


}


void loop(void) {

  float T, H;                           //Temp and humidity.  Guess which one is which!

  BME280Data* data = bme.read();        //This is where the measurement happens
  
  if (data != nullptr) {                //If it comes back with anything other than null, it will start assiging data
    
    T = (data->temperature);            //Making T the data for temp
    H = (data->humidity);               //take a wild guess
  
      u8g.firstPage();                  //Doing the display stuff
      do {
        draw(T, H);                    //the draw function is what puts the data on your display
      } while ( u8g.nextPage() );
      u8g.firstPage();   
  }


  V =  map(T, 19, 28, 10, 99);
      if(V<19){
        V=19;
      }
      if(V>99){
        V=99;
      }

  float Vf = V;
  Vf = Vf/100.0;

  delay(100);
 
  setPWM1A(Vf);

 
long cR = calcRPM();
//avcount = 0;
//for (avcount = 0; avcount < 10; avcount++) {
//        cR[avcount] = calcRPM();
//        
//        delay(10);
//      }
//      avcR=0;
//for (avcount = 0; avcount < 10; avcount++) {
//  avcR = avcR +cR[avcount];
//}
//avcR=avcR/10;
//
//  Serial.println(avcR);
  dtostrf(cR, 4, 0, sR);
  
   flipVertical = !flipVertical;
}



void draw(float T, float H) {

  u8g.setFont(u8g_font_ncenB12r);       //Sets the font for the yellow title part of the screen
  u8g.drawStr( 0, 12, Printername);     //Writes your printer name

  dtostrf(T, 4, 1, sT);                 //Changes float T to string T
  dtostrf(H, 2, 0, sH);                 //Same for H
  //dtostrf(cR, 4, 4, sR);

  u8g.setFont(u8g_font_ncenB14r);       //Font for the C and %
  u8g.drawStr( 50, 35, "C");
  u8g.drawStr( 102, 35, "%");

  u8g.setFont(u8g_font_ncenB08r);
  u8g.drawStr( 118, 25, "R");
  u8g.drawStr( 118, 35, "H");

  u8g.setFont(u8g_font_ncenB18r);       //Font for Temp and humidity
  u8g.drawStr( 0, 35, sT);             //Displaying the Temp
  u8g.drawStr( 72, 35, sH);             //And the humidity

  if (flipVertical) {
     // Draw the bitmap with a flipped Y-coordinate (flipped vertically)
     u8g.drawBitmapP(102, 40, 3, 24, epd_bitmap_fanblades3i); // Shift it down by the height (24px)
    } else {
      u8g.drawBitmapP(102, 40, 3, 24, epd_bitmap_fanblades4i); // Normal orientation
    }
 
  u8g.drawStr( 38, 62, sR);  
  
}
