i2c-master: cleaned up again on l1

now has repeated-start and stop/start support, with the same API as v2

Just to decide whether all of it goes up into the library or not.
This commit is contained in:
Karl Palsson 2017-03-23 22:29:52 +00:00
parent dcd8f459b1
commit 112e9e6814

View file

@ -105,10 +105,81 @@ static void i2c_set_speed(uint32_t p, enum i2c_speeds speed, uint32_t clock_mega
#endif
}
// read/write are almost identical!
//static void i2c__transfer_helper(uint32_p, uint8_t addr, uint8_t *buf)
static void i2c_write7_v1(uint32_t i2c, int addr, uint8_t *data, size_t n)
{
while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
}
i2c_send_start(i2c);
/* Wait for master mode selected */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
i2c_send_7bit_address(i2c, addr, I2C_WRITE);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
uint32_t reg32 = I2C_SR2(i2c);
(void) reg32; /* unused */
size_t i;
for (i = 0; i < n; i++) {
i2c_send_data(i2c, data[i]);
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));
}
}
static void i2c_read7_v1(uint32_t i2c, int addr, uint8_t *res, int n)
{
i2c_send_start(i2c);
i2c_enable_ack(i2c);
/* Wait for master mode selected */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
i2c_send_7bit_address(i2c, addr, I2C_READ);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Clearing ADDR condition sequence. */
uint32_t reg32 = I2C_SR2(i2c);
(void) reg32; /* unused */
int i = 0;
for (i = 0; i < n; ++i) {
if (i == n - 1) {
i2c_disable_ack(i2c);
}
while (!(I2C_SR1(i2c) & I2C_SR1_RxNE));
res[i] = i2c_get_data(i2c);
}
i2c_send_stop(i2c);
return;
}
/* v1 isn't handling stop/start vs repeated start very well yet */
/* probably good enough to merge, but... maybe not put the v1 in the library.*/
static
void i2c_transfer7(uint32_t i2c, uint8_t addr, uint8_t *w, size_t wn, uint8_t *r, size_t rn)
void i2c_transfer7_v1(uint32_t i2c, uint8_t addr, uint8_t *w, size_t wn, uint8_t *r, size_t rn) {
if (wn) {
i2c_write7_v1(i2c, addr, w, wn);
}
if (rn) {
i2c_read7_v1(i2c, addr, r, rn);
} else {
i2c_send_stop(i2c);
}
}
static
void i2c_transfer7_v2(uint32_t i2c, uint8_t addr, uint8_t *w, size_t wn, uint8_t *r, size_t rn)
{
int wait;
size_t i;
@ -160,72 +231,16 @@ void i2c_transfer7(uint32_t i2c, uint8_t addr, uint8_t *w, size_t wn, uint8_t *r
}
/**
* Write bytes to a 7bit address
* @param p i2c peripheral of interest
* @param addr 7bit i2c slave address (unshifted)
* @param buf data to send
* @param count how many bytes to send
* @param end true if you wish to send a stop bit. false if you intend to
* continue sending data with a repeated start
*/
static
void i2c_write_bytes7(uint32_t p, uint8_t addr, uint8_t *buf, size_t count, bool end)
void i2c_transfer7(uint32_t i2c, uint8_t addr, uint8_t *w, size_t wn, uint8_t *r, size_t rn)
{
bool wait;
size_t i;
/* start transfer */
i2c_send_start(p);
while (i2c_busy(p) == 1);
// while (i2c_is_start(p) == 1);
/* Setting transfer properties */
i2c_set_bytes_to_transfer(p, count);
i2c_set_7bit_address(p, addr);
i2c_set_write_transfer_dir(p);
if (end) {
i2c_enable_autoend(p);
} else {
i2c_disable_autoend(p);
}
for (i = 0; i < count; i++) {
wait = true;
while (wait) {
if (i2c_transmit_int_status(p)) {
wait = false;
}
while (i2c_nack(p));
}
i2c_send_data(p, buf[i]);
}
#if defined I2C_SR2
i2c_transfer7_v1(i2c, addr, w, wn, r, rn);
#else
i2c_transfer7_v2(i2c, addr, w, wn, r, rn);
#endif
}
static
void i2c_read_bytes7(uint32_t p, uint8_t addr, uint8_t *buf, size_t count, bool end)
{
bool wait;
size_t i;
//while (i2c_busy(p) == 1); // FIXME - repeated start vs not
//while (i2c_is_start(p) == 1);
/* Setting transfer properties */
i2c_set_bytes_to_transfer(p, 1);
i2c_set_7bit_address(p, addr);
i2c_set_read_transfer_dir(p);
if (end) {
i2c_enable_autoend(p);
} else {
i2c_disable_autoend(p);
}
/* start transfer */
i2c_send_start(p);
for (i = 0; i < count; i++) {
while (i2c_received_data(p) == 0);
buf[i] = i2c_get_data(p);
}
}
// --------------- end of upstream planned section
void i2cm_init(void)
@ -239,91 +254,6 @@ void i2cm_init(void)
i2c_peripheral_enable(hw_details.periph);
}
#if defined I2C_SR2
static void sht21_send_data(uint32_t i2c, size_t n, uint8_t *data)
{
while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
}
i2c_send_start(i2c);
/* Wait for master mode selected */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
i2c_send_7bit_address(i2c, SENSOR_ADDRESS, I2C_WRITE);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
uint32_t reg32 = I2C_SR2(i2c);
(void) reg32; /* unused */
size_t i;
for (i = 0; i < n; i++) {
i2c_send_data(i2c, data[i]);
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));
}
}
// FIXME - this is dumb, just need send_data with len==1!
static void sht21_send_cmd(uint32_t i2c, uint8_t cmd)
{
while ((I2C_SR2(i2c) & I2C_SR2_BUSY)) {
} // wait for not busy!
i2c_send_start(i2c);
/* Wait for master mode selected */
while (!((I2C_SR1(i2c) & I2C_SR1_SB) // waiting for start bit to hav ebeen sent
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY)))); // and waiting for no longer busy again
i2c_send_7bit_address(i2c, SENSOR_ADDRESS, I2C_WRITE);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
uint32_t reg32 = I2C_SR2(i2c);
(void) reg32; /* unused */
i2c_send_data(i2c, cmd);
while (!(I2C_SR1(i2c) & (I2C_SR1_BTF)));
}
static void sht21_readn(uint32_t i2c, int n, uint8_t *res)
{
//assert(n > 0);
i2c_send_start(i2c);
i2c_enable_ack(i2c);
/* Wait for master mode selected */
while (!((I2C_SR1(i2c) & I2C_SR1_SB)
& (I2C_SR2(i2c) & (I2C_SR2_MSL | I2C_SR2_BUSY))));
i2c_send_7bit_address(i2c, SENSOR_ADDRESS, I2C_READ);
/* Waiting for address is transferred. */
while (!(I2C_SR1(i2c) & I2C_SR1_ADDR));
/* Cleaning ADDR condition sequence. */
uint32_t reg32 = I2C_SR2(i2c);
(void) reg32; /* unused */
int i = 0;
for (i = 0; i < n; ++i) {
if (i == n - 1) {
i2c_disable_ack(i2c);
}
while (!(I2C_SR1(i2c) & I2C_SR1_RxNE));
res[i] = i2c_get_data(i2c);
}
i2c_send_stop(i2c);
return;
}
#endif
static float sht21_convert_temp(uint16_t raw)
{
@ -344,10 +274,6 @@ static float sht21_convert_humi(uint16_t raw)
static float sht21_read_temp_hold(uint32_t i2c)
{
uint8_t data[3];
#if 0
sht21_send_cmd(i2c, SHT21_CMD_TEMP_HOLD);
sht21_readn(i2c, 2, data);
#endif
uint8_t cmd = SHT21_CMD_TEMP_HOLD;
i2c_transfer7(i2c, SENSOR_ADDRESS, &cmd, 1, data, sizeof(data));
uint8_t crc = data[2];
@ -360,10 +286,6 @@ static float sht21_read_temp_hold(uint32_t i2c)
static float sht21_read_humi_hold(uint32_t i2c)
{
uint8_t data[3];
#if 0
sht21_send_cmd(i2c, SHT21_CMD_HUMIDITY_HOLD);
sht21_readn(i2c, 2, data);
#endif
uint8_t cmd = SHT21_CMD_HUMIDITY_HOLD;
i2c_transfer7(i2c, SENSOR_ADDRESS, &cmd, 1, data, sizeof(data));
@ -377,10 +299,6 @@ static float sht21_read_humi_hold(uint32_t i2c)
static void sht21_readid(void)
{
uint8_t raw = 0;
#if defined I2C_SR2
sht21_send_cmd(I2C1, SHT21_CMD_READ_REG);
sht21_readn(I2C1, 1, &raw);
#else
uint8_t cmd = SHT21_CMD_READ_REG;
printf("RP...");
i2c_transfer7(hw_details.periph, SENSOR_ADDRESS, &cmd, 1, &raw, 1);
@ -389,7 +307,6 @@ static void sht21_readid(void)
i2c_transfer7(hw_details.periph, SENSOR_ADDRESS, &cmd, 1, 0, 0);
i2c_transfer7(hw_details.periph, SENSOR_ADDRESS, 0, 0, &raw, 1);
#endif
printf("raw user reg = %#x\n", raw);
int resolution = ((raw & 0x80) >> 6) | (raw & 1);
printf("temp resolution is in %d bits\n", 14 - resolution);
@ -398,13 +315,9 @@ static void sht21_readid(void)
uint8_t req1[] = {0xfa, 0x0f};
uint8_t res[8];
// sht21_send_data(I2C1, 2, req1);
// sht21_readn(I2C1, sizeof(res), res);
i2c_transfer7(hw_details.periph, SENSOR_ADDRESS, req1, sizeof(req1), res, 8);
uint8_t req2[] = {0xfc, 0xc9};
uint8_t res2[8];
// sht21_send_data(I2C1, 2, req2);
// sht21_readn(I2C1, sizeof(res), res2);
i2c_transfer7(hw_details.periph, SENSOR_ADDRESS, req1, sizeof(req1), res2, 8);
printf("Serial = %02x%02x %02x%02x %02x%02x %02x%02x\n",
@ -414,7 +327,7 @@ static void sht21_readid(void)
void i2cm_task(void)
{
static int i = 1;
printf("Starting iteration %d\n", i++);
printf(">>>>Starting iteration %d\n", i++);
gpio_set(hw_details.trigger_port, hw_details.trigger_pin);
sht21_readid();
float temp = sht21_read_temp_hold(hw_details.periph);