Shop OBEX P1 Docs P2 Docs Learn Events
How to use I2C without a register address and read sequential FIFO? — Parallax Forums

How to use I2C without a register address and read sequential FIFO?

4Alex4Alex Posts: 119
edited 2008-10-02 22:36 in Propeller 1
Hi All,

I am using the I2C SPIN Object from James Burrows (May 2006 Version 1.3).

I am trying (very hard) to interface a keypad controller (MAX11041 - 30 keys). This chip can monitor up to 30 keys, and report which one was pressed, in what sequence if any, and for how long. Great for a custom made mp3 player...

I have a working proto and I can detect the presence of the IC using 'devicePresent(deviceAddress)'. My problems comes when I try to read the key log of the chip. The key log is composed of 8-word FIFO (8 keystrokes can be logged sequentially: K1Byte1=key#, K1Byte2=duration, K2Byte1=key#, K2Byte2=duration, and so on).

From the datasheet (page 9), you can read the IC using the slave address ($42 in my case) and then 8 consecutive bytes (chip ID, control reg, key byte1, key byte2), separated by 1 ACK each. The read is terminated by a stop.

My question: how can I read an I2C device knowing only the slave address, not referencing any register, and read successively 4 bytes separated with an ACK? The method I use is readLocation(deviceAddress, deviceRegister, addressbits, databits). It doesn't work with this IC.

Any help would be greatly appreciated. Thanks in advance.

Cheers,

Alex

PS1: The url is www.maxim-ic.com/quick_view2.cfm/qv_pk/4944
PS2: I've used the following modified code but it doesn't seems to work either:

PUB readMax11041(deviceAddress,seq) : i2cData | ackbit,deviceRegister
  ' read a device's register
  ackbit := _i2cACK
  deviceRegister := 0  
  if i2cStarted == true  
    if seq == "1"
      i2cStart
      ackbit := (ackbit << 1) | i2cWrite(deviceAddress | 0,8)
      'send a 8 bit deviceRegister. (i2cWrite will shift left 24 bits)
      ackbit := (ackbit << 1) | i2cWrite(deviceRegister << 24, 0)
         
      i2cStart
      'Ireg
      ackbit := (ackbit << 1) | i2cWrite(deviceAddress | 1, 8)
      i2cData := i2cRead(_i2cACK)
    if seq == "2"
      'i2cStart
      'Creg
      'ackbit := (ackbit << 1) | i2cWrite(deviceAddress | 1, 8)
      i2cData := i2cRead(_i2cACK)
    if seq == "3"
      'i2cStart
      'Kreg
      'ackbit := (ackbit << 1) | i2cWrite(deviceAddress | 1, 8)
      i2cData := i2cRead(_i2cACK)
    if seq == "4"
      'i2cStart
      'Treg
      'ackbit := (ackbit << 1) | i2cWrite(deviceAddress | 1, 8)
      i2cData := i2cRead(_i2cNAK)
      i2cStop
    
  else
    ackbit := _i2cNAK
  ' set the last i2cACK bit
  lastackbit := ackbit
  ' return the data      
  return i2cData


[url=http://][/url] hop.gif

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2008-10-01 18:56
    The sequence you need is:

    i2cStart

    i2cWrite with the device select code and a read bit in bit0

    as many i2cRead cycles as you need/want.· The last cycle has ACK=0.· All the others have ACK=1

    i2cStop

    Take a look at some of the examples in the I2C routines if the above isn't clear


    Post Edited (Mike Green) : 10/1/2008 7:02:24 PM GMT
  • 4Alex4Alex Posts: 119
    edited 2008-10-01 20:06
    Good afternoon Mike,

    Thank you so much for your reply.

    I have done the following (and several other variants) but it still doesn't work. Clearly, there's something I don't get. Sorry if I'm so obtuse.

        'read data device
        'in i2cObject: _i2cNAK         = 1
        'in i2cObject: _i2cACK         = 0
    
        i2cObject.i2cStart
        i2cObject.i2cWrite ($42,8)
    
        Ireg := i2cObject.i2cRead(i2cObject#_i2cACK)
        Creg := i2cObject.i2cRead(i2cObject#_i2cACK)
        Kreg := i2cObject.i2cRead(i2cObject#_i2cACK)
        Treg := i2cObject.i2cRead(i2cObject#_i2cNAK)
        i2cObject.i2cStop
    
    



    I have re-checked all contacts, shorts, etc., and compared with typical app schematics. All are ok.

    Any other suggestions? (please, pretty please)

    Cheers,

    Alex
  • KeithEKeithE Posts: 957
    edited 2008-10-01 21:02
    I've never used this object, but are you sure that:

    i2cObject.i2cWrite ($42,8)

    Is setting the R/!W bit to a 1?

    Also I don't know why the datasheet says this, but it says to give an ACK after every read. It's possible that a NACK will confuse it down the line.
  • Mike GreenMike Green Posts: 23,101
    edited 2008-10-01 21:05
    You have to use $43 to set the read bit in bit 0 of the device select code. $42 is for writing. The "higher level" routines in the I2C libraries take care of this for you, but you're using the low level routines which don't know which way the transfers go. For example, if you have to "address" a device like a memory or some I/O expanders with registers, the register address or memory address is sent with "write" transfers, then the device has to be reselected for "read" mode if you're reading the memory. In your case, there are no separate internal registers that have to be selected.

    The last read has to have a NACK so the device knows that this is the last byte to be transferred and a stop will follow.
  • KeithEKeithE Posts: 957
    edited 2008-10-01 21:14
    "The last read has to have a NACK so the device knows that this is the last byte to be transferred and a stop will follow."

    Yes I'm aware that this is normally done however the datasheet says:

    "
    ...
    5) The MAX11041/MAX11042 send the corresponding
    keypress time duration (OF, T6–T0) stored in the
    FIFO starting with the most significant bit (OF).
    Afterwards the master must send an ACK bit.
    6) The master must generate a stop condition (P)."

    So I'm just pointing this out in case he still has problems after fixing the slave address.
  • KeithEKeithE Posts: 957
    edited 2008-10-01 21:21
    The other thing that I noticed is that there is no error checking being done after the initial slave address. You should really verify that you received an ack from the slave before trying to read data from it. If you don't receive an ack then you'll probably get back all 0xFFs due to the bus being inactive and pulled high.
  • JoJo Posts: 55
    edited 2008-10-01 21:37
    You can have a look at the Nunchuck code for a similar example. The nunchuck interface needs to read 6 bytes sequentially in one go.
    That example can be found at:
    http://forums.parallax.com/forums/default.aspx?f=25&m=294507

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    ---
    Jo
  • 4Alex4Alex Posts: 119
    edited 2008-10-01 22:15
    @Mike:

    Thank you for reminding me to add '1' to the base address for reading: I already knew that but while swearing (nono.gif) at the circuit, I simply forgot to increment the address in the code! I have corrected this mistake and I get the first segment properly. The rest of the data makes no sense at all...

    I have also implemented the 'reset' code mentionned in the DS, using the approach you suggested and this too seems to work. Thanks again.

    The following code does result in correct values for the first reading:
        'read data device
        '_i2cNAK         = 1
        '_i2cACK         = 0
        i2c.i2cStart
        i2c.i2cWrite($43, 8)  '$42 + 1 for read
        Ireg := i2c.i2cRead(i2c#_i2cACK)
        Creg := i2c.i2cRead(i2c#_i2cACK)
        Kreg := i2c.i2cRead(i2c#_i2cACK)
        Treg := i2c.i2cRead(i2c#_i2cNAK)
        i2c.i2cStop
    
    


    @Keith:

    Thank you for checking the datasheet. The least I can say about the DS is that it is written in an arcane way! Thank you for your suggestion to check the ACK bit. Simple question: how do you do that in an easy way?!?

    @Joao:

    Your posting is very interesting. Thank you for the Nunchuck object.


    Thank you all for your help.

    Cheers,

    Alex
  • Mike GreenMike Green Posts: 23,101
    edited 2008-10-01 22:22
    Reading the datasheet, the last ACK/NACK is used to tell the device to advance the FIFO or not. You probably want to use an ACK on the 4th byte read (Treg).
  • 4Alex4Alex Posts: 119
    edited 2008-10-02 00:36
    Somebody said...
    Reading the datasheet, the last ACK/NACK is used to tell the device to advance the FIFO or not.
    Dear Mike,

    You will never cease to amaze me! How in in the world did you found that?!? I will try this tomorrow morning and report.

    As for the circuit board, I unfortunately have to report that I have somewhat roughended a few pads...

    Many thanks again,

    Cheers,

    Alex
  • Mike GreenMike Green Posts: 23,101
    edited 2008-10-02 02:15
    It's on page 12 where they describe the interaction with the I2C protocol.
  • 4Alex4Alex Posts: 119
    edited 2008-10-02 15:39
    @Mike,

    Thanks, everything is working fine now. I had to repair a couple of pads, reprogrammed using your approach, and (not surprisingly) I can now read the whole register properly. Many thanks again for your help.

    Cheers,

    Alex
  • 4Alex4Alex Posts: 119
    edited 2008-10-02 22:36
    Hi all,

    I received a reply from tech support at Maxim regarding the MAX11041. Since they clarify the datasheet (and some errors in it), I tought it would be becoming to share this reply with you (just in case someone wants to use the IC in the future):

    Many thanks again to those who helped - its very appreciated.

    Cheers,

    Alex
    Somebody said...
    Hi Alex,
    |
    | It doesn't look like we have an example application to give you,
    | but I can clarify the operation of the device. First let's cover
    | reading and writing (pages and tables I refer to are all in the
    | datasheet):
    |
    | Because there is really only 1 register to write to (Control
    | Register), there isn't an address associated with that register.
    | The only write you can do is to modify the Control Register. This
    | is done by:
    | 1) Start Command plus Slave Address. It seems you've already got
    | this, but for clarification sake, the slave address is 01000
    | followed by the logic values of A1 and A0. Write is of course a
    | 0.
    | 2) Receive ACK from MAX11041
    | 3) Send Control Register Byte (Table 1); for normal operation:
    | (10XXXXXX)
    | 4) Receive ACK, Send STOP (This is all in Figure 5)
    |
    | When reading the device, you don't have control over what you
    | read. Follow this procedure (Figure 5):
    | 1) You first send your Start bit, Address byte, and 1 for read.
    | 2) The MAX11041 will then generate an acknowledge, followed by
    | the CHIP ID byte, which is all 0s for the MAX11041.
    | 3) You then send an acknowledge, and the MAX11041 will send back
    | the contents of the Control Register.
    | 4) Send another acknowledge, and the MAX11041 sends the Key
    | value. (I'll explain this a little later)
    | 5) Send another acknowledge, and the MAX11041 sends the Key
    | duration value.
    | 6) Send an ACK and STOP.
    |
    | So now that we have reading and writing down, I'll explain how to
    | get valuable information out of this. The part really works as a
    | voltage divider (with an internal resistor) with an internal ADC.
    | Each key you connect to FORCE/SENSE has a series resistor (See
    | Figure 2 for connections, and Table 4, columns 1 and 2 for
    | resistor values), and this determines the voltage seen by the
    | MAX11041.
    |
    | We are really only interested in the 5 MSBs of the Key Press
    | value. So if you right shift by 3 any received Key value you will
    | have a unique code (0x00 to 0x1F) for each specific key press.
    | Don't pay attention to the Keypress type bit names in Table 2. It
    | looks like the MAX11041 and 42 were switched.
    |
    | As for key duration, upon a key press, an internal counter
    | continuously increments the Key duration byte. See "Keypress FIFO
    | and Time Duration" on page 8 for details.
    |
    | When reading from the device, you'll get the latest FIFO value.
    | After reading, the value will be cleared and you can get the next
    | FIFO value by reading again. An exception to this is if you
    | happen to read a value of a key while it is still being pressed,
    | you'll get the latest information on that key (key value and key
    | duration), but the value will not be cleared. The interrupt will
    | clear, and the MAX11041 will send another interrupt once the key
    | has been released (see page 9). Bit 5 in the Control byte becomes
    | 1 when the FIFO has been cleared, i.e. there are no more key
    | presses to read (Table 1).
    |
    |
    | I hope this clears up your confusion with the MAX11041.
Sign In or Register to comment.