parent
79232c5d2c
commit
fb7002e68b
@ -0,0 +1,232 @@ |
||||
//
|
||||
// Created by MightyPork on 2022/11/12.
|
||||
//
|
||||
|
||||
#include "user_interface.h" |
||||
#include "framebuffer.h" |
||||
#include "ssd1306.h" |
||||
|
||||
/* Tiny framebuffer */ |
||||
#define FBW DISPLAY_W |
||||
#define FBH DISPLAY_H |
||||
|
||||
#define MIN(a,b) ((a)>(b)?(b):(a)) |
||||
#define MAX(a,b) ((a)>(b)?(a):(b)) |
||||
|
||||
static uint8_t fb[(FBH/8)*FBW]; |
||||
|
||||
/** Fill with a vertical pattern, 1 byte */ |
||||
void fb_fill(uint8_t pattern) { |
||||
memset(fb, pattern, sizeof(fb)); |
||||
} |
||||
|
||||
void fb_clear() { |
||||
fb_fill(0); |
||||
} |
||||
|
||||
void fb_px(uint8_t x, uint8_t y, uint8_t color) { |
||||
if (x >= FBW || y >= FBH) return; |
||||
const uint8_t row = y / 8; |
||||
const uint8_t rowrem = y % 8; |
||||
const uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; |
||||
if (color) { |
||||
fb[cell] |= (1 << rowrem); |
||||
} else { |
||||
fb[cell] &= ~(1 << rowrem); |
||||
} |
||||
} |
||||
|
||||
void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color) { |
||||
if (x >= FBW || y >= FBH) return; |
||||
w = MIN(FBW - x, w); |
||||
const uint8_t row = y / 8; |
||||
const uint8_t rowrem = y % 8; |
||||
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; |
||||
for(uint8_t i = 0; i < w; i++) { |
||||
if (color) { |
||||
fb[cell] |= (1 << rowrem); |
||||
} else { |
||||
fb[cell] &= ~(1 << rowrem); |
||||
} |
||||
cell++; |
||||
} |
||||
} |
||||
|
||||
void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color) { |
||||
if (x >= FBW || y >= FBH) return; |
||||
h = MIN(FBH - y - 1, h); |
||||
const uint8_t row = y / 8; |
||||
const uint8_t rowrem = y % 8; |
||||
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; |
||||
|
||||
if (rowrem + h < 8) { |
||||
// all within one cell
|
||||
uint8_t mask = (0xFF << rowrem) & (0xFF >> (h-rowrem)); |
||||
if (color) { |
||||
fb[cell] |= mask; |
||||
} else { |
||||
fb[cell] &= ~mask; |
||||
} |
||||
return; |
||||
} else { |
||||
// First
|
||||
uint8_t mask = (0xFF << rowrem); |
||||
if (color) { |
||||
fb[cell] |= mask; |
||||
} else { |
||||
fb[cell] &= ~mask; |
||||
} |
||||
h -= rowrem; |
||||
|
||||
uint8_t whole_cells = h / 8; |
||||
h -= whole_cells * 8; |
||||
for(uint8_t i = 0; i < whole_cells; i++) { |
||||
cell += FBW; |
||||
if (color) { |
||||
fb[cell] = 0xFF; |
||||
} else { |
||||
fb[cell] = 0; |
||||
} |
||||
} |
||||
|
||||
// last
|
||||
mask = (0xFF >> (8-h)); |
||||
if (color) { |
||||
fb[cell] |= mask; |
||||
} else { |
||||
fb[cell] &= ~mask; |
||||
} |
||||
} |
||||
} |
||||
|
||||
void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) { |
||||
if (x >= FBW || y >= FBH) return; |
||||
w = MIN(FBW - x - 1, w); |
||||
h = MIN(FBH - y - 1, h); |
||||
const uint8_t row = y / 8; |
||||
const uint8_t rowrem = y % 8; |
||||
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; |
||||
|
||||
if (rowrem + h <= 8) { |
||||
// all within one cell
|
||||
uint8_t mask = (0xFF << rowrem) & (0xFF >> (8 - (h - rowrem))); |
||||
|
||||
for(uint8_t i = 0; i < w; i++) { |
||||
if (color) { |
||||
fb[cell + i] |= mask; |
||||
} else { |
||||
fb[cell + i] &= ~mask; |
||||
} |
||||
} |
||||
return; |
||||
} else { |
||||
// First
|
||||
uint8_t mask = (0xFF << rowrem); |
||||
for(uint8_t i = 0; i < w; i++) { |
||||
if (color) { |
||||
fb[cell + i] |= mask; |
||||
} else { |
||||
fb[cell + i] &= ~mask; |
||||
} |
||||
} |
||||
h -= 8 - rowrem; |
||||
|
||||
uint8_t whole_cells = h / 8; |
||||
h -= whole_cells * 8; |
||||
for(uint8_t j = 0; j < whole_cells; j++) { |
||||
cell += FBW; |
||||
for(uint8_t i = 0; i < w; i++) { |
||||
if (color) { |
||||
fb[cell + i] = 0xFF; |
||||
} else { |
||||
fb[cell + i] = 0; |
||||
} |
||||
} |
||||
} |
||||
|
||||
cell += FBW; |
||||
|
||||
// last
|
||||
mask = (0xFF >> (8-h)); |
||||
for(uint8_t i = 0; i < w; i++) { |
||||
if (color) { |
||||
fb[cell + i] |= mask; |
||||
} else { |
||||
fb[cell + i] &= ~mask; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color) { |
||||
if (x >= FBW || y >= FBH) return; |
||||
const uint8_t w0 = w; |
||||
const uint8_t h0 = h; |
||||
w = MIN(FBW - x - 1, w); |
||||
h = MIN(FBH - y - 1, h); |
||||
const uint8_t row = y / 8; |
||||
const uint8_t rowrem = y % 8; |
||||
uint16_t cell = (uint16_t) x + (uint16_t) row * FBW; |
||||
|
||||
if (rowrem + h <= 8) { |
||||
for(uint8_t i = 0; i < w; i++) { |
||||
// all within one cell
|
||||
uint8_t mask = (map[i] & (0xFF >> (8-h))) << rowrem; |
||||
if (color) { |
||||
fb[cell + i] |= mask; |
||||
} else { |
||||
fb[cell + i] &= ~mask; |
||||
} |
||||
} |
||||
return; |
||||
} else if (rowrem == 0) { |
||||
// Optimization
|
||||
|
||||
// First
|
||||
for(uint8_t i = 0; i < w; i++) { |
||||
uint8_t mask = map[i]; |
||||
if (color) { |
||||
fb[cell + i] |= mask; |
||||
} else { |
||||
fb[cell + i] &= ~mask; |
||||
} |
||||
} |
||||
h -= 8; |
||||
|
||||
// Middle
|
||||
uint8_t whole_cells = h / 8; |
||||
h -= whole_cells * 8; |
||||
for(uint8_t j = 0; j < whole_cells; j++) { |
||||
cell += FBW; |
||||
for(uint8_t i = 0; i < w; i++) { |
||||
uint8_t mask = map[i + (j+1)*w0]; |
||||
if (color) { |
||||
fb[cell + i] |= mask; |
||||
} else { |
||||
fb[cell + i] &= ~mask; |
||||
} |
||||
} |
||||
} |
||||
|
||||
// last
|
||||
cell += FBW; |
||||
|
||||
// last
|
||||
for(uint8_t i = 0; i < w; i++) { |
||||
uint8_t mask = map[i + (whole_cells+1)*w0] & (0xFF >> (8-h)); |
||||
if (color) { |
||||
fb[cell + i] |= mask; |
||||
} else { |
||||
fb[cell + i] &= ~mask; |
||||
} |
||||
} |
||||
|
||||
} else { |
||||
// TODO wild combination, unaligned multi-row
|
||||
} |
||||
} |
||||
|
||||
|
||||
void fb_blit() { |
||||
ssd1306_drawBuffer(0, 0, FBW, FBH, fb); |
||||
} |
@ -0,0 +1,20 @@ |
||||
//
|
||||
// Created by MightyPork on 2022/11/12.
|
||||
//
|
||||
|
||||
#ifndef FRAMEBUFFER_H |
||||
#define FRAMEBUFFER_H |
||||
|
||||
#include <stdbool.h> |
||||
#include <stdint.h> |
||||
|
||||
void fb_fill(uint8_t pattern); |
||||
void fb_clear(void); |
||||
void fb_px(uint8_t x, uint8_t y, uint8_t color); |
||||
void fb_hline(uint8_t x, uint8_t y, uint8_t w, uint8_t color); |
||||
void fb_vline(uint8_t x, uint8_t y, uint8_t h, uint8_t color); |
||||
void fb_rect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color); |
||||
void fb_bitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *map, uint8_t color); |
||||
void fb_blit(void); |
||||
|
||||
#endif //FRAMEBUFFER_H
|
Loading…
Reference in new issue