Speeding up COM writing

This commit is contained in:
PS 2020-10-05 13:17:33 -07:00
parent 83ed23280a
commit ecca6c691a
9 changed files with 186 additions and 67 deletions

View File

@ -35,6 +35,17 @@ struct anim_layer
blend_mode BlendMode; blend_mode BlendMode;
}; };
struct animation
{
anim_layer* Layers;
u32 LayersCount;
u32 LayersMax;
gs_list<animation_block> Blocks;
frame_range PlayableRange;
};
#define ANIMATION_SYSTEM_LAYERS_MAX 128 #define ANIMATION_SYSTEM_LAYERS_MAX 128
#define ANIMATION_SYSTEM_BLOCKS_MAX 128 #define ANIMATION_SYSTEM_BLOCKS_MAX 128
struct animation_system struct animation_system

View File

@ -0,0 +1,10 @@
//
// File: foldhaus_animation_serializer.cpp
// Author: Peter Slattery
// Creation Date: 2020-10-04
//
#ifndef FOLDHAUS_ANIMATION_SERIALIZER_CPP
#define FOLDHAUS_ANIMATION_SERIALIZER_CPP
#endif // FOLDHAUS_ANIMATION_SERIALIZER_CPP

View File

@ -284,7 +284,7 @@ ReadInt(assembly_tokenizer* T)
} }
internal gs_string internal gs_string
ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Arena) ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Arena, bool ShouldNullTerminate = false)
{ {
gs_string Result = {}; gs_string Result = {};
if (ReadFieldIdentifier(Field, T)) if (ReadFieldIdentifier(Field, T))
@ -293,8 +293,13 @@ ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Ar
if (ReadFieldEnd(T)) if (ReadFieldEnd(T))
{ {
// Success // Success
Result = PushString(Arena, ExistingString.Length); u64 Length = ExistingString.Length + (ShouldNullTerminate ? 1 : 0);
Result = PushString(Arena, Length);
PrintF(&Result, "%S", ExistingString); PrintF(&Result, "%S", ExistingString);
if (ShouldNullTerminate)
{
NullTerminate(&Result);
}
} }
} }
return Result; return Result;
@ -430,6 +435,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe
if (StringsEqual(OutputModeString.ConstString, ConstString("UART"))) if (StringsEqual(OutputModeString.ConstString, ConstString("UART")))
{ {
Assembly->OutputMode = NetworkProtocol_UART; Assembly->OutputMode = NetworkProtocol_UART;
Assembly->UARTComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena, true).ConstString;
} }
else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN"))) else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN")))
{ {
@ -459,7 +465,6 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe
if (ReadStructOpening(AssemblyField_OutputUART, &Tokenizer, PARSER_FIELD_OPTIONAL)) if (ReadStructOpening(AssemblyField_OutputUART, &Tokenizer, PARSER_FIELD_OPTIONAL))
{ {
StripAt->UARTAddr.Channel = (u8)ReadIntField(AssemblyField_UART_Channel, &Tokenizer); StripAt->UARTAddr.Channel = (u8)ReadIntField(AssemblyField_UART_Channel, &Tokenizer);
StripAt->UARTAddr.ComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena).ConstString;
if (!ReadStructClosing(&Tokenizer)) if (!ReadStructClosing(&Tokenizer))
{ {

View File

@ -61,6 +61,7 @@ AddressedDataBufferList_PushEmpty(addressed_data_buffer_list* List)
{ {
addressed_data_buffer* Result = PushStruct(List->Arena, addressed_data_buffer); addressed_data_buffer* Result = PushStruct(List->Arena, addressed_data_buffer);
*Result = {0}; *Result = {0};
Result->Next = 0;
Result->MemorySize = 0; Result->MemorySize = 0;
Result->Memory = 0; Result->Memory = 0;

View File

@ -58,7 +58,6 @@ struct strip_sacn_addr
struct strip_uart_addr struct strip_uart_addr
{ {
u8 Channel; u8 Channel;
gs_const_string ComPort;
}; };
struct v2_strip struct v2_strip
@ -103,6 +102,7 @@ struct assembly
v2_strip* Strips; v2_strip* Strips;
network_protocol OutputMode; network_protocol OutputMode;
gs_const_string UARTComPort;
}; };
struct assembly_array struct assembly_array

View File

@ -81,25 +81,16 @@ UART_FillFooter(uart_footer* Footer, u8* BufferStart)
} }
internal void internal void
UART_SetChannelBuffer_Create(addressed_data_buffer_list* Output, uart_channel ChannelSettings, v2_strip Strip, led_buffer LedBuffer) UART_SetChannelBuffer_Create(gs_memory_cursor* WriteCursor, uart_channel ChannelSettings, v2_strip Strip, led_buffer LedBuffer)
{ {
// NOTE(pjs): This is just here because the information is duplicated and I want to be sure // NOTE(pjs): This is just here because the information is duplicated and I want to be sure
// to catch the error where they are different // to catch the error where they are different
Assert(ChannelSettings.PixelsCount == Strip.LedCount); Assert(ChannelSettings.PixelsCount == Strip.LedCount);
u32 BufferSize = sizeof(uart_header) + sizeof(uart_channel); uart_header* Header = PushStructOnCursor(WriteCursor, uart_header);
BufferSize += ChannelSettings.ElementsCount * ChannelSettings.PixelsCount;
BufferSize += sizeof(uart_footer);
addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, BufferSize);
AddressedDataBuffer_SetCOMPort(Buffer, Strip.UARTAddr.ComPort);
gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data);
uart_header* Header = PushStructOnCursor(&WriteCursor, uart_header);
UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812); UART_FillHeader(Header, Strip.UARTAddr.Channel, UART_SET_CHANNEL_WS2812);
uart_channel* Channel = PushStructOnCursor(&WriteCursor, uart_channel); uart_channel* Channel = PushStructOnCursor(WriteCursor, uart_channel);
*Channel = ChannelSettings; *Channel = ChannelSettings;
for (u32 i = 0; i < Channel->PixelsCount; i++) for (u32 i = 0; i < Channel->PixelsCount; i++)
@ -107,7 +98,7 @@ UART_SetChannelBuffer_Create(addressed_data_buffer_list* Output, uart_channel Ch
u32 LedIndex = Strip.LedLUT[i]; u32 LedIndex = Strip.LedLUT[i];
pixel Color = LedBuffer.Colors[LedIndex]; pixel Color = LedBuffer.Colors[LedIndex];
u8* OutputPixel = PushArrayOnCursor(&WriteCursor, u8, 3); u8* OutputPixel = PushArrayOnCursor(WriteCursor, u8, 3);
OutputPixel[Channel->RedIndex] = Color.R; OutputPixel[Channel->RedIndex] = Color.R;
OutputPixel[Channel->GreenIndex] = Color.G; OutputPixel[Channel->GreenIndex] = Color.G;
@ -123,8 +114,18 @@ UART_SetChannelBuffer_Create(addressed_data_buffer_list* Output, uart_channel Ch
} }
} }
uart_footer* Footer = PushStructOnCursor(&WriteCursor, uart_footer); uart_footer* Footer = PushStructOnCursor(WriteCursor, uart_footer);
UART_FillFooter(Footer, Buffer->Memory); UART_FillFooter(Footer, (u8*)Header);
}
internal void
UART_DrawAll_Create(gs_memory_cursor* WriteCursor)
{
uart_header* Header = PushStructOnCursor(WriteCursor, uart_header);
UART_FillHeader(Header, 1, UART_DRAW_ALL);
uart_footer* Footer = PushStructOnCursor(WriteCursor, uart_footer);
UART_FillFooter(Footer, (u8*)Header);
} }
internal void internal void
@ -137,17 +138,31 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli
ChannelSettings.BlueIndex = 3; ChannelSettings.BlueIndex = 3;
ChannelSettings.WhiteIndex = 0; ChannelSettings.WhiteIndex = 0;
// NOTE(pjs): This is the minimum size of every UART message. SetChannelBuffer messages will
// be bigger than this, but their size is based on the number of pixels in each channel
u32 MessageBaseSize = sizeof(uart_header) + sizeof(uart_channel) + sizeof(uart_footer);
for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++) for (u32 AssemblyIdx = 0; AssemblyIdx < Assemblies.Count; AssemblyIdx++)
{ {
assembly Assembly = Assemblies.Values[AssemblyIdx]; assembly Assembly = Assemblies.Values[AssemblyIdx];
led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex); led_buffer* LedBuffer = LedSystemGetBuffer(LedSystem, Assembly.LedBufferIndex);
u32 TotalBufferSize = MessageBaseSize * Assembly.StripCount; // SetChannelBuffer messages
TotalBufferSize += MessageBaseSize; // DrawAll message
TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel
addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize);
AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort);
gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data);
for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++) for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++)
{ {
v2_strip StripAt = Assembly.Strips[StripIdx]; v2_strip StripAt = Assembly.Strips[StripIdx];
ChannelSettings.PixelsCount = StripAt.LedCount; ChannelSettings.PixelsCount = StripAt.LedCount;
UART_SetChannelBuffer_Create(Output, ChannelSettings, StripAt, *LedBuffer); UART_SetChannelBuffer_Create(&WriteCursor, ChannelSettings, StripAt, *LedBuffer);
} }
UART_DrawAll_Create(&WriteCursor);
} }
} }

View File

@ -44,5 +44,6 @@ PushLogEntry(event_log* Log, gs_string Message, log_entry_type Type)
#define FOLDHAUS_LOG_H #define FOLDHAUS_LOG_H
#endif // FOLDHAUS_LOG_H #endif // FOLDHAUS_LOG_H

View File

@ -364,6 +364,58 @@ Win32LoadSystemCursor(char* CursorIdentifier)
return Result; return Result;
} }
internal void
Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_list OutputData)
{
DEBUG_TRACK_FUNCTION;
u32 BuffersSent = 0;
for (addressed_data_buffer* BufferAt = OutputData.Root;
BufferAt != 0;
BufferAt = BufferAt->Next)
{
switch(BufferAt->AddressType)
{
case AddressType_NetworkIP:
{
Win32Socket_SendTo(BufferAt->SendSocket,
BufferAt->V4SendAddress,
BufferAt->SendPort,
(const char*)BufferAt->Memory,
BufferAt->MemorySize,
0);
}break;
case AddressType_ComPort:
{
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1);
if (SerialPort != INVALID_HANDLE_VALUE)
{
if (Win32SerialPort_Write(SerialPort, BufferAt->Data))
{
BuffersSent += 1;
}
}
}break;
InvalidDefaultCase;
}
}
gs_string OutputStr = AllocatorAllocString(Context.Allocator, 256);
PrintF(&OutputStr, "Buffers Sent: %d\n", BuffersSent);
NullTerminate(&OutputStr);
OutputDebugStringA(OutputStr.Str);
}
internal void
Win32_SendAddressedDataBuffers_Job(gs_thread_context Context, gs_data Arg)
{
addressed_data_buffer_list* OutputData = (addressed_data_buffer_list*)Arg.Memory;
Win32_SendAddressedDataBuffers(Context, *OutputData);
}
int WINAPI int WINAPI
WinMain ( WinMain (
HINSTANCE HInstance, HINSTANCE HInstance,
@ -504,6 +556,8 @@ WinMain (
Context.ReloadStaticData(Context, GlobalDebugServices); Context.ReloadStaticData(Context, GlobalDebugServices);
} }
AddressedDataBufferList_Clear(&OutputData);
{ // Mouse Position { // Mouse Position
POINT MousePos; POINT MousePos;
GetCursorPos (&MousePos); GetCursorPos (&MousePos);
@ -534,39 +588,10 @@ WinMain (
if (true) if (true)
{ {
// NOTE(pjs): Send the network data gs_data ProcArg = {};
ProcArg.Memory = (u8*)&OutputData;
// TODO(pjs): This should happen on another thread ProcArg.Size = sizeof(OutputData);
/* Win32PushWorkOnQueue(&WorkQueue, Win32_SendAddressedDataBuffers_Job, ProcArg, ConstString("Send UART Data"));
Saved this lien as an example of pushing onto a queue
Context->GeneralWorkQueue->PushWorkOnQueue(Context->GeneralWorkQueue, SACNSendDMXBufferListJob, Job, "SACN Send Data Job");
*/
for (addressed_data_buffer* BufferAt = OutputData.Root;
BufferAt != 0;
BufferAt = BufferAt->Next)
{
switch(BufferAt->AddressType)
{
case AddressType_NetworkIP:
{
Win32Socket_SendTo(BufferAt->SendSocket,
BufferAt->V4SendAddress,
BufferAt->SendPort,
(const char*)BufferAt->Memory,
BufferAt->MemorySize,
0);
}break;
case AddressType_ComPort:
{
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 9600, 8, 0, 1);
Win32SerialPort_Write(SerialPort, BufferAt->Data);
}break;
InvalidDefaultCase;
}
}
} }
Context.Mouse.LeftButtonState = GetMouseButtonStateAdvanced(Context.Mouse.LeftButtonState); Context.Mouse.LeftButtonState = GetMouseButtonStateAdvanced(Context.Mouse.LeftButtonState);
@ -610,6 +635,8 @@ WinMain (
SwapBuffers(DeviceContext); SwapBuffers(DeviceContext);
ReleaseDC(MainWindow.Handle, DeviceContext); ReleaseDC(MainWindow.Handle, DeviceContext);
//Win32DoQueueWorkUntilDone(&WorkQueue, Context.ThreadContext);
s64 FinishedWorkTime = GetWallClock(); s64 FinishedWorkTime = GetWallClock();
r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency); r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency);

View File

@ -13,6 +13,7 @@ global gs_string* Win32SerialPortNames;
DCB DCB
Win32SerialPort_GetState(HANDLE ComPortHandle) Win32SerialPort_GetState(HANDLE ComPortHandle)
{ {
DEBUG_TRACK_FUNCTION;
DCB ControlSettings = {0}; DCB ControlSettings = {0};
ZeroStruct(&ControlSettings); ZeroStruct(&ControlSettings);
ControlSettings.DCBlength = sizeof(ControlSettings); ControlSettings.DCBlength = sizeof(ControlSettings);
@ -26,14 +27,45 @@ Win32SerialPort_GetState(HANDLE ComPortHandle)
void void
Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits) Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits)
{ {
DEBUG_TRACK_FUNCTION;
DCB ControlSettings = Win32SerialPort_GetState(ComPortHandle); DCB ControlSettings = Win32SerialPort_GetState(ComPortHandle);
//PrintCommState(ControlSettings);
// TODO(pjs): Validate BaudRate - There's only certain rates that are valid right? // TODO(pjs): Validate BaudRate - There's only certain rates that are valid right?
ControlSettings.BaudRate = BaudRate; ControlSettings.BaudRate = BaudRate;
ControlSettings.ByteSize = ByteSize;
ControlSettings.Parity = Parity; if (Parity == NOPARITY)
{
ControlSettings.Parity = Parity;
ControlSettings.fParity = 0;
}
if (Parity == EVENPARITY || Parity == ODDPARITY)
{
ControlSettings.Parity = Parity;
ControlSettings.fParity = 1;
}
ControlSettings.StopBits = StopBits; ControlSettings.StopBits = StopBits;
ControlSettings.ByteSize = ByteSize;
ControlSettings.fBinary = true;
ControlSettings.fOutxCtsFlow = false;
ControlSettings.fOutxDsrFlow = false;
ControlSettings.fDtrControl = DTR_CONTROL_DISABLE;
ControlSettings.fDsrSensitivity = 0;
ControlSettings.fRtsControl = RTS_CONTROL_DISABLE;
ControlSettings.fOutX = false;
ControlSettings.fInX = false;
ControlSettings.fErrorChar = 0;
ControlSettings.fNull = false;
ControlSettings.fAbortOnError = false;
ControlSettings.wReserved = false;
ControlSettings.XonLim = 2;
ControlSettings.XoffLim = 4;
ControlSettings.XonChar = 0x13;
ControlSettings.XoffChar = 0x19;
ControlSettings.EvtChar = 0;
bool Success = SetCommState(ComPortHandle, &ControlSettings); bool Success = SetCommState(ComPortHandle, &ControlSettings);
} }
@ -41,6 +73,7 @@ Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Par
HANDLE HANDLE
Win32SerialPort_Open(char* PortName) Win32SerialPort_Open(char* PortName)
{ {
DEBUG_TRACK_FUNCTION;
HANDLE ComPortHandle = CreateFile(PortName, HANDLE ComPortHandle = CreateFile(PortName,
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
@ -52,11 +85,11 @@ Win32SerialPort_Open(char* PortName)
if (ComPortHandle != INVALID_HANDLE_VALUE) if (ComPortHandle != INVALID_HANDLE_VALUE)
{ {
COMMTIMEOUTS Timeouts = { 0 }; COMMTIMEOUTS Timeouts = { 0 };
Timeouts.ReadIntervalTimeout = 50; // in milliseconds Timeouts.ReadIntervalTimeout = 0; // in milliseconds
Timeouts.ReadTotalTimeoutConstant = 50; // in milliseconds Timeouts.ReadTotalTimeoutConstant = 0; // in milliseconds
Timeouts.ReadTotalTimeoutMultiplier = 10; // in milliseconds Timeouts.ReadTotalTimeoutMultiplier = 0; // in milliseconds
Timeouts.WriteTotalTimeoutConstant = 50; // in milliseconds Timeouts.WriteTotalTimeoutConstant = 0; // in milliseconds
Timeouts.WriteTotalTimeoutMultiplier = 10; // in milliseconds Timeouts.WriteTotalTimeoutMultiplier = 0; // in milliseconds
if (SetCommTimeouts(ComPortHandle, &Timeouts)) if (SetCommTimeouts(ComPortHandle, &Timeouts))
{ {
@ -65,14 +98,14 @@ Win32SerialPort_Open(char* PortName)
else else
{ {
s32 Error = GetLastError(); s32 Error = GetLastError();
InvalidCodePath; // TODO(pjs): Error logging
} }
} }
else else
{ {
// Error // Error
s32 Error = GetLastError(); s32 Error = GetLastError();
InvalidCodePath; // TODO(pjs): Error logging
} }
return ComPortHandle; return ComPortHandle;
@ -84,15 +117,18 @@ Win32SerialPort_Close(HANDLE PortHandle)
CloseHandle(PortHandle); CloseHandle(PortHandle);
} }
void bool
Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer) Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
{ {
DEBUG_TRACK_FUNCTION;
Assert(PortHandle != INVALID_HANDLE_VALUE); Assert(PortHandle != INVALID_HANDLE_VALUE);
bool Success = false;
DWORD BytesWritten = 0; DWORD BytesWritten = 0;
if (WriteFile(PortHandle, Buffer.Memory, Buffer.Size, &BytesWritten, NULL)) if (WriteFile(PortHandle, Buffer.Memory, Buffer.Size, &BytesWritten, NULL))
{ {
if (BytesWritten != Buffer.Size) Success = (BytesWritten == Buffer.Size);
if (!Success)
{ {
OutputDebugString("Error: Entire buffer not written.\n"); OutputDebugString("Error: Entire buffer not written.\n");
} }
@ -103,6 +139,8 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
s32 Error = GetLastError(); s32 Error = GetLastError();
//InvalidCodePath; //InvalidCodePath;
} }
return Success;
} }
///////////////////////// /////////////////////////
@ -111,6 +149,8 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
void void
Win32SerialArray_Create(gs_thread_context Context) Win32SerialArray_Create(gs_thread_context Context)
{ {
DEBUG_TRACK_FUNCTION;
Win32SerialHandlesCountMax = 32; Win32SerialHandlesCountMax = 32;
Win32SerialHandlesCount = 0; Win32SerialHandlesCount = 0;
Win32SerialHandles = AllocatorAllocArray(Context.Allocator, HANDLE, Win32SerialHandlesCountMax); Win32SerialHandles = AllocatorAllocArray(Context.Allocator, HANDLE, Win32SerialHandlesCountMax);
@ -124,6 +164,8 @@ Win32SerialArray_Create(gs_thread_context Context)
void void
Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName) Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName)
{ {
DEBUG_TRACK_FUNCTION;
Assert(Win32SerialHandlesCount < Win32SerialHandlesCountMax); Assert(Win32SerialHandlesCount < Win32SerialHandlesCountMax);
u32 Index = Win32SerialHandlesCount++; u32 Index = Win32SerialHandlesCount++;
Win32SerialHandles[Index] = SerialHandle; Win32SerialHandles[Index] = SerialHandle;
@ -133,6 +175,8 @@ Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName)
HANDLE HANDLE
Win32SerialArray_Get(gs_const_string PortName) Win32SerialArray_Get(gs_const_string PortName)
{ {
DEBUG_TRACK_FUNCTION;
HANDLE PortHandle = INVALID_HANDLE_VALUE; HANDLE PortHandle = INVALID_HANDLE_VALUE;
for (u32 i = 0; i < Win32SerialHandlesCount; i++) for (u32 i = 0; i < Win32SerialHandlesCount; i++)
{ {
@ -148,13 +192,18 @@ Win32SerialArray_Get(gs_const_string PortName)
HANDLE HANDLE
Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits) Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits)
{ {
DEBUG_TRACK_FUNCTION;
HANDLE PortHandle = Win32SerialArray_Get(PortName); HANDLE PortHandle = Win32SerialArray_Get(PortName);
if (PortHandle == INVALID_HANDLE_VALUE) if (PortHandle == INVALID_HANDLE_VALUE)
{ {
Assert(IsNullTerminated(PortName)); Assert(IsNullTerminated(PortName));
PortHandle = Win32SerialPort_Open(PortName.Str); PortHandle = Win32SerialPort_Open(PortName.Str);
Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits); if (PortHandle != INVALID_HANDLE_VALUE)
Win32SerialArray_Push(PortHandle, PortName); {
Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits);
Win32SerialArray_Push(PortHandle, PortName);
}
} }
return PortHandle; return PortHandle;
} }