Fix up SMX PGEX to remove timing desync bugs and add second pad compatibility.

master
sigonasr2 4 days ago
parent ecba99cd7e
commit 04636be072
  1. 100
      sample/PGEX_SMX.h
  2. 10
      smx-config/App.config
  3. 2
      smx-config/Properties/Resources.Designer.cs
  4. 2
      smx-config/Properties/Settings.Designer.cs
  5. 3
      smx-config/SMXConfig.csproj

@ -1,6 +1,7 @@
#pragma once
#include "olcPixelGameEngine.h"
#include "SMX.h"
#include <assert.h>
using namespace olc;
@ -15,15 +16,17 @@ public:
//LEFT is 0x08
//Add these bytes together to get the combination (all 4 held down is 0xAA
HWButton GetPanel(Key k,int pad=0)const{
return panelState[k-UP];
return panelState[k-UP][pad];
};
void EnableLogMessages(bool enabled){
logMessages=enabled;
}
private:
static bool logMessages;
HWButton internal_panelState[4];
HWButton panelState[4]; //We store the 4 main panel states, similar to how PGE does.
HWButton internal_panelState[4][2];
HWButton panelState[4][2]; //We store the 4 main panel states, similar to how PGE does.
double totalElapsedTime{0.};
double nextLightUpdate{0.};
//SMX "screen" is 12x21
//Each panel is 4x7
static void SMXStateChangedCallback(int pad, SMXUpdateCallbackReason reason, void *pUser)
@ -44,31 +47,57 @@ private:
{
if(logMessages){
printf("Device %i state changed: %04x\n", pad, SMX_GetInputState(pad));
printf("Device %i state changed: %04x\n", 1, SMX_GetInputState(1));
}
int16_t state(SMX_GetInputState(pad));
if(state&0x2&&!internal_panelState[UP-UP].bPressed){
internal_panelState[UP-UP]={true,false,true};
int16_t state(SMX_GetInputState(0));
if(state&0x2&&!internal_panelState[UP-UP][0].bPressed){
internal_panelState[UP-UP][0]={true,false,true};
}else
if(!(state&0x2)&&!internal_panelState[UP-UP].bReleased){
internal_panelState[UP-UP]={false,true,false};
if(!(state&0x2)&&!internal_panelState[UP-UP][0].bReleased){
internal_panelState[UP-UP][0]={false,true,false};
}
if(state&0x20&&!internal_panelState[RIGHT-UP].bPressed){
internal_panelState[RIGHT-UP]={true,false,true};
if(state&0x20&&!internal_panelState[RIGHT-UP][0].bPressed){
internal_panelState[RIGHT-UP][0]={true,false,true};
}else
if(!(state&0x20)&&!internal_panelState[RIGHT-UP].bReleased){
internal_panelState[RIGHT-UP]={false,true,false};
if(!(state&0x20)&&!internal_panelState[RIGHT-UP][0].bReleased){
internal_panelState[RIGHT-UP][0]={false,true,false};
}
if(state&0x80&&!internal_panelState[DOWN-UP].bPressed){
internal_panelState[DOWN-UP]={true,false,true};
if(state&0x80&&!internal_panelState[DOWN-UP][0].bPressed){
internal_panelState[DOWN-UP][0]={true,false,true};
}else
if(!(state&0x80)&&!internal_panelState[DOWN-UP].bReleased){
internal_panelState[DOWN-UP]={false,true,false};
if(!(state&0x80)&&!internal_panelState[DOWN-UP][0].bReleased){
internal_panelState[DOWN-UP][0]={false,true,false};
}
if(state&0x8&&!internal_panelState[LEFT-UP].bPressed){
internal_panelState[LEFT-UP]={true,false,true};
if(state&0x8&&!internal_panelState[LEFT-UP][0].bPressed){
internal_panelState[LEFT-UP][0]={true,false,true};
}else
if(!(state&0x8)&&!internal_panelState[LEFT-UP].bReleased){
internal_panelState[LEFT-UP]={false,true,false};
if(!(state&0x8)&&!internal_panelState[LEFT-UP][0].bReleased){
internal_panelState[LEFT-UP][0]={false,true,false};
}
state=SMX_GetInputState(1);
if(state&0x2&&!internal_panelState[UP-UP][1].bPressed){
internal_panelState[UP-UP][1]={true,false,true};
}else
if(!(state&0x2)&&!internal_panelState[UP-UP][1].bReleased){
internal_panelState[UP-UP][1]={false,true,false};
}
if(state&0x20&&!internal_panelState[RIGHT-UP][1].bPressed){
internal_panelState[RIGHT-UP][1]={true,false,true};
}else
if(!(state&0x20)&&!internal_panelState[RIGHT-UP][1].bReleased){
internal_panelState[RIGHT-UP][1]={false,true,false};
}
if(state&0x80&&!internal_panelState[DOWN-UP][1].bPressed){
internal_panelState[DOWN-UP][1]={true,false,true};
}else
if(!(state&0x80)&&!internal_panelState[DOWN-UP][1].bReleased){
internal_panelState[DOWN-UP][1]={false,true,false};
}
if(state&0x8&&!internal_panelState[LEFT-UP][1].bPressed){
internal_panelState[LEFT-UP][1]={true,false,true};
}else
if(!(state&0x8)&&!internal_panelState[LEFT-UP][1].bReleased){
internal_panelState[LEFT-UP][1]={false,true,false};
}
}
@ -79,18 +108,29 @@ private:
virtual bool OnBeforeUserUpdate(float& fElapsedTime){
//We don't want the panel states changing in the middle of a frame, since the input polling is on a separate thread.
//Copy over the internal button states to the current panel state.
for(int i=0;i<4;i++){
panelState[i]=internal_panelState[i];
internal_panelState[i].bPressed=false;
internal_panelState[i].bReleased=false;
for(int pad=0;pad<2;pad++){
for(int i=0;i<4;i++){
panelState[i][pad]=internal_panelState[i][pad];
internal_panelState[i][pad].bPressed=false;
internal_panelState[i][pad].bReleased=false;
}
}
return false;
}
virtual void OnAfterUserUpdate(float fElapsedTime)override{
for(int i=0;i<4;i++){
panelState[i].bPressed=false;
panelState[i].bReleased=false;
double previousTotalElapsedTime{totalElapsedTime};
totalElapsedTime=fmod(totalElapsedTime+fElapsedTime,10000.);
if(previousTotalElapsedTime>totalElapsedTime){
//We are in the past, so reset lastLightUpdate to keep lights running.
nextLightUpdate=totalElapsedTime;
}
if(nextLightUpdate>totalElapsedTime)return; //Ignore light updates if not enough time has passed. We can only send light updates at 30 FPS.
for(int pad=0;pad<2;pad++){
for(int i=0;i<4;i++){
panelState[i][pad].bPressed=false;
panelState[i][pad].bReleased=false;
}
}
std::string lightData;
//The light data for an SMX dance pad is outlined in the docs but the code used to transform the PGE's pixels to SMX pad's lights will be annotated here.
@ -105,7 +145,7 @@ private:
col++;
continue;
}
Pixel p(pge->GetDrawTarget()->GetPixel(x,y));
Pixel p(pge->GetDrawTarget()->GetPixel(x+12*pad,y));
lightData.append(1,p.r);
lightData.append(1,p.g);
lightData.append(1,p.b);
@ -121,7 +161,7 @@ private:
col++;
continue;
}
Pixel p(pge->GetDrawTarget()->GetPixel(x,y));
Pixel p(pge->GetDrawTarget()->GetPixel(x+12*pad,y));
lightData.append(1,p.r);
lightData.append(1,p.g);
lightData.append(1,p.b);
@ -131,6 +171,8 @@ private:
}
}
}
if(lightData.size()!=1350)throw;
nextLightUpdate=totalElapsedTime+1/30.f;
SMX_SetLights2( lightData.data(), lightData.size() );
}
};

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="smx_config.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="smx_config.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false"/>
</sectionGroup>
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
<userSettings>
<smx_config.Properties.Settings>
@ -14,7 +14,7 @@
<value>False</value>
</setting>
<setting name="CustomSensors" serializeAs="String">
<value />
<value/>
</setting>
<setting name="UseInnerSensorThresholds" serializeAs="String">
<value>False</value>

@ -19,7 +19,7 @@ namespace smx_config.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {

@ -12,7 +12,7 @@ namespace smx_config.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>smx_config</RootNamespace>
<AssemblyName>SMXConfig</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
@ -29,6 +29,7 @@
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>

Loading…
Cancel
Save