Reworking the AVR specific stuff into an AVRInterface class.
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -127,11 +127,13 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AVR.cpp" />
|
||||
<ClCompile Include="AVRCommandDecoder.cpp" />
|
||||
<ClCompile Include="AVRInterface.cpp" />
|
||||
<ClCompile Include="ConsoleHandler.cpp" />
|
||||
<ClCompile Include="SerialPort\SerialPort.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AVRCommandDecoder.h" />
|
||||
<ClInclude Include="AVRInterface.h" />
|
||||
<ClInclude Include="ConsoleHandler.h" />
|
||||
<ClInclude Include="SerialPort\SerialPort.h" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
<ClCompile Include="ConsoleHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AVRInterface.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SerialPort\SerialPort.h">
|
||||
@@ -38,5 +41,8 @@
|
||||
<ClInclude Include="ConsoleHandler.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AVRInterface.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
159
AVR Working Controller/AVRInterface.cpp
Normal file
159
AVR Working Controller/AVRInterface.cpp
Normal file
@@ -0,0 +1,159 @@
|
||||
|
||||
#include <memory.h>
|
||||
#include <malloc.h>
|
||||
#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 <msg> ETX
|
||||
break;
|
||||
case 0x11: // DC1 <msg> ETX
|
||||
break;
|
||||
case 0x12: // DC2 <msg> ETX
|
||||
if (CheckTheChecksum(buffer, len)) {
|
||||
readyResponsReceived = true;
|
||||
}
|
||||
break;
|
||||
case 0x14: // DC4 <extended response> 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;
|
||||
}
|
||||
111
AVR Working Controller/AVRInterface.h
Normal file
111
AVR Working Controller/AVRInterface.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
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();
|
||||
};
|
||||
@@ -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)
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user