Oshonsoft programs with INTERRUPTS and PARSE

Thread Starter

camerart

Joined Feb 25, 2013
3,724
Here you go.
Note that at the top you see:
The active setting speeds up the timers for use in the sim. Bigger number is slower timers.
Comment that out and uncomment the line above to set PR2 to 250 for the live version.

This code uses TIMER2 to generate an interrupt every 20ms. It drives a set of timers from that interrupt.
Each timer is one byte that counts from whatever value you set (0-255) down to 0 then stops at 0. Each timer is used as a guard timer on various info.

To know if a timer has timed out, just read it and test for 0 as you see in main_loop.

There are 2 periods in use:
20ms/count for the UART receive guard timer. This timer is set and begins to run whenever setUARTchannel is called to select a new channel. The default time is 5secs.
Main waiting for new sentence OR timeout:
    waitBuf:
    If buf_done = 0 Then
        'Other processing..
        If ms20_RXguard = 0 Then
            Goto sentence_done
        Endif
        Goto waitBuf
    Endif

'Sentence is received, proceed to parsing it
'Since parsing SHARES some variables with the IRQ service, you can't begin
'looking for the next sentence until parsing is complete.
    Gosub parse  'parse the received sentence

'Process any new data from parseing (while new sentence is being received)
    If prsed_GNRMC = 1 Then
        Hserout "T=", strtim, " N=", strlat, " W=", strlong, CrLf  'process new data
        prsed_GNRMC = 0  'and clear flag to indicate that new data has been "processed"
    Endif

    If prsed_QEIDEG = 1 Then
        Hserout "QEIDEG=  ", qeideg, CrLf  'QEIDEG=BASE 4431 Opto encoder
        prsed_QEIDEG = 0
    Endif

    If prsed_REMOTE = 1 Then
        Hserout "REMVOLT=", strremvolt, " REMALT=", strremalt, " REMDIST=", strremdist, CrLf
        prsed_REMOTE = 0
    Endif

    If prsed_GOOD = 0 Then  'parse tried but string was unknown, corrupt or wrong length
        Hserout "Parse fail Chan: ", #datasw, CrLf
    Endif

'-------------- SENTENCE PROCESSING COMPLETE  ---------------
'Done receiving, parsing and processing ONE sentence.
sentence_done:
    Gosub next_channel  'select next channel
    Gosub setUARTchannel  'start UART on channel(datasw), begins looking for sentence

    Goto main_loop
Note that in main_loop, it now polls the timer along with buf_done. Most of the time, buf_done will be true (meaning it got a sentence from $-W) before the timer runs to 0 and it will fall through to calling parse. If the timer DOES run to 0 before buf_full it means that it did not get a sentence within 5 seconds and it jumps to select the next channel then loops back to see what's happening on that one. In this way, a dead GPS or radio out of range won't lock up the system.

I also added a separate timer for each of the sentence types on the assumption that even if the system did not lock up waiting for a sentence, it would be handy to know which sentence(s) were missing i.e. if it's been too long since the data would be updated. Example, suppose lat and long haven't been updated in awhile, is it at rest or is the GPS dead? Nice to know. These timers are maintained by parse but the code doesn't check them for 0. You can add that as necessary if you want.

The timer names, periods, and default values are shown in the code as:
Timer names and settings:
'receive guard timer
Dim ms20_RXguard As Byte  'native 20ms RX guard timer derived from TMR2 irq
Const RXguardSet = 250  '20ms * 250 = 5 secs to wait for any RX sentence

'Guard timers for each sentence type and their set times
Dim ms100_GNRMCguard As Byte  'GNRMC message guard timer * 100ms
Const GNRMCguardSet = 100  '100ms * 100 = 10 secs to get a good GNRMC sentence

Dim ms100_REMOTEguard As Byte  'REMOTE sentence guard timer *100ms
Const REMOTEguardSet = 100  '100ms * 100 = 10 secs to get a good REMOTE sentence

Dim ms100_QEIDEGguard As Byte  'QEI guard timer *100ms
Const QEIDEGguardSet = 100  '100ms * 100 = 10 secs to get a good QEIDEG sentence
Setting a timer, in this case the RX sentence guard timer, looks like this:
Setting the RX timer in chan_set::
chan_set:
    Gosub IRQinitBuf  'RCIE is off, init buffer, index, flags
    RCSTA.CREN = 1
    RXIRQchar = RCREG
    RXIRQchar = RCREG
    PIE1.RCIE = 1
    ms20_RXguard = RXguardSet 'set RX sentence timer
Return
That's all there is to it.

When you load this in the sim, use the 8xLED window to monitor the Yel and Red LED channel indicators without sending anything. You'll see them changing as ms20_RXguard runs down to 0 and main_loop exits and changes the channel.
In the 'Watch" window, you can see the values of the timers. You'll see the ms20_RXguard running round and round with the channel changing when it goes to 0 and gets reloaded.

Sentence guard timers:
When you send a good sentence and it's parsed, you'll see its timer get set and begin to run down. If you don't send anything else, it will run to 0 indicating it's been a long time since it received that sentence and the data is getting stale. Look at these as juggling to keep 3 balls in the air. As long as you are tossing the balls (receiving and processing valid sentences) they'll stay in the air (timer never runs to 0). Stop juggling and the balls hit the floor (timer runs to 0). Right now, we don't do anything with the timeout indication but if your code is interested in whether your data is recent, read the sentence's timer, if it's non-zero, the data is recent. If 0, stale.

The lesson here is what you've already found out - never wait endlessly on something from the horrible outside world to arrive.. always have some sort of mechanism to keep an eye on things, allow the code to keep moving and give you a chance to take action if something goes away unexpectedly.

Final note: the times were picked out of the air and are likely longer than necessary. They can be adjusted by changing the Const... values near the top of the file. I'm not sure what your sentence rate is.

This is new stuff but worth the study.
Good luck!

EDIT: add example setting timer
Hi JT,
You used a juggling metaphor as an explanation, well, using the same metaphor, I'm now juggling 3x more balls than I'm capable of :)

Thanks you for this thought out solution. I can basically understand it, but not really. E,G, I try to visualise what would happen with an actual flying machine, and saw a line [10 secs to get a good REMOTE sentence] so, if I understand correctly, a flying machine may have moved for 10Secs, and they can go perhaps 20MPH. When flying near object this is too long to act. I did note however, that you mention correcting the timings, which I'll bear in mind if I do manage to follow your CODE properly, but you may be able to imagine it also.

I like that 'the end of one message triggers then next in the sequence', and think that this is the most efficient, if there is always a sentence, but if one doesn't arrive, then things happen. Previously, I had it that the DATASWITCH would switch through the sequence anyway, but not as fast. I was wondering if the DATASWITCH switched 3x/sec if the previous sentence didn't switch it, this would be faster.

Trying to visualise the timings of the receving sentences. Each of the sentences are arriving at 5x/sec but rather randonmly. The GPS has 2x values '5/sec' or '1/sec', the REMOTE and 4431 timings can be changed in their programs. The GPS is the most accurate I think, so it may be possible to use the 5/sec to trigger the DATASWITCH or the 18F4431. I also wondered about synching every thing together, using either the GPS or the 18LF4620 clock.

Anyway, I'll try your program, and see if I can follow it.
Cheers, C.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
Hi JT,
Hi JT,
You used a juggling metaphor as an explanation, well, using the same metaphor, I'm now juggling 3x more balls than I'm capable of :)

Thanks you for this thought out solution. I can basically understand it, but not really. E,G, I try to visualise what would happen with an actual flying machine, and saw a line [10 secs to get a good REMOTE sentence] so, if I understand correctly, a flying machine may have moved for 10Secs, and they can go perhaps 20MPH. When flying near object this is too long to act. I did note however, that you mention correcting the timings, which I'll bear in mind if I do manage to follow your CODE properly, but you may be able to imagine it also.

I like that 'the end of one message triggers then next in the sequence', and think that this is the most efficient, if there is always a sentence, but if one doesn't arrive, then things happen. Previously, I had it that the DATASWITCH would switch through the sequence anyway, but not as fast. I was wondering if the DATASWITCH switched 3x/sec if the previous sentence didn't switch it, this would be faster.

Trying to visualise the timings of the receving sentences. Each of the sentences are arriving at 5x/sec but rather randonmly. The GPS has 2x values '5/sec' or '1/sec', the REMOTE and 4431 timings can be changed in their programs. The GPS is the most accurate I think, so it may be possible to use the 5/sec to trigger the DATASWITCH or the 18F4431. I also wondered about synching every thing together, using either the GPS or the 18LF4620 clock.

Anyway, I'll try your program, and see if I can follow it.
Cheers, C.
Hi JT,
In #321, I was wondering! (Marked in red) and it appears that your CODE does exactly this. If I understand correctly, the TMR can be changed to 1/3 sec, which would be better I think.

I almost understand what your CODE is doing. In the SIM it worked fine. LIVE it also worked fine, with the occasional error showing on the REMOTE. As before it's 'seeing' each second of the GPS readings with the occasional 2/sec, I presume this applies to all 3x channels, although the REMOTE READings sometimes miss a few. Normally only the GPS needs fast READings as the other 2x are normally slow to change.

Well done, thanks.
C.
 

JohnInTX

Joined Jun 26, 2012
4,787
Nice! Let's talk about the RX guard timer and get it slicked up.
As you've deduced, the timer is a last-resort. If a good string is received, buf_done is set and the processing begins immediately regardless of the current value of the timer. But we don't need to wait all day so how to figure out what a reasonable timer setting is i.e. don't wait too long to decide that a sentence is not coming but don't give up too soon. My thoughts are you need to set the time to:
2x the time to send one sentence + the time between sentences + 1x the guard time period as a minimum. I imagined that the channel was selected right after the $ of a sentence. You would have to wait for that entire sentence to finish, then wait for the inter-sentence time, then receive the next, hopefully good, sentence. The timer design is such that the time is up to 1 period less than the count so add one count.
Suppose the $GNRMC sentence is sent 2 times a second. A minimum timer setting would be:
2x 46.8ms (45 characters at 1.04ms/char at 9600baud) +
500ms (time between sentences) +
20ms (timer uncertainty). =
613.6ms. Rounding up to the timer period you get 620ms. The timer setting is then 620ms/20ms = 31.
So with those assumptions on the worst case, you wait up to 620ms for any sentence, not my overly generous 5 sec.

How can that be better?
  • Decrease the TX time between sentences to the minimum available for all of them.
  • The guard timer can be set to different values for each channel by moving where we set it to the individual channel set code. No sense in waiting the worst case sentence if others are faster.
  • Decrease the timer period. If we're not waiting 5 sec for a sentence, we can run the 8bit timer faster for finer resolution.
  • Determine what the inter-sentence time is based on. I assumed the worst case last character to next $. It may be time between the $ of successive sentences. That would shorten the guard time by a sentence length. That also could be different for each channel.
  • Relocate the channel switch for the next sentence to just after the return from parse. That way, it can start looking for the next sentence while you process the new sentence and do whatever else you need. No sense in leaving the receiver idle when it could be getting the next sentence in the background

In a nutshell, I set the times very long so that we wouldn't be tripped up by timeouts while verifying other stuff. If we're ready to tune the timers, let me know what you think the max wait time for each sentence should be.

Onward!
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
Nice! Let's talk about the RX guard timer and get it slicked up.
As you've deduced, the timer is a last-resort. If a good string is received, buf_done is set and the processing begins immediately regardless of the current value of the timer. But we don't need to wait all day so how to figure out what a reasonable timer setting is i.e. don't wait too long to decide that a sentence is not coming but don't give up too soon. My thoughts are you need to set the time to:
2x the time to send one sentence + the time between sentences + 1x the guard time period as a minimum. I imagined that the channel was selected right after the $ of a sentence. You would have to wait for that entire sentence to finish, then wait for the inter-sentence time, then receive the next, hopefully good, sentence. The timer design is such that the time is up to 1 period less than the count so add one count.
Suppose the $GNRMC sentence is sent 2 times a second. A minimum timer setting would be:
2x 46.8ms (45 characters at 1.04ms/char at 9600baud) +
500ms (time between sentences) +
20ms (timer uncertainty). =
613.6ms. Rounding up to the timer period you get 620ms. The timer setting is then 620ms/20ms = 31.
So with those assumptions on the worst case, you wait up to 620ms for any sentence, not my overly generous 5 sec.

How can that be better?
  • Decrease the TX time between sentences to the minimum available for all of them.
  • The guard timer can be set to different values for each channel by moving where we set it to the individual channel set code. No sense in waiting the worst case sentence if others are faster.
  • Decrease the timer period. If we're not waiting 5 sec for a sentence, we can run the 8bit timer faster for finer resolution.
  • Determine what the inter-sentence time is based on. I assumed the worst case last character to next $. It may be time between the $ of successive sentences. That would shorten the guard time by a sentence length. That also could be different for each channel.
  • Relocate the channel switch for the next sentence to just after the return from parse. That way, it can start looking for the next sentence while you process the new sentence and do whatever else you need. No sense in leaving the receiver idle when it could be getting the next sentence in the background

In a nutshell, I set the times very long so that we wouldn't be tripped up by timeouts while verifying other stuff. If we're ready to tune the timers, let me know what you think the max wait time for each sentence should be.

Onward!
Hi JT,
If I'm reading my oscilloscope correctly, the length of the longest $sentence (GPS) is 70ms and the gap till the next $ is 130ms so total 200ms and as it is set to 5xsec this adds up.

The QEIDEG sentence will always be the same length, but the REMOTE is an example for testing, I'm not sure what that will be until working on the REMOTE. Both of these are sent 5Xsec also.

Regarding your comment in #306, you mention a COMPASS, there is a COMPASS peripheral (SPI), but the Degrees we're talking about here is from an incremental encoder on 18F4431 which is a dial on the transmitter, where a bearing can be steered.
C.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
OK so we'll set the $GNRMC RX guard time to 300ms - 200ms between the $ and 45ms for the message. Note that even if the message length is 70ms, we are only reading until the "W" which shortens it.
Changing the REMOTE format is OK. You'll of course need to update 'parse' to extract the various bits.

What is the rep rate of the other two sentences? I'll update those times and send something to you.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
OK so we'll set the $GNRMC RX guard time to 300ms - 200ms between the $ and 45ms for the message. Note that even if the message length is 70ms, we are only reading until the "W" which shortens it.
Changing the REMOTE format is OK. You'll of course need to update 'parse' to extract the various bits.

What is the rep rate of the other two sentences? I'll update those times and send something to you.
Hi JT,
I tried 25 instead of 250, which I think '=' 1/2 sec and it seemed to work ok. I switched off/on the REMOTE TX from the computer.

With the GPS, the $GNRMC sentences @5/sec, if we miss the 1st digit of a message and go to the W in the next, I assume it would see:
$GNRMC,123456.00,A,1234.76019,N,01234.93717,W,0.301,,150620,,,A*7E........................................................
............................................................$GNRMC,123456.00,A,1234.76019,N,01234.93717,W
,0.301,,150620,,,A*7E

All sentences repeat @5/sec.
C
 

JohnInTX

Joined Jun 26, 2012
4,787
Hi JT,
I tried 25 instead of 250, which I think '=' 1/2 sec and it seemed to work ok. I switched off/on the REMOTE TX from the computer.

With the GPS, the $GNRMC sentences @5/sec, if we miss the 1st digit of a message and go to the W in the next, I assume it would see:
$GNRMC,123456.00,A,1234.76019,N,01234.93717,W,0.301,,150620,,,A*7E........................................................
............................................................$GNRMC,123456.00,A,1234.76019,N,01234.93717,W
,0.301,,150620,,,A*7E

All sentences repeat @5/sec.
C
Correct! So the elapsed time for the two sentences in red is 200ms (5/sec) + 1.04ms * 45 (the number of characters in the 2ed 'good' one.) I'd round it up to 300ms for now.
The timing would be essentially the same for the other two, a little shorter because of fewer characters in the sentence.
I am detailing the timers to offer better resolution and will post when tested.

When done, that will pretty much finish this phase i.e. getting the communications robust and properly parsed into strings. There are some detail performance improvements we can contemplate before tying a bow on it:
We should move the 'next channel' selection to right after parse so that it can receive while you are processing the previous message.
You should realize that Hserout is a 'blocking' routine i.e. it hogs the CPU for roughly 1.04ms per character sent. If that is an issue, we can address it. You can get some immediate benefit by being less verbose in your readouts.
As long as you are sending all of that info back to the PC, you will be missing the occasional REMOTE message because of the half-duplex nature of the comms link. Is that going to be a problem?

Let me know what you think about those questions.
JinT
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
I detailed the various timers for better resolution.
Timers are running at actual speed (not sped up for sim).
Done.
See the notes.
Have fun!
Hi JT,
For my scanning preferences, I try to keep things as flowing as possible, and of course had to accept the fact that e,g, [Hseropen 9600] needs to be in a certain order with [RCSTA.CREN = 0] as you explained.
For me, I prefer the [On High Interrupt] to be top of the SUBROUTINES, then each [GOSUB/CALL ROUTINE] in order of use below their [GOSUB/CALL] If that's ok with you, I can re-order them, but again of course, if it is poor programming then I'll accept them as you place them. It would also be safer for you to move them, in case of me confusing the situation, but I'm happy to do it.
NOTE: Oshonsoft requires the END before any SUBROTINES/INTERRUPTS.
--------------------------------------------------------------------------------------------------------
"Correct! So the elapsed time for the two sentences in red is 200ms (5/sec) + 1.04ms * 45 (the number of characters in the 2ed 'good' one.) I'd round it up to 300ms for now."

I'm not as good at calculations as you are, and I've spent my life guessing. Regarding the length of time to wait, if there is no signal: My logic is, that if there is no signal, there won't be a '$' within 1.5 %sentences, so 300ms, any longer is slowing down the other 2x % sentences till a signal is received. So I would guess 300ms for the timer, would be better, any thoughts? If it helps, I think that only 1x

I note this latest program is LIVE. I've just tried it and if you recall previously, the $GNRMC Sentence PARSED at 1x sometimes 2x/sec, and now mostly being PARSED 2x/Sec, so improvement there.
-----------------------------------------------------------------------------
"You can get some immediate benefit by being less verbose in your readouts. "
Will you clarify please?
--------------------------------------------------------------------------------------
"As long as you are sending all of that info back to the PC, you will be missing the occasional REMOTE message because of the half-duplex nature of the comms link. Is that going to be a problem? "
Looking at the Terminal view, the $GNRMC sentences seem more successful than the REMOTE sentences. I can't tell with the QEIDEG sentence. I don't think it will be a problem when flying, as the REMOTE messages will be things like battery voltage, and perhaps temperature, which change slowly. QEIDEG knob will be turned pretty slowly I think, you didn't mention QEIDEG, but I don't thnk it will be a problem.
Well done again. What colour will the bow be? A small thing, but if we are using BST, then the Day will be before the month, so 140720. which of course is the correct way round.;)

EDIT: I just ran the #328 program, with REMOTE OFF, and tried to keep up counting the other two $Sentences using the LEDS, and it was >110/Sec.
C.
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,787
I think the 300ms is fine for sentences at 5/sec. You could tighten it up a bit but at this point, I'd leave it at that.

Re: LIVE. I said that because the PR2 setting for the TIMER2 system tik was set to the LIVE value instead of the shorter value for the sim. BUT, I forgot about the OSH define that shortened delays for the sim. That was left enabled so there might be some issues there. To mitigate problems like that, I like to put ALL of the things that are target related (sim or LIVE PCB) near the top of the source file so that I don't miss things like that.

Re: less verbose readouts. Hserout waits on each character to be fully sent before it returns. At 9600 baud, each character is about 1msec. So for timing purposes, sending a 30 character message to the PC has the same timing as dropping a Waitms(30) into your code. It's actually a little worse when you include overhead but you get the idea. My point was that we've sped this thing up considerably and now things like Hserout can be a factor in the total processing time. There are ways to beat that if the delay from the reports to the PC are an issue. But shortening the number of characters sent is a cheap way to make that part of the code run faster if that becomes an issue. If it's fast enough now, just make a note of this discussion and continue on.

Re: REMOTE readouts. There's not much we can do to fix the lost messages due to the half-duplex radio. I thought up a way to synchronize a timer to the REMOTE message to figure out when it might be using the radio but it's not trivial and best left alone unless you have a compelling reason.

But since REMOTE doesn't have fast changing information, you could keep the other stuff more current by only selecting and processing $REMOTE once in awhile rather than a round-robin deal. The code is currently structured to make that not too hard to do. You could specify the channels in a string that indicated the order to look for sentences:
"020202021" Alternate between 0 and 2 4 times then get REMOTE.
OR
"000010002" Get channel 0 mostly and poke in 1 and 2 once in awhile as needed.
Using a string allows you to rework the scheduling just by re-typing the string. Nice.

Organizing the source code: Sure. Move the blocks around to make yourself comfortable. As you've seen, I am visually organized and like lots of space and delimiters. I try to write so that each function or routine fits on one screen or close to it. I would consider using OSH's INCLUDE directive to move all of the support functions to another file and just have the declarations and main loop in the main file. That way, you treat those other functions as black-boxes that just do helpful things and you can concentrate on your main code flow. But it's completely up to you. You will be integrating this back into your other code and need to be able to manage that so have at it.

BST: sure, I didn't recall your method of time and was too lazy to look it up. :cool:

So.. I'm thinking this is about ready to kick loose? If not, what's left?
J
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
I think the 300ms is fine for sentences at 5/sec. You could tighten it up a bit but at this point, I'd leave it at that.

Re: LIVE. I said that because the PR2 setting for the TIMER2 system tik was set to the LIVE value instead of the shorter value for the sim. BUT, I forgot about the OSH define that shortened delays for the sim. That was left enabled so there might be some issues there. To mitigate problems like that, I like to put ALL of the things that are target related (sim or LIVE PCB) near the top of the source file so that I don't miss things like that.

Re: less verbose readouts. Hserout waits on each character to be fully sent before it returns. At 9600 baud, each character is about 1msec. So for timing purposes, sending a 30 character message to the PC has the same timing as dropping a Waitms(30) into your code. It's actually a little worse when you include overhead but you get the idea. My point was that we've sped this thing up considerably and now things like Hserout can be a factor in the total processing time. There are ways to beat that if the delay from the reports to the PC are an issue. But shortening the number of characters sent is a cheap way to make that part of the code run faster if that becomes an issue. If it's fast enough now, just make a note of this discussion and continue on.

Re: REMOTE readouts. There's not much we can do to fix the lost messages due to the half-duplex radio. I thought up a way to synchronize a timer to the REMOTE message to figure out when it might be using the radio but it's not trivial and best left alone unless you have a compelling reason.

But since REMOTE doesn't have fast changing information, you could keep the other stuff more current by only selecting and processing $REMOTE once in awhile rather than a round-robin deal. The code is currently structured to make that not too hard to do. You could specify the channels in a string that indicated the order to look for sentences:
"020202021" Alternate between 0 and 2 4 times then get REMOTE.
OR
"000010002" Get channel 0 mostly and poke in 1 and 2 once in awhile as needed.
Using a string allows you to rework the scheduling just by re-typing the string. Nice.

Organizing the source code: Sure. Move the blocks around to make yourself comfortable. As you've seen, I am visually organized and like lots of space and delimiters. I try to write so that each function or routine fits on one screen or close to it. I would consider using OSH's INCLUDE directive to move all of the support functions to another file and just have the declarations and main loop in the main file. That way, you treat those other functions as black-boxes that just do helpful things and you can concentrate on your main code flow. But it's completely up to you. You will be integrating this back into your other code and need to be able to manage that so have at it.

BST: sure, I didn't recall your method of time and was too lazy to look it up. :cool:

So.. I'm thinking this is about ready to kick loose? If not, what's left?
J
Hi JT,
Re: REMOTE readouts. In the Terminal we can see all of the REMOTE sentences being TX, but we can't see the other two types, and I think it may be an optical illusion, that we're missing sentences. e,g, I mostly see 2x $GNRMC sentences, but there are 5x sent.

Re: INCLUDE There is an INCLUDE in the FULL program, for screen text, but I don't need to see it, for programming. It will be a good idea later.

Re: Other Timing issues. I'll try to remember what you say, regarding trimming sentences etc.

As for BST, It's just the way I save PIC programs, I wouldn't say you are lazy:)

I'm eager to "Kick loose" I'll move a few blocks around to help me scan, and hope I don't damage anything. I can always return to the #328

I see ['Other processing here] is this where the FULL program MAIN LOOP goes?
C.


Code:
main_loop:  '/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

waitBuf:
    If buf_done = 1 Then  'If got A sentence, parse it
        Goto do_parse
    Endif
        
    If ms05_RXguard = 0 Then  'If timeout, change channels
        Gosub next_channel
        Gosub setUARTchannel
    Endif
    
    'Other processing here
    Goto waitBuf  'loop until something happens

    
'Sentence is received, proceed to parsing it
'Since parsing SHARES some variables with the IRQ service, you can't begin
'looking for the next sentence until parsing is complete.
do_parse:
    Gosub parse  'parse the received sentence
    
    Gosub next_channel  'select next channel before processing
    Gosub setUARTchannel  'start UART on channel(datasw), begins looking for sentence
    
'Process any new data from parseing (while new sentence is being received)
    If prsed_GNRMC = 1 Then
        Hserout "T=", strtim, " N=", strlat, " W=", strlong, CrLf  'process new data
        prsed_GNRMC = 0  'and clear flag to indicate that new data has been "processed"
    Endif

    If prsed_QEIDEG = 1 Then
        Hserout "QEIDEG=  ", qeideg, CrLf  'QEIDEG=BASE 4431 Opto encoder
        prsed_QEIDEG = 0
    Endif

    If prsed_REMOTE = 1 Then
        Hserout "REMVOLT=", strremvolt, " REMALT=", strremalt, " REMDIST=", strremdist, CrLf
        prsed_REMOTE = 0
    Endif
    
    If prsed_GOOD = 0 Then  'parse tried but string was unknown, corrupt or wrong length
        Hserout "Parse fail Chan: ", #prsed_ERRchan, CrLf
    Endif
    
'-------------- SENTENCE PROCESSING COMPLETE  ---------------
'Done receiving, parsing and processing ONE sentence.
sentence_done:
    Goto main_loop
    
End  'don't really need this as main stays in a loop
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
Hi JT,
I re-arranged it slightly, and don't think I broke anything.

I tried in in SIM, but with the LIVE DATASWITCH acting differently from the SIM one, I don't think it SIMs correctly. I think a special long string of good and bad $sentences has to be made, that is exactly timed for the SIM. Anyway, it mostly SIMs, with a bit of coaxing, not your fault.
I had job following it, with you're clever bits in it, but I could generally see it is good.

LIVE it works really well.

I think it may be time to add it into the FULL program. Note my last message.
Cheers, C
 

JohnInTX

Joined Jun 26, 2012
4,787
Re: REMOTE readouts. In the Terminal we can see all of the REMOTE sentences being TX, but we can't see the other two types, and I think it may be an optical illusion, that we're missing sentences. e,g, I mostly see 2x $GNRMC sentences, but there are 5x sent.
I don't think it's an illusion, you really are 'missing' some sentences but that's the nature of the beast when you share the UART between 3 sources.
As a rough analysis consider that you are slicing one second of time into 5 slices each 200ms long (all sentences sent at 5/sec). The first sentence received occupies one of those slices. The other two use two more slices, leaving two left. The first sentence uses one of those leaving one for the next sentence. That uses up all of the slices in one second. Now, how many times did the first sentence get received in that full second of time? Two times, yes. So.. that's what you are seeing. It's the nature of the beast.
I see ['Other processing here] is this where the FULL program MAIN LOOP goes?
Depends. This little work of art we've done here is primarily concerned with receiving and parsing sentences. It also does some processing of data received in a newly received sentence. I would think a good organization would be:
While waiting on new data
do things that use the current data - flight controls etc.
When new sentence is received
parse that data fully into 'current' data INCLUDING any string to numeric variable conversion
Loop back to the top

As a general rule:
If the processing to be done is a direct result of a new sentence with the goal of updating system variables, put that code between the return from parse and the loop back to main_loop.
If it is something else, put it where it says Other Processing Here.

I think...

Give it a shot and see how that works.
EDIT: was typing when you posted #322. Glad it's working well LIVE. Glad also that you were able to follow my code including the 'clever bits'.
Carry on!
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
I don't think it's an illusion, you really are 'missing' some sentences but that's the nature of the beast when you share the UART between 3 sources.
As a rough analysis consider that you are slicing one second of time into 5 slices each 200ms long (all sentences sent at 5/sec). The first sentence received occupies one of those slices. The other two use two more slices, leaving two left. The first sentence uses one of those leaving one for the next sentence. That uses up all of the slices in one second. Now, how many times did the first sentence get received in that full second of time? Two times, yes. So.. that's what you are seeing. It's the nature of the beast.
Depends. This little work of art we've done here is primarily concerned with receiving and parsing sentences. It also does some processing of data received in a newly received sentence. I would think a good organization would be:
While waiting on new data
do things that use the current data - flight controls etc.
When new sentence is received
parse that data fully into 'current' data INCLUDING any string to numeric variable conversion
Loop back to the top

As a general rule:
If the processing to be done is a direct result of a new sentence with the goal of updating system variables, put that code between the return from parse and the loop back to main_loop.
If it is something else, put it where it says Other Processing Here.

I think...

Give it a shot and see how that works.
EDIT: was typing when you posted #322. Glad it's working well LIVE. Glad also that you were able to follow my code including the 'clever bits'.
Carry on!
Hi JT,
I think it was my incorrect use of the word illusion, but I think it is exactly as you say.

As you say, I'll give it a shot. I'll do it as best as I can and put each section in blocks, to that it can be changed. For me this is an unknown 'adventure' so who knows what will happen. We can always drop back and start again with todays programs, I'm quite used to back tracking, and repairs.

As this thread is done, I'll go back to the main thread here: https://forum.allaboutcircuits.com/threads/remote-control-by-location-pic-in-oshonsoft.148795/

Thanks again, this has been an education, although a bit beyond me. Not forgetting all of the other contributers. :)
Cheers, Camerart
 

JohnInTX

Joined Jun 26, 2012
4,787
Thanks again, this has been an education, although a bit beyond me.
You're welcome, it's been fun. Do keep in mind that all education is 'beyond' the student. Otherwise, you wouldn't need it. ;) Don't fret too much about the new stuff. Understanding will grow as you use it.
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
Hi JT,
I've been re-reading you comments in this thread, and need to do it again, but I don't retain all of it, and somewhere along it, the 'adding zeros' section went missing.
You will notice that [CAP2BUF] was used. This was from the hardware QEI of the 4431, and the reason the 4431 was added. This used WORDs. However in the present application, SPI is READing the Compass, and there are calculation, so SINGLEs are used, and there are differences.

As the latest programs have been tuned by you, I'll use them, and add in the 'adding zeros' CODE, and see if I can get it working.

I'll report back.
C
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
Hi,
I'm re-checking some of the information in this thread.
Around: https://forum.allaboutcircuits.com/...with-interrupts-and-parse.168960/post-1529995 is a section about adding zeros in front of some data so that there are always 3x digits, keeping the DATA the same length, for parsing, e,g, 001 020, 359.

Around this section: https://forum.allaboutcircuits.com/...location-pic-in-oshonsoft.148795/post-1533954 is a suggestion to only use BYTEs word, but not STRINGS for sending and receiving, until e,g, it is needed to be sent to a terminal for reading while testing. (Search the page for NORMALIZE)

Any guidance welcome please.
Cheers, C.
 
Last edited:

sagor

Joined Mar 10, 2019
903
I always use bytes, never strings (where possible). When Oshonsoft defines a string, it is allocated a specific length for storage. This is for ALL string declarations, they are all allocated the maximum length you define, even when you want only a single string character. Strings can be very wasteful. Bytes contain the same ASCII characters, you can check any byte by checking its ASCII value, instead of string comparison. String comparisons use a lot of CPU cycles compared to byte comparisons.
True, byte arrays also reserve memory, but only for the one variable you are defining. And, if you need a 5 byte array, it uses 5 bytes. If you need an 80 byte array, you define it separately and only that variable uses 80 bytes.
Not true for strings. Oshonsoft sets a definition for maximum string length, and all strings reserve that length, regardless if you only need a shorter string.
Now if a device sends only character data to the program, you do have to do some conversions if you want to extract values, but that is relatively easy to do with the STRVALB and STRVALW functions (and STRVALS, etc). But, those string to value conversions do take CPU cycles too...
 

Thread Starter

camerart

Joined Feb 25, 2013
3,724
I always use bytes, never strings (where possible). When Oshonsoft defines a string, it is allocated a specific length for storage. This is for ALL string declarations, they are all allocated the maximum length you define, even when you want only a single string character. Strings can be very wasteful. Bytes contain the same ASCII characters, you can check any byte by checking its ASCII value, instead of string comparison. String comparisons use a lot of CPU cycles compared to byte comparisons.
True, byte arrays also reserve memory, but only for the one variable you are defining. And, if you need a 5 byte array, it uses 5 bytes. If you need an 80 byte array, you define it separately and only that variable uses 80 bytes.
Not true for strings. Oshonsoft sets a definition for maximum string length, and all strings reserve that length, regardless if you only need a shorter string.
Now if a device sends only character data to the program, you do have to do some conversions if you want to extract values, but that is relatively easy to do with the STRVALB and STRVALW functions (and STRVALS, etc). But, those string to value conversions do take CPU cycles too...
Hi S,
I've looked through the manual, and the first thing is:
Example of an ARRAY: DIM A(10) AS BYTE
Is [ A ] the name of the ARRAY, or does it stand for ARRAY?

I'm used to [ Define STRING_MAX_LENGTH = 20 ] and that this means all STRINGS take this much memory.

I think there won't be too many STRINGS, using this method.
I also think the length of BYTEs sent and received will be a fixed length.

Apart from that I've got to figure out quite a few things to switch over. I'll post an example program, and see what it looks like.
Thanks, C.
 
Top