Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* gfx.c
*
* Created on: 28/11/2013
* Author: pfowler
*/
#include <avr/io.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <string.h>
#include "avrutil.h"
#include "gfx.h"
void gfx_init(uint8_t* buffer, uint8_t width, uint8_t height) {
gfx.width = width;
gfx.height = height;
gfx.buffer = buffer;
gfx_font.cursor_x = 0;
gfx_font.cursor_y = 0;
gfx_font.textsize = 1;
gfx_font.textcolor = 1;
gfx_font.textbgcolor = 1;
gfx_font.wrap = 1;
}
uint8_t gfx_getRotation(void) {
return gfx.rotation;
}
void gfx_setRotation(uint8_t x) {
gfx.rotation = (x & 3);
uint8_t ow = gfx.width;
uint8_t oh = gfx.height;
switch(gfx.rotation) {
case 0:
case 2:
gfx.width = ow;
gfx.height = oh;
break;
case 1:
case 3:
gfx.width = oh;
gfx.height = ow;
break;
}
}
void gfx_setDrawFunc(pixelptr ptr) {
gfx.drawPixel = ptr;
}
void gfx_setFlipFunc(flipptr ptr) {
gfx.flip = ptr;
}
void gfx_flip(void) {
(*gfx.flip)();
}
void gfx_clear(void) {
memset(gfx.buffer, 0x00, (gfx.width * gfx.height / 8));
}
void gfx_drawPixel(uint16_t x, uint16_t y, uint8_t color) {
if (gfx.drawPixel) {
(*gfx.drawPixel)(gfx.buffer, x, y, color);
return;
}
if (color)
gfx.buffer[x+ (y/8)*gfx.width] |= _BV((y%8));
else
gfx.buffer[x+ (y/8)*gfx.width] &= ~_BV((y%8));
}
void gfx_drawFastVLine(uint8_t x, uint8_t y, uint8_t h, uint8_t color) {
gfx_drawLine(x, y, x, y+h-1, color);
}
void gfx_drawFastHLine(uint8_t x, uint8_t y, uint8_t w, uint8_t color) {
gfx_drawLine(x, y, x+w-1, y, color);
}
void gfx_drawRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) {
gfx_drawFastHLine(x, y, w, color);
gfx_drawFastHLine(x, y+h-1, w, color);
gfx_drawFastVLine(x, y, h, color);
gfx_drawFastVLine(x+w-1, y, h, color);
}
void gfx_fillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) {
uint8_t i;
for (i=x; i<x+w; i++) {
gfx_drawFastVLine(i, y, h, color);
}
}
void gfx_fillScreen(uint8_t color) {
gfx_fillRect(0, 0, gfx.width, gfx.height, 1);
}
void gfx_drawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color) {
int8_t steep = abs(y1 - y0) > abs(x1 - x0);
//uint8_t t = 0;
if (steep) {
swapu(&x0, &y0);
swapu(&x1, &y1);
}
if (x0 > x1) {
swapu(&x0, &x1);
swapu(&y0, &y1);
}
int8_t dx, dy;
dx = x1 - x0;
dy = abs(y1-y0);
int8_t err = dx /2;
int8_t ystep;
if (y0 < y1)
ystep = 1;
else
ystep = -1;
for (; x0<=x1; x0++) {
if (steep)
gfx_drawPixel(y0, x0, color);
else
gfx_drawPixel(x0, y0, color);
err -= dy;
if (err < 0) {
y0 += ystep;
err += dx;
}
}
}
void gfx_drawChar(uint8_t x, uint8_t y, unsigned char c, uint8_t color, uint8_t bg, uint8_t size) {
if((x >= gfx.width) || // Clip right
(y >= gfx.height) || // Clip bottom
((x + 6 * size - 1) < 0) || // Clip left
((y + 8 * size - 1) < 0)) // Clip top
return;
uint8_t i;
for (i=0; i<6; i++) {
uint8_t line;
if (i == 5)
line = 0x0;
else
line = pgm_read_byte(gfx_font_data + (c*5)+i);
uint8_t j;
for (j=0; j<8; j++) {
if (line & 0x01) {
if (size == 1)
gfx_drawPixel(x+i, y+j, color);
else
gfx_fillRect(x+(i*size), y+(j*size), size, size, color);
} else if (bg != color) {
if (size==1)
gfx_drawPixel(x+i, y+j, bg);
else
gfx_fillRect(x+i*size, y+j*size, size, size, bg);
}
line >>= 1;
}
}
}
void gfx_writec(uint8_t c) {
if (c == '\n') {
gfx_font.cursor_y += gfx_font.textsize*8;
gfx_font.cursor_x = 0;
} else if (c == '\r') {
} else {
gfx_drawChar(gfx_font.cursor_x, gfx_font.cursor_y, c,
gfx_font.textcolor, gfx_font.textbgcolor, gfx_font.textsize);
gfx_font.cursor_x += gfx_font.textsize * 6;
if (gfx_font.wrap &&
(gfx_font.cursor_x > (gfx.width - gfx_font.textsize*6))) {
gfx_font.cursor_y += gfx_font.textsize = 8;
gfx_font.cursor_x = 0;
}
}
}
void gfx_writeb(uint8_t *buffer, size_t size) {
while (size--)
gfx_writec(*buffer++);
}
void gfx_writes(char* s) {
while (*s)
gfx_writec(*s++);
}
void gfx_printNumber(unsigned long n, uint8_t base) {
unsigned char buf[8 * sizeof(long)];
unsigned long i = 0;
if (n==0) {
gfx_writec('0');
return;
}
while (n > 0) {
buf[i++] = n % base;
n /= base;
}
for (; i>0; i--)
gfx_writec((buf[i-1]<10) ?
'0' + buf[i-1] :
'A' + buf[i-1]-10);
}
void gfx_printFloat(double number, uint8_t digits) {
if (number < 0.0) {
gfx_writec('-');
number = -number;
}
double rounding = 0.5;
uint8_t i;
for (i=0; i<digits; ++i)
rounding /= 10.0;
number += rounding;
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
gfx_printNumber(int_part, 10);
if (digits > 0)
gfx_writec('.');
while (digits-- > 0) {
remainder *= 10.0;
unsigned long toPrint = (unsigned long)remainder;
gfx_printNumber(toPrint, 10);
remainder -= toPrint;
}
}
void gfx_setCursor(uint8_t x, uint8_t y) {
gfx_font.cursor_x = x;
gfx_font.cursor_y = y;
}
void gfx_setTextSize(uint8_t s) {
gfx_font.textsize = (s>0)? s : 1;
}
void gfx_setTextColor(uint8_t c) {
gfx_font.textcolor = c;
}
void gfx_setTextBgColor(uint8_t bg) {
gfx_font.textbgcolor = bg;
}
void gfx_setTextWrap(uint8_t w) {
gfx_font.wrap = w;
}