From: Fevric J. Glandules on 11 Sep 2009 16:38 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 11 Sep 2009 16:46 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 11 Sep 2009 16:58 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 11 Sep 2009 17:26 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 11 Sep 2009 18:27
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. |