implemented segmented led strips
This commit is contained in:
parent
0ba59d3767
commit
bfd50c9129
|
@ -166,7 +166,7 @@ SculptureView_Render(panel Panel, rect2 PanelBounds, render_command_buffer* Rend
|
||||||
u32 MaxLEDsPerJob = 2048;
|
u32 MaxLEDsPerJob = 2048;
|
||||||
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal);
|
render_quad_batch_constructor RenderLEDsBatch = PushRenderQuad3DBatch(RenderBuffer, State->LedSystem.LedsCountTotal);
|
||||||
|
|
||||||
u32 FocusPixel = 256;
|
u32 FocusPixel = 100;
|
||||||
|
|
||||||
for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++)
|
for (u32 BufferIndex = 0; BufferIndex < State->LedSystem.BuffersCount; BufferIndex++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,6 +135,46 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 Position)
|
||||||
Buffer->Positions[Led] = Position;
|
Buffer->Positions[Led] = Position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal u32
|
||||||
|
Assembly_ConstructStrip(assembly* Assembly, led_buffer* LedBuffer, v2_strip* StripAt, strip_gen_data GenData, v4 RootPosition, u32 LedStartIndex)
|
||||||
|
{
|
||||||
|
u32 LedsAdded = 0;
|
||||||
|
|
||||||
|
switch (GenData.Method)
|
||||||
|
{
|
||||||
|
case StripGeneration_InterpolatePoints:
|
||||||
|
{
|
||||||
|
strip_gen_interpolate_points InterpPoints = GenData.InterpolatePoints;
|
||||||
|
v4 WS_StripStart = RootPosition + ToV4Point(InterpPoints.StartPosition * Assembly->Scale);
|
||||||
|
v4 WS_StripEnd = RootPosition + ToV4Point(InterpPoints.EndPosition * Assembly->Scale);
|
||||||
|
|
||||||
|
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)InterpPoints.LedCount;
|
||||||
|
for (u32 Step = 0; Step < InterpPoints.LedCount; Step++)
|
||||||
|
{
|
||||||
|
s32 LedIndex = LedStartIndex + LedsAdded++;
|
||||||
|
v4 LedPosition = WS_StripStart + (SingleStep * Step);
|
||||||
|
LedBufferSetLed(LedBuffer, LedIndex, LedPosition);
|
||||||
|
StripAt->LedLUT[Step] = LedIndex;
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case StripGeneration_Sequence:
|
||||||
|
{
|
||||||
|
strip_gen_sequence Sequence = GenData.Sequence;
|
||||||
|
for (u32 i = 0; i < Sequence.ElementsCount; i++)
|
||||||
|
{
|
||||||
|
__debugbreak();
|
||||||
|
strip_gen_data SegmentGenData = Sequence.Elements[i];
|
||||||
|
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, SegmentGenData, RootPosition, LedStartIndex + LedsAdded);
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
InvalidDefaultCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LedsAdded;
|
||||||
|
}
|
||||||
|
|
||||||
internal void
|
internal void
|
||||||
ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem)
|
ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem)
|
||||||
{
|
{
|
||||||
|
@ -150,17 +190,8 @@ ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem)
|
||||||
v2_strip* StripAt = &Assembly->Strips[StripIdx];
|
v2_strip* StripAt = &Assembly->Strips[StripIdx];
|
||||||
StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount);
|
StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount);
|
||||||
|
|
||||||
v4 WS_StripStart = RootPosition + ToV4Point(StripAt->StartPosition * Assembly->Scale);
|
strip_gen_data GenData = StripAt->GenerationData;
|
||||||
v4 WS_StripEnd = RootPosition + ToV4Point(StripAt->EndPosition * Assembly->Scale);
|
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded);
|
||||||
|
|
||||||
v4 SingleStep = (WS_StripEnd - WS_StripStart) / (r32)StripAt->LedCount;
|
|
||||||
for (u32 Step = 0; Step < StripAt->LedCount; Step++)
|
|
||||||
{
|
|
||||||
s32 LedIndex = LedsAdded++;
|
|
||||||
v4 LedPosition = WS_StripStart + (SingleStep * Step);
|
|
||||||
LedBufferSetLed(LedBuffer, LedIndex, LedPosition);
|
|
||||||
StripAt->LedLUT[Step] = LedIndex;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,41 @@ struct strip_sacn_addr
|
||||||
struct strip_uart_addr
|
struct strip_uart_addr
|
||||||
{
|
{
|
||||||
u8 Channel;
|
u8 Channel;
|
||||||
|
|
||||||
|
gs_string ComPort;
|
||||||
|
// This may not be used based on the value of the parent
|
||||||
|
// assembly's NetworkPortMode field
|
||||||
|
};
|
||||||
|
|
||||||
|
enum strip_gen_method
|
||||||
|
{
|
||||||
|
StripGeneration_InterpolatePoints,
|
||||||
|
StripGeneration_Sequence,
|
||||||
|
|
||||||
|
StripGeneration_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct strip_gen_data strip_gen_data;
|
||||||
|
|
||||||
|
struct strip_gen_interpolate_points
|
||||||
|
{
|
||||||
|
v3 StartPosition;
|
||||||
|
v3 EndPosition;
|
||||||
|
u32 LedCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct strip_gen_sequence
|
||||||
|
{
|
||||||
|
strip_gen_data* Elements;
|
||||||
|
u32 ElementsCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct strip_gen_data
|
||||||
|
{
|
||||||
|
strip_gen_method Method;
|
||||||
|
|
||||||
|
strip_gen_interpolate_points InterpolatePoints;
|
||||||
|
strip_gen_sequence Sequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct v2_strip
|
struct v2_strip
|
||||||
|
@ -67,10 +102,7 @@ struct v2_strip
|
||||||
strip_sacn_addr SACNAddr;
|
strip_sacn_addr SACNAddr;
|
||||||
strip_uart_addr UARTAddr;
|
strip_uart_addr UARTAddr;
|
||||||
|
|
||||||
// TODO(Peter): When we create more ways to calculate points, this needs to become
|
strip_gen_data GenerationData;
|
||||||
// a type enum and a union
|
|
||||||
v3 StartPosition;
|
|
||||||
v3 EndPosition;
|
|
||||||
|
|
||||||
u32 LedCount;
|
u32 LedCount;
|
||||||
u32* LedLUT;
|
u32* LedLUT;
|
||||||
|
@ -86,6 +118,21 @@ struct led_strip_list
|
||||||
u32* StripIndices;
|
u32* StripIndices;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum network_port_mode
|
||||||
|
{
|
||||||
|
// This enum defines the scope which contains what network
|
||||||
|
// port each address should be sent over.
|
||||||
|
|
||||||
|
NetworkPortMode_GlobalPort,
|
||||||
|
// GlobalPort means that the port is defined in the assembly structure
|
||||||
|
|
||||||
|
NetworkPortMode_PortPerStrip,
|
||||||
|
// PortPerStrip means that the address stored in the strip structure
|
||||||
|
// should be used, and each strip might have a different port
|
||||||
|
|
||||||
|
NetworkPortMode_Count,
|
||||||
|
};
|
||||||
|
|
||||||
struct assembly
|
struct assembly
|
||||||
{
|
{
|
||||||
gs_memory_arena Arena;
|
gs_memory_arena Arena;
|
||||||
|
@ -102,7 +149,8 @@ struct assembly
|
||||||
v2_strip* Strips;
|
v2_strip* Strips;
|
||||||
|
|
||||||
network_protocol OutputMode;
|
network_protocol OutputMode;
|
||||||
gs_const_string UARTComPort;
|
network_port_mode NetPortMode;
|
||||||
|
gs_string UARTComPort;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct assembly_array
|
struct assembly_array
|
||||||
|
@ -120,6 +168,31 @@ LedSystemGetBuffer(led_system* System, u32 Index)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal u32
|
||||||
|
StripGenData_CountLeds(strip_gen_data Data)
|
||||||
|
{
|
||||||
|
u32 Result = 0;
|
||||||
|
|
||||||
|
switch (Data.Method)
|
||||||
|
{
|
||||||
|
case StripGeneration_InterpolatePoints:
|
||||||
|
{
|
||||||
|
Result += Data.InterpolatePoints.LedCount;
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case StripGeneration_Sequence:
|
||||||
|
{
|
||||||
|
for (u32 i = 0; i < Data.Sequence.ElementsCount; i++)
|
||||||
|
{
|
||||||
|
Result += StripGenData_CountLeds(Data.Sequence.Elements[i]);
|
||||||
|
}
|
||||||
|
}break;
|
||||||
|
|
||||||
|
InvalidDefaultCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
#define FOLDHAUS_ASSEMBLY_H
|
#define FOLDHAUS_ASSEMBLY_H
|
||||||
#endif // FOLDHAUS_ASSEMBLY_H
|
#endif // FOLDHAUS_ASSEMBLY_H
|
|
@ -33,10 +33,16 @@ enum assembly_field
|
||||||
AssemblyField_UART_ComPort,
|
AssemblyField_UART_ComPort,
|
||||||
|
|
||||||
AssemblyField_PointPlacementType,
|
AssemblyField_PointPlacementType,
|
||||||
|
|
||||||
AssemblyField_InterpolatePoints,
|
AssemblyField_InterpolatePoints,
|
||||||
AssemblyField_Start,
|
AssemblyField_Start,
|
||||||
AssemblyField_End,
|
AssemblyField_End,
|
||||||
AssemblyField_LedCount,
|
AssemblyField_LedCount,
|
||||||
|
|
||||||
|
AssemblyField_SegmentSequence,
|
||||||
|
AssemblyField_SegmentSequenceLength,
|
||||||
|
AssemblyField_Segment,
|
||||||
|
|
||||||
AssemblyField_TagsCount,
|
AssemblyField_TagsCount,
|
||||||
AssemblyField_Tag,
|
AssemblyField_Tag,
|
||||||
AssemblyField_Name,
|
AssemblyField_Name,
|
||||||
|
@ -63,12 +69,16 @@ global gs_const_string AssemblyFieldIdentifiers[] = {
|
||||||
ConstString("com_port"), // AssemblyField_UART_ComPort
|
ConstString("com_port"), // AssemblyField_UART_ComPort
|
||||||
|
|
||||||
ConstString("point_placement_type"), // AssemblyField_PointPlacementType
|
ConstString("point_placement_type"), // AssemblyField_PointPlacementType
|
||||||
|
|
||||||
ConstString("interpolate_points"), // AssemblyField_InterpolatePoints
|
ConstString("interpolate_points"), // AssemblyField_InterpolatePoints
|
||||||
ConstString("start"), // AssemblyField_Start
|
ConstString("start"), // AssemblyField_Start
|
||||||
ConstString("end"), // AssemblyField_End
|
ConstString("end"), // AssemblyField_End
|
||||||
|
|
||||||
ConstString("led_count"), // AssemblyField_LedCount
|
ConstString("led_count"), // AssemblyField_LedCount
|
||||||
|
|
||||||
|
ConstString("segment_sequence"), // AssemblyField_SegmentSequence
|
||||||
|
ConstString("segment_count"), // AssemblyField_SegmentSequenceLength
|
||||||
|
ConstString("segment"), // AssemblyField_Segment
|
||||||
|
|
||||||
ConstString("tags_count"), // AssemblyField_TagCount
|
ConstString("tags_count"), // AssemblyField_TagCount
|
||||||
ConstString("tag"), // AssemblyField_Tag
|
ConstString("tag"), // AssemblyField_Tag
|
||||||
ConstString("name"), // AssemblyField_Name
|
ConstString("name"), // AssemblyField_Name
|
||||||
|
@ -84,6 +94,170 @@ StripSetTag(v2_strip* Strip, u32 TagIndex, gs_const_string TagName, gs_const_str
|
||||||
TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue));
|
TagAt->ValueHash = HashDJB2ToU32(StringExpand(TagValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal strip_sacn_addr
|
||||||
|
AssemblyParser_ReadSACNAddr(parser* Parser, assembly Assembly)
|
||||||
|
{
|
||||||
|
strip_sacn_addr Result = {0};
|
||||||
|
|
||||||
|
if (Parser_ReadOpenStruct(Parser, AssemblyField_OutputSACN))
|
||||||
|
{
|
||||||
|
Result.StartUniverse = Parser_ReadU32Value(Parser, AssemblyField_SACN_StartUniverse);
|
||||||
|
Result.StartChannel = Parser_ReadU32Value(Parser, AssemblyField_SACN_StartChannel);
|
||||||
|
|
||||||
|
if (!Parser_ReadCloseStruct(Parser))
|
||||||
|
{
|
||||||
|
//TokenizerPushError(&Tokenizer, "Struct doesn't close where expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal strip_uart_addr
|
||||||
|
AssemblyParser_ReadUARTAddr(parser* Parser, assembly Assembly)
|
||||||
|
{
|
||||||
|
strip_uart_addr Result = {0};
|
||||||
|
|
||||||
|
if (Parser_ReadOpenStruct(Parser, AssemblyField_OutputUART))
|
||||||
|
{
|
||||||
|
Result.Channel = (u8)Parser_ReadU32Value(Parser, AssemblyField_UART_Channel);
|
||||||
|
|
||||||
|
bool HasNetPort = Parser_ReadStringValue(Parser, AssemblyField_UART_ComPort, &Result.ComPort, true);
|
||||||
|
if (Assembly.NetPortMode == NetworkPortMode_PortPerStrip && !HasNetPort)
|
||||||
|
{
|
||||||
|
Parser_PushErrorF(Parser, "NetPortMode for assembly is PortPerStrip, but this strip doesn't have an output port.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Parser_ReadCloseStruct(Parser))
|
||||||
|
{
|
||||||
|
Parser_PushErrorF(Parser, "Struct doesn't close where expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
AssemblyParser_ReadTag(parser* Parser, v2_strip* StripAt, u32 TagIndex)
|
||||||
|
{
|
||||||
|
if (Parser_ReadOpenStruct(Parser, AssemblyField_Tag))
|
||||||
|
{
|
||||||
|
// TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface
|
||||||
|
// right now they are stored in temp memory and won't persist
|
||||||
|
gs_string TagName = Parser_ReadStringValue(Parser, AssemblyField_Name);
|
||||||
|
gs_string TagValue = Parser_ReadStringValue(Parser, AssemblyField_Value);
|
||||||
|
StripSetTag(StripAt, TagIndex, TagName.ConstString, TagValue.ConstString);
|
||||||
|
if (!Parser_ReadCloseStruct(Parser))
|
||||||
|
{
|
||||||
|
Parser_PushErrorF(Parser, "Tag struct doesn't close where expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Parser_PushErrorF(Parser, "Expected a tag struct, but none was found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal void
|
||||||
|
AssemblyParser_ReadTagList(parser* Parser, v2_strip* StripAt, assembly* Assembly)
|
||||||
|
{
|
||||||
|
StripAt->TagsCount = Parser_ReadU32Value(Parser, AssemblyField_TagsCount);
|
||||||
|
// NOTE(pjs): Always add one tag to the input to leave room for the assembly name
|
||||||
|
StripAt->TagsCount += 1;
|
||||||
|
StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount);
|
||||||
|
|
||||||
|
StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString);
|
||||||
|
|
||||||
|
for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++)
|
||||||
|
{
|
||||||
|
AssemblyParser_ReadTag(Parser, StripAt, Tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal strip_gen_data AssemblyParser_ReadStripGenData(parser* Parser, assembly* Assembly);
|
||||||
|
|
||||||
|
internal strip_gen_interpolate_points
|
||||||
|
AssemblyParser_ReadInterpolatePoints(parser* Parser)
|
||||||
|
{
|
||||||
|
strip_gen_interpolate_points Result = {0};
|
||||||
|
if (Parser_ReadOpenStruct(Parser, AssemblyField_InterpolatePoints))
|
||||||
|
{
|
||||||
|
Result.StartPosition = Parser_ReadV3Value(Parser, AssemblyField_Start);
|
||||||
|
Result.EndPosition = Parser_ReadV3Value(Parser, AssemblyField_End);
|
||||||
|
Result.LedCount = Parser_ReadU32Value(Parser, AssemblyField_LedCount);
|
||||||
|
if (!Parser_ReadCloseStruct(Parser))
|
||||||
|
{
|
||||||
|
// TODO(pjs):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO(pjs):
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal strip_gen_sequence
|
||||||
|
AssemblyParser_ReadSequence(parser* Parser, assembly* Assembly)
|
||||||
|
{
|
||||||
|
strip_gen_sequence Result = {0};
|
||||||
|
if (Parser_ReadOpenStruct(Parser, AssemblyField_SegmentSequence))
|
||||||
|
{
|
||||||
|
Result.ElementsCount = Parser_ReadU32Value(Parser, AssemblyField_SegmentSequenceLength);
|
||||||
|
Result.Elements = PushArray(&Assembly->Arena, strip_gen_data, Result.ElementsCount);
|
||||||
|
for (u32 i = 0; i < Result.ElementsCount; i++)
|
||||||
|
{
|
||||||
|
Result.Elements[i] = AssemblyParser_ReadStripGenData(Parser, Assembly);
|
||||||
|
}
|
||||||
|
if (!Parser_ReadCloseStruct(Parser))
|
||||||
|
{
|
||||||
|
// TODO(pjs):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO(pjs):
|
||||||
|
}
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal strip_gen_data
|
||||||
|
AssemblyParser_ReadStripGenData(parser* Parser, assembly* Assembly)
|
||||||
|
{
|
||||||
|
strip_gen_data Result = {0};
|
||||||
|
|
||||||
|
if (Parser_ReadOpenStruct(Parser, AssemblyField_Segment))
|
||||||
|
{
|
||||||
|
gs_string PointPlacementType = Parser_ReadStringValue(Parser, AssemblyField_PointPlacementType);
|
||||||
|
|
||||||
|
// TODO(pjs): We want to store enum strings in some unified way
|
||||||
|
// :EnumStringsGen
|
||||||
|
if (StringsEqual(PointPlacementType.ConstString, ConstString("InterpolatePoints")))
|
||||||
|
{
|
||||||
|
Result.Method = StripGeneration_InterpolatePoints;
|
||||||
|
Result.InterpolatePoints = AssemblyParser_ReadInterpolatePoints(Parser);
|
||||||
|
}
|
||||||
|
else if (StringsEqual(PointPlacementType.ConstString,
|
||||||
|
ConstString("SegmentSequence")))
|
||||||
|
{
|
||||||
|
Result.Method = StripGeneration_Sequence;
|
||||||
|
Result.Sequence = AssemblyParser_ReadSequence(Parser, Assembly);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Parser_PushErrorF(Parser, "Incorrect Point Placement Type found for segment");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Parser_ReadCloseStruct(Parser))
|
||||||
|
{
|
||||||
|
Parser_PushErrorF(Parser, "Strip Gen Data did not close the struct where expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
internal bool
|
internal bool
|
||||||
ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileText, gs_memory_arena* Transient)
|
ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileText, gs_memory_arena* Transient)
|
||||||
{
|
{
|
||||||
|
@ -96,19 +270,26 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe
|
||||||
Parser.At = Parser.String.Str;
|
Parser.At = Parser.String.Str;
|
||||||
Parser.LineStart = Parser.At;
|
Parser.LineStart = Parser.At;
|
||||||
Parser.Arena = &Assembly->Arena;
|
Parser.Arena = &Assembly->Arena;
|
||||||
|
Parser.Transient = Transient;
|
||||||
|
|
||||||
Assembly->Name = Parser_ReadStringValue(&Parser, AssemblyField_AssemblyName);
|
Assembly->Name = Parser_ReadStringValue(&Parser, AssemblyField_AssemblyName);
|
||||||
Assembly->Scale = Parser_ReadR32Value(&Parser, AssemblyField_AssemblyScale);
|
Assembly->Scale = Parser_ReadR32Value(&Parser, AssemblyField_AssemblyScale);
|
||||||
Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter);
|
Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter);
|
||||||
Assembly->StripCount = Parser_ReadU32Value(&Parser, AssemblyField_LedStripCount);
|
Assembly->StripCount = Parser_ReadU32Value(&Parser, AssemblyField_LedStripCount);
|
||||||
|
|
||||||
Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount);
|
Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount);
|
||||||
|
|
||||||
gs_string OutputModeString = Parser_ReadStringValue(&Parser, AssemblyField_OutputMode);
|
gs_string OutputModeString = Parser_ReadStringValue(&Parser, AssemblyField_OutputMode);
|
||||||
if (StringsEqual(OutputModeString.ConstString, ConstString("UART")))
|
if (StringsEqual(OutputModeString.ConstString, ConstString("UART")))
|
||||||
{
|
{
|
||||||
Assembly->OutputMode = NetworkProtocol_UART;
|
Assembly->OutputMode = NetworkProtocol_UART;
|
||||||
Assembly->UARTComPort = Parser_ReadStringValue(&Parser, AssemblyField_UART_ComPort, true).ConstString;
|
if (Parser_ReadStringValue(&Parser, AssemblyField_UART_ComPort, &Assembly->UARTComPort, true))
|
||||||
|
{
|
||||||
|
Assembly->NetPortMode = NetworkPortMode_GlobalPort;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Assembly->NetPortMode = NetworkPortMode_PortPerStrip;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN")))
|
else if (StringsEqual(OutputModeString.ConstString, ConstString("SACN")))
|
||||||
{
|
{
|
||||||
|
@ -116,7 +297,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TokenizerPushError(&Tokenizer, "Invalid output mode specified.");
|
Parser_PushErrorF(&Parser, "Invalid output mode specified for assembly.");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (u32 i = 0; i < Assembly->StripCount; i++)
|
for (u32 i = 0; i < Assembly->StripCount; i++)
|
||||||
|
@ -124,83 +305,26 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe
|
||||||
v2_strip* StripAt = Assembly->Strips + i;
|
v2_strip* StripAt = Assembly->Strips + i;
|
||||||
if (Parser_ReadOpenStruct(&Parser, AssemblyField_LedStrip))
|
if (Parser_ReadOpenStruct(&Parser, AssemblyField_LedStrip))
|
||||||
{
|
{
|
||||||
if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputSACN))
|
StripAt->SACNAddr = AssemblyParser_ReadSACNAddr(&Parser, *Assembly);
|
||||||
{
|
StripAt->UARTAddr = AssemblyParser_ReadUARTAddr(&Parser, *Assembly);
|
||||||
StripAt->SACNAddr.StartUniverse = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartUniverse);
|
StripAt->GenerationData = AssemblyParser_ReadStripGenData(&Parser, Assembly);
|
||||||
StripAt->SACNAddr.StartChannel = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartChannel);
|
StripAt->LedCount = StripGenData_CountLeds(StripAt->GenerationData);
|
||||||
|
AssemblyParser_ReadTagList(&Parser, StripAt, Assembly);
|
||||||
|
|
||||||
if (!Parser_ReadCloseStruct(&Parser))
|
|
||||||
{
|
|
||||||
//TokenizerPushError(&Tokenizer, "Struct doesn't close where expected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputUART))
|
|
||||||
{
|
|
||||||
StripAt->UARTAddr.Channel = (u8)Parser_ReadU32Value(&Parser, AssemblyField_UART_Channel);
|
|
||||||
|
|
||||||
if (!Parser_ReadCloseStruct(&Parser))
|
|
||||||
{
|
|
||||||
//TokenizerPushError(&Tokenizer, "Struct doesn't close where expected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(Peter): Need to store this
|
|
||||||
gs_string PointPlacementType = Parser_ReadStringValue(&Parser, AssemblyField_PointPlacementType);
|
|
||||||
// TODO(Peter): Switch on value of PointPlacementType
|
|
||||||
if (Parser_ReadOpenStruct(&Parser, AssemblyField_InterpolatePoints))
|
|
||||||
{
|
|
||||||
StripAt->StartPosition = Parser_ReadV3Value(&Parser, AssemblyField_Start);
|
|
||||||
StripAt->EndPosition = Parser_ReadV3Value(&Parser, AssemblyField_End);
|
|
||||||
if (!Parser_ReadCloseStruct(&Parser))
|
|
||||||
{
|
|
||||||
// TODO(Peter): @ErrorHandling
|
|
||||||
// Have this function prepend the filename and line number.
|
|
||||||
// Create an error display popup window, or an error log window that takes over a panel automatically
|
|
||||||
// TokenizerPushError(&Tokenizer, "Unable to read
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StripAt->LedCount = Parser_ReadU32Value(&Parser, AssemblyField_LedCount);
|
|
||||||
Assembly->LedCountTotal += StripAt->LedCount;
|
Assembly->LedCountTotal += StripAt->LedCount;
|
||||||
|
|
||||||
StripAt->TagsCount = Parser_ReadU32Value(&Parser, AssemblyField_TagsCount);
|
|
||||||
// NOTE(pjs): Always add one tag to the input to leave room for the assembly name
|
|
||||||
StripAt->TagsCount += 1;
|
|
||||||
StripAt->Tags = PushArray(&Assembly->Arena, v2_tag, StripAt->TagsCount);
|
|
||||||
StripSetTag(StripAt, 0, ConstString("assembly"), Assembly->Name.ConstString);
|
|
||||||
for (u32 Tag = 1; Tag < StripAt->TagsCount; Tag++)
|
|
||||||
{
|
|
||||||
if (Parser_ReadOpenStruct(&Parser, AssemblyField_Tag))
|
|
||||||
{
|
|
||||||
// TODO(Peter): Need to store the gs_string somewhere we can look it up for display in the interface
|
|
||||||
// right now they are stored in temp memory and won't persist
|
|
||||||
gs_string TagName = Parser_ReadStringValue(&Parser, AssemblyField_Name);
|
|
||||||
gs_string TagValue = Parser_ReadStringValue(&Parser, AssemblyField_Value);
|
|
||||||
StripSetTag(StripAt, Tag, TagName.ConstString, TagValue.ConstString);
|
|
||||||
if (!Parser_ReadCloseStruct(&Parser))
|
|
||||||
{
|
|
||||||
//TokenizerPushError(&Tokenizer, "Struct doesn't close where expected");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!Parser_ReadCloseStruct(&Parser))
|
if (!Parser_ReadCloseStruct(&Parser))
|
||||||
{
|
{
|
||||||
//TokenizerPushError(&Tokenizer, "Struct doesn't close where expected");
|
Parser_PushErrorF(&Parser, "Strip struct doesn't close where expected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found");
|
Parser_PushErrorF(&Parser, "Expected a strip struct but none was found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(pjs): invalidate the file if its incorrect
|
||||||
return true; //Tokenizer.ParsingIsValid;
|
return true; //Tokenizer.ParsingIsValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
//
|
|
||||||
// File: foldhaus_parser.h
|
|
||||||
// Author: Peter Slattery
|
|
||||||
// Creation Date: 2020-10-09
|
|
||||||
//
|
|
||||||
#ifndef FOLDHAUS_PARSER_H
|
|
||||||
|
|
||||||
struct parser
|
|
||||||
{
|
|
||||||
gs_string String;
|
|
||||||
gs_const_string* Identifiers;
|
|
||||||
u32 IdentifiersCount;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define FOLDHAUS_PARSER_H
|
|
||||||
#endif // FOLDHAUS_PARSER_H
|
|
|
@ -134,11 +134,17 @@ Serializer_WriteV3Value(serializer* Serializer, u32 IdentIndex, v3 Value)
|
||||||
struct parser_error
|
struct parser_error
|
||||||
{
|
{
|
||||||
gs_string Message;
|
gs_string Message;
|
||||||
|
|
||||||
|
gs_string FileName;
|
||||||
|
u32 LineNumber;
|
||||||
|
|
||||||
parser_error* Next;
|
parser_error* Next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct parser
|
struct parser
|
||||||
{
|
{
|
||||||
|
gs_string FileName;
|
||||||
|
|
||||||
gs_string String;
|
gs_string String;
|
||||||
|
|
||||||
gs_const_string* Identifiers;
|
gs_const_string* Identifiers;
|
||||||
|
@ -160,7 +166,11 @@ internal void
|
||||||
Parser_PushErrorF(parser* Parser, char* Format, ...)
|
Parser_PushErrorF(parser* Parser, char* Format, ...)
|
||||||
{
|
{
|
||||||
parser_error* Error = PushStruct(Parser->Transient, parser_error);
|
parser_error* Error = PushStruct(Parser->Transient, parser_error);
|
||||||
|
Error->FileName = Parser->FileName;
|
||||||
|
Error->LineNumber = Parser->Line;
|
||||||
|
|
||||||
Error->Message = PushString(Parser->Transient, 1024);
|
Error->Message = PushString(Parser->Transient, 1024);
|
||||||
|
PrintF(&Error->Message, "File: %S Line: %d - ", Error->FileName, Error->LineNumber);
|
||||||
|
|
||||||
va_list Args;
|
va_list Args;
|
||||||
va_start(Args, Format);
|
va_start(Args, Format);
|
||||||
|
@ -268,11 +278,13 @@ Parser_ReadString(parser* P, u32 IdentIndex)
|
||||||
return Parser_ReadString(P, Ident);
|
return Parser_ReadString(P, Ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal gs_string
|
internal bool
|
||||||
Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false)
|
Parser_ReadStringValue(parser* P, gs_const_string Ident, gs_string* Output, bool ShouldNullTerminate = false)
|
||||||
{
|
{
|
||||||
|
Assert(Output != 0);
|
||||||
|
|
||||||
// ident: "value";
|
// ident: "value";
|
||||||
gs_string Result = {};
|
bool Result = false;
|
||||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")) &&
|
Parser_AdvanceIfTokenEquals(P, ConstString(":")) &&
|
||||||
Parser_AdvanceIfTokenEquals(P, ConstString("\"")))
|
Parser_AdvanceIfTokenEquals(P, ConstString("\"")))
|
||||||
|
@ -294,10 +306,12 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat
|
||||||
{
|
{
|
||||||
StringLength += 1;
|
StringLength += 1;
|
||||||
}
|
}
|
||||||
Result = PushStringF(P->Arena, StringLength, "%S", FileString);
|
|
||||||
|
Result = true;
|
||||||
|
*Output = PushStringF(P->Arena, StringLength, "%S", FileString);
|
||||||
if (ShouldNullTerminate)
|
if (ShouldNullTerminate)
|
||||||
{
|
{
|
||||||
NullTerminate(&Result);
|
NullTerminate(Output);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -305,14 +319,25 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat
|
||||||
Parser_PushErrorF(P, "String doesn't have a closing quote, or line doesn't end with a semicolon");
|
Parser_PushErrorF(P, "String doesn't have a closing quote, or line doesn't end with a semicolon");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Parser_PushErrorF(P, "String doesn't begin correctly");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
Parser_ReadStringValue(parser* P, u32 IdentIndex, gs_string* Result, bool ShouldNullTerminate = false)
|
||||||
|
{
|
||||||
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||||
|
return Parser_ReadStringValue(P, Ident, Result, ShouldNullTerminate);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal gs_string
|
||||||
|
Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false)
|
||||||
|
{
|
||||||
|
gs_string Result = {0};
|
||||||
|
Parser_ReadStringValue(P, Ident, &Result, ShouldNullTerminate);
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
internal gs_string
|
internal gs_string
|
||||||
Parser_ReadStringValue(parser* P, u32 IdentIndex, bool ShouldNullTerminate = false)
|
Parser_ReadStringValue(parser* P, u32 IdentIndex, bool ShouldNullTerminate = false)
|
||||||
{
|
{
|
||||||
|
@ -346,42 +371,66 @@ Parser_ReadCloseStruct(parser* P)
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
Parser_ReadNumberString(parser* P, gs_const_string* Output)
|
||||||
|
{
|
||||||
|
Assert(Output != 0);
|
||||||
|
|
||||||
|
bool Success = false;
|
||||||
|
|
||||||
|
if (IsNumericExtended(P->At[0]))
|
||||||
|
{
|
||||||
|
char* NumStart = P->At;
|
||||||
|
while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0]))
|
||||||
|
{
|
||||||
|
Parser_AdvanceChar(P);
|
||||||
|
}
|
||||||
|
|
||||||
|
Output->Str = NumStart;
|
||||||
|
Output->Length = P->At - NumStart;
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
internal gs_const_string
|
internal gs_const_string
|
||||||
Parser_ReadNumberString(parser* P)
|
Parser_ReadNumberString(parser* P)
|
||||||
{
|
{
|
||||||
gs_const_string Result = {};
|
gs_const_string Result = {0};
|
||||||
Result.Str = P->At;
|
Parser_ReadNumberString(P, &Result);
|
||||||
while(Parser_AtValidPosition(*P) && IsNumericExtended(P->At[0]))
|
|
||||||
{
|
|
||||||
Parser_AdvanceChar(P);
|
|
||||||
}
|
|
||||||
Result.Length = P->At - Result.Str;
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal u32
|
internal bool
|
||||||
Parser_ReadU32Value(parser* P, gs_const_string Ident)
|
Parser_ReadU32Value(parser* P, gs_const_string Ident, u32* Result)
|
||||||
{
|
{
|
||||||
// ident: value;
|
// ident: value;
|
||||||
u32 Result = 0;
|
bool Success = false;
|
||||||
|
|
||||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||||||
{
|
{
|
||||||
gs_const_string NumStr = Parser_ReadNumberString(P);
|
gs_const_string NumStr = Parser_ReadNumberString(P);
|
||||||
if (Parser_AdvanceIfLineEnd(P))
|
if (Parser_AdvanceIfLineEnd(P))
|
||||||
{
|
{
|
||||||
Result = (u32)ParseInt(NumStr);
|
*Result = (u32)ParseInt(NumStr);
|
||||||
|
Success = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Parser_PushErrorF(P, "U32 Value doesn't end with semicolon");
|
Parser_PushErrorF(P, "U32 Value doesn't end with semicolon");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Parser_PushErrorF(P, "U32 value doesn't begin properly");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal u32
|
||||||
|
Parser_ReadU32Value(parser* P, gs_const_string Ident)
|
||||||
|
{
|
||||||
|
u32 Result = 0;
|
||||||
|
Parser_ReadU32Value(P, Ident, &Result);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,52 +441,72 @@ Parser_ReadU32Value(parser* P, u32 IdentIndex)
|
||||||
return Parser_ReadU32Value(P, Ident);
|
return Parser_ReadU32Value(P, Ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal bool
|
||||||
|
Parser_ReadR32(parser* P, r32* Result)
|
||||||
|
{
|
||||||
|
bool Success = false;
|
||||||
|
gs_const_string NumStr = {0};
|
||||||
|
if (Parser_ReadNumberString(P, &NumStr))
|
||||||
|
{
|
||||||
|
*Result = (r32)ParseFloat(NumStr);
|
||||||
|
Success = true;
|
||||||
|
}
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
internal r32
|
internal r32
|
||||||
Parser_ReadR32(parser* P)
|
Parser_ReadR32(parser* P)
|
||||||
{
|
{
|
||||||
r32 Result = 0;
|
r32 Result = 0;
|
||||||
gs_const_string NumStr = Parser_ReadNumberString(P);
|
Parser_ReadR32(P, &Result);
|
||||||
Result = (r32)ParseFloat(NumStr);
|
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal r32
|
internal bool
|
||||||
Parser_ReadR32Value(parser* P, gs_const_string Ident)
|
Parser_ReadR32Value(parser* P, gs_const_string Ident, r32* Result)
|
||||||
{
|
{
|
||||||
// ident: value;
|
// ident: value;
|
||||||
r32 Result = 0;
|
bool Success = false;
|
||||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||||||
{
|
{
|
||||||
r32 Value = Parser_ReadR32(P);
|
r32 Value = Parser_ReadR32(P);
|
||||||
if (Parser_AdvanceIfLineEnd(P))
|
if (Parser_AdvanceIfLineEnd(P))
|
||||||
{
|
{
|
||||||
Result = Value;
|
*Result = Value;
|
||||||
|
Success = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Parser_PushErrorF(P, "R32 Value doesn't end with semicolon");
|
Parser_PushErrorF(P, "R32 Value doesn't end with semicolon");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Parser_PushErrorF(P, "R32 value doesn't begin properly");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal r32
|
||||||
|
Parser_ReadR32Value(parser* P, gs_const_string Ident)
|
||||||
|
{
|
||||||
|
r32 Result = 0;
|
||||||
|
Parser_ReadR32Value(P, Ident, &Result);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal u32
|
internal r32
|
||||||
Parser_ReadR32Value(parser* P, u32 IdentIndex)
|
Parser_ReadR32Value(parser* P, u32 IdentIndex)
|
||||||
{
|
{
|
||||||
|
r32 Result = 0;
|
||||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||||
return Parser_ReadR32Value(P, Ident);
|
Parser_ReadR32Value(P, Ident, &Result);
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal v3
|
internal bool
|
||||||
Parser_ReadV3Value(parser* P, gs_const_string Ident)
|
Parser_ReadV3Value(parser* P, gs_const_string Ident, v3* Result)
|
||||||
{
|
{
|
||||||
v3 Result = {0};
|
Assert(Result != 0);
|
||||||
|
bool Success = false;
|
||||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")) &&
|
Parser_AdvanceIfTokenEquals(P, ConstString(":")) &&
|
||||||
Parser_AdvanceIfTokenEquals(P, ConstString("(")))
|
Parser_AdvanceIfTokenEquals(P, ConstString("(")))
|
||||||
|
@ -458,27 +527,35 @@ Parser_ReadV3Value(parser* P, gs_const_string Ident)
|
||||||
if (Parser_AdvanceIfTokenEquals(P, ConstString(")")) &&
|
if (Parser_AdvanceIfTokenEquals(P, ConstString(")")) &&
|
||||||
Parser_AdvanceIfLineEnd(P))
|
Parser_AdvanceIfLineEnd(P))
|
||||||
{
|
{
|
||||||
Result.x = X;
|
Result->x = X;
|
||||||
Result.y = Y;
|
Result->y = Y;
|
||||||
Result.z = Z;
|
Result->z = Z;
|
||||||
|
Success = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Parser_PushErrorF(P, "V3 Value doesn't end correctly");
|
Parser_PushErrorF(P, "V3 Value doesn't end correctly");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return Success;
|
||||||
Parser_PushErrorF(P, "V3 Value doesn't begin correctly");
|
}
|
||||||
}
|
|
||||||
|
internal v3
|
||||||
|
Parser_ReadV3Value(parser* P, gs_const_string Ident)
|
||||||
|
{
|
||||||
|
v3 Result = {0};
|
||||||
|
Parser_ReadV3Value(P, Ident, &Result);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal v3
|
internal v3
|
||||||
Parser_ReadV3Value(parser* P, u32 IdentIndex)
|
Parser_ReadV3Value(parser* P, u32 IdentIndex)
|
||||||
{
|
{
|
||||||
|
v3 Result = {0};
|
||||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||||
return Parser_ReadV3Value(P, Ident);
|
Parser_ReadV3Value(P, Ident, &Result);
|
||||||
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ UART_BuildOutputData(addressed_data_buffer_list* Output, assembly_array Assembli
|
||||||
TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel
|
TotalBufferSize += ChannelSettings.ElementsCount * Assembly.LedCountTotal; // pixels * channels per pixel
|
||||||
|
|
||||||
addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize);
|
addressed_data_buffer* Buffer = AddressedDataBufferList_Push(Output, TotalBufferSize);
|
||||||
AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort);
|
AddressedDataBuffer_SetCOMPort(Buffer, Assembly.UARTComPort.ConstString);
|
||||||
gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data);
|
gs_memory_cursor WriteCursor = CreateMemoryCursor(Buffer->Data);
|
||||||
|
|
||||||
for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++)
|
for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++)
|
||||||
|
|
|
@ -123,7 +123,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
||||||
State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128);
|
State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128);
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
gs_const_string SculpturePath = ConstString("data/blumen_lumen_v2.fold");
|
gs_const_string SculpturePath = ConstString("data/blumen_lumen_silver_spring.fold");
|
||||||
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog);
|
LoadAssembly(&State->Assemblies, &State->LedSystem, State->Transient, Context, SculpturePath, State->GlobalLog);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -389,14 +389,21 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_
|
||||||
|
|
||||||
case AddressType_ComPort:
|
case AddressType_ComPort:
|
||||||
{
|
{
|
||||||
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1);
|
if (BufferAt->ComPort.Length > 0)
|
||||||
if (SerialPort != INVALID_HANDLE_VALUE)
|
|
||||||
{
|
{
|
||||||
if (Win32SerialPort_Write(SerialPort, BufferAt->Data))
|
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1);
|
||||||
|
if (SerialPort != INVALID_HANDLE_VALUE)
|
||||||
{
|
{
|
||||||
BuffersSent += 1;
|
if (Win32SerialPort_Write(SerialPort, BufferAt->Data))
|
||||||
|
{
|
||||||
|
BuffersSent += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OutputDebugStringA("Skipping data buffer because its COM Port isn't set");
|
||||||
|
}
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
InvalidDefaultCase;
|
InvalidDefaultCase;
|
||||||
|
|
Loading…
Reference in New Issue