Code formatted, minor fixes (#466)

This commit is contained in:
Ruslan V. Uss 2017-10-19 00:25:48 +05:00 committed by Johan Kanflo
parent 8a474d749d
commit 5fa48d0298
28 changed files with 623 additions and 608 deletions

View file

@ -1,4 +1,4 @@
# Driver for SSD1306 OLED LCD
# Driver for SSD1306/SH1106 OLED LCD
This driver is written for usage with the ESP8266 and FreeRTOS ([esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos)).
@ -11,34 +11,38 @@ This driver is written for usage with the ESP8266 and FreeRTOS ([esp-open-rtos](
## Supported connection interfaces
Currently supported two of them: I2C and SPI4.
I2C, SPI3 and SPI4.
## Usage
If Reset pin is accesible in your display module, connect it to the RESET pin of ESP8266.
If you don't do this, display RAM may be glitchy after the power lost/restore.
If you don't, display RAM could be glitchy after the power cycle.
### I2C protocol
Before using the SSD1306 LCD module the function `i2c_init(SCL_PIN, SDA_PIN)` needs to be
called to setup the I2C interface and then you must call `ssd1306_init()`.
Before using the OLED module you need to call the function `i2c_init(BUS, SCL_PIN, SDA_PIN, I2C_FREQ_400K)`
to configure the I2C interface and then you should call `ssd1306_init()`.
#### Example
```C
#define SCL_PIN 5
#define SDA_PIN 4
#define I2C_BUS 0
...
static const ssd1306_t device = {
.protocol = SSD1306_PROTO_I2C,
.width = 128,
.height = 64
.protocol = SSD1306_PROTO_I2C,
.screen = SSD1306_SCREEN, // or SH1106_SCREEN
.i2c_dev.bus = I2C_BUS,
.i2c_dev.addr = SSD1306_I2C_ADDR_0,
.width = 128,
.height = 64
};
...
i2c_init(SCL_PIN, SDA_PIN);
i2c_init(I2C_BUS, SCL_PIN, SDA_PIN, I2C_FREQ_400K);
if (ssd1306_init(&device)) {
// An error occured, while performing SSD1306 init (E.g device not found etc.)
@ -47,14 +51,15 @@ if (ssd1306_init(&device)) {
// rest of the code
```
### SPI4 protocol
### SPI3 and SPI4 protocols
This protocol MUCH faster than I2C but uses 2 additional GPIO pins (beside of HSPI CLK
and HSPI MOSI): Data/Command pin and Chip Select pin.
These protocols are MUCH faster than I2C, but use 2 additional GPIO pins
(besides the **HSPI CLK** and **HSPI MOSI**): **Chip Select** and **Data/Command** (in case of SPI4).
No additional function calls are required before `ssd1306_init()`.
#### Example
#### SPI4 Example
```C
#define CS_PIN 5
@ -64,10 +69,35 @@ No additional function calls are required before `ssd1306_init()`.
static const ssd1306_t device = {
.protocol = SSD1306_PROTO_SPI4,
.cs_pin = CS_PIN,
.dc_pin = DC_PIN,
.width = 128,
.height = 64
.screen = SSD1306_SCREEN,
.cs_pin = CS_PIN,
.dc_pin = DC_PIN,
.width = 128,
.height = 64
};
...
if (ssd1306_init(&device)) {
// An error occured, while performing SSD1306 init
}
// rest of the code
```
#### SPI3 example
```C
#define CS_PIN 5
...
static const ssd1306_t device = {
.protocol = SSD1306_PROTO_SPI3,
.screen = SSD1306_SCREEN,
.cs_pin = CS_PIN,
.width = 128,
.height = 64
};
...

View file

@ -85,11 +85,10 @@
#define abs(x) ((x)<0 ? -(x) : (x))
#define swap(x, y) do { typeof(x) temp##x##y = x; x = y; y = temp##x##y; } while (0)
#if (SSD1306_I2C_SUPPORT)
static int inline i2c_send(const ssd1306_t *dev, uint8_t reg, uint8_t* data, uint8_t len)
{
return i2c_slave_write(dev->i2c_dev.bus, dev->i2c_dev.addr , &reg, data, len);
return i2c_slave_write(dev->i2c_dev.bus, dev->i2c_dev.addr, &reg, data, len);
}
#endif
@ -120,7 +119,7 @@ int ssd1306_command(const ssd1306_t *dev, uint8_t cmd)
#if (SSD1306_SPI3_SUPPORT)
case SSD1306_PROTO_SPI3:
gpio_write(dev->cs_pin, false);
spi_set_command(SPI_BUS,1,0); // command mode
spi_set_command(SPI_BUS, 1, 0); // command mode
spi_transfer_8(SPI_BUS, cmd);
spi_clear_command(SPI_BUS);
gpio_write(dev->cs_pin, true);
@ -135,7 +134,7 @@ int ssd1306_command(const ssd1306_t *dev, uint8_t cmd)
}
/* Perform default init routine according
* to SSD1306 datasheet from adafruit.com */
* to SSD1306 datasheet from adafruit.com */
int ssd1306_init(const ssd1306_t *dev)
{
uint8_t pin_cfg;
@ -221,10 +220,12 @@ int ssd1306_init(const ssd1306_t *dev)
return -EIO;
}
static int sh1106_go_coordinate(const ssd1306_t *dev, uint8_t x, uint8_t y) {
if (x >= dev->width || y >= (dev->height/8)) return -EINVAL;
static int sh1106_go_coordinate(const ssd1306_t *dev, uint8_t x, uint8_t y)
{
if (x >= dev->width || y >= (dev->height / 8))
return -EINVAL;
int err = 0;
x+=2 ; //offset : panel is 128 ; RAM is 132 for sh1106
x += 2; //offset : panel is 128 ; RAM is 132 for sh1106
if ((err = ssd1306_command(dev, SH1106_SET_PAGE_ADDRESS + y))) // Set row
return err;
if ((err = ssd1306_command(dev, SH1106_SET_LOW_COL_ADDR | (x & 0xf)))) // Set lower column address
@ -237,11 +238,10 @@ int ssd1306_load_frame_buffer(const ssd1306_t *dev, uint8_t buf[])
uint16_t i;
uint8_t j;
#if (SSD1306_I2C_SUPPORT)
uint8_t tab[16] = { 0 } ;
uint8_t tab[16] = { 0 };
#endif
size_t len = dev->width * dev->height / 8;
if(dev->screen == SSD1306_SCREEN)
{
if (dev->screen == SSD1306_SCREEN) {
ssd1306_set_column_addr(dev, 0, dev->width - 1);
ssd1306_set_page_addr(dev, 0, dev->height / 8 - 1);
}
@ -249,35 +249,33 @@ int ssd1306_load_frame_buffer(const ssd1306_t *dev, uint8_t buf[])
switch (dev->protocol) {
#if (SSD1306_I2C_SUPPORT)
case SSD1306_PROTO_I2C:
for (i = 0; i < len; i++)
{
if(dev->screen == SH1106_SCREEN && i%dev->width == 0) sh1106_go_coordinate(dev,0,i/dev->width);
for (i = 0; i < len; i++) {
if (dev->screen == SH1106_SCREEN && i % dev->width == 0)
sh1106_go_coordinate(dev, 0, i / dev->width);
i2c_send(dev, 0x40, buf ? &buf[i] : tab, 16);
i+=15 ;
i += 15;
}
break;
#endif
#if (SSD1306_SPI4_SUPPORT)
case SSD1306_PROTO_SPI4:
gpio_write(dev->cs_pin, false);
if(dev->screen == SSD1306_SCREEN)
{
if (dev->screen == SSD1306_SCREEN) {
gpio_write(dev->dc_pin, true); // data mode
if (buf)
spi_transfer(SPI_BUS, buf, NULL, len, SPI_8BIT);
else
spi_repeat_send_8(SPI_BUS,0,len);
spi_repeat_send_8(SPI_BUS, 0, len);
}
else
{
for (i = 0 ; i < (dev->height/8) ; i++) {
sh1106_go_coordinate(dev,0,i);
else {
for (i = 0; i < (dev->height / 8); i++) {
sh1106_go_coordinate(dev, 0, i);
gpio_write(dev->dc_pin, true); // data mode
gpio_write(dev->cs_pin, false);
if (buf)
spi_transfer(SPI_BUS, &buf[dev->width*i], NULL, dev->width, SPI_8BIT);
spi_transfer(SPI_BUS, &buf[dev->width * i], NULL, dev->width, SPI_8BIT);
else
spi_repeat_send_8(SPI_BUS,0,dev->width);
spi_repeat_send_8(SPI_BUS, 0, dev->width);
}
}
gpio_write(dev->cs_pin, true);
@ -286,36 +284,30 @@ int ssd1306_load_frame_buffer(const ssd1306_t *dev, uint8_t buf[])
#if (SSD1306_SPI3_SUPPORT)
case SSD1306_PROTO_SPI3:
gpio_write(dev->cs_pin, false);
if(dev->screen == SSD1306_SCREEN)
{
spi_set_command(SPI_BUS,1,1); // data mode
if (buf)
{
for (i = 0; i < len; i++)
{
if (dev->screen == SSD1306_SCREEN) {
spi_set_command(SPI_BUS, 1, 1); // data mode
if (buf) {
for (i = 0; i < len; i++) {
spi_transfer(SPI_BUS, &buf[i], NULL, 1, SPI_8BIT);
}
}
else
{
for (i = 0; i < len; i++)
{
else {
for (i = 0; i < len; i++) {
spi_transfer_8(SPI_BUS, 0);
}
}
}
else
{
for (i = 0 ; i < (dev->height/8) ; i++) {
sh1106_go_coordinate(dev,0,i);
spi_set_command(SPI_BUS,1,1); // data mode
else {
for (i = 0; i < (dev->height / 8); i++) {
sh1106_go_coordinate(dev, 0, i);
spi_set_command(SPI_BUS, 1, 1); // data mode
gpio_write(dev->cs_pin, false);
if (buf)
for (j = 0 ; j < dev->width ; j++)
spi_transfer_8(SPI_BUS, buf[dev->width*i+j]);
for (j = 0; j < dev->width; j++)
spi_transfer_8(SPI_BUS, buf[dev->width * i + j]);
else
for (j = 0 ; j < dev->width ; j++)
spi_transfer_8(SPI_BUS, buf[dev->width*i+j]);
for (j = 0; j < dev->width; j++)
spi_transfer_8(SPI_BUS, buf[dev->width * i + j]);
}
}
spi_clear_command(SPI_BUS);
@ -357,41 +349,38 @@ int ssd1306_set_display_offset(const ssd1306_t *dev, uint8_t offset)
int sh1106_set_charge_pump_voltage(const ssd1306_t *dev, sh1106_voltage_t select)
{
if (dev->screen == SSD1306_SCREEN)
{
if (dev->screen == SSD1306_SCREEN) {
debug("Unsupported screen type");
return -ENOTSUP ;
return -ENOTSUP;
}
return ssd1306_command(dev, select | SH1106_CHARGE_PUMP_VALUE);
}
int ssd1306_set_charge_pump_enabled(const ssd1306_t *dev, bool enabled)
{
int err = 0;
switch (dev->screen) {
case SH1106_SCREEN:
if ((err = ssd1306_command(dev, SH1106_SET_CHARGE_PUMP)))
return err;
return ssd1306_command(dev, enabled ? SH1106_CHARGE_PUMP_EN : SH1106_CHARGE_PUMP_DIS);
break;
case SSD1306_SCREEN:
if ((err = ssd1306_command(dev, SSD1306_SET_CHARGE_PUMP)))
return err;
return ssd1306_command(dev, enabled ? SSD1306_CHARGE_PUMP_EN : SSD1306_CHARGE_PUMP_DIS);
break;
default:
debug("Unsupported screen type");
return -ENOTSUP;
case SH1106_SCREEN:
if ((err = ssd1306_command(dev, SH1106_SET_CHARGE_PUMP)))
return err;
return ssd1306_command(dev, enabled ? SH1106_CHARGE_PUMP_EN : SH1106_CHARGE_PUMP_DIS);
break;
case SSD1306_SCREEN:
if ((err = ssd1306_command(dev, SSD1306_SET_CHARGE_PUMP)))
return err;
return ssd1306_command(dev, enabled ? SSD1306_CHARGE_PUMP_EN : SSD1306_CHARGE_PUMP_DIS);
break;
default:
debug("Unsupported screen type");
return -ENOTSUP;
}
}
int ssd1306_set_mem_addr_mode(const ssd1306_t *dev, ssd1306_mem_addr_mode_t mode)
{
if (dev->screen == SH1106_SCREEN)
{
if (dev->screen == SH1106_SCREEN) {
debug("Unsupported screen type");
return -ENOTSUP ;
return -ENOTSUP;
}
int err = 0;
if ((err = ssd1306_command(dev, SSD1306_SET_MEM_ADDR_MODE)))
@ -498,7 +487,7 @@ int ssd1306_set_deseltct_lvl(const ssd1306_t *dev, uint8_t lvl)
int ssd1306_set_whole_display_lighting(const ssd1306_t *dev, bool light)
{
return ssd1306_command(dev, light ? SSD1306_SET_ENTIRE_DISP_ON : SSD1306_SET_ENTIRE_DISP_OFF);
return ssd1306_command(dev, light ? SSD1306_SET_ENTIRE_DISP_ON : SSD1306_SET_ENTIRE_DISP_OFF);
}
/* one byte of xbm - 8 dots in line of picture source
@ -510,9 +499,9 @@ int ssd1306_load_xbm(const ssd1306_t *dev, uint8_t *xbm, uint8_t *fb)
int row = 0;
int column = 0;
for (row = 0; row < dev->height; row ++) {
for (row = 0; row < dev->height; row++) {
for (column = 0; column < dev->width / 8; column++) {
uint16_t xbm_offset = row * 16 + column;
uint16_t xbm_offset = row * 16 + column;
for (bit = 0; bit < 8; bit++) {
if (*(xbm + xbm_offset) & 1 << bit) {
*(fb + dev->width * (row / 8) + column * 8 + bit) |= 1 << row % 8;
@ -532,19 +521,18 @@ int ssd1306_draw_pixel(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, ss
return -EINVAL;
index = x + (y / 8) * dev->width;
switch (color)
{
case OLED_COLOR_WHITE:
fb[index] |= (1 << (y & 7));
break;
case OLED_COLOR_BLACK:
fb[index] &= ~(1 << (y & 7));
break;
case OLED_COLOR_INVERT:
fb[index] ^= (1 << (y & 7));
break;
default:
break;
switch (color) {
case OLED_COLOR_WHITE:
fb[index] |= (1 << (y & 7));
break;
case OLED_COLOR_BLACK:
fb[index] &= ~(1 << (y & 7));
break;
case OLED_COLOR_INVERT:
fb[index] ^= (1 << (y & 7));
break;
default:
break;
}
return 0;
}
@ -565,32 +553,28 @@ int ssd1306_draw_hline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, ui
t = w;
index = x + (y / 8) * dev->width;
mask = 1 << (y & 7);
switch (color)
{
case OLED_COLOR_WHITE:
while (t--)
{
fb[index] |= mask;
++index;
}
break;
case OLED_COLOR_BLACK:
mask = ~mask;
while (t--)
{
fb[index] &= mask;
++index;
}
break;
case OLED_COLOR_INVERT:
while (t--)
{
fb[index] ^= mask;
++index;
}
break;
default:
break;
switch (color) {
case OLED_COLOR_WHITE:
while (t--) {
fb[index] |= mask;
++index;
}
break;
case OLED_COLOR_BLACK:
mask = ~mask;
while (t--) {
fb[index] &= mask;
++index;
}
break;
case OLED_COLOR_INVERT:
while (t--) {
fb[index] ^= mask;
++index;
}
break;
default:
break;
}
return 0;
}
@ -619,19 +603,18 @@ int ssd1306_draw_vline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, ui
mask = premask[mod];
if (t < mod)
mask &= (0xFF >> (mod - t));
switch (color)
{
case OLED_COLOR_WHITE:
fb[index] |= mask;
break;
case OLED_COLOR_BLACK:
fb[index] &= ~mask;
break;
case OLED_COLOR_INVERT:
fb[index] ^= mask;
break;
default:
break;
switch (color) {
case OLED_COLOR_WHITE:
fb[index] |= mask;
break;
case OLED_COLOR_BLACK:
fb[index] &= ~mask;
break;
case OLED_COLOR_INVERT:
fb[index] ^= mask;
break;
default:
break;
}
if (t < mod)
@ -640,35 +623,31 @@ int ssd1306_draw_vline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, ui
index += dev->width;
}
if (t >= 8) // byte aligned line at middle
{
switch (color)
{
case OLED_COLOR_WHITE:
do
{
fb[index] = 0xff;
index += dev->width;
t -= 8;
} while (t >= 8);
break;
case OLED_COLOR_BLACK:
do
{
fb[index] = 0x00;
index += dev->width;
t -= 8;
} while (t >= 8);
break;
case OLED_COLOR_INVERT:
do
{
fb[index] = ~fb[index];
index += dev->width;
t -= 8;
} while (t >= 8);
break;
default:
break;
switch (color) {
case OLED_COLOR_WHITE:
do {
fb[index] = 0xff;
index += dev->width;
t -= 8;
} while (t >= 8);
break;
case OLED_COLOR_BLACK:
do {
fb[index] = 0x00;
index += dev->width;
t -= 8;
} while (t >= 8);
break;
case OLED_COLOR_INVERT:
do {
fb[index] = ~fb[index];
index += dev->width;
t -= 8;
} while (t >= 8);
break;
default:
break;
}
}
if (t) // partial line at bottom
@ -676,19 +655,18 @@ int ssd1306_draw_vline(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, ui
mod = t & 7;
static const uint8_t postmask[8] = { 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F };
mask = postmask[mod];
switch (color)
{
case OLED_COLOR_WHITE:
fb[index] |= mask;
break;
case OLED_COLOR_BLACK:
fb[index] &= ~mask;
break;
case OLED_COLOR_INVERT:
fb[index] ^= mask;
break;
default:
break;
switch (color) {
case OLED_COLOR_WHITE:
fb[index] |= mask;
break;
case OLED_COLOR_BLACK:
fb[index] &= ~mask;
break;
case OLED_COLOR_INVERT:
fb[index] ^= mask;
break;
default:
break;
}
}
return 0;
@ -706,7 +684,6 @@ int ssd1306_draw_rectangle(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y
return ssd1306_draw_vline(dev, fb, x + w - 1, y, h, color);
}
int ssd1306_fill_rectangle(const ssd1306_t *dev, uint8_t *fb, int8_t x, int8_t y, uint8_t w, uint8_t h, ssd1306_color_t color)
{
// Can be optimized?
@ -738,8 +715,7 @@ int ssd1306_draw_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0,
if ((err = ssd1306_draw_pixel(dev, fb, x0, y0 + r, color)))
return err;
while (x >= y)
{
while (x >= y) {
if ((err = ssd1306_draw_pixel(dev, fb, x0 + x, y0 + y, color)))
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 - x, y0 + y, color)))
@ -748,8 +724,7 @@ int ssd1306_draw_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0,
return err;
if ((err = ssd1306_draw_pixel(dev, fb, x0 - x, y0 - y, color)))
return err;
if (x != y)
{
if (x != y) {
/* Otherwise the 4 drawings below are the same as above, causing
* problem when color is INVERT
*/
@ -788,14 +763,12 @@ int ssd1306_fill_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0,
if ((err = ssd1306_draw_vline(dev, fb, x0, y0 - r, 2 * r + 1, color))) // Center vertical line
return err;
while (y >= x)
{
while (y >= x) {
if ((err = ssd1306_draw_vline(dev, fb, x0 - x, y0 - y, 2 * y + 1, color)))
return err;
if ((err = ssd1306_draw_vline(dev, fb, x0 + x, y0 - y, 2 * y + 1, color)))
return err;
if (color != OLED_COLOR_INVERT)
{
if (color != OLED_COLOR_INVERT) {
if ((err = ssd1306_draw_vline(dev, fb, x0 - y, y0 - x, 2 * x + 1, color)))
return err;
if ((err = ssd1306_draw_vline(dev, fb, x0 + y, y0 - x, 2 * x + 1, color)))
@ -811,8 +784,7 @@ int ssd1306_fill_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0,
}
}
if (color == OLED_COLOR_INVERT)
{
if (color == OLED_COLOR_INVERT) {
x1 = x; // Save where we stopped
y = 1;
@ -822,15 +794,14 @@ int ssd1306_fill_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0,
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 - r, y0, r - x1 + 1, color)))
return err;
while (x >= y)
{
while (x >= y) {
if ((err = ssd1306_draw_hline(dev, fb, x0 + x1, y0 - y, x - x1 + 1, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 + x1, y0 + y, x - x1 + 1, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 - x, y0 - y, x - x1 + 1, color)))
if ((err = ssd1306_draw_hline(dev, fb, x0 - x, y0 - y, x - x1 + 1, color)))
return err;
if ((err = ssd1306_draw_hline(dev, fb, x0 - x, y0 + y, x - x1 + 1, color)))
if ((err = ssd1306_draw_hline(dev, fb, x0 - x, y0 + y, x - x1 + 1, color)))
return err;
++y;
if (radius_err < 0) {
@ -845,59 +816,59 @@ int ssd1306_fill_circle(const ssd1306_t *dev, uint8_t *fb, int8_t x0, int8_t y0,
return 0;
}
int ssd1306_draw_line(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0,
int16_t x1, int16_t y1, ssd1306_color_t color)
int ssd1306_draw_line(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0, int16_t x1, int16_t y1, ssd1306_color_t color)
{
if ((x0 >= dev->width) || (x0 < 0) || (y0 >= dev->height) || (y0 < 0))
return -EINVAL;
if ((x1 >= dev->width) || (x1 < 0) || (y1 >= dev->height) || (y1 < 0))
return -EINVAL;
int err;
bool steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
int err;
bool steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int16_t errx = dx / 2;
int16_t ystep;
int16_t errx = dx / 2;
int16_t ystep;
if (y0 < y1) {
ystep = 1;
} else {
ystep = -1;
}
if (y0 < y1) {
ystep = 1;
}
else {
ystep = -1;
}
for (; x0 <= x1; x0++) {
if (steep) {
if ((err = ssd1306_draw_pixel(dev, fb, y0, x0, color)))
return err;
} else {
if ((err = ssd1306_draw_pixel(dev, fb, x0, y0, color)))
return err;
}
errx -= dy;
if (errx < 0) {
y0 += ystep;
errx += dx;
}
}
return 0;
if (steep) {
if ((err = ssd1306_draw_pixel(dev, fb, y0, x0, color)))
return err;
}
else {
if ((err = ssd1306_draw_pixel(dev, fb, x0, y0, color)))
return err;
}
errx -= dy;
if (errx < 0) {
y0 += ystep;
errx += dx;
}
}
return 0;
}
int ssd1306_draw_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0,
int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
ssd1306_color_t color)
int ssd1306_draw_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
ssd1306_color_t color)
{
int err;
if ((err = ssd1306_draw_line(dev, fb, x0, y0, x1, y1, color)))
@ -907,25 +878,24 @@ int ssd1306_draw_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0,
return ssd1306_draw_line(dev, fb, x2, y2, x0, y0, color);
}
int ssd1306_fill_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0,
int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
ssd1306_color_t color)
int ssd1306_fill_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2,
ssd1306_color_t color)
{
int16_t a, b, y, last;
int err;
// Sort coordinates by Y order (y2 >= y1 >= y0)
if (y0 > y1) {
swap(y0, y1); swap(x0, x1);
swap(y0, y1);swap(x0, x1);
}
if (y1 > y2) {
swap(y2, y1); swap(x2, x1);
swap(y2, y1);swap(x2, x1);
}
if (y0 > y1) {
swap(y0, y1); swap(x0, x1);
swap(y0, y1);swap(x0, x1);
}
if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
if (y0 == y2) { // Handle awkward all-on-same-line case as its own thing
a = b = x0;
if (x1 < a) a = x1;
else if (x1 > b) b = x1;
@ -984,14 +954,13 @@ int ssd1306_fill_triangle(const ssd1306_t *dev, uint8_t *fb, int16_t x0,
*/
if (a > b) swap(a, b);
if ((err = ssd1306_draw_hline(dev, fb, a, y, b - a + 1, color)))
return err;
return err;
}
return 0;
}
int ssd1306_draw_char(const ssd1306_t *dev, uint8_t *fb,
const font_info_t *font, uint8_t x, uint8_t y, char c,
ssd1306_color_t foreground, ssd1306_color_t background)
int ssd1306_draw_char(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, char c, ssd1306_color_t foreground,
ssd1306_color_t background)
{
uint8_t i, j;
const uint8_t *bitmap;
@ -1015,30 +984,29 @@ int ssd1306_draw_char(const ssd1306_t *dev, uint8_t *fb,
err = ssd1306_draw_pixel(dev, fb, x + i, y + j, foreground);
}
else {
switch (background)
{
case OLED_COLOR_TRANSPARENT:
// Not drawing for transparent background
break;
case OLED_COLOR_WHITE:
case OLED_COLOR_BLACK:
err = ssd1306_draw_pixel(dev, fb, x + i, y + j, background);
break;
case OLED_COLOR_INVERT:
// I don't know why I need invert background
break;
switch (background) {
case OLED_COLOR_TRANSPARENT:
// Not drawing for transparent background
break;
case OLED_COLOR_WHITE:
case OLED_COLOR_BLACK:
err = ssd1306_draw_pixel(dev, fb, x + i, y + j, background);
break;
case OLED_COLOR_INVERT:
// I don't know why I need invert background
break;
}
}
if (err) return -ERANGE ;
if (err)
return -ERANGE;
line = line << 1;
}
}
return d->width;
}
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb,
const font_info_t *font, uint8_t x, uint8_t y, char *str,
ssd1306_color_t foreground, ssd1306_color_t background)
int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb, const font_info_t *font, uint8_t x, uint8_t y, char *str,
ssd1306_color_t foreground, ssd1306_color_t background)
{
uint8_t t = x;
int err;
@ -1046,11 +1014,10 @@ int ssd1306_draw_string(const ssd1306_t *dev, uint8_t *fb,
if (font == NULL || str == NULL)
return 0;
while (*str)
{
if ((err = ssd1306_draw_char(dev, fb, font, x, y, *str, foreground, background)) < 0 )
while (*str) {
if ((err = ssd1306_draw_char(dev, fb, font, x, y, *str, foreground, background)) < 0)
return err;
x += err;
x += err;
++str;
if (*str)
x += font->c;
@ -1067,13 +1034,11 @@ int ssd1306_start_scroll_hori(const ssd1306_t *dev, bool way, uint8_t start, uin
{
int err;
if (way)
{
if (way) {
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_LEFT)))
return err;
}
else
{
else {
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_RIGHT)))
return err;
}
@ -1089,7 +1054,7 @@ int ssd1306_start_scroll_hori(const ssd1306_t *dev, bool way, uint8_t start, uin
return -EIO;
}
int ssd1306_start_scroll_hori_vert(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, uint8_t dy, ssd1306_scroll_t frame)
int ssd1306_start_scroll_hori_vert(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, uint8_t dy, ssd1306_scroll_t frame)
{
//this function dont work well if no vertical setting.
if ((!dy) || (dy > 63))
@ -1104,13 +1069,11 @@ int ssd1306_start_scroll_hori_vert(const ssd1306_t *dev, bool way, uint8_t star
if ((err = ssd1306_command(dev, dev->height)))
return err;
if (way)
{
if (way) {
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_VER_LEFT)))
return err;
}
else
{
else {
if ((err = ssd1306_command(dev, SSD1306_SCROLL_HOR_VER_RIGHT)))
return err;
}

View file

@ -65,13 +65,16 @@ typedef enum
typedef struct
{
ssd1306_protocol_t protocol;
ssd1306_screen_t screen ;
union {
ssd1306_screen_t screen;
union
{
#if (SSD1306_I2C_SUPPORT)
i2c_dev_t i2c_dev; //!< I2C devuce descriptor, used by SSD1306_PROTO_I2C
#endif
uint8_t cs_pin ; //!< Chip Select GPIO pin, used by SSD1306_PROTO_SPI3, SSD1306_PROTO_SPI4
} ;
#if (SSD1306_SPI4_SUPPORT) || (SSD1306_SPI3_SUPPORT)
uint8_t cs_pin; //!< Chip Select GPIO pin, used by SSD1306_PROTO_SPI3, SSD1306_PROTO_SPI4
#endif
};
#if (SSD1306_SPI4_SUPPORT)
uint8_t dc_pin; //!< Data/Command GPIO pin, used by SSD1306_PROTO_SPI4
#endif
@ -520,7 +523,7 @@ int ssd1306_start_scroll_hori(const ssd1306_t *dev, bool way, uint8_t start, uin
* @param frame Time interval between each scroll
* @return Non-zero if error occured
*/
int ssd1306_start_scroll_hori_vert(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, uint8_t dy, ssd1306_scroll_t frame);
int ssd1306_start_scroll_hori_vert(const ssd1306_t *dev, bool way, uint8_t start, uint8_t stop, uint8_t dy, ssd1306_scroll_t frame);
#ifdef __cplusplus
extern "C"