Shop OBEX P1 Docs P2 Docs Learn Events
Check specific bit of a byte — Parallax Forums

Check specific bit of a byte

qsuscsqsuscs Posts: 12
edited 2013-08-14 13:27 in Propeller 1
Hi,

for my morse keyer, I have to get the sequence for every letter. It is either "dit" or "dah" some times, e.g. the letter A is "dit dah", the letter B is "dah dit dit dit", and so on. A PIC programmer told me how he stored the "codes": one byte per character, consisting of zeroes, the startbit and a 0 for "dit" and a 1 for "dah". So a A would be stored as %0000_0101, a B would be %0001_1000, etc. The program shall read from Bit #7 to #1, if it's 0, continue reading, it it's 1, go ahead and issue dit or da for 0 or 1. My implementation looks like that:
sign := byte[@A]
  repeat i from 7 to 0
    if sign[i] == 1
      repeat j from i-1 to 0
        case sign[j]
          0 : dit
          1 : dah
        waitdit
      quit

DAT
A       byte  %0000_0101
dit and dah are methods, sign, i and j are declared as byte.
But this code doesn't work, I don't hear any output. The methods dit and dah are definitely working, I tested them.
What am I doing wrong?

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2013-08-14 08:21
    The bit access syntax ([ n ] or [ m..n ]) only works for the special function registers like OUTA or INA. It doesn't work for ordinary variables. You have two options:
    1) Use bitmasks (|<) and the bit logical operations (& | ^ !)
    2) Move your value to one of the unused special function registers (OUTB or DIRB) and use the bit access syntax there

    To check for bit x, do: "IF sign & |< x" or "IFNOT sign & |< x" (note: IFNOT is one word).
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-08-14 09:58
    I have these routines in my template program -- they're useful:
    con 
    
      { ----------------- }
      {  B I T   W O R K  }
      { ----------------- }
    
    
    pub rd_bit(value, pos)
    
    '' Returns value.pos (0 or 1)
    
      return (value >> pos) & 1
      
    
    pub wr_bit(value, pos, bit)
    
    '' Returns modifed value with value.pos set to bit
    
      if (bit & 1)                                                  ' use lsb
        return set_bit(value, pos)
      else
        return clear_bit(value, pos)
     
    
    pub set_bit(value, pos)
    
    '' Returns value with bit at pos set (1)
    
      return value | (1 << pos)
    
    
    pub clear_bit(value, pos)
    
    '' Returns value with bit at pos clear (0)
    
      return value & !(1 << pos)
    


    A couple years ago I did lighting control for this display, which included Morse Code output of the character names (Mourningstar and Typhon) from the back of their costumes:

    attachment.php?attachmentid=84574&d=1314418483

    At that particular convention, G4 TV did an interview with Steve Wang (his shop built the display) and the Morse Code IFF output from the characters was a big topic of discussion. I chucked it in for fun as I had an extra cog!


    Here's the code I converted from a Scott Edwards program for the BASIC Stamp 1 (grandfather of the Propeller); you'll need to define timing constants.
    pub morse(char, pin) | key, idx, len
    
    '' Output char as Morse Code on pin
    '' -- makes pin an output
    
      outa[pin] := 0
      dira[pin] := 1
    
      key := ucase(char)                                            ' convert to upper case
      idx := lookdown(key : "A".."Z", "0".."9")                     ' if alpha-numeric
      if (idx > 0)
        key := byte[@Alphas][idx-1]                                 ' convert to Morse
        len := (key & %111)                                         ' extract length
        if (len == 7)                                               ' adjust if required
          len := 6
        elseif (len == 6)
          key &= %11111011          
        repeat len                                                  ' output char
          outa[pin] := 1                                            ' led on
          if ((key & %1000_0000) == 0)                              ' if 0
            pause(DIT_TIME)                                         '   dit   
          else                                                      ' if 1
            pause(DAH_TIME)                                         '   dah
          outa[pin] := 0                                            ' led off
          key <<= 1                                                 ' prep for next bit
          pause(DIT_TIME)                                           ' inter-flash delay
          
      elseif (key == " ")                                           ' if space
        pause(WRD_TIME)                                             '   pad with word delay
          
            
    pub ucase(ch)
    
    '' Converts lowercase ch to uppercase
    
      if ((ch => "a") and (ch =< "z"))
        ch -= 32
    
      return ch
    
    
    pub pause(ms) | tix, t
    
      tix := clkfreq / 1_000
    
      t := cnt
      repeat ms
        waitcnt(t += tix)
     
    
    dat
    
      Alphas                byte    %01000_010              ' A
                            byte    %10000_100              ' B 
                            byte    %10100_100              ' C
                            byte    %10000_011              ' D
                            byte    %00000_001              ' E
                            byte    %00100_100              ' F 
                            byte    %11000_011              ' G
                            byte    %00000_100              ' H
                            byte    %00000_010              ' I
                            byte    %01110_100              ' J
                            byte    %10100_011              ' K
                            byte    %01000_100              ' L
                            byte    %11000_010              ' M
                            byte    %10000_010              ' N
                            byte    %11100_011              ' O
                            byte    %01100_100              ' P
                            byte    %11010_100              ' Q
                            byte    %01000_011              ' R
                            byte    %00000_011              ' S
                            byte    %10000_001              ' T 
                            byte    %00100_011              ' U
                            byte    %00010_100              ' V
                            byte    %01100_011              ' W
                            byte    %10010_100              ' X
                            byte    %10110_100              ' Y
                            byte    %11000_100              ' Z
                             
      Numbers               byte    %11111_101              ' 0
                            byte    %01111_101              ' 1
                            byte    %00111_101              ' 2
                            byte    %00011_101              ' 3
                            byte    %00001_101              ' 4
                            byte    %00000_101              ' 5
                            byte    %10000_101              ' 6
                            byte    %11000_101              ' 7
                            byte    %11100_101              ' 8
                            byte    %11110_101              ' 9
    


    Scott uses a clever scheme of encoding the length (number of dits and dahs) in the lower three bits of the character code. See page 39 of this document for Scott's original BS1 project:

    -- http://www.parallax.com/Portals/0/Downloads/appnt/stamps/bs1Appnotes.pdf
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-08-14 11:17
    +1 on Scott Edwards' app notes for the BS1. A great reference on how to do more with less. I used that encoding too in the Applied Sensors text to transmit sensor readings by Morse code from a BS2. Note that the method does also support the 6 element punctuation like period and question mark, although it is not included in the DATa or the LookDown.
  • JonnyMacJonnyMac Posts: 9,107
    edited 2013-08-14 11:29
    I did that code for a fun trade show demo. If I were going to create a keyer application, I would extract the ASCII-to-Morse encoding from the actual transmission loop -- that would allow more flexibility and more characters than my simple table provides for.
  • qsuscsqsuscs Posts: 12
    edited 2013-08-14 13:27
    Thanks to Mike Green, it works fine now. Now I can go ahead and do all the rest. Gonna be funny, lol, haven't done anything with microcontrollers for a eternity.
    Code is at GitHub: https://github.com/qsuscs/PropCW
Sign In or Register to comment.