I have designed this in the past to sniff a i2c display of a DAB radio. The trick is to 'sit' on the same address to catch commands and print it to the serial monitor. It creates macros with hex values of each command that you can replay with displayrawwrite.ino below first sketch. You can copy the macros in the serial monitor into this sketch.
displaysniffer.ino:
#include "Wire.h"
#define IPMB_I2C_ADDRESS 0x3c // The I2C address of this device
#define IPMB_BHS_SERIAL_BAUD_SPEED 115200UL
#define IPMB_BHS_I2C_CLOCK_SPEED 200000UL // 200Mhz is max, higher don't work
static const char szNibbleToHex[16] = { "0123456789ABCDEF" };
char* getHexStr( byte n )
{
static char sHex[5] = {'0', 'x', '?', ' ', '\0' };
sHex[2] = szNibbleToHex[(byte)(n >> 4)];
sHex[3] = szNibbleToHex[(byte)(n & 0x0F) ];
return (char *)&sHex[0];
}
bool getDataAvailable()
{ return ( Wire.available() > 0 ); }
uint8_t getData()
{ return Wire.read(); }
/*
The event handlers, how it works:
When a master (or an other slave) do a request with Wire.beginTransmission() to this
device and writes some byte data to it with the Wire.write() method and ends the
transmission with Wire.endTransmission(), the eventCollectRequestDataHandler() method
is called. The eventCollectRequestDataHandler() 'eats', collects all of the data on the
bus (buffer) that has been send. It is important to consume all data to avoid data will
messed up when there is a next I2C request. The data represent a call for information,
data or instruction and is based upon the 'ipmbDataStruc' record format.
To finalize a request, to perform a result and release/restart the bus, the master (or an
other slave) must call the Wire.requestFrom() method to trigger the
eventHandleRequestReplyHandler() method. This method verifies the data previously
collected by the eventCollectRequestDataHandler() method and finally performs an action
and report the result to the master (or an other slave).
*/
void eventCollectRequestDataHandler(int iAvailBytes ) // #1 Get bytes to progress
{
Serial.print( "Wri(" );
//while ( getDataAvailable() )
if( iAvailBytes > 0 )
while( iAvailBytes-- )
{
//Serial.print( "0x" );
Serial.print( " "+String(getHexStr(getData()))+(iAvailBytes?",":"") );
}
Serial.println( " );" );
// Flush/eat/read unhandled bytes
//while( getDataAvailable() )
// { getData(); }
}
void eventHandleRequestReplyHandler() // #2 Finish request, implement received data
{
Serial.println("");
}
void setup()
{
// Start serial
Serial.begin( IPMB_BHS_SERIAL_BAUD_SPEED );
// Start I2C
Wire.begin( IPMB_I2C_ADDRESS );
//Wire.setClock( IPMB_BHS_I2C_CLOCK_SPEED );
Wire.onReceive( eventCollectRequestDataHandler );
Wire.onRequest( eventHandleRequestReplyHandler );
}
void loop()
{
}
displayrawwrite.ino (just an example how to replay):
#include <Wire.h>
void setup() {
// put your setup code here, to run once:
Wire.begin();
}
void loop() {
// put your main code here, to run repeatedly:
test();
delay(2000);
}
void Start()
{
delay(100);
Wire.beginTransmission(0x3C);
}
void Stop()
{
Wire.endTransmission();
}
#define _wri(n) if(n!=0xFF) {Wire.write(n); delay(1);}
void Wri( uint8_t d01 = -1,
uint8_t d02 = 0xFF,
uint8_t d03 = 0xFF,
uint8_t d04 = 0xFF,
uint8_t d05 = 0xFF,
uint8_t d06 = 0xFF,
uint8_t d07 = 0xFF,
uint8_t d08 = 0xFF,
uint8_t d09 = 0xFF,
uint8_t d10 = 0xFF,
uint8_t d11 = 0xFF,
uint8_t d12 = 0xFF,
uint8_t d13 = 0xFF,
uint8_t d14 = 0xFF,
uint8_t d15 = 0xFF,
uint8_t d16 = 0xFF,
uint8_t d17 = 0xFF,
uint8_t d18 = 0xFF,
uint8_t d19 = 0xFF,
uint8_t d20 = 0xFF )
{
delay(50);
Wire.beginTransmission(0x3C);
_wri(d01); _wri(d02); _wri(d03); _wri(d04); _wri(d05);
_wri(d06); _wri(d07); _wri(d08); _wri(d09); _wri(d10);
_wri(d11); _wri(d12); _wri(d13); _wri(d14); _wri(d15);
_wri(d16); _wri(d17); _wri(d18); _wri(d19); _wri(d20);
Wire.endTransmission();
}
void test()
{
Wri( 0x00, 0x01 );
Wri( 0x00, 0x0C, 0x06 );
// Welcome to digital radio:
Wri( 0x80, 0x80, 0x40, 0x20, 0x20, 0x20, 0x57, 0x65, 0x6C, 0x63, 0x6F, 0x6D, 0x65, 0x20, 0x21, 0x20, 0x20, 0x20, 0x20 );
Wri( 0x80, 0xC0, 0x40, 0x20, 0x44, 0x69, 0x67, 0x69, 0x74, 0x61, 0x6C, 0x20, 0x52, 0x61, 0x64, 0x69, 0x6F, 0x20, 0x20 );
// Scanning:
Wri( 0x80, 0x80, 0x40, 0x53, 0x63, 0x61, 0x6E, 0x6E, 0x69, 0x6E, 0x67, 0x2E, 0x2E, 0x2E, 0x20, 0x20, 0x20, 0x20, 0x30 );
// etc
}
Have fun!