From: Fevric J. Glandules on
Bob wrote:

> I'm always amazed at how hung-up programmers get about parsing. If you
> have the authority to define the command set, you can make it easy on
> yourself by having fixed length commands; Even a single character (A -
> Z, e.g.) might suffice.

That's probably what I would have done; OTOH at least they are all
exactly three characters long.

> A query has a '?' in buf[1] (or whatever your
> command identifier length is), and a list of comma separated numeric
> arguments is trivial to collect. Since a small project often has no
> floating point, the numbers are all integers.

And numbers - whatever they are - are also all exactly three characters
long, which helps. E.g. 12.3 volts is "123".
From: Hans-Bernhard Bröker on
Fevric J. Glandules wrote:

> I've written some code to parse incoming strings; 'AB1' triggers foo(),
> 'AB2' triggers bar(), and so on. Is the following sensible?

It can be. It may not be. It all depends on the circumstances. How
many commands are there? Do you get any chance to change the command
names? Is the command set fixed for the foreseeable future or likely to
change at a whim?

For large-scale applications of such lexical recognition, there are
general-purpose tools like regexp, tool generators like lex/yacc, and
perfect hash generators.

> switch (*ptrUartRxBuf++) {
> case 'A':
> switch (*ptrUartRxBuf++) {

I'll second the suggestion to leave the pointer alone. Make those
ptrUartRxBuf[0] and ptrUartRxBuf[1]. *ptr++ is a useful idiom
sometimes, but not really in this case.
From: Fevric J. Glandules on
Joe Chisolm wrote:

> Depends on the communications flow. If the commands occur anywhere
> in the buffer and you have an ISR filling the UartRXBuf then things get
> complicated. If the flow is a simple command/response and the commands
> will always be at the beginning of the buffer, then simplify life.

Still up in the air.

> UartRxBuf will be static, hopefully in access memory. If this can be
> the case then use something like:
> switch(UartRxBuf[0])
> case 'A':
> switch(UartRxBuf[1])

I was going on something I'd remembered from this:
http://www.microchipc.com/conference/PIC18Fxxx_comprehensive_tutorial_containing_7Mb_of_info.pdf
but now you've made me go back and check my facts it seems
that array indexes should only be avoided (and pointers used
instead) for "large" (>256 byte) arrays.

Or perhaps the last line on page 64 really does mean that pointers
are /always/ more code efficient than array indexing.

Either way, I really shouldn't be thinking about these issues
at this stage at all! Premature optimisation and all that...

> style you like. If you have to start playing tricks, please be nice
> to the next person who has to look at the code and comment, comment
> comment - and not crappy comments like // load character from buffer

+1 to that.


From: Fevric J. Glandules on
Hans-Bernhard Br�ker wrote:

> Fevric J. Glandules wrote:
>
>> I've written some code to parse incoming strings; 'AB1' triggers foo(),
>> 'AB2' triggers bar(), and so on. Is the following sensible?
>
> It can be. It may not be. It all depends on the circumstances. How
> many commands are there? Do you get any chance to change the command
> names? Is the command set fixed for the foreseeable future or likely to
> change at a whim?

The command set is fixed, and consists of about 30 ASCII triplets, and
with any luck won't change too much.

What I'm doing at this stage is, I'm afraid, asking rather open-ended
and general questions with the aim of getting into the right mindset
for this level of device / code. I've done embedded stuff with
bytes of RAM and with megabytes of RAM; just not with kilobytes.
In addition, all that was a few years ago - I've mostly been
doing PHP, mysql, and Linux server admin in recent years.

> For large-scale applications of such lexical recognition, there are
> general-purpose tools like regexp, tool generators like lex/yacc, and
> perfect hash generators.

Meanwhile I've got a little less than 4K of RAM to play with <grin>.

>> switch (*ptrUartRxBuf++) {
>> case 'A':
>> switch (*ptrUartRxBuf++) {
>
> I'll second the suggestion to leave the pointer alone. Make those
> ptrUartRxBuf[0] and ptrUartRxBuf[1]. *ptr++ is a useful idiom
> sometimes, but not really in this case.

As per the other post, I was going on some Microchip advice to use
pointers not indexes - advice I probably misunderstood the first
time I skimmed through the hundreds of slides in that PDF.

Thanks to all, again, for the responses, questions and suggestions.

And if anybody here is struggling with the DMA engine on a PPC403,
I may have some tips for you <grin>.

From: Hans-Bernhard Bröker on
Fevric J. Glandules wrote:
> Hans-Bernhard Br�ker wrote:
>> Fevric J. Glandules wrote:

> The command set is fixed, and consists of about 30 ASCII triplets, and
> with any luck won't change too much.

Encoding a mere 30 commands as three-letter tokens is excessively
redundant. I would strongly suggest to abbreviate further, to one or
two letters. In the process you would both reduce your communication
load and speed up the interpretation.

> Meanwhile I've got a little less than 4K of RAM to play with <grin>.

You could still use a perfect hash function. That would basically
amount to letting a machine condense your command set to single letters,
in whichever way it liked.

Or you could combine all three letters into a single number, then
switch() directly on that:

switch((u16)buf[0]<<16 + (u16)buf[1]<<8 + (u16)buf[2]<<0)

and let the compiler decide how to implement that most efficiently.