mirror of
https://github.com/usetrmnl/bb_epaper.git
synced 2026-04-29 13:43:26 -07:00
Added patches to G5 decoder for AVR
This commit is contained in:
@@ -18,7 +18,7 @@ void app_main(void)
|
||||
|
||||
init_ulp_program();
|
||||
/* Go to sleep, only the ULP Risc-V will run */
|
||||
printf("Entering in deep sleep\n\n");
|
||||
// printf("Entering in deep sleep\n\n");
|
||||
|
||||
/* 5 second delay to ensure we can reflash from USB */
|
||||
// vTaskDelay(500);
|
||||
@@ -35,9 +35,9 @@ static void init_ulp_program(void)
|
||||
ESP_ERROR_CHECK(err);
|
||||
|
||||
/* The first argument is the period index, which is not used by the ULP-RISC-V timer
|
||||
* The second argument is the period in microseconds, which gives a wakeup time period of: 20ms
|
||||
* The second argument is the period in microseconds
|
||||
*/
|
||||
ulp_set_wakeup_period(0, 5000000); // 5 seconds
|
||||
ulp_set_wakeup_period(0, 20000); // 20 miliseconds for first wakeup
|
||||
|
||||
/* Start the program */
|
||||
err = ulp_riscv_run();
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "ulp_riscv.h"
|
||||
#include "ulp_riscv_utils.h"
|
||||
#include "ulp_riscv_gpio.h"
|
||||
#include "ulp_common.h"
|
||||
|
||||
// Tell the bb_epaper library not to include code related to
|
||||
// drawing with a back buffer for the epaper panel
|
||||
@@ -65,6 +66,6 @@ int main (void)
|
||||
// }
|
||||
// }
|
||||
/* ulp_riscv_halt() is called automatically when main exits */
|
||||
// ulp_set_wakeup_period(0, 5000000); // period in usec
|
||||
// ulp_set_wakeup_period(0, 25000000); // period of next wake up in usec
|
||||
return 0;
|
||||
}
|
||||
|
||||
+22
-20
@@ -112,32 +112,36 @@ void bbepInitIO(BBEPDISP *pBBEP, uint8_t u8DC, uint8_t u8RST, uint8_t u8BUSY, ui
|
||||
//
|
||||
// Bit Bang SPI
|
||||
//
|
||||
void SPIWriteByte(BBEPDISP *pBBEP, uint8_t uc)
|
||||
void SPIWriteBytes(BBEPDISP *pBBEP, uint8_t *pData, int iLen)
|
||||
{
|
||||
uint8_t u8MOSI = pBBEP->iMOSIPin;
|
||||
uint8_t u8SCK = pBBEP->iCLKPin;
|
||||
const uint8_t u8MOSI = pBBEP->iMOSIPin;
|
||||
const uint8_t u8SCK = pBBEP->iCLKPin;
|
||||
uint8_t uc;
|
||||
|
||||
if (uc == 0 || uc == 0xff) { // special case
|
||||
ulp_riscv_gpio_output_level(u8MOSI, (uc & 1));
|
||||
for (int i=0; i<8; i++) {
|
||||
ulp_riscv_gpio_output_level(u8SCK, 1); // no delays needed since it runs at a slow clock
|
||||
ulp_riscv_gpio_output_level(u8SCK, 0);
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<8; i++) {
|
||||
ulp_riscv_gpio_output_level(u8MOSI, (uc & 0x80)); // msb first
|
||||
ulp_riscv_gpio_output_level(u8SCK, 1); // no delays needed since it runs at a slow clock
|
||||
uc <<= 1;
|
||||
ulp_riscv_gpio_output_level(u8SCK, 0);
|
||||
for (int j=0; j<iLen; j++) {
|
||||
uc = *pData++;
|
||||
if (uc == 0 || uc == 0xff) { // special case
|
||||
ulp_riscv_gpio_output_level(u8MOSI, (uc & 1));
|
||||
for (int i=0; i<8; i++) {
|
||||
ulp_riscv_gpio_output_level(u8SCK, 1); // no delays needed since it runs at a slow clock
|
||||
ulp_riscv_gpio_output_level(u8SCK, 0);
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<8; i++) {
|
||||
ulp_riscv_gpio_output_level(u8MOSI, (uc & 0x80)); // msb first
|
||||
ulp_riscv_gpio_output_level(u8SCK, 1); // no delays needed since it runs at a slow clock
|
||||
uc <<= 1;
|
||||
ulp_riscv_gpio_output_level(u8SCK, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* SPIWriteByte() */
|
||||
} /* SPIWriteBytes() */
|
||||
|
||||
void bbepWriteCmd(BBEPDISP *pBBEP, uint8_t ucCMD)
|
||||
{
|
||||
digitalWrite(pBBEP->iDCPin, LOW);
|
||||
digitalWrite(pBBEP->iCSPin, LOW);
|
||||
SPIWriteByte(pBBEP, ucCMD);
|
||||
SPIWriteBytes(pBBEP, &ucCMD, 1);
|
||||
digitalWrite(pBBEP->iDCPin, HIGH);
|
||||
digitalWrite(pBBEP->iCSPin, HIGH);
|
||||
} /* bbepWriteCmd() */
|
||||
@@ -145,9 +149,7 @@ void bbepWriteCmd(BBEPDISP *pBBEP, uint8_t ucCMD)
|
||||
void bbepWriteData(BBEPDISP *pBBEP, uint8_t *pData, int iLen)
|
||||
{
|
||||
digitalWrite(pBBEP->iCSPin, LOW);
|
||||
for (int i=0; i<iLen; i++) {
|
||||
SPIWriteByte(pBBEP, pData[i]);
|
||||
}
|
||||
SPIWriteBytes(pBBEP, pData, iLen);
|
||||
digitalWrite(pBBEP->iCSPin, HIGH);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
//
|
||||
// Group5 1-bit image compression library
|
||||
// Written by Larry Bank
|
||||
@@ -82,7 +85,17 @@ typedef struct g5_dec_image_tag
|
||||
} G5DECIMAGE;
|
||||
|
||||
// Due to unaligned memory causing an exception, we have to do these macros the slow way
|
||||
#ifdef __AVR__
|
||||
// assume PROGMEM as the source of data
|
||||
inline uint32_t TIFFMOTOLONG(uint8_t *p)
|
||||
{
|
||||
uint32_t u32 = pgm_read_dword(p);
|
||||
return __builtin_bswap32(u32);
|
||||
}
|
||||
#else
|
||||
#define TIFFMOTOLONG(p) (((uint32_t)(*p)<<24UL) + ((uint32_t)(*(p+1))<<16UL) + ((uint32_t)(*(p+2))<<8UL) + (uint32_t)(*(p+3)))
|
||||
#endif // __AVR__
|
||||
|
||||
#define TOP_BIT 0x80000000
|
||||
#define MAX_VALUE 0xffffffff
|
||||
// Must be a 32-bit target processor
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
// foreward references
|
||||
void bbepWakeUp(BBEPDISP *pBBEP);
|
||||
//
|
||||
// Initialize the GPIO pins and SPI for use by bb_eink
|
||||
//
|
||||
|
||||
+28
-23
@@ -594,20 +594,25 @@ unsigned int c;
|
||||
uint8_t *s, bInvert = 0;
|
||||
BB_GLYPH *pGlyph;
|
||||
uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
uint8_t first, last;
|
||||
|
||||
if (pBBEP == NULL || pFont == NULL) return; // invalid param
|
||||
|
||||
if (x == -1)
|
||||
x = pBBEP->iCursorX;
|
||||
if (y == -1)
|
||||
y = pBBEP->iCursorY;
|
||||
first = pgm_read_byte(&pFont->first);
|
||||
last = pgm_read_byte(&pFont->last);
|
||||
if (x == CENTER_X) { // center the string on the e-paper
|
||||
dx = i = 0;
|
||||
while (szMsg[i]) {
|
||||
c = szMsg[i++];
|
||||
if (c < pFont->first || c > pFont->last) // undefined character
|
||||
if (c < first || c > last) // undefined character
|
||||
continue; // skip it
|
||||
c -= pFont->first; // first char of font defined
|
||||
c -= first; // first char of font defined
|
||||
pGlyph = &pFont->glyphs[c]; // glyph info for this character
|
||||
dx += pGlyph->xAdvance;
|
||||
dx += pgm_read_byte(&pGlyph->xAdvance);
|
||||
}
|
||||
x = (pBBEP->native_width - dx)/2;
|
||||
if (x < 0) x = 0;
|
||||
@@ -615,26 +620,26 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
// Point to the start of the compressed data
|
||||
pBits = (uint8_t *)pFont;
|
||||
pBits += sizeof(BB_FONT);
|
||||
pBits += (pFont->last - pFont->first + 1) * sizeof(BB_GLYPH);
|
||||
pBits += (last - first + 1) * sizeof(BB_GLYPH);
|
||||
i = 0;
|
||||
while (szMsg[i] && x < pBBEP->native_width && y < pBBEP->native_height) {
|
||||
c = szMsg[i++];
|
||||
if (c < pFont->first || c > pFont->last) // undefined character
|
||||
if (c < first || c > last) // undefined character
|
||||
continue; // skip it
|
||||
c -= pFont->first; // first char of font defined
|
||||
c -= first; // first char of font defined
|
||||
pGlyph = &pFont->glyphs[c]; // glyph info for this character
|
||||
if (pGlyph->width > 1) { // skip this if drawing a space
|
||||
s = pBits + pGlyph->bitmapOffset; // start of compressed bitmap data
|
||||
if (pFont->rotation == 0 || pFont->rotation == 180) {
|
||||
h = pGlyph->height;
|
||||
w = pGlyph->width;
|
||||
dx = x + pGlyph->xOffset; // offset from character UL to start drawing
|
||||
dy = y + pGlyph->yOffset;
|
||||
if (pgm_read_byte(&pGlyph->width) > 1) { // skip this if drawing a space
|
||||
s = pBits + pgm_read_word(&pGlyph->bitmapOffset); // start of compressed bitmap data
|
||||
if (pgm_read_word(&pFont->rotation) == 0 || pgm_read_word(&pFont->rotation) == 180) {
|
||||
h = pgm_read_word(&pGlyph->height);
|
||||
w = pgm_read_byte(&pGlyph->width);
|
||||
dx = x + pgm_read_word(&pGlyph->xOffset); // offset from character UL to start drawing
|
||||
dy = y + pgm_read_word(&pGlyph->yOffset);
|
||||
} else { // rotated
|
||||
w = pGlyph->height;
|
||||
h = pGlyph->width;
|
||||
dx = x + pGlyph->yOffset; // offset from character UL to start drawing
|
||||
dy = y + pGlyph->xOffset;
|
||||
w = pgm_read_word(&pGlyph->height);
|
||||
h = pgm_read_byte(&pGlyph->width);
|
||||
dx = x + pgm_read_word(&pGlyph->yOffset); // offset from character UL to start drawing
|
||||
dy = y + pgm_read_word(&pGlyph->xOffset);
|
||||
}
|
||||
if ((dy + h) > pBBEP->native_height) { // trim it
|
||||
h = pBBEP->native_height - dy;
|
||||
@@ -644,7 +649,7 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
u8EndMask <<= (8-(w & 7));
|
||||
}
|
||||
end_y = dy + h;
|
||||
ty = (pGlyph[1].bitmapOffset - (intptr_t)(s - pBits)); // compressed size
|
||||
ty = (pgm_read_word(&pGlyph[1].bitmapOffset) - (intptr_t)(s - pBits)); // compressed size
|
||||
if (ty < 0 || ty > 4096) ty = 4096; // DEBUG
|
||||
rc = g5_decode_init(&g5dec, w, h, s, ty);
|
||||
if (rc != G5_SUCCESS) return; // corrupt data?
|
||||
@@ -689,8 +694,8 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
u8CMD = u8CMD2; // second plane is red (inverted)
|
||||
}
|
||||
bbepWriteCmd(pBBEP, u8CMD); // memory write command
|
||||
for (ty=dy; ty<end_y && ty < pBBEP->native_height; ty++) {
|
||||
g5_decode_line(&g5dec, u8Cache);
|
||||
for (ty=dy; ty<end_y && rc == G5_SUCCESS && ty < pBBEP->native_height; ty++) {
|
||||
rc = g5_decode_line(&g5dec, u8Cache);
|
||||
u8Cache[iSrcPitch-1] &= u8EndMask; // clean pixels beyond character width
|
||||
u8Cache[iSrcPitch] = 0;
|
||||
if (dx & 7) { // need to shift it over by 1-7 bits
|
||||
@@ -710,10 +715,10 @@ uint8_t *pBits, u8CMD1, u8CMD2, u8CMD, u8EndMask;
|
||||
} // for y
|
||||
}
|
||||
} // if not drawing a space
|
||||
if (pFont->rotation == 0 || pFont->rotation == 180) {
|
||||
x += pGlyph->xAdvance; // width of this character
|
||||
if (pgm_read_word(&pFont->rotation) == 0 || pgm_read_word(&pFont->rotation) == 180) {
|
||||
x += pgm_read_byte(&pGlyph->xAdvance); // width of this character
|
||||
} else {
|
||||
y += pGlyph->xAdvance;
|
||||
y += pgm_read_byte(&pGlyph->xAdvance);
|
||||
}
|
||||
} // while drawing characters
|
||||
pBBEP->iCursorX = x;
|
||||
|
||||
+6
-13
@@ -115,7 +115,6 @@ static void Decode_Begin(G5DECIMAGE *pPage)
|
||||
{
|
||||
int i, xsize;
|
||||
int16_t *CurFlips, *RefFlips;
|
||||
uint8_t *pBuf, *pBufEnd;
|
||||
|
||||
xsize = pPage->iWidth;
|
||||
|
||||
@@ -135,21 +134,15 @@ static void Decode_Begin(G5DECIMAGE *pPage)
|
||||
|
||||
pPage->pCur = CurFlips;
|
||||
pPage->pRef = RefFlips;
|
||||
|
||||
pBuf = pPage->pSrc;
|
||||
//
|
||||
// Some files may have leading 0's that would confuse the decoder
|
||||
// Valid G5 data can't begin with a 0
|
||||
//
|
||||
pBufEnd = &pBuf[128]; // DEBUG
|
||||
while (pBuf < pBufEnd && pBuf[0] == 0)
|
||||
{ pBuf++; }
|
||||
|
||||
pPage->pBuf = pBuf;
|
||||
pPage->ulBits = TIFFMOTOLONG(pBuf); // load 32 bits to start
|
||||
pPage->pBuf = pPage->pSrc;
|
||||
pPage->ulBits = TIFFMOTOLONG(pPage->pSrc); // load 32 bits to start
|
||||
pPage->ulBitOff = 0;
|
||||
// Calculate the number of bits needed for a long horizontal code
|
||||
#ifdef __AVR__
|
||||
pPage->iHLen = 16 - __builtin_clz(pPage->iWidth);
|
||||
#else
|
||||
pPage->iHLen = 32 - __builtin_clz(pPage->iWidth);
|
||||
#endif
|
||||
} /* Decode_Begin() */
|
||||
//
|
||||
// Decode a single line of G5 data (private function)
|
||||
|
||||
Reference in New Issue
Block a user