From 280a78480f49017ba3fc3bd61145a4900413cdb2 Mon Sep 17 00:00:00 2001 From: argandas Date: Wed, 9 Apr 2014 21:20:18 -0500 Subject: [PATCH] Actualizacion protocolo I2C --- I2C/i2c.c | 774 ++++++++++++++++++++---------------------------------- I2C/i2c.h | 35 ++- 2 files changed, 319 insertions(+), 490 deletions(-) diff --git a/I2C/i2c.c b/I2C/i2c.c index 3e40758..0860209 100644 --- a/I2C/i2c.c +++ b/I2C/i2c.c @@ -38,9 +38,7 @@ ** =================================================================== */ -static void (* near const _vect_I2C[])(void) @OSWarrior_ISR_I2CPort_Vector = { - _OSWarrior_ISR_i2c_main -}; +static void (* near const _vect_I2C[])(void) @OSWarrior_ISR_I2CPort_Vector = { _OSWarrior_ISR_i2c_main }; /* ** =================================================================== @@ -48,28 +46,14 @@ static void (* near const _vect_I2C[])(void) @OSWarrior_ISR_I2CPort_Vector = { ** =================================================================== */ -PRIVATE_DATA E_I2C_STATUS _OSWarrior_i2c_ctrl_step; -PRIVATE_DATA E_DATA_DIR _OSWarrior_i2c_ctrl_direction; -PRIVATE_DATA T_UBYTE _OSWarrior_i2c_ctrl_dataLength; - -PRIVATE_DATA T_UBYTE _OSWarrior_i2c_write_index; -PRIVATE_DATA T_UBYTE _OSWarrior_i2c_write_buffer[16]; - -PRIVATE_DATA T_UBYTE _OSWarrior_i2c_read_index; -PRIVATE_DATA T_UBYTE _OSWarrior_i2c_read_next; -PRIVATE_DATA T_UBYTE _OSWarrior_i2c_read_buffer[16]; +/* Globals to be shared throughout the project */ +PRIVATE_DATA I2C_BUFFER i2c_tx_buffer; +PRIVATE_DATA I2C_BUFFER i2c_rx_buffer; -/* -#ifdef __OSWarrior_DK__ - PRIVATE_DATA const int _OSWarrior_i2c_SCLdivider[64] = - { - 20, 22, 24, 26, 28, 30, 34, 40, 28, 32, 36, 40, 44, 48, 56, 68, - 48, 56, 64, 72, 80, 88, 104, 128, 80, 96, 112, 128, 144, 160, 192, 240, - 160, 192, 224, 256, 288, 320, 384, 480, 320, 384, 448, 512, 576, 640, 768, 960, - 640, 768, 896, 1024, 1152, 1280, 1536, 1920, 1280, 1536, 1792, 2048, 2304, 2560, 3072, 3840 - }; -#endif -*/ +/* Globals for this file only */ +PRIVATE_DATA T_UBYTE stop_condition; +PRIVATE_DATA T_UBYTE master_mode; +PRIVATE_DATA T_UBYTE master_tx_done; /* ** =================================================================== @@ -89,37 +73,18 @@ S_I2CSTR I2C = { _OSWarrior_i2c_read }; -/* -** =================================================================== -** Function : I2C.enable -** Handler : _OSWarrior_i2c_enable -** -** Description : -** Initialise the OSWarrior I2C library and set the device -** address when used as slave, this function must me called -** only once. -** -** Parameters : -** address: Device address when used as slave -** -** Returns : Nothing -** =================================================================== -*/ - void _OSWarrior_i2c_enable(T_UBYTE address) { #ifdef __OSWarrior_DK__ { - //static T_UBYTE Freq; - I2C_EN = I2C_ENABLED; // Enable I2C + + I2C_EN = I2C_ENABLED; + + //IIC1C = IIC1C_IICEN_MASK; + I2C.address = address; // IIC Address to structure I2C_ADD = address; // IIC Address - //Freq = _OSWarrior_i2c_baud_calc(I2C.baudRate); - //I2C_FREQ = 0x4C; I2C_FREQ = I2C_STANDARD; - //I2C_FREQ = Freq; - _OSWarrior_i2c_ctrl_step = READY; - I2C_IE = I2C_IE_EN; // Enable IIC interrupts } #endif @@ -134,344 +99,135 @@ void _OSWarrior_i2c_mode(T_UBYTE mode) #endif } -/* -** =================================================================== -** Function : _OSWarrior_i2c_baud_calc -** -** Description : -** Initialise the OSWarrior I2C library and set the device -** address when used as slave, this function must me called -** only once. -** Example: -** BUSCLOCK = 4MHz, BR = 50kbps, mul = 2 -** -** ( mul * SCLdivider ) = 4MHz / 50kbps -** ( mul * SCLdivider ) = 80 -** -** SCLdivider = 80 / mul = 80 / 2 -** SCLdivider = 40 -** -** SCLdivider = 40 ( ICR = 0x07 ) --> 2 x 40 = 80 : IIC1F = 0x47 -** SCLdivider = 40 ( ICR = 0x0B ) --> 2 x 40 = 80 : IIC1F = 0x4B -** -** Parameters : -** address: Device address when used as slave -** -** Returns : Nothing -** =================================================================== -*/ - -/* -T_UBYTE _OSWarrior_i2c_baud_calc(T_ULONG br) -{ - #ifdef __OSWarrior_DK__ - { - const T_UBYTE MULT = 0x00; - const T_UBYTE mul = 1; - register T_UBYTE ICR; - T_UWORD SCLDivider = (T_UWORD)((BUSCLOCK/br)/mul); - ICR = _OSWarrior_i2c_select_icr(SCLDivider); - return ((MULT << 6)|ICR); - } - #endif -} -*/ - -/* -** =================================================================== -** Function : _OSWarrior_i2c_select_icr -** -** Description : -** Initialise the OSWarrior I2C library and set the device -** address when used as slave, this function must me called -** only once. -** -** Parameters : -** address: Device address when used as slave -** -** Returns : Nothing -** =================================================================== -*/ - -/* -T_UBYTE _OSWarrior_i2c_select_icr(T_UWORD SCLDivider) -{ - #ifdef __OSWarrior_DK__ - { - register T_UBYTE i, I2C_SCLdivider_index = 0; - int I2C_SCLdivider_diference_Array[64], I2C_SCLdivider_lastValue = 1000; - - for(i = 0; i < 64; i++) - I2C_SCLdivider_diference_Array[i] = absvalue(_OSWarrior_i2c_SCLdivider[i] - SCLDivider); - - for(i = 0; i < 64; i++) - { - if(I2C_SCLdivider_diference_Array[i] <= I2C_SCLdivider_lastValue) - { - I2C_SCLdivider_index = i; - I2C_SCLdivider_lastValue = I2C_SCLdivider_diference_Array[i]; - } - } - return I2C_SCLdivider_index; - } - #endif -} -*/ - -/* -** =================================================================== -** Function : I2C.start -** Handler : _OSWarrior_i2c_start -** -** Description : -** Starts the transmission to the I2C slave device with the -** given address, this function only send the start sequence -** and the address byte, to add data to the message you must -** use the send() function and the end() to complete the data -** transfer. -** -** Parameters : Nothing -** slv_adr: Slave address to transmit data -** -** Returns : Nothing -** =================================================================== -*/ - void _OSWarrior_i2c_start (T_UBYTE slv_adr) { - _OSWarrior_i2c_write_index = 0; - _OSWarrior_i2c_write_buffer[_OSWarrior_i2c_write_index] = slv_adr; - _OSWarrior_i2c_write_index++; + i2c_tx_buffer.tx_index = 0; + i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++] = slv_adr; } - -/* -** =================================================================== -** Function : I2C.send -** Handler : _OSWarrior_i2c_send -** -** Description : -** Adds a value to the message initiated by the start() -** function, to complete the data transmission you must use -** the end() function. -** -** Parameters : -** data : A value to send as a single byte -** -** Returns : Nothing -** =================================================================== -*/ void _OSWarrior_i2c_send (T_UBYTE data) { - _OSWarrior_i2c_write_buffer[_OSWarrior_i2c_write_index] = data; - _OSWarrior_i2c_write_index++; + i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++] = data; } - -/* -** =========================================================================== -** Function : I2C.end -** Handler : _OSWarrior_i2c_end -** -** Description : -** Ends a transmission to a slave device that was begun by the -** start() function and transmit the bytes added by the send() -** function. -** -** Parameters : Nothing -** -** Returns : byte, which indicates the status of the transmission -** =========================================================================== -*/ -void _OSWarrior_i2c_end(void) +void _OSWarrior_i2c_end(T_BOOLEAN stop) { - T_UBYTE Temp; - _OSWarrior_i2c_ctrl_dataLength = _OSWarrior_i2c_write_index; - _OSWarrior_i2c_write_index = 0; - _OSWarrior_i2c_ctrl_step = HEADER_SENT; - _OSWarrior_i2c_ctrl_direction = TRANSMIT; - + int Temp; + #ifdef __OSWarrior_DK__ { - I2C_EN = I2C_DISABLED; - I2C_EN = I2C_ENABLED; - Temp = I2C_STATUS; /* Clear any pending interrupt */ - I2C_IF = I2C_CLR_IF; - I2C_MODE = I2C_SLAVE; - I2C_SRW = I2C_SLV_RX; + + while (IIC1S & IIC1S_BUSY_MASK); + + stop_condition = (T_UBYTE)stop; + + master_mode = I2C_TX; + master_tx_done = FALSE; + + /* Reset index for TX and RX buffers */ + i2c_tx_buffer.length = i2c_tx_buffer.tx_index - 1; + + i2c_tx_buffer.tx_index = 0; + I2C_TMODE = I2C_TRANSMIT; - I2C_MODE = I2C_MASTER; /* Select Master Mode (Send Start Bit) */ - for(Temp=0;Temp<3;Temp++); /* Small delay */ - I2C_DATA = (_OSWarrior_i2c_write_buffer[_OSWarrior_i2c_write_index]<<1)&0xFE; /* Send selected slave address */ - _OSWarrior_i2c_write_index++; + I2C_MODE = I2C_MASTER; + I2C_IE = I2C_IE_EN; + + /* Put target address into IBDR */ + IIC1D = ( 0 | (i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++]<<1) | master_mode); + + /* Wait for I2SR[IBB] (bus busy) to be set */ + while (!(IIC1S & IIC1S_BUSY_MASK)); + + /* Wait for bus to become free before continuing */ + while (IIC1S & IIC1S_BUSY_MASK); + + /* Restore module to it's idle (but active) state */ + //IIC1C |= IIC1C_IICIE_MASK; + + return; + } #endif } -/* -** =================================================================== -** Function : I2C.requestFrom -** Handler : _OSWarrior_i2c_requestFrom -** -** Description : -** This function is used by the master device to request -** bytes from a slave device. -** The bytes will be retrieved with the available() and -** read() functions. -** -** Parameters : -** slv_adr: Slave device address to request bytes from -** qty : the number of bytes requested -** -** Returns : Nothing -** =================================================================== -*/ - void _OSWarrior_i2c_requestFrom(T_UBYTE slv_adr, T_UBYTE numberOfBytes) { - T_UBYTE Temp; - - _OSWarrior_i2c_ctrl_dataLength = numberOfBytes; - _OSWarrior_i2c_read_index = 0; - _OSWarrior_i2c_read_next = 0; - _OSWarrior_i2c_ctrl_step = HEADER_SENT; - _OSWarrior_i2c_ctrl_direction = RECEIVE; - + int Temp; + #ifdef __OSWarrior_DK__ { - I2C_EN = I2C_DISABLED; - I2C_EN = I2C_ENABLED; - Temp = I2C_STATUS; /* Clear any pending interrupt */ - I2C_IF = I2C_CLR_IF; + + while (IIC1S & IIC1S_BUSY_MASK); + + stop_condition = 1; + + master_mode = I2C_RX; + master_tx_done = FALSE; + + i2c_rx_buffer.rx_index = 0; + I2C_TMODE = I2C_TRANSMIT; - I2C_MODE = I2C_MASTER; - for(Temp=0;Temp<3;Temp++); /* Small delay */ - I2C_DATA = ((slv_adr<<1)&0xFE)|0x01; /* Send selected slave address */ + I2C_MODE = I2C_MASTER; + I2C_IE = I2C_IE_EN; + + /* Put target address into IBDR */ + IIC1D = ( 0 | (slv_adr << 1) | master_mode); + + /* Wait for I2SR[IBB] (bus busy) to be set */ + while (!(IIC1S & IIC1S_BUSY_MASK)); + + /* Wait for bus to become free before continuing */ + while (IIC1S & IIC1S_BUSY_MASK); + + /* Restore module to it's idle (but active) state */ + //IIC1C |= IIC1C_IICIE_MASK; + + return; + } #endif } -/* -** =================================================================== -** Function : I2C.available -** Handler : _OSWarrior_i2c_available -** -** Description : -** This function returns the number of bytes available for -** retrieval with the I2C.read() function. -** This should be called on a master device after a call -** to requestFrom() or on a slave inside the -** I2C.onReceive() handler. -** -** Parameters : Nothing -** -** Returns : The number of bytes available for reading -** =================================================================== -*/ - T_UBYTE _OSWarrior_i2c_available(void) { - delay(5); - return ((_OSWarrior_i2c_read_index)>(0)?(TRUE):(FALSE)); + delay(1); + return ((i2c_rx_buffer.rx_index)>(0)?(TRUE):(FALSE)); } -/* -** =================================================================== -** Function : I2C.read -** Handler : _OSWarrior_i2c_read -** -** Description : -** Reads a byte that was requested by the request() function. -** -** Parameters : Nothing -** -** Returns : The next byte received -** =================================================================== -*/ - T_UBYTE _OSWarrior_i2c_read(void) { - T_UBYTE Temp; - Temp = _OSWarrior_i2c_read_buffer[_OSWarrior_i2c_read_next]; - _OSWarrior_i2c_read_next++; - _OSWarrior_i2c_read_index--; - return Temp; -} + PRIVATE_DATA T_UBYTE index = 0; + + T_UBYTE temp = i2c_rx_buffer.buf[index++]; + + if(index == i2c_rx_buffer.rx_index) index = 0; -/* -** =========================================================================== -** Function : I2C.onReceive -** Handler : _OSWarrior_i2c_onReceive -** -** Description : -** Registers a function to be called when a slave device -** receives a transmission from a master. -** -** Parameters : -** handler: the function to be called when the slave receives data -** -** Returns : Nothing -** =========================================================================== -*/ + return temp; +} void _OSWarrior_i2c_onReceive(void (*handler)(void)) { (*handler)(); } - -/* -** =================================================================== -** Function : I2C.onRequest -** Handler : _OSWarrior_i2c_onRequest -** -** Description : -** Register a function to be called when a master requests -** data from this slave device. -** -** Parameters : -** handler: the function to be called -** -** Returns : Nothing -** =================================================================== -*/ void _OSWarrior_i2c_onRequest(void (*handler)(void)) { (*handler)(); } -/* -** =================================================================== -** Interrupt : _OSWarrior_ISR_i2c_main -** -** Description : -** An interruption from the IIC is generated when any of the -** next three events occur: -** 1.- Complete 1-byte transfer -** 2.- Match of receiving call address -** 3.- Arbitration lost -** The interrupt type can be determinate by reading the -** status register. -** -** =================================================================== -*/ - __interrupt void _OSWarrior_ISR_i2c_main(void) { - T_UBYTE Temp; - #ifdef __OSWarrior_DK__ { - Temp = I2C_STATUS; + + /* Clear the I2C Interrupt Flag. */ + //IIC1S &= (T_UBYTE) ~IIC1S_IICIF_MASK; + + (void)I2C_STATUS; /* ACK the interrupt */ I2C_IF = I2C_CLR_IF; - if( I2C_ARBL == I2C_ARBL_LOST ) // Verify the Arbitration lost status - { - I2C_ARBL= 1; - I2C_MODE = I2C_SLAVE; //Generate Stop Signal - _OSWarrior_i2c_ctrl_step = ERROR; - return; - } - if( I2C_MODE == I2C_MASTER ) + + if( IIC1C & IIC1C_MST_MASK ) { _OSWarrior_i2c_master(); //I2C as Master } @@ -483,167 +239,219 @@ __interrupt void _OSWarrior_ISR_i2c_main(void) #endif } -/* -** =================================================================== -** Function : _OSWarrior_i2c_master -** -** Description : -** Handle interruption vector when the device is configured -** as master. -** -** Parameters : Nothing -** Returns : Nothing -** =================================================================== -*/ - void _OSWarrior_i2c_master(void) { + /* + ** ============================================================== + ** MASTER MODE OPERATION + ** ============================================================== + */ + #ifdef __OSWarrior_DK__ { - /* - ** ============================================================== - ** MASTER MODE OPERATION - ** ============================================================== - */ - T_UBYTE Temp; - - if( I2C_ACK == I2C_NO_ACK ){ /* Verify if byte sent was ACK */ - I2C_MODE = I2C_SLAVE; //Generate Stop Signal - _OSWarrior_i2c_ctrl_step = ERROR; - return; - } - /* - ** ============================================================== - ** HEADER SENT STATUS - ** ============================================================== - */ - if( _OSWarrior_i2c_ctrl_step == HEADER_SENT ){ /* Header Sent */ - - I2C_TMODE = (T_UBYTE)_OSWarrior_i2c_ctrl_direction; - _OSWarrior_i2c_ctrl_step = DATA_TRANSMISSION; - - if( I2C_TMODE == I2C_RECEIVE ){ /* If we are reading data clock in first slave byte */ - Temp = I2C_DATA; - return; - } - } - /* - ** ============================================================== - ** DATA TRANSMISSION STATUS - ** ============================================================== - */ - if( _OSWarrior_i2c_ctrl_step == DATA_TRANSMISSION ){ /* If byte transmission is in progress.*/ - - if( I2C_TMODE == I2C_TRANSMIT ){ - /* - ** ============================================================== - ** MASTER SENDING DATA TO SLAVE - ** ============================================================== - */ - - //Serial.println("MASTER MODE OPERATION - SENDING DATA TO SLAVE"); - - I2C_DATA = _OSWarrior_i2c_write_buffer[_OSWarrior_i2c_write_index]; /* Send the next byte */ - _OSWarrior_i2c_write_index++; - if(_OSWarrior_i2c_ctrl_dataLength <= _OSWarrior_i2c_write_index){ - _OSWarrior_i2c_ctrl_step = DATA_SENT; /* Mark we are done sending Bytes */ + /* Temp variable for dummy reads */ + T_UBYTE dummy_read; + + /* Master Mode - Check if this device is in Transmit or Receive Mode. */ + if (IIC1C & IIC1C_TX_MASK) + { + /* Master Transmit Mode - Check if last byte was tranmitted. */ + if ( i2c_tx_buffer.length == 0 ) + { + if(stop_condition == 1) I2C_MODE = I2C_SLAVE; /* Generate a stop condition */ + else IIC1C_RSTA = 1; /* Generate a repeated start condition */ + } + else + { + /* More bytes to be transmitted - Check if ACK received. */ + if (IIC1S & IIC1S_RXAK_MASK) + { + /* ACK not received - Generate STOP */ + IIC1C &= (T_UBYTE)(~IIC1C_MST_MASK & 0xFF); } - return; - - }else{ - /* - ** ============================================================== - ** MASTER READING DATA FROM SLAVE - ** ============================================================== - */ - - if( ( _OSWarrior_i2c_read_index ) == _OSWarrior_i2c_ctrl_dataLength ) I2C_TACK = I2C_NO_TACK; - _OSWarrior_i2c_read_buffer[_OSWarrior_i2c_read_index] = I2C_DATA; /* Send the next byte */ - _OSWarrior_i2c_read_index++; - if( _OSWarrior_i2c_ctrl_dataLength <= _OSWarrior_i2c_read_index ){ - _OSWarrior_i2c_ctrl_step = DATA_SENT; /* Mark we are done sending Bytes */ - } - return; /* Return until next byte is read */ - } - } - /* - ** ============================================================== - ** DATA SENT STATUS - ** ============================================================== - */ - if( _OSWarrior_i2c_ctrl_step == DATA_SENT ) /* We are done with the transmition.*/ - { - - _OSWarrior_i2c_ctrl_step = READY; /* Reset our status flag */ - Temp = I2C_STATUS; /* ACK the interrupt */ - I2C_IF = I2C_CLR_IF; - I2C_TMODE = (T_UBYTE)RECEIVE; - I2C_SRW = I2C_SLV_RX; - I2C_MODE = I2C_SLAVE; /* Generate a stop condition */ - return; - + else + { + /* Check if end of address cycle */ + if (master_mode == I2C_RX) + { + IIC1C &= (T_UBYTE)(~IIC1C_TX_MASK & 0xFF); + dummy_read = IIC1D; + } + /* ACK received, send data */ + else + { + /* Not end of address cycle - Write next byte to MBDR */ + IIC1D = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++]; + i2c_tx_buffer.length--; + } + } + } } + else + { + /* Master Receive Mode - Check if this is last byte to be read. */ + if (i2c_rx_buffer.length == 1) + { + //printf("I2CR TXAK = 0x%02X\n",IIC1C); + /* Last byte to be read - + Generate Stop signal by changing to Slave Mode. */ + IIC1C &= (T_UBYTE)(~IIC1C_MST_MASK & 0xFF); + } + else + { + /* Not last byte to be read - Check if second to last byte. */ + if (i2c_rx_buffer.length == 2) + { + /* Second to last byte to be read - Set Transmit Acknowledge Enable + bit so no ACK is sent after the next byte is received, which + indicates "end of data" to the slave. */ + IIC1C |= IIC1C_TXAK_MASK; + } + } + + /* Store received data in RX buffer */ + i2c_rx_buffer.buf[i2c_rx_buffer.rx_index++] = IIC1D; + i2c_rx_buffer.length--; + } } #endif } -/* -** =================================================================== -** Function : _OSWarrior_i2c_slave -** -** Description : -** Handle interruption vector when the device is configured -** as slave. -** -** Parameters : Nothing -** Returns : Nothing -** =================================================================== -*/ - -void _OSWarrior_i2c_slave(void){ +void _OSWarrior_i2c_slave(void) +{ /*************************/ /* Slave Mode Operation */ /*************************/ - #ifdef __OSWarrior_DK__ + #ifdef __OSWarrior_DK_I2C_SLAVE__ { - T_UBYTE Temp; - - if(_OSWarrior_i2c_ctrl_step <= READY) /* If it is the first byte transmitted */ - { - _OSWarrior_i2c_ctrl_step = DATA_TRANSMISSION; - I2C_TMODE = I2C_SRW; /* Set the transmission reception status */ - _OSWarrior_i2c_write_index = 0; - - if( I2C_TMODE == I2C_RECEIVE ) /* If we are receiving data read IIC1D to get free bus and get the next byte */ - { - Temp = I2C_DATA; - return; - } - } - - if( I2C_TCF == I2C_TC_CPL ) /* Transmission complete */ - { - if( I2C_TMODE == I2C_RECEIVE ) /* If data is received store it on the buffer */ - { - //I2C_DATA_BUFFER[_OSWarrior_i2c_write_index] = I2C_DATA; - _OSWarrior_i2c_write_index++; - return; - } - else /* Data sent by the slave */ - { - if( I2C_ACK == I2C_NO_ACK ) /* Check for ACK */ - { - I2C_TMODE = I2C_RECEIVE; - Temp = I2C_DATA; - _OSWarrior_i2c_ctrl_step = READY; - return; + /* Slave Mode - Check if Arbitration Lost. */ + if (MCF5282_I2C_I2SR & MCF5282_I2C_I2SR_IAL) + { + #ifdef DEBUG + printf("Arbitration Lost.\n"); + #endif + + /* Clear IAL bit */ + MCF5282_I2C_I2SR &= ~MCF5282_I2C_I2SR_IAL; + + /* Arbitration Lost - Check if this device is being addressed as slave. + (If not, nothing more needs to be done.) */ + if (MCF5282_I2C_I2SR & MCF5282_I2C_I2SR_IAAS) + { + /* Addressed as slave - + Check if master was reading from slave or writing to slave. */ + if (MCF5282_I2C_I2SR & MCF5282_I2C_I2SR_SRW) + { + /* Set tx_index to 0 */ + i2c_tx_buffer.tx_index = 0; + + /* Master was reading from slave - Set Transmit Mode. */ + MCF5282_I2C_I2CR |= MCF5282_I2C_I2CR_MTX; + + /* Write data to MBDR. */ + MCF5282_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++]; + + #ifdef DEBUG + printf("Arbitration Lost: Addressed as slave - TX mode.\n"); + #endif + } + else + { + /* Set rx_index to 0 */ + i2c_rx_buffer.rx_index = 0; + + /* Master was writing to slave - Set Receive Mode. */ + MCF5282_I2C_I2CR &= ~MCF5282_I2C_I2CR_MTX; + + /* Dummy read from MBDR, to clear the ICF bit. */ + dummy_read = MCF5282_I2C_I2DR; + + #ifdef DEBUG + printf("Arbitration Lost: Addressed as slave - RX mode.\n"); + #endif + } + } + } + else + { + /* Arbitration Not Lost - Check if data byte is this devices's Slave Address byte. */ + if (MCF5282_I2C_I2SR & MCF5282_I2C_I2SR_IAAS) + { + /* Data byte is Slave Address byte - Check Slave Read/Write bit. */ + if (MCF5282_I2C_I2SR & MCF5282_I2C_I2SR_SRW) + { + /* Set tx_index to 0 */ + i2c_tx_buffer.tx_index = 0; + + /* Master was reading from slave - Set Transmit Mode. */ + MCF5282_I2C_I2CR |= MCF5282_I2C_I2CR_MTX; + + /* Write data to MBDR. */ + MCF5282_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++]; + + #ifdef DEBUG + printf("Slave TX: First byte - 0x%02X\n",i2c_tx_buffer.buf[i2c_tx_buffer.tx_index-1]); + #endif + } + else + { + /* Master has specified Slave Receive Mode. + Set Receive Mode. (Writing to MBCR clears IAAS.) */ + + /* Set rx_index to 0 */ + i2c_rx_buffer.rx_index = 0; + + MCF5282_I2C_I2CR &= ~MCF5282_I2C_I2CR_MTX; + + /* Read address data from MBDR and store it. */ + dummy_read = MCF5282_I2C_I2DR; + + #ifdef DEBUG + printf("Slave RX: Receive address.\n"); + #endif + } + } + else + { + /* Data byte received is not Slave Address byte - + Check if this device is in Transmit or Receive Mode. */ + if (MCF5282_I2C_I2CR & MCF5282_I2C_I2CR_MTX) + { + /* Last byte received? */ + if (MCF5282_I2C_I2SR & MCF5282_I2C_I2SR_RXAK) + { + MCF5282_I2C_I2CR &= ~MCF5282_I2C_I2CR_MTX; + dummy_read = MCF5282_I2C_I2DR; + + #ifdef DEBUG + printf("Slave TX: Last byte has been sent.\n"); + #endif + } + else + { + /* Write data to MBDR. */ + MCF5282_I2C_I2DR = i2c_tx_buffer.buf[i2c_tx_buffer.tx_index++]; + i2c_tx_buffer.length--; + + #ifdef DEBUG + printf("Slave TX: Send byte - 0x%02X\n",i2c_tx_buffer.buf[i2c_tx_buffer.tx_index-1]); + #endif + } + } + else + { + /* Receive Mode - Read data from MBDR and store it. */ + i2c_rx_buffer.buf[i2c_rx_buffer.rx_index++] = MCF5282_I2C_I2DR; + i2c_rx_buffer.length++; + i2c_rx_buffer.data_present = TRUE; + + #ifdef DEBUG + printf("Slave RX: Receive byte - 0x%02X\n",i2c_rx_buffer.buf[i2c_rx_buffer.rx_index-1]); + #endif + } + } } - //I2C_DATA = I2C_DATA_BUFFER[_OSWarrior_i2c_write_index]; - _OSWarrior_i2c_write_index++; - return; - } - } } #endif } diff --git a/I2C/i2c.h b/I2C/i2c.h index 32d9ed9..b058aa6 100644 --- a/I2C/i2c.h +++ b/I2C/i2c.h @@ -48,6 +48,19 @@ #define I2C_FAST 0x03 /* 400 kbps */ #endif + /* I2C parameters */ + #define I2C_BUFFER_SIZE (50) + #define I2C_TXRX (2) + #define I2C_TX (0) + #define I2C_RX (1) + #define iPORT (0x6E) + + /* Driver-specific defines */ + // Use polling instead of interrupt-driven transfers + #undef POLLING_MODE + // Use debug prints to view byte level transfers via COM port + #define DEBUG + /* ** =================================================================== ** I2C type definitions @@ -65,15 +78,23 @@ typedef struct{ T_UBYTE address; - void (*enable)(T_UBYTE masterAddress); - void (*mode)(T_UBYTE mode); - void (*start)(T_UBYTE slaveAddress); - void (*send)(T_UBYTE value); - void (*end)(void); - void (*requestFrom)(T_UBYTE slaveAddress, T_UBYTE numberOfBytes); + void (*enable)(T_UBYTE); + void (*mode)(T_UBYTE); + void (*start)(T_UBYTE); + void (*send)(T_UBYTE); + void (*end)(T_BOOLEAN); + void (*requestFrom)(T_UBYTE, T_UBYTE); T_UBYTE (*available)(void); T_UBYTE (*read)(void); }S_I2CSTR; + + typedef struct { + int tx_index; /* TX index */ + int rx_index; /* RX index */ + int data_present; /* Data present flag */ + T_ULONG length; /* Length of the buffer in bytes */ + T_UBYTE buf[I2C_BUFFER_SIZE]; /* Data buffer */ + } I2C_BUFFER; /* ** =================================================================== @@ -96,7 +117,7 @@ PUBLIC_FCT void _OSWarrior_i2c_start(T_UBYTE slv_adr); PUBLIC_FCT void _OSWarrior_i2c_send (T_UBYTE value); - PUBLIC_FCT void _OSWarrior_i2c_end(void); + PUBLIC_FCT void _OSWarrior_i2c_end(T_BOOLEAN stop); PUBLIC_FCT void _OSWarrior_i2c_requestFrom(T_UBYTE slv_adr, T_UBYTE numberOfBytes); PUBLIC_FCT T_UBYTE _OSWarrior_i2c_available(void);