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;
};
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_BLOCKS_MAX 128
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
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 = {};
if (ReadFieldIdentifier(Field, T))
@ -293,8 +293,13 @@ ReadStringField(assembly_field Field, assembly_tokenizer* T, gs_memory_arena* Ar
if (ReadFieldEnd(T))
{
// Success
Result = PushString(Arena, ExistingString.Length);
u64 Length = ExistingString.Length + (ShouldNullTerminate ? 1 : 0);
Result = PushString(Arena, Length);
PrintF(&Result, "%S", ExistingString);
if (ShouldNullTerminate)
{
NullTerminate(&Result);
}
}
}
return Result;
@ -430,6 +435,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe
if (StringsEqual(OutputModeString.ConstString, ConstString("UART")))
{
Assembly->OutputMode = NetworkProtocol_UART;
Assembly->UARTComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena, true).ConstString;
}
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))
{
StripAt->UARTAddr.Channel = (u8)ReadIntField(AssemblyField_UART_Channel, &Tokenizer);
StripAt->UARTAddr.ComPort = ReadStringField(AssemblyField_UART_ComPort, &Tokenizer, &Assembly->Arena).ConstString;
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);
*Result = {0};
Result->Next = 0;
Result->MemorySize = 0;
Result->Memory = 0;

View File

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

View File

@ -81,25 +81,16 @@ UART_FillFooter(uart_footer* Footer, u8* BufferStart)
}
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
// to catch the error where they are different
Assert(ChannelSettings.PixelsCount == Strip.LedCount);
u32 BufferSize = sizeof(uart_header) + sizeof(uart_channel);
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_header* Header = PushStructOnCursor(WriteCursor, uart_header);
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;
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];
pixel Color = LedBuffer.Colors[LedIndex];
u8* OutputPixel = PushArrayOnCursor(&WriteCursor, u8, 3);
u8* OutputPixel = PushArrayOnCursor(WriteCursor, u8, 3);
OutputPixel[Channel->RedIndex] = Color.R;
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_FillFooter(Footer, Buffer->Memory);
uart_footer* Footer = PushStructOnCursor(WriteCursor, uart_footer);
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
@ -137,17 +138,31 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli
ChannelSettings.BlueIndex = 3;
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++)
{
assembly Assembly = Assemblies.Values[AssemblyIdx];
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++)
{
v2_strip StripAt = Assembly.Strips[StripIdx];
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
#endif // FOLDHAUS_LOG_H

View File

@ -364,6 +364,58 @@ Win32LoadSystemCursor(char* CursorIdentifier)
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
WinMain (
HINSTANCE HInstance,
@ -504,6 +556,8 @@ WinMain (
Context.ReloadStaticData(Context, GlobalDebugServices);
}
AddressedDataBufferList_Clear(&OutputData);
{ // Mouse Position
POINT MousePos;
GetCursorPos (&MousePos);
@ -534,39 +588,10 @@ WinMain (
if (true)
{
// NOTE(pjs): Send the network data
// TODO(pjs): This should happen on another thread
/*
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;
}
}
gs_data ProcArg = {};
ProcArg.Memory = (u8*)&OutputData;
ProcArg.Size = sizeof(OutputData);
Win32PushWorkOnQueue(&WorkQueue, Win32_SendAddressedDataBuffers_Job, ProcArg, ConstString("Send UART Data"));
}
Context.Mouse.LeftButtonState = GetMouseButtonStateAdvanced(Context.Mouse.LeftButtonState);
@ -610,6 +635,8 @@ WinMain (
SwapBuffers(DeviceContext);
ReleaseDC(MainWindow.Handle, DeviceContext);
//Win32DoQueueWorkUntilDone(&WorkQueue, Context.ThreadContext);
s64 FinishedWorkTime = GetWallClock();
r32 SecondsElapsed = GetSecondsElapsed(LastFrameEnd, FinishedWorkTime, PerformanceCountFrequency);

View File

@ -13,6 +13,7 @@ global gs_string* Win32SerialPortNames;
DCB
Win32SerialPort_GetState(HANDLE ComPortHandle)
{
DEBUG_TRACK_FUNCTION;
DCB ControlSettings = {0};
ZeroStruct(&ControlSettings);
ControlSettings.DCBlength = sizeof(ControlSettings);
@ -26,14 +27,45 @@ Win32SerialPort_GetState(HANDLE ComPortHandle)
void
Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits)
{
DEBUG_TRACK_FUNCTION;
DCB ControlSettings = Win32SerialPort_GetState(ComPortHandle);
//PrintCommState(ControlSettings);
// TODO(pjs): Validate BaudRate - There's only certain rates that are valid right?
ControlSettings.BaudRate = BaudRate;
ControlSettings.ByteSize = ByteSize;
if (Parity == NOPARITY)
{
ControlSettings.Parity = Parity;
ControlSettings.fParity = 0;
}
if (Parity == EVENPARITY || Parity == ODDPARITY)
{
ControlSettings.Parity = Parity;
ControlSettings.fParity = 1;
}
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);
}
@ -41,6 +73,7 @@ Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Par
HANDLE
Win32SerialPort_Open(char* PortName)
{
DEBUG_TRACK_FUNCTION;
HANDLE ComPortHandle = CreateFile(PortName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
@ -52,11 +85,11 @@ Win32SerialPort_Open(char* PortName)
if (ComPortHandle != INVALID_HANDLE_VALUE)
{
COMMTIMEOUTS Timeouts = { 0 };
Timeouts.ReadIntervalTimeout = 50; // in milliseconds
Timeouts.ReadTotalTimeoutConstant = 50; // in milliseconds
Timeouts.ReadTotalTimeoutMultiplier = 10; // in milliseconds
Timeouts.WriteTotalTimeoutConstant = 50; // in milliseconds
Timeouts.WriteTotalTimeoutMultiplier = 10; // in milliseconds
Timeouts.ReadIntervalTimeout = 0; // in milliseconds
Timeouts.ReadTotalTimeoutConstant = 0; // in milliseconds
Timeouts.ReadTotalTimeoutMultiplier = 0; // in milliseconds
Timeouts.WriteTotalTimeoutConstant = 0; // in milliseconds
Timeouts.WriteTotalTimeoutMultiplier = 0; // in milliseconds
if (SetCommTimeouts(ComPortHandle, &Timeouts))
{
@ -65,14 +98,14 @@ Win32SerialPort_Open(char* PortName)
else
{
s32 Error = GetLastError();
InvalidCodePath;
// TODO(pjs): Error logging
}
}
else
{
// Error
s32 Error = GetLastError();
InvalidCodePath;
// TODO(pjs): Error logging
}
return ComPortHandle;
@ -84,15 +117,18 @@ Win32SerialPort_Close(HANDLE PortHandle)
CloseHandle(PortHandle);
}
void
bool
Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
{
DEBUG_TRACK_FUNCTION;
Assert(PortHandle != INVALID_HANDLE_VALUE);
bool Success = false;
DWORD BytesWritten = 0;
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");
}
@ -103,6 +139,8 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
s32 Error = GetLastError();
//InvalidCodePath;
}
return Success;
}
/////////////////////////
@ -111,6 +149,8 @@ Win32SerialPort_Write(HANDLE PortHandle, gs_data Buffer)
void
Win32SerialArray_Create(gs_thread_context Context)
{
DEBUG_TRACK_FUNCTION;
Win32SerialHandlesCountMax = 32;
Win32SerialHandlesCount = 0;
Win32SerialHandles = AllocatorAllocArray(Context.Allocator, HANDLE, Win32SerialHandlesCountMax);
@ -124,6 +164,8 @@ Win32SerialArray_Create(gs_thread_context Context)
void
Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName)
{
DEBUG_TRACK_FUNCTION;
Assert(Win32SerialHandlesCount < Win32SerialHandlesCountMax);
u32 Index = Win32SerialHandlesCount++;
Win32SerialHandles[Index] = SerialHandle;
@ -133,6 +175,8 @@ Win32SerialArray_Push(HANDLE SerialHandle, gs_const_string PortName)
HANDLE
Win32SerialArray_Get(gs_const_string PortName)
{
DEBUG_TRACK_FUNCTION;
HANDLE PortHandle = INVALID_HANDLE_VALUE;
for (u32 i = 0; i < Win32SerialHandlesCount; i++)
{
@ -148,14 +192,19 @@ Win32SerialArray_Get(gs_const_string PortName)
HANDLE
Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize, u8 Parity, u8 StopBits)
{
DEBUG_TRACK_FUNCTION;
HANDLE PortHandle = Win32SerialArray_Get(PortName);
if (PortHandle == INVALID_HANDLE_VALUE)
{
Assert(IsNullTerminated(PortName));
PortHandle = Win32SerialPort_Open(PortName.Str);
if (PortHandle != INVALID_HANDLE_VALUE)
{
Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits);
Win32SerialArray_Push(PortHandle, PortName);
}
}
return PortHandle;
}