/*
  Name:    Interface.cpp
  Author:  Roman Schönfeld & Daniel Hausherr
*/

/***********************************************************************************************
  This work is licensed under a Creative Commons Attribution 4.0 International (CC BY 4.0) License.

  You are free to:

  Share — copy and redistribute the material in any medium or format
  Adapt — remix, transform, and build upon the material
  for any purpose, even commercially.

  The licensor cannot revoke these freedoms as long as you follow the license terms.

  Under the following terms:

  Attribution — You must give appropriate credit, provide a link to the license, and indicate if
  changes were made. You may do so in any reasonable manner, but not in any way that suggests
  the licensor endorses you or your use.

  No additional restrictions — You may not apply legal terms or technological measures that
  legally restrict others from doing anything the license permits.

  Credits:
  Laboratory for Physics and Illumination Technologies,
  University of Applied Sciences Southern Westfalia
  Germany

  Make Light! Support by the BMBF in the development of this device is gratefully acknowledged
***************************************************************************************************/
#include "Interface.h"

#include "Menu.h"
#include "SauronPlus.h"
#include "Display.h"
#include "PhotometerPRO.h"
#include "PdResponse.h"


static const char *_VERSION = "Photometer PRO 2.1.3", *_VERSIONDATE = "Change:    08.11.2018";

// constants
static const char *_MAIN_MENU = "Hauptmenü", *_SETTING = "Einstellung", *_WAVELENGHT = "Wavelenght", *_DETECTOR = "Detector", *_MEASUREMENT = "Mess", *_INTEGRATION = "Integration", *_NUMBER = "Average", *_FIRMWARE = "Firmware";

// local variable
static uint8_t _bright = _TFT_BRIGHTNESS_HIGH, _number = 0;
static bool _isMeasurment = false, _update = false, auto_range = true;

static int8_t _isMicroAmps = -1, _isMicroPower = -1;

static uint16_t _nmtorgb[] = { (uint16_t)RGB(0xFF, 0x00, 0x90), (uint16_t)RGB(0xFF, 0x00, 0x78), (uint16_t)RGB(0xFF, 0x00, 0x66), (uint16_t)RGB(0xFF, 0x00, 0x56), (uint16_t)RGB(0xFF, 0x00, 0x54), (uint16_t)RGB(0xFF, 0x00, 0x50), (uint16_t)RGB(0xFF, 0x00, 0x8), (uint16_t)RGB(0xFF, 0x39, 0x00), (uint16_t)RGB(0xFF, 0xDB, 0x00),
                               (uint16_t)RGB(0xEC, 0xFF, 0x00), (uint16_t)RGB(0x2F, 0xFF, 0x00), (uint16_t)RGB(0x00, 0xFF, 0x8F), (uint16_t)RGB(0x00, 0xFF, 0xC7),
                               (uint16_t)RGB(0x00, 0xEB, 0xFF), (uint16_t)RGB(0x00, 0x8C, 0xFF), (uint16_t)RGB(0x79, 0x00, 0xFF), (uint16_t)RGB(0x89, 0x00, 0xFF), (uint16_t)RGB(0x91, 0x00, 0xFF)
                             };

static struct Menu *ptr_current_menu = NULL;
static struct MenueEntry *ptr_current_detector = NULL;
static struct MenueEntry *ptr_current_waveleght = NULL;

integrationTime         current_time;
photometer_wavelenght   current_wavelenght;
detectors               current_detector;
io_expander             current_io;
attenuation             current_attenuation;

// function pointer
typedef void(*MenuFnct) (void*);

// local function
static void draw_parameter(bool, const char*);
static void compute_value(void*);
static double get_unit_amps(double);
static double get_unit_power(double);
static void get_max_value(double, double);

static void down_fnct(void*);
static void up_fnct(void*);
static void right_fnct(void*);
static void left_fnct(void*);
static void enter_fnct(void*);

static void build_main_menu(void*, void*);
static void build_wavelenght_menu(void*, void*);
static void build_setting_menu(void*, void*);
static void build_detector_menu(void*, void*);
static void build_measurement_menu(void*, void*);
static void build_integration_menu(void*, void*);
static void build_numbermeas_menu(void*, void*);
static void build_firmware_menu(void*, void*);

// *************************************************************************************************
static const MenuFnct myfunc[] = {
  NULL,
  down_fnct,
  up_fnct,
  right_fnct,
  left_fnct
};
// *************************************************************************************************

// Menu struct
// ********************************* Main **********************************************************
Menu m_main[] = {
  _MAIN_MENU,
  0,
  NULL,
  hauptmenu,
  build_main_menu,
  NULL
};
MenueEntry hauptmenu[] = {
  { "Measurement", 0, NULL, m_measurement },
  { "Wavelenght", 0, NULL, m_wavelenght },
  { "Settings", 0, NULL, m_setting },
  NULL
};
// ********************************* Setting *******************************************************
Menu m_setting[] = {
  _SETTING,
  0,
  m_main,
  setting,
  build_setting_menu,
  NULL
};


MenueEntry setting[] = {
  { "Number of Averages", 0, NULL, m_numbermeas },
  { "Integrationtime", 0, NULL, m_integration },
  { "Detector", 0, NULL, m_detector },
  { "Firmware", 0, NULL, m_firmware },
  NULL
};
// ********************************* Firmware Version *******************************************************
Menu m_firmware[] = {
  _FIRMWARE,
  0,
  m_setting,
  firmware,
  build_firmware_menu,
  NULL
};
MenueEntry firmware[] = {
  { _VERSION, 0, NULL, NULL },
  { _VERSIONDATE, 0, NULL, NULL },
  NULL
};

// ********************************* Integrationstime *******************************************************
Menu m_integration[] = {
  _INTEGRATION,
  0,
  m_setting,
  integration,
  build_integration_menu,
  NULL
};
MenueEntry integration[] = {
  { "1 ms", 0, NULL, NULL },
  { "2 ms", 1, NULL, NULL },
  { "4 ms", 2, NULL, NULL },
  { "8 ms", 3, NULL, NULL },
  { "16 ms", 4, NULL, NULL },
  { "32 ms", 5, NULL, NULL },
  { "64 ms", 6, NULL, NULL },

  NULL
};
// ********************************* Anzahl Messungen *******************************************************
Menu m_numbermeas[] = {
  _NUMBER,
  0,
  m_setting,
  numbermeas,
  build_numbermeas_menu,
  NULL
};
MenueEntry numbermeas[] = {
  { "enf", 0, NULL, NULL },
  { "1", 1, NULL, NULL },
  { "10", 10, NULL, NULL },
  { "20", 20, NULL, NULL },
  { "40", 40, NULL, NULL },
  { "60", 60, NULL, NULL },
  { "80", 80, NULL, NULL },
  { "100", 100, NULL, NULL },

  NULL
};

// ******************************** Photodiode *****************************************************
Menu m_detector[] = {
  _DETECTOR,
  0,
  m_setting,
  detector,
  build_detector_menu,
  NULL
};
MenueEntry detector[] = {
  { "BPX-61",   0, get_bpx61_characteristic,        NULL },
  { "OSD-50",   1, get_osd50_characteristic,        NULL },

  NULL
};
//******************************* Wellenlänge ******************************************************
Menu m_wavelenght[] = {
  _WAVELENGHT,
  0,
  m_main,
  wavelenght,
  build_wavelenght_menu,
  NULL
};
MenueEntry wavelenght[] = {
  { "785 nm", 0, NULL, NULL },
  { "750 nm", 1, NULL, NULL },
  { "725 nm", 2, NULL, NULL },
  { "700 nm", 3, NULL, NULL },
  { "670 nm", 4, NULL, NULL },
  { "650 nm", 5, NULL, NULL },
  { "632 nm", 6, NULL, NULL },
  { "605 nm",  7, NULL, NULL },
  { "575 nm",  8, NULL, NULL },
  { "568 nm",  9, NULL, NULL },
  { "550 nm",  10, NULL, NULL },
  { "532 nm",  11, NULL, NULL },
  { "505 nm",  12, NULL, NULL },
  { "488 nm",  13, NULL, NULL },
  { "475 nm",  14, NULL, NULL },
  { "445 nm",  15, NULL, NULL },
  { "425 nm",  16, NULL, NULL },
  { "405 nm",  17, NULL, NULL },

  NULL
};

// *********************************** Messung *****************************************************
Menu m_measurement[] = {
  _MEASUREMENT,
  0,
  m_main,
  measurement,
  build_measurement_menu,
  NULL
};
MenueEntry measurement[] = {
  { " ", 0, compute_value, NULL },

  NULL
};


// Initialisiert die Menustruktur
void init_menu() {

  current_detector = (detectors)OSD_50;
  current_wavelenght = (photometer_wavelenght)NM_532;

  // Menuzeiger setzen
  ptr_current_menu = m_main;
  ptr_current_detector = detector;
  ptr_current_waveleght = wavelenght;

  ptr_current_menu->FnctDraw(&(ptr_current_menu->pointer), &(_update = false));

  draw_parameter(_update = false, NULL);
}

// Zeichnet die Parameter Wellenlänge und Messkopf
static void draw_parameter(bool change, const char* para) {

  if (!change) {
    clear_area_tft(0, 0, 160, 52, BLACK);

    set_cursor_tft(1, 1);
    print_text_tft((char*)_WAVELENGHT, WHITE);
    print_text_tft((char*)":", WHITE);

    set_text_size_tft(2);
    set_cursor_tft(75, 1);
    print_text_tft((char*)wavelenght[(uint8_t)current_wavelenght].e_name, _nmtorgb[wavelenght[(uint8_t)current_wavelenght].value]);
    set_text_size_tft(1);

    set_cursor_tft(1, 22);
    print_text_tft((char*)_DETECTOR, WHITE);
    print_text_tft((char*)":", WHITE);
    set_cursor_tft(75, 22);
    print_text_tft((char*)detector[(uint8_t)current_detector].e_name, NAV_COLOR);

    set_cursor_tft(1, 32);
    print_text_tft((char*)_INTEGRATION, WHITE);
    print_text_tft((char*)":", WHITE);
    set_cursor_tft(75, 32);
    print_text_tft((char*)integration[(uint8_t)current_time].e_name, NAV_COLOR);

    set_cursor_tft(1, 42);
    print_text_tft((char*)_NUMBER, WHITE);
    print_text_tft((char*)":", WHITE);
    set_cursor_tft(75, 42);
    print_text_tft((char*)numbermeas[_number].e_name, NAV_COLOR);
  }
  else {
    if ( para == _WAVELENGHT ) {
      clear_area_tft(75, 0, 90, 20, BLACK);
      set_cursor_tft(75, 1);
      set_text_size_tft(2);
      current_wavelenght = (photometer_wavelenght)ptr_current_menu->sublevel[ptr_current_menu->pointer].value;
      print_text_tft((char*)wavelenght[current_wavelenght].e_name, _nmtorgb[wavelenght[(uint8_t)current_wavelenght].value]);
      set_text_size_tft(1);
    }
    if ( para == _DETECTOR ) {
      clear_area_tft(75, 22, 85, 10, BLACK);
      set_cursor_tft(75, 22);
      print_text_tft((char*)detector[current_detector].e_name, NAV_COLOR);
    }
    if ( para == _INTEGRATION ) {
      clear_area_tft(75, 32, 85, 10, BLACK);
      set_cursor_tft(75, 32);
      print_text_tft((char*)integration[current_time].e_name, NAV_COLOR);
    }
    if ( para == _NUMBER) {
      clear_area_tft(75, 42, 85, 10, BLACK);
      set_cursor_tft(75, 42);
      print_text_tft((char*)numbermeas[_number].e_name, NAV_COLOR);
    }
  }
}

// Erstellt Menupunkte
static void build_main_menu(void* count, void* change) {
  uint8_t i = 0, x = 0, y = 0, offset_y = 65, offset_x = 15;
  const char *up = "Up", *down = "Down", *start = "Start", *entry = "Entry";
  static const char *right = "";

  if (!(*(bool*)change)) {
    clear_area_tft(0, 50, 160, 100, BLACK);
  }

  while (true) {
    if (ptr_current_menu->sublevel[i].e_name == NULL)
      break;

    set_cursor_tft((offset_x + x), (offset_y + y));

    if (i == *(uint8_t*)count)
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, NAV_COLOR);
    else
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, WHITE);

    i++;
    y += 10;
  }

  x = 65;
  y = 122;

  // Navigationsinfo Part
  if (ptr_current_menu->sublevel[*(uint8_t*)count].e_name == (char*)"Messung") {
    if (right == start) {
      ;
    } else {
      drawArrowRight(x + 45, y, (char*)right,  BLACK);
      right = start;
    }
  }
  else {
    if (right == entry) {
      ;
    } else {
      drawArrowRight(x + 45, y, (char*)right,  BLACK);
      right = entry;
    }
  }
  drawArrowRight(x + 45, y, (char*)right,  NAV_COLOR);

  if (!(*(bool*)change)) {
    drawArrowUp(x, y - 7, (char*)up,  NAV_COLOR);
    drawArrowDown(x, y + 3, (char*)down,  NAV_COLOR);
  }
}
static void build_wavelenght_menu(void* count, void* change) {
  uint8_t y = 65, x = 15;
  const char *right = "Confirm", *left = "Exit";


  if (!(*(bool*)change))
    clear_area_tft(0, 50, 160, 100, BLACK);
  else
    clear_area_tft(0, 50, 160, 67, BLACK);

  if (ptr_current_menu->sublevel[ptr_current_menu->pointer].e_name == NULL)
    ;
  else {
    set_text_size_tft(2);
    set_cursor_tft(x, y);
    print_text_tft((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer].e_name, _nmtorgb[(*(uint8_t*)count)]);
    set_text_size_tft(1);

    x = 1;
    y = 122;

    if (!(*(bool*)change)) {
      drawArrowRight(x + 104, y, (char*)right,  NAV_COLOR);
      drawArrowLeft(x, y, (char*)left,  NAV_COLOR);
    }

    clear_area_tft(50, 101, 40, 27, BLACK);

    if ((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer - 1].e_name == NULL)
      ;
    else
      drawArrowUp(x + 44, y - 7, (char*)ptr_current_menu->sublevel[ptr_current_menu->pointer - 1].e_name,  NAV_COLOR);

    if ((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer + 1].e_name == NULL)
       clear_area_tft(40, 118, 10, 20, BLACK);
    else
      drawArrowDown(x + 44, y + 3, (char*)ptr_current_menu->sublevel[ptr_current_menu->pointer + 1].e_name,  NAV_COLOR);
  }
}
static void build_setting_menu(void* count, void* change) {
  uint8_t i = 0, x = 0, y = 0, offset_y = 65, offset_x = 15;
  const char *up = "Up", *down = "Down", *left = "Exit", *right = "Entry";


  if (!(*(bool*)change)) {
    clear_area_tft(0, 50, 160, 100, BLACK);
  }


  while (true) {
    if (ptr_current_menu->sublevel[i].e_name == NULL)
      break;

    set_cursor_tft((offset_x + x), (offset_y + y));

    if (i == *(uint8_t*)count)
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, NAV_COLOR);
    else
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, WHITE);

    i++;
    y += 10;
  }
  x = 1;
  y = 122;

  if (!(*(bool*)change)) {
    drawArrowRight(x + 109, y, (char*)right,  NAV_COLOR);
    drawArrowLeft(x, y, (char*)left,  NAV_COLOR);
    drawArrowUp(x + 64, y - 7, (char*)up,  NAV_COLOR);
    drawArrowDown(x + 64, y + 3, (char*)down,  NAV_COLOR);
  }
}

void Enter_LabVIEW_Mode() {
  clear_area_tft(0, 0, 160, 128, BLACK);

  set_text_size_tft(2);
  set_cursor_tft(8, 55);
  print_text_tft("LabVIEW Mode", NAV_COLOR);
  set_text_size_tft(1);
    
  drawArrowLeft(1, 122, (char*)"Exit",  NAV_COLOR);
}



static void build_numbermeas_menu(void* count, void* change) {
  uint8_t y = 65, x = 15;
  const char *right = "Confirm", *left = "Exit";


  if (!(*(bool*)change))
    clear_area_tft(0, 50, 160, 100, BLACK);
  else
    clear_area_tft(0, 50, 160, 67, BLACK);

  if (ptr_current_menu->sublevel[ptr_current_menu->pointer].e_name == NULL)
    ;
  else {
    set_text_size_tft(2);
    set_cursor_tft(x, y);
    print_text_tft((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer].e_name, NAV_COLOR);
    set_text_size_tft(1);

    x = 1;
    y = 122;

    if (!(*(bool*)change)) {
      drawArrowRight(x + 104, y, (char*)right,  NAV_COLOR);
      drawArrowLeft(x, y, (char*)left,  NAV_COLOR);
    }

    clear_area_tft(45, 108, 60, 20, BLACK);
    if ((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer - 1].e_name == NULL)
      ;
    else
      drawArrowUp(x + 50, y - 7, (char*)ptr_current_menu->sublevel[ptr_current_menu->pointer - 1].e_name,  NAV_COLOR);

    if ((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer + 1].e_name == NULL)
      ;
    else
      drawArrowDown(x + 50, y + 3, (char*)ptr_current_menu->sublevel[ptr_current_menu->pointer + 1].e_name,  NAV_COLOR);
  }
}

static void build_integration_menu(void* count, void* change) {
  uint8_t y = 65, x = 15;
  const char *right = "Confirm", *left = "Exit";


  if (!(*(bool*)change))
    clear_area_tft(0, 50, 160, 100, BLACK);
  else
    clear_area_tft(0, 50, 160, 65, BLACK);

  if (ptr_current_menu->sublevel[ptr_current_menu->pointer].e_name == NULL)
    ;
  else {
    set_text_size_tft(2);
    set_cursor_tft(x, y);
    print_text_tft((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer].e_name, NAV_COLOR);
    set_text_size_tft(1);

    x = 1;
    y = 122;

    if (!(*(bool*)change)) {
      drawArrowRight(x + 104, y, (char*)right,  NAV_COLOR);
      drawArrowLeft(x, y, (char*)left,  NAV_COLOR);
    }

    clear_area_tft(45, 108, 60, 20, BLACK);
    if ((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer - 1].e_name == NULL)
      ;
    else
      drawArrowUp(x + 50, y - 7, (char*)ptr_current_menu->sublevel[ptr_current_menu->pointer - 1].e_name,  NAV_COLOR);

    if ((char*)ptr_current_menu->sublevel[ptr_current_menu->pointer + 1].e_name == NULL)
      ;
    else
      drawArrowDown(x + 50, y + 3, (char*)ptr_current_menu->sublevel[ptr_current_menu->pointer + 1].e_name,  NAV_COLOR);
  }
}

static void build_detector_menu(void* count, void* change) {
  uint8_t i = 0, x = 0, y = 0, offset_y = 65, offset_x = 15;
  const char *up = "Up", *down = "Down", *left = "Exit", *right = "Confirm";


  if (!(*(bool*)change)) {
    clear_area_tft(0, 50, 160, 100, BLACK);
  }

  while (true) {
    if (ptr_current_menu->sublevel[i].e_name == NULL)
      break;

    set_cursor_tft((offset_x + x), (offset_y + y));

    if (i == *(uint8_t*)count)
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, NAV_COLOR);
    else
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, WHITE);

    i++;
    y += 10;
  }
  x = 1;
  y = 122;

  if (!(*(bool*)change)) {
    drawArrowRight(x + 104, y, (char*)right,  NAV_COLOR);
    drawArrowLeft(x, y, (char*)left,  NAV_COLOR);
    drawArrowUp(x + 59, y - 7, (char*)up,  NAV_COLOR);
    drawArrowDown(x + 59, y + 3, (char*)down,  NAV_COLOR);
  }
}

static void build_measurement_menu(void* count, void* change) {
  uint8_t x = 1, y = 122;

  if (!_isMeasurment) {
    right_fnct(NULL);
  } else {
    _isMeasurment = false;

    clear_area_tft(0, 108, 160, 20, BLACK);
    drawArrowRight(x + 104, y, (char*)"Start",  NAV_COLOR);
    drawArrowLeft(x, y, (char*)"Exit",  NAV_COLOR);
  }
}
static void build_firmware_menu(void* count, void* change) {
  uint8_t i = 0, x = 0, y = 0, offset_y = 65, offset_x = 15;



  if (!(*(bool*)change)) {
    clear_area_tft(0, 50, 160, 100, BLACK);
  }

  while (true) {
    if (ptr_current_menu->sublevel[i].e_name == NULL)
      break;

    set_cursor_tft((offset_x + x), (offset_y + y));

    if (i == *(uint8_t*)count)
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, WHITE);
    else
      print_text_tft((char*)ptr_current_menu->sublevel[i].e_name, WHITE);

    i++;
    y += 10;
  }
  x = 1;
  y = 122;

  clear_area_tft(0, 108, 160, 20, BLACK);
  drawArrowLeft(x, y, (char*)"Exit",  NAV_COLOR);

}

// *************************************************************************************************
void navigation_menue(uint8_t p_position) {
  if (p_position >= 1 && p_position <= 4)
    myfunc[p_position](NULL);
}
static void down_fnct(void*) {
  ptr_current_menu->pointer++;
  if (ptr_current_menu->sublevel[ptr_current_menu->pointer].e_name == NULL) {
    ptr_current_menu->pointer--;
  }
  else {
    ptr_current_menu->FnctDraw(&(ptr_current_menu->pointer), &(_update = true));
  }
}
static void up_fnct(void*) {
  if (ptr_current_menu->pointer <= 0)
    ;
  else {
    ptr_current_menu->pointer--;
    ptr_current_menu->FnctDraw(&(ptr_current_menu->pointer), &(_update = true));
  }
}
static void right_fnct(void*) {
  if (ptr_current_menu->sublevel[ptr_current_menu->pointer].child == NULL) {

    // Messung neu starten bei Richts
    if (ptr_current_menu->e_name == _MEASUREMENT) {
      if ( !_isMeasurment )
        ptr_current_menu->sublevel[ptr_current_menu->pointer].Fnct(NULL);
    }


    // Messkopf übernehmen bei Richts
    if (ptr_current_menu->e_name == _DETECTOR) {
      current_detector = (detectors)ptr_current_menu->sublevel[ptr_current_menu->pointer].value;
      ptr_current_detector = ptr_current_menu->sublevel;
      draw_parameter(_update = true, _DETECTOR);
    } 

    // Wellenlänge übernehmen bei Richts
    if (ptr_current_menu->e_name == _WAVELENGHT) {
      current_wavelenght = (photometer_wavelenght)ptr_current_menu->sublevel[ptr_current_menu->pointer].value;
      draw_parameter(_update = true, _WAVELENGHT);
    }

    //
    if (ptr_current_menu->e_name == _INTEGRATION) {
      current_time = (integrationTime)ptr_current_menu->sublevel[ptr_current_menu->pointer].value;
      draw_parameter(_update = true, _INTEGRATION);
    }

    //
    if (ptr_current_menu->e_name == _NUMBER) {
      _number = (uint8_t)ptr_current_menu->pointer ;
      draw_parameter(_update = true, _NUMBER);
    }
  }
  else {
    ptr_current_menu = ptr_current_menu->sublevel[ptr_current_menu->pointer].child;
    ptr_current_menu->FnctDraw(&(ptr_current_menu->pointer), &(_update = false));
  }
}
static void left_fnct(void*) {
  if (ptr_current_menu->parent == NULL)
    ;
  else {
    ptr_current_menu = ptr_current_menu->parent;
    ptr_current_menu->FnctDraw(&(ptr_current_menu->pointer), &(_update = false));
  }
}

static void connect_labview(void*) {

  set_cursor_tft(0, 0);
  print_text_tft((char*)"LabVIEW", YELLOW);

  ptr_current_menu->FnctDraw(NULL, NULL);
}

//**************************************************************************************************
static void compute_value(void*) {
  bool first = true, meas_break = false, first_digit_zero_amps = false, first_digit_zero_power = false, first_digit_zero_range = false, change_digit = false;

  uint8_t x = 1, y = 122, tmp_num = 0, range = 0;

  int16_t digits[] = {0, 0, 0, 0, 0}, digits_amps[] = {0, 0, 0, 0, 0}, digits_range[] = {0, 0, 0, 0, 0};
  int16_t prevDigits[] = { -1, -1, -1, -1, -1}, prevDigits_amps[] = { -1, -1, -1, -1, -1},  prevDigits_range[] = { -1, -1, -1, -1, -1};
  uint16_t digitPos[] = {32, 44, 56, 74, 86}, digitPos_amps[] = {50, 56, 62, 71, 77}, digitPos_range[] = {120, 126, 132, 141, 147};

  uint16_t time_break = 0;

  const char *left = "Stop", current_unit = "";

  double factor_unit_power = 1.0d, current_in_microa = 0.0d, average = 0.0d, peek_max = -1.0d, current_to_power = 1.0d, power = 0.0d, tmp_digit = 0.0d, tmp = 0.0d;

  clear_area_tft(0, 50, 160, 80, BLACK);

  drawArrowLeft(x, y, (char*)left,  NAV_COLOR);


  _isMeasurment = true;

  tmp_num = numbermeas[_number].value;

  ptr_current_detector[(uint8_t)current_detector].Fnct(&current_to_power);   // Counts je 1 mW, abhängig von der Photodiode und Sphäre

  while (true) {
    //***********************************************************************************
    // check for count loop if NULL break meas. loop
    if (numbermeas[_number].value != 0) {
      if (tmp_num == 0)
        break;
      else
        tmp_num--;
    }
    //***********************************************************************************

    //***********************************************************************************
    // check for break "Exit"
    while (true) {
      if ((uint16_t)analogRead(_X_MOVE) > (MAX_THRESHOLD - 100)) {
        meas_break = true;
      }

      time_break++;

      if (time_break >= 6 || meas_break) {
        time_break = 0;

        break;
      } else
        delay(25);
    }

    // now exit
    if (meas_break) {
      meas_break = false;
      break;
    }
    //***********************************************************************************

    //***********************************************************************************
    // check for auto range
    if (auto_range)
      define_matching_range();
    else
      set_settings_device();
    //***********************************************************************************
    
    if ((get_value_in_current(&current_in_microa) == 0)) {   // 0 success

      // *********************************************************************************************
      // ********************************* Begin Digit Current ***************************************
      tmp = current_in_microa * get_unit_amps(current_in_microa);

      digits_amps[0] = (int16_t)(tmp / 100.0d);
      tmp_digit = (double)digits_amps[0] * 100.0d;

      digits_amps[1] = (int16_t)((tmp - tmp_digit) / 10.0d);
      tmp_digit = tmp_digit + ((double)digits_amps[1] * 10.0d);

      digits_amps[2] = (int16_t)(tmp - tmp_digit);
      tmp_digit = tmp_digit + (double)digits_amps[2];

      digits_amps[3] = (int16_t)((tmp - tmp_digit) * 10.0d);
      tmp_digit = tmp_digit + ((double)digits_amps[3] / 10.0d);

      digits_amps[4] = (int16_t)((tmp - tmp_digit) * 100.0d);


      set_cursor_tft(66, 118);
      print_text_tft((char*)".", YELLOW);

      for (uint8_t i = 0; i < 5; i++) {
        if ((prevDigits_amps[i] != digits_amps[i])) {
          set_cursor_tft(digitPos_amps[i], 118);

          if (prevDigits_amps[i] != -1) {
            print_value_tft(prevDigits_amps[i], BLACK);
            set_cursor_tft(digitPos_amps[i], 118);
          }

          print_value_tft(digits_amps[i], YELLOW);

          prevDigits_amps[i] = digits_amps[i];
        }
      }
      
      // ********************************* End Digit Current ***************************************
      // *******************************************************************************************
      // ****************************** Begin Draw Current Range ***********************************
      
      if (range != get_range()) 
      {
        clear_area_tft(103, 117, 12, 12, BLACK);
        range = get_range();
        if (range > 1 && range < 9) {
          drawArrowDown(x + 110, y + 2, "", YELLOW);
          drawArrowUp(x + 105, y + 2, "", YELLOW);
        } else if ( range == 1 ) {
          drawArrowUp(x + 105, y + 2, "", YELLOW);
        } else {
          drawArrowDown(x + 110, y + 2, "", YELLOW);
        }
      }
   
      set_cursor_tft(150, 118);
      print_text_tft((char*)"%", YELLOW);

      tmp = ((current_in_microa / get_max_range()) * 100.0d);

      digits_range[0] = (int16_t)(tmp / 100.0d);
      tmp_digit = (double)digits_range[0] * 100.0d;

      digits_range[1] = (int16_t)((tmp - tmp_digit) / 10.0d);
      tmp_digit = tmp_digit + ((double)digits_range[1] * 10.0d);

      digits_range[2] = (int16_t)(tmp - tmp_digit);
      tmp_digit = tmp_digit + (double)digits_range[2];

      digits_range[3] = (int16_t)((tmp - tmp_digit) * 10.0d);

      set_cursor_tft(136, 118);
      print_text_tft((char*)".", YELLOW);

      for (uint8_t i = 0; i < 4; i++) {
        if ((prevDigits_range[i] != digits_range[i])) {
          set_cursor_tft(digitPos_range[i], 118);

          if (prevDigits_range[i] != -1) {
            print_value_tft(prevDigits_range[i], BLACK);
            set_cursor_tft(digitPos_range[i], 118);
          }

          print_value_tft(digits_range[i], YELLOW);
          
          prevDigits_range[i] = digits_range[i];
        }
      }

      // ****************************** End Draw Current Range ***********************************
      // *****************************************************************************************
      // ********************************* Begin Digit Power *************************************
       
      power = (current_in_microa / current_to_power);
      
      factor_unit_power = get_unit_power(power);
      
      //********************************* get peek value ***************************************** 
      if (power > peek_max)
      {      
        if(first)
        {
          set_cursor_tft(1, 65);
          print_text_tft((char*)"Max: ", WHITE);
        }
        
        peek_max = power;

        clear_area_tft(35, 63, 42, 11, BLACK);
        
        if((peek_max * factor_unit_power) < 100.0d)
        {
          set_cursor_tft(44, 65);
        }
        else
        if((peek_max * factor_unit_power) >= 100.0d && (peek_max * factor_unit_power) < 1000.0d)
        {      
          set_cursor_tft(39, 65);
        }
        
        print_value_tft_double((peek_max * factor_unit_power), YELLOW);

        if ( factor_unit_power == 1000.0d ) 
        {
          clear_area_tft(80, 65, 45, 10, BLACK);
          set_cursor_tft(80, 65);
          print_text_tft((char*)"nW", YELLOW);

        } 
        else 
        if ( factor_unit_power == 1.0d ) 
        {
          clear_area_tft(80, 65, 50, 10, BLACK);
          drawMicro(84, 67, 1, YELLOW);
          set_cursor_tft(90, 65);
          print_text_tft((char*)"W", YELLOW);
        } else 
        if(factor_unit_power == 0.001d)
        {
          clear_area_tft(80, 65, 45, 10, BLACK);
          set_cursor_tft(80, 65);
          print_text_tft((char*)"mW", YELLOW);
        } 
        else 
        if(factor_unit_power == 0.000001d)
        {
          clear_area_tft(75, 65, 45, 10, BLACK);
          set_cursor_tft(75, 65);
          print_text_tft((char*)"W", YELLOW);
        }       
      }
      //************************************* End peek value *************************************

      tmp = (power * factor_unit_power);

      digits[0] = (int16_t)(tmp / 100.0d);
      tmp_digit = (double)digits[0] * 100.0d;

      digits[1] = (int16_t)((tmp - tmp_digit) / 10.0d);
      tmp_digit = tmp_digit + ((double)digits[1] * 10.0d);

      digits[2] = (int16_t)(tmp - tmp_digit);
      tmp_digit = tmp_digit + (double)digits[2];

      digits[3] = (int16_t)((tmp - tmp_digit) * 10.0d);
      tmp_digit = tmp_digit + ((double)digits[3] / 10.0d);

      digits[4] = (int16_t)((tmp - tmp_digit) * 100.0d);

      set_text_size_tft(2);
      set_cursor_tft(64, 90);
      print_text_tft((char*)".", YELLOW);

      for (uint8_t i = 0; i < 5; i++) {
        if ((prevDigits[i] != digits[i])) {
          set_cursor_tft(digitPos[i], 90);
          if (prevDigits[i] != -1) {
            print_value_tft(prevDigits[i], BLACK);
            set_cursor_tft(digitPos[i], 90);
          }
          
          print_value_tft(digits[i], YELLOW);
          
          prevDigits[i] = digits[i];
        }
      }
      
      set_text_size_tft(1);

      if (numbermeas[_number].value != 0) {
        average = (power + average);
      }
      else
      {
        average = power;
      }
      
      if (first)
        first = false;

    }
    else {
      _isMeasurment = false;
      
      break;
    }
  } // end main loop
  //************************************************** End of LOOP ********************************************
  //************************************************** Mittelwert ausgeben ************************************

  if (numbermeas[_number].value != 0) {
    set_text_size_tft(2);

    average = (average / numbermeas[_number].value);

    clear_area_tft(106, 90, 54, 20, BLACK);

    tmp = average;

    if (average < 1.0d) 
    {
      tmp *= 1000.0d;

      set_cursor_tft(106, 90);
      print_text_tft((char*)"nW", YELLOW);
    }
    else
    if (average < 1000.0d && average >= 1.0d) 
    {
      drawMicro(106, 95, 2, YELLOW);
      set_cursor_tft(116, 90);
      print_text_tft((char*)"W", YELLOW);
    }
    else 
    if (average >= 1000.0d && average < 1000000.0d) 
    {
      tmp *=  0.001d;

      set_cursor_tft(106, 90);
      print_text_tft((char*)"mW", YELLOW);
    } 
    else 
    if (average >= 1000000.0d) 
    {
        tmp *=  0.000001d;

      set_cursor_tft(106, 90);
      print_text_tft((char*)"W", YELLOW);
    }

    digits[4] = (((uint16_t)((tmp / 2) * 100.0f) * 2) % 10);

    digits[3] = ((uint16_t)(tmp * 10.0f) % 10);

    digits[2] = ((uint16_t)tmp % 10);

    digits[1] = ((uint16_t)(tmp / 10.0f) % 10);

    digits[0] = ((uint16_t)(tmp / 100.0f) % 10);

    for (uint8_t i = 0; i < 5; i++)
    {
      if ((prevDigits[i] != digits[i]))
      {
        set_cursor_tft(digitPos[i], 90);
        if (prevDigits[i] != -1)
        {
          print_value_tft(prevDigits[i], BLACK);
          set_cursor_tft(digitPos[i], 90);
        }
        print_value_tft(digits[i], YELLOW);
        prevDigits[i] = digits[i];
      }
    }

    set_text_size_tft(1);
  }
  //************************************************************************************

  _isMicroPower = -1;
  _isMicroAmps = -1;

  ptr_current_menu->FnctDraw(NULL, NULL);
}

double get_unit_amps(double mirco_amps) 
{
  set_cursor_tft(92, 118);
  print_text_tft((char*)"A", YELLOW);
  
  // µA 
  if (mirco_amps < 1000.0d && mirco_amps >= 1.0d)         
  {        
    if (_isMicroAmps != 1) {

      clear_area_tft(85, 118, 6, 10, BLACK);
      drawMicro(87, 120, 1, YELLOW);

      _isMicroAmps = 1;
    }
    
    return 1.0d;
  }
  // mA 
  if (mirco_amps >= 1000.0d) 
  {                     
    if (_isMicroAmps != 2) {

      clear_area_tft(85, 118, 6, 10, BLACK);

      set_cursor_tft(85, 118);
      print_text_tft((char*)"m", YELLOW);

      _isMicroAmps = 2;
    }
    
    return 0.001d;
  }
  // nA 
  if (mirco_amps < 1.0d) 
  {                        
    if (_isMicroAmps != 0) {

      clear_area_tft(86, 118, 5, 10, BLACK);

      set_cursor_tft(86, 118);
      print_text_tft((char*)"n", YELLOW);

      _isMicroAmps = 0;
    }
    
    return 1000.0d;
  }
}
double get_unit_power(double mirco_power) {
  // nW
  if (mirco_power < 1.0d) 
  {                         
    if (_isMicroPower != 0) 
    {

      set_text_size_tft(2);
      clear_area_tft(106, 90, 54, 20, BLACK);

      set_cursor_tft(106, 90);
      //print_text_tft((char*)"nW", YELLOW);
      set_text_size_tft(1);

      _isMicroPower = 0;
    }
    
    return 1000.0d;
  }
  
  // µW
  if (mirco_power < 1000.0d && mirco_power >= 1.0d) 
  {      
     if (_isMicroPower != 1) 
    {         
      clear_area_tft(106, 90, 54, 20, BLACK);

      set_text_size_tft(2);
      drawMicro(106, 95, 2, YELLOW);
      set_cursor_tft(116, 90);
      print_text_tft((char*)"W", YELLOW);
      set_text_size_tft(1);

      _isMicroPower = 1;
    }

    return 1.0d;
  } 

  // mW
  if (mirco_power >= 1000.0d && mirco_power < 1000000.0d) 
  {                   
    if (_isMicroPower != 2)
    {

      set_text_size_tft(2);
      clear_area_tft(106, 90, 54, 20, BLACK);

      set_cursor_tft(106, 90);
      print_text_tft((char*)"mW", YELLOW);
      set_text_size_tft(1);

      _isMicroPower = 2;
    }
    
    return 0.001d;
  } 

  // W
  if (mirco_power >= 1000000.0d) 
  {                   
    if (_isMicroPower != 3)
    {

      set_text_size_tft(2);
      clear_area_tft(104, 88, 26, 16, BLACK);

      set_cursor_tft(106, 90);
      print_text_tft((char*)"W", YELLOW);
      set_text_size_tft(1);

      _isMicroPower = 3;
    }
    
    return 0.000001d;
  }
}
