PDA

View Full Version : An array of strings



acantostega
10-19-2006, 06:21 AM
Hi all,
I'm trying to make something like an array of strings. The ideas is to have various cogs running, each one writing a string in their own slot in the array, while another cog, which controls an LCD, selects one of the strings (based on some priority scheme) to write to the LCD.
Now, I know there aren't any double arrays (e.g. byte str_array[10][LEN]) so instead I'm using one long linear array and appropiate methods to manipulate them. Here's the code:



CON
LEN = 32 ' the max length of a string
NUM_STRINGS = 10 ' number of strings

OBJ
uart_lcd "SimpleSerial" ' the serial lcd-controlling object

VAR
byte str_array[LEN*NUM_STRINGS] ' the array itself




Now to write to the array, a method on some cog (that is supposed to write on, say the kth slot) would be something like



bytemove(@str_array + LEN*k, string("a message"), LEN) ' write "a message" to the Kth slot.



and the LCD writing method, in reading the i-th slot, would do



uart_lcd.str(@str_array + LEN*i) ' give uart_lcd.str() the address of the ith string in the array.



Alas, it won't work. It compiles, but the LCD remains blank (and the LCD is ok). Is the code correct? Do you have a better approach? Another approach I tried was instead using something like what you would in C, e.g., have char **str_array, and directing each pointer in str_array to the correct address (str_array[j] = address_of_string). Memory addressess in the Prop are LONGs, right? So I have



LONG str_array[N]
'....
str_array[k] := string("a message") ' write to kth slot
'....
uart_lcd.str(str_array[j]) ' send to lcd string in jth slot



This method would have the advantage of using up only half the space. But it isn't working either, I still get a blank lcd. (I zeroed out the arrays beforehand, so I guess that's why I don't get garbage either).

No, wait! I spoke too soon, both methods work. I had a bug in the lcd-sending behavior. I like the second method better, it's shorter and it saves memory.

Post Edited (acantostega) : 10/18/2006 10:28:28 PM GMT

Mike Green
10-19-2006, 06:47 AM
As long as you have string constants, either scheme works fine and storing the addresses saves on copying the string data too.
If you end up building the messages, have a simple string (byte array) variable in each cog that will construct its own message
and still pass the address of the string to be displayed. In your routine to display messages to the LCD, check for a zero address
and skip that message if so. Initialize the "str_array" to zeros during your program's initialization.

Great example of how to do things in SPIN.

acantostega
10-19-2006, 07:36 AM
Thanks, Mike. Good ideas!

Cliff L. Biffle
10-19-2006, 11:04 PM
And the manual describes SPIN as a "high-level language."

Enjoy the pointer twiddling.

Mike Green
10-19-2006, 11:16 PM
Cliff,
It's not helpful to gripe. SPIN is a high level language by most standards, particularly its control structures. It happens to have been designed primarily for hardware control where things like string manipulation and dynamic storage allocation are not that important. That said, it would be useful to have a library of string manipulation routines. Given that SPIN treats string information similar to the way C does it (as pointers to zero-terminated strings), maybe a library of routines loosely based on C's packaged as an object would be helpful.
Mike

Cliff L. Biffle
10-19-2006, 11:32 PM
Mike Green said...

It's not helpful to gripe.



You're right. I'll save the griping for my blog. http://forums.parallax.com/images/smilies/smile.gif I just read all the way through the Propeller Manual for the first time, and every time they used the terms "high-level" and "object-based," as a language implementer, I died a little inside.


Mike Green said...

SPIN is a high level language by most standards, particularly its control structures.



Macro libraries could add similar structured programming facilities to s390 assembler. Perhaps we're coming at this from different angles, but for me, control structures don't make a language high-level -- abstraction does.

If we're counting BCPL as high-level, then sure -- like SPIN, it lacked any type system beyond "machine word." http://forums.parallax.com/images/smilies/smile.gif

C is also designed for systems programming, but has a decent type system (which is admittedly limited), structs, namespaced enums, and the ability to declare locals and constants at least within the procedure where they're used (though ANSI C limits this unnecessarily). For low level programming on AVRs, I find the distinction between integers and pointers, and the 'const' modifier, indispensible. SPIN offers neither.

A consistent way of handling strings in SPIN would be to simply create the statically-allocated ones as objects. Then they get namespaced functions and constants and so forth.

(This wouldn't work, of course, because SPIN's "object system" is really a half-formed module system -- which is why it would make sense to distribute a string library as an "object," but not create each string separately as one.)

If people would find it useful, I could implement a libc-like string package for Spin. I just finished implementing one for another language (though in Unicode), so the algorithms are fresh in my mind.

Edit: Why every website needs its own markup language, I'll never know. Markup fixed.

Bill Henning
10-20-2006, 12:15 AM
It would be possible to implement a C compiler for the propeller, however it would require a cog to run some sort of interpreter as the native architecture of cogs is VERY unsuitable for C... namely, there is no hardware stack, and no provisions for easy/fast indexed addressing of hub memory, and no provisions of anything but word addressing of cog memory, and only 512 words of directly addressible code space (it is possible to swap in code from hub memory for cogs, thus the program size limit can be bypassed) / fast data space. Among other things, it would make "local variable" that lived on a stack comparatively slow to access.

Personally, the more I use the propeller, the more I look at it as a very cool piece of programmable hardware, with spin acting like a high(er) level to implement more complex (code space wise) programs with, and cogs running very fast assembly code. For more conventional HLL oriented controllers, I have several ARM7 variations to play with... for my AVR's I still code in assembly, though I must admit, I have installed WinAVR. (for one of my projects I am actually seriously considering marrying an ARM7 with the propeller - prop for high speed I/O, LCD, etc., ARM for "conventional" HLL coding with LOTS of memory)

I'm having too much fun writing very high speed assembly code for the propeller to worry too much about high level languages right now :)

Mike Green
10-20-2006, 12:22 AM
Cliff,
I've programmed pretty much everything from a plug-board "calculating punch" to a System 360/195 to the latest Intel chip and in everything from pure binary instructions to Smalltalk / Lisp / APL / COBOL / Snobol / RPG / TMG / Pascal / "I don't know I've lost track", written commercial compilers, operating systems, built and debugged CPUs. Anyway, I've seen it all, either from direct experience or literally looking over someone's shoulder.

1) Control structures do make a language high-level, so do data structures. They're all forms of abstraction. They're all useful for trying to represent the "deep" structure of our algorithms. Some tasks and algorithms become crystal clear and precise when represented in one particular notation / language and absolutely impenetrable in another and other tasks the opposite.

2) SPIN isn't a bad language for the particular application set and processor capabilities it was developed for. The Propeller is sufficiently powerful that SPIN and its limitations, both in language and implementation will be a problem later, particularly with the probable improvements in a 2nd generation Propeller.

a) You're right, you can do really remarkable data and control structuring and abstracting with a good macro processor and there are no provisions in the current IDE for that. Fortunately, it could be added later. The indenting type of lexical structuring does make this very difficult, but not impossible.

b) The interpretive code is proprietary, limiting experimentation with alternative languages and features. I know there's this constant tension of people potentially stealing your intellectual property and the Propeller is very very new still. Parallax does have a lot of competition with "Me Too" lookalikes for the Stamps for example. The interpreter is very good and it is part of every Propeller chip. It would be a shame to have to recreate something like it just to play with alternative language features.

3) A libc-like string package would be lovely. I don't know how often this would be used, but it would be better to have one standard package rather than reinventing it when needed.

Post Edited (Mike Green) : 10/19/2006 4:26:15 PM GMT

Cliff L. Biffle
10-20-2006, 12:46 AM
Mike Green said...

I've programmed pretty much everything from [snip]



Ah, good, then we're on the same page. http://forums.parallax.com/images/smilies/smile.gif I miss PL/1, personally.

For reference, to show what a language bigot I am, I consider Smalltalk, Lisp, and APL to be the "high level" languages in your list, with the possible additional inclusion of Pascal and COBOL (but it would take convincing). The bar for "high level" raises over time, with languages like Fortran no longer really qualifying. (In my opinion.)

(Whether or not being a language bigot is a good thing, I'll leave as an exercise for the reader. It does help me in my line of work, but it also leads to bitchy posts on the Propeller forums...so.)


Mike Green said...

Control structures do make a language high-level, so do data structures. They're all forms of abstraction.



Point taken. SPIN's case statement in particular is refreshing. It would be handier if the language had abstract data types (i.e. made a better go at being object-oriented), which is really one of my primary beefs with the language.

(Since ADTs are a consensual hallucination between you and the compiler, it wouldn't change the underpinnings much.)


Mike Green said...

You're right, you can do really remarkable data and control structuring and abstracting with a good macro processor



Don't get me wrong -- I brought up assembler macros primarily to explain why I don't feel an if/else/then or a for-loop is a high-level construct.

(I do agree with you, though I worry that any macro system we're given will be closer to C's broken preprocessor than to, say, macros in Lisp.)


Mike Green said...

The interpretive code is proprietary, limiting experimentation with alternative languages and features. I know there's this constant tension of people potentially stealing your intellectual property and the Propeller is very very new still.



I hope that's not the reason. (I assumed SPIN code was proprietary so they wouldn't have to support the bytecode format across revisions.)

The SPIN interpreter is just machine code for the Propeller. I'm sure Parallax recognizes that, while the SPIN interpreter is a useful, copyrighted work, their real competitive IP is in the Propeller hardware design. Someone writing a SPIN clone would mean little if they didn't also design an eight-core micro. http://forums.parallax.com/images/smilies/smile.gif

Cliff L. Biffle
10-20-2006, 12:59 AM
Acantostega, I appear to have totally hijacked your thread. Sorry; you can hijack one of mine over on the Gumstix list sometime. http://forums.parallax.com/images/smilies/smile.gif


Bill Henning said...

It would be possible to implement a C compiler for the propeller, however it would require a cog to run some sort of interpreter as the native architecture of cogs is VERY unsuitable for C...



An interpreter, or fantastically creative self-modifying code.

I was trying for a while to implement a FORTH for the Propeller -- which, of course, is even more stack-dependent than C. (You can actually get by without a stack in C, if you limit recursion and statically-allocate the activation records.)

The simplest way to create an in-cog stack is with self-modifying MOVs. Since none of the MOV-class instructions support indirection, you wind up leaning heavily on MOVS and MOVD to rewrite your pop/push code.

Alternatively, of course, you can put TOS at a fixed location in the Cog, and have all pops and pushes move the rest of the stack up or down. This is slower, but for the shallow stacks that these sort of embedded apps usually have, it may not be a huge penalty compared to tracking down and modifying the MOVs.

The main issue with C, for the Propeller, is that normal unadulterated C expects a flat memory space -- your RAM can consist of multiple speed grades, but a single pointer should unambiguously identify a single memory location. In the Propeller, not only can the address $0000 describe two distinct cells, but each one must be accessed with different instructions! (The ATmegas also have separate instructions for different areas of memory, but their space is flat.)

Yes, you can get around this, but it boosts complexity.

I really like the Propeller's instruction set, so I'm generally pretty happy writing in native assembler -- but I will definitely get behind whatever native compilers come out.

Phil Pilgrim (PhiPi)
10-20-2006, 01:05 AM
I don't know if this will be useful, but since Mike broached the subject of a string manipulation library, I'll mention it here.

Awhile back I wrote a heap management object and a string manipulation object. Together, they permit the implementation of dynamically-allocated strings. There didn't seem to be mcuh interest in them at the time, but perhaps things have changed now as more people are using the Propeller. Anyway, here's a link to my original post:

http://forums.parallax.com/showthread.php?p=587930

Enjoy!
Phil

Cliff L. Biffle
10-20-2006, 03:18 AM
Neat, Phil. This may come in handy for me shortly.

acantostega
10-21-2006, 08:48 AM
Cliff L. Biffle said...
Acantostega, I appear to have totally hijacked your thread. Sorry; you can hijack one of mine over on the Gumstix list sometime. http://forums.parallax.com/images/smilies/smile.gif

Heh heh, it's OK, it's an interesting discussion . I've been pretty busy with school, so my gumstix has been abandoned lately :-(

Regarding the whole language issue, as a newbie compared to you guys (I've only programmed lengthy stuff in C, C#, Java, Lisp & Python) I do feel Spin as pretty "high level" compared to assembly. (Of which my only experience is only small programs with the PIC 14 bit micros). Maybe it's because I really haven't got into assembly, so the whole register manipulation to do something simple like adding two numbers feels pretty alien and long programs in assembly tell me nothing.

I do feel the SPIN object system is sort of awkward, and I've found myself writing large programs as a bunch of functions rather than writing new objects. This does make feel kinda guilty, though.
And I would support a macro system, even if it's more like C's macros than Lisp's. (I admit I never got around to learning how to write Lisp macros).

One thing I really like about the Spin / Prop combination is that they just work together. With the various micro / C compiler implementations available for other micros like AVR and PIC you have to worry about what subset of C is implemented, what's the convention for register names, how do you relate fragments of code to interrupts (in particular since ANSI says nothing about this, I find all the different conventions a real headache) and what really happens under the hood. In the end it's necessary to know assembly language for that micro anyway, to really understand what's going on if you run into problems. With Spin + Propstick I've found most of my code working as expected with relatively little debugging and no assembly knowledge required. (I would like to learn some, however, when I get some free time ...)
I'm sure other relative newcomers to microcontrollers, who have used (really?) high level languages will appreciate finding the familiar looping / if-then-else / etc constructs without having to learn assembly first.

And a string lib would be nice! I was kind of expecting to see strcat, strcpy et al in the Propeller manual.


Phil Pilgrim (PhiPi) said...

Awhile back I wrote a heap management object and a string manipulation object. Together, they permit the implementation of dynamically-allocated strings. There didn't seem to be mcuh interest in them at the time, but perhaps things have changed now as more people are using the Propeller.


Neat! I missed it when I searched for "string array" and such before writing the aforementioned code. Maybe it should be in the object exchange!

Post Edited (acantostega) : 10/21/2006 12:53:05 AM GMT

Phil Pilgrim (PhiPi)
10-21-2006, 10:36 AM
acantostega,

I would gladly contribute these to the object exchange, but for the still extant condition that contributions have no copyright. I've chosen instead to copyright and license them under the GPL. If/when Parallax's terms change, they'll be added to the library posthaste.

-Phil