2017-01-16 19:22:03 +01:00
|
|
|
/*
|
|
|
|
Master i2c (advanced)
|
2017-01-22 18:32:00 +01:00
|
|
|
Redirecting slave write & read functions in setup (to custom functions following typedef)
|
2017-01-16 19:22:03 +01:00
|
|
|
Read and Write operations are then called using the same functions
|
2017-01-22 18:32:00 +01:00
|
|
|
Function to get Chip ID are device dependant (and will probably only work on FUJITSU devices)
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
This example code is in the public domain.
|
|
|
|
|
|
|
|
created Jan 12 2017
|
2017-11-30 22:40:42 +01:00
|
|
|
latest mod Nov 30 2017
|
2017-01-16 19:22:03 +01:00
|
|
|
by SMFSW
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <ci2c.h>
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
const uint8_t blank = 0xEE; // blank tab filling value for test
|
|
|
|
|
|
|
|
I2C_SLAVE FRAM; // slave declaration
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
void setup() {
|
2017-01-22 18:32:00 +01:00
|
|
|
uint8_t str[3];
|
|
|
|
memset(&str, blank, sizeof(str));
|
|
|
|
|
2017-01-16 19:22:03 +01:00
|
|
|
Serial.begin(115200); // start serial for output
|
2017-02-02 00:03:07 +01:00
|
|
|
I2C_init(I2C_FM); // init with Fast Mode (400KHz)
|
2017-01-16 19:22:03 +01:00
|
|
|
I2C_slave_init(&FRAM, 0x50, I2C_16B_REG);
|
2017-11-21 23:15:55 +01:00
|
|
|
I2C_slave_set_rw_func(&FRAM, (ci2c_fct_ptr) I2C_wr_advanced, I2C_WRITE);
|
|
|
|
I2C_slave_set_rw_func(&FRAM, (ci2c_fct_ptr) I2C_rd_advanced, I2C_READ);
|
2017-01-22 18:32:00 +01:00
|
|
|
|
|
|
|
I2C_get_chip_id(&FRAM, &str[0]);
|
|
|
|
|
|
|
|
Serial.println();
|
|
|
|
//for (uint8_t i = 0; i < sizeof(str); i++) { Serial.print(str[i], HEX); } // print hex values
|
|
|
|
Serial.print("\nManufacturer ID: ");
|
|
|
|
Serial.print((str[0] << 4) + (str[1] >> 4), HEX);
|
|
|
|
Serial.print("\nProduct ID: ");
|
|
|
|
Serial.print(((str[1] & 0x0F) << 8) + str[2], HEX);
|
2017-01-16 19:22:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void loop() {
|
|
|
|
const uint16_t reg_addr = 0;
|
|
|
|
uint8_t str[7];
|
2017-01-22 18:32:00 +01:00
|
|
|
memset(&str, blank, sizeof(str));
|
|
|
|
|
|
|
|
I2C_read(&FRAM, reg_addr, &str[0], sizeof(str)); // FRAM, Addr 0, str, read chars for size of str
|
2017-01-16 19:22:03 +01:00
|
|
|
|
|
|
|
Serial.println();
|
|
|
|
for (uint8_t i = 0; i < sizeof(str); i++)
|
|
|
|
{
|
2017-01-22 18:32:00 +01:00
|
|
|
Serial.print(str[i], HEX); // print hex values
|
2017-01-16 19:22:03 +01:00
|
|
|
Serial.print(" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
delay(5000);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief This procedure calls appropriate functions to perform a proper send transaction on I2C bus.
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] reg_addr - register address in register map
|
|
|
|
* \param [in] data - pointer to the first byte of a block of data to write
|
|
|
|
* \param [in] bytes - indicates how many bytes of data to write
|
|
|
|
* \return Boolean indicating success/fail of write attempt
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-11-21 23:15:55 +01:00
|
|
|
bool I2C_wr_advanced(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes)
|
2017-01-16 19:22:03 +01:00
|
|
|
{
|
2017-11-30 01:32:44 +01:00
|
|
|
if (bytes == 0) { return false; }
|
2017-11-21 23:15:55 +01:00
|
|
|
|
2017-01-16 19:22:03 +01:00
|
|
|
if (I2C_start() == false) { return false; }
|
2017-01-22 18:32:00 +01:00
|
|
|
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; }
|
2017-11-30 22:40:42 +01:00
|
|
|
if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if writing next
|
2017-01-16 19:22:03 +01:00
|
|
|
{
|
2017-11-30 22:40:42 +01:00
|
|
|
slave->reg_addr = reg_addr;
|
|
|
|
|
2017-01-16 19:22:03 +01:00
|
|
|
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
|
|
|
|
{
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
}
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_wr8((uint8_t) reg_addr) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
}
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
2017-01-16 19:22:03 +01:00
|
|
|
{
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_wr8(*(data++)) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
slave->reg_addr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (I2C_stop() == false) { return false; }
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*! \brief This procedure calls appropriate functions to perform a proper receive transaction on I2C bus.
|
2017-01-22 18:32:00 +01:00
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in] reg_addr - register address in register map
|
|
|
|
* \param [in, out] data - pointer to the first byte of a block of data to read
|
|
|
|
* \param [in] bytes - indicates how many bytes of data to read
|
|
|
|
* \return Boolean indicating success/fail of read attempt
|
2017-01-16 19:22:03 +01:00
|
|
|
*/
|
2017-11-21 23:15:55 +01:00
|
|
|
bool I2C_rd_advanced(I2C_SLAVE * slave, const uint16_t reg_addr, uint8_t * data, const uint16_t bytes)
|
2017-01-16 19:22:03 +01:00
|
|
|
{
|
2017-11-30 01:32:44 +01:00
|
|
|
if (bytes == 0) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
|
2017-11-30 22:40:42 +01:00
|
|
|
if ((slave->cfg.reg_size) && (reg_addr != slave->reg_addr)) // Don't send address if reading next
|
2017-01-16 19:22:03 +01:00
|
|
|
{
|
2017-11-30 22:40:42 +01:00
|
|
|
slave->reg_addr = reg_addr;
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
if (I2C_start() == false) { return false; }
|
|
|
|
if (I2C_sndAddr(slave, I2C_WRITE) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
if (slave->cfg.reg_size >= I2C_16B_REG) // if size >2, 16bit address is used
|
|
|
|
{
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_wr8((uint8_t) (reg_addr >> 8)) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
}
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_wr8((uint8_t) reg_addr) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
}
|
2017-01-22 18:32:00 +01:00
|
|
|
if (I2C_start() == false) { return false; }
|
|
|
|
if (I2C_sndAddr(slave, I2C_READ) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
2017-01-16 19:22:03 +01:00
|
|
|
{
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_rd8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
2017-01-16 19:22:03 +01:00
|
|
|
*data++ = TWDR;
|
|
|
|
slave->reg_addr++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (I2C_stop() == false) { return false; }
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-22 18:32:00 +01:00
|
|
|
|
|
|
|
/*! \brief This procedure calls appropriate functions to get chip ID of FUJITSU devices.
|
|
|
|
* \param [in, out] slave - pointer to the I2C slave structure
|
|
|
|
* \param [in, out] data - pointer to the first byte of a block of data to read
|
|
|
|
* \return Boolean indicating success/fail of read attempt
|
|
|
|
*/
|
|
|
|
bool I2C_get_chip_id(I2C_SLAVE * slave, uint8_t * data)
|
|
|
|
{
|
|
|
|
const uint16_t bytes = 3;
|
|
|
|
I2C_SLAVE FRAM_ID;
|
|
|
|
|
|
|
|
I2C_slave_init(&FRAM_ID, 0xF8 >> 1, I2C_16B_REG); // Dummy slave init for I2C_sndAddr
|
|
|
|
|
|
|
|
if (I2C_start() == false) { return false; }
|
|
|
|
if (I2C_sndAddr(&FRAM_ID, I2C_WRITE) == false) { return false; }
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_wr8(slave->cfg.addr << 1) == false) { return false; }
|
2017-01-22 18:32:00 +01:00
|
|
|
if (I2C_start() == false) { return false; }
|
|
|
|
if (I2C_sndAddr(&FRAM_ID, I2C_READ) == false) { return false; }
|
|
|
|
|
|
|
|
for (uint16_t cnt = 0; cnt < bytes; cnt++)
|
|
|
|
{
|
2017-02-02 00:03:07 +01:00
|
|
|
if (I2C_rd8((cnt == (bytes - 1)) ? false : true) == false) { return false; }
|
2017-01-22 18:32:00 +01:00
|
|
|
*data++ = TWDR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (I2C_stop() == false) { return false; }
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|