14#include "i2c_rp2350.h"
15#include "system_rp2350.h"
18using namespace _I2C1_;
19using namespace _IO_BANK0_;
20using namespace _RESETS_;
22i2c_rp2350::i2c_rp2350(gpio_pin_t sda_pin,
25 : _initialized(false), _sda(sda_pin), _scl(scl_pin),
26 _mode(mode), _restart_on_next(false) {
28 if ((((sda_pin-0) % 4) == 0) && (((scl_pin-1) % 4) == 0)) {
33 }
else if ((((sda_pin-2) % 4) == 0) && (((scl_pin-3) % 4) == 0) ) {
39 assert(
false &&
"I2C pins do not fit!");
43i2c_rp2350::~i2c_rp2350() {
52void i2c_rp2350::initialize() {
54 if (_index) RESETS_CLR.RESET.I2C1 = 1;
55 else RESETS_CLR.RESET.I2C0 = 1;
57 _sda.setSEL(GPIO_CTRL_FUNCSEL__i2c);
58 _scl.setSEL(GPIO_CTRL_FUNCSEL__i2c);
61 _i2c->IC_ENABLE.ENABLE = 0;
64 _i2c->IC_CON.MASTER_MODE = 1;
65 _i2c->IC_CON.SPEED = IC_CON_SPEED__FAST;
66 _i2c->IC_CON.IC_10BITADDR_MASTER = 0;
67 _i2c->IC_CON.IC_RESTART_EN = 1;
68 _i2c->IC_CON.IC_SLAVE_DISABLE = 1;
69 _i2c->IC_CON.TX_EMPTY_CTRL = 1;
81int16_t i2c_rp2350::i2cRead (uint16_t addr, uint8_t *rxbuf,
82 uint16_t len,
bool sendStop) {
83 if (!_initialized) initialize();
85 _i2c->IC_ENABLE.ENABLE = 0;
87 _i2c->IC_ENABLE.ENABLE = 1;
90 for (byte_ctr = 0; byte_ctr < len; ++byte_ctr) {
91 bool first = byte_ctr == 0;
92 bool last = byte_ctr == len - 1;
94 while(_i2c->IC_TXFLR == 16) ;
96 uint32_t cmd = 1 << 8;
97 if (first && _restart_on_next) {
100 if (last && sendStop) {
103 _i2c->IC_DATA_CMD = cmd;
105 while(_i2c->IC_RXFLR == 0) ;
107 *rxbuf++ = _i2c->IC_DATA_CMD.DAT;
109 _restart_on_next = !sendStop;
113int16_t i2c_rp2350::i2cWrite(uint16_t addr, uint8_t *txbuf,
114 uint16_t len,
bool sendStop) {
115 if (!_initialized) initialize();
117 _i2c->IC_ENABLE.ENABLE = 0;
119 _i2c->IC_ENABLE.ENABLE = 1;
122 for (byte_ctr = 0; byte_ctr < len; ++byte_ctr) {
123 bool first = byte_ctr == 0;
124 bool last = byte_ctr == len - 1;
126 uint32_t cmd = *txbuf++;
127 if (first && _restart_on_next) {
130 if (last && sendStop) {
133 _i2c->IC_DATA_CMD = cmd;
139 while(!_i2c->IC_RAW_INTR_STAT.TX_EMPTY) ;
141 _restart_on_next = !sendStop;
145void i2c_rp2350::setSpeed(uint32_t freq) {
146 if (!_initialized) initialize();
149 uint32_t freq_in = CLK_SYS;
152 uint32_t period = (freq_in + freq / 2) / freq;
153 uint32_t lcnt = period * 3 / 5;
154 uint32_t hcnt = period - lcnt;
160 uint32_t sda_tx_hold_count;
161 if (freq < 1000000) {
165 sda_tx_hold_count = ((freq_in * 3) / 10000000) + 1;
170 sda_tx_hold_count = ((freq_in * 3) / 25000000) + 1;
172 assert(sda_tx_hold_count <= lcnt - 2);
174 _i2c->IC_ENABLE.ENABLE = 0;
176 _i2c->IC_CON.SPEED = IC_CON_SPEED__FAST;
177 _i2c->IC_FS_SCL_HCNT = hcnt;
178 _i2c->IC_FS_SCL_LCNT = lcnt;
179 _i2c->IC_FS_SPKLEN = lcnt < 16 ? 1 : lcnt / 16;
180 _i2c->IC_SDA_HOLD.IC_SDA_TX_HOLD = sda_tx_hold_count;
182 _i2c->IC_ENABLE.ENABLE = 1;