Forum breadcrumbs - You are here:ForumGeneral: Report BugsAttiny85 USI I2C
You need to log in to create posts and topics.

Attiny85 USI I2C

PreviousPage 3 of 5Next

Thanks for the code and explanation, that will be useful to test.

but I don't see any code to reset the USISIF bit by writing a 1 to it. There is just code for USIPF.

The interrupt takes care of that.

 
Quote from arcachofo on January 6, 2024, 10:17 am

The interrupt takes care of that.

Even if the interrupt is turned off? Shouldn't writing a 1 into USISIF always reset that bit, not matter if the interrupt takes care or not.

Even if the interrupt is turned off? Shouldn't writing a 1 into USISIF always reset that bit, not matter if the interrupt takes care or not.

Yes, that's the idea.

Quote from arcachofo on January 6, 2024, 10:38 am

Even if the interrupt is turned off? Shouldn't writing a 1 into USISIF always reset that bit, not matter if the interrupt takes care or not.

Yes, that's the idea.

But this is different from the behaviour described in the documentation of Atiny85:

• Bit 7 – USISIF: Start Condition Interrupt Flag
When two-wire mode is selected, the USISIF Flag is set (to one) when a start condition has been detected. When
three-wire mode or output disable mode has been selected any edge on the SCK pin will set the flag.

If USISIE bit in USICR and the Global Interrupt Enable Flag are set, an interrupt will be generated when this flag is
set. The flag will only be cleared by writing a logical one to the USISIF bit. Clearing this bit will release the start
detection hold of USCL in two-wire mode.

I see a difference in this:

Clearing this bit will release the start detection hold of USCL in two-wire mode.

But nothing about holding clock pin is implemented yet.

The rest should work...

I'm doing some testing with your code:

USICR =
(0<<USISIE)|(0<<USIOIE)|             // Interrupts disabled
(1<<USIWM1)|(0<<USIWM0)|             // Set USI in Two-wire mode.
(1<<USICS1)|(0<<USICS0)|(1<<USICLK)| // Software clock strobe as source.
(1<<USITC);                          // Toggle Clock Port.

I know why Clock pin is not toggling, but there is something I'm not sure:

• Bit 0 – USITC: Toggle Clock Port Pin
Writing a one to this bit location toggles the USCK/SCL value either from 0 to 1, or from 1 to 0.
The toggling is independent of the setting in the Data Direction Register,
but if the PORT value is to be shown on the pin the corresponding DDR pin must be set as output (to one).

So... writing 1 to USITC toggles the value of PORTB.
So It does not control the pin directly. I have this wrong.

 

There are actually two different TWI modes:

(1 << USICS1) | (0 << USICS0) | (1 << USICLK)

or

(0 << USICS1) | (0 << USICS0) | (1 << USICLK) 

I always use the first one which toggles the SCL pin if a 1 is written into USITC and the PORTB pin was set to an output. The second option just increments the counter and shifts the data (if a 1 is written into USICLK), but doesn't seem to toggle any output pin. I don't know when to use this mode.

https://github.com/adafruit/TinyWireM/blob/master/USI_TWI_Master.cpp has the code I'm using and of which I know it is working.

I'm getting more confused lol.

The datasheet states that writing to USITC toggles "the USCK/SCL value".
And is not conditioned to the mode.

Now... what "the USCK/SCL value" means?
As I understand in the next sentence it means bit 2 in PORTB:

but if the PORT value is to be shown on the pin the corresponding DDR pin must be set as output 

It took some time for me to start to understand this (still very confused).
USICS1 and USICS0 seems to select the "clock" source for the shift register and counter, but nothing to do with the clock pin.
AS I see in the block diagram USICSx drive the two multiplexers selecting the line connected shift register and counter...

Clock pin is now working with your code (Rev 2125).

It controls the clock pin by writing to the PORT register.

I think there is some confusion with interrupts, interrupt flags, etc.
So let me clarify:

When I say that "the interrupt" takes care about setting and clearing flags and so on, I don't mean the interrupt routine in the firmware.
I'm talking about the interrupt implementation in simulide.

When you "raise" an interrupt: interrupt->raise(), it takes care about the flag and if enabled adds itself to pending interrupts.
When the bit corresponding to the flag is written to 1, the interrupt itself clears the flag.
Some interrupts also clear the flag after returning from the interrupt routine.

PreviousPage 3 of 5Next