// Frequency Standard firmware version 1.0
// Public domain software by SP
#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 8, 7, 6, 5);

#include <TinyGPS++.h>
TinyGPSPlus gps;

// constants for buttons and MUX adr.
const int UPBUTT = 12;     // Button UP
const int DWNBUTT = 13;     // Button DOWN
const int MUXA = 9;     // MUX adr. A
const int MUXB = 10;     // MUX adr. B
const int MUXC = 11;     // MUX adr. C

// NEO7M module comands
byte GPSdata1[]={0xB5,0x62,0x06,0x16,0x08,0,0,0x03,0x03,0,0xD1,0xA2,0x06,0,0xA3,0xE7};  // SBAS -16
byte GPSdata2[]={0xB5,0x62,0x06,0x1D,0x1C,0,0x01,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x80,0x51,0x01,0,0x01,0,0,0,0x13,0xE8};  // TMODE -36
byte GPSdata3[]={0xB5,0x62,0x06,0x31,0x20,0,0,0x01,0,0,0,0,0,0,0x01,0,0,0,0x40,0x42,0x0F,0,0,0,0,0x80,0,0,0,0x80,0,0,0,0,0x2F,0,0,0,0x19,0xB2}; // TP5 -40
// Variables for frequency setting
int lastButtUp = 1;
int lastButtDown = 1;
int nMuxPos = 3;
int nMiliSec = 0;
int ModeCnt = 0;
boolean ModeFS = false;  // Mode of device (true == Service mode INT)

void setup() {
  // initialize pin 6,7,8 as an output for MUX:
  pinMode(MUXA, OUTPUT);
  pinMode(MUXB, OUTPUT);
  pinMode(MUXC, OUTPUT);
  digitalWrite(MUXA, LOW);  digitalWrite(MUXB, LOW);  digitalWrite(MUXC, HIGH);
  // initialize the pushbutton pins as an input:
  pinMode(UPBUTT, INPUT);
  pinMode(DWNBUTT, INPUT);
  // initialize the relay pin:
  pinMode(A1, OUTPUT);
  digitalWrite(A1, LOW);
 
// Setup serial port and start display
  Serial.begin(9600);
  lcd.begin(8, 2);
  lcd.print("GPS freq");
  lcd.setCursor(0,1);
  lcd.print(" normal");
  // Setup NEO7M module
  delay (4000);
  Serial.write(GPSdata1,16);
  delay (1000);
  Serial.write(GPSdata2,36);
  delay (1000);
  Serial.write(GPSdata3,40);
 
  lcd.clear();
}

void loop() {

  while (Serial.available() > 0)
  gps.encode(Serial.read());
  delay(1);                       // wait for a milisecond
  nMiliSec++;
 
  if(nMiliSec == 100) {
    nMiliSec = 0;   // Clear 100 milisec timer

    // Test buttons
    // Test service mode
    if(!digitalRead(DWNBUTT) && !digitalRead(UPBUTT)) {if(++ModeCnt > 20) ModeFS= true;} else ModeCnt=0;
    // Read the state of the Up button into a local variable and procces it:
    int reading = digitalRead(UPBUTT);
    if(reading != lastButtUp) {
      lastButtUp=reading;
      if(!reading)
      {
        if(nMuxPos < 7) nMuxPos++;
      }
    }
    // Read the state of the Down button into a local variable and procces it:
    reading = digitalRead(DWNBUTT);
    if(reading != lastButtDown) {
      lastButtDown=reading;
      if(!reading)
      {
        if(nMuxPos > 0) nMuxPos--;
      }
    }

    // Display status on the first line
    lcd.setCursor(0,0);
    int sat=gps.satellites.value();
    if(sat<3 || ModeFS) {lcd.print("INT");   digitalWrite(A1, LOW);}
    else {lcd.print("GPS");   digitalWrite(A1, HIGH);}
    // Display Mux frequency
    lcd.setCursor(4,0);
    // do something different depending on the nMuxPos value:
    switch (nMuxPos) {
    case 0:    // 1 Hz
      lcd.print(" 1Hz");  digitalWrite(MUXA, HIGH);  digitalWrite(MUXB, LOW);  digitalWrite(MUXC, HIGH);
      break;
    case 1:    // 10 Hz
      lcd.print("10Hz");  digitalWrite(MUXA, HIGH);  digitalWrite(MUXB, LOW);  digitalWrite(MUXC, LOW);
      break;
    case 2:    // 100 Hz
      lcd.print("100H");  digitalWrite(MUXA, LOW);  digitalWrite(MUXB, HIGH);  digitalWrite(MUXC, LOW);
      break;
    case 3:    // 1 kHz
      lcd.print("1kHz");  digitalWrite(MUXA, LOW);  digitalWrite(MUXB, LOW);  digitalWrite(MUXC, HIGH);
      break;
    case 4:    // 10 kHz
      lcd.print("10kH");  digitalWrite(MUXA, LOW);  digitalWrite(MUXB, HIGH);  digitalWrite(MUXC, HIGH);
      break;
    case 5:    // 100 kHz
      lcd.print("100k");  digitalWrite(MUXA, LOW);  digitalWrite(MUXB, LOW);  digitalWrite(MUXC, LOW);
      break;
    case 6:    // 1 MHz
      lcd.print("1MHz");  digitalWrite(MUXA, HIGH);  digitalWrite(MUXB, HIGH);  digitalWrite(MUXC, LOW);
      break;
    case 7:    // 10 MHz
      lcd.print("10MH");  digitalWrite(MUXA, HIGH);  digitalWrite(MUXB, HIGH);  digitalWrite(MUXC, HIGH);
      break;
  }
    
    // Display UTC time
    lcd.setCursor(0,1);
    String MyTime ="";
    int Hours=gps.time.hour();
    int Minutes=gps.time.minute();
    int Seconds=gps.time.second();
    if (Hours<10) { MyTime=MyTime+"0"+Hours;}
      else {MyTime=MyTime+Hours;}
    if (Minutes<10) { MyTime=MyTime+":"+"0"+Minutes;}
      else {MyTime=MyTime+":"+Minutes;}
    if (Seconds<10){MyTime=MyTime+":"+"0"+Seconds;}
      else {MyTime=MyTime+":"+Seconds;}
    lcd.print(MyTime);
  }
}