Go Down

Topic: Good practice: Buffer for shared data- SOLVED (Read 552 times) previous topic - next topic

tkbyd

Feb 27, 2011, 11:21 pm Last Edit: Feb 28, 2011, 12:05 am by tkbyd Reason: 1
This is a general enquiry about what people feel is a "Good" way to do something like the following....

I want to set aside some RAM to hold some bytes.

I want to be able to access those bytes within subroutines, with a minumum use of global variables.

I could do this in other languages! I just don't know "the right" way to do it in Arduino programming, or even if my approach is sensible.

Before I go into detail, a word about context...

The Sparkfun/ Innovations RFID reader transmits a burst of 14 bytes each time it sees a RFID tag.

Getting them displayed in the basic serial monitor is no big deal...

http://sheepdogguides.com/arduino/art3rfid1.htm

At the heart of that...

Code: [Select]
if (mySerialPort.available() > 0) {
// read the incoming byte from the serial buffer
incomingByte = mySerialPort.read();
// show what was received
Serial.print(incomingByte, DEC);
               Serial.print(' ');
               if (incomingByte==3) Serial.println();


(incomingByte will == 3 at the end of the bytes from a given tag)

I'd like to "catch" those bytes, store them someplace, and have easy access to them from other parts of the program.

I could, of course, establish a global array, access the array elements as needed.

It seemed a little "neater" to do something like the following, if possible....

At the top of the program, do something like....

byte myBuffer[6];

... to set aside 7 bytes of RAM where data could be stored.

Now, of course(?) you could fill the first byte with something like...

myBuffer[0]=27;

... in some, easy, circumstances.

I'd like to use that block of memory, though, less "directly"... primarily within subroutines.

Take for instance a subroutine to add 1 to each byte in the buffer... and we'll stipulate that no datum is 255, or if it is, rollover doesn't matter.

You could, of course, just use....

void AddOne
{
byte counter=0;
do {
myBuffer[counter]=myBuffer[counter]+1;
++counter;
} while (counter<8);

This "suffers" from the flaw that forces you to make changes within the subroutine if the buffer you want to process changes.

I was hoping there's a way to use... pointers?

Is there a way to, in old fashioned terms, "peek" and "poke" memory addresses? And to know where the buffer myBuffer is in memory, following the declaration given above? Why? Just for a start... suppose there were TWO such buffers, and you wanted to be able to add one to each element, with two calls of the same subroutine, just a different parameter...

Here's a rough, not- in- actual- Arduino- code idea of the subroutine that I hope is possible, with an example of it being called....

Code: [Select]

//Program with two buffers
byte myBufferA[6];
byte myBufferB[6];

... other stuff....
... somewhere in loop(), something that
...     happens from time to time...
AddOneFancy(PmyBufferA);
AddOneFancy(PmyBufferB);

... rest of loop()
}//end of loop()

AddOneFancy(pointer PtToBuff)
{
byte counter=0;
do {

byte in memory location at address of PtToBuff + counter
=
that byte, plus 1;

++counter;
} while (counter<8);
}

I hope the idea comes though? The gap in my knowledge is with how I say something's a pointer, or maybe simple what data type to use in the header of  AddOneFancy (in place of the word "pointer" there), and how to do the "peek" and the "poke" of and too the contents of that memory address...

Sorry if that didn't make sense. Thank you if you've struggled through... and have an answer for me!

WHY??? I think if I can crack this, I can write better general purpose routines for a bunch of things I want to do....




pocketscience

You can use a pointer into the array you define no problem...
#define SOME_LENGTH 7
char my_array[ SOME_LENGTH ];
char *my_ptr;
...
my_ptr = &( my_array[ 0 ] );
...

Except you still need to keep track of the end of your array so you don't go running past it. You could define another pointer to the last element and compare the pointers.

I don't quite understand why you say "the flaw that forces you to make changes within the subroutine if the buffer you want to process changes". Do you mean the length of the buffer? That's why you use #define's for buffer lengths - then if the length changes you only ever have to update the #define - the rest of the code is unchanged.

Cheers,
Is life really that serious...??!

tkbyd

Many thanks... I think your answer fills my want. I'll go and play with what you've given me.

As for...
Quote
I don't quite understand why you say "the flaw that forces you to make changes...


Without being able to pass the pointer to where the buffer is, or passing the whole array to the subroutine (which seemed "messy" and cumbersome.. and(?) slow), I imagined I'd need two copies of the AddOne array, each hard-coded to add one to the elements of a specific globally defined array. Yuck.

Thank you for pointing out that working like this, care needs to be taken not to run past the end of the buffer.

EVP

In C ive used malloc with a sizeof what ever you need ( maybe the size of a header , plus how ever many multiples of the stuct? variable you are using)]
I think for C++ you would use new instead.
you then have a void pointer that you can increment thought the memory in what ever size steps suits, i.e if you have a header thats a 20char , 2 int's and a bool you cast the pointer to there size and increment it ++. One of the int in the header contains the size of the whole memory area.
If this is a class when you create an instance you can provide the size information and then it will create the area in memory. Using appropriate functions you can edit, add, sort the contents of the memory area. To do this ive found you should only need two pointers.
This is just a brief over view of a way ive done something similar before. Weather it the 'right' way i'm not sure.

PaulS

Code: [Select]
byte myBuffer[6];

Quote
... to set aside 7 bytes of RAM where data could be stored.

No. That declaration sets aside 6 bytes, numbered 0 to 5.

Quote
You could, of course, just use....

void AddOne
{
byte counter=0;
do {
myBuffer[counter]=myBuffer[counter]+1;

You know, the language used to program the Arduinos is not called c=c+1.

Quote
Without being able to pass the pointer to where the buffer is,

But, of course, you CAN pass the pointer to where the buffer is. That's the whole reason for using poitners.

Go Up