int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop) { int i, status; // full reset i2c_reg_reset(obj); status = i2c_start(obj); if ((status == 0xff)) { i2c_stop(obj); i2c_wait_STOP(obj); return I2C_ERROR_BUS_BUSY; } /**/ status = REG(CR2.UINT32); status = REG(SR2.UINT32); /**/ status = i2c_do_write(obj, address); if (status & 0x10) { i2c_stop(obj); i2c_wait_STOP(obj); return I2C_ERROR_NO_SLAVE; } /**/ status = REG(CR2.UINT32); status = REG(SR2.UINT32); /**/ for (i=0; i<length; i++) { /**/ status = REG(CR2.UINT32); status = REG(SR2.UINT32); /**/ status = i2c_do_write(obj, data[i]); if(status & 0x10) { i2c_stop(obj); i2c_wait_STOP(obj); return i; } } i2c_wait_TEND(obj); // If not repeated start, send stop. if (stop) { i2c_stop(obj); i2c_wait_STOP(obj); } return length; }
void i2c_init(i2c_t *obj, PinName sda, PinName scl) { // determine the SPI to use I2CName i2c_sda = (I2CName)pinmap_peripheral(sda, PinMap_I2C_SDA); I2CName i2c_scl = (I2CName)pinmap_peripheral(scl, PinMap_I2C_SCL); obj->i2c = pinmap_merge(i2c_sda, i2c_scl); MBED_ASSERT((int)obj->i2c != NC); // enable power i2c_power_enable(obj); // set default frequency at 100k i2c_frequency(obj, 100000); // full reset i2c_reg_reset(obj); pinmap_pinout(sda, PinMap_I2C_SDA); pinmap_pinout(scl, PinMap_I2C_SCL); }
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop) { int count = 0; int status; int value; volatile uint32_t work_reg = 0; // full reset i2c_reg_reset(obj); obj->dummy = 1; status = i2c_start(obj); if (status == 0xff) { i2c_stop(obj); i2c_wait_STOP(obj); return I2C_ERROR_BUS_BUSY; } status = i2c_do_write(obj, (address | 0x01)); if (status & 0x01) { i2c_stop(obj); i2c_wait_STOP(obj); return I2C_ERROR_NO_SLAVE; } /* wati RDRF */ i2c_wait_RDRF(obj); /* check ACK/NACK */ if ((REG(SR2.UINT32) & (1 << 4) == 1)) { /* Slave sends NACK */ i2c_stop(obj); // dummy read value = REG(DRR.UINT32); i2c_wait_STOP(obj); return I2C_ERROR_NO_SLAVE; } // Read in all except last byte if (length > 2) { for (count = 0; count < (length - 1); count++) { if (count == (length - 2)) { value = i2c_do_read(obj, 1); } else if ((length >= 3) && (count == (length - 3))) { value = i2c_do_read(obj, 2); } else { value = i2c_do_read(obj, 0); } status = i2c_status(obj); if (status & 0x10) { i2c_stop(obj); i2c_wait_STOP(obj); return count; } data[count] = (char) value; } } else if (length == 2) { /* Set MR3 WATI bit is 1 */; REG(MR3.UINT32) |= (1 << 6); // dummy read value = REG(DRR.UINT32); // wait for it to arrive i2c_wait_RDRF(obj); // send a NOT ACK REG(MR3.UINT32) |= (1 <<4); REG(MR3.UINT32) |= (1 <<3); REG(MR3.UINT32) &= ~(1 <<4); data[count] = (char)REG(DRR.UINT32); count++; } else if (length == 1) { /* Set MR3 WATI bit is 1 */; REG(MR3.UINT32) |= (1 << 6); // send a NOT ACK REG(MR3.UINT32) |= (1 <<4); REG(MR3.UINT32) |= (1 <<3); REG(MR3.UINT32) &= ~(1 <<4); // dummy read value = REG(DRR.UINT32); } else { // Do Nothing } // read in last byte i2c_wait_RDRF(obj); // If not repeated start, send stop. if (stop) { /* RIICnSR2.STOP = 0 */ REG(SR2.UINT32) &= ~(1 << 3); /* RIICnCR2.SP = 1 */ REG(CR2.UINT32) |= (1 << 3); /* RIICnDRR read */ value = REG(DRR.UINT32) & 0xFF; data[count] = (char) value; /* RIICnMR3.WAIT = 0 */ REG(MR3.UINT32) &= ~(1 << 6); i2c_wait_STOP(obj); } else { /* RIICnDRR read */ value = REG(DRR.UINT32) & 0xFF; data[count] = (char) value; } return length; }
void i2c_frequency(i2c_t *obj, int hz) { float64_t pclk_val; float64_t wait_utime; volatile float64_t bps; volatile float64_t L_time; /* H Width period */ volatile float64_t H_time; /* L Width period */ uint32_t tmp_L_width; uint32_t tmp_H_width; uint32_t remainder; uint32_t wk_cks = 0; /* set PCLK */ if (false == RZ_A1_IsClockMode0()) { pclk_val = (float64_t)CM1_RENESAS_RZ_A1_P0_CLK; } else { pclk_val = (float64_t)CM0_RENESAS_RZ_A1_P0_CLK; } /* Min 10kHz, Max 400kHz */ if (hz < 10000) { bps = 10000; } else if (hz > 400000) { bps = 400000; } else { bps = (float64_t)hz; } /* Calculation L width time */ L_time = (1 / (2 * bps)); /* Harf period of frequency */ H_time = L_time; /* Check I2C mode of Speed */ if (bps > 100000) { /* Fast-mode */ L_time -= 102E-9; /* Falling time of SCL clock. */ H_time -= 138E-9; /* Rising time of SCL clock. */ /* Check L wideth */ if (L_time < 1.3E-6) { /* Wnen L width less than 1.3us */ /* Subtract Rise up and down time for SCL from H/L width */ L_time = 1.3E-6; H_time = (1 / bps) - L_time - 138E-9 - 102E-9; } } tmp_L_width = (uint32_t)(L_time * pclk_val * 10); tmp_L_width >>= 1; wk_cks++; while (tmp_L_width >= 341) { tmp_L_width >>= 1; wk_cks++; } remainder = tmp_L_width % 10; tmp_L_width = ((tmp_L_width + 9) / 10) - 3; /* carry */ tmp_H_width = (uint32_t)(H_time * pclk_val * 10); tmp_H_width >>= wk_cks; if (remainder == 0) { tmp_H_width = ((tmp_H_width + 9) / 10) - 3; /* carry */ } else { remainder += tmp_H_width % 10; tmp_H_width = (tmp_H_width / 10) - 3; if (remainder > 10) { tmp_H_width += 1; /* fine adjustment */ } } /* timeout of BBSY bit is minimum low width by frequency */ /* so timeout calculates "(low width) * 2" by frequency */ wait_utime = (L_time * 2) * 1000000; /* 1 wait of BBSY bit is about 0.3us. if it's below 0.3us, wait count is set as 1. */ if (wait_utime <= 0.3) { obj->bbsy_wait_cnt = 1; } else { obj->bbsy_wait_cnt = (int)(wait_utime / 0.3); } /* I2C Rate */ obj->pclk_bit = (uint8_t)(0x10 * wk_cks); /* P_phi / xx */ obj->width_low = (uint8_t)(tmp_L_width | 0x000000E0); obj->width_hi = (uint8_t)(tmp_H_width | 0x000000E0); /* full reset */ i2c_reg_reset(obj); }
void i2c_abort_asynch(i2c_t *obj) { i2c_data[obj->i2c.i2c].async_obj = NULL; i2c_irqs_set(obj, 0); i2c_reg_reset(obj); }