Skip to content

Instantly share code, notes, and snippets.

@0xLeon
Last active May 23, 2016 19:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0xLeon/1ad75bd3d1522eaf5a13a2701d0eb8d3 to your computer and use it in GitHub Desktop.
Save 0xLeon/1ad75bd3d1522eaf5a13a2701d0eb8d3 to your computer and use it in GitHub Desktop.
Performance optimized graphics functions based on Teensy library for CAB202
unsigned char bm_face_happy[] = {
0b11111111, 0b11111111,
0b00000001, 0b10000000,
0b00000001, 0b10000000,
0b00000001, 0b10000011,
0b00110001, 0b10000100,
0b00110001, 0b10001000,
0b00000001, 0b10001000,
0b00000001, 0b10001000,
0b00000001, 0b10001000,
0b00000001, 0b10001000,
0b00110001, 0b10001000,
0b00110001, 0b10000100,
0b00000001, 0b10000011,
0b00000001, 0b10000000,
0b00000001, 0b10000000,
0b11111111, 0b11111111
};
unsigned char bm_face_angry[] = {
0b11111111, 0b11111111,
0b00000001, 0b10000000,
0b00000001, 0b10000000,
0b00001001, 0b10000000,
0b00010001, 0b10001000,
0b00100001, 0b10000100,
0b00000001, 0b10000010,
0b00000001, 0b10000010,
0b00000001, 0b10000010,
0b00000001, 0b10000010,
0b00100001, 0b10000100,
0b00010001, 0b10001000,
0b00001001, 0b10000000,
0b00000001, 0b10000000,
0b00000001, 0b10000000,
0b11111111, 0b11111111
};
unsigned char bm_face_mad[] = {
0b11111111, 0b11111111,
0b00000001, 0b10000000,
0b00000001, 0b10000000,
0b00000001, 0b10000000,
0b00011001, 0b10000001,
0b00011001, 0b10000001,
0b00000001, 0b10000001,
0b00000001, 0b10000001,
0b00000001, 0b10000111,
0b00000001, 0b10000111,
0b00000001, 0b10000001,
0b01100001, 0b10000000,
0b01100001, 0b10000000,
0b00000001, 0b10000000,
0b00000001, 0b10000000,
0b11111111, 0b11111111
};
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <avr/pgmspace.h>
#include "ascii_font.h"
#include "graphics.h"
#include "pgraphics.h"
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
static uint8_t reverse_byte_lookup[16U] = {0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf};
uint8_t p_reverse_byte(const uint8_t b) {
return ((reverse_byte_lookup[b & 15U] << 4U) | (reverse_byte_lookup[b >> 4U]));
}
void p_clear_screen(void) {
memset(screenBuffer, 0U, LCD_BUFFER_SIZE);
}
void p_show_screen(void) {
LCDPosition(0U, 0U);
for (uint16_t i = 0U; i < LCD_BUFFER_SIZE; ++i) {
LCDWrite(LCD_D, screenBuffer[i]);
}
}
void p_draw_char(uint8_t x, uint8_t y, uint8_t c) {
if ((c < 32U) || (c > 127U)) {
return;
}
// TODO: partly visible chars, left or top
if ((x > LCD_X) || (y > LCD_Y) || (x < 0U) || (y < 0U)) {
return;
}
uint8_t x_max = MIN((x + 5U), LCD_X);
uint8_t v_offset = y - (((uint8_t) floor(y / 8.f)) * 8U);
uint16_t y_sb = ((uint16_t) floor(y / 8.f)) * LCD_X;
c -= 32U;
if (y_sb < LCD_BUFFER_SIZE) {
if (0U == v_offset) {
for (uint8_t x_sb = x, i = 0; (i < 5U) && (x_sb < x_max); ++i, ++x_sb) {
screenBuffer[y_sb + x_sb] |= pgm_read_byte((&(ASCII[c][i])));
}
}
else {
uint8_t i_v_offset = 8U - v_offset;
uint16_t inc_y_sb = y_sb + LCD_X;
for (uint8_t x_sb = x, i = 0; (i < 5U) && (x_sb < x_max); ++i, ++x_sb) {
screenBuffer[y_sb + x_sb] |= (pgm_read_byte((&(ASCII[c][i]))) << v_offset);
if (inc_y_sb < LCD_BUFFER_SIZE) {
screenBuffer[inc_y_sb + x_sb] |= (pgm_read_byte((&(ASCII[c][i]))) >> i_v_offset);
}
}
}
}
}
void p_draw_string(uint8_t x, uint8_t y, char *str) {
for (uint8_t i = 0U; (*str) != '\0'; ++i, ++str) {
p_draw_char(x + i * 5U, y, (*str));
}
}
void p_draw_stringn(uint8_t x, uint8_t y, uint8_t n, char *str) {
--n;
for (; n >= 0U; --n) {
p_draw_char(x + n * 5U, y, str[n]);
}
}
void p_draw_formatted_string(uint8_t x, uint8_t y, const char *fmt, ...) {
char buffer[18U];
va_list args;
va_start(args, fmt);
vsnprintf(buffer, 18U, fmt, args);
p_draw_string(x, y, buffer);
}
void p_draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) {
// TODO: performance bottle neck, implement own draw line function
draw_line(x1, y1, x2, y2);
}
void p_init_sprite(psprite_p sprite, float x, float y, uint8_t width, uint8_t height, uint8_t *bitmap) {
sprite->x = x;
sprite->y = y;
sprite->width = width;
sprite->height = height;
sprite->bitmap = bitmap;
sprite->is_visible = 1U;
sprite->dx = 0.f;
sprite->dy = 0.f;
}
void p_draw_sprite(const psprite_p sprite) {
if ((NULL == sprite) || !(sprite->is_visible)) {
return;
}
// TODO: partly visible sprites, left or top
if ((sprite->x >= LCD_X) || (sprite->y >= LCD_Y) ||
((sprite->x < 0U)/* && ((sprite->x + sprite->width) < 0)*/) ||
((sprite->y < 0U)/* && ((sprite->y + sprite->height) < 0)*/)) {
return;
}
uint8_t x_max = MIN(((uint8_t) sprite->x + sprite->width), LCD_X);
uint8_t v_byte_count = ((uint8_t) ceil(sprite->height / 8.f));
uint8_t v_offset = ((uint8_t) sprite->y) - (((uint8_t) floor(sprite->y / 8U)) * 8U);
if (0U == v_offset) {
for (uint8_t y = ((uint8_t) floor(sprite->y / 8U)), c = 0U; (c < v_byte_count) && ((y * LCD_X) < LCD_BUFFER_SIZE); ++y, ++c) {
for (uint8_t x = sprite->x, d = 0U; x < x_max; ++x, ++d) {
screenBuffer[y * LCD_X + x] = sprite->bitmap[v_byte_count * d + c];
}
}
}
else {
uint8_t i_v_offset = 8U - v_offset;
for (uint8_t y = ((uint8_t) floor(sprite->y / 8)), c = 0U; (c < v_byte_count) && ((y * LCD_X) < LCD_BUFFER_SIZE); ++y, ++c) {
for (uint8_t x = sprite->x, d = 0U; x < x_max; ++x, ++d) {
screenBuffer[y * LCD_X + x] |= (sprite->bitmap[v_byte_count * d + c] << v_offset);
if (((y + 1U) * LCD_X) < LCD_BUFFER_SIZE) {
screenBuffer[(y + 1U) * LCD_X + x] |= (sprite->bitmap[v_byte_count * d + c] >> i_v_offset);
}
}
}
}
}
#ifndef PGRAPHICS_H_
#define PGRAPHICS_H_
#include <stdint.h>
typedef struct psprite {
uint8_t *bitmap;
float x;
float y;
float dx;
float dy;
uint8_t width;
uint8_t height;
uint8_t is_visible;
} psprite_t;
typedef psprite_t* psprite_p;
uint8_t p_reverse_byte(const uint8_t b);
void p_clear_screen(void);
void p_show_screen(void);
void p_draw_char(uint8_t x, uint8_t y, uint8_t c);
void p_draw_string(uint8_t x, uint8_t y, char *str);
void p_draw_stringn(uint8_t x, uint8_t y, uint8_t n, char *str);
void p_draw_formatted_string(uint8_t x, uint8_t y, const char *fmt, ...);
void p_draw_line(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
void p_init_sprite(psprite_p sprite, float x, float y, uint8_t width, uint8_t height, uint8_t *bitmap);
void p_draw_sprite(const psprite_p sprite);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment