I2C. 10-bit slave addressing done. Not tested at all.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/branches/i2c_dev@2729 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
c2d458110c
commit
eafaa7d6cf
|
@ -73,12 +73,14 @@
|
|||
typedef enum {
|
||||
I2C_UNINIT = 0, /**< Not initialized. */
|
||||
I2C_STOP = 1, /**< Stopped. */
|
||||
I2C_READY = 2, /**< Ready. */
|
||||
I2C_MACTIVE = 3, /**< START condition sent. */
|
||||
I2C_MTRANSMIT = 4, /**< Master transmitting. */
|
||||
I2C_MRECEIVE = 5, /**< Master receiving. */
|
||||
I2C_MWAIT_TF = 6, /**< Master wait Transmission Finished */
|
||||
I2C_MERROR = 7 /**< Error condition. */
|
||||
I2C_READY = 2, /**< Ready. Start condition generated. */
|
||||
I2C_MACTIVE = 3, /**< I2C configured and waiting start cond. */
|
||||
I2C_10BIT_HANDSHAKE = 4, /**< 10-bit address sending */
|
||||
I2C_MWAIT_ADDR_ACK = 5, /**< Waiting ACK on address sending. */
|
||||
I2C_MTRANSMIT = 6, /**< Master transmitting. */
|
||||
I2C_MRECEIVE = 7, /**< Master receiving. */
|
||||
I2C_MWAIT_TF = 8, /**< Master wait Transmission Finished */
|
||||
I2C_MERROR = 9 /**< Error condition. */
|
||||
} i2cstate_t;
|
||||
|
||||
#include "i2c_lld.h"
|
||||
|
|
|
@ -110,10 +110,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) {
|
|||
int n = 0;
|
||||
int m = 0;
|
||||
|
||||
if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent
|
||||
i2cp->id_state = I2C_MACTIVE;
|
||||
/*TODO: 10 bit address handling
|
||||
In 10-bit addressing mode,
|
||||
/* In 10-bit addressing mode,
|
||||
– To enter Transmitter mode, a master sends the header (11110xx0) and then the
|
||||
slave address, (where xx denotes the two most significant bits of the address).
|
||||
– To enter Receiver mode, a master sends the header (11110xx0) and then the
|
||||
|
@ -122,20 +119,50 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) {
|
|||
address).
|
||||
The TRA bit indicates whether the master is in Receiver or Transmitter mode.*/
|
||||
|
||||
i2cp->id_i2c->DR = (i2cp->id_slave_config->address << 1) |
|
||||
i2cp->id_slave_config->rw_bit; // write slave address in DR
|
||||
if ((i2cp->id_state == I2C_READY) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// start bit sent
|
||||
i2cp->id_state = I2C_MACTIVE;
|
||||
|
||||
if(!(i2cp->id_slave_config->address & 0x8000)){ // slave address is 7-bit
|
||||
i2cp->id_i2c->DR = ((i2cp->id_slave_config->address & 0x7F) << 1) |
|
||||
i2cp->id_slave_config->rw_bit;
|
||||
i2cp->id_state = I2C_MWAIT_ADDR_ACK;
|
||||
return;
|
||||
}
|
||||
else{ // slave address is 10-bit
|
||||
i2cp->id_state = I2C_10BIT_HANDSHAKE;
|
||||
// send MSB with header. LSB = 0.
|
||||
i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// "wait" interrupt with ADD10 flag
|
||||
if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){
|
||||
i2cp->id_i2c->DR = i2cp->id_slave_config->address & 0x00FF; // send remaining bits of address
|
||||
if (!(i2cp->id_slave_config->rw_bit))
|
||||
// in transmit mode there is nothing to do with 10-bit handshaking
|
||||
i2cp->id_state = I2C_MWAIT_ADDR_ACK;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADD10)){// header sent
|
||||
|
||||
// "wait" interrupt with ADDR
|
||||
if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address ACKed
|
||||
i2cp->id_i2c->CR1 |= I2C_CR1_START;
|
||||
return;
|
||||
}
|
||||
|
||||
// "wait" interrupt with ADDR flag
|
||||
if ((i2cp->id_state == I2C_MACTIVE) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR)){// address successfully sent
|
||||
if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){
|
||||
i2c_lld_txbyte(i2cp); // send first byte
|
||||
if ((i2cp->id_state == I2C_10BIT_HANDSHAKE) && (i2cp->id_i2c->SR1 & I2C_SR1_SB)){// restart generated
|
||||
// send MSB with header. LSB = 1
|
||||
i2cp->id_i2c->DR = ((i2cp->id_slave_config->address >> 7) & 0x6) | 0xF1;
|
||||
i2cp->id_state = I2C_MWAIT_ADDR_ACK;
|
||||
return;
|
||||
}
|
||||
|
||||
// "wait" interrupt with ADDR (ADD10 in 10-bit receiver mode) flag
|
||||
if ((i2cp->id_state == I2C_MWAIT_ADDR_ACK) && (i2cp->id_i2c->SR1 & I2C_SR1_ADDR & I2C_SR1_ADD10)){// address ACKed
|
||||
if(i2cp->id_i2c->SR2 & I2C_SR2_TRA){// I2C is transmitting data
|
||||
i2cp->id_state = I2C_MTRANSMIT; // change state
|
||||
i2c_lld_txbyte(i2cp); // send first byte
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -145,7 +172,7 @@ static void i2c_serve_event_interrupt(I2CDriver *i2cp) {
|
|||
*/
|
||||
if (i2cp->id_slave_config->rxbytes > 1)
|
||||
i2cp->id_i2c->CR1 |= I2C_CR1_ACK; // set ACK bit
|
||||
i2cp->id_state = I2C_MRECEIVE; // change status
|
||||
i2cp->id_state = I2C_MRECEIVE; // change state
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue