diff --git a/AVR Working Controller/AVR.cpp b/AVR Working Controller/AVR.cpp index 5944992..c09ec08 100644 --- a/AVR Working Controller/AVR.cpp +++ b/AVR Working Controller/AVR.cpp @@ -24,7 +24,7 @@ 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 +const uint32_t retryInterval = 1000; // ms // Each DT is the hex-character from the stream // @@ -219,13 +219,13 @@ int DetachSerialPort(); // @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); +bool SerialSend(const uint8_t *p, uint16_t len); // Just big enough to hold an OSD message which is a 1 message command, 4 messages with text #define SERIALQUEUESIZE 5 typedef struct { uint8_t *messageToSend; - DWORD len; + uint16_t len; } SerialQueue_T; static SerialQueue_T serialQueue[SERIALQUEUESIZE]; @@ -241,7 +241,7 @@ static int serialQueueCount = 0; // @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); +bool ProcessSerialQueue(const uint8_t *p = NULL, uint16_t len = 0); // ProcessSerialReceive @@ -257,11 +257,11 @@ unsigned long Hex2Dec(uint8_t *p, int dig); void ShowAllStatusInfo(); bool UserWantsToExitCanSniff = false; -DWORD progStartTime; +DWORD progStartTime_ms; typedef struct { const char *pMsg; - DWORD MsgLen; + uint16_t MsgLen; } Message_T; typedef struct { @@ -531,11 +531,11 @@ void ProcessWindowsMessage(void) { 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; - DWORD now = timeGetTime(); + uint32_t now_ms = 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); + sprintf_s(txtBuf, MAXTEXTLEN, "%7.3f: [%3d]%s", (float)(now_ms - progStartTime_ms)/1000.0f, (int)strlen(p), prefix); Console_Write(txtBuf); while (*p && ((unsigned)(p - (const char *)buf) < len)) { if (isprint(*p)) { @@ -575,7 +575,7 @@ void EchoSerialRecv(const uint8_t *pMsg) { Console_ScrollBottomRegion(); } -bool SerialSend(const uint8_t *p, DWORD len) { +bool SerialSend(const uint8_t *p, uint16_t len) { bool retVal = false; Console_SetCursor(0, -1); EmitBuffer("> ", p, len); @@ -590,7 +590,7 @@ bool SerialSend(const uint8_t *p, DWORD len) { return retVal; } -bool ProcessSerialQueue(const uint8_t *p, DWORD len) { +bool ProcessSerialQueue(const uint8_t *p, uint16_t len) { bool retVal = false; // assume fail static bool freshData = false; @@ -920,7 +920,7 @@ int __cdecl main(int argc, char *argv[]) { short consoleHeight = 80; short consoleScrollHeight = 30; - progStartTime = timeGetTime(); + progStartTime_ms = timeGetTime(); MessageHandlerSanityCheck(); // If the table is bad, we exit here UserCommandsSanityCheck(); // If the table is bad, we exit here @@ -1174,7 +1174,7 @@ void EnumerateComPorts() { bool portFound = false; HANDLE port = CreateFile(cBuf, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); if (port == INVALID_HANDLE_VALUE) { - DWORD dwError = GetLastError(); + uint32_t dwError = GetLastError(); if ((dwError == ERROR_ACCESS_DENIED) || (dwError == ERROR_GEN_FAILURE) || (dwError == ERROR_SHARING_VIOLATION) || (dwError == ERROR_SEM_TIMEOUT)) { foundPorts++; @@ -1208,7 +1208,7 @@ int AttachToSerialPort() { char buf[20]; // generously sized. sprintf_s(buf, sizeof(buf), "\\\\.\\COM%d", avrOnPort); - DWORD Access = GENERIC_WRITE | GENERIC_READ; + uint32_t Access = GENERIC_WRITE | GENERIC_READ; if (avr.Open(buf, avrBaud, 8, NOPARITY, ONESTOPBIT, Access)) { success = true; avr.Set_RTS_State(false); diff --git a/AVR Working Controller/AVR.vcxproj b/AVR Working Controller/AVR.vcxproj index d08249e..bf2740a 100644 --- a/AVR Working Controller/AVR.vcxproj +++ b/AVR Working Controller/AVR.vcxproj @@ -127,11 +127,13 @@ + + diff --git a/AVR Working Controller/AVR.vcxproj.filters b/AVR Working Controller/AVR.vcxproj.filters index b43dc3a..8c750f6 100644 --- a/AVR Working Controller/AVR.vcxproj.filters +++ b/AVR Working Controller/AVR.vcxproj.filters @@ -27,6 +27,9 @@ Source Files + + Source Files + @@ -38,5 +41,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/AVR Working Controller/AVRInterface.cpp b/AVR Working Controller/AVRInterface.cpp new file mode 100644 index 0000000..13afe5e --- /dev/null +++ b/AVR Working Controller/AVRInterface.cpp @@ -0,0 +1,159 @@ + +#include +#include +#include "AVRInterface.h" + +//AVRInterface::AVRInterface(int (*SendMessage)(const void *buffer, unsigned int bufferSize)) { +//} +AVRInterface::~AVRInterface() { + FreeMemory(); +} + +void AVRInterface::Tick(uint32_t now_ms) { + uint32_t elapsed_ms = now_ms - sentAtTime_ms; + + switch (state) { + default: + case AVRState_T::stPoweringUp: + readyResponsReceived = false; + ProcessSerialQueue((uint8_t *)"\x11" "000" "\x03", 5); // Send the Ready Command + sentAtTime_ms = now_ms; + readyTries++; + state = stAwaitingReadyResponse; + break; + case stAwaitingReadyResponse: + if (readyResponsReceived) { + state = stReady; + } else if (elapsed_ms > RETRY_INTERVAL_ms) { + if (readyTries > MAXTRIES) { + // fail + + } else { + state = stPoweringUp; + } + } + break; + case AVRState_T::stInitializing: + break; + case AVRState_T::stRetryInitializing: + break; + case AVRState_T::stAwaitingResponse: + break; + case AVRState_T::stReady: + ProcessSerialQueue(); + break; + } +} + +bool AVRInterface::HandleMessage(const uint8_t *buffer, uint16_t len) { + switch (state) { + case stAwaitingReadyResponse: + switch (buffer[0]) { + case 0x02: // STX ETX + break; + case 0x11: // DC1 ETX + break; + case 0x12: // DC2 ETX + if (CheckTheChecksum(buffer, len)) { + readyResponsReceived = true; + } + break; + case 0x14: // DC4 ETX + break; + default: + break; + } + readyResponsReceived = true; + break; + case stReady: + break; + } + return true; +} + +bool AVRInterface::Initialize() { + return true; +} + +bool AVRInterface::IsOnline() { + return true; +} +bool AVRInterface::Power(AVRPower_T cmd) { + return true; +} + +bool AVRInterface::MasterVolumeButton(AVRVolumeButton_T cmd) { + return true; +} +bool AVRInterface::Mute(AVRMute_T cmd) { + return true; +} + +bool AVRInterface::ProcessSerialQueue(const uint8_t *p, uint16_t len) { + bool retVal = false; // assume fail + static bool freshData = false; + + 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 ((*SendMethod)((const uint8_t *)serialQueue[0].messageToSend, serialQueue[0].len)) { + --serialQueueCount; + free(serialQueue[0].messageToSend); + serialQueue[0].messageToSend = NULL; + for (int i = 0; i < serialQueueCount; i++) { + serialQueue[i] = serialQueue[i + 1]; + } + retVal = true; + } + } + return retVal; +} + +void AVRInterface::FreeMemory() { + for (int i = 0; i < serialQueueCount; i++) { + if (serialQueue[0].messageToSend) + free(serialQueue[0].messageToSend); + } +} + + +bool AVRInterface::CheckTheChecksum(const uint8_t *szBuffer, uint32_t num) { + uint8_t sum = 0; + for (uint16_t i = 1; i < num - 3; i++) { + sum += szBuffer[i]; + } + uint8_t cksum = (uint8_t)Hex2Dec(&szBuffer[num - 3], 2); + //printf("CheckSum: %02X v. %c%c\n", sum, szBuffer[num - 3], szBuffer[num - 2]); + return (sum == cksum); +} + +// Hex2Dec +// +// All responses are pretty much Hex-ASCII, so +// we sometimes want to convert it to decimal +// This takes a buffer and converts the specified +// number of characters. +// +unsigned long AVRInterface::Hex2Dec(const uint8_t *p, int dig) { + unsigned long x = 0; + while (dig--) { + if (*p >= '0' && *p <= '9') + x = x * 16 + *p - '0'; + else if (*p >= 'a' && *p <= 'f') + x = x * 16 + 0x0a + *p - 'a'; + else if (*p >= 'A' && *p <= 'F') + x = x * 16 + 0x0a + *p - 'A'; + p++; + } + return x; +} diff --git a/AVR Working Controller/AVRInterface.h b/AVR Working Controller/AVRInterface.h new file mode 100644 index 0000000..f2d2ee0 --- /dev/null +++ b/AVR Working Controller/AVRInterface.h @@ -0,0 +1,111 @@ +#pragma once +#include + +class AVRInterface { +public: + /// @brief + /// @param SendMessage is the function this AVRInterface calls to send a message to the device + /// + AVRInterface(int (*SendMessage)(const uint8_t *buffer, uint16_t len)) + : SendMethod(SendMessage) {}; + + ~AVRInterface(); + + /// @brief When the system receives something from the device, give it to this function to handle it + /// @param buffer + /// @param len + /// @return true if it was handled + /// + bool HandleMessage(const uint8_t *buffer, uint16_t len); + + /// @brief Call this periodically so timed activities can be handled. + /// + /// Every 1 or even 50 to 100 msec is ok. + /// + /// @param millisec + /// + void Tick(uint32_t millisec); + + /// @brief Initialize the AVR interface and issue the ready command. + /// + /// This is temporarily blocking since nothing else should run until ready + /// + /// @return true if initialized + /// + bool Initialize(); + + /// @brief determine if the device is ready + /// + /// @return true if ready + /// + bool IsOnline(); + + /// @brief Power on and off commands + /// + typedef enum { + avrPowerOff, + avrPowerOn, + } AVRPower_T; + + /// @brief Send the power command + /// @param cmd + /// @return true if sent + /// + bool Power(AVRPower_T cmd); + + // MasterVolumeButton + // Issues volume up and down commands to the AVR. + // + typedef enum { + avrVolumeUp, + avrVolumeDown, + } AVRVolumeButton_T; + bool MasterVolumeButton(AVRVolumeButton_T cmd); + + // Mute, UnMute + typedef enum { + avrMute, + avrUnMute, + } AVRMute_T; + bool Mute(AVRMute_T cmd); + +private: + uint32_t sentAtTime_ms; + + typedef enum { + stPoweringUp, + stAwaitingReadyResponse, + stInitializing, + stRetryInitializing, + stReady, + stAwaitingResponse, + } AVRState_T; + AVRState_T state = stPoweringUp; + + AVRState_T GetState() { + return state; + } + + bool readyResponsReceived; + int readyTries; + #define RETRY_INTERVAL_ms 500 + #define MAXTRIES 5 + + #define SERIALQUEUESIZE 5 + typedef struct { + uint8_t *messageToSend; + uint16_t len; + } SerialQueue_T; + + SerialQueue_T serialQueue[SERIALQUEUESIZE]; + int serialQueueCount = 0; + + bool ProcessSerialQueue(const uint8_t *p = NULL, uint16_t len = NULL); + + int (*SendMethod)(const uint8_t *buffer, uint16_t bufferSize); + + bool CheckTheChecksum(const uint8_t *szBuffer, uint32_t num); + unsigned long Hex2Dec(const uint8_t *p, int dig); + + void FreeMemory(); +}; diff --git a/AVR Working Controller/SerialPort/SerialPort.cpp b/AVR Working Controller/SerialPort/SerialPort.cpp index ea2b455..c790ab4 100644 --- a/AVR Working Controller/SerialPort/SerialPort.cpp +++ b/AVR Working Controller/SerialPort/SerialPort.cpp @@ -36,7 +36,7 @@ CSerialPort::~CSerialPort() Close(); } -BOOL CSerialPort::Open(LPCTSTR PortName, DWORD BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits, DWORD DesiredAccess) +BOOL CSerialPort::Open(LPCTSTR PortName, uint32_t BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits, uint32_t DesiredAccess) { Close(); m_PortHandle = CreateFile(PortName, DesiredAccess, 0, NULL, OPEN_EXISTING, 0, 0); @@ -72,7 +72,7 @@ BOOL CSerialPort::Open(LPCTSTR PortName, DWORD BaudRate, BYTE ByteSize, BYTE Par SetCommState(m_PortHandle, &dcb); COMMTIMEOUTS touts; - touts.ReadIntervalTimeout = MAXDWORD; // This, plus the zero timeouts causes immediate return + touts.ReadIntervalTimeout = UINT32_MAX; // This, plus the zero timeouts causes immediate return touts.ReadTotalTimeoutMultiplier = 0; touts.ReadTotalTimeoutConstant = 0; touts.WriteTotalTimeoutConstant = 1; @@ -104,7 +104,7 @@ BOOL CSerialPort::IsOpen() return (m_PortHandle != INVALID_HANDLE_VALUE); } -DWORD CSerialPort::Read(LPVOID Buffer, DWORD BufferSize) +uint32_t CSerialPort::Read(LPVOID Buffer, uint32_t BufferSize) { DWORD Res(0); if (m_PortHandle != INVALID_HANDLE_VALUE) @@ -114,7 +114,7 @@ DWORD CSerialPort::Read(LPVOID Buffer, DWORD BufferSize) return Res; } -DWORD CSerialPort::Write(const LPVOID Buffer, DWORD BufferSize) +uint32_t CSerialPort::Write(const LPVOID Buffer, uint32_t BufferSize) { DWORD Res(0); if (m_PortHandle != INVALID_HANDLE_VALUE) diff --git a/AVR Working Controller/SerialPort/SerialPort.h b/AVR Working Controller/SerialPort/SerialPort.h index 4ede3b4..28b9fd9 100644 --- a/AVR Working Controller/SerialPort/SerialPort.h +++ b/AVR Working Controller/SerialPort/SerialPort.h @@ -32,12 +32,12 @@ public: BOOL Get_DSR_State(); BOOL Get_CTS_State(); BOOL Get_CD_State(); - virtual DWORD Write(const LPVOID Buffer, DWORD BufferSize); - virtual DWORD Read(LPVOID Buffer, DWORD BufferSize); + virtual uint32_t Write(const LPVOID Buffer, uint32_t BufferSize); + virtual uint32_t Read(LPVOID Buffer, uint32_t BufferSize); virtual BOOL IsOpen(); virtual void Close(); // Use PortName usually "COM1:" ... "COM4:" note that the name must end by ":" - virtual BOOL Open(LPCTSTR PortName, DWORD BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits, DWORD DesiredAccess = GENERIC_READ|GENERIC_WRITE); + virtual BOOL Open(LPCTSTR PortName, uint32_t BaudRate, BYTE ByteSize, BYTE Parity, BYTE StopBits, uint32_t DesiredAccess = GENERIC_READ|GENERIC_WRITE); CSerialPort(); virtual ~CSerialPort(); diff --git a/DataSheets/Yamaha RX-V2400_RS232C_Standard.pdf b/DataSheets/Yamaha RX-V2400_RS232C_Standard.pdf index 313d0c4..941acbc 100644 Binary files a/DataSheets/Yamaha RX-V2400_RS232C_Standard.pdf and b/DataSheets/Yamaha RX-V2400_RS232C_Standard.pdf differ