Thursday, November 11, 2010

MP3 ID3v1 tag reading in Perl and in Haskell

I am building an MP3 jukebox for my home...

I know that I am supposed to use ID3v2, but my MP3 collection (CD ripped, Amazon and Emusic) still sports ID3v1 tags, so I thought it would be a safe  bet to just parse it.

I quickly wrote an ID3v1 tag parser in Perl (yes, I know CPAN has several solutions for this but I wanted to write my own just for the fun). Here is what it looks like:


use strict;
use warnings;
use Fcntl qw(:seek);


my @genre = (
'Blues','Classic Rock','Country','Dance',
'Disco','Funk','Grunge','Hip-Hop',
'Jazz','Metal','New Ag(e','Oldies',
'Other','Pop','R&B','Rap',
'Reggae','Rock','Techno','Industrial',
'Alternative','Ska','Death Metal','Pranks',
'Soundtrack','Euro-Techno','Ambient','Trip-Hop',
'Vocal','Jazz+Funk','Fusion','Trance',
'Classical','Instrumental','Acid','House',
'Game','Sound Clip','Gospel','Noise',
'AlternRock','Bass','Soul','Punk',
'Space','Meditative','Instrumental Pop','Instrumental Rock',
'Ethnic','Gothic','Darkwave','Techno-Industrial',
'Electronic','Pop-Folk','Eurodance','Dream',
'Southern Rock','Cult','Gangsta','Top 40',
'Christian Rap','Pop/Funk','Jungle','Native American',
'Cabaret','New Wave','Psychadelic','Rave',
'Showtunes','Trailer','Lo-Fi','Tribal',
'Acid Punk','Acid Jazz','Polka','Retro',
'Musical','Rock &','Hard Rock','Folk',
'Folk-Rock','National Folk','Swing','Fast Fusion',
'Bebob','Latin','Revival','Celtic',
'Bluegrass','Avantgarde','Gothic Rock','Progressive Rock',
'Psychedelic Rock','Symphonic Rock','Slow Rock','Big Band',
'Chorus','Easy Listening','Acoustic','Humour',
'Speech','Chanson','Opera','Chamber Music',
'Symphony','Booty Brass','Primus','Porn Groove',
'Satire','Slow Jam','Club','Tango',
'Samba','Folklore','Ballad','Power Ballad',
'Rhytmic Soul','Freestyle','Duet','Punk Rock',
'Drum Solo','A Capela','Euro-House','Dance Hall' );


my $id3v1;
my $id3v1_tmpl = "A3 A30 A30 A30 A4 A28 C C C";


while (my $filename = ) {
    chomp $filename;
    open my $fh, '<', $filename or next;
    binmode $fh;
    seek $fh, -128, SEEK_END and read $fh, $id3v1, 128;
    close $fh;
    my (undef,$title,$artist,$album,$year,$comment,undef,$trk,$genr) =
unpack($id3v1_tmpl,$id3v1);
    print "$filename|$title|$artist|$album|$year|$trk|".$genre[$genr]."\n";
}

Basically it takes a stream of MP3 filenames over stdin, opens them and dumps out a pipe delimited summary of what it found. Here is how it is run:

$ find /home/todd/music -name "*.mp3" | perl mp3info.pl >mp3_data.txt

Here is a line from the output (mp3_data.txt):
/home/todd/music/Charles Mingus/Ah Um/Charles Mingus_10_Pedal Point Blues.mp3|Pedal Point Blues|Charles Mingus|Ah Um|1959|10|Jazz

I am considering using Haskell for my jukebox, so I was curious what this would look like in Haskell.  Here is my newbie Haskell implementation:

import Text.Printf
import Data.Array
import Char
import System.Environment
import System.IO

-- Create a array of genres
genres = listArray (0, l-1) genres_l 
         where 
           genres_l = [
             "Blues", "Classic Rock","Country","Dance",
             "Disco","Funk","Grunge","Hip-Hop",
             "Jazz","Metal","New Age","Oldies",
             "Other","Pop","R&B","Rap",
             "Reggae","Rock","Techno","Industrial",
             "Alternative","Ska","Death Metal","Pranks",
             "Soundtrack","Euro-Techno","Ambient","Trip-Hop",
             "Vocal","Jazz+Funk","Fusion","Trance",
             "Classical","Instrumental","Acid","House",
             "Game","Sound Clip","Gospel","Noise",
             "AlternRock","Bass","Soul","Punk",
             "Space","Meditative","Instrumental Pop","Instrumental Rock",
             "Ethnic","Gothic","Darkwave","Techno-Industrial",
             "Electronic","Pop-Folk","Eurodance","Dream",
             "Southern Rock","Cult","Gangsta","Top 40",
             "Christian Rap","Pop/Funk","Jungle","Native American",
             "Cabaret","New Wave","Psychadelic","Rave",
             "Showtunes","Trailer","Lo-Fi","Tribal",
             "Acid Punk","Acid Jazz","Polka","Retro",
             "Musical","Rock &","Hard Rock","Folk",
             "Folk-Rock","National Folk","Swing","Fast Fusion",
             "Bebob","Latin","Revival","Celtic",
             "Bluegrass","Avantgarde","Gothic Rock","Progressive Rock",
             "Psychedelic Rock","Symphonic Rock","Slow Rock","Big Band",
             "Chorus","Easy Listening","Acoustic","Humour",
             "Speech","Chanson","Opera","Chamber Music",
             "Symphony","Booty Brass","Primus","Porn Groove",
             "Satire","Slow Jam","Club","Tango",
             "Samba","Folklore","Ballad","Power Ballad",
             "Rhytmic Soul","Freestyle","Duet","Punk Rock",
             "Drum Solo","A Capela","Euro-House","Dance Hall" ]
           l = length genres_l

main = do

  hSetEncoding stdin latin1
  hSetEncoding stdout latin1

  fname <- getContents          -- lazily read list of files from stdin
  mapM print_id3v1 (lines fname)
    
print_id3v1 fname = do
  print fname
  inh <- openBinaryFile fname ReadMode
  hSeek inh SeekFromEnd (-128)
  dat <- hGetContents inh
  printf "%s|%s|%s|%s|%s|%d|%s\n"
       fname
       (extract 3 30 dat)      -- Title
       (extract 33 30 dat)     -- Artist
       (extract 63 30 dat)     -- Album
       (extract 93 4 dat)                              -- Year
       (Char.ord (head (extract 126 1 dat)))           -- Track
       (genres !(Char.ord (head (extract 127 1 dat)))) -- Genre
  hClose inh

-- extract and trim a range of elements from list
extract idx ln s = 
    trim0 (take ln (drop idx s))

-- Trim nulls from list
trim0 s = filter (/= '\0') s

You run it similarly. Frustratingly, it isn't very happy with filenames with non-ASCII characters :-(

$ find /home/todd/music/ -name "*.mp3" -print | ./mp3info >mp3_files.txt 
mp3info: /home/todd/Music/music/Ch�ying Drolma & Steve Tibbetts/Selwa/Ch�ying Drolma & Steve Tibbetts_05_Gayatri.mp3: openBinaryFile: does not exist (No such file or directory)

I am not a Haskell expert, but I didn't expect it to choke there...

EDIT: Fixed the filename problem by adding:

  hSetEncoding stdin latin1
  hSetEncoding stdout latin1

Tuesday, October 19, 2010

Future runtime environment for Robots

Embedded systems are getting smaller and more sophisticated. While there are currently bare ARMs and 8/16-bit micros controlling our mainstream robots, this won't do for the more sophisticated (domestic) robots of the near future.

When we consider sophisticated robots (whether ruled by a subsumption architecture or other invariably concurrent system), we won't think of Python, Java, Ruby or Perl. We will be thinking of something more Erlang-like or perhaps Unix-y.

Can you imagine jacking into your robot's debug port, typing "ps" and seeing a collection of inter-communicating processes running on a Linux kernel?  Or will it be something like Erlang/OTP?  (Erlang is the dark horse here... Unix may never go away as a platform.)

So, how about it? Erlang on a gumstix?

Friday, September 10, 2010

New AFT release!

AFT development has dormant for about 1 year, so I decided to reboot it with a minor (experimental) release (5.098) that supports Indexing. This is mostly useful for LaTeX output. I'm not sure how useful the HTML output will be.

I've also started to clean up the Perl source for AFT.  I am currently reading the new edition of Effective Perl Programming and hope to apply more idiomatic Modern Perl conventions to the 14+ year old AFT sources.

As always, AFT is available through "sudo apt-get install aft" under Ubuntu (and Debian?). But to get this new release, go to the AFT website. (For a quick look at Indexing in action, look at the aft reference manual and scroll to the last page).

I need to start archiving my art...

This is an airbrush I made 23 years ago:
Miles Davis


I need to scan in all my old artwork and figure out the best place to post them.

Wednesday, September 08, 2010

I miss Perl...

I've been going through my old books and came upon a stash of Perl tomes.  I had a love/hate relationship with Perl. I wrote AFT in Perl, but have not used it as my language of choice in (almost) a decade.

Stumbling across these books got me wondering: Where have all the Perl hackers gone?

Well, I can't say where they have all gone (Ruby? Python? Retirement?), but I miss the funky vibe that Perl had in it's day.  Perl was messy, but the language attracted the most interesting people.  I've always seen it to be the language of poets (as opposed to engineers).  Perl people loved wordplay. Perl people weren't just interested in producing interesting apps, but also making the app source code look interesting.

Well, Perl isn't gone. Apparently, strides have been made in Perl 6 and Rakudo is available for playing around with a lot of Perl 6 features.

But, will the hackers come?

I am reminded of a quote from Ratatouille (Colette introducing the kitchen staff to Linguine):
 "... So you see: We are Artists. Pirates. More than cooks are we."

Sunday, August 29, 2010

Scratch, Squeak and so Forth: Robot programming enviroments

A thought experiment...

If I was going to teach kids how to control a Roomba by way of programming, where would I start?
Outside of Squeak and Scratch, I think the most common answer involves also teaching them how to use a source code editor.

This is unacceptable.

Squeak (as derived from Smalltalk-80) and Scratch (as derived from various Logos) integrates the programming environment with the language. This isn't about just being an "IDE".

Squeak let's you hack in a workspace without concern for files. It is persistent and natural. You write a little, see how it works out and continue.  At some point you may save your workspace, but you aren't really thinking about files at this point.

Scratch has a similar (although not as radical) approach. My youngest kids  (age 7 & 7) would script for a few hours and then pick some random series of characters as a "name" to save their project into (for later recovery). Eventually, they started using more descriptive words for naming their projects. But at no time did they think about files and file systems.

I think files and editors are distractions (and not necessary ones -- unless you want to get a mainstream programming job).

Forth had this idea decades ago (and so did Smalltalk).  Forth had blocks (1K blocks to be specific) that held text and data. The early bare-metal Forths used blocks as the single abstraction from persistent storage devices (disks).  Eventually, folks "enhanced" line oriented block editing with a visual screen (with single character cursor movement!).

Forthers in the early 1980s (my self included) were happy.

Now, in 2010, I face the prospect of teaching my oldest kid (age 12 -- expert Scratcher, beginning Python programmer) how to control a Roomba via programming that require the selection and mastery of files (and file systems) -- or at least some kind of file based IDE.

Of the languages I have been looking at, Forth, Python and Lua are the front runners.

I think Forth is a more natural fit. I have just downloaded VIBE and I am being transported back 30 years.  I use to write (and extend) Forth editors like this. I am remembering how natural it felt to edit in blocks. (ColorForth continues this tradition, so Chuck Moore arguably never found much of an improvement in using file oriented environments ;-)

Forth has always made me feel "closer to the machine". Plus, with a built-in editor, I am no longer doing the context switch being external editor and Forth. VIBE (or any other Forth Screen Editor) keeps me in Forth.

I will be playing with VIBE under gforth (and perhaps extending it).  I am curious to see if this feeling is simply nostalgia or if my 23+ years of Emacs (w/ language editing modes) has been a bad move.

Tuesday, August 24, 2010

Greenspun's Tenth Rule adapted to Unix

Greenspun's Tenth Rule: Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
can be adapted to Unix:
Any sufficiently complicated Perl, Python, Ruby, Lua, etc  script contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Unix.


And I don't mean the all of the "system" calls. I mean: concurrency, fault tolerance, data persistence, configuration and scalability. 


It may be ugly, but combine ksh93/bash, awk, bc, etc (whatever you find on a standard Unix/Linux distro) and you'll find an analog to the features offered by the above mentioned languages. This does not include "abstractions" such as fancy data structures and other syntactical sugar.   And, of course, fork/exec isn't going to beat a function call. 


However, (and this will be the subject of the next post), Unix under control of advanced shell (such as ksh93 or bash) can have the following capabilities (at least!):
  1. Coroutines (Co-processes in ksh93 or recent Bash)
  2. Communicating Sequential Processes (CSP) via named pipes and co-processes
  3. Dataflow processing (pipes)
  4. Arbitrary precision math (bc or other calculator)
  5. Reuse (command line apps)
  6. File (database) support (ls, awk, find, grep, sqlite command line, etc)
  7. List processing (command line args + ksh93/bash)
  8. Functions/apps as first class objects
And more...

Saturday, August 21, 2010

iRobot Create and Unix Programming

In my previous post I talked about using Unix as an embedded programming "language" (as opposed to a hosting environment for embedded apps).

I started to think about where to begin.  Well, let's consider the iRobot Create platform (Roomba too!).
Between your controller and the iRobot is a serial port and a binary command protocol.
If I wrote a small C app to talk over the serial port and convert to/from binary and text, I can utilize the Unix pipeline for some further down app that reads the robot's binary response as newline delimited text data.
For example:

echo "get sensors" | irobot-oi /dev/ttyS0 | some-later-app


The "irobot-oi" open "/dev/ttyS0", takes text commands as input ("get sensors"), converts it to an iRobot OI binary request, sends it, reads the binary response and converts it to text for "some-later-app".  This app could be written in C, awk, perl, etc. 


This approach is so obvious that I would be shocked to learn that no one has tried it.  I know there are libraries available the iRobot Open Interface (OI) in python and other languages, but is there a Unix command line available?


From a traditionalist Unix position, "irobot-oi" is actually doing too much.  You'd have to encode mappings between each binary command/response byte/bit and text.  A more minimal approach would be to write an even simpler binary/text converter that simply understands the protocol encapsulation and accepts/emits a comma delimited representation of the binary data. (Since the OI response protocol is directly dependent on request -- there are varying length responses with no terminator -- we have to develop some smarts into the converter.)


So, instead we would have something like this:


echo "142,2,9,13" | irobot-oi-cvt /dev/ttyS0 | some-later-app


The above command requests the state of the left cliff sensor (9) and the virtual wall detector (13) and sends the result (in comma delimited text) to "some-later-app" (which may do the actual english text mapping or simply react to the numbers).

Unix as a Programming Language - Rethink Embedded Scripting (and CSP)

As I look at eLua (on an mbed for one of my robot projects), my mind wanders... have I stumbled into another monolithic system approach?

eLua embedded systems are Lua and (maybe) some C.  I like Lua, but am I just trading one language ( Forth, C, etc) for another?

This line of thinking keeps bringing me back to Unix. Under (traditional) Unix, I have a multi-process environment connected by pipes.  I choose the appropriate language (or existing app) for the task at hand and glue it together with a shell.

Now, this would (most likely) be overkill for a small embedded device, especially in regards to power consumption. But, assume for the moment, that I had all of the Unix resources at hand and didn't concern myself with power consumption.  What would my robot controller design look like?

I design and build GPS trackers during the day. I use C and (sometimes) Forth.  I've thought about eLua, but I'd still have to write a NMEA sentence parser and fencing algorithm in a language not necessarily perfect for parsing.  How would I go about doing this if I had awk at my disposal? Or grep/sed? Or... the whole unix environment tied together with pipes under a shell.  Would something like BusyBox be a good foundation?

What is the smallest MCU (or embedded SBC) that I could run something like uCLinux and BusyBox on?
Could I do development under a fairly modest laptop Linux and port down to uCLinux and BusyBox?

Right now I am looking (again) at CSP (perhaps built upon Lua co-routines) as a mechanism for architecting embedded systems that integrate multiple (sensor) inputs.  You can also build CSP upon Unix processes (and pipes). This is the way I've done it for 25+ years.  Do I really need to cast my architecture into another monolith?
This is just me bring up Unix as a Programming Language again (but this time under the constraints of embedded computing)

Wednesday, August 11, 2010

Resurrecting BLOGnBOX

I've been thinking about resurrecting my gawk based blogging system BLOGnBOX.  I am getting tired of Blogger.

While BLOGnBOX doesn't have as many features, it lets me focus on what I want from a blog.  Although this has changed over time, I think what I currently want is:

  1. A way to publish my thoughts and ideas.
  2. An archive of my thoughts and ideas.
  3. A primary means of writing.
I am less concerned with the web aspects of a blogging system.  I'd like to have a clean, simple (yet elegantly presented) blog that I can tinker with as needed.

What led me down this path of thought is the desire to extract blog entries (or the whole blog) as a PDF document. By PDF, I really mean LaTeX or TeX quality (not just a dump).  AFT does this for me, but it might be overkill for a blogging system. Perhaps the next iteration of BLOGnBOX should  leverage LaTeX directly?

And, of course, the next iteration should be composed as a Literate Program!  (I'm leaning towards Noweb.)

Wednesday, August 04, 2010

Humans were not meant to...

Humans were not meant to sit in cubicles.
Humans were not meant to spend 8 hours a day working on reports and clicking aimlessly on the web to relieve the tedium.
Humans were not meant to be imprisoned by a workforce that wants you to do repetitive tasks mindlessly.

Humans are meant to be adventurous and creative, with bursts of brilliance (whether through exuberant play or hard knuckled persistence).
Children understand this. As adults we unlearn this. We are taught to work hard, conform for the good of society, buy a house, put away money into a 401K and make a stable environment for raising our kids. We are taught to be "wage slaves".

Sadly, most humans will never break free. But that makes it even more important that you become that rare exception (at least for a while). You have a duty to be brilliant, exuberant and adventurous. Laugh hard, fight injustice (aka stupidity), be creative and kind.

Be passionate. Don't be afraid to piss off people. Sometimes people need to be shook up.

Draw, paint, dance, program -- set an example for your kids. Let them know that it isn't their duty to conform, accept the status quo or "work for the weekend". The best thing you can do for your kids is to show them what it means to be free -- to be truly human. Brilliant, volatile and utterly unique. Take chances. (You don't have to quit your job to do this.) Just do something to express your joy, your uniqueness, your value as a human.

F*ck your boss. No, not that person you report to at work. Your real boss: the mental shackles that keeps you "in line". Break those shackles.

Not everyone can do this. But it is your duty to try.

Sometimes, when your boss isn't looking... let go.

Myforth, 8051 and minimalism

Programming in Myforth has given me a greater appreciation for minimalism.  (I suppose programming in ColorForth would be even better, but I don't have access to the proper hardware...)

Using minimalistic (simple) tools forces you to approach a problem differently.  I felt some of this back in the 80's when all I had was a little Commodore 64 and some big ideas, but coming back to minimalism from two decades of big iron is refreshing.

I now look at a problem and think "what is the simplest way to solve this?".  This takes on a deeper meaning when you consider that the tools force you to find simpler ways. When all you have is 768 bytes of RAM and 8KB of flash, you have to think in simple terms.

Take, for instance, the problem of geofencing.  I do GPS trackers (on 16-bit micros) for my day job.  I have an MSP430, 16KB of RAM and 256KB of program space (flash).  The trackers I build have a concept called geofencing. Here you define polygons or circles that affect how the GPS points are handled. Sometimes you want to log at a different rate based on the fence you are in; sometimes you want to "beacon" (transmit) at a different rate.

Programming a fence algorithm can be tricky (and computationally intensive). In addition, GPS coordinates are represented typically in (at least) scaled 32 bit values (w/ 5 decimal digit precision).

Thirty-two bit math is taxing for an MCU that only supports 8-bit math. What is a lowly 8-bit to do?
Well, if your "problem domain" only needs to deal with fences defined around just a few miles, you can truncate a lot of the math to 16 (or fewer) bits while retaining precision. Once you know that you are "in the ball park", you only need to look at the lower bits.  You don't need to consider the whole 32 bits.

This is a good example of how refining the problem domain helps generate a simpler (smaller) solution. Even if I used 16 bit or 32 bit MCUs, this can save me some processing time. (My field is "low power consumption" solutions, so saving processing time equals saving power).

Tuesday, July 20, 2010

myforth, 8051 and robotics

Just an update. I am quite taken by Charley Shattuck's myforth (click link and scroll to the bottom of the page). Porting it to an obscure 8051 part  (for  24 bit sigma-delta ADC) greatly increased my knowledge of 8051 assembly. Myforth is more of a Forth-based macro-assembler than a Forth dialect. It is both minimalistic and rich.

I got great pleasure out of implementing a moving average over 24 bit ADC samples using just 8-bit operators for the math.  It reminds me that I take a lot for granted when I toss about 32 bit integers using C on an MCU.

(I've previously used SwiftX Forthfor 8051 programming, but the part in question had only 768 bytes of RAM -- not quite enough.)

Sunday, June 06, 2010

Ideas are dangerous things...

A movement starts with an idea. A revolution starts with an idea. An invention starts with an idea.
Ideas are volatile things.
...There are thoughts enough
To blow men’s minds and tear great worlds apart 
 My thoughts were in embedded systems for the past 4 years.  Four years ago I left behind large systems development.  I went minimal -- 8-bits in fact.  Improbable as it seems, I managed to get back into Forth development. I've spent the last 8 months writing Forth code on a 16-bit MCU (MSP430).  The project is ending and the product is about to be delivered.

My thoughts now turn to vacation.  But, once on vacation, my thoughts will wander back to computers. So, what's next?

I'd like to finish my embedded system CFT projects, but of course, my mind wanders.

My mind is wandering here  and here.

A while back, I read (and mentioned)  Reaching Escape Velocity (and Gonzo Engineering).  Steven Roberts suggests that you find your all consuming project and pursue it.

The problem is, I don't have such a project in mind.
Maybe my true passion isn't making things.

I love ideas.  I think I am a programmer (rather than inventor) because I often don't need to build something. Sometimes it is just enough to think it (and most importantly share it).  Ideas are like.

So, I am not sure what I am going to do next.
So whatever your hands find to do
You must do with all your heart
There are thoughts enough
To blow men’s minds and tear great worlds apart

There’s a healing touch to find you
On that broad highway somewhere
To lift you high
As music flying
Through the angel’s hair.

Don’t ask what you are not doing
Because your voice cannot command
In time we will move mountains
And it will come through your hands  -- John Hiatt, "Through Your Hands"

Friday, June 04, 2010

Posterous... BLoGnBOX

I stumbled upon Posterous and it sounds a bit like my BLoGnBOX.
Posterous came out in 2008; BLoGnBOX went live in 2006.

BLoGnBOX was never hosted but the concept is the same: Email to Blog posting.

Posterous recently announced Markdown support.
Markdown is very similiar to my own AFT.

Wednesday, June 02, 2010

WikiReader Data Logger

A quick hack. Here is a data logger I wrote for the WikiReader that I use at work. It uses my previously discussed WikiReader Serial port hack:


160 constant max-line-chars
variable byte
create line-buf max-line-chars chars allot
variable lbcnt
variable fd
variable linecnt


\ Base logfile
\
: logfile s" log.000" ;


\ Create a new logfile with new 3 digit numeric extension 
\ (e.g. log.001)
\
: gen-logfile ( nnn -- caddr u) 0 <# # # # #> logfile + 3 - swap drop 3 cmove logfile ;


\ Does this log file exist or is it available (free)?
\
: logfile-free? ( caddr u -- f) r/o open-file ?dup if drop 1 exit then close-file drop 0  ;


\ Iterate through to a free logfile. 
\ We support up to 1000 log files before we fail.
\ (Need a failure handler!)
\
: next-logfile ( -- )  999 0 do i gen-logfile logfile-free? if unloop exit then loop ;


: wiki-logger ( -- )
    0 lbcnt !
    lcd-cls
    next-logfile
    logfile w/o create-file ?dup if 
        cr lcd-." Can't create log: " lcd-.  drop exit
    then
    fd !
    lcd-cr
    logfile lcd-type lcd-cr
    lcd-." Ready. Press any button to exit." lcd-cr lcd-cr
    begin
        \ sleep only between lines
        key? 0= lbcnt @ 0= and if wait-for-event then 
        key? if
            key dup line-buf lbcnt @ + c!  1 lbcnt +! ( -- c)
            10 = if 
                line-buf lbcnt @  2dup fd @  write-line drop
                lcd-type lcd-cr
                0 lbcnt !
            then
        then
        button? if
            \ A button was pressed so clean up 
            \ and exit.
            \
            button-flush
            fd @ close-file
            exit
        then
        ctp-flush   \ not interested
    again ;
wiki-logger

Thursday, May 27, 2010

WikiReader Serial Port Hack Pictures

Per a recent request...

Here are some pictures of my small hardware hack.

First, I just added 3 header pin sockets to the already exposed debug port:



But that proved too cumbersome to maintain a good tethered connection to my laptop (plus the batteries would have to be exposed).

So, with the aid of a master machinist (Sandor -- a co-worker), I put a stereo "micro" jack on the top side of the device:




Here is the finished result:




You can see where I (badly) pried open the case ;-)

And here is where I am today:



Now, onto software...

Wednesday, May 19, 2010

So many CFT projects...

  1. Hands-off! - Small, mountable, personal alarm system. Attach to a bike, briefcase, computer bag, etc. Arm/Disarm with a key fob. Piercing alarm when someone "moves" your possession. Key fob also has a smaller alarm/buzzer to notify you (up to 10 meters away).
  2. mooTracker - Ultra low power GPS tracker for livestock, pets, etc. Can be used with GSM/SMS module, Iridium modem, etc. Uses an accelerometer to detect motion before engaging GPS trackers. Standby current should be <>
  3. UV Index Clip - Small (discrete) UV Index sensor (1" square max). Uses a button cell battery, SiLabs C8051F930, and ANT for communication to iPod/iPhone/Pocket-device to alert you when you've had enough rays. Can be clipped to clothing or hat.
  4. Crop/Garden moisture monitor. Seed your garden (co-op, winery, etc) with low cost, very low power wireless sensors. They contact a hub (with GSM/SMS capability) to send you status/alerts as text messages. The hub should also support data logging/consolidation for summation or later retrieval.
  5. Portable Power Consumption Data Logger. The key word is "portable" here. This data logger/monitor is designed to be used "in the field" with portable devices (sensors, auto accessories, robots, etc). Mainly for battery powered devices. Should be able to measure power consumption between 0-12volt and between 1uA and 3A.
  6. WikiReader Portable Terminal - Use the WikiReader as a local/personal display and a controller of UART enabled devices. Maybe use Bluetooth to use it to query/control sensors.

So many CFT projects, so little time. Is there a way to tie them together?
Is there a common theme?

If I only built the things that "I" find useful, which would they be?

I could use #4 in my yard and I have friends that would find it useful.

My wife could use #3....

I could see where #1 would be useful, but it generally sounds pretty boring
(from an implementation point of view).

None of these projects are terribly unique. Maybe my approach is
"low cost / low power". I find it challenging to do a lot with a little.


Tuesday, May 18, 2010

Gonzo Engineering

This manifesto strikes a chord. I am not as brave (or insane?) as Steven Roberts, but I do find resonance with his writings. I remember briefly encountering Roberts at InterOp Spring 1992 where he had a booth showing off his BEHEMOTH bike.

I just finished his book.

I need to do more about my crazy dreams.

Sunday, May 16, 2010

WikiReader, Forth and Hacking

It's old news, but I find the WikiReader very cool. It is an "offline" pocket size wikipedia reader (searches a mini-SD card of a wikipedia dump). It came out last fall (2009) and it has already been subject to a teardown and random hacks. What finally got me interested is knowing that it runs a cross compiled (almost ANSI) Forth.

I've been doing a lot of low level and high level Forth recently and wanted a "lighweight" hackable device for some mall programming (my 11 yr old son plays Warhammer 4K at a local mall and can be engaged for up to 3 hrs -- ugh, 3 hrs of waiting in a mall). The problem with most of my devices is that they have lots of wires, bare boards and LEDs. I don't need the attention (blinking LED.. somebody call the police!).

So, I got me a WikiReader and I've already opened it up to hack in a connector for a serial port (pictures later).

The toolchain and source code is free (developed under Linux w/ open source tools), so I installed ubuntu (once again: goodbye windows) and was quickly cross compiling new Forth engines!

More later, but some quick mini-stats:

The device works off of 3 AAA batteries and draws 11-13mA (avg) while "idle" (waiting for a touch screen or serial event) and 80-90mA (avg) while searching, handling I/O and doing wikipedia stuff.

Not bad.

/todd

Wednesday, April 28, 2010

myforth, 8051 and iRobot Create

At the end of my previous post I entertained the idea of using a SiLabs C8051 for controlling the Create. Of course, I can't run Lua on that MCU, so the obvious alternative is Forth.

But which Forth? I have a copy of SwiftX for the 8051, but I decided to look at an interesting environment called MyForth that i found here. This is the, quite detailed, manual.
Its non-standard (I don't really care), influenced by colorforth (yeah!) and completely tied to the 8051.

In this day and age, who would use a language completely tied to a platform? Well, apparently, the point of MyForth was to produce a true 8-bit Forth that would match the 8-bit nature of the 8051. (Most 8051 Forths are 16-bit, while the registers and most efficient instructions on the 8051 are 8-bit based.)

After a while, I started to think: so what? As modern programmers we've embraced portability over efficiency. No, its more that that: We strive to avoid software that locks us to a particular piece of hardware.

Is this a real problem (all of the time)? If I want to augment Create (or other consumer robots) with an MCU and some code, should I strive to make it portable? Or do I just concern myself with the problem at hand: Making the robot do interesting things.

Another plus for MyForth is its development environment: It uses gforth as a cross-compiler. I have full access to the cross (meta) compilation. I can craft MyForth to become "my forth". So, who says I can't re-target it for another MCU? Or, at the very minimum, use it as a model for cross-compilation.

Interesting reading and hacking for the weekend.

Saturday, April 24, 2010

eLua and mbed and iRobot Create

Mbed is 5V tolerant. This means I should be able to connect a board directly to the iRobot Create that has been sitting gathering dust for a couple of years. I couldn't get motivated to write in C for it; I didn't have a viable Forth option at the time (although now I do).

Since the Create sucks big power as it is, the addition of an mbed shouldn't be a problem.

While I am quite deep into Forth these days, development may be better suited for eLua (since it is free). Maybe? Something to think about.

Of course, the SiLabs C8051F340x is also fully 5V tolerant (including power supply) with fewer external circuit requirements and much lower power consumption. I can't run eLua on it, but I've got my trusty SwiftX 8051 Forth....

So many options, so little time.

eLua and mbed

Sometimes I get lost in the whole "low power" thing. I've been focused so much on power saving processors that I forget what fun it is to just program. Forth is great for getting the job done, but sometimes I just want to play around with algorithms and want something a little more... infix.

So, eLua fits the bill, especially on mbed. (Lua on Cortex-M3! Yay!)


Monday, April 12, 2010

mbed (Cortex-M3) and MPE Forth

Mbed is a neat little NXP LPC1768 based Cortex M3 development environment. It has a web based IDE, but I'm not interested in that. You can flash it by dragging a *.bin file to its embedded flash drive. Once you drag, you reset (via pushbutton) and a second or two later the device is reprogrammed.

This made a nice target for MPE's Forth 7 Cortex-M3 cross compiler. (I purchased the inexpensive "Stamp" version for ~ $115).

There was no included Mbed support, so I attempted a port. The port was easy -- I got the LEDs to blink. Now to figure out what to do with the thing...

While the LPC1768 has some interesting low power modes, the extra programming/flash-drive circuitry of the mbed doesn't allow full exploitation. However, until the Gecko Starter Kit becomes available, the mbed will do (for development purposes).

Saturday, March 13, 2010

SiLabs C8051 and SwiftX Forth

It's been a while since I've posted... I am very busy these days. :-(

I am currently playing with SiLabs C8051F344 with a purchased copy of Forth Inc's SwiftX (under Windows -- my Linux development effort never fully cooked).

I am impressed with the speed of this "lowly" 8051 derived 8-bitter. It isn't meant to do big things, but for small things it fairly rocks.

I've previously played with the C8051F93x very lower power MCU, but given my current interests (GPS tracking), the difference in power consumption between that very low power part and the more power hungry F344 is minimal. The GPS consumes so much current when running that the MCU is just "noise" in any power chart plots.

When asleep, the difference between consuming 1uA (sleep mode) on the F93xx vs 25-50uA on the F344 (clocking way down to around 40Khz) is not worth considering (we are talking years of battery life for either).

More on my current project later... but for now I am just enjoying crafting Forth on a 8-bit MCU :-)

Tuesday, January 05, 2010

SwiftX Forth and 8051 and Linux

Maybe 3 other people in the world would probably be interested in hearing that I have gotten the evaluation copy of SwiftX Forth running under Linux (Wine) talking to Silab's USB Toolstick's C8015F931 daughter card.

I had to steal the daughter card UART and re-route it to a separate USB->UART bridge for SwitfX's XTL (programming still works through the Toolstick), but it all works (so far) under both Windows and Linux (Ubuntu!).

I am playing around with 8051s because I am feeling retro and a bit weary of the TI MSP430 family. The C8015F931 has some impressive low power numbers and some neat features to make even a lowly 8051 appealing.

I have to remember to do a post on my newest interest: Augmenting sensors with tiny low power MCUs to make them smarter.

Friday, December 04, 2009

uForth 0.99 -- almost there....

A bit fatter, but more capable... Plus there is some initial refactoring of the code. Download the latest here .

Monday, November 02, 2009

case statements in uForth

case .. of .. endof .. endcase was surprisingly easy to implement:


\ Variable used to keep track of how many 'of' clauses we have.
\
variable _endof

: case ( n -- )
0 _endof !
[compile] >r
; immediate

: of ( n -- )
[compile] r@
[compile] =
postpone if
; immediate

: endof ( -- )
_endof incr
postpone else
; immediate

: endcase ( -- )
_endof @ 0 do postpone then loop
[compile] r>
[compile] drop
; immediate



And, an example:


: test ( number -- )
case
1 of ." one" endof
2 of ." two" endof
3 of ." three" endof
." none"
endcase
;

Friday, October 30, 2009

Hexbug + MSP430 = Robotrophic Parasitism


It's been almost 2 years since I wrote about my interest in Biotrophic Parasitism in robotics...

In Biotrophic Parasitism, the parasite and host co-exist with (potentially) mutual benefits.
In what I am calling Robotrophic Parasitism, the parasite (in this case a MSP430 based $3 EZ430-T2102), and the host (an original $10 Hexbug) live happily together.

In this case, the parasite was minimally invasive: the EZ430 lives between the battery switch and the Hexbug circuit, controlling the power. It also has a bi-directional line tapped to the antenna sensors so it can detect a "bump" or steer (the original hexbug only turns clockwise).

The parasite seeks light and steers the bug in that direction. When you first apply power, the parasite turns the hexbug clockwise (up to 6 times) looking for any light bearing direction. It then drives the hexbug in that direction. If the light wanes, it will then do another set of clockwise searches looking for a stronger light source.

I've got some fine tuning to do...

The parts list:
  1. 1 EZ430-T2102 board.
  2. 1 Hexbug.
  3. 1 photoresistor and 1 voltage dividing 1/8 watt resistor (from my parts bin).
  4. 1 TS5A3127DBVRG4 analog switch (free sample from TI).
Total Cost: ~ $15

This is the first of (hopefully) many Hexbug Robotrophic Parasites!

Wednesday, October 28, 2009

Unschooling days...


Wednesday early afternoon...



Claire in her tree.
Annie drawing worms (science).
Nate hacking Python.













Tuesday, October 27, 2009

uForth 0.96 -- getting closer...

I've simplified uforth.c in this release. Some words coded in C were moved to core.f and init.f.
This made the C code smaller, so you can now compile uForth with the free IAR MSP430 Kickstart Edition!

Still no DOES> (not sure how to do this without dictionary rewriting which is a no-no in my MSP430 flash approach).

It is nicely shaping up though. I am really enjoying rewriting parts of uforth.c in uForth itself (see core.f and init.f in the distribution).

Downloads are here.

Friday, October 16, 2009

uforth 0.921 -- more pre-release goodness

Visit uforth for the latest "on your own for now" pre-release. I've included a link to a prebuilt binary for the MSP430 ez430-rf2500 board.

It's more robust and comprehensive. Plus it supports direct word compiles to the MSP430 flash.
It weighs just over 8KB flash + 900 bytes RAM. It support an 8KB (4096 cell) dictionary, so there is plenty of room to play.

The PC/Unix version still works well too. I use it for new dictionary development and create a TI file of the compiled dictionary for the MSP430.

Nothing automated yet and very little documentation. But, hey you can define words, loop and do some "meta" stuff.

Wednesday, October 07, 2009

uForth 0.7 pre-release

Last night I finally made some progress with compiling to the MSP430 flash dictionary: I can now compile words on the MSP430!

I also moved the MSP430 development to the more widely available (and cheaper!) ez430RF module (MSP430F2274 based).

Unoptimized, the VM/interpreter is 6.6KB and the RAM footprint is 844 bytes (essentially leaving room for 90 one cell variables on the MSP430F2274). I made the dictionary 4092 words (~8KB) to leave room for C app code. The uForth dictionary is (by architecture) limited to 32KB.

The brave can grab at snapshot (or look at documentation) here. If you have an ez430RF and you want to poke about (you're on your own for now), you can grab this big TI format flash file here. This file contains both the VM/interpreter and a dictionary.

Sunday, October 04, 2009

Development Support words for uForth

Support words shouldn't be in the core. As smaller as it could be to write in C, I am resisting the urge of making the core larger. Take for instance "words". It is very, very useful for debugging but not so useful in a "finished" system. Why should it eat precious RAM or Flash if you don't need it?

Here is a quick definition of words in uForth. You can place it in init.f (for BOOTSTRAP versions) or pass it to "uforth_interpret()". It depends on a few words I've already shipped in init.f:


( Implementation of words in pure uForth! )
create _ ( dummy "known length" entry )
variable last_word
variable ccnt ( keep track of # of characters on a line)


: words ( -- )
_ 6 - @ last_word ! ( We know where the prev word link is inside of _ )
0 ccnt !
last_word @ ( pointer to last word )
begin
dup ( keep it on the stack )
1+ count 63 and dup ccnt +! ( get length of word's name )
ccnt @ 70 > if cr 0 ccnt ! then ( 70 characters per line )
type 32 emit 32 emit ( print word's name )
2 ccnt +! ( add in spaces )
@ ( get prev link from last word )
dup -1 = ( -1 link means no more words! )
until
drop ;

Friday, October 02, 2009

Simulating MSP430 I/O on PC uForth (Solution?)

One horrible solution (but may work for me) is to simulate the MSP430 I/O under PC uForth.

Keep in mind: uForth is about scripting, not about writing system level Forth stuff on an MCU. It is meant for slinging around C functions and libraries. I don't intend on doing much bit banging in uForth. There will be no UART driver, no interrupt handler, no deep notion of MSP430 power modes. SwiftX Forth (and others?) is the best fit for that.

I want to take existing C app (maybe already running on an MSP430) and manipulate it.

However, some times I may want to toggle some ports. I can do this with a minimal RAM_DICT uForth on the MCU. That may be adequate. This would allow me to hack the MSP430. Maybe I should create a special "hackers" dictionary for the MCU that allows me to bit bang ports and interact with peripherals. (This *should* be a writable dictionary.. try blinking an LED without some sort of DO .. LOOP construct -- this requires compilation!)

If I really do need the ability to do bit banging in the full "scripted application", I should be able to simulate it on the PC uForth. This wouldn't be a full MSP430 simulation, but maybe just enough so that I can compile the word, test it (maybe textual output: "LED bit0/port1 is ON!") and then dump/flash the dictionary.

Just a thought... but, uh it sounds oh so "batchy".

uForth MSP430isms

I'm trying to figure out how to best do uForth word compilation on the MSP430. Right now, if you want to do that you must use the RAM_DICT option (RAM based dictionary). This is inconvenient at best. A typical MSP430 part will have between 1KB to 8KB of RAM. Your initial dictionary may be larger than that!

Then there is the problem that compilation often involves rewriting memory (resolving BEGIN, DO .. LOOP references, etc). The MSP430 main memory is divided into 512 byte segments. And, each segment must be erased before writing (technically, you can write twice safely without an erase). What if the word definition spans two segments? I would need at least 512 bytes of RAM for buffering. Will I need more?

Another approach is to use a "tethered" development environment. With this, I would attach the PC uForth to the MSP430 uForth, compile the word locally and send the byte codes to the MSP430 to be flashed. This simplifies Flashing since there doesn't need to be a concern for rewriting bytes. However, this means that the PC and MSP430 uForths must be tightly bound.

SwiftX Forth takes a more formal tethered approach, but I like the more standalone nature of uForth right now.

The batch approach I take right now is to develop and test the word on the PC uForth, dump the dictionary and recompile the MSP430 Forth with this dictionary (flash based). The big problem with that can be summarized by the following example -->

: led-on bit0 port1 mem! ;

Ugh. There is no analogue for this on the PC uForth. My only recourse is to use a RAM based MSP430. But, after defining "port1", "mem!", etc. a 1KB RAM MSP430 part won't be big enough to support the dictionary. (And, obviously, using a Flash based MSP430 uForth, I won't be able to define led-on !)

Solution to follow... hopefully...

Thursday, October 01, 2009

uForth 0.4 ... more preliminary madness

Still very, very alpha. But here is another tarball: version 0.4

I got FLASH based MSP430 support working. No interactive compiling into Flash, but you can build a dictionary on the PC and then rebuild the MSP430 version with a Flash based dictionary.

Default still uses RAM_DICT under MSP430. The quick reference is still the best way to make sense of what you've downloaded.

Wednesday, September 30, 2009

uForth preliminary release... very, very alpha

This probably won't be usable for anyone and it isn't organized well at all. In fact, you could view it as a drunken pseudo-intellectual ramble captured as source code. It may mean something, or it just could be plain useless. For me, personally, it is an achievement.

I am sitting here right now, enjoying a Taylor Fladgate 10 year old Tawny Port, listening to a heady mix of Abdullah Ibrahim, Michael Franti, Dinosaur Jr. and Arcade Fire, considering if I should release this.

Aw, hell. If you want to muck with it, go ahead. Here is the (probably uncompilable) tarball of uForth.

P.S. I actually got it to run on an MSP430 today (via Rowley Crossworks). I can't promise support, nor can I promise a steady stream of releases, although it is geared to become the basis of some stuff at my day job.

Sunday, September 27, 2009

u4th - Forth for microcontrollers

Okay, I got tired of searching and waiting. I decided to roll my own "portable" Forth targeted for microcontrollers with limited resources. I want to do a Forth that would work on MSP430s, ARM Cortex and desktop PCs.

This would be more of a "scripting" Forth vs a full bottom up programming language. It would expect to be embedded in C and able to call C functions (like a scripting language!).

Right now I have something working on both a PC and MSP430 (simulator). u4th is written in C and makes no presumption about I/O (you can extend and add UART support, but it is happy to just work with a dictionary and an init() function). It supports a RAM or ROM/Flash resident dictionary (but no Flash writing support built in). It compiles a position independent dictionary that can be transfered to/from a PC and MCU without modification.

It does not implement ANSI Forth.. it is it's own beast geared for scripting, not system building.

I have a few more things to add (no DO .. LOOP yet) , but right now it runs (interpreter + VM) just under 4KB RAM (with a 2KB RAM resident dictionary -- so if the dictionary is Flash based, we are talking well under 2KB RAM!) and around 7KB of program (flash resident code).

More to follow!

/todd

Wednesday, August 26, 2009

compose-tex vs AFT

I've been doing some AFT hacking for a person who needed some text support. There are many AFT alternatives out there these days but he says that AFT hits the spot because it produces LaTeX as well as HTML.

There are some decent LaTeX to HTML converters out there too (have been for years).

I've been thinking about making a simple "free-ish text" converter that produces only LaTeX. It would be a LaTeX helper of sort. It would allow a casual user the ability to produce very high quality print without the learning curve of LaTeX.

The trick is, the "almost free text" format markup would have to be beautiful. The idea is "beautiful plain text in", "beautiful print out".

What if everyone could produce beautiful print? What would you typeset?

Friday, July 03, 2009

Living my values...

This old blog entry struck a chord. I followed a bunch of links from TED.


Thursday, July 02, 2009

Colorforth as inspiration

I always keep up the best I can with what Chuck Moore (inventor of Forth) is up to. I've always found colorforth to be fascinating.

Mr. Moore has started a couple of blogs. Of particular interest is his recent blog for tracking progress with his latest creation.

This reminds me why playing with hardware is so much fun. I am a bare-metal guy at heart, although there isn't much opportunity for doing this type of work (for me) these days.

How do I make a career out of bare metal progamming? Forth gives me some of this thrill. I like to poke and peek hardware to see it work. Something about batch compiling/loading (C and C++) through an IDE loses that feel.

I don't really want to "roll my own" Forth these days. Language design as a thrill has come and pass.

I got a buzz out of using SwiftX Forth (for the MSP430) at work a while back. Getting an unsupported MSP430 (the MSP430F5XX) working with SwiftX was a blast.

If I can scrape together $395 for a SwiftX MSP430 license (for non-work use), I'd like to kickstart an idea I had for doing a Simpliciti clone in Forth.... but my wife's van needs new tires :-(

Monday, June 15, 2009

More on (embedded) C++

Interesting paper regarding using C++ for embedded work by Stroustrup. I wonder how much of this is taken to heart by embedded developers.

Thursday, June 11, 2009

Evaluating the Cortex-M3

So, I have 2 evaluation kits: the stm32circle and the stm32-performancestick. Each under $100 and each with interesting features and annoyances. I've spent around $130 between the two.

I suppose it would have made more sense to just get the Olimex header board ( STM32-H103) for $40, a $70-100 JTAG, and GCC, but the point of the evaluation excercise is NOT to spend hours doing the "let's build everything from scratch". When the right integrated environment is chosen it sometimes worth the money. I still (and will continue to) do my source code editing in emacs but I have become pampered by the often richer experience of debugging with a decent IDE.

I would still like to just use emacs + gdb + gcc for development, but while I'm learning the chip I'd rather have an IDE with integrated documentation and GUI hand holding. My days of grunting manly about how I built all my tools by hand and debug via gdb command line is probably over. I will probably never replace my beloved emacs (used mainly out of habit) for editing and browsing code, but the point here is to hit the ground running and focus on the Cortex.

So far... stm32circle and Raisonance is nice, but I have no interest in CircleOS, so I've yet to see what it offers me in turns of raw EABI programming. Raisonance Ride is limiting me to 32KB debugging. I suppose I won't be using a lot of the advanced features of the stm32circle (color LCD, sound, etc) but it is a very rich platform (for only $40).

The smt32-performance sticks comes through Hitex (which is promising me unlimited debugging after I send them email). No response yet. The older license key (I am using the most up to date version of the debugger) doesn't work. They said I should email them a request for a new license. I was able to run their "dashboard" which allows me to do some performance/power tests. This is very informative.

At some point I will choose one or the other to do some development with. I guess I am hoping that the stm32circle will "win". Ride7 looks nice (reminds me of Crossworks). I need to see how well it does without forcing me into CircleOS.

I'll post updates in the next couple of days.



Monday, June 08, 2009

Forth on the Cortex-M3?

I can't seem to find any Forth running on a Cortex-M3 (let alone an ARM Thumb).  This is the reason why I started to look at C++ again.  I'm getting sick of plain old C -- great for little things, but I have bigger fish to fry.

I won't bother to convince myself that I have time to craft/port a Forth to the Cortex.  However, I wonder if porting a Forth written in C is an acceptable compromise?

Hmm...

Sunday, June 07, 2009

Stroustrup's new book

I swore I would never do C++ programming again (3 yrs ago). Never say never. I realize that I miss some of the abstractive capabilities compared to C. I don't miss OO, I miss Generic Programming.

I was browsing Reiters a couple of weeks ago and was shocked to find this book. C++ as a first language? I was intrigued. I think that Stroustrup is a good concise writer and I wondered what an "intro to programming" book would look like (coming from his hands).

I purchased the book last week.

The book is interesting. I don't know how well it would do with a newbie, but I tend to like his no-bullshit approach. It is quite refreshing. He is very pragmatic and I liked how STL (generic programming) takes a front seat.

I am also a fan of Alexander Stepanov. He has a book coming out this month. I've already pre-ordered it.

This nicely meshes wth my current interest in Cortex M3 microcontrollers. I don't want to resort to C programming when I start messing with my Primer.

Friday, June 05, 2009

IAR, STL and the MSP430

Apparently, the IAR MSP430 compiler supports C++'s STL.  My jaw drops.

In my previous post, I alluded to the desire to try generic programming on a Cortex M3.  Out of curiosity, I wondered whether or not it would be possible/practical to do C++ on an MSP430.

Well,  after some deep digging I've found that IAR has "some" C++ support that includes the STL!

How efficient can it be? Well, I don't like resorting to dynamic memory allocation when I don't have to (and certainly not on an MSP430) but I decided to give some basic STL algorithms a try.  I am less concerned about performance than about code size. STL is (undeservedly, IMHO) notorious about being a source of bloat.

Here is the sample code:

#include  <msp430x54x.h>
#include <numeric>
#include <functional>

static volatile int res;

int main( void )
{
  int a[] = { 9, 1, 5, 6, 7, 8};
  
  // Stop watchdog timer to prevent time out reset
  WDTCTL = WDTPW + WDTHOLD;
  
  res = accumulate(a,a+sizeof(a)/sizeof(int),0);
  res = accumulate(a, a+sizeof(a)/sizeof(int), 1, multiplies<int>());

  return 0;
}

This compiles to 250 bytes of CODE, 162 bytes of DATA and 12 bytes of CONST  with default compile settings. (Some of the DATA is pre-sized stack and heap.)

With the highest optimization settings this compiles to 180 bytes of CODE, 162 bytes of DATA and 12 bytes of CONST.

I am impressed.

Sure this was a contrived test, but I am amazed that I could even do this.

Is this more efficient than a hand written accumulator? No. There are function calls here that wouldn't exist if I were to do it by hand. However, this may scale better than I could muster by hand:  By cherry picking STL algorithms I am choosing to be more type "aware".  I am also avoiding writing stuff like:
  for (int i=0; i < sizeof(a)/sizeof(int); i++)
    res += a[i];
Simple, right? But do you see the two potential problems? First, I never initialized "res". Second, I introduced another variable "i".  While the STL code has the overhead of function calls, it uses the more space efficient technique of incrementing through "a" rather than indexing.

I'm not planning on using the STL for any real MSP430 work. That would be overkill.  But the Cortex M3 is a different issue...


Wednesday, June 03, 2009

C++ on ARM Cortex-M3?

I've been wondering how many people use C++ on ARMs. I don't mean C++ as in a "better C", but C++ in full (sans dynamic memory management and exception handling -- both casting non-determinism on systems seeking deterministic behavior).

The embedded development community/industry seems stuck in C.  (I'm talking truly embedded here -- not Linux gumsticks, not "single board computers", etc.)

How about C++ with STL (but without vector and other containers that use new/malloc)?
Does this buy you anything?

There has to be an alternative to C.  I wish it was Forth, but there doesn't even seem to be a Forth for Cortex.

I love C, but it doesn't scale very well (when it comes to abstractions and type safety).

How would generic programming (templates) look on an MCU?  Would I be able to come up with a template that would let me abstract away SPI and UART code?

Is Embedded C++ (with templates) inevitable?

The prospect almost makes me want to buy this: http://www.digikey.com/scripts/dksearch/dksus.dll?Detail&name=497-6049-ND&enterprise=12 (a Cortex M3 demo/devkit for < $40).