From b109908d282c10d7aa07adf2e7926e5eae9fbccf Mon Sep 17 00:00:00 2001 From: Scott Allen Date: Sat, 26 Jul 2014 20:19:17 -0400 Subject: [PATCH 1/6] Fast SPI pin changes - added defines to map ports and bits for RESET, DC and SS. - added macros to quickly control RESET, DC and SS using the internal weak pullup for high. --- MicroView.h | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/MicroView.h b/MicroView.h index 4b35a31..6fe37e6 100644 --- a/MicroView.h +++ b/MicroView.h @@ -24,15 +24,36 @@ #define swap(a, b) { uint8_t t = a; a = b; b = t; } +#define OLEDPWR 4 // 3.3V regulator enable + #define DC 8 +#define DCPORT PORTB +#define DCDDR DDRB +#define DCBIT 0 + #define RESET 7 -#define OLEDPWR 4 +#define RESETPORT PORTD +#define RESETDDR DDRD +#define RESETBIT 7 + +#define SSPORT PORTB +#define SSDDR DDRB +#define SSBIT 2 + +#define DCHIGH ((DCPORT |= _BV(DCBIT)), (DCDDR &= ~_BV(DCBIT))) +#define DCLOW ((DCPORT &= ~_BV(DCBIT)), (DCDDR |= _BV(DCBIT))) + +#define RESETHIGH ((RESETPORT |= _BV(RESETBIT)), (RESETDDR &= ~_BV(RESETBIT))) +#define RESETLOW ((RESETPORT &= ~_BV(RESETBIT)), (RESETDDR |= _BV(RESETBIT))) // SS, SCK, MOSI already defined by original pins_arduino.h //#define CS 10 //#define SCK 13 //#define MOSI 11 +#define SSHIGH ((SSPORT |= _BV(SSBIT)), (SSDDR &= ~_BV(SSBIT))) +#define SSLOW ((SSPORT &= ~_BV(SSBIT)), (SSDDR |= _BV(SSBIT))) + #define BLACK 0 #define WHITE 1 From fa09bdd7aae4fe78798ae8d3c51e4a884b9bd23d Mon Sep 17 00:00:00 2001 From: Scott Allen Date: Sun, 27 Jul 2014 16:04:21 -0400 Subject: [PATCH 2/6] Eliminate compiler warnings - Fixed use of = instead of == in "if" statment. - Fixed uninitialised count variable in "for" loop. - Removed unused variables. - Replaced line splice characters (backslash) at end of comments. --- MicroView.cpp | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/MicroView.cpp b/MicroView.cpp index 6a12b4c..6212a58 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -60,18 +60,18 @@ Page buffer is required because in SPI mode, the host cannot read the SSD1306's static uint8_t screenmemory [] = { // LCD Memory organised in 64 horizontal pixel and 6 rows of byte // B B .............B ----- - // y y .............y \ - // t t .............t \ - // e e .............e \ - // 0 1 .............63 \ - // \ - // D0 D0.............D0 \ - // D1 D1.............D1 / ROW 0 - // D2 D2.............D2 / - // D3 D3.............D3 / - // D4 D4.............D4 / - // D5 D5.............D5 / - // D6 D6.............D6 / + // y y .............y | + // t t .............t | + // e e .............e | + // 0 1 .............63 | + // | + // D0 D0.............D0 | ROW 0 + // D1 D1.............D1 | + // D2 D2.............D2 | + // D3 D3.............D3 | + // D4 D4.............D4 | + // D5 D5.............D5 | + // D6 D6.............D6 | // D7 D7.............D7 ---- //SparkFun Electronics LOGO @@ -955,7 +955,7 @@ size_t MicroView::write(uint8_t c) { Serial.println(serCmd[2]); pixel(serCmd[1],serCmd[2]); display(); - } else if (cmdCount=4) { + } else if (cmdCount==4) { Serial.print("pixel "); Serial.print(serCmd[1]); Serial.print(" "); @@ -1269,7 +1269,7 @@ size_t MicroView::write(uint8_t c) { temp=atoi(result); serCmd[index]=(uint8_t)temp & 0xff; // we only need 8 bit number index++; - for (uint8_t i;i Date: Wed, 30 Jul 2014 19:28:39 -0400 Subject: [PATCH 3/6] Help further reduce overdriving display inputs (and fixed a few spelling errors in comments) - Use fast pin change macros for RESET, SS and DC. - Implement MVSPI.packetBegin() and MVSPI.packetEnd() to allow sending multiple byte "packets" while SS remains enabled. - Add 2 and 3 byte command() functions to send multiple command bytes in one packet. - Modify clear() and display() functions to send commands and data in packets. - Do the "wait for SPI transfer complete" just before sending the next byte (plus after the last or only byte) in a packet, so code can be executed while bytes are being sent. - Disable SPI mode when not transmitting, so MOSI (and SCK) will go low. - Keep DC low except when sending data bytes. - Change MVSPI.transfer() to void since nothing can be received from the display. --- MicroView.cpp | 266 ++++++++++++++++++++++++++------------------------ MicroView.h | 43 +++++--- 2 files changed, 167 insertions(+), 142 deletions(-) diff --git a/MicroView.cpp b/MicroView.cpp index 6212a58..a7ed534 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -123,119 +123,99 @@ void MicroView::begin() { setColor(WHITE); setDrawMode(NORM); setCursor(0,0); + + RESETLOW; + // Enable 3.3V power to the display pinMode(OLEDPWR, OUTPUT); digitalWrite(OLEDPWR,HIGH); - // Setting up SPI pins - pinMode(MOSI, OUTPUT); - pinMode(SCK, OUTPUT); - - //pinMode(DC, OUTPUT); - pinMode(RESET, OUTPUT); - pinMode(SS, INPUT); - digitalWrite(SS, HIGH); - - ssport = portOutputRegister(digitalPinToPort(SS)); - sspinmask = digitalPinToBitMask(SS); - ssreg = portModeRegister(digitalPinToPort(SS)); - - dcport = portOutputRegister(digitalPinToPort(DC)); - dcpinmask = digitalPinToBitMask(DC); - dcreg = portModeRegister(digitalPinToPort(DC)); - - digitalWrite(RESET, HIGH); - // VDD (3.3V) goes high at start, lets just chill for 5 ms + + // Give some time for power to stabilise + delay(10); + + RESETHIGH; delay(5); - // bring reset low - digitalWrite(RESET, LOW); - + RESETLOW; + // Setup SPI frequency MVSPI.setClockDivider(SPI_CLOCK_DIV2); + // Initialise SPI MVSPI.begin(); - - // wait 10ms - delay(10); + + delay(5); + // bring out of reset - pinMode(RESET,INPUT_PULLUP); - //digitalWrite(RESET, HIGH); + RESETHIGH; + + delay(10); // Init sequence for 64x48 OLED module - command(DISPLAYOFF); // 0xAE - - command(SETDISPLAYCLOCKDIV); // 0xD5 - command(0x80); // the suggested ratio 0x80 - - command(SETMULTIPLEX); // 0xA8 - command(0x2F); - - command(SETDISPLAYOFFSET); // 0xD3 - command(0x0); // no offset - - command(SETSTARTLINE | 0x0); // line #0 - - command(CHARGEPUMP); // enable charge pump - command(0x14); - - command(NORMALDISPLAY); // 0xA6 - command(DISPLAYALLONRESUME); // 0xA4 - + command(DISPLAYOFF); // 0xAE + command(SETDISPLAYCLOCKDIV, 0x80); // 0xD5 / the suggested ratio 0x80 + command(SETMULTIPLEX, 0x2F); // 0xA8 + command(SETDISPLAYOFFSET, 0x0); // 0xD3 / no offset + command(SETSTARTLINE | 0x0); // line #0 + command(CHARGEPUMP, 0x14); // enable charge pump + command(NORMALDISPLAY); // 0xA6 + command(DISPLAYALLONRESUME); // 0xA4 command(SEGREMAP | 0x1); command(COMSCANDEC); + command(SETCOMPINS, 0x12); // 0xDA + command(SETCONTRAST, 0x8F); // 0x81 + command(SETPRECHARGE, 0xF1); // 0xd9 + command(SETVCOMDESELECT, 0x40); // 0xDB + command(DISPLAYON); //--turn on oled panel - command(SETCOMPINS); // 0xDA - command(0x12); + clear(ALL); // Erase hardware memory inside the OLED controller to avoid random data in memory. - command(SETCONTRAST); // 0x81 - command(0x8F); - - command(SETPRECHARGE); // 0xd9 - command(0xF1); - - command(SETVCOMDESELECT); // 0xDB - command(0x40); - - command(DISPLAYON); //--turn on oled panel - clear(ALL); // Erase hardware memory inside the OLED controller to avoid random data in memory. Serial.begin(115200); } -/** \brief SPI command. - - Setup DC and SS pins, then send command via SPI to SSD1306 controller. +/** \brief Send 1 command byte. + + Send 1 command byte via SPI to SSD1306 controller. */ void MicroView::command(uint8_t c) { - // Hardware SPI - *dcreg |= dcpinmask; // Set DC pin to OUTPUT - *dcport &= ~dcpinmask; // DC pin LOW - - *ssreg |= sspinmask; // Set SS pin to OUTPUT - *ssport &= ~sspinmask; // SS LOW - + MVSPI.packetBegin(); MVSPI.transfer(c); + MVSPI.packetEnd(); +} - *ssport |= sspinmask; // SS HIGH - *ssreg &= ~sspinmask; // Set SS pin to INPUT - - *dcreg &= ~dcpinmask; // Set DC to INPUT to avoid high voltage over driving the OLED logic +/** \brief Send 2 command bytes. + + Send 2 command bytes via SPI to SSD1306 controller. +*/ +void MicroView::command(uint8_t c1, uint8_t c2) { + MVSPI.packetBegin(); + MVSPI.transfer(c1); + MVSPI.wait(); + MVSPI.transfer(c2); + MVSPI.packetEnd(); +} + +/** \brief Send 3 command bytes. + + Send 3 command bytes via SPI to SSD1306 controller. +*/ +void MicroView::command(uint8_t c1, uint8_t c2, uint8_t c3) { + MVSPI.packetBegin(); + MVSPI.transfer(c1); + MVSPI.wait(); + MVSPI.transfer(c2); + MVSPI.wait(); + MVSPI.transfer(c3); + MVSPI.packetEnd(); } /** \brief SPI data. - Setup DC and SS pins, then send data via SPI to SSD1306 controller. + Send 1 data byte via SPI to SSD1306 controller. */ void MicroView::data(uint8_t c) { - // Hardware SPI - *dcport |= dcpinmask; // DC HIGH - - *ssreg |= sspinmask; // Set SS pin to OUTPUT - *ssport &= ~sspinmask; // SS LOW - + MVSPI.packetBegin(); + DCHIGH; MVSPI.transfer(c); - - *ssport |= sspinmask; // SS HIGH - *ssreg &= ~sspinmask; // Set SS pin to INPUT - - *dcreg &= ~dcpinmask; // Set DC to INPUT to avoid high voltage over driving the OLED logic + MVSPI.packetEnd(); } /** \brief Set SSD1306 page address. @@ -243,8 +223,7 @@ void MicroView::data(uint8_t c) { Send page address command and address to the SSD1306 OLED controller. */ void MicroView::setPageAddress(uint8_t add) { - add=0xb0|add; - command(add); + command(SETPAGE|add); return; } @@ -253,8 +232,7 @@ void MicroView::setPageAddress(uint8_t add) { Send column address command and address to the SSD1306 OLED controller. */ void MicroView::setColumnAddress(uint8_t add) { - command((0x10|(add>>4))+0x02); - command((0x0f&add)); + command((SETHIGHCOLUMN|(add>>4))+0x02, SETLOWCOLUMN|(0x0f&add)); return; } @@ -268,9 +246,14 @@ void MicroView::clear(uint8_t mode) { for (int i=0;i<8; i++) { setPageAddress(i); setColumnAddress(0); - for (int j=0; j<0x80; j++) { - data(0); + MVSPI.packetBegin(); + DCHIGH; + MVSPI.transfer(0); + for (int j=1; j<0x80; j++) { + MVSPI.wait(); + MVSPI.transfer(0); } + MVSPI.packetEnd(); } } else @@ -290,9 +273,14 @@ void MicroView::clear(uint8_t mode, uint8_t c) { for (int i=0;i<8; i++) { setPageAddress(i); setColumnAddress(0); - for (int j=0; j<0x80; j++) { - data(c); + MVSPI.packetBegin(); + DCHIGH; + MVSPI.transfer(c); + for (int j=1; j<0x80; j++) { + MVSPI.wait(); + MVSPI.transfer(c); } + MVSPI.packetEnd(); } } else @@ -315,11 +303,10 @@ void MicroView::invert(boolean inv) { /** \brief Set contrast. - OLED contract value from 0 to 255. Note: Contrast level is not very obvious. + OLED contrast value from 0 to 255. Note: Contrast level is not very obvious. */ void MicroView::contrast(uint8_t contrast) { - command(SETCONTRAST); // 0x81 - command(contrast); + command(SETCONTRAST, contrast); // 0x81 } /** \brief Transfer display memory. @@ -332,9 +319,14 @@ void MicroView::display(void) { for (i=0; i<6; i++) { setPageAddress(i); setColumnAddress(0); - for (j=0;j<0x40;j++) { - data(screenmemory[i*0x40+j]); + MVSPI.packetBegin(); + DCHIGH; + MVSPI.transfer(screenmemory[i*0x40]); + for (j=1;j<0x40;j++) { + MVSPI.wait(); + MVSPI.transfer(screenmemory[i*0x40+j]); } + MVSPI.packetEnd(); } } @@ -847,14 +839,9 @@ size_t MicroView::write(uint8_t c) { if (stop Date: Thu, 31 Jul 2014 16:43:25 -0400 Subject: [PATCH 4/6] Added uView.end() to power off the display. In uView.begin() don't send commands that default to desired values. --- MicroView.cpp | 42 ++++++++++++++++++++++++++++++++---------- MicroView.h | 1 + 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/MicroView.cpp b/MicroView.cpp index a7ed534..b3b123f 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -128,7 +128,7 @@ void MicroView::begin() { // Enable 3.3V power to the display pinMode(OLEDPWR, OUTPUT); - digitalWrite(OLEDPWR,HIGH); + digitalWrite(OLEDPWR, HIGH); // Give some time for power to stabilise delay(10); @@ -150,19 +150,19 @@ void MicroView::begin() { delay(10); // Init sequence for 64x48 OLED module - command(DISPLAYOFF); // 0xAE - command(SETDISPLAYCLOCKDIV, 0x80); // 0xD5 / the suggested ratio 0x80 +// command(DISPLAYOFF); // 0xAE +// command(SETDISPLAYCLOCKDIV, 0x80); // 0xD5 / the suggested ratio 0x80 command(SETMULTIPLEX, 0x2F); // 0xA8 - command(SETDISPLAYOFFSET, 0x0); // 0xD3 / no offset - command(SETSTARTLINE | 0x0); // line #0 - command(CHARGEPUMP, 0x14); // enable charge pump - command(NORMALDISPLAY); // 0xA6 - command(DISPLAYALLONRESUME); // 0xA4 +// command(SETDISPLAYOFFSET, 0x0); // 0xD3 / no offset +// command(SETSTARTLINE | 0x0); // 0x40 / line #0 + command(CHARGEPUMP, 0x14); // 0x8D / enable charge pump +// command(NORMALDISPLAY); // 0xA6 +// command(DISPLAYALLONRESUME); // 0xA4 command(SEGREMAP | 0x1); command(COMSCANDEC); - command(SETCOMPINS, 0x12); // 0xDA +// command(SETCOMPINS, 0x12); // 0xDA command(SETCONTRAST, 0x8F); // 0x81 - command(SETPRECHARGE, 0xF1); // 0xd9 + command(SETPRECHARGE, 0xF1); // 0xD9 command(SETVCOMDESELECT, 0x40); // 0xDB command(DISPLAYON); //--turn on oled panel @@ -171,6 +171,23 @@ void MicroView::begin() { Serial.begin(115200); } +/** \brief Power off the OLED display. + + Reset display control signals and + prepare the SSD1306 controller for power off, + then power off the 3.3V regulator. +*/ +void MicroView::end() { + DCLOW; // Just in case + command(DISPLAYOFF); + command(CHARGEPUMP, 0x10); // Disable the charge pump + delay(150); // Wait for charge pump off + RESETLOW; + SSLOW; + MVSPI.end(); // Disable SPI mode + digitalWrite(OLEDPWR, LOW); // Power off the 3.3V regulator +} + /** \brief Send 1 command byte. Send 1 command byte via SPI to SSD1306 controller. @@ -1652,6 +1669,11 @@ size_t MicroView::write(uint8_t c) { /** \brief End SPI. */ void MVSPIClass::end() { SPCR &= ~_BV(SPE); + // SCK and MOSI should already be low but set them again, to be sure. + digitalWrite(SCK, LOW); + digitalWrite(MOSI, LOW); + pinMode(SCK, OUTPUT); + pinMode(MOSI, OUTPUT); } /** \brief Set up SPI for transmitting diff --git a/MicroView.h b/MicroView.h index 1129158..59abb9c 100644 --- a/MicroView.h +++ b/MicroView.h @@ -134,6 +134,7 @@ class MicroView : public Print{ public: MicroView(void) {}; void begin(void); + void end(void); //#if ARDUINO >= 100 From 9c5568418ab14326672c6951010eac33b5743394 Mon Sep 17 00:00:00 2001 From: Scott Allen Date: Thu, 31 Jul 2014 22:37:58 -0400 Subject: [PATCH 5/6] Improve speed of display() and clear() functions by using horizontal addressing mode. --- MicroView.cpp | 78 +++++++++++++++++++++++++++------------------------ MicroView.h | 8 ++++++ 2 files changed, 49 insertions(+), 37 deletions(-) diff --git a/MicroView.cpp b/MicroView.cpp index b3b123f..10488fd 100644 --- a/MicroView.cpp +++ b/MicroView.cpp @@ -258,24 +258,25 @@ void MicroView::setColumnAddress(uint8_t add) { To clear GDRAM inside the LCD controller, pass in the variable mode = ALL and to clear screen page buffer pass in the variable mode = PAGE. */ void MicroView::clear(uint8_t mode) { - // uint8_t page=6, col=0x40; if (mode==ALL) { - for (int i=0;i<8; i++) { - setPageAddress(i); - setColumnAddress(0); - MVSPI.packetBegin(); - DCHIGH; + command(SETADDRESSMODE, 0); // Set horizontal addressing mode + command(SETCOLUMNBOUNDS, 0, LCDTOTALWIDTH - 1); // Set width + command(SETPAGEBOUNDS, 0, LCDTOTALPAGES - 1); // Set height + + MVSPI.packetBegin(); + DCHIGH; + MVSPI.transfer(0); + for (int i = 1; i < LCDTOTALWIDTH * LCDTOTALPAGES; i++) { + MVSPI.wait(); MVSPI.transfer(0); - for (int j=1; j<0x80; j++) { - MVSPI.wait(); - MVSPI.transfer(0); - } - MVSPI.packetEnd(); } + MVSPI.packetEnd(); + + command(SETADDRESSMODE, 2); // Return display to page addressing mode } else { - memset(screenmemory,0,384); // (64 x 48) / 8 = 384 + memset(screenmemory, 0, LCDWIDTH * LCDPAGES); //display(); } } @@ -285,24 +286,25 @@ void MicroView::clear(uint8_t mode) { To clear GDRAM inside the LCD controller, pass in the variable mode = ALL with c character and to clear screen page buffer, pass in the variable mode = PAGE with c character. */ void MicroView::clear(uint8_t mode, uint8_t c) { - //uint8_t page=6, col=0x40; if (mode==ALL) { - for (int i=0;i<8; i++) { - setPageAddress(i); - setColumnAddress(0); - MVSPI.packetBegin(); - DCHIGH; + command(SETADDRESSMODE, 0); // Set horizontal addressing mode + command(SETCOLUMNBOUNDS, 0, LCDTOTALWIDTH - 1); // Set width + command(SETPAGEBOUNDS, 0, LCDTOTALPAGES - 1); // Set height + + MVSPI.packetBegin(); + DCHIGH; + MVSPI.transfer(c); + for (int i = 1; i < LCDTOTALWIDTH * LCDTOTALPAGES; i++) { + MVSPI.wait(); MVSPI.transfer(c); - for (int j=1; j<0x80; j++) { - MVSPI.wait(); - MVSPI.transfer(c); - } - MVSPI.packetEnd(); } + MVSPI.packetEnd(); + + command(SETADDRESSMODE, 2); // Return display to page addressing mode } else { - memset(screenmemory,c,384); // (64 x 48) / 8 = 384 + memset(screenmemory, c, LCDWIDTH * LCDPAGES); display(); } } @@ -331,20 +333,22 @@ void MicroView::contrast(uint8_t contrast) { Bulk move the screen buffer to the SSD1306 controller's memory so that images/graphics drawn on the screen buffer will be displayed on the OLED. */ void MicroView::display(void) { - uint8_t i, j; - - for (i=0; i<6; i++) { - setPageAddress(i); - setColumnAddress(0); - MVSPI.packetBegin(); - DCHIGH; - MVSPI.transfer(screenmemory[i*0x40]); - for (j=1;j<0x40;j++) { - MVSPI.wait(); - MVSPI.transfer(screenmemory[i*0x40+j]); - } - MVSPI.packetEnd(); + command(SETADDRESSMODE, 0); // Set horizontal addressing mode + command(SETCOLUMNBOUNDS, + LCDCOLUMNOFFSET, + LCDCOLUMNOFFSET + LCDWIDTH - 1); // Set width + command(SETPAGEBOUNDS, 0, LCDPAGES - 1); // Set height + + MVSPI.packetBegin(); + DCHIGH; + MVSPI.transfer(screenmemory[0]); + for (int i = 1; i < LCDWIDTH * LCDPAGES; i++) { + MVSPI.wait(); + MVSPI.transfer(screenmemory[i]); } + MVSPI.packetEnd(); + + command(SETADDRESSMODE, 2); // Restore to page addressing mode } //#if ARDUINO >= 100 diff --git a/MicroView.h b/MicroView.h index 59abb9c..4a93ab2 100644 --- a/MicroView.h +++ b/MicroView.h @@ -60,6 +60,13 @@ #define LCDWIDTH 64 #define LCDHEIGHT 48 +#define LCDPAGES (LCDHEIGHT / 8) +#define LCDCOLUMNOFFSET 32 // Visible start column within SSD1306 controller memory + +#define LCDTOTALWIDTH 128 // Full width of SSD1306 controller memory +#define LCDTOTALHEIGHT 64 // Full height of SSD1306 controller memory +#define LCDTOTALPAGES (LCDTOTALHEIGHT / 8) + #define FONTHEADERSIZE 6 #define NORM 0 @@ -88,6 +95,7 @@ #define SETLOWCOLUMN 0x00 #define SETHIGHCOLUMN 0x10 #define SETPAGE 0xB0 +#define SETADDRESSMODE 0x20 #define SETCOLUMNBOUNDS 0x21 #define SETPAGEBOUNDS 0x22 #define SETSTARTLINE 0x40 From c67593e3217249089de022b7724285e5030c7020 Mon Sep 17 00:00:00 2001 From: Scott Allen Date: Fri, 1 Aug 2014 15:33:49 -0400 Subject: [PATCH 6/6] Fix positioning of "3" on clock face. --- examples/MicroViewDemo/MicroViewDemo.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/MicroViewDemo/MicroViewDemo.ino b/examples/MicroViewDemo/MicroViewDemo.ino index de3d5ca..bef5cec 100644 --- a/examples/MicroViewDemo/MicroViewDemo.ino +++ b/examples/MicroViewDemo/MicroViewDemo.ino @@ -373,7 +373,7 @@ void loop() { uView.print(6); uView.setCursor(0,uView.getLCDHeight() /2-(uView.getFontHeight()/2)); uView.print(9); - uView.setCursor(uView.getLCDWidth()-uView.getFontWidth(),uView.getLCDWidth()/2-(uView.getFontHeight()/2)); + uView.setCursor(uView.getLCDWidth()-uView.getFontWidth(),uView.getLCDHeight()/2-(uView.getFontHeight()/2)); uView.print(3); uView.display(); // display the memory buffer drawn @@ -618,4 +618,4 @@ void loop() { uView.clear(PAGE); } - +