Some pattern work, added a way to identify what COM ports are available on windows, implemented multithreading patterns, and added a path to turn all the lights off on shutdown

This commit is contained in:
Peter Slattery 2021-03-22 20:58:52 -07:00
parent 4085d3acf9
commit 3140ff3fe6
13 changed files with 329 additions and 128 deletions

View File

@ -25,12 +25,12 @@ SET LastError=%ERRORLEVEL%
del lock.tmp del lock.tmp
cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib cl %CommonCompilerFlags% %SourceCodePath%\platform_win32\win32_foldhaus.cpp /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib opengl32.lib dsound.lib Ws2_32.lib Comdlg32.lib Winspool.lib
REM COMPILE UTILITY EXES REM COMPILE UTILITY EXES
cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial_monitor.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib cl %CommonCompilerFlags% %ProjectDevPath%\src\serial_monitor\first.cpp /Feserial_monitor.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib Winspool.lib
cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib cl %CommonCompilerFlags% %ProjectDevPath%\src\sculpture_gen\gen_blumen_lumen.cpp /Fegen_blumen_lumen.exe /link %CommonLinkerFlags% user32.lib winmm.lib gdi32.lib

View File

@ -5,7 +5,7 @@
// //
#ifndef FOLDHAUS_ANIMATION #ifndef FOLDHAUS_ANIMATION
#define ANIMATION_PROC(name) void name(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) #define ANIMATION_PROC(name) void name(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
typedef ANIMATION_PROC(animation_proc); typedef ANIMATION_PROC(animation_proc);
struct frame_range struct frame_range

View File

@ -89,14 +89,71 @@ struct pattern_args
u8* UserData; u8* UserData;
}; };
internal void struct render_anim_to_led_buffer_job_data
AnimationSystem_RenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, animation_pattern_array Patterns, pattern_args PatternArgs)
{ {
animation_pattern Pattern;
led_buffer Buffer;
led_buffer_range BufferRange;
pattern_args PatternArgs;
r32 SecondsIntoBlock;
};
internal void
AnimationSystem_RenderAnimationToLedBufferJob(gs_thread_context Context, gs_data Data)
{
render_anim_to_led_buffer_job_data JobData = *(render_anim_to_led_buffer_job_data*)Data.Memory;
JobData.Pattern.Proc(&JobData.Buffer,
JobData.BufferRange,
JobData.PatternArgs.Assembly,
JobData.SecondsIntoBlock,
JobData.PatternArgs.Transient,
JobData.PatternArgs.UserData);
}
#define MULTITHREAD_PATTERN_RENDERING 1
internal void
AnimationSystem_BeginRenderBlockToLedBuffer(animation_system* System, animation_block Block, led_buffer* Buffer, animation_pattern_array Patterns, pattern_args PatternArgs,
context Context)
{
DEBUG_TRACK_FUNCTION;
u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min; u32 FramesIntoBlock = System->CurrentFrame - Block.Range.Min;
r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame; r32 SecondsIntoBlock = FramesIntoBlock * System->SecondsPerFrame;
animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle); animation_pattern Pattern = Patterns_GetPattern(Patterns, Block.AnimationProcHandle);
#if MULTITHREAD_PATTERN_RENDERING
u32 JobsCount = 4;
u32 LedsPerJob = Buffer->LedCount / JobsCount;
for (u32 i = 0; i < JobsCount; i++)
{
gs_data Data = PushSizeToData(Context.ThreadContext.Transient, sizeof(render_anim_to_led_buffer_job_data));
render_anim_to_led_buffer_job_data* JobData = (render_anim_to_led_buffer_job_data*)Data.Memory;
JobData->Pattern = Pattern;
JobData->Buffer = *Buffer;
JobData->BufferRange.First = LedsPerJob * i;
JobData->BufferRange.OnePastLast = LedsPerJob * (i + 1);
JobData->PatternArgs = PatternArgs;
JobData->SecondsIntoBlock = SecondsIntoBlock;
Context.GeneralWorkQueue->PushWorkOnQueue(Context.GeneralWorkQueue,
(thread_proc*)AnimationSystem_RenderAnimationToLedBufferJob,
Data,
ConstString("Render Pattern To Buffer"));
}
#else
Pattern.Proc(Buffer, PatternArgs.Assembly, SecondsIntoBlock, PatternArgs.Transient, PatternArgs.UserData); Pattern.Proc(Buffer, PatternArgs.Assembly, SecondsIntoBlock, PatternArgs.Transient, PatternArgs.UserData);
#endif
}
internal void
AnimationSystem_EndRenderBlockToLedBuffer (context Context)
{
#if MULTITHREAD_PATTERN_RENDERING
Context.GeneralWorkQueue->CompleteQueueWork(Context.GeneralWorkQueue, Context.ThreadContext);
#endif
} }
// NOTE(pjs): This mirrors animation_layer_frame to account // NOTE(pjs): This mirrors animation_layer_frame to account
@ -114,7 +171,8 @@ RenderAnimationToLedBuffer (animation_system* System,
layer_led_buffer* LayerBuffers, layer_led_buffer* LayerBuffers,
led_buffer* AssemblyLedBuffer, led_buffer* AssemblyLedBuffer,
animation_pattern_array Patterns, animation_pattern_array Patterns,
gs_memory_arena* Transient) gs_memory_arena* Transient,
context Context)
{ {
led_buffer AccBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient); led_buffer AccBuffer = LedBuffer_CreateCopyCleared(*AssemblyLedBuffer, Transient);
@ -144,15 +202,17 @@ RenderAnimationToLedBuffer (animation_system* System,
{ {
led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer; led_buffer TempBuffer = LayerBuffers[Layer].HotBuffer;
animation_block Block = LayerFrame.Hot; animation_block Block = LayerFrame.Hot;
AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs); AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context);
} }
if (LayerFrame.HasNextHot) if (LayerFrame.HasNextHot)
{ {
led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer; led_buffer TempBuffer = LayerBuffers[Layer].NextHotBuffer;
animation_block Block = LayerFrame.NextHot; animation_block Block = LayerFrame.NextHot;
AnimationSystem_RenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs); AnimationSystem_BeginRenderBlockToLedBuffer(System, Block, &TempBuffer, Patterns, PatternArgs, Context);
} }
AnimationSystem_EndRenderBlockToLedBuffer(Context);
} }
// Blend together any layers that have a hot and next hot buffer // Blend together any layers that have a hot and next hot buffer
@ -193,8 +253,11 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
led_system* LedSystem, led_system* LedSystem,
animation_pattern_array Patterns, animation_pattern_array Patterns,
gs_memory_arena* Transient, gs_memory_arena* Transient,
context Context,
u8* UserData) u8* UserData)
{ {
DEBUG_TRACK_FUNCTION;
s32 CurrentFrame = System->CurrentFrame; s32 CurrentFrame = System->CurrentFrame;
r32 FrameTime = CurrentFrame * System->SecondsPerFrame; r32 FrameTime = CurrentFrame * System->SecondsPerFrame;
@ -231,7 +294,8 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
FromLayerBuffers, FromLayerBuffers,
AssemblyLedBuffer, AssemblyLedBuffer,
Patterns, Patterns,
Transient); Transient,
Context);
led_buffer ConsolidatedBuffer = FromBuffer; led_buffer ConsolidatedBuffer = FromBuffer;
if (ToAnim) { if (ToAnim) {
@ -241,7 +305,8 @@ AnimationSystem_RenderToLedBuffers(animation_system* System, assembly_array Asse
ToLayerBuffers, ToLayerBuffers,
AssemblyLedBuffer, AssemblyLedBuffer,
Patterns, Patterns,
Transient); Transient,
Context);
r32 BlendPercent = FadeGroup.FadeElapsed / FadeGroup.FadeDuration; r32 BlendPercent = FadeGroup.FadeElapsed / FadeGroup.FadeDuration;
LedBuffer_Blend(FromBuffer, ToBuffer, &ConsolidatedBuffer, LedBlend_Lerp, (u8*)&BlendPercent); LedBuffer_Blend(FromBuffer, ToBuffer, &ConsolidatedBuffer, LedBlend_Lerp, (u8*)&BlendPercent);

View File

@ -32,6 +32,12 @@ struct led_buffer
v4* Positions; v4* Positions;
}; };
struct led_buffer_range
{
u32 First;
u32 OnePastLast;
};
struct led_system struct led_system
{ {
gs_allocator PlatformMemory; gs_allocator PlatformMemory;
@ -184,6 +190,8 @@ LedBuffer_ClearToBlack(led_buffer* Buffer)
internal void internal void
LedBuffer_Copy(led_buffer From, led_buffer* To) LedBuffer_Copy(led_buffer From, led_buffer* To)
{ {
DEBUG_TRACK_FUNCTION;
Assert(From.LedCount == To->LedCount); Assert(From.LedCount == To->LedCount);
u32 LedCount = To->LedCount; u32 LedCount = To->LedCount;
for (u32 i = 0; i < LedCount; i++) for (u32 i = 0; i < LedCount; i++)
@ -195,6 +203,8 @@ LedBuffer_Copy(led_buffer From, led_buffer* To)
internal void internal void
LedBuffer_Blend(led_buffer A, led_buffer B, led_buffer* Dest, led_blend_proc* BlendProc, u8* UserData) LedBuffer_Blend(led_buffer A, led_buffer B, led_buffer* Dest, led_blend_proc* BlendProc, u8* UserData)
{ {
DEBUG_TRACK_FUNCTION;
Assert(A.LedCount == B.LedCount); Assert(A.LedCount == B.LedCount);
Assert(Dest->LedCount == A.LedCount); Assert(Dest->LedCount == A.LedCount);
Assert(BlendProc); Assert(BlendProc);
@ -211,6 +221,8 @@ LedBuffer_Blend(led_buffer A, led_buffer B, led_buffer* Dest, led_blend_proc* Bl
internal led_buffer internal led_buffer
LedBuffer_CreateCopyCleared (led_buffer Buffer, gs_memory_arena* Arena) LedBuffer_CreateCopyCleared (led_buffer Buffer, gs_memory_arena* Arena)
{ {
DEBUG_TRACK_FUNCTION;
led_buffer Result = {}; led_buffer Result = {};
Result.LedCount = Buffer.LedCount; Result.LedCount = Buffer.LedCount;
Result.Positions = Buffer.Positions; Result.Positions = Buffer.Positions;

View File

@ -95,6 +95,21 @@ INITIALIZE_APPLICATION(InitializeApplication)
State->RunEditor = true; State->RunEditor = true;
} }
internal void
BuildAssemblyData (app_state* State, context Context, addressed_data_buffer_list* OutputData)
{
#define SEND_DATA
#ifdef SEND_DATA
// NOTE(pjs): Building data buffers to be sent out to the sculpture
// This array is used on the platform side to actually send the information
assembly_array SACNAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaSACN, State->Transient);
assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient);
SACN_BuildOutputData(&State->SACN, OutputData, SACNAssemblies, &State->LedSystem);
UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem, State->Transient);
#endif
}
UPDATE_AND_RENDER(UpdateAndRender) UPDATE_AND_RENDER(UpdateAndRender)
{ {
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
@ -119,6 +134,7 @@ UPDATE_AND_RENDER(UpdateAndRender)
&State->LedSystem, &State->LedSystem,
State->Patterns, State->Patterns,
State->Transient, State->Transient,
*Context,
State->UserSpaceDesc.UserData.Memory); State->UserSpaceDesc.UserData.Memory);
} }
@ -133,20 +149,21 @@ UPDATE_AND_RENDER(UpdateAndRender)
Editor_Render(State, Context, RenderBuffer); Editor_Render(State, Context, RenderBuffer);
} }
#define SEND_DATA BuildAssemblyData(State, *Context, OutputData);
#ifdef SEND_DATA
// NOTE(pjs): Building data buffers to be sent out to the sculpture
// This array is used on the platform side to actually send the information
assembly_array SACNAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaSACN, State->Transient);
assembly_array UARTAssemblies = AssemblyArray_Filter(State->Assemblies, AssemblyFilter_OutputsViaUART, State->Transient);
SACN_BuildOutputData(&State->SACN, OutputData, SACNAssemblies, &State->LedSystem);
UART_BuildOutputData(OutputData, UARTAssemblies, &State->LedSystem, State->Transient);
#endif
} }
CLEANUP_APPLICATION(CleanupApplication) CLEANUP_APPLICATION(CleanupApplication)
{ {
app_state* State = (app_state*)Context.MemoryBase; app_state* State = (app_state*)Context.MemoryBase;
for (u32 i = 0; i < State->Assemblies.Count; i++)
{
assembly Assembly = State->Assemblies.Values[i];
led_buffer LedBuffer = State->LedSystem.Buffers[Assembly.LedBufferIndex];
AssemblyDebug_OverrideWithColor(Assembly, LedBuffer, pixel{0, 0, 0});
}
BuildAssemblyData(State, Context, OutputData);
US_CustomCleanup(&State->UserSpaceDesc, State, Context); US_CustomCleanup(&State->UserSpaceDesc, State, Context);
SACN_Cleanup(&State->SACN, Context); SACN_Cleanup(&State->SACN, Context);
} }

View File

@ -76,7 +76,7 @@ typedef UPDATE_AND_RENDER(update_and_render);
#define RELOAD_STATIC_DATA(name) void name(context Context, debug_services* DebugServices) #define RELOAD_STATIC_DATA(name) void name(context Context, debug_services* DebugServices)
typedef RELOAD_STATIC_DATA(reload_static_data); typedef RELOAD_STATIC_DATA(reload_static_data);
#define CLEANUP_APPLICATION(name) void name(context Context) #define CLEANUP_APPLICATION(name) void name(context Context, addressed_data_buffer_list* OutputData)
typedef CLEANUP_APPLICATION(cleanup_application); typedef CLEANUP_APPLICATION(cleanup_application);
// Platform Functions // Platform Functions

View File

@ -411,30 +411,30 @@ GetColor(v4* Colors, u32 ColorsCount, r32 Percent)
} }
internal void internal void
SolidColorPattern(led_buffer* Leds, pixel Color) SolidColorPattern(led_buffer* Leds, led_buffer_range Range, pixel Color)
{ {
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
Leds->Colors[LedIndex] = Color; Leds->Colors[LedIndex] = Color;
} }
} }
internal void internal void
Pattern_Blue(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_Blue(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
pixel Blue = pixel{0, 0, 255}; pixel Blue = pixel{0, 0, 255};
SolidColorPattern(Leds, Blue); SolidColorPattern(Leds, Range, Blue);
} }
internal void internal void
Pattern_Green(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_Green(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
pixel Green = pixel{0, 255, 0}; pixel Green = pixel{0, 255, 0};
SolidColorPattern(Leds, Green); SolidColorPattern(Leds, Range, Green);
} }
internal void internal void
Pattern_FlowerColors(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_FlowerColors(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 CycleTime = 10; r32 CycleTime = 10;
r32 CyclePercent = ModR32(Time, CycleTime) / CycleTime; r32 CyclePercent = ModR32(Time, CycleTime) / CycleTime;
@ -442,7 +442,7 @@ Pattern_FlowerColors(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
v4 CA = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, CyclePercent); v4 CA = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, CyclePercent);
v4 CB = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, 1.0f - CyclePercent); v4 CB = GetColor(FlowerAColors, FLOWER_COLORS_COUNT, 1.0f - CyclePercent);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 P = Leds->Positions[LedIndex]; v4 P = Leds->Positions[LedIndex];
r32 Pct = (Abs(ModR32(P.y, 150) / 150) + CycleTime) * PiR32; r32 Pct = (Abs(ModR32(P.y, 150) / 150) + CycleTime) * PiR32;
@ -453,7 +453,7 @@ Pattern_FlowerColors(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
} }
internal void internal void
TestPatternOne(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) TestPatternOne(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
led_strip_list BlumenStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Blumen Lumen"), Transient); led_strip_list BlumenStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Blumen Lumen"), Transient);
led_strip_list RadiaStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Radialumia"), Transient); led_strip_list RadiaStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("assembly"), ConstString("Radialumia"), Transient);
@ -485,7 +485,7 @@ TestPatternOne(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
} }
internal void internal void
TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) TestPatternTwo(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 PeriodicTime = (Time / PiR32) * 2; r32 PeriodicTime = (Time / PiR32) * 2;
@ -504,7 +504,7 @@ TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
r32 OuterRadiusSquared = 1000000; r32 OuterRadiusSquared = 1000000;
r32 InnerRadiusSquared = 0; r32 InnerRadiusSquared = 0;
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 Position = Leds->Positions[LedIndex]; v4 Position = Leds->Positions[LedIndex];
@ -537,7 +537,7 @@ TestPatternTwo(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
} }
internal void internal void
TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) TestPatternThree(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
v4 GreenCenter = v4{0, 0, 150, 1}; v4 GreenCenter = v4{0, 0, 150, 1};
r32 GreenRadius = Abs(SinR32(Time)) * 200; r32 GreenRadius = Abs(SinR32(Time)) * 200;
@ -548,7 +548,7 @@ TestPatternThree(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
r32 FadeDist = 35; r32 FadeDist = 35;
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 LedPosition = Leds->Positions[LedIndex]; v4 LedPosition = Leds->Positions[LedIndex];
u8 Red = 0; u8 Red = 0;
@ -702,7 +702,7 @@ while (Hue > 360.0f) { Hue -= 360.0f; }
} }
internal void internal void
Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_HueShift(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 Height = SinR32(Time) * 25; r32 Height = SinR32(Time) * 25;
@ -713,7 +713,7 @@ Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
v4 HSV = { CycleProgress * 360, 1, 1, 1 }; v4 HSV = { CycleProgress * 360, 1, 1, 1 };
v4 RGB = HSVToRGB(HSV); v4 RGB = HSVToRGB(HSV);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 Pos = Leds->Positions[LedIndex]; v4 Pos = Leds->Positions[LedIndex];
r32 Dist = Pos.y - Height; r32 Dist = Pos.y - Height;
@ -732,7 +732,7 @@ Pattern_HueShift(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
} }
internal void internal void
Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_HueFade(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 HueBase = ModR32(Time * 50, 360); r32 HueBase = ModR32(Time * 50, 360);
@ -740,7 +740,7 @@ Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
r32 CycleProgress = FractR32(Time / CycleLength); r32 CycleProgress = FractR32(Time / CycleLength);
r32 CycleBlend = (SinR32(Time) * .5f) + .5f; r32 CycleBlend = (SinR32(Time) * .5f) + .5f;
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 Pos = Leds->Positions[LedIndex]; v4 Pos = Leds->Positions[LedIndex];
r32 Hue = HueBase + Pos.y + Pos.x; r32 Hue = HueBase + Pos.y + Pos.x;
@ -752,9 +752,9 @@ Pattern_HueFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena*
} }
internal void internal void
Pattern_AllGreen(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_AllGreen(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
u32 I = LedIndex + 1; u32 I = LedIndex + 1;
Leds->Colors[LedIndex] = {}; Leds->Colors[LedIndex] = {};
@ -781,7 +781,7 @@ PatternHash(r32 Seed)
} }
internal void internal void
Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_Spots(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
pixel ColorA = { 0, 255, 255 }; pixel ColorA = { 0, 255, 255 };
pixel ColorB = { 255, 0, 255 }; pixel ColorB = { 255, 0, 255 };
@ -790,7 +790,7 @@ Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Tr
Time *= Speed; Time *= Speed;
r32 ScaleA = 2 * SinR32(Time / 5); r32 ScaleA = 2 * SinR32(Time / 5);
r32 ScaleB = 2.4f * CosR32(Time / 2.5f); r32 ScaleB = 2.4f * CosR32(Time / 2.5f);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 P = Leds->Positions[LedIndex]; v4 P = Leds->Positions[LedIndex];
r32 V = P.y; r32 V = P.y;
@ -807,10 +807,10 @@ Pattern_Spots(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Tr
} }
internal void internal void
Pattern_LighthouseRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_LighthouseRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
v2 RefVector = V2Normalize(v2{ SinR32(Time), CosR32(Time) }); v2 RefVector = V2Normalize(v2{ SinR32(Time), CosR32(Time) });
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v2 Vector = v2{ v2 Vector = v2{
Leds->Positions[LedIndex].x, Leds->Positions[LedIndex].x,
@ -828,7 +828,7 @@ Pattern_LighthouseRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memo
} }
internal void internal void
Pattern_SmoothGrowRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_SmoothGrowRainbow(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 FillCycleTime = ModR32(Time, 7.0f) / 7.0f; r32 FillCycleTime = ModR32(Time, 7.0f) / 7.0f;
r32 ColorCycleTime = ModR32(Time, 21.0f) / 21.0f; r32 ColorCycleTime = ModR32(Time, 21.0f) / 21.0f;
@ -850,7 +850,7 @@ Pattern_SmoothGrowRainbow(led_buffer* Leds, assembly Assembly, r32 Time, gs_memo
} }
internal void internal void
Pattern_GrowAndFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_GrowAndFade(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 PercentCycle = ModR32(Time, 10) / 10; r32 PercentCycle = ModR32(Time, 10) / 10;
v4 HSV = { PercentCycle * 360, 1, 1, 1 }; v4 HSV = { PercentCycle * 360, 1, 1, 1 };
@ -859,7 +859,7 @@ Pattern_GrowAndFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_are
r32 RefHeight = -100 + (Smoothstep(PercentCycle * 1.4f) * 400); r32 RefHeight = -100 + (Smoothstep(PercentCycle * 1.4f) * 400);
r32 RefBrightness = 1.0f - Smoothstep(PercentCycle); r32 RefBrightness = 1.0f - Smoothstep(PercentCycle);
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 P = Leds->Positions[LedIndex]; v4 P = Leds->Positions[LedIndex];
@ -873,7 +873,7 @@ Pattern_GrowAndFade(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_are
} }
internal void internal void
Pattern_ColorToWhite(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_ColorToWhite(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 FadeBottomBase = 50; r32 FadeBottomBase = 50;
r32 FadeTop = 125; r32 FadeTop = 125;
@ -935,7 +935,7 @@ Pattern_ColorToWhite(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
} }
internal void internal void
Pattern_FlowerColorToWhite(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_FlowerColorToWhite(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
r32 FadeBottomBase = 50; r32 FadeBottomBase = 50;
r32 FadeTop = 125; r32 FadeTop = 125;
@ -999,7 +999,7 @@ v4* FBC = &FlowerBColors[0];
v4* FCC = &FlowerCColors[0]; v4* FCC = &FlowerCColors[0];
internal void internal void
Pattern_BasicFlowers(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_BasicFlowers(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
if (TLastFrame > Time) if (TLastFrame > Time)
{ {
@ -1042,16 +1042,11 @@ Pattern_BasicFlowers(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_ar
} }
internal void internal void
Pattern_Wavy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_Wavy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
DEBUG_TRACK_FUNCTION;
} for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
internal void
Pattern_Patchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
#if 0
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
{ {
v4 P = Leds->Positions[LedIndex]; v4 P = Leds->Positions[LedIndex];
@ -1072,8 +1067,14 @@ Pattern_Patchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
Leds->Colors[LedIndex] = V4ToRGBPixel(C); Leds->Colors[LedIndex] = V4ToRGBPixel(C);
//Leds->Colors[LedIndex] = pixel{NV, NV, NV}; //Leds->Colors[LedIndex] = pixel{NV, NV, NV};
} }
#elif 1 }
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
internal void
Pattern_Patchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{
DEBUG_TRACK_FUNCTION;
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 P = Leds->Positions[LedIndex]; v4 P = Leds->Positions[LedIndex];
r32 LedRange = 300.0f; r32 LedRange = 300.0f;
@ -1093,37 +1094,17 @@ Pattern_Patchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* T
v4 C = CA + CB; v4 C = CA + CB;
Leds->Colors[LedIndex] = V4ToRGBPixel(C); Leds->Colors[LedIndex] = V4ToRGBPixel(C);
} }
#else
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
r32 LedRange = 300.0f;
r32 ScaleFactor = 1.0f / LedRange;
v3 Pp = P.xyz + v3{150, 100, 0};
r32 NoiseA = Fbm3D((Pp / 35), Time * 0.5f);
//NoiseA = PowR32(NoiseA, 3);
NoiseA = Smoothstep(NoiseA);
v4 CA = v4{1, 0, 1, 1} * NoiseA;
r32 NoiseB = Noise3D((Pp / 35) + v3{0, 0, Time * 5});
NoiseB = PowR32(NoiseB, 3);
NoiseB = Smoothstep(NoiseB);
v4 CB = v4{0, 1, 1, 1};
v4 C = V4Lerp(NoiseB, CA, CB);
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
}
#endif
} }
internal void internal void
Pattern_Leafy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_Leafy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
DEBUG_TRACK_FUNCTION;
v4* Colors = &FlowerBColors[0]; v4* Colors = &FlowerBColors[0];
for (u32 LedIndex = 0; LedIndex < Leds->LedCount; LedIndex++) for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{ {
v4 P = Leds->Positions[LedIndex]; v4 P = Leds->Positions[LedIndex];
@ -1177,15 +1158,35 @@ Pattern_Leafy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Tr
} }
internal void internal void
Pattern_LeafyPatchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_LeafyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
DEBUG_TRACK_FUNCTION;
for (u32 LedIndex = Range.First; LedIndex < Range.OnePastLast; LedIndex++)
{
v4 P = Leds->Positions[LedIndex];
r32 LedRange = 300.0f;
r32 ScaleFactor = 1.0f / LedRange;
v3 Pp = P.xyz + v3{150, 100, 0};
r32 NoiseA = Fbm3D((Pp / 35), Time * 0.5f);
//NoiseA = PowR32(NoiseA, 3);
NoiseA = Smoothstep(NoiseA);
v4 CA = v4{1, 0, 1, 1} * NoiseA;
r32 NoiseB = Noise3D((Pp / 35) + v3{0, 0, Time * 5});
NoiseB = PowR32(NoiseB, 3);
NoiseB = Smoothstep(NoiseB);
v4 CB = v4{0, 1, 1, 1};
v4 C = V4Lerp(NoiseB, CA, CB);
Leds->Colors[LedIndex] = V4ToRGBPixel(C);
}
} }
internal void internal void
Pattern_WavyPatchy(led_buffer* Leds, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData) Pattern_WavyPatchy(led_buffer* Leds, led_buffer_range Range, assembly Assembly, r32 Time, gs_memory_arena* Transient, u8* UserData)
{ {
DEBUG_TRACK_FUNCTION;
} }
#define BLUMEN_PATTERNS_H #define BLUMEN_PATTERNS_H

View File

@ -396,7 +396,7 @@ Win32_SendAddressedDataBuffer(gs_thread_context Context, addressed_data_buffer*
{ {
if (BufferAt->ComPort.Length > 0) if (BufferAt->ComPort.Length > 0)
{ {
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1); HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1, Context.Transient);
if (SerialPort != INVALID_HANDLE_VALUE) if (SerialPort != INVALID_HANDLE_VALUE)
{ {
if (Win32SerialPort_Write(SerialPort, BufferAt->Data)) if (Win32SerialPort_Write(SerialPort, BufferAt->Data))
@ -525,6 +525,37 @@ SetWorkingDirectory(HINSTANCE HInstance, gs_thread_context ThreadContext)
#include "../../gs_libs/gs_path.h" #include "../../gs_libs/gs_path.h"
internal void
Win32_SendOutputData(gs_thread_context ThreadContext, addressed_data_buffer_list OutputData)
{
bool Multithread = true;
if (Multithread)
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffer_Job, ProcArg, ConstString("Send UART Data"));
}
}
else
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32_SendAddressedDataBuffer_Job(ThreadContext, ProcArg);
}
}
}
int WINAPI int WINAPI
WinMain ( WinMain (
HINSTANCE HInstance, HINSTANCE HInstance,
@ -689,31 +720,7 @@ WinMain (
Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData); Context.UpdateAndRender(&Context, InputQueue, &RenderBuffer, &OutputData);
bool Multithread = false; Win32_SendOutputData(ThreadContext, OutputData);
if (Multithread)
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32PushWorkOnQueue(&Win32WorkQueue.WorkQueue, Win32_SendAddressedDataBuffer_Job, ProcArg, ConstString("Send UART Data"));
}
}
else
{
for (addressed_data_buffer* At = OutputData.Root;
At != 0;
At = At->Next)
{
gs_data ProcArg = {};
ProcArg.Memory = (u8*)At;
ProcArg.Size = sizeof(addressed_data_buffer);
Win32_SendAddressedDataBuffer_Job(ThreadContext, ProcArg);
}
}
RenderCommandBuffer(RenderBuffer); RenderCommandBuffer(RenderBuffer);
ClearRenderBuffer(&RenderBuffer); ClearRenderBuffer(&RenderBuffer);
@ -741,7 +748,9 @@ WinMain (
LastFrameEnd = GetWallClock(); LastFrameEnd = GetWallClock();
} }
Context.CleanupApplication(Context); Context.CleanupApplication(Context, &OutputData);
Win32_SendOutputData(ThreadContext, OutputData);
Win32DoQueueWorkUntilDone(&Win32WorkQueue.WorkQueue, Context.ThreadContext);
Win32WorkQueue_Cleanup(); Win32WorkQueue_Cleanup();
//Win32_TestCode_SocketReading_Cleanup(); //Win32_TestCode_SocketReading_Cleanup();

View File

@ -70,20 +70,74 @@ Win32SerialPort_SetState(HANDLE ComPortHandle, u32 BaudRate, u8 ByteSize, u8 Par
bool Success = SetCommState(ComPortHandle, &ControlSettings); bool Success = SetCommState(ComPortHandle, &ControlSettings);
} }
gs_const_string_array
Win32SerialPorts_List(gs_memory_arena* Arena, gs_memory_arena* Transient)
{
gs_const_string_array Result = {};
DWORD SizeNeeded0 = 0;
DWORD CountReturned0 = 0;
EnumPorts(NULL, 1, 0, 0, &SizeNeeded0, &CountReturned0);
Assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER);
DWORD SizeNeeded1 = 0;
DWORD CountReturned1 = 0;
PORT_INFO_1* PortsArray = (PORT_INFO_1*)PushSize(Transient, SizeNeeded0);
if (EnumPorts(NULL,
1,
(u8*)PortsArray,
SizeNeeded0,
&SizeNeeded1,
&CountReturned1))
{
Result.CountMax = (u64)CountReturned1;
Result.Strings = PushArray(Arena, gs_const_string, Result.CountMax);
for (; Result.Count < Result.CountMax; Result.Count++)
{
u64 Index = Result.Count;
u64 StrLen = CStringLength(PortsArray[Index].pName);
gs_string Str = PushString(Arena, StrLen);
PrintF(&Str, "%.*s", StrLen, PortsArray[Index].pName);
Result.Strings[Result.Count] = Str.ConstString;
}
}
return Result;
}
bool
Win32SerialPort_Exists(char* PortName, gs_memory_arena* Transient)
{
bool Result = false;
if (PortName != 0)
{
gs_const_string PortIdent = ConstString(PortName);
u32 IdentBegin = FindLast(PortIdent, '\\') + 1;
PortIdent = Substring(PortIdent, IdentBegin, PortIdent.Length);
gs_const_string_array PortsAvailable = Win32SerialPorts_List(Transient, Transient);
for (u64 i = 0; i < PortsAvailable.Count; i++)
{
gs_const_string AvailablePortName = PortsAvailable.Strings[i];
if (StringsEqualUpToLength(AvailablePortName, PortIdent, PortIdent.Length))
{
Result = true;
break;
}
}
}
return Result;
}
HANDLE HANDLE
Win32SerialPort_Open(char* PortName) Win32SerialPort_Open(char* PortName, gs_memory_arena* Transient)
{ {
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
HANDLE ComPortHandle = INVALID_HANDLE_VALUE;; HANDLE ComPortHandle = INVALID_HANDLE_VALUE;;
WIN32_FIND_DATA FindData; if (Win32SerialPort_Exists(PortName, Transient))
HANDLE ComPortExists = FindFirstFile(PortName, &FindData);
// TODO(PS): we aren't sure yet if FindFirstFile will actually work
// for the purpose of checking to see if a ComPort actually exists.
// When you go to Foldspace next time, make sure we are still connecting
// the sculpture
if (ComPortExists != INVALID_HANDLE_VALUE)
{ {
ComPortHandle = CreateFile(PortName, ComPortHandle = CreateFile(PortName,
@ -289,7 +343,7 @@ 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, gs_memory_arena* Transient)
{ {
DEBUG_TRACK_FUNCTION; DEBUG_TRACK_FUNCTION;
@ -297,7 +351,7 @@ Win32SerialArray_GetOrOpen(gs_const_string PortName, u32 BaudRate, u8 ByteSize,
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, Transient);
if (PortHandle != INVALID_HANDLE_VALUE) if (PortHandle != INVALID_HANDLE_VALUE)
{ {
Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits); Win32SerialPort_SetState(PortHandle, BaudRate, ByteSize, Parity, StopBits);

View File

@ -133,8 +133,11 @@ BlumenLumen_LoadPatterns(app_state* State)
Patterns_PushPattern(Patterns, Pattern_FlowerColorToWhite); Patterns_PushPattern(Patterns, Pattern_FlowerColorToWhite);
Patterns_PushPattern(Patterns, Pattern_BasicFlowers); Patterns_PushPattern(Patterns, Pattern_BasicFlowers);
// 15 // 15
Patterns_PushPattern(Patterns, Pattern_Wavy);
Patterns_PushPattern(Patterns, Pattern_Patchy); Patterns_PushPattern(Patterns, Pattern_Patchy);
Patterns_PushPattern(Patterns, Pattern_Leafy); Patterns_PushPattern(Patterns, Pattern_Leafy);
Patterns_PushPattern(Patterns, Pattern_LeafyPatchy);
Patterns_PushPattern(Patterns, Pattern_WavyPatchy);
} }
internal v4 internal v4

View File

@ -1557,6 +1557,25 @@ FindFirst(gs_string String, char C)
return FindFirst(String.ConstString, 0, C); return FindFirst(String.ConstString, 0, C);
} }
internal s64
FindLast(char* String, s64 StartIndex, char C)
{
s64 Result = -1;
s64 i = 0;
while (String[i] != 0 && i < StartIndex)
{
i++;
}
while (String[i])
{
if (String[i] == C)
{
Result = i;
}
i++;
}
return Result;
}
internal s64 internal s64
FindLast(gs_const_string String, u64 StartIndex, char C) FindLast(gs_const_string String, u64 StartIndex, char C)
{ {

View File

@ -232,7 +232,7 @@ struct u64_array
# define InvalidDefaultCase default: { AssertBreak("invalid default case"); } break; # define InvalidDefaultCase default: { AssertBreak("invalid default case"); } break;
# define StaticAssert(c) \ # define StaticAssert(c) \
enum { \ enum { \
Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \ Glue(gs_AssertFail_, __LINE__) = 1 / (int)(!!(c)), \
} }
#else #else
# define Assert(c) # define Assert(c)
@ -560,7 +560,7 @@ struct gs_const_string_array
{ {
gs_const_string* Strings; gs_const_string* Strings;
u64 Count; u64 Count;
u64 Used; u64 CountMax;
}; };
struct gs_string_array struct gs_string_array
@ -579,6 +579,27 @@ CStringLength(char* Str)
return Result; return Result;
} }
internal bool
CStringsEqual(char* A, char* B)
{
bool Result = true;
char* AAt = A;
char* BAt = B;
while (AAt[0] && BAt[0])
{
if (AAt[0] != BAt[0])
{
Result = false;
break;
}
AAt++;
BAt++;
}
if (AAt[0] != 0 || BAt[0] != 0) { Result = false; }
return Result;
}
#define StringExpand(str) (int)(str).Length, (str).Str #define StringExpand(str) (int)(str).Length, (str).Str
#define LitString(cstr) gs_const_string{(char*)(cstr), CStringLength((char*)cstr) } #define LitString(cstr) gs_const_string{(char*)(cstr), CStringLength((char*)cstr) }

View File

@ -93,7 +93,7 @@ int main(int ArgCount, char** Args)
{ {
gs_thread_context Ctx = Win32CreateThreadContext(); gs_thread_context Ctx = Win32CreateThreadContext();
HANDLE SerialHandle = Win32SerialPort_Open("\\\\.\\COM9"); HANDLE SerialHandle = Win32SerialPort_Open("\\\\.\\COM9", Ctx.Transient);
Win32SerialPort_SetState(SerialHandle, 2000000, 8, 0, 1); Win32SerialPort_SetState(SerialHandle, 2000000, 8, 0, 1);
gs_const_string OutFileName = ConstString("./serial_dump.data"); gs_const_string OutFileName = ConstString("./serial_dump.data");