NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Managing data tables

November 18, 2009
by gnkarn
gnkarn's Avatar

I would like to generate data tables ( 1 byte each data), in order to use the data to write "pre generated" patterns to a led array. How can i put the data table in program memory?, Which function may I use to read from data table line0 to data table finish one address at a time? thank you

November 18, 2009
by hevans
(NerdKits Staff)

hevans's Avatar

Hi gnkarn,

In C, there is no real concept of a table, the best you can do is an array of arrays. However, since the data for the LED Array is held as an array of ints, you can probably get away with holding int arrays in memory to represent the different patterns with one uint8 per column.

To put an array in program memory, you need to use the PROGMEM modifier, so:

const uint8_t pattern1[] PROGMEM = {0x00,0x00,0x00,0x00};

My array above contains all 0s, and only 4 ints. But yours could contain the pixel data for your array. To retrieve an integer you would use the function memcpy_P() which copies data from one place to another. The _P means that this variant of the function expects one of the arrays it is copying from to be in program space. So if I had some data array in RAM I wanted to copy my pattern1 into you could do.

memcpy_P(myDataArray, pattern1, n);

Where n is the number of bytes you want to copy. All this good stuff can be found in the Program Space avr-libc documentation.

It takes a bit of time and hacking around to get very familiar with these concepts, but go ahead and try it, and let us know if you have any questions.

Humberto

November 23, 2009
by gnkarn
gnkarn's Avatar

Humberto and all, thanks for the comments, I have the prgramm working and i´m experimenting with including interrupts in my code, I have changed a working code with the needed modifications just to make the leds array to be writen by the int handler, now nothing works , even the display ( i kept the display for debugging purposes, in order to see where the program is).

Here is the timer and interrupt part of the code so can see what am I missing , thanks,

// ************ initialize timer *********
void ledarray_init() {
// Timer0 CK/64 (900Hz) , Fclck=14745600 , prescale = 64 y counter = 255(then interrupt is generated at 900 hz
TCCR0B = (1<<CS01) | (1<<CS00);
TIMSK0 = (1<<TOIE0);

// enable the LED pins as outputs

DDRC |= 0b01111111 ; DDRB |= 0b00111111 ; //RGB latch control lines }

// bad interrupt do nothing
ISR(BADISR_vect)
{
// user code here
}

// *************************************************************************************************

// *** interrupcion ** MODIFICAR

SIGNAL(SIG_OVERFLOW0) {
PORTB &=0xf8; // PONE EN 000 RGB   dejand bits 3 y 4 sin cambio
PORTC = byte;
  buffer = (byte >> 3);
  PORTB = ((buffer & 0x18)|Color);//00011000 bits 3 y 4 go an latches the proper color 
    lcd_line_four();
    lcd_write_string(PSTR("signal "));
    lcd_write_int16(byte);

     }
November 23, 2009
by gnkarn
gnkarn's Avatar

ok, is partially working now, i found that the vector name was wrong, must be TIM0_OVF_vect, but the interrupt itself is still not working, the leds display is.

continue debugging...

November 23, 2009
by gnkarn
gnkarn's Avatar

it seams that the main function is executing partially, I understand that this is not possible, but it explains the symptoms.

the following code of the main function is only doing the first part, the "loop forever" appears not to executed at all. Strange isnt it?, it seams to stay all the time on the interrupt routine

int main() { ledarray_init();

  // start up the LCD
  lcd_init();
  FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, 0, _FDEV_SETUP_WRITE);
  lcd_home();
 lcd_line_one();
  lcd_write_string(PSTR("main "));
  sei();// activate interrupts
// loop forever!
  while(1)
 {
    lcd_line_three();
   fprintf_P(&lcd_stream, PSTR("%16.2f sec"), (double) reloj);

  snakeini();
  snakeout();
  snakein();
  snakeouti();
  escribedata();
}

return 0; }

November 23, 2009
by BobaMosfet
BobaMosfet's Avatar

Perhaps this will help, conceptually at least. When you activate interrupts, it means the processor is in full control of your program, not the other way around. It means that when something occurs (some event) that triggers an 'interrupt'- the processor does just that-- it interrupts your code and runs the code that the interrupt vector (aka interrupt jump table) points to.

If you have something causing constant interrupts out of the gate, as soon as you activate interrupts, the processor will begin serving those interrupts and your while may never get executed-- you need to service those interrupts first.

November 23, 2009
by hevans
(NerdKits Staff)

hevans's Avatar

Hi gnkarn,

I think you are running into one of the main reasons why using interrupts is considered an "advanced" topic. They can be very very hard to debug. In a normal program with a single flow of execution you can stick calls to printf or lcd_write wherever you want and your program will still work the same. When you bring interrupts into the equation, the time it takes for these debug statements to run can drastically change the way your program operates. Lets take a look at your program, remembering that the timer interrupt is firing at 900Htz (every .001 sec). That means that in order to keep from one one interrupt firing immediately after the other, the interrupt itself better take a lot less than 1 millisecond to run if it is to let other things run after it is done. See our Interrupts tutorial for a great demonstration of this concept.

In your program, the calls setting PORTB, PORTC, and shifting are each about one instruction, each taking about .06 microseconds, that is so tiny that it doesn't matter. However, take a look at how long the calls to the LCD lines take. The LCD device itself is very slow. If you take a look at lcd.c, you will see that every call to lcd_write_byte() has an 80 microseconds built in delay. The call to lcd_line_four() uses this once, and the call to lcd_write_string() calls it once for every character. This means that in those two lines you have already used at least 80microseconds*8 = 640microseconds. This is without including the delays in writing the integer, and all the overhead of the function calls themselves. You can see how all this can very easily add up to more than 1 millisecond resulting the main function never getting a chance to run.

The fact that you have to be very careful about how long your interrupt handlers take to run is a great lesson to learn. In general, you will not have time to print to the LCD, or to the serial port in an interrupt handler. You can often get away with printing debug information about your interrupt handlers in the main() method by printing out the current state of a global variable. If you really need to, you can blink an LED on and off inside the handler, that is usually quick enough that it won't affect the overall system.

On another level, you can turn this lesson into a deeper concept and realize you can never really observe a system without changing it. Sometimes changing it so much that it is not at all what you were trying to observe anymore. It is something to be aware of when coding, measuring voltages, or doing quantum physics.

Humberto

December 19, 2009
by BobaMosfet
BobaMosfet's Avatar

Quote: "In C, there is no real concept of a table, the best you can do is an array of arrays."

coughs... ahem... 'structs'.... typedef struct.... makes for fine tables.... coughs. Just in an array....

Just thought I'd clarify slightly.... :P

December 20, 2009
by hevans
(NerdKits Staff)

hevans's Avatar

You are right BobaMosfet. I stand corrected. =)

Perhaps I should have said: There is no higher level data structure that directly implements a table the way you are used to thinking about it. You have to figure out a way to create the data structure yourself. Either with nested arrays, structs that group arrays, arrays that group structs, structs that group other structs, or any sort of ingenious combination thereof.

Humberto

December 21, 2009
by BobaMosfet
BobaMosfet's Avatar

Humberto--

It's just that I've been coding for over a quarter of a century-- been there and done that. If you think interrupts are tough, try working (the way it was in the beginning) in an environment that had interrupts.... and self-modifying code. Very, very useful trick that, when memory is at $1Million/1KByte.

You do realize this ATMEGA168 is many, many times more powerful than the DEC PDP8 that put man on the moon? It's even more powerful than the MC68000, in the first Mac.

Can't thank you guys enough. Simply put, you've changed my life, and given me the opportunity to pursue dreams I thought were gone, never-gonna-happens, 10 years ago.

You have done the best thing any teacher can do-- provide an excellent starting point, with enough meat to be challenging and yet enough support to prevent someone from crashing and burning-- but ultimately, what you offer is hope and inspiration, and a pointer in the right direction-- the student must be able and willing to run (not walk) with it, if they want it.

I want this.... I want this more than anything I've ever done in my life. I'm not sharp in the head like you guys-- you're gifted, and unlike many, you are really taking advantage of it and putting your innate abilities to good use and helping people. I'm a plodder... slow but steady. What I lack in brains, I make up for in determination.

I hope you guys have the most wonderful and amazing Christmas and 2010, EVER! Same goes to all the rest of you wire-heads :P

December 21, 2009
by Rick_S
Rick_S's Avatar

Boba, I couldn't agree more with your statements to the NK guys. I have to say thank you to you as well considering the detailed explanations you have provided in some of the threads. Thank you for the Christmas wishes. I would like to extend those wishes to everyone as well.

Rick

December 21, 2009
by JKITSON
JKITSON's Avatar

Rick & Bobba & the NERD guys...

I started with computers in 1960 (analog). In 1965 had the opportunity to learn and work on a B727 digital flight simulator. WOW had 1K of real core memory with the wires and donuts. The NERDKITS have allowed me to continue and learn and take ideas and make them come true.... Your COMPLETE KIT has worked perfect. I use it on 4 different PC's at various times.

Thanks all of you for your ideas and help... I sure needed it..

MERRY CHRISTMAS TO ALL

JIM

Post a Reply

Please log in to post a reply.

Did you know that you can impress a loved one with a digitally-controlled Valentine's Day Card with randomly twinkling LEDs? Learn more...