void setup_screen() {
  // Initialise the TFT registers
  tft.init();
  tft.setRotation(3);

  // Optionally set colour depth to 8 or 16 bits, default is 16 if not spedified
   spr.setColorDepth(8);

  // Create a sprite of defined size
  spr.createSprite(HEIGHT, WIDTH);
  // Clear the TFT screen to blue
  tft.fillScreen(TFT_BLACK);
}

int data[HEIGHT] = {0};

float to_scale(float reading) {
  float temp = WIDTH -
               (
                 (
                   (
                     (float)((reading - 20480.0) / 4095.0)
                     + (offset / 3.3)
                   )
                   * 3300 /
                   (v_div * 6)
                 )
               )
               * (WIDTH - 1)
               - 1;
  return temp;
}

float to_voltage(float reading) {
  return  (reading - 20480.0) / 4095.0 * 3.3;
}

uint32_t from_voltage(float voltage) {
  return uint32_t(voltage / 3.3 * 4095 + 20480.0);
}

void update_screen(uint16_t *i2s_buff, float sample_rate) {

  float mean = 0;
  float max_v, min_v;

  peak_mean(i2s_buff, BUFF_SIZE, &max_v, &min_v, &mean);

  float freq = 0;
  float period = 0;
  uint32_t trigger0 = 0;
  uint32_t trigger1 = 0;

  //if analog mode OR auto mode and wave recognized as analog
  bool digital_data = false;
  if (digital_wave_option == 1) {
    trigger_freq_analog(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0, &trigger1);
  }
  else if (digital_wave_option == 0) {
    digital_data = digital_analog(i2s_buff, max_v, min_v);
    if (!digital_data) {
      trigger_freq_analog(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0, &trigger1);
    }
    else {
      trigger_freq_digital(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0);
    }
  }
  else {
    trigger_freq_digital(i2s_buff, sample_rate, mean, max_v, min_v, &freq, &period, &trigger0);
  }

  draw_sprite(freq, period, mean, max_v, min_v, trigger0, sample_rate, digital_data, true);
}

void draw_sprite(float freq,
                 float period,
                 float mean,
                 float max_v,
                 float min_v,
                 uint32_t trigger,
                 float sample_rate,
                 bool digital_data,
                 bool new_data
                ) {

  max_v = to_voltage(max_v);
  min_v = to_voltage(min_v);

  String frequency = "";
  if (freq < 1000)
    frequency = String(freq) + "hz";
  else if (freq < 100000)
    frequency = String(freq / 1000) + "khz";
  else
    frequency = "----";

  String s_mean = "";
  if (mean > 1.0)
    s_mean = "Avg: " + String(mean) + "V";
  else
    s_mean = "Avg: " + String(mean * 1000.0) + "mV";

  String str_filter = "";
  if (current_filter == 0)
    str_filter = "None";
  else if (current_filter == 1)
    str_filter = "Pixel";
  else if (current_filter == 2)
    str_filter = "Mean-5";
  else if (current_filter == 3)
    str_filter = "Lpass9";

  String str_stop = "";
  if (!stop)
    str_stop = "RUNNING";
  else
    str_stop = "STOPPED";

  String wave_option = "";
  if (digital_wave_option == 0)
    if (digital_data )
      wave_option = "AUTO:Dig./data";
    else
      wave_option = "AUTO:Analog";
  else if (digital_wave_option == 1)
    wave_option = "MODE:Analog";
  else
    wave_option = "MODE:Dig./data";


  if (new_data) {
    // Fill the whole sprite with black (Sprite is in memory so not visible yet)
    spr.fillSprite(TFT_BLACK);

    draw_grid();

    if (auto_scale) {
      auto_scale = false;
      v_div = 1000.0 * max_v / 6.0;
      s_div = period / 3.5;
      if (s_div > 7000 || s_div <= 0)
        s_div = 7000;
      if (v_div <= 0)
        v_div = 550;
    }

    //only draw digital data if a trigger was in the data
    if (!(digital_wave_option == 2 && trigger == 0))
      draw_channel1(trigger, 0, i2s_buff, sample_rate);
  }

  int shift = 150;
  if (menu) {
    spr.drawLine( 0, 120, HEIGHT, 120, TFT_WHITE); //center line
    spr.fillRect(shift, 0, 102, 135, TFT_BLACK);
    spr.drawRect(shift, 0, 102, 135, TFT_WHITE);
    spr.fillRect(shift + 1, 3 + 10 * (opt - 1), 100, 11, TFT_RED);

    spr.drawString("AUTOSCALE",  shift + 5, 5);
    spr.drawString(String(int(v_div)) + "mV/div",  shift + 5, 15);
    spr.drawString(String(int(s_div)) + "uS/div",  shift + 5, 25);
    spr.drawString("Offset: " + String(offset) + "V",  shift + 5, 35);
    spr.drawString("T-Off: " + String((uint32_t)toffset) + "uS",  shift + 5, 45);
    spr.drawString("Filter: " + str_filter, shift + 5, 55);
    spr.drawString(str_stop, shift + 5, 65);
    spr.drawString(wave_option, shift + 5, 75);
    spr.drawString("Single " + String(single_trigger ? "ON" : "OFF"), shift + 5, 85);

    spr.drawLine(shift, 103, shift + 100, 103, TFT_WHITE);

    spr.drawString("Vmax: " + String(max_v) + "V",  shift + 5, 105);
    spr.drawString("Vmin: " + String(min_v) + "V",  shift + 5, 115);
    spr.drawString(s_mean,  shift + 5, 125);

    shift -= 70;

    //spr.fillRect(shift, 0, 70, 30, TFT_BLACK);
    spr.drawRect(shift, 0, 70, 30, TFT_WHITE);
    spr.drawString("P-P: " + String(max_v - min_v) + "V",  shift + 5, 5);
    spr.drawString(frequency,  shift + 5, 15);
    //String offset_line = String((2.0 * v_div) / 1000.0 - offset) + "V";
    String offset_line = String((3.0 * v_div) / 1000.0 - offset) + "V";
    spr.drawString(offset_line,  shift + 40, 59);

    if (set_value) {
      spr.fillRect(229, 0, 11, 11, TFT_BLUE);
      spr.drawRect(229, 0, 11, 11, TFT_WHITE);
      spr.drawLine(231, 5, 238 , 5, TFT_WHITE);
      spr.drawLine(234, 2, 234, 8, TFT_WHITE);


      spr.fillRect(229, 124, 11, 11, TFT_BLUE);
      spr.drawRect(229, 124, 11, 11, TFT_WHITE);
      spr.drawLine(231, 129, 238, 129, TFT_WHITE);
    }
  }
  else if (info) {
    spr.drawLine( 0, 120, HEIGHT, 120, TFT_WHITE); //center line
    //spr.drawRect(shift + 10, 0, HEIGHT - shift - 20, 30, TFT_WHITE);
    spr.drawString("P-P: " + String(max_v - min_v) + "V",  shift + 15, 5);
    spr.drawString(frequency,  shift + 15, 15);
    spr.drawString(String(int(v_div)) + "mV/div",  shift - 100, 5);
    spr.drawString(String(int(s_div)) + "uS/div",  shift - 100, 15);
    //String offset_line = String((2.0 * v_div) / 1000.0 - offset) + "V";
    String offset_line = String((3.0 * v_div) / 1000.0 - offset) + "V";
    spr.drawString(offset_line,  shift + 100, 112);
  }


  //push the drawed sprite to the screen
  spr.pushSprite(0, 0);

  yield(); // Stop watchdog reset
}

void draw_grid() {

  for (int i = 0; i < (HEIGHT/10); i++) {
    spr.drawPixel(i * 10, 40, TFT_WHITE);
    spr.drawPixel(i * 10, 80, TFT_WHITE);
    spr.drawPixel(i * 10, 120, TFT_WHITE);
    spr.drawPixel(i * 10, 160, TFT_WHITE);
    spr.drawPixel(i * 10, 200, TFT_WHITE);
  }
  for (int i = 0; i < WIDTH; i += 10) {
    for (int j = 0; j < HEIGHT; j += 40) {
      spr.drawPixel(j, i, TFT_WHITE);
    }
  }
}

void draw_channel1(uint32_t trigger0, uint32_t trigger1, uint16_t *i2s_buff, float sample_rate) {
  //screen wave drawing
  data[0] = to_scale(i2s_buff[trigger0]);
  low_pass filter(0.99);
  mean_filter mfilter(5);
  mfilter.init(i2s_buff[trigger0]);
  filter._value = i2s_buff[trigger0];
  float data_per_pixel = (s_div / 40.0) / (sample_rate / 1000);

  //  uint32_t cursor = (trigger1-trigger0)/data_per_pixel;
  //  spr.drawLine(cursor, 0, cursor, 135, TFT_RED);

  uint32_t index_offset = (uint32_t)(toffset / data_per_pixel);
  trigger0 += index_offset;  
  uint32_t old_index = trigger0;
  float n_data = 0, o_data = to_scale(i2s_buff[trigger0]);
  for (uint32_t i = 1; i < HEIGHT; i++) {
    uint32_t index = trigger0 + (uint32_t)((i + 1) * data_per_pixel);
    if (index < BUFF_SIZE) {
      if (full_pix && s_div > 40 && current_filter == 0) {
        uint32_t max_val = i2s_buff[old_index];
        uint32_t min_val = i2s_buff[old_index];
        for (int j = old_index; j < index; j++) {
          //draw lines for all this data points on pixel i
          if (i2s_buff[j] > max_val)
            max_val = i2s_buff[j];
          else if (i2s_buff[j] < min_val)
            min_val = i2s_buff[j];

        }
        spr.drawLine(i, to_scale(min_val), i, to_scale(max_val), TFT_BLUE);
      }
      else {
        if (current_filter == 2)
          n_data = to_scale(mfilter.filter((float)i2s_buff[index]));
        else if (current_filter == 3)
          n_data = to_scale(filter.filter((float)i2s_buff[index]));
        else
          n_data = to_scale(i2s_buff[index]);

        spr.drawLine(i - 1, o_data, i, n_data, TFT_BLUE);
        o_data = n_data;
      }

    }
    else {
      break;
    }
    old_index = index;
  }
}
