// // The AVR Interface object and interaction methods // #include #include #include #include #include #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, /// 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 " }, { 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" }, { Hall_B, "Hall B" }, { Hall_C, "Hall C" }, { Hall_USA, "Hall USA" }, { Hall_E, "Hall E" }, { Live_Concert, "Live Concert" }, { Tokyo, "Tokyo" }, { Freiburg, "Freiburg" }, { Royaumont, "Royaumont" }, { Village_Gate, "Village Gate" }, { Village_Vanguard, "Village Vanguard" }, { The_Bottom_Line, "The Bottom Line" }, { The_Roxy_Theater, "The Roxy Theater" }, { Warehouse_Loft, "Warehouse Loft" }, { Arena, "Arena" }, { Disco, "Disco" }, { Party, "Party" }, { Game, "Game" }, { Stereo_6_8Ch, "Stereo 6/8Ch" }, { Pop_Rock, "Pop/Rock" }, { DJ, "DJ" }, { Opera, "Opera" }, { Pavillion, "Pavillion" }, { Mono_Movie, "Mono/Movie" }, { Variety_Sports, "Variety/Sports" }, { Spectacre, "Spectacre" }, { Sci_Fi, "Sci-Fi" }, { Adventure, "Adventure" }, { General, "General" }, { Normal, "Normal" }, { Enhanced, "Enhanced" }, { PLII_Movie, "PLII Movie" }, { PLII_Music, "PLII Music" }, { Neo_6_Movie, "Neo 6 Movie" }, { Neo_6_Music, "Neo 6 Music" }, { Direct_2Ch, "Direct 2Ch" }, { Stereo_2Ch, "Stereo 2Ch" }, { THX_Ultra_PL, "THX Ultra PL" }, { THX_Music, "THX Music" }, { 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); } } }