I have a simple circuit where I bitbang I2C (SCL/SDA is GP5/GP4) on a pic 12F629. It works perfectly, all the timings are correct, no errors etc. The exact schematic is irrelevant because I deconstructed the whole circuit to basic blocks and tested each part separately to make sure the slave is not at fault.
Note that I tested with different chips and different models and the problem persists.
Now I want to drive a random pin, say GP2 low. The moment I do this, the I2C waveform goes crazy. Here's the waveform after pulling GP2 low (SDA blue, SCL yellow):
After some experimenting, here are my conclusions:
In I2C the devices are only allowed to either pull down or release SDA/SCL (in which case they are pulled up by the pull ups). So in order to designate HIGH we set SDA or SCL pin to input and thus it gets released and pulled up to +5V, and to designate LOW we set it to output and it is driven LOW. Of course for it to drive SDA/SCL low when setting them to output, during the program's initialization both these pins are first set to output and given the value LOW, so now everytime they're switched from inputs to outputs during the i2c comms they automatically drive LOW.
And that last part is where I think it all breaks.
If after some point, after an i2c communication, I drive a GPIO pin eg. GP2 LOW or HIGH, this somehow affects the GPIO value of the OTHER gpio pins (namely SCL/SDA) which messes up everything. ie. SDA/SCL GPIO pins are set to 1, so when they are switched from input to output during the i2c comms, they get the value 1 instead of 0 and thus instead of driving the i2c bus LOW they drive it HIGH which isn't allowed. And now the only way to make it work again is: 1. Set SDA/SCL direction in TRISIO to OUTPUT 2. Set SDA/SCL value in GPIO to 0 3. Set SDA/SCL direction back to input to release the bus and let it get pulled up by the pullups.
And now we're ready to resume communcations. Until I pull another GPIO high or low of course where everything is screwed again.
Now my question is this: How could one go about fixing this? Could this be a read-modify-write problem? I thought this would be a common problem, I was sure there would be a lot of people using i2c and a gpio pin at once and have them interefere with each other, but my searches returned no results.
Keep in mind there is nothing connected to the uC but the oscilloscope. I removed everything one by one to find the problem and the problem still persists.