/****************************************
've added Serial.println() statements to display the following 
actions:

Setup started
Drawing the big motif
Drawing lots of small motifs
Drawing 'Arvind' in yellow
Loop started
Plasma reset
Random or centered position of the motif
Filling plasma
Switching to a random motif
Randomising plasma properties
These statements will help you track the
 progress of the code in the serial monitor.

modified wokwi examplee


arvind patil 7/4/24





**************************************/



#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(" By Arvind" );
  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;
  }
}

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;
    Serial.print(free);
    Serial.println(" free");
  }
  return free;
}