From: Joe Chisolm on 11 Sep 2009 02:38 On Thu, 10 Sep 2009 21:06:26 +0000, Fevric J. Glandules wrote: > nospam wrote: > >> PIC18s are 8 bit processors. > > So they are. I've spent enough time with the datasheet and looking at > example assembler and my own disassembled C code that you'd think it > would have percolated back to my consciousness by now. Mind, it was > quite late when I wrote that. I have found there are several coding constructs that help the MPLAB compiler create tighter code. Define a bit field for logical flags. The compiler will emit BTFSS, BTFSC instructions. If you use a full byte the compiler will emit a MOVF to W and test instructions. If you have something like: flag = 0; ..... flag = 1; ..... if (flag != 0) ... you can save a couple of instruction words by using flag += 1 instead of the flag=1. This is because the compiler will generate a INCF instruction instead of a MOVLW and MOVWF. Many times a switch statement will generate cleaner code than using a if/elsif/else The compiler does a lot of work dealing with pointers and pushing arguments on the stack. If I start running low on program memory I'll usually try different coding constructs and look at the assembly listing to find the best generated code. -- Joe Chisolm Marble Falls, Tx.
From: Fevric J. Glandules on 11 Sep 2009 06:01 Tim Wescott wrote: > This looked interesting when I first saw it, but I haven't tried it: > http://www.embedded.com/columns/technicalinsights/190302110? > _requestid=61933. Thanks for that - it looks well worth reading.
From: Fevric J. Glandules on 11 Sep 2009 06:10 Joe Chisolm wrote: > Many times a switch statement will generate cleaner code than using a > if/elsif/else I've written some code to parse incoming strings; 'AB1' triggers foo(), 'AB2' triggers bar(), and so on. Is the following sensible? // Coded with nested switches in the belief that this will // be far more code and RAM efficient than a strcmp... switch (*ptrUartRxBuf++) { case 'A': switch (*ptrUartRxBuf++) { case 'B': switch (*ptrUartRxBuf++) { case '1': foo(); break; case '2': bar(); break; } break; } break; }
From: Bob on 11 Sep 2009 12:08 Fevric J. Glandules wrote: > Joe Chisolm wrote: > >> Many times a switch statement will generate cleaner code than using a >> if/elsif/else > > I've written some code to parse incoming strings; 'AB1' triggers foo(), > 'AB2' triggers bar(), and so on. Is the following sensible? > > // Coded with nested switches in the belief that this will > // be far more code and RAM efficient than a strcmp... > switch (*ptrUartRxBuf++) { > case 'A': > switch (*ptrUartRxBuf++) { > case 'B': > switch (*ptrUartRxBuf++) { > case '1': > foo(); > break; > case '2': > bar(); > break; > } > break; > } > break; > } > Whether it is more efficient depends on a lot of things - compile it w/ assembly output and compare it to other implementations. It's not the way I would do it unless I had to. 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. 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. Bob
From: Joe Chisolm on 11 Sep 2009 14:18
On Fri, 11 Sep 2009 10:10:02 +0000, Fevric J. Glandules wrote: > Joe Chisolm wrote: > >> Many times a switch statement will generate cleaner code than using a >> if/elsif/else > > I've written some code to parse incoming strings; 'AB1' triggers foo(), > 'AB2' triggers bar(), and so on. Is the following sensible? > > // Coded with nested switches in the belief that this will // be far > more code and RAM efficient than a strcmp... > switch (*ptrUartRxBuf++) { > case 'A': > switch (*ptrUartRxBuf++) { > case 'B': > switch (*ptrUartRxBuf++) { > case '1': > foo(); > break; > case '2': > bar(); > break; > } > break; > } > break; > } 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. 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]) .... Of course, part of this decision is if you are speed or memory size constrained. If you are not hitting up against a program memory size limit or not hitting a execution speed limit, then program in a 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 -- Joe Chisolm Marble Falls, Tx. |