SIMPL Best Practices

I recently received an email asking if I could document some of the things I wished I had known when I started Crestron programming. I didn’t touch Crestron until the twilight years of the 2-series (2010), but it was thankfully a solid platform to learn SIMPL Windows on. I had several years of AMX under my belt, so at least SIMPL+ wasn’t strange to me.

I’d like to write a few posts that explore how I approach programming now that I have a little hindsight. I’ll also reveal areas where I still struggle to find the best methods.

Crestron has a SIMPL Windows Best Practices guide that is useful. The release notes also contain some good rules to follow. I’ll try not to repeat what’s already stated there.

Let’s dig in!

Naming

Signal naming wasn’t discussed until I got to the 301 class. Prior to that, I had tried to name things consistently, but didn’t give much thought to how I would debug something later. For example, my early programs had names like:

clear_mode
pres_btn
pres_mode
video_conf_btn
video_conf_mode

You start to realize what a pain it is to debug something when you’re constantly flipping back and forth between different folders in SIMPL debugger. A better naming scheme would be:

mode_clear
mode_pres_sel
mode_pres_fb
mode_vtc_sel
mode_vtc_fb

Now if I need to simulate a mode change, I just have to look in the M folder in SIMPL debugger. Much easier to watch the states of associated signals change!

The 301 class recommended a format that looked like:

[Device][Function][Action]

So you would end up with a bunch of signals named:

[TP1][Lights][Preset][1]
[TP1][Lights][Preset][1][Fb]

Which I don’t like to look at. Instead, I name my signals:

tp1_lights_preset_1_sel
tp1_lights_preset_1_fb

I write this way mostly because I’m lazy: I don’t have to hit Shift since Spacebar makes the _ automatically in SIMPL Windows. I’ve worked with other programmers who alternate between -, _, and . in their names, but I would find myself struggling to guess which punctuation was used when trying to tie into existing signals in the program. So, I almost never use . (except for keyboard signal names) and always go with _ since Spacebar is the easiest key to press.

Change Your Font

A trick I didn’t try until recently is changing the default font. SIMPL Windows defaults to Arial which makes some characters hard to distinguish. The . in names would sometimes hide between letters. Recently I switched to using JetBrains Mono and it makes it much easier to read signal names. Compare these two:

Arial 10pt Regular
JetBrains Mono 9pt Regular

You can change the font from the View > Detail Font… menu.

Shortcut Keys

Shortcut keys are a MUST when you need to write programs with thousands of signals in it. When I took the 101 class, there was no mention of shortcut keys, so I spent my first year as a Crestron programmer frantically typing out every signal name. I’d spend a week and barely get everything typed in correctly. In case you haven’t used them, here are the ones I rely on the most:

Alt-YShow/Hide symbol library
F4Auto-increment last digit
Shift-F4Auto-increment first digit
Alt-6Prompt for suffix and add to signal name
Alt-Shift-6Prompt for prefix and add to signal name
Alt-RRename signal globally
F9Search and Replace
Alt-F12Recompile All

The suffix and prefix shortcuts are also why it’s important to name your signals along the lines of:

tp1_lights_preset_1
tp1_lights_preset_2
tp1_lights_preset_3
etc...

I can quickly add 10 more presets by highlighting the rows below the first signal and pressing F4.

There are also mouse gesture shortcuts. If you right-click-and-drag from one symbol to another, a bunch of options appear:

Right-click-and-drag is an uncommon mouse action in most software

Using these shortcuts to speed up your program development is crucial when so much of SIMPL programming is giving signals unique names.

Program Structure

The only strict requirement for program structure is that NVRAM symbols go near the top (so their position doesn’t move around when editing the rest of the program). This has to do with how those symbols store and retrieve their values from NVRAM. I typically end up with a structure that looks like this:

Logic
 - NVRAM
 - Config
 - Devices
    - DSP
    - Codec
    - Displays
 - Rooms
    - rm1
    - rm2
 - Panels
    - tp1
    - tp2
 - Divide/Combine
 - Testing

Depending on how devices are shared between rooms, I may do Equipment Crosspoints to those or have one that represents the entire room.

Versions

I always name my programs using the following format:

Customer_Location_System_Processor_vMajor.Minor.Revision
...e.g...
Hasbro_Pawtucket RI_Boardroom_PRO4_v1.0.0

Any time a new version is sent to a technician to load, I bump the Revision number. Any time the user interface is modified, I update the Minor number and reset the Revision. If we implement a major change order or this is an update to their existing system, I bump the Major number and reset both Minor and Revision. By the end of an install, I might end up with:

Hasbro_Pawtucket RI_Boardroom_PRO4_v1.3.7

I know git is the preferred way to manage source code now, but I’ve been hesitant to use it with SIMPL Windows programs since it seems to clobber the files. I probably need to investigate it more, but I’ve never relied solely on git for maintaining SIMPL Windows code. Other types of code (such as HTML, JS, C#, etc.) should definitely be tracked via git.

Renaming

When I take over another programmer’s code, I try to fit into their style as seamless as possible. But over the years, I’ve learned that sometimes the original programmer just didn’t grasp something and tried to program around it.

With SIMPL programming, sometimes the signal naming gets in the way of understanding what’s going on. For example, if I was staring at a signal in debugger that appeared to mute microphones but was named:

volume_rm1_mix_out_off

I would likely rename it to something that fits better with my understanding:

mic_mute_on_sel

This would match up better to what actually happens on the DSP (a mute block is enabled) so I can observe the correct behavior when I see this signal fly by in debugger. Renaming can be done by pressing Alt-R when highlighting a signal. It will be renamed everywhere (also good for replacing one signal with another that already exists in the program).

Renaming can also untangle another programmer’s disorganized planning. Going back to my old naming habits, they could quickly be fixed with:

clear_mode       -->  mode_clear
pres_btn         -->  mode_pres_sel
pres_mode        -->  mode_pres_fb
video_conf_btn   -->  mode_vtc_sel
video_conf_mode  -->  mode_vtc_fb

There’s no reason to tie your brain into knots trying to maintain another programmer’s mess. I like to think of Renaming as leaving the forest better than you found it.

Deterministic Programming

Another thing that stumped me when I first started out was that logic solutions sometimes didn’t solve the way I expected them to. It’s better to program in a deterministic way (and only worry about logic waves when you absolutely have to).

When I started Crestron programming, I might have done something like:

It’s a sequence of things I want to happen when the shutdown button is pushed. There are so many time delays and pulses happening, it makes it difficult to determine when the shutdown sequence actually finishes. You can see I gave it an optimistic 5 seconds delay at the end to give everything a chance to wrap up. But what happens if somebody tries to shutdown too quickly while devices are still powering up? What if everything is already off, should the user still have to wait?

A better approach would be:

In this example, pressing shutdown will always tell the displays to turn off (at the same time, not staggered like they were before), ATC and VTC calls need to hang up, and the UI should return to the splash page. These things always happen when the shutdown button is pressed. What also happens is the pop_shutdown_busy_show signal goes high and remains high until reset by shutdown_done_and. The shutdown is only considered done when the busy pop-up is showing, we’re back on the splash page, both displays are off, and both calls are disconnected. shutdown_done_and may take a short or long time to go high, but eventually all the conditions will be satisfied. The user will be able to use the system again immediately once all the equipment reports the correct status.

Say I only wanted a maximum of 10 seconds to pass before giving up on the shutdown sequence? I could easily add that:

It’s a few more symbols, but the behavior is much more tightly controlled.

Next Time

Next time, I’ll discuss my approach to writing modules. I have a good example in mind that I’d like to walk through: Dynamic EISC. Thanks for reading!

4 thoughts on “SIMPL Best Practices

  1. That deterministic programming concept is awesome! Thank you! I’ve been struggling with cutting out steppers as I’ve heard the new 4 series isn’t a huge fan.

    Liked by 1 person

    1. Thank you, Doug! I’ve also tried to migrate most of my One Shots to Logic Wave Pulses since then it’s guaranteed to only be high for a certain number of logic waves. Definitely helped clean up some of those instances where I thought a Buffer was breaking something!

      Like

      1. Just started p201, and this is the first time I’ve started digging into Logic Waves, so I might use those going forward.

        Will you be addressing signal naming and code readability in future articles?

        Like

      2. I did touch on naming a little; you really just want to pick names that group together nicely in debugger. I do find sometimes I pick a bad name, but it’s easy to fix with Alt-R to change it to something that fits better. I’d like to do an article on crosspoint routing, I think that would be a great opportunity to discuss logic separation and readability. Thanks!

        Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s