@ -34,6 +34,10 @@
# define __INCLUDE_FROM_TWI_C
# include "../TWI.h"
static inline bool bitmask_is_set ( uint8_t byte , uint8_t mask ) {
return ( byte & mask ) = = mask ;
}
uint8_t TWI_StartTransmission ( TWI_t * twi ,
const uint8_t SlaveAddress ,
const uint8_t TimeoutMS )
@ -45,22 +49,25 @@ uint8_t TWI_StartTransmission(TWI_t *twi,
TimeoutRemaining = ( TimeoutMS * 100 ) ;
while ( TimeoutRemaining )
{
if ( twi - > MASTER . STATUS & ( TWI_MASTER_WIF_bm | TWI_MASTER_ARBLOST_bm ) )
uint8_t status = twi - > MASTER . STATUS ;
if ( bitmask_is_set ( status , TWI_MASTER_WIF_bm | TWI_MASTER_ARBLOST_bm ) )
{
// Case 1: Arbitration lost. Try again. (or error)
twi - > MASTER . ADDR = SlaveAddress ;
}
else if ( twi - > MASTER . STATUS & ( TWI_MASTER_WIF_bm | TWI_MASTER_RXACK_bm ) )
else if ( bitmask_is_set ( status , TWI_MASTER_WIF_bm | TWI_MASTER_RXACK_bm ) )
{
// Case 2: No response from slave.
// We need to release the bus.
TWI_StopTransmission ( twi ) ;
return TWI_ERROR_SlaveResponseTimeout ;
}
else if ( twi- > MASTER . STATUS & ( TWI_MASTER_WIF_bm ) )
else if ( status & TWI_MASTER_WIF_bm )
{
// Case 3: Slave ACK the Write. Ready!
return TWI_ERROR_NoError ;
}
else if ( twi- > MASTER . STATUS & ( TWI_MASTER_RIF_bm ) )
else if ( status & TWI_MASTER_RIF_bm )
{
// Case 4: Slave ACK the Read. Ready! (a byte will be read)
return TWI_ERROR_NoError ;
@ -73,7 +80,7 @@ uint8_t TWI_StartTransmission(TWI_t *twi,
if ( ! ( TimeoutRemaining ) ) {
if ( twi - > MASTER . STATUS & TWI_MASTER_CLKHOLD_bm ) {
// Release the bus if we're holding it.
twi - > MASTER . CTRLC = TWI_MASTER_CMD_STOP_gc ;
TWI_StopTransmission ( twi ) ;
}
}
return TWI_ERROR_BusCaptureTimeout ;
@ -84,20 +91,20 @@ bool TWI_SendByte(TWI_t *twi, const uint8_t Byte)
// We assume we're ready to write!
twi - > MASTER . DATA = Byte ;
while ( ! ( twi - > MASTER . STATUS & TWI_MASTER_WIF_bm ) ) ;
return ( twi - > MASTER . STATUS & TWI_MASTER_WIF_bm ) & ! ( twi - > MASTER . STATUS & TWI_MASTER_RXACK_bm ) ;
return ( twi - > MASTER . STATUS & TWI_MASTER_WIF_bm ) & & ! ( twi - > MASTER . STATUS & TWI_MASTER_RXACK_bm ) ;
}
bool TWI_ReceiveByte ( TWI_t * twi , uint8_t * const Byte ,
const bool LastByte )
{
// If we're here, we should already be reading. Wait if we haven't read yet.
if ( twi - > MASTER . STATUS & ( TWI_MASTER_BUSERR_bm | TWI_MASTER_ARBLOST_bm ) ) {
if ( bitmask_is_set ( twi - > MASTER . STATUS , TWI_MASTER_BUSERR_bm | TWI_MASTER_ARBLOST_bm ) ) {
return false ;
}
while ( ! ( twi - > MASTER . STATUS & TWI_MASTER_RIF_bm ) ) ;
* Byte = twi - > MASTER . DATA ;
if ( LastByte )
twi - > MASTER . CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_ RECVTRANS _gc;
twi - > MASTER . CTRLC = TWI_MASTER_ACKACT_bm | TWI_MASTER_CMD_ STOP _gc;
else
twi - > MASTER . CTRLC = TWI_MASTER_CMD_RECVTRANS_gc ;
return true ;
@ -137,8 +144,8 @@ uint8_t TWI_ReadPacket(TWI_t *twi,
}
}
TWI_StopTransmission ( twi ) ;
}
TWI_StopTransmission ( twi ) ;
}
return ErrorCode ;
@ -153,7 +160,6 @@ uint8_t TWI_WritePacket(TWI_t *twi,
uint8_t Length )
{
uint8_t ErrorCode ;
if ( ( ErrorCode = TWI_StartTransmission ( twi , ( SlaveAddress & TWI_DEVICE_ADDRESS_MASK ) | TWI_ADDRESS_WRITE ,
TimeoutMS ) ) = = TWI_ERROR_NoError )
{