Для PIC18. Используются прерывание (pin change). Два уровня прерываний. По изменению ножки -- высокий приоритет. Запоминается состояние SCL/SDA и всё и вызывается прерывание низкого приоритета, из которого всё остальное работает: попадает в конечный автомат, который реализует "протокол I2C" (из прерываний). Потом в ещё один автомат (i2c_sslave_handler). Который уже реализует протокол для конкретного "слейва" (его и менять в основном). На 100КГц нормально работать не будет. От силы 50 и меньше (для 8МГц пика).