Shop OBEX P1 Docs P2 Docs Learn Events
14 bit 2s complement — Parallax Forums

14 bit 2s complement

CannibalRoboticsCannibalRobotics Posts: 535
edited 2014-08-19 08:36 in Propeller 1
On the Freescale Xtrinsic FXOS8700CQ the accelerometer data is presented in the form of a 14 bit 2s complement. Following the "invert and + 1" technique they recommend I can not get SPIN to clear off the bits above the 13th on a negitive number. My feeling is that it's something obvious Im just not picking up.
Some fresh eyes on this would be great.
Pri FixA(d)| bits               '' Returns Signed Long of G force on axis for data d
  
  bits := d & $0000_3FFF                                ' Reduce to 14 bits to work with

  if bits > $0000_1FFF                                  ' Is sign bit (14th) set ?
    bits &= $0000_0000_1FFF                             ' Clear sign off base number
    bits :=(! bits) + 1                                 ' Invert the remainder and add 1
    bits := bits & $0000_0000_0000_1FFF                 ' Clear off upper ones from ! operation
    bits := -1 * bits                                   ' Make it negitive (set sign bit)

  Return bits

For Negitive numbers I get:
 AxC Raw: 00000000000000000011101110111111
 14 bits: 00000000000000000011111111111111
FixA out: 11111111111111111111101110111111 = -1089
For Positive I get:
 AxC Raw: 00000000000000000000010001110100
 14 bits: 00000000000000000011111111111111
FixA out: 00000000000000000000010001110100 = 1140

Why is the routine returning all 1's above the 13th bit after I've ANDed them all off with
bits := bits & $0000_0000_0000_1FFF                 ?

Thanks in advance.

Comments

  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-08-18 13:13
    Do this:
    value := value << 18 ~> 18

    The << gets the sign bit into bit 31, and the ~> does a signed right shift back, preserving the sign bit.

    -Phil
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2014-08-18 13:15
    Thanks for reply, where?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-08-18 13:16
    pri fixA(d)
      return d << 18 ~> 18
    
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2014-08-18 13:22
    New code:
    Pri FixA(d)| bits               '' Returns Signed Long of G force on axis for data d
      return d << 18 ~> 18
    
    Result for negitive
     AxC Raw: 00000000000000000011110010010000
     14 bits: 00000000000000000011111111111111
    FixA out: 11111111111111111111110010010000 = -880
    
  • abecedarianabecedarian Posts: 312
    edited 2014-08-18 14:04
    Shouldn't you be able to add 16384 to the value and be done with it?
    Then you should end up with something ranging from 0 to 37267.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2014-08-18 14:08
    Shouldn't you be able to add 16384 to the value and be done with it?
    No, that doesn't work. Remember, it's still 32-bit arithmetic: 16384 (i.e. -16384) + 16384 == 32768, not 0. Besides, he wants the signed value for +/- G forces.

    -Phil
  • abecedarianabecedarian Posts: 312
    edited 2014-08-18 14:12
    Nevermind, just realized you're taking a 14 bit signed value into a 32 bit variable.

    So shift left 18 bits, then right 18 bits, to get rid of 'stray' bits on the end, then add 16384 to get rid of the sign.

    - edit: Just noticed Phil's response above. I'll shut up.
  • CannibalRoboticsCannibalRobotics Posts: 535
    edited 2014-08-19 08:36
    Thanks all, working now and the code is much skinnier!
Sign In or Register to comment.