Sorry, I guess I should have posted my code, but it seems fairly involved...
As I mentioned, when I load the same file (modified slightly) into the ESP32, the Read Frequency command is answered quite promptly. When I read through the MEGA(2560) & the HC-05, I (typically) get a 4 second timeout, retry, another command retry, and a 4 second timeout, and finally the response.
Because of the delays, I had to build in the "WAIT" period to wait for the response. (kludge...)
When I spin the dial (the radio transmits each update, quite quickly). The ESP32 seems to be able to keep up, whereas the MEGA/HC-05 drops out after a few seconds and picks up again...
void setup()
{
Serial.begin(115200);
Serial3.begin(38400); //Default Baud for BT comm
Serial.println("Setup");
Serial.println(F(" 'r' Read Frequency,"));
Serial.println(F(" 'p' processCatMessages."));
}
//IC-705 Settings:
// Settings, Bluetooth, Data Device Set, Serialport Function: CI-V(Echo Back OFF)
void loop() {
ReadMonitor();
}
void ReadMonitor() {
//Read the Character from the input:
if (Serial.available() > 0) { // is a character available?
unsigned long StartTime = millis();
uint32_t rx_byte = Serial.read(); // get the character
// check if a Char was received
if (rx_byte == 'r') {
Serial.println(F("COMMAND: 'r', Read The Frequency."));
uint32_t Freq = CIV_Read_Frequency();
Serial.print(F("OUTCOME: Frequency = ")); Serial.println(Freq);
Serial.println();
}
else if (rx_byte == 'p') {
Serial.println(F("COMMAND: 'p', ProcessCatMessages (60 seconds)."));
do {
uint32_t Frequency = processCatMessages(false);
if (Frequency > 1000) {
Serial.print(F(" Freq = ")); Serial.println(Frequency);
}
//When the CheckSpin is done, re-read the frequency:
if (CheckSpin()) {
Serial.print(F(" CheckSpin Timeout: Freq = ")); Serial.println(Frequency);
//Manually read the frequency:
Frequency = CIV_Read_Frequency();
}
delay(10);
} while ((millis() - StartTime) < 60000);
Serial.println(F("OUTCOME: 60 Seconds Complete "));
Serial.println();
}
Serial.print(F(" Runtime = ")); Serial.println(millis() - StartTime); Serial.println();
} // end: if (Serial.available() > 0)
}
The Other file with all the meat in it...
uint8_t RADIO_ADDRESS = 0xA4; //Transiever address
const byte BROADCAST_ADDRESS = 0x00; //Broadcast address
const byte CONTROLLER_ADDRESS = 0xE0; //Controller address
const byte START_BYTE = 0xFE; //Start byte
const byte STOP_BYTE = 0xFD; //Stop byte
const byte CMD_READ_FREQ = 0x03; //Read operating frequency data
const byte CMD_TRANSCEIVE_FREQ = 0x00;
const byte AckMsg = 0xFB; //Received an ACK from the ICOM rig.
const byte NacMsg = 0xFA; //Receive a "Not Good" message from the rig.
const uint32_t decMulti[] = {1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1};
uint32_t readtimeout = 5000; //Serial port read timeout, Not sure what to set at, trying 5 seconds. (Mike 10/23/21)
int gDialSpin = 0; // Transceive mode, we stop decoding the frequency, then read Frequency 5 seconds later after the updates stop.
uint32_t processCatMessages(boolean WaitCmd) {
//Set WaitCmd to 'true' if a SPECIFIC command was sent, and you are waiting for a response.
//Set WaitCmd to 'false' if you are just checking the buffer (i.e.:Transceive Mode).
//Returns the data Read from: Frequency,
uint8_t read_buffer[12]; //Read buffer
byte Count = 0;
//A SPECIFIC command was sent, wait for the response!
if (WaitCmd) {
unsigned long StartWait = millis();
do {
delay(20);
Count++;
} while ((Serial3.available() == 0) && (Count < 200)); //Count limited to 255
Serial.print(F(" processCatMessages Count = ")); Serial.print(Count); Serial.print(F(" Out of 200."));
Serial.print(F(" Wait Time = ")); Serial.println(millis() - StartWait);
if (Serial3.available() == 0) return 0;
}
while (Serial3.available()) {
if (readLine(read_buffer, sizeof(read_buffer)) > 0) {
if (read_buffer[0] == START_BYTE && read_buffer[1] == START_BYTE) {
if ((read_buffer[3] == RADIO_ADDRESS) || (read_buffer[4] == RADIO_ADDRESS)) {
if ((read_buffer[2] == BROADCAST_ADDRESS) || (read_buffer[2] == CONTROLLER_ADDRESS)) {
switch (read_buffer[4]) {
case CMD_TRANSCEIVE_FREQ: //0x00
case CMD_READ_FREQ: { //0x03
if (gDialSpin == 0) {
//Dial is not spinning, decode the frequency:
Serial.print(F("gDialSpin =")); Serial.print(gDialSpin);
gDialSpin++;
Serial.print(F(" gDialSpin updated to: =")); Serial.println(gDialSpin);
return printFrequency(read_buffer);
}
else {
//Add to the global int gDialSpin.
gDialSpin++;
Serial.print("*");
return 0;
}
break;
}
case AckMsg: { //Ack Message (FB) from ICOM
Serial.println(F(" FB Recieved, Returned 255."));
return 255;
}
case NacMsg: { //Ack Message (FA) from ICOM
Serial.println(F(" FB Recieved, Returned 254."));
return 254;
}
default: {
//Any other messages that may come through, print them out...
Serial.print(" ## ERROR? Default <");
for (uint8_t i = 0; i < sizeof(read_buffer); i++) {
if (read_buffer[i] < 16)Serial.print("0");
Serial.print(read_buffer[i], HEX);
Serial.print(" ");
if (read_buffer[i] == STOP_BYTE) break;
}
Serial.println(">");
break;
}
}
}
}
}
}
}
return 0;
}
uint8_t readLine(uint8_t buffer[], uint8_t ArraySize) {
//This function reads the line from the CIV Buffer and returns it in the 'buffer[]' array.
// NOTE: I don't think the Timeout is required at all.
uint8_t NextByte;
uint8_t counter = 0;
uint32_t ed = readtimeout;
while (true)
{
while (!Serial3.available()) {
if (--ed == 0)return 0;
}
ed = readtimeout;
NextByte = Serial3.read(); // Read 1 byte at a time.
// NOT SURE WHAT THIS DOES, I don't think the '0xFF' is used! Mike 11/6/21
//if (NextByte == 0xFF) continue; //TODO skip to start byte instead
buffer[counter++] = NextByte;
if (STOP_BYTE == NextByte) break;
if (counter >= ArraySize) return 0;
}
//Temporarily, print out ALL lines that are received.
Serial.print(" ####### readLine Data<");
for (uint8_t i = 0; i < counter; i++) {
if (buffer[i] < 16)Serial.print("0");
Serial.print(buffer[i], HEX);
Serial.print(" ");
if (buffer[i] == STOP_BYTE)break;
}
Serial.println(">");
return counter;
}
uint32_t printFrequency(uint8_t buffer[]) {
uint32_t frequency = 0;
//Freq<FE FE E0 A4 03 00 00 00 01 00 FD> 1.0 MHz
//Freq<FE FE E0 A4 03 00 00 00 33 04 FD> 433.0 MHz
//Start at the Right most digit, read_buffer[9] (MSD):
for (uint8_t i = 0; i < 5; i++) {
if (buffer[9 - i] == 0xFD) continue; //End of Message, break out of loop...
frequency += (buffer[9 - i] >> 4) * decMulti[i * 2];
frequency += (buffer[9 - i] & 0x0F) * decMulti[i * 2 + 1];
}
//We divide by 1000 to give freq in KHz. Precision is not requried.
frequency = frequency / 1000;
return frequency;
}
void CivSendCmd(uint8_t buffer[], uint8_t ArraySize) {
//This functiobn is used to SEND the commands (from the 'buffer[]' to the CIV port
Serial.print(F(" SEND CMD: <"));
for (uint8_t i = 0; i < ArraySize; i++) {
Serial3.write(buffer[i]);
Serial.print(buffer[i], HEX); Serial.print(" ");
}
Serial.println(F("> SEND Command Complete"));
}
boolean WaitOkMsg(void) {
//If a command was send that does NOT expect specific data return, then we wait for the OK Message (FB) return data.
// If the command failed, then the Message NG "FA" will be returned.
uint8_t Return;
Return = processCatMessages(true);
if (Return == 255) {
Serial.println(F(" GOT RETURN OF 255 After Command"));
return false;
}
else if (Return == 254) {
Serial.println(F(" ERROR, NG CODE OF 254 (NacMsg) After Command"));
return true;
}
else {
Serial.println(F(" ERROR, NO RETURN of OK Message After Command"));
return true;
}
}
boolean CheckSpin(void) {
//When the dial is spinning, the frequencies change so fast, we can't keep up (don't need to!), so we stop decoding the Frequencies.
// This function is only called when the Frequency is changed in Transceive mode.
static unsigned long StartSpin;
static int LastDialSpin;
if (gDialSpin == 0) {
//Frequency changed and global gDialSpin==0
// Start the timer
StartSpin = millis();
LastDialSpin = gDialSpin;
return false;
}
else {
//Frequency changed again, or we are just checking for state...
if (((millis() - StartSpin) > 5000) && (LastDialSpin == gDialSpin)) {
//Return true will trigger a manual Read of the Frequency.
Serial.println(F(" $$$$ Return Timeout, > 5 Sec."));
gDialSpin = 0;
StartSpin = millis();
return true;
}
if (LastDialSpin != gDialSpin) {
Serial.print(F(" LastDialSpin="));
Serial.print(LastDialSpin);
Serial.print("/");
Serial.println(gDialSpin);
}
LastDialSpin = gDialSpin;
return false;
}
}
uint32_t CIV_Read_Frequency(void) {
//Don't Read the message, it will be picked up by the normal processCatMessages() loop...
//Construct the message to read the frequency
byte ReadFreq[] = {START_BYTE, START_BYTE, RADIO_ADDRESS, CONTROLLER_ADDRESS, CMD_READ_FREQ, STOP_BYTE};
uint32_t ReturnFreq = 0;
byte Count = 0;
do
{
//Send the message
CivSendCmd(ReadFreq, sizeof(ReadFreq));
//Decode the returned message
ReturnFreq = processCatMessages(true);
Serial.print(F(" CIV_Read_Frequency read: ")); Serial.print(ReturnFreq); Serial.print(F(" Count = ")); Serial.println(Count);
Count++;
} while ((ReturnFreq < 1000) && (Count < 5)); //Expect the Frequency to be > 1.0 MHz.
Serial.print(F(" CIV_Read_Frequency read: ")); Serial.println(ReturnFreq);
//Manual Read the the frequency always clears the gDialSpin variable.
gDialSpin = 0;
return ReturnFreq;
}