IguanaIR send and receive

01.09.2012 16:37

Today I've been playing with the IguanaWorks USB IR transceiver I wrote about previously. I managed to record a few codes transmitted by remote controls that were lying around the room and also control devices by re-transmitting the codes. As details of this operation were not completely obvious to me from the documentation available, here's a short tutorial.

For basic receive and transmit you need just the iguanaIR package (igdaemon and igclient). There is no need for lirc.

For reception, use the following command:

$ igclient --receiver-on --sleep 10
received 1 signal(s):
  space: 57344
received 6 signal(s):
  space: 2901
  pulse: 2389
  space: 576
  pulse: 1194
  space: 554
  pulse: 597

This gives you 10 seconds to point any device that is transmitting IR codes to the Iguana receiver. The receiver demodulates the amplitude modulation and prints out lengths of interchanging silence and carrier signal intervals (in microseconds) to standard output. received ... signal(s) lines can be ignored as they appear to only tell you how the data was divided into chunks when it was sent from the daemon to the client.

As far as I know, there is now way to determine the carrier frequency.

Signals recorded this way can be translated into a raw, unsigned, 8-bit data stream with 1 MHz sample rate using the following Python script.

import sys

for line in sys.stdin:
	f = line.strip().split()
	if len(f) != 2:
		continue

	s = f[0]
	l = int(f[1])

	if s.startswith('pulse'):
		sys.stdout.write('\xff' * l)
	elif s.startswith('space'):
		sys.stdout.write('\x00' * l)

This can be handy for viewing or editing signals, for instance in Audacity.

To transmit a signal, use the following:

$ igclient --send path-to-file
send: success

path-to-file should in this case point to a file that has a similar, but not quite the same format as the receiver output above:

pulse 2389
space 576
pulse 1194
space 554
pulse 597

Apart from missing colons this format is also a bit stricter regarding the sequence of pulse/space lines. The file should always start with a pulse (not space) and the client won't allow for multiple consecutive pulse or space lines (i.e. you should consolidate them into a single line). It also appears that if the sequence described by the file is too long, you will get a timeout error from the client, even though the sequence will actually be transmitted by the USB dongle.

You can set the carrier frequency using igclient --set-carrier.

To get this format from a raw file that was produced by the Python script above, use this snippet:

import sys
import itertools

data = sys.stdin.read()
data = map(lambda x: x > '\x7f', data)

for k, g in itertools.groupby(data):
	l = sum(1 for x in g)
	if k:
		print "pulse", l
	else:
		print "space", l
Posted by Tomaž | Categories: Code | Comments »

Monitoring serial console through JTAG

30.08.2012 18:15

I've written previously that VESNA has an unfortunately placed debug serial console. The connector with the RX and TX pins also provides power to the microcontroller in the common configuration we have deployed in the field. This means that it's quite hard to connect a terminal emulator to it without resetting the node. While it might seem that debug messages printed on the serial console are only useful in testing and development, we have a common occurrence where deployed VESNAs would stop responding to the network commands. Since checking the serial console is the first step in debugging such an issue, it's important that it's accessible even in a production system.

If you have a JTAG port accessible (and enabled) and an in-circuit debugger (like OpenOCD) that works with GDB you can attempt to monitor what is being printed to the serial port in the following way.

Load up the debug information for the firmware running on the microcontroller, set GDB for remote debugging through in-circuit debugger and enter the following commands:

(gdb) break _write
Breakpoint 1 at 0x80001c8: file hello-world.c, line 43.

This sets a break point on the function that writes to the serial console. I'm using the int _write(int file, char *ptr, int len) syscall hook here, which in turn calls low-level UART functions.

(gdb) commands 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>silent
>output *ptr@len
>echo \n
>continue
>end

Here we instruct GDB to skip the usual informative messages about a break point being reached, print the array of characters in the function's arguments and continue without the usual command prompt.

(gdb) set height 0

Finally, we disable the built-in pager, so that GDB doesn't wait for confirmation on every screenful of print out. Now we can continue the execution of the program, and GDB will print a line for each invocation of the _write function:

(gdb) c
Continuing.
Note: automatically using hardware breakpoints for read-only addresses.
"Hello, world!\n"
"Hello, world!\n"
"Hello, world!\n"

In a pinch this turns out to be a useful workaround when debugging with no serial console. Be warned though that breaking into GDB this way does seem to incur a significant overhead. Programs that print a lot of output will run significantly slower, although I haven't measured exactly how much. This shouldn't be a problem unless the root of problem you are debugging is time-sensitive or you are calling printf() in interrupt handlers (but you wouldn't be doing that, would you?)

Posted by Tomaž | Categories: Code | Comments »

EnergyCount 3000, part 2

15.07.2012 20:18

A few months ago I was writing about my attempts to reverse engineer radio transmissions from Voltcraft EnergyCount 3000 devices. Since then a lot of the things I was speculating about got much clearer, mostly thanks to reverse engineering efforts on the jeelabs.net forum. Yesterday there was an Open Data Hackday in Kiberpipa and, while this wasn't strictly on topic, I finally managed to integrate all of the little pieces of the puzzle together into one working, simple to use Python module.

Voltcraft Energycount 3000 energy logger

So today, I'm pleased to announce the first release of ec3k, a software receiver for EnergyCount 3000 devices. It's built around GNU Radio and currently works with cheap, RTL2833-based receivers. You can fetch it from Cheese shop or directly from GitHub. It's licensed under GPL version 3 or later.

The biggest obstacle you need to cross before using it is installing GNU Radio, rtl-sdr and gr-osmosdr. A good starting point is the Osmocom Wiki which has a quick overview and links to other relevant documents. When GNU Radio is working for you, only the standard Python distutils dance remains:

$ python setup.py install
$ python setup.py test

The package includes a simple command utility which prints out all received packets to the standard output:

$ ec3k_recv 
linux; GNU C++ version 4.4.5; Boost_104200; UHD_003.004.002-128-g12f7a5c9

gr-osmosdr supported device types: file fcd rtl rtl_tcp uhd 
Using 16 buffers of size 262144.
Using device #0: ezcap USB 2.0 DVB-T/DAB/FM dongle
Found Elonics E4000 tuner
>>> gr_fir_ccf: using SSE
Using Volk machine: avx_64
Noise level: -27.3 dB
Noise level: -27.4 dB
Noise level: -27.5 dB
id              : f100
uptime          : 4004 seconds
since last reset: 37809 seconds
energy          : 385300 Ws
current power   : 1.3 W
max power       : 2.3 W
energy          : 4579600 Ws
Noise level: -26.7 dB
Noise level: -26.8 dB

Here is how you can use the ec3k module from your own Python code:

import ec3k

def callback(state):
    print state

my_ec3k = ec3k.EnergyCount3K(callback=callback)

my_ec3k.start()
while not want_stop:
    time.sleep(2)
    print "Noise level: %.1f dB" % (my_ec3k.noise_level,)

my_ec3k.stop()

As shipped, the receiver uses around 20% of one CPU core on a 2.7 GHz Intel i5 CPU. You can improve that by using my C implementation of the base-band decoder from the am433 project. Just compile the capture binary (version 0.0.4 or later) and drop it somewhere in your PATH. ec3k should find it automatically and use it instead of the built-in pure Python implementation.

For details on the API, please check the included README and docstrings. README also lists a couple of known problems that are still present in the code. Any help regarding those, or otherwise, is most welcome as always.

Again, thanks goes to the people on jeelabs.net forum for figuring out how to descramble the packets and Gašper for providing the hardware, Python base-band decoding code and testing.

Posted by Tomaž | Categories: Code | Comments »

Broken C++ compilation on Debian

13.07.2012 9:24

I've noticed lately an issue with GNU C++ compilation on a few machines running mostly Debian Squeeze. Mostly because each one also has a few cherry picked testing and backports packages installed over the basic Squeeze system.

The symptoms are that linking all C++ programs will fail with an error message like this:

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/4.4.5/libstdc++.a(functexcept.o):
relocation R_X86_64_32 against `std::bad_typeid::~bad_typeid()' can not be used
when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/4.4.5/libstdc++.a: could not read symbols: Bad
value

This error points in a completely wrong direction though and made me loose a few hours in hunting down its true cause. So for future reference, here is what's really causing it.

For some reason, this symlink for the standard C++ library gets broken:

/usr/lib/gcc/x86_64-linux-gnu/4.4.5/libstdc++.so -> ../../../libstdc++.so.6

It seems that GCC sees the broken link and quietly decides the dynamic version of libstdc++ isn't available and attempts to link programs with the static one, which fails. I'm not sure exactly which package upgrade breaks the link, but since I saw this on more than one machine I'm guessing it's a bug somewhere and not just some quirk specific to me.

Once you know it, the fix is simple:

$ cd /usr/lib/gcc/x86_64-linux-gnu/4.4.5
$ sudo ln -s ../../../x86_64-linux-gnu/libstdc++.so.6 libstdc++.so
Posted by Tomaž | Categories: Code | Comments »

Switching PulseAudio output device

25.06.2012 13:27

I have my desktop computer connected to a hi-fi and a television screen through HDMI. This means that I'm often switching video and audio outputs from my monitor and speakers on the desk to the TV and vice-versa. Changing video output via xrandr from a shell script is trivial. Convincing PulseAudio daemon to switch audio outputs is a completely different can of worms.

In GNOME you switch the audio output from the user-friendly Sound Preferences window (internally called gnome-volume-control). This requires several clicks of the mouse and doesn't have a command-line interface to it as far as I know. Its effect is instantaneous and even works reliably with applications that are playing audio while switching outputs.

PulseAudio itself comes with two basic command line tools, called pacmd and pactl. Former offers a set-default-sink command, but that doesn't do what you expect from it. It turns out that, at least on my system, PulseAudio daemon keeps persistent settings for each application that ever connected to it. This means that the default sink only gets used for applications that the daemon hasn't seen yet.

Digging through the source code of gnome-volume-control revealed that it walks through the stored persistent settings and modifies them each time you change the sound output device in that dialog window.

So what I did is copy the way gnome-volume-control does it and package it into a simple command-line utility, paswitch.

You can get it here:

$ git clone http://www.tablix.org/~avian/git/paswitch.git

Once you compile it by calling make, the usage is straightforward:

$ paswitch alsa_output.pci-0000_01_00.1.hdmi-stereo

To obtain the name of the sink, you can run pactl:

$ pactl list
...
Sink #0
        State: SUSPENDED
        Name: alsa_output.pci-0000_01_00.1.hdmi-stereo
...

By the way, this answer offers a different way of doing it. However it requires turning off persistent settings via restore_device=false in PulseAudio configuration.

Posted by Tomaž | Categories: Code | Comments »

SPI interrupts versus polling

17.06.2012 9:12

SPI peripheral on the ATmega328 microcontroller only has a single byte buffer. Since this microcontroller family doesn't have a DMA controller this means that when it wants to transfer multiple bytes the CPU must re-fill the buffer each time 8 bits have been transferred over the line. There are two straightforward mechanisms to do that: the software can poll a flag in the SPI status register and wait in a busy loop until the hardware peripheral has emptied the buffer, or it can install an interrupt routine for the serial transfer complete interrupt request which fills the buffer when necessary, without the need for polling.

Arduino ships with a SPI library that uses the former approach: it transfers one byte at a time and uses a busy loop to wait for transfer to finish. While playing with the OLED shield I was wondering if an interrupt request would be more efficient. The usual SPI use case with such a display is that the CPU calculates some pixel values and stores them in a buffer. This buffer is then pushed through the SPI to the display controller and the CPU goes to calculate another buffer worth of pixels. I thought it might be possible to get a higher frame rate if the CPU could do some calculations while the transfer was in progress and only get interrupted when it needs to fill the transmit buffer.

Hence I came up with two implementations of the seps525_dataBurst() function:

/* polling method */
void seps525_dataBurst(const uint16_t* values, int len)
{
  uint8_t *p = (uint8_t*) values;
  for(; len > 0; --len) {
    /* start the transfer */
    SPDR = *(p+1);
    /* wait for the transfer to finish */
    while (!(SPSR & _BV(SPIF)));
    SPDR = *p;
    p += 2;
    while (!(SPSR & _BV(SPIF)));
  }
}

and

/* interrupt request method */
static uint8_t* volatile burstData;
static volatile int burstLen = -1;

ISR(SPI_STC_vect) {
  burstLen--;
  if(burstLen < 0) {
    /* finished, turn off the interrupt request */
    SPCR &= ~_BV(SPIE);
  } else {
    /* start the transfer of the next byte */
    SPDR = *burstData;
    burstData++;
  }
} 

void seps525_dataBurst(uint8_t* values, int len)
{
  /* wait if the software buffer is not empty */
  while(burstLen >= 0);
  burstLen = len;
  burstData = values;

  /* enable interrupt */
  SPCR |= _BV(SPIE);

  /* start the transfer of the first byte */
  SPI_STC_vect();
}

(interrupt request routine here is somewhat simpler and doesn't correct for the CPU byte order)

Surprisingly, the polling function outperforms the interrupt request by almost a factor of 2! On the plot below the upper trace shows the performance of the polling routine while the lower trace shows the interrupt routine. Both were called from an identical animation event loop. When the signal connected to the oscilloscope is low the SPI transfer of a single display frame is in progress, so the period of the signal shows the frame rate.

As shown the polling routine achieves around 15 frames per second while the interrupt gets to around 8 frames per second.

Performance comparison between IRQ and polling methods

In hindsight this result might not be so surprising. SPI in this case works at half the CPU frequency, which means that the CPU can only execute less than 16 instructions per byte sent. The polling loop wastes less time per transfer than an overhead of an interrupt call.

What is the lesson here? Certainly that a more complicated solution is not always better. Interrupt routine was tricky to get right, has more than twice the amount of code and is harder to understand for someone looking at the code for the first time (not to mention that it requires global variables). In embedded software, just like with any other kind of programming, it makes sense to do some profiling to see if it is actually worth it to complicate the code with performance optimizations.

Posted by Tomaž | Categories: Code | Comments »

z80dasm 1.1.3

06.03.2012 19:42

Last week Eric Smith found a bug in z80dasm, the disassembler for the Zilog Z80 microprocessor I put together a few years ago when I was researching Galaksija's ROM. It turns out a corner case in relative addressing where the offset would wrap around the 16-bit address space boundary of the CPU wasn't handled correctly. For such cases the code would create labels with excessively long names which overflowed some internal fixed-length string buffers, leading to stack corruption.

Hence a new release of z80dasm after almost 4 years. You can download the source tarball from http://www.tablix.org/~avian/z80dasm/.

I also used this opportunity to move the code from my old CVS repository to git, so you can now also clone the repository with:

$ git clone http://www.tablix.org/~avian/git/z80dasm.git

As for binary packages, Eric is packaging z80dasm for Fedora. I've put together updated packages for Debian and will do my best to get them into the Debian Unstable as soon as possible (as Debian is now three releases of z80dasm behind).

Posted by Tomaž | Categories: Code | Comments »

Too much NoScript

22.02.2012 22:57

I am a long time user of NoScript Firefox extension. I find it's an effective cure for obtrusive advertisements and weird page features, plus it gives me the feeling that I can still control who can execute code on my computers. I also hate being tracked by various bugs embedded in pages and NoScript allows me to block those iframes and scripts that send information about my visit to third parties.

It's not perfect (what is on the web today?) but in my experience the domain based blocking of Javascript seems to be an effective heuristic against unwanted content. Plus in contrast to various other ad- and tracking-blocking extensions it's very simple to temporarily or partially disable the block should I stumble upon a page that absolutely requires some piece of Javascript.

Unfortunately NoScript took a path all to many software projects take. From doing a simple task of blocking script execution it grew into a giant that wants to solve all of the browser-related security problems. That by itself isn't such a bad thing, but such complexity invariably leads to problems and it's those that are starting to annoy me.

For instance, NoScript nowadays comes with some heuristical algorithms for preventing XSS. As far as I know, they have yet to save me from malicious content, but are constantly breaking legitimate scripts like Instapaper, even when I put it on all white lists I can find. Same goes for something called ABE, which constantly prevents me from following links to servers on my local network. Again, it might prevent attacks against my local routers, but security that constantly gets in your way is worthless.

These two annoyances however at least identify themselves by descriptive error messages. Lately, some web applications started to repeatably break when NoScript is enabled without as much as a warning. One thing I found for instance is that NoScript will silently block Javascript that is served as MIME type text/plain. How that could be a security risk, I don't know. But it appears a few legitimate sites have misconfigured servers that do that.

As I've been looking a bit more closely at this project, I discovered another surprising thing: while the code is indeed released under a free license, the development process is all but open. There is no public source repository. There is no bug tracker. There is even no mailing list. All you get is a web forum and a bunch of XPI files that you can decompress to get to thousands of lines of dense Javascript code. You don't get any scripts for instance that are surely used in the release process to generate some files and pack all the parts into the XPI file itself. For a security oriented project, that is quite unusual to say the least.


Now I hate to only give criticism and not offer any solutions. Unfortunately my experience with Firefox extensions is limited to some prehistoric version and I have neither the time nor will to refresh it enough to be able to look into any of the bugs I described above. I know there are many talented Javascript developers out there that are more than capable of making a better NoScript, but the closed nature of this extension makes it hard to make a fork.

So I decided to rather donate some of my time to help with that last problem. I downloaded the complete history of stable and development NoScript releases from addons.mozilla.org and committed them to a GitHub repository. Using their API I also set in place a mechanism that will automatically update the repository with new releases, hopefully with minimal maintenance from my side. I also added a simple script that can be used to create an XPI file from code in the repository that should be nearly identical to official releases (except for author's cryptographic signature, of course).

As usual, you can check it out with a command like this:

$ git clone https://github.com/avian2/noscript.git

This also has a useful side effect in that it makes the original upstream development somewhat more transparent. With a diff between two releases one click away on GitHub, you can check the changes between two releases yourself. With a tool like that undesirable changes like NoScript messing with Adblock Plus back in 2009 might have been discovered earlier.

And finally, having all of NoScript history in git means you can easily create nice graphs in a few key strokes (courtesy of gitstats). Enjoy.

Number of releases of NoScript per month

Number of releases of NoScript per month (note that for releases earlier than 2007 I don't have information of their exact date hence the spike on the graph)

Number of files in NoScript XPI through time

Number of files in NoScript XPI through time

Lines of code in NoScript through time

Lines of code in NoScript through time

Posted by Tomaž | Categories: Code | Comments »

Electronics design, automation?

26.01.2012 16:03

Recently I had an opportunity to see development labs of a few local hardware shops and chat with people working there. In addition to my recent work at the Jožef Stefan Institute it made me realize that, for someone familiar with development practices in the world of free open source software, the field of professional electronics development is quite lacking in some regards.

Interesting. The software world has long ago established a need for revision control systems, code review tools, bug trackers and release procedures. And rightfully so - as I often rant about here, most software is so complicated today you are basically forced to use of such tools to achieve any kind of collaboration or a usable quality level. While it's true that too often good practices are overlooked in commercial settings and deadlines and marketing given priority, at least most developers will tell you what is the ideal they strive for.

Compared to that it was somewhat striking to hear that manual checking over multiple-sheet schematics for differences is common practice. Or that proper revision control systems aren't required and that keeping multiple folders of versions was all anyone would ever need. Or procedures for making fabrication documents, equivalent to a software release, that take too many minutes of clicking various settings in a graphical interface.

Agreed, most electronics development done in small groups and companies is simple enough to involve only one person. It also involves simpler designs and nowhere near the layers of abstraction present in software. But on the other hand mistakes are much costlier here. If a botched software release these days means uploading a new package or even just updating some scripts on your web server, a broken prototype hardware design sent to manufacture wastes much more tangible resources.

A collection of Eagle dialogs

One thing software developers learn is not to trust themselves. Any repetitive tasks should be scripted and should involve as few and as simple steps as possible. There should always be ways to double check your or your colleague's work. After a long work day I don't trust myself that upon saving a file I only made the changes I wanted and didn't accidentally drag an odd trace out of place while I was experimenting with layout. I don't believe that I won't forget to check that critical check box in the GUI the tenth time I will be exporting Gerber files. And most of all, I will never be sure that when comparing two PDFs centimeter by centimeter and line by line I won't miss a difference.

Not surprisingly, voices to improve this situation are being heard as open hardware philosophy becomes more widespread. Some of the blame here certainly goes to the lack of tools that would allow such processes. It appears that if you want to have them out of the box, you either need to go for some very expensive proprietary software aimed at large teams and huge projects, or funny enough, free software tools like gEDA.

More concretely, CadSoft Eagle, the software most used for small projects and not that uncommon also in the open hardware community because of its low cost, has a distinct lack of such capabilities. Having just finished my first design in it and finding out all of the above, I tried to change a few things for the better.

Demonstration of eaglediff, visual diff for CadSoft Eagle.

Hence, eagle-automation. It's a small collection of Python scripts that currently allow you to do just two things:

  • Make a set of fabrication documents from a single Makefile without clicking on a single dialog (with credits to Andrew and his blog post).
  • Do visual diffs between revisions of schematics and board layouts stored in git, like the one shown above

The installation is as simple as the usual Python setup.py install dance (you need Python Imaging Library) and the git integration uses git-difftool which is present in recent versions of git. For the rest I refer you to the README file. Apart from finicky Eagle scripting it's quite simple actually.

So, most of all, I hope this will make open hardware development easier and more reliable. I will still strive to use open tools like gEDA as much as possible - with which, by the way, I never had much use for visual diffs because of its human readable ASCII file format - but I also understand that a lot of people are stuck and will be stuck for some time behind proprietary tools. But I don't see that as a reason why lessons learned the hard way by the software world should not be reused.

Posted by Tomaž | Categories: Code | Comments »

Funcube spectrum analyzer

10.12.2011 11:49

I've written before about the Funcube Dongle Pro. Apart from receiving satellite telemetry and amateur narrow-band FM, it can also be useful as a poor man's spectrum analyzer.

I'm not talking about doing a Fourier transform on the baseband data. At around 80 kHz that's not really useful if you want to see the big picture, for instance when measuring spectrum of a DVB-T transmitter with a channel width of around 6 MHz.

What you can do however is to emulate a swept-tuned spectrum analyzer. You sweep the Funcube's tuner through the range of frequencies using steps of several tens of kHz and pipe the baseband stream to a software power detector. Then you can plot the received signal strength against the frequency and get a fancy graph like this:

Spectrum of a DVB-T transmitter measured using FCD

Of course, there's a catch. Funcube Dongle uses an audio codec that is connected to the user space through the ALSA interface. This means that after you change the tuner frequency the sampled data needs to go through plenty of big buffers before it gets to the detector.

So while the actual hardware might settle very quickly to the new frequency (I don't have data for the E4000 chip used in FCD, but other comparable tuners have channel change times in the order of milliseconds), software buffers limit the minimum sweep time.

For instance, this is what becomes of the picture above when you are not waiting enough time for the buffers to flush between (random, in this particular case) frequency hops.

Noisy spectrum of a DVB-T transmitter measured using FCD

It takes around 5 minutes to draw such a persistence plot with the bandwidth of 20 MHz, 50 kHz hops and 10 passes. So don't expect to get anywhere near the theoretical limit for sweep time versus resolution bandwidth.

You can get the Python source from the git repository below. It requires a recent GNU Radio installation, FCD source block and matplotlib.

$ git clone http://www.tablix.org/~avian/git/fcd_scanner.git
$ python fcd_scanner/fcd_scanner.py --help
Usage: fcd_scanner.py: [options]

Options:
  -h, --help            show this help message and exit
  -d DEV, --device=DEV  Use Alsa DEVICE for FCD access
  -c FREQ, --center=FREQ
                        Center frequency in kHz
  -s SPAN, --span=SPAN  Scanning bandwidth in kHz
  -t ST, --sweep-time=ST
                        Time for one frequency sweep in s
  -g GAIN, --lna-gain=GAIN
                        LNA gain in dB (default 10)
  -p STEP, --step=STEP  Frequency step in kHz (default 25)
  -n N, --pass=N        Number of passes (default 1)
  -o FILE, --output=FILE
                        Write measurements to FILE
  -l, --line-plot       Draw a real-time line plot
  -e, --pers-plot       Draw a real-time persistence plot
Posted by Tomaž | Categories: Code | Comments »

HP EliteBook 8460p

03.12.2011 23:14

With a new job comes a new work laptop. Last week a shiny new Hewlett Packard EliteBook 8460p was waiting for me on my desk at Institute Jožef Stefan.

Plush penguin on a HP EliteBook 8460p

From the outside it's one of the prettier PC laptops and it's hard to say HP industrial designers haven't looked at Apple for inspiration. Aluminum case dotted with small white LEDs, chiclet keyboard, black bezel around the screen, a round HP logo on the back of the display. If you've seen a MacBook Pro you can probably see the similarity. However, good looks don't necessarily mean good design and HP made some weird decisions that I find hard to believe for a machine that costs more than 1600 €.

First of all, I might say quality control seems a bit lacking. Left and right mouse buttons were out of level just enough to look sloppy. The "a" key keeps falling out. There's something wrong with the latches on the docking station since the cracking noise they make when I take the laptop off always makes me cringe. There are also some unfortunate design decisions: each time you pick up the laptop from the table you basically lift it up by the DVD drive door, which I fear is not good for its longevity. The Apple-like LEDs that shine through (laser-drilled?) holes in the aluminum are quite hard to see unless you bend down to the table and look directly at them.

What about the software side? Linux Laptop Wiki has some general information that gives a good overview of Linux support for this laptop's hardware.

Out of the box the disk had all 4 primary partitions already used. Sadly I had to retain the Windows installation, so I only deleted two partitions at the end of the drive that looked like they contained some HP restore and diagnostics software. Debian Squeeze installer then shrunk the remaining NTFS filesystem without further problems and Windows seemed to have survived the operation without any noticeable damage.

Getting the installer to boot however did take some experimenting: the laptop has 4 USB ports and will happily boot off a USB key in any of them. However for some reason all except one on the right with a thunderbolt icon are turned off after the boot. So unless the installation USB key was in that drive, the installer couldn't find the installation media. Funny, since after installation all USB ports work without problems.

To get the Radeon HD 6470M running in xorg I had to install a newer kernel from Squeeze backports (linux-image-2.6.39-bpo.2-amd64) and a newer Radeon driver (xserver-xorg-video-ati 1:6.14.2-1). The card also requires non-free firmware, which is shipped separately in the firmware-linux-nonfree package. Without it you will only get military-grade noise on the LCD panel. For 3D acceleration you also need libdrm-radeon1. With this setup everything seems to work fine except setting the display brightness (there's a kernel bug already reported): manual setup through the sysfs is ignored although the interface is there and I don't even know how to approach the ambient light sensor.

By the way, I've heard complaints about the low quality of the LCD. Mine looks great and makes my EeePC 901 look pretty dim in comparison.

Regarding other periphery, there is not much to say. Wi-Fi works with Intel drivers and requires firmware-iwlwifi. Compared to the Thinkpad monstrosity the dock is only a bunch of hot-pluggable USB devices, which means no additional headaches there. Web-cam for some reason isn't detected automatically and you need to insert uvcvideo kernel module manually for it to work.

The power consumption hovers around 25 watts at idle, which is 10 watts more than when booted up in Windows. With that battery lasts a little bit more than 2 hours. This might have something to do with that kernel PCI Express power consumption bug. Setting power saving profiles on Radeon doesn't affect the battery drain which makes me suspect that power management doesn't work there either. Also, GNOME power manager crashes because of an empty second battery bay. I've written a patch against the version shipped in Debian Squeeze, but I'm not that optimistic it will get applied, since it's now sitting in the bug tracker right next to another patch I've made 3 years ago.

I should also mention the weird phenomenon where the computer freezes for several tens of seconds sometime after boot. There are no kernel messages logged about that and it doesn't seem to affect the running processes. I've seen such freezes on my old Thinkpad and on the EeePC, but they were always connected to IO contention. These freezes occur on an otherwise idle machine and the HDD light remains off, which makes me think they have some other cause. Also, a colleague with the exact same hardware and the latest Ubuntu version isn't seeing this, so I'm guessing it has something to do with my setup.

As you can see, after a week with this machine I have very mixed feelings about it. On one hand the aluminum case gives you a solid feeling. I love the dead simple screwdriver-less access to all the components inside, Linux support is pretty good and of course I don't have any complaints about the performance either. But seriously, shipping a laptop in this price range with a broken keyboard, dock and cheap-looking track pad?

Posted by Tomaž | Categories: Code | Comments »

Plotting a density map

28.11.2011 20:04

Density maps are one of those things I need rarely enough that I forget how I did it last time but also often enough that spending 15 minutes searching on Google and browsing Octave manual seems unnecessary.

So, for my reference and yours, here's the simplest, fastest way I know of producing one on a vanilla GNU/Linux box. Density plot is something Gnuplot doesn't know how to do by itself. So you need to fire up Octave:

octave> [c,x,y] = hist2d(load("foo"), 150, 150); imagesc(x,y,c)

Here, foo is a tab-separated-values text file with two columns: X and Y coordinate of each point. The two numerical arguments to hist2d are the numbers of buckets for each axis. This produces a plot like this by default:

Example density map

As with all Octave plots, you can write the current picture to a file using:

octave> print -dpng foo.png

On Debian you need octave-plot package installed for hist2d to work. See Octave manual for ways to further customize the look.

By the way, you might have noticed that the Y axis is up-side-down on the example plot above. That seems to be a bug in Octave when you only have negative values on the axis and I haven't yet figured out how to work around it.

Update: Running set(gca,'ydir','normal'); after the imagesc command restores the usual orientation of the axes for image plots.

Posted by Tomaž | Categories: Code | Comments »

ARM primer

24.11.2011 15:10

My first somewhat serious look into the ARM architecture was at the CCC Camp, where I attempted to extract the secret signing keys via a buffer overflow exploit in the r0ket. Recently I started working on a bit more serious project that also involves copious amount of C code compiled for ARM and I thought I might give a quick overview of the little important details I learned in the last few weeks.

STM32F103 ARM microcontroller

First of all, targeting ARM is tricky business. As the Wikipedia article nicely explains, you have multiple families (versions) of ARM cores. They are slightly incompatible, since instructions and features have been added and deprecated over time. Recent cores are divided between application, real-time and microcontroller profiles. You find application cores (say Cortex-A9) in iPads, phones and other gadgets that need a fancy CPU with cache, SMP and so on, while microcontrollers obviously omit most of that. The most popular microcontroller profile core right now seems to be Cortex-M3 - where Cortex is a code name for ARM version 7 and M3 stands for the third microcontroller profile. However, this is still a very broad term, since these cores get licensed by different vendors that put all kinds of their own proprietary periphery (RAM, non-volatile storage, timers, ...) around them. So stating the fact that you target Cortex-M3 is much less specific than, say, targeting x86 where you have de-facto standards for at least some basic components around the CPU. That's why the current Linux kernel lists 64 ARM machine types compared with practically just one for x86.

Speaking of Intel's x86, people like to say how it is full of weird legacy quirks, ARM has some of its own. One thing that caught me completely by surprise is the Thumb instruction set. It turns out the that original dream of a clean, simple design with a fixed instruction length didn't play out that well. So ARM today supports two different instruction sets, the old fixed-length one and a new variable-length "Thumb" set that mostly has a one-to-one relation to the old one. In fact, the CPU is capable of switching between instruction sets on function call boundary, so you can even mix both in a single binary.

To add to the confusion, there are two function call conventions, meaning you have to be careful when mixing binaries from different compilers. There's also a mess regarding hardware floating point instructions, but thankfully not many microcontrollers include those. Debian Wiki nicely documents some of the finer details concerning ARM binary compatibility.

All of these issues mean there's a similar state of chaos regarding cross-compiler toolchains. After what seems like many discussions Debian developers haven't yet come to a consensus on what kind flavor to include in the distribution. That means you can't simply apt-get install arm-gcc, like you can for AVR. Embedian provides some cross-compiler binaries, but those are targeted at compiling binaries for ARM port of Linux, not bare-bones systems for microcontrollers. You can build stripped-down binaries with such a compiler, but expect trouble since build systems for microcontroller software don't expect that. From what I've seen the most popular option by far appears to be CodeSourcery, a binary distribution of the GNU compiler toolchain. The large binary blob installer for Linux made my hair stand up. Luckily there's an alternative called summon-arm-toolchain which pieces together a rough equivalent after a couple of hours of downloading and compiling. If this particular one doesn't do the trick for you, there's a ton of slightly tweaked GitHub forks out there.

By the way, GCC has a weird naming policy for ARM-related targets. For instance, CodeSourcery contains arm-elf-gcc and arm-none-eabi-gcc (where arm-elf and arm-none-eabi refer to the --target configure option when compiling GCC). Both will in fact produce ELF object files and I'm not sure what the actual difference is. Some say that it's the ABI (function call convention) and in fact you can't link binaries from one with binaries from the other. However you can control both the ABI and the instruction set at run-time through the GCC's target machine options. Other than that, they seem to be freely interchangeable.

For uploading the software to the microcontroller's flash ROM I'm using the Olimex ARM-USB-OCD with the openocd, which also seems to be a popular option. It allows you to program the microcontroller through JTAG and is capable of interfacing with the GNU debugger. This means you can upload code, inspect memory and debug with single-stepping and break points from GDB's command line in much the same way you would a local process. There are some quirks to get it running though, namely OpenOCD 0.5.0 doesn't like recent versions of GDB (a version that works for sure is 7.0.1).

I think this kind of wraps it up. As always, a reference manual of the particular processor you use at the reach of a hand is a must. When things stubbornly refuse to work correctly it's good to fall back to a disassembled listing of your program (objdump -d) to check for any obvious linking snafus. And, when trust in all other parts of your toolchain fails and sharks a circling ever closer, a trusty LED is still sometimes an indispensable debugging equipment.

Posted by Tomaž | Categories: Code | Comments »

Persistent camera switch

07.09.2011 22:04

In case someone else has been wondering why the integrated camera on the EeePC mysteriously gets switched on sometimes. It's not a sign that someone is spying on you through your netbook's webcam. It turns out it's a feature of the eeepc-laptop module in the recent versions of Linux kernel. I've been noticing this since I upgraded to Debian Squeeze with the 2.6.32 kernel.

The eeepc-laptop: enable camera by default thread on LKML pretty much explains it. The kernel module that provides access to the laptop's power switches for various peripherals got patched so that it unconditionally turns on the camera each time it's loaded. This usually happens at boot, but it took me a while to find that out since I mostly put my computer to sleep and only occasionally reboot it.

Now in my humble opinion it was a pretty bad decision to include this patch in the mainline kernel. Leaving paranoia aside for the moment, turning camera on increases power consumption. The LKML thread addresses that but it appears they didn't get to any certain conclusions about the impact to battery life.

I also find the practice of fixing broken userland in the kernel questionable. The rationale for this patch was that people get confused when the camera is turned off and software reports no cameras on the system. Why is that a problem? If the camera is turned off, it's not there. Period. If a particular userland distribution isn't happy with a camera that is turned off it can fix this with a one-liner in a boot script.

Also the state of the hardware power switches is persistent over reboots. So if someone likes to have a camera switched on at all times, he can switch it on once and it will stay that way. This weird crutch of turning the camera on at boot just makes it confusing when one switch fails to retain its state while all others do.

Reverting this patch is simple, but I'm not going to maintain a custom-compiled kernel just for this - I'm still too happy that Squeeze removed the need for five custom kernel patches for various quirks of this laptop. So now I have a one-liner in a boot script that switches off the camera after the module has been loaded.

Posted by Tomaž | Categories: Code | Comments »

Thunderbird mail header style

01.09.2011 11:45

After I upgraded my laptop to Debian Squeeze, Icedove (Debian's rebranded Thunderbird 3.0.11) developed an annoying problem. The mail header names (from, to, cc, etc.) got nearly invisible on the dark GTK theme I'm using:

Default Thunderbird header style.

After some experimenting with the GTK theme itself I found out that the color used for this text is now actually hard-coded (bug 583197). I should mention that neither GTK Parasite nor Mozilla's DOM inspector were useful in finding the particular style this text is using.

As suggested on the thread above, the color can be corrected by modifying the offending headerName style. Instead of rebuilding the default theme it is however enough to simply add an override to ~/.icedove/<profile>/chrome/userChrome.css:

.headerName {
	color: #333 !important;
	font-style: italic !important;
}

Of course, choose the color and style that matches your theme. Here's how this looks like on mine:

Corrected Thunderbird header style.
Posted by Tomaž | Categories: Code | Comments »