Tuesday, March 4, 2014

Access Memory Mapped Registers


woaahh I hear you, chill bro!!
To get the feel of it, first get rid of the outer most bracket and the asterisk at the left:
((volatile unsigned long *)0x12345678)
looks easy now?

Whats happening here is that we made a pointer that points to the address 0x12345678 in the memory(RAM).
In other (pro)words we type-casted 0x12345678 to a volatile unsigned long pointer.

The volatile keyword here makes sure that you will get the current value from the address 0x12345678.
For more information on volatile kindly see this shit.

so
((volatile unsigned long *)0x12345678) is a pointer

Now when we de-reference it with the asterisk on the left like so
((volatile unsigned long *)0x12345678)
 to access the value stored at this location.

EXAMPLE:
This technique is used to read write IO mapped registers among other things.
 
a) Reading
Suppose in an SoC the output of an ADC is stored in a register which is mapped to location 0xDEADBABE.
We will always want the updated value of ADC in mission critical systems hence we will use the volatile keyword.

#define     ADC    (*((volatile unsigned long *)0x12345678))

then in code to read the value of ADC in a variable temp we simply do:
temp = ADC; // cool ryt? 

b) Writing
The same technique can be use to write the value to a memory mapped register.
Suppose we have a 32 bit output port called LEDBANK located at 0xCAFEC0DE then

#define     LEDBANK    (*((volatile unsigned long *)0xCAFEC0DE))
LEDBANK = 0xDECAFBAD

and 0xDECAFBAD will be transferred to LEDBANK

If you need more help, kindly leave a comment below :)

Friday, July 8, 2011

Knight Crawler

Hello everyone, i'm trying to build a 256 color (8-bit) pov display with animation, based on Arduino and the 16-channel pwm controller TLC5940. This post discusses a mini-project titled "Knight Crawler" , which i made to get familiar with the basics of interfacing the TLC5940.


KNIGHT CRAWLER



Better Quality video - Coutesy of SlashDot



Circuit Diagram

Yesterday i began the experimentation with TLC5940 and interfaced it with arduino according to the info on this page and installed the library to the relevant arduino directory.

After going through the "basic use" example from the TLC library i decided to write my own code. First step was to find the correct ratio of forward current flowing through Red, Green and Blue leds to produce a white light. After playing with different values of pwm for red,green and blue channels i figured out that the correct ratio is R:G:B=4:1:1. i.e G=B=(1/4)*R for white light.

The TLC5940 comes with 16 pwm channels, each having 4096 steps of greyscale. It means that the TLC can divide the max value of current flowing through a channel into 4o96 discrete steps.
In the TLC library we define the output of a channel with the function:

Tlc.set(channel no, greyscale value);

so to produce a white light, i connected an rgb led with its red,green and blue cathodes into channel 0,1 and 2 respectively. And the values i passed on to Tlc were (R=4095,G=1023,b=1023). But since its not a good practice to use a device at its max potential i decided to stick with the round figures of 4000,1000,1000.

Heres the code for white light... i will explain the functions used in this code in a while... hang on :)
/*************************************
7-8-11
7:46 pm
*suggestions and queries are welcomed
*Abdur-Rehman mani16pk@gmail.com
**************************************/
#include "Tlc5940.h"

void setup()
{
Tlc.init();
}

void loop()
{
int
R=4000,G=1000,B=1000;

delay(1000);
Tlc.set(0,R);
Tlc.update();
delay(1000);
Tlc.set(1,G);
Tlc.update();
delay(1000);
Tlc.set(2,B);
Tlc.update();
delay(1000);
}
/*********************************************/



After learning the magic spell of 4:1:1 it was time to do some tricks.
Some keys punched and the result was a sketch that rotated 5 colors red,yellow,cyan,magenta,
and white on 5 RGB leds. A mini Color-Scroller.

Color Scroller


below is the code... functions of this and the previous code will be explained soon, stay tuned...

/**********************************************************
7-8-11
9:04 pm PST
*
This sketch rotates 5 colors i.e red,yellow,cyan,magenta,
and white on 5 RGB leds
*
Abdur Rehman
mani16pk@gmail.com , queries and suggestions are welcomed!
/**********************************************************/
#include "Tlc5940.h"

void setup()
{
Tlc.init();
}

void ledColor(int lednum, int color)
{
int r=0,g=0,b=0;
if (color==1) //red
{
r=4000;
g=0;
b=0;
}
if (color==2) //Yellow
{
r=4000;
g=1000;
b=0;
}
if (color==3){ //cyan
r=0;
g=1000;
b=1000;
}
if (color==4){ //magenta
r=4000;
g=0;
b=1000;
}
if (color==5){ //white
r=4000;
g=1000;
b=1000;
}

Tlc.set((lednum-1)*3+0,r) ;
Tlc.set((lednum-1)*3+1,g) ;
Tlc.set((lednum-1)*3+2,b) ;
}

void loop()
{
int del=500;
ledColor(1,1);
ledColor(2,2);
ledColor(3,3);
ledColor(4,4);
ledColor(5,5);
Tlc.update();
delay(del);
ledColor(1,5);
ledColor(2,1);
ledColor(3,2);
ledColor(4,3);
ledColor(5,4);
Tlc.update();
delay(del);
ledColor(1,4);
ledColor(2,5);
ledColor(3,1);
ledColor(4,2);
ledColor(5,3);
Tlc.update();
delay(del);
ledColor(1,3);
ledColor(2,4);
ledColor(3,5);
ledColor(4,1);
ledColor(5,2);
Tlc.update();
delay(del);
ledColor(1,2);
ledColor(2,3);
ledColor(3,4);
ledColor(4,5);
ledColor(5,1);
Tlc.update();
delay(del);
}
/**********************************************************/

Finally the epic "Knight Crawler"

i had daisy-chained 3 TLCs and was wondering what to do with them, then an LED blinked in my brain, and i decided to make color changing Knight Rider lights.

The code is shown below, comments explain whats happening inside.

/**********************************************************
7-9-11
12:48 pm PST
*
KNIGHT CRAWLER
*
Abdur Rehman
mani16pk@gmail.com , queries and suggestions are welcomed!
/**********************************************************/

#include "Tlc5940.h" //Tlc library

void setup()
{
Tlc.init(); //Tlc initialization routine
}

void ledColor(int lednum, int color)
/* This function takes two arguments: 'lednum' which tells the
Tlc's which led to light up and the 'color' which takes a value
between 1 and 10. The pwm values for r,g and b channels are
assigned in the if statements which check for the color number
and assign the respective values of color intensities to that
led*/
{
int r=0,g=0,b=0;
if (color==1) //red
{
r=4000;
g=0;
b=0;
}
if (color==2) //green
{
r=0;
g=1000;
b=0;
}
if (color==3){ //blue
r=0;
g=0;
b=1000;
}
if (color==4){ //cyan
r=0;
g=1000;
b=1000;
}
if (color==5){ //magenta
r=4000;
g=0;
b=1000;
}
if (color==6){ //yellow
r=4000;
g=1000;
b=0;
}
if (color==7){ //white
r=4000;
g=1000;
b=1000;
}
if (color==8){ //orange (red+yellow)
r=4000;
g=500;
b=0;
}
if (color==9){ //violet (blue+magenta)
r=2000;
g=0;
b=1000;
}
if (color==10){ //spring green (green+cyan)
r=0;
g=1000;
b=500;
}
/*i figured out the following algo after doing a little
paper pencil math work. i was connecting the...
led1 on ch0,1,2
led2 on ch3,4,5
and so on to
led16 on ch46,47,48
*/

Tlc.set((lednum-1)*3+0,r) ; //Tlc.set passes the values to Tlc
Tlc.set((lednum-1)*3+1,g) ; //but these values do not show up on
Tlc.set((lednum-1)*3+2,b) ; //pins untill we use the Tlc.update function
} //which i'm using in the main loop.

void loop()
{
int del=500;
float x,y,z;
for (x=1;x<=10;x++) // outer x loop changes the color
{
for (y=1;y<=16;y++) // first y loop scrolls in 1 direction
{

ledColor(y,x); //passing the parameters to function
Tlc.update(); //The greyscale values are not updated untill v use this function
delay(50); //50ms delay

}
x++; //then x is incremented to change the color
for (y=16;y>=1;y--)// second y loop scrolls in the opposite direction
{

ledColor(y,x); //passing the parameters to function
Tlc.update(); //The greyscale values are not updated untill v use this function
delay(50); //50ms delay

}

}
// well the loop continues and leds glow happily for ever :)
}