CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug Reports on this forum. Send them to support@ccsinfo.com

Buffer help please

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
billy jones
Guest







Buffer help please
PostPosted: Wed Apr 21, 2004 3:32 am     Reply with quote

Hi all.
Im new to PICs and C programming and I was wondering if anyone would be kind enough to explain to me how the buffer in the file EX_SISR.C works as Im having trouble understanding.
Thanks
Billy
Ttelmah
Guest







Re: Buffer help please
PostPosted: Wed Apr 21, 2004 4:39 am     Reply with quote

billy jones wrote:
Hi all.
Im new to PICs and C programming and I was wondering if anyone would be kind enough to explain to me how the buffer in the file EX_SISR.C works as Im having trouble understanding.
Thanks
Billy

Ouch!...
Ok. Let's split it up a little. Imagine you have an array of storage locations, callled 'buffer', and these are 'addressable', using a number. So:
buffer[0] refers to the first location,
while
buffer[n] is the n+1'th location (arrays in C are 'zero referenced').

Now you have characters arriving from an external source, that need to be temporarily stored, and retrieved in the same order. So you have a pair of 'indexes' to the array, called 'in', and 'out'.
Now initially, you can just add characters to the array, by using:

buffer[in] = chr; //put 'chr' into the address 'in'
Then incrementing 'in', to point to the next location.

However, since the buffer cannot be of infinite size, you have to also handle the condition that 'in' can get to the end of the buffer. This is done by:

in = (++in % size);

where 'size' is the size of the buffer. The '%' symbol, means to generate the remainder, when the first number is divided by the second. So if the 'size' was 8, and in was 6, then the result would be:

6+1 = 7
7/8, = 0 remainder 7

So the result would be '7'.

However the next time the function is called, the maths goes:

7+1 = 8
8/8 = 1 remainder 0

So the result now is '0'.
Hence using this function makes 'in' (and 'out'), increment through the sequence:
0 1 2 3 4 5 6 7 0 1 2 3 4 ....

So now, the address used to store the character, will 'wrap' back to the start of the storage area, when it reaches the end.

The 'retrieval' operation, uses the 'out' address. When the first character is added, 'in' increments. Now the 'out' value and the 'in' value differ. This is used to detect that there is a character in the buffer. Hence you can test at any time for the buffer containing data, by coding:
if (in != out) - here the buffer has got data.
Alternatively if you want to wait till data arrives (as is done in the 'getc' function), if you code as:
while (in==out) - the code will wait here till a character arrives.

The two addresses 'chase' each other round the addresses allowed (hence such buffers are often called 'ring' buffers).

When you increment the 'in' value, if it 'catches up' with the output value, then the buffer is full. The CCS code handles this, by setting 'in' back to the last value if this happens, throwing away the newest character. I often handle this the opposite way, throwing away the 'oldest' character instead.
The operation to do this, is:
buff[in] = chr;
in = ++in % size;
if (in==out) out = ++out % size;

Now the use of the '%' operation, allows the buffer to be any size (5, 10, 20 characters etc.), but has the 'downside', that this involves more arithmetic than some alternatives.
The obvious alternative, is the binary '&' operation. If the buffer 'size' is only allowed to be a direct 'binary' power (so 2, 4, 8, 16, 32 bytes), then you can instead use:

in = ++in & (size-1);

This codes as just a couple of instructions, making for faster buffer handling. The '&' operator, only returns bits in the output, where bits are present in both input values. So, with 'size' = 8:
size-1 = 7 = 00000111
6 = 00000110 & 00000111 = 00000110 = 6
7 = 00000111 & 00000111 = 00000111 = 7
8 = 00001000 & 00000111 = 00000000 = 0

Giving the same 'wrap' effect.

If you do a search on 'ring buffers', you should find a lot more about this.

Best Wishes
billy jones
Guest







PostPosted: Wed Apr 21, 2004 10:02 am     Reply with quote

excellent stuff. thank you
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group