Skip to content

Commit

Permalink
Portduino/Native: arduino_default SPI and I2C enhancements (#557)
Browse files Browse the repository at this point in the history
* Add basic support for I2C touchscreens on arduino_default
* Add quirk for platforms that can't continue an I2C read
* Add configurable SPI device to arduino_default BUS_SPI
* Use more appropriate define for PORTDUINO
  • Loading branch information
jp-bennett authored Apr 24, 2024
1 parent a0e0d14 commit 0e474e2
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 18 deletions.
37 changes: 21 additions & 16 deletions src/lgfx/v1/platforms/arduino_default/Bus_SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,41 +50,46 @@ namespace lgfx
{
dc_h();
pinMode(_cfg.pin_dc, pin_mode_t::output);
//SPI.pins(_cfg.pin_sclk, _cfg.pin_miso, _cfg.pin_mosi, -1);
SPI.begin();
//PrivateSPI->pins(_cfg.pin_sclk, _cfg.pin_miso, _cfg.pin_mosi, -1);
PrivateSPI->begin();
return true;
}

void Bus_SPI::release(void)
{
SPI.end();
PrivateSPI->end();
}

void Bus_SPI::spi_device(HardwareSPI *newSPI)
{
PrivateSPI = newSPI;
}

void Bus_SPI::beginTransaction(void)
{
dc_h();
//SPISettings setting(_cfg.freq_write, BitOrder::MSBFIRST, _cfg.spi_mode, true);
SPISettings setting(_cfg.freq_write, MSBFIRST, _cfg.spi_mode);
SPI.beginTransaction(setting);
PrivateSPI->beginTransaction(setting);
}

void Bus_SPI::endTransaction(void)
{
SPI.endTransaction();
PrivateSPI->endTransaction();
dc_h();
}

void Bus_SPI::beginRead(void)
{
SPI.endTransaction();
PrivateSPI->endTransaction();
//SPISettings setting(_cfg.freq_read, BitOrder::MSBFIRST, _cfg.spi_mode, false);
SPISettings setting(_cfg.freq_read, MSBFIRST, _cfg.spi_mode);
SPI.beginTransaction(setting);
PrivateSPI->beginTransaction(setting);
}

void Bus_SPI::endRead(void)
{
SPI.endTransaction();
PrivateSPI->endTransaction();
beginTransaction();
}

Expand All @@ -100,14 +105,14 @@ namespace lgfx
bool Bus_SPI::writeCommand(uint32_t data, uint_fast8_t bit_length)
{
dc_l();
SPI.transfer((uint8_t*)&data, bit_length >> 3);
PrivateSPI->transfer((uint8_t*)&data, bit_length >> 3);
dc_h();
return true;
}

void Bus_SPI::writeData(uint32_t data, uint_fast8_t bit_length)
{
SPI.transfer((uint8_t*)&data, bit_length >> 3);
PrivateSPI->transfer((uint8_t*)&data, bit_length >> 3);
}

void Bus_SPI::writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t length)
Expand All @@ -116,7 +121,7 @@ namespace lgfx
auto bytes = bit_length >> 3;
do
{
SPI.send(reinterpret_cast<uint8_t*>(&data), bytes);
PrivateSPI->send(reinterpret_cast<uint8_t*>(&data), bytes);
} while (--length);
/*/
const uint8_t dst_bytes = bit_length >> 3;
Expand All @@ -137,7 +142,7 @@ namespace lgfx
fillpos += fillpos;
}

SPI.transfer(buf, len * dst_bytes);
PrivateSPI->transfer(buf, len * dst_bytes);
} while (length -= len);
//*/
}
Expand All @@ -153,15 +158,15 @@ namespace lgfx
if (limit <= 32) limit <<= 1;
auto buf = _flip_buffer.getBuffer(len * dst_bytes);
param->fp_copy(buf, 0, len, param);
SPI.transfer(buf, len * dst_bytes);
PrivateSPI->transfer(buf, len * dst_bytes);
} while (length -= len);
}

void Bus_SPI::writeBytes(const uint8_t* data, uint32_t length, bool dc, bool use_dma)
{
if (dc) dc_h();
else dc_l();
SPI.transfer(const_cast<uint8_t*>(data), length);
PrivateSPI->transfer(const_cast<uint8_t*>(data), length);
if (!dc) dc_h();
}

Expand All @@ -173,7 +178,7 @@ namespace lgfx
int idx = 0;
do
{
res |= SPI.transfer(0) << idx;
res |= PrivateSPI->transfer(0) << idx;
idx += 8;
} while (--bit_length);
return res;
Expand All @@ -183,7 +188,7 @@ namespace lgfx
{
do
{
dst[0] = SPI.transfer(0);
dst[0] = PrivateSPI->transfer(0);
++dst;
} while (--length);
return true;
Expand Down
4 changes: 3 additions & 1 deletion src/lgfx/v1/platforms/arduino_default/Bus_SPI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace lgfx

bool init(void) override;
void release(void) override;
void spi_device(HardwareSPI *newSPI);

void beginTransaction(void) override;
void endTransaction(void) override;
Expand All @@ -76,7 +77,7 @@ namespace lgfx
bool readBytes(uint8_t* dst, uint32_t length, bool use_dma) override;
void readPixels(void* dst, pixelcopy_t* param, uint32_t length) override;

private:
protected:

__attribute__ ((always_inline)) inline void dc_h(void) {
gpio_hi(_cfg.pin_dc);
Expand All @@ -85,6 +86,7 @@ namespace lgfx
gpio_lo(_cfg.pin_dc);
}

HardwareSPI *PrivateSPI = &SPI;
config_t _cfg;
FlipBuffer _flip_buffer;
bool _need_wait;
Expand Down
87 changes: 86 additions & 1 deletion src/lgfx/v1/platforms/arduino_default/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,93 @@ namespace lgfx

//----------------------------------------------------------------------------

/// unimplemented.

namespace i2c
{
#ifdef TwoWire_h
cpp::result<void, error_t> init(int i2c_port, int pin_sda, int pin_scl) { Wire.begin(); return {};}
cpp::result<void, error_t> release(int i2c_port) { Wire.end(); return {};}
cpp::result<void, error_t> restart(int i2c_port, int i2c_addr, uint32_t freq, bool read) { Wire.endTransmission(true); Wire.beginTransmission(i2c_addr); return {};}
cpp::result<void, error_t> beginTransaction(int i2c_port, int i2c_addr, uint32_t freq, bool read) { Wire.beginTransmission(i2c_addr); return {};}
cpp::result<void, error_t> endTransaction(int i2c_port) { Wire.endTransmission(true); return {};}
cpp::result<void, error_t> writeBytes(int i2c_port, const uint8_t *data, size_t length) { Wire.write(data, length); return {};}
cpp::result<void, error_t> readBytes(int i2c_port, uint8_t *data, size_t length)
{
Wire.readBytes((char *)data, (size_t)length);
/*
printf("0x");
for (int i=0; i< length; i++) {
printf("%02x ", data[i]);
}
printf("\n");
*/
return {};
}
cpp::result<void, error_t> readBytes(int i2c_port, uint8_t *data, size_t length, bool last_nack)
{
Wire.readBytes((char *)data, (size_t)length);
/*
printf("0x");
for (int i=0; i< length; i++) {
printf("%02x ", data[i]);
}
printf("\n");
*/
return {};
}

cpp::result<void, error_t> transactionWrite(int i2c_port, int addr, const uint8_t *writedata, uint8_t writelen, uint32_t freq) {
cpp::result<void, error_t> res;
if ((res = beginTransaction(i2c_port, addr, freq, false)).has_value() && (res = writeBytes(i2c_port, writedata, writelen)).has_value())
{
res = endTransaction(i2c_port);
}
return res;
}

cpp::result<void, error_t> transactionRead(int i2c_port, int addr, uint8_t *readdata, uint8_t readlen, uint32_t freq) {
cpp::result<void, error_t> res;
if ((res = beginTransaction(i2c_port, addr, freq, false)).has_value() && (res = readBytes(i2c_port, readdata, readlen)).has_value())
{
res = endTransaction(i2c_port);
}
return res;
}

cpp::result<void, error_t> transactionWriteRead(int i2c_port, int addr, const uint8_t *writedata, uint8_t writelen, uint8_t *readdata, size_t readlen, uint32_t freq) {
cpp::result<void, error_t> res;
if ((res = beginTransaction(i2c_port, addr, freq, false)).has_value() && (res = writeBytes(i2c_port, writedata, writelen)).has_value() &&
(res = restart(i2c_port, addr, freq, false)).has_value() && (res = readBytes(i2c_port, readdata, readlen)).has_value())
{
res = endTransaction(i2c_port);
}
return res;
}

cpp::result<uint8_t, error_t> readRegister8(int i2c_port, int addr, uint8_t reg, uint32_t freq) {
auto res = transactionWriteRead(i2c_port, addr, &reg, 1, &reg, 1, freq);
if (res.has_value())
{
return reg;
}
return cpp::fail(res.error());
}

cpp::result<void, error_t> writeRegister8(int i2c_port, int addr, uint8_t reg, uint8_t data, uint8_t mask, uint32_t freq) {
uint8_t tmp[2] = {reg, data};
if (mask != 0)
{
auto res = transactionWriteRead(i2c_port, addr, &reg, 1, &tmp[1], 1, freq);
if (res.has_error())
{
return res;
}
tmp[1] = (tmp[1] & mask) | data;
}
return transactionWrite(i2c_port, addr, tmp, 2, freq);
}

#else
cpp::result<void, error_t> init(int i2c_port, int pin_sda, int pin_scl) { return cpp::fail(error_t::unknown_err); }
cpp::result<void, error_t> release(int i2c_port) { return cpp::fail(error_t::unknown_err); }
cpp::result<void, error_t> restart(int i2c_port, int i2c_addr, uint32_t freq, bool read) { return cpp::fail(error_t::unknown_err); }
Expand All @@ -99,6 +183,7 @@ namespace lgfx

cpp::result<uint8_t, error_t> readRegister8(int i2c_port, int addr, uint8_t reg, uint32_t freq) { return cpp::fail(error_t::unknown_err); }
cpp::result<void, error_t> writeRegister8(int i2c_port, int addr, uint8_t reg, uint8_t data, uint8_t mask, uint32_t freq) { return cpp::fail(error_t::unknown_err); }
#endif
}

//----------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions src/lgfx/v1/touch/Touch_FT5x06.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ if (_inited)
uint_fast8_t points = std::min<uint_fast8_t>(max_touch_points, readdata[0] & 0x0Fu);
if (points)
{
#ifdef PORTDUINO_LINUX_HARDWARE
readdata[1] = 0x03;
lgfx::i2c::writeBytes(_cfg.i2c_port, &readdata[1], 1);
#endif
if (lgfx::i2c::readBytes(_cfg.i2c_port, &readdata[1], points * 6 - 2))
{
res = points * 6 - 1;
Expand Down

0 comments on commit 0e474e2

Please sign in to comment.