--- /dev/null
+/****************************************************************************
+ * 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"
+ :
+ );
+}
* 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)
/* 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;
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;
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)
{
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;
}
*/
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));
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;
-}
-
--- /dev/null
+/****************************************************************************
+ * 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
/***************************************************************************** */
/* 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
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 */
*/
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);
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 */