I2C dual bus question
Tapperman
Posts: 319
@Peter Jakacki, I saw in one of your threads you mentioned using SPI over the bus.
@All, has anyone ever hooked up another set of hardware on the bus with the clock and data reversed? And can the two buses co-exist in one bus?
... Tim
PS - [post=1326225]info[/post]
@All, has anyone ever hooked up another set of hardware on the bus with the clock and data reversed? And can the two buses co-exist in one bus?
... Tim
PS - [post=1326225]info[/post]
Comments
To use it, you place the code is two cogs and give one of them the reverse clock and data pins as the other has.
... Tim
You cannot support both at the same time they have to share in the time domain, with alternate access.
Test as follows
with two PCF8574's on a bread board ... one connected properly ... the other, has it's data and clock pins connected in reverse. Easy to do when you get old and suffer from vision issues.
both are jumper wire set to the same device address.
the one master then talks to either chip without confusion. one busses 'startbit' is ignored by the other slaves on 'back-bus' (their data pin is your clock pin) .... when the 'front' bus sends a startbit ... the back bus 'doesn't see it'.
... Tim
Probably ok on simplest HW slaves (like PCF8574 et al), but it may scramble the brains of a MCU based i2c slave, so you should test in all cases.
But, in practice ... I don't think I'm going to find but 2 varieties of the PCF8574. And, I think there is a 'A' version that permits another 8 devices on the same bus. For a total of 16 Expansion chips ... For me, this could be 32 Expansion chips with 8 quasi I/O bits each, on the same bus.
BTW, if the clock line stays high on the 'front-bus' and data line is toggled rapidly ... the 'slaves' start to listen on the negative edge for their device number, and then reset on the positive edge. For the back bus, the slaves see the clock raise and lower (for the same signal) but don't act on a signal since no start bit has been received. You could in concept transmit a 'anch. serial' burst without confusing the slaves. But I haven't gone that far yet.
... Tim
By swapping the pins as suggested, you could have unpredictable results.
If you need "lots of slaves" then also consider small MCUs., either on i2c or in a ring-bus.
Example :
Cheapest PCF8574 Digikey $0.504 @ 2,500 (1.25 1+)
vs MCU ( i2c, SPI, ADC, UART, PWM )
EFM8BB1 [2KF,QFN20] $0.31361 @ 1500 (42c 1+)
EFM8BB1 [8KF,SO16] $0.42268 @ 2500 (56c 1+)
addit - I also find this info on FLASH Programming these MCUs from Prop,
by Peter Jakacki
https://docs.google.com/document/pub?id=1CzYzYPhQGb8qpLi8Pw_2cHbRjZeOsWyg_ZyT5GaNp44
(will need updates to DEVICE SPECIFC area, for F850/EFM8 variants,
eg F850,BB1 are this in SiLabs SW
Uh ... when do you not depend on this logic? With I2C, that is.
... Tim
PS - Thanx for input on links ... alternatives are great!
I'd guess that a PCF8574 would be OK with many fast stop/start chatters, but anything with a MCU coupled to a i2c would need careful checking.
I have seen relatively simple (clocked) i2c slaves cough when even slightly outside spec.
OK ... point taken .... I put my parallax FM radio (I2C) on the bus and noticed it did have an issue. But, I programmed it to Startbit/Stopbit/Startbit/device# ... etc. And it worked ok.
... Tim
But, here is my question .... am I outside the specs? Why would it work at all? And then stop working later?
I use this attached monitor to 'see' how this works. Check it out yourself ... on a prop that has nothing attached to its IO pins ... then perhaps you can answer my question "am I outside the specs?"
... Tim
Here the word (you) refers to the bus master. Only one master may 'speak' at any instant.
rule 1 - when no activity is on the bus ... the data and clock line must be high. Often referred
to as the idle/bus free state. If the bus is not idle, you must wait for a stop\bit before
the bus can be considered idle/free again.
rule 2 - "when the clock line is 'high' the data line must not change" ... now, violation of this rule
is not 'the end of the world' ... it just changes the meaning of things a little.
rule 3 - If you violate rule 2, then your sending a 'start' or 'stop' bit (depending on the violation)
rule 4 - If you violate rule number 2 by lowering the data line ... you generate a start\bit. And
conversely, if you violate rule 2 by raising the data line, you generate a stop\bit.
rule 5 - If you follow a start bit by lowering the clock line ... the line is 'seized'.
... 7 bit device address, direction bit and 'ACK' ... etc. More rules than I care to list for now. Besides we need only examine these shown to explain the concept.
The bus is 'open collector' and therefore must have pull up resistors. So, if you have a conflict between any two confused 'slaves' that would attempt to communicate ... when they should not ... your hardware is 'safe'. I hope that everyone can see that ... and realize that I have in fact studied the effects closely.
In fact, I will make so bold as to claim 'I don't think you can harm a slave this way?'
So, regardless of which 'side' of the bus (front/rear) you configure a slave to ... both lines must be high for the bus to be considered 'idle' ... and line activity that does not conform to the rules above, is IGNORED by all slaves. On both sides.
As an example: a 8-1-N @ 9600 baud serial burst appearing on the DATA line would be ignored by both sides!!!!!!!! That's right, you can even send serial across the bus ... with no conflicts. However, the sender (need not be the master in this case) must watch for a 'stop\bit' before sending its burst, if any other master has seized the line.
All this is made possible, by rule #5. That's right .... before you can send a device# to any slave, you must lower the clock line first!
... Tim
The start bit should prevent either the normally-connected or the reverse-connected device from getting confused, and even if the opposite device does somehow see a start bit, it will only ever detect zeroes clocked in (sda only toggles while scl is low). I was intrigued enough to modify an old spin driver and test it with two eeproms, and it seems to work fine.
It is a bit of a kluge, but if you need more devices than there are address for, and don't want to create a second i2c bus, it's certainly a possibility. You're also correct that the PCF8574 and PCF8574A use different addresses.
I2C reversed test - Archive.zip
Can you point to an i2c spec that defines reverse connection behaviour ?
Not only are you outside specs, you are moving into territory the vendors are unlikely to have ever tested.
That means you do your own testing, for every vendor change & die revision.
As your own post #11 above shows, it may work, or it may have problems.
Your state assumptions are just that, and they exclude the time-domain.
They are likely to be ok on the simplest Logic based, no-internal-clock designs
I can see a use for this sort of library, eg for config, i2c debug terminals and setup uses where the 2nd bus is not present in the field.
It is the type of library that also needs a list of tested/proven devices, and device pairings, and some warnings....
It also does fit well on a Prop, which has the free-pin access.
Depends how you define harm
I have seen a general trend to include reset pins on i2c devices like RTC, which suggests repeated stop may not be enough to recover those state engines in all disturbance cases.
Well, my original question in post#1 was "Has anybody ever done this before?" I thought the people in this forum would be 'excited' by my 'blind reverse wiring by mistake' ... instead, most responses have been 'negative' (yours excluded) .... at least some-one out their in forum land actually TRIED my idea!
And, I guess that I can assume the answer to my original question is [size=+2]NO[/size].
Thankyou very much Chris,
... Tim
No,I have not tried your solution.
Your explanation a few posts above seems to make sense. I have not drawn out a timing chart to verify (insufficient time with other projects on the go) but it does make sense.
I have however successfully tried out sharing the /R and /W lines of a SRAM with SDA & SCL with no problems. In the way I use it, there is no possibility to get a valid I2C start condition registered on the I2C bus, and hence no conflicts can arise. My use of the SRAM is full on as I am running C code from it in XMM mode.
Back to your solution...
Since you have described a solution where it is not possible to get a valid start condition to be seen, the I2C device(s) will be fine. That is the pre-condition for the I2C to work. So provided you have correctly given an I2C device attached a valid stop, then that device will remain unselected and hence in an idle state waiting for a start, and this means it will not output on the bus.
Using a line for serial (half duplex) while the other line remains steady would likewise work. But you WILL NOT be able to send serial on both lines concurrently, for fear that a condition may meet the I2C start selection.
FWIW the SPI of the SD Cards have a situation where they do not release the DO line correctly at the end of a transaction. It is necessary to give it some extra clocks to clear down the problem.
BTW, to your question, sometimes it is only possible to find problems with a solution. That's what we look for. To fail to do so could result in all sorts of problems. We have to consider everything.
Sir .... I AM INSIDE the TRUE I2C specs. I do not wish to conduct an argument from this thread ... send me PM with any 'outside' issues you think may exist, and I will publicly state I'm 'outside' ... review my I2C monitor I uploaded for evidence in your argument.
I maintain I am assuming NOTHING at this point. You on the other hand are assuming the FM radio w/MCU is conforming exactly to the rules!!!!
It's all there for anyone to view ... and at least one other user of the forum has used it! But I'm not sure if you understand the problem? If you did, your comments may have been different?
really!
How?
... Tim
["I put my parallax FM radio (I2C) on the bus [B]and noticed it did have an issue[/B]. But, I programmed it to Startbit/Stopbit/Startbit/device# ... etc. And it worked ok."]
Voila, an exception case, provided by yourself - nicely done.
Claimed "rules" mean little in the real world - things work, or they have problems.....
Relax - Yes, it is a useful idea, but it needs care.
I can see a use for something like an Invisible Debug link to a Ptrop.- certainly saves pins, but has caveats.
Thank you for that excellent analysis!!! And my assertion did say 'DATA' line only.
... Tim
I mean 'Phil P.', 'Mike Green', 'Chip G.', 'Heater', 'Jonny Mac', etc.
... Tim
I haven't read all your posts because I was a little confused as to what you were asking. However I frequently reuse the I2C bus lines for SCK and MOSI to save a some I/O as SPI devices will not care what the I2C bus is doing as long as they are deselected. Conversely I2C bus devices will not care what SCL and SDA are doing while it does not sense a start condition so they are always "deselected". Using SDA as the MOSI ensures we keep control and do not inadvertently issue STARTs and STOPs. So when sharing these lines with SPI the MISO has it's own I/O input which could also be shared with other SPI devices too.
I also use Silabs CPUs for I2C slaves but I also take the SDA line as the C2D programming data input and control the RST/C2K line from a dedicated I/O. So sending serial data on the SDA line to program the Silabs parts does not affect other devices on the bus as they are "deselected". Even if SCL is left high while SDA is sending serial data it doesn't really matter if a START condition is sensed by other I2C devices as there is no clock. So SCL can be left high or taken low, it doesn't matter, as long as the bus is reset either by a proper START or STOP.
First, thank you for your input!!!!! I think the last time we text was when I ordered the wrong LCD module from one of your very old threads?
I was calling it 'open collector' in earlier posts. What I was 'hinting' at was that the slave would only 'output' when the device number was received ... regardless of direction.
However, the biggest danger is when the 'rear' bus thinks it has received a 'read' request from activity on the other 'side' ... which then will switch to 'active' output on any additional clock pulses ... what do you call it bit acc. (pull up resistors wont change state fast enough) or something? Meaning 'a problem exists' ... the open collector nature of the bus changes.
Thanks for expressing that better than I could ... my point exactly.
... Tim
PS - I had seen an earlier post where you mentioned SPI over the I2C bus ... and I chimed in with 'me too'. But, I don't know if you saw that or not?
NOTE - I do not simplify the state table ... easier to detect errors when left as is.
outputs
(SbD-I2C-SPI-Stp-Ovr)
[SbD] Start Bit Detected
[I2C] The clock line is lowered after the start bit to cause this event
[SPI] When I mix SPI on the same bus .... this pin shows the activity is not an I2C burst. NOTE ... a spike on this line followed by rapid start & stop bits indicates 'rear' bus activity.
[Stp] Stop Bit Detected ... bus is idle/free.
[Ovr] Over-run ... arriving bits are changing faster than the machine code can read.
... Tim
If the device on the 'rear' side was to falsely go from 'inactive' to 'outputting (READ direction), it's output would be on the FRONT sides 'clock' line ... which is an active out from the 'master' conducting bit talk with any given slave. And that would be an 'unwelcome' event in my hardware.
I saw the MCP23008 (idbruce is using in his project) does have a reset pin ... but the data sheet was unclear if the reset pin reset the I2C internal logic or if that pin was for the reset of /interrupt settings, direction registers, etc?
I've not encountered I2C slaves that refuse to reset?
... Tim
I don't believe that's a problem; consider that data (opposite device's clock) only toggles while the clock (opposite's data) is low. When one device puts a '1' on sda, the opposite bus sees a stop, followed by an idle state. When the '1' is clocked in, the opposite bus sees that as a start. If one bus sends multiple consecutive '0's or '1's, the opposite simply sees a long period with no clocks. It shouldn't be possible for the opposite bus to ever get into any trouble; it'll reset long before reaching an ack bit, and even if it doesn't, the only ID it could receive is $00. I sometimes run into problems with slaves not resetting, which I realized is caused by reloading some code at the precise instant that the slave is sending, in which case the slave might still be holding the data line low when the Prop reboots. This is easily solved by toggling scl until sda floats high, assuming that pullup resistors are used with an open-drain driver. A push-pull driver might damage something if the master is outputting a high for the idle state while the slave is still trying to send a '0'.
I took a look at your I2C monitor, but have no idea what I'm supposed to be seeing.
Chris
No, youre correct, its not a problem. I was responding to another message, to clarify what harm means for me. I was trying to define what the worst case scenario might be for the dual bus. IF and only IF it was possible and it is not therefore, the technique is sound and for those readers that dont wish to use it, I say Fine
I should not even have responded to that message. Its just a waste of time to communicate with some people who only seek an argument.
I was trying to ask a legitimate question of everyone on the forum. I just wanted to know if anyone had ever done this before? I searched the forum and could find no mention of it. And I refused to believe, that such a simple trick had gone unnoticed by absolutely everyone who has used it for the past 20+ years?
I already knew it would work, and I knew why it would work. A nice little side benefit derived from my bus monitor.
And you, just went and tried it first. Then you commented on it (nice). But my thread got hi-jacked, and spun out of control in a direction I really did not intend. By those who neither understood it or tried it!!!!
But thats the Achilles heel of this forum. I still have not received any replies to post #2, which was the real reason I started this thread!!!
BTW, I see you went through a ton of work to make that graphic!! Nice job. Can I borrow it for my docs?
Tim
PS - I'll document that Bus Monitor as soon as I have a 'half' day free.
Okay, I'm still confused. I don't know why you want to run code in 2 cogs when one will do since you can only access one device at a time, or am I missing something?
The bit where you say " I'm writing to support both busses at the same time" is confusing too.
Oops ... No, I lost my focus with all the distractions ... Now I remember, I wanted to try to simulate the open collector nature of the bus, and instead of wiring two CPUs together to try it. I thought I would just put them into one, and avoid the wiring.
Oh yeah, and I also did not document that the timer A in this arrangement is counting edges (negative that is) on the data line. That initialization code is not shown.
... Tim
The I2C Monitors’ principle of operation
Because of the move source (MOVS) command on the propeller, only the lowest nine bits matter in this approach. The direction register is set so the lowest 2 bits are inputs, and the remaining 7 bits are set to outputs. NOTE – no other cog may use the lower 9 pins while this code executes.
In the propeller, output trumps input and one trumps zero. So, whenever you write a value to the lower 9 pins of the output register. On the read of input register you will input only those bits from the outside that are set as inputs. The pins declared as output will read back the last value written for those bits by the command OUTA.
Figure: Propeller I/O Register configuration.
So, this simple 3 line loop moves the lower 9 bits of the state table to the lower 9 bits of the output register … of course, the lowest 2 bits are ignored. The next time the input register is read it will contain ‘feedback’ from the last OUTA command and input from the 2 pins that are ‘live’ or real time.
So this is the principle used in a state machine …. “what we do next, depends on where we have gone and what’s going on now?”
So how the machine behaves depends on the table that is loaded into the cog ram at startup. Now, the table itself has special rules … since we are trying to duplicate ‘dedicated’ hardware that could do the same thing … we must be mindful that the CPU is clocked. So it cannot operate at the speed of hardwired logic. Therefore, the layout of the table is such that each ‘row’ has but one stable state and the first row is the initial state on power up … for my use here, that means an input of ‘11’ is idle on the bus.
When the next state is the same as the current state … that state is said to be ‘stable’. When that’s not the case you’ve reached a transition state, and that will move you to a different row of the table.
Now, the columns of the table are arranged so the change of a single bit of input moves you either left or right in the table one column. Because of that, anytime a change of 2 bits occur from the last read of ina (or 2 columns in the table) … we know the machine is not able to keep up … and that generates an ‘error’ condition. I believe its sends the machine to state 36.
Now, the outputs are just “OR’d” into the upper bits (above 9) of the transition state table, along with the state values, and they are written to the output port at the same time the state is!
… Tim