After completing stage 1 and reviewing it with my friends I decided that it needs the following changes and additions – hence stage 2:
- Manage 4 LEDs and not only two as in the code of stage 1
- Allow the app to change the state of each LED to OFF, ON or BLINKING while the app is running. This is a fundamental feature for the full LED controller because the user will be changing the state of the LEDs by the remote control.
- Allow the app to set the intensity of each LED
- Change the LED Controller API functions to start with LC in order to avoid namespace collisions with the client app (although I realise that this is for a tiny PIC and not a desktop).
In short, I wanted my application code (main.c) to look like this:
[file]http://www.qcptr.com/code-snippets/led-controller-stage-2/main.c[/file]
The file starts with the regular setting of the configuration words and then defines an array of “state” structures:
struct {
LEDState state;
short blinkCount;
short intensity;
} states[] = {
{LEDON, 0, 10},
{LEDBLINKING, 1, 5},
{LEDBLINKING, 3, 15},
{LEDOFF, 0, 15},
{LEDON, 0, 15},
{LEDBLINKING, 4, 10}
};
Each state consists of an action – Off, On or Blinking. If the state is “blinking” then the second member is the number of blinks and the third member is intensity – a number between 1 and 15 where 15 is brightest and 1 is the least bright.
The array contains six different states and LED 1 (the rightmost LED will cycle through these states.
The main function itself sets up LEDConfig structs, sets the initial states for each LED (note that LED 2 – the second from right) is OFF throughout and enters the main loop. In the main loop LED 2 will remain off. LEDs 3, and 4 will blink at a fixed rate and LED 1 will move through the states above.
This is how it looks like:
The header file now contains some #ifdefs that allow it to compile and run on an iOS device (more about that later). The LEDConfig structure was changed from stage 1 and the functions are prefixed with LC.
Here is the header file.
[file]http://www.qcptr.com/code-snippets/led-controller-stage-2/ledcontrol.h[/file]
The LED controller C file is here:
[file]http://www.qcptr.com/code-snippets/led-controller-stage-2/ledcontrol.c[/file]
A word on the (free) XC8 compiler
It seems that the free XC8 compiler is extremely inefficient in transforming the C code to assembly. I noticed that dereferencing a member in a struct requires countless assembly commands. For example, the command (from main.c):
946 ;main.c: 56: short b = states[index].blinkCount;
maps to the following assembly code:
947 02F3 3005 movlw 5
948 02F4 00A2 movwf ??_set_state
949 02F5 0822 movf ??_set_state,w
950 02F6 00F1 movwf ___bmul@multiplicand
951 02F7 0820 movf set_state@index,w
952 02F8 23D5 fcall ___bmul
953 02F9 3E01 addlw 1
954 02FA 3EA0 addlw _states& (0+255)
955 02FB 0086 movwf 6
956 02FC 0187 clrf 7
957 02FD 3F40 moviw [0]fsr1
958 02FE 0020 movlb 0 ; select bank0
959 02FF 00A4 movwf set_state@b
960 0300 3F41 moviw [1]fsr1
961 0301 00A5 movwf set_state@b+1
When the compiler finishes it gives me the following statistics:
Memory Summary:
Program space used 3FEh ( 1022) of 800h words ( 49.9%)
Data space used 7Eh ( 126) of 80h bytes ( 98.4%)
EEPROM space used 0h ( 0) of 100h bytes ( 0.0%)
Data stack space used 0h ( 0) of 1h byte ( 0.0%)
Configuration bits used 2h ( 2) of 2h words (100.0%)
ID Location space used 0h ( 0) of 4h bytes ( 0.0%)
This means that not much is left for the rest of my controller code on this chip. The compiler also says that if I’ll buy the PRO version it will shrink the code by 40% and I will save 408 words.
Other areas of inefficiency in my code are the modulo-6 operation (index = (index + 1) % 6) and all the function calls that are an inherent part of the “pseudo object oriented programming” that I use here
Despite of all this inefficiency, I think it is worth writing in C because it it much more readable (to most of us) and allows us to give the program some structure. I think it is possible to overcome the memory capacity problem in several ways:
- Use a larger chip – the price difference is probably negligible
- Write some parts of the code in efficient assembly (will take me ages)
- Buy the PRO version of XC8
- Buy another compiler for the PIC processor. I found one for $50.
- Check out the GPUTILS – Gnu PIC utilities – I’m going to do this right after I finish this post.
The next steps towards the final LED controller are:
- Add a potentiometer that will control the length of the blink of the LEDs
- Learn how to receive a PWM signal into the PIC
- Revisit the product requirements and modify (I have some ideas for modifications already)
- Write a good specification of the init and initial configuration stage. This is not simple as it sounds.
- Implement the init and configuration stage
- Define the states and update the main function
- Test on the breadboard with regular LEDs – add the transistors to the circuit for driving the LEDs
- Build the real circuit with the high-power LEDs that I ordered
- Build a few more kits and try to sell them