From: David Odin Date: Wed, 19 Apr 2017 18:32:53 +0000 (+0200) Subject: Remove the gddram internal buffer X-Git-Url: http://git.techno-innov.fr/?a=commitdiff_plain;h=06b94003c4a22fcf6a40fb5a3cc70391d3eccbdf;p=soft%2Flpc122x%2Fcore Remove the gddram internal buffer --- diff --git a/extdrv/ssd130x_oled_buffer.c b/extdrv/ssd130x_oled_buffer.c new file mode 100644 index 0000000..89018b6 --- /dev/null +++ b/extdrv/ssd130x_oled_buffer.c @@ -0,0 +1,123 @@ +/**************************************************************************** + * extdrv/ssd130x_oled_buffer.c + * + * Set of functions helping using the 128x64 buffer for the SSD130X + * + * Copyright 2017 Nathael Pajani + * + * + * 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 . + * + *************************************************************************** */ + +#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" + : + ); +} diff --git a/extdrv/ssd130x_oled_driver.c b/extdrv/ssd130x_oled_driver.c index ef4ade2..8f8355b 100644 --- a/extdrv/ssd130x_oled_driver.c +++ b/extdrv/ssd130x_oled_driver.c @@ -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 index 0000000..2241d8a --- /dev/null +++ b/include/extdrv/ssd130x_oled_buffer.h @@ -0,0 +1,42 @@ +/**************************************************************************** + * extdrv/ssd130x_oled_buffer.h + * + * Set of functions helping using the 128x64 buffer for the SSD130X + * + * Copyright 2017 Nathael Pajani + * + * + * 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 . + * + *************************************************************************** */ + +#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 diff --git a/include/extdrv/ssd130x_oled_driver.h b/include/extdrv/ssd130x_oled_driver.h index 8552c39..d3802a3 100644 --- a/include/extdrv/ssd130x_oled_driver.h +++ b/include/extdrv/ssd130x_oled_driver.h @@ -30,16 +30,17 @@ /***************************************************************************** */ /* 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 */