Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add round rectangle #9

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 182 additions & 0 deletions oled.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,188 @@ OLED_err OLED_put_pixel(OLED *oled, uint8_t x, uint8_t y, bool pixel_state)
}


/**************************************************************************/
/*!
@brief Draw a rounded rectangle with no fill color
@param oled Display data struct
@param x_from Top left corner x coordinate
@param y_from Top left corner y coordinate
@param x_to Width in pixels
@param y_to Height in pixels
@param r Radius of corner rounding
@param params Color and fill
*/
/**************************************************************************/
OLED_err OLED_put_roundRect(OLED* oled, uint8_t x_from, uint8_t y_from, uint8_t x_to, uint8_t y_to, uint8_t r, enum OLED_params params)
{

if (params > (OLED_BLACK | OLED_FILL))
return OLED_EPARAMS;
bool pixel_color = (OLED_BLACK & params) != 0;
bool is_fill = (OLED_FILL & params) != 0;

/* Limit coordinates to display bounds */
uint8_t size_errors = 0;
uint8_t w_max = oled->width - 1;
uint8_t h_max = oled->height - 1;
if (x_from > w_max) {
x_from = w_max;
size_errors++;
}
if (x_to > w_max) {
x_to = w_max;
size_errors++;
}
if (y_from > h_max) {
y_from = h_max;
size_errors++;
}
if (y_to > h_max) {
y_to = h_max;
size_errors++;
}
/* If all coordinates are out of bounds */
if (size_errors >= 4)
return OLED_EBOUNDS;

//OLED_WITH_SPINLOCK(oled) {
/* Normalize coordinates */
/* start_@ indicates coordinates of upper left corner */
/* stop_@ indicates coordinates of bottom right corner */
uint8_t start_x = x_from; /* x min */
uint8_t start_y = y_from;
uint8_t stop_x = x_to; /* x max */
uint8_t stop_y = y_to; /* y max */

if (is_fill) {
/* Fill whole area */
for (uint8_t x = start_x + r; x <= stop_x + r; x++) {
for (uint8_t y = start_y; y <= stop_y + 2 * r; y++) {
OLED_put_pixel_(oled, x, y, pixel_color);
}
}
fillCircleHelper(oled, start_x + stop_x - r - 1, start_y + r, r, 1, stop_y - 2 * r - 1, pixel_color);
fillCircleHelper(oled, start_x + r, start_y + r, r, 2, stop_y - 2 * r - 1, pixel_color);
}
else {
/* Draw outer frame */
for (uint8_t x = start_x; x <= stop_x; x++) {
OLED_put_pixel_(oled, x + r, start_y, pixel_color);
OLED_put_pixel_(oled, x + r, stop_y + r * 2, pixel_color);
}
for (uint8_t y = start_y; y <= stop_y; y++) {
OLED_put_pixel_(oled, start_x, y + r, pixel_color);
OLED_put_pixel_(oled, stop_x + 2 * r, y + r, pixel_color);
}

drawCircleHelper(oled, x_from + r, start_y + r, r, 1, pixel_color);
drawCircleHelper(oled, start_x + stop_x - r - 1, start_y + r, r, 2, pixel_color);
drawCircleHelper(oled, start_x + stop_x - r - 1, start_y + stop_y - r - 1, r, 4, pixel_color);
drawCircleHelper(oled, start_x + r, start_y + stop_y - r - 1, r, 8, pixel_color);
}

return OLED_EOK;
}
/**************************************************************************/
/*!
@brief Quarter-circle drawer, used to do circles and roundrects
@param oled Display data struct
@param x0 Center-point x coordinate
@param y0 Center-point y coordinate
@param r Radius of circle
@param cornername Mask bit #1 or bit #2 to indicate which quarters of the circle we're doing
@param params Color and fill
*/
/**************************************************************************/
OLED_err drawCircleHelper(OLED* oled, int16_t x0, int16_t y0, int16_t r, uint8_t cornername, enum OLED_params params)
{

if (params > (OLED_BLACK | OLED_FILL))
return OLED_EPARAMS;
bool pixel_color = (OLED_BLACK & params) != 0;

int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;

while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
if (cornername & 0x4) {
OLED_put_pixel_(oled, x0 + x, y0 + y, pixel_color);
OLED_put_pixel_(oled, x0 + y, y0 + x, pixel_color);
}
if (cornername & 0x2) {
OLED_put_pixel_(oled, x0 + x, y0 - y, pixel_color);
OLED_put_pixel_(oled, x0 + y, y0 - x, pixel_color);
}
if (cornername & 0x8) {
OLED_put_pixel_(oled, x0 - y, y0 + x, pixel_color);
OLED_put_pixel_(oled, x0 - x, y0 + y, pixel_color);
}
if (cornername & 0x1) {
OLED_put_pixel_(oled, x0 - y, y0 - x, pixel_color);
OLED_put_pixel_(oled, x0 - x, y0 - y, pixel_color);
}
}
return OLED_EOK;
}
/**************************************************************************/
/*!
@brief Quarter-circle drawer with fill, used to do circles and roundrects
@param oled Display data struct
@param x0 Center-point x coordinate
@param y0 Center-point y coordinate
@param r Radius of circle
@param cornername Mask bit #1 or bit #2 to indicate which quarters of the circle we're doing
@param delta Offset from center-point, used for round-rects
@param params Color and fill
*/
/**************************************************************************/
OLED_err fillCircleHelper(OLED* oled, int16_t x0, int16_t y0, int16_t r, uint8_t cornername, int16_t delta, enum OLED_params params)
{

if (params > (OLED_BLACK | OLED_FILL))
return OLED_EPARAMS;
bool pixel_color = (OLED_BLACK & params) != 0;

int16_t f = 1 - r;
int16_t ddF_x = 1;
int16_t ddF_y = -2 * r;
int16_t x = 0;
int16_t y = r;

while (x < y) {
if (f >= 0) {
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;

if (cornername & 0x1) {
OLED_put_line(oled, x0 + x, y0 - y, x0 + x, y0 - y + (2 * y + 1 + delta) - 1, OLED_FILL | params);
OLED_put_line(oled, x0 + y, y0 - x, x0 + y, y0 - x + (2 * x + 1 + delta) - 1, OLED_FILL | params);
}
if (cornername & 0x2) {
OLED_put_line(oled, x0 - x, y0 - y, x0 - x, y0 - y + (2 * y + 1 + delta) - 1, OLED_FILL | params);
OLED_put_line(oled, x0 - y, y0 - x, x0 - y, y0 - x + (2 * x + 1 + delta) - 1, OLED_FILL | params);
}
}
return OLED_EOK;
}


OLED_err OLED_put_rectangle(OLED *oled, uint8_t x_from, uint8_t y_from, uint8_t x_to, uint8_t y_to, enum OLED_params params)
{
if (params > (OLED_BLACK | OLED_FILL))
Expand Down
6 changes: 5 additions & 1 deletion oled.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,4 +275,8 @@ OLED_err OLED_put_pixel(OLED *oled, uint8_t x, uint8_t y, bool pixel_state);
*
* (!) Notice: method is not atomic. If required, protect it with lock
*/
OLED_err OLED_put_rectangle(OLED *oled, uint8_t x_from, uint8_t y_from, uint8_t x_to, uint8_t y_to, enum OLED_params params);
OLED_err OLED_put_rectangle(OLED *oled, uint8_t x_from, uint8_t y_from, uint8_t x_to, uint8_t y_to, enum OLED_params params);

OLED_err OLED_put_roundRect(OLED *oled, uint8_t x_from, uint8_t y_from, uint8_t x_to, uint8_t y_to, uint8_t r, enum OLED_params params);
OLED_err fillCircleHelper(OLED *oled, int16_t x0, int16_t y0, int16_t r,uint8_t cornername, int16_t delta, enum OLED_params params);
OLED_err drawCircleHelper(OLED *oled, int16_t x0, int16_t y0, int16_t r, uint8_t cornername, enum OLED_params params);
87 changes: 24 additions & 63 deletions oled_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,67 +6,28 @@

int main()
{
/* output by letter? (not related to lib) */
bool byletter = false;

sei();
OLED oled;
uint8_t fb[1024] = {0};
OLED_init(&oled, 128, 64, fb, 200000, 0b0111100);

/* Try to decrease frequency and see what happens without lock */
OLED_WITH_SPINLOCK(&oled) {
OLED_put_rectangle(&oled, 0, 0, 127, 63, OLED_FILL | 0);
OLED_put_rectangle(&oled, 2, 2, 125, 61, OLED_FILL | 1);
OLED_put_rectangle(&oled, 4, 4, 123, 57, 0);
}
if (byletter) OLED_refresh(&oled);

// T letter drawn with rectangles
OLED_put_rectangle(&oled, 17, 22, 30, 25, OLED_FILL | 0);
OLED_put_rectangle(&oled, 22, 26, 25, 39, OLED_FILL | 0);
if (byletter) OLED_refresh(&oled);

// E letter drawn with rectangles
OLED_put_rectangle(&oled, 34, 22, 45, 39, OLED_FILL | 0);
OLED_put_rectangle(&oled, 38, 26, 45, 28, OLED_FILL | 1);
OLED_put_rectangle(&oled, 42, 29, 45, 32, OLED_FILL | 1);
OLED_put_rectangle(&oled, 38, 33, 45, 35, OLED_FILL | 1);
if (byletter) OLED_refresh(&oled);

// S letter drawn with rectangles
OLED_put_rectangle(&oled, 48, 22, 59, 39, OLED_FILL | 0);
OLED_put_rectangle(&oled, 52, 26, 59, 28, OLED_FILL | 1);
OLED_put_rectangle(&oled, 48, 33, 55, 35, OLED_FILL | 1);
if (byletter) OLED_refresh(&oled);

// T letter drawn with rectangles
OLED_put_rectangle(&oled, 62, 22, 75, 25, OLED_FILL | 0);
OLED_put_rectangle(&oled, 67, 25, 70, 39, OLED_FILL | 0);
if (byletter) OLED_refresh(&oled);

// O letter drawn with rectangles
OLED_put_rectangle(&oled, 86, 22, 96, 39, OLED_FILL | 0);
OLED_put_rectangle(&oled, 89, 25, 93, 36, OLED_FILL | 1);
if (byletter) OLED_refresh(&oled);

// K letter drawn with rectangles
OLED_put_rectangle(&oled, 99, 22, 102, 39, OLED_FILL | OLED_WHITE);
OLED_put_rectangle(&oled, 105, 31, 100, 28, OLED_FILL | OLED_WHITE);
OLED_put_rectangle(&oled, 109, 32, 106, 39, OLED_FILL | OLED_WHITE);
OLED_put_rectangle(&oled, 104, 30, 107, 33, OLED_FILL | OLED_WHITE);
OLED_put_rectangle(&oled, 107, 29, 104, 26, OLED_FILL | OLED_WHITE);
OLED_put_rectangle(&oled, 109, 27, 106, 22, OLED_FILL | OLED_WHITE);

if (byletter) OLED_refresh(&oled);

bool color = OLED_BLACK;
while (1) {
/* Horizontal line of 1 px width */
OLED_WITH_SPINLOCK(&oled) {
OLED_put_rectangle(&oled, 10, 47, 117, 47, color);
}
color = !color;
OLED_refresh(&oled);
}
/* output by letter? (not related to lib) */
bool byletter = false;

sei();
OLED oled;
uint8_t fb[1024] = {0};
OLED_init(&oled, 128, 64, fb, 200000, 0b0111100);

/* Try to decrease frequency and see what happens without lock */
OLED_WITH_SPINLOCK(&oled) {
OLED_put_rectangle(&oled, 0, 0, 127, 63, OLED_FILL | 0);
OLED_put_rectangle(&oled, 2, 2, 125, 61, OLED_FILL | 1);
OLED_put_rectangle(&oled, 4, 4, 123, 57, 0);
}
if (byletter) OLED_refresh(&oled);
OLED_WITH_SPINLOCK(&oled) {
OLED_put_roundRect(&oled, 10, 10, 40, 20, 5, OLED_FILL | 0 );
OLED_put_roundRect(&oled, 14, 14, 90, 25, 7, 0);
//OLED_put_line(&oled,10, 10, 120, 25, OLED_FILL | 0 );
}
OLED_refresh(&oled);

while (1) {
}
}