Firmware Tips & Techniques
Light controllers are essentially small computers that have a dedicated purpose. They don't have features for a keyboard or mouse, they don't have an electronic subsystem for hi-res video displays, hard disk drives or networking, but they have the ability to turn things "on" and "off," sometimes very quickly -- hundreds and thousands of times per second. To do this, the "chip" or "chips" that are inside a light controller use "firmware." Firmware for one of these chips is the equivalent of "software" for your PC. Except while you can generally control what software does on your computer because you're sitting in front of it, firmware on a chip generally runs unattended and only reacts to whatever data is sent to it.
From the factory, these chips are blank and do not contain the firmware control to make lights blink or fade up/down. It is up to the user to put the necessary firmware ONTO the chip. The process for putting firmware on a chip is called "flashing the chip." Once the chip has been flashed with firmware, it retains that firmware whether the chip is powered on or not. If you remove the chip from the controller, the firmware remains stored on the chip, and it remains there unless you either erase it or replace it with different firmware. Most chips can be reflashed with different firmware many tens or hundreds of thousands of times, so you don't have to worry about wearing it out. But it's important to know that the firmware for one type of chip may not work on a different kind of chip. This is because of the internal electrical design of the chips themselves -- it's not a one-size-fits-all kind of thing. Some chips have only 8 pins or "legs" while others may have 14, 16, 18, 24, or 40 pins, and each chip's internal structure is different, so you must use the firmware designed for the chip you're using in your controller or the firmware likely won't work. For example, if you drive a Corvette, you use gasoline fuel. You can't put diesel fuel in the Corvette and expect it to run. Firmware is like that. You need the right firmware for each kind of chip.
Firmware comes in two basic formats: source code and compiled code. The source code is the human-readable format that is written/modified using common text editor tools. The source code is usually modified by the user to tweak it to his/her needs. For example, you might want the controller to use a specific communication speed so your computer can talk to it. The communication speed (i.e. baud rate) is a number that you would change in the source code. Then you would use a piece of software on your computer to load the source code and "compile" it into compiled format. While the source code is the stuff humans understand, the compiled code is the machine code that the chip understands; the "compiler" transforms the source code into machine code. Compiled, machine code is usually a "hex" file because it typically has "hex" at the end of the file name, such as renard_dmx.hex. Source code is often referred to as "asm" because the file name may have "asm" at the end of the file name, such as renard_dmx.asm. If you're curious, here's what source code and compiled code looks like:
In the case of the source code (above, left) notice the text formatting. Source code lines must be kept intact when editing -- they cannot be combined together like the following example. This sometimes happens if you edit and save the code with a text editor that is set to use "word wrapping." The compiler can't understand jumbled code like this and subsequently won't compile it.
The compiler is not generic for all chips. It is provided by the chip manufacturer for that manufacturer's chips and is usually free. This is the case with Microchip's products although some others may require purchase. Microchip's compiler will not work with chips manufactured by Atmel -- you need Atmel's compiler for them. The Propeller chip is manufactured by Parallax, so for their chips, you need whatever compiler Parallax recommends. See how this works? If you use all different kinds of controllers, you may need many different kinds of software compilers installed on your computer. Sounds complicated but it's really pretty logical.
Because of the many differences in compiler display screens and options they are not shown here. There are ample video tutorials available on the Internet and usually from the manufacturers' web sites as well and users are encouraged to seek them out. Suffice to say that the following outline is the general sequence used by most compiler software:
- Start the compiler software.
- Set the compiler's options to use a specific programming device that's approved for use by the compiler software. Your device may or may not be on the list. If it is a compatible device, you may have to try different options.
- Set the compiler's options for the specific chip to be used.
- Load the desired source code file into the compiler's editor.
- Make the desired changes to the source code.
- Save the revised source code.
- Select to "compile" the source code. The output format is normally a ".hex" file.
- Select the option to "flash" or "write" the compiled (hex) firmware to the chip using the programming device.
- Note that sometimes one or more of the above steps may be combined together into a single step.
In cases where the compiler doesn't recognize the programming device you have, you can usually still compile the source code into the resulting hex file, and later, flash the chip using the software for your programming device.
Compiler Errors and Warning Messages
Sometimes an error code may appear on your screen when you select to compile the source code into hex code. Some of these messages are terminal errors and some are only warnings. When a terminal error occurs the hex file probably won't even been created. The down side to such error messages is that with assembly language code (which is what source code normally is), there is generally little additional on-screen information provided that tells you what's wrong. The error code is very cryptic and terse, usually telling what line the error is on and the compiler just stops dead in its tracks. Example: "Hey buddy, you've got a problem on line 309" and that's all you get. In some cases you might get a hint that it's a syntax error (probably a typo) or an undefined variable, but more often than not, you get nothing.
When a warning message appears, it's likely that the hex file was created and the only way you'll know whether it works or not is to flash the chip with it and try it out. A typical warning message might be related to start address firmware where the chip's internal address for the storage of the start address setting may not be recognized. If you flash the chip anyway and subsequently discover that the chip responds properly with that address, you'll know that particular warning message is okay to ignore. In some cases, one warning message will cause a second or third warning to appear but the compiler will create the hex file anyway. Will the firmware work? Flash the chip and try it.
This is an electronic device that physically connects to your computer, often via USB port, and you either plug the chip into it or use an ICSP (in-circuit serial programmer) connection to the chip to electrically program it with the compiled hex firmware. A popular programmer for Microchip's PIC chips is the PicKit from Microchip, available in multiple models. The PicKit-3 with additional options is shown below.
The PicKit-3 is recognized by Microchip's compiler and makes for a seamless way to modify firmware, recompile and flash Microchip's products. There are many clones of the PicKit-3 (and other PicKit models) on the marketplace via eBay, Amazon and other online stores. While some clones may work perfectly fine and you may save a few dollars on purchasing one, consider that the programmer is one of the most important tools you can have and in the long run, you may be better served by buying the original product from vendors that the manufacturer endorses.
Problems users may encounter with "clone" programmers:
- The computer doesn't recognize the USB device.
- The compiler software doesn't recognize the programming device.
- The programmer is cheaply made or assembled, causing inconsistent behavior.
- There is no support from the manufacturer; don't expect Microchip to support non-Microchip products.
- Standalone programming software may not recognize the programming device.
- The programmer may have flaws that produce inconsistently programmed chips, which then perform erratically if at all.
- The programmer may be of an older design and consequently won't work with the newer chips.
This is an acronym for "in-circuit serial programming" and it refers to leaving the chip in the existing circuit and programming it there instead of physically removing the chip, placing it in the programmer, flashing the chip, then removing it from the programmer and putting it back into the circuit. Sometimes a chip is soldered directly into the circuit board, making removal problematic. Some circuit boards have a 5 or 6-pin ICSP header built into the board which allows connecting the programmer to the board and programming the chip that way in case the chip is soldered-in or otherwise difficult to remove.
Not all circuit boards have such ICSP connections. They have proven to be generally convenient and popular to use, especially when the chips in question have 24, 32 or 40 or more pins such as the Renard Plus controllers do. Removing a 40-pin PIC chip from its socket can be a daunting task and if not done carefully, the socket or the chip can be damaged. ICSP simplifies reprogramming the chip's firmware.
- Test Clip ICSP: Another type of ICSP connection can be made using a spring test clip, which clamps onto the chip's pins. You simply connect the necessary clamp connectors for the chip in question to the proper ICSP wires for the programmer -- works slick.
- CAUTION: An ICSP connection provides for direct electrical access to specific pins on the PIC chip itself, so care should be taken to make sure the cable connecting the programmer to the ICSP header hits the right pins. A chip can be electrically damaged if the wrong connections are made.
Changing Firmware Settings
First of all, understand that program source code is written by many different authors and consequently, code design is usually different using perhaps different words, different variable names, different locations within the code may be reserved for different functions, etc. Therefore, there isn't a hard-and-fast rule for declaring and designing the code -- and to make changes, sometimes you have to search within the source code for the items that you can change. In some cases, the original programmer may insert comments into the code to tell you what you can change and what you should NOT change.
But there are many common items that users change and it's worth noting some of them here. More often than not, you'll find these items somewhere near the beginning/top sections of the source code and they're often listed as a #define variable. Do NOT change the name of the variable -- they are usually upper/lower case sensitive. Usually all you need to change is the number or value that follows the variable name: in some cases, defining an item to 0 or 1 means that 0 is the "off" or "false" setting while 1 is the "on" or "true" setting. Also take heed of the formatting of the line which is very specific; where there's a space, keep the space. Don't insert any extra spaces between anything. The variable names here are just examples of some names that might have been used in the code you're reviewing:
- Oscillator or crystal speed. This is what sets the overall speed of the chip itself which relates to how fast it can process tasks. Some chips can operate at different speeds and this generally is used to set the chip to its best speed for optimum performance. You might look for something like:
- #define CLOCKRATE 18432000
- #define OSCRATE 16000000
- #define CLKSPEED 12000000
- Baud rate. This is the speed at which the firmware can receive data from the computer. For example, if the computer is set to send data at 57600 baud, then the chip has to be set the same way or it won't be able to receive the data. Some ideas of things to look for:
- #define BAUDRATE 115200
- #define COMSPEED 9600
- #define BAUD 57600
- Address. This is sometimes referred to as "start address" and is usually related to the channel number that the controller will use as it's first channel. However, it could also mean something else, such as a DMX universe, so you may need to do some research on what the author meant by the term address.
- #define START_ADDR 27
- #define ADDRESS 4
- #define DMX_START_ADDRESS 1
- PWM. This stands for 'pulse-width-modulation' and it relates to the method the firmware uses to deal with dimming. It can apply to either AC or DC lights. Generally speaking, PWM provides for smoother dimming.
- #define PWM 1
- #define PWM_MODE 0
- #define PWM TRUE
- DC settings. This usually relates to something that affects LED lighting and is sometimes closely related to PWM. If so, usually the firmware makes a comment about the setting itself. Generally speaking, the zero-cross signal is needed only for AC lights and in DC mode, the program can usually skip the AC-related computations, thus allowing the chip to be more efficient.
- #define DC_BUILD 0
- #define DCBUILD 1
- CTR_LOCKOUT. This is more related to LED lighting than for A/C incandescents and isn't always used. It's a setting that can change how LEDs react to the firmware in the lower intensity range -- the LEDs dim down further before they go out when this setting is lower.
- #define CTR_LOCKOUT 40
- #define CTR_LOCKOUT 32
- #define CTRLOUT 16
- Output Polarity. This is a tricky little thing that reverses the "on" setting from being high on the output pin (+5V) to being low (0v). Long explanation here, but it essentially changes whether the output reacts to positive output or negative output. Since it's a true/false setting and if it's active, the value becomes true. Simply placing a semi-colon comment mark at the very start of the program line turns the line off and logically sets the value to false. This setting exists to accommodate different kinds of electrical circuits: some of them invert the polarity of the signal on their own and this setting in effect "fools" them so when the circuit inverts the signal, the result is a properly polarized signal sent to the remote devices.
- #define OUTPUT_NEGATIVE_TRUE
- ; #define OUTPUT_NEGATIVE_TRUE (the semi-colon at the start of the line would make it false)