Announcement

Collapse
No announcement yet.

NAK - flush buffers

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

  • NAK - flush buffers

    Hi,

    After a receiving a NAK from my uLCD-43PTC, I correctly send the next packet but the display still returns a NAK.

    Does the uLCD flush its internal rx buffer after sending a NAK? I'm thinking it should but if it does, why does it still respond with a NAK?

    The cause of the initial error was that I sent to much data to a string object, which then caused the NAK.

    ​What happens now with these NAKs is that I am still getting valid button-push ReportMessage events, but I cannot send data to the display. I have checked my TX buffer before a send and it has the correct data.
    Last edited by Voodle; 28th May 2014, 02:58 PM.

  • #2
    It does flush the buffers, but that wont really help you as you don't know at what point the NAK was generated. (i.e. it may have been generated by other than the last character you sent, hence there will be new information in the buffer).

    The trick is to send 0x00s one at a time, giving a few ms and then checking for another NAK, once you get the second NAK you should be ready to go normally again.
    Mark

    Comment


    • #3
      I understand. That's a good idea to send 0. I shall try that to "re-sync" the send queue.

      Thanks Mark.

      Comment


      • #4
        Hi,

        I've implemented your suggestion and it works 99% of the time. It would actually be nice to have a command that could be sent to the uLCD to tell it to flush the buffers. I just don't want to be caught out.

        But of course, a command to flush the buffers would most probably be appended to 'garbage' that already existed in the rx buffer, making it impossible for the uLCD to tell the difference between data and a command. Serial comms is great, when there are no errors. Theoretically there should be none in such a tight, closed system.
        Last edited by Voodle; 29th May 2014, 01:30 AM.

        Comment


        • #5
          Yes, as you surmise, it cannot really be done.

          Can you work out why the errors are occurring, or when they are occurring?

          Some people, who get into this situation, take the reset line to their controller and reset the display when they get an error.

          We do not endorse this, as surely the best way is to find why the error occurs in the first place.
          Mark

          Comment


          • #6
            Hi Mark,

            A NAK shouldn't really be an issue in these systems unless a cable is unplugged or a buffer is overflowed etc. If I see it happening I will do some digging. As mentioned, the first problem was me sending incorrect data.

            Comment


            • #7
              Hello everyone,
              I'm working with a gen4-uLCD-70DT and I have the same problem. Also in my case the problem occurred the first time due to the sending of a string not terminated by the NULL character. However, although I modified the string control from Book to Message, the NAK problem still occurs.
              The page contains 7 LEDDigit and a string that are continuously updated at least one time every 2/3 seconds.

              Sometimes it seems that the LCD locks with the values ​​of the LED digits that are no longer updated ...
              Investigating I noticed that in fact I receive all the Report messages regularly but any message I send to the LCD gets a NAK response.

              I found the suggestion to send a 0x00 character interesting when I receive an NAK, but I could not figure out how many 0x00 I need to send, or if it is good to send a 0x00 every time I receive an NAK ...

              You could clarify what you mean by saying: "The trick is to send at the time, giving you a few ms and then checking for another, NAK, once you get the second NAK you should be ready to go normally again."

              I almost forgot! The project is written in VISI-Genie.

              Out of curiosity I tried to convert it to VISI Designer to see how the LCD managed the communication, but it did not help me to understand how a 0x00 could clean up the RX buffer. Thanks for your help! Osvaldo
              Last edited by osvaldo71; 24th April 2018, 06:58 AM.

              Comment


              • #8
                if the crc is not valid and/or your writing before the lcd finishes “processing” the widget before it returns the ACK, you will undoubtedly continue to receive NAKs

                you must always wait for ACK before sending another command, ALWAYS. ignoring this and continuing to blast the data will never work. the display has to finish the current processing before continuing before it can orocess the next commands, do this consecutively until the buffer overflows and bam, NAKs again. this is normal and must be handled by the library, properly, by waiting for the ACK, as intended.

                Comment


                • #9

                  Thank you for replying so quickly!

                  So to prevent NAK reception, if I understand correctly, you suggest to implement a "Sliding Window" mechanism, where the host could send a maximum of n commands over which it should wait to receive the corresponding ACK before continue...?

                  Just to clarify what I'm trying to do ...
                  I am developing the host application on a cRIO-9637 platform using LabVIEW.
                  I rewrote the communication library with LCD from scratch.

                  I have a backgrund process that handles serial communication at 115200 Baud: if characters arrive on the serial port the message recognition process begins. When a message is detected it is removed from the buffer and inserted into a single output queue. If there are no bytes in the input buffer, the first command on the input queue is taken and sent to the serial. Then there is another process that manages the user interface that picks up messages from the receive queue, processes them and, if necessary, generates new messages that are queued to be transmitted. (Event Driven user interface)

                  Thank you.

                  Osvaldo

                  Comment


                  • #10
                    you should use baudrate of 200000 for diablo, most people are
                    but yeah, im not saying to send a few commands and wait, the genie protocol has a uart buffer of probably ~ 40 bytes in the display code (dont quote me on that, its somewhere there)
                    think of the lcd as a 2-way link
                    you command it ( DO THIS ) and wait for a response (ACK)
                    as soon as the ACK is received, you can immediately send next request without any delay. Keep in mind you can still receive touched events during the ACK period, so those must be “collected” into a queue system (like genie’s framebuffer does) until the ACK is received. usually this can be within 20-40ms timeframe depending on the object refresh rate, maybe less.

                    you just cant do this:
                    change this string
                    change that string
                    change form
                    are you done?

                    from a loop() perspective on above, you sent 3 commands and then asking a response, it cannot be...

                    are you using a custom library? or one of the official ones? if you have a custom one and getting issues we can surely point out something that may be wrong if a function is shown.
                    if your using a custom library, theres a beta version on the repo that you can disassemble as it gives a better idea of how the functions work in genie, and when/when not to wait for the ACK.
                    Last edited by tonton81; 24th April 2018, 10:36 PM.

                    Comment


                    • #11
                      Hi,

                      Let's see if I understand what you mean ...

                      Some background facts...
                      115200 baud is the maximum speed that can be set on the platform on which I am developing ...

                      The library I am using is totally custom and I developed it from scratch directly in LabVIEW ...
                      For those who do not know it, LabVIEW is a graphic language and it is difficult to bring portions of code on a forum.

                      But the cycle of the process that manages the communication with the LCD can be schematized as follows (pseudo-code):

                      Code:
                      WHILE( 1 ) DO
                              // check for bytes in input buffer. If any begin decoding process
                      
                              IF(Serial.byteAvaiable() >= 0)
                                THEN
                                   // There are bytes in the input buffer
                                
                                   c = serial.getBytes(1);  //Get next 1 byte from the stream
                      
                                   CASE (c) OF
                                       0x06         : // ACK: Do nothing
                                       0x15         : // NAK: Do nothing
                                       0x05, 0x07: // Report Event or Report Message
                                                         IF (Serial.byteAvaiable() >= 5)  THEN
                                                             //at least 5 byte in buffer
                                                           
                                                            msg[0] = c;
                                                            msg[1 TO 6] = serial.getBytes(5);  //get next 5 bytes from the stream (array) e put them into the message array
                      
                                                            IF (CheckSumOK(msg))  THEN GUIqueue.Send(msg);   //send the message to the user interface event routine queue
                                        0x0A, 0x0B: // Report Magic Event or Report Magic Message
                                                          
                                                           // similar code above to process magic messages...
                      
                                        default: // Other then valid messages type: do nothing
                      
                                    END CASE
                      
                                  ELSE
                                     // there are no bytes in the input serial buffer
                                     serial.write( CmdQueue.Dequeue() );  //Get the next msg to send to LCD (array of byte with Checsum) from the queue
                                                                                             // and send it on the serial link
                                  END IF
                      END WHILE
                      As you can see, if there is at least one byte in the input buffer, the host does not send any message to the LCD.
                      Messages queued by the application are forwarded (one at a time) to the LCD only if it is not transmitting anything.

                      The indicated cycle is performed every approximately 50ms.

                      In fact it can happen that if the LCD takes more than 100ms to execute a command (and for an ActivateForm command is plausible
                      if the form is moderately complex) the host, not detecting the ACK, interprets the empty buffer as an "ok to proceed "to send a new command...
                      I use mostly WriteObject commands that are 6 bytes long...

                      So... If the delay between sending the ActiveForm (or any other message) and receiving the related ACK is greater than 350ms,
                      the host would send 6 or 7 WriteObject commands for a total of 36/42 bytes ... sufficient to overflow the LCD input buffer!

                      In addition, the last WriteObject would remain in the buffer only the first 2/3 bytes that would be interpreted with the first 2/3 bytes of the next command thus disallineating the buffer and starting the sequence of NAK that the host detects ... Sequence ending only when, due to the presence of NAKs, the host suspends the transmission for enough time to allow the LCD to empty its buffer...

                      Now I try to change the code to force the host to wait for the ACK before sending new commands and let's see what happens..

                      Thanks so much!

                      Osvaldo

                      Comment


                      • #12
                        Sorry I didn't see this thread, your loop looks fine however, the ACK must be handled, lets say (to keep it simple) set a flag notbusy=1;

                        so after you WriteObject, you can set the flag to notbusy=0;
                        and as soon as the ACK comes in your loop (0x06) you must discard that byte and then unset your flag.

                        The flag is just an idea of one way to handle the situation between writes, that your code must at least wait for an ACK or NAK before sending the next command

                        Code:
                                      CASE (c) OF                  0x06         : // ACK: Do nothing                  0x15         : // NAK: Do nothing
                        if you want to do nothing, you should at the bare minimum discard the byte from the buffer, so the comms can continue.

                        EDIT, ah yes, you actually did discard it via the switch statement.

                        EDIT 2:
                        .. Sequence ending only when, due to the presence of NAKs, the host suspends the transmission for enough time to allow the LCD to empty its buffer...
                        The LCD won't discard the bad bytes in buffer, they are valid (first part) but incomplete, You have 2 ways to get in sync again:

                        #1 Reset the display

                        #2 Handle the NAK's, but don't just write anything.
                        First, on the first NAK, you should send a valid request to the screen (I recommend GENIE_OBJ_FORM request) which is 4 bytes.
                        If a NAK is returned, send a dummy byte into the LCD (0xFF), and do another GENIE_OBJ_FORM request.
                        Repeat, after 1-3 times you'll get an Event back (which is the current form the LCD is on), then your in SYNC
                        At that point you may continue processing

                        Any progress ?

                        Tony
                        Last edited by tonton81; 1st May 2018, 07:58 AM.

                        Comment


                        • #13
                          Originally posted by tonton81 View Post
                          Sorry I didn't see this thread, your loop looks fine however, the ACK must be handled, lets say (to keep it simple) set a flag notbusy=1;
                          Hi, no problem!
                          Thank you for answering!

                          I was thinking of a very similar solution, in fact ... Use a flag to avoid sending commands to the LCD as long as the ACK of the previous command does not arrive.
                          The fact that you suggest it means I'm on the right path!


                          Originally posted by tonton81 View Post
                          EDIT 2:

                          The LCD won't discard the bad bytes in buffer, they are valid (first part) but incomplete, You have 2 ways to get in sync again:
                          Good to know! I had this impression looking at the code obtained by converting the Genie project into VISI ...

                          Originally posted by tonton81 View Post
                          You have 2 ways to get in sync again:

                          #1 Reset the display
                          Not feasible...

                          Originally posted by tonton81 View Post
                          #2 Handle the NAK's, but don't just write anything.
                          First, on the first NAK, you should send a valid request to the screen (I recommend GENIE_OBJ_FORM request) which is 4 bytes.
                          If a NAK is returned, send a dummy byte into the LCD (0xFF), and do another GENIE_OBJ_FORM request.
                          Repeat, after 1-3 times you'll get an Event back (which is the current form the LCD is on), then your in SYNC
                          At that point you may continue processing
                          Great idea! I will try to implement it as soon as possible!

                          Thanks so much!

                          Originally posted by tonton81 View Post
                          Any progress ?

                          Tony
                          Unfortunately the Windows7 in the virtual machine that I use for development has crashed ...
                          And the backup did not work ... So I'm rebuilding the environment from scratch ...

                          As soon as I'm operational again I'll try to apply all the suggestions !

                          Osvaldo


                          Comment


                          • #14
                            One more thing for the flag, lets say if you ever get a rare situation of not receiving the ACK or NAK, it might block you from writing more objects if your flag is still set. Usually the ACK/NAK happen within a 40uS window, you can add a timeout flag restore that maybe after 100uS or so if no ACK/NAK if flag is set, to unset the flag and continue writing after

                            Tony

                            Comment


                            • #15
                              Hello tonton81,

                              sorry for the delay with which I answer.

                              In the end I managed to implement your suggestion and the system seems to work much better!

                              I took advantage of this to implement a message log mechanism in and out of the serial port.

                              Analyzing the communication log, observing the timestamps it is clear that the redesign of some particularly complex forms requires about one second!
                              If you do not wait for the ACK the buffer hurries to fill with its misalignment and all that goes with it!

                              At the moment I have implemented only the flag waiting for the AAC and the relative timeout because sending the message
                              to query the currently displayed form (0x00 0x0A 0x00 0x0A) results in a NAK response... As soon as possible I will
                              try to re-implement also the suggestion for the buffer re-alignment.

                              Thank you so much!

                              Osvaldo

                              Comment

                              Working...
                              X