From: Stef on
In comp.arch.embedded,
Hans-Bernhard Br�ker <HBBroeker(a)t-online.de> wrote:
> 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.

That's how I implemented a little command interface for setting
parameters a while ago. All commands in the form xy=i. Precheck
the length and extract 'i' and then assign it based on 'xy' in a
switch.

if((len > 3) && (buf[2] == '=')) {
p = (tolower(buf[0]) << 8) | tolower(buf[1]);
i = (int) strtol(&buf[3], NULL, 10);
switch(p) {
case ('k' << 8) | 'p':
set_kp(i);
break;

case ('k' << 8) | 'i':
set_ki(i);
break;


--
Stef (remove caps, dashes and .invalid from e-mail address to reply by mail)

NOWPRINT. NOWPRINT. Clemclone, back to the shadows again.
- The Firesign Theater
From: Fevric J. Glandules on
Hans-Bernhard Br�ker wrote:

> 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.

So would I <grin> but the spec says (e.g.) "0x01 0x44 0x45 0x41 0x03"
[0] i.e. "start-byte ascii ascii ascii end-byte" and the chip that's
talking to me says the same too. I'm not designing [1], I'm
implementing. If the spec says "jump" I ask "how high?". Only if
the spec says "jump off a cliff" do I raise objections.

>> 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.

Let me guess - you live in a 32 bit world, right? <grin>

This is an 8 bit chip, and from what I've seen of its output, the
C18 compiler isn't all that brilliant [2]. I think this is very
much a case of using C as a "high level assembler" - assume that
the compiler will treat everything literally and if it does manage
to optimise every now and then, it's a bonus.


Footnotes:
[0] somebody somewhere got SOH (0x01) confused with STX (0x02).

[1] at that level, at any rate. I have a (relatively) free hand
with what happens on "my" chip.

[2] I'm far from fluent in PIC assembler, in fact I am trying to
avoid spending time on it, but I can read it and get the general
idea, based on past experience with other assembly languages.

From: Paul Keinanen on
On Fri, 11 Sep 2009 21:26:43 +0000 (UTC), "Fevric J. Glandules"
<fjg(a)invalid.invalid> wrote:

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

The command table would consume 30x3 bytes and a jump table based on
the command index 30x2 bytes (assuming 16 bit addresses), so the total
overhead would be 30x5=150 bytes and perhaps 10-20 bytes for scanning
the command table and then performing an indexed jump based on the
result.

Or is that processor too braindead to perform an indexed jump ?

With such a large number of commands, it is more memory space
effective (on any regular processor at least) to scan a command table
and jump/call an action routine based on the command index than build
a case/switch structure on a character by character basis.

Anyway, if the commands are generated by a human user, 3 unambigous
characters is quite sufficient to create a large command set, in which
the user can type in the whole command 3 to INFINITY characters long
(which is great for documentation purposes).

A command table is also useful if support for commands in different
laguages is needed. A switch/case structure would be a mess to
maintain for each language :-).

Paul

From: Paul Carpenter on
In article <nv9ma5h2ae4h545niqs0kscqkle223n76a(a)4ax.com>, keinanen(a)sci.fi
says...
> On Fri, 11 Sep 2009 21:26:43 +0000 (UTC), "Fevric J. Glandules"
> <fjg(a)invalid.invalid> wrote:
>
> >The command set is fixed, and consists of about 30 ASCII triplets, and
> >with any luck won't change too much.
>
> The command table would consume 30x3 bytes and a jump table based on
> the command index 30x2 bytes (assuming 16 bit addresses), so the total
> overhead would be 30x5=150 bytes and perhaps 10-20 bytes for scanning
> the command table and then performing an indexed jump based on the
> result.
>
> Or is that processor too braindead to perform an indexed jump ?

I agree with that and have implemented such schemes several times,
first time being in 1983 on an 8 bit processor with limited memory.

> With such a large number of commands, it is more memory space
> effective (on any regular processor at least) to scan a command table
> and jump/call an action routine based on the command index than build
> a case/switch structure on a character by character basis.

So much easier to add/remove commands to the set.

> Anyway, if the commands are generated by a human user, 3 unambigous
> characters is quite sufficient to create a large command set, in which
> the user can type in the whole command 3 to INFINITY characters long
> (which is great for documentation purposes).

Extending this to a command line structure becomes a lot easier where
you match the first part (upto first delimiter often a SPACE), and get
each command function to call common routines to check the additional
parameters and convert them.

> A command table is also useful if support for commands in different
> laguages is needed. A switch/case structure would be a mess to
> maintain for each language :-).

Easier to reuse the code later in another project.

--
Paul Carpenter | paul(a)pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/> PC Services
<http://www.pcserviceselectronics.co.uk/fonts/> Timing Diagram Font
<http://www.gnuh8.org.uk/> GNU H8 - compiler & Renesas H8/H8S/H8 Tiny
<http://www.badweb.org.uk/> For those web sites you hate
From: Paul Carpenter on
In article <h8en5s$ets$1(a)news.tornevall.net>, fjg(a)invalid.invalid says...
> Hans-Bernhard Bröker wrote:
>
> > 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.

So put the list of triplets in a command table, that means it is easy to
maintain, then have a matching table of functions to jump to.

If you are clever then if the last digit refers to a mode you only
match the first two and then process the last digit appropraitely.
Especially if the command set is two digit alpha for function and
third digit is numerical parameter.

With a command table you can choose whether to match all three or
the first 1 or 2 characters, so the rest are checked by the called
function.

Alternatively you can decode the last digit if it is always numerical
and pass that to the called function.

> > Encoding a mere 30 commands as three-letter tokens is excessively
> > redundant. I would strongly suggest to abbreviate further, to one or
> > two letters.
>
> So would I <grin> but the spec says (e.g.) "0x01 0x44 0x45 0x41 0x03"
> [0] i.e. "start-byte ascii ascii ascii end-byte" and the chip that's
> talking to me says the same too. I'm not designing [1], I'm
> implementing. If the spec says "jump" I ask "how high?". Only if
> the spec says "jump off a cliff" do I raise objections.

A scan of command table is easy to write in C or even assembler.
If all commands start and end with the same byte sequence the processing
can be easier, and these bytes handled before processing the data between
the terminators by scanning a command table.

Also a command table allows you later add a four or larger command as
well.

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

In 1983 I wrote an application to control TV studio Digital Video Effects
controller on an 8 bit micro, that had debug routines to enable the
maintenance and developers to examine memory, registers, devices and had
a command line structure that decoded additional numerical/alpha
parameters.

This sat in an 8 bit processor with external RAM of 2kBytes for the
whole application with over 1kBytes of the RAM spare!

All written in assembler. I have since rewritten and used similar
code or reused similar code in C.

> > 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.
>
> Let me guess - you live in a 32 bit world, right? <grin>

I have done command table with index jump on an 8 bit processor, it
is nothing new.

If you build the right flexibility into the command table handling
once, you can make all your command processing easier and smaller.

Some of my command table implementations, include

min. max character match
min, max parameters on same line
System mode that command can be entered in
different tables sometimes for which mode of operation.
function(s) to call. (same code different table)

Then generalised functions deal with parsing, function calling,
parameter checks, parameter conversions, error reporting handling.

> This is an 8 bit chip, and from what I've seen of its output, the
> C18 compiler isn't all that brilliant [2]. I think this is very
> much a case of using C as a "high level assembler" - assume that
> the compiler will treat everything literally and if it does manage
> to optimise every now and then, it's a bonus.

I personally would not use a PIC, but have used various small
processors to do this sort of command processing, even ones
with binary packet transmissions.

--
Paul Carpenter | paul(a)pcserviceselectronics.co.uk
<http://www.pcserviceselectronics.co.uk/> PC Services
<http://www.pcserviceselectronics.co.uk/fonts/> Timing Diagram Font
<http://www.gnuh8.org.uk/> GNU H8 - compiler & Renesas H8/H8S/H8 Tiny
<http://www.badweb.org.uk/> For those web sites you hate