How to stop a program HSERIN blocking

sagor

Joined Mar 10, 2019
1,049
That is over 550 characters/sec, and at 9600baud (I'm assuming this is at 9600???), that would take well over 550mS just to receive that data every second. A huge overhead...
If you are processing and sending data strings out in the main program, you have very little time left to do anything else.
What you may want to do, is interpret the string as it comes it, looking for the one key phrase you want, and when you have the key information, turn off the UART and ignore the rest so you are not wasting time processing the other 450+ characters with the UART. When ready in the main program, turn the UART back on when ready to receive new data, whether from the GPS or the other source. Timing may still be an issue, but if you can skip a message once in a while, that may be an option.
Of course, an RX interrupt routine filtering the data and setting a flag when you get a valid string of interest would be more efficient, as interrupt can process in background all the time regardless of what the main program is doing. I know it gets complicated, but that is still a valid option.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,830
That is over 550 characters/sec, and at 9600baud (I'm assuming this is at 9600???), that would take well over 550mS just to receive that data every second. A huge overhead...
If you are processing and sending data strings out in the main program, you have very little time left to do anything else.
What you may want to do, is interpret the string as it comes it, looking for the one key phrase you want, and when you have the key information, turn off the UART and ignore the rest so you are not wasting time processing the other 450+ characters with the UART. When ready in the main program, turn the UART back on when ready to receive new data, whether from the GPS or the other source. Timing may still be an issue, but if you can skip a message once in a while, that may be an option.
Of course, an RX interrupt routine filtering the data and setting a flag when you get a valid string of interest would be more efficient, as interrupt can process in background all the time regardless of what the main program is doing. I know it gets complicated, but that is still a valid option.
Hi S,
From #140:
I am only interested in the RED sentence and only the dark RED digits.
If you look at #140 you will see the digits I'm interested in, which end in a [ W ] I can test for a [ W ] once that sentence has been collected and checked.

Also from #140
In simple terms, where would the [ If PIR1.RCIF = 1 ] be? In the MAIN LOOP or as I have it, in a [ GET_DATA ] GOSUB?
C.
 

djsfantasi

Joined Apr 11, 2010
9,237
Hi Both,
Blimey!

To explain what's arriving at the UART!

On the PCB, is a SWITCH that can be switched between the 2x DATA sources, so only one is arriving at any one time. (NOTE a [ ? ] was added to the REMOTE $Sentences as an EOL)

'Say' the DATASWITCH is set to GPS. This is what arrives one/sec.
____________________________________________________________________________
$GPRMC,162254.00,A,3723.02837,N,12159.39853,W,0.820,188.36,110706,,,A*74
$GPVTG,188.36,T,,M,0.820,N,1.519,K,A*3F
$GPGGA,162254.00,3723.02837,N,12159.39853,W,1,03,2.36,525.6,M,-25.6,M,,*65
$GPGSA,A,2,25,01,22,,,,,,,,,,2.56,2.36,1.00*02
$GPGSV,4,1,14,25,15,175,30,14,80,041,,19,38,259,14,01,52,223,18*76
$GPGSV,4,2,14,18,16,079,,11,19,312,,14,80,041,,21,04,135,25*7D
$GPGSV,4,3,14,15,27,134,18,03,25,222,,22,51,057,16,09,07,036,*79
$GPGSV,4,4,14,07,01,181,,15,25,135,*76
$GPGLL,3723.02837,N,12159.39853,W,162254.00,A,A*7C
$GPZDA,162254.00,11,07,2006,00,00*63
_____________________________________________________________________________
I am only interested in the RED sentence and only the dark RED digits.

In simple terms, where would the [ If PIR1.RCIF = 1 ] be? In the MAIN LOOP or as I have it in a [ GET_DATA ] GOSUB?
C
In simple terms, it doesn’t make a bit of a difference.

Let me know if you want to know why!
 

Thread Starter

camerart

Joined Feb 25, 2013
3,830
In simple terms, it doesn’t make a bit of a difference.

Let me know if you want to know why!
Hi D,
OK, either way, thanks. That's fine.

Am I correct that, if there's a [ PIR1.RCIF ] in the MAIN program LOOP I need to add an INTERRUPT routine after the END?

Am I correct that, in the attached mages, showing [ PIR1.RCIF= 0 ] when there were digits, in the UART, was more of a timing thing, and would be catered for by the INTERRUPT process?

C.
 

sagor

Joined Mar 10, 2019
1,049
Ok, I usually do not write code for others, but I'll make an exception here. This is an example of a RX UART interrupt routine to look at all the data and filter out the one string you want. When it finds the string, it sets a STR_DONE flag for the main program to check. Once the main program finds it, it should process the string to your liking and clear the STR_DONE flag as in the example.
I fed this code in the SIM with the following string, to include some garbage strings:
$GPZDA,162254.00,11,07,2006,00,00*63?
$GPRMC,162254.00,A,3723.02837,N,12159.39853,W,0.820,188.36,110706,,,A*74?
$GPVTG,188.36,T,,M,0.820,N,1.519,K,A*3F?
Notice your string of interest is in the middle.
My output shows:
upload_2019-6-4_15-31-58.png

Here is the code. Modify it to your purposes. It is basically an example of how to use an interrupt to find a specific string in a series of characters. It may not be complete, but it works in the SIM just fine. It will capture your string, and never capture anything again until you have processed the buffer array and clear the STR_DONE flag. Consider it a learning lesson:

Code:
Dim buffer(80) As Byte
Dim rxin As Byte
Dim temp As Byte
Dim valid As Byte
Dim str_done As Byte
Dim i As Byte


Hseropen 9600
'set up interrupts
PIE1.RCIE = 1
INTCON.PEIE = 1
INTCON.GIE = 1

rxin = 0  'Initialize
valid = 0


'main loop
'---------
main:
  
        If str_done = 1 Then  'a valid packet has arrived
            Hserout "Got it", CrLf
            For i = 0 To valid
            Hserout buffer(i)
            Next i
            str_done = 0
            valid = 0
        Endif
WaitMs 1
Goto main
End                                             


On Interrupt
    Save System
    If str_done = 1 Then
    temp = RCREG
    Goto fin  'Completed string has not been processed yet by MAIN program
    Endif
If RCSTA.OERR = True Then  'any error reboot serial module..
RCSTA.CREN = 0
RCSTA.CREN = 1
Goto fin
Endif

    temp = RCREG
'Now check for valid string to save. Must contain $GPRMC at first, then read rest until EOL
    Select Case rxin
        Case 0  'Must be $ sign
        If temp = "$" Then
        buffer(rxin) = temp
        valid = 1
        Else
        valid = 0
        rxin = 0
        Endif
        Case 1
        If temp = "G" Then
        buffer(rxin) = temp
        valid = 1
        Else
        valid = 0
        rxin = 0
        Endif
        Case 2
        If temp = "P" Then
        buffer(rxin) = temp
        valid = 1
        Else
        valid = 0
        rxin = 0
        Endif
        Case 3
        If temp = "R" Then
        buffer(rxin) = temp
        valid = 1
        Else
        valid = 0
        rxin = 0
        Endif
        Case 4
        If temp = "M" Then
        buffer(rxin) = temp
        valid = 1
        Else
        valid = 0
        rxin = 0
        Endif
        Case 5
        If temp = "C" Then
        buffer(rxin) = temp
        valid = 1
        Else
        valid = 0
        rxin = 0
        Endif
    Case Else


    If valid = 1 Then buffer(rxin) = temp  'get character(reading clears the RCIF)
  
EndSelect

        If buffer(rxin) = "?" Then
            valid = rxin  'set length of valid string
            str_done = 1  'Flag we have a completed string. Main program to check for this and process
        Else
            If valid = 1 Then rxin = rxin + 1
            If rxin = 80 Then rxin = 0  '80 position circular buffer. If overflow, start from scratch
        Endif



fin:
Resume
 
Last edited:

djsfantasi

Joined Apr 11, 2010
9,237
Hi D,
OK, either way, thanks. That's fine.

Am I correct that, if there's a [ PIR1.RCIF ] in the MAIN program LOOP I need to add an INTERRUPT routine after the END?

Am I correct that, in the attached mages, showing [ PIR1.RCIF= 0 ] when there were digits, in the UART, was more of a timing thing, and would be catered for by the INTERRUPT process?

C.
No, you don’t need an INTERRUPT routine

No, the fact that the USART is processing bits has nothing to do with any INTERRUPT process.

How can I help?
 

djsfantasi

Joined Apr 11, 2010
9,237
@sagor posted while I was answering. While interrupts CAN be used, in my humble opinion, you don’t need them. Are they confusing?

Sorry @sagor , IMHO interrupts are inappropriate here.

I don’t want to confuse the TS, so until asked I will bow out.
 

sagor

Joined Mar 10, 2019
1,049
No problem DJ, Camerart has to decide how his code is going to run in the long run. I just posted another option that parses all the UART data and just returns the one string he wants. He could use the same logic externally in a regular program loop, with proper checking of RCIF and using Hserin, I guess...
His original post was related to the Hserin (serial input) command blocking, locking up his program and wanted a way to prevent this. One can only assume he wanted to do other processing, or have some timeout function to kill the hardware serial input. All the solutions posted (by all of us) so far have had limited success, so either his code is still "blocking" or he is not properly reading all characters, or his overall code is taking too long to process vs the incoming data volume. Hard to say for sure.
Using interrupts to capture item of interest, then ignore the rest of the UART data does prevent any blocking, as once the string is saved, nothing else will happen until the main code decides to process the string. Thus, his main program runs "forever" regardless of input data stream on the hardware UART. Even if the main program ignores the saved string, the UART routine simply dumps any data until the main program says it is ready.
I'm sure there are other ways of doing this, but that may require a re-write of his code, which only he can do...

Thanks for your input so far, we all try to help even if we have different solutions. It is up to Cameart to decide which way he wants to go...
 

djsfantasi

Joined Apr 11, 2010
9,237
@camerart

I’ve modified my sample program. It will only extract the message you highlighted in red. All other characters are cleared from the receive buffer, but if they aren’t in the message you want, they are thrown away.

Code:
While STUFF_TO_DO
‘ do other stuff here while waiting
‘ for a message. Could be nothing
‘ or something that was being
‘ blocked by your input code

    WHILE PIR1.RCIF = 1

        Hserin char

‘ start a new message
        If char = “$” then ‘SOM
                str1(0) = “$”
                rxi  = 0
                Endif

‘ build the message
        If str1(0) = “$” then ‘ MSG
                rxi = rxi + 1
               str1(rxi) = char
               Endif

‘ identify the desired message
        If rx1=5 and char<> “C”
             str1(0) = “x” ‘ discard “$”
             rx1=o
             Endif
‘ by overwriting the ‘$’ character,
‘ everything else will be ignored

‘ finish a message
        If char = “?” or char = 0x0A then
            gosub msg_eol
            Endif

        If rxi > 79 then ‘ Overflow
                ‘ do your overflow stuff
                Endif

    Wend
‘ no characters in buffer
‘ do something else
Wend
Try to look at this separately from the code you have. Read through the code and tell me if you understand it. Or ask me questions about what you don’t understand.
 

sagor

Joined Mar 10, 2019
1,049
Another good option DJ. I think, however, that MSG_EOL has to be within his main program in your example. Not sure how he can branch to it, he has to figure that out. MSG_EOL can also be some flag for the main program (stuff_to_do) to check and process when it gets set....
 

Thread Starter

camerart

Joined Feb 25, 2013
3,830
Hi S and D,
Well that's amazing and very much appreciated. It's going to take me a little while to understand, and test both CODES properly.
I'm sure I'll be asking questions, thanks to both of you.
C.
 

sagor

Joined Mar 10, 2019
1,049
A minor correction to my code. Either may still work, but clearing the "valid" byte makes more sense if the string length goes over 80 bytes:
Code:
.....
        Else
            If valid = 1 Then rxin = rxin + 1
            If rxin = 80 Then
            rxin = 0  '80 position circular buffer. If overflow, start from scratch
            valid = 0
            Endif
        Endif
fin:
Resume
 

sagor

Joined Mar 10, 2019
1,049
C
Ask question soon, as I'll be on holidays for most of June, with limited access to the Internet...
Regardless, study all the code submitted, and test it with your overall program. Only you can decide which way to go....
 

djsfantasi

Joined Apr 11, 2010
9,237
Another good option DJ. I think, however, that MSG_EOL has to be within his main program in your example. Not sure how he can branch to it, he has to figure that out. MSG_EOL can also be some flag for the main program (stuff_to_do) to check and process when it gets set....
I agree... generally.

I see MSG_EOL as being a true subroutine (in BASIC). Which means it isn’t part of the main routine. He just has to transfer execution with a gosub, not a goto. Using goto presents other problems. Problems which are eliminated by using a BASIC gosub.

In his last posted code he used a goto but ended the routine with a return. This is s recipe for disaster. Return should only be used with a gosub in BASIC.

In C, MSG_EOL would be implemented as a function call.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,830
I agree... generally.

I see MSG_EOL as being a true subroutine (in BASIC). Which means it isn’t part of the main routine. He just has to transfer execution with a gosub, not a goto. Using goto presents other problems. Problems which are eliminated by using a BASIC gosub.

In his last posted code he used a goto but ended the routine with a return. This is s recipe for disaster. Return should only be used with a gosub in BASIC.

In C, MSG_EOL would be implemented as a function call.
Hi D,
I don't follow the MSG_EOL conversation, 'yet' but I think we can leave it till a bit later, after I've checked both of your CODES.

Regarding the RETURN at the bottom of the section I posted. This is a RETURN to the GOSUB GET_DATA in the MAIN LOOP.

While testing your CODE, there are a few Oshonsoft SYNTAX errors, that I will have to look into and correct, before testing. Not your fault!

I like the concept of passing the priority from [ $ ] to the next priority. 'If you know what I mean'

I'll let you know how I get on.
Thanks
 

Thread Starter

camerart

Joined Feb 25, 2013
3,830
C
Ask question soon, as I'll be on holidays for most of June, with limited access to the Internet...
Regardless, study all the code submitted, and test it with your overall program. Only you can decide which way to go....
Hi S,
Your CODE worked almost immediately, I see you have a SIM, which makes my life easier :)

Looking at the $sentences: The GPS and the REMOTE
$GPRMC,162254.00,A,3723.02837,N,12159.39853,W,0.820,188.36,110706,,,A*74
$GPVTG,188.36,T,,M,0.820,N,1.519,K,A*3F
$GPGGA,162254.00,3723.02837,N,12159.39853,W,1,03,2.36,525.6,M,-25.6,M,,*65
$GPGSA,A,2,25,01,22,,,,,,,,,,2.56,2.36,1.00*02
$GPGSV,4,1,14,25,15,175,30,14,80,041,,19,38,259,14,01,52,223,18*76
$GPGSV,4,2,14,18,16,079,,11,19,312,,14,80,041,,21,04,135,25*7D
$GPGSV,4,3,14,15,27,134,18,03,25,222,,22,51,057,16,09,07,036,*79
$GPGSV,4,4,14,07,01,181,,15,25,135,*76
$GPGLL,3723.02837,N,12159.39853,W,162254.00,A,A*7C
$GPZDA,162254.00,11,07,2006,00,00*63
________________________________________
$REMOTE,1234,4321,1111,1010,5555,66664444444W,?

You will see the two we are interested in have 2x unique situations, marked RED.
Would it be a good idea to have fewer CASES, checking only the RED digits.

Would it be possible to either check the number of digits between the [ $ ] and the [ W, ] marked in blue, OR check left of the CSV (Comma separated values). I can then always SEND messages 'from the REMOTE' with a [ W, ] at the same point. This way the sentences checking could be curtailed after the [ W, ] instead of the EOL.

I now need to run you CODE in SIM and LIVE to get the feel of it.
Thanks very much for making an exception.
C
 

djsfantasi

Joined Apr 11, 2010
9,237
Hi D,
I don't follow the MSG_EOL conversation, 'yet' but I think we can leave it till a bit later, after I've checked both of your CODES.

Regarding the RETURN at the bottom of the section I posted. This is a RETURN to the GOSUB GET_DATA in the MAIN LOOP.

While testing your CODE, there are a few Oshonsoft SYNTAX errors, that I will have to look into and correct, before testing. Not your fault!

I like the concept of passing the priority from [ $ ] to the next priority. 'If you know what I mean'

I'll let you know how I get on.
Thanks
Sorry that my program didn’t work for you. It was not a complete program; just a code sample to illustrate a possible technique.

Glad for you that sagor’s code worked.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,830
Sorry that my program didn’t work for you. It was not a complete program; just a code sample to illustrate a possible technique.

Glad for you that sagor’s code worked.
Hi D,
It's not a good idea to choose between two CODE versions, by taking the easiest way, but this is how we chose the gauge of our railway tracks, instead of the wiser Brunel width ;)

Anyway I'll return to it later, after testing the 'S' CODE.

The problem is by the use of [ AND ] I think this means something different in Oshonsoft, but I'll look into it and re-try.
Much appreciated.
C
 
Last edited:
Top