/*
 * Author: klaute -Kai Lauterbach - @kailauterbach - me@klaute.de
 * Date: 09/2016
 * License: GPLv3
 */

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

#include <si5351.h>
#include "Wire.h"

#include <EEPROM.h>

extern "C" {
  #include "globals.h"
}

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

Si5351 si5351;

uint32_t start_freq = 10000;
uint32_t   end_freq = 50000000;
uint32_t  step_freq = 1000000; // 1 MHz default step size
uint16_t  intervall = 1000; // intervall to change the frequency as milli seconds
enum si5351_drive drive_str = SI5351_DRIVE_2MA;

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

void setup()
{
  // manage the analog pins
  pinMode(A0, INPUT); // forward SWR measurement
  pinMode(A1, INPUT); // backward SWR measurement
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  pinMode(A6, OUTPUT);
  pinMode(A7, OUTPUT);

  digitalWrite(A2, LOW);
  digitalWrite(A3, LOW);
  digitalWrite(A6, LOW);
  digitalWrite(A7, LOW);

  // Init the serial connection
  Serial.begin(115200);

  // initialize the command control module
  cc_init();

  // init the Si5351
  si5351.init(SI5351_CRYSTAL_LOAD_8PF, 0);

  si5351.set_pll(SI5351_PLL_FIXED, SI5351_PLLA);

  si5351.output_enable(SI5351_CLK0, 0); // disable clock output 0
  si5351.output_enable(SI5351_CLK1, 0); // disable clock output 1
  si5351.output_enable(SI5351_CLK2, 0); // disable clock output 2

  analogReference(DEFAULT); // 5V reference

  readEEPValues();

}

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

void loop()
{
  // Read the Status Register and print it every 10 seconds
  si5351.update_status();

  /*
  Serial.print("SYS_INIT: ");
  Serial.print(si5351.dev_status.SYS_INIT);
  Serial.print("  LOL_A: ");
  Serial.print(si5351.dev_status.LOL_A);
  Serial.print("  LOL_B: ");
  Serial.print(si5351.dev_status.LOL_B);
  Serial.print("  LOS: ");
  Serial.print(si5351.dev_status.LOS);
  Serial.print("  REVID: ");
  Serial.println(si5351.dev_status.REVID);
  */

  if (Serial.available() > 0)
  {
    uint8_t c = Serial.read() & 0xff;

    cc_processData(c);
  }

  //cc_abort();

  delay(100);
}

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

void saveEEPValues()
{

  EEPROM.write( 0, (uint8_t)((start_freq & 0xff000000) >> 24));
  EEPROM.write( 1, (uint8_t)((start_freq & 0x00ff0000) >> 16));
  EEPROM.write( 2, (uint8_t)((start_freq & 0x0000ff00) >>  8));
  EEPROM.write( 3, (uint8_t) (start_freq & 0x000000ff));
  EEPROM.write( 4, (uint8_t)((end_freq & 0xff000000) >> 24));
  EEPROM.write( 5, (uint8_t)((end_freq & 0x00ff0000) >> 16));
  EEPROM.write( 6, (uint8_t)((end_freq & 0x0000ff00) >>  8));
  EEPROM.write( 7, (uint8_t) (end_freq & 0x000000ff));
  EEPROM.write( 8, (uint8_t)((step_freq & 0xff000000) >> 24));
  EEPROM.write( 9, (uint8_t)((step_freq & 0x00ff0000) >> 16));
  EEPROM.write(10, (uint8_t)((step_freq & 0x0000ff00) >>  8));
  EEPROM.write(11, (uint8_t) (step_freq & 0x000000ff));
  EEPROM.write(12, (uint8_t)((intervall & 0xff00) >> 8));
  EEPROM.write(13, (uint8_t) (intervall & 0x00ff));
  EEPROM.write(14, (uint8_t) drive_str);

}

void readEEPValues()
{
  uint32_t tmp_start_freq  = (uint32_t)EEPROM.read(0) << 24;
           tmp_start_freq += (uint32_t)EEPROM.read(1) << 16;
           tmp_start_freq += (uint32_t)EEPROM.read(2) <<  8;
           tmp_start_freq += (uint32_t)EEPROM.read(3);
  if (tmp_start_freq < 1)
    tmp_start_freq = 1;
  if (tmp_start_freq > 150000000)
    tmp_start_freq = 150000000;

  start_freq = tmp_start_freq;

  uint32_t tmp_end_freq  = (uint32_t)EEPROM.read(4) << 24;
           tmp_end_freq += (uint32_t)EEPROM.read(5) << 16;
           tmp_end_freq += (uint32_t)EEPROM.read(6) <<  8;
           tmp_end_freq += (uint32_t)EEPROM.read(7);
  if (tmp_end_freq < 1)
    tmp_end_freq = 1;
  if (tmp_end_freq > 150000000)
    tmp_end_freq = 150000000;

  end_freq = tmp_end_freq;

  uint32_t tmp_step_freq  = (uint32_t)EEPROM.read( 8) << 24;
           tmp_step_freq += (uint32_t)EEPROM.read( 9) << 16;
           tmp_step_freq += (uint32_t)EEPROM.read(10) <<  8;
           tmp_step_freq += (uint32_t)EEPROM.read(11);
  if (tmp_step_freq < 1)
    tmp_step_freq = 1;
  if (tmp_step_freq > 150000000)
    tmp_step_freq = 150000000;

  step_freq = tmp_step_freq;

  uint16_t tmp_intervall  = (uint16_t)EEPROM.read(12) << 8;
           tmp_intervall += (uint16_t)EEPROM.read(13);
  if (tmp_intervall < 1)
    tmp_intervall = 1;
  if (tmp_intervall > 150000000)
    tmp_intervall = 150000000;

  intervall = tmp_intervall;

  enum si5351_drive tmp_ds  = (enum si5351_drive)EEPROM.read(14);
  if (tmp_ds == SI5351_DRIVE_2MA ||
      tmp_ds == SI5351_DRIVE_4MA ||
      tmp_ds == SI5351_DRIVE_6MA ||
      tmp_ds == SI5351_DRIVE_8MA)
  {
    drive_str = tmp_ds;
  } else {
    drive_str = SI5351_DRIVE_2MA;
  }
}

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

