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. }