Created
June 24, 2017 22:24
-
-
Save savetheclocktower/8c8b3b3a9aabf5dd7f8b5a78156989c9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# For now, let's just turn all LEDs back on. | |
exec(%Q[/home/pi/bin/pacdrive -a -q]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'optparse' | |
require 'pathname' | |
require 'pp' | |
$options = { | |
debug: false, | |
debug_path: '/home/pi/led_log.txt' | |
} | |
# Takes a string like "1,2,3,7,8,9" and determines which LEDs should be lit | |
# up. Shells out to the `pacdrive` binary to do it. | |
$usage = OptionParser.new do |opts| | |
opts.banner = "Usage: led-start [OPTIONS] system game" | |
opts.separator "" | |
opts.on('-d', '--debug', "Writes debug output to the specified file (defaults to ~/led_log.txt).") do |path| | |
$options[:debug] = true | |
$options[:debug_path] = path unless (path.nil? || path.empty?) | |
end | |
opts.on_tail('-h', '--help', "Displays this help message.") | |
end | |
$usage.parse! | |
# The path to the file that sets defaults for LED state. If no config is | |
# found for a certain game, this file ends up determining all states. If a | |
# game config omits a certain button, the default config can specify that | |
# that button should nonetheless be on. (This is useful for, e.g., coin | |
# buttons, aux buttons, and such. These should almost always be on, but it's | |
# dumb to have to specify them in every game config file.) | |
DEFAULT_CONFIG_PATH = Pathname.new('/home/pi/.ledrc') | |
# The base directory where all configs are stored. Each system should be its | |
# own folder; each game should be a text file in that folder whose name | |
# matches the game's name and has a "cfg" extension. | |
BASE_CONFIG_PATH = Pathname.new('/home/pi/leds') | |
class LEDState | |
def initialize(path) | |
@contents = path.is_a?(String) ? path : File.read(path).chomp | |
@button_map = {} | |
debug "config file contents: #{@contents}" | |
buttons = @contents.split(/,\s*/) | |
(1..16).each do |digit| | |
state = { value: 0, force: false } | |
if buttons.include?(digit.to_s) | |
state = { value: 1, force: false } | |
elsif buttons.include?("+#{digit}") | |
# "+x" syntax means we should force this button to be on. | |
state = { value: 1, force: true } | |
elsif buttons.include?("-#{digit}") | |
# "-x" syntax means we should force this button to be off. | |
state = { value: 0, force: true } | |
end | |
debug "State for button #{digit}:" | |
debug state | |
@button_map[digit] = state | |
end | |
self | |
end | |
def with_default(path) | |
debug "Combining with default config" | |
default = LEDState.new(path) | |
merge!(default) | |
self | |
end | |
def map | |
@button_map | |
end | |
# Converts the state to the format expected by the `pacdrive` utility. | |
def to_s | |
str = (1..16).map do |digit| | |
state = '0' | |
data = @button_map[digit] | |
if data && data.has_key?(:value) | |
state = data[:value] == 1 ? '1' : '0' | |
end | |
end | |
binary = str.join('').reverse | |
"0x%04x" % binary.to_i(2) | |
end | |
# Calls the external `pacdrive` app to set the LEDs to the represented | |
# state. | |
# | |
# Uses `exec`, so once this method is called, we implicitly exit. | |
def apply! | |
exec("/home/pi/bin/pacdrive", "-q", "-s", to_s) | |
end | |
protected | |
# For combining this state with another. The argument to this function is | |
# assumed to be a default, which means it will take precedence over this | |
# state when conflicts happen. | |
def merge!(default) | |
output = {} | |
default_map = default.map | |
@button_map.keys.each do |digit| | |
own = @button_map[digit] | |
dflt = default_map[digit] | |
result = nil | |
if !dflt[:force] | |
# Our version always wins. | |
result = own[:value] | |
else | |
# Default wants to force a value... | |
if !own[:force] | |
# ...and we don't, so use the default. | |
result = dflt[:value] | |
else | |
# ...and so do we, so we win. | |
result = own[:value] | |
end | |
end | |
output[digit] = { value: result } | |
end # each | |
# Replace the button map with the merged version. | |
@button_map = output | |
end # merge | |
end # LEDState | |
def debug(str) | |
return unless $options[:debug] | |
`echo "#{str}" >> #{$options[:debug_path]}` | |
end | |
if ARGV.size == 1 | |
# We've been given a string like "1,2,3,7,8,9" (probably for debugging). | |
# Ignore all configs and just create and apply an LED state. | |
debug "Given input: #{ARGV[0]}" | |
LEDState.new(ARGV[0]).apply! | |
elsif ARGV.size == 2 | |
# We've been given a system and a ROM name. Look up its config file and | |
# turn it into a binary string. | |
system, game = ARGV | |
debug "Setting LEDs for game #{game} on system #{system}..." | |
game_config_path = BASE_CONFIG_PATH.join(system, "#{game}.cfg") | |
if game_config_path.exist? | |
state = LEDState.new(game_config_path).with_default(DEFAULT_CONFIG_PATH) | |
else | |
# No specific LEDs for this game, so just apply the default. | |
state = LEDState.new(DEFAULT_CONFIG_PATH) | |
end | |
state.apply! | |
else | |
puts $usage | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/bash | |
# ARGUMENTS, IN ORDER: | |
# 1. System (e.g., "arcade") | |
# 2. Emulator (e.g. "lr-fba-next") | |
# 3. Full path to game (e.g., /home/pi/RetroPie/roms/arcade/wjammers.zip) | |
if [ -z "$3" ]; then | |
exit 0 | |
fi | |
system=$1 | |
emulator=$2 | |
# Gets the basename of the game (e.g., "wjammers") | |
game=$(basename $3) | |
game=${game%.*} | |
/home/pi/bin/led-end "$system" "$game" >/dev/null |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/bash | |
# ARGUMENTS, IN ORDER: | |
# 1. System (e.g., "arcade") | |
# 2. Emulator (e.g. "lr-fba-next") | |
# 3. Full path to game (e.g., /home/pi/RetroPie/roms/arcade/wjammers.zip) | |
if [ -z "$3" ]; then | |
exit 0 | |
fi | |
system=$1 | |
emulator=$2 | |
# Gets the basename of the game (e.g., "wjammers") | |
game=$(basename $3) | |
game=${game%.*} | |
# Turn on the relevant LEDs for this game. | |
/home/pi/bin/led-start "$system" "$game" >/dev/null |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment