Website Reference Documentation bugs for Wire lib.

The documentation on the Wire library is unclear in a few sections; the main problem is that it is not clear what functions can be called as a master, and which ones as a slave.

A suggestion to help make this clearer would be to do the following:

a) Page: Wire - Arduino Reference

change text:

address: the 7-bit slave address (optional); if not specified, join the bus as a master. You can initiate a connection to a device by address with the beginTransmission() / send() / endTransmission() functions whether you are a slave or a master; the only difference with using an address parameter on the begin function is that other devices can only initiate communications with this device if you have specified an address.

b) Page: Wire - Arduino Reference

change text:

Begin a transmission to the I2C slave device with the given address. Subsequently, queue bytes for transmission with the send() function and transmit them by calling endTransmission(). You can use this method, along with subsequent send() and endTransmission(), regardless of whether you have called Wire.begin() with an address or without one.

Please let me know if you have any questions.

Cheers

It's also not clear at all how to generate the Repeat Start sequence from the reference material.

I am not familiar with the Repeat Start sequence; would you be able to expand on what this is / what it does, and if possible write up a suggested documentation section for it? I'm hoping that if we can get all of the hard work (writing the content) done for the website admins, they will be able to just quickly copy / paste it up on the site.

Cheers

There is some danger here for making this more complicated than it needs to be. An alternative might be to just point out in the Wire intro that an Arduino may act as master, slave or both. A master only would call begin with no address, and the slave or slave/master would call begin with an address.

It's also not clear at all how to generate the Repeat Start sequence from the reference material.

It appears to be custom for manufacturers to include a substantial part of the TWI specification in their datasheets and when we interface a new chip some of us may read that section to check how we would go about fulfilling the protocol requirements (typically when it's not working as we expect it to first time around). The fact is however that bus timing, arbitration, repeat start, stop, reset and so forth is all handled by the atmega chip in hardware and there is basically nothing we (or the Wire library) can do about it. The Wire library core is just sending/receiving data as and when dictated by the Atmel hardware.

If there really was a protocol/timing issue between an atmega and an I2C chip we would probably need Atmel and/or the I2C chip manufacturer to fix the issue (e.g. with a revised chip design).

An alternative might be to just point out in the Wire intro that an Arduino may act as master, slave or both. A master only would call begin with no address, and the slave or slave/master would call begin with an address.

I would be quite happy even with this change. All I am concerned about is that the documentation seems to indicate (although it doesn't come right out and say it) that devices which joined the bus with an address cannot initiate a message to another addressed device. Anything which makes it clear, one way or another, that they can still initiate a transmission is fine with me. :sunglasses:

Cheers

wyatt, I'm glad you've volunteered to work on the Wire documentation as it needs a little.

Basically, the Repeated Start condition on the I2C bus is said to have occurred when during data transfer the Master reasserts the Start condition without sendig stop, thereby not relinquishing the bus. If a master receiver sends a Repeated Start condition, it has previously sent a not-acknowledge (!A).

This is used when the direction of data transfer is reversed during the transaction and it is important that the Master doesn't release the bus to another master. For example, The Master addresses the Slave with Write set, the next byte is a command to read a register, the Master then asserts a Repeated Start by resending the Slave address with Read set, the Slave sends the register data, then the master sends Nak and Stop.

The Wire documentation is relatively clear on transactions that are unidirectional but not on the ones where the data direction changes during the transaction.

A master only would call begin with no address, and the slave or slave/master would call begin with an address.

This untrue and should be addressed in the documentation as wyatt has suggested.

The fact is however that bus timing, arbitration, repeat start, stop, reset and so forth is all handled by the atmega chip in hardware and there is basically nothing we (or the Wire library) can do about it.

The fact is that the AVR TWI hardware is programatically commanded to do Start, Repeat Start, Read with Ack, Read with Nak, etc. It does handle bus timing but arbitration is both the responsibility of the programmer and the hardware.

It is true that we programatically initiate a start, but it will not appear on the bus until the atmega determines that the bus is ready. It is also a fact that a repeat start is initiated exactly as a start and is reckognized as repeat start only because the atmega knows it already has control of the bus.

The Wire libary is an abstraction layer (we want to send and receive data) and my point is simply that protocol specific details are better dealt with in other sources.

"repeat start" is as far as I can see not supported/used by the Wire library in master context (in slave mode it will be supported/honored through the atmega TWI state engine). You may want to propose this as an enhancement rather than a documentation issue.

It is also a fact that a repeat start is initiated exactly as a start and is reckognized as repeat start only because the atmega knows it already has control of the bus.

It is not irelevant that the Master knows that it has control of the bus, it is important that the other members of the bus not try to seize control and they know to do this because instead of programatically issuing a stop condition the program must initiate another SLA+rw sequence to turn the bus around. Repeat start is used when the master wants to reverse the direction of data travel on the bus while not providing any chance of losing the bus to another device.

The Wire libary is an abstraction layer (we want to send and receive data) and my point is simply that protocol specific details are better dealt with in other sources.

That is all well and good until a library abstracts to the point of making it impossible or very difficult to do a common task. Many devices require the Repeat Start condition in order to use them.

"repeat start" is as far as I can see not supported/used by the Wire library in master context (in slave mode it will be supported/honored through the atmega TWI state engine).

Then this is in direct conflict with the TWI specification and needs to be corrected. Or if it is simply a case of the documentation not defining how to accomplish it, the documentation needs to be edited.

You may want to propose this as an enhancement rather than a documentation issue.

I would expect to get tires on my car without having to suggest it to the dealer. :smiley:

With all respect Emiliy the arguments are getting pedantic, but it may be that I fail to realize what you're after.

The "requestFrom" function will initiate SLA+R, reverse the bus and receive any number of bytes as per your request without giving up the bus.

If on the other hand you (as a master) want to send AND receive data without giving up the bus - this is not supported by the library. Likewise I do not see support for exchanging data with multiple slaves without giving up the bus in between.

What is that you're after and what chip will require this?

With all respect Emiliy the arguments are getting pedantic, but it may be that I fail to realize what you're after.

With all due respect, I believe it is the latter because I would not waste my time on pedantry. I have a legitimate question and it seems rather than answer it you insist on waving it away. I am far from stupid and I wouldn't be expressing these concerns if I hadn't thought them through.

If on the other hand you (as a master) want to send AND receive data without giving up the bus - this is not supported by the library. Likewise I do not see support for exchanging data with multiple slaves without giving up the bus in between.

A normal exchange with a device with a command register and the capability of returning data would be to do an SLA+w followed by the address of the register then SLA+r to turn the bus around and read bytes, ACK-ing each one until it's none and then issuing the NAK.

What is that you're after and what chip will require this?

I'm after a better explanation of the functions in Wire so that I can communicate with devices like the SCP1000 absolute pressure sensor and the (NXP/Phillips) SC16IS750 chip and others that require the Repeat Start in order to work.

I have already solved this problem by supplementing Wire's apparent shortcomings myself. It is unclear to me how your suggestion to use "requestFrom" will solve the problem as it doesn't allow for specifying a command register.

I've been happily communicating with I2C devices for almost two decades now and I assure you I would not be asking these questions just to annoy you. Perhaps you could take a break and let someone else take a crack at answering my questions.

I have the highest regards for your contributions in this forum and the competence you share and I'm not implying in any way whatsoever that you are stupid - quite the contrary.

I am not a beginner in this field either and have more years of professional experience with low level software development than I care to admit. Nor would I add to this topic unless I knew it well.

It's also not clear at all how to generate the Repeat Start sequence from the reference material.

With your intimate knowledge of the I2C specification, you will also know that it is impossible to discuss this topic without breaking it down to master/slave transmit/receive and I could only assume you wanted general information on the I2C protocol to be included in the documentation. From your last post however I understand know that you had a specific need.

A master only would call begin with no address, and the slave or slave/master would call begin with an address.

This statement is indeed true and it suggests to me that you may not be intimate with the Wire library. Nor do you offer an explanation to why it would be incorrect.

TWAR = address << 1;

When you call begin with an address above code is all that happends. The address will simply be loaded into the I2C TWAR register. As you know this is used by the atmega to recognize when it's being addressed as a slave. It is used for nothing else whatsoever within the wire library.

The Wire library approach to what you request would be as follows:

  beginTransmission(address);  // saves copy of address
  send(chip_reg); // buffer data
  send(chip_sub_reg); // buffer data
  endTransmission();  // send as twi master, end with stop

  requestFrom(address,count); // receive as master, end with stop
  while (available()) {
     data=receive();
    // do something useful
  }

The stop sequence is issued within the ISR that handles TWI state callbacks and there is no way to use the high level API that would allow a send/receive operation to take place without the stop as it is written today.

I have used a number of I2C chips that support repeat start, but I've not run across any that will not also work with a bus release in between.

There are other issues however that have bogged me and I've created a version that address the following:

  • smaller memory footprint (isolate master/slave code with a conditional define)
  • use static buffers rather than calloc
  • add non-blocking versions of the master transmit/request functions with callbacks

As for a function that would combine transmit/receive without releasing the bus would not be much of an issue to add, but I trust you have figured this out already.

Quote:
A master only would call begin with no address, and the slave or slave/master would call begin with an address.

This statement is indeed true and it suggests to me that you may not be intimate with the Wire library. Nor do you offer an explanation to why it would be incorrect.

I am not intimate with the Wire library, hence these questions. In wyatt's initial post, he explains that a master can call begin with an address. There doesn't seem to be a need to differentiate between a master and a slave /master because it appears that the only difference is that the slave/master is a master that has an address. If there truly is a difference, then you need a category in your statement for a master that has called begin with an address. At any rate for you to declare that a master would not call begin with an address seemed untrue.

As proof of concept wyatt posted this sketch where he shows that muuli-masters are indeed supported by wire:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1248239313/5#5

When you call begin with an address above code is all that happends. The address will simply be loaded into the I2C TWAR register. As you know this is used by the atmega to recognize when it's being addressed as a slave. It is used for nothing else whatsoever within the wire library.

If you read the 328 data sheet:

The TWAR should be loaded with the 7-bit Slave address (in the seven most significant bits of
TWAR) to which the TWI will respond when programmed as a Slave Transmitter or Receiver,
and not needed in the Master modes. In multi master systems, TWAR must be set in masters
which can be addressed as Slaves by other Masters.

It would appear that Wire does support multi masters.

I have used a number of I2C chips that support repeat start, but I've not run across any that will not also work with a bus release in between.

Well I can assure you that the two that I mentioned don't support it, they require it. It would seem that the devices you are familiar with that tolerate the bus release could not publish that they are I2C compatible. They certainly would not be usable in a multi master network that expected compliancy.

Your statements have reinforced my belief that Wire does not support repeat start. The functionality may be there however and has just been buried in the abstraction. I intend to continue studying it anyway.

Peter Fleury has a very nice collection of functions that I have found let me implement I2C fully. They are at this web site if anyone is interested.
http://homepage.hispeed.ch/peterfleury/avr-software.html

Thanks for your help. I appreciate the time you have taken to explain things.

At any rate for you to declare that a master would not call begin with an address seemed untrue.

It states specifically that the "slave/master" would call begin with an address.

slave/master would call begin with an address

From the 328 datasheet quote you provided there is wording to the same effect:

The TWAR should be loaded with the 7-bit Slave address (in the seven most significant bits of
TWAR) to which the TWI will respond when programmed as a Slave Transmitter or Receiver,
and not needed in the Master modes.

The change I proposed to the wire documentation was indeed meant to suggest that Wire will support a combined master/slave mode which obviously would be of no use unless you have multiple masters on the same bus.

The NXP PCF8563 is an example I2C chip that works equally well with bus release between register addressing (write) and data read. It is not a matter of being "bus tolerant" as the register address is latched and the chip will retain its current register address pointer until read after which it will conveniently auto increment. This is perfectly valid and also in compliance with I2C specification.

The presence of other masters on the bus does not in itself violate this design. If the same chip however would serve multiple masters, the use of "repeat start" would be a design imposed requirement for this particular application.