added gfx (empty test)
working on gfx module added a few draw function gfx still wip added tamplate for test
This commit is contained in:
364
oled/gfx.c
Normal file
364
oled/gfx.c
Normal file
@@ -0,0 +1,364 @@
|
||||
#include "gfx.h"
|
||||
|
||||
/**
|
||||
* @brief Set the pixel
|
||||
*
|
||||
* @param hOled Display object
|
||||
* @param x X coordinate
|
||||
* @param y Y coordinate
|
||||
* @param color Color of pixel WHITE(0), BLACK(1) or INVERSE(2)
|
||||
*/
|
||||
void writePixel(OLED_HandleTypeDef *hOled, uint8_t x, uint8_t y, GFX_Color_t color)
|
||||
{
|
||||
if (x > hOled->Width || y > hOled->Height)
|
||||
return;
|
||||
|
||||
switch (color)
|
||||
{
|
||||
case WHITE:
|
||||
hOled->Buffer[(y / 8) * hOled->Width + x] |= (1 << (y % 8));
|
||||
break;
|
||||
case BLACK:
|
||||
hOled->Buffer[(y / 8) * hOled->Width + x] &= ~(1 << (y % 8));
|
||||
break;
|
||||
case INVERSE:
|
||||
hOled->Buffer[(y / 8) * hOled->Width + x] ^= (1 << (y % 8));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
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 buf_mask_top;
|
||||
uint8_t buf_mask_bottom;
|
||||
uint8_t bitmap_col;
|
||||
uint8_t bitmap_row_first;
|
||||
uint8_t bitmap_row_last;
|
||||
uint8_t bitmap_shift;
|
||||
} buf_bitmap_boundry_t;
|
||||
|
||||
static void _getBoundry(OLED_HandleTypeDef *hOled, 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->bitmap_shift = 8 + (pos_y % 8);
|
||||
boundry->bitmap_row_first = (pos_y / 8) * (-1) + 1;
|
||||
boundry->buf_row_first = 0;
|
||||
boundry->buf_mask_top = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundry->bitmap_shift = pos_y % 8;
|
||||
boundry->bitmap_row_first = 0;
|
||||
boundry->buf_row_first = pos_y / 8;
|
||||
boundry->buf_mask_top = 0xFF >> (8 - boundry->bitmap_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) > hOled->Width)
|
||||
{
|
||||
boundry->buf_col_last = hOled->Width;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundry->buf_col_last = bitmap_width + pos_x;
|
||||
}
|
||||
|
||||
if (bitmap_height + pos_y > hOled->Height)
|
||||
{
|
||||
boundry->buf_row_last = hOled->Height / 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
boundry->buf_row_last = (bitmap_height + pos_y + 7) / 8;
|
||||
}
|
||||
|
||||
boundry->bitmap_row_last = (pos_y + bitmap_height) / 8;
|
||||
boundry->bitmap_max_idx = bitmap_width * ((bitmap_height + 7) / 8);
|
||||
}
|
||||
|
||||
static inline uint8_t _getBitmapByte(const uint8_t *bitmap, uint16_t index, GFX_Color_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
|
||||
* |
|
||||
* |
|
||||
* \ /
|
||||
* y
|
||||
* @param bitmap A pointer to bitmap array.
|
||||
* @param bitmap_width Bitmap witdh in pixels.
|
||||
* @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 NORMAL (2) normal mode or INVERSE(3) mode for bitmap
|
||||
* WHITE (0) or BLACK (1) for fill screen
|
||||
*/
|
||||
void writeBitmap(OLED_HandleTypeDef *hOled, const uint8_t *bitmap, uint8_t bitmap_width, uint8_t bitmap_height, int8_t pos_x, int8_t pos_y, GFX_Color_t color)
|
||||
{
|
||||
if (bitmap_width + pos_x < 0 || bitmap_height + pos_y < 0)
|
||||
return;
|
||||
|
||||
uint16_t tmp_buf16, bitmap_idx, buf_idx;
|
||||
uint8_t tmp_bitmap, bitmap_row;
|
||||
|
||||
buf_bitmap_boundry_t b;
|
||||
_getBoundry(hOled, &b, bitmap_width, bitmap_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;
|
||||
|
||||
if (b.bitmap_row_first > 0)
|
||||
{
|
||||
tmp_buf16 = _getBitmapByte(bitmap, bitmap_width * (b.bitmap_row_first - 1) + b.bitmap_col, color) >> (8 - b.bitmap_shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_buf16 = hOled->Buffer[b.buf_row_first * hOled->Width + 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 * bitmap_row + b.bitmap_col;
|
||||
buf_idx = buf_row * hOled->Width + col;
|
||||
|
||||
if (bitmap_idx < b.bitmap_max_idx)
|
||||
{
|
||||
tmp_bitmap = _getBitmapByte(bitmap, bitmap_idx, color);
|
||||
tmp_buf16 |= tmp_bitmap << b.bitmap_shift;
|
||||
}
|
||||
|
||||
if (b.bitmap_row_last == buf_row)
|
||||
{
|
||||
hOled->Buffer[buf_idx] = (hOled->Buffer[buf_idx] & b.buf_mask_bottom) | (tmp_buf16 & ~(b.buf_mask_bottom));
|
||||
}
|
||||
else
|
||||
{
|
||||
hOled->Buffer[buf_idx] = (uint8_t)tmp_buf16;
|
||||
}
|
||||
tmp_buf16 = tmp_buf16 >> 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void writeSlashLine(OLED_HandleTypeDef *hOled, int16_t x0, int16_t y0, int16_t x1, int16_t y1, GFX_Color_t color)
|
||||
{
|
||||
uint8_t steep = _diff(y1, y0) > _diff(x1, x0); // bool
|
||||
if (steep)
|
||||
{
|
||||
_swap_int16_t(x0, y0);
|
||||
_swap_int16_t(x1, y1);
|
||||
}
|
||||
|
||||
if (x0 > x1)
|
||||
{
|
||||
_swap_int16_t(x0, x1);
|
||||
_swap_int16_t(y0, y1);
|
||||
}
|
||||
|
||||
int16_t dx = x1 - x0;
|
||||
int16_t dy = _diff(y1, y0);
|
||||
int16_t err = dx >> 1;
|
||||
int16_t step = (y0 < y1) ? 1 : -1;
|
||||
|
||||
for (; x0 <= x1; x0++)
|
||||
{
|
||||
if (steep)
|
||||
{
|
||||
writePixel(hOled, y0, x0, color);
|
||||
}
|
||||
else
|
||||
{
|
||||
writePixel(hOled, x0, y0, color);
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0)
|
||||
{
|
||||
err += dx;
|
||||
y0 += step;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Write a perfectly vertical line
|
||||
@param x Top-most x coordinate
|
||||
@param y Top-most y coordinate
|
||||
@param height Height in pixels
|
||||
@param color Color of pixel WHITE(0), BLACK(1) or INVERSE(2)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void writeVerticalLine(OLED_HandleTypeDef *hOled, int16_t x, int16_t y, int16_t height, GFX_Color_t color)
|
||||
{
|
||||
for (int16_t i = y; i < y + height; i++)
|
||||
{
|
||||
writePixel(hOled, x, i, color);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Write a perfectly horizontal line
|
||||
@param x Left-most x coordinate
|
||||
@param y Left-most y coordinate
|
||||
@param width Width in pixels
|
||||
@param color Color of pixel WHITE(0), BLACK(1) or INVERSE(2)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void writeHorizontalLine(OLED_HandleTypeDef *hOled, int16_t x, int16_t y, int16_t width, GFX_Color_t color)
|
||||
{
|
||||
for (int16_t i = x; i < x + width; i++)
|
||||
{
|
||||
writePixel(hOled, i, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
void writeRect(OLED_HandleTypeDef *hOled, int16_t x, int16_t y, int16_t width, int16_t height, GFX_Color_t color)
|
||||
{
|
||||
writeHorizontalLine(hOled, x, y, width, color);
|
||||
writeHorizontalLine(hOled, x, y + height - 1, width, color);
|
||||
writeVerticalLine(hOled, x, y, height, color);
|
||||
writeVerticalLine(hOled, x + width - 1, y, height, color);
|
||||
}
|
||||
|
||||
void writeFillRect(OLED_HandleTypeDef *hOled, int16_t x, int16_t y, int16_t width, int16_t height, GFX_Color_t color)
|
||||
{
|
||||
writeBitmap(hOled, NULL, width, height, x, y, color);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Draw a circle outline
|
||||
@param x0 Center-point x coordinate
|
||||
@param y0 Center-point y coordinate
|
||||
@param radius Radius of circle
|
||||
@param color 16-bit 5-6-5 Color to draw with
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void writeCircle(OLED_HandleTypeDef *hOled, int16_t x0, int16_t y0, uint8_t radius, GFX_Color_t color)
|
||||
{
|
||||
|
||||
int16_t f = 1 - radius;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * radius;
|
||||
int16_t x = 0;
|
||||
int16_t y = radius;
|
||||
|
||||
writePixel(hOled, x0, y0 + radius, color);
|
||||
writePixel(hOled, x0, y0 - radius, color);
|
||||
writePixel(hOled, x0 + radius, y0, color);
|
||||
writePixel(hOled, x0 - radius, y0, color);
|
||||
|
||||
while (x < y)
|
||||
{
|
||||
if (f >= 0)
|
||||
{
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
writePixel(hOled, x0 + x, y0 + y, color);
|
||||
writePixel(hOled, x0 - x, y0 + y, color);
|
||||
writePixel(hOled, x0 + x, y0 - y, color);
|
||||
writePixel(hOled, x0 - x, y0 - y, color);
|
||||
writePixel(hOled, x0 + y, y0 + x, color);
|
||||
writePixel(hOled, x0 - y, y0 + x, color);
|
||||
writePixel(hOled, x0 + y, y0 - x, color);
|
||||
writePixel(hOled, x0 - y, y0 - x, color);
|
||||
}
|
||||
endWrite();
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Quarter-circle drawer, used to do circles and roundrects
|
||||
@param x0 Center-point x coordinate
|
||||
@param y0 Center-point y coordinate
|
||||
@param radius Radius of circle
|
||||
@param corner Mask bit #1 or bit #2 to indicate which quarters of
|
||||
the circle we're doing
|
||||
@param color 16-bit 5-6-5 Color to draw with
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void writeQuarterCircle(OLED_HandleTypeDef *hOled, int16_t x0, int16_t y0, uint8_t radius, CIRC_Corners_t corner, GFX_Color_t color)
|
||||
{
|
||||
int16_t f = 1 - radius;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * radius;
|
||||
int16_t x = 0;
|
||||
int16_t y = radius;
|
||||
|
||||
while (x < y)
|
||||
{
|
||||
if (f >= 0)
|
||||
{
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
if (corner & BOTTOM_LEFT)
|
||||
{
|
||||
writePixel(hOled, x0 + x, y0 + y, color);
|
||||
writePixel(hOled, x0 + y, y0 + x, color);
|
||||
}
|
||||
if (corner & BOTTOM_RIGHT)
|
||||
{
|
||||
writePixel(hOled, x0 + x, y0 - y, color);
|
||||
writePixel(hOled, x0 + y, y0 - x, color);
|
||||
}
|
||||
if (corner & TOP_LEFT)
|
||||
{
|
||||
writePixel(hOled, x0 - y, y0 + x, color);
|
||||
writePixel(hOled, x0 - x, y0 + y, color);
|
||||
}
|
||||
if (corner & TOP_RIGHT)
|
||||
{
|
||||
writePixel(hOled, x0 - y, y0 - x, color);
|
||||
writePixel(hOled, x0 - x, y0 - y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
39
oled/gfx.h
Normal file
39
oled/gfx.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "oled.h"
|
||||
|
||||
#ifndef _swap_int16_t
|
||||
#define _swap_int16_t(a, b) \
|
||||
{ \
|
||||
int16_t t = a; \
|
||||
a = b; \
|
||||
b = t; \
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef _diff
|
||||
#define _diff(a, b) ((a > b) ? (a - b) : (b - a))
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WHITE,
|
||||
BLACK,
|
||||
NORMAL,
|
||||
INVERSE
|
||||
} GFX_Color_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TOP_RIGHT = 1,
|
||||
BOTTOM_RIGHT = 2,
|
||||
BOTTOM_LEFT = 4,
|
||||
TOP_LEFT = 8
|
||||
} CIRC_Corners_t;
|
||||
|
||||
void writePixel(OLED_HandleTypeDef *hOled, uint8_t x, uint8_t y, GFX_Color_t color);
|
||||
void writeBitmap(OLED_HandleTypeDef *hOled, const uint8_t *bitmap, uint8_t bitmap_width, uint8_t bitmap_height, int8_t pos_x, int8_t pos_y, GFX_Color_t color);
|
||||
void writeSlashLine(OLED_HandleTypeDef *hOled, int16_t x0, int16_t y0, int16_t x1, int16_t y1, GFX_Color_t color);
|
||||
void writeVerticalLine(OLED_HandleTypeDef *hOled, int16_t x, int16_t y, int16_t height, GFX_Color_t color);
|
||||
void writeHorizontalLine(OLED_HandleTypeDef *hOled, int16_t x, int16_t y, int16_t width, GFX_Color_t color);
|
||||
void writeRect(OLED_HandleTypeDef *hOled, int16_t x, int16_t y, int16_t width, int16_t height, GFX_Color_t color);
|
||||
void writeCircle(OLED_HandleTypeDef *hOled, int16_t x0, int16_t y0, uint8_t radius, GFX_Color_t color);
|
||||
void writeQuarterCircle(OLED_HandleTypeDef *hOled, int16_t x0, int16_t y0, uint8_t radius, CIRC_Corners_t corner, GFX_Color_t color);
|
||||
@@ -10,12 +10,13 @@ set(INCLUDE_DIRS
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
../../oled/oled.c
|
||||
../../oled/connection.c
|
||||
../../oled/ssd1306/ssd1306.c
|
||||
../../oled/sh1106/sh1106.c
|
||||
# ../../oled/oled.c
|
||||
# ../../oled/connection.c
|
||||
# ../../oled/ssd1306/ssd1306.c
|
||||
# ../../oled/sh1106/sh1106.c
|
||||
|
||||
helpers/src/mock_i2c.c
|
||||
# helpers/src/mock_i2c.c
|
||||
oled_test.c
|
||||
)
|
||||
|
||||
add_definitions(-DTEST)
|
||||
|
||||
26
test/oled/oled_test.c
Normal file
26
test/oled/oled_test.c
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "unity.h"
|
||||
|
||||
|
||||
|
||||
void setUp(void)
|
||||
{
|
||||
}
|
||||
|
||||
void tearDown(void)
|
||||
{
|
||||
}
|
||||
|
||||
void test_one(void)
|
||||
{
|
||||
TEST_FAIL();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_one);
|
||||
|
||||
return UNITY_END();
|
||||
}
|
||||
Reference in New Issue
Block a user