AVR128Dx TWI as I2C Sniffer...

Go To Last Post
22 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm using the AVR128DA in a project where I want to use the TWI normally for some addresses but simply listen/sniff to an attached device's communication with it's IO expanders. It seems like this should be pretty easy, but I've been struggling for weeks now to figure out exactly how to set the TWI Registers based on the incoming data.

 

For the sniffer, I only care about 3 addresses and I only care about writes to their output ports (Command = 0x02). I can toss reads (which are button presses) which should make things a bit easier. The IO expanders use a specific sequence for writes and reads, where 'Command' is the port we want to target. For the reads, the Command will always be 0x00.

 

Write: Start >> ADDR+W >> Command >> DATA0 >> DATA1 >> Stop

Read: Start >> ADDR+W >> Command (0x00) >> Rep. Start >> ADDR+R >> DATA0 >> DATA1 >> Stop

 

I'm using the TWIC with interrupts and can successfully get the address, commands and data. But as far as I can tell, the TWI needs a very specific response when sniffing to avoid triggering errors or bad data. For instance, for ADDR+W and DATA+W, it appears that clearing the CLKHOLD bit in SSTATUS works as it also clears the APIF or DIF and keeps listening without having to ACK/NACK.

 

Reads are tricky because we don't have any data to send. When we see ADDR+R, I've tried clearing the CLKHOLD bit, but since we don't care about reads, I've also tried setting NOACT and COMPTRANS in the SCMD bit field with both ACK and NACK responses to no longer trigger the interrupts until a new start. For the DATA+R, I've tried all of the above as well, but it appears that the TWI wants to shift out whatever is in the SDATA register (which is the address+read bit) regardless.

 

Stop is another tricky one. I wouldn't think you'd have to do anything here but clear the CLKHOLD (I use it to set a flag to the main application that we have all the data and can process). However, when a button is pressed on the device we are sniffing, we read the port then read it again 2ms later to verify the press. This will trigger a collision on the 2nd read's ADDR+W, which according to the datasheet means the client address match already took place. 

 

Does anyone know what commands TWI needs to just sniff? The best I've managed to do was get the correct data, but randomly the TWI would interfere with a read causing a button press to be missed on the 'sniffed' device (this does not occur with the sniffer turned off).

 

Thank you and I hope you all are doing well!!

 

This topic has a solution.
Last Edited: Fri. May 20, 2022 - 12:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Exactly the same as any other sniffer.  i.e. look at return value from i2c_start(address_W)

 

If it ACKs you have found a slave.

 

You don't need to read or write any actual data.

I suggest that you release the bus when done.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Well that's what I'm trying and is the part that works, but it appears the Dx TWI wants an action or to be put in a certain state of some sort to end the interrupts via setting/clearing bits in SSTATUS or SCTRLB. This is especially true for reads. For instance, when SSTATUS says ADDR+R, doing nothing results in the address just received from ADDR+R to be shifted out as data. Trying certain responses, I've even seen it shift out the ADDR+R as if I told it SDATA = (ADDR+R<<1). But then I wouldn't think you could clear SDATA anyway because it's going to shift out whatever you put in there. So there has to be some way to tell the TWI either a) pretend like you're Rx'ing data instead of Tx'ing it, or b) just sit quiet until a new start. That's what I can't figure out.

 

I'll look and some sniffer code and I haven't been releasing the bus so that is something else to try. Any sniffers in particular that you like? Thank you, David!

Last Edited: Tue. May 17, 2022 - 03:12 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It appears that the only thing in the way of this working is that by ending the transaction in ADDR+R, the TWI interface still believes it is in a transaction when the next ADDR+W and thus we get a collision error. Here is some code illustrating what I am trying to do.

ISR (TWI1_TWIS_vect)
{
	static uint8_t TxBufferPtr = RESET;
	static uint8_t RxBufferPtr = RESET;

	uint8_t status = TWI1.SSTATUS;		// Get copy of status 

	// Check if Stop was received
	if ((status & TWIC_GET_STOP) == TWIC_STOP)
	{
		// Check if we are NOT ignoring msg
		if(TWIClientStatusReg.Ignore == FALSE)
		{
			TWICStopFlag = TRUE;	// Set Stop flag
		}

		TWI1.SCTRLB = TWIC_ENDTX_NACK;
	}
	// Check if ADR+W
	else if ((status & TWIC_GET_ADDR) == TWIC_ADDR_W)
	{
		/* Ext device wants to send data (Write Start) */
		TWIClientStatus.all = FALSE;				// Reset Status reg
		TWICAddress = TWI1.SDATA;				// Get the address Rx'd

		switch (TWICAddress & ~I2C_READ)
		{
			case ADDR_NO_RESP_0:
			case ADDR_NO_RESP_1:
			case ADDR_NO_RESP_2:
				TWIClientStatus.Ignore = TRUE;		// Ignore data from these addresses
				TWICAddress = RESET;
			case ADDR_RESP_0:
			case ADDR_RESP_1:
			case ADDR_RESP_2:
				TWIClientStatus.SniffAddr = TRUE;	// Get data if next byte is to out port
				break;
		}

		TWI1.SSTATUS |= TWI_CLKHOLD_bm;				// Release SCL for next byte (IO Expander should Ack/Nack for us)

	}
	// Check if DATA+W
	else if ((status & TWIC_GET_DATA) == TWIC_DATA_W_RX)
	{
		/* Ext device sent us data (Write Send Data) */

		// Check if first byte (will be a command byte)
		if(TWIClientStatus.CommandRx == FALSE)
		{
			TWIClientStatus.CommandRx = TRUE;		// Set that we've RX'd a command byte
			TWICCommand = TWI1.SDATA;			// Data is a command byte
			RxBufferPtr = RESET;				// Set buffer to first location

			if(TWICCommand != PCA9535_OUT_PORT_CB)		// Only care about writes to output port
			{
				TWIClientStatus.Ignore = TRUE;
				TWICCommand = RESET;
			}

		}
		else
		{
			// Check if this is the first data byte
			if(RxBufferPtr == RESET)
			{
				TWIClientStatus.FirstByteRx = TRUE;	// We've Rx'd the first data byte (Flag to set data)
			}

			TWIRxBuffer[RxBufferPtr++] = TWI1.SDATA;	// Load Rx'd data in buffer and increment
		}

		TWI1.SSTATUS |= TWI_CLKHOLD_bm;				// Release SCL for next byte

	}
	// Check if ADDR+R
	else if ((status & TWIC_GET_ADDR) == TWIC_ADDR_R)
	{
		/* Ext device has requested data from us (Read Start) */

		TWI1.SCTRLB = TWIC_ENDTX_NACK;				// Don't care about reads so end transaction
	}
	// Check if Data+R
	else if ((status & TWIC_GET_DATA) == TWIC_DATA_R_TX)
	{
		/* Sent data to ext device (Read Send Data) */
		// Should never get here
	}
}
/* END I2C ISR */

Note that clearing SDATA in ADDR+R and setting the bus state to Idle had no effect. I also tried clearing the DIR bit in SSTATUS in an attempt to fool the TWI into thinking that it was addressed as a write instead of read...it's too smart for that. sad

Last Edited: Tue. May 17, 2022 - 05:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sothis wrote:
It appears that the only thing in the way of this working is that by ending the transaction in ADDR+R

 

Why do it then ?

 

You normally just check ADDR+W.   If it ACKs the Slave is present.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

Why do it then ?

 

You normally just check ADDR+W.   If it ACKs the Slave is present.

 

Because every time the external device writes an IO expander I care about's output port, I need DATA1 (referencing the OP) and to know which IO expander it was sent too.

 

And...apparently I didn't know what a "sniffer" was, because I thought it was a passive listener of all communication on the bus. It is not that, lol. I need a passive listener. 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Since you are only interested in the writes, ignore the reads. A COMPTRANS+NACK command for an address not interested in, or an addressR, will simply wait for the next start. 

 

Using this-

https://github.com/cv007/Avr01Dx...

 

Something like the following where you will be ack'ing the addressW and writes along with the other i2c device, which I'm assuming both i2c 'engines' will be happy to see the same correct sda state even though it may not happen at the exact same time. Reads may not be possible using the twi peripheral, since you will get a collision trying to do anything that keeps the twi engine going (like sending 0xFF). Once a collision, you have to wait for another start.

 

volatile uint8_t sniff_data[3]; //command, data, data

/*------------------------------------------------------------------------------
    slave - all addresses
------------------------------------------------------------------------------*/
bool twisCallback(twis_irqstate_t state, u8 statusReg){

    static uint8_t sniff_data_idx; //current index into sniff_data;
    bool ret = false;              //assume do not want to proceed

    switch( state ) {
        case TWIS_ADDRESSED:
            { //since using local variable
            uint8_t addr = twis_read(); //addr+rw
            if( addr & 1 ) break;       //we only want writes
            addr >>= 1;                 //to i2c address
            ret = (addr == 0x44) | (addr == 0x48) | (addr == 0x40); //sniff only addresses interested in
            //will ack address if was address match, and was WR (ret=true)
            sniff_data_idx = 0;         //reset index
            }
            break;
        case TWIS_MWRITE:
            if( sniff_data_idx >= sizeof(sniff_data) ) break; //too much data, done
            sniff_data[sniff_data_idx++] = twis_read(); //command,data,data
            break;
        case TWIS_MREAD: //should not get here, since we are ignoring reads
        case TWIS_STOPPED:
        case TWIS_ERROR:
            break;
        }
    return ret; //true = continue (ack/response), false = done (nack/comptrans)
}

/*------------------------------------------------------------------------------
    main
------------------------------------------------------------------------------*/
int main(){

    twis_defaultPins();             // slave pins
    twis_addressMask(0x7F);         // respond to all addresses
    twis_init( 0, twisCallback );   // address doesn't matter, use callback function above
    sei();

    while(1){
        //read sniff_data[3]
    }

}

Last Edited: Tue. May 17, 2022 - 08:58 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Please describe what you actually want to do.

 

It is simple enough to be a "passive listener".   What do you think that a Logic Analyser does to decode data?

 

If this is your own hardware and your own project,  you know which data port is connected to which outputs.

And you would know the Slave address of every expander that is on the I2C bus.

 

If it is foreign hardware,  just log the bus activity with a Logic Analyser.

 

Questions would be much easier to answer if you say exactly what you want and what your problem is.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@curtvm: Wow, thank you for that. I must admit I studied your TWI code A LOT while working on this so thank you for having it online!! I'm really impressed at how elegant and efficient your code is.

 

So originally I was ACK'ing the ADDR+W and DATA+W, and COMPTRANS NACK'ing the ADDR+R like you describe. The TWI hardware doesn't like the NACK and will flag a collision (APIF + COLL), I think because it sees the IO expander ACK and go low but we want to NACK and stay high. I changed this to a COMPTRANS ACK and it seems to work except for the random dropped press. Beginning to wonder if this isn't a hardware issue or some bug in the external device.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Hard to avoid collisions on reads as you do not know what will go on the bus from the other device before it happens. Maybe I misunderstood, but I assumed you only wanted to 'see' the writes, which is why the example simply does not respond to any reads (thus avoiding the problem).

 

If you want to see the reads, it may be that you have to use the twi to alert you of a transaction start, and if a address+read you are interested in you then switch over to bit-banging the data from there (bit-sniffing I guess, no banging taking place). In other words, a write you want to see do as normally would do (I assume that works ok), if its a read you want to see you switch into 'bit-sniffing mode' until you get what you want (twi is back to waiting for a start while you do that).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@david.prentice: I admit that I SUCK at asking questions, lol. For whatever reason, it is very hard for me to figure out how to be brief but also give you and others as much information as I can about the problem. Because I don't want to burden you, I think I err too far in that direction.

So, ya, passive listener. The key thing is getting DATA1 when there's a write operation to the output port of the addresses we care about. This is my own hardware so the addresses are known. Basically what I'm trying to do is pick up button presses on the external device, figure out what happened, then perform an action in this device based on that press. 

 

The problem was that the device I want to listen to would randomly not react to a button press. When this would happen my logic analyzer would show the response from the IO Expander of that button report no press. I interpreted this as the listening device interfering with the transmission because I had never observed that before, and it stopped when I'd turn off the listener.

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
Maybe I misunderstood, but I assumed you only wanted to 'see' the writes, which is why the example simply does not respond to any reads (thus avoiding the problem).

No you have it right, I only want to see the writes. But the TWI doesn't like COMPTRANS+NACK on the ADDR+R because the IO Expander will ACK like it is supposed to, and therefore the TWI tries to NACK but sees the line low. That's the collision. If we COMPTRANS+ACK there though, the TWI and the IO expander will both ACK, but the TWI will wait for the next Start and everything is fine.

 

I don't need the reads but I can see the utility in "bit sniffing" them. It's a shame you can't clear the DIR bit when in ADDR+R so it treats the rest of the Tx as a write. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If we COMPTRANS+ACK there though, the TWI and the IO expander will both ACK, but the TWI will wait for the next Start and everything is fine.

Maybe I still misunderstand- my example responds to an address+W with a response+ack (callback returns true = response+ack), and keeps doing the same for up to 3 bytes after which it does a comptrans+nack (and is now waiting for another start). So in the example, there is nothing that should be colliding (at the clock edge) for a master write if you simply respond to a write normally. The example also does not respond to address+R. Are you doing something like this, and does this work?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
Maybe I still misunderstand-

It's prolly me, lol.

 

As I understand it, the problem is that COMPTRANS+NACK to address+R does respond, as it is the slave's responsibility to ACK/NACK to the master when an address match is Rx'd. Here's a capture of a read in progress for illustration:

When 'Address read: 24' comes along, we COMPTRANS+NACK since we know at this point we don't care. The IO expander will ACK that like it is supposed to, but the TWI will NACK there, shown as the thick red line. It then stops doing anything (shown as the vertical red line) and waits for the next Start. The problem is that the TWI must be monitoring the pin value while NACK'ing, sees that the pin is actually low when it thinks it should be high, which triggers the collision (0b01001000 or 0b01001010, can't remember). The kicker is what happens next.

Imagine the same message comes again in a few ms because that's the way the external device debounces...it's looking for the Data read to be 0xFE again to confirm the press. The interrupt fires at the end of the first byte (Address write: 24) but for whatever reason the collision is still set in TWI.SSTATUS so it enters the Error routine rather than the ADDR+W routine. It appears that the TWI hardware doesn't clear the registers on Stop, Bus Idle or Start in this case. Might this be a hardware bug?

 

To avoid this all, we just need to COMPTRANS+ACK when we see ( addr & 1 ) because that way the SDA pin state will be in agreeance with the TWI's action, but it will still ignore the rest of the Tx. At least, this is my working theory, haha.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why don't you describe in English what you actually want to do.

 

You don't even say which Expander chip(s) you are using.

Note that most chips will capture any pin-changes and set an IRQ pin.

 

You don't say whether it is Multi-Master.

Or whether you are in single control of the Master.

 

If you find this all too difficult,  design a system with a "big" MCU e.g. AVR128DA64 or ATmega2560 with plenty of GPIO pins.

Get it working with regular GPIO.

 

Then we can show you how to use an expander chip.   Which chip model(s) are suitable and how to use the INT pin(s).

 

David.

Last Edited: Wed. May 18, 2022 - 04:36 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Yes, I get why the master read has to be ignored. When a master read is ignored, the twi simply waits for the next start as it will do a comptrans+nack. So, we forget about master reads.

 

For a master write, we simply respond normally as if we were the only device on the bus, nothing special is done because we can ack at the same time anyone else is acking.

 

So- are you ignoring the master reads? are you responding to master writes normally? Assuming no reads can be done, what is not working?

 

 

I had 2 mistakes in the example callback- I was using | on the addresses when I should have used || (I normally use c++, and always use bitor/or/etc. to avoid all that), and forgot to set ret=true at the end of the TWIS_MWRITE case.

 

Using the same example code, but changing main, using the master to do the slave testing (they are on the same pins of course)-

 

/*------------------------------------------------------------------------------
    main
------------------------------------------------------------------------------*/
int main(){

    while(1){

        twis_defaultPins();             // slave pins
        twis_addressMask(0x7F);         // respond to all addresses
        twis_init( 0, twisCallback );   // address doesn't matter, use callback function above

 

        twim_defaultPins();             //master pins (same as slave)
        twim_baud( F_CPU, 100000ul );   //100kHz
        sei();

 

        //try a read to one of the addresses (0x40,0x44,or 0x48)
        twim_on( 0x44 );                //on, slave address 0x44
        u8 rdbuf[3];                    //read 3 bytes
        twim_read( rdbuf, sizeof(rdbuf) );//do transaction, read n bytes
        twim_waitUS( 3000 );            //wait for completion or timeout (3ms)
        //slave should not respond

 

        _delay_ms(1);

 

        //try a write to one of the addresses (0x40,0x44,or 0x48)
        twim_on( 0x48 );                //on, slave address 0x48
        u8 wrbuf[3] = { 0,1,2 };        //write 3 bytes
        twim_write( wrbuf, sizeof(wrbuf) );//do transaction, write n bytes
        twim_waitUS( 3000 );            //wait for completion or timeout (3ms)
        //slave should respond and store the 3 bytes

 

        asm("nop"); //break here to read sniff_data[3]
        _delay_ms(1000);

        }

    }
 

The screenshots show the slave ignoring the reads, responding to the writes. There is no other device on the bus, so is not a great test as will not see any collisions. If the 'real' device acks an address+read while 'our' twi nacks it, the collision bit is set I assume, but no matter since we are waiting for the next start and a start clears the collision bit for us.

 

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Why don't you describe in English what you actually want to do.

A bit uncalled for, don't you think? curtvm clearly understood what was being asked as he wrote code in #7 (his first response) that is functionally identical to my code example in #4, just way more elegant and straightforward. At this point, curtvm and I are just talking about how the approach we both took causes an error and I'm trying to explain it.

 

I don't know how else to describe this, but the questions asked are really irrelevant to the problem. Nonetheless, I'll try to incorporate the answers.

 

Device A (External device): Based on an ATMega164AU 44pin as a single master system with 6 PCA9535 IO Expanders. These IO Expanders handle LEDs and buttons. I use the INT/IRQ pins to alert the ATMega164 that a button was pressed. It then reads the IO Expander at 2ms intervals until it gets the same result which is our debounce. It then will send out writes to all 6 IO Expanders to update the state of the unit based on the button pressed. This device also has an I2C output buffered with a PCA9508 to get/send data to a peripheral, along with a single wire that connects the peripheral's IO Expander's INT pin to the ATMega. All basic stuff.

 

Device B (The listener): Based on an AVR128DA48 48pin which will be a pseudo multi-master system. Since there's 2x TWI interfaces, I use TWI0 as an internal bus which again has 3 PCA9535 IO Expanders and functions as a single master identical to Device A. TWI1 is connected to the 'external' bus which has an I2C out buffered by a PCA9508 and an I2C input that also has a PCA9508 buffer on it (although I will be switching this to an isolator, something like an ADUM1250).  This 'external' bus will be entirely used as a multi-master system to allow device to device communication between other B-type devices. I say 'pseudo' multi-master because just like in Device A, the I2C In and Out cabling also has a single pin connection which will be used to claim the bus if any Device B wants to send a message to the others.

 

So what I'm trying to do is to allow Device A integrate with this system of Device B's. My solution for this is to have the B-type device directly connected to Device A be listening to Device A's I2C bus for when it updates it's IO Expanders after a button press occurs. That's the place where we can pick up any state changes. This is what I was having a problem doing and what the OP was about. From here, the B-type device will send a message about what happened in Device A to the other B-Type devices, and all the Device B's can do what they need to do with that information. So effectively, we're turning Device A into a Device B.

 

Maybe part of the confusion is "Why not just modify Device A since it's your own hardware?" Valid question, and the only reason really is legacy support.

 

Last Edited: Wed. May 18, 2022 - 09:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
Yes, I get why the master read has to be ignored. When a master read is ignored, the twi simply waits for the next start as it will do a comptrans+nack. So, we forget about master reads.

All I'm saying is at least on my device COMPTRANS+NACK there causes a collision, where COMPTRANS+ACK doesn't. 

 

curtvm wrote:
So- are you ignoring the master reads? are you responding to master writes normally? Assuming no reads can be done, what is not working?

Yes, I was ignoring master reads with COMPTRANS+NACK like you were, and am RESP+ACK to master writes (although TWI1.SSTATUS |= TWI_CLKHOLD_bm; seems to work as well there).

 

Are those screenshots of a master read to a peripheral? If so, can you set a break point on the isError(s) and read twice? Here's what happens for me with COMPTRANS+NACK on master reads:

 

The top lane is the close up of the two master reads back to back. I have a breakpoint set on the my isError routine and it triggers after the first byte which is why it stops...Clock hold is active at that point. SStatus reads 0b01001010. I believe the collision actually occurs in the first transaction's address+r but we only see it at the start of the second because there's no "Error Interrupt" in the DA's TWI...only Address match, Data and Stop. COMPTRANS must disable the Stop interrupt. The bottom lane is the whole recording from the time I turn on the external device or Device A.

 

Here is with COMPTRANS+ACK:

Same setup but the collision isn't triggered this time. You can see at the end of the 2nd read a new transaction starts, those are the master writes that we actually want get data from.

 

Last Edited: Thu. May 19, 2022 - 01:17 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Are those screenshots of a master read to a peripheral? 

The first single transaction is a master read, which the slave nacks (comptrans+nack). The second is a master write, where the slave responds normally.

COMPTRANS must disable the Stop interrupt.

A comptrans basically puts the twi in a state where it is now only looking for start/sr, so you will not see anything after this command until you get to another s/sr.

 

 

I'll have to simulate another device on the bus by acking the address+r with another pin, or get another avr involved which can act as the real device.

 

What is supposed to happen when you get a collision in this case-

you comptrans+nack an address+r (now twi engine will be waiting for an s/sr)

another device ack's the same address+r, a collision occurs in the ack timeslot

we may have a collision bit set, but we already did a comptrans so are now waiting for an s/sr in any case

the collision bit automatically clears on any s/sr

so, we should be passive after the comptrans+nack regardless if the collision occurs on the nack

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

curtvm wrote:
so, we should be passive after the comptrans+nack regardless if the collision occurs on the nack

Ok, this has been my hang-up, that the collision is occurring in the first place.

 

What's interesting to me is that the collision bit is still set at the next ADDR+W interrupt. On the one hand, I can see keeping the collision bit set so the user know it has occurred...the next opportunity to display that would be the Addr match interrupt. But that then forces the error routine to trigger instead of the ADDR+W routine. I guess the proper way to write the ISR then is to have the error routine in it's own if statement at the top instead of "if (error), else if (ADDR+W), else if (ADDR+R)"?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I setup a tiny416 xplained nano to do the master/slave to itself, and a mega4809 curiosity nano to do the sniffing (slave only).

 

The two attached screenshots are-

master sending (tiny 416 master to tiny 416 slave)- [s] [0x40 write] [0x00 mdata] [sr] [0x40 read] [0x22 sdata] [0xFE sdata] [p]

master sending (tiny 416 master to tiny 416 slave)- [s] [0x40 write] [0x00 mdata] [0x22 mdata] [0xFE mdata] [p]

 

The mega4809 is listening on the same twi bus, doing as previously suggested- ignoring reads, responding to writes.

The mega4809 blinks its led when all the sniff data matches- I store address,command,data,data, so am looking for 0x40,0x02,0x22,0xFE (I clear [0] after so will wait for the next match). I am getting the led to blink at the same rate the tiny 416 is sending data.

 

Seems to work fine, logic analyser shows as if I am only looking at the tiny416 with no way to tell the mega4809 is listening in.

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you so much curtvm for verifying that, and for all your help. I really appreciate it, especially you taking the time to write a code example that nailed what I was trying to do. And for having your TWI drivers available for reference; that code has been helpful numerous times as I try to learn this new chip. Thank you!