Roku Soundbridge

Last week I stumbled upon a second-hand Roku Soundbridge M1001 network music player, with a nice 280x16 pixel VFD (vacuum fluorescent display.)

I don’t necessarily need another music payer, but I might still patch a long S/PDIF coax to the amplifier on the other side of the room later on. It seems to work pretty well as a music player, indeed.

I was mainly interested in using the VFD to display things like the weather forecasts, syslog warnings, etc.

The great thing about the Soundbridge is that the people that designed it have spent quite some time implementing a nice command set to draw on the display. There are commands for drawing points, rectangles, text in various fonts, etc. Actually everything that you need to use the Roku as a universal display for just about any kind of information that you can think of.

Even though it is not finished yet, as you can see from the image, the Roku already found a prominent place on the wall in my living room.

A bit of pencil and paper design, ugly text files and abuse of netcat later and I ended up with this:

These icons were first designed on graph paper, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1 1 1 1 1 1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
  0
  1               X X
  2               X X
  3       X X             X X
  4       X       X X       X
  5             X X X X
  6           X X X X X X
  7   X X   X X X X X X X X   X X
  8   X X   X X X X X X X X   X X
  9           X X X X X X 
 10             X X X X
 11       X       X X       X
 12       X X             X X
 13               X X
 14               X X
 15

The resulting coordinates I then converted to a file with hardcoded drawing commands like so:

1
2
3
4
5
6
7
point 1 7
point 1 8
point 2 7
point 2 8
point 3 3
point 3 4
and so on...

Some Bash to parse ascii-art icons and dynamically create drawing commands from that was quickly written. I soon realized that that did not scale, though. It also meant that I had to create each and every icon by hand, while lazy people like me rather steal some cute icons from the web: icons designed by people that are more skilled in graphics than me.

I remembered that the PBM image format has an ascii version that is really easy to parse (or generate) and it meant that I could just take any graphics, manipulate it with either Imagemagick or the GIMP, depending how much editing it needs to use it for display on the Roku.

An 1-bit monochrome, ascii formatted PBM file looks like this:

1
2
3
4
5
6
7
P1
# isquared logo
16 16
0000000000000000000000000011100000000011001010000000001100001000000000
0000110000000000000111100000011110000000000000011000000000000001100000
0000000011000000000000001100000000000000110000000000000011000000000000
0011100000000000000000000000000000000000000000

The P1 header tells that this image is 1-bit monochrome, ascii formatted. Then follows a comment on the second line. On the third line it gives the image width and height, so 16x16 pixels in this case. After the coordinates all pixels follow on multiple lines. As far as I know the linebreaks can be made on arbitrarily chosen positions. (At least my PBM handling scripts do not care, they just realign the pixels based on the image width.)

A bit of Bash now parses these files and spits out the equivalent Roku drawing commands, with an optional offset added to them to be able to position icons anywhere on the Roku’s display.

Another neat feature of the Roku is that it also has a blit command with the following syntax:

  blit x1 y1 x y w h            - blits from (x,y,w,h) to (x1,y1)

Of course I had to use this command, so I rewrote my icon drawing script to scroll large PBM files vertically over the narrow display of the Roku. This script should give enough info to do similar things with PBM files and Soundbridges:

pbmscroll.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
!/bin/bash
# pbmscroll.sh - scroll a pbm file line by line over the Roku's display
# Hessel Schut, hessel@isquared.nl, 2013-01-13

echo sketch

cat ${1} | {
  # handles only monochrome ascii images for now
  read magic
  if [[ "${magic}" != "P1" ]]
  then
      echo "Unsupported file format." >&2
      exit
 fi

  # keep skipping comments in the header until
  # image dimensions are read 
  # TODO: sanity checking on dimensions
  xsize="#"
  while [[ "${xsize:0:1}" == "#" ]]
  do
      read xsize ysize
  done

  x=0
  while read line
  do
      # skip comment lines
      if [[ "${line:0:1}" == "#" ]]
      then
          continue
      fi

      # process pixels in current line
      for ((char=0; char <${#line}; char++))
      do
          # allow spaces between pixel data
          if [[ "${line:char:1}" == " " ]]
          then
              continue
          fi

          # draw pixel
          if [[ ${line:char:1} -gt 0 ]]
          then
              echo color 1
          else
              echo color 0
          fi
          echo point ${x} 15

          # align pixels, blit screen up on new image row
          if [[ ${x} -lt $((xsize - 1)) ]]
          then
              ((x++))
          else
              x=0
              echo blit 0 -1 0 0 280 16
          fi
      done
  done
}

The script is meant to be used as a component in a framework using multiple plugins to display various kinds of information on the Roku. To use it by itself, one can just pipe the output to netcat like so:

hessch@turing:~/roku$ ./pbmscroll.sh icons/tree.pbm | \
    nc tube.intra.isquared.nl 4444 > /dev/null

Comments