diff --git a/Core/Inc/SSD1306_oled.h b/Core/Inc/SSD1306_oled.h index 5e8f0ab..b8ac233 100644 --- a/Core/Inc/SSD1306_oled.h +++ b/Core/Inc/SSD1306_oled.h @@ -29,13 +29,15 @@ #define BLACK SSD1306_BLACK ///< Draw 'off' pixels #define WHITE SSD1306_WHITE ///< Draw 'on' pixels +#define NORMAL SSD1306_NORMAL #define INVERSE SSD1306_INVERSE ///< Invert pixels #define SSD1306_ADDRESS 0x3C #define SSD1306_TIMEOUT 100 #define SSD1306_BLACK 0 ///< Draw 'off' pixels #define SSD1306_WHITE 1 ///< Draw 'on' pixels -#define SSD1306_INVERSE 2 ///< Invert pixels +#define SSD1306_NORMAL 2 +#define SSD1306_INVERSE 3 ///< Invert pixels #define SSD1306_MEMORYMODE 0x20 ///< See datasheet #define SSD1306_COLUMNADDR 0x21 ///< See datasheet diff --git a/Core/Src/SSD1306_oled.c b/Core/Src/SSD1306_oled.c index afdecfe..01dd8b7 100644 --- a/Core/Src/SSD1306_oled.c +++ b/Core/Src/SSD1306_oled.c @@ -243,9 +243,11 @@ typedef struct uint8_t buf_row_last; uint8_t buf_col_first; uint8_t buf_col_last; + uint8_t buf_mask_top; + uint8_t buf_mask_bottom; uint8_t bitmap_col; - uint8_t bitmap_row; uint8_t bitmap_row_first; + uint8_t bitmap_row_last; uint8_t shift; }buf_bitmap_boundry_t; @@ -260,13 +262,20 @@ static void get_boundry (buf_bitmap_boundry_t* boundry, uint8_t bitmap_width, ui } if (pos_y < 0) { - boundry->shift = (pos_y * -1); - boundry->bitmap_row_first = boundry->shift / 8; + boundry->shift = 8 + (pos_y % 8) ; + boundry->bitmap_row_first = (pos_y / 8) * (-1) + 1; boundry->buf_row_first = 0; + boundry->buf_mask_top = 0; + // boundry->buf_mask_bottom = 0xFF << ((pos_y + bitmap_height) % 8); } else { - boundry->shift = pos_y; + boundry->shift = pos_y % 8; boundry->bitmap_row_first = 0; boundry->buf_row_first = pos_y / 8; + boundry->buf_mask_top = 0xFF >> (8 - boundry->shift); + } + boundry->buf_mask_bottom = 0xFF << ((pos_y + bitmap_height) % 8); + if (boundry->buf_mask_bottom == 0xFF) { + boundry->buf_mask_bottom = 0; } if ((bitmap_width + pos_x) > SSD1306_LCDWIDTH) { @@ -281,8 +290,24 @@ static void get_boundry (buf_bitmap_boundry_t* boundry, uint8_t bitmap_width, ui boundry->buf_row_last = (bitmap_height + pos_y + 7) / 8; } + boundry->bitmap_row_last = (bitmap_height + 7) / 8; boundry->bitmap_max_idx = bitmap_width * ((bitmap_height + 7) / 8); } + +uint8_t get_bitmap_byte (const uint8_t* bitmap, uint16_t index, uint8_t color) +{ + switch (color) + { + case INVERSE: + return ~(bitmap[index]); + case WHITE: + return 0xFF; + case BLACK: + return 0x00; + default: + return bitmap[index]; + } +} /** * @brief A function that writes a bitmap into the buffer at the given position. * 0,0 -------->x @@ -295,14 +320,15 @@ static void get_boundry (buf_bitmap_boundry_t* boundry, uint8_t bitmap_width, ui * @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 + * @param color NORMAL (2) normal mode or INVERSE mode for bitmap + * WHITE (0) or black (1) for fill screen */ 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; - uint8_t mask_buf, tmp_bitmap; + uint16_t tmp_buf16, bitmap_idx, buf_idx; + uint8_t mask_buf, tmp_bitmap, bitmap_row; buf_bitmap_boundry_t b; get_boundry(&b, bitmap_width, bitmap_height, pos_x, pos_y); @@ -310,43 +336,56 @@ void SSD1306_write_to_buffer(const uint8_t* bitmap, uint8_t bitmap_width, uint8_ 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_row = b.bitmap_row_first; + + if (b.bitmap_row_first > 0) { + tmp_buf16 = get_bitmap_byte(bitmap, bitmap_width * (b.bitmap_row_first - 1) + b.bitmap_col, color) >> (8 - b.shift); + } else { + tmp_buf16 = buffer_oled[b.buf_row_first * SSD1306_LCDWIDTH + col] & b.buf_mask_top; + } + + for( uint8_t buf_row = b.buf_row_first; buf_row < b.buf_row_last; buf_row++, bitmap_row++ ) { - bitmap_idx = bitmap_width * b.bitmap_row + b.bitmap_col; - mask_buf = 0; + bitmap_idx = bitmap_width * bitmap_row + b.bitmap_col; + buf_idx = buf_row * SSD1306_LCDWIDTH + col; + // mask_buf = 0; + + // if (bitmap_row == b.bitmap_row_first) { + // mask_buf |= b.buf_mask_bottom; + // } + + // uint8_t shifted_pixels_left = (pos_y%8 + bitmap_height) - bitmap_row * 8; + // if (shifted_pixels_left < 8) { + // mask_buf |= (0xFF << shifted_pixels_left); + // } + + // if (bitmap_height < (bitmap_row +1 ) * 8) { + // mask_buf |= b.buf_mask_top; + // } - if (b.bitmap_row == 0 && pos_y > 0) { - mask_buf |= 0xFF >> (8 - (b.shift % 8)); - } - uint8_t shifted_pixels_left = (pos_y%8 + 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 < 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 |= (tmp_bitmap >> (b.shift % 8)) & ~(mask_buf); - } else { - tmp_buf16 |= (tmp_bitmap << (b.shift % 8)) & ~(mask_buf); - } + // if (bitmap_row == b.bitmap_row_first && pos_y < 0) { + // tmp_buf16 |= (tmp_bitmap >> (8 - b.shift));// & ~(mask_buf); + // bitmap_row++; + // } + tmp_bitmap = get_bitmap_byte(bitmap, bitmap_idx, color); + tmp_buf16 |= tmp_bitmap << b.shift; } - buffer_oled[buf_row * SSD1306_LCDWIDTH + col] = (uint8_t) tmp_buf16; + // if (buf_row + 1 == b.buf_row_last && bitmap_row + 1 >= b.bitmap_row_last) { + if ( (pos_y + bitmap_height) / 8 == buf_row) { + buffer_oled[buf_idx] = (buffer_oled[buf_idx] & b.buf_mask_bottom) | (tmp_buf16 & ~(b.buf_mask_bottom)); + } else { + buffer_oled[buf_idx] = (uint8_t) tmp_buf16; + } + // tmp_buf16 = (buffer_oled[buf_idx] & mask_buf) | (tmp_buf16 & ~(mask_buf)); + // buffer_oled[buf_idx] = (uint8_t) tmp_buf16; tmp_buf16 = tmp_buf16 >> 8; } } @@ -354,56 +393,59 @@ 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; - uint16_t mask_buf; - uint8_t bitmap_row; - - 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; - bitmap_row = b.bitmap_row_first; - for( uint8_t buf_row = b.buf_row_first; buf_row < b.buf_row_last; buf_row++, bitmap_row++ ) - { - bitmap_idx = width * bitmap_row + b.bitmap_col; - mask_buf = 0; - - if (bitmap_row == 0 && pos_y > 0) { - mask_buf |= 0xFF >> (8 - (b.shift % 8)); - } - - uint8_t shifted_pixels_left = (pos_y%8 + height) - 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)) & ~(mask_buf); - } else { - tmp_buf16 |= (color << (b.shift % 8)) & ~(mask_buf); - } - } - - buffer_oled[buf_row * SSD1306_LCDWIDTH + col] = (uint8_t) tmp_buf16; - tmp_buf16 = tmp_buf16 >> 8; - } - } + SSD1306_write_to_buffer(NULL, width, height, pos_x, pos_y, color); } +// { +// if (width + pos_x < 0 || height + pos_y < 0) return; + +// uint16_t tmp_buf16, bitmap_idx; +// uint16_t mask_buf; +// uint8_t bitmap_row; + +// 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; +// bitmap_row = b.bitmap_row_first; +// for( uint8_t buf_row = b.buf_row_first; buf_row < b.buf_row_last; buf_row++, bitmap_row++ ) +// { +// bitmap_idx = width * bitmap_row + b.bitmap_col; +// mask_buf = 0; + +// if (bitmap_row == 0 && pos_y > 0) { +// mask_buf |= 0xFF >> (8 - (b.shift % 8)); +// } + +// uint8_t shifted_pixels_left = (pos_y%8 + height) - 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)) & ~(mask_buf); +// } else { +// tmp_buf16 |= (color << (b.shift % 8)) & ~(mask_buf); +// } +// } + +// buffer_oled[buf_row * SSD1306_LCDWIDTH + col] = (uint8_t) tmp_buf16; +// tmp_buf16 = tmp_buf16 >> 8; +// } +// } +// } diff --git a/test/test_SSD1306_oled.c b/test/test_SSD1306_oled.c index 04a7ef8..1a76773 100644 --- a/test/test_SSD1306_oled.c +++ b/test/test_SSD1306_oled.c @@ -18,105 +18,105 @@ void tearDown(void) void test_wrtie_to_buffer_at_pos_0_0_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, 0, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, 0, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_0_8pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_1_0_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, 1, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, 1, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_1_8pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_7_0_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, 7, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, 7, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_7_8pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_0_0_height_16pt(void) { - SSD1306_write_to_buffer(picture_16pt, SSD1306_LCDWIDTH, 16, 0, 0, WHITE); + SSD1306_write_to_buffer(picture_16pt, SSD1306_LCDWIDTH, 16, 0, 0, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_0_16pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_1_0_height_16pt(void) { - SSD1306_write_to_buffer(picture_16pt, SSD1306_LCDWIDTH, 16, 0, 1, WHITE); + SSD1306_write_to_buffer(picture_16pt, SSD1306_LCDWIDTH, 16, 0, 1, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_1_16pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_7_0_height_16pt(void) { - SSD1306_write_to_buffer(picture_16pt, SSD1306_LCDWIDTH, 16, 0, 7, WHITE); + SSD1306_write_to_buffer(picture_16pt, SSD1306_LCDWIDTH, 16, 0, 7, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_7_16pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_0_0_height_12pt(void) { - SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 0, WHITE); + SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 0, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_0_12pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_1_0_height_12pt(void) { - SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 1, WHITE); + SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 1, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_1_12pt, buffer_oled, SSD1306_BUF_SIZE); } -void test_wrtie_to_buffer_at_pos_0_4_height_12pt(void) +void test_wrtie_to_buffer_at_pos_4_0_height_12pt(void) { - SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 4, WHITE); + SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 4, NORMAL); TEST_ASSERT_EQUAL_UINT8_ARRAY(posX_0_posY_4_12pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_7_0_height_12pt(void) { - SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 7, WHITE); + SSD1306_write_to_buffer(picture_12pt, SSD1306_LCDWIDTH, 12, 0, 7, NORMAL); TEST_ASSERT_EQUAL_HEX8_ARRAY(posX_0_posY_7_12pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_minus1_0_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, -1, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, -1, NORMAL); TEST_ASSERT_EQUAL_HEX8_ARRAY(posX_0_posY_minus1_8pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_minus7_0_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, -7, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, -7, NORMAL); TEST_ASSERT_EQUAL_HEX8_ARRAY(posX_0_posY_minus7_8pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_minus8_0_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, -8, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, 0, -8, NORMAL); TEST_ASSERT_EQUAL_HEX8_ARRAY(buffer_oled, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_0_minus1_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, -1, 0, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, -1, 0, NORMAL); TEST_ASSERT_EQUAL_HEX8_ARRAY(posX_minus1_posY_0_8pt, buffer_oled, SSD1306_BUF_SIZE); } void test_wrtie_to_buffer_at_pos_60_minus1_height_8pt(void) { - SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, -1, 60, WHITE); + SSD1306_write_to_buffer(picture_8pt, SSD1306_LCDWIDTH, 8, -1, 60, NORMAL); TEST_ASSERT_EQUAL_HEX8_ARRAY(posX_minus1_posY_60_8pt, buffer_oled, SSD1306_BUF_SIZE); }