diff --git a/AVR Working w-o Decoder/AVR.cpp b/AVR Working w-o Decoder/AVR.cpp index 8c0f487..f34be04 100644 --- a/AVR Working w-o Decoder/AVR.cpp +++ b/AVR Working w-o Decoder/AVR.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "SerialPort\SerialPort.h" enum @@ -21,6 +22,8 @@ CSerialPort avr; int avrOnPort = COM_NO_PORT; // Serial Port 1, 2, ... taking note that some USB adapters can be up toward channel 11, 12, ... unsigned avrBaud = 9600; +DWORD const retryInterval = 1000; // ms + // Each DT is the hex-character from the stream // // @@ -234,36 +237,92 @@ char progname[MAXTEXTLEN]; int AttachToSerialPort(); int DetachSerialPort(); -void ProcessSerialReceive(void); + +// SerialSend +// +// Try to send the message. +// +// @param[in] p is a pointer to the message to send +// @param[in] len is the count of bytes in the message +// @returns true if the serial interface accepted it. +// +bool SerialSend(const uint8_t *p, DWORD len); + +#define SERIALQUEUESIZE 3 +typedef struct { + uint8_t *messageToSend; + DWORD len; +} SerialQueue_T; + +static SerialQueue_T serialQueue[SERIALQUEUESIZE]; +static int serialQueueCount = 0; + + +// ProcessSerialQueue +// +// If there are parameters passed, insert a message into the queue. +// Process the queue (with zero or more messages) to send +// +// @param[in] p is a pointer to the message to send +// @param[in] len is the count of bytes in the message +// @returns false if the queue (which is a fixed size) is full. +// +bool ProcessSerialQueue(const uint8_t *p = NULL, DWORD len = 0); + + +// ProcessSerialReceive +// +// See if anything came in, and if so, process it. +// +// @returns true if a message was processed. +// +bool ProcessSerialReceive(void); void EnumerateComPorts(); unsigned long Hex2Dec(uint8_t *p, int dig); bool UserWantsToExitCanSniff = false; +DWORD progStartTime; // For special cursor positioning bool consoleInit = false; HANDLE hStdout, hStdin; -CONSOLE_SCREEN_BUFFER_INFO csbiInfo; +CONSOLE_SCREEN_BUFFER_INFO csbi; WORD wOldColorAttrs; // Save the current console colors +short consoleWidth = 105; +short consoleHeight = 70; +short consoleScrollHeight = 14; +// 0 99 +// +---------------------------------------------------------------+ +// | Program banner information | 0 +// | on two lines | +// | Current status information starts on line 3 | +// | and down a ways... | +// | | +// | | +// | | +// + Down near the bottom is the scroll region + 69 +// | | +// | | 79 +// +---------------------------------------------------------------+ +const int scrollTop = 59; +const int scrollBot = 69; + + void Console_Init(); void Console_Cls(); void Console_SetCursor(short x, short y); -void Console_Write(char *text); -void Console_WriteAt(short x, short y, char *text); +void Console_Write(const char *text); +void Console_WriteAt(short x, short y, const char *text); void Console_ScrollBottomRegion(short topLine, short bottomLine); bool Console_AdvanceToNextLineIfNotRoomFor(short x, int scroll = -1); -uint8_t LastSentMessage[MAXTEXTLEN]; -uint16_t LastSentMessageLen; -uint64_t LastSentMessageTime; // when the last message was sent - typedef struct { const char Char; const char *pDescription; const char *pCommand; - int cmdLen; + DWORD cmdLen; } UserCmd_T; const UserCmd_T UserCommands[] = { @@ -324,21 +383,26 @@ void ProcessWindowsMessage(void) { // EmitBuffer // // Emits the provided buffer to the console, translating non-printable -// characters into hex codes enclosed in angle brackets. +// characters into hex codes enclosed in square brackets. // // Consider line-wrapping to align the next line // -void EmitBuffer(const char *prefix, const uint8_t *buf, bool appendReturn = false) { +void EmitBuffer(const char *prefix, const uint8_t *buf, size_t len = 0, bool appendReturn = false) { int i = 0; const char *p = (const char *)buf; - printf("[%3d]%s", (int)strlen(p), prefix); - while (*p) { + DWORD now = timeGetTime(); + char txtBuf[MAXTEXTLEN] = ""; + + if (len == 0) len = strlen((const char *)buf); + sprintf_s(txtBuf, MAXTEXTLEN, "%7.3f: [%3d]%s", (float)(now - progStartTime)/1000.0f, (int)strlen(p), prefix); + Console_Write(txtBuf); + while (*p && ((unsigned)(p - (const char *)buf) < len)) { if (isprint(*p)) { putchar(*p); i++; } else if (*p == '\r') { putchar('\n'); - Console_ScrollBottomRegion(-14, -1); + Console_ScrollBottomRegion(scrollTop, scrollBot); } else if (*p == '\n') { // skip it } else { @@ -346,7 +410,8 @@ void EmitBuffer(const char *prefix, const uint8_t *buf, bool appendReturn = fals } if ((i & 3) == 0) { if (Console_AdvanceToNextLineIfNotRoomFor(12, 1)) { - printf(" "); + //Console_ScrollBottomRegion(scrollTop, scrollBot); + printf(" "); // sized to get past the timestamp, length, and prefix i = 0; } else { printf(" "); @@ -355,34 +420,64 @@ void EmitBuffer(const char *prefix, const uint8_t *buf, bool appendReturn = fals p++; } if (appendReturn) { - putch('\r'); + Console_ScrollBottomRegion(scrollTop, scrollBot); // putch('\r'); } else { - putch('\n'); - Console_ScrollBottomRegion(-14, -1); + //putch('\n'); + //Console_ScrollBottomRegion(scrollTop, scrollBot); } } void EchoSerialRecv(const uint8_t *pMsg) { - Console_SetCursor(0, -3); + Console_SetCursor(0, -1); EmitBuffer("< ", pMsg); - Console_ScrollBottomRegion(-14, -1); + Console_ScrollBottomRegion(scrollTop, scrollBot); } -void SerialSend(const uint8_t *p, int len) { - Console_SetCursor(0, -3); - EmitBuffer("> ", p); - Console_ScrollBottomRegion(-14, -1); - if (avr.Write((const LPVOID)p, len) != len) { - Console_SetCursor(0, -3); - Console_Write("***** Failed to send. Port not open?"); - Console_ScrollBottomRegion(-14, -1); +bool SerialSend(const uint8_t *p, DWORD len) { + bool retVal = false; + Console_SetCursor(0, -1); + EmitBuffer("> ", p, len); + Console_ScrollBottomRegion(scrollTop, scrollBot); + if (avr.Write((const LPVOID)p, len) == len) { + retVal = true; } else { - // If we send something, we expect a response within ?200ms? and if not we should try again, up to 5 times. - memcpy(LastSentMessage, p, len); - LastSentMessageTime = GetTickCount64(); - LastSentMessageLen = len; + Console_SetCursor(0, -1); + Console_Write("***** Failed to send. Port not open?"); + Console_ScrollBottomRegion(scrollTop, scrollBot); } + return retVal; +} + +bool ProcessSerialQueue(const uint8_t *p, DWORD len) { + bool retVal = false; // assume fail + static bool freshData = false; + //DWORD now = timeGetTime(); + //static DWORD lastSendTime = timeGetTime(); + + if (p && len) { + if (serialQueueCount < SERIALQUEUESIZE) { + serialQueue[serialQueueCount].messageToSend = (uint8_t *)malloc(len); + if (serialQueue[serialQueueCount].messageToSend) { + memcpy(serialQueue[serialQueueCount].messageToSend, p, len); + serialQueue[serialQueueCount].len = len; + serialQueueCount++; + retVal = true; + freshData = true; + } + } + } + if (serialQueueCount) { + if (SerialSend((const uint8_t *)serialQueue[0].messageToSend, serialQueue[0].len)) { + --serialQueueCount; + free(serialQueue[0].messageToSend); + for (int i = 0; i < serialQueueCount; i++) { + serialQueue[i] = serialQueue[i + 1]; + } + retVal = true; + } + } + return retVal; } @@ -412,13 +507,13 @@ void EmitRuntimeHelp() { Console_Write(buf); } if (avr.IsOpen()) { - Console_SetCursor(0, -3); + 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"); - Console_ScrollBottomRegion(-14, -1); + Console_ScrollBottomRegion(scrollTop, scrollBot); } } @@ -450,8 +545,8 @@ static void PCMessage(const char *msg, int len, uint8_t **src, const char * (fnc msg, p ); + Console_AdvanceToNextLineIfNotRoomFor(26); Console_Write(outBuf); - Console_AdvanceToNextLineIfNotRoomFor(28); } @@ -491,6 +586,75 @@ const char * InputText(uint32_t val) { } } +const char *ProgramName(uint8_t val) { + val &= 0x7F; // Not accommodating the other variants yet + const char *nameList[] = { + "Hall A(HALL1)", + "Hall B", + "Hall C", + "unk", + "Hall C", + "Hall E", + "Live Concert", + "unk", + "Tokyo", + "Freiburg", + "Royaumont", + "unk", + "Village Gate", + "Village Vanguard", + "The Bottom Line", + "unk", + "The Roxy Theater", + "Warehouse Loft", + "Arena", + "unk", + "Disco", + "Party", + "Game", + "6 / 8CH Stereo", + "Pop / Rock", + "DJ", + "unk", + "unk", + "Opera", + "Pavillion", + "unk", + "unk", + "Mono Movie", + "Variety Sports", + "unk", + "unk", + "Spectacre", + "Sci - Fi", + "unk", + "unk", + "Adventure", + "General", + "unk", + "unk", + "Normal", + "Enhanced", + "unk", + "unk", + "PLII Movie", + "PLII Music", + "Neo: 6 Movie", + "Neo: 6 Music", + "STEREO A 2CH Stereo", + "STEREO B 2CH Direct Stereo" + "THX A Cinema", + "THX B Music", + }; + if (val < sizeof(nameList)) { + return nameList[val]; + } else { + return "huh?"; + } +} + + + // VolumeDB // // Convert the communication units of volume into db @@ -521,7 +685,7 @@ const char *VolumeDB(uint32_t val) { void ShowAll(void) { if (avrStatus.headerValid) { - Console_SetCursor(0, 3); + Console_SetCursor(0, 2); char buf[MAXTEXTLEN]; sprintf_s(buf, MAXTEXTLEN, "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], @@ -637,7 +801,7 @@ void ProcessKeyboard(void) { static uint32_t spin = 0; bool cmdFound = false; - Console_SetCursor(0, -3); + Console_SetCursor(0, -1); if (spin++ % 16 == 0) EmitSpinner(); if (CS_KeyHit()) { @@ -654,28 +818,28 @@ void ProcessKeyboard(void) { break; case 'S': avr.Set_RTS_State(TRUE); - Console_SetCursor(0, -3); + Console_SetCursor(0, -1); printf("RTS set ON\n"); - Console_ScrollBottomRegion(-14, -1); + Console_ScrollBottomRegion(scrollTop, scrollBot); break; case 's': avr.Set_RTS_State(FALSE); - Console_SetCursor(0, -3); + Console_SetCursor(0, -1); printf("RTS set OFF\n"); - Console_ScrollBottomRegion(-14, -1); + Console_ScrollBottomRegion(scrollTop, scrollBot); break; default: for (int i = 0; i < sizeof(UserCommands) / sizeof(UserCmd_T); i++) { if (UserCommands[i].Char == c) { - SerialSend((const uint8_t *)UserCommands[i].pCommand, UserCommands[i].cmdLen); + ProcessSerialQueue((const uint8_t *)UserCommands[i].pCommand, UserCommands[i].cmdLen); cmdFound = true; break; } } if (!cmdFound) { - Console_SetCursor(0, -3); + Console_SetCursor(0, -1); printf("Unrecognized command '%c' (0x%02X)\n", isprint(c) ? c : '.', (unsigned char)c); - Console_ScrollBottomRegion(-14, -1); + Console_ScrollBottomRegion(scrollTop, scrollBot); } break; } @@ -699,7 +863,7 @@ void GetProgName(char *name) { } -void EmitHelp() { +void EmitCommandLineHelp() { printf("%s [options] by Smartware Computing\n", progname); printf(" options:\n"); printf(" -C=X[,yyyy] Set to Com port X to baud rate yyyy\n"); @@ -718,6 +882,7 @@ void EmitHelp() { /******************************************************/ int __cdecl main(int argc, char *argv[]) { + progStartTime = timeGetTime(); Console_Init(); GetProgName(argv[0]); @@ -732,12 +897,12 @@ int __cdecl main(int argc, char *argv[]) { avrBaud = param2; } else { printf("***** Unrecognized command '%s' *****\n", argv[i]); - EmitHelp(); + EmitCommandLineHelp(); exit(EXIT_IllegalOption); } } if (argc == 0 || avrOnPort == COM_NO_PORT) { - EmitHelp(); + EmitCommandLineHelp(); } Console_Cls(); @@ -750,7 +915,8 @@ int __cdecl main(int argc, char *argv[]) { printf("Attached to Serial Port on COM%i at %i baud\n", avrOnPort, avrBaud); do { ProcessKeyboard(); - ProcessSerialReceive(); + /* bool anyRcvdMsg = */ ProcessSerialReceive(); + ProcessSerialQueue(); ProcessWindowsMessage(); } while (!UserWantsToExitCanSniff); DetachSerialPort(); @@ -815,14 +981,23 @@ void ProcessResponse(uint8_t type, uint8_t guard, uint16_t cmd, uint16_t data) { char buf[MAXTEXTLEN]; switch (cmd) { case 0x26: - sprintf_s(buf, MAXTEXTLEN, "Vol: %s", VolumeDB(data)); + sprintf_s(buf, MAXTEXTLEN, "Vol: %s\n", VolumeDB(data)); SetData(&avrStatus.config.DT15, Dec2Hex(data, 2)); Console_Write(buf); + Console_ScrollBottomRegion(scrollTop, scrollBot); + ShowAll(); + break; + case 0x28: + sprintf_s(buf, MAXTEXTLEN, "Prog: %s\n", ProgramName(data)); + SetData(&avrStatus.config.DT19, Dec2Hex(data, 2)); + Console_Write(buf); + Console_ScrollBottomRegion(scrollTop, scrollBot); ShowAll(); break; default: sprintf_s(buf, MAXTEXTLEN, "type: %X, guard: %X, cmd: %02X, data: %02X", type, guard, cmd, data); Console_Write(buf); + Console_ScrollBottomRegion(scrollTop, scrollBot); break; } } @@ -902,7 +1077,8 @@ void AnalyzeResponse(uint8_t *szBuffer, uint32_t num) { // All character sequences end with \x03 (this is the equiv of a ) // // -void ProcessSerialReceive() { +bool ProcessSerialReceive() { + bool anythingReceived = false; uint8_t rcv_buff[MAXTEXTLEN] = { 0 }; static uint8_t messageBuf[MAXTEXTLEN] = { 0 }; static uint8_t *p = messageBuf; // used to fill the rcv_buff as data comes in @@ -921,20 +1097,14 @@ void ProcessSerialReceive() { p = messageBuf; // Reset the buffer for the next message, which might be in rcv_buff *p = '\0'; + anythingReceived = true; } } if (messageBuf[0]) { - //EmitBuffer("~", messageBuf, true); // Show them the partial receipt if anything is there - } - } else { - // If we're waiting for a response to something we sent, and it's been more than 200ms, resend it - if (LastSentMessageTries > 0) { - if ((GetTickCount64() - LastSentMessageTime) > 200) { - LastSentMessageLen && (GetTickCount64() - LastSentMessageTime) > 200); - SerialSend(LastSentMessage, LastSentMessageLen); - } + //EmitBuffer("~", messageBuf, 0, true); // Show them the partial receipt if anything is there } } + return anythingReceived; } @@ -997,8 +1167,47 @@ int AttachToSerialPort() { void Console_Init() { hStdin = GetStdHandle(STD_INPUT_HANDLE); hStdout = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(hStdout, &csbiInfo); - wOldColorAttrs = csbiInfo.wAttributes; + if (!GetConsoleScreenBufferInfo(hStdout, &csbi)) { + fprintf(stderr, "Error: Unable to get console buffer info. Code: %lu\n", GetLastError()); + exit(1); + } + + // Desired size (width x height) + COORD newSize; + newSize.X = consoleWidth; // columns + newSize.Y = consoleHeight; // rows + + // Step 1: Shrink window if needed before shrinking buffer + SMALL_RECT tempWindow = csbi.srWindow; + tempWindow.Right = tempWindow.Left + (newSize.X - 1); + tempWindow.Bottom = tempWindow.Top + (newSize.Y - 1); + + if (!SetConsoleWindowInfo(hStdout, TRUE, &tempWindow)) { + fprintf(stderr, "Error: Unable to temporarily resize window. Code: %lu\n", GetLastError()); + exit(1); + } + + // Step 2: Set new buffer size + if (!SetConsoleScreenBufferSize(hStdout, newSize)) { + fprintf(stderr, "Error: Unable to set console buffer size. Code: %lu\n", GetLastError()); + exit(1); + } + + // Step 3: Set final window size to match buffer + SMALL_RECT newWindow; + newWindow.Left = 0; + newWindow.Top = 0; + newWindow.Right = newSize.X - 1; + newWindow.Bottom = newSize.Y - 1; + + if (!SetConsoleWindowInfo(hStdout, TRUE, &newWindow)) { + fprintf(stderr, "Error: Unable to set console window size. Code: %lu\n", GetLastError()); + exit(1); + } + + // end + + wOldColorAttrs = csbi.wAttributes; //SetConsoleTextAttribute(hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY); } @@ -1009,7 +1218,6 @@ void Console_Close() { void Console_Cls() { COORD coordScreen = { 0, 0 }; // home for the cursor DWORD cCharsWritten; - CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD dwConSize; // Get the number of character cells in the current buffer. @@ -1041,8 +1249,12 @@ void Console_Cls() { SetConsoleCursorPosition(hStdout, coordScreen); } -void Console_Write(char *text) { +void Console_Write(const char *text) { DWORD written; + GetConsoleScreenBufferInfo(hStdout, &csbi); + if (csbi.dwCursorPosition.Y >= (csbi.srWindow.Bottom - consoleScrollHeight)) { + //Console_ScrollBottomRegion(scrollTop, scrollBot); + } WriteConsole(hStdout, text, (DWORD)strlen(text), &written, nullptr); } @@ -1053,33 +1265,34 @@ void Console_WriteAt(short x, short y, char *text) { } void Console_SetCursor(short x, short y) { - GetConsoleScreenBufferInfo(hStdout, &csbiInfo); - csbiInfo.dwCursorPosition.X = (short)((x < 0) ? csbiInfo.srWindow.Right + x : x); - csbiInfo.dwCursorPosition.Y = (short)((y < 0) ? csbiInfo.srWindow.Bottom + y : y); - SetConsoleCursorPosition(hStdout, csbiInfo.dwCursorPosition); + 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); + SetConsoleCursorPosition(hStdout, csbi.dwCursorPosition); } void Console_ScrollBottomRegion(short topLine, short bottomLine) { - GetConsoleScreenBufferInfo(hStdout, &csbiInfo); - if (topLine < 0) topLine = csbiInfo.srWindow.Bottom + topLine; - if (bottomLine < 0) bottomLine = csbiInfo.srWindow.Bottom + bottomLine; - SMALL_RECT scrollRect = { 0, topLine, csbiInfo.dwMaximumWindowSize.X, bottomLine }; + GetConsoleScreenBufferInfo(hStdout, &csbi); + if (topLine < 0) topLine = csbi.srWindow.Bottom + topLine; + if (bottomLine < 0) bottomLine = csbi.srWindow.Bottom + bottomLine; + SMALL_RECT scrollRect = { 0, topLine, csbi.dwMaximumWindowSize.X-1, bottomLine }; COORD dest = { 0, topLine - 1 }; CHAR_INFO fill = { ' ', { FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE } }; - ScrollConsoleScreenBuffer(hStdout, &scrollRect, nullptr, dest, &fill); + ScrollConsoleScreenBuffer(hStdout, &scrollRect, &scrollRect, dest, &fill); + putch('\r'); // Cursor to left margin } bool Console_AdvanceToNextLineIfNotRoomFor(short x, int scroll) { bool advanced = false; - GetConsoleScreenBufferInfo(hStdout, &csbiInfo); - if (csbiInfo.dwCursorPosition.X + x > csbiInfo.dwMaximumWindowSize.X) { + GetConsoleScreenBufferInfo(hStdout, &csbi); + if (csbi.dwCursorPosition.X + x > csbi.dwMaximumWindowSize.X) { advanced = true; if (scroll == 1) { - Console_ScrollBottomRegion(-14, -1); + Console_ScrollBottomRegion(scrollTop, scrollBot); } else { - csbiInfo.dwCursorPosition.Y++; + csbi.dwCursorPosition.Y++; } - Console_SetCursor(0, csbiInfo.dwCursorPosition.Y); + Console_SetCursor(0, csbi.dwCursorPosition.Y); } return advanced; } \ No newline at end of file diff --git a/DataSheets/Yamaha RX-V2400_RS232C_CommandsForSW.pdf.xlsx b/DataSheets/Yamaha RX-V2400_RS232C_CommandsForSW.pdf.xlsx index adc66ec..18a7e29 100644 Binary files a/DataSheets/Yamaha RX-V2400_RS232C_CommandsForSW.pdf.xlsx and b/DataSheets/Yamaha RX-V2400_RS232C_CommandsForSW.pdf.xlsx differ