summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/driver/pervasive_aurora_mb.h28
-rw-r--r--src/driver/Kconfig4
-rw-r--r--src/driver/pervasive_aurora_mb.cc126
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 &copy);
+ 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, &reg, 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;