diff --git a/csl/stm32f042/Src/imp_i2c.c b/csl/stm32f042/Src/imp_i2c.c index 387c055..02e9109 100644 --- a/csl/stm32f042/Src/imp_i2c.c +++ b/csl/stm32f042/Src/imp_i2c.c @@ -1,17 +1,18 @@ - #include "i2c.h" +#include "usart.h" -#define I2C_BASE ((I2C_TypeDef*)i2cBase_Addr_List[i2cHardware->channelNo]) +#define I2C_BASE ((I2C_TypeDef*)i2cBase_Addr_List[i2c_dev->channelNo]) uint8_t temp8 = 0; uint16_t temp16 = 0; -void i2cEnableHardware(i2c_t *i2cHardware) +void i2c_hardware_enable(i2c_t *i2c_dev) { - i2cHardwareReset(i2cHardware); + i2c_hardware_reset(i2c_dev); // Enables the i2c bus - RCC->APB1ENR |= (1 << i2cBus_En_bitPos[i2cHardware->channelNo]); + RCC->APB1ENR |= (1 << i2cBus_En_bitPos[i2c_dev->channelNo]); + i2c_dev->hardwareState = i2c_hw_enabled; pinInit(pinA9); pinInit(pinA10); @@ -19,52 +20,55 @@ void i2cEnableHardware(i2c_t *i2cHardware) pinConfig(pinA10, alternate, openDrain, pullUp, fast);// I2C CSA pinSetAlternate(pinA9, 4); pinSetAlternate(pinA10, 4); + i2c_dev->hardwareState = i2c_hw_ready; } -void i2cHardwareReset(i2c_t *i2cHardware) +// Resets the I2C hardware using the reset registers, +// This will init the device to it's defualt configuration established by STM +void i2c_hardware_reset(i2c_t *i2c_dev) { - // Resete the I2C hardware using the reset registers, - RCC->APB1RSTR |= (1 << i2cBus_Rst_bitPos[i2cHardware->channelNo]); - RCC->APB1RSTR &= ~(1 << i2cBus_Rst_bitPos[i2cHardware->channelNo]); + RCC->APB1RSTR |= (1 << i2cBus_Rst_bitPos[i2c_dev->channelNo]); + RCC->APB1RSTR &= ~(1 << i2cBus_Rst_bitPos[i2c_dev->channelNo]); + i2c_dev->hardwareState = i2c_hw_reset; } - -void i2cEnablePeriferal(i2c_t *i2cHardware) +//enables periferal +void i2c_periferal_enable(i2c_t *i2c_dev) { I2C_BASE->CR1 |= I2C_CR1_PE; + i2c_dev->periferalState = i2c_perif_enabled; + //Wait untill periferal is ready for communication + while(!i2c_is_perif_ready(i2c_dev)); + i2c_dev->periferalState = i2c_perif_ready; } -void i2cDisablePeriferal(i2c_t *i2cHardware) +void i2c_periferal_disable(i2c_t *i2c_dev) { I2C_BASE->CR1 &= ~I2C_CR1_PE; + i2c_dev->periferalState = i2c_perif_disabled; } -void i2cSetMode(i2c_t *i2cHardware, i2cMode_t mode) +void i2c_set_mode(i2c_t *i2c_dev, i2c_mode_t mode) { //This device will set himself automatically to master mode - if(i2cHardware->mode == i2cModeMaster) + if(i2c_dev->mode == i2c_mode_master) { //Automatic end mode (master mode) disabled Enablede as default I2C_BASE->CR2 &= ~I2C_CR2_AUTOEND; //I2C_BASE->CR2 |= I2C_CR2_AUTOEND; } - else if(i2cHardware->mode == i2cModeSlave) + else if(i2c_dev->mode == i2c_mode_slave) { // to be written. } } -void i2cSetAddress(i2c_t *i2cHardware, uint16_t mainAddress, uint16_t secondAddress) +void i2c_set_address_lenght(i2c_t *i2c_dev, i2c_address_size_t size) { - -} - -void i2cSetAddressLenght(i2c_t *i2cHardware, i2cAddressSize_t size) -{ - if(i2cHardware->mode == i2cModeMaster) + if(i2c_dev->mode == i2c_mode_master) { - if(i2cHardware->addressSize == i2cAddressSizeTenBits) + if(i2c_dev->addressSize == i2c_address_size_10b) { I2C_BASE->CR2 |= I2C_CR2_ADD10; // 10 Bit addressing I2C_BASE->CR2 &= ~I2C_CR2_HEAD10R; // 7 Bit header read turned on DEFAULT @@ -75,42 +79,42 @@ void i2cSetAddressLenght(i2c_t *i2cHardware, i2cAddressSize_t size) I2C_BASE->CR2 |= I2C_CR2_HEAD10R; // 7 Bit header read turned off DEFAULT } } - else if(i2cHardware->mode == i2cModeSlave) + else if(i2c_dev->mode == i2c_mode_slave) { // to be written. } } -void i2cSetClockStretch(i2c_t *i2cHardware, i2cClockStretching_t stretching) +void i2c_set_clk_stretch(i2c_t *i2c_dev, i2c_clk_stretching_t stretching) { - if(i2cHardware->stretching == i2cClockStretchingEnable) + if(i2c_dev->stretching == i2c_clk_stretching_enable) { I2C_BASE->CR1 &=~ I2C_CR1_NOSTRETCH; } - else if(i2cHardware->stretching == i2cClockStretchingDisable) + else if(i2c_dev->stretching == i2c_clk_stretching_disable) { I2C_BASE->CR1 |= I2C_CR1_NOSTRETCH; } } -void i2cSetSpeed(i2c_t *i2cHardware, i2cSpeed_t speed) +void i2c_set_clk_speed(i2c_t *i2c_dev, i2c_clk_speed_t speed) { switch(speed) { - case i2cSpeedStandart: + case i2c_clk_speed_standart: I2C_BASE->TIMINGR = 0x2000090E; break; - case i2cSpeedFast: + case i2c_clk_speed_fast: break; - case i2cSpeedFastPlus: + case i2c_clk_speed_fastPlus: break; - case i2cSpeedHightSpeed: + case i2c_clk_speed_hightSpeed: break; - case i2cSpeedUltraFast: + case i2c_clk_speed_ultraFast: break; default: @@ -118,213 +122,261 @@ void i2cSetSpeed(i2c_t *i2cHardware, i2cSpeed_t speed) } } -void i2cConfigureFilters(i2c_t *i2cHardware) +void i2c_set_filter(i2c_t *i2c_dev, uint8_t enable) { - //Anlalog filter is on - I2C_BASE->CR1 &= ~I2C_CR1_ANFOFF; + if(enable) + { + //Anlalog filter is on + I2C_BASE->CR1 &= ~I2C_CR1_ANFOFF; + } + else + { + //Anlalog filter is on + I2C_BASE->CR2 |= I2C_CR2_START; + } } - /************************************************************************************************** I2C Hardware functions ***************************************************************************************************/ - -void i2cGenerateStart(i2c_t *i2cHardware) +void i2c_send_start(i2c_t *i2c_dev) { I2C_BASE->CR2 &=~ I2C_CR2_STOP; I2C_BASE->CR2 |= I2C_CR2_START; - //Wait until the start condition in generated. + + //Wait until the start condition in generated. + //Bit 15BUSY: Bus busy + //This flag indicates that a communication is in progress on the bus. It is set by hardware when a + //START condition is detected. It is cleared by hardware when a Stop condition is detected, or + //when PE=0. while(!(I2C_BASE->ISR & (I2C_ISR_BUSY))); - i2cHardware->hardwareState = i2cHwStartGenerated; + + i2c_dev->hardwareState = i2c_hw_sent_start; } -void i2cGenerateStop(i2c_t *i2cHardware) +void i2c_send_stop(i2c_t *i2c_dev) { // Send stop command I2C_BASE->CR2 |= I2C_CR2_STOP; I2C_BASE->CR2 &=~ I2C_CR2_START; - i2cHardware->hardwareState = i2cHwStopGenerated; + i2c_dev->hardwareState = i2c_hw_sent_stop; } -void i2cIsPeriferalReady(i2c_t *i2cHardware) +uint8_t i2c_is_perif_ready(i2c_t *i2c_dev) { - if((I2C_BASE->ISR & (I2C_ISR_BUSY))!=I2C_ISR_BUSY) - { - i2cHardware->periferalState = i2cPerifReady; - } + return ((I2C_BASE->ISR & (I2C_ISR_BUSY))!=I2C_ISR_BUSY); } -void i2cSetTransferCounter(i2c_t *i2cHardware, uint8_t count) +void i2c_set_tx_counter(i2c_t *i2c_dev, uint8_t count) { I2C_BASE->CR2 &= ~(0xFF << I2C_CR2_NBYTES_Pos); I2C_BASE->CR2 |= (count << I2C_CR2_NBYTES_Pos); } -void i2cSendSlaveAddressWrite(i2c_t *i2cHardware, uint16_t *slaveAddress) +void i2c_init_write_command(i2c_t *i2c_dev) { - // The Slave addrress is automatically place on the output buffer (must be done before the start condition) - I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode + I2C_BASE->CR2 &= ~I2C_CR2_RD_WRN; + i2c_dev->hardwareState = i2c_hw_send_write; +} + +void i2c_init_read_command(i2c_t *i2c_dev) +{ + I2C_BASE->CR2 |= I2C_CR2_RD_WRN; + i2c_dev->hardwareState =i2c_hw_send_read; +} + + +void i2c_send_address_for_write(i2c_t *i2c_dev, uint16_t *slaveAddress) +{ + // Arch nemesis ! We send only one byte of data which is the register adress. + i2c_set_tx_counter(i2c_dev,1); // On This chip this shoudl be done before the start condition - i2cInitiateWriteCommand(i2cHardware); + i2c_init_write_command(i2c_dev); - i2cGenerateStart(i2cHardware); + // The Slave addrress is automatically place on the output buffer (must be done before the start condition) + I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode // This device places the salve address automaticaly in the output buffer before sending the star condition - i2cHardware->hardwareState = i2cHwOutputBufferFull; + i2c_send_start(i2c_dev); + i2c_dev->hardwareState = i2c_hw_out_buff_full; - // Wait until the data in the ouput buffer is put to the i2c BUS - while((i2cHardware->hardwareState =! i2cHwOutputBufferEmpty)) - { - i2cIsOutputBufferEmpty(i2cHardware); - } + while(i2c_is_output_buffer_full(i2c_dev)); + + i2c_dev->periferalState = i2c_perif_address_sent; - if(i2cCheckNack(i2cHardware)) - { - i2cHardware->hardwareState = i2cHwGotNack; - i2cThrowError(i2cHardware->hardwareState); + if(i2c_check_nack(i2c_dev)) + { + i2c_dev->hardwareState = i2c_hw_got_nack; + i2c_throw_error(i2c_dev,i2c_dev->hardwareState); } - i2cHardware->hardwareState = i2cHwGotAck; + i2c_dev->hardwareState = i2c_hw_got_ack; } -void i2cSendSlaveAddressRead(i2c_t *i2cHardware, uint16_t *slaveAddress) +void i2c_send_address_for_read(i2c_t *i2c_dev, uint16_t *slaveAddress) { - // The Slave addrress is automatically place on the output buffer (must be done before the start condition) - I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode + // Arch nemesis ! We only setn the address + // but the counter allso socunt the bits that we have recieved + // and we want to read one byte + // every transaction counts + i2c_set_tx_counter(i2c_dev,1); // On This chip this shoudl be done before the start condition - i2cInitiateReadCommand(i2cHardware); + i2c_init_read_command(i2c_dev); - i2cGenerateStart(i2cHardware); - + // The Slave addrress is automatically place on the output buffer (must be done before the start condition) + I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode // This device places the salve address automaticaly in the output buffer before sending the star condition - i2cHardware->hardwareState = i2cHwOutputBufferFull; + i2c_send_start(i2c_dev); + i2c_dev->hardwareState = i2c_hw_out_buff_full; - while((i2cHardware->hardwareState =! i2cHwOutputBufferEmpty)) - { - i2cIsOutputBufferEmpty(i2cHardware); - } + while(i2c_is_output_buffer_full(i2c_dev)); + + i2c_dev->periferalState = i2c_perif_address_sent; - if(i2cCheckNack(i2cHardware)) - { - i2cHardware->hardwareState = i2cHwGotNack; - i2cThrowError(i2cHardware->hardwareState); + if(i2c_check_nack(i2c_dev)) + { + i2c_dev->hardwareState = i2c_hw_got_nack; + i2c_throw_error(i2c_dev,i2c_dev->hardwareState); } - i2cHardware->hardwareState = i2cHwGotAck; + i2c_dev->hardwareState = i2c_hw_got_ack; } -void i2cSendRegisterAddress(i2c_t *i2cHardware, uint8_t *registerAddress) +uint8_t i2c_is_output_buffer_full(i2c_t *i2c_dev) { - i2cSendData(i2cHardware,registerAddress); + /* + Bit 0 TXE: Transmit data register empty (transmitters) + This bit is set by hardware when the I2C_TXDR register is empty. It is cleared when the next + data to be sent is written in the I2C_TXDR register. + This bit can be written to ‘1’ by software in order to flush the transmit data register I2C_TXDR. + Note: This bit is set by hardware when PE=0. + */ + if(I2C_BASE->ISR & I2C_ISR_TXE) + { + i2c_dev->hardwareState = i2c_hw_out_buff_empty; + return 0; + } + else + { + i2c_dev->hardwareState = i2c_hw_out_buff_full; + return 1; + } } -void i2cInitiateWriteCommand(i2c_t *i2cHardware) +void i2c_send_reg_address(i2c_t *i2c_dev, uint8_t *registerAddress) { - I2C_BASE->CR2 &= ~I2C_CR2_RD_WRN; + i2c_send_data(i2c_dev,registerAddress); } -void i2cInitiateReadCommand(i2c_t *i2cHardware) +void i2c_send_data(i2c_t *i2c_dev, uint8_t *data) { - I2C_BASE->CR2 |= I2C_CR2_RD_WRN; + I2C_BASE->TXDR = *data; + i2c_dev->hardwareState = i2c_hw_out_buff_full; + while(i2c_is_output_buffer_full(i2c_dev)); } -void i2cSendData(i2c_t *i2cHardware, uint8_t *registerAddress) +uint8_t i2c_is_tx_complete(i2c_t *i2c_dev) { - while((i2cHardware->hardwareState =! i2cHwOutputBufferEmpty)) + /* + TC: Transfer Complete (master mode) + This flag is set by hardware when RELOAD=0, AUTOEND=0 and NBYTES data have been + transferred. It is cleared by software when START bit or STOP bit is set. + Note: This bit is cleared by hardware when PE=0. + */ + + if(I2C_BASE->ISR & I2C_ISR_TC) { - i2cIsOutputBufferEmpty(i2cHardware); - } - - i2cSetOutputRegister(i2cHardware,registerAddress); - - while((i2cHardware->hardwareState =! i2cHwOutputBufferEmpty)) - { - i2cIsOutputBufferEmpty(i2cHardware); + i2c_dev->periferalState = i2c_perif_tx_done; + return 1; } - if(i2cCheckNack(i2cHardware)) + else { - i2cHardware->hardwareState = i2cHwGotNack; - i2cThrowError(i2cHardware->hardwareState); + i2c_dev->periferalState = i2c_perif_tx_ongoing; + return 0; } - i2cHardware->hardwareState = i2cHwGotAck; } -void i2cIsOutputBufferEmpty(i2c_t *i2cHardware) +uint8_t i2c_is_input_buffer_full(i2c_t *i2c_dev) { - if((i2cHardware->periferalState) == i2cPerifTransmitting) + if(I2C_BASE->ISR & I2C_ISR_RXNE) { - if((I2C_BASE->ISR & (I2C_ISR_TXIS)) == I2C_ISR_TXIS) - { - i2cHardware->hardwareState = i2cHwOutputBufferEmpty; - } - else - { - i2cHardware->hardwareState = i2cHwOutputBufferFull; - } + i2c_dev->hardwareState = i2c_hw_in_buff_full; + return 1; } - else if((i2cHardware->periferalState) == i2cPerifRecieving) + else { - if((I2C_BASE->ISR & (I2C_ISR_TXE)) == I2C_ISR_TXE) - { - i2cHardware->hardwareState = i2cHwOutputBufferEmpty; - } - else - { - i2cHardware->hardwareState = i2cHwOutputBufferFull; - } + i2c_dev->hardwareState = i2c_hw_in_buff_empty; + return 0; } } -void i2cIsInputBufferEmpty(i2c_t *i2cHardware) +void i2c_get_input_register(i2c_t *i2c_dev, uint8_t *data) +{ + *data = I2C_BASE->RXDR; +} + +void i2c_send_nack(i2c_t *i2c_dev) { - if((I2C_BASE->ISR & (I2C_ISR_RXNE)) == I2C_ISR_RXNE) + if(i2c_dev->mode == i2c_mode_master) { - i2cHardware->hardwareState = i2cHwInputBufferFull; + //IN master mode this ic geretes NACK's otomatically + i2c_dev->hardwareState = i2c_hw_sent_nack; } - else + else if(i2c_dev->mode == i2c_mode_slave) { - i2cHardware->hardwareState = i2cHwInputBufferEmpty; + // to be written. } } - -void i2cReadInputRegister(i2c_t *i2cHardware, uint8_t *data) +/* +void i2cSendSlaveAddressRead(i2c_t *i2c_dev, uint16_t *slaveAddress) { - *data = I2C_BASE->RXDR; + I2C_BASE->CR2 &= ~I2C_CR2_AUTOEND; + // The Slave addrress is automatically place on the output buffer (must be done before the start condition) + I2C_BASE->CR2 |= (*slaveAddress & 0xff) << 1; // The bit no 0 is not taken in concideration in 7bit mode + + // On This chip this shoudl be done before the start condition + i2cInitiateReadCommand(i2c_dev); + + i2cGenerateStart(i2c_dev); + + // This device places the salve address automaticaly in the output buffer before sending the star condition + i2c_dev->hardwareState = i2cHwOutputBufferFull; + + while((i2c_dev->hardwareState =! i2cHwOutputBufferEmpty)) + { + i2cIsOutputBufferEmpty(i2c_dev); + } } -void i2cSetOutputRegister(i2c_t *i2cHardware, uint8_t *data) + + + + + + + +void i2cSetOutputRegister(i2c_t *i2c_dev, uint8_t *data) { - I2C_BASE->TXDR = *data; - i2cHardware->hardwareState = i2cHwOutputBufferFull; + i2c_dev->hardwareState = i2cHwOutputBufferFull; } -void i2cIsTransferComplete(i2c_t *i2cHardware) +void i2cIsTransferComplete(i2c_t *i2c_dev) { if((I2C_BASE->ISR & (I2C_ISR_TC)) == I2C_ISR_TC) { - i2cHardware->periferalState = i2cPerifTransferComplete; + i2c_dev->periferalState = i2cPerifTransferComplete; } else { - i2cHardware->periferalState = i2cPerifTransferOngoign; + i2c_dev->periferalState = i2cPerifTransferOngoign; } } -void i2cGenerateNack(i2c_t *i2cHardware) -{ - if(i2cHardware->mode == i2cModeMaster) - { - //IN master mode this ic geretes NACK's otomatically - i2cHardware->hardwareState = i2cHwSentNack; - } - else if(i2cHardware->mode == i2cModeSlave) - { - // to be written. - } } +*/ -uint8_t i2cCheckNack(i2c_t *i2cHardware) +uint8_t i2c_check_nack(i2c_t *i2c_dev) { if((I2C_BASE->ISR & (I2C_ISR_NACKF))) { @@ -332,3 +384,7 @@ uint8_t i2cCheckNack(i2c_t *i2cHardware) } return 0; } + +void i2c_set_address(i2c_t *i2c_dev, uint16_t address){} +void i2c_set_address_second(i2c_t *i2c_dev, uint16_t address){} + diff --git a/peripherals/i2c.c b/peripherals/i2c.c index 9bb46bb..5a6cb93 100644 --- a/peripherals/i2c.c +++ b/peripherals/i2c.c @@ -1,61 +1,63 @@ #include "i2c.h" #include "usart.h" -//uint32_t i2cCR1; -//uint32_t i2cCR2; -//uint32_t i2cISR; -void i2cInit( i2c_t *i2cHardware, - i2cCh_t channelNo, - i2cMode_t mode, - uint16_t mainAddress, - uint16_t secondAddress, - i2cAddressCount_t addressCount, - i2cAddressSize_t addressSize, - i2cSpeed_t speed, - i2cOpperationMode_t opperationMode, - i2cClockStretching_t stretching, - i2cWakeUpTypes_t wakeOn) +void i2c_init( i2c_t *i2c_dev, /*!< Pointer to I2C hardware Object */ + i2cCh_t channelNo, /*!< The harware channel to be used */ + i2c_mode_t mode, /*!< Master, Slave or Multymaster Modes */ + uint16_t mainAddress, /*!< First and Main address of the device */ + uint16_t secondAddress, /*!< Second address if dual addresse mode is configured */ + i2c_address_count_t addressCount, /*!< Single or multiple */ + i2c_address_size_t addressSize, /*!< 10 or 7 bit address size */ + i2c_clk_speed_t speed, /*!< Bus Speed */ + i2c_clk_stretching_t stretching, /*!< Clock Stretching enable onyl in slave mode */ + i2c_wake_types_t wakeOn /*!< Wake up condition */ + ) { - i2cHardware->channelNo = channelNo; - i2cHardware->mode = mode; - i2cHardware->mainAddress = mainAddress; - i2cHardware->secondAddress = secondAddress; - i2cHardware->addressCount = addressCount; - i2cHardware->addressSize = addressSize; - i2cHardware->speed = speed; - i2cHardware->opperationMode = opperationMode; - i2cHardware->stretching = stretching; - i2cHardware->wakeOn = wakeOn; - i2cHardware->hardwareState = i2cHwIdle; - i2cHardware->periferalState = i2cPerifNotInitialized; - - i2cEnableHardware(i2cHardware); - i2cDisablePeriferal(i2cHardware); - i2cConfigureFilters(i2cHardware); - i2cSetClockStretch(i2cHardware, stretching); - i2cSetSpeed(i2cHardware, speed); - i2cSetMode(i2cHardware, opperationMode); - i2cSetAddressLenght(i2cHardware, addressSize); - i2cSetAddress(i2cHardware, mainAddress, secondAddress); - i2cEnablePeriferal(i2cHardware); + i2c_dev->channelNo = channelNo; + i2c_dev->mode = mode; + i2c_dev->mainAddress = mainAddress; + i2c_dev->secondAddress = secondAddress; + i2c_dev->addressCount = addressCount; + i2c_dev->addressSize = addressSize; + i2c_dev->speed = speed; + i2c_dev->stretching = stretching; + i2c_dev->wakeOn = wakeOn; - while(i2cHardware->periferalState != i2cPerifReady) - { - i2cIsPeriferalReady(i2cHardware); - } - - i2cHardware->periferalState = i2cPerifInitialized; + //Initial state States + i2c_dev->hardwareState = i2c_hw_disabled; + i2c_dev->periferalState = i2c_perif_disabled; + + i2c_hardware_enable(i2c_dev); + i2c_periferal_disable(i2c_dev); // Just to be sure as periferal configuration can not be dont when active. + i2c_set_filter(i2c_dev,1); + i2c_set_clk_stretch(i2c_dev, stretching); + i2c_set_clk_speed(i2c_dev, speed); + i2c_set_mode(i2c_dev, mode); + i2c_set_address_lenght(i2c_dev, addressSize); + i2c_set_address(i2c_dev, mainAddress); + i2c_set_address_second(i2c_dev, mainAddress); + i2c_periferal_enable(i2c_dev); + print_Usart(usart2, "I2C -> periferal enabled\n\r"); } - -void i2cDeInit(i2c_t *i2cHardware) +void i2c_read(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght) { + i2c_send_address_for_write(i2c_dev, slaveAddress); + i2c_send_reg_address(i2c_dev, registerAddress); + while(!i2c_is_tx_complete(i2c_dev)); + i2c_send_address_for_read(i2c_dev, slaveAddress); + while(!i2c_is_input_buffer_full(i2c_dev)); + i2c_get_input_register(i2c_dev, data); + while(!i2c_is_tx_complete(i2c_dev)); + i2c_send_nack(i2c_dev); + i2c_send_stop(i2c_dev); + print_Usart(usart2, "I2C -> Read Done\n\r"); +} +void i2c_write(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght){} -} - - -void i2cRead(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght) +/* +void i2cRead(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght) { // @@ -63,54 +65,67 @@ void i2cRead(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddres // Send Address // Wait For ACK // - i2cSetTransferCounter(i2cHardware,1); - i2cSendSlaveAddressWrite(i2cHardware, slaveAddress); - i2cHardware->periferalState = i2cPerifTransmitting; - - i2cSendRegisterAddress(i2cHardware,registerAddress); + uint8_t nbytes = 0; - while(i2cHardware->periferalState != i2cPerifTransferComplete) + i2c_dev->periferalState = i2cPerifTransmitting; + + i2cSetTransferCounter(i2c_dev,1); + i2cSendSlaveAddressWrite(i2c_dev, slaveAddress); + i2cSendRegisterAddress(i2c_dev,registerAddress); + + while(i2c_dev->periferalState != i2cPerifTransferComplete) { - i2cIsTransferComplete(i2cHardware); + i2cIsTransferComplete(i2c_dev); } - i2cSendSlaveAddressRead(i2cHardware, slaveAddress); - i2cHardware->periferalState = i2cPerifRecieving; + i2c_dev->periferalState = i2cPerifRecieving; + i2cSendSlaveAddressRead(i2c_dev, slaveAddress); - while(i2cHardware->periferalState != i2cPerifTransferComplete) + + while(i2c_dev->periferalState != i2cPerifTransferComplete) { - i2cIsTransferComplete(i2cHardware); + i2cIsTransferComplete(i2c_dev); } - i2cGenerateNack(i2cHardware); - i2cGenerateStop(i2cHardware); + i2cGenerateNack(i2c_dev); + i2cGenerateStop(i2c_dev); + + i2cReadInputRegister(i2c_dev, data); - i2cReadInputRegister(i2cHardware, data); + print_Usart(usart2, "\n\rI2C Read completed\n\r"); - while(i2cHardware->periferalState != i2cPerifReady) + while(i2c_dev->periferalState != i2cPerifReady) { - i2cIsPeriferalReady(i2cHardware); + i2cIsPeriferalReady(i2c_dev); } - i2cHardware->periferalState = i2cPerifReady; - i2cHardware->hardwareState = i2cHwIdle; + i2c_dev->periferalState = i2cPerifReady; + i2c_dev->hardwareState = i2cHwIdle; } -void i2cWrite(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght) +void i2cWrite(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght) { - i2cSetTransferCounter(i2cHardware,0); - i2cSendSlaveAddressWrite(i2cHardware, slaveAddress); - i2cHardware->periferalState = i2cPerifTransmitting; - i2cSendRegisterAddress(i2cHardware,registerAddress); - i2cHardware->periferalState = i2cPerifTransmitting; - i2cSendData(i2cHardware,data); - while(i2cHardware->periferalState != i2cPerifTransferComplete) + i2cSetTransferCounter(i2c_dev,2); + i2cSendSlaveAddressWrite(i2c_dev, slaveAddress); + i2cSendRegisterAddress(i2c_dev,registerAddress); + while((i2c_dev->hardwareState =! i2cHwOutputBufferEmpty)) { - i2cIsTransferComplete(i2cHardware); + i2cIsOutputBufferEmpty(i2c_dev); } + i2cSendData(i2c_dev,data); + + i2cGenerateStop(i2c_dev); + print_Usart(usart2, "\n\rI2C Transfer completed\n\r"); } -void i2cThrowError(int16_t error) +*/ +void i2c_throw_error(i2c_t *i2c_dev, int16_t error) { - print_Usart(usart2, "I2C Error Detected : "); + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "I2C Error Detected : "); + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "I2C Error No: "); usartSendChar(usart2, error + 0x30); + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "\n\r"); } diff --git a/peripherals/i2c.h b/peripherals/i2c.h old mode 100755 new mode 100644 index 2f38353..d666764 --- a/peripherals/i2c.h +++ b/peripherals/i2c.h @@ -1,566 +1,522 @@ -/** - ************************************************************************************************** - * @file i2c.h - * @author Kerem Yollu & Edwin Koch - * @date 18.07.2022 - * @version 1.01 - ************************************************************************************************** - * @brief I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : - * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA - * This will also not have a I3C support for the forseable futrue. - * - * **Detailed Description :** - * - * I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : - * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA - * This will also not have a I3C support for the forseable futrue. - * - * @todo - * - 26.07.2021 : Implement the DMA - * - 26.07.2021 : Implement the Interrupt - * - 26.07.2021 : Implement the Sleep/WakeUp - * - 26.07.2021 : Implement the Slave opperation - ************************************************************************************************** -*/ - -#ifndef _I2C_H_ -#define _I2C_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "hardwareDescription.h" -#include "pin.h" - - - -/*! Enum of possible I2C opperation modes */ -typedef enum{ - i2cModeMaster, /*!< Master mode : In Master mode, the I2C interface initiates - a data transfer and generates the clock signal. **DEFAULT** */ - i2cModeMultyMaster, /*!< Multimaster Mode : In case if more than one master are present - in one I2C bus. In such case each device needs to be able to - cooperate knowing that another device could talking - therefore the bus is busy (Arbirtation). - For More information : https://www.i2c-bus.org/multimaster/ */ - i2cModeSlave /*!< Slave mode : A slave device has to always be ready to detect and - process a start condition and to recognize its address */ -}i2cMode_t; - -/*! Enum of possible I2C speeds */ -typedef enum{ - i2cSpeedStandart, /*!< SM 100 kbits/s Standart i2c Speed **DEFAULT** */ - i2cSpeedFast, /*!< FM 400 kbits/s */ - i2cSpeedFastPlus, /*!< FM+ 1 Mbits/s */ - i2cSpeedHightSpeed, /*!< HS 3.4 Mbits/s */ - i2cSpeedUltraFast /*!< UFM 5 Mbits/s */ -}i2cSpeed_t; - -/*! Enum of possible I2C Adress sizes */ -typedef enum{ - i2cAddressSizeSevenBits, /*!< 7 Bits address size **DEFAULT** */ - i2cAddressSizeTenBits /*!< 10 Bits address size */ -}i2cAddressSize_t; - -/*! Enum of possible I2C Address count */ -typedef enum{ - i2cAddressCountSingle, /*!< Only one address for communication **DEFAULT** */ - i2cAddressCountDual /*!< Dual addresses for one device respondng to two addresses */ -}i2cAddressCount_t; - -/*! Enum for clock strechning activation. Can only be implmented as Slave - * for more information : https://www.i2c-bus.org/clock-stretching/ */ -typedef enum{ - i2cClockStretchingDisable, /*!< We assume that the master and slave have compatible - Clock frequencies **DEFAULT** */ - i2cClockStretchingEnable /*!< In situations where an I2C slave is not able to co-operate - with the clock speed given by the master and needs to slow down. - This is done by a mechanism referred to as clock stretching. */ -}i2cClockStretching_t; - -/*! Enum for diffenrent wake up methodes wehnin sleep mode */ -typedef enum{ - i2cWakeUpDisabled, /*!< No wake up is possible this is the default mode also means that - the sleep function is not implmentes **DEFAULT** */ - i2cWakeUpOnAddressMatch /*!< Wakes up on address match, this can be harware dependent */ -}i2cWakeUpTypes_t; - -/*! Enum operation mode of the i2c channel */ -typedef enum{ - i2cOpperationPolling, /*!< Polling mode Blocking, i2c communication states are constantly - checked on polling mode so it can be stoped - when interrupts occures **DEFAULT** */ - i2cOpperationInt, /*!< Interrut Mode Non-blocking, i2c communications state changes - generates an interrupt and can be handeled this way */ - i2cOpperationDma /*!< DMA Mode Non-blocking, I2C communication satets are managed - via Inteerupts and with Direct Memory Access */ -}i2cOpperationMode_t; - -/*! typedef for the i2c states*/ -typedef enum -{ - i2cHwIdle, /*!< Hardware is in Idle Mode **DEFAULT** */ - i2cHwStartGenerated, /*!< Generated the star condition */ - i2cHwOutputBufferFull, /*!< The output buffer of the I2C Periferal is Full */ - i2cHwOutputBufferEmpty, /*!< The output buffer of the I2C Periferal is Empty */ - i2cHwInputBufferFull, /*!< The input buffer of the I2C Periferal Is Full */ - i2cHwInputBufferEmpty, /*!< The input buffer of the I2C Periferal Is Empty */ - i2cHwSentRead, /*!< Sent read request */ - i2cHwSentWrite, /*!< Sent write request */ - i2cHwGotAck, /*!< Recieved ACK */ - i2cHwGotNack, /*!< Recieved NACK */ - i2cHwSentAck, /*!< Sent ACK */ - i2cHwSentNack, /*!< Sent NACK */ - i2cHwStopGenerated, /*!< Generated the star condition */ - i2cHwError /*!< Error */ -} i2cHardwareState_t; - -typedef enum -{ - i2cPerifNotInitialized, /*!< Default Peripheral is not yet Initialized **DEFAULT** */ - i2cPerifInitialized, /*!< I2C CHannle is initilized but not neceserly ready */ - i2cPerifSlaveAddressSent, /*!< The Salve Address Was Sent to the bus */ - i2cPerifTransferComplete, /*!< A full communication process is complete (wire or Read) */ - i2cPerifTransferOngoign, /*!< A full communication process is in progress (wire or Read) */ - i2cPerifReady, /*!< Peripheral Initialized and ready for use */ - i2cPerifSlaveNotFound, /*!< Desired Slave was not able to be found */ - i2cPerifTransmitting, /*!< Data Transmission process is ongoing */ - i2cPerifRecieving, /*!< Data Reception process is ongoing */ - i2cPerifListening, /*!< Address Listen Mode is ongoing */ - i2cPerifListeningAndTransmitting, /*!< Address Listen Mode and ongoing Data Transmission */ - i2cPerifListeningAndRecieveing, /*!< Address Listen Mode and ongoing Data Reception */ - i2cPerifAbort, /*!< Abort user request ongoing */ - i2cPerifTimeout, /*!< Timeout state */ - i2cPerifError /*!< Error */ -} i2cPeriferalState_t; -/*! Struture a an i2c channel with all the required propereties*/ -typedef struct i2c_t -{ - i2cCh_t channelNo; /*!< The harware channel to be used */ - i2cMode_t mode; /*!< Master, Slave or Multymaster Modes */ - uint16_t mainAddress; /*!< First and Main address of the device */ - uint16_t secondAddress; /*!< Second address if dual addresse mode is configured */ - i2cAddressCount_t addressCount; /*!< Single or multiple */ - i2cAddressSize_t addressSize; /*!< 10 or 7 bit address size */ - i2cSpeed_t speed; /*!< Bus Speed */ - i2cOpperationMode_t opperationMode; /*!< Blocking or non blocking polling, Int or DMA */ - i2cClockStretching_t stretching; /*!< Clock Stretching enable onyl in slave mode */ - i2cWakeUpTypes_t wakeOn; /*!< Define on which type of action the i2c channel should - wake up. Only if de prefiral goes to sleep */ - i2cHardwareState_t hardwareState; /*!< The current sitate of the I2C Bus */ - i2cPeriferalState_t periferalState; /*!< The current sitate of the I2C Bus */ -}i2c_t; - -/*************************************************************************************************** - I2C Configuration functions -***************************************************************************************************/ - -/** - * @brief Initilize the I2C Hardware - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cInit( i2c_t *i2cHardware, /*!< Pointer to I2C hardware Object */ - i2cCh_t channelNo, /*!< The harware channel to be used */ - i2cMode_t mode, /*!< Master, Slave or Multymaster Modes */ - uint16_t mainAddress, /*!< First and Main address of the device */ - uint16_t secondAddress, /*!< Second address if dual addresse mode is configured */ - i2cAddressCount_t addressCount, /*!< Single or multiple */ - i2cAddressSize_t addressSize, /*!< 10 or 7 bit address size */ - i2cSpeed_t speed, /*!< Bus Speed */ - i2cOpperationMode_t opperationMode, /*!< Blocking or non blocking polling, Int or DMA */ - i2cClockStretching_t stretching, /*!< Clock Stretching enable onyl in slave mode */ - i2cWakeUpTypes_t wakeOn /*!< Wake up condition */ - ); - -/** - * @brief De-Initilize the I2C Hardware - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cDeInit(i2c_t *i2cHardware); - -/** - * @brief Set the i2c channle to the gievn mode - * @param Channel is the i2c hardware channel - * @param mode The mode for i2c : Master Slave or Multymaster - */ -void i2cSetMode(i2c_t *i2cHardware, i2cMode_t mode); - -/** - * @brief Set the i2c channles mode as Master Slave or Multymaster - * @param i2cHardware is the i2c hardware channel - * @param addressOne The forst address for the device - * @param addressTwo The second address for the device only if dual address mode is not defined - */ -void i2cSetAddress(i2c_t *i2cHardware, uint16_t mainAddress, uint16_t secondAddress); - -/** - * @brief Set the i2c Address Lenght, 7 bit or 8 bit, Master or slave doesn't make any difference - * @param i2cHardware is the i2c hardware channel - * @param size Is the Adress isze to be used 7 Bit or 10 Bit - */ -void i2cSetAddressLenght(i2c_t *i2cHardware, i2cAddressSize_t size); - -/** - * @brief Stets the Communication speed - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param speed the different awailable speeds - */ -void i2cSetSpeed(i2c_t *i2cHardware, i2cSpeed_t speed); - -/** - * @brief Initiates the opperation mode for the selected i2c Channel - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param opperation define if the i2c channel will opperate on pollin, Interrupt, or DMA modes - */ -void i2cSetOpperation(i2c_t *i2cHardware, i2cOpperationMode_t opperation); - - -/** - * @brief Ebales or disables clock stretching functionalities - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param The value to be written in the register. This will heavily depend on the hardware - */ -void i2cSetClockStretch(i2c_t *i2cHardware, i2cClockStretching_t stretching); - -/** - * @brief Set the wakeup mode - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param wake the desider wakeup mode for now i have found only one mode. - */ -void i2cSetWakeup(i2c_t *i2cHardware, i2cWakeUpTypes_t wake); - -/** - * @brief Configures Hardware implmente filters if there are any. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cConfigureFilters(i2c_t *i2cHardware); - -/** - * @brief Set the timeout to close the i2c wait time if a communication fails. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param timeout the desider timeout duration in ticks. - */ -void i2cSetTimeout(i2c_t *i2cHardware, uint8_t timeout); - -/** - * @brief Resets the i2c Periferal to it's inital state. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cPeriferalReset(i2c_t *i2cHardware); - -/** - * @brief Resets the i2c Harware and register to it's factory deflauts. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cHardwareReset(i2c_t *i2cHardware); - -/** - * @brief Enables I2C Hardware BUS & Clock & Pins - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cEnableHardware(i2c_t *i2cHardware); - -/** - * @brief Enables I2C Periferal core. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cEnablePeriferal(i2c_t *i2cHardware); - -/** - * @brief Disables I2C Periferal core. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cDisablePeriferal(i2c_t *i2cHardware); - -/************************************************************************************************** - I2C Communication functions independen of opperating mode -***************************************************************************************************/ - -/** - * @brief Writes the given amount of data to the selected device. This function will - * automaticaly choose between i2cMasterSend(); or i2cSlaveSend(); - * Depending if the I2C channel was initiated as slave or master. - * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data to be written - * @param dataLenght is the total quantity of 8 bit data to be written. - */ -void i2cWrite(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght); - -/** - * @brief Reads the given amount of data to the selected device. This function will - * automaticaly choose between i2cMasterRecieve(); or i2cSlaveRecieve(); - * Depending if the I2C channel was initiated as slave or master. - * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data which has been red - * @paran dataLenght is the total quantity of 8 bit data to be red - */ -void i2cRead(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght); - -/** - * @brief Recieve a Single Byte as master from from the given devices register. - * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data whic has been red - */ -void i2cMasterRecieve(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); -/** - * @brief Sends a Single Byte as master to the given devices register. - * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the send command will be sent - * @param registerAddress is the regiter to be written to the device - * @param data is the data to be sent - */ -void i2cMasterSend(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); - -/** - * @brief Recieve a Single Byte as slave from given devices register. - * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data whic has been red - */ -void i2cSlaveRecieve(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); - -/** - * @brief Recieve a Single Byte as slave from the given devices register. - * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data whic has been red - */ -void i2cSlaveSend(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); - -/************************************************************************************************** - I2C Hardware functions -***************************************************************************************************/ -/** - * @brief Checks if the device is ready for any type of communication - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cIsPeriferalReady(i2c_t *i2cHardware); - -/** - * @brief Generates a Start condition. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cGenerateStart(i2c_t *i2cHardware); - -/** - * @brief Generates a Start condition. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cGenerateStop(i2c_t *i2cHardware); - -/** - * @brief Generates a NACK condition. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cGenerateNack(i2c_t *i2cHardware); - -/** - * @brief Checks If a NACK is recieved. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -uint8_t i2cCheckNack(i2c_t *i2cHardware); - -/** - * @brief Generates a ACK condition. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cGenerateAck(i2c_t *i2cHardware); - -/** - * @brief Initiates the communication by sending the slave address on the bus followed by a WRITE - * and waits for an ACK (aknowledge) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress The address of the slave to be communicated - */ -void i2cSendSlaveAddressWrite(i2c_t *i2cHardware, uint16_t *slaveAddress); - -/** - * @brief Initiates the communication by sending the slave address on the bus followed by a READ - * and waits for an ACK (aknowledge) - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress The address of the slave to be communicated - */ -void i2cSendSlaveAddressRead(i2c_t *i2cHardware, uint16_t *slaveAddress); - -/** - * @brief Sende the register adrres with which we want to communicate. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param registerAddress The register address of the slave device that we are communication with - */ -void i2cSendRegisterAddress(i2c_t *i2cHardware, uint8_t *registerAddress); - -/** - * @brief Send the register that we want to read or write. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param registerAddress the register that need to be accessed - */ -void i2cSendData(i2c_t *i2cHardware, uint8_t *registerAddress); - -/** - * @brief Initiates a Write command with the previously set slave address. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cInitiateWriteCommand(i2c_t *i2cHardware); - -/** - * @brief Initiates a read command with the previously set slave address. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cInitiateReadCommand(i2c_t *i2cHardware); - -/** - * @brief Is the output buffer empty. This allso meas that the data that was in the ouput buffer - * is sent to the i2c BUS. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cIsOutputBufferEmpty(i2c_t *i2cHardware); - -/** - * @brief Is the output buffer empty. This allso meas that the data that was in the ouput buffer - * is sent to the i2c BUS. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cIsInputBufferEmpty(i2c_t *i2cHardware); - -/** - * @brief reads the I2C input buffer - * is sent to the i2c BUS. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param data pointer to the data that need to be read and returned - */ -void i2cReadInputRegister(i2c_t *i2cHardware, uint8_t *data); - -/** - * @brief writes to the I2C output buffer - * is sent to the i2c BUS. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param data pointer to the data that need to be read and returned - */ -void i2cSetOutputRegister(i2c_t *i2cHardware, uint8_t *data); - -/** - * @brief Checks is transfer is complete - * is sent to the i2c BUS. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param data pointer to the data that need to be read and returned - */ -void i2cIsTransferComplete(i2c_t *i2cHardware); - -/** - * @brief Defines the amount of transfers to be made. Address exchange and start conditon does not count - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param count amount o data to be transfered. - */ -void i2cSetTransferCounter(i2c_t *i2cHardware, uint8_t count); -/************************************************************************************************** - I2C Communication functions Polling / Blocking Mode -***************************************************************************************************/ - -/** - * @brief Recieve a Single Byte in polling mode as master from from the given devices register. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data whic has been red - */ -void i2cMasterRecievePolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); -/** - * @brief Sends a Single Byte in polling mode as master to the given devices register. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the send command will be sent - * @param registerAddress is the regiter to be written to the device - * @param data is the data to be sent - */ -void i2cMasterSendPolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); - -/** - * @brief Recieve a Single Byte in polling mide as slave from the given devices register. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data whic has been red - */ -void i2cSlaveRecievePolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); - -/** - * @brief Recieve a Single Byte in polling mode as slave from the given devices register. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - * @param registerAddress is the regiter to be red from the device - * @param data is the data whic has been red - */ -void i2cSlaveSendPolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); - -/************************************************************************************************** - I2C Arbitration Functions for Multymaster mode and slaves clock stretching -***************************************************************************************************/ -void i2cClockSynchronise(); // I2C Standart : Clock Syncronization -void i2cAbortTransmit(); // I2c Standart : Stop Communication for multimaster mode -void i2cArbitration(); // I2C Standart : Arbitration for multimaster mode to define the right master. -void i2cSoftReset(); // I2C Standart : Software reset not supported by all hardware. -void i2cBusClear(); // I2C Standart : in case if SCL is stuck - - -/************************************************************************************************** - I2C Extra functions that are not esential for the main functionality -***************************************************************************************************/ - -/** - * @brief This function will scan every for possible addresses to discover devices on the bus. - * And write them to the Devices list given to him. This function will not discover more - * devices than what he is told. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param devices list where the discevered devices will be written - * @param deviceCount Max number of devices to be discovered. - */ -void i2cDiscoverDevices(i2c_t *i2cHardware, uint16_t *devices, uint8_t deviceCount); - -/** - * @brief This function will try to communicate with a device with every speed - * allowed by his hardware to find out the maximum communication sppeed possible. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to which the read command will be sent - */ -i2cSpeed_t i2cTestDeviceSpeed(i2c_t *i2cHardware, uint16_t *slaveAddress); - -/** - * @brief This function will read the device info register (if awailable) as follows : - * I2c Standart : 3 Bytes (24 bits) | 12 Bits : Manufacturer info | 9 Bits: Part Identification | 3 Bits DIE Rev. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - * @param slaveAddress is the address of the device to be red - */ -uint32_t i2cReadDeviceInfo(i2c_t *i2cHardware, uint16_t *slaveAddress); - -/** - * @brief The selected i2c channel is put on sleep. - * @param i2cHardware is the beforehand declared i2c channel with his opperation modes - */ -void i2cSleep(i2c_t *i2cHardware); - -/** - * @brief Error handling. - * @param error The error no generated. - */ -void i2cThrowError(int16_t error); // Defined by me : Private error function for error handling - - -#ifdef __cplusplus -} -#endif - -#endif // _I2C_H_ +/** + ************************************************************************************************** + * @file i2c.h + * @author Kerem Yollu & Edwin Koch + * @date 16.02.2023 + * @version 1.2 + ************************************************************************************************** + * @brief I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : + * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA + * This will also not have a I3C support for the forseable futrue. + * + * **Detailed Description :** + * + * I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : + * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA + * This will also not have a I3C support for the forseable futrue. + * + * @todo + * - 26.07.2021 : Implement DMA + * - 26.07.2021 : Implement Interrupt + * - 26.07.2021 : Implement Sleep/WakeUp + * - 26.07.2021 : Implement Slave opperation + ************************************************************************************************** +*/ + +#ifndef _I2C_H_ +#define _I2C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "hardwareDescription.h" +#include "pin.h" + + + +/*! Enum of possible I2C opperation modes */ +typedef enum{ + i2c_mode_master, /*!< Master mode : In Master mode, the I2C interface initiates + a data transfer and generates the clock signal. **DEFAULT** */ + i2c_mode_multyMaster, /*!< Multimaster Mode : In case if more than one master are present + in one I2C bus. In such case each device needs to be able to + cooperate knowing that another device could talking + therefore the bus is busy (Arbirtation). + For More information : https://www.i2c-bus.org/multimaster/ */ + i2c_mode_slave /*!< Slave mode : A slave device has to always be ready to detect and + process a start condition and to recognize its address */ +}i2c_mode_t; + +/*! Enum of possible I2C speeds */ +typedef enum{ + i2c_clk_speed_standart, /*!< SM 100 kbits/s Standart i2c Speed **DEFAULT** */ + i2c_clk_speed_fast, /*!< FM 400 kbits/s */ + i2c_clk_speed_fastPlus, /*!< FM+ 1 Mbits/s */ + i2c_clk_speed_hightSpeed, /*!< HS 3.4 Mbits/s */ + i2c_clk_speed_ultraFast /*!< UFM 5 Mbits/s */ +}i2c_clk_speed_t; + +/*! Enum of possible I2C Adress sizes */ +typedef enum{ + i2c_address_size_7b, /*!< 7 Bits address size **DEFAULT** */ + i2c_address_size_10b /*!< 10 Bits address size */ +}i2c_address_size_t; + +/*! Enum of possible I2C Address count */ +typedef enum{ + i2c_address_count_single, /*!< Only one address for communication **DEFAULT** */ + i2c_address_count_dual /*!< Dual addresses for one device respondng to two addresses */ +}i2c_address_count_t; + +/*! Enum for clock strechning activation. Can only be implmented as Slave + * for more information : https://www.i2c-bus.org/clock-stretching/ */ +typedef enum{ + i2c_clk_stretching_disable, /*!< We assume that the master and slave have compatible + Clock frequencies **DEFAULT** */ + i2c_clk_stretching_enable /*!< In situations where an I2C slave is not able to co-operate + with the clock speed given by the master and needs to slow down. + This is done by a mechanism referred to as clock stretching. */ +}i2c_clk_stretching_t; + +/*! Enum for diffenrent wake up methodes wehnin sleep mode */ +typedef enum{ + i2c_wake_disabled, /*!< No wake up is possible this is the default mode also means that + the sleep function is not implmentes **DEFAULT** */ + i2c_wakeUp_address_match /*!< Wakes up on address match, this can be harware dependent */ +}i2c_wake_types_t; + +/*! typedef for the i2c states*/ +typedef enum +{ + i2c_hw_disabled, /*!< Hardware Is Disabled */ + i2c_hw_reset, /*!< Hardware Is Reseted and in reset mode and need to be initialised */ + i2c_hw_enabled, /*!< I2C Hardware is initilized but not neceserly ready */ + i2c_hw_ready, /*!< Hardware Initialized and ready for use */ + i2c_hw_sent_start, /*!< Generated the star condition */ + i2c_hw_out_buff_full, /*!< The output buffer of the I2C Periferal is Full */ + i2c_hw_out_buff_empty, /*!< The output buffer of the I2C Periferal is Empty */ + i2c_hw_in_buff_full, /*!< The input buffer of the I2C Periferal Is Full */ + i2c_hw_in_buff_empty, /*!< The input buffer of the I2C Periferal Is Empty */ + i2c_hw_send_read, /*!< Sent read request */ + i2c_hw_send_write, /*!< Sent write request */ + i2c_hw_got_ack, /*!< Recieved ACK */ + i2c_hw_got_nack, /*!< Recieved NACK */ + i2c_hw_sent_ack, /*!< Sent ACK */ + i2c_hw_sent_nack, /*!< Sent NACK */ + i2c_hw_sent_stop, /*!< Generated the star condition */ + i2c_hw_error /*!< Error */ +} i2c_hw_state_t; + +typedef enum +{ + i2c_perif_disabled, /*!< Peripheral Is Disabled */ + i2c_perif_reset, /*!< Peripheral Is Reseted and in reset mode and need to be initialised */ + i2c_perif_enabled, /*!< I2C CHannle is initilized but not neceserly ready */ + i2c_perif_ready, /*!< Peripheral Initialized and ready for use */ + i2c_perif_address_sent, /*!< The Salve Address Was Sent to the bus */ + i2c_perif_tx_ongoing, /*!< A transfer to the bus is ongoing */ + i2c_perif_tx_done, /*!< The transfer to the bus is finished */ + i2c_perif_rx_ongoing, /*!< Recieving from the bus */ + i2c_perif_rx_done, /*!< Recived everything from the bus */ + i2c_perif_listening, /*!< Address Listen Mode is ongoing */ + i2c_perif_listening_and_tx, /*!< Address Listen Mode and ongoing Data Transmission */ + i2c_perif_listening_and_rx, /*!< Address Listen Mode and ongoing Data Reception */ + i2c_perif_timeout, /*!< Timeout state */ + i2c_perif_Error /*!< Error */ +} i2c_perif_state_t; +/*! Struture a an i2c channel with all the required propereties*/ +typedef struct i2c_t +{ + i2cCh_t channelNo; /*!< The harware channel to be used */ + i2c_mode_t mode; /*!< Master, Slave or Multymaster Modes */ + uint16_t mainAddress; /*!< First and Main address of the device */ + uint16_t secondAddress; /*!< Second address if dual addresse mode is configured */ + i2c_address_count_t addressCount; /*!< Single or multiple */ + i2c_address_size_t addressSize; /*!< 10 or 7 bit address size */ + i2c_clk_speed_t speed; /*!< Bus Speed */ + i2c_clk_stretching_t stretching; /*!< Clock Stretching enable onyl in slave mode */ + i2c_wake_types_t wakeOn; /*!< Define on which type of action the i2c channel should + wake up. Only if de prefiral goes to sleep */ + i2c_hw_state_t hardwareState; /*!< The current sitate of the I2C Bus */ + i2c_perif_state_t periferalState; /*!< The current sitate of the I2C Bus */ +}i2c_t; + +/*************************************************************************************************** + I2C Configuration functions +***************************************************************************************************/ + +/** + * @brief Initilize the I2C Hardware + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_init( i2c_t *i2c_dev, /*!< Pointer to I2C hardware Object */ + i2cCh_t channelNo, /*!< The harware channel to be used */ + i2c_mode_t mode, /*!< Master, Slave or Multymaster Modes */ + uint16_t mainAddress, /*!< First and Main address of the device */ + uint16_t secondAddress, /*!< Second address if dual addresse mode is configured */ + i2c_address_count_t addressCount, /*!< Single or multiple */ + i2c_address_size_t addressSize, /*!< 10 or 7 bit address size */ + i2c_clk_speed_t speed, /*!< Bus Speed */ + i2c_clk_stretching_t stretching, /*!< Clock Stretching enable onyl in slave mode */ + i2c_wake_types_t wakeOn /*!< Wake up condition */ + ); + +/** + * @brief De-Initilise the I2C Hardware + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_deinitialise(i2c_t *i2c_dev); + +/** + * @brief Set the i2c channle to the gievn mode + * @param Channel is the i2c hardware channel + * @param mode The mode for i2c : Master Slave or Multymaster + */ +void i2c_set_mode(i2c_t *i2c_dev, i2c_mode_t mode); + +/** + * @brief Set the i2c channel's address + * @param i2c_dev is the i2c hardware channel + * @param address is the desired address for the device + * @param addressTwo The second address for the device only if dual address mode is not defined + */ +void i2c_set_address(i2c_t *i2c_dev, uint16_t address); + +/** + * @brief Set the i2c channel's second address if the hardware allows it + * @param i2c_dev is the i2c hardware channel + * @param address is the desired address for the device + */ +void i2c_set_address_second(i2c_t *i2c_dev, uint16_t address); + +/** + * @brief Set the i2c Address Lenght, 7 bit or 8 bit, Master or slave doesn't make any difference + * @param i2c_dev is the i2c hardware channel + * @param size Is the Adress isze to be used 7 Bit or 10 Bit + */ +void i2c_set_address_lenght(i2c_t *i2c_dev, i2c_address_size_t size); + +/** + * @brief Stets the Communication speed + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param speed the different awailable speeds + */ +void i2c_set_clk_speed(i2c_t *i2c_dev, i2c_clk_speed_t speed); + +/** + * @brief Ebales or disables clock stretching functionalities + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param The value to be written in the register. This will heavily depend on the hardware + */ +void i2c_set_clk_stretch(i2c_t *i2c_dev, i2c_clk_stretching_t stretching); + +/** + * @brief Set the wakeup mode + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param wake the desider wakeup mode for now i have found only one mode. + */ +void i2c_set_wakeup(i2c_t *i2c_dev, i2c_wake_types_t wake); + +/** + * @brief Configures Hardware implmente filters if there are any. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_set_filter(i2c_t *i2c_dev, uint8_t enable); + +/** + * @brief Set the timeout to close the i2c wait time if a communication fails. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param timeout the desider timeout duration in ticks. + */ +void i2c_set_timeout(i2c_t *i2c_dev, uint8_t timeout); + +/** + * @brief Resets the i2c Harware and register to it's factory deflauts. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_hardware_reset(i2c_t *i2c_dev); + +/** + * @brief Enables I2C Hardware BUS & Clock & Pins + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_hardware_enable(i2c_t *i2c_dev); + +/** + * @brief Disables I2C Hardware. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_hardware_disable(i2c_t *i2c_dev); + +/** + * @brief Resets the i2c Periferal to it's inital state. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_periferal_reset(i2c_t *i2c_dev); + +/** + * @brief Enables I2C Periferal core. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_periferal_enable(i2c_t *i2c_dev); + +/** + * @brief Disables I2C Periferal core. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_periferal_disable(i2c_t *i2c_dev); + +/************************************************************************************************** + I2C Communication functions independen of opperating mode +***************************************************************************************************/ + +/** + * @brief Writes the given amount of data to the selected device. This function will + * automaticaly choose between i2cMasterSend(); or i2cSlaveSend(); + * Depending if the I2C channel was initiated as slave or master. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data to be written + * @param dataLenght is the total quantity of 8 bit data to be written. + */ +void i2c_write(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght); + +/** + * @brief Reads the given amount of data to the selected device. This function will + * automaticaly choose between i2cMasterRecieve(); or i2cSlaveRecieve(); + * Depending if the I2C channel was initiated as slave or master. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data which has been red + * @paran dataLenght is the total quantity of 8 bit data to be red + */ +void i2c_read(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght); + +/** + * @brief Recieve a Single Byte as master from from the given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2c_master_recieve(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); +/** + * @brief Sends a Single Byte as master to the given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the send command will be sent + * @param registerAddress is the regiter to be written to the device + * @param data is the data to be sent + */ +void i2c_master_send(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/** + * @brief Recieve a Single Byte as slave from given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2c_slave_recieve(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/** + * @brief Recieve a Single Byte as slave from the given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2c_slave_send(i2c_t *i2c_dev, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/************************************************************************************************** + I2C Hardware functions +***************************************************************************************************/ +/** + * @brief Checks if the device is ready for any type of communication + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +uint8_t i2c_is_perif_ready(i2c_t *i2c_dev); + +/** + * @brief Generates a Start condition. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_send_start(i2c_t *i2c_dev); + +/** + * @brief Generates a Start condition. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_send_stop(i2c_t *i2c_dev); + +/** + * @brief Generates a NACK condition. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_send_nack(i2c_t *i2c_dev); + +/** + * @brief Checks If a NACK is recieved. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +uint8_t i2c_check_nack(i2c_t *i2c_dev); + +/** + * @brief Generates a ACK condition. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_send_ack(i2c_t *i2c_dev); + +/** + * @brief Initiates the communication by sending the slave address on the bus followed by a WRITE + * and waits for an ACK (aknowledge) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress The address of the slave to be communicated + */ +void i2c_send_address_for_write(i2c_t *i2c_dev, uint16_t *slaveAddress); + +/** + * @brief Initiates the communication by sending the slave address on the bus followed by a READ + * and waits for an ACK (aknowledge) + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress The address of the slave to be communicated + */ +void i2c_send_address_for_read(i2c_t *i2c_dev, uint16_t *slaveAddress); + +/** + * @brief Sende the register adrres with which we want to communicate. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param registerAddress The register address of the slave device that we are communication with + */ +void i2c_send_reg_address(i2c_t *i2c_dev, uint8_t *registerAddress); + +/** + * @brief Send the register that we want to read or write. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param registerAddress the register that need to be accessed + */ +void i2c_send_data(i2c_t *i2c_dev, uint8_t *data); + +/** + * @brief Initiates a Write command with the previously set slave address. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_init_write_command(i2c_t *i2c_dev); + +/** + * @brief Initiates a read command with the previously set slave address. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_init_read_command(i2c_t *i2c_dev); + +/** + * @brief Is the output buffer full. This also means that there is data present in the ouput buffer + * is sent to the i2c BUS. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +uint8_t i2c_is_output_buffer_full(i2c_t *i2c_dev); + +/** + * @brief Is the input buffer full. This also means that there is data present in the input buffer + * is sent to the i2c BUS. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @return 1 when input buffer is full | 0 whenthe input buffer is empty + */ +uint8_t i2c_is_input_buffer_full(i2c_t *i2c_dev); + +/** + * @brief reads the I2C input buffer + * is sent to the i2c BUS. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param data pointer to the data that need to be read and returned + */ +void i2c_get_input_register(i2c_t *i2c_dev, uint8_t *data); + +/** + * @brief writes to the I2C output buffer + * is sent to the i2c BUS. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param data pointer to the data that need to be read and returned + */ +void i2c_set_output_register(i2c_t *i2c_dev, uint8_t *data); + +/** + * @brief Checks if transfer is complete + * is sent to the i2c BUS. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param data pointer to the data that need to be read and returned + * @return 1 when Transefer is complete | 0 When Transfer is ongoing + */ +uint8_t i2c_is_tx_complete(i2c_t *i2c_dev); + +/** + * @brief Defines the amount of transfers to be made. Address exchange and start conditon does not count + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param count amount o data to be transfered. + */ +void i2c_set_tx_counter(i2c_t *i2c_dev, uint8_t count); + +/************************************************************************************************** + I2C Arbitration Functions for Multymaster mode and slaves clock stretching +***************************************************************************************************/ +void i2c_arbitrate_clk_sync(); // I2C Standart : Clock Syncronization +void i2c_arbitrate_multymaster_abort_tx(); // I2c Standart : Stop Communication for multimaster mode +void i2c_arbitrate(); // I2C Standart : Arbitration for multimaster mode to define the right master. +void i2c_arbitrate_soft_rst(); // I2C Standart : Software reset not supported by all hardware. +void i2c_arbitration_clear_bus(); // I2C Standart : in case if SCL is stuck + +/************************************************************************************************** + I2C Extra functions that are not esential for the main functionality +***************************************************************************************************/ + +/** + * @brief This function will scan every for possible addresses to discover devices on the bus. + * And write them to the Devices list given to him. This function will not discover more + * devices than what he is told. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param devices list where the discevered devices will be written + * @param deviceCount Max number of devices to be discovered. + */ +void i2c_discover_devices(i2c_t *i2c_dev, uint16_t *devices, uint8_t deviceCount); + +/** + * @brief This function will try to communicate with a device with every speed + * allowed by his hardware to find out the maximum communication sppeed possible. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + */ +i2c_clk_speed_t i2c_test_bus_speed(i2c_t *i2c_dev, uint16_t *slaveAddress); + +/** + * @brief This function will read the device info register (if awailable) as follows : + * I2c Standart : 3 Bytes (24 bits) | 12 Bits : Manufacturer info | 9 Bits: Part Identification | 3 Bits DIE Rev. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to be red + */ +uint32_t i2c_get_device_info(i2c_t *i2c_dev, uint16_t *slaveAddress); + +/** + * @brief The selected i2c channel is put on sleep. + * @param i2c_dev is the beforehand declared i2c channel with his opperation modes + */ +void i2c_sleep(i2c_t *i2c_dev); + +/** + * @brief Error handling. + * @param error The error no generated. + */ +void i2c_throw_error(i2c_t *i2c_dev, int16_t error); + +#ifdef __cplusplus +} +#endif + +#endif // _I2C_H_ diff --git a/peripherals/i2c.bak.c b/peripherals/i2c/i2c.bak.c similarity index 100% rename from peripherals/i2c.bak.c rename to peripherals/i2c/i2c.bak.c diff --git a/peripherals/i2c.bak.h b/peripherals/i2c/i2c.bak.h similarity index 100% rename from peripherals/i2c.bak.h rename to peripherals/i2c/i2c.bak.h diff --git a/peripherals/i2c/i2c.c b/peripherals/i2c/i2c.c new file mode 100644 index 0000000..e3dfc98 --- /dev/null +++ b/peripherals/i2c/i2c.c @@ -0,0 +1,130 @@ +#include "i2c.h" +#include "usart.h" + +void i2cInit( i2c_t *i2cHardware, + i2cCh_t channelNo, + i2cMode_t mode, + uint16_t mainAddress, + uint16_t secondAddress, + i2cAddressCount_t addressCount, + i2cAddressSize_t addressSize, + i2cSpeed_t speed, + i2cOpperationMode_t opperationMode, + i2cClockStretching_t stretching, + i2cWakeUpTypes_t wakeOn) +{ + i2cHardware->channelNo = channelNo; + i2cHardware->mode = mode; + i2cHardware->mainAddress = mainAddress; + i2cHardware->secondAddress = secondAddress; + i2cHardware->addressCount = addressCount; + i2cHardware->addressSize = addressSize; + i2cHardware->speed = speed; + i2cHardware->opperationMode = opperationMode; + i2cHardware->stretching = stretching; + i2cHardware->wakeOn = wakeOn; + i2cHardware->hardwareState = i2cHwIdle; + i2cHardware->periferalState = i2cPerifNotInitialized; + + i2cEnableHardware(i2cHardware); + i2cDisablePeriferal(i2cHardware); + i2cConfigureFilters(i2cHardware); + i2cSetClockStretch(i2cHardware, stretching); + i2cSetSpeed(i2cHardware, speed); + i2cSetMode(i2cHardware, opperationMode); + i2cSetAddressLenght(i2cHardware, addressSize); + i2cSetAddress(i2cHardware, mainAddress, secondAddress); + i2cEnablePeriferal(i2cHardware); + + while(i2cHardware->periferalState != i2cPerifReady) + { + i2cIsPeriferalReady(i2cHardware); + } + + i2cHardware->periferalState = i2cPerifInitialized; +} + + +void i2cDeInit(i2c_t *i2cHardware) +{ + +} + + +void i2cRead(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght) +{ + +// +// Start +// Send Address +// Wait For ACK +// + uint8_t nbytes = 0; + + i2cHardware->periferalState = i2cPerifTransmitting; + + i2cSetTransferCounter(i2cHardware,1); + i2cSendSlaveAddressWrite(i2cHardware, slaveAddress); + i2cSendRegisterAddress(i2cHardware,registerAddress); + + while(i2cHardware->periferalState != i2cPerifTransferComplete) + { + i2cIsTransferComplete(i2cHardware); + } + + i2cHardware->periferalState = i2cPerifRecieving; + i2cSendSlaveAddressRead(i2cHardware, slaveAddress); + + + while(i2cHardware->periferalState != i2cPerifTransferComplete) + { + i2cIsTransferComplete(i2cHardware); + } + + i2cGenerateNack(i2cHardware); + i2cGenerateStop(i2cHardware); + + i2cReadInputRegister(i2cHardware, data); + + print_Usart(usart2, "\n\rI2C Read completed\n\r"); + + while(i2cHardware->periferalState != i2cPerifReady) + { + i2cIsPeriferalReady(i2cHardware); + } + i2cHardware->periferalState = i2cPerifReady; + i2cHardware->hardwareState = i2cHwIdle; +} + +void i2cWrite(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght) +{ + i2cSetTransferCounter(i2cHardware,2); + i2cSendSlaveAddressWrite(i2cHardware, slaveAddress); + i2cSendRegisterAddress(i2cHardware,registerAddress); + while((i2cHardware->hardwareState =! i2cHwOutputBufferEmpty)) + { + i2cIsOutputBufferEmpty(i2cHardware); + } + i2cSendData(i2cHardware,data); + + i2cGenerateStop(i2cHardware); + print_Usart(usart2, "\n\rI2C Transfer completed\n\r"); +} + +void i2cThrowError(i2c_t *i2cHardware, int16_t error) +{ + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "I2C Error Detected : "); + + if (i2cHardware->periferalState == i2cPerifTransmitting) + print_Usart(usart2, "i2cPerifTransmitting"); + if (i2cHardware->periferalState == i2cPerifRecieving) + print_Usart(usart2, "i2cPerifRecieving"); + + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "I2C Error No: "); + usartSendChar(usart2, error + 0x30); + print_Usart(usart2, "\n\r"); + print_Usart(usart2, "\n\r"); +} diff --git a/peripherals/i2c/i2c.h b/peripherals/i2c/i2c.h new file mode 100755 index 0000000..c2cda5d --- /dev/null +++ b/peripherals/i2c/i2c.h @@ -0,0 +1,565 @@ +/** + ************************************************************************************************** + * @file i2c.h + * @author Kerem Yollu & Edwin Koch + * @date 18.07.2022 + * @version 1.01 + ************************************************************************************************** + * @brief I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : + * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA + * This will also not have a I3C support for the forseable futrue. + * + * **Detailed Description :** + * + * I2C communitation based on the Standart I2C Protocol V7 Defined by NXP/Philips : + * following third Party Protocols based on I2C Bus are not going to be implemented : C-BUS SMBUS PMBUS IPMI DDC ATCA + * This will also not have a I3C support for the forseable futrue. + * + * @todo + * - 26.07.2021 : Implement the DMA + * - 26.07.2021 : Implement the Interrupt + * - 26.07.2021 : Implement the Sleep/WakeUp + * - 26.07.2021 : Implement the Slave opperation + ************************************************************************************************** +*/ + +#ifndef _I2C_H_ +#define _I2C_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "hardwareDescription.h" +#include "pin.h" + + + +/*! Enum of possible I2C opperation modes */ +typedef enum{ + i2cModeMaster, /*!< Master mode : In Master mode, the I2C interface initiates + a data transfer and generates the clock signal. **DEFAULT** */ + i2cModeMultyMaster, /*!< Multimaster Mode : In case if more than one master are present + in one I2C bus. In such case each device needs to be able to + cooperate knowing that another device could talking + therefore the bus is busy (Arbirtation). + For More information : https://www.i2c-bus.org/multimaster/ */ + i2cModeSlave /*!< Slave mode : A slave device has to always be ready to detect and + process a start condition and to recognize its address */ +}i2cMode_t; + +/*! Enum of possible I2C speeds */ +typedef enum{ + i2cSpeedStandart, /*!< SM 100 kbits/s Standart i2c Speed **DEFAULT** */ + i2cSpeedFast, /*!< FM 400 kbits/s */ + i2cSpeedFastPlus, /*!< FM+ 1 Mbits/s */ + i2cSpeedHightSpeed, /*!< HS 3.4 Mbits/s */ + i2cSpeedUltraFast /*!< UFM 5 Mbits/s */ +}i2cSpeed_t; + +/*! Enum of possible I2C Adress sizes */ +typedef enum{ + i2cAddressSizeSevenBits, /*!< 7 Bits address size **DEFAULT** */ + i2cAddressSizeTenBits /*!< 10 Bits address size */ +}i2cAddressSize_t; + +/*! Enum of possible I2C Address count */ +typedef enum{ + i2cAddressCountSingle, /*!< Only one address for communication **DEFAULT** */ + i2cAddressCountDual /*!< Dual addresses for one device respondng to two addresses */ +}i2cAddressCount_t; + +/*! Enum for clock strechning activation. Can only be implmented as Slave + * for more information : https://www.i2c-bus.org/clock-stretching/ */ +typedef enum{ + i2cClockStretchingDisable, /*!< We assume that the master and slave have compatible + Clock frequencies **DEFAULT** */ + i2cClockStretchingEnable /*!< In situations where an I2C slave is not able to co-operate + with the clock speed given by the master and needs to slow down. + This is done by a mechanism referred to as clock stretching. */ +}i2cClockStretching_t; + +/*! Enum for diffenrent wake up methodes wehnin sleep mode */ +typedef enum{ + i2cWakeUpDisabled, /*!< No wake up is possible this is the default mode also means that + the sleep function is not implmentes **DEFAULT** */ + i2cWakeUpOnAddressMatch /*!< Wakes up on address match, this can be harware dependent */ +}i2cWakeUpTypes_t; + +/*! Enum operation mode of the i2c channel */ +typedef enum{ + i2cOpperationPolling, /*!< Polling mode Blocking, i2c communication states are constantly + checked on polling mode so it can be stoped + when interrupts occures **DEFAULT** */ + i2cOpperationInt, /*!< Interrut Mode Non-blocking, i2c communications state changes + generates an interrupt and can be handeled this way */ + i2cOpperationDma /*!< DMA Mode Non-blocking, I2C communication satets are managed + via Inteerupts and with Direct Memory Access */ +}i2cOpperationMode_t; + +/*! typedef for the i2c states*/ +typedef enum +{ + i2cHwIdle, /*!< Hardware is in Idle Mode **DEFAULT** */ + i2cHwStartGenerated, /*!< Generated the star condition */ + i2cHwOutputBufferFull, /*!< The output buffer of the I2C Periferal is Full */ + i2cHwOutputBufferEmpty, /*!< The output buffer of the I2C Periferal is Empty */ + i2cHwInputBufferFull, /*!< The input buffer of the I2C Periferal Is Full */ + i2cHwInputBufferEmpty, /*!< The input buffer of the I2C Periferal Is Empty */ + i2cHwSentRead, /*!< Sent read request */ + i2cHwSentWrite, /*!< Sent write request */ + i2cHwGotAck, /*!< Recieved ACK */ + i2cHwGotNack, /*!< Recieved NACK */ + i2cHwSentAck, /*!< Sent ACK */ + i2cHwSentNack, /*!< Sent NACK */ + i2cHwStopGenerated, /*!< Generated the star condition */ + i2cHwError /*!< Error */ +} i2cHardwareState_t; + +typedef enum +{ + i2cPerifNotInitialized, /*!< Default Peripheral is not yet Initialized **DEFAULT** */ + i2cPerifInitialized, /*!< I2C CHannle is initilized but not neceserly ready */ + i2cPerifSlaveAddressSent, /*!< The Salve Address Was Sent to the bus */ + i2cPerifTransferComplete, /*!< A full communication process is complete (wire or Read) */ + i2cPerifTransferOngoign, /*!< A full communication process is in progress (wire or Read) */ + i2cPerifReady, /*!< Peripheral Initialized and ready for use */ + i2cPerifSlaveNotFound, /*!< Desired Slave was not able to be found */ + i2cPerifTransmitting, /*!< Data Transmission process is ongoing */ + i2cPerifRecieving, /*!< Data Reception process is ongoing */ + i2cPerifListening, /*!< Address Listen Mode is ongoing */ + i2cPerifListeningAndTransmitting, /*!< Address Listen Mode and ongoing Data Transmission */ + i2cPerifListeningAndRecieveing, /*!< Address Listen Mode and ongoing Data Reception */ + i2cPerifAbort, /*!< Abort user request ongoing */ + i2cPerifTimeout, /*!< Timeout state */ + i2cPerifError /*!< Error */ +} i2cPeriferalState_t; +/*! Struture a an i2c channel with all the required propereties*/ +typedef struct i2c_t +{ + i2cCh_t channelNo; /*!< The harware channel to be used */ + i2cMode_t mode; /*!< Master, Slave or Multymaster Modes */ + uint16_t mainAddress; /*!< First and Main address of the device */ + uint16_t secondAddress; /*!< Second address if dual addresse mode is configured */ + i2cAddressCount_t addressCount; /*!< Single or multiple */ + i2cAddressSize_t addressSize; /*!< 10 or 7 bit address size */ + i2cSpeed_t speed; /*!< Bus Speed */ + i2cOpperationMode_t opperationMode; /*!< Blocking or non blocking polling, Int or DMA */ + i2cClockStretching_t stretching; /*!< Clock Stretching enable onyl in slave mode */ + i2cWakeUpTypes_t wakeOn; /*!< Define on which type of action the i2c channel should + wake up. Only if de prefiral goes to sleep */ + i2cHardwareState_t hardwareState; /*!< The current sitate of the I2C Bus */ + i2cPeriferalState_t periferalState; /*!< The current sitate of the I2C Bus */ +}i2c_t; + +/*************************************************************************************************** + I2C Configuration functions +***************************************************************************************************/ + +/** + * @brief Initilize the I2C Hardware + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cInit( i2c_t *i2cHardware, /*!< Pointer to I2C hardware Object */ + i2cCh_t channelNo, /*!< The harware channel to be used */ + i2cMode_t mode, /*!< Master, Slave or Multymaster Modes */ + uint16_t mainAddress, /*!< First and Main address of the device */ + uint16_t secondAddress, /*!< Second address if dual addresse mode is configured */ + i2cAddressCount_t addressCount, /*!< Single or multiple */ + i2cAddressSize_t addressSize, /*!< 10 or 7 bit address size */ + i2cSpeed_t speed, /*!< Bus Speed */ + i2cOpperationMode_t opperationMode, /*!< Blocking or non blocking polling, Int or DMA */ + i2cClockStretching_t stretching, /*!< Clock Stretching enable onyl in slave mode */ + i2cWakeUpTypes_t wakeOn /*!< Wake up condition */ + ); + +/** + * @brief De-Initilize the I2C Hardware + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cDeInit(i2c_t *i2cHardware); + +/** + * @brief Set the i2c channle to the gievn mode + * @param Channel is the i2c hardware channel + * @param mode The mode for i2c : Master Slave or Multymaster + */ +void i2cSetMode(i2c_t *i2cHardware, i2cMode_t mode); + +/** + * @brief Set the i2c channles mode as Master Slave or Multymaster + * @param i2cHardware is the i2c hardware channel + * @param addressOne The forst address for the device + * @param addressTwo The second address for the device only if dual address mode is not defined + */ +void i2cSetAddress(i2c_t *i2cHardware, uint16_t mainAddress, uint16_t secondAddress); + +/** + * @brief Set the i2c Address Lenght, 7 bit or 8 bit, Master or slave doesn't make any difference + * @param i2cHardware is the i2c hardware channel + * @param size Is the Adress isze to be used 7 Bit or 10 Bit + */ +void i2cSetAddressLenght(i2c_t *i2cHardware, i2cAddressSize_t size); + +/** + * @brief Stets the Communication speed + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param speed the different awailable speeds + */ +void i2cSetSpeed(i2c_t *i2cHardware, i2cSpeed_t speed); + +/** + * @brief Initiates the opperation mode for the selected i2c Channel + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param opperation define if the i2c channel will opperate on pollin, Interrupt, or DMA modes + */ +void i2cSetOpperation(i2c_t *i2cHardware, i2cOpperationMode_t opperation); + + +/** + * @brief Ebales or disables clock stretching functionalities + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param The value to be written in the register. This will heavily depend on the hardware + */ +void i2cSetClockStretch(i2c_t *i2cHardware, i2cClockStretching_t stretching); + +/** + * @brief Set the wakeup mode + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param wake the desider wakeup mode for now i have found only one mode. + */ +void i2cSetWakeup(i2c_t *i2cHardware, i2cWakeUpTypes_t wake); + +/** + * @brief Configures Hardware implmente filters if there are any. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cConfigureFilters(i2c_t *i2cHardware); + +/** + * @brief Set the timeout to close the i2c wait time if a communication fails. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param timeout the desider timeout duration in ticks. + */ +void i2cSetTimeout(i2c_t *i2cHardware, uint8_t timeout); + +/** + * @brief Resets the i2c Periferal to it's inital state. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cPeriferalReset(i2c_t *i2cHardware); + +/** + * @brief Resets the i2c Harware and register to it's factory deflauts. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cHardwareReset(i2c_t *i2cHardware); + +/** + * @brief Enables I2C Hardware BUS & Clock & Pins + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cEnableHardware(i2c_t *i2cHardware); + +/** + * @brief Enables I2C Periferal core. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cEnablePeriferal(i2c_t *i2cHardware); + +/** + * @brief Disables I2C Periferal core. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cDisablePeriferal(i2c_t *i2cHardware); + +/************************************************************************************************** + I2C Communication functions independen of opperating mode +***************************************************************************************************/ + +/** + * @brief Writes the given amount of data to the selected device. This function will + * automaticaly choose between i2cMasterSend(); or i2cSlaveSend(); + * Depending if the I2C channel was initiated as slave or master. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data to be written + * @param dataLenght is the total quantity of 8 bit data to be written. + */ +void i2cWrite(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght); + +/** + * @brief Reads the given amount of data to the selected device. This function will + * automaticaly choose between i2cMasterRecieve(); or i2cSlaveRecieve(); + * Depending if the I2C channel was initiated as slave or master. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data which has been red + * @paran dataLenght is the total quantity of 8 bit data to be red + */ +void i2cRead(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data, uint8_t *dataLenght); + +/** + * @brief Recieve a Single Byte as master from from the given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2cMasterRecieve(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); +/** + * @brief Sends a Single Byte as master to the given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the send command will be sent + * @param registerAddress is the regiter to be written to the device + * @param data is the data to be sent + */ +void i2cMasterSend(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/** + * @brief Recieve a Single Byte as slave from given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2cSlaveRecieve(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/** + * @brief Recieve a Single Byte as slave from the given devices register. + * this function will adapt himself to the selected oppeartion mode (Polling / Int / DMA) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2cSlaveSend(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/************************************************************************************************** + I2C Hardware functions +***************************************************************************************************/ +/** + * @brief Checks if the device is ready for any type of communication + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cIsPeriferalReady(i2c_t *i2cHardware); + +/** + * @brief Generates a Start condition. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cGenerateStart(i2c_t *i2cHardware); + +/** + * @brief Generates a Start condition. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cGenerateStop(i2c_t *i2cHardware); + +/** + * @brief Generates a NACK condition. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cGenerateNack(i2c_t *i2cHardware); + +/** + * @brief Checks If a NACK is recieved. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +uint8_t i2cCheckNack(i2c_t *i2cHardware); + +/** + * @brief Generates a ACK condition. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cGenerateAck(i2c_t *i2cHardware); + +/** + * @brief Initiates the communication by sending the slave address on the bus followed by a WRITE + * and waits for an ACK (aknowledge) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress The address of the slave to be communicated + */ +void i2cSendSlaveAddressWrite(i2c_t *i2cHardware, uint16_t *slaveAddress); + +/** + * @brief Initiates the communication by sending the slave address on the bus followed by a READ + * and waits for an ACK (aknowledge) + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress The address of the slave to be communicated + */ +void i2cSendSlaveAddressRead(i2c_t *i2cHardware, uint16_t *slaveAddress); + +/** + * @brief Sende the register adrres with which we want to communicate. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param registerAddress The register address of the slave device that we are communication with + */ +void i2cSendRegisterAddress(i2c_t *i2cHardware, uint8_t *registerAddress); + +/** + * @brief Send the register that we want to read or write. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param registerAddress the register that need to be accessed + */ +void i2cSendData(i2c_t *i2cHardware, uint8_t *data); + +/** + * @brief Initiates a Write command with the previously set slave address. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cInitiateWriteCommand(i2c_t *i2cHardware); + +/** + * @brief Initiates a read command with the previously set slave address. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cInitiateReadCommand(i2c_t *i2cHardware); + +/** + * @brief Is the output buffer empty. This allso meas that the data that was in the ouput buffer + * is sent to the i2c BUS. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cIsOutputBufferEmpty(i2c_t *i2cHardware); + +/** + * @brief Is the output buffer empty. This allso meas that the data that was in the ouput buffer + * is sent to the i2c BUS. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cIsInputBufferEmpty(i2c_t *i2cHardware); + +/** + * @brief reads the I2C input buffer + * is sent to the i2c BUS. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param data pointer to the data that need to be read and returned + */ +void i2cReadInputRegister(i2c_t *i2cHardware, uint8_t *data); + +/** + * @brief writes to the I2C output buffer + * is sent to the i2c BUS. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param data pointer to the data that need to be read and returned + */ +void i2cSetOutputRegister(i2c_t *i2cHardware, uint8_t *data); + +/** + * @brief Checks is transfer is complete + * is sent to the i2c BUS. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param data pointer to the data that need to be read and returned + */ +void i2cIsTransferComplete(i2c_t *i2cHardware); + +/** + * @brief Defines the amount of transfers to be made. Address exchange and start conditon does not count + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param count amount o data to be transfered. + */ +void i2cSetTransferCounter(i2c_t *i2cHardware, uint8_t count); +/************************************************************************************************** + I2C Communication functions Polling / Blocking Mode +***************************************************************************************************/ + +/** + * @brief Recieve a Single Byte in polling mode as master from from the given devices register. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2cMasterRecievePolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); +/** + * @brief Sends a Single Byte in polling mode as master to the given devices register. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the send command will be sent + * @param registerAddress is the regiter to be written to the device + * @param data is the data to be sent + */ +void i2cMasterSendPolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/** + * @brief Recieve a Single Byte in polling mide as slave from the given devices register. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2cSlaveRecievePolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/** + * @brief Recieve a Single Byte in polling mode as slave from the given devices register. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + * @param registerAddress is the regiter to be red from the device + * @param data is the data whic has been red + */ +void i2cSlaveSendPolling(i2c_t *i2cHardware, uint16_t *slaveAddress, uint8_t *registerAddress, uint8_t *data); + +/************************************************************************************************** + I2C Arbitration Functions for Multymaster mode and slaves clock stretching +***************************************************************************************************/ +void i2cClockSynchronise(); // I2C Standart : Clock Syncronization +void i2cAbortTransmit(); // I2c Standart : Stop Communication for multimaster mode +void i2cArbitration(); // I2C Standart : Arbitration for multimaster mode to define the right master. +void i2cSoftReset(); // I2C Standart : Software reset not supported by all hardware. +void i2cBusClear(); // I2C Standart : in case if SCL is stuck + + +/************************************************************************************************** + I2C Extra functions that are not esential for the main functionality +***************************************************************************************************/ + +/** + * @brief This function will scan every for possible addresses to discover devices on the bus. + * And write them to the Devices list given to him. This function will not discover more + * devices than what he is told. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param devices list where the discevered devices will be written + * @param deviceCount Max number of devices to be discovered. + */ +void i2cDiscoverDevices(i2c_t *i2cHardware, uint16_t *devices, uint8_t deviceCount); + +/** + * @brief This function will try to communicate with a device with every speed + * allowed by his hardware to find out the maximum communication sppeed possible. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to which the read command will be sent + */ +i2cSpeed_t i2cTestDeviceSpeed(i2c_t *i2cHardware, uint16_t *slaveAddress); + +/** + * @brief This function will read the device info register (if awailable) as follows : + * I2c Standart : 3 Bytes (24 bits) | 12 Bits : Manufacturer info | 9 Bits: Part Identification | 3 Bits DIE Rev. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + * @param slaveAddress is the address of the device to be red + */ +uint32_t i2cReadDeviceInfo(i2c_t *i2cHardware, uint16_t *slaveAddress); + +/** + * @brief The selected i2c channel is put on sleep. + * @param i2cHardware is the beforehand declared i2c channel with his opperation modes + */ +void i2cSleep(i2c_t *i2cHardware); + +/** + * @brief Error handling. + * @param error The error no generated. + */ +void i2cThrowError(i2c_t *i2cHardware, int16_t error); + +#ifdef __cplusplus +} +#endif + +#endif // _I2C_H_