diff options
-rw-r--r-- | include/driver/pervasive_aurora_mb.h | 28 | ||||
-rw-r--r-- | src/driver/Kconfig | 4 | ||||
-rw-r--r-- | src/driver/pervasive_aurora_mb.cc | 126 |
3 files changed, 158 insertions, 0 deletions
diff --git a/include/driver/pervasive_aurora_mb.h b/include/driver/pervasive_aurora_mb.h new file mode 100644 index 0000000..8e34501 --- /dev/null +++ b/include/driver/pervasive_aurora_mb.h @@ -0,0 +1,28 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Driver for Pervasive Aurora Mb E-Paper displays with internal Timing + * Controller (iTC). Configured for the 300x400px 4.2" variant. + */ +#pragma once + +class PervasiveAuroraMb { + private: + PervasiveAuroraMb(const PervasiveAuroraMb ©); + bool isBusy(); + void spiWrite(unsigned char reg, const unsigned char *txbuf, unsigned int length); + + public: + PervasiveAuroraMb() {} + + void setup(); + void powerOn(); + void initialize(signed char temperature = 20); + void sendImage(unsigned char *frame); + void sendUpdate(); + void powerOff(); +}; + +extern PervasiveAuroraMb pervasiveAuroraMb; diff --git a/src/driver/Kconfig b/src/driver/Kconfig index 3c96d9e..b2d57e9 100644 --- a/src/driver/Kconfig +++ b/src/driver/Kconfig @@ -72,6 +72,10 @@ config driver_nrf24l01 bool "nRF24L01+ 2.4GHz Radio" depends on meta_driver_spi +config driver_pervasive_aurora_mb +bool "Pervasive Aurora Mb" +depends on ( arch_msp430fr5969lp || arch_msp430fr5994lp ) && meta_driver_spi + # resistive_load is AEMR-specific and not included in Kconfig # s5851a is broken and incomplete diff --git a/src/driver/pervasive_aurora_mb.cc b/src/driver/pervasive_aurora_mb.cc new file mode 100644 index 0000000..c244a72 --- /dev/null +++ b/src/driver/pervasive_aurora_mb.cc @@ -0,0 +1,126 @@ +/* + * Copyright 2021 Daniel Friesel + * + * SPDX-License-Identifier: BSD-2-Clause + * + * Driver for Pervasive Aurora Mb E-Paper displays with internal Timing + * Controller (iTC). Configured for the 300x400px 4.2" variant. + */ +#include "driver/pervasive_aurora_mb.h" +#include "driver/spi.h" +#include "driver/gpio.h" +#include "arch.h" + +void PervasiveAuroraMb::setup() +{ + gpio.output(PERVASIVE_AURORA_RESET_PIN, 0); + gpio.output(PERVASIVE_AURORA_CS_PIN, 0); + gpio.output(PERVASIVE_AURORA_DC_PIN, 0); + gpio.output(PERVASIVE_AURORA_VCC_PIN, 0); + gpio.input(PERVASIVE_AURORA_BUSY_PIN); +} + +void PervasiveAuroraMb::powerOn() +{ + gpio.write(PERVASIVE_AURORA_VCC_PIN, 1); + arch.delay_ms(5); + gpio.write(PERVASIVE_AURORA_RESET_PIN, 1); + arch.delay_ms(1); + gpio.write(PERVASIVE_AURORA_CS_PIN, 1); +} + +void PervasiveAuroraMb::initialize(signed char temperature) +{ + // "Input Temperature" + spiWrite(0xe5, (const unsigned char*)&temperature, 1); + + // "Active Temperature" + spiWrite(0xe0, (const unsigned char[]){0x02}, 1); + + // "Panel Settings" + spiWrite(0x00, (const unsigned char[]){0x0f}, 1); + + // "Panel Settings" + spiWrite(0x00, (const unsigned char[]){0x0f}, 1); + + // "Booster soft start settings" + spiWrite(0x06, (const unsigned char[]){0x17, 0x17, 0x27}, 3); + + // "Resolution settings": 300 x 400 -> 0x12c x 0x190 + spiWrite(0x61, (const unsigned char[]){0x01, 0x90, 0x01, 0x2c}, 4); + + // "Vcom and data interval setting" + spiWrite(0x50, (const unsigned char[]){0x87}, 1); + + // "Power Saving" + spiWrite(0xe3, (const unsigned char[]){0x88}, 1); +} + +void PervasiveAuroraMb::sendImage(unsigned char *frame) +{ + unsigned char null_int[2] = {0x00, 0x00}; + spiWrite(0x10, 0, 0); + + gpio.write(PERVASIVE_AURORA_CS_PIN, 0); + spi.xmit(300*(400/8), frame, 0, frame); + gpio.write(PERVASIVE_AURORA_CS_PIN, 1); + + /* + * Second Pass: All zeroes (-> update entire display). + * A 1 bit indicates that the corresponding pixel should be skipped. + */ + spiWrite(0x13, 0, 0); + gpio.write(PERVASIVE_AURORA_CS_PIN, 0); + for (unsigned int i = 0; i < 300*(400/16); i++) { + spi.xmit(2, null_int, 0, frame); + } + gpio.write(PERVASIVE_AURORA_CS_PIN, 1); +} + +void PervasiveAuroraMb::sendUpdate() +{ + while (isBusy()) ; + + spiWrite(0x04, 0, 0); + + while (isBusy()) ; + + spiWrite(0x12, 0, 0); + + while (isBusy()) ; +} + +void PervasiveAuroraMb::powerOff() +{ + spiWrite(0x02, 0, 0); + while (isBusy()) ; + gpio.output(PERVASIVE_AURORA_RESET_PIN, 0); + gpio.output(PERVASIVE_AURORA_CS_PIN, 0); + gpio.output(PERVASIVE_AURORA_DC_PIN, 0); + gpio.output(PERVASIVE_AURORA_VCC_PIN, 0); +} + +bool PervasiveAuroraMb::isBusy() +{ + return !gpio.read(PERVASIVE_AURORA_BUSY_PIN); +} + +void PervasiveAuroraMb::spiWrite(unsigned char reg, const unsigned char *txbuf, unsigned int length) +{ + gpio.write(PERVASIVE_AURORA_DC_PIN, 0); + gpio.write(PERVASIVE_AURORA_CS_PIN, 0); + + spi.xmit(1, ®, 0, 0); + + gpio.write(PERVASIVE_AURORA_CS_PIN, 1); + gpio.write(PERVASIVE_AURORA_DC_PIN, 1); + + if (length) { + arch.delay_us(1); + gpio.write(PERVASIVE_AURORA_CS_PIN, 0); + spi.xmit(length, (unsigned char*)txbuf, 0, 0); + gpio.write(PERVASIVE_AURORA_CS_PIN, 1); + } +} + +PervasiveAuroraMb pervasiveAuroraMb; |