-
Notifications
You must be signed in to change notification settings - Fork 455
/
Copy pathWire.h
143 lines (113 loc) · 4.94 KB
/
Wire.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
I2C Master/Slave library for the Raspberry Pi Pico RP2040
Copyright (c) 2021 Earle F. Philhower, III <earlephilhower@yahoo.com>
Based off of TWI/I2C library for Arduino Zero
Copyright (c) 2015 Arduino LLC. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include <Arduino.h>
#include "api/HardwareI2C.h"
#include <hardware/i2c.h>
// WIRE_HAS_END means Wire has end()
#define WIRE_HAS_END 1
#ifndef WIRE_BUFFER_SIZE
#define WIRE_BUFFER_SIZE 256
#endif
class TwoWire : public HardwareI2C {
public:
TwoWire(i2c_inst_t *i2c, pin_size_t sda, pin_size_t scl);
// Start as Master
void begin() override;
// Start as Slave
void begin(uint8_t address) override;
// Shut down the I2C interface
void end() override;
// Select IO pins to use. Call before ::begin()
bool setSDA(pin_size_t sda);
bool setSCL(pin_size_t scl);
void setClock(uint32_t freqHz) override;
void beginTransmission(uint8_t) override;
uint8_t endTransmission(bool stopBit) override;
uint8_t endTransmission(void) override;
size_t requestFrom(uint8_t address, size_t quantity, bool stopBit) override;
size_t requestFrom(uint8_t address, size_t quantity) override;
size_t write(uint8_t data) override;
size_t write(const uint8_t * data, size_t quantity) override;
virtual int available(void) override;
virtual int read(void) override;
virtual int peek(void) override;
virtual void flush(void) override;
void onReceive(void(*)(int));
void onRequest(void(*)(void));
inline size_t write(unsigned long n) {
return write((uint8_t)n);
}
inline size_t write(long n) {
return write((uint8_t)n);
}
inline size_t write(unsigned int n) {
return write((uint8_t)n);
}
inline size_t write(int n) {
return write((uint8_t)n);
}
using Print::write;
// DMA/asynchronous transfers. Do not combime with synchronous runs or bad stuff will happen
// All buffers must be valid for entire DMA and not touched until `finishedAsync()` returns true.
bool writeReadAsync(uint8_t address, const void *wbuffer, size_t wbytes, const void *rbuffer, size_t rbytes, bool sendStop = true);
bool writeAsync(uint8_t address, const void *buffer, size_t bytes, bool sendStop = true);
bool readAsync(uint8_t address, void *buffer, size_t bytes, bool sendStop = true);
bool finishedAsync(); // Call to check if the async operations is completed and the buffer can be reused/read
void abortAsync(); // Cancel an outstanding async I2C operation
void onFinishedAsync(void(*function)(void)); // Set callback for async operation
void _dma_irq_handler(); // "private" method, made public to call this method from low level dma irq handler
void setTimeout(uint32_t timeout = 25, bool reset_with_timeout = false); // sets the maximum number of milliseconds to wait
bool getTimeoutFlag(void);
void clearTimeoutFlag(void);
// IRQ callback
void onIRQ();
private:
i2c_inst_t *_i2c;
pin_size_t _sda;
pin_size_t _scl;
int _clkHz;
bool _running;
bool _slave;
uint8_t _addr;
bool _txBegun;
bool _timeoutFlag;
bool _reset_with_timeout;
void _handleTimeout(bool reset);
uint8_t _buff[WIRE_BUFFER_SIZE];
int _buffLen;
int _buffOff;
// Callback user functions
void (*_onRequestCallback)(void);
void (*_onReceiveCallback)(int);
bool _slaveStartDet = false;
// TWI clock frequency
static const uint32_t TWI_CLOCK = 100000;
// DMA
bool _dmaRunning = false; // set to true after successful beginAsync() call
int _dmaChannelReceive = -1; // dma channel to receive i2c data
int _dmaChannelSend = -1; // dma channel to send i2c commands
uint16_t *_dmaSendBuffer = nullptr; // dma command send buffer (dynamically allocated)
size_t _dmaSendBufferLen = 0; // size of dma command buffer
volatile bool _dmaFinished = true; // signals dma completion
void (*_dmaOnFinished)(void) = nullptr; // user handler to call on dma completion
void beginAsync(); // setup dma channels and irq, called on first use of an async read/write function
void endAsync(); // close dma channels, irq, buffers, called from end()
};
extern TwoWire Wire;
extern TwoWire Wire1;