diff --git a/CMakeLists.txt b/CMakeLists.txt index eee5105d..76ecef83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ file(GLOB SRCS src/lgfx/v1/misc/*.cpp src/lgfx/v1/panel/*.cpp src/lgfx/v1/platforms/arduino_default/*.cpp + src/lgfx/v1/platforms/portduino/*.cpp src/lgfx/v1/platforms/esp32/*.cpp src/lgfx/v1/platforms/esp32c3/*.cpp src/lgfx/v1/platforms/esp32s2/*.cpp diff --git a/src/lgfx/v1/platforms/arduino_default/Bus_SPI.cpp b/src/lgfx/v1/platforms/arduino_default/Bus_SPI.cpp index 4035ae0a..65c8d8b4 100644 --- a/src/lgfx/v1/platforms/arduino_default/Bus_SPI.cpp +++ b/src/lgfx/v1/platforms/arduino_default/Bus_SPI.cpp @@ -22,6 +22,7 @@ Original Source: #elif defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) #elif defined (ARDUINO_ARCH_SPRESENSE) #elif defined (ARDUINO_ARCH_MBED_RP2040) || defined(ARDUINO_ARCH_RP2040) +#elif defined (PORTDUINO_LINUX_HARDWARE) #elif defined (ARDUINO) #include "Bus_SPI.hpp" @@ -60,10 +61,6 @@ namespace lgfx PrivateSPI->end(); } - void Bus_SPI::spi_device(HardwareSPI *newSPI) - { - PrivateSPI = newSPI; - } void Bus_SPI::beginTransaction(void) { diff --git a/src/lgfx/v1/platforms/arduino_default/Bus_SPI.hpp b/src/lgfx/v1/platforms/arduino_default/Bus_SPI.hpp index 40de089d..a5705778 100644 --- a/src/lgfx/v1/platforms/arduino_default/Bus_SPI.hpp +++ b/src/lgfx/v1/platforms/arduino_default/Bus_SPI.hpp @@ -52,7 +52,6 @@ namespace lgfx bool init(void) override; void release(void) override; - void spi_device(HardwareSPI *newSPI); void beginTransaction(void) override; void endTransaction(void) override; diff --git a/src/lgfx/v1/platforms/arduino_default/Bus_Stream.cpp b/src/lgfx/v1/platforms/arduino_default/Bus_Stream.cpp index ab29aea0..855cd565 100644 --- a/src/lgfx/v1/platforms/arduino_default/Bus_Stream.cpp +++ b/src/lgfx/v1/platforms/arduino_default/Bus_Stream.cpp @@ -15,7 +15,7 @@ Original Source: [mongonta0716](https://github.com/mongonta0716) [tobozo](https://github.com/tobozo) /----------------------------------------------------------------------------*/ -#if defined (ARDUINO) +#if defined (ARDUINO) && !defined (PORTDUINO_LINUX_HARDWARE) #include "Bus_Stream.hpp" #include "../../misc/pixelcopy.hpp" diff --git a/src/lgfx/v1/platforms/arduino_default/common.cpp b/src/lgfx/v1/platforms/arduino_default/common.cpp index 5237a127..3cf7cee7 100644 --- a/src/lgfx/v1/platforms/arduino_default/common.cpp +++ b/src/lgfx/v1/platforms/arduino_default/common.cpp @@ -22,6 +22,7 @@ Original Source: #elif defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) #elif defined (ARDUINO_ARCH_SPRESENSE) #elif defined (ARDUINO_ARCH_MBED_RP2040) || defined(ARDUINO_ARCH_RP2040) +#elif defined (PORTDUINO_LINUX_HARDWARE) #elif defined (ARDUINO) #include "common.hpp" diff --git a/src/lgfx/v1/platforms/common.hpp b/src/lgfx/v1/platforms/common.hpp index 4789dd69..dbb790ca 100644 --- a/src/lgfx/v1/platforms/common.hpp +++ b/src/lgfx/v1/platforms/common.hpp @@ -45,6 +45,10 @@ Original Source: #include "rp2040/common.hpp" +#elif defined (PORTDUINO_LINUX_HARDWARE) + +#include "portduino/common.hpp" + #elif defined (ARDUINO) #include "arduino_default/common.hpp" diff --git a/src/lgfx/v1/platforms/device.hpp b/src/lgfx/v1/platforms/device.hpp index 182886f4..5cd81988 100644 --- a/src/lgfx/v1/platforms/device.hpp +++ b/src/lgfx/v1/platforms/device.hpp @@ -84,6 +84,10 @@ Original Source: #include "rp2040/Bus_I2C.hpp" #include "rp2040/Bus_SPI.hpp" +#elif defined (PORTDUINO_LINUX_HARDWARE) + +#include "portduino/Bus_SPI.hpp" + #elif defined (ARDUINO) #include "arduino_default/Bus_SPI.hpp" diff --git a/src/lgfx/v1/platforms/portduino/Bus_SPI.cpp b/src/lgfx/v1/platforms/portduino/Bus_SPI.cpp new file mode 100644 index 00000000..d986c92c --- /dev/null +++ b/src/lgfx/v1/platforms/portduino/Bus_SPI.cpp @@ -0,0 +1,219 @@ +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#if defined (ESP_PLATFORM) +#elif defined (ESP8266) +#elif defined (__SAMD21__) || defined(__SAMD21G18A__) || defined(__SAMD21J18A__) || defined(__SAMD21E17A__) || defined(__SAMD21E18A__) +#elif defined (__SAMD51__) +#elif defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) +#elif defined (ARDUINO_ARCH_SPRESENSE) +#elif defined (ARDUINO_ARCH_MBED_RP2040) || defined(ARDUINO_ARCH_RP2040) +#elif defined (PORTDUINO_LINUX_HARDWARE) + +#include "Bus_SPI.hpp" +#include "../../misc/pixelcopy.hpp" +#include +#include + +namespace lgfx +{ + inline namespace v1 + { +//---------------------------------------------------------------------------- + + void Bus_SPI::config(const config_t& config) + { + _cfg = config; + + if (_cfg.pin_dc >= 0) + { + pinMode(_cfg.pin_dc, pin_mode_t::output); + gpio_hi(_cfg.pin_dc); + } + } + + bool Bus_SPI::init(void) + { + dc_h(); + pinMode(_cfg.pin_dc, pin_mode_t::output); + char x = (_cfg.spi_host & (1 << 4) - 1) + '0'; + char y = (_cfg.spi_host >> 4) + '0'; + PrivateSPI = new HardwareSPI(); + std::string spiString = "/dev/spidev"; + spiString += x; + spiString += "."; + spiString += y; + PrivateSPI->begin(spiString.c_str()); + return true; + } + + void Bus_SPI::release(void) + { + PrivateSPI->end(); + } + + + 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); + PrivateSPI->beginTransaction(setting); + } + + void Bus_SPI::endTransaction(void) + { + PrivateSPI->endTransaction(); + dc_h(); + } + + void Bus_SPI::beginRead(void) + { + PrivateSPI->endTransaction(); + //SPISettings setting(_cfg.freq_read, BitOrder::MSBFIRST, _cfg.spi_mode, false); + SPISettings setting(_cfg.freq_read, MSBFIRST, _cfg.spi_mode); + PrivateSPI->beginTransaction(setting); + } + + void Bus_SPI::endRead(void) + { + PrivateSPI->endTransaction(); + beginTransaction(); + } + + void Bus_SPI::wait(void) + { + } + + bool Bus_SPI::busy(void) const + { + return false; + } + + bool Bus_SPI::writeCommand(uint32_t data, uint_fast8_t bit_length) + { + dc_l(); + PrivateSPI->transfer((uint8_t*)&data, bit_length >> 3); + dc_h(); + return true; + } + + void Bus_SPI::writeData(uint32_t data, uint_fast8_t bit_length) + { + PrivateSPI->transfer((uint8_t*)&data, bit_length >> 3); + } + + void Bus_SPI::writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t length) + { +/* + auto bytes = bit_length >> 3; + do + { + PrivateSPI->send(reinterpret_cast(&data), bytes); + } while (--length); +/*/ + const uint8_t dst_bytes = bit_length >> 3; + uint32_t limit = (dst_bytes == 3) ? 12 : 16; + auto buf = _flip_buffer.getBuffer(512); + size_t fillpos = 0; + reinterpret_cast(buf)[0] = data; + fillpos += dst_bytes; + uint32_t len; + do + { + len = ((length - 1) % limit) + 1; + if (limit <= 64) limit <<= 1; + + while (fillpos < len * dst_bytes) + { + memcpy(&buf[fillpos], buf, fillpos); + fillpos += fillpos; + } + + PrivateSPI->transfer(buf, len * dst_bytes); + } while (length -= len); +//*/ + } + + void Bus_SPI::writePixels(pixelcopy_t* param, uint32_t length) + { + const uint8_t dst_bytes = param->dst_bits >> 3; + uint32_t limit = (dst_bytes == 3) ? 12 : 16; + uint32_t len; + do + { + len = ((length - 1) % limit) + 1; + if (limit <= 32) limit <<= 1; + auto buf = _flip_buffer.getBuffer(len * dst_bytes); + param->fp_copy(buf, 0, len, param); + 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(); + PrivateSPI->transfer(const_cast(data), length); + if (!dc) dc_h(); + } + + uint32_t Bus_SPI::readData(uint_fast8_t bit_length) + { + uint32_t res = 0; + bit_length >>= 3; + if (!bit_length) return res; + int idx = 0; + do + { + res |= PrivateSPI->transfer(0) << idx; + idx += 8; + } while (--bit_length); + return res; + } + + bool Bus_SPI::readBytes(uint8_t* dst, uint32_t length, bool use_dma) + { + do + { + dst[0] = PrivateSPI->transfer(0); + ++dst; + } while (--length); + return true; + } + + void Bus_SPI::readPixels(void* dst, pixelcopy_t* param, uint32_t length) + { + uint32_t bytes = param->src_bits >> 3; + uint32_t dstindex = 0; + uint32_t len = 4; + uint8_t buf[24]; + param->src_data = buf; + do { + if (len > length) len = length; + readBytes((uint8_t*)buf, len * bytes, true); + param->src_x = 0; + dstindex = param->fp_copy(dst, dstindex, dstindex + len, param); + length -= len; + } while (length); + } + +//---------------------------------------------------------------------------- + } +} + +#endif diff --git a/src/lgfx/v1/platforms/portduino/Bus_SPI.hpp b/src/lgfx/v1/platforms/portduino/Bus_SPI.hpp new file mode 100644 index 00000000..576b6945 --- /dev/null +++ b/src/lgfx/v1/platforms/portduino/Bus_SPI.hpp @@ -0,0 +1,104 @@ +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#pragma once + +#include + +#include "../../Bus.hpp" +#include "../common.hpp" + +namespace lgfx +{ + inline namespace v1 + { +//---------------------------------------------------------------------------- + + class Bus_SPI : public IBus + { + public: + struct config_t + { + uint32_t freq_write = 16000000; + uint32_t freq_read = 8000000; + //bool spi_3wire = true; + //bool use_lock = true; + int16_t pin_sclk = -1; + int16_t pin_miso = -1; + int16_t pin_mosi = -1; + int16_t pin_dc = -1; + uint8_t spi_mode = 0; + int8_t spi_host = 0; + }; + + const config_t& config(void) const { return _cfg; } + + void config(const config_t& config); + + bus_type_t busType(void) const override { return bus_type_t::bus_spi; } + + bool init(void) override; + void release(void) override; + + void beginTransaction(void) override; + void endTransaction(void) override; + void wait(void) override; + bool busy(void) const override; + + bool writeCommand(uint32_t data, uint_fast8_t bit_length) override; + void writeData(uint32_t data, uint_fast8_t bit_length) override; + void writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t count) override; + void writePixels(pixelcopy_t* param, uint32_t length) override; + void writeBytes(const uint8_t* data, uint32_t length, bool dc, bool use_dma) override; + + void initDMA(void) {} + void flush(void) {} + void addDMAQueue(const uint8_t* data, uint32_t length) override { writeBytes(data, length, true, true); } + void execDMAQueue(void) {} + uint8_t* getDMABuffer(uint32_t length) override { return _flip_buffer.getBuffer(length); } + + void beginRead(void) override; + void endRead(void) override; + uint32_t readData(uint_fast8_t bit_length) override; + bool readBytes(uint8_t* dst, uint32_t length, bool use_dma) override; + void readPixels(void* dst, pixelcopy_t* param, uint32_t length) override; + + protected: + + __attribute__ ((always_inline)) inline void dc_h(void) { + gpio_hi(_cfg.pin_dc); + } + __attribute__ ((always_inline)) inline void dc_l(void) { + gpio_lo(_cfg.pin_dc); + } + + HardwareSPI *PrivateSPI = &SPI; + config_t _cfg; + FlipBuffer _flip_buffer; + bool _need_wait; + uint32_t _mask_reg_dc; + uint32_t _last_apb_freq = -1; + uint32_t _clkdiv_write; + uint32_t _clkdiv_read; + volatile uint32_t* _gpio_reg_dc_h; + volatile uint32_t* _gpio_reg_dc_l; + + }; + +//---------------------------------------------------------------------------- + } +} diff --git a/src/lgfx/v1/platforms/portduino/Bus_Stream.cpp b/src/lgfx/v1/platforms/portduino/Bus_Stream.cpp new file mode 100644 index 00000000..ab29aea0 --- /dev/null +++ b/src/lgfx/v1/platforms/portduino/Bus_Stream.cpp @@ -0,0 +1,127 @@ +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#if defined (ARDUINO) + +#include "Bus_Stream.hpp" +#include "../../misc/pixelcopy.hpp" + +namespace lgfx +{ + inline namespace v1 + { +//---------------------------------------------------------------------------- + + void Bus_Stream::config(const config_t& config) + { + _cfg = config; + } + + void Bus_Stream::writeData(uint32_t data, uint_fast8_t bit_length) + { + const uint8_t dst_bytes = bit_length >> 3; + writeBytes((uint8_t*)&data, dst_bytes); + } + + void Bus_Stream::writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t length) + { + const uint8_t dst_bytes = bit_length >> 3; + uint32_t buf0 = data | data << bit_length; + uint32_t buf1; + uint32_t buf2; + // make 12Bytes data. + if (dst_bytes != 3) + { + if (dst_bytes == 1) + { + buf0 |= buf0 << 16; + } + buf1 = buf0; + buf2 = buf0; + } + else + { + buf1 = buf0 >> 8 | buf0 << 16; + buf2 = buf0 >> 16 | buf0 << 8; + } + uint32_t src[8] = { buf0, buf1, buf2, buf0, buf1, buf2, buf0, buf1 }; + auto buf = reinterpret_cast(src); + uint32_t limit = 32 / dst_bytes; + uint32_t len; + do + { + len = ((length - 1) % limit) + 1; + writeBytes(buf, len * dst_bytes); + } while (length -= len); + } + + void Bus_Stream::writePixels(pixelcopy_t* param, uint32_t length) + { + const uint8_t dst_bytes = param->dst_bits >> 3; + uint32_t limit = 32 / dst_bytes; + uint32_t len; + uint8_t buf[32]; + do + { + len = ((length - 1) % limit) + 1; + param->fp_copy(buf, 0, len, param); + writeBytes(buf, len * dst_bytes); + } while (length -= len); + } + + void Bus_Stream::writeBytes(const uint8_t* data, uint32_t length) + { + _cfg.stream->write(data, length); + } + + uint32_t Bus_Stream::readData(uint_fast8_t bit_length) + { + const uint8_t dst_bytes = bit_length >> 3; + uint32_t res; + _cfg.stream->readBytes(reinterpret_cast(&res), dst_bytes); + return res; + } + + bool Bus_Stream::readBytes(uint8_t* dst, uint32_t length, bool use_dma) + { + _cfg.stream->readBytes(dst, length); + return true; + } + + void Bus_Stream::readPixels(void* dst, pixelcopy_t* param, uint32_t length) + { + beginRead(); + const auto bytes = param->src_bits >> 3; + uint32_t regbuf[8]; + uint32_t limit = 32 / bytes; + + param->src_data = regbuf; + int32_t dstindex = 0; + do { + uint32_t len = (limit > length) ? length : limit; + length -= len; + _cfg.stream->readBytes((uint8_t*)regbuf, len * bytes); + param->src_x = 0; + dstindex = param->fp_copy(dst, dstindex, dstindex + len, param); + } while (length); + } + +//---------------------------------------------------------------------------- + } +} + +#endif diff --git a/src/lgfx/v1/platforms/portduino/Bus_Stream.hpp b/src/lgfx/v1/platforms/portduino/Bus_Stream.hpp new file mode 100644 index 00000000..52fec4ad --- /dev/null +++ b/src/lgfx/v1/platforms/portduino/Bus_Stream.hpp @@ -0,0 +1,81 @@ +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#pragma once + +#include +#include + +#include "../../Bus.hpp" +#include "../common.hpp" + +namespace lgfx +{ + inline namespace v1 + { +//---------------------------------------------------------------------------- + + class Bus_Stream : public IBus + { + public: + struct config_t + { + Stream* stream = nullptr; + }; + + const config_t& config(void) const { return _cfg; } + + void config(const config_t& config); + + bus_type_t busType(void) const override { return bus_type_t::bus_stream; } + + bool init(void) override {return true;} + void release(void) override {} + + void beginTransaction(void) override {} + void endTransaction(void) override {} + void wait(void) override {} + bool busy(void) const override {return false;} + + void flush(void) override {} + bool writeCommand(uint32_t data, uint_fast8_t bit_length) override {return false;} + void writeData(uint32_t data, uint_fast8_t bit_length) override; + void writeDataRepeat(uint32_t data, uint_fast8_t bit_length, uint32_t count) override; + void writePixels(pixelcopy_t* param, uint32_t length) override; + void writeBytes(const uint8_t* data, uint32_t length, bool dc, bool use_dma) override { writeBytes(data, length); } + + void initDMA(void) override {} + void addDMAQueue(const uint8_t* data, uint32_t length) override { writeBytes(data, length); } + void execDMAQueue(void) {} + uint8_t* getDMABuffer(uint32_t length) override { return _flip_buffer.getBuffer(length); } + + void beginRead(void) override {} + void endRead(void) override {} + uint32_t readData(uint_fast8_t bit_length) override; + bool readBytes(uint8_t* dst, uint32_t length, bool use_dma) override; + void readPixels(void* dst, pixelcopy_t* param, uint32_t length) override; + + private: + void writeBytes(const uint8_t* data, uint32_t length); + config_t _cfg; + SimpleBuffer _flip_buffer; + + }; + +//---------------------------------------------------------------------------- + } +} diff --git a/src/lgfx/v1/platforms/portduino/common.cpp b/src/lgfx/v1/platforms/portduino/common.cpp new file mode 100644 index 00000000..81a8e70e --- /dev/null +++ b/src/lgfx/v1/platforms/portduino/common.cpp @@ -0,0 +1,205 @@ +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#if defined (ESP_PLATFORM) +#elif defined (ESP8266) +#elif defined (__SAMD21__) || defined(__SAMD21G18A__) || defined(__SAMD21J18A__) || defined(__SAMD21E17A__) || defined(__SAMD21E18A__) +#elif defined (__SAMD51__) +#elif defined (STM32F2xx) || defined (STM32F4xx) || defined (STM32F7xx) +#elif defined (ARDUINO_ARCH_SPRESENSE) +#elif defined (ARDUINO_ARCH_MBED_RP2040) || defined(ARDUINO_ARCH_RP2040) +#elif defined (PORTDUINO_LINUX_HARDWARE) + +#include "common.hpp" + +namespace lgfx +{ + inline namespace v1 + { +//---------------------------------------------------------------------------- + + void pinMode(int_fast16_t pin, pin_mode_t mode) + { + switch (mode) + { + case pin_mode_t::output: + ::pinMode(pin, OUTPUT); + break; + +#if defined (INPUT_PULLUP) + case pin_mode_t::input_pullup: + ::pinMode(pin, INPUT_PULLUP); + break; +#endif +#if defined (INPUT_PULLDOWN) + case pin_mode_t::input_pulldown: + ::pinMode(pin, INPUT_PULLDOWN); + break; +#endif +#if defined (INPUT_PULLDOWN_16) + case pin_mode_t::input_pulldown: + ::pinMode(pin, INPUT_PULLDOWN_16); + break; +#endif + + default: + ::pinMode(pin, INPUT); + break; + } + } + +//---------------------------------------------------------------------------- + + namespace spi + { + HardwareSPI *SPI_dev = &SPI; + cpp::result init(int spi_host, int spi_sclk, int spi_miso, int spi_mosi) { + cpp::result res = {}; + char x = (spi_host & (1 << 4) - 1) + '0'; + char y = (spi_host >> 4) + '0'; + SPI_dev = new HardwareSPI(); + std::string spiString = "/dev/spidev"; + spiString += x; + spiString += "."; + spiString += y; + SPI_dev->begin(spiString.c_str()); + return res; } + void release(int spi_host) {} + void beginTransaction(int spi_host, uint32_t freq, int spi_mode) { + SPISettings setting(freq, MSBFIRST, SPI_MODE0); + SPI_dev->beginTransaction(setting); + } + void endTransaction(int spi_host) { SPI_dev->endTransaction();} + void writeBytes(int spi_host, const uint8_t* data, size_t length) {} + void readBytes(int spi_host, uint8_t* data, size_t length) { + SPI_dev->transfer(data, length); + } } + +//---------------------------------------------------------------------------- + + + namespace i2c + { +#ifdef TwoWire_h + cpp::result init(int i2c_port, int pin_sda, int pin_scl) { Wire.begin(); return {};} + cpp::result release(int i2c_port) { Wire.end(); return {};} + cpp::result restart(int i2c_port, int i2c_addr, uint32_t freq, bool read) { Wire.endTransmission(true); Wire.beginTransmission(i2c_addr); return {};} + cpp::result beginTransaction(int i2c_port, int i2c_addr, uint32_t freq, bool read) { Wire.beginTransmission(i2c_addr); return {};} + cpp::result endTransaction(int i2c_port) { Wire.endTransmission(true); return {};} + cpp::result writeBytes(int i2c_port, const uint8_t *data, size_t length) { Wire.write(data, length); return {};} + cpp::result 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 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 transactionWrite(int i2c_port, int addr, const uint8_t *writedata, uint8_t writelen, uint32_t freq) { + cpp::result 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 transactionRead(int i2c_port, int addr, uint8_t *readdata, uint8_t readlen, uint32_t freq) { + cpp::result 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 transactionWriteRead(int i2c_port, int addr, const uint8_t *writedata, uint8_t writelen, uint8_t *readdata, size_t readlen, uint32_t freq) { + cpp::result 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 readRegister8(int i2c_port, int addr, uint8_t reg, uint32_t freq) { + auto res = transactionWriteRead(i2c_port, addr, ®, 1, ®, 1, freq); + if (res.has_value()) + { + return reg; + } + return cpp::fail(res.error()); + } + + cpp::result 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, ®, 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 init(int i2c_port, int pin_sda, int pin_scl) { return cpp::fail(error_t::unknown_err); } + cpp::result release(int i2c_port) { return cpp::fail(error_t::unknown_err); } + cpp::result restart(int i2c_port, int i2c_addr, uint32_t freq, bool read) { return cpp::fail(error_t::unknown_err); } + cpp::result beginTransaction(int i2c_port, int i2c_addr, uint32_t freq, bool read) { return cpp::fail(error_t::unknown_err); } + cpp::result endTransaction(int i2c_port) { return cpp::fail(error_t::unknown_err); } + cpp::result writeBytes(int i2c_port, const uint8_t *data, size_t length) { return cpp::fail(error_t::unknown_err); } + cpp::result readBytes(int i2c_port, uint8_t *data, size_t length) { return cpp::fail(error_t::unknown_err); } + cpp::result readBytes(int i2c_port, uint8_t *data, size_t length, bool last_nack) { return cpp::fail(error_t::unknown_err); } + +//-------- + + cpp::result transactionWrite(int i2c_port, int addr, const uint8_t *writedata, uint8_t writelen, uint32_t freq) { return cpp::fail(error_t::unknown_err); } + cpp::result transactionRead(int i2c_port, int addr, uint8_t *readdata, uint8_t readlen, uint32_t freq) { return cpp::fail(error_t::unknown_err); } + cpp::result transactionWriteRead(int i2c_port, int addr, const uint8_t *writedata, uint8_t writelen, uint8_t *readdata, size_t readlen, uint32_t freq) { return cpp::fail(error_t::unknown_err); } + + cpp::result readRegister8(int i2c_port, int addr, uint8_t reg, uint32_t freq) { return cpp::fail(error_t::unknown_err); } + cpp::result 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 + } + +//---------------------------------------------------------------------------- + } +} + +#endif diff --git a/src/lgfx/v1/platforms/portduino/common.hpp b/src/lgfx/v1/platforms/portduino/common.hpp new file mode 100644 index 00000000..f0dc6d46 --- /dev/null +++ b/src/lgfx/v1/platforms/portduino/common.hpp @@ -0,0 +1,177 @@ +/*----------------------------------------------------------------------------/ + Lovyan GFX - Graphics library for embedded devices. + +Original Source: + https://github.com/lovyan03/LovyanGFX/ + +Licence: + [FreeBSD](https://github.com/lovyan03/LovyanGFX/blob/master/license.txt) + +Author: + [lovyan03](https://twitter.com/lovyan03) + +Contributors: + [ciniml](https://github.com/ciniml) + [mongonta0716](https://github.com/mongonta0716) + [tobozo](https://github.com/tobozo) +/----------------------------------------------------------------------------*/ +#pragma once + +#include "../../misc/DataWrapper.hpp" +#include "../../misc/enum.hpp" +#include "../../../utility/result.hpp" + +#if defined ( CONFIG_ARCH_BOARD_SPRESENSE ) +#include +#else +#include +#endif + +#include + +namespace lgfx +{ + inline namespace v1 + { +//---------------------------------------------------------------------------- + + __attribute__ ((unused)) + static inline unsigned long millis(void) + { + return ::millis(); + } + __attribute__ ((unused)) + static inline unsigned long micros(void) + { + return ::micros(); + } + __attribute__ ((unused)) + static inline void delay(unsigned long milliseconds) + { + ::delay(milliseconds); + } + __attribute__ ((unused)) + static void delayMicroseconds(unsigned int us) + { + ::delayMicroseconds(us); + } + + static inline void* heap_alloc( size_t length) { return malloc(length); } + static inline void* heap_alloc_psram(size_t length) { return malloc(length); } + static inline void* heap_alloc_dma( size_t length) { return malloc(length); } // aligned_alloc(16, length); + static inline void heap_free(void* buf) { free(buf); } + + static inline void gpio_hi(uint32_t pin) { digitalWrite(pin, HIGH); } + static inline void gpio_lo(uint32_t pin) { digitalWrite(pin, LOW); } + static inline bool gpio_in(uint32_t pin) { return digitalRead(pin); } + + enum pin_mode_t + { output + , input + , input_pullup + , input_pulldown + }; + + void pinMode(int_fast16_t pin, pin_mode_t mode); + inline void lgfxPinMode(int_fast16_t pin, pin_mode_t mode) + { + pinMode(pin, mode); + } + +//---------------------------------------------------------------------------- + struct FileWrapper : public DataWrapper + { + FileWrapper() : DataWrapper() { need_transaction = true; } + +#if defined (ARDUINO) && defined (__SEEED_FS__) + + fs::File _file; + fs::File *_fp; + + fs::FS *_fs = nullptr; + void setFS(fs::FS& fs) { + _fs = &fs; + need_transaction = false; + } + FileWrapper(fs::FS& fs) : DataWrapper(), _fp(nullptr) { setFS(fs); } + FileWrapper(fs::FS& fs, fs::File* fp) : DataWrapper(), _fp(fp) { setFS(fs); } + + bool open(fs::FS& fs, const char* path) { + setFS(fs); + return open(path); + } + + bool open(const char* path) override { + fs::File file = _fs->open(path, "r"); + // この邪悪なmemcpyは、Seeed_FSのFile実装が所有権moveを提供してくれないのにデストラクタでcloseを呼ぶ実装になっているため、; + // 正攻法ではFileをクラスメンバに保持できない状況を打開すべく応急処置的に実装したものです。; + memcpy(&_file, &file, sizeof(fs::File)); + // memsetにより一時変数の中身を吹っ飛ばし、デストラクタによるcloseを予防します。; + memset(&file, 0, sizeof(fs::File)); + _fp = &_file; + return _file; + } + + int read(uint8_t *buf, uint32_t len) override { return _fp->read(buf, len); } + void skip(int32_t offset) override { seek(offset, SeekCur); } + bool seek(uint32_t offset) override { return seek(offset, SeekSet); } + bool seek(uint32_t offset, SeekMode mode) { return _fp->seek(offset, mode); } + void close() override { _fp->close(); } + int32_t tell(void) override { return _fp->position(); } + +#else // dummy. + + bool open(const char*) override { return false; } + int read(uint8_t*, uint32_t) override { return 0; } + void skip(int32_t) override { } + bool seek(uint32_t) override { return false; } + bool seek(uint32_t, int) { return false; } + void close() override { } + int32_t tell(void) override { return 0; } + +#endif + + }; + +//---------------------------------------------------------------------------- + +#if defined (ARDUINO) && defined (Stream_h) + + struct StreamWrapper : public DataWrapper + { + void set(Stream* src, uint32_t length = ~0u) { _stream = src; _length = length; _index = 0; } + + int read(uint8_t *buf, uint32_t len) override { + if (len > _length - _index) { len = _length - _index; } + _index += len; + return _stream->readBytes((char*)buf, len); + } + void skip(int32_t offset) override + { + if (0 >= offset) { return; } + _index += offset; + char dummy[64]; + size_t len = ((offset - 1) & 63) + 1; + do + { + _stream->readBytes(dummy, len); + offset -= len; + len = 64; + } while (offset); + } + bool seek(uint32_t offset) override { if (offset < _index) { return false; } skip(offset - _index); return true; } + void close() override { } + int32_t tell(void) override { return _index; } + + private: + Stream* _stream; + uint32_t _index; + uint32_t _length = 0; + + }; + +#endif + +//---------------------------------------------------------------------------- + } +}