Shop OBEX P1 Docs P2 Docs Learn Events
Weird values — Parallax Forums

Weird values

John AbshierJohn Abshier Posts: 1,116
edited 2006-11-03 16:59 in Propeller 1
CON  'CMPSO3Demo
  _CLKMODE = XTAL1 + PLL16X
  _XINFREQ = 5_000_000
  SCL = 0                                    'Define Constants
  SDA = 1
VAR
  
OBJ
  C : "CMPS03"
  Tv : "Tv_Text"
PUB Main   |  version, bBearing, wBearing    
  Init
  Tv.str(string("Bus check "))
  Tv.dec(C.BusCheck)
  Tv.out(13)
  Tv.str(string("Device Present "))
  Tv.dec(C.Present)
  Tv.out(13)
  if C.Present
    Tv.str(string("Present"))
    Tv.out(13) 
  version := C.GetVersion
  Tv.str(string("Version "))
  Tv.hex(version,8)
  Tv.out(13)
  bBearing :=  C.GetBBearing
  Tv.str(string("Byte Bearing "))
  Tv.hex(bBearing,8)
  Tv.out(13)
  wBearing := C.GetWBearing
  Tv.str(string("Word Bearing "))
  Tv.hex(WBearing,8)
PUB Init
  Tv.start(12)                                          ' should check fail
  Tv.out($00)                 ' clear
  Tv.out($01)                 ' home
  C.Init(SDA, SCL)     

CON 'CMPS03 object
  CMP_ADDRESS = $C0
OBJ
  I2C      : "I2C LowLevel"
PUB Init(SDA, SCL)  
  repeat 9
    I2C.i2cStop
  I2C.Initialize(SDA, SCL)              '     Initialize i2c MASTER in present COG
PUB GetVersion
  result := ReadReg($00)
  return
PUB GetBBearing 
  result  := ReadReg($1)
  return
PUB GetWBearing  : wBearing
  wBearing := ReadReg($2)
  wBearing <<= 8
  wBearing |= REadReg($3)
  return  
PRI ReadReg(reg)
  I2C.i2cStart
  I2C.i2cWrite(CMP_ADDRESS | 0, 8)
  I2C.i2cWrite(reg, 8)
  I2C.i2cStart
  I2C.i2cWrite(CMP_ADDRESS | 1, 8)
  result := I2C.i2cRead(0, 8)
  return
PUB BusCheck
  result := I2C.testBus
  return
PUB Present
  result := I2C.devicePresent(CMP_ADDRESS)
  return

The output of the program that reads a CMPS03 compass is
Version 9· This is the correct value.
bBearing $9E8· This should be a byte. E8 would be reasonable.
wBearing $9E80CD6 This should be a word. $0CD6 is a consistent result with $E8 for bBearing
I don't understand what is going on.· I thought that the result local variable was set to 0 on a call.

Comments

  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2006-11-03 08:02
    I'll need to look at this closer, but in the I2C routine the data is not cleared. It is simply shifted left. This is not an error , the Idea was to be able retain a data stream in a 4-byte FIFO approach.
    This is simple to fix... if you are expecting a BYTE, then just AND the result with $FF... expecting a WORD, then AND the result with $FFFF... for a LONG, just leave it alone.

    I'll make note of this when I release this object in the future.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
  • CJCJ Posts: 470
    edited 2006-11-03 15:10
    Beau, wouldn't it do the same thing if you stuffed the returned result into the proper sized variable rather than go through the extra step of anding it? I can see anding being useful for units like the ds1620 which return 9 bits & $1FF.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Who says you have to have knowledge to use it?

    I've killed a fly with my bare mind.
  • John AbshierJohn Abshier Posts: 1,116
    edited 2006-11-03 15:29
    Beau, perhaps the answer is documentation. The misleading part is that you tell i2cRead how many bits you want and it returns more than that number of bits. I guess this is a design decision. The other part of the object that I don't understand is what to do with ack on i2cRead.

    CJ, I tried stuffing the result into the proper sized variable, but Spin only allows long local variables.
  • Beau SchwabeBeau Schwabe Posts: 6,568
    edited 2006-11-03 16:59
    CJ and John,

    John, as you pointed out in a PM...
    "The problem is that i2cData is global to the object. Making it local to Pub i2cRead solves the problem."

    The reason I made i2cData global was so that I could use the incoming data as a FIFO (First-In-First-Out).
    This kind of circumstance has been handy for some applications I have come across so I implemented the variable
    this way.· That said, it is difficult to design a one size fits all.· The whole idea anyway is that the propeller
    objects can be modified by the user to fit a specific application.· In some cases, the way I did it can reduce
    the amount of code space required, when in a pinch can make a real impact.· For example:

    a section of your code that reads....

    PUB GetWBearing : wBearing 
        wBearing := ReadReg($2) 
        wBearing <<= 8 
        wBearing |= REadReg($3) 
    return
    

    ...could be re-written as...

    PUB GetWBearing : wBearing 
        ReadReg($2) 
        wBearing := REadReg($3) & $FFFF 
        return
    

    ...it only saves a 'long' but if this can be applied several times, it could make a difference.


    And yes, documentation is the answer, however the Lowlevel I2C routines John uses here have not officially been released
    to the object exchange, instead they were used in an object (DS1307) which has been released.


    As far as the ack bit ... this depends on the i2c device itself.· On some devices they don't care, on others they either
    look for a "1" or a "0".· From the documentation, it looks like the CMPS03 wants to see a "0".

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Beau Schwabe

    IC Layout Engineer
    Parallax, Inc.
Sign In or Register to comment.