Pointers and Queues

Discussion in 'C-Touch/HomeGate/SchedulePlus/PICED Software' started by MadMal, Jan 11, 2010.

  1. MadMal

    MadMal

    Joined:
    Dec 16, 2009
    Messages:
    79
    Likes Received:
    1
    Location:
    Perth, WA
    I am trying to build a robust program to handle serial comms to an external device ... best solution I can come up with is to use two queues for the command strings and received responses to be able to allow for delays in processing commands as well as being able to handle non solicited responses, etc.

    I have the following custom types:

    StringQPtr = ^StringQNode;

    StringQNode = record
    data : string;
    nextString : StringQPtr;
    end;

    StringQueue = record
    head : StringQPtr;
    tail : StringQPtr;
    end;

    And am trying to implement the standard init, push, pop routines ...

    Hence the init routine should be similar to:
    procedure Init (var q: StringQueue);
    (* Initializes the queue
    pre: true
    post: q is empty *)
    begin
    New(q.tail);
    q.tail^.nextString:=nil;
    q.head := q.tail;
    end (* Init *);

    However, I am getting :
    Error C399: Feature not implemented
    Error C006: Illegal symbol

    on the last two lines ...

    I am using the latest PICED and have tried all project types (CTouch, B&W Mk II, PAC) ...

    Any suggestions - is my Pascal rusty, or do I have a problem?
     
    MadMal, Jan 11, 2010
    #1
  2. MadMal

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    I just pasted the above code into a new Colour C-Touch project and it compiled.

    Sometimes it is possible to get confusing compilation errors if there is an error in a previous section of the code.

    For example, this error points towards the "init" procedure, but it may be caused by a problem back in the "global variables" section.

    You might need a bit of trial and error to find it.
     
    Darren, Jan 11, 2010
    #2
  3. MadMal

    MadMal

    Joined:
    Dec 16, 2009
    Messages:
    79
    Likes Received:
    1
    Location:
    Perth, WA
    Well - I'll be a monkey's ....

    Thanks for that Darren ...

    Still didnt get very far starting a brand new project and copying the code to it .. however, I did copy the code back from my post and it worked perfectly!

    About only thing I can come up with is there must be some sort of blind character on those lines (maybe when I was copying and pasting I hit another key instead of C or V when the ctrl key was down!) ...

    Now got my code to compile ...

    Next qn ... disposal of pointers ... std Pascal would be a Dispose(s) in the Pop procedure ... looking at the PICED doco, the best option would be something like :

    Procedure Pop (var q: StringQueue; var x: String);
    var
    MarkPtr : ^integer;
    s : StringQPtr;
    begin
    mark(MarkPtr);
    x:=q.head^.data;
    s := q.head;
    q.head:=q.head^.nextString;
    release(MarkPtr);
    end;

    Doesnt really seem to make sense as I only want to release the specific mem location and not a block, and dont want to also release all mem in the Queue as it is expected to exist (with length from zero to unknown members) for the duration of operation ...
     
    MadMal, Jan 12, 2010
    #3
  4. MadMal

    Darren Senior Member

    Joined:
    Jul 29, 2004
    Messages:
    2,361
    Likes Received:
    0
    Location:
    Adelaide, South Australia
    The memory management for the heap in PICED is very basic. What you have suggested will probably not work.

    You might be better off to use a static array of strings to implement the queue. Use separate variables to keep track of the head and tail of the queue. It isn't as memory efficient, but should do what you want.
     
    Darren, Jan 12, 2010
    #4
  5. MadMal

    ashleigh Moderator

    Joined:
    Aug 4, 2004
    Messages:
    2,398
    Likes Received:
    26
    Location:
    Adelaide, South Australia
    I've been writing embedded systems code for more years than I care to remember, and when I do a queue I always just use a plain ole statically declared array, and I even get lazy and use 3 variables:

    - input index
    - output index
    - size

    I know you can calculate size on the fly but it gets to be a pain when the indices have rolled around off the end and back to the start.

    You add operation becomes something like this (in pseudo code):

    ADD:
    Code:
    buffer[input_index] := item;
    size := size + 1;
    if input_index > buffer_size then
      input_index := 1;
    end if
    
    REMOVE: (which assumes there is something there to remove...)
    Code:
    result := buffer[output_index];
    size := size - 1;
    output_index := output_index + 1;
    if output_index > buffer_size then
      output_index := 1;
    end if
    
    The above assume that the buffer is a 1-based array. If its 0-based then the tests need to change to "if blah_index > (buffer_size - 1) then", and the rolled over value would change from :=1 to :=0.

    This approach is simple, easy to understand, and fast.
     
    ashleigh, Jan 12, 2010
    #5
  6. MadMal

    MadMal

    Joined:
    Dec 16, 2009
    Messages:
    79
    Likes Received:
    1
    Location:
    Perth, WA
    Thanks Ashleigh - thats actually where I started and then headed off in the more dynamc pointers path, only to get slammed with the memory issues :( serves me right on getting too fancy for no real benefit - you would think I would listen to the advice on the KISS principal I force on my guys!
     
    MadMal, Jan 13, 2010
    #6
Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.