PERSISTENT, VOLATILE and NONVOLATILE
Spire_Jeff
Posts: 1,917
Back when I took the programmer classes, I thought I was told that it was good practice to put VOLATILE in front of your variable declarations, but not necessary. The other option was PERSISTENT, which saves the value of the variable through reboots and power loss. Obviously, being a good programmer I normally put VOLATILE in front of my declarations. Well, today my understanding has changed. I was using a modified version of the Escient fireball module in which they left out the VOLATILE. As soon as I doubled up the module to support 2 fireball units, my touchpanels ceased to function properly. I telneted into the processor and did a SHOW MEM command. It showed my nonvolatile memory at -697,000. I knew right away that it was the fireball modules since I just doubled the instances.
I called to verify with AMX tech support before I started to change a functional module and this is where it was made clear that what I was told in class was slightly different than what the processor does. In fact a quick RTFM produced this result:
In the few years since my classes, this is the first time I've run into a problem of running out of NON-VOLATILE memory, but I figured I'd pass this on as a good habit to develop.
Jeff
I called to verify with AMX tech support before I started to change a functional module and this is where it was made clear that what I was told in class was slightly different than what the processor does. In fact a quick RTFM produced this result:
TFM wrote:Non-volatile variables: A variable declared with the NON_VOLATILE keyword is stored in non-volatile memory. It will retain its value in the event of a system power-down, but is reset to zero if the program is reloaded. [BOLD]Unless specified otherwise, all variables are stored in non-volatile memory.[/BOLD]
Volatile variables: A variable declared with the VOLATILE keyword is stored in volatile memory and reset to zero after either power-down or reload. Volatile memory is generally faster and more plentiful than non-volatile memory. For this reason, you should use the VOLATILE keyword when declaring large data arrays where persistence of the data is not a requirement.
Persistent variables: If a variable is declared with the PERSISTENT keyword, it is initialized to zero the first time the program is loaded but will retain its value after either power-down or reload.
In the few years since my classes, this is the first time I've run into a problem of running out of NON-VOLATILE memory, but I figured I'd pass this on as a good habit to develop.
Jeff
0
Comments
I haven't touched a program in about a month and it's amazing how much I can't remember. God, getting old sucks!
Most likely because when NetLinx was introduced, everyone was so used to the tiny, tiny memory space of an Axcent3, that it wasn't really an issue.
I tend to store all my customer presets in non-voloatile. (like volume presets, radio staion presets, etc...) I also store some of the large data tables there that are a pain to download. (like cable/satellite channel assignments) there as well.
I've always put volatile in front of the var declarations out of old habit.
I've noticed that the Escient module is quite a memory hog. I think it's about time AMX et al maybe thought about re-doing the protocol of module design in general. For something that's supposed to make life easier, it ends up being the thing I spend the most time debugging. Debugging a black box is very difficult. I also think that programmers in general seem to overlook just how much their concept of touch panel navigation shapes the module programming.
If I remember correctly, the whole idea of a module was to be two-part. 1 being the communication protocol from/to the device and the main program. Part II was the user interface. But somehow, module writers are basing part 1 from how they plan out the UI.
Consequently, what is really a function that is supposed to be defined by the end programmer (us) ends up being put in both the UI and the Comm modules; that being the touch panel navigation functions.
The origianl idea was that when you push a button on the UI (say play for example) that it would communicate to the comm module that the user wants to make the thing play. Then the comm module is supposed to then tell the box to play.
However, with a lot of the modules being designed out there there is typically a whole raft of crap that also happens when you hit the play button that does ancillary things to both the Comm moduel and the UI. They are typically things to do with the particulars that they've added to the UI module. (how they like to operate a user's experience on the touch panel)
Where as one programmer may only want to light up the Play button on Page X, another may want to switch over to a different page (Y) that has the Play button highlighted. Or, one programmer wants to use the page tracking feature and turns it on all the touch panels in the system but that action causes heartache in some other module or whatnot. (I have this situation happening between two AMX made modules.) Things like this are borne out in how every module has some quirky or wierd way of handling multiple touch panels using a module to control a single peice of gear. Or worse, not being able to allow multiple TPs to work at all without declaring multiple versions of the module.
I realize that simply mapping out a huge array of buttons and saying that button 1 of those equals Play and button 101 equals put the thing in 'genre' mode, etc... is not as sexy and fun as handing the client a finished touch panel design, it is necessary to make the end programmers ease of use better. Touch panel design and layout really drives how a program is approached at a fundamental level. When the module writer spends so much time in touch panel design, they naturally bend the Comm/UI modules toward their particular flavor of TP navigation.
I would argue that this is the single biggest weakness in module design being currently practiced today. They are not TP navigation neutral.
wow, that got of topic! Sorry...
Perhaps I'm not making myself clear. I agree with you that they should not have to do all the work and that it's for mining what you need. My complaint was that they are doing too much of the work. I'd prefer a basic interface with no graphics, just the buttons to show that it works. It is when they doo too much work on the UI that they complicate mining it beyond usefulness.
I once spent almost 2 hours on the phone with AMX tech support trying to figure out why I couldn't debug my program. Commented out the whole thing and finally ended up with:
DEFINE_VARIABLE
VOLATILE INTEGER nFLASH
DEFINE_PROGRAM
WAIT 5 nFLASH = !nFLASH
And I still couldn't debug! Take out the "Volatile" and it worked.
Turns out this is the first system I have tried to debug that didn't have a projector in it (Lamp hours = persistent). I have started declaring my flash feedback variable as non-volatile.
That's exactly what the AMX modules are. They are slim comms modules. Plus a whole stack of UI in separate modules that you can entirely ignore.
I suppose I'm including OEM modules as well. AMX does a reasonable job keeping Comm and UI fairly separate.
An example I can cite of OEM is Kaleidescape. Their comm and UI are hopelessly intertwined. the only work around if is to rename all the touch panel pages and popups associated. This is one of those examples I spoke of in another thread that I brought thier 4-page, 6-popup interface down to 1 main popup and 1 keyboard popup.
I do think the iWeather and MAX comm modules do seem to need some kind of panel feedback. I cannot speak with authority on that since we don't have the source. However, there is some starnge page naviation behavior if you try to use thier UI in any way other than intended. If you leave the AMX pages in the touch panel file but take away the UI module, the program will ocassionally bring up the main page of the i! Weather or Max without provocation.
Also, the MAX interface won't work properly unless its buttons and fields are on port 1. I had to move all the other buttons/fields on the client's interface to port 2, so that the MAX could use port 1. Having done those two things I didn't have any more problems with the UI.
Sorry if this is a bit off topic but I was just expanding on what eric said.