From b5be96f8bb65d526a744795e8e3777d5ed47a034 Mon Sep 17 00:00:00 2001
From: brickbots <rich@brickbots.com>
Date: Sat, 14 Mar 2020 14:04:34 -0700
Subject: [PATCH] Adding OLED scroll setup functions (#8386)

* Adding scroll setup functions:

* Clarifying values stored in oled_scroll_speed
---
 docs/feature_oled_driver.md | 16 ++++++++++++++--
 drivers/oled/oled_driver.c  | 36 ++++++++++++++++++++++++++++++++----
 drivers/oled/oled_driver.h  | 12 ++++++++++++
 3 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/docs/feature_oled_driver.md b/docs/feature_oled_driver.md
index f4e5db0f4b..772ce57bdd 100644
--- a/docs/feature_oled_driver.md
+++ b/docs/feature_oled_driver.md
@@ -261,12 +261,24 @@ void oled_task(void);
 // Called at the start of oled_task, weak function overridable by the user
 void oled_task_user(void);
 
-// Scrolls the entire display right
+// Set the specific 8 lines rows of the screen to scroll.
+// 0 is the default for start, and 7 for end, which is the entire
+// height of the screen.  For 128x32 screens, rows 4-7 are not used.
+void oled_scroll_set_area(uint8_t start_line, uint8_t end_line);
+
+// Sets scroll speed, 0-7, fastest to slowest. Default is three.
+// Does not take effect until scrolling is either started or restarted
+// the ssd1306 supports 8 speeds with the delay
+// listed below betwen each frame of the scrolling effect
+// 0=2, 1=3, 2=4, 3=5, 4=25, 5=64, 6=128, 7=256
+void oled_scroll_set_speed(uint8_t speed);
+
+// Begin scrolling the entire display right
 // Returns true if the screen was scrolling or starts scrolling
 // NOTE: display contents cannot be changed while scrolling
 bool oled_scroll_right(void);
 
-// Scrolls the entire display left
+// Begin scrolling the entire display left
 // Returns true if the screen was scrolling or starts scrolling
 // NOTE: display contents cannot be changed while scrolling
 bool oled_scroll_left(void);
diff --git a/drivers/oled/oled_driver.c b/drivers/oled/oled_driver.c
index 079f5688fe..690efa4a6e 100644
--- a/drivers/oled/oled_driver.c
+++ b/drivers/oled/oled_driver.c
@@ -108,6 +108,9 @@ bool            oled_active         = false;
 bool            oled_scrolling      = false;
 uint8_t         oled_rotation       = 0;
 uint8_t         oled_rotation_width = 0;
+uint8_t         oled_scroll_speed   = 0; // this holds the speed after being remapped to ssd1306 internal values
+uint8_t         oled_scroll_start   = 0;
+uint8_t         oled_scroll_end     = 7;
 #if OLED_TIMEOUT > 0
 uint32_t oled_timeout;
 #endif
@@ -515,12 +518,37 @@ bool oled_off(void) {
     return !oled_active;
 }
 
+// Set the specific 8 lines rows of the screen to scroll.
+// 0 is the default for start, and 7 for end, which is the entire
+// height of the screen.  For 128x32 screens, rows 4-7 are not used.
+void oled_scroll_set_area(uint8_t start_line, uint8_t end_line) {
+    oled_scroll_start = start_line;
+    oled_scroll_end = end_line;
+}
+
+void oled_scroll_set_speed(uint8_t speed) {
+    // Sets the speed for scrolling... does not take effect
+    // until scrolling is either started or restarted
+    // the ssd1306 supports 8 speeds
+    // FrameRate2   speed = 7
+    // FrameRate3   speed = 4
+    // FrameRate4   speed = 5
+    // FrameRate5   speed = 0
+    // FrameRate25  speed = 6
+    // FrameRate64  speed = 1
+    // FrameRate128 speed = 2
+    // FrameRate256 speed = 3
+    // for ease of use these are remaped here to be in order
+    static const uint8_t scroll_remap[8] = {7, 4, 5, 0, 6, 1, 2, 3};
+    oled_scroll_speed = scroll_remap[speed];
+}
+
 bool oled_scroll_right(void) {
     // Dont enable scrolling if we need to update the display
     // This prevents scrolling of bad data from starting the scroll too early after init
     if (!oled_dirty && !oled_scrolling) {
-        static const uint8_t PROGMEM display_scroll_right[] = {I2C_CMD, SCROLL_RIGHT, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, ACTIVATE_SCROLL};
-        if (I2C_TRANSMIT_P(display_scroll_right) != I2C_STATUS_SUCCESS) {
+        uint8_t display_scroll_right[] = {I2C_CMD, SCROLL_RIGHT, 0x00, oled_scroll_start, oled_scroll_speed, oled_scroll_end, 0x00, 0xFF, ACTIVATE_SCROLL};
+        if (I2C_TRANSMIT(display_scroll_right) != I2C_STATUS_SUCCESS) {
             print("oled_scroll_right cmd failed\n");
             return oled_scrolling;
         }
@@ -533,8 +561,8 @@ bool oled_scroll_left(void) {
     // Dont enable scrolling if we need to update the display
     // This prevents scrolling of bad data from starting the scroll too early after init
     if (!oled_dirty && !oled_scrolling) {
-        static const uint8_t PROGMEM display_scroll_left[] = {I2C_CMD, SCROLL_LEFT, 0x00, 0x00, 0x00, 0x0F, 0x00, 0xFF, ACTIVATE_SCROLL};
-        if (I2C_TRANSMIT_P(display_scroll_left) != I2C_STATUS_SUCCESS) {
+        uint8_t display_scroll_left[] = {I2C_CMD, SCROLL_LEFT, 0x00, oled_scroll_start, oled_scroll_speed, oled_scroll_end, 0x00, 0xFF, ACTIVATE_SCROLL};
+        if (I2C_TRANSMIT(display_scroll_left) != I2C_STATUS_SUCCESS) {
             print("oled_scroll_left cmd failed\n");
             return oled_scrolling;
         }
diff --git a/drivers/oled/oled_driver.h b/drivers/oled/oled_driver.h
index 6d1cee9b79..3e5a5bcabe 100644
--- a/drivers/oled/oled_driver.h
+++ b/drivers/oled/oled_driver.h
@@ -246,6 +246,18 @@ void oled_task(void);
 // Called at the start of oled_task, weak function overridable by the user
 void oled_task_user(void);
 
+// Set the specific 8 lines rows of the screen to scroll.
+// 0 is the default for start, and 7 for end, which is the entire
+// height of the screen.  For 128x32 screens, rows 4-7 are not used.
+void oled_scroll_set_area(uint8_t start_line, uint8_t end_line);
+
+// Sets scroll speed, 0-7, fastest to slowest. Default is three.
+// Does not take effect until scrolling is either started or restarted
+// the ssd1306 supports 8 speeds with the delay
+// listed below betwen each frame of the scrolling effect
+// 0=2, 1=3, 2=4, 3=5, 4=25, 5=64, 6=128, 7=256
+void oled_scroll_set_speed(uint8_t speed);
+
 // Scrolls the entire display right
 // Returns true if the screen was scrolling or starts scrolling
 // NOTE: display contents cannot be changed while scrolling