I would very much appreciate any advice on this.

I am reading a single byte from the serial port and wanting to store up to a hundred of these. Essentially I need to check incoming data to see if the value of it has been sent previously. These are my thoughts.

Set up a Fifo or Ring buffer with 100 elements
When a byte is received check through all 100 elements to see if it has been sent before, discard if so, otherwise store. Lose oldest data or flush when full.

Embedded CPU, so need to be as memory efficient as possible.

Would you consider this the best way of doing this. Still fairly new to C, so any guidelines on how to set this up, or indeed any better suggestions. Many thanks.

Recommended Answers

All 6 Replies

do you need to be limited to storing 100 bytes? because if you kept a record of all possible 256 bytes, you could make it both faster and more memory-efficient.

example: instead of actually copying and storing the value of 256 (or even 100) separate bytes, you really only need to store 32 bytes. for a total of 256 bits. where each bit is a placeholder representing the value of the potential received byte. and each of these bits is set to 1 if it the byte value it represents has been received, or 0 if it has not.

so you've got byte[0] - byte[31], where:

bit 0 of byte[0] represents serial byte value 0x00
bit 7 of byte[0] represents serial byte value 0x07
bit 0 of byte[1] represents serial byte value 0x08
bit 7 of byte[1] represents serial byte value 0x0F
...
bit 0 of byte[31] represents serial byte value 0xF8
bit 7 of byte[31] represents serial byte value 0xFF

i think you'll best accomplish this mulitplexing with a macro.

check this out i think you'll see what i mean

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define RECEIVED_SERIAL_BYTE(x) { byte[x/8] |= (1 << (x%8)); }

unsigned char byte[32];  // embedded memory location

int main(void)
{
   char buf[5];
   int i, j, value;


   while(1)
   {
      do 
      {
         printf("\ninput decimal value 0-255: ");
         fflush(stdout);
         fgets(buf,sizeof(buf),stdin);
         errno=0;
         value = strtol(buf,NULL,0);
         if (errno)
            perror(NULL);
      } while (errno);

      if (value<0 || value>255) // out of range value will quit loop
      { 
         printf("quit requested.\n");
         break;
      }

      RECEIVED_SERIAL_BYTE((unsigned char)value);  // store value 

      printf("\n+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\n");
      for (i=0; i<32; i++)                 // dump entire memory contents
      {
         for (j=0; j<8; j++)
            if (byte[i] & (1 << j))
               printf(" %02X",i*8+j);
            else
               printf("   ");
         for (i++, j=0; j<8; j++)
            if (byte[i] & (1 << j))
               printf(" %02X",i*8+j);
            else
               printf("   ");
         printf("\n");
      }
      printf("+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+\n\n\n\n");
   }

   return 0;
}

.

well, on second look, any claims to speed improvement is completely dependent on how this is used.

because while it's faster to "store" the bytes in memory, it will be slower to retrieve all bytes currently stored. so... will depend on how you need to access the data. if you have high throughput on collection and less need to access, it will be better than if you collect less and access frequently.

the worst case is if you have frequent access requirements and just a few possible bytes that can be stored, the sparsely filled memory would make this method considerably slower.

still, it is more memory friendly: rather than storing 100 bytes in 100 bytes of memory, you get 256 effective bytes of "storage" for 32 bytes of memory. compression of 8:1. how important is that? eh, probably not too much depending on how much memory you have available.


.

What a great idea, I would never have thought to do it this way. I guess this would work for the following.

Essentially what I am trying to do is the this.

I have a lot of remote alarm points, when these are activated, they transmit a unique byte about every 30 seconds until canceled at source. These then go off to various monitors that sound when a byte is received. Now I have been asked to fit a serial logging printer to the system. Clearly it would be very wasteful of paper, if it had to keep printing the same data every 30 seconds. So what I am trying to do, is once a number has been printed, any further reception should be ignored for printing purposes. I would probably also clear the buffer ever 10 mins or so, to allow printing again, if the call had not been canceled in the meantime.

I very much appreciate your input, I am sure it will be very useful.

Given that, another option is to have an array, one entry for each alarm.
Option 1:
When a value is received,

1) if array entry = 0
    a) print the alarm
    b) load 20 into the value
2) if array entry <> 0  decrement the array value

This way every 10 minutes the value becomes 0 and and printing will happen again. But when an alarm becomes inactive, you'll have to get a 'clear' signal and clear the value.

Option 2:
When a value is received,

1) if array entry = 0
    a) print the alarm
    b) load 20 into the value
2) Every 30 seconds, go through the array and decrement any values > 0.

This will automatically turn off any alarms that are no longer active.

well, knowing your exact requirements changes the nature of what would be an efficient solution.

the way i described above was more of an abstract exercise on a general "how else could i do _____" sort of thing. it may be somewhat clever, but there may be other solutions that are more appropriate.

though given what you've described, it sounds like memory and speed are not an issue for your processor at all --- that you're really just trying to keep a printer from spilling rolls of paper every time some remote alarm goes off.

I know the Comp Sci folks will probably sh*t kittens if i say this, but being familiar with remote monitoring industury, i know it tends to be that any solution that gets the job done is a good solution. :P


.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.