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.
Let’s dig in!
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:
So you would end up with a bunch of signals named:
Which I don’t like to look at. Instead, I name my signals:
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:
You can change the font from the View > Detail Font… menu.
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-Y||Show/Hide symbol library|
|F4||Auto-increment last digit|
|Shift-F4||Auto-increment first digit|
|Alt-6||Prompt for suffix and add to signal name|
|Alt-Shift-6||Prompt for prefix and add to signal name|
|Alt-R||Rename signal globally|
|F9||Search and Replace|
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:
Using these shortcuts to speed up your program development is crucial when so much of SIMPL programming is giving signals unique names.
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.
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:
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.
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:
I would likely rename it to something that fits better with my understanding:
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.
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, 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!