Files
AVR/AVR Working Controller/AVRInterface.cpp
David 6d16d119cd Clean up unused options for soundscape.
Clean up console interface to be less likely to fail to define the width and height.
Update notes in the PDF.
Add the PDF for newer Yamaha even if I don't have one (and the protocol has significant differences).
2026-02-27 12:57:20 -06:00

918 lines
39 KiB
C++

//
// The AVR Interface object and interaction methods
//
#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#include "AVRInterface.h"
#include "AVRCommandDecoder.h"
#define LONGESTTEXT 150
typedef enum {
eReady,
ePowerOn,
ePowerOff,
eVolumeUp,
eVolumeDown,
eMute,
eUnMute,
} AVRCommands_E;
typedef struct {
AVRCommands_E MsgID;
const char *pMsg;
uint16_t MsgLen;
} Message_T;
typedef struct {
uint8_t rCmd;
uint8_t configOffset; // offset into the Config DT0 - DT155 array, or 0xFF for no action
uint8_t numToTransfer; // number of bytes to transfer into the Config array, or 0 for no action
bool showAll; // true to call ShowAllStatusInfo after processing
const char *TextFormatter; // used primarily for development printf(TextFormatter, value)
const char *(*fncValueToText)(uint8_t rDat);
} MessageTextHandler_T;
// This is based on the longest thing from the MessageHandlerText 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)
// show all status
// fncHelper: optional function to call upon receipt
//
static const MessageTextHandler_T MessageHandlerText[] = {
//
// Configuration Map for Response Messages
//
// +---------------------------- rCmd
// | +----------------------- DT Block Offset
// | | +-------------------- Number of Bytes to transfer into the DT Block
// | | | +----------------- Force a 'show all' status screen update
// | | | |
// | | | | +-------- sprintf format string for the following Helper
// | | | | | +--- Helper to convert numeric value to text
// | | | | | |
{ 0x00, 7, 1, 1, "System Report: %s", BusyToText },
{ 0x01, 0, 0, 0, "Warning Report: %s", WarnToText },
{ 0x10, 31, 1, 1, "Playback Report: %s", PlaybackToText },
{ 0x11, 32, 1, 1, "Fs Report: %s", FsToText },
{ 0x12, 33, 1, 1, "Ex/Ex: %s", OffMatrixDiscreteText }, // EX/EX
{ 0x13, 34, 1, 1, "Thr Bypass: %s", OffOnText }, // Thr / Bypass
{ 0x14, 35, 1, 1, "RED dts: %s", ReleaseWaitText}, // RED dts
{ 0x15, 38, 1, 1, "Tuner tuned: %s", NotTunedTunedText}, // Tuner tuned
{ 0x16, 43, 1, 1, "DTS 96/24: %s", OffOnText}, // Dts 96/24
{ 0x20, 8, 0, 1, "Zone Power: %s", ZonePower },
{ 0x21, 9, 1, 1, "Input: %s", InputText}, // Input Source
{ 0x22, 11, 1, 1, "Input Mode: %s", InputModeText}, // Input Mode
{ 0x23, 12, 1, 1, "Mute: %s", OffOnText },
{ 0x24, 13, 1, 1, "Zone 2 Input: %s", InputText}, // Zone 2 Input Source
{ 0x25, 14, 1, 1, "Zone 2 Mute: %s", OffOnText },
{ 0x26, 15, 2, 1, "Volume: %s", VolumeDB },
{ 0x27, 17, 2, 1, "Zone 2 Vol: %s", VolumeDB}, // Zone 2 Vol
{ 0x28, 19, 2, 1, "Program: %s", ProgramName }, // Program
{ 0x29, 25, 1, 1, "Tuner Page: %s", PresetLabelText}, // Tuner Page
{ 0x2A, 26, 1, 1, "Tuner Preset: %s", PresetNumberText}, // Tuner Preset Number
{ 0x2B, 23, 1, 1, "OSD: %s", OSDFullShortOffText}, // OSD
{ 0x2C, 24, 1, 1, "Sleep: %s", SleepTimerText}, // Sleep Timer
{ 0x2D, 22, 1, 1, "EX/ES(Key): %s", OffMatrixDiscreteAutoText}, // EX/ES(Key)
{ 0x2E, 29, 1, 1, "SP Relay A: ", OffOnText}, // Speaker Relay A
{ 0x2F, 30, 1, 1, "SP Relay B: ", OffOnText}, // Speaker Relay B
{ 0x30, 0, 0, 0, "Home Preset:%s", PresetLabelText }, // Preset A, B, ... F
{ 0x31, 0, 0, 0, "Home Memory:%s", PresetLabelText }, // Preset A, B, ... F
{ 0x32, 0, 0, 0, "Home Vol Preset: %s", PresetLabelText }, // Preset A, B, ... F
{ 0x33, 0, 0, 0, "Home Vol Memory: %s", PresetLabelText }, // Preset A, B, ... F
{ 0x34, 36, 1, 1, "Headphone: %s", OffOnText },
{ 0x35, 37, 1, 1, "FM/AM: %s", FMAMText },
{ 0x36, 39, 1, 1, "DC1 Trigger Out: %s", OffOnText },
{ 0x37, 0, 0, 0, "Home Zone 2 Vol Preset: %s", PresetLabelText },
{ 0x38, 0, 0, 0, "Home Zone 2 Vol: %s", PresetLabelText },
{ 0x39, 0, 0, 0, "Dual Mono: %s", MainSubAllText },
{ 0x3A, 42, 1, 1, "DC1 Trigger Control: %s", WhichZoneText },
{ 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", Zone1Zone2Text },
{ 0x3F, 47, 1, 1, "Zone 2 Speaker: %s", OffOnText },
{ 0x40, 48, 2, 1, "Level Main R: %s", PM10dbText },
{ 0x41, 50, 2, 1, "Level Main L: %s", PM10dbText },
{ 0x42, 52, 2, 1, "Level Center: %s", PM10dbText },
{ 0x43, 54, 2, 1, "Level Rear R: %s", PM10dbText },
{ 0x44, 56, 2, 1, "Level Rear L: %s", PM10dbText },
{ 0x45, 58, 2, 1, "Level Sur Back R: %s", PM10dbText },
{ 0x46, 60, 2, 1, "Level Sur Back L: %s", PM10dbText },
{ 0x47, 62, 2, 1, "Level Front R: %s", PM10dbText },
{ 0x48, 64, 2, 1, "Level Front L: %s", PM10dbText },
{ 0x49, 66, 2, 1, "Level Swfr 1: %s", PM10dbText },
{ 0x4A, 0, 0, 0, "Level Swfr 2: %s", PM10dbText },
{ 0x50, 0, 0, 0, "Main L/R Bal: %s", BalanceText },
{ 0x51, 74, 2, 1, "LFE Level SP: %s", M20P0dbText },
{ 0x52, 76, 2, 1, "LFE Level HP: %s", M20P0dbText },
{ 0x53, 78, 2, 1, "Audio Delay: %s", ZeroTo160msText },
{ 0x54, 0, 0, 0, "SP Delay Center: %s", ZeroTo5msText },
{ 0x55, 0, 0, 0, "SP Delay Rear CT: %s", ZeroTo30msText },
{ 0x60, 84, 1, 1, "Input Mode: %s", AutoLastText },
{ 0x61, 85, 1, 1, "Dimmer: %s", M4To0Text },
{ 0x62, 87, 2, 1, "OSD Shift: %s", M5toP5Text },
{ 0x63, 89, 1, 1, "Gray Back: %s", OffAutoText },
{ 0x64, 91, 1, 1, "Dynamic Range SP: %s", MaxStdMinText },
{ 0x65, 92, 1, 1, "Dynamic Range HP: %s", MaxStdMinText },
{ 0x66, 93, 0, 0, "Zone 2 Vol out: %s", VarFixText },
{ 0x67, 0, 0, 0, "Zone 2 Mode: %s", Mode1Mode2Text },
{ 0x68, 95, 1, 1, "Mem Guard: %s", OffOnText },
{ 0x69, 90, 1, 1, "Video Conv: %s", OffOnText },
{ 0x6A, 136, 1, 1, "Comp OSD: %s", OffOnText },
{ 0x6B, 0, 0, 0, "Zone 3 Vol out: %s", VarFixText },
{ 0x70, 96, 1, 1, "Center Sp Size: %s", LSNText },
{ 0x71, 97, 1, 1, "Main Sp Size: %s", LSNText },
{ 0x72, 98, 1, 1, "Rear LR Sp Size: %s", LSNText },
{ 0x73, 99, 1, 1, "Sur Back Size: %s", LLSSNText },
{ 0x74, 100, 1, 1, "Front Sp: %s", YesNoneText },
{ 0x75, 101, 1, 1, "LFE Bass Out: %s", SwfrMainBothText },
{ 0x76, 134, 1, 1, "SW1: %s", LrFrNoneText },
{ 0x78, 102, 1, 1, "6 Ch Center: %s", CenterMainText },
{ 0x79, 103, 1, 1, "6 Ch Swfr: %s", SwfrMainText },
{ 0x7A, 133, 1, 1, "6 Ch Surround: %s", SurrMainText },
{ 0x7B, 0, 0, 0, "Multi Ch Select: %s", SixEightText },
{ 0x7E, 135, 1, 1, "SW Crossover", CrossOverText },
{ 0x80, 105, 1, 1, "Test Mode: %s", OffDolbyDspText },
{ 0x81, 0, 0, 0, "Analog Special: %s", OffOn2OnMultiText },
{ 0x82, 27, 1, 1, "Night Mode: %s", OffOnText },
{ 0x90, 0, 0, 0, "Multi Ch Level Main R: %s", M10P10dbText },
{ 0x91, 0, 0, 0, "Multi Ch Level Main L: %s", M10P10dbText },
{ 0x92, 0, 0, 0, "Multi Ch Level Center: %s", M10P10dbText },
{ 0x93, 0, 0, 0, "Multi Ch Level Rear R: %s", M10P10dbText },
{ 0x94, 0, 0, 0, "Multi Ch Level Rear L: %s", M10P10dbText },
{ 0x95, 0, 0, 0, "Multi Ch Level Sur B R: %s", M10P10dbText },
{ 0x96, 0, 0, 0, "Multi Ch Level Sur B L: %s", M10P10dbText },
{ 0x97, 0, 0, 0, "Multi Ch Level Front R: %s", M10P10dbText },
{ 0x98, 0, 0, 0, "Multi Ch Level Front L: %s", M10P10dbText },
{ 0x99, 0, 0, 0, "Multi Ch Level Swfr 1: %s", M20P0dbText },
{ 0x9A, 0, 0, 0, "Multi Ch Level Swfr 2: %s", M20P0dbText },
{ 0xA1, 0, 0, 0, "Zone 3 Mute: %s", OffOnText },
};
const char *StateMachineTextLabel[] = {
"Powering Up",
"Awaiting Ready Response",
"Initializing",
"Retry Initializing",
"Ready",
"Awaiting Response",
"Failed to contact",
"Unknown State",
};
// static instance definition
AVRInterface *AVRInterface::s_instance = nullptr;
// Trampoline: assigned into AVRDriver::NotifyHost so the driver calls into
// AVRInterface::ProcessReportResponse(instance, ...). This avoids changing
// the existing NotifyCallBack signature which has no context pointer.
bool AVRInterface::NotifyTrampoline(AVRMessageType_T type, const void *message, uint32_t attrib) {
if (AVRInterface::s_instance) {
return AVRInterface::s_instance->ProcessReportResponse(type, message, attrib);
}
return false;
}
AVRInterface::AVRInterface(
NotifyCallBack notifyCB, ///<! used to notify the host of internal events
SendCallBack sendCB ///<! used to send to the RS-232 interface
) : AVRDriver(nullptr, sendCB) {
// store application callback
AppNotify = notifyCB;
// mark global instance and install trampoline so AVRDriver calls instance method
s_instance = this;
// AVRDriver::NotifyHost is protected; accessible here via inheritance
NotifyHost = &AVRInterface::NotifyTrampoline;
RS232Send = sendCB;
IsSanityCheckOK();
MessageHandlerSanityCheck();
//Initialize();
//avrDrvr = new AVRDriver(ProcessReportResponse, HostSendPassthru);
}
AVRInterface::~AVRInterface() {
// clear static instance if this was set
if (s_instance == this) s_instance = nullptr;
}
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 = GetTick();
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) / 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') {
if (AppNotify) { // Guard it
(*AppNotify)(mtInfo, txtBuf, (uint32_t) strlen(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) {
if (AppNotify) { // Guard it
(*AppNotify)(mtInfo, txtBuf, (uint32_t)strlen(txtBuf));
}
sprintf_s(txtBuf, LONGESTTEXT, " "); // new line
pTxtAppend = txtBuf + strlen(txtBuf);
} else {
strcat_s(txtBuf, LONGESTTEXT, " ");
pTxtAppend++;
}
i = 0;
}
p++;
}
if (strlen(txtBuf)) {
if (AppNotify) { // Guard it
(*AppNotify)(mtInfo, txtBuf, (uint32_t)strlen(txtBuf));
}
}
}
//bool AVRInterface::HostSendPassthru(const uint8_t * message, uint32_t len) {
// return (*HostSendCB)(message, len);
//}
const char *AVRInterface::GetStateLabel(uint32_t st) {
if (st >= stMaxStates) {
st = stMaxStates;
}
return StateMachineTextLabel[st];
}
#if 1
// ProcessReportResponse
//
// @param[in] szBuffer is the received message
// @param[in] len is the null terminated string length of the message
//
// Typical Message:
// '\x02' 'type' 'guard' 'rcmd0' 'rcmd1' 'rdat0' 'rdat1' '\x03'
// [0] [1] [2] [3] [4] [5] [6] [7]
//
bool AVRInterface::ProcessReportResponse(AVRMessageType_T mtype, const void *szBuffer, uint32_t param) {
const uint8_t *p = (const uint8_t *)szBuffer;
char buf[LONGESTTEXT];
(void)param; // not used
bool showAllFlag = false;
switch (mtype) {
case mtModelInfo:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtState:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtInfo:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtStreamStart:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtStream:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtRcvdMsg:
if (p) {
// These don't have a checksum ...
// Example: [02] 4026 66[03]
// 4 - controlled by encoder
// 0 - guard status 0 = no guard
// 26 - master vol
// 66 - volume setting (-54.6db)
uint8_t type = (uint8_t)Hex2Dec(p + 1, 1);
uint8_t guard = (uint8_t)Hex2Dec(p + 2, 1);
uint8_t rcmd = (uint8_t)Hex2Dec(p + 3, 2);
uint8_t rdat = (uint8_t)Hex2Dec(p + 5, 2);
bool found = false;
for (int i = 0; i < sizeof(MessageHandlerText) / sizeof(MessageHandlerText[0]); i++) {
if (MessageHandlerText[i].rCmd == rcmd) {
found = true;
//if (MessageHandlerText[i].numToTransfer == 1) {
// //memcpy(&avrStatus.config.DT0 + MessageHandlerText[i].configOffset, p + 6, 1);
//}
//if (MessageHandlerText[i].numToTransfer == 2) {
// //memcpy(&avrStatus.config.DT0 + MessageHandlerText[i].configOffset, p + 5, 2);
//}
if (MessageHandlerText[i].TextFormatter && MessageHandlerText[i].fncValueToText) {
if (AppNotify) { // Guard it
sprintf_s(buf, LONGESTTEXT, MessageHandlerText[i].TextFormatter, MessageHandlerText[i].fncValueToText(rdat));
(*AppNotify)(mtInfo, buf, (uint32_t)strlen(buf));
}
}
if (MessageHandlerText[i].showAll) {
showAllFlag = true; // ShowAllStatusInfo();
}
break; // no need to scan more
}
}
if (!found && AppNotify) {
sprintf_s(buf, LONGESTTEXT, "***** type: %X, guard: %X, cmd: %02X, data: %02X", type, guard, rcmd, rdat);
(*AppNotify)(mtInfo, buf, (uint32_t)strlen(buf));
}
} else {
(*AppNotify)(mtype, szBuffer, param);
}
case mtXmtdMsg:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtStatusMsg:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtOperationResp:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtParamUpdated:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtExtendedResp:
(*AppNotify)(mtype, szBuffer, param);
break;
case mtErrNotFound:
// forward formatted error to application callback
if (AppNotify) {
sprintf_s(buf, LONGESTTEXT, "AVRCommand(%d,%d,%d) is invalid.", (param >> 16) & 0xFF, (param >> 8) & 0xFF, param & 0xFF);
(*AppNotify)(mtype, buf, (uint32_t)strlen(buf));
}
break;
case mtErrRxLength:
if (AppNotify) {
sprintf_s(buf, LONGESTTEXT, "Receive Message Length (%d) is invalid.", param);
(*AppNotify)(mtype, buf, (uint32_t)strlen(buf));
}
break;
case mtErrMalloc:
if (AppNotify) {
sprintf_s(buf, LONGESTTEXT, "Malloc (%d) Failed.", param);
(*AppNotify)(mtype, buf, (uint32_t)strlen(buf));
}
break;
case mtFailed:
if (AppNotify) {
(*AppNotify)(mtype, szBuffer, (uint32_t)strlen((const char *)szBuffer));
}
};
return showAllFlag;
}
#endif
void AVRInterface::MessageHandlerSanityCheck() {
uint8_t usedCommands[256] = { 0 };
uint8_t blockOffset[256] = { 0 };
bool fail = false;
// Ensure that the MessageHandlerText table is correct
for (int i = 0; i < sizeof(MessageHandlerText) / sizeof(MessageHandlerText[0]); i++) {
usedCommands[MessageHandlerText[i].rCmd]++;
if (usedCommands[MessageHandlerText[i].rCmd] > 1) {
printf("***** MessageHandler entry %d has duplicate rCmd of 0x%02X\n", i, MessageHandlerText[i].rCmd);
fail = true;
}
blockOffset[MessageHandlerText[i].configOffset]++;
if (MessageHandlerText[i].configOffset != 0 && blockOffset[MessageHandlerText[i].configOffset] > 1) {
printf("***** MessageHandler entry %d has duplicate configOffset of %d\n", i, MessageHandlerText[i].configOffset);
fail = true;
}
if (MessageHandlerText[i].numToTransfer > 2) {
printf("***** MessageHandler entry %d has invalid numToTransfer of %d\n", i, MessageHandlerText[i].numToTransfer);
}
if (MessageHandlerText[i].configOffset + MessageHandlerText[i].numToTransfer > sizeof(AVR_Configuration_T)) {
printf("***** MessageHandler entry %d has invalid configOffset of %d\n", i, MessageHandlerText[i].configOffset);
}
}
if (fail) {
printf("***** MessageHandler table sanity check failed. Exiting.\n");
}
return;
}
// PCMessage
//
// Various responses need to be formatted and shown on screen
// The last param will allow resetting the column counter
// and pre and post-pending \n
//
// @returns how far we moved in the buffer
//
uint8_t AVRInterface::PCMessage(const char *msg, uint8_t len, uint8_t **src, const char *(fncHelper)(uint8_t val), bool highlight) {
char buf[LONGESTTEXT] = "";
const char *p = buf;
if (fncHelper) {
// Get the binary value if we need it
uint8_t val = (uint8_t)Hex2Dec(*src, len);
p = (*fncHelper)(val);
*src += len;
} else {
// Create a string value when we need that
strncpy_s(buf, LONGESTTEXT, (char *)*src, len); // s/w
*src += len;
buf[len] = '\0';
}
char outBuf[LONGESTTEXT] = "";
sprintf_s(outBuf, LONGESTTEXT, PCMessageFormat,
msg,
p
);
if (AppNotify) { // Guard it
(*AppNotify)(mtStream, outBuf, highlight);
}
return len;
}
void AVRInterface::ExportInformation(AVRSubsystem_T subsystem,
AVRFunction_T function,
AVRArg_T arg) {
char buf[LONGESTTEXT] = "";
typedef struct {
uint16_t value;
const char *helpText;
} ValuePurpose_T;
const ValuePurpose_T subsysList[] = {
{ sysCommand, "System Command" },
{ subMain, "Main Subsystem" },
{ subRadio, "Radio Control" },
{ subAudio, "Audio Control" },
{ subZone1, "Zone 1 Control" },
{ subZone2, "Zone 2 Control" },
{ subZone3, "Zone 3 Control" },
};
const ValuePurpose_T funcList[] = {
{ fncReady, "Ready Check" },
{ fncReportEnable, "Report Enable" },
{ fncReportDelay, "Report Delay" },
{ fncRequest, "Report Request" },
{ fncSetValue, "Set Function Value" },
{ fncPower, "Power" },
{ fncVolume, "Volume" },
{ fncMute, "Mute" },
{ fncVolumeMemory, "Volume Memory" },
{ fncVolumeRecall, "Volume Memory Recall" },
{ fncSpeakerAOnOff, "Speaker A" },
{ fncSpeakerBOnOff, "Speaker B" },
{ fncSpeakerBZone, "Speaker B Zone Assignment" },
{ fncZone2SpeakerOnOff, "Zone 2 Speaker" },
{ fncNightModeOnOff, "Night Mode Sound Level" },
{ fncEffect, "Effect <something> " },
{ fncDSPSoundScape, "DSP Sound Scape" },
{ fncInput, "Input Selection" },
{ fncRadioBand, "Radio Band Selection" },
{ fncRadioTune, "Radio Tune" },
{ fncRadioPresetPage, "Radio Preset Page" },
{ fncRadioPresetNumber, "Radio Preset Number" },
{ fncRadioPresetMemory, "Radio Preset Memory" },
{ fncRadioPresetRecall, "Radio Preset Recall" },
{ fncSleep, "Sleep Timer" },
{ fncOSD, "On Screen Display Control" },
{ fnc6ChInput, "6 Channel Input mode" },
{ fncEx_EsOnOff, "EX / ES Mode" },
{ fncInputMode, "Input Mode" },
{ fncDualMono, "Dual Mono" },
{ fncDC1TrigControl, "DC1 Trigger Control" },
{ fncDC2TrigControl, "DC2 Trigger Control" },
{ fncDC1OnOff, "DC1" },
{ fncDC2OnOff, "DC2" },
};
const ValuePurpose_T valueList[] = {
{ eOn, "On" },
{ eOff, "Off" },
{ eStandby, "Standby" },
{ eUp, "Up" },
{ eDown, "Down" },
{ eOSDOff, "Off" },
{ eOSDShort, "Short" },
{ eOSDFull, "Full" },
{ eSleepOff, "Off" },
{ eSleep120, "120" },
{ eSleep90, "90" },
{ eSleep60, "60" },
{ eSleep30, "30" },
{ eOnMatrix, "EX-ES Mode Matrix On" },
{ eESESOff, "EX-ES Mode Off" },
{ eAuto, "EX-ES Mode Auto" },
{ eDiscrete, "EX-ES Mode Discrete" },
{ eEffectOn, "Effect On" },
{ eStereo, "Effect Stereo" },
{ eFM, "FM Band" },
{ eAM, "AM Band" },
{ eA, "Group A" },
{ eB, "Group B" },
{ eC, "Group C" },
{ eD, "Group D" },
{ eE, "Group E" },
{ eF, "Group F" },
{ e1, "Preset 1" },
{ e2, "Preset 2" },
{ e3, "Preset 3" },
{ e4, "Preset 4" },
{ e5, "Preset 5" },
{ e6, "Preset 6" },
{ e7, "Preset 7" },
{ e8, "Preset 8" },
{ ePhono, "Phono" },
{ eCD, "CD" },
{ eTuner, "Tuner" },
{ eCDR, "CDR" },
{ eMD_Tape, "MD_Tape" },
{ eDVD, "DVD" },
{ eDTV, "DTV" },
{ eCable, "Cable" },
{ eSat, "Sat" },
{ eVCR1, "VCR1" },
{ eVCR2_DVR, "VCR2_DVR" },
{ eVCR3, "VCR3" },
{ eV_Aux, "V Aux" },
{ Hall_A, "Hall A" }, // 00
{ Hall_B, "Hall B" }, // 01
{ Hall_C, "Hall C" }, // 02
{ Hall_USA, "Hall C2" }, // 04
{ Hall_E, "Hall E" }, // 05
{ Live_Concert, "Live Concert" }, // 06
{ Tokyo, "Tokyo" }, // 08
{ Freiburg, "Freiburg" }, // 09
{ Royaumont, "Royaumont" }, // 0A
{ Village_Gate, "Village Gate" }, // 0C
{ Village_Vanguard, "Village Vanguard" }, // 0D
{ The_Bottom_Line, "The Bottom Line" }, // 0E
{ The_Roxy_Theater, "The Roxy Theater" }, // 10
{ Warehouse_Loft, "Warehouse Loft" }, // 11
{ Arena, "Arena" }, // 12
{ Disco, "Disco" }, // 14
{ Party, "Party" }, // 15
{ Game, "Game" }, // 16
{ Stereo_6_8Ch, "Stereo 6/8Ch" }, // 17
{ Pop_Rock, "Pop/Rock" }, // 18
{ DJ, "DJ" }, // 19
{ Opera, "Opera" }, // 1C
{ Pavillion, "Pavillion" }, // 1D
{ Mono_Movie, "Mono/Movie" }, // 20
{ Variety_Sports, "Variety/Sports" }, // 21
{ Spectacre, "Spectacre" }, // 24
{ Sci_Fi, "Sci-Fi" }, // 25
{ Adventure, "Adventure" }, // 28
{ General, "General" }, // 29
{ Normal, "Normal" }, // 2C
{ Enhanced, "Enhanced" }, // 2D
{ PLII_Movie, "PLII Movie" }, // 30
{ PLII_Music, "PLII Music" }, // 31
{ Neo_6_Movie, "Neo 6 Movie" }, // 32
{ Neo_6_Music, "Neo 6 Music" }, // 33
{ Direct_2Ch, "Direct 2Ch" }, // 34
{ Stereo_2Ch, "Stereo 2Ch" }, // 35
{ THX_Ultra_PL, "THX A Ultra PL" }, // 36
{ THX_Music, "THX B Music" }, // 37
{ THX_Ultra_PL2, "THX Ultra PL2" },
{ THX_Ultra_NEO6, "THX Ultra NEO6" },
{ eInpAuto, "Input Auto" },
{ eDD_RF, "Input DD/RF" },
{ eDTS, "Input DTS" },
{ eDigital, "Input Digital" },
{ eAnalog, "Input Analog" },
{ eAAC, "Input AAC" },
{ eZone1, "Zone 1" },
{ eZone2, "Zone 2" },
{ eZone3, "Zone 3" },
{ eZoneOR, "Zone OR" },
{ eDualMain, "Dual Main" },
{ eDualSub, "Dual Sub" },
{ eDualAll, "Dual All" },
{ e0ms, "0 ms" },
{ e50ms, "50 ms" },
{ e100ms, "100 ms" },
{ e150ms, "150 ms" },
{ e200ms, "200 ms" },
{ e250ms, "250 ms" },
{ e300ms, "300 ms" },
{ e350ms, "350 ms" },
{ e400ms, "400 ms" },
{ eTuningFreq, "Tuning Frequency" },
{ eMainVolDB, "Main Volume" },
{ eZone2VolDB, "Zone 2 Volume" },
{ eInputName, "Zone 1 Input Name" },
{ eZone2InputName, "Zone 2 Input Name" },
{ eZoneXVolDB, "Zone X Volume" },
{ eZoneXInputName, "Zone X Input Name" },
{ eMasterVol, "Master Volume" },
{ eZone2Vol, "Zone 2 Volume" },
{ eMainLRBal, "Left-Right Balance" },
{ eMainLevel, "Main Level" },
{ eZone3Vol, "Zone 3 Volume" },
{ eMainLevelR, "Main Level R" },
{ eMainLevelL, "Main Level L" },
{ eCenterLevel, "Center Level" },
{ eRearR, "Rear Level R" },
{ eRearL, "Rear Level L" },
{ eFrontR, "Front Level R" },
{ eFrontL, "Front Level L" },
{ eSurBackR, "Surround Back R" },
{ eSurBackL, "Surround Back L" },
{ eSwfr1, "Subwoofer 1" },
{ eSwfr2, "Subwoofer 2" },
{ e0ms, "0 ms" },
};
(*NotifyHost)(mtInfo, "", 0);
(*NotifyHost)(mtInfo, "AVR Command Line Control uses 3 numeric parameters:", 0);
(*NotifyHost)(mtInfo, " 1) Subsystem Identifier for the subsystem control", 0);
(*NotifyHost)(mtInfo, " 2) Function Identifier valid for the subsystem", 0);
(*NotifyHost)(mtInfo, " 3) Value Identifier valid for the subsystem and function", 0);
(*NotifyHost)(mtInfo, "", 0);
(*NotifyHost)(mtInfo, " NOTE: Most commands are unavailable when the system is off.", 0);
(*NotifyHost)(mtInfo, " ", 0);
(*NotifyHost)(mtInfo, "", 0);
sprintf_s(buf, LONGESTTEXT, "%8d: %-21s | %3d: %-28s | %3d: %-22s | %-13s",
1, "Subsystem Identifier", 2, "Function Identifier", 3, "Value Identifier", "Stream"
);
(*NotifyHost)(mtInfo, buf, (uint32_t)strlen(buf));
sprintf_s(buf, LONGESTTEXT, " %2s: %-21s | %3s: %-28s | %3s: %22s | %13s",
"##", "#####################", "##", "############################", "##", "######################", "#############"
);
(*NotifyHost)(mtInfo, buf, (uint32_t)strlen(buf));
AVRSubsystem_T refSub = subsystemCount;
AVRFunction_T refFnc = fncFunctionCount;
const char *pSubsystemText = NULL, *pFunctionText = NULL, *pValueText = NULL;
uint16_t count = GetMessageTableSize();
for (uint16_t i = 0; i < count; i++) {
MessageTable_T *p = GetMessageTableRecord(i);
// Subsystem scan or filter
//
if (subsystem != subsystemCount && subsystem != p->subsystem) {
continue;
}
if (function != fncFunctionCount && function != p->function) {
continue;
}
if (arg != eARGCount && arg != p->arg) {
continue;
}
if (refSub != p->subsystem) {
refSub = p->subsystem;
for (int j = 0; j < sizeof(subsysList) / sizeof(ValuePurpose_T); j++) {
if (subsysList[j].value == refSub) {
pSubsystemText = subsysList[j].helpText;
break;
} else {
pSubsystemText = "";
}
}
} else {
pSubsystemText = "";
}
//
// function choices
//
if (refFnc != p->function) {
refFnc = p->function;
for (int j = 0; j < sizeof(funcList) / sizeof(ValuePurpose_T); j++) {
if (funcList[j].value == refFnc) {
pFunctionText = funcList[j].helpText;
break;
} else {
pFunctionText = "";
}
}
} else {
pFunctionText = "";
}
//
// argument choices
//
for (int j = 0; j < sizeof(valueList) / sizeof(ValuePurpose_T); j++) {
if (valueList[j].value == p->arg) {
pValueText = valueList[j].helpText;
break;
} else {
pValueText = "";
}
}
sprintf_s(buf, LONGESTTEXT, "%8d: %-21s | %3d: %-28s | %3d: %-22s | %s",
refSub, pSubsystemText,
refFnc, pFunctionText,
p->arg, pValueText,
MessageToText(p->Message, p->MessageLen)
);
(*NotifyHost)(mtInfo, buf, (uint32_t)strlen(buf));
}
};
const char *AVRInterface::MessageToText(const char *p, size_t len) {
static char privateBuffer[LONGESTTEXT] = "";
char *pOut = privateBuffer;
for (int i = 0; i < len; i++) {
if (isprint(*p)) {
*pOut++ = *p++;
} else {
pOut += sprintf_s(pOut, LONGESTTEXT - strlen(privateBuffer), "[%02X]", *p++);
}
*pOut = '\0'; // keep it null terminated
}
return privateBuffer;
}
//
// Single Linear according to the on-screen display of Volume
// db = 0.5 x - 99.5
// therefore:
// db + 99.5 = 0.5 x
// 0.5 x == db + 99.5
// x = 2 * (db + 99.5)
//
uint8_t AVRInterface::VolumeDBtoAPIValue(float db) {
if (db >= -80.0f && db <= +16.5f) {
return (uint8_t)(2 * (db + 99.5));
} else {
return (0); // mute
}
}
/// ReportAllStatus
///
/// This emits (via a callback) all the status, in DT0 to DT137 order.
/// You cannot rearrange the sequence to make grouping more logical.
///
/// @param[in] offsetChanged indicates what index into the big buffer changed
///
void AVRInterface::ReportAllStatus(uint8_t offsetChanged) {
const AVRDriver::AVR_Status_T * avStat = GetAVRStatusData();
if (avStat->headerValid && AppNotify) {
char buf[LONGESTTEXT];
sprintf_s(buf, LONGESTTEXT, "Model ID: %c%c%c%c%c, ver: %c\n", avStat->header.type[0], avStat->header.type[1],
avStat->header.type[2], avStat->header.type[3], avStat->header.type[4],
avStat->header.version);
(*AppNotify)(mtModelInfo, buf, (uint32_t)strlen(buf));
uint8_t *p = (uint8_t *)&avStat->config;
(*AppNotify)(mtStreamStart, "---- AVR Status Report ----\n", 0);
int offset = 0;
offset += PCMessage("Baud Rate", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Rx Buffer", 2, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Cmd Timeout", 3, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Handshake", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Busy", 1, &p, BusyToText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Power", 1, &p, ZonePower, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
if (avStat->configValid) {
offset += PCMessage("Zone 1 Input", 1, &p, InputText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("6 ch", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Inp mode", 1, &p, InputModeText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Mute", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 2 Input", 1, &p, InputText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 2 Mute", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Volume", 2, &p, VolumeDB, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 2 Volume", 2, &p, VolumeDB, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Prog", 2, &p, ProgramName, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Effect", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("6.1/es status", 1, &p, OffMatrixDiscreteAutoText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("OSD", 1, &p, OSDFullShortOffText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Sleep", 1, &p, SleepTimerText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Tuner Pg", 1, &p, PresetLabelText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Tuner #", 1, &p, PresetNumberText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Night", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("?????", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Spkr A", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Spkr B", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Playback", 1, &p, PlaybackToText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Fs", 1, &p, FsToText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Ex/Es", 1, &p, OffMatrixDiscreteText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Thr Bypass", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Red DTS", 1, &p, ReleaseWaitText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Headphone", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Tuner Band", 1, &p, FMAMText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Tuner Tuned", 1, &p, NotTunedTunedText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("DC1 Control Out", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("?????", 2, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("DC1 Trig Ctrl", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("DTS 96/24", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("DC2 Trig Ctrl", 1, &p, WhichZoneText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("DC2 Trig Out", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Spkr B Set", 1, &p, Zone1Zone2Text, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 2 SP out", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Main R", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Main L", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Center", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Rear R", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Rear L", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Sur Bk R", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Sur Bk L", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Front R", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Front L", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Subwfr 1", 2, &p, PM10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("?????", 6, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("LFE SP", 2, &p, M20P0dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("LFE HP", 2, &p, M20P0dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Audio Delay", 2, &p, ZeroTo160msText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("?????", 4, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Inp Mode Set", 1, &p, AutoLastText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Dimmer", 1, &p, M4To0Text, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("OSD Msg", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("OSD Shift", 2, &p, M5toP5Text, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Gray Back", 1, &p, OffAutoText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Video Conv", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("D Range SP", 1, &p, MaxStdMinText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("D Range HP", 1, &p, MaxStdMinText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 2 Vol out", 1, &p, VarFixText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("?????", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false); // "Zone 2 Mode: %s", Mode1Mode2Text ???
offset += PCMessage("Memory Guard", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP set center", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP set main", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP set rear L/R", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP set rear ct", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP set front", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP set LFE/Bass", 1, &p, SwfrMainBothText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("6 ch center", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("6 ch sub", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Main level", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Test Mode", 1, &p, OffDolbyDspText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("?????", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch main L", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch main R", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch center", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch sl", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch sr", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch sbl", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch sbr", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch F L", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch F R", 2, &p, M10P10dbText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Lvl 6 Ch swfr", 2, &p, M20P0dbText , (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 3 Input", 1, &p, PlaybackToText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 3 Mute", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Zone 3 Volume", 2, &p, VolumeDB, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("?????", 1, &p, NULL, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("MultiCh Select", 1, &p, SixEightText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("MultiCh Surround", 1, &p, SurrMainText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP Set SW1", 1, &p, LrFrNoneText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("SP Set Crossover", 1, &p, CrossOverText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("Component OSD", 1, &p, OffOnText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
offset += PCMessage("PB/SB Select", 1, &p, PRSBText, (offsetChanged == 0xFF || offsetChanged == offset) ? true : false);
}
}
}