Hi all,
A few years ago i built an LED cube and i never stop wandering how it actually worked. So i did some research and found that bit angle modulation was one of the most important aspect of it. I couldn't really find any C code examples so i created my own. The code turns a led on and makes it more brighter. Is there a way to make the code more efficiëntly?
/***************************************
* PROJECT: Bit angle modulation example
* AUTHOR: Steve
* VERSION: 1.0
**************************************/
#define F_CPU 16000000UL //Define CPU speed because timing for the interrupt is important.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
int bitResolution[8]; //Define the bit resolution for the bit angle modulation. In this case it's 8-bit.
int bitShift = 0; //Used to store a bit value.
int ledBrightness = 0; //Used to store the led brightness.
int cycleCounter = 0; //Used to count the micro controller cycles.
int main(void)
{
ioInit();
while (1)
{
if(ledBrightness > (int)pow(2,(sizeof(bitResolution)/sizeof(int)))-1) //When the brightness value is bigger than the maximum bit value (2^8=255 (counted from zero) in this case).
{
ledBrightness = 0;
}
brightnessMask(ledBrightness); //Calling method that handles the bit mask.
bitAngleModulation(); //Calling method that handles the bit angle modulation (BAM).
}
}
void ioInit()
{
TCNT1 = 0x00; //Initialize the timer value.
TCCR1B = 0x0D; //Enable the CTC mode and prescale the clock by 1024 (clock/1024).
TIMSK1 = 0x02; //Enable interrupt on match between OCR1A and TCNT1.
OCR1A = 15; //After 15 cycles there is a match between OCR1A and TCNT1. A interrupt will occur.
sei(); //Enable interrupts.
DDRD = 0x01; //Define the output register.
}
void brightnessMask(int brightness)
{
for(int i = (sizeof(bitResolution)/sizeof(int) - 1); i >= 0; i--) //I use a decreasing for loop. Because the bit value always counts from right to left. So we want to have the lowest value on place 1 in the array.
{
if(brightness - (1<<i) >= 0) //Compares if the brightness value minus the shifted value is bigger or equal as zero. If that is the case the bit should be 1. Otherwise 0.
{
brightness -= (1<<i); //Safe the current value
bitResolution[i] = 1; //Write a one to a specific array place.
}
else
{
bitResolution[i] = 0; //Write a zero to a specific array place.
}
}
}
void bitAngleModulation()
{
for(int i = 0; i < sizeof(bitResolution)/sizeof(int);i++) //Loop as long as the value of the bit angle modulation you defined.
{
bitShift = (1<<i); //Store the value of the current bit.
for(int j = 0; j < bitShift; j++) //Loop as long as the value of the current bit. (Example: 0b0100 has a value of 4. This means that the for loop would loop 4 times)
{
if(bitResolution[i] == 1) //Compare if the specific array place contains a bit value of 1.
{
PORTD = 0x01; //Enable the output
}
else
{
PORTD = 0x00; //Disable the output
}
}
}
}
ISR(TIMER1_COMPA_vect)
{
/* Calculate how fast you want to change brightness. It is done with the following calculation:
Clockspeed/prescaler/OCR1A/100 = brightness change frequency. So in this case it goes as followed:
16.000.000/1024//15/100 = 10,41 hertz. This would mean that it takes (1/10,41)*255 = 24,52 seconds to go from 0-255.
*/
if(cycleCounter > 100)
{
cycleCounter=0; //Reset cycle counter
ledBrightness++; //Increase brightness by 1.
}
cycleCounter++; //Increase cycle counter by 1.
}