diff options
author | Simon Kühling <mail@simonkuehling.de> | 2021-09-03 20:58:22 +0200 |
---|---|---|
committer | KevinOConnor <kevin@koconnor.net> | 2021-10-06 21:27:51 -0400 |
commit | d90da37433634b93ac0bc6efebee9cf39c928880 (patch) | |
tree | b650f485e3b14ab236a5dffcf0559314f4d68cf5 /src | |
parent | 2822680eb453656673931eff5c5f3a8bd37df63a (diff) | |
download | kutter-d90da37433634b93ac0bc6efebee9cf39c928880.tar.gz kutter-d90da37433634b93ac0bc6efebee9cf39c928880.tar.xz kutter-d90da37433634b93ac0bc6efebee9cf39c928880.zip |
atsamd: Add i2c_read() implementation
Signed-off-by: Simon Kühling <mail@simonkuehling.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/atsamd/i2c.c | 44 |
1 files changed, 43 insertions, 1 deletions
diff --git a/src/atsamd/i2c.c b/src/atsamd/i2c.c index a5c128cc..0a920d85 100644 --- a/src/atsamd/i2c.c +++ b/src/atsamd/i2c.c @@ -102,5 +102,47 @@ void i2c_read(struct i2c_config config, uint8_t reg_len, uint8_t *reg , uint8_t read_len, uint8_t *read) { - shutdown("i2c_read not supported on samd21"); + SercomI2cm *si = (SercomI2cm *)config.si; + + // start in write mode and write register if provided + if(reg_len) { + // start in write mode + si->ADDR.reg = config.addr; + while (!(si->INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB)); + + // write registers + while (reg_len--){ + si->DATA.reg = *reg++; + while (!(si->INTFLAG.reg & SERCOM_I2CM_INTFLAG_MB)); + } + } + + // start with read bit enabled + si->ADDR.reg = (config.addr | 0x1); + + // read bytes from slave + while (read_len--){ + while (!(si->INTFLAG.reg & SERCOM_I2CM_INTFLAG_SB)); + + if (read_len){ + // set ACK response + si->CTRLB.reg &= ~SERCOM_I2CM_CTRLB_ACKACT; + while (si->SYNCBUSY.bit.SYSOP); + + // execute ACK succeded by byte read + si->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(2); + while (si->SYNCBUSY.bit.SYSOP); + } else { + // set NACK response + si->CTRLB.reg |= SERCOM_I2CM_CTRLB_ACKACT; + while (si->SYNCBUSY.bit.SYSOP); + + // execute NACK succeded by stop condition + si->CTRLB.reg |= SERCOM_I2CM_CTRLB_CMD(3); + while (si->SYNCBUSY.bit.SYSOP); + } + + // read received data byte + *read++ = si->DATA.reg; + } } |