Skip to content

Instantly share code, notes, and snippets.

@k4kfh
Last active November 26, 2015 05:10
Show Gist options
  • Save k4kfh/beb7341004ff95bf277a to your computer and use it in GitHub Desktop.
Save k4kfh/beb7341004ff95bf277a to your computer and use it in GitHub Desktop.
ZephyrCab decoder Example
decoders = {
//This is EXACTLY the same string value recieved from JMRI for the decoderFamily attribute.
"ESU LokSound Select": {
//This is EXACTLY the same string value recieved from JMRI for the decoderModel attribute.
"LokSound Select EMD 567": function (address, trainPosition) {
//First thing we do is create the throttle object. Make sure you use jmri.throttleName.generate() for the name! That function generates a unique name for each throttle, and if you don't use it you'll probably run into issues.
train.all[trainPosition].throttle = new jmri.throttle(address, jmri.throttleName.generate()); //we use the train position as the throttle name for future lookup purposes
/*
Functions:
All the functions are stored as subobjects of the f object. Most functions follow a pretty simple "standard", but there are a few exceptions, including the manual notching system, which is very different from the other sounds.
If your sound decoder does not have any of these functions, make a dummy function instead. Remove the line that sends the throttle command, but leave all the things that make ths .state variables work! sim.js relies on a number of the .state booleans, so if you don't make a full dummy function that makes those work, you're screwed.
*/
this.f = new Object();
//Main Headlight (NOT ditch lights or other aux lights)
this.f.headlight = new Object();
this.f.headlight.set = function (state) {
train.all[trainPosition].throttle.f.set(0, state);
train.all[trainPosition].dcc.f.headlight.state = state;
}
//Bell sound
this.f.bell = new Object();
this.f.bell.set = function (state) {
train.all[trainPosition].throttle.f.set(1, state)
train.all[trainPosition].dcc.f.bell.state = state;
}
this.f.bell.state = false;
//Horn
this.f.horn = new Object();
this.f.horn.set = function (state) {
train.all[trainPosition].throttle.f.set(2, state)
train.all[trainPosition].dcc.f.horn.state = state;
}
this.f.horn.state = false;
//Air Compressor
this.f.compressor = new Object();
this.f.compressor.set = function (state) {
train.all[trainPosition].throttle.f.set(20, state)
train.all[trainPosition].dcc.f.compressor.state = state;
}
this.f.compressor.state = false;
//Air Dump Noise
this.f.airdump = new Object();
this.f.airdump.set = function (state) {
//I haven't got this finished yet, so this is an example of a dummy function.
train.all[trainPosition].dcc.f.airdump.state = state;
}
this.f.airdump.state = false;
//dyn brake fans
this.f.dynbrakes = new Object();
this.f.dynbrakes.set = function (state) {
}
this.f.dynbrakes.state = false;
/*
Engine Startup Noise
This function does a lot of things.
*/
this.f.engine = new Object();
this.f.engine.set = function (state) {
//This IF checks to see if the locomotive is out of fuel. If it is out of fuel, the function should behave much differently, as shown below.
if (train.all[trainPosition].prototype.realtime.fuel.status != 0) {
train.all[trainPosition].throttle.f.set(8, state);
train.all[trainPosition].dcc.f.engine.state = state;
//This code sets engineRunning to 0 or 1 depending on the state. This MUST be set even if this function is a dummy function!
if (state == true) {
train.all[trainPosition].prototype.engineRunning = 1;
}
else if (state == false) {
train.all[trainPosition].prototype.engineRunning = 0;
}
}
else {
/*
Remember what I said above about the function acting totally different if you're out of fuel? This code is what it does.
When the loco runs out of fuel, sim.js will call engine.set() to turn the engine sound off. Because of this, we have to allow the function to do SOMETHING when we're out of fuel, but we can't allow it to behave as normal. Thus, if we have no fuel left, the function will set the engine sounds to OFF regardless of the arguments passed to it.
I highly recommend just using my code minus the line with the throttle; this feature could break a LOT of things if it's not done correctly.
*/
train.all[trainPosition].throttle.f.set(8, false);
train.all[trainPosition].prototype.engineRunning = 0;
train.all[trainPosition].dcc.f.engine.state = false;
}
}
this.f.engine.state = false; //We go ahead and define this as false just to protect against undefined errors
/*
Manual Notching Sounds
- This is only present on certain decoders, but PLEASE be sure to faithfully replicate the appropriate dummy functions if your decoder doesn't support this. If you mess this up, sim.js will become horribly confused. This could cause the world to end, so please be careful.
- up() and down() should accept no arguments, and should return nothing. However, it is very important that they increment notch.state appropriately!
*/
this.f.notch = {
up: function () {
//Notch up code
//This is inside an IF statement to make sure we don't try to notch OVER 8.
var newNotch = (train.all[trainPosition].dcc.f.notch.state + 1)
if (newNotch <= 8) {
train.all[trainPosition].dcc.f.notch.state++; //This should run instantly, not on a timer, or sim.js will get confused.
//These two setTimeout functions are specific to ESU decoders that I have.
setTimeout(function () {
train.all[trainPosition].throttle.f.set(9, true)
}, 500);
setTimeout(function () {
train.all[trainPosition].throttle.f.set(9, false);
}, 1750)
}
},
down: function () {
//Notch down code
//This is inside an IF statement to make sure we don't try to notch LESS THAN idle.
var newNotch = (train.all[trainPosition].dcc.f.notch.state - 1)
if (newNotch >= 0) {
train.all[trainPosition].dcc.f.notch.state--; //This should run instantly, not on a timer, or sim.js will get confused.
//These two setTimeout functions are specific to my ESU decoders.
setTimeout(function () {
train.all[trainPosition].throttle.f.set(10, true)
}, 500);
setTimeout(function () {
train.all[trainPosition].throttle.f.set(10, false);
}, 1750)
}
},
state: 0, //This should reflect the current notching state of the sound decoder. You should increment this up or down 1 when your up() and down() functions finish, or sim.js's functions will be horribly confused and mess up your sounds.
}
//Speed Functions - these are basically wrappers for .throttle's speed functions. If your decoder does anything bizarre with speed, here's your chance to deal with it.
this.speed = new Object();
this.speed.state = 0; //This is as a percent decimal. 0.75 would be 75% speed, etc.
//This function accepts a percent-decimal, as described above.
this.speed.set = function (speed) {
train.all[trainPosition].throttle.speed.set(speed)
train.all[trainPosition].dcc.speed.state = speed;
}
/*
This function sets a specific speed in scale mph. Please use this exact code unless you have a very specific reason not to. This code integrates with the model object, which is how it should be.
*/
this.speed.setMPH = function (mph) {
var speed = train.all[trainPosition].model.speed(mph)
train.all[trainPosition.dcc.speed.set(speed)]
}
}
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment