clear_buffer poprawione, dodano color

This commit is contained in:
2021-05-30 15:51:31 +02:00
parent 8189b0b947
commit 218724b5da
6 changed files with 256 additions and 114 deletions

View File

@@ -11,18 +11,18 @@
I2C_HandleTypeDef *oled_i2c;
#ifndef TEST
static uint8_t buffer_oled[SSD1306_BUF_SIZE];
#else
#ifdef TEST
uint8_t buffer_oled[SSD1306_BUF_SIZE];
#else
static uint8_t buffer_oled[SSD1306_BUF_SIZE];
#endif
void SSD1306_SendCommand(uint8_t cmd)
static void SSD1306_SendCommand(uint8_t cmd)
{
HAL_I2C_Mem_Write(oled_i2c, SSD1306_ADDRESS<<1, 0x00, 1, &cmd, 1, SSD1306_TIMEOUT);
}
void SSD1306_SendData(uint8_t *data, uint16_t size)
static void SSD1306_SendData(uint8_t *data, uint16_t size)
{
HAL_I2C_Mem_Write(oled_i2c, SSD1306_ADDRESS<<1, 0x40, 1, data, size, SSD1306_TIMEOUT);
}
@@ -130,7 +130,7 @@ void SSD1306_Init(I2C_HandleTypeDef *i2c)
}
void ssd1306_set_pixel(uint8_t x, uint8_t y, uint8_t bw)
void SSD1306_set_pixel(uint8_t x, uint8_t y, uint8_t bw)
{
if (x > SSD1306_LCDWIDTH || y > SSD1306_LCDHEIGHT) return;
@@ -205,37 +205,84 @@ void ssd1306_set_pixel(uint8_t x, uint8_t y, uint8_t bw)
// }
// }
void ssd1306_clear_buffer (uint8_t width, uint8_t height, uint8_t pos_x, uint8_t pos_y)
// void ssd1306_clear_buffer (uint8_t width, uint8_t height, uint8_t pos_x, uint8_t pos_y)
// {
// uint16_t max_x, max_y, index = 0, temp, row = 0;
// if (width + pos_x > SSD1306_LCDWIDTH) max_x = SSD1306_LCDWIDTH;
// else max_x = width + pos_x;
// if (height + pos_y > SSD1306_LCDHEIGHT) max_y = SSD1306_LCDHEIGHT;
// else max_y = height + pos_y;
// max_y = max_y / 8 + (max_y % 8 == 0 ? 0 : 1);
// uint8_t shift = pos_y % 8;
// uint8_t mask_right = 0xFF >> shift;
// uint8_t mask_left = 0xFF << (8 - shift);
// for (uint8_t y = pos_y / 8; y < max_y; y++, index = width * row)
// {
// for (uint8_t x = pos_x; x < max_x; x++, index++)
// {
// temp = buffer_oled[y * SSD1306_LCDWIDTH + x];
// if (index < width * height/8)
// temp &= mask_left;
// if (index >= width)
// temp &= mask_right;
// buffer_oled[y * SSD1306_LCDWIDTH + x] = temp;
// }
// row++;
// }
// }
typedef struct
{
uint16_t max_x, max_y, index = 0, temp, row = 0;
if (width + pos_x > SSD1306_LCDWIDTH) max_x = SSD1306_LCDWIDTH;
else max_x = width + pos_x;
uint16_t bitmap_max_idx;
uint8_t buf_row_first;
uint8_t buf_row_last;
uint8_t buf_col_first;
uint8_t buf_col_last;
uint8_t bitmap_col;
uint8_t bitmap_row;
uint8_t bitmap_row_first;
uint8_t shift;
}buf_bitmap_boundry_t;
if (height + pos_y > SSD1306_LCDHEIGHT) max_y = SSD1306_LCDHEIGHT;
else max_y = height + pos_y;
max_y = max_y / 8 + (max_y % 8 == 0 ? 0 : 1);
uint8_t shift = pos_y % 8;
uint8_t mask_right = 0xFF >> shift;
uint8_t mask_left = 0xFF << (8 - shift);
for (uint8_t y = pos_y / 8; y < max_y; y++, index = width * row)
{
for (uint8_t x = pos_x; x < max_x; x++, index++)
{
temp = buffer_oled[y * SSD1306_LCDWIDTH + x];
if (index < width * height/8)
temp &= mask_left;
if (index >= width)
temp &= mask_right;
buffer_oled[y * SSD1306_LCDWIDTH + x] = temp;
}
row++;
static void get_boundry (buf_bitmap_boundry_t* boundry, uint8_t bitmap_width, uint8_t bitmap_height, int8_t pos_x, int8_t pos_y)
{
if (pos_x < 0) {
boundry->bitmap_col = pos_x * -1;
boundry->buf_col_first = 0;
} else {
boundry->bitmap_col = 0;
boundry->buf_col_first = pos_x;
}
}
if (pos_y < 0) {
boundry->shift = (pos_y * -1);
boundry->bitmap_row_first = boundry->shift / 8;
boundry->buf_row_first = 0;
} else {
boundry->shift = pos_y;
boundry->bitmap_row_first = 0;
boundry->buf_row_first = pos_y / 8;
}
if ((bitmap_width + pos_x) > SSD1306_LCDWIDTH) {
boundry->buf_col_last = SSD1306_LCDWIDTH;
} else {
boundry->buf_col_last = bitmap_width + pos_x;
}
if (bitmap_height + pos_y > SSD1306_LCDHEIGHT) {
boundry->buf_row_last = SSD1306_LCDHEIGHT / 8;
} else {
boundry->buf_row_last = (bitmap_height + pos_y + 7) / 8;
}
boundry->bitmap_max_idx = bitmap_width * ((bitmap_height + 7) / 8);
}
/**
* @brief A function that writes a bitmap into the buffer at the given position.
* 0,0 -------->x
@@ -248,74 +295,54 @@ void ssd1306_clear_buffer (uint8_t width, uint8_t height, uint8_t pos_x, uint8_t
* @param bitmap_height Bitmap height in pixels.
* @param pos_x Position x in the display
* @param pos_y Position y in the display
* @param color WHITE (1) normal mode, others will cause inverse mode
*/
void SSD1306_write_to_buffer(const uint8_t* bitmap, uint8_t bitmap_width, uint8_t bitmap_height, int8_t pos_x, int8_t pos_y)
void SSD1306_write_to_buffer(const uint8_t* bitmap, uint8_t bitmap_width, uint8_t bitmap_height, int8_t pos_x, int8_t pos_y, uint8_t color)
{
if (bitmap_width + pos_x < 0 || bitmap_height + pos_y < 0) return;
uint16_t tmp_buf16, bitmap_idx, bitmap_max_idx;
uint8_t buf_row_first, buf_row_last, buf_col_first, buf_col_last;
uint8_t bitmap_col, bitmap_row, bitmap_row_first;
uint8_t mask_buf, shift;
uint16_t tmp_buf16, bitmap_idx;
uint8_t mask_buf, tmp_bitmap;
if (pos_x < 0) {
bitmap_col = pos_x * -1;
buf_col_first = 0;
} else {
bitmap_col = 0;
buf_col_first = pos_x;
}
buf_bitmap_boundry_t b;
get_boundry(&b, bitmap_width, bitmap_height, pos_x, pos_y);
if (pos_y < 0) {
shift = (pos_y * -1);
bitmap_row_first = shift / 8;
buf_row_first = 0;
} else {
shift = pos_y;
bitmap_row_first = 0;
buf_row_first = pos_y / 8;
}
if ((bitmap_width + pos_x) > SSD1306_LCDWIDTH) {
buf_col_last = SSD1306_LCDWIDTH;
} else {
buf_col_last = bitmap_width + pos_x;
}
if (bitmap_height + pos_y > SSD1306_LCDHEIGHT) {
buf_row_last = SSD1306_LCDHEIGHT / 8;
} else {
buf_row_last = (bitmap_height + pos_y + 7) / 8;
}
bitmap_max_idx = bitmap_width * ((bitmap_height + 7) / 8);
for(uint8_t col = buf_col_first; col < buf_col_last; col++, bitmap_col++)
for(uint8_t col = b.buf_col_first; col < b.buf_col_last; col++, b.bitmap_col++)
{
tmp_buf16 = 0;
bitmap_row = bitmap_row_first;
for( uint8_t buf_row = buf_row_first; buf_row < buf_row_last; buf_row++, bitmap_row++ )
b.bitmap_row = b.bitmap_row_first;
for( uint8_t buf_row = b.buf_row_first; buf_row < b.buf_row_last; buf_row++, b.bitmap_row++ )
{
bitmap_idx = bitmap_width * bitmap_row + bitmap_col;
bitmap_idx = bitmap_width * b.bitmap_row + b.bitmap_col;
mask_buf = 0;
if (bitmap_row == 0 && pos_y > 0) {
mask_buf |= 0xFF >> (8 - (shift % 8));
if (b.bitmap_row == 0 && pos_y > 0) {
mask_buf |= 0xFF >> (8 - (b.shift % 8));
}
uint8_t shifted_pixels_left = (pos_y + bitmap_height) - bitmap_row * 8;
uint8_t shifted_pixels_left = (pos_y + bitmap_height) - b.bitmap_row * 8;
if (shifted_pixels_left < 8) {
mask_buf |= (0xFF << shifted_pixels_left);
}
tmp_buf16 |= buffer_oled[buf_row * SSD1306_LCDWIDTH + col] & mask_buf;
if (bitmap_idx < bitmap_max_idx)
if (bitmap_idx < b.bitmap_max_idx)
{
switch (color)
{
case WHITE:
tmp_bitmap = bitmap[bitmap_idx];
break;
default:
tmp_bitmap = ~(bitmap[bitmap_idx]);
break;
}
if (pos_y < 0) {
tmp_buf16 |= bitmap[bitmap_idx] >> (shift % 8);
tmp_buf16 |= tmp_bitmap >> (b.shift % 8);
} else {
tmp_buf16 |= bitmap[bitmap_idx] << (shift % 8);
tmp_buf16 |= tmp_bitmap << (b.shift % 8);
}
}
@@ -325,4 +352,57 @@ void SSD1306_write_to_buffer(const uint8_t* bitmap, uint8_t bitmap_width, uint8_
}
}
void SSD1306_clear_buffer(uint8_t width, uint8_t height, int8_t pos_x, int8_t pos_y, uint8_t color)
{
if (width + pos_x < 0 || height + pos_y < 0) return;
uint16_t tmp_buf16, bitmap_idx;
uint8_t mask_buf;
switch(color)
{
case WHITE:
color = 0xFF;
break;
case BLACK:
color = 0x00;
break;
}
buf_bitmap_boundry_t b;
get_boundry(&b, width, height, pos_x, pos_y);
for(uint8_t col = b.buf_col_first; col < b.buf_col_last; col++, b.bitmap_col++)
{
tmp_buf16 = 0;
b.bitmap_row = b.bitmap_row_first;
for( uint8_t buf_row = b.buf_row_first; buf_row < b.buf_row_last; buf_row++, b.bitmap_row++ )
{
bitmap_idx = width * b.bitmap_row + b.bitmap_col;
mask_buf = 0;
if (b.bitmap_row == 0 && pos_y > 0) {
mask_buf |= 0xFF >> (8 - (b.shift % 8));
}
uint8_t shifted_pixels_left = (pos_y + height) - b.bitmap_row * 8;
if (shifted_pixels_left < 8) {
mask_buf |= (0xFF << shifted_pixels_left);
}
tmp_buf16 |= buffer_oled[buf_row * SSD1306_LCDWIDTH + col] & mask_buf;
if (bitmap_idx < b.bitmap_max_idx)
{
if (pos_y < 0) {
tmp_buf16 |= color >> (b.shift % 8);
} else {
tmp_buf16 |= color << (b.shift % 8);
}
}
buffer_oled[buf_row * SSD1306_LCDWIDTH + col] = (uint8_t) tmp_buf16;
tmp_buf16 = tmp_buf16 >> 8;
}
}
}