Lumenarium/src/app/ss_blumen_lumen/blumen_lumen.cpp

545 lines
21 KiB
C++
Raw Normal View History

//
// File: blumen_lumen.cpp
// Author: Peter Slattery
// Creation Date: 2021-01-23
//
#ifndef BLUMEN_LUMEN_CPP
internal s32
GetCCIndex (assembly Assembly, blumen_lumen_state* BLState)
{
s32 Result = 0;
u64 AssemblyNameHash = HashDJB2ToU32(StringExpand(Assembly.Name));
for (u32 i = 0; i < BLState->AssemblyNameToClearCoreMapCount; i++)
{
if (AssemblyNameHash == BLState->AssemblyNameToClearCore_Names[i])
{
Result = (s32)i;
break;
}
}
return Result;
}
internal void
DEBUG_AppendText(gs_string Str, gs_thread_context Ctx)
2021-03-20 22:15:35 +00:00
{
gs_const_string DebugPath = ConstString("data/debug_motor_changes.txt");
gs_file DebugFile = ReadEntireFile(Ctx.FileHandler,
DebugPath);
gs_string NewString = PushString(Ctx.Transient, DebugFile.Size + Str.Size + 16);
if (DebugFile.Size > 0)
{
PrintF(&NewString, "%.*s\nENTRY:\n", DebugFile.Size, (char*)DebugFile.Memory);
}
AppendPrintF(&NewString, "%S\n", Str.ConstString);
NullTerminate(&NewString);
if (!WriteEntireFile(Ctx.FileHandler, DebugPath, StringToData(NewString)))
{
InvalidCodePath;
}
2021-03-20 22:15:35 +00:00
}
internal void
DEBUG_SentMotorCommand(motor_packet Packet, gs_thread_context Ctx)
2021-03-20 22:15:35 +00:00
{
gs_string Str = PushStringF(Ctx.Transient, 256, "Motor Command Sent\nRequested Positions: %d %d %d\n",
Packet.FlowerPositions[0],
Packet.FlowerPositions[1],
Packet.FlowerPositions[2]);
DEBUG_AppendText(Str, Ctx);
NullTerminate(&Str);
OutputDebugStringA(Str.Str);
}
internal void
DEBUG_ReceivedMotorPositions(motor_packet NewPos,
motor_packet LastPos,
gs_thread_context Ctx)
{
bool PosChanged = (LastPos.FlowerPositions[0] != NewPos.FlowerPositions[0] ||
LastPos.FlowerPositions[1] != NewPos.FlowerPositions[1] ||
LastPos.FlowerPositions[2] != NewPos.FlowerPositions[2]);
if (PosChanged)
{
gs_string Str = PushStringF(Ctx.Transient, 256, "Motor Status Received\nCurrent Positions: %d %d %d\n",
NewPos.FlowerPositions[0],
NewPos.FlowerPositions[1],
NewPos.FlowerPositions[2]);
DEBUG_AppendText(Str, Ctx);
NullTerminate(&Str);
OutputDebugStringA(Str.Str);
}
2021-03-20 22:15:35 +00:00
}
internal void
2021-03-27 23:07:31 +00:00
DEBUG_ReceivedTemperature(temp_packet Temp, gs_thread_context Ctx)
2021-03-20 22:15:35 +00:00
{
2021-03-27 23:07:31 +00:00
gs_string TempStr = PushStringF(Ctx.Transient, 256,
"\nTemperature: %d\n",
Temp.Temperature);
NullTerminate(&TempStr);
OutputDebugStringA(TempStr.Str);
}
internal void
BlumenLumen_MicListenJob(gs_thread_context* Ctx, u8* UserData)
{
mic_listen_job_data* Data = (mic_listen_job_data*)UserData;
gs_data Msg = {};
2021-01-31 03:33:44 +00:00
u8 WeathermanIPAddr[4] = {};
WeathermanIPAddr[0] = 127;
WeathermanIPAddr[1] = 0;
WeathermanIPAddr[2] = 0;
WeathermanIPAddr[3] = 1;
u32 WeathermanIPV4 = (u32)UpackB4(WeathermanIPAddr);
u32 WeathermanPort = 20185;
platform_socket_handle_ ListenSocket = {0};
while (*Data->Running)
{
if (!SocketQueryStatus(Data->SocketManager, ListenSocket))
{
if (SocketHandleIsValid(ListenSocket))
{
OutputDebugStringA("Disconnected from Python Server\n");
CloseSocket(Data->SocketManager, ListenSocket);
}
ListenSocket = CreateSocket(Data->SocketManager, "127.0.0.1", "20185");
if (ListenSocket.Index != 0)
{
OutputDebugStringA("Connected to Python Server\n");
}
}
if (SocketQueryStatus(Data->SocketManager, ListenSocket))
{
if (SocketPeek(Data->SocketManager, ListenSocket))
{
// TODO(pjs): Make this a peek operation
Msg = SocketRecieve(Data->SocketManager, ListenSocket, Ctx->Transient);
if (Msg.Size > 0)
{
2021-03-20 22:15:35 +00:00
MessageQueue_Write(Data->IncomingMsgQueue, Msg);
}
}
while (MessageQueue_CanRead(*Data->OutgoingMsgQueue))
{
2021-03-20 22:15:35 +00:00
Msg = MessageQueue_Read(Data->OutgoingMsgQueue);
u32 Address = WeathermanIPV4;
u32 Port = WeathermanPort;
s32 Flags = 0;
SocketSend(Data->SocketManager, ListenSocket, Address, Port, Msg, Flags);
}
}
MessageQueue_Clear(Data->OutgoingMsgQueue);
}
CloseSocket(Data->SocketManager, ListenSocket);
}
2021-01-23 23:58:05 +00:00
internal void
BlumenLumen_LoadPatterns(app_state* State)
{
animation_pattern_array* Patterns = &State->Patterns;
if (Patterns->CountMax == 0)
{
*Patterns = Patterns_Create(&State->Permanent, 32);
}
Patterns->Count = 0;
Patterns_PushPattern(Patterns, TestPatternOne, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, TestPatternTwo, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, TestPatternThree, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_AllGreen, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_HueShift, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_HueFade, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Spots, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_LighthouseRainbow, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_SmoothGrowRainbow, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_GrowAndFade, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_ColorToWhite, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Blue, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Green, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_FlowerColors, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_FlowerColorToWhite, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_BasicFlowers, PATTERN_MULTITHREADED);
2021-03-20 22:15:35 +00:00
// 15
Patterns_PushPattern(Patterns, Pattern_Wavy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Patchy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_Leafy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_LeafyPatchy, PATTERN_MULTITHREADED);
Patterns_PushPattern(Patterns, Pattern_WavyPatchy, PATTERN_SINGLETHREADED);
2021-01-31 03:33:44 +00:00
}
internal gs_data
BlumenLumen_CustomInit(app_state* State, context Context)
{
// This is memory for any custom data that we want to use
// as a part of a particular sculpture.
// By returning it from here, it will be sent as an argument to
// the sculpture's CustomUpdate function;
gs_data Result = {};
2021-01-24 01:38:19 +00:00
Result = PushSizeToData(&State->Permanent, sizeof(blumen_lumen_state));
blumen_lumen_state* BLState = (blumen_lumen_state*)Result.Memory;
BLState->Running = true;
2021-03-20 22:15:35 +00:00
BLState->BrightnessPercent = 1;
MessageQueue_Init(&BLState->IncomingMsgQueue, &State->Permanent);
MessageQueue_Init(&BLState->OutgoingMsgQueue, &State->Permanent);
BLState->MicListenJobData.Running = &BLState->Running;
BLState->MicListenJobData.SocketManager = Context.SocketManager;
2021-03-20 22:15:35 +00:00
BLState->MicListenJobData.IncomingMsgQueue = &BLState->IncomingMsgQueue;
BLState->MicListenJobData.OutgoingMsgQueue = &BLState->OutgoingMsgQueue;
#if 1
BLState->MicListenThread = CreateThread(Context.ThreadManager, BlumenLumen_MicListenJob, (u8*)&BLState->MicListenJobData);
#endif
assembly* Flower0 = LoadAssembly(Flower0AssemblyPath, State, Context);
assembly* Flower1 = LoadAssembly(Flower1AssemblyPath, State, Context);
assembly* Flower2 = LoadAssembly(Flower2AssemblyPath, State, Context);
BLState->AssemblyNameToClearCoreMapCount = 3;
BLState->AssemblyNameToClearCore_Names = PushArray(&State->Permanent,
u64,
BLState->AssemblyNameToClearCoreMapCount);
BLState->AssemblyNameToClearCore_Names[0] = HashDJB2ToU32(StringExpand(Flower2->Name));
BLState->AssemblyNameToClearCore_Names[1] = HashDJB2ToU32(StringExpand(Flower1->Name));
BLState->AssemblyNameToClearCore_Names[2] = HashDJB2ToU32(StringExpand(Flower0->Name));
2021-01-23 23:58:05 +00:00
gs_file_handler FileHandler = Context.ThreadContext.FileHandler;
gs_file ColorPhraseCSVFile = ReadEntireFile(FileHandler, PhraseMapCSVPath);
gs_const_string ColorPhraseMapStr = DataToString(ColorPhraseCSVFile.Data);
gscsv_sheet ColorPhraseSheet = CSV_Parse(ColorPhraseMapStr,
{ PhraseMapCSVSeparator },
State->Transient);
BLState->PhraseHueMap = PhraseHueMap_GenFromCSV(ColorPhraseSheet,
&State->Permanent);
2021-03-27 21:46:17 +00:00
#if 0
{ // Animation PLAYGROUND
animation_desc Desc = {};
Desc.NameSize = 256;
Desc.LayersCount = 8;
Desc.BlocksCount = 8;
Desc.MinFrames = 0;
Desc.MaxFrames = SecondsToFrames(15, State->AnimationSystem);
2021-01-23 23:58:05 +00:00
animation_desc Desc0 = Desc;
Desc.Name = "test_anim_zero";
animation Anim0 = Animation_Create(Desc0, &State->AnimationSystem);
Animation_AddLayer(&Anim0, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem);
2021-01-31 03:33:44 +00:00
Animation_AddBlock(&Anim0, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(15), 0);
BLState->AnimHandles[0] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim0);
animation_desc Desc1 = Desc;
Desc1.Name = "test_anim_one";
animation Anim1 = Animation_Create(Desc1, &State->AnimationSystem);
2021-01-23 23:58:05 +00:00
Animation_AddLayer(&Anim1, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem);
2021-01-24 01:38:19 +00:00
Animation_AddBlock(&Anim1, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(12), 0);
BLState->AnimHandles[1] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim1);
animation_desc Desc2 = Desc;
Desc2.Name = "i_love_you";
animation Anim2 = Animation_Create(Desc2, &State->AnimationSystem);;
2021-01-24 01:38:19 +00:00
Animation_AddLayer(&Anim2, MakeString("Base Layer"), BlendMode_Overwrite, &State->AnimationSystem);
Animation_AddBlock(&Anim2, 0, Anim0.PlayableRange.Max, Patterns_IndexToHandle(20), 0);
BLState->AnimHandles[2] = AnimationArray_Push(&State->AnimationSystem.Animations, Anim2);
2021-01-24 01:38:19 +00:00
State->AnimationSystem.ActiveFadeGroup.From = BLState->AnimHandles[2];
} // End Animation Playground
#else
animation_handle DemoPatternsAnim = AnimationSystem_LoadAnimationFromFile(&State->AnimationSystem,
State->Patterns,
Context,
ConstString("data/demo_patterns.foldanim"));
State->AnimationSystem.ActiveFadeGroup.From = DemoPatternsAnim;
#endif
State->AnimationSystem.TimelineShouldAdvance = true;
2021-01-31 03:33:44 +00:00
return Result;
}
internal void
BlumenLumen_CustomUpdate(gs_data UserData, app_state* State, context* Context)
{
2021-01-24 01:38:19 +00:00
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory;
2021-03-21 04:49:02 +00:00
bool SendMotorCommand = false;
blumen_packet MotorCommand = {};
while (MessageQueue_CanRead(BLState->IncomingMsgQueue))
2021-01-24 01:38:19 +00:00
{
2021-03-20 22:15:35 +00:00
gs_data PacketData = MessageQueue_Read(&BLState->IncomingMsgQueue);
2021-01-24 01:38:19 +00:00
2021-03-20 22:15:35 +00:00
blumen_packet Packet = *(blumen_packet*)PacketData.Memory;
switch (Packet.Type) {
case PacketType_PatternCommand:
{
2021-03-20 22:15:35 +00:00
microphone_packet Mic = Packet.MicPacket;
2021-03-27 21:46:17 +00:00
u64 NameHash = HashDJB2ToU32(Mic.AnimationFileName);
2021-03-20 22:15:35 +00:00
u32 NameLen = CStringLength(Mic.AnimationFileName);
2021-03-21 04:49:02 +00:00
2021-03-27 21:46:17 +00:00
phrase_hue NewHue = PhraseHueMap_Get(BLState->PhraseHueMap, NameHash);
if (NewHue.PhraseHash != 0)
{
u32 AssemblyIdx = BLState->LastAssemblyColorSet;
BLState->AssemblyColors[AssemblyIdx] = NewHue;
}
}break;
case PacketType_MotorState:
{
2021-03-21 04:49:02 +00:00
motor_status_packet Motor = Packet.MotorStatusPacket;
2021-03-21 01:06:04 +00:00
// NOTE(pjs): Python sends multi-byte integers in little endian
// order. Have to unpack
u8* T = (u8*)&Motor.Temperature;
Motor.Temperature = (T[0] << 8 |
T[1] << 0);
motor_packet LastPos = BLState->LastKnownMotorState;
DEBUG_ReceivedMotorPositions(LastPos, Motor.Pos, Context->ThreadContext);
2021-03-21 04:49:02 +00:00
BLState->LastKnownMotorState = Motor.Pos;
}break;
case PacketType_Temperature:
{
2021-03-20 22:15:35 +00:00
temp_packet Temp = Packet.TempPacket;
if (Temp.Temperature > 0)
2021-03-20 22:15:35 +00:00
{
2021-03-21 01:06:04 +00:00
BLState->BrightnessPercent = .25f;
2021-03-20 22:15:35 +00:00
}
else
{
BLState->BrightnessPercent = 1.f;
}
2021-03-27 23:07:31 +00:00
DEBUG_ReceivedTemperature(Temp, Context->ThreadContext);
}break;
InvalidDefaultCase;
2021-01-24 01:38:19 +00:00
}
}
2021-03-20 22:15:35 +00:00
// Open / Close the Motor
if (MessageQueue_CanWrite(BLState->OutgoingMsgQueue))
{
2021-03-20 22:15:35 +00:00
for (u32 i = 0; i < MotorOpenTimesCount; i++)
{
2021-03-20 22:15:35 +00:00
time_range Range = MotorOpenTimes[i];
bool CurrTimeInRange = SystemTimeIsInTimeRange(Context->SystemTime_Current, Range);
2021-03-21 01:06:04 +00:00
bool LastSendTimeInRange = SystemTimeIsInTimeRange(BLState->LastSendTime, Range);
2021-03-20 22:15:35 +00:00
bool LastTimeInRange = SystemTimeIsInTimeRange(Context->SystemTime_Last, Range);
2021-03-21 01:06:04 +00:00
bool SendOpen = CurrTimeInRange && !LastSendTimeInRange;
bool SendClose = !CurrTimeInRange && LastSendTimeInRange;
2021-03-21 01:06:04 +00:00
2021-03-21 04:49:02 +00:00
//SendOpen = SecondsSinceLastSend > 2;
2021-03-21 01:06:04 +00:00
if (SendOpen)
2021-03-20 22:15:35 +00:00
{
2021-03-21 04:49:02 +00:00
SendMotorCommand = true;
2021-03-21 01:06:04 +00:00
BLState->LastSendTime = Context->SystemTime_Current;
OutputDebugString("Motors: Open\n");
2021-03-21 04:49:02 +00:00
2021-03-21 01:06:04 +00:00
blumen_packet Packet = {};
Packet.Type = PacketType_MotorState;
Packet.MotorPacket.FlowerPositions[0] = 2;
Packet.MotorPacket.FlowerPositions[1] = 2;
Packet.MotorPacket.FlowerPositions[2] = 2;
2021-03-21 04:49:02 +00:00
MotorCommand = Packet;
2021-03-20 22:15:35 +00:00
}
else if (SendClose)
2021-03-20 22:15:35 +00:00
{
2021-03-21 04:49:02 +00:00
SendMotorCommand = true;
BLState->LastSendTime = Context->SystemTime_Current;
2021-03-21 01:06:04 +00:00
OutputDebugString("Motors: Close\n");
2021-03-21 04:49:02 +00:00
2021-03-21 01:06:04 +00:00
blumen_packet Packet = {};
Packet.Type = PacketType_MotorState;
Packet.MotorPacket.FlowerPositions[0] = 1;
Packet.MotorPacket.FlowerPositions[1] = 1;
Packet.MotorPacket.FlowerPositions[2] = 1;
2021-03-21 04:49:02 +00:00
MotorCommand = Packet;
2021-03-20 22:15:35 +00:00
}
2021-02-06 23:10:14 +00:00
}
2021-03-21 04:49:02 +00:00
if (SendMotorCommand)
{
gs_data Msg = StructToData(&MotorCommand, blumen_packet);
MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg);
DEBUG_SentMotorCommand(MotorCommand.MotorPacket, Context->ThreadContext);
2021-03-21 04:49:02 +00:00
}
2021-03-20 22:15:35 +00:00
}
// Dim the leds based on temp data
for (u32 i = 0; i < State->LedSystem.BuffersCount; i++)
{
led_buffer Buffer = State->LedSystem.Buffers[i];
for (u32 j = 0; j < Buffer.LedCount; j++)
2021-02-06 23:10:14 +00:00
{
2021-03-20 22:15:35 +00:00
pixel* Color = Buffer.Colors + j;
Color->R = Color->R * BLState->BrightnessPercent;
Color->G = Color->G * BLState->BrightnessPercent;
Color->B = Color->B * BLState->BrightnessPercent;
}
2021-03-20 22:15:35 +00:00
}
2021-03-21 04:49:02 +00:00
// NOTE(PS): If the flowers are mostly open or full open
// we mask off the top leds to prevent them from overheating
// while telescoped inside the flower
motor_packet CurrMotorPos = BLState->LastKnownMotorState;
for (u32 a = 0; a < State->Assemblies.Count; a++)
{
assembly Assembly = State->Assemblies.Values[a];
u64 AssemblyCCIndex = GetCCIndex(Assembly, BLState);
u8 MotorPos = CurrMotorPos.FlowerPositions[AssemblyCCIndex];
if (MotorPos == MotorState_Closed ||
MotorPos == MotorState_HalfOpen)
{
continue;
}
led_buffer Buffer = State->LedSystem.Buffers[Assembly.LedBufferIndex];
led_strip_list TopStrips = AssemblyStripsGetWithTagValue(Assembly, ConstString("section"), ConstString("inner_bloom"), State->Transient);
for (u32 s = 0; s < TopStrips.Count; s++)
{
u32 SIndex = TopStrips.StripIndices[s];
v2_strip Strip = Assembly.Strips[SIndex];
for (u32 l = 0; l < Strip.LedCount; l++)
{
u32 LIndex = Strip.LedLUT[l];
Buffer.Colors[LIndex] = {0};
}
}
}
2021-03-20 22:15:35 +00:00
// Send Status Packet
{
system_time LastSendTime = BLState->LastStatusUpdateTime;
2021-03-21 01:06:04 +00:00
r64 NanosSinceLastSend = ((r64)Context->SystemTime_Current.NanosSinceEpoch - (r64)LastSendTime.NanosSinceEpoch);
r64 SecondsSinceLastSend = NanosSinceLastSend / PowR32(10, 8);
2021-03-20 22:15:35 +00:00
if (SecondsSinceLastSend >= STATUS_PACKET_FREQ_SECONDS)
{
2021-03-20 22:15:35 +00:00
BLState->LastStatusUpdateTime = Context->SystemTime_Current;
OutputDebugString("Attempting to Send Lumenarium Status\n");
2021-02-06 23:10:14 +00:00
2021-03-21 01:06:04 +00:00
blumen_packet Packet = {};
Packet.Type = PacketType_LumenariumStatus;
Packet.StatusPacket.NextMotorEventType = 0;
Packet.StatusPacket.NextEventTime = 0;
2021-03-20 22:15:35 +00:00
animation* ActiveAnim = AnimationSystem_GetActiveAnimation(&State->AnimationSystem);
2021-03-21 01:06:04 +00:00
CopyMemoryTo(ActiveAnim->Name.Str, Packet.StatusPacket.AnimFileName,
2021-03-20 22:15:35 +00:00
Min(ActiveAnim->Name.Length, 32));
2021-03-21 01:06:04 +00:00
Packet.StatusPacket.AnimFileName[ActiveAnim->Name.Length] = 0;
gs_data Msg = StructToData(&Packet, blumen_packet);
MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg);
}
}
}
US_CUSTOM_DEBUG_UI(BlumenLumen_DebugUI)
{
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory;
ui_interface* I = &State->Interface;
// NOTE(PS): Motors
{
motor_packet PendingPacket = BLState->DEBUG_PendingMotorPacket;
for (u32 MotorIndex = 0; MotorIndex < 3; MotorIndex++)
{
gs_string Label = PushStringF(State->Transient, 32, "Motor %d", MotorIndex);
ui_BeginRow(I, 5);
{
ui_Label(I, Label);
bool IsClosed = PendingPacket.FlowerPositions[MotorIndex] == 1;
if (ui_ToggleText(I, MakeString("Closed (1)"), IsClosed))
{
PendingPacket.FlowerPositions[MotorIndex] = 1;
}
bool IsHOpen = PendingPacket.FlowerPositions[MotorIndex] == 3;
if (ui_ToggleText(I, MakeString("Half Open (3)"), IsHOpen))
{
PendingPacket.FlowerPositions[MotorIndex] = 3;
}
bool IsMOpen = PendingPacket.FlowerPositions[MotorIndex] == 4;
if (ui_ToggleText(I, MakeString("Mostly Open (4)"), IsMOpen))
{
PendingPacket.FlowerPositions[MotorIndex] = 4;
}
bool IsOpen = PendingPacket.FlowerPositions[MotorIndex] == 2;
if (ui_ToggleText(I, MakeString("Open (2)"), IsOpen))
{
PendingPacket.FlowerPositions[MotorIndex] = 2;
}
}
ui_EndRow(I);
}
BLState->DEBUG_PendingMotorPacket = PendingPacket;
if (ui_Button(I, MakeString("Send Motor Packet")))
{
blumen_packet Packet = {};
Packet.Type = PacketType_MotorState;
Packet.MotorPacket = BLState->DEBUG_PendingMotorPacket;
gs_data Msg = StructToData(&Packet, blumen_packet);
MessageQueue_Write(&BLState->OutgoingMsgQueue, Msg);
DEBUG_SentMotorCommand(Packet.MotorPacket, Context.ThreadContext);
}
}
}
US_CUSTOM_CLEANUP(BlumenLumen_CustomCleanup)
{
blumen_lumen_state* BLState = (blumen_lumen_state*)UserData.Memory;
BLState->Running = false;
}
internal user_space_desc
BlumenLumen_UserSpaceCreate()
{
user_space_desc Result = {};
Result.LoadPatterns = BlumenLumen_LoadPatterns;
Result.CustomInit = BlumenLumen_CustomInit;
Result.CustomUpdate = BlumenLumen_CustomUpdate;
Result.CustomDebugUI = BlumenLumen_DebugUI;
Result.CustomCleanup = BlumenLumen_CustomCleanup;
return Result;
}
#define BLUMEN_LUMEN_CPP
#endif // BLUMEN_LUMEN_CPP