Monday, January 16, 2012

Hellschreiber QRSS using Propeller

Last evening, I shared the experience of creating a FeldHell-like QRSS beacon.  The bulk of the effort was in creating an acceptable font.  The Propeller chip has a rather nice font already in ROM but it is more suited for TV video output than for QRSS due to its 16x32 size.  I felt that this was too much bandwidth to occupy for a single signal in the QRSS band.

I created the font definition in a text editor and decided to try a 5x7 font initially.  With this format, each character is 5 bytes (one byte for each column of the font character).  For example, the letter "A" is represented thus:

     XXX
    X   X
    X   X
    XXXXX
    X   X
    X   X
    X   X

Each colum of the character in the 5x7 grid is encoded as a byte where the "X" character above is encoded as a set bit and the lack of an "X" is encoded as a 0.  So to create this, I defined all my characters (0..9, A..Z) as shown above in a text file.  I then imported the text file into a spreadsheet and rotated the rows and columns 90 degrees using the spreadsheet "Transpose" function.  This had the effect of laying all the characters down on their sides, thus:

     XXXXXX
    X  X
    X  X
    X  X
     XXXXXX

I then exported the file back to a text file for further processing.  You have to now imagine each of the font characters lying on their sides like the example above, occupying five very long lines of my text file.  I then globally replaced all the space characters (there is a space in each 5x7 grid anyplace there is no "X") with a "0" character and replaced the "X" characters with "1".  For the "A" character above, this resulted in:

    0111111
    1001000
    1001000
    1001000
    0111111

I then turned this mess into a valid DAT block containing binary byte values like so:

DAT
    ' FeldHell font definitions
    '             A         B         etc
    Col5 BYTE %0111111, %xxxxxxx, ...
    Col4 BYTE %1001000, %xxxxxxx, ...
    Col3 BYTE %1001000, %xxxxxxx, ...
    Col2 BYTE %1001000, %xxxxxxx, ...
    Col1 BYTE %0111111, %xxxxxxx, ...

Now I can index into this table and obtain the column data I need for each character.  So now in the main loop, I can call this procedure to process the beacon text:

PUB doFeldHellBeacon
    ' Send Feld Hell beacon text
    sendFeldHellString(string("KO7M CN87xp"))


PUB sendFeldHellString(strMsg)
    repeat STRSIZE(strMsg)
      sendFeldHellChar(BYTE[strMsg++])


The code to send each character is a quick hack, so don't beat me up too much.  I am still playing around with the timing to make it look nice.  Each character of the message text is looked up in the DAT table above to obtain the byte containing each of the 5 column definitions.  The character is sent from bottom left (least significant bit of Col1) to the top of the column and then proceeding with the next column until all five columns have been sent.  I test the least significant bit of each byte of column data and send a tone if it is set and send nothing if unset.  Right shift to get the next bit and continue for all 7 bits.

PUB sendFeldHellChar(ch) | i, j, iCol, columnData, Time
   
    Time := 300
   
    ' set up column index to default to space character
    iCol := -1
   
    case ch
      "a".."z": iCol := ch - "a" + 10
      "A".."Z": iCol := ch - "A" + 10
      "0".."9": iCol := ch - "0"
   
    if iCol < 0
      delay(Time*12)            ' Handle the space character specially
    else
      repeat i from 4 to 0               ' 5 columns in reverse order
        columnData := Col5[iCol+(i*36)]  ' get the current column data
        repeat j from 0 to 6
          if columnData & 1    ' If the font bit is set, send a tone
            sendTone(j*2)
          else
            noTone
          columnData >>= 1     ' Right shift font data to get next bit
          delay(Time)          ' Give a little space between columns

        noTone
      delay(Time*6)            ' Give a little more space between letters


So, that is it...  Simple, eh?  Since the font definition is  five really long lines of text, I am not going to post the entire program here.  If you would like to have a copy of it however, I will be happy to email it to you if you will drop me a comment to this post on the blog.

I will be creating "a".."z" characters in the font and some punctuation, but have no plans to create any characters beyond what would be in a typical QRSS message.  I am using Eldon's 10 minute QRSS sync algorithm for stacked grabbers.  See his article here.

Here is what it looks like on the air:

1 comment:

  1. Nicely done, and well described! As it happens, I am in need of a 5x7 font for the Propeller. If you could post or email what you did and save me some time, that would be awesome. Thanks!

    ReplyDelete