0,0 → 1,509 |
#include "maindefs.h" |
#include "Adafruit_GFX.h" |
#include "glcdfont.c" |
#include "oled_ssd1306.h" |
#include "oled_ssd1331.h" |
#include <string.h> |
#include <stdio.h> |
|
static GFX_DATA gfx_data; |
|
void GFX_Init(int w, int h) { |
gfx_data._width = gfx_data.WIDTH = w; |
gfx_data._height = gfx_data.HEIGHT = h; |
gfx_data.rotation = 0; |
gfx_data.cursor_x = gfx_data.cursor_y = 0; |
gfx_data.textsize = 1; |
gfx_data.textcolor = gfx_data.textbgcolor = 0xFFFF; |
gfx_data.wrap = 1; |
} |
|
int GFX_Abs(int i) { |
if (i < 0) |
return -i; |
else |
return i; |
} |
|
void GFX_Swap(int *a, int *b) { |
int tmp = *a; |
*a = *b; |
*b = tmp; |
} |
|
void GFX_drawLine(int x0, int y0, int x1, int y1, unsigned int color) { |
#ifdef GFX_SSD1306 |
int dx, dy, err, ystep; |
int steep = GFX_Abs(y1 - y0) > GFX_Abs(x1 - x0); |
if (steep) { |
GFX_Swap(&x0, &y0); |
GFX_Swap(&x1, &y1); |
} |
|
if (x0 > x1) { |
GFX_Swap(&x0, &x1); |
GFX_Swap(&y0, &y1); |
} |
|
dx = x1 - x0; |
dy = GFX_Abs(y1 - y0); |
|
err = dx / 2; |
|
if (y0 < y1) { |
ystep = 1; |
} else { |
ystep = -1; |
} |
|
for (; x0 <= x1; x0++) { |
|
if (steep) { |
SSD1306_Draw_Pixel(y0, x0, color); |
} else { |
SSD1306_Draw_Pixel(x0, y0, color); |
} |
err -= dy; |
if (err < 0) { |
y0 += ystep; |
err += dx; |
} |
} |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Draw_Line(x0, y0, x1, y1, color); |
#endif |
} |
|
void GFX_drawFastVLine(int x, int y, int h, unsigned int color) { |
GFX_drawLine(x, y, x, y + h - 1, color); |
} |
|
void GFX_drawFastHLine(int x, int y, int w, unsigned int color) { |
GFX_drawLine(x, y, x + w - 1, y, color); |
} |
|
void GFX_drawRect(int x, int y, int w, int h, unsigned int color) { |
#ifdef GFX_SSD1306 |
GFX_drawFastHLine(x, y, w, color); |
GFX_drawFastHLine(x, y + h, w, color); |
GFX_drawFastVLine(x, y, h, color); |
GFX_drawFastVLine(x + w, y, h, color); |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Draw_Rect(x, y, x + w, y + h, color); |
#endif |
} |
|
void GFX_fillRect(int x, int y, int w, int h, unsigned int color) { |
#ifdef GFX_SSD1306 |
int i; |
for (i = x; i < x + w; i++) { |
GFX_drawFastVLine(i, y, h, color); |
} |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Fill_Rect(x, y, x + w, y + h, color); |
#endif |
} |
|
void GFX_fillScreen(unsigned int color) { |
GFX_fillRect(0, 0, gfx_data._width, gfx_data._height, color); |
} |
|
void GFX_clearScreen() { |
#ifdef GFX_SSD1306 |
GFX_fillScreen(SSD1306_BLACK); |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Clear_Display(); |
#endif |
} |
|
void GFX_drawCircle(int x0, int y0, int r, unsigned int color) { |
int f = 1 - r; |
int ddF_x = 1; |
int ddF_y = -2 * r; |
int x = 0; |
int y = r; |
|
#ifdef GFX_SSD1306 |
SSD1306_Draw_Pixel(x0, y0 + r, color); |
SSD1306_Draw_Pixel(x0, y0 - r, color); |
SSD1306_Draw_Pixel(x0 + r, y0, color); |
SSD1306_Draw_Pixel(x0 - r, y0, color); |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Draw_Pixel(x0, y0 + r, color); |
SSD1331_Draw_Pixel(x0, y0 - r, color); |
SSD1331_Draw_Pixel(x0 + r, y0, color); |
SSD1331_Draw_Pixel(x0 - r, y0, color); |
#endif |
|
while (x < y) { |
if (f >= 0) { |
y--; |
ddF_y += 2; |
f += ddF_y; |
} |
x++; |
ddF_x += 2; |
f += ddF_x; |
|
#ifdef GFX_SSD1306 |
SSD1306_Draw_Pixel(x0 + x, y0 + y, color); |
SSD1306_Draw_Pixel(x0 - x, y0 + y, color); |
SSD1306_Draw_Pixel(x0 + x, y0 - y, color); |
SSD1306_Draw_Pixel(x0 - x, y0 - y, color); |
SSD1306_Draw_Pixel(x0 + y, y0 + x, color); |
SSD1306_Draw_Pixel(x0 - y, y0 + x, color); |
SSD1306_Draw_Pixel(x0 + y, y0 - x, color); |
SSD1306_Draw_Pixel(x0 - y, y0 - x, color); |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Draw_Pixel(x0 + x, y0 + y, color); |
SSD1331_Draw_Pixel(x0 - x, y0 + y, color); |
SSD1331_Draw_Pixel(x0 + x, y0 - y, color); |
SSD1331_Draw_Pixel(x0 - x, y0 - y, color); |
SSD1331_Draw_Pixel(x0 + y, y0 + x, color); |
SSD1331_Draw_Pixel(x0 - y, y0 + x, color); |
SSD1331_Draw_Pixel(x0 + y, y0 - x, color); |
SSD1331_Draw_Pixel(x0 - y, y0 - x, color); |
#endif |
} |
} |
|
void GFX_drawCircleHelper(int x0, int y0, int r, unsigned char cornername, unsigned int color) { |
int f = 1 - r; |
int ddF_x = 1; |
int ddF_y = -2 * r; |
int x = 0; |
int y = r; |
|
while (x < y) { |
if (f >= 0) { |
y--; |
ddF_y += 2; |
f += ddF_y; |
} |
x++; |
ddF_x += 2; |
f += ddF_x; |
#ifdef GFX_SSD1306 |
if (cornername & 0x4) { |
SSD1306_Draw_Pixel(x0 + x, y0 + y, color); |
SSD1306_Draw_Pixel(x0 + y, y0 + x, color); |
} |
if (cornername & 0x2) { |
SSD1306_Draw_Pixel(x0 + x, y0 - y, color); |
SSD1306_Draw_Pixel(x0 + y, y0 - x, color); |
} |
if (cornername & 0x8) { |
SSD1306_Draw_Pixel(x0 - y, y0 + x, color); |
SSD1306_Draw_Pixel(x0 - x, y0 + y, color); |
} |
if (cornername & 0x1) { |
SSD1306_Draw_Pixel(x0 - y, y0 - x, color); |
SSD1306_Draw_Pixel(x0 - x, y0 - y, color); |
} |
#endif |
#ifdef GFX_SSD1331 |
if (cornername & 0x4) { |
SSD1331_Draw_Pixel(x0 + x, y0 + y, color); |
SSD1331_Draw_Pixel(x0 + y, y0 + x, color); |
} |
if (cornername & 0x2) { |
SSD1331_Draw_Pixel(x0 + x, y0 - y, color); |
SSD1331_Draw_Pixel(x0 + y, y0 - x, color); |
} |
if (cornername & 0x8) { |
SSD1331_Draw_Pixel(x0 - y, y0 + x, color); |
SSD1331_Draw_Pixel(x0 - x, y0 + y, color); |
} |
if (cornername & 0x1) { |
SSD1331_Draw_Pixel(x0 - y, y0 - x, color); |
SSD1331_Draw_Pixel(x0 - x, y0 - y, color); |
} |
#endif |
} |
} |
|
void GFX_fillCircle(int x0, int y0, int r, unsigned int color) { |
GFX_drawFastVLine(x0, y0 - r, 2 * r + 1, color); |
GFX_fillCircleHelper(x0, y0, r, 3, 0, color); |
} |
|
void GFX_fillCircleHelper(int x0, int y0, int r, unsigned char cornername, int delta, unsigned int color) { |
int f = 1 - r; |
int ddF_x = 1; |
int ddF_y = -2 * r; |
int x = 0; |
int 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) { |
GFX_drawFastVLine(x0 + x, y0 - y, 2 * y + 1 + delta, color); |
GFX_drawFastVLine(x0 + y, y0 - x, 2 * x + 1 + delta, color); |
} |
if (cornername & 0x2) { |
GFX_drawFastVLine(x0 - x, y0 - y, 2 * y + 1 + delta, color); |
GFX_drawFastVLine(x0 - y, y0 - x, 2 * x + 1 + delta, color); |
} |
} |
} |
|
void GFX_drawTriangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color) { |
GFX_drawLine(x0, y0, x1, y1, color); |
GFX_drawLine(x1, y1, x2, y2, color); |
GFX_drawLine(x2, y2, x0, y0, color); |
} |
|
void GFX_fillTriangle(int x0, int y0, int x1, int y1, int x2, int y2, unsigned int color) { |
int a, b, y, last; |
int dx01 = x1 - x0; |
int dy01 = y1 - y0; |
int dx02 = x2 - x0; |
int dy02 = y2 - y0; |
int dx12 = x2 - x1; |
int dy12 = y2 - y1; |
int sa = 0; |
int sb = 0; |
|
// Sort coordinates by Y order (y2 >= y1 >= y0) |
if (y0 > y1) { |
GFX_Swap(&y0, &y1); |
GFX_Swap(&x0, &x1); |
} |
if (y1 > y2) { |
GFX_Swap(&y2, &y1); |
GFX_Swap(&x2, &x1); |
} |
if (y0 > y1) { |
GFX_Swap(&y0, &y1); |
GFX_Swap(&x0, &x1); |
} |
|
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; |
if (x2 < a) a = x2; |
else if (x2 > b) b = x2; |
GFX_drawFastHLine(a, y0, b - a + 1, color); |
return; |
} |
|
// For upper part of triangle, find scanline crossings for segments |
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 |
// is included here (and second loop will be skipped, avoiding a /0 |
// error there), otherwise scanline y1 is skipped here and handled |
// in the second loop...which also avoids a /0 error here if y0=y1 |
// (flat-topped triangle). |
if (y1 == y2) last = y1; // Include y1 scanline |
else last = y1 - 1; // Skip it |
|
for (y = y0; y <= last; y++) { |
a = x0 + sa / dy01; |
b = x0 + sb / dy02; |
sa += dx01; |
sb += dx02; |
/* longhand: |
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); |
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
*/ |
if (a > b) GFX_Swap(&a, &b); |
GFX_drawFastHLine(a, y, b - a + 1, color); |
} |
|
// For lower part of triangle, find scanline crossings for segments |
// 0-2 and 1-2. This loop is skipped if y1=y2. |
sa = dx12 * (y - y1); |
sb = dx02 * (y - y0); |
for (; y <= y2; y++) { |
a = x1 + sa / dy12; |
b = x0 + sb / dy02; |
sa += dx12; |
sb += dx02; |
/* longhand: |
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); |
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); |
*/ |
if (a > b) GFX_Swap(&a, &b); |
GFX_drawFastHLine(a, y, b - a + 1, color); |
} |
} |
|
void GFX_drawRoundRect(int x, int y, int w, int h, int r, unsigned int color) { |
// smarter version |
GFX_drawFastHLine(x + r, y, w - 2 * r, color); // Top |
GFX_drawFastHLine(x + r, y + h - 1, w - 2 * r, color); // Bottom |
GFX_drawFastVLine(x, y + r, h - 2 * r, color); // Left |
GFX_drawFastVLine(x + w - 1, y + r, h - 2 * r, color); // Right |
|
// draw four corners |
GFX_drawCircleHelper(x + r, y + r, r, 1, color); |
GFX_drawCircleHelper(x + w - r - 1, y + r, r, 2, color); |
GFX_drawCircleHelper(x + w - r - 1, y + h - r - 1, r, 4, color); |
GFX_drawCircleHelper(x + r, y + h - r - 1, r, 8, color); |
} |
|
void GFX_fillRoundRect(int x, int y, int w, int h, int r, unsigned int color) { |
// smarter version |
GFX_fillRect(x + r, y, w - 2 * r, h, color); |
|
// draw four corners |
GFX_fillCircleHelper(x + w - r - 1, y + r, r, 1, h - 2 * r - 1, color); |
GFX_fillCircleHelper(x + r, y + r, r, 2, h - 2 * r - 1, color); |
} |
|
void GFX_drawBitmap(int x, int y, const unsigned char* bitmap, int w, int h, unsigned int color) { |
int i, j; |
for (j = 0; j < h; j++) { |
for (i = 0; i < w; i++) { |
if (bitmap[i + (j / 8) * w] & (j % 8)) { |
#ifdef GFX_SSD1306 |
SSD1306_Draw_Pixel(x + i, y + j, color); |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Draw_Pixel(x + i, y + j, color); |
#endif |
} |
} |
} |
} |
|
void GFX_drawChar(int x, int y, unsigned char c, unsigned int color, unsigned int bg, unsigned char size) { |
int i, j; |
unsigned int line; |
|
if ((x >= gfx_data._width) || // Clip right |
(y >= gfx_data._height) || // Clip bottom |
((x + 5 * size - 1) < 0) || // Clip left |
((y + 8 * size - 1) < 0)) // Clip top |
return; |
|
for (i = 0; i < 6; i++) { |
if (i == 5) |
line = 0x0; |
else |
line = font[(c * 5) + i]; |
for (j = 0; j < 8; j++) { |
if (line & 0x1) { |
if (size == 1) {// default size |
#ifdef GFX_SSD1306 |
SSD1306_Draw_Pixel(x + i, y + j, color); |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Draw_Pixel(x + i, y + j, color); |
#endif |
} else { // big size |
GFX_fillRect(x + (i * size), y + (j * size), size, size, color); |
} |
} else if (bg != color) { |
if (size == 1) { // default size |
#ifdef GFX_SSD1306 |
SSD1306_Draw_Pixel(x + i, y + j, bg); |
#endif |
#ifdef GFX_SSD1331 |
SSD1331_Draw_Pixel(x + i, y + j, bg); |
#endif |
} else { // big size |
GFX_fillRect(x + i*size, y + j*size, size, size, bg); |
} |
} |
line >>= 1; |
} |
} |
} |
|
void GFX_write(unsigned char c) { |
if (c == '\n') { |
gfx_data.cursor_y += gfx_data.textsize * 8; |
gfx_data.cursor_x = 0; |
} else if (c == '\r') { |
// skip em |
} else { |
GFX_drawChar(gfx_data.cursor_x, gfx_data.cursor_y, c, gfx_data.textcolor, gfx_data.textbgcolor, gfx_data.textsize); |
gfx_data.cursor_x += gfx_data.textsize * 6; |
if (gfx_data.wrap && (gfx_data.cursor_x > (gfx_data._width - gfx_data.textsize * 6))) { |
gfx_data.cursor_y += gfx_data.textsize * 8; |
gfx_data.cursor_x = 0; |
} |
} |
} |
|
void GFX_writeString(const rom char *fmt, ...) { |
unsigned char i, len; |
va_list args; |
va_start(args, fmt); |
vsprintf((char *) gfx_data.buffer, fmt, args); |
va_end(args); |
len = strlen((char *) gfx_data.buffer); |
for (i = 0; i < len; i++) { |
GFX_write(gfx_data.buffer[i]); |
} |
} |
|
void GFX_setCursor(int x, int y) { |
gfx_data.cursor_x = x; |
gfx_data.cursor_y = y; |
} |
|
void GFX_setTextColor(unsigned int c) { |
// for 'transparent' background, we'll set the bg |
// to the same as fg instead of using a flag |
gfx_data.textcolor = c; |
gfx_data.textbgcolor = c; |
} |
|
void GFX_setTextColorBG(unsigned int c, unsigned int bg) { |
gfx_data.textcolor = c; |
gfx_data.textbgcolor = bg; |
} |
|
void GFX_setTextSize(unsigned char s) { |
gfx_data.textsize = (s > 0) ? s : 1; |
} |
|
void GFX_setTextWrap(unsigned char w) { |
gfx_data.wrap = w; |
} |
|
void GFX_setRotation(unsigned char x) { |
x %= 4; // cant be higher than 3 |
gfx_data.rotation = x; |
switch (x) { |
case 0: |
case 2: |
gfx_data._width = gfx_data.WIDTH; |
gfx_data._height = gfx_data.HEIGHT; |
break; |
case 1: |
case 3: |
gfx_data._width = gfx_data.HEIGHT; |
gfx_data._height = gfx_data.WIDTH; |
break; |
} |
} |
|
unsigned char GFX_getRotation() { |
gfx_data.rotation %= 4; |
return gfx_data.rotation; |
} |
|
int GFX_height() { |
return gfx_data._height; |
} |
|
int GFX_width() { |
return gfx_data._width; |
} |