Pico-Arduino
PicoHardwareI2C.h
1 #pragma once
2 #include "HardwareI2C.h"
3 #include "hardware/i2c.h"
4 
5 
14 class PicoHardwareI2C : public HardwareI2C {
15  public:
17  PicoHardwareI2C(i2c_inst_t *i2c, int maxBufferSize, int sdaPin, int sclPin){
18  this->i2c = i2c;
19  this->maxBufferSize = maxBufferSize;
20  gpio_set_function(sdaPin, GPIO_FUNC_I2C);
21  gpio_set_function(sclPin, GPIO_FUNC_I2C);
22  gpio_pull_up(sdaPin);
23  gpio_pull_up(sclPin);
24  }
25 
28  end();
29  }
30 
32  virtual void begin() {
33  Logger.info("begin");
34  i2c_init(i2c, 100000);
35  i2c_set_slave_mode(i2c, false, 0);
36  is_slave_mode = false;
37  setupWriteBuffer();
38  }
39 
41  virtual void begin(uint8_t address) {
42  Logger.info("begin");
43  i2c_set_slave_mode(i2c, true, address);
44  is_slave_mode = true;
45  setupWriteBuffer();
46  }
47 
49  virtual void end() {
50  Logger.info("end");
51  i2c_deinit(i2c);
52  if (read_buffer !=nullptr){
53  delete[]read_buffer;
54  read_buffer = nullptr;
55  }
56  if (write_buffer !=nullptr){
57  delete[]write_buffer;
58  write_buffer = nullptr;
59  }
60  }
61 
63  virtual void setClock(uint32_t baudrate) {
64  Logger.info("setClock");
65  i2c_set_baudrate(i2c, baudrate);
66  }
67 
69  virtual void beginTransmission(uint8_t address) {
70  Logger.info("beginTransmission");
71  transmission_address=address;
72  }
73 
75  virtual uint8_t endTransmission(bool stopBit) {
76  Logger.info("endTransmission");
77  transmission_address = -1;
78  return flush(true);
79  }
80 
82  virtual uint8_t endTransmission(void) {
83  Logger.info("endTransmission");
84  transmission_address = -1;
85  return flush(false);
86  }
87 
89  virtual size_t write(uint8_t c) {
90  Logger.debug("write");
91  size_t result = 0;
92  if (write_pos>=maxBufferSize){
93  flush(false);
94  }
95  // we just write to a buffer
96  if (write_pos<maxBufferSize){
97  result = 1;
98  write_buffer[write_pos]=c;
99  write_pos++;
100  }
101  return result;
102  }
103 
105  size_t write(const char *buffer, size_t size) {
106  Logger.debug("write[]");
107  // if we have any data in the buffer flush this first
108  flush();
109  // and now write out the requested data
110  return i2c_write_blocking(i2c, transmission_address, write_buffer, size, true);
111  }
112 
114  virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) {
115  Logger.info("requestFrom");
116  flush();
117  setupReadBuffer(len);
118 
119  // call requestHandler
120  if (this->requestHandler!=nullptr){
121  Logger.info("requestHandler");
122  (*this->requestHandler)();
123  }
124 
125  read_len = i2c_read_blocking(i2c, read_address, read_buffer, len, stopBit);
126  read_pos = 0;
127 
128  // call recieveHandler
129  if (read_len>0 && this->recieveHandler!=nullptr){
130  Logger.info("recieveHandler");
131  (*this->recieveHandler)(read_len);
132  }
133 
134  return read_len;
135  }
136 
138  virtual size_t requestFrom(uint8_t address, size_t len) {
139  return requestFrom(address, len, true);
140  }
141 
143  virtual int read() {
144  Logger.debug("read");
145  // trigger flush of write buffer
146  int result = (read_pos<read_len) ? read_buffer[read_pos++] : -1;
147  return result;
148  }
149 
151  virtual int peek() {
152  Logger.debug("peek");
153  return (read_pos<read_len) ? read_buffer[read_pos] : -1;
154  }
155 
157  virtual int available() {
158  Logger.debug("available");
159  int buffer_available = read_len - read_pos;
160  return buffer_available;
161  }
162 
164  virtual void onReceive(void(*recieveHandler)(int)) {
165  this->recieveHandler = recieveHandler;
166  Logger.info("onReceive");
167  }
168 
170  virtual void onRequest(void(*requestHandler)(void)) {
171  this->requestHandler = requestHandler;
172  Logger.info("onRequest");
173  };
174 
175  protected:
176  bool is_slave_mode;
177  i2c_inst_t *i2c;
178  int maxBufferSize;
179  // write
180  uint8_t transmission_address;
181  int write_pos;
182  uint8_t *write_buffer;
183 
184  // read
185  size_t read_len;
186  size_t read_pos;
187  bool read_stop_bit;
188  uint8_t read_address;
189  uint8_t *read_buffer;
190 
191  // handler
192  void(*recieveHandler)(int);
193  void(*requestHandler)(void);
194 
195 
196  int flush(bool end=false) {
197  bool result = 0; // 4:other error
198  if (write_pos>0) {
199  Logger.debug("flush");
200  int result = i2c_write_blocking(i2c, transmission_address, write_buffer, write_pos, !end);
201  if (result == write_pos){
202  result = 0;
203  } else if (result < write_pos){
204  result = 1; // 1:data too long to fit in transmit buffer
205  } else {
206  result = 4; // 4:other error
207  }
208  write_pos = 0;
209  }
210  return result;
211  }
212 
213  void setupWriteBuffer(){
214  // setup buffer only if needed
215  if (write_buffer==nullptr){
216  Logger.info("setupWriteBuffer");
217  write_buffer = new uint8_t(maxBufferSize);
218  }
219  }
220 
221  void setupReadBuffer(int len){
222  if (read_buffer==nullptr){
223  // setup buffer only if needed
224  maxBufferSize = max(len, maxBufferSize);
225  Logger.info("setupReadBuffer: ",Logger.toStr(maxBufferSize));
226  read_buffer = new uint8_t(maxBufferSize);
227  } else {
228  if (len>maxBufferSize){
229  // grow the read buffer to the requested size
230  maxBufferSize = len;
231  Logger.info("setupReadBuffer: ",Logger.toStr(maxBufferSize));
232  delete[] read_buffer;
233  read_buffer = new uint8_t(maxBufferSize);
234  }
235  }
236  }
237 
238 };
239 
240 
Arduino I2C implementation using the Pico functionality. In Arduino we can read and write individal c...
Definition: PicoHardwareI2C.h:14
virtual void beginTransmission(uint8_t address)
Begin a transmission to the I2C slave device with the given address. Subsequently,...
Definition: PicoHardwareI2C.h:69
PicoHardwareI2C(i2c_inst_t *i2c, int maxBufferSize, int sdaPin, int sclPin)
Standard Constructor for PicoHardwareI2C class.
Definition: PicoHardwareI2C.h:17
virtual size_t write(uint8_t c)
Writes data from a slave device in response to a request from a master, or queues bytes for transmiss...
Definition: PicoHardwareI2C.h:89
virtual void end()
Closes the Wire Library.
Definition: PicoHardwareI2C.h:49
size_t write(const char *buffer, size_t size)
Writes data from a slave device in response to a request from a master, or queues bytes for transmiss...
Definition: PicoHardwareI2C.h:105
virtual int read()
Reads a byte that was transmitted from a slave device to a master after a call to requestFrom() or wa...
Definition: PicoHardwareI2C.h:143
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit)
Used by the master to request bytes from a slave device. The bytes may then be retrieved with the ava...
Definition: PicoHardwareI2C.h:114
virtual void begin(uint8_t address)
Initiate the Wire library and join the I2C bus as a slave. This should normally be called only once.
Definition: PicoHardwareI2C.h:41
virtual uint8_t endTransmission(void)
Ends a transmission to a slave device that was begun by beginTransmission() and transmits the bytes t...
Definition: PicoHardwareI2C.h:82
virtual void setClock(uint32_t baudrate)
This function modifies the clock frequency for I2C communication. I2C slave devices have no minimum w...
Definition: PicoHardwareI2C.h:63
virtual void onRequest(void(*requestHandler)(void))
Register a function to be called when a master requests data from this slave device.
Definition: PicoHardwareI2C.h:170
~PicoHardwareI2C()
Destructor for PicoHardwareI2C class.
Definition: PicoHardwareI2C.h:27
virtual int peek()
Peeks current unread byte that was transmitted from a slave device to a master after a call to reques...
Definition: PicoHardwareI2C.h:151
virtual void begin()
Initiate the Wire library and join the I2C bus as a master. This should normally be called only once.
Definition: PicoHardwareI2C.h:32
virtual int available()
Returns the number of bytes available for retrieval with read(). This should be called on a master de...
Definition: PicoHardwareI2C.h:157
virtual void onReceive(void(*recieveHandler)(int))
Registers a function to be called when a slave device receives a transmission from a master.
Definition: PicoHardwareI2C.h:164
virtual uint8_t endTransmission(bool stopBit)
Ends a transmission to a slave device that was begun by beginTransmission() and transmits the bytes t...
Definition: PicoHardwareI2C.h:75
virtual size_t requestFrom(uint8_t address, size_t len)
Used by the master to request bytes from a slave device. The bytes may then be retrieved with the ava...
Definition: PicoHardwareI2C.h:138
Definition: HardwareI2C.h:27