• Hacking a Sangean HDT-20 tuner

    I’ve been interested in HD Radio for many years, and maintain open-source software for receiving and transmitting HD Radio signals. To verify that the transmit software (gr-nrsc5) is working correctly, I use a Sangean HDT-20 tuner to receive the generated signal.

    The HD Radio standard (NRSC-5) defines various “service modes,” which allow broadcasters to select how much bandwidth they would like to assign to their digital signal, and how that bandwidth should divided up. The standard defines many modes, but in practice almost all FM stations are using either:

    • MP1, which has a total throughput of 99 kbit/s; or
    • MP3, which increases the throughput to 124 kbit/s by widening the digital signal slightly.

    WWWT-FM recently began using MP11, which prompted me to look into this mode more deeply. It builds on top of MP3 by widening the digital signal further, increasing throughput to 149 kbit/s. Someone was kind enough to send me a recording of the WWWT-FM signal, but my trusty Sangean HDT-20 could not decode the additional subchannel. Nor could any of the other receivers we tried. A test signal generated by gr-nrsc5 didn’t work either, but I couldn’t be certain whether its MP11 implementation was correct.

    After searching the web, I found a possible explanation in the Si468x Programming Guide:


    This property Enables MP11 mode support. If MP11 support is disabled using this property the receiver will fall back to MP3 mode of operation when tuned to a station that is transmitting the MP11 subcarriers.

    Default: 0x0000

    Most HD Radio receivers use Si468x demodulator chips, and the Sangean HDT-20 is no exception. For reasons unknown, the chip does not decode the extra subchannel unless the receiver specifically opts in by switching on the HD_SERVICE_MODE_CONTROL_MP11_ENABLE property. MP11 is the only service mode that gets this special treatment, so I can only speculate that perhaps a problem with an implementation of MP11 was discovered after it was standardized.

    I wondered whether it might be possible to coax the HDT-20 into receiving MP11 by switching on the HD_SERVICE_MODE_CONTROL_MP11_ENABLE property somehow. I opened up the receiver and found that the interesting bits were hidden inside an RF shield, but there was also a 10-pin header that looked suspiciously like a JTAG debug port.

    interior view of a Sangean HDT-20 showing the location of the JTAG port

    I didn’t know much about JTAG, so I read over wrongbaud’s JTAG guide and installed JTAGenum on a Raspberry Pi to determine the JTAG pinout. It worked, and I was able to fetch the ID code register: 0x6974403f. This told me the manufacturer (0x01f = Atmel) and part number (0x9744). I made a few attempts to go further, but it became apparent that things would be difficult without using Atmel’s debugging hardware & software. So I bought an Atmel-ICE and installed Microchip Studio on a Windows machine.

    I looked through Microchip Studio’s device definition files, and found that part number 0x9744 corresponds to the ATxmega192A3 and ATxmega192A3U microcontrollers. With that information in hand, I was able to probe the device and fetch its memory map:

    C:\Users\Clayton\Documents>atprogram -t atmelice -i jtag -d ATxmega192A3 info
    Firmware check OK
    Tool atmelice has firmware version: 01.00
    Target voltage: 3.20 V
    Device information:
    Name:       ATxmega192A3
    JtagId:     0x6974403f
    Revision:   G
    CPU arch.:  AVR8_XMEGA
    Signature:  0x1e9744
    Memory Information:
    Address Space    StartAddress            Size
    prog                      0x0         0x32000
      APP_SECTION             0x0         0x30000
      APPTABLE_SECTION    0x2e000          0x2000
      BOOT_SECTION        0x30000          0x2000
    data                      0x0          0x6000
      IO                      0x0          0x1000
      MAPPED_EEPROM        0x1000           0x800
      INTERNAL_SRAM        0x2000          0x4000
    eeprom                    0x0           0x800
    signatures                0x0             0x3
    fuses                     0x0             0x6
    lockbits                  0x0             0x1
    user_signatures           0x0           0x200
    prod_signatures           0x0            0x34
    FUSEBYTE5 (0b11100101 <-> 0xe5):
       BODACT        0x2
       EESAVE        0
       BODLEVEL      0x5
    FUSEBYTE4 (0b11110010 <-> 0xf2):
       RSTDISBL      1
       STARTUPTIME   0x0
       WDLOCK        1
       JTAGEN        0
    FUSEBYTE2 (0b11111110 <-> 0xfe):
       BOOTRST       1
       BODPD         0x2
    FUSEBYTE1 (0b00000000 <-> 0x00):
       WDWPER        0x0
       WDPER         0x0
    FUSEBYTE0 (0b11111111 <-> 0xff):
       JTAGUSERID    0xff
    LOCKBITS (0b11111111 <-> 0xff):
       BLBB          0x3
       BLBA          0x3
       BLBAT         0x3
       LB            0x3

    And then extract the firmware:

    C:\Users\Clayton\Documents>atprogram -t atmelice -i jtag -d ATxmega192A3 read -fl -o 0x0 -s 0x30000 --format bin -f app_section.bin
    Firmware check OK
    Output written to app_section.bin

    Back on my Linux machine, I was able to convert the firmware dump to ELF and disassemble it:

    avr-objcopy -I binary -O elf32-avr app_section.bin app_section.elf
    avr-objdump -D app_section.elf > app_section.asm

    Since the Si468x Programming Guide has a list of property numbers, I decided to pick a couple (FM_SEEK_BAND_BOTTOM = 0x3100, and FM_SEEK_BAND_TOP = 0x3101) and see whether I could find those numbers in the firmware. I eventually found this interesting code fragment:

       1bfa8:   60 91 ea 3b   lds  r22, 0x3BEA
       1bfac:   70 91 eb 3b   lds  r23, 0x3BEB
       1bfb0:   80 e0         ldi  r24, 0x00
       1bfb2:   91 e3         ldi  r25, 0x31
       1bfb4:   0e 94 c5 88   call 0x1118a
       1bfb8:   60 91 e6 3b   lds  r22, 0x3BE6
       1bfbc:   70 91 e7 3b   lds  r23, 0x3BE7
       1bfc0:   81 e0         ldi  r24, 0x01
       1bfc2:   91 e3         ldi  r25, 0x31
       1bfc4:   0e 94 c5 88   call 0x1118a
       1bfc8:   60 91 e2 3b   lds  r22, 0x3BE2
       1bfcc:   70 91 e3 3b   lds  r23, 0x3BE3
       1bfd0:   82 e0         ldi  r24, 0x02
       1bfd2:   91 e3         ldi  r25, 0x31
       1bfd4:   0e 94 c5 88   call 0x1118a
       1bfd8:   60 e0         ldi  r22, 0x00
       1bfda:   70 e0         ldi  r23, 0x00
       1bfdc:   81 e0         ldi  r24, 0x01
       1bfde:   95 e3         ldi  r25, 0x35
       1bfe0:   0e 94 c5 88   call 0x1118a

    It appears that the function at offset 0x1118a sets a property on the Si468x chip, taking the property number from registers r25 & r24, and the value from registers r23 & r22. So this code sets not only FM_SEEK_BAND_BOTTOM and FM_SEEK_BAND_TOP, but also FM_SEEK_FREQUENCY_SPACING (property 0x3102) and FM_SOFTMUTE_SNR_ATTENUATION (property 0x3501).

    Assuming this code runs at boot, it should be possible to modify the instructions that set FM_SOFTMUTE_SNR_ATTENUATION to instead set HD_SERVICE_MODE_CONTROL_MP11_ENABLE (0x9A00) to 0x0001. The modified instructions are:

       1bfd8:   61 e0         ldi  r22, 0x01
       1bfda:   70 e0         ldi  r23, 0x00
       1bfdc:   80 e0         ldi  r24, 0x00
       1bfde:   9a e9         ldi  r25, 0x9A

    On my Windows machine, I wrote the new instructions into the firmware:

    C:\Users\Clayton\Documents>atprogram -t atmelice -i jtag -d ATxmega192A3 write -fl -o 0x1bfd8 --values 61e070e080e09ae9
    Firmware check OK
    Write completed successfully.

    It worked! After rebooting the HDT-20, I was finally able to receive an MP11 signal.

    While this patch worked, I was worried that failing to set the FM_SOFTMUTE_SNR_ATTENUATION property might cause trouble, so I instead overwrote that code with a jump to an unused memory location:

       1bfd8:   0d 94 00 78   jmp  0x2f000

    At that location, I placed code to set both FM_SOFTMUTE_SNR_ATTENUATION and HD_SERVICE_MODE_CONTROL_MP11_ENABLE, then jump back:

       2f000:   60 e0         ldi  r22, 0x00
       2f002:   70 e0         ldi  r23, 0x00
       2f004:   81 e0         ldi  r24, 0x01
       2f006:   95 e3         ldi  r25, 0x35
       2f008:   0e 94 c5 88   call 0x1118a
       2f00c:   61 e0         ldi  22, 0x01
       2f00e:   70 e0         ldi  r23, 0x00
       2f010:   80 e0         ldi  r24, 0x00
       2f012:   9a e9         ldi  r25, 0x9A
       2f014:   0e 94 c5 88   call 0x1118a
       2f018:   0c 94 f2 df   jmp  0x1bfe4

    To write the patched code, I ran:

    atprogram -t atmelice -i jtag -d ATxmega192A3 write -fl -o 0x1bfd8 --values 0d940078
    atprogram -t atmelice -i jtag -d ATxmega192A3 write -fl -o 0x2f000 --values 60e070e081e095e30e94c58861e070e080e09ae90e94c5880c94f2df

    If needed, the original code could be restored like so:

    atprogram -t atmelice -i jtag -d ATxmega192A3 write -fl -o 0x1bfd8 --values 60e070e0
    atprogram -t atmelice -i jtag -d ATxmega192A3 write -fl -o 0x2f000 --values ffffffffffffffffffffffffffffffffffffffffffffffffffffffff

    Now that I was comfortable modifying the firmware, I decided to have some fun with it. Why not change the bootup logo? After digging through the firmware dump, I found the bitmap at offset 0x1ca1 and was able to decode and display it with Python:

    from PIL import Image
    with open("app_section.bin", "rb") as f:
        data =
    offset = 0x1ca1
    width, height = 128, 64
    len_bytes = width * height // 8
    image_data = data[offset:offset + len_bytes]
    img ='1', (width, height))
    for row in range(height // 8):
        for col in range(width):
            pixels = image_data[row*width + col]
            for r in range(8):
                img.putpixel((col, row*8 + r), (pixels >> (7-r)) & 1)

    HD Radio logo

    With a bit more Python, I was able to convert my own image into the correct format:

    from PIL import Image
    img ="doge.png")
    pix = img.load()
    width, height = img.size
    image_data = []
    for row in range(height // 8):
        for col in range(width):
            pixels = 0
            for r in range(8):
                pixels |= ((1 if pix[col, row*8 + r][1] == 0 else 0) << (7-r))
    image_data = bytes(image_data)

    And write the bytes to flash:

    atprogram -t atmelice -i jtag -d ATxmega192A3 write -fl -o 0x1ca1 --values fffffffffffff7fbfdfefefdfdfd03fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0eff7fbfcfffffffffffffffffffffffffffffffffffffffffffefdfbfbfdfefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffce31ffffefdfdfdfdfdfdfdfdfefefefefefefefefefefefefffffffffffffffffffffffffffffffffffffffefefefdfbfbf707f7efdfff7fbfdfdfdfdfdfdfdfdfefefefefedeeefefdebd7bf7efdfeff3ff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbdbdbddede1edededee01fffffffffffffffffffffffffffffffffffffffff7807fffffffffffffffffffffffffee1dfbf7ffffff9f6e0e0f1fbfffffffffffffffffffefdfcfcfeffffffffffff7f7fbfbfdfeff7f7ffff877bfdfeffffffffff7f8ff7cff78f7fff8f77778fff7f8ff7cff78f7ffffffffffffffffffffffffffffffffffffffee11ffffffffffffffffffffffffffffffffffffffce39f7fffffffffffffffffffffffffe01ffffffef8f0f0f0f0f0f0f8f8fdfeffffffffff3f1fdfdf1f1f3f7fffffffffffffffffffffffffffffffffffff03fdfeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdfdfdfdfdfdfdf1fdfefefefefefefefefefefeff7f7f7f7f7f7f7c73bfbfbfbfbfbfbfbfbfdfdfdfdfdfdfd00ffff1feff375363737377b7bfdfdfd7d6d8debeaf5ffffffffffffffffffffffffffffffffffffffffffffffffffffffff01feffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7897ebfbfdfeff7fbfbfbfbfbfbfbfbfbf7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00bf7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8778ffffffffff7fbfbfdfdfefefefefefefefdfdfdfdfdfdfbfbfffffffffffffffffffffffffffffffffffffffffffffffffff00fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefdfbf7efefdfdfbfbf7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff


    Sangean HDT-20 bootup screen replaced with a Doge meme

  • Trolling CTF players (again) with gr-paint

    Last week I headed back to Ottawa for the BSides Ottawa conference & CTF. As usual, I put together a series of radio challenges, and Xanthus Security generously provided each team with an RTL-SDR dongle that they could use to receive the mysterious signals floating around the conference area.

    CTF players were asked to imagine they were employees of “Hackers 4 Cash,” a consulting firm hired by pickle farm “Ye Olde Pickles” to hack their competitor, “CyberPickle.” Not surprisingly, CyberPickle relied heavily on radio to automate their operations.

    The first radio challenge was called “Wide Load,” and players were given the following challenge:

    To keep their communications private, CyberPickle is testing out a new wideband communication system on the 902-928 MHz ISM band. Is it possible to intercept the message?

    When tuning to the low end of the band, around 905 MHz, the following signal appeared in the waterfall once every 45 seconds:

    Screenshot of Gqrx, showing "flag{this_is_" in the waterfall

    Clearly that’s the start of a flag, but we need to tune higher to see more. After tuning to 907 MHz and patiently waiting, the next piece of the flag could be seen:

    Screenshot of Gqrx, showing "is_a_very_wi" in the waterfall

    After repeating this process another nine times or so, players would finally reach the end of the flag:

    Screenshot of Gqrx, showing "15a166ff9}" in the waterfall

    Many players asked me whether it’s possible to “zoom out” and see more of the radio spectrum at once. Unfortunately, it’s not possible to do that directly because the RTL-SDR is limited to a sample rate of approximately 2.4 million samples per second, which means that it’s only possible to see a frequency span of 2.4 MHz at a time. (In practice, the usable bandwidth is a bit lower than that due to aliasing; if you look closely at the screenshots above, you’ll see that signals near the edges of the display begin fading out and then “wrap around” to the opposite edge due to the imperfect anti-aliasing filter in the receiver.)

    More expensive receivers can operate at much higher sample rates. For instance, the USRP B200 can receive up to 56 MHz at once, allowing the entire 902-928 MHz ISM band to be recorded:

    Screenshot of Gqrx, showing "flag{this_is_a_very_wide_flag_indeed_c928359da12a4a00e32fa43063e5037256c571a0e75ff2019a6741215a166ff9}" in the waterfall

    To create this challenge, I used ImageMagick to create a large PNG file containing the flag, and then painted that onto the radio spectrum using gr-paint. I’ve published the source code for all my challenges, and the pieces used to generate the “Wide Load” challenge can be found here and here.

  • Inverting the Raspberry Pi Debug Probe's UART pins

    Last week I attended the NorthSec conference & CTF in Montreal. It was a great event, and I had a lot of fun! This year’s conference badge included a neat game where attendees could plug their badges together to earn points and unlock additional LED blinking patterns:

    NorthSec 2023 electronic badges Photo by Simon Carpentier is licensed under CC BY-NC 4.0

    I wanted to reverse engineer the badge-to-badge communication protocol, and soon found out that it was asynchronous serial at 38400 baud, but with inverted polarity. While my Saleae logic analyzer happily decoded the inverted signal, my Raspberry Pi Debug Probe could not. I worked around the problem by building a couple inverters (one for transmit, one for receive) on a breadboard, and putting them between the badge and the Debug Probe. This worked, but it was cumbersome enough that I wanted to find a better solution.

    After searching the web and digging through datasheets, I learned that the RP2040 chip’s GPIO pins can be inverted by setting GPIO control registers (specifically, the INOVER and OUTOVER fields in the GPIO*_CTRL registers). The gpio_set_outover and gpio_set_inover functions in the Raspberry Pi Pico SDK provide a convenient way to set these registers. It only took a couple lines of code to invert the UART pins in the Debug Probe firmware.

    In case you’d like to try this out on your own Debug Probe, I’ve posted the compiled firmware on GitHub.

  • Building challenges for the GRCon22 CTF

    Since 2016, the GNU Radio Conference has held a Capture the Flag (CTF) competition in parallel with its technical track. Secret messages (“flags”) are hidden in radio signals, which players have to find and then submit to a scoring system to earn points. The CTF is my favourite part of GRCon, so when the conference organizers asked whether I’d be willing to organize this year’s competition, I jumped at the opportunity. Luckily, I didn’t have to do it alone: Muad’Dib, Aerospace Corporation, Daniel Estévez, and Yamakaja all stepped up to contribute challenges of their own.

    The event was a phenomenal success. There were 52 challenges, and 71 teams submitted 686 valid flags. Even though the competition period has ended, most of the challenges are still up and playable at

    In this post, I’ll describe how I created my challenges, and how I anticipated they might be solved. If you don’t want any spoilers, stop reading here!

    Signal identification

    Screenshot of Gqrx receiving signals from the "Signal identification" challenge

    This challenge track consisted of 13 flags embedded in 11 signals, all contained in a single SigMF recording. I expected that players might use the Signal Identification Wiki to help identify the signals and find decoding software.

    From left to right, the signals were:

    1. FM-modulated Slow-Scan Television (SSTV). The flag appeared in a QR code within the image.
    2. Narrow-band FM voice.
    3. Automatic Packet Reporting System (APRS).
    4. M17 digital voice.
    5. Wide-band (broadcast) FM. Flags were in the mono audio (L+R) channel, stereo audio (L-R) channel, and Radio Data System (RDS) subcarrier.
    6. POCSAG 1200 bps.
    7. PSK 31.
    8. Upper sideband voice.
    9. AM voice.
    10. Morse Code (CW).
    11. Lower sideband voice.

    This challenge has its origins in a tutorial session I created for the Ottawa Amateur Radio Club in 2014. I later published the source code, and in 2019 I adapted it for use as a CTF challenge at BSides Ottawa. For GRCon22, I added M17, a promising open-source alterative to proprietary digital voice protocols.

    Most of the signals can be received directly within Gqrx, but a few require additional software. To test the challenges, I used the following:

    • SSTV → qsstv
    • M17 → m17-cxx-demod
    • POCSAG → multimon-ng
    • PSK 31 → fldigi

    If you solved the SSTV challenge, you can also receive the SSTV images that the International Space Station occasionally broadcasts on 145.800 MHz!

    Fox hunting

    This challenge was inspired by amateur radio direction finding (also known as radio fox hunting) where competitors run through the woods searching for hidden radio transmitters.

    I built two hidden transmitters (“foxes”) which transmitted Morse code. One ran at approximately 433 MHz, and was hidden at a fixed location in the conference area. The other transmitted at approximately 904 MHz, and was carried around by various conference organizers in their backpacks, making it a moving target. Players had to determine the exact frequency of each transmitter, copy the flag which was included in the Morse code message, and then physically locate the transmitter to read another flag which was printed on it. Here’s a peek inside the hidden transmitters:

    Two hidden transmitters sitting on a table with covers removed

    I built them with Adafruit Feather M0 RFM69HCW Packet Radios, which are available in 433 MHz and 915 MHz versions. These boards are normally used to transmit and receive FSK signals, but they also have an on-off keying mode where the transmitter can be switched on and off using a GPIO pin. That makes it easy to tap out a message in Morse code. Each transmitter is powered by a 2000 mAh lithium cell, which is enough to provide four days of power.

    Gqrx does a fine job of receiving the Morse code, and it’s even possible to read it by eye from the waterfall:

    Gqrx receiving morse code from the 433 MHz hidden transmitter

    Although directional antennas can be helpful to find hidden transmitters, most players got by with omnidirectional antennas. I recommend putting on a pair of headphones and disabling both hardware and software AGC, thus making the audio amplitude directly proportional to the incoming RF signal power. Walking closer to the transmitter will then make the signal louder, and walking away will make it quieter. Once you’re close enough to the signal that the receiver is saturated (and audio begins clipping), reduce the RF input gain and keep searching for a stronger signal. When you get very close and your RF gain is already at a minimum, it may be necessary to switch to a worse antenna or remove the antenna completely. Beware that some things other than distance from the transmitter also affect received signal power. For instance, obstacles may absorb or reflect radio signals.

    Signal to noise

    The start of the flag for "Signal to noise", as viewed in inspectrum

    In this challenge, the start of a spectrum-painted flag is apparent when the signal is viewed in inspectrum, but as time progresses the signal narrows in frequency, widens in time, and is engulfed by an ever-increasing amount of noise. By playing with the “FFT size”, “Power max”, and “Power min” settings it is possible to read off the first half of the flag: flag{a4146a8247. But the remainder is impossibly difficult to read.

    Fortunately, Gqrx allows larger FFT sizes and finer control over the FFT rate, which is just barely enough to read off the rest of the letters:

    The middle of the flag for "Signal to noise", as viewed in Gqrx The end of the flag for "Signal to noise", as viewed in Gqrx

    By stitching these parts together, we get the complete flag: flag{a4146a8247fa439d6879}.

    To make this challenge, I used gr-paint to generate a rectangular spectrum-painted image, then passed this through a Polyphase Arbitrary Resampler block with progressively increasing resampling rate, and added noise from a Gaussian noise source with progressively increasing amplitude. A Python script dynamically adjusts the parameters of the resampler and noise source after each line from the rectangular image is processed.

    Never the same color

    The name of this challenge hints at NTSC, an analog television standard. Engineers jokingly referred to it as “Never The Same Color” because its colour accuracy was sometimes poor.

    The challenge consisted of an NTSC signal containing seven flags. One was in the video, four were in the audio (mono, stereo, second audio program, and PRO subcarrier), and two were in EIA-608 closed captions (channels CC1 and CC3). One twist was that the video flag only appeared once every 176 frames. The other frames contained a decoy. (If you’re curious, scan the QR code in the image below to see what it was!)

    To produce the signal, I made some improvements to the NTSC signal generator from my SDR examples repository, and tested with a television set. In fact, every flag except for the PRO (professional) subcarrier can be received by an ordinary television set:

    A television set receiving an NTSC signal and displaying a flag

    Many players found the flags this way, piping the signal into a nearby television. (Even the television sets in guest rooms at the conference hotel could be coaxed into receiving NTSC.) But I was very impressed by Daniel Estévez, who built his own NTSC demodulator in a Jupyter notebook!

    Shall we play a game?

    This was my favourite challenge, and I had a lot of fun building it.

    The challenge description asked the player to transmit an APRS packet at 903.5 MHz, with their team name as the source address and “new” in the comment field. A response would then arrive somewhere in the 900 MHz ISM band. In fact, it arrived at 926 MHz in the form of a spectrum-painted rules page for a variation of Wordle called “SDRdle”:

    A Gqrx waterfall showing spectrum-painted text: "Guess the SDRdle in 6 tries. Each guess must be a valid 5-letter word. Transmit an APPRS packet to submit. After each guess, the color of the tiles will change to show how close your guess was to the word."

    All the player had to do at this point was follow the instructions and transmit further APRS packets containing their guesses:

    A Gqrx waterfall showing a spectrum-painted Wordle board, with "ATONE" as the guessed word A Gqrx waterfall showing a spectrum-painted Wordle board, with "ATONE" and "FLAIR" as the guessed words A Gqrx waterfall showing a spectrum-painted Wordle board, with "ATONE", "FLAIR", and "CAULK" as the guessed words. A message instructs the player to contact @argilo to get their flag.

    To test the challenge, I used Dire Wolf to generate APRS packets and place them in WAV files:

    echo "ARGILO>WORLD:>new" | gen_packets -r 48000 -o aprs.wav -

    I then made a simple flow graph to FM-modulate them and transmit them on a HackRF.

    The challenge server received APRS packets using rtl_fm piped into Dire Wolf, generated game board images using the Python Imaging Library, and transmitted them using gr-paint.


    Source code for all of the above challenges can be found in my grcon22 GitHub repository. I’ve released the code under the GPL so that they can be adapted and used for other purposes. If you use them for an event of your own, I’d love to hear about it!

    I hope players had as much fun solving the challenges as I did creating them.

  • Building a frequency hopping CTF challenge

    For this year’s BSides Ottawa CTF, I built a number of software-defined radio challenges. (More about the CTF can be found in my previous post). One of my favourites was “Hopping along”, a four-part frequency hopping challenge.

    When players tuned to 922.125 MHz, they were greeted with a narrow-band FM signal: “This is VE3IRR. The first flag is tango…” And then the signal hopped down to 922.025 MHz. Tuning there would reveal some more letters of the flag: “…victor echo uniform golf whiskey tango papa papa…” Next the signal hopped up to 922.450 MHz, providing the end of the flag: “…kilo sierra hotel delta victor tango charlie.” Of course, you’d invariably miss some of the letters while tuning from one frequency to the next. But since the signal repeated about once per minute, you could camp out on any one of the three frequencies and wait for the piece you were missing to be transmitted again. Players were awarded with 50 points for putting together the three pieces.

    Then the problem got harder. Part two (worth 100 points) was similar, except that the signal hopped once per second. This challenge could be completed in a similar fashion, as long as you had a lot of patience. Part three (worth 150 points) had 5 hops per second, and part four (worth 200 points) had 50 hops per second! Clearly these were too hard to be solved by hand, and so a better approach was needed.

    Here’s how things looked on the waterfall, with part one at the bottom and part four at the top:

    frequency hopping waterfall

    There are several ways to approach this problem, but the end goal is always the same: to remove the hopping component from the signal so the audio can be demodulated.

    My favourite approach is to take advantage of aliasing. Usually aliasing is a bad thing, because it causes two or more input frequencies to map to the same output frequency, making them indistinguishable. But in the case of a frequency hopping signal, it would actually be helpful if all the channel frequencies were mapped into a single one! To make this happen, all we need to do is sample the signal at some integer multiple of the channel spacing, then downsample the signal by keeping one out of every n samples, where n is the ratio of the sample rate to the channel spacing.

    In this case, the channel spacing is 25 kHz, so we can sample the signal at 2 MHz and keep one out of every 2,000,000 / 25,000 = 80 samples. GNU Radio provides a “Keep 1 in N” block to do exactly that. We can then increase the sample rate back to a more convenient 96,000 samples per second and run it through an FM demodulator:

    solution 1 flowgraph

    One disadvantage of this approach is that the noise in all the channels is combined. But as long as the signal-to-noise ratio is high and only a single channel is transmitting at a time, that’s not a problem. This receiver works beautifully, and all the flags can easily be heard.

    Another approach is to demodulate the entire band as if it was a single FM signal. This will result in a step function being added into the audio signal. Since this step function is mostly a DC signal, we can remove it with a DC Blocker (a special type of high-pass filter):

    solution 2 flowgraph

    This mostly works, but a noisy “pop” bleeds through the filter every time a hop occurs. In part four this results in a loud buzz at 50 Hz, but the flag can still be heard.

    A third approach, which a friend of mine came up with during the competition, is to use a fast Fourier transform to detect which channel is active, and use that information to shift the input signal up or down in frequency so as to map the active channel’s frequency to zero. Here I’ve used an Argmax block to detect which FFT bin contains the most energy, a VCO (voltage controlled oscillator) block to generate a signal whose frequency is the negative of the active channel’s offset, and a Multiply block to combine the VCO with the input signal, shifting the frequency up or down as required:

    solution 3 flowgraph

    This flow graph provides a very clean output signal, and would work well even if the signal-to-noise ratio was lower.

    In case you’re curious, here’s the GNU Radio flowgraph I used to create sample files for each of the four parts of the challenge. The Vector Source and Repeat blocks generate a random step function, and the VCO and Multiply blocks shift the FM signal up or down in frequency in proportion to the step function.

    transmit flowgraph

    In the end, 16 teams solved part one, four got part two, and two teams got all four parts.

  • Trolling CTF players with gr-paint

    BSides Ottawa took place on November 28 & 29, and this year’s CTF was the biggest ever! 200 players showed up, and organized themselves into 35 teams. I volunteered to create a radio track with 24 flags, as well as a crypto track with four flags. Thanks to a generous donation from Xanthus Security, each team received an RTL-SDR dongle which could be used to solve the radio challenges.

    My favourite radio challenge was called “Waterfall”. When players tuned to 924.5 MHz, they saw the BSides Ottawa logo painted onto the waterfall, followed by the start of a flag:

    Gqrx screenshot 1

    At this point it seemed as though you just had to patiently wait for the rest of the flag to scroll by. But as time went on, the letters in the flag got smaller, and smaller, and smaller:

    Gqrx screenshot 2

    By the end, the letters were much too small to read in Gqrx, even when the FFT rate was increased to the maximum of 60 fps!

    Fortunately, there are other tools which are designed for offline signal analysis, and which allow the user to have a much closer look at short, bursty signals. My favourites are Inspectrum and Baudline. After capturing the signal to a file with Gqrx’s “Record and play I/Q data” button, it was easy to read off the tail end of the flag with Baudline:

    Baudline screenshot

    So how did I build this challenge? I needed two things: a way to distort an image so it would become thinner and thinner at one end, and a way to paint that image onto the radio spectrum.

    To produce the distorted image, I used ImageMagick’s FX special effects image operator, which allows the user to define an arbitrary mapping between input pixels and output pixels. After some experimentation, I found that transforming the y axis using an exponential function worked best:

    convert \
      \( \
        -background White \
        -gravity Center \
        -pointsize 400 \
        label:flag\{look_closer_a4146a8247fa439d6879\} \
        -rotate 270 \
      \) \
      bsides-ottawa-logo.jpg \
      -append \
      -crop 50x100%-30+0 \
      -gravity North \
      -extent 100%x200% \
      -fx "xx = i; yy = ln(j/7978/2 * (exp(5)-1) + 1) / 5 * 7978; v.p{xx,yy}" \

    Painting the resulting image onto the spectrum was easy, thanks to gr-paint, a GNU Radio module written by Ron Economos (a.k.a. @drmpeg). This module takes an image file as input, and uses an inverse FFT to map each row of pixels into a set of OFDM carriers with the corresponding amplitudes.

    It was a joy to watch players copying down the start of the flag, only to realize they would have to work harder to get the rest. The first person to solve the problem was my friend and former colleague Serge Mister from Entrust Datacard’s “Reverse Solidus” team. By the end of the competition, another 12 teams had solved it.

  • Tracking down a water leak with rtlamr

    When my water bill arrived a couple weeks ago, I noticed it was higher than usual. I suspected a leaky appliance, but wasn’t sure what it might be.

    I was already aware that Ottawa’s water meters use the ERT protocol, which can be received using an RTL-SDR dongle and rtlamr. I installed the program on an old laptop, and stored its output in a file with rtlamr | tee usage.txt. I checked my meter number and ran tail -f usage.txt | grep 12345678 to confirm I was receiving packets from it. Fresh packets were arriving every few minutes. After a few hours it became apparent that the resolution of the readings was 0.05 m³, and that the reading only changes once per hour, on the hour.

    With this information in hand, I put together a Python script to extract my meter’s readings from the file, keep the first reading from each hour, and plot the results with Pyplot:

    #!/usr/bin/env python3
    import matplotlib.pyplot as plt
    import dateutil.parser
    import re
    MY_ID = 12345678
    regex = re.compile(r"{Time:(.*) SCM:{ID:\s*(\d*) .* Consumption:\s*(\d*) .*")
    times = []
    usages = []
    last_time = None
    for line in open('usage.txt'):
        result = regex.match(line)
        if not result:
            print("Error parsing line:")
        id = int(result[2])
        if id != MY_ID:
        time = dateutil.parser.parse(result[1])
        measurement_time = time.replace(minute=0, second=0, microsecond=0)
        consumption = int(result[3]) / 100
        if measurement_time != last_time:
            last_time = measurement_time
    plt.figure(figsize=(14, 9))
    plt.plot(times, usages)

    Here’s the result after a week collecting packets:

    Pyplot output showing a week of water usage

    During the first few days, I observed that water was consumed at about 0.05 m³ every five hours even when I was away from home, suggesting that the leak was about 10 litres per hour. I turned off the input values to my toilets, and the next day the reading stayed constant all day. The flappers in two of the toilets had warped with age, and replacing them brought water consumption back to normal.

    Of course, I could have just run down to the basement now and then to read the meter, but where would the fun be in that?

  • Reverse engineering a ceiling fan

    Tonight I was visiting a friend of mine, and noticed a strange looking switch on the wall. My friend explained that it was a wireless controller for his ceiling fan. Since we’re both radio geeks, and I happened to have my BladeRF with me, I got the idea to reverse engineer it.

    The first step was to figure out what frequency the controller was transmitting on. The BladeRF makes that a fairly easy task, since it has a bandwidth of 28 MHz. I fired up gqrx to get a nice waterfall view of all that bandwidth. My first guess was that the signal might be on the 902-928 MHz band, and sure enough, I spotted a signal popping up at 911.24 MHz whenever I pressed a button on the controller. But it was quite weak, which led me to suspect it might be a harmonic. Indeed, when I tuned lower I found a very strong signal at 303.747 MHz, and I could easily detect it from across the room.

    The next step was to check what modulation scheme the controller used. Most simple devices like this are using either on-off keying or frequency-shift keying. Zooming in on the signal in gqrx, I saw only a single peak, which suggested on-off keying.

    I knew my trusty RTL-SDR dongle would be more than capable of receiving and demodulating the signal, so I threw together a very simple GNU Radio flow graph to show me the amplitude of the 303.747 MHz signal over time:


    Here’s what I saw on the scope, once I set it to trigger on a rising edge and pressed the “light” button on the ceiling fan controller:


    The transmission was short enough that I could just read the bits off visually: 1011011001011001001001001001001001011. And by measuring the time from the start to the end of those bits, I worked out that the symbol rate was about 3211 baud.

    In fact, all the buttons generated very similar 37-bit patterns:

    off:   1011011001011001001001001001001011001
    low:   1011011001011001001001001011001001001
    med:   1011011001011001001001011001001001001
    high:  1011011001011001001011001001001001001
    light: 1011011001011001001001001001001001011

    The bits were repeated for as long as a button was held, with about another 37 bits worth of zeroes between each repetition.

    Given this information, it was trivial to build a flow graph to transmit an on-off keying signal using the BladeRF:


    My first attempt was unsuccessful, but it turned out the problem was just that the output gain wasn’t set high enough. Bringing it up to about 15 dB was sufficient to reliably control the ceiling fan!

    The whole reverse engineering project took only about a half an hour, which really demonstrates the power of software-defined radio.

    I’ve already added the receiver and transmitter to my sdr-examples repository on Github:

    Receiver: ceiling_fan_rx.grc
    Transmitter: ceiling_fan_tx.grc

    Update: Looking at the bit patterns above, it is apparent that the bits come in groups of three: either 001 or 011. Presumably, 001 represents a baseband 0, and 011 represents a baseband 1. That is, a narrow pulse represents a zero and a wide pulse represents a one. That would make the baseband bit patterns as follows:

    off:   0110100000010
    low:   0110100001000
    med:   0110100010000
    high:  0110100100000
    light: 0110100000001
  • Digital amateur TV on 70cm, 33cm and 23cm

    I love my BladeRF! It’s a very versatile SDR transceiver, and I’ve used it to receive and transmit all sorts of signals. Most recently I got it transmitting DVB-T digital television signals on the amateur radio bands, with my trusty NooElec TV28T serving as the receiver. (It is a TV tuner, after all, so why not use it as one for once?) In this post, I’ll show you how to replicate what I’ve done.

    First off, you’ll need two laptops running Linux: one to transmit, and one to receive. The transmit laptop needs to have the latest version of GNU Radio installed. If you’re running Ubuntu, the easiest way to get that done is to use OZ9AEC’s package archive. At a command prompt, run the following:

    sudo add-apt-repository ppa:gqrx/snapshots
    sudo apt-get install gnuradio gnuradio-dev gqrx libboost-all-dev libcppunit-dev swig liblog4cpp5-dev

    Once that’s done, you’ll need to install YO3IIU’s DVB-T package for GNU Radio:

    git clone
    cd gr-dvbt
    mkdir build
    cd build
    cmake -DCMAKE_INSTALL_PREFIX=/usr ../
    sudo make install
    sudo ldconfig
    cd ..

    Next, grab my collection of SDR examples:

    git clone

    Included in that collection is, a script written by W6RZ that lets you transmit DVB-T from the command line using a BladeRF. Since amateur stations typically operate at much lower power than commercial broadcasters, I’ve modified it to use the lowest available bit rate, which should maximize the distance at which the signal can be received. (If you want to experiment with higher bit rates, you can change the “channel_mhz”, “mode”, “code_rate”, “constellation” and “guard_interval” variables. You’ll also need to adjust the mux rate of your transport stream, which can be calculated using W6RZ’s dvbrate.c.) The script is configured to transmit at a centre frequency of 441 MHz, so be sure to attach a suitable 70cm antenna to your BladeRF’s TX port before transmitting.

    The script expects to be given an MPEG transport stream as input. Fortunately, we can produce one in real time using avconv. It can record video from the laptop’s webcam and audio from the laptop’s microphone, and encode them into a suitable transport stream. To let avconv and talk to each other, we’ll create a fifo:

    mkfifo in.fifo

    Then we launch and tell it to read from the fifo:

    sdr-examples/ in.fifo

    You’ll see some output, but nothing will be transmitted yet because no data is arriving in the fifo. To fix that, open a second terminal window and run avconv like so. Be sure to replace XXXXXX with your own call sign, which will be displayed in the lower right corner of the video.

    avconv -f alsa -i pulse -f video4linux2 -s 640x480 -i /dev/video0 -vf drawtext=fontfile=/usr/share/fonts/truetype/freefont/FreeSerif.ttf:text="XXXXXX":x=440:y=420:fontsize=48:fontcolor=white@0.6:box=1:boxcolor=black@0.2 -vcodec mpeg2video -s 640x480 -r 60 -b 4000000 -acodec mp2 -ar 48000 -ab 192000 -ac 2 -muxrate 4524064 -mpegts_transport_stream_id 1025 -mpegts_service_id 1 -mpegts_pmt_start_pid 0x1020 -mpegts_start_pid 0x0121 -f mpegts -y in.fifo

    You may need to install additional packages so that avconv has access to all the codecs it needs. If all goes well, your two terminal windows should look like this:



    Now, over to the receiving laptop, which will use an RTL-SDR dongle to pick up the signal. Since support for the RTL2832 chip was only recently added to the Linux kernel, you’ll want to be running a recent Linux distribution such as Ubuntu 13.10. Make sure you have vlc installed:

    sudo apt-get install vlc

    Then launch vlc like so:

    vlc dvb://frequency=441000000:bandwidth=6

    If all goes well, you’ll see your video and hear your audio!


    Now that you’ve succeeded on the 70cm band, you may want to try this on the 33cm and 23cm bands as well. Unfortunately, the Linux drivers for the RTL-SDR dongle currently limit its maximum frequency to 862 MHz, a bit below the 33cm band. Until the drivers get updated (I’ve already submitted a patch request), you can work around the problem by patching the kernel modules on your receiving laptop using the script in my sdr-examples repository:

    sudo sdr-examples/

    If everything worked correctly, the script should print out “Success!” twice. If you saw that, then reboot, and you should now be able to tune all the way up to 1750 MHz. On the transmitting laptop, change the “center_freq” variable to 913000000 for 33cm or 1279000000 for 23cm, put an appropriate antenna on your BladeRF’s TX port, and fire up and avconv again. On the receiving laptop, fire up vlc again, putting the appropriate value in for the “frequency” parameter.

    In my experiments, I found that the BladeRF put out the most power on the 33cm band. I was able to receive the signal all around the house, using a rubber duck 33cm antenna on the BladeRF and the RTL-SDR dongle’s stock antenna. I’ve had a QSO with VA3DGN on 70cm. To get the signal beyond my house, I hooked the BladeRF up to a Down East Microwave 70cm 25 watt power amplifier.

    Have fun with DVB-T! I’d love to hear back if you make any contacts.

  • Tracking planes for $20 or less

    My new favourite toy is a cheap $20 USB TV tuner. It’s made to receive DVB-T signals, which aren’t even used in North America. So what use could I possibly have for it?

    Back in February, Linux kernel developer Antti Palosaari discovered that certain USB TV tuners can be configured to send the raw, unprocessed radio signal straight to the computer for decoding in software. (They use this mode when tuning FM or DAB radio signals. Think of it as the Winmodem approach to radio.) Palosaari realized that by running the right software, almost any radio signal could be received by these tuners. Not long thereafter, the RTL-SDR project was born, allowing these tuners to be used in Linux.

    I should note that receiving (and transmitting) radio signals in software is nothing new. Software-defined radio has been around for years, but the hardware required (such as the Ettus Research USRP has generally been expensive. The availability of a $20 software-defined radio receiver has truly opened up the world of radio to anyone who takes the time to learn.

    Since getting my hands on a compatible TV tuner, I’ve been able to listen to police radio, pager networks, garage door openers, air traffic control, and lots more. I recently tweeted that I had succeeded in tracking the aircraft in my area by using my TV tuner as an ADS-B receiver and feeding the output into Google Earth. This caught the interest of a pilot friend of mine, so I thought I’d put together a tutorial for anyone interested in capturing these signals. Although the tutorial is specific to ADS-B, keep in mind that the software tools (and in particular GNU Radio) can be reconfigured to tune in virtually any radio signal.

    So let’s get started!

    1. Purchase a USB TV tuner based on the Realtek RTL2832U chip. For best results, choose one that uses the Elonics E4000 tuner, which will let you tune in the widest range of frequencies, from 64 to 1700 MHz. The OsmoSDR site has a list of supported hardware to get you started. I chose the Newsky TV28T tuner, which I purchased from Aliexpress. (I paid 40 USD for two tuners, shipping included.)
    2. If you’re not running it already, download and install Ubuntu Desktop 12.04 LTS. I would recommend using the 64-bit version.
    3. Install all the available Ubuntu software updates using Update Manager and restart.
    4. Download, build and install GNU Radio using the build-gnuradio script. This can be done in a terminal window by running the following commands:
      cd ~
      mkdir build-gnuradio
      cd build-gnuradio/
      chmod a+x ./build-gnuradio

      Note that GNU Radio is quite a large piece of software and has a lot of dependencies, so the install process can take a long time.

    5. Download, build and install gr-air-modes. This is the piece of software that knows how to decode the ADS-B signals that many planes transmit. In a terminal window, run the following commands:
      cd ~
      git clone
      cd gr-air-modes
      cmake .
      sudo make install
      sudo ldconfig
    6. Plug in your TV tuner, and check whether you can receive ADS-B traffic by running the following in a terminal window: --rtlsdr

      If it works, you should see output like the following:

      (-42 0.0000000000) Type 11 (all call reply) from c0636c in reply to interrogator 0 with capability level 6
      (-41 0.0000000000) Type 17 BDS0,5 (position report) from c078b2 at (45.199942, -75.541590) at 30050ft
      (-39 0.0000000000) Type 11 (all call reply) from c078b2 in reply to interrogator 0 with capability level 6
      (-39 0.0000000000) Type 17 BDS0,9-1 (track report) from c078b2 with velocity 443kt heading 259 VS 1664
      (-40 0.0000000000) Type 17 BDS0,5 (position report) from c078b2 at (45.199616, -75.544069) at 30075ft
      (-42 0.0000000000) Type 17 BDS0,5 (position report) from c078b2 at (45.199265, -75.546504) at 30100ft

      We’re already seeing some GPS coordinates and altitudes! Press CTRL-C to stop it for now. If you don’t see any traffic, try going outside for better reception.

    7. To see the output in a more convenient form, we’ll use Google Earth. Download the 64-bit .deb version from the download page, and open the file to run the installer.
    8. For nicer-looking fonts in Google Earth, install the xfonts-75dpi and xfonts-100dpi packages by running the following in a terminal window:
      sudo apt-get install xfonts-75dpi xfonts-100dpi

      Then log out and log back in so the new fonts will get loaded.

    9. Launch Google Earth.
    10. If Google Earth fails to launch, it may be because it can’t find libGL. (This happened on one of my two laptops.) To fix it, run the following command in a terminal window:
      sudo ln -s /usr/lib/i386-linux-gnu/mesa/ /usr/lib/
    11. Run again, this time telling it to write its output to a KML file, the format used by Google Earth. In a terminal window, run the following: --rtlsdr --kml=planes.kml
    12. In Google Earth, select “Network Link” from the “Add” menu. Enter “Planes” in the “Name” field, then click the Browse button next to the “Link” field and choose the “planes.kml” file in the file chooser. Click on the “Refresh” tab and set a time-based refresh to occur periodically with a frequency of 5 seconds. Click “OK”, then zoom in to your location. With any luck, you should see some planes start to appear and move around!
    13. To see more details about a plane, click the “X” that appears on the map. Or go to the “Places” section in the left sidebar and expand “Planes” and “Aircraft locations”. Here’s a screenshot of Air Canada flight 839 coming in for a landing at YOW, with several more planes at cruising altitude in the background: Screenshot of gr-air-modes in Google Earth

    I hope you find this tutorial useful, and that you’ll do more exploring with software-defined radio once you’ve succeeded in watching planes!

  • Moving from Tomboy to Gnote in Ubuntu 12.04

    Gnote in the tray

    Yesterday I updated from Ubuntu 10.04 to 12.04. As usual, I did a completely fresh install, only copying over the things I still need. Tomboy is at the top of that list, so I copied over my ~/.local/share/tomboy/ directory. I read that Gnote is now the preferred replacement for Tomboy, so I installed it and was pleased to see that it read in my Tomboy notes automatically. But it didn’t put an icon in my tray, and that was my favourite Tomboy feature. To get the tray icon back, I did the following:

    Fisrt, I added gnote to the systray whitelist:

    gsettings set com.canonical.Unity.Panel systray-whitelist "['JavaEmbeddedFrame', 'Wine', 'Update-notifier', 'gnote']"

    Next, I set Gnote to auto-start:

    mkdir ~/.config/autostart
    cp /usr/share/applications/gnote.desktop ~/.config/autostart/
    chmod u+x ~/.config/autostart/gnote.desktop

    Finally, I turned on the tray icon in Gnote itself: Edit → Preferences → Use Status Icon. After logging out and back in, Gnote started up in the tray just the way Tomboy used to.

  • Using the Raspberry Pi's serial port

    The stock Debian image for the Raspberry Pi uses the UART as a serial console. I was able to connect to it from my Ubuntu laptop via my 3.3-volt USB FTDI TTL-232 cable. I connected Raspberry Pi’s ground pin to the ground pin of the FTDI, the Rasberry Pi’s TX pin to the FTDI’s RX pin and vice versa. (The Raspberry Pi’s pinout is available here.) Then on my Ubuntu laptop I installed minicom (sudo apt-get install minicom) and fired it up with:

    minicom -b 115200 -o -D /dev/ttyUSB0

    After typing in a username, I got a password prompt and was able to log in. Also, the serial console allowed me to see all the kernel output during boot, which could be handy someday.

    But I wanted to use the Raspberry Pi’s UART for my own purposes, not as a serial console. To achieve that, I did the following.

    First, I made a backup of the /boot/cmdline.txt file, which contains the kernel parameters:

    sudo cp /boot/cmdline.txt /boot/cmdline_backup.txt

    Then I edited it:

    sudo vi /boot/cmdline.txt

    Originally it contained:

    dwc_otg.lpm_enable=0 rpitestmode=1 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait

    I deleted the two parameters involving the serial port (ttyAMA0) to get the following:

    dwc_otg.lpm_enable=0 rpitestmode=1 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait

    I rebooted (sudo reboot) to confirm that kernel output was no longer going to the serial port. But the serial console was still available. So I edited /etc/inittab:

    sudo vi /etc/inittab

    I commented out the following line:

    2:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

    Finally, I rebooted again and confirmed that nothing was touching the serial port anymore. Then, to test it out I installed minicom on the Raspberry Pi:

    sudo apt-get install minicom

    And ran it:

    minicom -b 115200 -o -D /dev/ttyAMA0

    After firing up minicom on my Ubuntu laptop again, I was able to send data in both directions!

    Now to get the Raspberry Pi talking to an Arduino…

  • Making the Raspberry Pi a little less British

    Raspberry Pi

    After a month and a half of obsessively checking for status updates, I finally received my Raspberry Pi yesterday. I love it!

    The first thing I noticed after booting up the stock Debian image was that things are set up for British users. Most annoyingly, the symbols on the keyboard weren’t where I expected them to be. To arrive at a more Canadian configuration, I did the following.

    First, I changed the system locale, turning off en_GB.UTF-8 and turning on en_CA.UTF-8:

    sudo dpkg-reconfigure locales

    Next, I changed the keyboard layout:

    sudo dpkg-reconfigure keyboard-configuration

    Next, I changed the time zone:

    sudo dpkg-reconfigure tzdata

    And finally, I changed to a Canadian Debian mirror by editing the “sources.list” file:

    sudo vi /etc/apt/sources.list

    On the first line, I changed “” to “”:

    deb squeeze main
    # Nokia Qt5 development
    deb unstable main

    After rebooting (sudo reboot) and updating my package list (sudo apt-get update) I had a pleasantly Canadian Pi. :-)

  • WIND Mobile: A bad first impression

    I’ve been wanting to try WIND Mobile for a while now, but my phone (Nexus One) didn’t support the frequency bands used by the new carriers. But recently I replaced it with a Galaxy Nexus, which supports the frequencies of all the Canadian carriers. WIND had a great deal on ($40 for unlimited everything), so I grabbed a WIND SIM card and signed up online.

    I didn’t want to port my number over until I was sure WIND’s coverage was adequate, so I declined the option when I activated my SIM. A few days later I was satisfied, so I called up WIND customer care to request the port. The person who answered my call told me it was impossible to port a number to a SIM that was already activated, and that I was stuck with the number that I had been assigned. Not happy with this response, I asked whether there wasn’t some other possibility, and I was told that I could go to a WIND store and get a replacement SIM, which could then have my number ported to it.

    I phoned my nearest WIND store, and was told it would cost $25 to get a replacement SIM. Obviously I had no intention of paying $25 to fix a problem on WIND’s end, so I headed to Howard Forums to see whether other customers had faced the same problem. It didn’t take long to find several discussion threads on the topic. Some customers had managed to get a free replacement SIM at a WIND store, and others had eventually convinced WIND to cancel and re-activate their existing SIM, entering a port request with the new activation.

    I called back, hoping to get a different customer care rep. This time, the rep was happy to put through a port request for me, but said the request would need to be handled by their back office staff, and would take three to five business days. While this seemed like an awfully long time for such a simple request, it sounded like a better option than making a trip to a WIND store, so I asked the rep to put through the request. She took down my information and gave me a reference number.

    After four business days had passed, I was getting impatient. So I called back and gave my reference number. The rep told me that the reference number didn’t exist in their system. He looked up my account, and found that no port request had been made. I explained what had been done on my previous call, but the rep insisted that it was not even possible; I could not port a number to a SIM that had already been activated. The rep told me I would need to go to a WIND store and get a new SIM, which he insisted I would not be charged for.

    At this point I was irate. How could my request have disappeared into thin air? I called back one more time, hoping there was somebody in customer care who could actually help me. The fourth rep again couldn’t find my request from the previous week, but after explaining my situation he told me that my number could easily be ported in to my existing SIM. He only had to cancel my existing SIM and re-activate it. He was able to do that within minutes, and my number was ported within the hour.

    Clearly WIND has a big problem with insufficiently trained customer care reps. Two out of the four reps I spoke to didn’t know it was even possible to help me, and one was too incompetent to do it properly. My tweets to @WINDmobile during the ordeal went unanswered, as did an email to customer care. While I plan to stay with WIND for the time being, in the hope that their network is better than their customer care, I will definitely not be recommending them to friends. Koodo will remain my recommendation.

  • Getting rid of tearing in MythTV

    I just upgraded to MythTV 0.24, and so far it’s looking great! Closed captions look much nicer and the revamped on-screen display looks very sharp. But one problem I’d seen occasionally in 0.23 seemed to be worse: tearing in video playback. I used to see tearing only occasionally in HD playback, but after the upgrade I started to see it more frequently, and in SD playback as well. After a bit of quick googling, I found a solution in the MythTV wiki. I added the following to my frontend’s /etc/X11/xorg.conf file:

    Section "Extensions"
        Option "Composite" "Disable"

    After a quick restart, the tearing was completely gone. Yay!

  • Switching to WordPress

    I was starting to get tired of Drupal, so I thought I’d switch my blog over to WordPress. So far I’m impressed. The installation was simple, and I was up and running in minutes. I thought of using a script to copy my old blog postings over, but since there weren’t many I just did it by hand. Now I’m putting the finishing touches on. Please let me know if you notice any problems.

  • My submission to the Copyright Consultation

    I just sent my submission to the Canadian Copyright Consultation. There’s still time to submit, if you haven’t done so already. I’d recommend reading Professor Michael Geist’s submission to get some ideas.

    Here’s my submission:

    Having read over the previous copyright bill (C-61), I would like to voice my opposition to the inclusion of anti-circumvention provisions in the new copyright bill. My reasons are as follows:

    1. The anti-circumvention provisions in bill C-61 would have made it illegal for consumers to unlock their cell phones. This would further stifle competition in Canada’s wireless sector by making it more difficult for consumers to switch carriers, since they would have to purchase new hardware. It is my view that competitiveness would be maximized by banning the practice of cell phone locking, rather than protecting it in law. The owner of a cell phone should be free to use it with the carrier of his or her choice.
    2. Users of the Linux operating system, myself included, must use a circumvention tool (libdvdcss) to play legally purchased DVDs on their computers. I see no reason why the use or distribution of this tool should be restricted, since it has many uses which do not infringe upon copyright.
    3. The anti-circumvention provisions in bill C-61 would have allowed copyright holders to take away users’ fair dealing rights simply by applying technological protection measures (TPMs) to their works. Fair dealing rights are a critical part of our copyright legislation, and we must not allow them to be taken away by anti-circumvention legislation.
    4. Technological protection measures can be harmful to consumers. For example, in 2005 Sony sold music CDs containing software intended to prevent unauthorized copying. This software installed itself without requesting the user’s consent and could not be un-installed. It also made the user’s computer unstable and vulnerable to attack. Other copy protection schemes use a central server to decide whether to allow users to access content they have purchased. When this server ceases to function, whether intentionally or unintentionally, users lose access to their content. In 2008, this occurred when Yahoo shut down its DRM server. I believe that rather than protecting TPMs in law, we should be protecting consumers from them by limiting their use.
    5. Technological protection measures can harm competition. For example, until recently, users who purchased songs through the Apple iTunes music store could only play such content on Apple iPods. A user wishing to switch to another brand of music player would be unable to do so without losing access to their purchased content. It is my opinion that users should be able to access legally purchased content on the device of their choice. Protecting TPMs in law would undermine this goal.

    I would further like to make the following suggestions for the upcoming copyright legislation:

    1. Crown copyright should be abolished. I believe that the benefit to the public of putting works produced by the government into the public domain would greatly outweigh the resultant loss of revenue to the government. This model is used in the United States, where works produced by its federal government are not entitled to domestic copyright protection.
    2. The term of copyright protection should be reduced. In my opinion, twenty years from the date of publication should suffice, since most works cease to be comercially exploitable before that point anyway. This would vastly enrich the pool of works in the public domain, upon which creators could freely build.

    Clayton Smith
    Ottawa, Ontario

  • Using your PVR to read a long list

    Tonight I watched the season finale of the Rick Mercer Report. It was a pretty normal episode, but one of the jokes nearly made me fall off my chair. It was in a spoof ad for “COLD-fX Drip”, an intravenous version of the medication once hawked by Don Cherry. Near the end of the spoof, a list of things you can do while using the medication zoomed by on the screen. Since I have a PVR, I jumped back 10 seconds to watch the list in slow motion to see if anything funny was in it. Lo and behold, Rick had anticipated my move! As it turns out, COLD-fX Drip is great to use while “using your PVR to read a long list!”

    Here’s a screen capture for your amusement:

    screenshot of the Rick Mercer Report

  • Compiz on my Inspiron 5100

    My laptop is an Inspiron 5100, and for the longest time I couldn’t figure out how to get “Desktop Effects” (compiz) going in Ubuntu. I didn’t think my video card (Radeon Mobility 7500) was compatible, but it turns out it is. I just needed to change a couple settings.

    First, I put the following in /etc/drirc:

    <option name="allow_large_textures" value="2" />

    Then, in /etc/X11/xorg.conf I changed my DefaultDepth from 24 to 16. Finally, I restarted X with Ctrl-Alt-Backspace, and enabled compiz in System → Preferences → Appearance → Visual Effects. Voila!

    I found these instructions here.

  • New machine

    I’ve been thinking about building myself a new desktop machine for a while now, but I finally got around to it this weekend after the motherboard in my old machine failed. Here’s what’s in the new one:

    • Intel Core 2 Duo E6750 (2.66 GHz)
    • Asus P5K-V (1333 MHz FSB, integrated video)
    • 2GB Corsair Twin2X PC2-6400 (4-4-4-12)
    • Antec Solo case
    • Corsair VX450 power supply
    • WD Caviar 500 GB SATA hard drive
    • Asus DRW-1814BLT SATA DVD burner

    It also has a few components from my old machine, namely a 250 GB PATA hard drive, Hauppauge HVR-1600 ATSC/NTSC tuner card, and M-Audio Omni sound card.

    Initially I was experiencing choppy sound and mouse movement whenever the hard drive was active, but I solved the problem by downloading the latest drivers for the JMicron PATA/SATA controller from the manufacturer’s website. Also, the memory was running at 5-5-5-18 timings by default, but I easily fixed that in BIOS. I used Norton Ghost to move Windows to my new SATA hard drive.

    This machine is smokin’! Prime95 is running about three times as fast as before, and I can’t believe how fast BeyondTV starts up. The new case is great too. It has way better ventilation than my old one, and I love having USB ports and audio jacks on the front!

  • Free at last

    It’s been a month now since all my Rogers services were canceled, and I couldn’t be happier. The National Capital Freenet is providing me with great DSL service at a great price, and over-the-air television is working out wonderfully thanks to my digital/analog TV tuner card. Watching the Senators destroy the Sabres in high definition is great. :-)

  • Rogers cancellation hell

    Since moving to Ottawa, I’ve been getting cable television and internet from Rogers. It wasn’t bad for the first year or so, but since then they’ve been raising their prices every six months, sometimes significantly. It had reached the point where it certainly wasn’t worth it any more, especially considering that Teodora and I don’t watch much television. Mostly we watch CBC shows (Air Farce, 22 Minutes, and Rick Mercer), and CBC has been broadcasting a digital high-definition signal in Ottawa since September 2006. So I took the plunge, and bought a hybrid (digital/analog) TV tuner card for my computer (Hauppauge WinTV HVR 1600) and a set of rabbit ears.

    At first I wasn’t pleased with the tuner card, due to the abysmal quality of the software that came with it. But at the recommendation of several reviewers of the card, I downloaded the trial version of a piece of PVR software called BeyondTV. It isn’t perfect, but it’s a vast improvement over Hauppauge’s software and it’s quite usable. Watching high-definition TV on the computer is great, and being able to skip the commercials makes it ever better!

    To replace our internet, I decided to switch to DSL service from the National Capital Freenet, a not-for-profit internet service provider and the world’s second free-net. Unfortunately, I’m quite far from Bell’s nearest central office and thus limited to a download speed of 2.5 Mbps, compared to 6 Mbps with Rogers. But the NCF’s price is significantly less, and some things are actually faster with NCF, for example BitTorrent downloads, which Rogers slowed significantly using traffic shaping.

    Yesterday I reached the point at which I was satisfied with the new television and internet setup, so it was time to pull the plug on Rogers. First I had a look through the FAQ on their web site to figure out what I needed to do to cancel my service. I was disappointed to learn that they require 30 days advance notice, but what can you do? I also read that cancellations can be done by phone any time from 7:00 am to 2:00 am, seven days a week. But after phoning them up and navigating through the annoying interactive voice response system, I reached a department that was currently closed, and would be open during their “normal business hours”, which they neglected to specify.

    I phoned again, taking a different path through the IVR with the hopes of getting a real human being on the phone. I succeeded, but the person who answered my call wasn’t able to handle cancellations, and forwarded my call to the same place I had reached on my previous attempt. I called a third time, reached a different person and asked again to cancel. When she proposed to forward my call, I told her about the “normal business hours” message and she told me that indeed that department was closed, and that the mysterious normal business hours were 8:00 am to 9:00 pm, seven days a week. I was surprised to hear that, considering that it was currently 6:00 pm. Upon pointing this out to her, she corrected herself and told me that the weekend hours were actually 8:00 am to 5:00 pm.

    So this morning, a bit after 8:00 am, I resumed my quest. Taking my original path through the IVR, I got the same old “normal business hours” message. I called again, taking the path that would bring me to a human. I got forwarded to the same place again. I called a third time, and the person who answered told me that she would be unable to make any changes to my account due to technical difficulties. I called a fourth time, and miraculously reached someone who didn’t decide to shunt me off to some other place after hearing what I was calling about.

    She of course told me that I wouldn’t be able to cancel my service for 30 days. I asked whether I could at least cancel my internet immediately, and she told me even that would not be possible. But luckily, I was able to switch my connection speed to the slowest available, thus avoiding most of the wasted cost.

    Anyway, I’m glad that in a month’s time I’ll finally be Rogers-free. I’ll be paying less than half what I was before while hardly giving up anything (and even getting a bit extra thrown in, namely CBC in high definition and fast BitTorrent downloads). And hopefully Rogers will stop sending me junk mail once a week! Well, maybe that’s too much to hope for…

  • Action Figure Party

    A while ago, I was fooling around with a couple of the music recommendation services, and Pandora. They didn’t suggest much interesting, with one notable exception: Action Figure Party. I heard their song “Everybody Ready” and loved it. I just received their CD, and I’m pleased to report that the rest of the tracks don’t disappoint. In fact, I’ve listened to most of them at least five times now, and love them more with each listen. “Where’s The Moment”, “Clock Radio”, and “Action Figure Party” are also exceptional tracks. There’s tons of vintage instruments: Arp, Moog, Wurlitzer, Hammond, Rhodes, Clavinet, you name it. One track even has some theremin. Definitely check it out if you’re into funky, jazzy music.

  • Voting for a winner

    For the first time in my life, I’ve voted for the winning candidate in an election, namely Paul Dewar of the NDP! In fact, he ended up winning by a fairly large margin, which surprised me. Another surprising thing is that the NDP ended up with more seats than ever in Ontario!

    Below are the final results. As you can see, both predictions came very close. Teodora and I ended up making about $27 on the stock market, which is not bad interest for an investment of $400 over a month!

    Liberal: 103
    Conservative: 124
    NDP: 29
    Bloc Quebecois: 51
    Others: 1

  • The predictions are in!

    Well, the Election Stock Market closed last night, and final prices would put the parties as follows:

    Liberal: 93
    Conservative: 127
    NDP: 33
    Bloc Quebecois: 54
    Others: 1

    The Election Prediction Project, which does a riding-by-riding analysis based on user-submitted commentaries, calls for:

    Liberal: 104
    Conservative: 118
    NDP: 29
    Bloc Quebecois: 56
    Others: 1

    Things are looking good for the NDP, but then again, the Election Prediction Project greatly overestimated the NDP last time, so I’m not getting my hopes up. In any case, it looks like Teodora and I will end up about $20 ahead in the stock market!

  • Election Stock Market

    Here’s a cool idea: a stock market where you can trade in shares of the political parties. The final values of the shares will be determined by the election results, so if you can accurately predict the results, you can make some money by buying shares that are undervalued and selling ones that are overvalued. It’s all done with real money, so you have a financial incentive to make serious predictions.

    Teodora and I have been participating since the market opened on December 13, and so far we’ve managed to lose $10 or so. But there’s still a couple weeks to go, so hopefully we can make that back and maybe end up a bit ahead.

    This is definitely a cool project to get involved in if you’re interested in politics. It’s actually a research project being done by the University of British Columbia. They’ve had similar markets for previous elections, and they’ve done a pretty good job of predicting the final results.

  • World record prime number

    Since 1998, I’ve been a participant in the Great Internet Mersenne Prime Search, a project which aims to find huge prime numbers. Just a couple weeks ago, the project broke the world record for the ninth straight time. The record-setting number is 230,402,457-1, which weighs in at 9,152,052 digits! We’re getting awfully close to finding a ten million digit prime and winning the $100,000 prize offered by the Electronic Frontier Foundation.

    If you’d like to participate in the project as well, it’s very simple. Just download and install the GIMPS software, which you won’t even notice running in the background. And who knows, you just might get lucky and win a share of that huge prize!

  • A new year, a new site

    Well, it’s the start of a new year, and I thought I’d start things off by finally getting off my butt and putting together a new web site. I’ve had an Esperanto site for a few years now, but a lot of my friends don’t speak Esperanto and have been asking for an English site. I always thought maintaining two sites would be a pain, but thanks to a nice piece of content management software, Drupal, it should be a piece of cake.

    Anyway, I wish everyone all the best in 2006, and I hope to hear from you soon. Leave a comment here or send me an email, and let me know what you’re up to these days.

subscribe via RSS