eZ430-F2013 - 4 Channel PWM program, with cursor, and edit keys - debounced.
I've been writing a PWM program - it uses arbitrary clock speeds, but with a couple of small and simple tweaks can be turned into an interrupt driven system to fix the frequency of the outputs at a set rate.
Pins 0-3 are the output pins.
Pins 4-7 are the user-control input pins.
There are two timings for each LED - the number of cycles the LED is on (LEDOn), followed by the overall number of cycles (dutyCycle). So if LEDOn is 2, and dutyCycles is 10, the following output is seen on an oscilloscope:
T-State : LED output
1 : On
2 : On
3 : Off
4 : Off
5 : Off
6 : Off
7 : Off
8 : Off
9 : Off
10 : Off
This is the same for all 4 LED's.
To select which attribute is being changed, the Up and Down attribute select buttons are pressed... these cycle through LEDOn for LED 1, dutyCycle for LED 1, LEDOn for LED 2, dutyCycle for LED 2, LEDOn for LED 3.... and so on.
The other two buttons amend the value of the attribute by +1 or -1.
Here's the test board. The two buttons on the left are the attribute-select buttons, and the bottom two are the attribute increase/decrease buttons.
Also, the potential dividers aren't used - I've just not took them off the board yet!
The code takes up 570 bytes of the 2048 available, and just 2 bytes of RAM of the 128 bytes available.
I have no idea how the compiler figured those sizes out, I would have thought the RAM used was more like 40 bytes?
#include <msp430x20x3.h>
int main(void)
{
unsigned short int index;
WDTCTL = WDTPW + WDTHOLD;
DCOCTL=CALDCO_16MHZ;
BCSCTL1=CALBC1_16MHZ;
P1REN=0xF0; //Pull them up?
P1DIR=0x0F; // High nybble in, low nybble out.
P1OUT=0;
// Having both the "Duty" and "On" cycles interleaved in the single array means we can
// use a simple cursor that acts as an index to step through both the Duty values, and On
// values of each LED, rather than needing more conditional code.
unsigned short int cycles[8];
unsigned short int currentCycle[4];
unsigned short int output[4];
unsigned short int cursor=0;
unsigned short int lastInput=0;
unsigned short int thisInput=0;
unsigned short int debounceTimer=0;
for(index=0;index<4;index++)
{
cycles[index*2]=5;
cycles[index*2+1]=2;
currentCycle[index]=0;
}
for(;;)
{
//I shift the high 4 bits right, to the low bit positions, because they're easier for me to add up
//There's no software reason....
thisInput=P1IN>>4;
//If the button is bouncing, going from high to low, or low to high, the debounce timer is set.
//This ensures we get a good 100 iterations of consistent button state before we action the button.
//This number "100", could be set to a higher value for buttons that bounce more, or less,
//for buttons that bounce less frequently. It also depends on the clock speed...
//e.g. Running at 1MHz, the debounceTimer could be set to a value of around 5 as the button
//will have stopped bouncing during the time it takes the program to loop around 5 times...
if(thisInput!=lastInput)
debounceTimer=100;
lastInput=thisInput;
if(debounceTimer>0) debounceTimer--;
//The following section is run when the debounceTimer is 1, and not 0 which is what the timer counts down to...
//This is to ensure that the keypress is actioned just once, and only when the key pressed
//state had been consistent for several itterations around the program.
if(debounceTimer==1)
{
if(thisInput&8) cursor>0?cursor--:cursor;
if(thisInput&4) cursor<7?cursor++:cursor;
if(thisInput&2)
{
cycles[cursor]>0?cycles[cursor]--:cycles[cursor];
//Check that the overall cycles time isn't less than the on time!
//If it is, drop it down too.
if(cursor%2==0)
{
if(cycles[cursor]<cycles[cursor+1]) cycles[cursor+1]=cycles[cursor];
}
}
if(thisInput&1) cycles[cursor]<255?cycles[cursor]++:cycles[cursor];
{
if(cursor%2==1)
{
if(cycles[cursor-1]<cycles[cursor]) cycles[cursor-1]=cycles[cursor];
}
}
}
for(index=0;index<4;index++)
{
output[index]=0;
if(++currentCycle[index]<cycles[index*2+1]) output[index]=1<<index;
if(currentCycle[index]>=cycles[index*2]) currentCycle[index]=0;
}
//Change all the outputs at once to avoid skew.
P1OUT=(output[0]+output[1]+output[2]+output[3]);
}
}