From: Joe Chisolm on
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
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
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
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
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.