Announcement

Collapse
No announcement yet.

storing strings from a serial buffer pointer

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • storing strings from a serial buffer pointer

    Hi all,

    I am currently having issues with storing a string from com1's buffer which I have set up using com1_Init().

    What I am trying to do is parse a NMEA sentence from a gps unit and then store the bits of information that I want for use later and updating them whenever new information has been sent from the gps unit.

    I am currently able to start buffering when I receive the qualifier '$' and then begin processing the NMEA sentence once the end char is received. I am then able to search through the received string in the buffer to replace all comma delimiters with '\0' and then store the pointer location of each part of the sentence in an array called strings.

    Next I try and compare the first entry of the received NMEA sentence so that I can process according to the protocol head. This is where I am having trouble as I am having issues storing the strings located at the pointer position.

    So my question is: if you have an array of pointers which point to a buffer memory location which contains strings what is the correct way to store just the strings as a variable so it can be used elsewhere like sending to another com port and printing on a screen?

    EDIT: I have just read the reference for the str_Printf() function more closely and it states:
    There is only one input argument, the byte region pointer ptr which is automatically advanced as the format specifier string is processed.
    Does this mean that when I use the function the pointer I have passed it is advanced and now points to a new location? If so, how do you print the string without moving the pointer? (I have done a fair bit of experimentation with functions like print() etc. but have had no luck so any advice would be great, in fact any advice on my code in general would be great)

    Below is my code which currently does print out and update on of the values I want, except that I cannot use my variables outside the if...

    Code:
    #platform "uLCD-24PTU"
    #inherit "4DGL_16bitColours.fnc"
    
    var strings[100]; // splitpoints
    var gpsBuf[100];
    var gpsPtr;
    
    #CONST // NMEA sentences
        mkr := "," // delimiter used in parser
        vtg := "GPVTG" // velocity to ground
        // more to add...
    #END
    
    func get_NMEA(var buf) // parse NMEA sentence and replace ',' with '\0'
        var p, q; // string pointers
        var n := 0; // counter
    
        p := str_Ptr(buf); // point to buffer containing sentence to split
    
        while(str_GetByte(p)) // split the sentence into substrings
            strings[n++] := p; // saving pointers to each splitpoint
            if(q := str_Find(&p, mkr)) str_PutByte(q,'\0'); // converting markers to '\0's
                p := q+1;
            wend
    endfunc
    
    func gps_Init()
        com1_Init(gpsBuf, 100, '$');  // reset the buffer
        gpsPtr := str_Ptr(gpsBuf); // reset pointer
    endfunc
    
    func main()
        gfx_ScreenMode(LANDSCAPE) ; // change manually if orientation change
    
        // instantiate variables
        var type; // NMEA sentence type
        var speed, speedUnit;
    
        com_SetBaud(COM1, 960); // baud rate for gps
        gps_Init(); // get the gps going
    
        print("Let's parse...\n");
    
        repeat
            if(com1_Error() || (com1_Full() && com1_Count() == 0)) // check for com errors
                if(com1_Full())
                    print("Com1 full...");
                else
                    print("Com1 error...");
                endif
                gps_Init(); // restart the gps coms
                print("Cleared!\n");
            else if (com1_Sync() && serin1() == 0x0A) // received NMEA sentence
    
                get_NMEA(gpsBuf); // parse the sentence
                gps_Init(); // restart the gps coms to keep track of the buffer pointer
    
                type := &strings[0];
    
                if(str_MatchI(type, vtg) )
                    // storing and printing here is fine except that i cant use the variables after...
                    speed := &strings[7];
                    speedUnit := &strings[8];
                    print("Velocity on ground is: ");
                    str_Printf(speed, "%s");
                    str_Printf(speedUnit, "%sm/h\r");
                endif
    
            endif
            /* // printing here causes all types of issues...
            print("Velocity on ground is: ");
            str_Printf(speed, "%s");
            str_Printf(speedUnit, "%sm/h\r");
            */
        forever
    
    endfunc
    Last edited by Askimov; 15th April 2018, 09:56 PM.

  • #2
    Hi Askimov! Welcome to forum.

    The simplest way that I can recommend to you in storing certain character/s from a buffer to a specific variable is by utilising str_CopyN() function. (Refer to PICASO PROCESSOR - Internal Functions Reference Manual page 276)
    In order to effectively use this function, you must first be particular about pointers and based on your code, I can see that you are.

    Below is a sample code on how to utilise characters inside a buffer by getting the location of the markers and put them in a certain variable (string).

    NOTE: To simulate the data received, NMEA sentence GPVTG,054.7,T,034.4,M,005.5,N,010.2,K is used in this code.

    Have fun testing!

    Code:
    var gpsBuf[100];
    var mrk_loc[10]; //marker ',' location
    
    var gpsPtr;
    var gpsPtrMin;
    
    var mrkPtr;
    var mrkPtrMin;
    
    var type[5]; // NMEA sentence type
    var speed[5];
    var speedUnit[5];
    
    
    #CONST
        MKR     ','     // delimiter used in parser
    
            // NMEA sentences
        VTG     "GPVTG" // velocity to ground
        // more to add...
    #END
    
    
    func getMarker_NMEA(var buf) // parse NMEA sentence with ',' as a marker
    
        var n; // counter
        var readPtr;
    
        readPtr := gpsPtrMin; // reinitialise ptr to avoid updating the min ptr
    
        while(n< str_Length(gpsPtrMin)) // scanning the whole data
    
            if(str_GetByte(readPtr) == MKR)
                //txt_MoveCursor(1,0);
                //print("\nmarker location: ", readPtr);
                str_PutByte(mrkPtr, readPtr);
                mrkPtr++;
            endif
            readPtr++;
            n++;
        wend
    
    endfunc
    
    
    func setup()
        putstr("Mounting...\n");
        if (!(file_Mount()))
            while(!(file_Mount()))
                putstr("Drive not mounted...");
                pause(200);
                gfx_Cls();
                pause(200);
            wend
        endif
    
    
        com1_Init(gpsBuf, 50, '$');          // reset the buffer
        com_SetBaud(COM1, 960);         // baud rate for gps
    
        print("Let's parse...\n");
    
        gfx_Cls();
        pause(2000);
    
        to(gpsBuf); putstr("GPVTG,054.7,T,034.4,M,005.5,N,010.2,K"); // simulate received data to buffer
        print("data received:\n", [STR] gpsBuf);
    
        gpsPtr := str_Ptr(gpsBuf); // set pointer
        gpsPtrMin := gpsPtr;    //    used to located init ptr
    
        mrkPtr := str_Ptr(mrk_loc);
        mrkPtrMin := mrkPtr;
    
    endfunc
    
    func main()
        setup();
        var numChar;
    
        getMarker_NMEA(gpsBuf);
    
        numChar :=  str_GetByte(mrkPtrMin) - gpsPtrMin ;  // char before 1st marker
        str_CopyN(str_Ptr(type), str_Ptr(gpsBuf), numChar  );
        print("\n\nType: ",[STR] type);
    
        if(mem_Compare(type, VTG , 5) == 0)     // true
    
            numChar :=  str_GetByte(mrkPtrMin + 7) - str_GetByte(mrkPtrMin + 6) - 1;   // char between 8th and 7th marker
    
            str_CopyN(str_Ptr(speed), str_GetByte(mrkPtrMin + 6) + 1,  numChar );
            print("\nSpeed: ",[STR] speed);
    
            numChar := gpsPtrMin + str_Length(gpsPtrMin) - str_GetByte(mrkPtrMin + 7) - 1; // (min ptr of gpsBuf + length of buff) - 8th marker ptr - 1
    
            str_CopyN(str_Ptr(speedUnit), str_GetByte(mrkPtrMin + 7) + 1,  numChar );
            print("\nUnit: ",[STR] speedUnit);
    
        endif
    
        repeat
    
        forever
    endfunc
    Best regards,
    Vince
    Vince_4D

    Comment


    • Askimov
      Askimov commented
      Editing a comment
      Hi Vince,

      Thanks for the sample code it works great and I have managed to extend it to read a stream of GPS data and update some text fields based off of a bunch of different sentence types.

      I have another couple of questions regarding the UART which I haven't found an answer to in the specs.

      When using the UART in buffered mode is it necessary to reinitialize the coms with com1_Init(..) each time I want to receive another sentence in qualified buffer mode?

      And is there a minimum setup time required for the com ports when using com1_Init(..)?

      Thanks again for your help.

  • #3
    Hi Askimov,

    Yes, it is necessary to reinitialise the COM you're using to catch another data after processing the packet and yes it can be done through com_Init() function.

    If you'd like to wait until the display is ready to receive the next packet, you can utilise the com_Error() function.

    For instance,
    Code:
    if (com_Errror())
     // error 
     Reinitialise COM
    else
     // no error hence COM is ready
     Send ACK to host controller 
    endif
    Hope this will help.

    - Vince -
    Vince_4D

    Comment

    Working...
    X