Skip to content

Adding Bad Apple Example for Sharp Display #1215

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
222 changes: 222 additions & 0 deletions SHARP_BadApple/SHARP_BadApple.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
// Bad Apple for ESP32 with OLED SSD1306 | 2018 by Hackerspace-FFM.de | MIT-License.
// Adapted for Sharp Memory display + Itsy Bitsy M4 - put video.hs on QSPI storage using CircuitPython
#include "heatshrink_decoder.h"

#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include <Adafruit_SharpMem.h>
#define BLACK 0
#define WHITE 1

#define SCALE 3


#if HEATSHRINK_DYNAMIC_ALLOC
#error HEATSHRINK_DYNAMIC_ALLOC must be false for static allocation test suite.
#endif

static heatshrink_decoder hsd;

// global storage for putPixels
int16_t curr_x = 0;
int16_t curr_y = 0;

// global storage for decodeRLE
int32_t runlength = -1;
int32_t c_to_dup = -1;

uint32_t lastRefresh = 0;

#define SHARP_SS A5
Adafruit_SharpMem display(&SPI, SHARP_SS, 400, 240, 3000000);
#define X_OFFSET (400 - SCALE*128) / 2
#define Y_OFFSET (240 - SCALE*64) / 2

Adafruit_FlashTransport_QSPI flashTransport;
Adafruit_SPIFlash flash(&flashTransport);
FatFileSystem fatfs;


void putPixels(uint8_t c, int32_t len) {
static uint8_t color;
uint8_t b = 0;
while(len--) {
b = 128;
for (int i=0; i<8; i++) {
if (c & b) {
color = WHITE;
} else {
color = BLACK;
}
b >>= 1;
if (color == BLACK) {
// we clear the buffer each frame so only black pixels need to be drawn
display.fillRect(X_OFFSET+curr_x*SCALE, Y_OFFSET+curr_y*SCALE, SCALE, SCALE, color);
}
curr_x++;
if(curr_x >= 128) {
curr_x = 0;
curr_y++;
if(curr_y >= 64) {
curr_y = 0;
display.refresh();
display.clearDisplayBuffer();
// 30 fps target rate
//if(digitalRead(0)) while((millis() - lastRefresh) < 33) ;
//lastRefresh = millis();
}
}
}
}
}

void decodeRLE(uint8_t c) {
if(c_to_dup == -1) {
if((c == 0x55) || (c == 0xaa)) {
c_to_dup = c;
} else {
putPixels(c, 1);
}
} else {
if(runlength == -1) {
if(c == 0) {
putPixels(c_to_dup & 0xff, 1);
c_to_dup = -1;
} else if((c & 0x80) == 0) {
if(c_to_dup == 0x55) {
putPixels(0, c);
} else {
putPixels(255, c);
}
c_to_dup = -1;
} else {
runlength = c & 0x7f;
}
} else {
runlength = runlength | (c << 7);
if(c_to_dup == 0x55) {
putPixels(0, runlength);
} else {
putPixels(255, runlength);
}
c_to_dup = -1;
runlength = -1;
}
}
}

#define RLEBUFSIZE 4096
#define READBUFSIZE 2048
void readFile(const char * path){
static uint8_t rle_buf[RLEBUFSIZE];
size_t rle_bufhead = 0;
size_t rle_size = 0;

size_t filelen = 0;
size_t filesize;
static uint8_t compbuf[READBUFSIZE];

Serial.printf("Reading file: %s\n", path);
File file = fatfs.open(path);
if(!file || file.isDirectory()){
Serial.println("Failed to open file for reading");
display.println("File open error. Upload video.hs using CircuitPython");
display.refresh();
return;
}
filelen = file.size();
filesize = filelen;
Serial.printf("File size: %d\n", filelen);

// init display, putPixels and decodeRLE
display.clearDisplay();
display.refresh();
curr_x = 0;
curr_y = 0;
runlength = -1;
c_to_dup = -1;
lastRefresh = millis();

// init decoder
heatshrink_decoder_reset(&hsd);
size_t count = 0;
uint32_t sunk = 0;
size_t toRead;
size_t toSink = 0;
uint32_t sinkHead = 0;


// Go through file...
while(filelen) {
if(toSink == 0) {
toRead = filelen;
if(toRead > READBUFSIZE) toRead = READBUFSIZE;
file.read(compbuf, toRead);
filelen -= toRead;
toSink = toRead;
sinkHead = 0;
}

// uncompress buffer
HSD_sink_res sres;
sres = heatshrink_decoder_sink(&hsd, &compbuf[sinkHead], toSink, &count);
//Serial.print("^^ sinked ");
//Serial.println(count);
toSink -= count;
sinkHead = count;
sunk += count;
if (sunk == filesize) {
heatshrink_decoder_finish(&hsd);
}

HSD_poll_res pres;
do {
rle_size = 0;
pres = heatshrink_decoder_poll(&hsd, rle_buf, RLEBUFSIZE, &rle_size);
//Serial.print("^^ polled ");
//Serial.println(rle_size);
if(pres < 0) {
Serial.print("POLL ERR! ");
Serial.println(pres);
return;
}

rle_bufhead = 0;
while(rle_size) {
rle_size--;
if(rle_bufhead >= RLEBUFSIZE) {
Serial.println("RLE_SIZE ERR!");
return;
}
decodeRLE(rle_buf[rle_bufhead++]);
}
} while (pres == HSDR_POLL_MORE);
}
file.close();
Serial.println("Done.");
}



void setup(){
Serial.begin(115200);
//while (!Serial) delay(10);
Serial.println("Bad apple");

flash.begin();
// Init file system on the flash
fatfs.begin(&flash);

display.begin();
display.clearDisplay();
display.setTextColor(BLACK, WHITE);
display.setTextSize(2);
display.println("Scaled Bad Apple For SHARP Memory");
display.refresh();

readFile("/video.hs");
}

void loop(){

}
Binary file added SHARP_BadApple/data/video.hs
Binary file not shown.
20 changes: 20 additions & 0 deletions SHARP_BadApple/heatshrink_common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef HEATSHRINK_H
#define HEATSHRINK_H

#define HEATSHRINK_AUTHOR "Scott Vokes <[email protected]>"
#define HEATSHRINK_URL "https://github.com/atomicobject/heatshrink"

/* Version 0.4.1 */
#define HEATSHRINK_VERSION_MAJOR 0
#define HEATSHRINK_VERSION_MINOR 4
#define HEATSHRINK_VERSION_PATCH 1

#define HEATSHRINK_MIN_WINDOW_BITS 4
#define HEATSHRINK_MAX_WINDOW_BITS 15

#define HEATSHRINK_MIN_LOOKAHEAD_BITS 3

#define HEATSHRINK_LITERAL_MARKER 0x01
#define HEATSHRINK_BACKREF_MARKER 0x00

#endif
26 changes: 26 additions & 0 deletions SHARP_BadApple/heatshrink_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef HEATSHRINK_CONFIG_H
#define HEATSHRINK_CONFIG_H

/* Should functionality assuming dynamic allocation be used? */
#ifndef HEATSHRINK_DYNAMIC_ALLOC
#define HEATSHRINK_DYNAMIC_ALLOC 0
#endif

#if HEATSHRINK_DYNAMIC_ALLOC
/* Optional replacement of malloc/free */
#define HEATSHRINK_MALLOC(SZ) malloc(SZ)
#define HEATSHRINK_FREE(P, SZ) free(P)
#else
/* Required parameters for static configuration */
#define HEATSHRINK_STATIC_INPUT_BUFFER_SIZE 2048
#define HEATSHRINK_STATIC_WINDOW_BITS 11
#define HEATSHRINK_STATIC_LOOKAHEAD_BITS 4
#endif

/* Turn on logging for debugging. */
#define HEATSHRINK_DEBUGGING_LOGS 0

/* Use indexing for faster compression. (This requires additional space.) */
#define HEATSHRINK_USE_INDEX 1

#endif
Loading