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 https://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 »

Microcontroller board design tips

20.06.2012 17:52

I've been working with VESNA for a better half of a year now and over time I have come to know some oversights that were made in the original hardware design that make development of software for VESNA unnecessary complicated. Of course, mistakes like these are only obvious in hindsight, so I'm sharing here a few tips that should prevent them in future designs.

Have a JTAG port always accessible. JTAG is what allows you to do any kind of debugging beyond simple printfs. Together with an on-chip debugger and the GNU debugger it makes it possible to debug firmware running on the microcontroller in much the same way as an executable on your PC. You can inspect parts of the CPU's address space, program new firmware right from the debugger and set break and watchpoints. However a JTAG port takes between 4 and 6 pins and many microcontrollers allow you to turn it off and remap other peripherals to those pins.

Relying on the functionality hidden behind JTAG pins is a bad idea and should only be used as a last resort. Doubly so on a board that is meant for multiple purposes and is going to see a lot of software development. VESNA has several peripherals on the core board that can only be used after JTAG is turned off. Needless to say, these are a pain to develop drivers for. This means that people avoid using those parts of the hardware as far as possible and in the cases when the use is unavoidable, the software is badly tested and bugs tends to linger around for longer than for other parts of the system.

Straightforward physical accessibility is also important. On VESNA, JTAG pins are routed through the general-purpose expansion connector and we had several cases where accessing the connector was a simple geometric impossibility. It also means that all expansion boards have to be designed with the debugability of the underlying core board in mind. Having a separate connector would be a much better choice. When designing a board, think how it will be mounted and what kind of expansions will there be in the future. These should not make the debug port inaccessible.

Use a separate serial port for diagnostics and debug messages. The Cortex M3 microcontroller used on VESNA has several hardware UART peripherals, but only one is accessible on a convenient connector, which means that one serial line is used for data transfer as well as random debug messages used during development. This violates the rule of separation, which means that debug messages jumbled up together with data are not a rare occurrence.

Advice regarding accessibility of the JTAG port applies to the diagnostic port as well. VESNA's serial line is available on the connector that is also used for external power. This means that in some configurations the serial line simply can't be connected, making debugging hard. A much better design choice would be to bundle JTAG and a diagnostic serial console on the same connector and leave the power supply separate.

Actually, I have come to learn that special care should be given to accessibility of the circuit in general. It should be possible to run the basic core board in a way that makes it possible to probe most nets and microcontroller pins with an oscilloscope or a logic analyzer. The positioning of the JTAG on the expansion connector on VESNA means that in order to use a debugger you have to use a special break-out debug board which, until a later redesign, used to cover half of the core board, making a part of the circuit inaccessible to a oscilloscope probe without a soldering iron and some wires. When a bug hits that requires you to use a debugger and an oscilloscope you really don't need any additional complications.

In short, design for debugability, both software and hardware. It will make people happier.

Posted by Tomaž | Categories: Digital | 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 »

GOTO 1982

09.06.2012 15:53

Last week the National museum of contemporary history opened the doors to a new temporary exhibition dedicated to the history of computing. While quite a few groups and sponsors were involved in the preparation of this exhibition, GOTO 1982 is also the culmination of efforts of Kiberpipa's computer museum to regroup, reorganize and give one more try at making a community that would do its best to preserve the history of computing in our country.

Wall of Sinclair and Commodore computers at GOTO 1982

Two years ago, things looked quite bleak. The old team pretty much went their separate ways for complicated reasons. Exhibits got scattered around Ljubljana as Kiberpipa and it's mothership organization was struggling with the large pile of old stuff that was taking precious storage space. The permanent exhibition in Kiberpipa's cellar went into an increasing state of disarray.

Apple II GS at GOTO 1982 exhibition

Last spring however at least some of the old disputes were settled and we got a new team together. We also got a sponsor for a proper storage space and spent the rest of the summer tracking where the old collection went and moving it all to the new location - involving lots of manual work, rented vans and forklifts in the process. We cleaned up the small exhibition in Kiberpipa and made it presentable again to the occasional visits from schools and reporters. I gave up on my former role of computer repair man and took care of cataloging our complete collection. We now have a web-based inventory tracking system and fancy QR-code stickers on each piece, with 312 pieces of inventory and 234 unique exhibits in the database. Being able to show a spreadsheet of possible display items goes a long way in presenting a credible case for an exhibition like GOTO 1982.

GOTO 1982 exhibition

I can't say how happy I am that GOTO 1982 turned out as well as it has. It was in no way a small feat and all of us have donated a lot of our time to make it possible. It also gives a spark of hope that one day there will be a permanent place somewhere in Slovenia where you can try out typing on Spectrum's rubber keyboard or listen to the original Prince of Persia theme beep out of the PC speaker.

Posted by Tomaž | Categories: Life | Comments »

Organic display, part 2

02.06.2012 21:06

Here is the follow up to the organic LED display I was reviewing back in February and my recently manufactured Arduino shield for it.

There is not much more to tell about the hardware. I basically went with the design I described in my first post. Display controller is powered from the 3.3 V line supplied by Arduino while the display itself uses a LM2703 step-up converter connected to Arduino's 5 V supply. This micropower switcher is sufficient to power the OLED array, but the reference design proved to be a bit slow to react to fast changes in display current. For instance, with a checkerboard pattern on the display, the supply voltage will drop for almost 1 V when display scans the high-brightness areas and this causes some visible shadowing. If you look closely at the photo below, you can see that the centers of white squares are darker than the corners.

Arduino OLED shield showing a checkerboard pattern

The reference LM2703 design I followed uses a single ceramic 4.7 µF capacitor at the switcher output, so this problem could most likely be fixed by adding some larger output capacitors.

VDDH supply when displaying a checkerboard pattern

Voltage drop on the VDDH line when displaying the 45° checkerboard pattern.

From the software side, SEPS525 controller turned out to be an interesting challenge. Densitron's datasheet warns that you need to correctly program the controller (like pixel driving current and timings) before turning on the high-voltage supply or risk damaging the display. This is somewhat of a gamble, since the SPI interface only allows for one-way communication and except for turning the display on you can't know whether you actually managed to set up SPI correctly. In my case this resulted in a few mishaps where the switcher's coil loudly complained about currents that were probably well beyond display's maximum ratings. Luckily, the display appears to have survived all of them.

SEPS525 datasheet is quite long and vague in places, but once you figure out the SPI protocol and set up the configuration registers correctly the use is quite straightforward: you give it a drawing area (either full screen or a part of it) and burst the pixel data in row-major order while the controller takes care of incrementing the framebuffer pointer and line wrap. Display supports either 6/6/6 or 5/6/5 RGB color formats, however I'm not aware of any microcontroller SPI peripheral that is actually capable of transmitting 18 bit words through SPI. Arduino's certainly isn't, which means you must either sacrifice 2 bits of color depth or bit-bang the SPI protocol which is horribly slow.

Talking about speed, bursting the whole screen worth of data from ATmega328 using hardware SPI through Arduino's library takes around 100 ms. If you want to do some calculations on the pixels (like the checkerboard pattern above) this might quickly become 1000 ms, so don't expect high frame rates. Another problem is that the framebuffer takes 40960 bytes, which is too much to store even a single full-screen image in ATmega328's 32 kB flash. I cooked up a simple RLE-compressor for the example you see below, which approximately halves the size of the stored images for the price of some extra CPU cycles (drawing this particular one takes 180 ms).

Arduino OLED shield showing Preening RD by MochaDelight

Preening RD by MochaDelight

Hardware design and software is available under CC-BY-SA 3.0 and GNU GPL 3 licenses respectively. The repository below contains a SEPS525 driver and an Arduino sketch that demonstrates its use with the three push-buttons that are also on the shield:

https://www.tablix.org/~avian/git/arduino-seps525-oled.git

I have a few of these boards extra. So if you're interested in getting a bare PCB or a kit, please let me know. Be warned though that soldering the OLED connector makes for a good exercise in precision SMD soldering.

Posted by Tomaž | Categories: Digital | Comments »