// // // #ifdef _DEBUG #include #endif #include #include #include #include #include "AVRInterface.h" #include "AVRCommandDecoder.h" #define LONGESTTEXT 150 using AVRSubsys = AVRInterface::AVRSubsystem_E; using AVRFunc = AVRInterface::AVRFunction_E; //using AVRArg = AVRInterface::AVRArgument_U; 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 type; // 0 to 4, and 0xFF for don't care //uint8_t guard; // 0 to 2, and 0xFF for don't care 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); } MessageHandler_T; static const char * StateText[] = { "Powering Up", "Awaiting Ready Response", "Initializing", "Retry Initializing", "Ready", "Awaiting Response", "Unknown State" }; static const Message_T AVRCommands[] = { { eReady, "\x11" "000" "\x03", 5 }, { ePowerOn, "\x02" "07A1D" "\x03", 7 }, { ePowerOff,"\x02" "07A1E" "\x03", 7 }, { eVolumeUp,"\x02" "07A1A" "\x03", 7 }, { eVolumeDown,"\x02" "07A1B" "\x03", 7 }, { eMute, "\x02" "07EA2" "\x03", 7 }, { 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) // show all status // fncHelper: optional function to call upon receipt // static const MessageHandler_T MessageHandlers[] = { // // 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\n", OffOnText }, }; AVRInterface::AVRInterface(bool (*SendMessage)(const uint8_t *buffer, uint16_t len)) { SendMethod = SendMessage; IsSanityCheckOK(); MessageHandlerSanityCheck(); Initialize(); } AVRInterface::~AVRInterface() { FreeMemory(); } bool AVRInterface::IsSanityCheckOK() { static bool checked = false; if (!checked) { checked = true; if (sizeof(AVRCommands) / sizeof(Message_T) != AVRState_T::stMaxStates + 1) { #ifdef _DEBUG printf("AVRCommands array size mismatch!\n"); #endif return false; } } 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') { if (ReportInformation) { // Guard it (*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) { if (ReportInformation) { // Guard it (*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)) { if (ReportInformation) { // Guard it (*ReportInformation)(mtInfo, txtBuf); } } } void AVRInterface::Tick(uint32_t now_ms) { if (!bFirstTickInitialized) { bFirstTickInitialized = true; firstTick_ms = now_ms; } lastTick_ms = now_ms; uint32_t elapsed_ms = now_ms - sentAtTime_ms; char buf[LONGESTTEXT] = ""; if (oldState != state && ReportInformation) { (*ReportInformation)(mtStatus, StateText[state]); } oldState = state; switch (state) { default: case AVRState_T::stPoweringUp: readyResponsReceived = false; ProcessSerialQueue(AVRCommands[eReady].pMsg, AVRCommands[eReady].MsgLen); sentAtTime_ms = now_ms; readyTries++; state = stAwaitingReadyResponse; break; case stAwaitingReadyResponse: if (readyResponsReceived) { state = stReady; } else if (elapsed_ms > RETRY_INTERVAL_ms) { if (readyTries > MAXTRIES) { // fail } else { state = stPoweringUp; } } break; case AVRState_T::stInitializing: break; case AVRState_T::stRetryInitializing: break; case AVRState_T::stAwaitingResponse: if (commandResponseReceived) { state = stReady; } else if (elapsed_ms > RETRY_INTERVAL_ms) { ProcessSerialQueue(); state = stAwaitingResponse; } break; case AVRState_T::stReady: ProcessSerialQueue(); break; } } /// @brief Handle a just received message by parsing it /// /// Given a response string, typically of the form: /// [02] .... [03] // Command Responses from the AVR /// [11] .... [03] // Commands to /// [12] .... [03] /// [14] ............ [03] /// /// @param buffer contains the message /// @param len of the message /// @return true, if data was accepted and the overall status changed, so might be shown /// bool AVRInterface::HandleMessage(const uint8_t *buffer, uint16_t len) { bool showAllFlag = false; MessageReport("<", buffer, len); switch (state) { case stAwaitingReadyResponse: switch (buffer[0]) { case 0x02: // STX ETX commandResponseReceived = true; showAllFlag = ProcessReportResponse(buffer, len); break; case 0x11: // DC1 ETX // AVR does not send any DC1 messages, these are for commands to the AVR break; case 0x12: // DC2 ETX if (CheckTheChecksum(buffer, len)) { if (len == 21) { // Short message when power is off memcpy(&avrStatus.header, &buffer[1], sizeof(AVR_StatusHeader_T)); len = Hex2Dec(&avrStatus.header.length[0], 2); memcpy(&avrStatus.config.DT0, &buffer[9], len); // Copy bits of the config avrStatus.headerValid = true; showAllFlag = true; } else if (len == 150) { // Long message when power is on memcpy(&avrStatus.header, &buffer[1], sizeof(AVR_StatusHeader_T)); len = Hex2Dec(&avrStatus.header.length[0], 2); memcpy(&avrStatus.config.DT0, &buffer[9], len); // Copy the config avrStatus.headerValid = true; avrStatus.configValid = true; showAllFlag = true; } else { printf("***** Received message of unexpected length [%u]\n", len); } readyResponsReceived = true; } break; case 0x14: // DC4 ETX // DecodeExtendedResponse(buffer, len); // once I figure out what is in here... break; default: break; } break; case stAwaitingResponse: // @TODO Process the message here... commandResponseReceived = true; break; case stReady: switch (buffer[0]) { case 0x02: // STX ETX commandResponseReceived = true; showAllFlag = ProcessReportResponse(buffer, len); break; case 0x11: // DC1 ETX break; case 0x12: // DC2 ETX if (CheckTheChecksum(buffer, len)) { if (len == 21) { // Short message when power is off memcpy(&avrStatus.header, &buffer[1], sizeof(AVR_StatusHeader_T)); len = Hex2Dec(&avrStatus.header.length[0], 2); memcpy(&avrStatus.config.DT0, &buffer[9], len); // Copy bits of the config avrStatus.headerValid = true; showAllFlag = true; } else if (len == 150) { // Long message when power is on memcpy(&avrStatus.header, &buffer[1], sizeof(AVR_StatusHeader_T)); len = Hex2Dec(&avrStatus.header.length[0], 2); memcpy(&avrStatus.config.DT0, &buffer[9], len); // Copy the config avrStatus.headerValid = true; avrStatus.configValid = true; showAllFlag = true; } else { printf("***** Received message of unexpected length [%u]\n", len); } readyResponsReceived = true; } break; case 0x14: // DC4 ETX // DecodeExtendedResponse(buffer, len); // once I figure out what is in here... break; default: break; } break; } return showAllFlag; } bool AVRInterface::Initialize() { state = AVRState_T::stPoweringUp; return true; } bool AVRInterface::IsOnline() { return true; } bool AVRInterface::Power(AVROnOff_E cmd) { commandResponseReceived = false; if (cmd == eOn) ProcessSerialQueue(AVRCommands[ePowerOn].pMsg, AVRCommands[ePowerOn].MsgLen); else ProcessSerialQueue(AVRCommands[ePowerOff].pMsg, AVRCommands[ePowerOff].MsgLen); state = stAwaitingResponse; return true; } bool AVRInterface::VolumeButton(AVRUpDown_E cmd) { switch (cmd) { case eUp: break; case eDown: break; default: return false; } return true; } bool AVRInterface::RegisterInformationCallback(void(*StatusChangeCallback)(AVRMessageType_T type, const char *msg)) { ReportInformation = StatusChangeCallback; return true; } bool AVRInterface::AVRSendOSDMessage(const char *pMsg) { const char valid[] = " !#%&()*+,-.0123456789:<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_abcdefghijklmnopqrstuvwxyz"; char buf[17] = { 0 }; if (strlen(pMsg) <= 16) { for (size_t i = 0; i < 16; i++) { if (*pMsg == '\0') { buf[i] = ' '; } else if (strchr(valid, *pMsg)) { buf[i] = *pMsg++; } else { return false; // Invalid character } } ProcessSerialQueue("\x02" "21000" "\x03", 7); // Start the OSD message char msg[8]; for (int i = 0; i < 16; i += 4) { strcpy_s(msg, sizeof(msg), "\x02"); // Each chunk strcat_s(msg, sizeof(msg), "3"); strncat_s(msg, sizeof(msg), &buf[i], 4); strcat_s(msg, sizeof(msg), "\x03"); ProcessSerialQueue(msg, 7); } return true; } else { return false; } } bool AVRInterface::ProcessSerialQueue(const void *msg, uint16_t len) { const char *p = (const char *)msg; bool retVal = false; // assume fail static bool freshData = false; 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); *(serialQueue[serialQueueCount].messageToSend + len) = '\0'; serialQueue[serialQueueCount].len = len; serialQueueCount++; retVal = true; freshData = true; } } } if (serialQueueCount) { if ((*SendMethod)((const uint8_t *)serialQueue[0].messageToSend, serialQueue[0].len)) { --serialQueueCount; free(serialQueue[0].messageToSend); serialQueue[0].messageToSend = NULL; for (int i = 0; i < serialQueueCount; i++) { serialQueue[i] = serialQueue[i + 1]; } retVal = true; } } return retVal; } void AVRInterface::FreeMemory() { for (int i = 0; i < serialQueueCount; i++) { if (serialQueue[0].messageToSend) free(serialQueue[0].messageToSend); } } bool AVRInterface::CheckTheChecksum(const uint8_t *szBuffer, uint32_t num) { uint8_t sum = 0; for (uint16_t i = 1; i < num - 3; i++) { sum += szBuffer[i]; } uint8_t cksum = (uint8_t)Hex2Dec(&szBuffer[num - 3], 2); //printf("CheckSum: %02X v. %c%c\n", sum, szBuffer[num - 3], szBuffer[num - 2]); return (sum == cksum); } // Hex2Dec // // All responses are pretty much Hex-ASCII, so // we sometimes want to convert it to decimal // This takes a buffer and converts the specified // number of characters. // uint16_t AVRInterface::Hex2Dec(const uint8_t *p, int dig) { uint16_t x = 0; while (dig--) { if (*p >= '0' && *p <= '9') x = x * 16 + *p - '0'; else if (*p >= 'a' && *p <= 'f') x = x * 16 + 0x0a + *p - 'a'; else if (*p >= 'A' && *p <= 'F') x = x * 16 + 0x0a + *p - 'A'; p++; } return x; } // 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(const uint8_t *szBuffer, uint32_t len) { // 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(&szBuffer[1], 1); uint8_t guard = (uint8_t)Hex2Dec(&szBuffer[2], 1); uint8_t rcmd = (uint8_t)Hex2Dec(&szBuffer[3], 2); uint8_t rdat = (uint8_t)Hex2Dec(&szBuffer[5], 2); char buf[LONGESTTEXT]; (void)len; // not used bool showAllFlag = false; bool found = false; for (int i = 0; i < sizeof(MessageHandlers) / sizeof(MessageHandlers[0]); i++) { if (MessageHandlers[i].rCmd == rcmd) { found = true; if (MessageHandlers[i].numToTransfer == 1) { memcpy(&avrStatus.config.DT0 + MessageHandlers[i].configOffset, &szBuffer[6], 1); } if (MessageHandlers[i].numToTransfer == 2) { memcpy(&avrStatus.config.DT0 + MessageHandlers[i].configOffset, &szBuffer[5], 2); } if (MessageHandlers[i].TextFormatter && MessageHandlers[i].fncValueToText) { if (ReportInformation) { // Guard it sprintf_s(buf, LONGESTTEXT, MessageHandlers[i].TextFormatter, MessageHandlers[i].fncValueToText(rdat)); (*ReportInformation)(mtInfo, buf); } } if (MessageHandlers[i].showAll) { showAllFlag = true; // ShowAllStatusInfo(); } break; // no need to scan more } } if (!found && ReportInformation) { sprintf_s(buf, LONGESTTEXT, "***** type: %X, guard: %X, cmd: %02X, data: %02X", type, guard, rcmd, rdat); (*ReportInformation)(mtInfo, buf); //Console_Write(buf); //Console_ScrollBottomRegion(); } return showAllFlag; } void AVRInterface::MessageHandlerSanityCheck() { uint8_t usedCommands[256] = { 0 }; uint8_t blockOffset[256] = { 0 }; bool fail = false; // Ensure that the MessageHandlers table is correct for (int i = 0; i < sizeof(MessageHandlers) / sizeof(MessageHandlers[0]); i++) { usedCommands[MessageHandlers[i].rCmd]++; if (usedCommands[MessageHandlers[i].rCmd] > 1) { printf("***** MessageHandler entry %d has duplicate rCmd of 0x%02X\n", i, MessageHandlers[i].rCmd); fail = true; } blockOffset[MessageHandlers[i].configOffset]++; if (MessageHandlers[i].configOffset != 0 && blockOffset[MessageHandlers[i].configOffset] > 1) { printf("***** MessageHandler entry %d has duplicate configOffset of %d\n", i, MessageHandlers[i].configOffset); fail = true; } if (MessageHandlers[i].numToTransfer > 2) { printf("***** MessageHandler entry %d has invalid numToTransfer of %d\n", i, MessageHandlers[i].numToTransfer); } if (MessageHandlers[i].configOffset + MessageHandlers[i].numToTransfer > sizeof(AVR_Configuration_T)) { printf("***** MessageHandler entry %d has invalid configOffset of %d\n", i, MessageHandlers[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 // void AVRInterface::PCMessage(const char *msg, int len, uint8_t **src, const char *(fncHelper)(uint8_t val)) { 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 (ReportInformation) { // Guard it (*ReportInformation)(mtStream, outBuf); } } typedef const struct { AVRInterface::AVRSubsystem_E subsystem; AVRInterface::AVRFunction_E function; AVRInterface::AVRArg_T arg; const char *Message; uint16_t MessageLen; // Helper? } MessageTable_T; MessageTable_T MessageTable[] = { { AVRSubsys::eMain, AVRFunc::fncVolume, AVRInterface::eUp, "\x02" "07A1A" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolume, AVRInterface::eDown, "\x02" "07A1B" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncMute, AVRInterface::eOn, "\x02" "07EA2" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncMute, AVRInterface::eOff, "\x02" "07EA3" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::ePhono, "\x02" "07A14" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eCD, "\x02" "07A15" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eTuner, "\x02" "07A16" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eCDR, "\x02" "07A19" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eMD_Tape, "\x02" "07AC9" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eDVD, "\x02" "07AC1" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eDTV, "\x02" "07A54" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eCable, "\x02" "07AC0" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eSat, "\x02" "07ACA" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eVCR1, "\x02" "07A0F" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eVCR2_DVR, "\x02" "07A13" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eVCR3, "\x02" "07AC8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInput, AVRInterface::eV_Aux, "\x02" "07A55" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fnc6ChInput, AVRInterface::eOn, "\x02" "07EA4" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fnc6ChInput, AVRInterface::eOff, "\x02" "07EA5" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInputMode, AVRInterface::eInpAuto, "\x02" "07EA6" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInputMode, AVRInterface::eDD_RF, "\x02" "07EA7" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInputMode, AVRInterface::eDTS, "\x02" "07EA8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInputMode, AVRInterface::eDigital, "\x02" "07EA9" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInputMode, AVRInterface::eAnalog, "\x02" "07EAA" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncInputMode, AVRInterface::eAAC, "\x02" "07E3B" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolume, AVRInterface::eUp, "\x02" "07ADA" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolume, AVRInterface::eDown, "\x02" "07ADB" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncMute, AVRInterface::eOn, "\x02" "07EA0" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncMute, AVRInterface::eOff, "\x02" "07EA1" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::ePhono, "\x02" "07AD0" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eCD, "\x02" "07AD1" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eTuner, "\x02" "07AD2" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eCDR, "\x02" "07AD4" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eMD_Tape, "\x02" "07ACF" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eDVD, "\x02" "07ACD" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eDTV, "\x02" "07AD9" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eCable, "\x02" "07ACC" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eSat, "\x02" "07ACB" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eVCR1, "\x02" "07AD6" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eVCR2_DVR, "\x02" "07AD7" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eVCR3, "\x02" "07ACE" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncInput, AVRInterface::eV_Aux, "\x02" "07AD8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncPower, AVRInterface::eOn, "\x02" "07A1D" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncPower, AVRInterface::eOff, "\x02" "07A1E" "\x03", 7 }, { AVRSubsys::eZone1, AVRFunc::fncPower, AVRInterface::eOn, "\x02" "07E7E" "\x03", 7 }, { AVRSubsys::eZone1, AVRFunc::fncPower, AVRInterface::eOff, "\x02" "07E7F" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncPower, AVRInterface::eOn, "\x02" "07EBA" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncPower, AVRInterface::eOff, "\x02" "07EBB" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncPower, AVRInterface::eOn, "\x02" "07AED" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncPower, AVRInterface::eStandby, "\x02" "07AEE" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncMute, AVRInterface::eOn, "\x02" "07E26" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncMute, AVRInterface::eOff, "\x02" "07E66" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolume, AVRInterface::eUp, "\x02" "07AFD" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolume, AVRInterface::eDown, "\x02" "07AFE" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::ePhono, "\x02" "07AF1" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eCD, "\x02" "07AF2" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eTuner, "\x02" "07AF3" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eCDR, "\x02" "07AF5" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eMD_Tape, "\x02" "07AF4" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eDVD, "\x02" "07AFC" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eDTV, "\x02" "07AF6" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eCable, "\x02" "07AF7" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eSat, "\x02" "07AF8" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eVCR1, "\x02" "07AF9" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eVCR2_DVR, "\x02" "07AFA" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eVCR3, "\x02" "07AFB" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncInput, AVRInterface::eV_Aux, "\x02" "07AF0" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncOSD, AVRInterface::eOSDOff, "\x02" "07EB0" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncOSD, AVRInterface::eOSDShort, "\x02" "07EB1" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncOSD, AVRInterface::eOSDFull, "\x02" "07EB2" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSleep, AVRInterface::eSleepOff, "\x02" "07EB3" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSleep, AVRInterface::eSleep120, "\x02" "07EB4" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSleep, AVRInterface::eSleep90, "\x02" "07EB5" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSleep, AVRInterface::eSleep60, "\x02" "07EB6" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSleep, AVRInterface::eSleep30, "\x02" "07EB7" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEx_EsOnOff, AVRInterface::eOnMatrix, "\x02" "07EB8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEx_EsOnOff, AVRInterface::eESESOff, "\x02" "07EB9" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEx_EsOnOff, AVRInterface::eAuto, "\x02" "07E7C" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEx_EsOnOff, AVRInterface::eDiscrete, "\x02" "07E7D" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncNightModeOnOff, AVRInterface::eOn, "\x02" "07E9B" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncNightModeOnOff, AVRInterface::eOff, "\x02" "07E9C" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::eEffectOn, "\x02" "07E27" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::eStereo, "\x02" "07EE0" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Hall_A, "\x02" "07EE1" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Hall_B, "\x02" "07EE2" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Hall_C, "\x02" "07EE3" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Hall_USA, "\x02" "07EE4" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Hall_E, "\x02" "07EE5" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Live_Concert, "\x02" "07EE6" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Tokyo, "\x02" "07EE7" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Freiburg, "\x02" "07EE8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Royaumont, "\x02" "07EE9" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Village_Gate, "\x02" "07EEA" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Village_Vanguard, "\x02" "07EEB" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::The_Bottom_Line, "\x02" "07EEC" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::The_Roxy_Theater, "\x02" "07EED" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Warehouse_Loft, "\x02" "07EEE" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Arena, "\x02" "07EEF" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Disco, "\x02" "07EF0" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Party, "\x02" "07EF1" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Game, "\x02" "07EF2" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Stereo_6_8Ch, "\x02" "07EFF" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Pop_Rock, "\x02" "07EF3" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::DJ, "\x02" "07EF4" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Opera, "\x02" "07EF5" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Pavillion, "\x02" "07EF6" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Mono_Movie, "\x02" "07EF7" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Variety_Sports, "\x02" "07EF8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Spectacre, "\x02" "07EF9" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Sci_Fi, "\x02" "07EFA" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Adventure, "\x02" "07EFB" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::General, "\x02" "07EFC" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Normal, "\x02" "07EFD" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Enhanced, "\x02" "07EFE" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::PLII_Movie, "\x02" "07E67" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::PLII_Music, "\x02" "07E68" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Neo_6_Movie, "\x02" "07E69" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Neo_6_Music, "\x02" "07E6A" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Direct_2Ch, "\x02" "07EC1" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::Stereo_2Ch, "\x02" "07EC0" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::THX_Ultra_PL, "\x02" "07EC2" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::THX_Music, "\x02" "07EC3" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::THX_Ultra_PL2, "\x02" "07EC7" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncEffect, AVRInterface::THX_Ultra_NEO6, "\x02" "07EC8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetPage, AVRInterface::eA, "\x02" "07AE0" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetPage, AVRInterface::eB, "\x02" "07AE1" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetPage, AVRInterface::eC, "\x02" "07AE2" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetPage, AVRInterface::eD, "\x02" "07AE3" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetPage, AVRInterface::eE, "\x02" "07AE4" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e1, "\x02" "07AE5" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e2, "\x02" "07AE6" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e3, "\x02" "07AE7" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e4, "\x02" "07AE8" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e5, "\x02" "07AE9" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e6, "\x02" "07AEA" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e7, "\x02" "07AEB" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetNumber, AVRInterface::e8, "\x02" "07AEC" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioBand, AVRInterface::eFM, "\x02" "07EBC" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioBand, AVRInterface::eAM, "\x02" "07EBD" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioTune, AVRInterface::eUp, "\x02" "07EBE" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioTune, AVRInterface::eDown, "\x02" "07EBF" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSpeakerAOnOff, AVRInterface::eOn, "\x02" "07EAB" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSpeakerAOnOff, AVRInterface::eOff, "\x02" "07EAC" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSpeakerBOnOff, AVRInterface::eOn, "\x02" "07EAD" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSpeakerBOnOff, AVRInterface::eOff, "\x02" "07EAE" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetMemory, AVRInterface::eA, "\x02" "07E2B" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetMemory, AVRInterface::eB, "\x02" "07E2C" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetMemory, AVRInterface::eC, "\x02" "07E2D" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetMemory, AVRInterface::eD, "\x02" "07E2E" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetMemory, AVRInterface::eE, "\x02" "07E2F" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetMemory, AVRInterface::eF, "\x02" "07E20" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetRecall, AVRInterface::eA, "\x02" "07E35" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetRecall, AVRInterface::eB, "\x02" "07E36" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetRecall, AVRInterface::eC, "\x02" "07E37" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetRecall, AVRInterface::eD, "\x02" "07E38" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetRecall, AVRInterface::eE, "\x02" "07E39" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncRadioPresetRecall, AVRInterface::eF, "\x02" "07E3A" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeMemory, AVRInterface::eA, "\x02" "07E6B" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeMemory, AVRInterface::eB, "\x02" "07E6C" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeMemory, AVRInterface::eC, "\x02" "07E6D" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeMemory, AVRInterface::eD, "\x02" "07E6E" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeMemory, AVRInterface::eE, "\x02" "07E6F" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeMemory, AVRInterface::eF, "\x02" "07E60" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeRecall, AVRInterface::eA, "\x02" "07E75" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeRecall, AVRInterface::eB, "\x02" "07E76" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeRecall, AVRInterface::eC, "\x02" "07E77" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeRecall, AVRInterface::eD, "\x02" "07E78" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeRecall, AVRInterface::eE, "\x02" "07E79" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncVolumeRecall, AVRInterface::eF, "\x02" "07E7A" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeMemory, AVRInterface::eA, "\x02" "07E87" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeMemory, AVRInterface::eB, "\x02" "07E88" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeMemory, AVRInterface::eC, "\x02" "07E89" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeMemory, AVRInterface::eD, "\x02" "07E8A" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeMemory, AVRInterface::eE, "\x02" "07E8B" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeMemory, AVRInterface::eF, "\x02" "07E8C" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeRecall, AVRInterface::eA, "\x02" "07E8D" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeRecall, AVRInterface::eB, "\x02" "07E8E" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeRecall, AVRInterface::eC, "\x02" "07E8F" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeRecall, AVRInterface::eD, "\x02" "07E90" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeRecall, AVRInterface::eE, "\x02" "07E91" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncVolumeRecall, AVRInterface::eF, "\x02" "07E92" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeMemory, AVRInterface::eA, "\x02" "07E20" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeMemory, AVRInterface::eB, "\x02" "07E21" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeMemory, AVRInterface::eC, "\x02" "07E22" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeMemory, AVRInterface::eD, "\x02" "07E23" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeMemory, AVRInterface::eE, "\x02" "07E24" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeMemory, AVRInterface::eF, "\x02" "07E25" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeRecall, AVRInterface::eA, "\x02" "07E60" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeRecall, AVRInterface::eB, "\x02" "07E61" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeRecall, AVRInterface::eC, "\x02" "07E62" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeRecall, AVRInterface::eD, "\x02" "07E63" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeRecall, AVRInterface::eE, "\x02" "07E64" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncVolumeRecall, AVRInterface::eF, "\x02" "07E65" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDC1TrigControl, AVRInterface::eZone1, "\x02" "07E32" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDC1TrigControl, AVRInterface::eZone2, "\x02" "07E33" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDC1TrigControl, AVRInterface::eZone3, "\x02" "07E31" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncDC1OnOff, AVRInterface::eOn, "\x02" "07E71" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncDC1OnOff, AVRInterface::eOff, "\x02" "07E72" "\x03", 7 }, { AVRSubsys::eZone1, AVRFunc::fncDC1OnOff, AVRInterface::eOn, "\x02" "07E73" "\x03", 7 }, { AVRSubsys::eZone1, AVRFunc::fncDC1OnOff, AVRInterface::eOff, "\x02" "07E74" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncDC1OnOff, AVRInterface::eOn, "\x02" "07E83" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncDC1OnOff, AVRInterface::eOff, "\x02" "07E84" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDualMono, AVRInterface::eDualMain, "\x02" "07E93" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDualMono, AVRInterface::eDualSub, "\x02" "07E94" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDualMono, AVRInterface::eDualAll, "\x02" "07E95" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDC1TrigControl, AVRInterface::eZone1, "\x02" "07E96" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDC1TrigControl, AVRInterface::eZone2, "\x02" "07E97" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDC1TrigControl, AVRInterface::eZone3, "\x02" "07E9F" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncDC1TrigControl, AVRInterface::eZoneOR, "\x02" "07E98" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncDC2OnOff, AVRInterface::eOn, "\x02" "07E3C" "\x03", 7 }, { AVRSubsys::eZone2, AVRFunc::fncDC2OnOff, AVRInterface::eOff, "\x02" "07E3D" "\x03", 7 }, { AVRSubsys::eZone1, AVRFunc::fncDC2OnOff, AVRInterface::eOn, "\x02" "07E3E" "\x03", 7 }, { AVRSubsys::eZone1, AVRFunc::fncDC2OnOff, AVRInterface::eOff, "\x02" "07E3F" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncDC2OnOff, AVRInterface::eOn, "\x02" "07E85" "\x03", 7 }, { AVRSubsys::eZone3, AVRFunc::fncDC2OnOff, AVRInterface::eOff, "\x02" "07E86" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSpeakerBZone, AVRInterface::eZone1, "\x02" "07E28" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncSpeakerBZone, AVRInterface::eZone2, "\x02" "07E29" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncZone2SpeakerOnOff, AVRInterface::eOn, "\x02" "07E99" "\x03", 7 }, { AVRSubsys::eMain, AVRFunc::fncZone2SpeakerOnOff, AVRInterface::eOff, "\x02" "07E9A" "\x03", 7 }, }; bool AVRInterface::AVRCommand(AVRInterface::AVRSubsystem_E subsystem, AVRInterface::AVRFunction_E function, AVRArg_T arg) { bool found = false; for (int i = 0; i < sizeof(MessageTable) / sizeof(MessageTable_T); i++) { if (MessageTable[i].subsystem == subsystem && MessageTable[i].function == function and MessageTable[i].arg == arg) { found = true; ProcessSerialQueue(MessageTable[i].Message, MessageTable[i].MessageLen); break; } } if (!found) { // then what? } return true; } /// 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 && ReportInformation) { char buf[LONGESTTEXT]; sprintf_s(buf, LONGESTTEXT, "Model ID: %c%c%c%c%c, ver: %c\n", avrStatus.header.type[0], avrStatus.header.type[1], avrStatus.header.type[2], avrStatus.header.type[3], avrStatus.header.type[4], avrStatus.header.version); (*ReportInformation)(mtModelInfo, buf); uint8_t *p = (uint8_t *)&avrStatus.config; (*ReportInformation)(mtStreamStart, "---- AVR Status Report ----\n"); PCMessage("Baud Rate", 1, &p); PCMessage("Rx Buffer", 2, &p); PCMessage("Cmd Timeout", 3, &p); PCMessage("Handshake", 1, &p); PCMessage("Busy", 1, &p, BusyToText); PCMessage("Power", 1, &p, OffOnText); if (avrStatus.configValid) { PCMessage("Input", 1, &p, InputText); 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("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, 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, 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, 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, M20P0dbText); PCMessage("LFE HP", 2, &p, M20P0dbText); PCMessage("Audio Delay", 2, &p, ZeroTo160msText); PCMessage("?????", 4, &p); PCMessage("Inp Mode Set", 1, &p, AutoLastText); PCMessage("Dimmer", 1, &p, M4To0Text); PCMessage("OSD Msg", 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, 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, SwfrMainBothText); PCMessage("6 ch center", 1, &p); PCMessage("6 ch sub", 1, &p); PCMessage("Main level", 1, &p); PCMessage("Test Mode", 1, &p, OffDolbyDspText); PCMessage("?????", 1, &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, 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, PRSBText); } } }