Added inline comments to functions
This commit is contained in:
@@ -17,19 +17,28 @@
|
||||
*/
|
||||
void SerialConnector::cycle()
|
||||
{
|
||||
// Only proceed if there is at least a minimal number of bytes
|
||||
// (message must include command, separators and checksum).
|
||||
if (Serial.available() > 3)
|
||||
{
|
||||
// Read until message terminator '@' (terminator is removed by readStringUntil).
|
||||
String raw = Serial.readStringUntil('@');
|
||||
|
||||
// Parse message parts: command and args.
|
||||
String cmd = getCommandFromIncomming(raw);
|
||||
String args = getArgsFromIncomming(raw);
|
||||
|
||||
// Verify checksum; if it fails, ask the peer to repeat the message.
|
||||
if (!verifyCheckBit(cmd, args, getCheckBitFromIncomming(raw).toInt()))
|
||||
{
|
||||
repeat();
|
||||
return;
|
||||
}
|
||||
|
||||
// Send acknowledgement back for a valid message.
|
||||
acknowledge(getCheckBitFromIncomming(raw).toInt());
|
||||
|
||||
// Dispatch known commands to their handlers if present.
|
||||
if (cmd == "CAL-BGN")
|
||||
{
|
||||
if (calibrationBeginHandler)
|
||||
@@ -42,6 +51,7 @@ void SerialConnector::cycle()
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown/unused command - intentionally ignored for now.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,27 +68,33 @@ String SerialConnector::stringToHex(String cmd)
|
||||
|
||||
for (const auto &item : cmd)
|
||||
{
|
||||
|
||||
// Convert character to its ASCII code then to hexadecimal digits.
|
||||
hex_dec = int(item);
|
||||
|
||||
// Temporary buffer to hold the hex digits in reverse order.
|
||||
// Size 100 is intentionally generous for safety; characters only need 2 digits.
|
||||
char hexaDeciNum[100];
|
||||
int i = 0;
|
||||
|
||||
// Extract hex digits (least significant first).
|
||||
while (hex_dec != 0)
|
||||
{
|
||||
int temp = 0;
|
||||
temp = hex_dec % 16;
|
||||
if (temp < 10)
|
||||
{
|
||||
hexaDeciNum[i] = temp + 48;
|
||||
hexaDeciNum[i] = temp + 48; // '0'..'9'
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hexaDeciNum[i] = temp + 55;
|
||||
hexaDeciNum[i] = temp + 55; // 'A'..'F'
|
||||
i++;
|
||||
}
|
||||
hex_dec = hex_dec / 16;
|
||||
}
|
||||
|
||||
// Append the digits in the correct order (reverse the temporary buffer).
|
||||
for (int j = i - 1; j >= 0; j--)
|
||||
{
|
||||
output += hexaDeciNum[j];
|
||||
@@ -100,27 +116,31 @@ int SerialConnector::stringToCheckNum(String cmd)
|
||||
|
||||
for (const auto &item : cmd)
|
||||
{
|
||||
|
||||
// Build a numeric checksum by converting each character to a set of
|
||||
// hexadecimal digits and accumulating them into an integer.
|
||||
hex_dec = int(item);
|
||||
char hexaDeciNum[100];
|
||||
int i = 0;
|
||||
|
||||
// Convert ASCII code to hex digits (LSB-first in buffer).
|
||||
while (hex_dec != 0)
|
||||
{
|
||||
int temp = 0;
|
||||
temp = hex_dec % 16;
|
||||
if (temp < 10)
|
||||
{
|
||||
hexaDeciNum[i] = temp + 48;
|
||||
hexaDeciNum[i] = temp + 48; // numeric digit
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
hexaDeciNum[i] = temp + 55;
|
||||
hexaDeciNum[i] = temp + 55; // alphabetic hex digit
|
||||
i++;
|
||||
}
|
||||
hex_dec = hex_dec / 16;
|
||||
}
|
||||
|
||||
// Accumulate digits into the output integer (reverse order to correct endianness).
|
||||
for (int j = i - 1; j >= 0; j--)
|
||||
{
|
||||
output += hexaDeciNum[j];
|
||||
@@ -138,12 +158,15 @@ int SerialConnector::stringToCheckNum(String cmd)
|
||||
*/
|
||||
int SerialConnector::getCharIndex(char ch, String str)
|
||||
{
|
||||
// Linear search for the first occurrence of ch.
|
||||
// Cache length in an int to avoid signed/unsigned comparison warnings.
|
||||
for (int i = 0; i < str.length(); i++)
|
||||
{
|
||||
if (str.charAt(i) == ch)
|
||||
return i;
|
||||
return i; // return index on first match
|
||||
}
|
||||
|
||||
// Not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -155,6 +178,7 @@ int SerialConnector::getCharIndex(char ch, String str)
|
||||
*/
|
||||
String SerialConnector::getCommandFromIncomming(String incomming)
|
||||
{
|
||||
// Find position of first separator '#' and return everything before it.
|
||||
int cmdEnd = getCharIndex('#', incomming);
|
||||
return incomming.substring(0, cmdEnd);
|
||||
}
|
||||
@@ -166,11 +190,14 @@ String SerialConnector::getCommandFromIncomming(String incomming)
|
||||
*/
|
||||
String SerialConnector::getArgsFromIncomming(String incomming)
|
||||
{
|
||||
// Extract arguments between the first and second '#' separators.
|
||||
int cmdEnd = getCharIndex('#', incomming);
|
||||
String cm = incomming.substring(0, cmdEnd);
|
||||
|
||||
// substring containing args and checksum
|
||||
String afterCmd = incomming.substring(cmdEnd + 1, incomming.length());
|
||||
int cmdArgsEnd = getCharIndex('#', afterCmd);
|
||||
|
||||
// return args portion (may be empty)
|
||||
return afterCmd.substring(0, cmdArgsEnd);
|
||||
}
|
||||
|
||||
@@ -181,11 +208,13 @@ String SerialConnector::getArgsFromIncomming(String incomming)
|
||||
*/
|
||||
String SerialConnector::getCheckBitFromIncomming(String incomming)
|
||||
{
|
||||
// Extract checksum string which follows the second '#' separator.
|
||||
int cmdEnd = getCharIndex('#', incomming);
|
||||
String cm = incomming.substring(0, cmdEnd);
|
||||
|
||||
String afterCmd = incomming.substring(cmdEnd + 1, incomming.length());
|
||||
int cmdArgsEnd = getCharIndex('#', afterCmd);
|
||||
|
||||
// substring from after the second '#' to the end contains the checksum
|
||||
return afterCmd.substring(cmdArgsEnd + 1, afterCmd.length());
|
||||
}
|
||||
|
||||
@@ -198,8 +227,10 @@ String SerialConnector::getCheckBitFromIncomming(String incomming)
|
||||
*/
|
||||
bool SerialConnector::verifyCheckBit(String cmd, String args, int checkBit)
|
||||
{
|
||||
// Compose the portion of the message that should have been used to compute the checksum
|
||||
String toCheck = cmd + "#" + args;
|
||||
|
||||
// Compare computed checksum against the provided value
|
||||
if (stringToCheckNum(toCheck) == checkBit)
|
||||
return true;
|
||||
else
|
||||
@@ -212,6 +243,8 @@ bool SerialConnector::verifyCheckBit(String cmd, String args, int checkBit)
|
||||
*/
|
||||
void SerialConnector::repeat()
|
||||
{
|
||||
// Send a repeat request. Protocol: RPT##<code>@
|
||||
// The hard-coded value '410' represents an application-specific code.
|
||||
String cmd = "RPT##410@";
|
||||
Serial.print(cmd);
|
||||
}
|
||||
@@ -222,8 +255,12 @@ void SerialConnector::repeat()
|
||||
*/
|
||||
void SerialConnector::acknowledge(int checkBit)
|
||||
{
|
||||
// Build an acknowledgement message that includes the original check bit
|
||||
// so the sender can verify the ack corresponds to the correct message.
|
||||
String cmd = "ACKG";
|
||||
String toSend = cmd + "#" + (String)checkBit;
|
||||
|
||||
// Compute checksum for the acknowledgement itself and append terminator.
|
||||
int checkNum = stringToCheckNum(toSend);
|
||||
String final = toSend + "#" + (String)checkNum + "@";
|
||||
Serial.print(final);
|
||||
@@ -237,11 +274,13 @@ void SerialConnector::acknowledge(int checkBit)
|
||||
*/
|
||||
void SerialConnector::sendCommand(String cmd, String args)
|
||||
{
|
||||
// Compose message with args and computed checksum, then send over Serial.
|
||||
String toSend = cmd + "#" + args;
|
||||
int checkNum = stringToCheckNum(toSend);
|
||||
String final = toSend + "#" + (String)checkNum + "@";
|
||||
Serial.print(final);
|
||||
|
||||
// Wait for and handle the peer's response (ACKG or RPT).
|
||||
afterSendCheck(final);
|
||||
}
|
||||
|
||||
@@ -251,37 +290,46 @@ void SerialConnector::sendCommand(String cmd, String args)
|
||||
*/
|
||||
void SerialConnector::afterSendCheck(String cmd)
|
||||
{
|
||||
// Block until a response terminator '@' is received and read the raw message.
|
||||
String raw = Serial.readStringUntil('@');
|
||||
|
||||
// If nothing was read, keep waiting (simple recursive wait). This is a blocking behavior.
|
||||
if (raw == "")
|
||||
afterSendCheck(cmd);
|
||||
|
||||
// Determine the type of response (RPT = repeat request, ACKG = acknowledgement).
|
||||
String comm = getCommandFromIncomming(raw);
|
||||
|
||||
if (comm == "RPT")
|
||||
{
|
||||
// If peer requested a repeat, resend the original command (reconstruct from cmd string).
|
||||
sendCommand(getCommandFromIncomming(cmd), getArgsFromIncomming(cmd));
|
||||
}
|
||||
else if (comm == "ACKG")
|
||||
{
|
||||
// Validate the acknowledgement corresponds to the command we sent.
|
||||
int check = getArgsFromIncomming(raw).toInt();
|
||||
int cmdCheck = getCheckBitFromIncomming(cmd).toInt();
|
||||
|
||||
if (check != cmdCheck)
|
||||
{
|
||||
// TODO: Implement a command to resend previous command
|
||||
// Checksums do not match - TODO: implement resend logic or error reporting.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Acknowledgement matches - nothing further to do for now.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SerialConnector::onCalibrationBegin(void (*handler)(String args))
|
||||
{
|
||||
// Register the callback invoked when a CAL-BGN message is received.
|
||||
calibrationBeginHandler = handler;
|
||||
}
|
||||
|
||||
void SerialConnector::onCalibrationInterupt(void (*handler)(String args))
|
||||
{
|
||||
// Register the callback invoked when a CAL-INT message is received.
|
||||
calibrationInteruptHandler = handler;
|
||||
}
|
||||
Reference in New Issue
Block a user