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;
|
||||
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++)
|
||||
{
|
||||
|
|
|
@ -135,6 +135,46 @@ LedBufferSetLed(led_buffer* Buffer, u32 Led, v4 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
|
||||
ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem)
|
||||
{
|
||||
|
@ -150,17 +190,8 @@ ConstructAssemblyFromDefinition (assembly* Assembly, led_system* LedSystem)
|
|||
v2_strip* StripAt = &Assembly->Strips[StripIdx];
|
||||
StripAt->LedLUT = PushArray(&Assembly->Arena, u32, StripAt->LedCount);
|
||||
|
||||
v4 WS_StripStart = RootPosition + ToV4Point(StripAt->StartPosition * Assembly->Scale);
|
||||
v4 WS_StripEnd = RootPosition + ToV4Point(StripAt->EndPosition * Assembly->Scale);
|
||||
|
||||
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;
|
||||
}
|
||||
strip_gen_data GenData = StripAt->GenerationData;
|
||||
LedsAdded += Assembly_ConstructStrip(Assembly, LedBuffer, StripAt, GenData, RootPosition, LedsAdded);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,41 @@ struct strip_sacn_addr
|
|||
struct strip_uart_addr
|
||||
{
|
||||
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
|
||||
|
@ -67,10 +102,7 @@ struct v2_strip
|
|||
strip_sacn_addr SACNAddr;
|
||||
strip_uart_addr UARTAddr;
|
||||
|
||||
// TODO(Peter): When we create more ways to calculate points, this needs to become
|
||||
// a type enum and a union
|
||||
v3 StartPosition;
|
||||
v3 EndPosition;
|
||||
strip_gen_data GenerationData;
|
||||
|
||||
u32 LedCount;
|
||||
u32* LedLUT;
|
||||
|
@ -86,6 +118,21 @@ struct led_strip_list
|
|||
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
|
||||
{
|
||||
gs_memory_arena Arena;
|
||||
|
@ -102,7 +149,8 @@ struct assembly
|
|||
v2_strip* Strips;
|
||||
|
||||
network_protocol OutputMode;
|
||||
gs_const_string UARTComPort;
|
||||
network_port_mode NetPortMode;
|
||||
gs_string UARTComPort;
|
||||
};
|
||||
|
||||
struct assembly_array
|
||||
|
@ -120,6 +168,31 @@ LedSystemGetBuffer(led_system* System, u32 Index)
|
|||
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
|
||||
#endif // FOLDHAUS_ASSEMBLY_H
|
|
@ -33,10 +33,16 @@ enum assembly_field
|
|||
AssemblyField_UART_ComPort,
|
||||
|
||||
AssemblyField_PointPlacementType,
|
||||
|
||||
AssemblyField_InterpolatePoints,
|
||||
AssemblyField_Start,
|
||||
AssemblyField_End,
|
||||
AssemblyField_LedCount,
|
||||
|
||||
AssemblyField_SegmentSequence,
|
||||
AssemblyField_SegmentSequenceLength,
|
||||
AssemblyField_Segment,
|
||||
|
||||
AssemblyField_TagsCount,
|
||||
AssemblyField_Tag,
|
||||
AssemblyField_Name,
|
||||
|
@ -63,12 +69,16 @@ global gs_const_string AssemblyFieldIdentifiers[] = {
|
|||
ConstString("com_port"), // AssemblyField_UART_ComPort
|
||||
|
||||
ConstString("point_placement_type"), // AssemblyField_PointPlacementType
|
||||
|
||||
ConstString("interpolate_points"), // AssemblyField_InterpolatePoints
|
||||
ConstString("start"), // AssemblyField_Start
|
||||
ConstString("end"), // AssemblyField_End
|
||||
|
||||
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("tag"), // AssemblyField_Tag
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
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.LineStart = Parser.At;
|
||||
Parser.Arena = &Assembly->Arena;
|
||||
Parser.Transient = Transient;
|
||||
|
||||
Assembly->Name = Parser_ReadStringValue(&Parser, AssemblyField_AssemblyName);
|
||||
Assembly->Scale = Parser_ReadR32Value(&Parser, AssemblyField_AssemblyScale);
|
||||
Assembly->Center = Parser_ReadV3Value(&Parser, AssemblyField_AssemblyCenter);
|
||||
Assembly->StripCount = Parser_ReadU32Value(&Parser, AssemblyField_LedStripCount);
|
||||
|
||||
Assembly->Strips = PushArray(&Assembly->Arena, v2_strip, Assembly->StripCount);
|
||||
|
||||
gs_string OutputModeString = Parser_ReadStringValue(&Parser, AssemblyField_OutputMode);
|
||||
if (StringsEqual(OutputModeString.ConstString, ConstString("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")))
|
||||
{
|
||||
|
@ -116,7 +297,7 @@ ParseAssemblyFile(assembly* Assembly, gs_const_string FileName, gs_string FileTe
|
|||
}
|
||||
else
|
||||
{
|
||||
//TokenizerPushError(&Tokenizer, "Invalid output mode specified.");
|
||||
Parser_PushErrorF(&Parser, "Invalid output mode specified for assembly.");
|
||||
}
|
||||
|
||||
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;
|
||||
if (Parser_ReadOpenStruct(&Parser, AssemblyField_LedStrip))
|
||||
{
|
||||
if (Parser_ReadOpenStruct(&Parser, AssemblyField_OutputSACN))
|
||||
{
|
||||
StripAt->SACNAddr.StartUniverse = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartUniverse);
|
||||
StripAt->SACNAddr.StartChannel = Parser_ReadU32Value(&Parser, AssemblyField_SACN_StartChannel);
|
||||
StripAt->SACNAddr = AssemblyParser_ReadSACNAddr(&Parser, *Assembly);
|
||||
StripAt->UARTAddr = AssemblyParser_ReadUARTAddr(&Parser, *Assembly);
|
||||
StripAt->GenerationData = AssemblyParser_ReadStripGenData(&Parser, Assembly);
|
||||
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;
|
||||
|
||||
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");
|
||||
Parser_PushErrorF(&Parser, "Strip struct doesn't close where expected");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//TokenizerPushError(&Tokenizer, "Expected a struct opening, but none was found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!Parser_ReadCloseStruct(&Parser))
|
||||
{
|
||||
//TokenizerPushError(&Tokenizer, "Struct doesn't close where expected");
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
gs_string Message;
|
||||
|
||||
gs_string FileName;
|
||||
u32 LineNumber;
|
||||
|
||||
parser_error* Next;
|
||||
};
|
||||
|
||||
struct parser
|
||||
{
|
||||
gs_string FileName;
|
||||
|
||||
gs_string String;
|
||||
|
||||
gs_const_string* Identifiers;
|
||||
|
@ -160,7 +166,11 @@ internal void
|
|||
Parser_PushErrorF(parser* Parser, char* Format, ...)
|
||||
{
|
||||
parser_error* Error = PushStruct(Parser->Transient, parser_error);
|
||||
Error->FileName = Parser->FileName;
|
||||
Error->LineNumber = Parser->Line;
|
||||
|
||||
Error->Message = PushString(Parser->Transient, 1024);
|
||||
PrintF(&Error->Message, "File: %S Line: %d - ", Error->FileName, Error->LineNumber);
|
||||
|
||||
va_list Args;
|
||||
va_start(Args, Format);
|
||||
|
@ -268,11 +278,13 @@ Parser_ReadString(parser* P, u32 IdentIndex)
|
|||
return Parser_ReadString(P, Ident);
|
||||
}
|
||||
|
||||
internal gs_string
|
||||
Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminate = false)
|
||||
internal bool
|
||||
Parser_ReadStringValue(parser* P, gs_const_string Ident, gs_string* Output, bool ShouldNullTerminate = false)
|
||||
{
|
||||
Assert(Output != 0);
|
||||
|
||||
// ident: "value";
|
||||
gs_string Result = {};
|
||||
bool Result = false;
|
||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString("\"")))
|
||||
|
@ -294,10 +306,12 @@ Parser_ReadStringValue(parser* P, gs_const_string Ident, bool ShouldNullTerminat
|
|||
{
|
||||
StringLength += 1;
|
||||
}
|
||||
Result = PushStringF(P->Arena, StringLength, "%S", FileString);
|
||||
|
||||
Result = true;
|
||||
*Output = PushStringF(P->Arena, StringLength, "%S", FileString);
|
||||
if (ShouldNullTerminate)
|
||||
{
|
||||
NullTerminate(&Result);
|
||||
NullTerminate(Output);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -305,11 +319,22 @@ 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");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parser_PushErrorF(P, "String doesn't begin correctly");
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -346,42 +371,66 @@ Parser_ReadCloseStruct(parser* P)
|
|||
return Result;
|
||||
}
|
||||
|
||||
internal gs_const_string
|
||||
Parser_ReadNumberString(parser* P)
|
||||
internal bool
|
||||
Parser_ReadNumberString(parser* P, gs_const_string* Output)
|
||||
{
|
||||
gs_const_string Result = {};
|
||||
Result.Str = P->At;
|
||||
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);
|
||||
}
|
||||
Result.Length = P->At - Result.Str;
|
||||
|
||||
Output->Str = NumStart;
|
||||
Output->Length = P->At - NumStart;
|
||||
Success = true;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
internal gs_const_string
|
||||
Parser_ReadNumberString(parser* P)
|
||||
{
|
||||
gs_const_string Result = {0};
|
||||
Parser_ReadNumberString(P, &Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal u32
|
||||
Parser_ReadU32Value(parser* P, gs_const_string Ident)
|
||||
internal bool
|
||||
Parser_ReadU32Value(parser* P, gs_const_string Ident, u32* Result)
|
||||
{
|
||||
// ident: value;
|
||||
u32 Result = 0;
|
||||
bool Success = false;
|
||||
|
||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||||
{
|
||||
gs_const_string NumStr = Parser_ReadNumberString(P);
|
||||
if (Parser_AdvanceIfLineEnd(P))
|
||||
{
|
||||
Result = (u32)ParseInt(NumStr);
|
||||
*Result = (u32)ParseInt(NumStr);
|
||||
Success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -392,52 +441,72 @@ Parser_ReadU32Value(parser* P, u32 IdentIndex)
|
|||
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
|
||||
Parser_ReadR32(parser* P)
|
||||
{
|
||||
r32 Result = 0;
|
||||
gs_const_string NumStr = Parser_ReadNumberString(P);
|
||||
Result = (r32)ParseFloat(NumStr);
|
||||
Parser_ReadR32(P, &Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal r32
|
||||
Parser_ReadR32Value(parser* P, gs_const_string Ident)
|
||||
internal bool
|
||||
Parser_ReadR32Value(parser* P, gs_const_string Ident, r32* Result)
|
||||
{
|
||||
// ident: value;
|
||||
r32 Result = 0;
|
||||
bool Success = false;
|
||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||
Parser_AdvanceIfTokenEquals(P, ConstString(":")))
|
||||
{
|
||||
r32 Value = Parser_ReadR32(P);
|
||||
if (Parser_AdvanceIfLineEnd(P))
|
||||
{
|
||||
Result = Value;
|
||||
*Result = Value;
|
||||
Success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
internal u32
|
||||
internal r32
|
||||
Parser_ReadR32Value(parser* P, u32 IdentIndex)
|
||||
{
|
||||
r32 Result = 0;
|
||||
gs_const_string Ident = Parser_GetIdent(*P, IdentIndex);
|
||||
return Parser_ReadR32Value(P, Ident);
|
||||
Parser_ReadR32Value(P, Ident, &Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal v3
|
||||
Parser_ReadV3Value(parser* P, gs_const_string Ident)
|
||||
internal bool
|
||||
Parser_ReadV3Value(parser* P, gs_const_string Ident, v3* Result)
|
||||
{
|
||||
v3 Result = {0};
|
||||
Assert(Result != 0);
|
||||
bool Success = false;
|
||||
if (Parser_AdvanceIfTokenEquals(P, Ident) &&
|
||||
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(")")) &&
|
||||
Parser_AdvanceIfLineEnd(P))
|
||||
{
|
||||
Result.x = X;
|
||||
Result.y = Y;
|
||||
Result.z = Z;
|
||||
Result->x = X;
|
||||
Result->y = Y;
|
||||
Result->z = Z;
|
||||
Success = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Parser_PushErrorF(P, "V3 Value doesn't end correctly");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Parser_PushErrorF(P, "V3 Value doesn't begin correctly");
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
internal v3
|
||||
Parser_ReadV3Value(parser* P, gs_const_string Ident)
|
||||
{
|
||||
v3 Result = {0};
|
||||
Parser_ReadV3Value(P, Ident, &Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
internal v3
|
||||
Parser_ReadV3Value(parser* P, u32 IdentIndex)
|
||||
{
|
||||
v3 Result = {0};
|
||||
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
|
||||
|
||||
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);
|
||||
|
||||
for (u32 StripIdx = 0; StripIdx < Assembly.StripCount; StripIdx++)
|
||||
|
|
|
@ -123,7 +123,7 @@ INITIALIZE_APPLICATION(InitializeApplication)
|
|||
State->LedSystem = LedSystemInitialize(Context.ThreadContext.Allocator, 128);
|
||||
|
||||
#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);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -388,6 +388,8 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_
|
|||
}break;
|
||||
|
||||
case AddressType_ComPort:
|
||||
{
|
||||
if (BufferAt->ComPort.Length > 0)
|
||||
{
|
||||
HANDLE SerialPort = Win32SerialArray_GetOrOpen(BufferAt->ComPort, 2000000, 8, NOPARITY, 1);
|
||||
if (SerialPort != INVALID_HANDLE_VALUE)
|
||||
|
@ -397,6 +399,11 @@ Win32_SendAddressedDataBuffers(gs_thread_context Context, addressed_data_buffer_
|
|||
BuffersSent += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputDebugStringA("Skipping data buffer because its COM Port isn't set");
|
||||
}
|
||||
}break;
|
||||
|
||||
InvalidDefaultCase;
|
||||
|
|
Loading…
Reference in New Issue