ft817_buddy/Arduino/src/main.cpp

932 wiersze
30 KiB
C++

/*
FT-817 Buddy v1.0
A companion display and programmable soft-buttons for thr Yaesu FT-817.
Project description: http://alloutput.com/amateur-radio/ft-817-companion-display-controls/
Project files: https://github.com/g7uhn/ft817_buddy
Building on the work of Clint Turner KA7OEI (http://www.ka7oei.com/ft817_meow.html)
and James Buck VE3BUX (https://ve3bux.com/study-guide/arduino-ft-857d-cat-library/)
Put together by a team:
Andy Webster G7UHN
Michael Sansom G0POT
Pavel Milanes Costa CO7WT
IMPORTANT NOTE! You MUST do/check two things before using this code:
1) By using this code you acknowledge that you accept the risk that comes with writing to the FT-817 EEPROM i.e. an interruption
or write error may reset your radio to pre-alignment factory defaults. See KA7OEI's page here (http://www.ka7oei.com/ft817_meow.html)
for details of how to record your own radio's unique factory settings such that you can restore your radio if the worst happens!
2) Uncomment the line below to unlock the sketch that may write to the EEPROM. You did record your own radio's 76 factory
calibration settings from the "soft calibration" menu... didn't you?
The authors above bear no responsibility for your use of this code and you proceed at your own risk.
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License
*/
// uncomment the line below if you want to use this sketch that writes to the EEPROM and accept the responsibility stated above! :-)
//#define EEPROM_WRITES
// uncomment the line below if you have fitted the Sparkfun DS1307 RTC module to the expansion header
// if no RTC module is fitted, this line should be commented out
//#define RTC_FITTED
// Include libraries
#include <Arduino.h> // required for PlatformIO IDE (not required if you're using Arduino IDE)
#include <SPI.h>
#include <Adafruit_PCD8544.h>
#include <Adafruit_GFX.h>
#include <Adafruit_I2CDevice.h>
#include <SoftwareSerial.h>
#include <ft817.h>
#include <SparkFunDS1307RTC.h>
#include <Wire.h>
// Declarations
Adafruit_PCD8544 display = Adafruit_PCD8544(7, 6, 5, 4, 3); // pins for (CLK,DIN,D/C,CE,RST)
FT817 radio; // define “radio” so that we may pass CAT and EEPROM commands
// Expansion software serial port: TX = digital pin 12, RX = digital pin 11
SoftwareSerial expansion(12,11);
// Define PCB pins
#define backlightPin 8 // backlight output pin (not the "LIGHT" input button!)
#define buttonPin A0 // SW1-SW6 arrive as different levels on analog input A0
#define sw7pin 11 // SW7 input is D11
#define sw8pin 10 // SW8 input is D10
#define sw9pin 9 // SW9 input is D9
#define keyerSw1 15 // A1 (pin 15) is Keyer SW1
#define keyerSw2 16 // A2 (pin 16) is Keyer SW2
#define keyerSw3 17 // A3 (pin 17) is Keyer SW3
#define keyerSw4 13 // D13 is Keyer SW4
#define SQW_INPUT_PIN 2 // Input pin to read RTC square wave
// Global variables - g7uhn TO DO: Needs a big tidy up here
bool sw7status = 1; // using pullup, pressing button takes this low
bool sw8status = 1; // using pullup, pressing button takes this low
bool sw9status = 1; // using pullup, pressing button takes this low
bool backlightStatus = 0; // Backlight, initialises as OFF
bool timedBacklight = 0; // is the Buddy performing a timed backlight operation?
bool expansionPage = 0; // is the Buddy displaying the expansion page?
int backlightCounter = 0;
long freq;
String mode;
byte modeByte;
byte modeBase; // used for the radio to return to this mode after generating Tune signal... needed to accomodate the CW/CWR/DIG NAR codes
byte modeReturn;
byte abcKeys = B1111;
int buttonStatus = 0; // analog value of buttonPin...
int button = 0; // ...button number
byte sMeter;
byte MSB;
byte LSB;
int currentPage = 2; // initialise at the last page
bool softkeyStatus[6] = {0, 0, 0, 0, 0, 0};
short int hh = 0; // clock hour
short int mm = 0; // clock minute
short int ss = 0; // clock seconds
long tickOver = 0; // a counter to store time values (?)
// Forward declaration of functions (required for PlatformIO)
// If you create your own user functions below, you'll need to declare them here for PlatformIO to compile
void drawMainDisplay(); // draw main display
void displayABCkeys(); // EEPROM read
void displaySoftKeyStatus(); // possible EEPROM reads
void getReadableMode(); // standard CAT command
void backlight(); // no FT-817 interaction
void changePage(); // no FT-817 interaction
void tuneSignalOn(); // standard CAT commands
void tuneSignalOff(); // standard CAT commands
void pressKeyerSw1(); // no FT-817 interaction
void pressKeyerSw2(); // no FT-817 interaction
void pressKeyerSw3(); // no FT-817 interaction
void pressKeyerSw4(); // no FT-817 interaction
void longPressKeyerSw1(); // no FT-817 interaction
void incrementSeconds(); // no FT-817 interaction
///////////// SETUP YOUR SOFT-KEY PAGES HERE! ////////////////////////
// Single functions from the ft817 library can be called straight from the pageXSoftKeyFunctionY function
// or, if the desired function is a combination of actions, define a function in the USER FUNCTIONS section below
// to be called by the sketch. If you make a new function, don't forget to forward declare your user function above.
// Page0 items
// SOFT-KEY 1
String page0SoftkeyLabel1 = "TUNon "; // 6 characters
void page0SoftkeyFunction1() {tuneSignalOn();}
boolean page0SoftkeyStatus1() {}
// SOFT-KEY 2
String page0SoftkeyLabel2 = "IPO"; // 3 characters
void page0SoftkeyFunction2() {radio.toggleIPO();} // EEPROM write
boolean page0SoftkeyStatus2() {return radio.getIPO();} // EEPROM read
// SOFT-KEY 3
String page0SoftkeyLabel3 = "KYR"; // 3 characters
void page0SoftkeyFunction3() {radio.toggleKeyer();} // EEPROM write
boolean page0SoftkeyStatus3() {return radio.getKeyer();} // EEPROM read
// SOFT-KEY 4
String page0SoftkeyLabel4 = "TUNoff"; // 6 characters
void page0SoftkeyFunction4() {tuneSignalOff();}
boolean page0SoftkeyStatus4() {}
// SOFT-KEY 5
String page0SoftkeyLabel5 = " BK"; // 3 characters
void page0SoftkeyFunction5() {radio.toggleBreakIn();} // EEPROM write
boolean page0SoftkeyStatus5() {return radio.getBreakIn();} // EEPROM read
// SOFT-KEY 6
String page0SoftkeyLabel6 = "NAR"; // 3 characters
void page0SoftkeyFunction6() {radio.toggleNar();} // EEPROM write
boolean page0SoftkeyStatus6() {return radio.getNar();} // EEPROM read
// Page1 items
// SOFT-KEY 1
String page1SoftkeyLabel1 = "getRTC"; // 6 characters
void page1SoftkeyFunction1() {rtc.update(); ss = rtc.second(); mm = rtc.minute(); hh = rtc.hour();} // get update from RTC and update Arduino's hh/mm/ss
boolean page1SoftkeyStatus1() {}
// SOFT-KEY 2
String page1SoftkeyLabel2 = "hh+"; // 3 characters
void page1SoftkeyFunction2() {hh = (hh + 1) % 24; tickOver = millis(); delay(300);}
boolean page1SoftkeyStatus2() {}
// SOFT-KEY 3
String page1SoftkeyLabel3 = "hh-"; // 3 characters
void page1SoftkeyFunction3() {if(hh==0) {hh=23;} else{hh = (hh - 1) % 24;}; tickOver = millis(); delay(300);}
boolean page1SoftkeyStatus3() {}
// SOFT-KEY 4
String page1SoftkeyLabel4 = "setRTC"; // 6 characters
void page1SoftkeyFunction4() {rtc.setTime(0, mm, hh, 1, 1, 1, 21);} // set RTC to hh:mm on the 1/1/21 (we're not interested in dates here, only time)
boolean page1SoftkeyStatus4() {}
// SOFT-KEY 5
String page1SoftkeyLabel5 = "mm+"; // 3 characters
void page1SoftkeyFunction5() {mm = (mm + 1) % 60; tickOver = millis(); delay(300);}
boolean page1SoftkeyStatus5() {}
// SOFT-KEY 6
String page1SoftkeyLabel6 = "mm-"; // 3 characters
void page1SoftkeyFunction6() {if(mm==0) {mm=59;} else{mm = (mm - 1) % 60;}; tickOver = millis(); delay(300);}
boolean page1SoftkeyStatus6() {}
// Page2 items
// SOFT-KEY 1
String page2SoftkeyLabel1 = "CMD "; // 6 characters
void page2SoftkeyFunction1() {longPressKeyerSw1();}
boolean page2SoftkeyStatus1() {}
// SOFT-KEY 2
String page2SoftkeyLabel2 = "M1 "; // 3 characters
void page2SoftkeyFunction2() {pressKeyerSw1();}
boolean page2SoftkeyStatus2() {}
// SOFT-KEY 3
String page2SoftkeyLabel3 = "M2 "; // 3 characters
void page2SoftkeyFunction3() {pressKeyerSw2();}
boolean page2SoftkeyStatus3() {}
// SOFT-KEY 4
String page2SoftkeyLabel4 = " NAR"; // 6 characters
void page2SoftkeyFunction4() {radio.toggleNar();}
boolean page2SoftkeyStatus4() {return radio.getNar();}
// SOFT-KEY 5
String page2SoftkeyLabel5 = " M3"; // 3 characters
void page2SoftkeyFunction5() {pressKeyerSw3();}
boolean page2SoftkeyStatus5() {}
// SOFT-KEY 6
String page2SoftkeyLabel6 = " M4"; // 3 characters
void page2SoftkeyFunction6() {pressKeyerSw4();}
boolean page2SoftkeyStatus6() {}
/////////////// END OF SOFT-KEY PAGE SETUP ////////////////////
//////////////////////////////////////////////////////////////////
void setup(void)
{
// Start serial
radio.begin(38400); // start the serial port for the CAT library
#ifdef RTC_FITTED
// Initialise RTC library
rtc.begin();
rtc.writeSQW(SQW_SQUARE_1); // Sets SQW output to 1Hz
attachInterrupt(digitalPinToInterrupt(SQW_INPUT_PIN), incrementSeconds, RISING);
#endif
// Start expansion software serial
//expansion.begin(115200); // start the expansion serial port at 115200 baud for GPS module
// Set up some pins
pinMode(backlightPin, OUTPUT);
pinMode(sw7pin, INPUT_PULLUP);
pinMode(sw8pin, INPUT_PULLUP);
pinMode(sw9pin, INPUT_PULLUP);
pinMode(keyerSw1, OUTPUT);
pinMode(keyerSw2, OUTPUT);
pinMode(keyerSw3, OUTPUT);
pinMode(keyerSw4, OUTPUT);
pinMode(SQW_INPUT_PIN, INPUT_PULLUP);
digitalWrite(backlightPin, LOW);
digitalWrite(keyerSw1, LOW);
digitalWrite(keyerSw2, LOW);
digitalWrite(keyerSw3, LOW);
digitalWrite(keyerSw4, LOW);
// Initialize Display
display.begin();
display.setContrast(62); // you can change the contrast around to adapt the display for the best viewing! 57 is default and good for Sparkfun
display.clearDisplay(); // Clear the buffer.
// Set up the timer interrupt to watch for button status at 50 Hz (needed to catch a quick button press)
cli(); // stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 311; // = (16*10^6) / (1*1024*50) - 1 (must be <65536)
TCCR1B |= (1 << WGM12); // turn on CTC mode
TCCR1B |= (1 << CS12) | (1 << CS10); // Set CS10 and CS12 bits for 1024 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
sei(); // allow interrupts
// Initial draw of the main display by calling changePage()
drawMainDisplay();
changePage();
#ifdef RTC_FITTED
// Get RTC time (non-blocking and clock will start at 00:00 if no RTC available????)
rtc.update();
ss = rtc.second();
mm = rtc.minute();
hh = rtc.hour();
#endif
#ifndef EEPROM_WRITES // if user has not accepted risk/responsibility of EEPROM writes, display a reminder :-)
display.setCursor(0, 0);
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
display.println(" Please agree ");
display.println(" to EEPROM ");
display.println(" writes to ");
display.println(" continue... ");
display.println(" See notes in ");
display.println(" the code ");
display.display();
#endif
} // end setup
void loop() // MAIN LOOP
{
#ifdef EEPROM_WRITES // if user has accepted the risk/responsibility of EEPROM writes, go ahead and run the main code block...
// Using two loops to avoid polling the radio too quickly with things we don't need a fast refresh on:
// 1) a "fast refresh" loop is run within the main loop for status items that we do want a quick refresh rate e.g. frequency and mode display
// 2) actions we only need a "slow refresh" are performed outside of the fast loop in the main loop e.g. status bits against soft-key labels
// FAST REFRESH LOOP starts here
for (int i = 0; i <=3; i++)
{
// Get frequency
freq = radio.getFreqMode(); //freq is a long integer of 10's of Hz
int MHz = freq / 100000;
long remainder = freq % 100000;
float kHz = remainder / 100.00;
// Get human readable mode data
getReadableMode();
// // Get Receiver status (S-meter)
// byte rxStatusCmd[5] = {0x00, 0x00, 0x00, 0x00, 0xe7};
// radioCAT.sendCmd(rxStatusCmd, 5);
// sMeter = radioCAT.getByte();
// sMeter = sMeter << 4; //left shift the bits by 4 to make this an S-meter byte ranging from 00000000 to 11110000
// BUTTON ACTIONS
// If user has pushed one of the soft-keys (1-6)
if (currentPage == 0)
{
if (button == 0) {goto endOfSoftKeyActions;}
else if (button == 1) { page0SoftkeyFunction1(); softkeyStatus[0] = page0SoftkeyStatus1();}
else if (button == 2) { page0SoftkeyFunction2(); softkeyStatus[1] = page0SoftkeyStatus2();}
else if (button == 3) { page0SoftkeyFunction3(); softkeyStatus[2] = page0SoftkeyStatus3();}
else if (button == 4) { page0SoftkeyFunction4(); softkeyStatus[3] = page0SoftkeyStatus4();}
else if (button == 5) { page0SoftkeyFunction5(); softkeyStatus[4] = page0SoftkeyStatus5();}
else if (button == 6) { page0SoftkeyFunction6(); softkeyStatus[5] = page0SoftkeyStatus6();}
button = 0; // reset button variable to zero once we've used it
displaySoftKeyStatus();
}
else if (currentPage == 1)
{
if (button == 0) {goto endOfSoftKeyActions;}
else if (button == 1) { page1SoftkeyFunction1(); softkeyStatus[0] = page1SoftkeyStatus1();}
else if (button == 2) { page1SoftkeyFunction2(); softkeyStatus[1] = page1SoftkeyStatus2();}
else if (button == 3) { page1SoftkeyFunction3(); softkeyStatus[2] = page1SoftkeyStatus3();}
else if (button == 4) { page1SoftkeyFunction4(); softkeyStatus[3] = page1SoftkeyStatus4();}
else if (button == 5) { page1SoftkeyFunction5(); softkeyStatus[4] = page1SoftkeyStatus5();}
else if (button == 6) { page1SoftkeyFunction6(); softkeyStatus[5] = page1SoftkeyStatus6();}
button = 0; // reset button variable to zero once we've used it
displaySoftKeyStatus();
}
else if (currentPage == 2)
{
if (button == 0) {goto endOfSoftKeyActions;}
else if (button == 1) { page2SoftkeyFunction1(); softkeyStatus[0] = page2SoftkeyStatus1();}
else if (button == 2) { page2SoftkeyFunction2(); softkeyStatus[1] = page2SoftkeyStatus2();}
else if (button == 3) { page2SoftkeyFunction3(); softkeyStatus[2] = page2SoftkeyStatus3();}
else if (button == 4) { page2SoftkeyFunction4(); softkeyStatus[3] = page2SoftkeyStatus4();}
else if (button == 5) { page2SoftkeyFunction5(); softkeyStatus[4] = page2SoftkeyStatus5();}
else if (button == 6) { page2SoftkeyFunction6(); softkeyStatus[5] = page2SoftkeyStatus6();}
button = 0; // reset button variable to zero once we've used it
displaySoftKeyStatus();
}
endOfSoftKeyActions:
if (sw7status == LOW) // PAGE button
{
changePage();
delay(200); // short delay to prevent occasional "double-press"
sw7status = HIGH; // reset sw7status to high
}
if (sw8status == LOW) // LIGHT button
{
backlight();
delay(200); // short delay to prevent occasional "double-press"
sw8status = HIGH; // reset sw8status to high
}
sw9status = HIGH; // reset sw9status to high
// FAST REFRESH STATUS DISPLAY ITEMS
// Print dial frequency
if (expansionPage != 1) { // don't display freq on the expansion page
display.setCursor(16, 32);
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
display.print(MHz);
display.print(",");
if (kHz < 100) display.print('0');
if (kHz < 10) display.print('0');
display.print(kHz);
if (MHz < 100) display.print(' ');
if (MHz < 10) display.print(' ');
display.print(' '); // extra character to print over the occasional stray "8"
}
// Print current mode
if (expansionPage != 1) { // don't display mode on the expansion page
display.setCursor(27, 22);
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
display.print(mode);
}
//// Print S-meter
// tft.setCursor(50,120);
// int sMeterWidth = 5*(sMeter / 16);
// tft.drawRect(51,119,76,8,WHITE);
// tft.fillRect(52,120,sMeterWidth,6,WHITE);
// tft.fillRect((52+sMeterWidth),120,(74-sMeterWidth),6,BLACK);
// Format and print time
char buffer[6]=""; // This is the buffer for the string the sprintf outputs to
sprintf(buffer, "%02d:%02d", hh, mm);
display.setCursor(27, 12);
display.print(buffer);
#ifndef RTC_FITTED // if RTC not fitted, use this clunky way out counting up the time in the main loop (RTC method uses hardware interrupt)
// Calculate time value (at boot this is uptime or user can set hh:mm values, install RTC module to avoid having to set this every boot)
if ( millis() - tickOver > 59999) {
if (mm == 59) {
hh = (hh + 1) % 24; // If mm == 59, increment hh modulo 24
}
mm = (mm + 1) % 60; // Increment mm modulo 60
tickOver = millis();
}
#endif
delay(200);
// write to display
display.display();
} // END OF FAST REFRESH LOOP (performed 4 times in every main loop)
// SLOW REFRESH STUFF
// Timed backlight countdown operation
if(timedBacklight == true)
{
if(backlightCounter > 0)
{
backlightCounter = backlightCounter - 1;
}
else
{
digitalWrite(backlightPin, 0); // turn the backlight off
backlightStatus = 0;
timedBacklight = 0; // end the timed backlight
}
}
display.display(); // update display
#endif
} // END OF MAIN LOOP
// Interrupt code reading buttons at 50Hz
ISR(TIMER1_COMPA_vect)
{ //change the 0 to 1 for timer1 and 2 for timer2
// Get button status (levels determined by resistor network)
buttonStatus = analogRead(buttonPin);
switch (buttonStatus) {
case 0 ... 79:
button = 1;
break;
case 80 ... 239:
button = 2;
break;
case 240 ... 399:
button = 3;
break;
case 400 ... 569:
button = 4;
break;
case 570 ... 749:
button = 5;
break;
case 750 ... 900:
button = 6;
break;
}
bool sw7 = digitalRead(sw7pin);
if (!sw7)
{
sw7status = LOW; // holds switch status LOW until it has been used in the main loop
}
bool sw8 = digitalRead(sw8pin);
if (!sw8)
{
sw8status = LOW; // holds switch status LOW until it has been used in the main loop
}
bool sw9 = digitalRead(sw9pin);
if (!sw9)
{
sw9status = LOW; // holds switch status LOW until it has been used in the main loop
}
}
// Increment the clock driven by RTC 1Hz square wave interrupt
void incrementSeconds()
{
if (ss == 59) {
if (mm == 59) {
hh = (hh + 1) % 24; // if second = 59 AND minute = 59, increment the hour, modulo 24
}
mm = (mm + 1) % 60; // if second = 59, increment the minute, modulo 60
}
ss = (ss + 1) % 60; // increment the second, modulo 60
}
// Draw main display
void drawMainDisplay()
{
// Initial display setup
display.drawFastVLine(41, 0, 10, BLACK);
display.drawFastVLine(24, 10, 21, BLACK);
display.drawFastVLine(59, 10, 21, BLACK);
display.drawFastHLine(0, 9, display.width(), BLACK);
display.drawFastHLine(0, 20, 24, BLACK);
display.drawFastHLine(60, 20, 24, BLACK);
display.drawFastHLine(0, 30, 24, BLACK);
display.drawFastHLine(60, 30, 24, BLACK);
// Update the ABC keys
displayABCkeys();
// write to display
display.display();
}
// Cycle through soft-key pages
void changePage()
{
if (sw9status == LOW) { // if SHIFT key is down, draw the location/time expansion page
expansionPage = 1;
display.clearDisplay();
display.setCursor(0, 11);
display.print("Time:");
// Time value printed in main loop
display.setCursor(0, 31);
display.print("Page reserved");
display.setCursor(0, 41);
display.print("for expansion!");
}
else {
if (expansionPage != 1) { // if we're not coming from the expansion page...
currentPage = ++currentPage % 3; // ...increment the current page (3 pages)
}
else { // if we are coming from the expansion page we need to...
display.clearDisplay(); // ...clear the display
display.display();
drawMainDisplay();
}
expansionPage = 0; // set expansionPage to false
// Label the soft keys
// may update this when I implement multiple pages of soft-keys...
if (currentPage == 0)
{
display.setTextSize(1);
//Button 1
display.setCursor(5, 0);
display.print(page0SoftkeyLabel1);
//Button 2
display.setCursor(5, 11);
display.print(page0SoftkeyLabel2);
//Button 3
display.setCursor(5, 22);
display.print(page0SoftkeyLabel3);
//Button 4
display.setCursor(44, 0);
display.print(page0SoftkeyLabel4);
//Button 5
display.setCursor(62, 11);
display.print(page0SoftkeyLabel5);
//Button 6
display.setCursor(62, 22);
display.print(page0SoftkeyLabel6);
}
else if (currentPage ==1)
{
display.setTextSize(1);
//Button 1
display.setCursor(5, 0);
display.print(page1SoftkeyLabel1);
//Button 2
display.setCursor(5, 11);
display.print(page1SoftkeyLabel2);
//Button 3
display.setCursor(5, 22);
display.print(page1SoftkeyLabel3);
//Button 4
display.setCursor(44, 0);
display.print(page1SoftkeyLabel4);
//Button 5
display.setCursor(62, 11);
display.print(page1SoftkeyLabel5);
//Button 6
display.setCursor(62, 22);
display.print(page1SoftkeyLabel6);
}
else if (currentPage ==2)
{
display.setTextSize(1);
//Button 1
display.setCursor(5, 0);
display.print(page2SoftkeyLabel1);
//Button 2
display.setCursor(5, 11);
display.print(page2SoftkeyLabel2);
//Button 3
display.setCursor(5, 22);
display.print(page2SoftkeyLabel3);
//Button 4
display.setCursor(44, 0);
display.print(page2SoftkeyLabel4);
//Button 5
display.setCursor(62, 11);
display.print(page2SoftkeyLabel5);
//Button 6
display.setCursor(62, 22);
display.print(page2SoftkeyLabel6);
}
// Update the soft-key status indicators
if (currentPage == 0)
{
softkeyStatus[0] = page0SoftkeyStatus1();
softkeyStatus[1] = page0SoftkeyStatus2();
softkeyStatus[2] = page0SoftkeyStatus3();
softkeyStatus[3] = page0SoftkeyStatus4();
softkeyStatus[4] = page0SoftkeyStatus5();
softkeyStatus[5] = page0SoftkeyStatus6();
}
else if (currentPage == 1)
{
softkeyStatus[0] = page1SoftkeyStatus1();
softkeyStatus[1] = page1SoftkeyStatus2();
softkeyStatus[2] = page1SoftkeyStatus3();
softkeyStatus[3] = page1SoftkeyStatus4();
softkeyStatus[4] = page1SoftkeyStatus5();
softkeyStatus[5] = page1SoftkeyStatus6();
}
else if (currentPage == 2)
{
softkeyStatus[0] = page2SoftkeyStatus1();
softkeyStatus[1] = page2SoftkeyStatus2();
softkeyStatus[2] = page2SoftkeyStatus3();
softkeyStatus[3] = page2SoftkeyStatus4();
softkeyStatus[4] = page2SoftkeyStatus5();
softkeyStatus[5] = page2SoftkeyStatus6();
}
// Display the soft-key indicators
displaySoftKeyStatus();
}
}
void displaySoftKeyStatus()
{
// Display the soft-key status indicators
if (softkeyStatus[0])
{
display.drawFastVLine(0, 0, 9, BLACK);
display.drawFastVLine(1, 0, 9, BLACK);
display.drawFastVLine(2, 0, 9, BLACK);
}
else
{
display.drawFastVLine(0, 0, 9, WHITE);
display.drawFastVLine(1, 0, 9, WHITE);
display.drawFastVLine(2, 0, 9, WHITE);
}
if (softkeyStatus[1])
{
display.drawFastVLine(0, 10, 10, BLACK);
display.drawFastVLine(1, 10, 10, BLACK);
display.drawFastVLine(2, 10, 10, BLACK);
}
else
{
display.drawFastVLine(0, 10, 10, WHITE);
display.drawFastVLine(1, 10, 10, WHITE);
display.drawFastVLine(2, 10, 10, WHITE);
}
if (softkeyStatus[2])
{
display.drawFastVLine(0, 21, 9, BLACK);
display.drawFastVLine(1, 21, 9, BLACK);
display.drawFastVLine(2, 21, 9, BLACK);
}
else
{
display.drawFastVLine(0, 21, 9, WHITE);
display.drawFastVLine(1, 21, 9, WHITE);
display.drawFastVLine(2, 21, 9, WHITE);
}
if (softkeyStatus[3])
{
display.drawFastVLine(83, 0, 9, BLACK);
display.drawFastVLine(82, 0, 9, BLACK);
display.drawFastVLine(81, 0, 9, BLACK);
}
else
{
display.drawFastVLine(83, 0, 9, WHITE);
display.drawFastVLine(82, 0, 9, WHITE);
display.drawFastVLine(81, 0, 9, WHITE);
}
if (softkeyStatus[4])
{
display.drawFastVLine(83, 10, 10, BLACK);
display.drawFastVLine(82, 10, 10, BLACK);
display.drawFastVLine(81, 10, 10, BLACK);
}
else
{
display.drawFastVLine(83, 10, 10, WHITE);
display.drawFastVLine(82, 10, 10, WHITE);
display.drawFastVLine(81, 10, 10, WHITE);
}
if (softkeyStatus[5])
{
display.drawFastVLine(83, 21, 9, BLACK);
display.drawFastVLine(82, 21, 9, BLACK);
display.drawFastVLine(81, 21, 9, BLACK);
}
else
{
display.drawFastVLine(83, 21, 9, WHITE);
display.drawFastVLine(82, 21, 9, WHITE);
display.drawFastVLine(81, 21, 9, WHITE);
}
}
// LIGHT = timed backlight, SHIFT+LIGHT = toggle backlight
void backlight()
{
if (backlightStatus == 1) // if backlight is already on, turn it off
{
digitalWrite(backlightPin, 0);
backlightStatus = 0;
timedBacklight = 0;
backlightCounter = 0;
}
else if (sw9status == LOW) // if SHIFT key is down, turn backlight on
{
digitalWrite(backlightPin, 1);
backlightStatus = 1;
}
else // if SHIFT key is not down, begin a timed backlight
{
timedBacklight = 1;
backlightCounter = 4; // set the backlight counter to a number, this will be counted down in the main loop
digitalWrite(backlightPin, 1);
backlightStatus = 1;
}
}
// Functions to trigger K1EL K16 keyer button input
void pressKeyerSw1()
{
digitalWrite(keyerSw1, HIGH);
delay(200);
digitalWrite(keyerSw1, LOW);
}
void pressKeyerSw2()
{
digitalWrite(keyerSw2, HIGH);
delay(200);
digitalWrite(keyerSw2, LOW);
}
void pressKeyerSw3()
{
digitalWrite(keyerSw3, HIGH);
delay(200);
digitalWrite(keyerSw3, LOW);
}
void pressKeyerSw4()
{
digitalWrite(keyerSw4, HIGH);
delay(200);
digitalWrite(keyerSw4, LOW);
}
void longPressKeyerSw1() // long press of KeyerSw1 = "CMD"
{
digitalWrite(keyerSw1, HIGH);
delay(1600);
digitalWrite(keyerSw1, LOW);
}
// USER FUNCTIONS
// Single functions from the ft817 library can be called straight from the pageXSoftKeyFunctionY function above
// or, if the desired function is a combination of actions, define a function below to be called by the sketch.
void tuneSignalOn()
{
sw9status = digitalRead(sw9pin);
if (sw9status == LOW) // is SHIFT key held down? (safety measure)
{
// Store current operating base mode i.e. ignoring the NAR mode codes
modeReturn = modeBase;
// Set mode to AM
radio.setMode(CAT_MODE_AM);
delay(200);
// Set PTT to ON
radio.PTT(true);
}
}
void tuneSignalOff()
{
// Set PTT to OFF
radio.PTT(false);
delay(200);
// Set mode to <retrieve from modeReturn>
radio.setMode(modeReturn);
}
void displayABCkeys() // includes EEPROM read
{
byte currentAbcKeys = radio.getDisplaySelection();
abcKeys = currentAbcKeys; // originally this function only updated the display if the abcKeys value changed (was continuously monitored)
// Print current ABC keys
display.setCursor(0, 41);
display.setTextSize(1);
display.setTextColor(BLACK, WHITE);
switch (abcKeys) {
case B0000:
display.print(" A/B A=B SPL");
break;
case B0001:
display.print(" MW MC TAG");
break;
case B0010:
display.print(" STO RCL PMS");
break;
case B0011:
display.print(" RPT REV TON");
break;
case B0100:
display.print(" SCN PRI DW ");
break;
case B0101:
display.print(" SSM SCH ART");
break;
case B0110:
display.print(" IPO ATT NAR");
break;
case B0111:
display.print(" NB AGC ");
break;
case B1000:
display.print(" PWR MTR ");
break;
case B1001:
display.print(" VOX BK KYR");
break;
case B1010:
display.print(" CHG VLT DSP");
break;
case B1011:
display.print(" TCH DCH ");
break;
}
}
// g7uhn TO DO: surely this function can be better performed by some kind of lookup table?
void getReadableMode() {
modeByte = radio.getMode();
if (modeByte == 0x00) {
mode = "LSB ";
modeBase = modeByte;
}
else if (modeByte == 0x01) {
mode = "USB ";
modeBase = modeByte;
}
else if (modeByte == 0x02) {
mode = "CW ";
modeBase = modeByte;
}
else if (modeByte == 0x03) {
mode = "CWR ";
modeBase = modeByte;
}
else if (modeByte == 0x82) {
mode = "CW N ";
modeBase = 0x02;
}
else if (modeByte == 0x83) {
mode = "CWR N";
modeBase = 0x03;
}
else if (modeByte == 0x8A) {
mode = "DIG N";
modeBase = 0x0A;
}
else if (modeByte == 0x04) {
mode = "AM ";
modeBase = modeByte;
}
else if (modeByte == 0x06) {
mode = "WFM ";
modeBase = modeByte;
}
else if (modeByte == 0x08) {
mode = "FM ";
modeBase = modeByte;
}
else if (modeByte == 0x88) { // this one wasn't listed in the spec?
mode = "FM-N ";
modeBase = modeByte;
}
else if (modeByte == 0x0A) {
mode = "DIG ";
modeBase = modeByte;
}
else if (modeByte == 0x0C) {
mode = "PKT ";
modeBase = modeByte;
}
else {
mode = "???";
}
}