Remove the gddram internal buffer
authorDavid Odin <david@forma3dev.fr>
Wed, 19 Apr 2017 18:32:53 +0000 (20:32 +0200)
committerNathael Pajani <nathael.pajani@ed3l.fr>
Tue, 8 Nov 2022 16:03:05 +0000 (17:03 +0100)
extdrv/ssd130x_oled_buffer.c [new file with mode: 0644]
extdrv/ssd130x_oled_driver.c
include/extdrv/ssd130x_oled_buffer.h [new file with mode: 0644]
include/extdrv/ssd130x_oled_driver.h

diff --git a/extdrv/ssd130x_oled_buffer.c b/extdrv/ssd130x_oled_buffer.c
new file mode 100644 (file)
index 0000000..89018b6
--- /dev/null
@@ -0,0 +1,123 @@
+/****************************************************************************
+ *   extdrv/ssd130x_oled_buffer.c
+ *
+ * Set of functions helping using the 128x64 buffer for the SSD130X
+ *
+ * Copyright 2017 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+#include "lib/string.h"
+
+#include "extdrv/ssd130x_oled_driver.h"
+
+/* Set whole display to given value */
+int ssd130x_buffer_set(uint8_t *gddram, uint8_t val)
+{
+       memset(gddram + 4, val, GDDRAM_SIZE);
+       return 0;
+}
+
+/* Change our internal buffer, without actually displaying the changes */
+int ssd130x_buffer_set_pixel(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t state)
+{
+       uint8_t* addr = gddram + 4 + ((y0 / 8) * 128) + x0;
+       if (state != 0) {
+               *addr |=  (0x01 << (y0 % 8));
+       } else {
+               *addr &= ~(0x01 << (y0 % 8));
+       }
+       return 0;
+}
+
+/* Change a "tile" in the bitmap memory.
+ * A tile is a 8x8 pixels region, aligned on a 8x8 grid representation of the display.
+ *  x0 and y0 are in number of tiles.
+ */
+int ssd130x_buffer_set_tile(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t* tile)
+{
+       uint8_t* addr = gddram + 4 + (y0 * 128) + (x0 * 8);
+       memcpy(addr, tile, 8);
+       return 0;
+}
+
+/* Simple RLE decompressor */
+void uncompress_image(uint8_t *compressed_data,
+                      uint8_t *buffer)
+{
+       int i;
+       signed char *in = (signed char *)compressed_data;
+       uint8_t* out = buffer;
+       do {
+               if (*in < 0) {
+                       int count = -(int)*in;
+                       in++;
+                       for (i = 0; i < count; i++)
+                               *out++ = *in++;
+               } else {
+                       int count = *in + 3;
+                       in++;
+                       for (i = 0; i < count; i++)
+                               *out++ = *in;
+                       in++;
+               }
+       } while (out - buffer < 8 * 128);
+}
+
+/* Simple RLE decompressor, asm implementation, experimental */
+void uncompress_image_asm(uint8_t *compressed_data,
+                          uint8_t *buffer)
+{
+  // note: r0 is compressed_data/in, r1 is buffer
+  // r2 is end_buffer
+  // r3 is count
+  // r4 is data
+  // r5 is in-offset
+  asm volatile(
+               ".syntax unified\n\t"
+               "push    {r2,r3,r4,r5}\n\t"
+               "movs    r2, 128\n\t"
+               "lsls    r2, 3\n\t"
+               "adds    r2, r2, r1\n\t"
+               ".label1:\n\t"
+               "  ldrb    r3, [r0]\n\t"
+               "  adds    r0, 1\n\t"
+               "  sxtb    r3, r3\n\t"
+               "  cmp     r3, 0\n\t"
+               "  bpl     .set\n\t"
+               "    rsbs    r3, r3, 0\t@ negs...\n\t"
+               "    movs    r5, 1\n\t"
+               "    b       .copy2\n"
+               ".set:\n\t"
+               "    adds    r3, 3\n\t"
+               "    movs    r5, 0\n"
+               ".copy2:\n\t"
+               "    ldrb    r4, [r0]\n\t"
+               "    strb    r4, [r1]\n\t"
+               "    adds    r0, r5\n\t"
+               "    adds    r1, 1\n\t"
+               "    subs    r3, 1\n\t"
+               "    bne     .copy2\n\t"
+               "    subs    r0, r0, r5\n\t"
+               "    adds    r0, r0, 1\n\t"
+               "  cmp     r1, r2\n\t"
+               "  bne     .label1\n"
+               ".end:\n\t"
+               "pop     {r2,r3,r4,r5}\n\t"
+              :
+              );
+}
index ef4ade2..8f8355b 100644 (file)
@@ -311,9 +311,8 @@ int ssd130x_display_on(struct oled_display* conf)
  * Graphical data starts at byte 4. The first four bytes are here for temporary
  *  storage of display data during I2C frame transfer.
  */
-#define GDDRAM_SIZE   (128 * 8)
-static uint8_t gddram[ 4 + GDDRAM_SIZE ];
-static uint8_t* gddram_start = (gddram + 4);
+//static uint8_t gddram[ 4 + GDDRAM_SIZE ];
+//static uint8_t* gddram_start = (gddram + 4);
 
 
 int ssd130x_send_data(struct oled_display* conf, uint8_t* start, uint16_t len)
@@ -323,8 +322,8 @@ int ssd130x_send_data(struct oled_display* conf, uint8_t* start, uint16_t len)
        /* Check that start and satrt + len are within buffer */
 
        /* Copy previous two bytes to storage area (gddram[0] and gddram[1]) */
-       gddram[0] = *(start - 2);
-       gddram[1] = *(start - 1);
+       conf->gddram[0] = *(start - 2);
+       conf->gddram[1] = *(start - 1);
 
        /* Setup I2C transfer */
        *(start - 2) = conf->address;
@@ -334,8 +333,8 @@ int ssd130x_send_data(struct oled_display* conf, uint8_t* start, uint16_t len)
        ret = i2c_write(conf->bus_num, (start - 2), (2 + len), NULL);
 
        /* Restore gddram data */
-       *(start - 2) = gddram[0];
-       *(start - 1) = gddram[1];
+       *(start - 2) = conf->gddram[0];
+       *(start - 1) = conf->gddram[1];
 
        if (ret != (2 + len)) {
                return ret;
@@ -343,14 +342,6 @@ int ssd130x_send_data(struct oled_display* conf, uint8_t* start, uint16_t len)
        return len;
 }
 
-/* Set whole display to given value */
-int ssd130x_display_set(struct oled_display* conf, uint8_t val)
-{
-       memset(gddram_start, val, GDDRAM_SIZE);
-       return 0;
-}
-
-
 /* Update what is really displayed */
 int ssd130x_display_full_screen(struct oled_display* conf)
 {
@@ -364,7 +355,7 @@ int ssd130x_display_full_screen(struct oled_display* conf)
        if (ret != 0) {
                return ret;
        }
-       ret = ssd130x_send_data(conf, gddram_start, GDDRAM_SIZE);
+       ret = ssd130x_send_data(conf, conf->gddram + 4, GDDRAM_SIZE);
        if (ret != GDDRAM_SIZE) {
                return ret;
        }
@@ -377,7 +368,7 @@ int ssd130x_display_full_screen(struct oled_display* conf)
  */
 int ssd130x_update_tile(struct oled_display* conf, uint8_t x0, uint8_t y0)
 {
-       uint8_t* addr = gddram_start + (y0 * 128) + x0 * 8;
+       uint8_t* addr = conf->gddram + 4 + (y0 * 128) + x0 * 8;
        int ret = 0;
 
        ret = ssd130x_set_column_address(conf, (x0 * 8), (((x0 + 1) * 8) - 1));
@@ -400,26 +391,3 @@ int ssd130x_update_modified(struct oled_display* conf)
        return 0;
 }
 
-/* Change our internal buffer, without actually displaying the changes */
-int ssd130x_set_pixel(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t state)
-{
-       uint8_t* addr = gddram_start + ((y0 / 8) * 128) + x0;
-       if (state != 0) {
-               *addr |=  (0x01 << (y0 % 8));
-       } else {
-               *addr &= ~(0x01 << (y0 % 8));
-       }
-       return 0;
-}
-
-/* Change a "tile" in the bitmap memory.
- * A tile is a 8x8 pixels region, aligned on a 8x8 grid representation of the display.
- *  x0 and y0 are in number of tiles.
- */
-int ssd130x_set_tile(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t* tile)
-{
-       uint8_t* addr = gddram_start + (y0 * 128) + (x0 * 8);
-       memcpy(addr, tile, 8);
-       return 0;
-}
-
diff --git a/include/extdrv/ssd130x_oled_buffer.h b/include/extdrv/ssd130x_oled_buffer.h
new file mode 100644 (file)
index 0000000..2241d8a
--- /dev/null
@@ -0,0 +1,42 @@
+/****************************************************************************
+ *   extdrv/ssd130x_oled_buffer.h
+ *
+ * Set of functions helping using the 128x64 buffer for the SSD130X
+ *
+ * Copyright 2017 Nathael Pajani <nathael.pajani@ed3l.fr>
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *************************************************************************** */
+
+#ifndef EXTDRV_SSD130X_OLED_BUFFER_H
+#define EXTDRV_SSD130X_OLED_BUFFER_H
+
+#include "lib/stdint.h"
+
+/* Set whole display to given value */
+int ssd130x_buffer_set(uint8_t* gddram, uint8_t val);
+
+/* Change our internal buffer, without actually displaying the changes */
+int ssd130x_buffer_set_pixel(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t state);
+int ssd130x_buffer_set_tile(uint8_t* gddram, uint8_t x0, uint8_t y0, uint8_t* tile);
+
+/* Simple RLE decompressor (two implementations, wip) */
+void uncompress_image(uint8_t* compressed_data,
+                      uint8_t* buffer);
+void uncompress_image_asm(uint8_t* compressed_data,
+                          uint8_t* buffer);
+
+#endif
index 8552c39..d3802a3 100644 (file)
 /***************************************************************************** */
 /* Oled Display */
 struct oled_display {
-       uint8_t address; /* 8 bits address */
-       uint8_t bus_num; /* I2C bus number */
-       uint8_t probe_ok;
-       uint8_t charge_pump;
-       uint8_t video_mode;
-       uint8_t contrast;
-       uint8_t scan_dir;
-       uint8_t read_dir;
-       uint8_t display_offset_dir;
-       uint8_t display_offset;
+       uint8_t  address; /* 8 bits address */
+       uint8_t  bus_num; /* I2C bus number */
+       uint8_t  probe_ok;
+       uint8_t  charge_pump;
+       uint8_t  video_mode;
+       uint8_t  contrast;
+       uint8_t  scan_dir;
+       uint8_t  read_dir;
+       uint8_t  display_offset_dir;
+       uint8_t  display_offset;
+  uint8_t* gddram;
 };
 
 #define SSD130x_NB_LINES   64
@@ -314,10 +315,8 @@ int ssd130x_set_display_offset(struct oled_display* conf, uint8_t dir, uint8_t n
 int ssd130x_display_on(struct oled_display* conf);
 int ssd130x_display_off(struct oled_display* conf);
 
-int ssd130x_display_init(struct oled_display* conf);
-
-
 
+#define GDDRAM_SIZE   (128 * 8)
 /***************************************************************************** */
 /* Data */
 
@@ -327,9 +326,6 @@ int ssd130x_display_init(struct oled_display* conf);
  */
 int ssd130x_send_data(struct oled_display* conf, uint8_t* start, uint16_t len);
 
-/* Set whole display to given value */
-int ssd130x_display_set(struct oled_display* conf, uint8_t val);
-
 
 /* Update what is really displayed */
 int ssd130x_display_full_screen(struct oled_display* conf);
@@ -338,9 +334,4 @@ int ssd130x_update_region(struct oled_display* conf,
                                                        uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);
 int ssd130x_update_modified(struct oled_display* conf);
 
-/* Change our internal buffer, without actually displaying the changes */
-int ssd130x_set_pixel(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t state);
-int ssd130x_set_tile(struct oled_display* conf, uint8_t x0, uint8_t y0, uint8_t* tile);
-
-
 #endif /* EXTDRV_SSD130X_OLED_DRIVER_H */