How are you storing the bitmaps for the character font? I assume you have some 3D array of either bits, greyscale or RGB data.
-----> X axis
|
|
v
y-axis
You could try something like this:
#include <avr\pgmspace.h>
struct RGB {
uint8_t r;
uint8_t g;
uint8_t b;
RGB() { };
RGB(uint8_t cr, uint8_t cg, uint8_t cb) { r = cr; g = cg; b = cb; };
};
// the capital letter N
#define SPRITE_N 0
#define SPRITE_WIDTH 5
#define SPRITE_HEIGHT 5
// 5x5 greyscale font
static const uint8_t sprites[25] PROGMEM = {
{ 0x00, 0x00, 0xFF, 0x00, 0x00,
0x00, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0xFF, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0xFF
}
};
#define FRAME_WIDTH 32
#define FRAME_HEIGHT 8
void draw_sprite(void* frame_start, uint8_t x, uint8_t y, void* sprite, RGB color) {
register uint8_t *p;
register uint8_t *s;
for (uint8_t i = 0; i < SPRITE_HEIGHT; i++) {
if ((y + i) >= FRAME_HEIGHT) {
break;
}
if ((y+i) % 2 == 0) { // even rows are left to right
s = (uint8_t *)sprite + i * SPRITE_HEIGHT;
p = (uint8_t *)frame_start + ((y + i) * FRAME_WIDTH + x) * 3;
for (uint8_t j = 0; j < SPRITE_WIDTH; j++) {
if ((j + x) >= FRAME_WIDTH) {
break;
}
*p++ = (uint8_t)((*s * color.b) >> 8);
*p++ = (uint8_t)((*s * color.g) >> 8);
*p++ = (uint8_t)((*s++ * color.r) >> 8);
}
} else { // odd rows are right to left
s = (uint8_t *)sprite + i * SPRITE_HEIGHT;
p = (uint8_t *)frame_start + ((y + i + 1) * FRAME_WIDTH - x) * 3;
for (uint8_t j = 0; j < SPRITE_WIDTH; j++) {
if ((j + x) >= FRAME_WIDTH) {
break;
}
*–p = (uint8_t)((*s * color.b) >> 8);
*–p = (uint8_t)((*s * color.g) >> 8);
*–p = (uint8_t)((*s++ * color.r) >> 8);
}
}
}
};
/*
Based on code from http://code.google.com/p/fastspi/
*/
void frame_out(void *frame_start) {
register uint8_t *p = (uint8_t *)frame_start;
register const uint8_t *e = p + FRAME_WIDTH * FRAME_HEIGHT * 3;
SPDR = *p;
while (p < e) {
while (!(SPSR & _BV(SPIF)));
SPDR = *++p;
while (!(SPSR & _BV(SPIF)));
SPDR = *++p;
while (!(SPSR & _BV(SPIF)));
SPDR = *++p;
}
while (!(SPSR & _BV(SPIF)));
};
To “print” the letter N at (x, y) position (10, 2) in 1/2 brightness green color:
RGB frame_buffer[FRAME_HEIGHT][FRAME_WIDTH];
uint8_t sprite[25];
memcpy_P(sprite, &sprites[SPRITE_N][0], 25);
draw_sprite(&frame_buffer[0][0], 10, 2, sprite, RGB(0, 127, 0));
frame_out(&frame_buffer[0][0], FRAME_WIDTH * FRAME_HEIGHT * 3);
I haven’t debugged the draw_sprite code. It looks good on paper, but I could have an error in there.