Thursday, 25 June 2020

Digital Modes Transceiver

Initial CAT Code. The radio emulates a Kenwood TS-480. (https://www.kenwood.com/i/products/info/amateur/ts_480/pdf/ts_480_pc.pdf)
Refer to the YouTube video for an explanation.




#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>

int debug = 0;

const int numChars = 14;
volatile long freq = 0;
boolean newCATcmd = false;

char CATcmd[numChars] = {'0'};    // an array to store the received CAT data
int freq10GHz = 0;
int freq1GHz = 0;
int freq100MHz = 0;
int freq10MHz = 1;
int freq1MHz = 4;
int freq100kHz = 1;
int freq10kHz = 2;
int freq1kHz = 3;
int freq100Hz = 4;
int freq10Hz = 5;
int freq1Hz = 6;
int RIT, XIT, MEM1, MEM2, RX, TX, VFO, SCAN, SIMPLEX, CTCSS, TONE1, TONE2 = 0;
int MODE = 2;

SoftwareSerial mySerial(31, 32);      // RX, TX
LiquidCrystal_I2C lcd(0x3F, 16, 2);

void setup()
{
  lcd.begin();
  lcd.backlight();
  CalcFreq();

  Serial.begin(9600);

  // Debug serial port
  mySerial.begin(9600);
}

void loop()
{
  rxCATcmd();
  analyseCATcmd();
}

void rxCATcmd()
{
  int index = 0;
  char endMarker = ';';
  char data;                    // CAT commands are ASCII characters

  while ((Serial.available() > 0) && (newCATcmd == false))
  {
    data = Serial.read();

    if (data != endMarker)
    {
      CATcmd[index] = data;
      index++;

      if (index >= numChars)
        index = numChars - 1;   // leave space for the \0 array termination
    }
    else
    {
      CATcmd[index] = ';';      // Indicate end of command
      debug = index;            // Needed later to print out the command
      CATcmd[index + 1] = '\0'; // terminate the array
      index = 0;                // reset for next CAT command
      newCATcmd = true;
    }
  }
}

void analyseCATcmd()
{
  if (newCATcmd == true)
  {
    newCATcmd = false;        // reset for next CAT time

    // Debug printing
    mySerial.println();
    for (int x = 0; x <= debug; x++)
      mySerial.print(CATcmd[x]);
    mySerial.print("\t");

    if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[2] == ';'))              // must be freq get command
      Command_GETFreqA();

    else if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[13] == ';'))        // must be freq set command
      Command_SETFreqA();

    else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'F') && (CATcmd[2] == ';'))
      Command_IF();

    else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
      Command_ID();

    else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
      Command_PS();

    else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == '1'))
      Command_PS1();

    else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == ';'))
      Command_AI();

    else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == '0'))
      Command_AI0();

    else if ((CATcmd[0] == 'M') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
      Command_MD();

    else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
      Command_RX();

    else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
      Command_TX();

    else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == '1'))
      Command_TX1();

    else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
      Command_RS();

    Serial.flush();       // Get ready for next command
    //delay(50);            // Needed to eliminate WSJT-X connection errors
  }
}

void Command_ID()
{
  Serial.print("ID020;");
  mySerial.print("ID020;");
}

void Command_PS()
{
  Serial.print("PS1;");
  mySerial.print("PS1;");
}

void Command_PS1()
{
  Serial.print("PS1;");
  mySerial.print("PS1;");
}

void Command_GETFreqA()
{
  Serial.print("FA");
  Serial.print(freq10GHz);
  Serial.print(freq1GHz);
  Serial.print(freq100MHz);
  Serial.print(freq10MHz);
  Serial.print(freq1MHz);
  Serial.print(freq100kHz);
  Serial.print(freq10kHz);
  Serial.print(freq1kHz);
  Serial.print(freq100Hz);
  Serial.print(freq10Hz);
  Serial.print(freq1Hz);
  Serial.print(";");

  mySerial.print("FA");
  mySerial.print(freq10GHz);
  mySerial.print(freq1GHz);
  mySerial.print(freq100MHz);
  mySerial.print(freq10MHz);
  mySerial.print(freq1MHz);
  mySerial.print(freq100kHz);
  mySerial.print(freq10kHz);
  mySerial.print(freq1kHz);
  mySerial.print(freq100Hz);
  mySerial.print(freq10Hz);
  mySerial.print(freq1Hz);
  mySerial.print(";");
}

void Command_SETFreqA()
{
  freq10GHz = CATcmd[2] - 48;       // convert ASCII char to int equivalent. int 0 = ASCII 48;
  freq1GHz = CATcmd[3] - 48;
  freq100MHz = CATcmd[4] - 48;
  freq10MHz = CATcmd[5] - 48;
  freq1MHz = CATcmd[6] - 48;
  freq100kHz = CATcmd[7] - 48;
  freq10kHz = CATcmd[8] - 48;
  freq1kHz = CATcmd[9] - 48;
  freq100Hz = CATcmd[10] - 48;
  freq10Hz = CATcmd[11] - 48;
  freq1Hz = CATcmd[12] - 48;

  //Command_GETFreqA();               // now RSP with FA

  Serial.print("FA");
  Serial.print(freq10GHz);
  Serial.print(freq1GHz);
  Serial.print(freq100MHz);
  Serial.print(freq10MHz);
  Serial.print(freq1MHz);
  Serial.print(freq100kHz);
  Serial.print(freq10kHz);
  Serial.print(freq1kHz);
  Serial.print(freq100Hz);
  Serial.print(freq10Hz);
  Serial.print(freq1Hz);
  Serial.print(";");

  mySerial.print("FA");
  mySerial.print(freq10GHz);
  mySerial.print(freq1GHz);
  mySerial.print(freq100MHz);
  mySerial.print(freq10MHz);
  mySerial.print(freq1MHz);
  mySerial.print(freq100kHz);
  mySerial.print(freq10kHz);
  mySerial.print(freq1kHz);
  mySerial.print(freq100Hz);
  mySerial.print(freq10Hz);
  mySerial.print(freq1Hz);
  mySerial.print(";");

  CalcFreq();
}

void CalcFreq()
{
  freq = (
                (10000000000L * freq10GHz) +
                (1000000000L * freq1GHz) +
                (100000000L * freq100MHz) +
                (10000000L * freq10MHz) +
                (1000000L * freq1MHz) +
                (100000L * freq100kHz) +
                (10000L * freq10kHz) +
                (1000L * freq1kHz) +
                (100L * freq100Hz) +
                (10L * freq10Hz) +
                freq1Hz);

  // Debug print
  lcd.setCursor(0, 1);
  lcd.print(freq10GHz);
  lcd.print(freq1GHz);
  lcd.print(freq100MHz);
  lcd.print(freq10MHz);
  lcd.print(freq1MHz);
  lcd.print(freq100kHz);
  lcd.print(freq10kHz);
  lcd.print(freq1kHz);
  lcd.print(freq100Hz);
  lcd.print(freq10Hz);
  lcd.print(freq1Hz);

  lcd.setCursor(0, 0);      // Col, Row
  lcd.print("                ");
  lcd.setCursor(0, 0);
  lcd.print(freq);
}

void Command_IF()
{
  Serial.print("IF");
  Serial.print(freq10GHz);        // P1
  Serial.print(freq1GHz);
  Serial.print(freq100MHz);
  Serial.print(freq10MHz);
  Serial.print(freq1MHz);
  Serial.print(freq100kHz);
  Serial.print(freq10kHz);
  Serial.print(freq1kHz);
  Serial.print(freq100Hz);
  Serial.print(freq10Hz);
  Serial.print(freq1Hz);
  Serial.print("00000");          // P2 Always five 0s
  Serial.print("+0000");          // P3 RIT/XIT freq +/-9990
  Serial.print(RIT);              // P4
  Serial.print(XIT);              // P5
  Serial.print("0");              // P6 Always 0
  Serial.print(MEM1);             // P7
  Serial.print(MEM2);
  Serial.print(RX);               // P8
  Serial.print(MODE);             // P9
  Serial.print(VFO);              // P10  FR/FT 0=VFO
  Serial.print(SCAN);             // P11
  Serial.print(SIMPLEX);          // P12
  Serial.print(CTCSS);            // P13
  Serial.print(TONE1);            // P14
  Serial.print(TONE2);
  Serial.print("0");              // P15 Always 0
  Serial.print(";");

  mySerial.print("IF");
  mySerial.print(freq10GHz);        // P1
  mySerial.print(freq1GHz);
  mySerial.print(freq100MHz);
  mySerial.print(freq10MHz);
  mySerial.print(freq1MHz);
  mySerial.print(freq100kHz);
  mySerial.print(freq10kHz);
  mySerial.print(freq1kHz);
  mySerial.print(freq100Hz);
  mySerial.print(freq10Hz);
  mySerial.print(freq1Hz);
  mySerial.print("00000");          // P2 Always five 0s
  mySerial.print("+0000");          // P3 RIT/XIT freq +/-9990
  mySerial.print(RIT);              // P4
  mySerial.print(XIT);              // P5
  mySerial.print("0");              // P6 Always 0
  mySerial.print(MEM1);             // P7
  mySerial.print(MEM2);
  mySerial.print(RX);               // P8
  mySerial.print(MODE);             // P9
  mySerial.print(VFO);              // P10  FR/FT 0=VFO
  mySerial.print(SCAN);             // P11
  mySerial.print(SIMPLEX);          // P12
  mySerial.print(CTCSS);            // P13
  mySerial.print(TONE1);            // P14
  mySerial.print(TONE2);
  mySerial.print("0");              // P15 Always 0
  mySerial.print(";");
}

void Command_AI()
{
  Serial.print("AI0;");
  mySerial.print("AI0;");
}

void Command_MD()
{
  Serial.print("MD2;");
  mySerial.print("MD2;");
}

void Command_AI0()
{
  Serial.print("AI0;");
  mySerial.print("AI0;");
}

void Command_RX()
{
  RX = 0;
  TX = 0;
  Serial.print("RX0;");
  mySerial.print("RX0;");
}

void Command_TX()
{
  RX = 1;
  TX = 1;
  Serial.print("TX0;");
  mySerial.print("TX0;");
}

void Command_TX1()
{
  RX = 1;
  TX = 1;
  Serial.print("TX2;");
  mySerial.print("TX2;");
}

void Command_RS()
{
  Serial.print("RS0;");
  mySerial.print("RS0;");
}


***********************************************************
Additional code to enable audio and serial data across the single USB connection. This is test code only at this stage.


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <Audio.h>                         // Teensy audio library

int debug = 0;

const int numChars = 14;
volatile long freq = 0;
boolean newCATcmd = false;

char CATcmd[numChars] = {'0'};    // an array to store the received CAT data
int freq10GHz = 0;
int freq1GHz = 0;
int freq100MHz = 0;
int freq10MHz = 1;
int freq1MHz = 4;
int freq100kHz = 1;
int freq10kHz = 2;
int freq1kHz = 3;
int freq100Hz = 4;
int freq10Hz = 5;
int freq1Hz = 6;
int RIT, XIT, MEM1, MEM2, RX, TX, VFO, SCAN, SIMPLEX, CTCSS, TONE1, TONE2 = 0;
int MODE = 2;

SoftwareSerial mySerial(31, 32);      // RX, TX
AudioControlSGTL5000    audioShield;

// Audio objects
AudioInputUSB           audioInputUSB;
AudioSynthWaveformSine  TestOsc;
AudioOutputUSB          audioOutputUSB;
AudioOutputI2S          audioOutputHeadphones;

// Audio connections
AudioConnection         patchCord5(TestOsc, 0, audioOutputUSB, 0);
AudioConnection         patchCord10(TestOsc, 0, audioOutputUSB, 1);
AudioConnection         patchCord15(audioInputUSB, 0, audioOutputHeadphones, 0);
AudioConnection         patchCord20(audioInputUSB, 1, audioOutputHeadphones, 1);


void setup()
{
  CalcFreq();

  Serial.begin(9600);
  mySerial.begin(9600);

  // Setup the audio shield
  AudioNoInterrupts();
  AudioMemory(12);
  audioShield.enable();
  TestOsc.amplitude(0.1);
  TestOsc.frequency(700);
  audioShield.unmuteHeadphone();                                              // Output to the audio amplifier
  audioShield.volume(0.8);
  AudioInterrupts();
}

void loop()
{
  rxCATcmd();
  analyseCATcmd();
}

void rxCATcmd()
{
  int index = 0;
  char endMarker = ';';
  char data;                    // CAT commands are ASCII characters

  while ((Serial.available() > 0) && (newCATcmd == false))
  {
    data = Serial.read();

    if (data != endMarker)
    {
      CATcmd[index] = data;
      index++;

      if (index >= numChars)
        index = numChars - 1;   // leave space for the \0 array termination
    }
    else
    {
      CATcmd[index] = ';';      // Indicate end of command
      debug = index;            // Needed later to print out the command
      CATcmd[index + 1] = '\0'; // terminate the array
      index = 0;                // reset for next CAT command
      newCATcmd = true;
    }
  }
}

void analyseCATcmd()
{
  if (newCATcmd == true)
  {
    newCATcmd = false;        // reset for next CAT time

    // Debug printing
    mySerial.println();
    for (int x = 0; x <= debug; x++)
      mySerial.print(CATcmd[x]);
    mySerial.print("\t");

    if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[2] == ';'))              // must be freq get command
      Command_GETFreqA();

    else if ((CATcmd[0] == 'F') && (CATcmd[1] == 'A') && (CATcmd[13] == ';'))        // must be freq set command
      Command_SETFreqA();

    else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'F') && (CATcmd[2] == ';'))
      Command_IF();

    else if ((CATcmd[0] == 'I') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
      Command_ID();

    else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
      Command_PS();

    else if ((CATcmd[0] == 'P') && (CATcmd[1] == 'S') && (CATcmd[2] == '1'))
      Command_PS1();

    else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == ';'))
      Command_AI();

    else if ((CATcmd[0] == 'A') && (CATcmd[1] == 'I') && (CATcmd[2] == '0'))
      Command_AI0();

    else if ((CATcmd[0] == 'M') && (CATcmd[1] == 'D') && (CATcmd[2] == ';'))
      Command_MD();

    else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
      Command_RX();

    else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == ';'))
      Command_TX();

    else if ((CATcmd[0] == 'T') && (CATcmd[1] == 'X') && (CATcmd[2] == '1'))
      Command_TX1();

    else if ((CATcmd[0] == 'R') && (CATcmd[1] == 'S') && (CATcmd[2] == ';'))
      Command_RS();

    Serial.flush();       // Get ready for next command
    //delay(50);            // Needed to eliminate WSJT-X connection errors
  }
}

void Command_ID()
{
  Serial.print("ID020;");
  mySerial.print("ID020;");
}

void Command_PS()
{
  Serial.print("PS1;");
  mySerial.print("PS1;");
}

void Command_PS1()
{
  Serial.print("PS1;");
  mySerial.print("PS1;");
}

void Command_GETFreqA()
{
  Serial.print("FA");
  Serial.print(freq10GHz);
  Serial.print(freq1GHz);
  Serial.print(freq100MHz);
  Serial.print(freq10MHz);
  Serial.print(freq1MHz);
  Serial.print(freq100kHz);
  Serial.print(freq10kHz);
  Serial.print(freq1kHz);
  Serial.print(freq100Hz);
  Serial.print(freq10Hz);
  Serial.print(freq1Hz);
  Serial.print(";");

  mySerial.print("FA");
  mySerial.print(freq10GHz);
  mySerial.print(freq1GHz);
  mySerial.print(freq100MHz);
  mySerial.print(freq10MHz);
  mySerial.print(freq1MHz);
  mySerial.print(freq100kHz);
  mySerial.print(freq10kHz);
  mySerial.print(freq1kHz);
  mySerial.print(freq100Hz);
  mySerial.print(freq10Hz);
  mySerial.print(freq1Hz);
  mySerial.print(";");
}

void Command_SETFreqA()
{
  freq10GHz = CATcmd[2] - 48;       // convert ASCII char to int equivalent. int 0 = ASCII 48;
  freq1GHz = CATcmd[3] - 48;
  freq100MHz = CATcmd[4] - 48;
  freq10MHz = CATcmd[5] - 48;
  freq1MHz = CATcmd[6] - 48;
  freq100kHz = CATcmd[7] - 48;
  freq10kHz = CATcmd[8] - 48;
  freq1kHz = CATcmd[9] - 48;
  freq100Hz = CATcmd[10] - 48;
  freq10Hz = CATcmd[11] - 48;
  freq1Hz = CATcmd[12] - 48;

  //Command_GETFreqA();               // now RSP with FA

  Serial.print("FA");
  Serial.print(freq10GHz);
  Serial.print(freq1GHz);
  Serial.print(freq100MHz);
  Serial.print(freq10MHz);
  Serial.print(freq1MHz);
  Serial.print(freq100kHz);
  Serial.print(freq10kHz);
  Serial.print(freq1kHz);
  Serial.print(freq100Hz);
  Serial.print(freq10Hz);
  Serial.print(freq1Hz);
  Serial.print(";");

  mySerial.print("FA");
  mySerial.print(freq10GHz);
  mySerial.print(freq1GHz);
  mySerial.print(freq100MHz);
  mySerial.print(freq10MHz);
  mySerial.print(freq1MHz);
  mySerial.print(freq100kHz);
  mySerial.print(freq10kHz);
  mySerial.print(freq1kHz);
  mySerial.print(freq100Hz);
  mySerial.print(freq10Hz);
  mySerial.print(freq1Hz);
  mySerial.print(";");

  CalcFreq();
}

void CalcFreq()
{
  freq = (
           (10000000000L * freq10GHz) +
           (1000000000L * freq1GHz) +
           (100000000L * freq100MHz) +
           (10000000L * freq10MHz) +
           (1000000L * freq1MHz) +
           (100000L * freq100kHz) +
           (10000L * freq10kHz) +
           (1000L * freq1kHz) +
           (100L * freq100Hz) +
           (10L * freq10Hz) +
           freq1Hz);
}

void Command_IF()
{
  Serial.print("IF");
  Serial.print(freq10GHz);        // P1
  Serial.print(freq1GHz);
  Serial.print(freq100MHz);
  Serial.print(freq10MHz);
  Serial.print(freq1MHz);
  Serial.print(freq100kHz);
  Serial.print(freq10kHz);
  Serial.print(freq1kHz);
  Serial.print(freq100Hz);
  Serial.print(freq10Hz);
  Serial.print(freq1Hz);
  Serial.print("00000");          // P2 Always five 0s
  Serial.print("+0000");          // P3 RIT/XIT freq +/-9990
  Serial.print(RIT);              // P4
  Serial.print(XIT);              // P5
  Serial.print("0");              // P6 Always 0
  Serial.print(MEM1);             // P7
  Serial.print(MEM2);
  Serial.print(RX);               // P8
  Serial.print(MODE);             // P9
  Serial.print(VFO);              // P10  FR/FT 0=VFO
  Serial.print(SCAN);             // P11
  Serial.print(SIMPLEX);          // P12
  Serial.print(CTCSS);            // P13
  Serial.print(TONE1);            // P14
  Serial.print(TONE2);
  Serial.print("0");              // P15 Always 0
  Serial.print(";");

  mySerial.print("IF");
  mySerial.print(freq10GHz);        // P1
  mySerial.print(freq1GHz);
  mySerial.print(freq100MHz);
  mySerial.print(freq10MHz);
  mySerial.print(freq1MHz);
  mySerial.print(freq100kHz);
  mySerial.print(freq10kHz);
  mySerial.print(freq1kHz);
  mySerial.print(freq100Hz);
  mySerial.print(freq10Hz);
  mySerial.print(freq1Hz);
  mySerial.print("00000");          // P2 Always five 0s
  mySerial.print("+0000");          // P3 RIT/XIT freq +/-9990
  mySerial.print(RIT);              // P4
  mySerial.print(XIT);              // P5
  mySerial.print("0");              // P6 Always 0
  mySerial.print(MEM1);             // P7
  mySerial.print(MEM2);
  mySerial.print(RX);               // P8
  mySerial.print(MODE);             // P9
  mySerial.print(VFO);              // P10  FR/FT 0=VFO
  mySerial.print(SCAN);             // P11
  mySerial.print(SIMPLEX);          // P12
  mySerial.print(CTCSS);            // P13
  mySerial.print(TONE1);            // P14
  mySerial.print(TONE2);
  mySerial.print("0");              // P15 Always 0
  mySerial.print(";");
}

void Command_AI()
{
  Serial.print("AI0;");
  mySerial.print("AI0;");
}

void Command_MD()
{
  Serial.print("MD2;");
  mySerial.print("MD2;");
}

void Command_AI0()
{
  Serial.print("AI0;");
  mySerial.print("AI0;");
}

void Command_RX()
{
  RX = 0;
  TX = 0;
  Serial.print("RX0;");
  mySerial.print("RX0;");
}

void Command_TX()
{
  RX = 1;
  TX = 1;
  Serial.print("TX0;");
  mySerial.print("TX0;");
}

void Command_TX1()
{
  RX = 1;
  TX = 1;
  Serial.print("TX2;");
  mySerial.print("TX2;");
}

void Command_RS()
{
  Serial.print("RS0;");
  mySerial.print("RS0;");
}


*************************************************************************

RF Splitter/Combiner