Continuing move to both OO interface and consolidation of commands into Subsystem, Command rather than all discrete commands.

This commit is contained in:
2026-01-26 13:42:28 -06:00
parent 152e0c2d80
commit 4e0035bea6
5 changed files with 374 additions and 188 deletions

View File

@@ -7,6 +7,8 @@
#include <memory.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include "AVRInterface.h"
#include "AVRCommandDecoder.h"
@@ -60,6 +62,11 @@ static const Message_T AVRCommands[] = {
{ eUnMute, "\x02" "07EA3" "\x03", 7 },
};
// This is based on the longest thing from the MessageHandlers text field and the generated text
// "MultiCh Surround" "Surround"
const char *PCMessageFormat = "%18s %-20s";
const uint8_t LengthCheck = 40;
// rCmd: 2-ASCII Hex Bytes converted to uint8_t
// configOffset: offset into avrStatus.config.DTxx
// numToTransfer: number of bytes to transfer from message to config (0 = none)
@@ -117,7 +124,7 @@ static const MessageHandler_T MessageHandlers[] = {
{ 0x3B, 44, 1, 1, "DC2 Trigger Control: %s", WhichZoneText },
{ 0x3C, 45, 1, 1, "DC2 Trigger Out: %s", OffOnText },
{ 0x3D, 104, 0, 0, "Main Level: %s", Norm10dbDownText },
{ 0x3E, 46, 1, 1, "SP B Set: %s", MainZoneBText },
{ 0x3E, 46, 1, 1, "SP B Set: %s", Zone1Zone2Text },
{ 0x3F, 47, 1, 1, "Zone 2 Speaker: %s", OffOnText },
{ 0x40, 48, 2, 1, "Level Main R: %s", PM10dbText },
@@ -210,8 +217,62 @@ bool AVRInterface::IsSanityCheckOK() {
return true;
}
// MessageReport
//
// Generate a text record to provide buffer to the console, translating non-printable
// characters into hex codes enclosed in square brackets.
//
// Consider line-wrapping to align the next line
//
void AVRInterface::MessageReport(const char *prefix, const void *buf, size_t len) {
int i = 0;
const char *p = (const char *)buf;
uint32_t now_ms = lastTick_ms;
char txtBuf[LONGESTTEXT] = "";
char smallBuf[10] = "";
char *pTxtAppend = txtBuf;
if (len == 0) len = strlen(p);
pTxtAppend += sprintf_s(txtBuf, LONGESTTEXT, "%9.3f: [%3d]%s", (float)(now_ms - firstTick_ms) / 1000.0f, (int)strlen(p), prefix);
while (*p && ((unsigned)(p - (const char *)buf) < len)) {
if (isprint(*p)) {
*pTxtAppend++ = *p;
*pTxtAppend = 0; // Keep it null-terminated
i++;
} else if (*p == '\r') {
(*ReportInformation)(mtInfo, txtBuf);
txtBuf[0] = 0; // clear it
} else if (*p == '\n') {
// skip it
} else {
sprintf_s(smallBuf, 10, "[%02X]", (unsigned char)*p);
strcat_s(txtBuf, LONGESTTEXT, smallBuf);
pTxtAppend = txtBuf + strlen(txtBuf);
}
if ((i & 3) == 0) {
if (strlen(txtBuf) > 100) {
(*ReportInformation)(mtInfo, txtBuf);
sprintf_s(txtBuf, LONGESTTEXT, " "); // new line
pTxtAppend = txtBuf + strlen(txtBuf);
} else {
strcat_s(txtBuf, LONGESTTEXT, " ");
pTxtAppend++;
}
i = 0;
}
p++;
}
if (strlen(txtBuf)) {
(*ReportInformation)(mtInfo, txtBuf);
}
}
void AVRInterface::Tick(uint32_t now_ms) {
lastTick_ms = now_ms;
uint32_t elapsed_ms = now_ms - sentAtTime_ms;
char buf[LONGESTTEXT] = "";
if (oldState != state && ReportInformation) {
oldState = state;
@@ -259,7 +320,8 @@ void AVRInterface::Tick(uint32_t now_ms) {
/// @brief Handle a just received message by parsing it
///
/// Given a response string, typically of the form:
/// [11] .... [03]
/// [02] .... [03] // Command Responses from the AVR
/// [11] .... [03] // Commands to
/// [12] .... [03]
/// [14] ............ [03]
///
@@ -270,6 +332,7 @@ void AVRInterface::Tick(uint32_t now_ms) {
bool AVRInterface::HandleMessage(const uint8_t *buffer, uint16_t len) {
bool showAllFlag = false;
MessageReport("<", buffer, len);
switch (state) {
case stAwaitingReadyResponse:
switch (buffer[0]) {
@@ -278,6 +341,7 @@ bool AVRInterface::HandleMessage(const uint8_t *buffer, uint16_t len) {
showAllFlag = ProcessReportResponse(buffer, len);
break;
case 0x11: // DC1 <msg> ETX
// AVR does not send any DC1 messages, these are for commands to the AVR
break;
case 0x12: // DC2 <msg> ETX
if (CheckTheChecksum(buffer, len)) {
@@ -359,9 +423,9 @@ bool AVRInterface::Initialize() {
bool AVRInterface::IsOnline() {
return true;
}
bool AVRInterface::Power(AVRPower_T cmd) {
bool AVRInterface::Power(AVROnOff_E cmd) {
commandResponseReceived = false;
if (cmd == avrPowerOn)
if (cmd == eOn)
ProcessSerialQueue(AVRCommands[ePowerOn].pMsg, AVRCommands[ePowerOn].MsgLen);
else
ProcessSerialQueue(AVRCommands[ePowerOff].pMsg, AVRCommands[ePowerOff].MsgLen);
@@ -369,10 +433,19 @@ bool AVRInterface::Power(AVRPower_T cmd) {
return true;
}
bool AVRInterface::MasterVolumeButton(AVRVolumeButton_T cmd) {
return true;
}
bool AVRInterface::Mute(AVRMute_T cmd) {
bool AVRInterface::VolumeButton(AVRVolume_E cmd) {
switch (cmd) {
case eVolumeUp:
break;
case eVolumeDown:
break;
case eMuteOn:
break;
case eMuteOff:
break;
default:
return false;
}
return true;
}
@@ -388,6 +461,7 @@ bool AVRInterface::ProcessSerialQueue(const void *msg, uint16_t len) {
if (p && len) {
if (serialQueueCount < SERIALQUEUESIZE) {
MessageReport(">", msg, len);
serialQueue[serialQueueCount].messageToSend = (uint8_t *)malloc(len + 1);
if (serialQueue[serialQueueCount].messageToSend) {
memcpy(serialQueue[serialQueueCount].messageToSend, p, len);
@@ -493,6 +567,7 @@ bool AVRInterface::ProcessReportResponse(const uint8_t *szBuffer, uint32_t len)
if (MessageHandlers[i].showAll) {
showAllFlag = true; // ShowAllStatusInfo();
}
break; // no need to scan more
}
}
if (!found) {
@@ -558,14 +633,18 @@ void AVRInterface::PCMessage(const char *msg, int len, uint8_t **src, const char
}
char outBuf[LONGESTTEXT] = "";
sprintf_s(outBuf, LONGESTTEXT, "%17s %-8s",
sprintf_s(outBuf, LONGESTTEXT, PCMessageFormat,
msg,
p
);
(*ReportInformation)(mtStream, outBuf);
}
/// ReportAllStatus
///
/// This emits (via a callback) all the status, in DT0 to DT137 order.
/// You cannot rearrange the sequence to make grouping more logical.
///
void AVRInterface::ReportAllStatus() {
if (avrStatus.headerValid) {
char buf[LONGESTTEXT];
@@ -584,97 +663,97 @@ void AVRInterface::ReportAllStatus() {
PCMessage("Power", 1, &p, OffOnText);
if (avrStatus.configValid) {
PCMessage("Input", 1, &p, InputText);
PCMessage("6 ch", 1, &p);
PCMessage("Inp mode", 1, &p);
PCMessage("6 ch", 1, &p, OffOnText);
PCMessage("Inp mode", 1, &p, InputModeText);
PCMessage("Mute", 1, &p, OffOnText);
PCMessage("Zone 2", 1, &p, InputText);
PCMessage("Mute 2", 1, &p, OffOnText);
PCMessage("Volume", 2, &p, VolumeDB);
PCMessage("Volume 2", 2, &p, VolumeDB);
PCMessage("pgm", 2, &p);
PCMessage("effect", 1, &p, OffOnText);
PCMessage("6.1/es status", 1, &p);
PCMessage("OSD", 1, &p);
PCMessage("sleep", 1, &p);
PCMessage("Tuner Pg", 1, &p);
PCMessage("Tuner #", 1, &p);
PCMessage("Prog", 2, &p, ProgramName);
PCMessage("Effect", 1, &p, OffOnText);
PCMessage("6.1/es status", 1, &p, OffMatrixDiscreteAutoText);
PCMessage("OSD", 1, &p, OSDFullShortOffText);
PCMessage("Sleep", 1, &p, SleepTimerText);
PCMessage("Tuner Pg", 1, &p, PresetLabelText);
PCMessage("Tuner #", 1, &p, PresetNumberText);
PCMessage("Night", 1, &p, OffOnText);
PCMessage("?????", 1, &p);
PCMessage("Spkr A", 1, &p, OffOnText);
PCMessage("Spkr B", 1, &p, OffOnText);
PCMessage("Playback", 1, &p);
PCMessage("Fs", 1, &p);
PCMessage("Ex/Es", 1, &p);
PCMessage("Thr Bypass", 1, &p);
PCMessage("Red DTS", 1, &p);
PCMessage("Headph", 1, &p, OffOnText);
PCMessage("Tuner Band", 1, &p);
PCMessage("Tuner Tuned", 1, &p);
PCMessage("DC1 Control Out", 1, &p);
PCMessage("Playback", 1, &p, PlaybackToText);
PCMessage("Fs", 1, &p, FsToText);
PCMessage("Ex/Es", 1, &p, OffMatrixDiscreteText);
PCMessage("Thr Bypass", 1, &p, OffOnText);
PCMessage("Red DTS", 1, &p, ReleaseWaitText);
PCMessage("Headphone", 1, &p, OffOnText);
PCMessage("Tuner Band", 1, &p, FMAMText);
PCMessage("Tuner Tuned", 1, &p, NotTunedTunedText);
PCMessage("DC1 Control Out", 1, &p, OffOnText);
PCMessage("?????", 2, &p);
PCMessage("DC1 Trig Ctrl", 1, &p);
PCMessage("DTS 96/24", 1, &p, OffOnText);
PCMessage("DC2 Trig Ctrl", 1, &p);
PCMessage("DC2 Trig", 1, &p);
PCMessage("Spkr B Set", 1, &p);
PCMessage("DC2 Trig Ctrl", 1, &p, WhichZoneText);
PCMessage("DC2 Trig Out", 1, &p, OffOnText);
PCMessage("Spkr B Set", 1, &p, Zone1Zone2Text);
PCMessage("Zone 2 SP out", 1, &p, OffOnText);
PCMessage("Main R", 2, &p);
PCMessage("Main L", 2, &p);
PCMessage("Center", 2, &p);
PCMessage("Rear R", 2, &p);
PCMessage("Rear L", 2, &p);
PCMessage("Sur Bk R", 2, &p);
PCMessage("Sur Bk L", 2, &p);
PCMessage("Front R", 2, &p);
PCMessage("Front L", 2, &p);
PCMessage("Sub", 2, &p);
PCMessage("Main R", 2, &p, PM10dbText);
PCMessage("Main L", 2, &p, PM10dbText);
PCMessage("Center", 2, &p, PM10dbText);
PCMessage("Rear R", 2, &p, PM10dbText);
PCMessage("Rear L", 2, &p, PM10dbText);
PCMessage("Sur Bk R", 2, &p, PM10dbText);
PCMessage("Sur Bk L", 2, &p, PM10dbText);
PCMessage("Front R", 2, &p, PM10dbText);
PCMessage("Front L", 2, &p, PM10dbText);
PCMessage("Subwfr 1", 2, &p, PM10dbText);
PCMessage("?????", 6, &p);
PCMessage("LFE SP", 2, &p);
PCMessage("LFE HP", 2, &p);
PCMessage("Audio Delay", 2, &p);
PCMessage("LFE SP", 2, &p, M20P0dbText);
PCMessage("LFE HP", 2, &p, M20P0dbText);
PCMessage("Audio Delay", 2, &p, ZeroTo160msText);
PCMessage("?????", 4, &p);
PCMessage("Inp Mode Set", 1, &p);
PCMessage("Dimmer", 1, &p);
PCMessage("Inp Mode Set", 1, &p, AutoLastText);
PCMessage("Dimmer", 1, &p, M4To0Text);
PCMessage("OSD Msg", 1, &p);
PCMessage("OSD Shift", 2, &p);
PCMessage("Gray Back", 1, &p);
PCMessage("OSD Shift", 2, &p, M5toP5Text);
PCMessage("Gray Back", 1, &p, OffAutoText);
PCMessage("Video Conv", 1, &p, OffOnText);
PCMessage("D Range SP", 1, &p);
PCMessage("D Range HP", 1, &p);
PCMessage("Zone 2 Vol out", 1, &p);
PCMessage("?????", 1, &p);
PCMessage("D Range SP", 1, &p, MaxStdMinText);
PCMessage("D Range HP", 1, &p, MaxStdMinText);
PCMessage("Zone 2 Vol out", 1, &p, VarFixText);
PCMessage("?????", 1, &p); // "Zone 2 Mode: %s", Mode1Mode2Text ???
PCMessage("Memory Guard", 1, &p, OffOnText);
PCMessage("SP set center", 1, &p);
PCMessage("SP set main", 1, &p);
PCMessage("SP set rear L/R", 1, &p);
PCMessage("SP set rear ct", 1, &p);
PCMessage("SP set front", 1, &p);
PCMessage("SP set LFE/Bass", 1, &p);
PCMessage("SP set LFE/Bass", 1, &p, SwfrMainBothText);
PCMessage("6 ch center", 1, &p);
PCMessage("6 ch sub", 1, &p);
PCMessage("Main level", 1, &p);
PCMessage("Test Mode", 1, &p);
PCMessage("Test Mode", 1, &p, OffDolbyDspText);
PCMessage("?????", 1, &p);
PCMessage("Lvl 6 ch main L", 2, &p);
PCMessage("Lvl 6 ch main R", 2, &p);
PCMessage("Lvl 6 ch center", 2, &p);
PCMessage("Lvl 6 ch sl", 2, &p);
PCMessage("Lvl 6 ch sr", 2, &p);
PCMessage("Lvl 6 ch sbl", 2, &p);
PCMessage("Lvl 6 ch sbr", 2, &p);
PCMessage("Lvl 6 ch front l", 2, &p);
PCMessage("Lvl 6 ch front r", 2, &p);
PCMessage("Lvl 6 ch swfr", 2, &p);
PCMessage("Zone 3 Inp", 1, &p);
PCMessage("Zone 3 Mute", 1, &p);
PCMessage("Zone 3 Vol", 2, &p);
PCMessage("Lvl 6 Ch main L", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch main R", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch center", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch sl", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch sr", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch sbl", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch sbr", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch F L", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch F R", 2, &p, M10P10dbText);
PCMessage("Lvl 6 Ch swfr", 2, &p, M20P0dbText );
PCMessage("Zone 3 Inp", 1, &p, PlaybackToText);
PCMessage("Zone 3 Mute", 1, &p, OffOnText);
PCMessage("Zone 3 Vol", 2, &p, VolumeDB);
PCMessage("?????", 1, &p);
PCMessage("MultiCh Select", 1, &p);
PCMessage("MultiCh Surround", 1, &p);
PCMessage("SP Set SW1", 1, &p);
PCMessage("SP Set Crossover", 1, &p);
PCMessage("MultiCh Select", 1, &p, SixEightText);
PCMessage("MultiCh Surround", 1, &p, SurrMainText);
PCMessage("SP Set SW1", 1, &p, LrFrNoneText);
PCMessage("SP Set Crossover", 1, &p, CrossOverText);
PCMessage("Component OSD", 1, &p, OffOnText);
PCMessage("PB/SB Select", 1, &p);
PCMessage("PB/SB Select", 1, &p, PRSBText);
}
}
}