#include <Adafruit_ILI9341.h>
#include "motif.h"
#include "rgb_plasma.h"
#include <Fonts/FreeSansBold9pt7b.h>
Adafruit_ILI9341 tft = Adafruit_ILI9341(10, 9);
Plasma plasma;
PROGMEM RLE565 * const motifs[] = {&smmotif, &bigmotif};
RLE565 *this_motif = motifs[0];
void draw_ILI9341(int16_t x, int16_t y, uint16_t *buffer, uint16_t width) {
tft.drawRGBBitmap(x, y, buffer, width, 1);
}
void drawText(int16_t x, int16_t y, const char* text, uint16_t color) {
tft.setFont(&FreeSansBold9pt7b);
tft.setCursor(x, y);
tft.setTextColor(color);
tft.print(text);
}
void setup(void) {
Serial.begin(115200);
Serial.println("Setup started");
tft.begin();
Serial.println("Drawing the big motif");
int16_t x = ILI9341_TFTWIDTH / 2 - bigmotif.width() / 2;
int16_t y = ILI9341_TFTHEIGHT / 2 - bigmotif.height() / 2;
bigmotif.plot(draw_ILI9341, x, y);
delay(1000);
Serial.println("Drawing lots of small motifs");
for (int16_t y = smmotif.height() / -3; y < ILI9341_TFTHEIGHT; y += smmotif.height())
for (int16_t x = smmotif.width() / -3; x < ILI9341_TFTWIDTH; x += smmotif.width())
smmotif.plot(draw_ILI9341, x, y);
Serial.println("Drawing 'Arvind' in yellow");
drawText(10, 10, "Arvind", ILI9341_YELLOW);
}
void loop() {
Serial.println("Loop started");
static int16_t last_ymin = 0;
static int16_t last_ymax = ILI9341_TFTHEIGHT;
int16_t h = this_motif->height();
int16_t w = this_motif->width();
int16_t x, y;
plasma.reset();
Serial.println("Plasma reset");
if (rand() & 0x1) {
x = (rand() % (ILI9341_TFTWIDTH - w / 3)) - w / 3;
y = (rand() % (ILI9341_TFTHEIGHT - h / 3 )) - h / 3;
Serial.print("Random position: x = "); Serial.print(x); Serial.print(", y = "); Serial.println(y);
} else {
x = ILI9341_TFTWIDTH / 2 - w / 2;
y = ILI9341_TFTHEIGHT / 2 - h / 2;
Serial.print("Centered position: x = "); Serial.print(x); Serial.print(", y = "); Serial.println(y);
}
int16_t ymin = min(y, last_ymin);
int16_t ymax = min(y + h, ILI9341_TFTHEIGHT);
ymin = max(ymin, 0);
ymax = max(ymax, last_ymax);
if (ymin < y) {
plasma.ystepn(ymin);
Serial.print("Filling plasma from ymin = "); Serial.print(ymin); Serial.print(" to y = "); Serial.println(y);
yfill_plasma(ymin, y, ILI9341_TFTWIDTH);
} else {
plasma.ystepn(y);
}
this_motif->plot(composite_ILI9341, x, y);
if (y + h < ymax) {
if (last_ymin > y + h) {
delay(2000);
plasma.ystepn(last_ymin - y - h);
Serial.print("Filling plasma from last_ymin = "); Serial.print(last_ymin); Serial.print(" to last_ymax = "); Serial.println(last_ymax);
yfill_plasma(last_ymin, last_ymax, ILI9341_TFTWIDTH);
} else {
Serial.print("Filling plasma from y = "); Serial.print(y + h); Serial.print(" to last_ymax = "); Serial.println(last_ymax);
yfill_plasma(y + h, last_ymax, ILI9341_TFTWIDTH);
}
}
last_ymin = max(y, 0);
last_ymax = min(y + h, ILI9341_TFTHEIGHT);
if (rand() & 1) {
uint8_t motif_num = rand() % (sizeof(motifs) / sizeof(motifs[0]));
this_motif = pgm_read_ptr_near(&motifs[motif_num]);
Serial.print("Switching to motif number: "); Serial.println(motif_num);
} else if (rand() & 1) {
last_ymin = 0, last_ymax = ILI9341_TFTHEIGHT;
plasma.randomise();
Serial.println("Randomising plasma properties");
if (rand() & 1)
plasma.p.paint.r = plasma.p.paint.g = plasma.p.paint.b = 0;
else
plasma.p.paint.r = plasma.p.paint.g = plasma.p.paint.b = 255;
if (rand() & 1)
plasma.compositeoperator = alphamask_op;
else
plasma.compositeoperator = invert_op;
}
Serial.print("Free memory: "); Serial.println(freemem());
Serial.println("---------------------------------------");
delay(5000);
}
void yfill_plasma(int16_t y0, int16_t y1, uint16_t width) {
uint16_t buffer[width];
for (auto y = y0; y < y1; y++) {
memset(buffer, 0, width * 2);
composite_ILI9341(0, y, buffer, width);
}
}
void composite_ILI9341(int16_t x, int16_t y, uint16_t *buffer, uint16_t width) {
if (y < 0) return;
plasma.ystep();
if (x > 0) {
int16_t left = x < ILI9341_TFTWIDTH ? x : ILI9341_TFTWIDTH;
uint16_t tmp[left];
memset(tmp, 0, left * 2);
plasma.composite_row(left, tmp);
tft.drawRGBBitmap(x - left, y, tmp, left, 1);
} else if (x < 0) {
buffer -= x;
width += x;
x = 0;
}
plasma.composite_row(width, buffer);
tft.drawRGBBitmap(x, y, buffer, width, 1);
int16_t right = ILI9341_TFTWIDTH - x - width;
if (right > 0) {
right = right < ILI9341_TFTWIDTH ? right : ILI9341_TFTWIDTH;
uint16_t tmp[right];
memset(tmp, 0, right * 2);
plasma.composite_row(right, tmp);
tft.drawRGBBitmap(ILI9341_TFTWIDTH - right, y, tmp, right, 1);
}
}
uint16_t freemem() {
extern int __heap_start;
extern int *__brkval;
static uint16_t freemin = -1;
uint16_t free;
free = (int) &free - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
if (free < freemin) {
freemin = free;
}
return free;
}