From c66e6af1535a48ae7d94bc83851102b4cbef1407 Mon Sep 17 00:00:00 2001 From: David Date: Sat, 24 Jan 2026 13:33:57 -0600 Subject: [PATCH] All command and response handled with decoders. --- AVR Working Controller/AVR.cpp | 1034 ++++++++++++----- ...aha RX-V2400_RS232C_CommandsForSW.pdf.xlsx | Bin 37073 -> 41527 bytes .../Yamaha RX-V2400_RS232C_Standard.pdf | Bin 179354 -> 179906 bytes 3 files changed, 735 insertions(+), 299 deletions(-) diff --git a/AVR Working Controller/AVR.cpp b/AVR Working Controller/AVR.cpp index 838a96f..8a1d185 100644 --- a/AVR Working Controller/AVR.cpp +++ b/AVR Working Controller/AVR.cpp @@ -28,7 +28,7 @@ DWORD const retryInterval = 1000; // ms // // typedef struct { - uint8_t DT0; // * Baud Rate + uint8_t DT0; // * Baud Rate '@' uint8_t DT1; // * Receive Buffer 'E' uint8_t DT2; // * Receive Buffer '0' uint8_t DT3; // * '1' @@ -41,165 +41,136 @@ typedef struct { uint8_t DT10; // 6ch input 0:Off, 1:On uint8_t DT11; // Input Mode 0:AUTO, 2:DTS, 4:Analog, 5:Analog Only uint8_t DT12; // Audio Mute 0:Off, 1:On - uint8_t DT13; - uint8_t DT14; - uint8_t DT15; - uint8_t DT16; - uint8_t DT17; - uint8_t DT18; - uint8_t DT19; + uint8_t DT13; // Zone2 Input 0: PHONO / 1: CD / 2: TUNER / 3: CD-R / 4: MD-TAPE / 5: DVD / 6: D-TV-LD / 7: CBL-SAT / 9: VCR1 / A: VCR2-DVR / C: V-AUX + uint8_t DT14; // Zone2 Mute 0: OFF / 1: ON + uint8_t DT15; // Master Volume Upper 4 bit + uint8_t DT16; // Master Volume Lower 4 bit + uint8_t DT17; // Zone2 Volume Upper 4 bit + uint8_t DT18; // Zone2 Volume Lower 4 bit + uint8_t DT19; // Program Upper 4 bit + uint8_t DT20; // Program Lower 4 bit + uint8_t DT21; // Effect 0: OFF / 1: ON + uint8_t DT22; // 6.1/ES key status 0: OFF / 1: MATRIX ON / 2: DISCRETE ON / 3: AUTO + uint8_t DT23; // OSD* 0: FULL / 1: SHORT / 2: OFF + uint8_t DT24; // Sleep 0: 120 / 2: 90 / 3: 60 / 4: 30 / 5: OFF + uint8_t DT25; // Tuner Page 0: Page A / 1: Page B / 2: Page C / 3: Page D / 4: PageE + uint8_t DT26; // Tuner No. 0: No.1 / 1: No.2 / 2: No.3 / 3: No.4 / 4: No.5 / 5: No.6 / 6: No.7 / 7: No.8 + uint8_t DT27; // Night mode 0: OFF / 1: ON + uint8_t DT28; // Care + uint8_t DT29; // Speaker relay A 0: OFF / 1: ON + uint8_t DT30; // Speaker relay B 0: OFF / 1: ON + uint8_t DT31; // Playback 0: 6ch input / 1: Analog / 2: PCM / 3: DD*(except 2.0) / 4: DD(2.0) / 5: DD.Karaoke / 6: DD.EX / 7: DTS / 8: DTS-ES / 9: Other DIGITAL / A: DTS Analog Mute / B: DTS ES Discrete + uint8_t DT32; // Fs 0: Analog / 1: 32kHz / 2: 44.1kHz / 3: 48kiHz / 4: 64kHz / 5: 88.2kHz / 6: 96kHz / 7: Unknown B: DTS 96/24 + uint8_t DT33; // EX/ES playback 0: OFF / 1: MATRIX ON / 2: DISCRETE ON + uint8_t DT34; // Thr / Bypass 0: Normal / 1: Bypass + uint8_t DT35; // RED dts 0: Release / 1: Wait + uint8_t DT36; // Head Phone 0: OFF / 1: ON + uint8_t DT37; // TUNER BAND 0: FM / 1: AM + uint8_t DT38; // TUNER TUNED 0: NOT TUNED / 1: TUNED + uint8_t DT39; // DC1 Control Out 0: LOW / 1: HIGH - uint8_t DT20; - uint8_t DT21; - uint8_t DT22; - uint8_t DT23; - uint8_t DT24; - uint8_t DT25; - uint8_t DT26; - uint8_t DT27; - uint8_t DT28; - uint8_t DT29; + uint8_t DT40; // Don’t care + uint8_t DT41; // Don't Care + uint8_t DT42; // 0-2 DC1 TRG Ctrl. 0: Zone1 / 1: Zone2 / 2: Zone1&2 + uint8_t DT43; // 0/1 dts 96/24 0: OFF / 1: ON + uint8_t DT44; // 0-2 DC2 TRG Ctrl. 0: Zone1 / 1: Zone2 / 2: Zone1&2 + uint8_t DT45; // 0/1 DC2 Trigger 0: LOW / 1: HIGH + uint8_t DT46; // SP B set 0: Zone1 / 1: Zone2 + uint8_t DT47; // Zone 2 SP out 0: OFF / 1: ON + uint8_t DT48; // MAIN R Upper 4bit + uint8_t DT49; // Lower 4bit + uint8_t DT50; // MAIN L Upper 4bit + uint8_t DT51; // Lower 4bit + uint8_t DT52; // CENTER Upper 4bit + uint8_t DT53; // Lower 4bit + uint8_t DT54; // REAR R Upper 4bit + uint8_t DT55; // Lower 4bit + uint8_t DT56; // REAR L Upper 4bit + uint8_t DT57; // Lower 4bit + uint8_t DT58; // SUR BACK Upper 4bit + uint8_t DT59; // R Lower 4bit + uint8_t DT60; // SUR BACK Upper 4bit + uint8_t DT61; // L Lower 4bit + uint8_t DT62; // FRONT R Upper 4bit + uint8_t DT63; // Lower 4bit + uint8_t DT64; // FRONT L Upper 4bit + uint8_t DT65; // Lower 4bit + uint8_t DT66; // SWFR 1 Upper 4bit + uint8_t DT67; // Lower 4bit + uint8_t DT68; // Don't Care + uint8_t DT69; // Don't Care + uint8_t DT70; // Don't Care + uint8_t DT71; // Don't Care + uint8_t DT72; // Don't Care + uint8_t DT73; // Don't Care + uint8_t DT74; // LFE Lvl. SP Upper 4bit + uint8_t DT75; // Lower 4bit + uint8_t DT76; // LFE Lvl. HP Upper 4bit + uint8_t DT77; // Lower 4bit + uint8_t DT78; // Audio Delay Upper 4bit + uint8_t DT79; // Lower 4bit - uint8_t DT30; - uint8_t DT31; - uint8_t DT32; - uint8_t DT33; - uint8_t DT34; - uint8_t DT35; - uint8_t DT36; - uint8_t DT37; - uint8_t DT38; - uint8_t DT39; + uint8_t DT80; // Don't Care + uint8_t DT81; // Don't Care + uint8_t DT82; // Don't Care + uint8_t DT83; // Don't Care + uint8_t DT84; // Input mode set 0: AUTO / 1: LAST + uint8_t DT85; // Dimmer 0: -4 / 1: -3 / 2: -2 / 3: -1 / 4: 0 + uint8_t DT86; // OSD Message + uint8_t DT87; // OSD shift Upper 4bit + uint8_t DT88; // Lower 4bit + uint8_t DT89; // Glay back 0: OFF / 1: AUTO + uint8_t DT90; // Video conversion 0: OFF / 1: ON + uint8_t DT91; // D. Range SP 0: MAX / 1: STD / 2: MIN + uint8_t DT92; // HP 0: MAX / 1: STD / 2: MIN + uint8_t DT93; // Zone 2 vol. Out + uint8_t DT94; // Don't Care + uint8_t DT95; // Memory guard 0: OFF / 1: ON + uint8_t DT96; // SP set Center 0: Large / 1: Small / 2: None + uint8_t DT97; // Main 0: Large / 1: Small + uint8_t DT98; // Rear L/R 0: Large / 1: Small / 2: None + uint8_t DT99; // Rear CT 0: Large / 1: Small / 2: None + uint8_t DT100; // Front 0: Yes / 1: None + uint8_t DT101; // LFE/BASS 0: SWFR / 1: Main / 2: Both + uint8_t DT102; // 6CH Center 0: Center / 1: Main + uint8_t DT103; // SWFR 0: SWFR / 1: Main + uint8_t DT104; // Main level 0: Normal / 1: -10dB + uint8_t DT105; // Test mode 0: OFF / 1: Dolby / 2: DTS + uint8_t DT106; // Don't Care + uint8_t DT107; // LVL 6CH MAIN L Upper 4bit + uint8_t DT108; // Lower 4bit + uint8_t DT109; // MAIN R Upper 4bit + uint8_t DT110; // Lower 4bit + uint8_t DT111; // CENTER Upper 4bit + uint8_t DT112; // Lower 4bit + uint8_t DT113; // SL Upper 4bit + uint8_t DT114; // Lower 4bit + uint8_t DT115; // SR Upper 4bit + uint8_t DT116; // Lower 4bit + uint8_t DT117; // SBL Upper 4bit + uint8_t DT118; // Lower 4bit + uint8_t DT119; // SBR Upper 4bit + uint8_t DT120; // Lower 4bit + uint8_t DT121; // FRONT L Upper 4bit + uint8_t DT122; // Lower 4bit + uint8_t DT123; // FRONT R Upper 4bit + uint8_t DT124; // Lower 4bit + uint8_t DT125; // SWFR Upper 4bit + uint8_t DT126; // Lower 4bit + uint8_t DT127; // 0 - C Z3 Input + uint8_t DT128; // 0/1 Z3 Mute + uint8_t DT129; // 0 - F Z3 Volume Upper 4bit - uint8_t DT40; - uint8_t DT41; - uint8_t DT42; - uint8_t DT43; - uint8_t DT44; - uint8_t DT45; - uint8_t DT46; - uint8_t DT47; - uint8_t DT48; - uint8_t DT49; + uint8_t DT130; // 0 - F Lower 4bit + uint8_t DT131; // Don't Care + uint8_t DT132; // MULTI_CH SELECT 00:6CH / 01:8CH TUNER / 02: 8CH CD / 04: 8CH CD-R / 05: 8CH DVD / 06: DTV / 07: 8CH CBL/SAT / 09: 8CH VCR1 / 0A: VCR2/DVR / 0C: VAUX + uint8_t DT133; // MULTI_CH SURROUND to 00: Surround / 01: Main + uint8_t DT134; // SP SET SW1 00: L-R / 01: F-R / 02: NONE + uint8_t DT135; // SP SET CROSSOVER 00: 40Hz / 01: 60Hz / 02: 80Hz / 03: 90Hz / 04: 100Hz / 05: 110Hz / 06: 120Hz / 07: 160Hz / 08: 200Hz + uint8_t DT136; // COMPONENT OSD 00: OFF / 01: ON + uint8_t DT137; // PB/SB SELECT 00: PR / 01: SB - uint8_t DT50; - uint8_t DT51; - uint8_t DT52; - uint8_t DT53; - uint8_t DT54; - uint8_t DT55; - uint8_t DT56; - uint8_t DT57; - uint8_t DT58; - uint8_t DT59; - - uint8_t DT60; - uint8_t DT61; - uint8_t DT62; - uint8_t DT63; - uint8_t DT64; - uint8_t DT65; - uint8_t DT66; - uint8_t DT67; - uint8_t DT68; - uint8_t DT69; - - uint8_t DT70; - uint8_t DT71; - uint8_t DT72; - uint8_t DT73; - uint8_t DT74; - uint8_t DT75; - uint8_t DT76; - uint8_t DT77; - uint8_t DT78; - uint8_t DT79; - - uint8_t DT80; - uint8_t DT81; - uint8_t DT82; - uint8_t DT83; - uint8_t DT84; - uint8_t DT85; - uint8_t DT86; - uint8_t DT87; - uint8_t DT88; - uint8_t DT89; - - uint8_t DT90; - uint8_t DT91; - uint8_t DT92; - uint8_t DT93; - uint8_t DT94; - uint8_t DT95; - uint8_t DT96; - uint8_t DT97; - uint8_t DT98; - uint8_t DT99; - - uint8_t DT100; - uint8_t DT101; - uint8_t DT102; - uint8_t DT103; - uint8_t DT104; - uint8_t DT105; - uint8_t DT106; - uint8_t DT107; - uint8_t DT108; - uint8_t DT109; - - uint8_t DT110; - uint8_t DT111; - uint8_t DT112; - uint8_t DT113; - uint8_t DT114; - uint8_t DT115; - uint8_t DT116; - uint8_t DT117; - uint8_t DT118; - uint8_t DT119; - - uint8_t DT120; - uint8_t DT121; - uint8_t DT122; - uint8_t DT123; - uint8_t DT124; - uint8_t DT125; - uint8_t DT126; - uint8_t DT127; - uint8_t DT128; - uint8_t DT129; - - uint8_t DT130; - uint8_t DT131; - uint8_t DT132; - uint8_t DT133; - uint8_t DT134; - uint8_t DT135; - uint8_t DT136; - uint8_t DT137; // PB/SB Select 00: PR, 01: SB // Last documented register - uint8_t DT138; - uint8_t DT139; - - uint8_t DT140; - uint8_t DT141; - uint8_t DT142; - uint8_t DT143; - uint8_t DT144; - uint8_t DT145; - uint8_t DT146; - uint8_t DT147; - uint8_t DT148; - uint8_t DT149; - - uint8_t DT150; - uint8_t DT151; - uint8_t DT152; - uint8_t DT153; - uint8_t DT154; - uint8_t DT155; - - uint8_t DT156_255[100]; + uint8_t DT138[100]; // From here on is just buffer in case it sends more data } AVR_Configuration_T; @@ -285,10 +256,54 @@ const char *BusyToText(uint8_t val); const char *WarnToText(uint8_t val); const char *PlaybackToText(uint8_t val); const char *FsToText(uint8_t val); +const char *OffMatrixDiscreteText(uint8_t val); +const char *OffMatrixDiscreteAutoText(uint8_t val); +const char *ReleaseWaitText(uint8_t val); +const char *NotTunedTunedText(uint8_t val); +const char *InputModeText(uint8_t val); +const char *PresetNumberText(uint8_t val); +const char *OSDFullShortOffText(uint8_t val); +const char *SleepTimerText(uint8_t val); +const char *InputText(uint8_t val); const char *ZonePower(uint8_t val); const char *VolumeDB(uint8_t val); +const char *PM10dbText(uint8_t val); +const char *M20P0dbText(uint8_t val); +const char *BalanceText(uint8_t val); +const char *ZeroTo160msText(uint8_t val); +const char *ZeroTo5msText(uint8_t val); +const char *ZeroTo30msText(uint8_t val); +const char *AutoLastText(uint8_t val); +const char *M4To0Text(uint8_t val); +const char *M5toP5Text(uint8_t val); +const char *OffAutoText(uint8_t val); +const char *MaxStdMinText(uint8_t val); +const char *VarFixText(uint8_t val); +const char *Mode1Mode2Text(uint8_t val); +const char *LSNText(uint8_t val); +const char *LLSSNText(uint8_t val); +const char *YesNoneText(uint8_t val); +const char *SwfrMainBothText(uint8_t val); +const char *LrFrNoneText(uint8_t val); +const char *CenterMainText(uint8_t val); +const char *SwfrMainText(uint8_t val); +const char *SurrMainText(uint8_t val); +const char *SixEightText(uint8_t val); +const char *CrossOverText(uint8_t val); +const char *OffDolbyDspText(uint8_t val); +const char *OffOn2OnMultiText(uint8_t val); +const char *M10P10dbText(uint8_t val); + const char *ProgramName(uint8_t val); -const char *OnOffText(uint8_t val); +const char *OffOnText(uint8_t val); +const char *FMAMText(uint8_t val); +const char *PresetLabelText(uint8_t val); +const char *MainSubAllText(uint8_t val); +const char *WhichZoneText(uint8_t val); +const char *Norm10dbDownText(uint8_t val); +const char *MainZoneBText(uint8_t val); + + void ShowAllStatusInfo(); @@ -304,6 +319,7 @@ WORD wOldColorAttrs; // Save the current console colors short consoleWidth = 105; short consoleHeight = 80; +short consoleScrollHeight = 30; // 0 99 // +---------------------------------------------------------------+ // | Program banner information | 0 @@ -318,9 +334,8 @@ short consoleHeight = 80; // | | // | | 79 // +---------------------------------------------------------------+ 80 -short scrollTop = 59; -short scrollBot = 79; -short consoleScrollHeight = 20; +short scrollBot = 0; // set at init: consoleHeight - 1 +short scrollTop = 0; // set at init: consoleHeight - consoleScrollHeight - 1 void Console_Init(); @@ -371,7 +386,6 @@ typedef struct { 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 - void (*fncHelper)(uint8_t rCmd, uint8_t rDat, uint8_t *pMessage, uint32_t msgLen); const char *TextFormatter; // used primarily for development printf(TextFormatter, value) const char *(*fncValueToText)(uint8_t rDat); } MessageHandler_T; @@ -390,43 +404,125 @@ void RxProgramStatus(uint8_t rCmd, uint8_t rDat, uint8_t *pMessage, uint32_t msg // 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 // const MessageHandler_T MessageHandlers[] = { - //rCmd cfgOfs num ShowAll function - {0x00, 7, 1, 1, RxSystemReport }, - {0x01, 0, 0, 0, RxWarningReport }, - {0x10, 31, 1, 1, RxPlaybackReport }, - {0x11, 32, 1, 1, RxFsReport }, - {0x12, 33, 1, 1, NULL }, // EX/EX - {0x13, 34, 1, 1, NULL }, // Thr / Bypass - {0x14, 35, 1, 1, NULL }, // RED dts - {0x15, 38, 1, 1, NULL }, // Tuner tuned - {0x16, 43, 1, 1, NULL }, // Dts 96/24 - {0x20, 8, 0, 1, NULL, "Zone Power: %s", ZonePower}, - {0x21, 9, 1, 1, NULL }, // Input Source - {0x22, 11, 1, 1, NULL }, // Input Mode - {0x23, 12, 1, 1, NULL, "Mute: %s", OnOffText}, - {0x24, 13, 1, 1, NULL }, // Zone 2 Input Source - {0x25, 14, 1, 1, NULL, "Zone 2 Mute: %s", OnOffText}, - {0x26, 15, 2, 1, RxMasterVolStatus, "Volume: %s", VolumeDB}, - {0x27, 17, 2, 1, NULL }, // Zone 2 Vol - {0x28, 19, 2, 1, RxProgramStatus, "Program: %s", ProgramName}, // Program - {0x29, 25, 1, 1, NULL }, // Tuner Page - {0x2A, 26, 1, 1, NULL }, // Tuner Preset Number - {0x2B, 23, 1, 1, NULL }, // OSD - {0x2C, 24, 1, 1, NULL }, // Sleep Timer - {0x2D, 22, 1, 1, NULL }, // EX/ES(Key) - {0x2E, 29, 1, 1, NULL }, // Speaker Relay A - {0x2F, 30, 1, 1, NULL }, // Speaker Relay B + // + // 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 + // | | | | | +--- Help 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", MainZoneBText }, + { 0x3F, 46, 1, 1, "Zone 2 Speaker: %s", OffOnText }, - {0x36, 39, 1, 1, NULL, "Trigger Out 1: %s", OnOffText}, + { 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 }, - {0x3C, 45, 1, 1, NULL, "Trigger Out 2: %s", OnOffText}, + { 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 }, - {0x82, 27, 1, 1, NULL, "Night Mode: %s", OnOffText}, + { 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 }, - {0xA1, 0, 0, 0, NULL, "Zone 3 Mute: %s\n", OnOffText}, + { 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 }, }; @@ -468,7 +564,7 @@ void RxPlaybackReport(uint8_t rCmd, uint8_t rDat, uint8_t *pMessage, uint32_t ms void RxFsReport(uint8_t rCmd, uint8_t rDat, uint8_t *pMessage, uint32_t msgLen) { (void)rCmd, pMessage, msgLen; char buf[MAXTEXTLEN]; - sprintf_s(buf, MAXTEXTLEN, "Playback Report: %s\n", FsToText(rDat)); + sprintf_s(buf, MAXTEXTLEN, "Fs Report: %s\n", FsToText(rDat)); Console_Write(buf); Console_ScrollBottomRegion(scrollTop, scrollBot); //ShowAllStatusInfo(); @@ -665,13 +761,15 @@ void EmitRuntimeHelp() { Console_Write(buf); } if (avr.IsOpen()) { + Console_ScrollBottomRegion(scrollTop, scrollBot); Console_SetCursor(0, -1); printf(" Com Status: RTS: %-3s ", avr.Get_RTS_State() ? "ON" : "OFF"); printf("DTR: %-3s ", avr.Get_DTR_State() ? "ON" : "OFF"); printf("CTS: %-3s ", avr.Get_CTS_State() ? "ON" : "OFF"); printf("DSR: %-3s ", avr.Get_DSR_State() ? "ON" : "OFF"); - printf("RI: %-3s\n", avr.Get_RI_State() ? "ON" : "OFF"); + printf("RI: %-3s", avr.Get_RI_State() ? "ON" : "OFF"); Console_ScrollBottomRegion(scrollTop, scrollBot); + Console_SetCursor(0, -1); } } @@ -683,7 +781,7 @@ void EmitRuntimeHelp() { // and pre and post-pending \n // static void PCMessage(const char *msg, int len, uint8_t **src, const char * (fncHelper)(uint8_t val) = NULL) { - char buf[MAXTEXTLEN]; + char buf[MAXTEXTLEN] = ""; const char *p = buf; if (fncHelper) { @@ -698,7 +796,7 @@ static void PCMessage(const char *msg, int len, uint8_t **src, const char * (fnc buf[len] = '\0'; } - char outBuf[MAXTEXTLEN]; + char outBuf[MAXTEXTLEN] = ""; sprintf_s(outBuf, MAXTEXTLEN, "%17s %-8s", msg, p @@ -781,7 +879,7 @@ const char *FsToText(uint8_t val) { -const char * OnOffText(uint8_t val) { +const char * OffOnText(uint8_t val) { static char buf[16]; if (val == 0) { strcpy_s(buf, sizeof(buf), "Off"); @@ -793,6 +891,289 @@ const char * OnOffText(uint8_t val) { return buf; } +const char *YesNoneText(uint8_t val) { + static const char *buf[] = { + "Yes", "None", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *OffMatrixDiscreteText(uint8_t val) { + static const char *buf[] = { + "Off", "Matrix On", "Discrete On", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *OffMatrixDiscreteAutoText(uint8_t val) { + static const char *buf[] = { + "Off", "Matrix On", "Discrete On", "Auto", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *ReleaseWaitText(uint8_t val) { + static const char *buf[] = { + "Release", "Wait", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *NotTunedTunedText(uint8_t val) { + static const char *buf[] = { + "Not Tuned", "Tuned", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *InputModeText(uint8_t val) { + static const char *buf[] = { + "Auto", "DTS", "Analog", "Analog Only", "AAC", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *SwfrMainBothText(uint8_t val) { + static const char *buf[] = { + "Subwoofer", "Main", "Both", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *LrFrNoneText(uint8_t val) { + static const char *buf[] = { + "L-R", "F-R", "None", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *CenterMainText(uint8_t val) { + static const char *buf[] = { + "Center", "Main", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *SwfrMainText(uint8_t val) { + static const char *buf[] = { + "Subwoofer", "Main", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *SurrMainText(uint8_t val) { + static const char *buf[] = { + "Surround", "Main", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *SixEightText(uint8_t val) { + static const char *buf[] = { + "6 Ch", "8 Ch", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *CrossOverText(uint8_t val) { + static char buf[16]; + static const uint8_t Hz[] = { + 40, 60, 80, 90, 100, 110, 120, 160, 200, 0 + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + sprintf_s(buf, sizeof(buf), "%d Hz", Hz[val]); + return buf; +} + +const char *OffDolbyDspText(uint8_t val) { + static const char *buf[] = { + "Off", "Dolby", "DSP" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *OffOn2OnMultiText(uint8_t val) { + static const char *buf[] = { + "Off", "On (2 Ch)", "On (Multi)" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + + +const char *Norm10dbDownText(uint8_t val) { + static const char *buf[] = { + "Normal", "-10 db", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *MainZoneBText(uint8_t val) { + static const char *buf[] = { + "Main", "Zone B", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + + +const char *FMAMText(uint8_t val) { + static const char *buf[] = { + "FM", "AM", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *AutoLastText(uint8_t val) { + static const char *buf[] = { + "Auto", "Last", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *OSDFullShortOffText(uint8_t val) { + static const char *buf[] = { + "Full", "Short", "Off", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *SleepTimerText(uint8_t val) { + static const char *buf[] = { + "120 min", "90 min", "60 min", "30 min", "Off", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *PresetLabelText(uint8_t val) { + static const char *buf[] = { + "A", "B", "C", "D", "E", "F", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *PresetNumberText(uint8_t val) { + static const char *buf[] = { + "1", "2", "3", "4", "5", "6", "7", "8", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *MainSubAllText(uint8_t val) { + static const char *buf[] = { + "Main", "Sub", "All", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *WhichZoneText(uint8_t val) { + static const char *buf[] = { + "All", "Zone 1", "Zone 2", "Zone 3", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *OffAutoText(uint8_t val) { + static const char *buf[] = { + "Off", "Auto", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *MaxStdMinText(uint8_t val) { + static const char *buf[] = { + "Max", "Std", "Min", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *VarFixText(uint8_t val) { + static const char *buf[] = { + "Var", "Fix", "Unk" + }; + if (val >= sizeof(buf)/sizeof(buf[0])) + val = sizeof(buf)/sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *LSNText(uint8_t val) { + static const char *buf[] = { + "Large", "Small", "None", "Unk" + }; + if (val >= sizeof(buf)/sizeof(buf[0])) + val = sizeof(buf)/sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *LLSSNText(uint8_t val) { + static const char *buf[] = { + "Large x 2", "Large x1", "Small x 2", "Small x 1", "None", "Unk" + }; + if (val >= sizeof(buf)/sizeof(buf[0])) + val = sizeof(buf)/sizeof(buf[0]) - 1; + return buf[val]; +} + +const char *Mode1Mode2Text(uint8_t val) { + static const char *buf[] = { + "Mode 1", "Mode 2", "Unk" + }; + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; +} + const char *ZonePower(uint8_t val) { static char buf[60]; const char *powerList[8] = { @@ -813,15 +1194,16 @@ const char *ZonePower(uint8_t val) { } const char * InputText(uint8_t val) { - const char *inputList[13] = { - "0:Phono", "1:CD", "2:Tuner", "3:CD-R", "4:MD-Tape", "5:DVD", "6:D-TV", - "7:Cable", "8:unk", "9:VCR1", "A:VCR2", "B:unk", "C:V-Aux" + const char *buf[] = { + "0:Phono", "1:CD", "2:Tuner", "3:CD-R", "4:MD-Tape", "5:DVD", "6:D-TV", "7:Cable", "8:unk", + "9:VCR1", "A:VCR2", "B:unk", "C:V-Aux", "D:unk", "E:unk", "F:unk", + "6 Ch 0:Phono", "6 Ch 1:CD", "6 Ch 2:Tuner", "6 Ch 3:CD-R", "6 Ch 4:MD-Tape", "6 Ch 5:DVD", "6 Ch 6:D-TV", "6 Ch 7:Cable", "6 Ch 8:unk", + "6 Ch 9:VCR1", "6 Ch A:VCR2", "6 Ch B:unk", "6 Ch C:V-Aux", "6 Ch D:unk", "6 Ch E:unk", "6 Ch F:unk", + "unknown" }; - if (val <= 12) { - return inputList[val]; - } else { - return "huh?"; - } + if (val >= sizeof(buf) / sizeof(buf[0])) + val = sizeof(buf) / sizeof(buf[0]) - 1; + return buf[val]; } const char *ProgramName(uint8_t val) { @@ -928,6 +1310,129 @@ const char *VolumeDB(uint8_t val) { return buf; } +const char *PM10dbText(uint8_t val) { + static char buf[16]; + float m, b; + + if (val < 0x14 || val > 0x3C) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + m = 0.5f; + b = -10.0f; + float db = m * (val - 0x14) + b; + sprintf_s(buf, sizeof(buf), "%+5.1f db", db); + } + return buf; +} + +const char *M20P0dbText(uint8_t val) { + static char buf[16]; + float m, b; + + if (val > 0x28) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + m = 0.5f; + b = -20.0f; + float db = m * (val) + b; + sprintf_s(buf, sizeof(buf), "%+5.1f db", db); + } + return buf; +} + +const char *M10P10dbText(uint8_t val) { + static char buf[16]; + float m, b; + + if (val < 0x14 || val > 0x3C) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + m = 0.5f; + b = -10.0f; + float db = m * (val - 0x14) + b; + sprintf_s(buf, sizeof(buf), "%+5.1f db", db); + } + return buf; +} + +const char *BalanceText(uint8_t val) { + static char buf[16]; + float m, b; + + if (val > 0x28) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + m = 0.5f; + b = -20.0f; + float lcr = m * (val + b); + sprintf_s(buf, sizeof(buf), "%+3.1f L-C-R", lcr); + } + return buf; +} + +const char *M4To0Text(uint8_t val) { + static char buf[16]; + + if (val > 0x04) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + sprintf_s(buf, sizeof(buf), "%u", (int8_t)val - 4); + } + return buf; +} + +const char *M5toP5Text(uint8_t val) { + static char buf[16]; + + if (val > 0x0A) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + sprintf_s(buf, sizeof(buf), "%+d", (int8_t)val - 5); + } + return buf; +} + +const char *ZeroTo160msText(uint8_t val) { + static char buf[16]; + + if (val > 0xA0) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + sprintf_s(buf, sizeof(buf), "%u ms", val); + } + return buf; +} + +const char *ZeroTo5msText(uint8_t val) { + static char buf[16]; + float m, b; + + if (val > 0x0A) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + m = 0.5f; + b = 0; + float delay = m * (val + b); + sprintf_s(buf, sizeof(buf), "%+3.1f ms", delay); + } + return buf; +} +const char *ZeroTo30msText(uint8_t val) { + static char buf[16]; + float m, b; + + if (val > 0x3C) { + sprintf_s(buf, sizeof(buf), "%02X OOR ?", val); + } else { + m = 0.5f; + b = 0; + float delay = m * (val + b); + sprintf_s(buf, sizeof(buf), "%+3.1f ms", delay); + } + return buf; +} + + void ShowAllStatusInfo(void) { if (avrStatus.headerValid) { bool priorState = Console_SetCursorVisibility(false); @@ -943,43 +1448,43 @@ void ShowAllStatusInfo(void) { PCMessage("Cmd Timeout", 3, &p); PCMessage("Handshake", 1, &p); PCMessage("Busy", 1, &p, BusyToText); - PCMessage("Power", 1, &p, OnOffText); + PCMessage("Power", 1, &p, OffOnText); if (avrStatus.configValid) { PCMessage("Input", 1, &p, InputText); PCMessage("6 ch", 1, &p); PCMessage("Inp mode", 1, &p); - PCMessage("Mute", 1, &p, OnOffText); + PCMessage("Mute", 1, &p, OffOnText); PCMessage("Zone 2", 1, &p, InputText); - PCMessage("Mute 2", 1, &p, OnOffText); + PCMessage("Mute 2", 1, &p, OffOnText); PCMessage("Volume", 2, &p, VolumeDB); PCMessage("Volume 2", 2, &p, VolumeDB); PCMessage("pgm", 2, &p); - PCMessage("effect", 1, &p, OnOffText); + PCMessage("effect", 1, &p, OffOnText); PCMessage("6.1/es status", 1, &p); PCMessage("OSD", 1, &p); PCMessage("sleep", 1, &p); PCMessage("Tuner Pg", 1, &p); PCMessage("Tuner #", 1, &p); - PCMessage("Night", 1, &p, OnOffText); + PCMessage("Night", 1, &p, OffOnText); PCMessage("?????", 1, &p); - PCMessage("Spkr A", 1, &p, OnOffText); - PCMessage("Spkr B", 1, &p, OnOffText); + PCMessage("Spkr A", 1, &p, OffOnText); + PCMessage("Spkr B", 1, &p, OffOnText); PCMessage("Playback", 1, &p); PCMessage("Fs", 1, &p); PCMessage("Ex/Es", 1, &p); PCMessage("Thr Bypass", 1, &p); PCMessage("Red DTS", 1, &p); - PCMessage("Headph", 1, &p, OnOffText); + PCMessage("Headph", 1, &p, OffOnText); PCMessage("Tuner Band", 1, &p); PCMessage("Tuner Tuned", 1, &p); PCMessage("DC1 Control Out", 1, &p); PCMessage("?????", 2, &p); PCMessage("DC1 Trig Ctrl", 1, &p); - PCMessage("DTS 96/24", 1, &p, OnOffText); + PCMessage("DTS 96/24", 1, &p, OffOnText); PCMessage("DC2 Trig Ctrl", 1, &p); PCMessage("DC2 Trig", 1, &p); PCMessage("Spkr B Set", 1, &p); - PCMessage("Zone 2 SP out", 1, &p, OnOffText); + PCMessage("Zone 2 SP out", 1, &p, OffOnText); PCMessage("Main R", 2, &p); PCMessage("Main L", 2, &p); PCMessage("Center", 2, &p); @@ -1000,12 +1505,12 @@ void ShowAllStatusInfo(void) { PCMessage("OSD Msg", 1, &p); PCMessage("OSD Shift", 2, &p); PCMessage("Gray Back", 1, &p); - PCMessage("Video Conv", 1, &p, OnOffText); + PCMessage("Video Conv", 1, &p, OffOnText); PCMessage("D Range SP", 1, &p); PCMessage("D Range HP", 1, &p); PCMessage("Zone 2 Vol out", 1, &p); PCMessage("?????", 1, &p); - PCMessage("Memory Guard", 1, &p, OnOffText); + 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); @@ -1035,7 +1540,7 @@ void ShowAllStatusInfo(void) { PCMessage("MultiCh Surround", 1, &p); PCMessage("SP Set SW1", 1, &p); PCMessage("SP Set Crossover", 1, &p); - PCMessage("Component OSD", 1, &p, OnOffText); + PCMessage("Component OSD", 1, &p, OffOnText); PCMessage("PB/SB Select", 1, &p); } printf("\n"); @@ -1066,13 +1571,13 @@ void ProcessKeyboard(void) { case 'S': avr.Set_RTS_State(TRUE); Console_SetCursor(0, -1); - printf("RTS set ON\n"); + printf("RTS set ON"); Console_ScrollBottomRegion(scrollTop, scrollBot); break; case 's': avr.Set_RTS_State(FALSE); Console_SetCursor(0, -1); - printf("RTS set OFF\n"); + printf("RTS set OFF"); Console_ScrollBottomRegion(scrollTop, scrollBot); break; default: @@ -1085,7 +1590,7 @@ void ProcessKeyboard(void) { } if (!cmdFound) { Console_SetCursor(0, -1); - printf("Unrecognized command '%c' (0x%02X)\n", isprint(c) ? c : '.', (unsigned char)c); + printf("Unrecognized command '%c' (0x%02X)", isprint(c) ? c : '.', (unsigned char)c); Console_ScrollBottomRegion(scrollTop, scrollBot); } break; @@ -1158,8 +1663,8 @@ int __cdecl main(int argc, char *argv[]) { } if (AttachToSerialPort()) { - printf("AVR - a command shell utility for a Yamaha RX-2400 AVR by D.Smart\n"); - printf("Attached to Serial Port on COM%i at %i baud\n", avrOnPort, avrBaud); + printf("AVR - a command shell utility for a Yamaha RX-2400 AVR by D.Smart "); + printf("[COM%i at %i baud]", avrOnPort, avrBaud); Console_WriteAt(0, scrollTop - 1, "----------------------------------------"); do { @@ -1256,9 +1761,9 @@ void ProcessResponse(uint8_t *szBuffer, uint32_t len) { if (MessageHandlers[i].numToTransfer == 2) { memcpy(&avrStatus.config.DT0 + MessageHandlers[i].configOffset, &szBuffer[5], 2); } - if (MessageHandlers[i].fncHelper) { - (*MessageHandlers[i].fncHelper)(rcmd, rdat, szBuffer, len); - } + //if (MessageHandlers[i].fncHelper) { + // (*MessageHandlers[i].fncHelper)(rcmd, rdat, szBuffer, len); + //} if (MessageHandlers[i].TextFormatter && MessageHandlers[i].fncValueToText) { sprintf_s(buf, MAXTEXTLEN, MessageHandlers[i].TextFormatter, MessageHandlers[i].fncValueToText(rdat)); Console_Write(buf); @@ -1269,84 +1774,13 @@ void ProcessResponse(uint8_t *szBuffer, uint32_t len) { } } } - Console_SetCursor(0, -1); if (!found) { - sprintf_s(buf, MAXTEXTLEN, "type: %X, guard: %X, cmd: %02X, data: %02X", type, guard, rcmd, rdat); + Console_SetCursor(0, -1); + sprintf_s(buf, MAXTEXTLEN, "***** type: %X, guard: %X, cmd: %02X, data: %02X", type, guard, rcmd, rdat); Console_Write(buf); Console_ScrollBottomRegion(scrollTop, scrollBot); } -// switch (rcmd) { -// case 0x20: // Power status -// SetData(&avrStatus.config.DT8, Dec2Hex(rdat, 1)); -// sprintf_s(buf, MAXTEXTLEN, "Zone Power: %s\n", ZonePower(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0x23: // Mute -// SetData(&avrStatus.config.DT12, Dec2Hex(rdat, 1)); -// sprintf_s(buf, MAXTEXTLEN, "Mute: %s\n", OnOffText(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0x25: // Zone 2 Mute -// SetData(&avrStatus.config.DT14, Dec2Hex(rdat, 1)); -// sprintf_s(buf, MAXTEXTLEN, "Zone 2 Mute: %s\n", OnOffText(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0x26: // Master Volume -// RxMasterVolStatus(rcmd, rdat, szBuffer, len); -// SetData(&avrStatus.config.DT15, Dec2Hex(rdat, 2)); -// sprintf_s(buf, MAXTEXTLEN, "Vol: %s\n", VolumeDB(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0x28: // Program -// SetData(&avrStatus.config.DT19, Dec2Hex(rdat, 2)); -// sprintf_s(buf, MAXTEXTLEN, "Prog: %s\n", ProgramName(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0x82: // Night Mode -// SetData(&avrStatus.config.DT27, Dec2Hex(rdat, 1)); -// sprintf_s(buf, MAXTEXTLEN, "Night Mode: %s\n", OnOffText(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0x36: // DC1 Trigger -// SetData(&avrStatus.config.DT39, Dec2Hex(rdat, 1)); -// sprintf_s(buf, MAXTEXTLEN, "Trigger Out 1: %s\n", OnOffText(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0x3C: // DC2 Trigger -// SetData(&avrStatus.config.DT45, Dec2Hex(rdat, 1)); -// sprintf_s(buf, MAXTEXTLEN, "Trigger Out 2: %s\n", OnOffText(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// case 0xA1: // Zone 3 Mute -// //SetData(&avrStatus.config.DT14, Dec2Hex(rdat, 1)); -// sprintf_s(buf, MAXTEXTLEN, "Zone 3 Mute: %s\n", OnOffText(rdat)); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// ShowAllStatusInfo(); -// break; -// default: // Everything not yet handled -// sprintf_s(buf, MAXTEXTLEN, "type: %X, guard: %X, cmd: %02X, data: %02X", type, guard, rcmd, rdat); -// Console_Write(buf); -// Console_ScrollBottomRegion(scrollTop, scrollBot); -// break; -// } } // AnalyzeResponse @@ -1501,6 +1935,8 @@ void Console_Init() { fprintf(stderr, "Error: Unable to get console buffer info. Code: %lu\n", GetLastError()); exit(1); } + scrollBot = consoleHeight - 1; + scrollTop = consoleHeight - consoleScrollHeight - 1; // Desired size (width x height) COORD newSize; @@ -1596,7 +2032,7 @@ void Console_WriteAt(short x, short y, const char *text) { void Console_SetCursor(short x, short y) { GetConsoleScreenBufferInfo(hStdout, &csbi); csbi.dwCursorPosition.X = (short)((x < 0) ? csbi.srWindow.Right + x : x); - csbi.dwCursorPosition.Y = (short)((y < 0) ? csbi.srWindow.Bottom + y : y); + csbi.dwCursorPosition.Y = (short)((y < 0) ? csbi.srWindow.Bottom + 1 + y : y); SetConsoleCursorPosition(hStdout, csbi.dwCursorPosition); } diff --git a/DataSheets/Yamaha RX-V2400_RS232C_CommandsForSW.pdf.xlsx b/DataSheets/Yamaha RX-V2400_RS232C_CommandsForSW.pdf.xlsx index 18a7e2908cff37e1d4dc268b1ab8daeddcb3b4cc..de4b6443cf32a4a46a2ff8b28cd6353c4f0dea25 100644 GIT binary patch delta 13128 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 VDo8`ayf;FA`$WG<#H7EM{vX{L5Oe?l delta 8703 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 delta 6832 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