I2C.... I am u can C I am 2 Confused.. help!  - Page 1
Forum section: electronics / general

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 06:33:00 pm
content: I am trying to communicate between two PIC 16F886 MCU using the built-in I2C functions, but I cannot understand how to do this after carefully reading the Microchip 16F886 datasheet and another appnote dedicated to I2C!I assume I will have a subroutine called from main() SendBytes(void) on the Master and Slave MCU's that will handle the reception of data and the transmission of data back to the Master.Firstly, each MCU must have an identifying address, but the somehow the SSPADD register is used to set the I2C clock frequency Baud Rate Generator..huh!Why should the I2C clock rate depend on the MCU address?Question 1: How do I set up the addressing for the ID's of the MCU's ??Question 2: How do I switch around from receiving to sending bytes back to the Master.I want to send and receive bytes between the tho MCU's. So, I configure one as Master and the other as i2C Slave operation.But how to set the ID address?I am certainly willing for both of them to have the same default address of 0 if that would work?Secondly, I want to send commands and data to the Slave and receive data back from the Slave. I figure upon 22 to 40 bytes to be sent each communication session. Now, that is a lot of time(even with a 20 MHz Xtal) to spend in an TMR0 IRQ that only lasts fpr 100 uSecs before it is called again, so I guess I must call the SendBytes routine from main() every millisecond or so to sync to keep both MCU's on the same page.Trapping a milliscecond in passing is no problem, I have timer code adding up 100uSec IRQ's events to count 100uSec to get 1mSec...10mSec,hun_mSec, Second, Min etc. counter code working perfectly.I know I can test for the SSPIF flag if it is set and then set a var called I2CRdy = 1 to tell my main() code that a new transmission has started and I can test for i2CRdy in my main() code loop..but will the Master MCU wait for the Slave while the SendBytes() position of my main() code is slowly being reached?Will the I2C transmission wait without a problem during my TMR0 IRQ interrupt service routine interrupts my SendBytes() (this is the name of my routine that receives/sends the correct bytes with both the Master<-->SlaveQuestion 3:How do I make the switch around at the Slave from Receive to Transmit?I can prescribe the order of all bytes sent, so each byte can be identified as a command or data by it's byte number position in the stream and even the last byte could be a checksum byte to verify the bytes are correct..no problem.Can I just start out by sending the address with a write bit, sending say, 4 one-byte commands next? Then I need the MCU's to switch roles and the Slave to send 20 ti 30 approx. bytes of data back to the Master.How to do the switch around?I can see from the datasheet that the SSPIF is set when a Start condition is initiated, a Stop condition is completed, when the receive buffer is full, etc. but how do I get my main() routine to respond in time to the start of a new communication session since it is in the main() program code loop, that is, the code is out of the IRQ handler and code the switch around from receive to transmit bytes back to the Master?At this point I am totally confused about how to do this. what register flags to set, which ones and where and what I am doing??

author: 22swg
author_rank: Frequent Contributor
timestamp: July 30, 2014, 06:56:29 pm
content: Many have fallen at the I2C fence... you need to follow the I2C communication sequence , strongly suggest you read the MC pdf AN735 it has some .asm code examples but if you are using C then presume you will be including a lib ... or code your own ! however .... slave has I2C device address, a 7 bit code , (avoid 00-0F ) masters don't and they dont switch roles master sends a  slave address and a write data , if a read is required then master sends a restart and switches on receiver and waits for data . there are acks nacks and stops also ! piece of cake....

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 07:02:06 pm
content: Thanks 22swg. Helping me with the adressing problem makes a difference. I will take a look at at An735. -Unfortunately, my programming language is strictly Hi-Tech ver 8.63 Pro C for MCU's. I don't understand how I or anyone else could do anything complex and then try to debug .asm code, so tedious a job..so much hard to fathom machine code using Assembly.I am still unsure on how to set the address of the Slave MCU. I know I can detect it? Am I just to compare the incoming byte to the one sent by the master to know it is the Master talking to the Slave. (After all in this case of only two i2c devices, the only transmitter is the Master MCU, so the Slave's address is set by comparison of received address?I got it!.all i2c devices listen to all transmissions and wait for their number(address) to show up!I have been able to get i2c to work with reading and even programming a MC 512k bit SEEPROM of the i2c type, but that is far different from two MCU's trying to converse with each other. In the SEEPROM case, I set the address to 1 by SEEPROM pins.I assume from what you say I should do the following sequence (in pseudo code)://Master to Slave:SEN=1; //Set SEN (start enable bit)Wait4SSPIF2Clr(); //Waits for SSPIF and SEN bits to clear?SSPBUF=(Addr | NotWrite_bit); //and now Transmission of 8-bits and ID address of Slave begins to be streamedWait4Ack2BeRecieved(); //Waits for ACKSTAT bit =0 from slave after address and write command sent to SlaveRSEN; //RestartSSPBUF=Command1_2Slave;Wait4SSPIF2Clr(); //Waits for *ACK or maybe SSPIF and RSEN bits to clear? I wonder which?SSPBUF=Command2_2Slave;Wait4SSPIF2Clr(); //Waits for *ACK or maybe SSPIF and RSEN bits to clear? I wonder which?.......... //Several command/data bytes have been sent OK to Slave?PEN=1; //Set Stop condition or just RSEN bit set? This is where I am getting lost! Do I need to check a SSPIF or ACKSTAT bit?RSEN ; //RestartWait4SSPIF2Clr(); //Waits for SSPIF or what? to clearRCEN=1; //Master Enters Receive Mode: Receive Enable Bit SetWait4SSPIF2Clr(); //Waits for SSPIF or WhatBitFlag?? to clearLoop:Byte=SSPBUF;if(n<numbytes2Receive) goto Loop; //Loop until bytes 0 to n are received in order in SendBytes loop until predetermined byes received finishesPEN=1; //Stop transmission..end of session?Can anyone see if this psuedo code is correct or help me find the flaws?

author: 22swg
author_rank: Frequent Contributor
timestamp: July 30, 2014, 07:23:56 pm
content: Got you... I have coded a PIC16F1847 as a slave, to a PIC24 I2C master sends command bytes slave sends back data it was written in MPLAB assembly , Ive not used I2c library for C. slave has to be interrupt driven with a fifo buffer .This may help ... or confuse , from master to request byte from slave lcd / keypad .void I2C_req_from_PB(){I2C_start_W(LCD_BP_addr);I2C_sendB(0xF7); // COMMANDI2C_sendB(0x99); // 2 BYTES backpack status..I2C_endtx();I2C_start_R(LCD_BP_addr);I2C1CONbits.RCEN = 1;while (!I2C1STATbits.RBF);inkey = I2C1RCV; // SLAVE RETURNS A BYTE..I2CNak();I2C_endtx();I2C1CONbits.RCEN = 0;}EDITISSSPADD=0x22; valid code ?FOR THE 16f184725.5.1 SLAVE MODE ADDRESSESThe SSPxADD register (Register 25-6) contains theSlave mode address. The first byte received after aStart or Restart condition is compared against thevalue stored in this register. If the byte matches, thevalue is loaded into the SSPxBUF register and aninterrupt is generated. If the value does not match, themodule goes idle and no indication is given to the softwarethat anything happened.

author: dannyf
author_rank: Super Contributor
timestamp: July 30, 2014, 07:59:07 pm
content: QuoteWriting a slave isn't for the faint of heart. It is (alot) easier with a hardware module and much harder with a bit bang slave.

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 08:05:14 pm
content: According to the SpecSheet for the 16F886, you cannot access directly the SSPADD reg unless the MSSPI mode is set to a special mode. For some odd reason the SSPADD reg bits set the Baud Rate Gen Freq.

author: SirNick
author_rank: Frequent Contributor
timestamp: July 30, 2014, 08:08:24 pm
content: I keep my own Cliffs Notes references on stuff like this, to get me back up to speed on stuff I don't use everyday. i2c is one of those things. Most of this is condensed from the typical online references, but organized into something easily digestible. This is device-agnostic, but maybe it will help clear things up?Synopsis:--------------------I2C uses a bi-directional bus topology, using two wires: Serial Clock (SCL), and Serial Data (SDA).Devices are individually addressed and communicate via a master/slave relationship. Any device can claim mastership by taking control of the clock and initiating communication. Slaves only communicate in response to a query by the master.Communication is usually between a master and a single slave, though it is possible to initiate a broadcast, called a General Call, by writing to a special address (0x00).SMBus is a subset of I2C. Vendors may use other names to avoid trademark infringement, such as Two-Wire Interface (TWI).Electrical:--------------------Every device is connected to the SCL and SDA bus via an open drain interface. The bus voltage is not defined, but is often 3.3v or 5v. The bus idles high via a pull-up resistor, and is pulled LOW by a device to transmit. In this way, devices with differing supply voltages can communicate, provided they are tolerant of the bus idle voltage. This can be accomplished through the use of clamping diodes or active level converters.The bus must have a total capacitance of 400pF or less to retain the transition edges at higher speeds, otherwise active termination may be necessary.Bus:--------------------All nodes on the SCL and SDA lines are connected in parallel, along with a pull-up resistor to Vbus. Devices become high-impedance when they are not transmitting.Data rate is determined by the serial clock, which is generated by the master, and runs only while devices are actively transmitting data. The actual clock speed is abitrary - the master can pulse the clock at any frequency up to its maximum, determined by the following speed classes:10kHz Low Speed Mode 100kHz Standard Mode400kHz Fast Mode 1.0MHz Fast Mode Plus [Fm+]3.4MHz High-Speed Mode 5.0MHz Ultra Fast Mode  (requires active pull-up)These modes determine the maximum speed at which a device can (or is configured to) communicate. Devices do not negotiate their capabilities, so the designer must ensure all devices are limited to the slowest on the bus.In practice, the actual maximum throughput will be reduced to some degree by interaction of the devices on the bus, and the electrical characteristics of the bus itself.During the clock's LOW phase, any device can hold SCL LOW as a method of flow-control. This is called clock stretching, and is commonly used when a device needs to prepare its data buffer, process data, or prepare a response. The transmitting device must monitor SCL after releasing it, and wait until the line floats high before proceeding.The actual rise time will be affected by the electrical properties of the bus -- that is, the pull-up resistor's value; the inductance of wires, leads, and traces; and the total bus capacitance.On the data bus, a binary zero is represented by logic LOW, and binary one is represented by logic HIGH. A bit is written by pulling the clock line LOW, holding SDA as required (either pulling it LOW, or letting it float HIGH), waiting for the bit to propagate, then allowing SCL to float HIGH. As other devices notice SCL is HIGH, they will read the bit on SDA. After a suitable period of time, the transmitting device can pull SCL LOW again and write the next bit.A reasonable hold time for 100kHz bus speeds is 4uS. (Each cycle takes at least 10uS at this speed.)If two (or more) devices attemp to claim the bus at the same time, the SCL pulses will appear to be stretched by the slower of the two devices. This does not inherently indicate a fault to any device on the bus. The transmitting device(s) must also monitor the SDA line in a process called arbitration. Since the SDA line idles HIGH, a transmitting device will only detect a collision when it attempts to signal a binary one (SDA HIGH), but reads back a zero (SDA LOW) instead. Upon detecting this condition, the transmitting device should yield and wait for the bus to become idle again. This carries on until one device wins by nature of sending the first unique binary zero.It is theorhetically possible for multiple devices to simultaneously transmit identical messages unbeknownst to each other, but if this happens, the net effect is still a successful transmission.Addressing:--------------------Devices functioning in a slave capacity are programmed to respond to an unique address. If the master device will never operate as a slave, its address is optional. Slave devices respond in a transactional model -- that is, the recipient of the slave's transmission is implied -- so only the master's initial query is directed to an address. The slave's response immediately follows the initial query, still clocked by the master. The slave will hold the SCL line LOW, if necessary, to provide time for internal processing.Addresses are either 7-bit (most common) or 10-bit.In I2C, slave devices are often simple components with very little intelligence. Their address is sometimes fixed, or partially fixed with programmable least-significant digit(s). This can limit the number of similar devices that can coexist on a single bus, and may even cause conflicts between different devices that happen to respond to the same address.Protocol:--------------------I2C defines only a minimal transaction framework. Each device will build upon this simple process with higher level protocols to provide whatever functionality it is meant to offer. Everything above the basic transport mechanism is application-specific.In a typical I2C implementation, the master device will be a microcontroller, and slave devices will be single-purpose components, such as temperature sensors, fan speed monitors, or ADC/DACs. With simple devices the command structure will be minimal -- perhaps only returning or accepting a raw data value in response to a read or write query.Devices with some minimal state awareness, such as EEPROM chips or user interface controllers, may require bidirectional commands to first request a data address (memory location, button, or indicator), and then write to, or read from, that address.More complex implementations may devise a packet-oriented "multi-master" scheme, where a device writes a message to another device, ends the I2C transaction, then waits asychronously for any further reply. In this case, devices may participate in both master and slave roles.In an I2C transaction, an active device can be in one of four modes:Master Transmit - The device initiated the transaction and is sending data to a slaveMaster Receive - The device initiated the transaction and is receiving data from a slaveSlave Transmit - The device is sending data to the masterSlave Receive - The device is receiving data from the masterTo begin a transaction, the master device will send a START bit, the target device's address, then a READ/WRITE flag bit to define the intended operation. The slave sends an acknowledgement (ACK) bit if it is present and able to communicate, then the transfer occurs as indicated by the read/write flag.If the master wishes to write data, it will proceed to do so, waiting for an ACK bit after each byte. In a read operation, the master retains control of the clock while the slave writes to SDA, with the master sending an ACK bit after each byte.To abort a transfer, the receiving device can send a NACK bit at the end of a cycle. The master may then send a STOP bit to release the bus.Frame Format:--------------------All data is sent in MSB (most-significant bit first) order.While the bus is idle, both SCL and SDA will be HIGH. To start a transaction, the master device will pull SDA LOW to indicate a START bit, then pull SCL LOW. The master will then send the target address and READ/WRITE bit. Each data bit is written to SDA while SCL is LOW, and read by all devices while SCL is HIGH.v Data sampled here_____|__ | ____________SDA | \______|_<____________>..._____|______ | ______SCL | \__|____/ \___...| |IDLE | START | ^ Data written hereBinary zero is indicated by pulling SDA LOW, and one by letting it float HIGH. The READ/WRITE flag is READ when SDA is HIGH (1), or WRITE when SDA is LOW (0).After writing the final bit to SDA, the master will release and read SCL. If any other devices are stretching the clock, SCL will remain LOW until they acquiesce, and then SCL will return HIGH again. (This is the 'read' portion of the final bit's cycle.)The master will then pull SCL LOW again and release SDA -- this is the start of the ACK cycle. The slave device is then expected to acknowledge the data by pulling SDA LOW. After waiting one typical clock cycle, the master will release SCL and examine SDA for the ACK bit.v SDA set by master v SDA set by slave_____|__ | | _________ | | __________|_SDA | \______|____________|_/ ...\__________|_/ | \__________..._____|______ | _____ | _____ | _____ | _____ | _____SCL | \__|___/ \__|___/ \_...__/ \__|___/ \__|___/ \__...| | | | | |IDLE | START | Addr6 == 0 | Addr5 == 1 | Addr0 == 0 | READ Mode | ACKAn ACK bit is asserted when SDA is LOW, or NACK when SDA is HIGH. In this manner, if a device does not respond to the given address, the idle bus will intrinsically signify NACK.If the query was acknowledged, the transaction continues. If the master wishes to write, it will begin sending one byte of data, followed by another clock pulse during which the slave should provide an ACK bit. Further bytes will be sent in this manner until the master completes its transfer, or receieves a NACK reply.In a read operation (after sending address and READ bits), the master watches for ACK. Once received, the slave will begin transferring data. The master continues generating the clock, but the slave can stretch each cycle as necessary. The master must generate an ACK after every byte. If the master is no longer interested in receiving more data, it can generate a NACK to end the transfer.At the end of a transaction, the master is required to release the bus with a STOP bit. It does this by pulling SDA LOW, releasing SCL, then releasing SDA. To begin a new transmission, the master can issue a RESTART condition. In this case, the master holds SDA HIGH, releases SCL (HIGH), then pulls SDA LOW again._____|__ __|____ ____|__ _______SDA | \______ ... ______/ | ... | \______ ... _/ \______..._____|______ ______|____ ____|______ _______SCL | \__ ... __/ | ... | \__ ... _____/ \__...| | |IDLE | START STOP | IDLE | START RESTARTThe only time SDA is changed during a HIGH clock period is during a START, STOP, or RESTART condition. This is useful to determine when the bus needs attention. When SDA falls while SCL is high, a device has claimed mastership and will be sending an address byte. This can be used in an interrupt service routine, or as a hardware trigger, to wake a device from sleep mode and/or begin monitoring for traffic. Once the address is transmitted, the receiver can decide whether any further action is necessary until the next START/RESTART condition.If a device is waiting with queued data, it can watch for a rising SDA on SCL HIGH. This indicates the bus is returning to an idle state and is ready for a new transaction.

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 08:10:39 pm
content: This really confuses me..setting the i2C baud rate with the SSPADD reg.FOSC=2000 //20mHz//code to initialize i2c operation:SSPADD=FOSC/((4 * i2cFREQ)+1) //clock 1mHz and the SSPADD register is not directly accessible!Also, do I need to use another I/O bit of the Slave or Master MCU to stretch the Clk low state in case of the IRQ is being serviced on one of the MCU's and while a byte that was still in the process of sending/receiving bit transfers is incomplete? Is this handled by the MCU's own hardware/firmware? Do I need to halt other IRQ's during i2c handling ?Should each byte to be sent/received be handled strictly in a portion of code in the general purpose TMR0 ISR so that it is not interrupted ? This limits Receive/Transmit to one byte per IRQ or restarting the ISR by setting some flag. This means that a receive or transmit byte may wait up to the 100uSec ISR interval, no matter if it is for the Master/Slave, while the respective Slave or Master itself is also doing code inside a ISR and so it is the one that is being held up from completing, thus upsetting timers/counters that must be updated/incremented at 100uSec intervals.

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 08:28:40 pm
content: Thanks SirNick, I copied your excellent help and printed it out and saved it in my programming notes!It does clear up some of the somethings, but leaves some questions(as I show in last response) yet to be answered..the devil is in the details.

author: 22swg
author_rank: Frequent Contributor
timestamp: July 30, 2014, 08:30:32 pm
content: Perhaps the 886 has a bug... this its data sheet ,," SSPADD Accessible only when SSPCON register bits SSPM<3:0> = 1001. (load mask function )"perhaps ? set SSPCON 'load mask function' write the slave address , switch SSPCON back to slave mode ?I would do it in MPLAB sim and hopeSlaves don't care about clock ! they can hold on to it but thats all...----------------------------------------In I2 C Slave mode:SCK release control1 = Enable clock0 = Holds clock low (clock stretch). (Used to ensure data setup time.)----------------------------------------------------------------------------The SSPCON bit 4 holds the clock while you look for the data....

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 08:45:07 pm
content: Ok, Slaves don't care abut the Clk, but what happens when a TMR0 ISR is called periodically and on schedule during a byte transfer in my SendBytes routine and the the byte is not yet been finished sent/received?[bThe Master controls the clock, how can the Slave know how/when to so quickly stretch the clock to tell the Master it is not ready for the next clock pulse(yet.)

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 08:54:09 pm
content: Ok, so I can stretch the clock low with the SCK release control, so I figure out how to check at the beginning of the ISR call to see if a byte transfer is in progress using one or more flags to tell if my SendBytes() routine was in the process of sending/receiving a byte..sounds like maybe set my BusyByteStatus var in my SendBytes code when after loading the SSPBUF in transmit or after checking the SSPIF flag in Receive for a low condition to be able to get the ISR to know what SendBytes is up to and stretch the clock low?Problem is, it takes approx several uSec for the ISR code to save status and flag registers values before before the ISR begins execution!Thank you very much again, 22swg, for your kind help!

author: 22swg
author_rank: Frequent Contributor
timestamp: July 30, 2014, 09:08:21 pm
content: Just tried in MPLAB with 886SSPCON = 0x29 ; enable mask writeSSPADD =0x12 ; slave I2C device addressSSPCON = 0x2E ; back to slave modeworks in MPLAB SIM( left out bank changes)TMR interrupt ... ? will scratch head !Would clearing TMR0 as the sendbytes starts up work ?

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 09:11:41 pm
content: SSPADD=FOSC/((4 * i2cFREQ)+1) //SSPI baud clock should be set to 1mHz and yet the SSPADD register is not directly accessible!

author: 22swg
author_rank: Frequent Contributor
timestamp: July 30, 2014, 09:15:25 pm
content: SSPADD is only baud rate in master ( your SSPADD=FOSC/((4 * i2cFREQ)+1) //clock 1mHz) . Its address in slave no baud is set ...If you clear the TMR0 registers to zero, not the flags, would that work....

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 09:30:25 pm
content: Ok, setting SSPADD works fine, since I do not at all set the baud rate for the Slave, it is clocked by the Master.Seems you can set SSPADD to 0x12, and that address value is retained until the SSPI i2C module is disabled.Clearing T0IE or setting TMR0=0 would definitely work on the Slave's side of the fence, but clearing the T0IF flag would not.Not allowing the T0IE will definitely slow down, thus screwup the timers/counters of the ISRs for the Slave.Perhaps I should keep only one set of books..I can send the correct timer/counter values to the Slave to update them for the operations on the Slave, so there is just a millisecond delay or so between updates when timings are correct again I need only to sync the pt1_mSec, millisecond, ten_mSec, hun_mSec, Sec, Min counters to the Master at the end of transfer of commands and data of Master to Slave. Six more bytes to travel the MCU highway.

author: free_electron
author_rank: Super Contributor
timestamp: July 30, 2014, 09:50:36 pm
content: Quote from: SirNick on July 30, 2014, 08:08:24 pmnot true. most devices actually use the falling edge of SCL to latch the SDA as they don;t have an internal timing generator.Quotenot true. the master will release tristate its SDA driver after the falling edge of SCL on the last bit. At the falling edge of the clock the slave will initiate the pulling low of SDA, or pulling low both SDA and SCL if it acknowledges + stretches.the master will now check to see if SDA is low BEFORE it will raise SCL. a low means acknowledge.if a valid acknowledge is detected the master will release the SCL and verify the SCL went high. it will wait until SCL goes high. and then it will pull SCL low to complete the ack cycle and stretching cycle.any other way of doing it has the risk of creating a false STOP or START operation as there is a risk that SDA toggles while SCL is high ( STOP or START)

author: SuzyC
author_rank: Frequent Contributor
timestamp: July 30, 2014, 10:14:46 pm
content: Especially high praise and thanks to all for their help and i2c errata, super-thanks to 22swg, I will now get the code into the MCUs, while also ask all here to notice that his profile's motto is very sage advice as well.

author: SirNick
author_rank: Frequent Contributor
timestamp: July 30, 2014, 10:47:06 pm
content: Thanks for the feedback. Got a question for ya though...Quote from: free_electron on July 30, 2014, 09:50:36 pmThat makes sense, and is a bit of hardware trivia I hadn't thought about. But just to verify -- do you meanreadlatch orwritelatch? I hope you meant write latch, since if the slave devices latch (sample) the line while SCL is LOW, that would present a race condition between assert and sample, wouldn't it?I.e., are we debating whether write latching is done on SCL==LOW or HIGH, or just if it's mid-cycle or on falling edge? (The latter seems totally reasonable to me.)Quote from: free_electron on July 30, 2014, 09:50:36 pmOops, you're right. I need to change that. As written, there would always be an ACK since the master is still holding SDA LOW. (The associated diagram is correct, though ambiguous, since SDA was already HIGH from the example READ mode bit.)Actually... Re-reading the entire paragraph in context, that's what I said: The master will write (latch) the final bit, tristate SCL, wait (this is the read portion of the final bit's cycle), assert SCL LOW (now we are in ACK cycle), tristate SDA, then wait for the slave to ACK. I have re-written this part to be more clear though.So, thanks for pointing out that my text was prone to confusion.Quote from: free_electron on July 30, 2014, 09:50:36 pmHm... I don't know. The way I see it, the slave should be holding SCL LOW until it has asserted SDA (or specifically not) -- thereby negating any risk of toggle during SCL==HIGH. The slave should have had ample opportunity to stretch the clock if it wanted to, otherwise the bus clock is going too fast for the slave hardware to react, and bus errors are inevitable.By the time the master is ready to release SCL (HIGH) again, it should already be asserting its own state on SDA -- either LOW to prepare for LOW->HIGH transition (STOP), or HIGH to prepare to HIGH->LOW transition (RESTART). Now that's not too far off from what you were saying -- it would need to sample before setting SDA itself and releasing SCL.We might actually be in agreement already, but if I'm wrong, please correct me. I might someday keep these notes online for public consumption and I want them to be accurate.