#include<Arduino.h>
#include<Wire.h>
#include<SI4735.h>
#define RESET_PIN 42              // GPIO12
#define TOUCH_BAND_BUTTON_UP 13   // Next band (GPIO13)
#define TOUCH_BAND_BUTTON_DOWN 14 // Previous band (GPIO14)
// I2C bus pin on ESP32
#define ESP32_I2C_SDA 15     // GPIO21
#define ESP32_I2C_SCL 16     // GPIO22 
#define CAPACITANCE 30
#define AM_FUNCTION 1
#define FM_FUNCTION 0
uint16_t currentFrequency;
uint16_t previousFrequency;
uint8_t bandwidthIdx = 0;
const char *bandwidth[] = {"6", "4", "3", "2", "1", "1.8", "2.5"};
SI4735 si4735;
void showHelp()
{
  Serial.println("Type F to FM; A to MW; L to LW; and 1 to SW");
  Serial.println("Type U to increase and D to decrease the frequency");
  Serial.println("Type S or s to seek station Up or Down");
  Serial.println("Type + or - to volume Up or Down");
  Serial.println("Type 0 to show current status");
  Serial.println("Type B to change Bandwidth filter");
  Serial.println("Type ? to this help.");
  Serial.println("==================================================");
  delay(1000);
}
// Show current frequency
void showStatus()
{
  si4735.getStatus();
  si4735.getCurrentReceivedSignalQuality();
  Serial.print("You are tuned on ");
  if (si4735.isCurrentTuneFM())
  {
    Serial.print(String(currentFrequency / 100.0, 2));
    Serial.print("MHz ");
    Serial.print((si4735.getCurrentPilot()) ? "STEREO" : "MONO");
  }
  else
  {
    Serial.print(currentFrequency);
    Serial.print("kHz");
  }
  Serial.print(" [SNR:");
  Serial.print(si4735.getCurrentSNR());
  Serial.print("dB");
  Serial.print(" Signal:");
  Serial.print(si4735.getCurrentRSSI());
  Serial.println("dBuV]");
}
int touchUp, touchDown;
int readX(int pin) {
  int val;
  val = 0;
  for (int i = 0; i < 50; i++ )
    val += touchRead(pin);
  return (val / 50);  
}
void setup()
{
  Serial.begin(115200);
  while(!Serial);
  digitalWrite(RESET_PIN, HIGH);
  
  Serial.println("AM and FM station tuning test.");
  showHelp();
  // The line below may be necessary to setup I2C pins on ESP32
  Wire.setPins(ESP32_I2C_SDA, ESP32_I2C_SCL);
  Wire.begin();
  delay(500);
  si4735.setup(RESET_PIN, 0, FM_FUNCTION, SI473X_ANALOG_AUDIO, 1,0);
  // Starts defaul radio function and band (FM; from 84 to 108 MHz; 103.9 MHz; step 100kHz)
  si4735.setFM(8400, 10800, 10390, 10);
  delay(500);
  currentFrequency = previousFrequency = si4735.getFrequency();
  si4735.setVolume(55);
  showStatus();
}
// Main
void loop()
{
  touchUp = readX(TOUCH_BAND_BUTTON_UP);
  touchDown = readX(TOUCH_BAND_BUTTON_DOWN);
  
  if (Serial.available() > 0)
  {
    char key = Serial.read();
    switch (key)
    {
    case '+':
      si4735.volumeUp();
      break;
    case '-':
      si4735.volumeDown();
      break;
    case 'a':
    case 'A':
      si4735.setAM(570, 1710, 810, 10);
      break;
    case 'f':
    case 'F':
      si4735.setFM(8600, 10800, 10390, 10);
      break;
    case '1':
      si4735.setAM(9400, 9990, 9600, 5);
      break;
    case 'U':
    case 'u':
      si4735.frequencyUp();
      break;
    case 'D':
    case 'd':
      si4735.frequencyDown();
      break;
    case 'b':
    case 'B':
      if (si4735.isCurrentTuneFM())
      {
        Serial.println("Not valid for FM");
      }
      else
      {
        if (bandwidthIdx > 6)
          bandwidthIdx = 0;
        si4735.setBandwidth(bandwidthIdx, 1);
        Serial.print("Filter - Bandwidth: ");
        Serial.print(String(bandwidth[bandwidthIdx]));
        Serial.println(" kHz");
        bandwidthIdx++;
      }
      break;
    case 'S':
      si4735.seekStationUp();
      break;
    case 's':
      si4735.seekStationDown();
      break;
    case '0':
      showStatus();
      break;
    case '?':
      showHelp();
      break;
    default:
      break;
    }
  } else if ( (touchUp < CAPACITANCE) ) // goes to the next band
  {
    si4735.seekStationUp();;
    delay(100);
  }
  else if ( (touchDown < CAPACITANCE) ) // goes to the previous band
  {
    si4735.seekStationDown();
    delay(100);
  }
  
  delay(100);
  currentFrequency = si4735.getCurrentFrequency();
  if (currentFrequency != previousFrequency)
  {
    previousFrequency = currentFrequency;
    showStatus();
    delay(300);
  }
  
}