[realtek-ambz] Add Wire library

This commit is contained in:
Kuba Szczodrzyński
2022-05-14 21:47:56 +02:00
parent f4f9788f68
commit 12338747bf
6 changed files with 342 additions and 10 deletions

View File

@@ -179,7 +179,7 @@ Flash I/O | ❓
**CORE LIBRARIES** |
SoftwareSerial | ❌
SPI | ❌
Wire |
Wire |
**OTHER LIBRARIES** |
Wi-Fi STA/AP/Mixed | ✔️
Wi-Fi Client (SSL) | ✔️ (✔️)

View File

@@ -0,0 +1,66 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-09. */
#include <api/Stream.h>
class ITwoWire : public Stream {
protected:
int8_t _sda = -1;
int8_t _scl = -1;
uint32_t _freq = 0;
void (*onRequestCallback)(void);
void (*onReceiveCallback)(int);
public:
bool begin() {
return begin(_sda, _scl, _freq);
}
bool begin(uint8_t address) {
return begin(address, _sda, _scl, _freq);
}
virtual bool setPins(int8_t sda, int8_t scl) = 0;
virtual bool begin(int8_t sda, int8_t scl, uint32_t frequency = 0) = 0;
virtual bool begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency = 0) = 0;
virtual bool end() = 0;
virtual bool setClock(uint32_t freq) = 0;
virtual void beginTransmission(uint8_t address) = 0;
virtual uint8_t endTransmission(bool stopBit) = 0;
virtual size_t requestFrom(uint8_t address, size_t len, bool stopBit) = 0;
virtual size_t write(const uint8_t *data, size_t len) = 0;
virtual int available() = 0;
virtual int read() = 0;
virtual int peek() = 0;
virtual void flush() = 0;
uint32_t getClock() {
return _freq;
}
uint8_t endTransmission() {
return endTransmission(true);
}
size_t requestFrom(uint8_t address, size_t len) {
return requestFrom(address, len, true);
}
virtual size_t write(uint8_t data) {
return write(&data, 1);
}
void onReceive(void (*cb)(int)) {
onReceiveCallback = cb;
}
void onRequest(void (*cb)(void)) {
onRequestCallback = cb;
}
};

View File

@@ -4,15 +4,12 @@
#include <Arduino.h>
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <flash_api.h>
}
#ifdef __cplusplus
} // extern "C"
#endif
// Global Flash object.
FlashClass Flash;
FlashClass::FlashClass() {
flash = NULL;
@@ -67,5 +64,3 @@ bool FlashClass::writeBlock(uint32_t offset, uint8_t *data, size_t size) {
initialize();
return flash_stream_write(flash, offset, size, data);
}
FlashClass Flash;

View File

@@ -0,0 +1,192 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-08. */
#include "Wire.h"
#include <Arduino.h>
extern "C" {
#include <i2c_api.h>
extern int i2c_write_timeout(i2c_t *obj, int address, char *data, int length, int stop, int timeout_ms);
}
#ifdef PIN_WIRE0_SDA
// Wire object associated to I2C0 interface.
TwoWire Wire(PIN_WIRE0_SDA, PIN_WIRE0_SCL);
#endif
#if defined(PIN_WIRE0_SDA) && defined(PIN_WIRE1_SDA)
// Wire object associated to I2C1 interface.
TwoWire Wire1(PIN_WIRE1_SDA, PIN_WIRE1_SCL);
#endif
#if !defined(PIN_WIRE0_SDA) && defined(PIN_WIRE1_SDA)
// Wire object associated to I2C1 interface. The board doesn't support I2C0.
TwoWire Wire(PIN_WIRE1_SDA, PIN_WIRE1_SCL);
#endif
TwoWire::TwoWire() {
_timeout = 50;
}
TwoWire::TwoWire(int8_t sda, int8_t scl) {
_timeout = 50;
_sda = sda;
_scl = scl;
}
TwoWire::~TwoWire() {}
bool TwoWire::setPins(int8_t sda, int8_t scl) {
// return true when changing pins on initialized I2C
if (_inSetPins)
return true;
// check if pins are provided
if (sda == -1 || scl == -1)
return false;
// set private pins
_sda = sda;
_scl = scl;
sda = g_APinDescription[sda].pinname;
scl = g_APinDescription[scl].pinname;
// check if pins are valid
if ((sda == PA_4 || sda == PA_19 || sda == PA_30) && (scl == PA_1 || scl == PA_22 || scl == PA_29)) {
// I2C index 0
_idx = 0;
} else if ((sda == PA_27 || sda == PA_2 || sda == PA_23) && (scl == PA_28 || scl == PA_3 || scl == PA_18)) {
// I2C index 1
_idx = 1;
} else {
return false;
}
// restart I2C if changing pins
// this will never be called from begin()
if (_i2c) {
_inSetPins = true;
end();
begin();
_inSetPins = false;
}
return true;
}
bool TwoWire::begin(int8_t sda, int8_t scl, uint32_t frequency) {
if (_i2c)
return true;
// set private i2c pins
if (!setPins(sda, scl))
return false;
// use default frequency
if (!frequency)
frequency = WIRE_DEFAULT_FREQ;
_i2c = new i2c_t;
i2c_init(_i2c, (PinName)g_APinDescription[_sda].pinname, (PinName)g_APinDescription[_scl].pinname);
i2c_frequency(_i2c, frequency);
_freq = frequency;
return true;
}
bool TwoWire::begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency) {
if (_i2c)
return true;
// init master bus first, return if failed (wrong pins)
if (!begin(sda, scl, frequency))
return false;
i2c_slave_address(_i2c, _idx, address, 0xff);
i2c_slave_mode(_i2c, true);
return true;
}
bool TwoWire::end() {
i2c_reset(_i2c);
delete _i2c;
_i2c = NULL;
}
bool TwoWire::setClock(uint32_t freq) {
if (_i2c) {
i2c_frequency(_i2c, freq);
}
_freq = freq;
}
void TwoWire::beginTransmission(uint8_t address) {
_txAddr = address;
_txBuf.clear();
}
// Errors:
// 0 : Success
// 1 : Data too long
// 2 : NACK on transmit of address
// 3 : NACK on transmit of data
// 4 : Other error
uint8_t TwoWire::endTransmission(bool stopBit) {
if (!_i2c || !_txAddr)
return 4;
char *buf = (char *)malloc(_txBuf.available());
uint8_t i = 0;
while (_txBuf.available()) {
buf[i++] = _txBuf.read_char();
}
int len = i2c_write_timeout(_i2c, _txAddr, buf, i, stopBit, _timeout);
free(buf);
_txAddr = 0;
if (len == -1)
return 2; // slave not available (if tx length == 0)
if (len != i)
return 3; // less bytes written
return 0;
}
size_t TwoWire::requestFrom(uint8_t address, size_t len, bool stopBit) {
if (!len)
return 0;
if (len > SERIAL_BUFFER_SIZE)
len = SERIAL_BUFFER_SIZE;
_rxBuf.clear();
char *buf = (char *)malloc(_txBuf.available());
i2c_read(_i2c, address, buf, len, stopBit);
uint8_t i = 0;
while (len) {
_rxBuf.store_char(buf[i++]);
len--;
}
free(buf);
return len;
}
size_t TwoWire::write(uint8_t data) {
if (!_txAddr || _txBuf.isFull())
return 0;
_txBuf.store_char(data);
return 1;
}
size_t TwoWire::write(const uint8_t *data, size_t len) {
for (size_t i = 0; i < len; i++) {
if (!write(data[i]))
return i;
}
return len;
}
int TwoWire::available() {
return _rxBuf.available();
}
int TwoWire::read() {
return _rxBuf.read_char();
}
int TwoWire::peek() {
return _rxBuf.peek();
}
void TwoWire::flush() {}

View File

@@ -0,0 +1,75 @@
/* Copyright (c) Kuba Szczodrzyński 2022-05-08. */
#pragma once
#include <api/RingBuffer.h>
#include <api/Wire.h>
#ifdef __cplusplus
extern "C" {
#endif
// #include <i2c_api.h>
#ifdef __cplusplus
}
#endif
#if !defined(PIN_WIRE0_SDA) && defined(PIN_WIRE1_SDA)
#define Wire1 Wire
#endif
#define WIRE_HAS_END 1
#define WIRE_DEFAULT_FREQ 100000
struct i2c_s;
typedef struct i2c_s i2c_t;
using arduino::RingBuffer;
class TwoWire : public ITwoWire {
private:
i2c_t *_i2c = NULL;
uint8_t _idx = 0;
RingBuffer _rxBuf;
RingBuffer _txBuf;
uint8_t _txAddr = 0;
bool _inSetPins = false;
public:
TwoWire();
TwoWire(int8_t sda, int8_t scl);
~TwoWire();
bool setPins(int8_t sda, int8_t scl);
bool begin(int8_t sda, int8_t scl, uint32_t frequency = 0);
bool begin(uint8_t address, int8_t sda, int8_t scl, uint32_t frequency = 0);
bool end();
bool setClock(uint32_t freq);
void beginTransmission(uint8_t address);
uint8_t endTransmission(bool stopBit);
size_t requestFrom(uint8_t address, size_t len, bool stopBit);
size_t write(uint8_t data);
size_t write(const uint8_t *data, size_t len);
int available();
int read();
int peek();
void flush();
using ITwoWire::begin;
using ITwoWire::endTransmission;
using ITwoWire::requestFrom;
using ITwoWire::write;
using Print::write;
};
#ifdef PIN_WIRE0_SDA
extern TwoWire Wire;
#endif
#ifdef PIN_WIRE1_SDA
extern TwoWire Wire1;
#endif

View File

@@ -40,7 +40,11 @@ static const uint8_t A2 = PIN_A2;
// Wire Interfaces
// ---------------
#define WIRE_INTERFACES_COUNT 0
#define WIRE_INTERFACES_COUNT 2
#define PIN_WIRE0_SDA 1u // PA_19
#define PIN_WIRE0_SCL 0u // PA_22
#define PIN_WIRE1_SDA 10u // PA_23
#define PIN_WIRE1_SCL 9u // PA_18
// Serial ports
// ------------