Saturday, December 24, 2011

How to get Android Icecream Sandwich working on a Pandaboard ES

I have, after some messing about, compiled Android from the AOSP source release and got it running on my Pandaboard ES. Here are some random hints for anyone else trying to do the same -


Most importantly, make sure you're pulling the latest master branch from AOSP. A fix went in on, oh, Tuesday or so that actually made the bootloader and fastboot work on the ES board. Without this, you are doomed. Thread here -

http://groups.google.com/group/android-building/browse_thread/thread/9d784fc702451c9f?pli=1

With this, the instructions in  device/ti/panda/README more or less work out of the box (exception: fastboot flash userdata and fastboot flashall both need -p panda specified). Without it you get stuck at the Waiting for Omap43xx... step because fastboot doesn't recognise the ID of the ES board, only the original Pandaboard.

If using HDMI, make sure to use the connector on the corner of the board - I saw SGX crashes trying to use the other.

The engineering build is sloooooow and would be a pain to develop with, I think; the user-with-root build is still a bit sluggish at first before code gets JITed but is usable.

Don't be tempted to try and format the SD card yourself, as I was before finding out how to get fastboot working; there's a script floating around out there called omap3-mkcard.sh, but for me it didn't produce anything I could boot. It has a bug in it, too - there's a section that goes like this:

if [ -x `which kpartx` ]; then
     kpartx -a ${DRIVE}
fi


If you actually have kpartx installed then this will 'hold onto' the partitions on your SD card, causing the filesystem creation code later to fail, every time, because the device is busy. Not sure how that got through testing, but it can be replaced with

sfdisk -R $DRIVE

Also, if you're adding udev rules so that you can use fastboot and adb as non-root, these are the entries needed for the ES (different from the plain Pandaboard) -

# fastboot protocol on panda (PandaBoard ES)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d010", MODE="0600", OWNER="<user>"
# adb protocol on panda (PandaBoard ES)
SUBSYSTEM=="usb", ATTR{idVendor}=="0451", ATTR{idProduct}=="d101", MODE="0600", OWNER="<user>"

where <user> should of course be replaced with your login. On my (Kubuntu 11.10) system these appear to live in /lib/udev/rules.d and not /etc/udev

Hope this helps someone! I'm pretty happy with the board now it's running; I have accelerated 3d (make sure to get the latest 4.0.3 binary driver drop from the Nexus drivers page) and working wifi. No audio, but I can live with that for now. I was also pleasantly surprised by the build time - Google recommends an absolute monster of a build machine, but my fairly middle of the road triple-core machine compiled ICS from scratch with -j 6 in about two hours.









Thursday, September 29, 2011

Digging up some old code

A year or so ago I started writing my own little debugger, just basically so I could know a bit more about what's going on under the hood in such programs. It was a natural follow-on from writing my own compiler/linker, which I sort of stopped working on after I satisfied myself I knew how to write such a thing (and came across LLVM which does that sort of thing about a thousand times better than I was going to be able to do on my own). Life events got in the way of my doing too much with it at the time, but here's the code anyway for those who might be curious - http://hu.gs/~emily/debugtoy.tar.gz It uses the Linux ptrace() system call and my own code to parse ELF and DWARF binaries; there are libraries out there that can help you do the latter, but as I say I was doing this to learn my way around the format myself. It can attach to processes, halt/single-step them, display/edit registers and memory, figure out the name of the function you're in, and identify the line in the source code that corresponds with the current instruction pointer.

Thursday, August 18, 2011

Calliope, a Mobipocket (Kindle) compatible ereader

I've lately been working on writing an ereader in Qt, with Android in mind. I let the project sit for a few weeks because of a combination of personal life events and bugs in the (very much still in development) Android port of Qt, but a couple of days ago I achieved the milestone of being able to read a commercially-released book on my Galaxy Tab.

Why work on an ereader, one might well ask? Amazon already have one for Android, and it's quite nice. Well, one thing that always annoys me reading ebooks is the somewhat....variable quality of the spellchecking; it seems quite common for them to be poorly spelled compared to printed books. This is a hundredfold more true of public-domain books from places like Project Gutenberg that have been OCR-scanned and tossed up on the site. How nice it would be, then, to be able to edit the book in situ and correct such errors. I plan to allow this, not by physically editing the ebook file (I'm wary of the legal implications of modifying a copyrighted work) but by storing an overlay file which in essence says 'word 20 of paragraph 32 should be 'mistake' and not 'mistaek''. As a side benefit, I can also provide a filter ability which can automatically convert all spellings of a word from one form to another - 'any time you see 'color', substitute 'colour'' - it always feels a little weird to me, as a Briton resident in the US, to buy a book by a British author whose spelling has been Americanised. I'm not yet at the point of doing any of this; right now I'm happy simply to be able to read the text as written, but I figured I might as well document what I've done to get to that point.

The reader, like the Kindle, reads Mobipocket files. These were originally designed to be read on Palm OS devices, and are stored in Palm-style database file. These consist of some headers and a series of blocks of data, each of which can be individually compressed with a form of Lempel-Ziv encoding (similar to what gzip uses, for instance). Mobipocket books consist of header information including optional tags for things like ISBN numbers, followed by the blocks that comprise the actual book (compressed, each block limited to 4k compressed size), followed by any images, each in its own block (required to be GIF format). The book text itself is HTML 3.2 with some customisations for purposes such as referring to images. The first image in the book is by convention the book cover. Books bought from Amazon are encrypted; while that encryption has been cracked and I could probably add support for reading them, I haven't because I'm not sure of the legal implications, even though it would only be used for books I've legitimately purchased.

I've written a 'bookshelf' that looks in a standard directory (currently fixed by platform; ~/Documents on desktop Linux, /sdcard/kindle on Android), sniffs all files in it to see if they're ebooks it can read, and displays those books in a list. Choosing one fires up a Page widget which actually displays (currently) the img and p tags from the book.

Doing this is more involved than one might think. Firstly there's the challenge of turning those compressed buckets into an uncompressed text stream. I accomplish this by writing a custom QIODevice (the underlying abstraction for Qt's files, network sockets etc) which wraps the document text and uncompresses it on the fly. Since it's a QIODevice I can also easily write the uncompressed text to disc. The Mobipocket header includes information on the character format used in the book (generally either Latin-1 or UTF-8) so I can construct a QTextStream that will do the appropriate conversions.

The book being HTML 3.2, Qt's inbuilt XML parser naturally chokes on it (I really can't blame it), so I had to write my own simple HTML parser. I've written it in more of a SAX than a DOM style (i.e. it parses the HTML stream incrementally rather than all at once) because by the nature of the thing an ereader is only concerned with displaying a small part of the document at a time; parsing the whole book on opening it would both take time at startup and needlessly consume RAM.

The stream is then split into Elements, each representing a block to be displayed on the screen; currently image and paragraph elements, the latter consisting of string fragments, which are collections of words with the same attributes (bold, italic, etc). Each element can report a size to the page layout algorithm and render itself; paragraph elements are careful not to render text where it would be partially cut off by the bottom of the page. Currently, the page renders as many elements as it can before hitting the bottom of the page; hitting the right of the window to go to the next page moves them 'up' by the height of the page then resumes rendering beginning with the element that was at the end of the last page.

Unfortunately, since I don't want to keep all elements parsed forever, I don't really have a good way to go back at present; an ereader that only goes forwards is a bit limited! I'm trying to figure out both how to handle this and how best to store position within the book, bearing in mind these problems -

- The page can be resized both during reading and between runs of the application (including on Android; think of rotating the tablet, for instance). These will cause paragraphs to reflow, taking up more or less lines on the page.

- There are ways to put pagebreaks into the book, which I do not yet support but will need to to handle, for example, the end of chapters.

I think the way I'm going to approach it is by viewing the book as a very very tall virtual screen of fixed width; so elements will have a virtual y coordinate starting at 0 and going down all the way to the end of the book, divided into pages every height-of-window pixels. The page itself acts as a window onto this virtual screen; going backwards will involve putting the page back by its height, then reparsing the book from the beginning until reaching elements that are visible on the page. I'll have to evaluate this for speed; it may be worth cacheing the previous page or two's elements since generally readers don't go much further back than that.

As for resizing, as well as storing the virtual y coordinate of the page, I'll keep track of the topmost element on the page (and in the case of a paragraph the word within it). Resizing involves repaginating and parsing from the beginning until that element and word appear on a page, then displaying that page.

Source for the app is at https://github.com/jotheberlock/reader

Saturday, April 16, 2011

Baby steps in electronics

My first self-designed circuit - though it's a bit of a stretch to call it that. I've got 12v coming into the near side of the breadboard from a NiMH battery (and I am a bad engineer for using the same colour wire for live and ground there, oops). That's being shunted through an adjustable switching regulator to provide 7.2v on the power rails on the far side.

The reason for this is I've gotten the superstructure off my new RC tank, removed the built-in RC controller and am getting close to testing it out with the motor controllers I used in the old tank. I need 12V because basically all the electronics I intend to put on the rover (Fit-PC2, Kinect, Arbotix and AX-12 servos) want that; however, unlike my old tank which ran on 9.6v and could tolerate 12, this one is based on 7.2v.

I could shunt 12v into the motor controllers (they'll take up to about that much) and rely on PWM to bring the effective voltage down to something the motor can handle without burning up - but I'm a programmer, and therefore I trust hardware more than my software, during development at least. This way there's no way I can mess up and explode my motors, and as a side effect I imagine the regulator will prevent too much EMI getting back and messing with the PC.

Saturday, April 9, 2011

Fitting a touchscreen to the EeePC 701

I have an old netbook I acquired second-hand as a robot controller a couple of years ago - it's an EEE PC 701. I thought it might be a cool hack to fit a touchscreen to it, so I ordered a cheap resistive one from DealExtreme. A week and a half long boat trip from China later, it arrived last week.

Picture of what I got

It consists of a small USB hub with display controller (bottom of the picture) and what amounts to a glass plate with a ribbon connector.

Installing it turned out not to be all that much hassle - you have to remove six screws from the front of the LCD casing and pop the bezel off. This takes a little bit of effort with some sort of flat blunt tool, in my case a dinner knife -

Case reveals its secrets

then I slipped the touch panel in there and used sticky tape to secure it to the screen. It's hard to get good pictures, unfortunately, since I didn't take the bezel completely off.

Seated touchpanel

I unplugged the camera up at the top (it's horrible and I never use it), put that connector into the hub/controller's in port, put the ribbon connector into the display's connector, and that was it (let a veil be discreetly drawn over my first attempt, where I failed to distinguish 'USB IN' and 'USB 3' on the circuit board). The controller is tucked under the left speaker grille; it causes a slight bulge when the bezel is screwed back on, but I gather this is normal.

After some unsuccessful attempts with the Kubuntu 10.04 I had installed to get it to properly recognise the touchscreen, I decided to embrace the bleeding edge of technology and install Kubuntu 11.04 Beta - the world of touchscreen input advances swiftly in Linux these days. Unfortunately my display connector was mis-soldered (not an uncommon problem apparently) resulting in inversion of the X axis, but this proved easy to solve temporarily by messing around with the xinput command-line program. A bit more challenging was calibrating the thing - this is an eGalax USB-HID touchscreen, which the standard tslib/ts_calibrate stuff doesn't seem to want to talk to. I managed to hunt down this program, however, which did the trick nicely - it calibrated my screen, altered the running server's parameters on the fly, and gave me a configuration snippet to put in /etc/X11/xorg.conf.d which worked just fine. Why it's not in Kubuntu's apt repository yet I'm not sure, it's pretty useful.

I also gave android-x86 Gingerbread a go from a live USB stick, just to see what would happen, but it didn't recognise the touchscreen at all. That might be something I have a go at fixing down the line, but I figured I'd done enough for now.

Still to do with this netbook, at some point, is taking the bottom half apart so I can try reseating the display connector; my screen sometimes goes all white and flickery, especially if there's a lot of black onscreen, which googling seems to indicate is a hardware problem. Also still to do is figuring out if I want to make and attach some kind of stylus holder.

Thursday, March 24, 2011

My mobile object system

This is what I've been tinkering with for the last couple of weeks. Basically, it's a distributed-object system with persistence based on top of Qt. It allows me to write objects that can be moved from computer to computer and automatically be persisted to disc (or wherever else) - so for example I can log into a site on my tablet in a web browser then move that browser to my desktop PC, keeping my login credentials and page position - something similar to what Engadget calls the continuous client.

Code tarball is here - I've been building it using android-qt's branch of qtcreator on Kubuntu 10.10. It's very definitely a prototype and does not (obviously) represent production-quality code.

Detailed description is in the tarball and also here.

Purpose of this blog

I'm a British software engineer living in Ann Arbor, Michigan. My day job involves embedded Linux and Qt in an automotive context, but I get up to a variety of hobby projects in my spare time, mostly related to Linux, robotics and Android. I decided having a dedicated blog to document such things without boring my non-technical friends to tears might be a good idea.

First up, I'll be posting shortly about my project of the last few weeks, a system for cross-platform mobile objects based on Qt.