Working on own LCD impl

This commit is contained in:
Michal Moskal 2017-07-10 21:37:29 +01:00
parent 1f51d137b3
commit 17a01b46be
2 changed files with 151 additions and 7 deletions

View File

@ -2,7 +2,7 @@
* [x] implement serialPoll
* [x] try some motors
* [x] add `control.interrupt(ms, () => { ... sync function ... })` - running outside regular JS thread
* [ ] add `//% whenUsed` on global variable initializers in PXT
* [x] add `//% whenUsed` on global variable initializers in PXT
* [ ] fix `@PXT@:` handling for ELF in PXT
* [x] parse Python field lists into offsets

View File

@ -25,20 +25,165 @@ enum class ScreenFont {
// We only support up to 4 arguments for C++ functions - need to pack them on the TS side
namespace screen {
#define ROW_SIZE 32
#define FB_SIZE (60 * LCD_HEIGHT)
static const uint8_t pixmap[] = {0x00, 0xE0, 0x1C, 0xFC, 0x03, 0xE3, 0x1F, 0xFF};
static uint8_t bitBuffer[ROW_SIZE * LCD_HEIGHT];
static uint8_t *mappedFrameBuffer;
static bool dirty;
static void bitBufferToFrameBuffer(uint8_t *bitBuffer, uint8_t *fb) {
uint32_t pixels;
for (int line = 0; line < LCD_HEIGHT; line++) {
int n = 7;
while (n--) {
pixels = *bitBuffer++ << 0;
pixels |= *bitBuffer++ << 8;
pixels |= *bitBuffer++ << 16;
int m = 8;
while (m--) {
*fb++ = pixmap[pixels & 0x07];
pixels >>= 3;
}
}
pixels = *bitBuffer++ << 0;
pixels |= *bitBuffer++ << 8;
bitBuffer += ROW_SIZE - 26;
int m = 4;
while (m--) {
*fb++ = pixmap[pixels & 0x07];
pixels >>= 3;
}
}
}
static void updateLCD() {
bitBufferToFrameBuffer(bitBuffer, mappedFrameBuffer);
}
#define OFF(x, y) (((y) << 5) + ((x) >> 3))
#define MASK(x, y) (1 << ((x)&7))
static inline void applyMask(int off, int mask, Draw mode) {
if (mode & Draw::Clear)
bitBuffer[off] &= ~mask;
else if (mode & Draw::Xor)
bitBuffer[off] ^= mask;
else
bitBuffer[off] |= mask;
}
static inline void setPixelCore(int x, int y, Draw mode) {
applyMask(OFF(x, y), MASK(x, y), mode);
}
static void setLineCore(int x0, int x1, int y, Draw mode) {
while (x0 < x1 && (x0 & 7)) {
setPixelCore(x0++, y, mode);
}
int off = OFF(x0, y);
// 8-aligned now
while (x0 < x1 - 8) {
applyMask(off++, 0xff, mode);
x0 += 8;
}
while (x0 < x1) {
setPixelCore(x0++, y, mode);
}
dirty = true;
}
void drawRect(int x, int y, int w, int h, Draw mode) {
if (x < 0) {
w += x;
x = 0;
}
if (y < 0) {
h += y;
y = 0;
}
if (w <= 0)
return;
if (h <= 0)
return;
int x1 = min(LCD_WIDTH, x + w);
int y1 = min(LCD_HEIGHT, y + h);
if (w == 1) {
while (y < y1)
setPixelCore(x, y++, mode);
return;
}
setLineCore(x, x1, y++, mode);
while (y < y1 - 1) {
if (mode & Draw::Fill) {
setLineCore(x, x1, y, mode);
} else {
setPixelCore(x, y, mode);
setPixelCore(x1 - 1, y, mode);
}
y++;
}
if (y < y1)
setLineCore(x, x1, y, mode);
}
void blitLine(int x, int y, int w, uint8_t *data, Draw mode) {
int shift = x & 7;
int off = OFF(x, y);
int x1 = x + w;
int prev = 0;
while (x < x1 - 8) {
int curr = *data++ << shift;
applyMask(off++, curr | prev);
prev = curr >> 8;
x += 8;
}
int left = x1 - x;
if (left > 0) {
int curr = *data << shift;
applyMask(off, (curr | prev) & ((1 << left) - 1));
}
}
/** Update a pixel on the screen. */
//%
void _drawLine(uint32_t p0, uint32_t p1, Draw mode) {
LineOutEx(XX(p0), YY(p0), XX(p1), YY(p1), (uint32_t)mode);
void setPixel(int x, int y, Draw mode) {
if (0 <= x && x < LCD_WIDTH && 0 <= y && y <= LCD_HEIGHT) {
setPixelCore(x, y, mode);
dirty = true;
}
}
//%
void _drawRect(uint32_t p0, uint32_t p1, Draw mode) {
RectOutEx(XX(p0), YY(p0), XX(p1), YY(p1), (uint32_t)mode);
drawRect(XX(p0), YY(p0), XX(p1), YY(p1), mode);
}
static int fontFirst, fontWidth, fontHeight, fontByteWidth;
static uint8_t *fontChars;
static Buffer currFont;
/** Set font. */
//%
void _drawEllipse(uint32_t p0, uint32_t p1, Draw mode) {
EllipseOutEx(XX(p0), YY(p0), XX(p1), YY(p1), (uint32_t)mode);
void setFont(Buffer font) {
if (!font || font->length < 100)
return;
if (font->data[0] != 0xf0 || font->data[1] != 0x42)
return;
fontFirst = font->data[2];
fontWidth = font->data[3];
fontHeight = font->data[4];
fontByteWidth = (fontWidth + 7) / 8;
fontChars = &font->data[8];
}
/** Draw text. */
@ -83,5 +228,4 @@ void screen_init() {
pthread_create(&pid, NULL, screenRefresh, NULL);
pthread_detach(pid);
}
}