Skip to content

Commit

Permalink
Add light output, reconfigure for new breakout board
Browse files Browse the repository at this point in the history
  • Loading branch information
geefr committed Jun 5, 2022
1 parent b880ad4 commit 720b430
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 19 deletions.
105 changes: 86 additions & 19 deletions arduino-fsr/arduino-fsr/arduino-fsr.ino
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,21 @@

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sketch configuration - Uncomment these to enable software features
// #define ENABLE_EEPROM // Save sensitivity data to board's EEPROM, persist settings without connecting to cabinet
// #define ENABLE_DEBUG // Various debug capability, may not work on your board
// (TODO) #define ENABLE_EEPROM // Save sensitivity data to board's EEPROM, persist settings without connecting to cabinet
// TODO: Configure light-fading for teensy (<1ms update rate), maybe add in the idle animation system
#define ENABLE_LIGHTS // Enable light output


// Global state setup - configure pin -> pad mappings and sketch features here
void initialiseState(State& s)
{
//////// SETUP STEPS ////////
// Firstly, Click Tools -> Board -> Teensyduino -> Teensy 4.0
// (Or your equivalent, this sketch shouldn't care much)
// Then Click Tools -> USB Type -> "Serial + Keyboard + Mouse + Joystick"
// (Joystick being the important bit - Serial is a nice to have if your board can do it as well)

// The serial protocol for talking to the cab, debug, or none.
// Debug is useful for setup but may cause polling issues
// A serial protocol must exist - If you don't need anything choose none here
Expand All @@ -50,20 +60,42 @@ void initialiseState(State& s)
// Using SerialInterfaceDebug and the arduino serial monitor can help here,
// or maybe there'll be a handy dandy UI to help set this up if you bug me about it <3
// s.sensors[analog pin index] = Panel::XXX
s.sensors[2].panel = Panel::P1Up;
s.sensors[6].panel = Panel::P1Up;
s.sensors[2].triggerValue = 80;
s.sensors[6].triggerValue = 80;
// On Teensy 4 analog index 0-7 correspond to pins 14-21

s.sensors[0].panel = Panel::P1Left;
s.sensors[1].panel = Panel::P1Left;

s.sensors[2].panel = Panel::P1Down;
s.sensors[3].panel = Panel::P1Down;

s.sensors[4].panel = Panel::P1Up;
s.sensors[5].panel = Panel::P1Up;

s.sensors[1].panel = Panel::P1Right;
s.sensors[3].panel = Panel::P1Right;
s.sensors[6].panel = Panel::P1Right;
s.sensors[7].panel = Panel::P1Right;

s.sensors[0].panel = Panel::P1Down;
s.sensors[7].panel = Panel::P1Down;
// To hard-code sensitivity set values here
// Defaults are set in common.h SensorState
s.sensors[4].triggerValue = 80;
s.sensors[5].triggerValue = 80;

s.sensors[4].panel = Panel::P1Left;
s.sensors[5].panel = Panel::P1Left;
// Configure mappings for light pins
// Output pins should be PWM - This firmware uses analogWrite for some nice effects
// Lighting constants, or swithcing to digitalWrite can be changed in light.h/cpp
// s.lights[Panel] = Light(output_pin)
s.lights[Panel::P1Right] = Light(12);
s.lights[Panel::P1Up] = Light(11);
s.lights[Panel::P1Down] = Light(10);
s.lights[Panel::P1Left] = Light(9);

pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);

// If you need to, set pinMode here
// I'm using the default mode of all these, so no need to change it

// Other state initialisation - Don't change this
if( s.serial ) s.serial->initialise();
for( auto& p : s.sensors ) s.panels[p.second.panel] = false;
Expand Down Expand Up @@ -144,8 +176,6 @@ void panelAlgorithm(State& s)
Joystick.useManualSend(false);
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main sketch functions - Binds basic sequence to the various program elements
void readInputPins(State& s)
{
static bool firstTime = true;
Expand All @@ -160,25 +190,53 @@ void readInputPins(State& s)
if( firstTime ) firstTime = false;
}

void lightUpdate(std::map<Panel, bool>& oldPanels, State& newState, float deltaSeconds)
{
for( auto& panel : newState.panels )
{
auto light = newState.lights.find(panel.first);
if( light == newState.lights.end() )
{
continue;
}

if( panel.second && !oldPanels[panel.first] )
{
// Panel pressed
light->second.target(0xff);
light->second.set(0xff);
}
else if( !panel.second && oldPanels[panel.first] )
{
// Panel released
light->second.target(0x00);
light->second.set(0x00);
}
}

for( auto& light : newState.lights )
{
light.second.tick(deltaSeconds);
}
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
State gState;
std::map<Panel, bool> gOldPanels;
float secondsSinceStartup = 0.f;

void setup(void) {
initialiseState(gState);

for( auto& l : gState.lights ) l.second.target(0x00);
// TODO
// - eeprom initialisation
// - eeprom save support
// - a whole load of stuff
}

void loop(void) {
static bool setup = false;
if( !setup )
{
//initialiseState(gState);
setup = true;
}
gOldPanels = gState.panels;

// Update timing data
auto t = static_cast<float>(millis()) / 1000.f;
Expand All @@ -194,11 +252,20 @@ void loop(void) {
// Combine the sensors, work out if panels are on/off, send joystick updates
panelAlgorithm(gState);

// Light update
lightUpdate(gOldPanels, gState, dT);

// Serial update - Handle any commands from the cabinet
static int i = 0;
++i;
if( i % 10 == 0 ) {
gState.serial->update(t, dT, gState);
i = 0;
}

#ifdef ENABLE_DEBUG
auto anyOn = false;
for(auto& p : gState.panels) if(p.second) anyOn = true;
digitalWrite(13, anyOn ? HIGH : LOW);
#endif
}
4 changes: 4 additions & 0 deletions arduino-fsr/arduino-fsr/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
#include <map>
#include <memory>
#include <limits>
#include <cstdint>
#include <algorithm>
#include "light.h"

// The directions on the pad
// Panel enum maps directly to joystick buttons
Expand Down Expand Up @@ -38,6 +41,7 @@ struct State
std::unique_ptr<SerialProto> serial;
std::map<int, SensorState> sensors; // <pin index, state>
std::map<Panel, bool> panels; // Whether panels are on or off, output of PanelAlgorithm
std::map<Panel, Light> lights; // Bindings between input panels and lights
};

#endif
46 changes: 46 additions & 0 deletions arduino-fsr/arduino-fsr/light.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "light.h"

#include <algorithm>

#include "Arduino.h"

Light::Light(int pin)
: mPin(pin)
{}

void Light::tick(float deltaSeconds) {
uint32_t deltaMS = static_cast<uint32_t>(deltaSeconds * 1000.0f);
if( mVal < mTargetVal ) {
mVal += mFadeInDelta * deltaMS;
} else if( mVal > mTargetVal ) {
mVal -= mFadeOutDelta * deltaMS;
}

mVal = std::max( mVal, static_cast<int32_t>(MinVal) );
mVal = std::min( mVal, static_cast<int32_t>(MaxVal) );
set( mVal );
}

void Light::target( uint8_t v ) {
mTargetVal = v;
if( mTargetVal > mVal ) {
set( mTargetVal );
}
}

void Light::set( uint8_t v ) {
mVal = std::max( v, MinVal );
mVal = std::min( v, MaxVal );
analogWrite( mPin, v );
mVal = v;
}

void Light::add( uint8_t v ) {
if( MaxVal - mVal < v ) set(MaxVal);
else set( static_cast<uint8_t>(mVal + v) );
}

void Light::sub( uint8_t v ) {
if( v > mVal ) set( MinVal );
else set( static_cast<uint8_t>(mVal - v) );
}
32 changes: 32 additions & 0 deletions arduino-fsr/arduino-fsr/light.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#ifndef LIGHT_H
#define LIGHT_H

#include <cstdint>

class Light {
private:
static const uint8_t MinVal = 0x00;
static const uint8_t MaxVal = 0xff;
// In val per millisecond i.e 1 == fade over 255 milliseconds
static const uint8_t mFadeInDelta = 4;
static const uint8_t mFadeOutDelta = 4;

public:
Light(int pin);
Light() = default;
Light( const Light& ) = default;
Light& operator=( const Light& ) = default;

void tick(float deltaSeconds);
void target( uint8_t v );
void set( uint8_t v );
void add( uint8_t v );
void sub( uint8_t v );

private:
int mPin;
int32_t mVal;
uint8_t mTargetVal;
};

#endif

0 comments on commit 720b430

Please sign in to comment.