Stamp Manual "I2CIN"/"I2COUT" discrepancy

From the Stamp Manual:
I2COUT Pin,SlaveID,{ Address{\LowAddress},}[ OutputData]
(The discussion is then provided into how to split an address >255 into 2 bytes for the "address \Low Address" format)

But in the following example program, the variable "addr" is defined as a word variable and is used as the incrementer in a "FOR...NEXT" LOOP.

FOR addr = 0 TO 2047 STEP 16 ' loop through all addresses
block = addr.NIB2 << 1 ' calculate block address (addr.NIB2 will range 0 ->7, which is then shifted left once in "block" to insert it into the "SlaveId")
value = addr >> 4 ' create value from upper 8 bits
' write 16 bytes

I2COUT SDA, $A0 | block, addr, [REP value\16]
^
Note that the word variable ^ is then used in the I2C command without breaking it out into the "address \Low Address" format.
Is this legal?
Since the 24LC16 is expecting an 8 bit low address here ( the top 3 bits are included in the SlaveId), what is it receiving from this command?

2nd question: can the "$A0 | block" operation be enclosed in parentheses to make it easier to read?
( the 24LC16 EEPROM being addressed requires that a block address be included in the SlaveId byte to distinguish which one of the 8 blocks of 256 bytes is being addressed)
( they used this method to "OR" the block number into position in the SlaveId )

The makers of the 24LC16 decided to differently use the 3 bits that normally are used to match 3 pins on the chip to help determine chip select.
They decided to use those 3 bits in the SlaveId as the high 3 address bits instead of a two byte address that would waste 5 bits in the high byte address.


Thanks

Comments

  • Tracy AllenTracy Allen Posts: 6,352
    edited 2018-02-19 - 18:04:59
    I2COUT SDA, $A0 | block, addr, [REP value\16]

    Yes, you can enclose ($A0 | block) in parentheses. Including part of an address in the slave ID is quite common, not so different. The I2C code $A (in 8-bit format) is reserved for memory devices. Or'ing into the device ID is common when it is necessary to select one of several memory chips. Here,
    block = addr.NIB2 << 1
    shifts the selector bits left by one so that when OR'd with the $A0, the lowest bit is left alone for use as read=%1 (by I2CIN) and write as %0.

    The addr is 16 bits, but the I2COUT command, as written, sends only 8 bits, the least significant byte of addr.
  • Thank you for the clarification.
    I was worried that it might be a typo.

    3rd question:
    If I'm using a chip that has more than 2K so that the block address
    is too big to fit in the 3 bits in the device ID, (so that I'm having
    to send the whole address word) will the following code work?

    SDA PIN 0
    SCL PIN SDA + 1
    addr VAR Word
    lab var addr.LOWBYTE
    hab var addr.HIGHBYTE
    (end of declarations)

    **************************
    FOR addr = 0 to 65535 STEP 16
    I2COUT SDA, $A0, hab, \lab, [REP value\16]
    NEXT

    Or do I have to actually calculate the high address byte and the
    low address byte inside the loop?

    ?
Sign In or Register to comment.