//fire with 8 custom chars on 2x16 lcd demo
//Yaroslaw Turbin 26-10-2024
//https://vk.com/ldirko
//https://www.reddit.com/user/ldirko/
//https://twitter.com/ldir_ko
//https://www.youtube.com/c/ldirldir

#include <Wire.h>
#include <hd44780.h>
#include <hd44780ioClass/hd44780_I2Cexp.h>

hd44780_I2Cexp lcd;

const int LCD_COLS = 16;
const int LCD_ROWS = 2;

#include <FastLED.h>

byte symb[8];

#define NUM_ROWS  8
#define NUM_COLS  40


byte firebuff[64];

void fire2021 (){
  int  a = millis();
  int  a1 = a/3;
  byte index = 0;
  int yoffs = 0;
  for (byte j = 0; j < NUM_ROWS; j++) {
    int xoffs = 0;
    byte bits = 4;
    for (byte i = 0; i < NUM_COLS; i++) {
      bits<<=1;
      byte color = qsub8 (inoise8 (xoffs, yoffs+a, a1), abs8(j - (NUM_ROWS-1)) * (255 / (NUM_ROWS+10)));
      // color = i*16+j*16+a1/2;  //for tests
      if (color>96) bits++;       // bits|=B00000001
      if (bits&128) {firebuff[index++]=bits; bits=4;}
      xoffs+=50;
    }
    yoffs+=50;
  }
}


void convertbuff (byte offset){
  for (byte j = 0; j < 8; j++){
    symb[j]=firebuff[offset+(j<<3)];
  }
}


void FPS(){
  static int frame = 0;
  static double currenttime = millis();
  frame++;

  if ((millis()-currenttime)>8000) {
    Serial.print(F("FPS: "));
    Serial.println(frame/8);
    frame = 0;
    currenttime = millis();
  }
}


int main(){
  init();
  Serial.begin(115200);
  lcd.init();
  lcd.backlight();
  lcd.noCursor();
  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("WORLD IN FIRE");
  lcd.setCursor(0, 1);
  lcd.print(" \1\2\3\4\5\6\7 \1\2\3\4\5\6\7");
  lcd.setCursor(0, 1);
  lcd.write(byte(0));
  lcd.setCursor(8, 1);
  lcd.write(byte(0));

  for(;;){
    fire2021();
    for (byte i = 0; i < 8; i++){
      convertbuff(i);
      lcd.createChar(i,symb);
    }
    FPS();
  }
}