/*********************************************************************
This is a library for our Monochrome OLEDs based on SSD1305 drivers
Adafruit 128x64 Product ID 2720
Arduino MKR1000
  Pick one up today in the adafruit shop!
  ------> https://www.adafruit.com/products/2675

These displays use SPI or I2C to communicate, 3-5 pins are required to  
interface

Adafruit invests time and resources providing this open source code, 
please support Adafruit and open-source hardware by purchasing 
products from Adafruit!

Written by Limor Fried/Ladyada  for Adafruit Industries.  
BSD license, check license.txt for more information
All text above, and the splash screen below must be included in any redistribution
*********************************************************************/

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1305.h>
#include "7_seg_64.h"
#include "7_seg_64_inv.h"

#include <Adafruit_GPS.h>

#define DAY_SW 2 // day/night switch // pin D2 to GND

// Used for software or hardware SPI
#define OLED_CS 4
#define OLED_DC 3

// Used for I2C or SPI
#define OLED_RESET 5

// hardware SPI - use 7Mhz (7000000UL) or lower because the screen is rated for 4MHz, or it will remain blank!
Adafruit_SSD1305 display(128, 64, &SPI, OLED_DC, OLED_RESET, OLED_CS, 7000000UL);

// what's the name of the hardware serial port?
#define GPSSerial Serial1

// Connect to the GPS on the hardware port
Adafruit_GPS GPS(&GPSSerial);

// Set GPSECHO to 'false' to turn off echoing the GPS data to the Serial console
// Set to 'true' if you want to debug and listen to the raw GPS sentences
#define GPSECHO false

uint32_t timer = millis();
int gpsMph = 0;
int mphX1 = 0;
int mphX10 = 0;
int mphX100 = 0;
int gpsDir = 0; // compass heading every 45 degrees
int dirCP = 0; // compass point

bool nightMode = 0;


void setup()   {                
  Serial.begin(115200);
  //while (! Serial) delay(1000);
  Serial.println("SSD1305 OLED test");
  Serial.println("Adafruit GPS library basic test!");
  
  if ( ! display.begin(0x3C) ) {
     Serial.println("Unable to initialize OLED");
     while (1) yield();
  }

   // 9600 NMEA is the default baud rate for Adafruit MTK GPS's- some use 4800
  GPS.begin(9600);
  // uncomment this line to turn on RMC (recommended minimum) and GGA (fix data) including altitude
  GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
  // uncomment this line to turn on only the "minimum recommended" data
  //GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
  // For parsing data, we don't suggest using anything but either RMC only or RMC+GGA since
  // the parser doesn't care about other sentences at this time
  // Set the update rate
  GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
  // For the parsing code to work nicely and have time to sort thru the data, and
  // print it out we don't suggest using anything higher than 1 Hz

  // Request updates on antenna status, comment out to keep quiet
//  GPS.sendCommand(PGCMD_ANTENNA);

  delay(1000);

  // Ask for firmware version
  GPSSerial.println(PMTK_Q_RELEASE);
   

  display.setRotation(0);
  
  // miniature bitmap display
  display.clearDisplay();
  
  //display.drawBitmap(15, 0,  LEK_bmp_inv_1a_64, 15, 64, 1);
  //display.drawBitmap(30, 0,  LEK_bmp_inv_8_64, 42, 64, 1);
  //display.drawBitmap(72, 0,  LEK_bmp_inv_8_64, 42, 64, 1);
  
  display.display();

  
  pinMode(DAY_SW, INPUT_PULLUP); // digital HIGH with switch open 

}

void loop() // run over and over again
{
  nightMode = digitalRead(DAY_SW); 
  //Serial.print("Night Mode = ");
  //Serial.println(nightMode);
  
  // read data from the GPS in the 'main loop'
  char c = GPS.read();
  // if you want to debug, this is a good time to do it!
  if (GPSECHO)
    if (c) Serial.print(c);
  // if a sentence is received, we can check the checksum, parse it...
  if (GPS.newNMEAreceived()) {
    // a tricky thing here is if we print the NMEA sentence, or data
    // we end up not listening and catching other sentences!
    // so be very wary if using OUTPUT_ALLDATA and trying to print out data
    Serial.println(GPS.lastNMEA()); // this also sets the newNMEAreceived() flag to false
    if (!GPS.parse(GPS.lastNMEA())) // this also sets the newNMEAreceived() flag to false
      return; // we can fail to parse a sentence in which case we should just wait for another
  }
  // if millis() or timer wraps around, we'll just reset it
  if (timer > millis()) timer = millis();

  // approximately every 2 seconds or so, print out the current stats
  if (millis() - timer > 2000) {
    timer = millis(); // reset the timer
    Serial.print("\nTime: ");
    if (GPS.hour < 10) { Serial.print('0'); }
    Serial.print(GPS.hour, DEC); Serial.print(':');
    if (GPS.minute < 10) { Serial.print('0'); }
    Serial.print(GPS.minute, DEC); Serial.print(':');
    if (GPS.seconds < 10) { Serial.print('0'); }
    Serial.print(GPS.seconds, DEC); Serial.print('.');
    if (GPS.milliseconds < 10) {
      Serial.print("00");
    } else if (GPS.milliseconds > 9 && GPS.milliseconds < 100) {
      Serial.print("0");
    }
    Serial.println(GPS.milliseconds);
    Serial.print("Date: ");
    Serial.print(GPS.day, DEC); Serial.print('/');
    Serial.print(GPS.month, DEC); Serial.print("/20");
    Serial.println(GPS.year, DEC);
    Serial.print("Fix: "); Serial.print((int)GPS.fix);
    Serial.print(" quality: "); Serial.println((int)GPS.fixquality);
       
    //if (GPS.fix) {
      Serial.print("Location: ");
      Serial.print(GPS.latitude, 4); Serial.print(GPS.lat);
      Serial.print(", ");
      Serial.print(GPS.longitude, 4); Serial.println(GPS.lon);
      Serial.print("Speed (knots): "); Serial.println(GPS.speed);
      gpsMph = int(GPS.speed * 1.15078); //knots to mph  //// knots * 1.15078
      //gpsMph = 100; //for testing
      Serial.print("Speed (mph): "); Serial.println(gpsMph);
      Serial.print("Angle: "); Serial.println(GPS.angle);
      gpsDir = int(GPS.angle);
      //gpsDir = 315; // for testing
      dirCP = round(gpsDir / 45);
      
      Serial.print("Altitude: "); Serial.println(GPS.altitude);
      Serial.print("Satellites: "); Serial.println((int)GPS.satellites);
      
      displayMPH();
      
   // }
  }
}

void displayMPH()
{
  
    display.clearDisplay();
    display.setRotation(0);
    display.setTextSize(1);
    display.fillScreen(BLACK);
    display.setTextColor(WHITE);
    
    
    if (gpsMph >= 100 && nightMode == 1) {
        display.drawBitmap(15, 0,  LEK_bmp_inv_1a_64, 15, 64, 1);
    }
    if (gpsMph >= 100 && nightMode == 0) {
          display.drawBitmap(15, 0,  LEK_bmp_1a_64, 15, 64, 1);  
          
     }
     
     mphX10 = int(gpsMph / 10);
     Serial.print("mphX10: "); Serial.println(mphX10);
     mphX1 = int(gpsMph - (mphX10 * 10));
     Serial.print("mphX1: "); Serial.println(mphX1);

      const uint8_t* bmpX1;
      const uint8_t* bmpX10;

  switch (mphX10){

    case 0:
      bmpX10 = LEK_bmp_inv_0_64; //night display
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_0_64; //day display
      }
      break;
    case 1:
      bmpX10 = LEK_bmp_inv_1_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_1_64;
      }
      break;
    case 2:
      bmpX10 = LEK_bmp_inv_2_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_2_64;
      }
      break;
    case 3:
      bmpX10 = LEK_bmp_inv_3_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_3_64;
      }
      break;
    case 4:
      bmpX10 = LEK_bmp_inv_4_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_4_64;
      }
      break;
    case 5:
      bmpX10 = LEK_bmp_inv_5_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_5_64;
      }
      break;
    case 6:
      bmpX10 = LEK_bmp_inv_6_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_6_64;
      }
      break;
    case 7:
      bmpX10 = LEK_bmp_inv_7_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_7_64;
      }
      break;
    case 8:
      bmpX10 = LEK_bmp_inv_8_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_8_64;
      }
      break;
    case 9:
      bmpX10 = LEK_bmp_inv_9_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_9_64;
      }
      break;
    case 10:
      bmpX10 = LEK_bmp_inv_0_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_0_64;
      }
      break;
    case 11:
      bmpX10 = LEK_bmp_inv_1_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_1_64;
      }
      break;
    case 12:
      bmpX10 = LEK_bmp_inv_2_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_2_64;
      }
      break;
    case 13:
      bmpX10 = LEK_bmp_inv_3_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_3_64;
      }
      break;
    case 14:
      bmpX10 = LEK_bmp_inv_4_64;
     if (nightMode == 0) {
        bmpX10 = LEK_bmp_4_64;
      } 
      break;
    case 15:
      bmpX10 = LEK_bmp_inv_5_64;
      if (nightMode == 0) {
        bmpX10 = LEK_bmp_5_64;
      }
      break;

   }

   switch (mphX1){

    case 0:
      bmpX1 = LEK_bmp_inv_0_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_0_64;
      }
      break;
    case 1:
      bmpX1 = LEK_bmp_inv_1_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_1_64;
      }
      break;
    case 2:
      bmpX1 = LEK_bmp_inv_2_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_2_64;
      }
      break;
    case 3:
      bmpX1 = LEK_bmp_inv_3_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_3_64;
      }
      break;
    case 4:
      bmpX1 = LEK_bmp_inv_4_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_4_64;
      }
      break;
    case 5:
      bmpX1 = LEK_bmp_inv_5_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_5_64;
      }
      break;
    case 6:
      bmpX1 = LEK_bmp_inv_6_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_6_64;
      }
      break;
    case 7:
      bmpX1 = LEK_bmp_inv_7_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_7_64;
      }
      break;
    case 8:
      bmpX1 = LEK_bmp_inv_8_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_8_64;
      }
      break;
    case 9:
      bmpX1 = LEK_bmp_inv_9_64;
      if (nightMode == 0) {
        bmpX1 = LEK_bmp_9_64;
      }
      break;

   }

   //dirCP = 8; //for testing

   switch (dirCP){

    case 0:
      display.setCursor(120,0);
      display.print("N");
      break;
    case 1:
      display.setCursor(120,0);
      display.print("N");
      display.setCursor(120,15);
      display.print("E");
      break;
    case 2:
      display.setCursor(120,15);
      display.print("E");
      break;
    case 3:
      display.setCursor(120,30);
      display.print("S");
      display.setCursor(120,15);
      display.print("E");
      break;
    case 4:
      display.setCursor(120,30);
      display.print("S");
      break;
    case 5:
      display.setCursor(120,30);
      display.print("S");
      display.setCursor(120,45);
      display.print("W");
      break;
    case 6:
      display.setCursor(120,45);
      display.print("W");
      break;
    case 7:
      display.setCursor(120,00);
      display.print("N");
      display.setCursor(120,45);
      display.print("W");
      break;
    case 8:
      display.setCursor(120,00);
      display.print("N");
      break;
   }


    display.drawBitmap(72, 0,  bmpX1, 42, 64, 1);
    display.drawBitmap(30, 0,  bmpX10, 42, 64, 1);
    display.setCursor(0,55);
    display.print(int(GPS.satellites));
    Serial.println(int(GPS.satellites));
    //display.setCursor(110,55);
    //display.print(int(GPS.angle));
    Serial.println(int(GPS.angle));
    
    display.display();
      
}
