Arduino:Примеры/GLCDdiags

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Тест памяти и интерфейса GLCD-модуля [1]

Этот пример показывает при помощи Arduino и библиотеки GLCD протестировать память и интерфейс GLCD-модуля. Тесты выполняются с использованием нескольких графиков.

Код

 
/*
 * Тест памяти и интерфейса GLCD-модуля (с графиками)
 *
 * Этот скетч тестирует память и интерфейс GLCD-модуля, а также сообщает 
 * о текущей конфигурации библиотеки GLCD (через последовательный порт).
 *
 * Последовательный порт настроен на скорость 9600 бод.
 *
 * Кроме того, он показывает на GLCD-панели несколько графиков, 
 * призванных помочь в диагностике того, правильно ли настроены
 * и подключены CS-линии.
 *
 * Память каждого чипа тестируется отдельно.
 * Тесты выполняются начиная с чипа #0.
 * Во время тестирования памяти на GLCD-панели будет поочередно показано 
 * несколько графиков. 
 * 
 * Кроме того, показывается номер чипа и значение координаты X. 
 * Если все настроено и работает правильно, чип #0 будет слева, а все 
 * последующие чипы – справа.
 *
 * Во время тестирования статус и информация об ошибках будут 
 * отправляться через последовательный порт.
 *
 * Этот скетч выполняет несколько разных тестов памяти, но главный тест 
 * работает через возрастание. При горизонтальных проходах возрастание 
 * будет осуществляться по столбцам (слева направо), а при вертикальных – 
 * по страницам (сверху вниз).
 * 
 * ПРИМЕЧАНИЕ:
 * Этот скетч – диагностический инструмент, а не пример 
 * использования библиотеки. Он использует внутреннюю информацию
 * библиотеки GLCD, которая обычно скетчами не используется. 
 * В будущих релизах скетчи, использующие эту информацию,
 * могут работать неправильно.
 */


#include <glcd.h>
#include "glcd_Buildinfo.h"
#include "include/glcd_io.h"
#include "include/glcd_errno.h"
#include "fonts/SystemFont5x7.h"       // системный шрифт

/*
 * Макрос, конвертирующий номер чипа в вертикальные координаты пикселя. 
 * x1,y1 это координаты для самого верхнего левого пикселя, а x2,y2 – 
 * для самого нижнего левого пикселя.
 */

#define chip2x1(chip) ((chip * CHIP_WIDTH) % DISPLAY_WIDTH)
#define chip2y1(chip) (((chip * CHIP_WIDTH)/DISPLAY_WIDTH) * CHIP_HEIGHT)
#define chip2x2(chip) ((chip2x1(chip) + CHIP_WIDTH) >= DISPLAY_WIDTH ? DISPLAY_WIDTH-1 : chip2x1(chip) + CHIP_WIDTH-1)
#define chip2y2(chip) ((chip2y1(chip) + CHIP_HEIGHT) >= DISPLAY_HEIGHT ? DISPLAY_HEIGHT-1 : chip2y1(chip) + CHIP_HEIGHT-1)

#include <avr/pgmspace.h>
#define P(name)   static const prog_char name[] PROGMEM   // объявляем статичную строку, которая будет храниться в программной памяти AVR

#define MAX_ERRORS 10

#ifdef _AVRIO_AVRIO_
#define SerialPrintPINstr(x) \
  _SerialPrintPINstr(x, AVRIO_PIN2AVRPORT(AVRIO_PIN2AVRPIN(x)), AVRIO_PIN2AVRBIT(AVRIO_PIN2AVRPIN(x)))
#else
#define SerialPrintPINstr(x) _SerialPrintPINStr(x)
#endif

/*
 * Объявляем в программной памяти строку для горизонтальной линии.
 */
P(hline) =  "--------------------------------------------------------------------\n";


#define xstr(s) str(s)
#define str(...) #__VA_ARGS__

/*
 * Функция для передачи простой закавыченной строки на 
 * последовательный порт. Она будет автоматически сохраняться в 
 * программной (flash) памяти.
 */

#define SerialPrintQ(str) SerialPrintP(PSTR(str))

/*
 * Передаем строку из программной памяти на последовательный порт.
 * Также вставляем символ новой строки, потому что последовательный порт
 * работает в «сыром» режиме.
 *
 */

void SerialPrintP(const prog_char * str )
{
  char c;
  const prog_char *p = str;

  while ((c = pgm_read_byte(p++)))
  {
    if(c == '\n')
      Serial.print('\r');
    Serial.print(c);   
  }
}

#ifdef SERIALPRINTF

/*
 * Задаем НАСТОЯЩУЮ printf(), потому что у Arduino такой нет.
 *
 * Функция SerialPrintf() автоматически поместит форматирующую строку 
 * в программную память AVR.
 * 
 */

#define SerialPrintf(fmt, ...) _SerialPrintf(PSTR(fmt), ##__VA_ARGS__)

extern "C" {
  int serialputc(char c, FILE *fp)
  { 
      if(c == '\n')
        Serial.write('\r'); 
    Serial.write(c); 
  }
}


void _SerialPrintf(const char *fmt, ...)
{
FILE stdiostr;
va_list ap;

  fdev_setup_stream(&stdiostr, serialputc, NULL, _FDEV_SETUP_WRITE);

  va_start(ap, fmt);
  vfprintf_P(&stdiostr, fmt, ap);
  va_end(ap);
}

/*
 * Задаем функцию eprintf() для вывода информации об ошибках.
 * Привязываем ее к функции SerialPrintf(), заданной выше.
 */
#define eprintf(...) SerialPrintf(__VA_ARGS__)

#endif //SERIALPRINTF


/*
 * Функция GlcdPrintf() будет автоматически помещать форматирующую строку
 * в программную память AVR.
 */
#define GlcdPrintf(fmt, ...) GLCD.Printf_P(PSTR(fmt), ##__VA_ARGS__)


void setup()
{
  Serial.begin(9600);

#ifdef CORE_TEENSY
  delay(2000);    // Даем некоторое время на появление USB-соединения.
                  // Плюс еще немного времени на то, чтобы пользователь 
                  // запустил монитор порта. 
                  // ПРИМЕЧАНИЕ ДЛЯ ПОЛЬЗОВАТЕЛЕЙ Teensy:
                  //    Ждите короткой «вспышки» на иконке монитора порта 
                  //    в IDE Arduino. Это значит, что USB-соединение 
                  //    появилось, а IDE Arduino заметила плату Teensy.
                  //    Затем кликните на эту иконку, чтобы подключиться 
                  //    к виртуальному COM-порту платы Teensy.
#endif

  delay(5);    // даем оборудованию время, чтобы загрузиться
  SerialPrintQ("Serial initialized\n");  //  "Последовательное соединение инициализировано\n"
}


/*
 * Пытаемся показать графическую информацию, которая демонстрирует,
 * правильно ли подключены SC-линии или нет.
 */
void showchipselscreen(void)
{
  /*
   * Рисуем треугольник.
   */
  for(int x = 0; x < GLCD.Width; x++)
  {
     GLCD.DrawVLine( x, 0, map(x, 0, GLCD.Right, 0, GLCD.Bottom));
     delay(50); // небольшая задержка, чтобы определить, не дублируются и не накладываются ли друг на друга CS-линии
  }   
  delay(4000);
  // show chips
  GLCD.ClearScreen();
  for(int chip = 0; chip < glcd_CHIP_COUNT; chip++)
  {
    // Задержка и переменная flash нужны, чтобы определить, 
    // не дублируются и не накладываются ли друг на друга CS-линии:
    for(uint8_t flash = 0; flash < 4; flash++)
    {
      GLCD.CursorToXY(chip2x1(chip), chip2y1(chip));
      if(flash & 1)
        GLCD.SetFontColor(BLACK);
      else
        GLCD.SetFontColor(WHITE);
      GLCD.print("Chip:");
      GLCD.print(chip);
      delay(350); 
    }
  }

  delay(5000);

  /*
   * Показываем информацию о версиях и символы формата ASCII.
   */
  GLCD.ClearScreen();
  GLCD.CursorTo(0,0);
  GLCD.print("GLCD   ver ");
  GLCD.println(GLCD_VERSION, DEC); 
  GLCD.print("gText  ver ");
  GLCD.println(GTEXT_VERSION, DEC); 
  GLCD.print("Device ver ");
  GLCD.println(GLCD_Device, DEC); // не ставим символ новой строки, чтобы не стереть EOL
  for(int i=0; i  < GLCD.Width / GLCD.CharWidth(' '); i++ )
  {
     GLCD.print(char('A' + i)); // показываем символ ASCII
  }
  delay(5000);
}

void  loop()
{   // Этот блок будет работать снова и снова.

int lcount = 1;
unsigned int glcdspeed, kops, kops_fract;
int status;

  while(1)
  {
    /*
     * Перед «общением» с GLCD выгружаем информацию о ее настройках,
     * чтобы затем, собственно, с этим общением не было никаких проблем. 
     * Благодаря этому последовательный порт всегда будет иметь доступ 
     * к информации о GLCD.
     */

    /*
     * Выгружаем информацию о настройках библиотеки GLCD
     * на последовательный порт.
     */
    showGLCDconfig();


    SerialPrintP(hline);
    SerialPrintQ("Diag Loop: ");    //  "Счетчик циклов"
    Serial.println(lcount);

    SerialPrintQ("Initializing GLCD\n");  //  "Инициализация GLCD\n"
    status = GLCD.Init();   // инициализируем библиотеку в режиме рисования

#ifndef GLCD_NOINIT_CHECKS
    if(status) // инициализация удалась?
    {
	SerialPrintQ("GLCD initialization Failed: ");  //  "Инициализация GLCD не удалась: " 
	switch(status)
	{
		case GLCD_EBUSY:
			SerialPrintQ("BUSY wait Timeout");  //  "GLCD занят, таймаут"
			break;
		case GLCD_ERESET:
			SerialPrintQ("RESET wait Timeout");  //  "Сброс, таймаут: "
			break;
	}
	SerialPrintQ(" (status code: ");    //  "Код статуса: "
	Serial.print(status);
	Serial.println(')');
    	goto finished;
    }
#endif


    GLCD.SelectFont(System5x7, BLACK);


    SerialPrintQ("Displaying ChipSelect Screens\n");    //  "График подключения CS-линий\n"
    showchipselscreen();
    if( lcdmemtest())
    {
      /*
       * Тесты памяти завершились неуспешно.
       */
      SerialPrintQ("TEST FAILED\n");  //  "ТЕСТ ЗАВЕРШИЛСЯ НЕУСПЕШНО\n: "
    }
    else
    {
      SerialPrintQ("Tests PASSED\n");  //  "ТЕСТ ПРОЙДЕН\n"

      /*
       * В конце показываем счетчик циклов.
       */
      GLCD.ClearScreen();
      GLCD.CursorTo(0,0);
      GLCD.print("Diag Loop: ");    //  "Счетчик циклов"
      GLCD.println(lcount);
      GLCD.println("Tests PASSED");  //  "Тесты ПРОЙДЕНЫ"

      /*
       * Теперь запускаем тест «скорости» GLCD.
       */

      glcdspeed = getglcdspeed();
      /*
       * Рассчитываем скорость в 1000 операций в секунду.
       * Чтобы получить фактическое значение, делим 
       * возвращенное значение на 100.
       */

      kops = glcdspeed/100;
      kops_fract = glcdspeed %100;

      GLCD.print("K SetDot/s: ");   //  "Тысяч нарисованных пикселей в секунду: "
      GLCD.print(kops);
      GLCD.print(".");
      GLCD.println(kops_fract);


      SerialPrintQ("GLCD.SetDot() speed (K ops/sec): ");  //  "Скорость GLCD.SetDot() (тысяч операций в секунду): "
      Serial.print(kops);
      SerialPrintQ(".");
      Serial.println(kops_fract);
    }

finished:

    delay(5000);
    lcount++;
  }
}


uint8_t lcdmemtest(void)
{
  uint8_t errors = 0;

  SerialPrintQ("Walking 1s data test\n");    //  "Тестирование одной (пробной) ячейки памяти\n"

  errors = lcdw1test();
  if(errors)
    return(errors);

  SerialPrintQ("Wr/Rd Chip Select Test\n");  //  "Тестирование записи/чтения номера чипа\n"

  errors = lcdrwseltest();
  if(errors)
    return(errors);

  GLCD.ClearScreen();

  SerialPrintQ("Testing GLCD memory pages\n");  //  "Тестирование страниц памяти GLCD-панели\n"

  for(uint8_t chip = 0; chip < glcd_CHIP_COUNT; chip++)
  {
    uint8_t col = chip2x1(chip);
    uint8_t ecol = chip2x2(chip);

    if(col >= CHIP_WIDTH)
      GLCD.CursorToXY(0,chip2y1(chip));
    else
      GLCD.CursorToXY(CHIP_WIDTH,chip2y1(chip));
    GLCD.print("Chip:");
    GLCD.print((int)chip);

    /*
     * Исходим из того, что высота шрифта – 8 пикселей.
     */
    if(col >= CHIP_WIDTH)
      GLCD.CursorToXY(0,chip2y1(chip)+8);
    else
      GLCD.CursorToXY(CHIP_WIDTH,chip2y1(chip)+8);
    GLCD.print((int)col);
    GLCD.print('-');
    GLCD.print((int)ecol);
    delay(500);

//  SerialPrintf("Horizontal Page Test Chip: %d Pixels %d-%d\n", chip, col, ecol);  //  "Тестирование с горизонтальным проходом по страницам"

    SerialPrintQ("Horizontal Page Test Chip: ");  //  "Тестирование с горизонтальным проходом по страницам"
    Serial.print((int)chip);
    SerialPrintQ(" Pixels ");
    Serial.print((int)col);
    Serial.print('-');
    Serial.println((unsigned int)ecol);

    errors += lcdhpagetest(col, ecol, chip2y1(chip)/8, (chip2y2(chip)+1)/8 - 1, 0, 255);


//  SerialPrintf("Vertical Page Test Chip: %d Pixels %d-%d\n", chip, col, ecol);  //  "Тестирование с вертикальным проходом по страницам"

    SerialPrintQ("Vertical Page Test Chip: ");  //  "Тестирование с вертикальным проходом по страницам"
    Serial.print((int)chip);
    SerialPrintQ(" Pixels ");
    Serial.print((int)col);
    Serial.print('-');
    Serial.println((int)ecol);

    errors += lcdvpagetest(col, ecol, chip2y1(chip)/8, (chip2y2(chip)+1)/8 - 1, 0, 255);
    GLCD.ClearScreen();

    col += CHIP_WIDTH;
    ecol += CHIP_WIDTH;
    if(ecol > GLCD.Right)
      ecol = GLCD.Right;
  }


  GLCD.CursorTo(0,0);
  GLCD.print("Full Display");
  GLCD.CursorTo(0,1);
  GLCD.print((int)0);
  GLCD.print('-');
  GLCD.print((int)GLCD.Right);
  delay(1000);

//SerialPrintf("Full Module Horizontal Page Test:Pixels %d-%d\n",  0, GLCD.Right);

  SerialPrintQ("Full Module Horizontal Page Test:Pixels ");
  Serial.print(0);
  Serial.print('-');
  Serial.println((int)GLCD.Right);

  errors += lcdhpagetest(0, GLCD.Right, 0, GLCD.Bottom/8, 0, 255);

//SerialPrintf("Full Module Vertical Page Test:Pixels %d-%d\n",  0, GLCD.Right);

  SerialPrintQ("Full Module Vertical Page Test:Pixels ");
  Serial.print(0);
  Serial.print('-');
  Serial.println((int)GLCD.Right);

  errors += lcdvpagetest(0, GLCD.Right, 0, GLCD.Bottom/8, 0, 255);

  GLCD.ClearScreen();

  return(errors);
}

/*
 * Проходимся по одной ячейке памяти, чтобы понять работают ли 
 * запись и считывание.
 */

uint8_t
lcdw1test(void)
{
  uint8_t errors = 0;
  uint8_t rdata;

  for(uint8_t pat = 1;  pat != 0; pat <<= 1)
  {
    GLCD.GotoXY(0,0);
    GLCD.WriteData(pat);
    GLCD.GotoXY(0,0);
    rdata = GLCD.ReadData();

    if(rdata != pat)
    {
//    eprintf(" Compare error: %x != %x\n", rdata, pat);
      SerialPrintQ(" Compare error: ");
      Serial.print((unsigned int)rdata, HEX);
      SerialPrintQ(" != ");
      Serial.println((unsigned int)pat, HEX);

      errors++;
    }
  }
  return(errors);
}

/*
 * Тест CS-линии с записью/считыванием памяти чипов.
 * Этот тест пытается определить проблемы с CS-линиями, записывая номер 
 * чипа в самую младшую страницу памяти каждого чипа. Это выполняется и 
 * при возрастании, и при убывании. Это делается два раза, поскольку если 
 * CS-линия задана неправильно, то запись можно совершить на несколько 
 * чипов одновременно. Чтобы избежать этого, запись нужно проделать два 
 * раза – сначала идя от младшего адреса к старшему (возрастание), а 
 * потом от старшего к младшему (убывание).
 */

uint8_t
lcdrwseltest()
{
  uint8_t errors = 0;
  uint8_t rdata; // считываем данные


  for(uint8_t chip = 0; chip < glcd_CHIP_COUNT; chip++)
  {
    GLCD.GotoXY(chip2x1(chip), chip2y1(chip));
    GLCD.WriteData(chip);
  }
  for(uint8_t chip = 0; chip < glcd_CHIP_COUNT; chip++)
  {
    GLCD.GotoXY(chip2x1(chip), chip2y1(chip));
    rdata = GLCD.ReadData();
    if(rdata != chip)
    {
//    eprintf(" Compare error: chip:%d %x != %x\n", chip, rdata, chip);
      SerialPrintQ(" Compare error: chip:");
      Serial.print((int)chip);
      Serial.print(' ');
      Serial.print((unsigned int)rdata, HEX);
      SerialPrintQ(" != ");
      Serial.println((unsigned int)chip, HEX);
      errors++;
    }
  }

  for(int chip = glcd_CHIP_COUNT - 1; chip >= 0; chip--)
  {
    GLCD.GotoXY(chip2x1(chip), chip2y1(chip));
    GLCD.WriteData(chip);
  }
  for(int chip = glcd_CHIP_COUNT - 1; chip >= 0; chip--)
  {
    GLCD.GotoXY(chip2x1(chip), chip2y1(chip));
    rdata = GLCD.ReadData();
    if(rdata != chip)
    {
//    eprintf(" Compare error: chip:%d  %x != %x\n", chip, rdata, chip);
      SerialPrintQ(" Compare error: chip:");
      Serial.print((int)chip);
      Serial.print(' ');
      Serial.print((unsigned int)rdata, HEX);
      SerialPrintQ(" != ");
      Serial.println((unsigned int)chip, HEX);
      errors++;
    }
  }

  return(errors);
}


/*
 * Поочередно проходим по всем ячейкам памяти.
 * 
 * Проход будет осуществляться горизонтально. Начальное значение – sval,
 * конечное значение – eval. Значение sval записывается в стартовую 
 * ячейку «x», а затем (по мере прохода через все тестируемые ячейки) 
 * постепенно увеличивается. Когда в текущем ряду/странице достигается 
 * максимальное значение «x», запись начинает выполняться 
 * в следующем ряду/странице.
 *
 * Кроме того, все эти значения будут считываться и сравниваться с
 * ожидаемыми значениями.
 *
 * Затем процесс начинается снова посредством постепенного увеличения 
 * стартового значения. Он повторяется, пока стартовое значение не 
 * достигнет конечного значения.
 *
 * Переход от одной ячейки к другой выполняется по формуле evel-sval+1.
 *
 * Если sval равно «0», а eval равно «255», будут протестированы
 * каждая ячейка и каждое значение. 
 *
 */


int lcdhpagetest(uint8_t x1, uint8_t x2, uint8_t spage, uint8_t epage, uint8_t sval, uint8_t eval)
{
  uint8_t x;
  uint8_t data;
  uint8_t rdata;
  uint8_t page;
  uint8_t errors = 0;

  /*
   * Выполняем тестовый проход по памяти, постепенно увеличивая 
   * значение sval, а затем удаляя его.
   */
  do
  {
    /*
     * Поочередно проходя по столбцам (значения x), осуществляем запись 
     * во все страницы памяти GLCD.
     */

    data = sval;
    for(page = spage; page <= epage; page++)
    {

      GLCD.GotoXY(x1, page * 8);
      for(x = x1; x <= x2; x++)
      {
        /*
	    * Функция GotoXY() намеренно не выполняется здесь, в цикле, 
	    * чтобы девайс смог выгрузить внутренний адрес. Это обеспечит, 
	    * что код для GLCD и оборудование будут должным образом 
	    * отслеживать друг друга.
         */
        GLCD.WriteData(data);
        data++;
      }
    }

    /*
     * Теперь идем обратно и проверяем страницы.
     */

    data = sval;
    for(page = spage; page <= epage; page++)
    {

      for(x = x1; x<= x2; x++)
      {
        /*
         * При считывании автоматическое увеличение X не выполняется.
         */
        GLCD.GotoXY(x, page * 8);
        rdata = GLCD.ReadData();

        if(data != rdata)
        {
//        eprintf(" Verify error: (%d,%d) %x!=%x\n", x, spage*8, data, rdata);
          SerialPrintQ(" Verify error: (");
          Serial.print((unsigned int) x);
          Serial.print(',');
          Serial.print((unsigned int) (spage*8));
          SerialPrintQ(") ");
          Serial.print((unsigned int)data, HEX);
          SerialPrintQ("!=");
          Serial.println((unsigned int)rdata, HEX);

          if(++errors > MAX_ERRORS)
            return(errors);
        }
        data++;
      }
    }
  } 
  while(sval++ != eval);
  return(0);
}

/*
 * Поочередно проходим по всем ячейкам памяти.
 * 
 * Проход будет осуществляться вертикально. Начальное значение – sval,
 * конечное значение – eval. Значение sval записывается в стартовую 
 * ячейку «x», а затем (по мере прохода через все тестируемые страницы) 
 * постепенно увеличивается. Когда достигается максимальный ряд/страница
 * запись продолжается на следующем.
 *
 * Кроме того, все эти значения будут считываться и сравниваться с
 * ожидаемыми значениями.
 * 
 * Затем процесс начинается снова посредством постепенного увеличения 
 * стартового значения. Он повторяется, пока стартовое значение не 
 * достигнет конечного значения.
 * 
 * В результате тестируется каждая ячейка памяти – посредством 
 * постепенного увеличения значения по формуле evel-sval+1. 
 *
 * Если sval равно «0», а eval равно «255», будут протестированы
 * каждая ячейка и каждое значение. 
 */


int lcdvpagetest(uint8_t x1, uint8_t x2, uint8_t spage, uint8_t epage, uint8_t sval, uint8_t eval)
{
  uint8_t x;
  uint8_t data;
  uint8_t rdata;
  uint8_t page;
  uint8_t errors = 0;

  /*
   * Выполняем тестовый проход по памяти, постепенно увеличивая 
   * значение sval, а затем удаляя его.
   */
  do
  {
    /*
     * Поочередно проходя по столбцам (значения x), осуществляем запись 
     * во все страницы памяти GLCD.
     */

    data = sval;
    for(x = x1; x <= x2; x++)
    {
      for(page = spage; page <= epage; page++)
      {
        GLCD.GotoXY(x, page * 8);
        GLCD.WriteData(data);
        data++;
      }
    }

    /*
     * Теперь идем обратно и проверяем страницы.
     */

    data = sval;
    for(x = x1; x<= x2; x++)
    {
      for(page = spage; page <= epage; page++)
      {
        GLCD.GotoXY(x, page * 8);
        rdata = GLCD.ReadData();

        if(data != rdata)
        {
//        eprintf(" Verify error: (%d,%d) %x!=%x\n", x, spage*8, data, rdata);

          SerialPrintQ(" Verify error: (");
          Serial.print((unsigned int) x);
          Serial.print(',');
          Serial.print((unsigned int) (spage*8));
          SerialPrintQ(") ");
          Serial.print((unsigned int)data, HEX);
          SerialPrintQ("!=");
          Serial.println((unsigned int)rdata, HEX);

          if(++errors > MAX_ERRORS)
            return(errors);
        }
        data++;
      }
    }
  } 
  while(sval++ != eval);
  return(0);
}

/*
 * Выгружаем информацию о настройках GLCD на последовательный порт.
 */

void showGLCDconfig(void)
{
#ifdef ARDUINO
  SerialPrintP(hline);
  SerialPrintQ("Reported Arduino Revision: ");  //  "Версия Arduino: "
  Serial.print(ARDUINO/100);
  Serial.print('.');
  Serial.println(ARDUINO%100);
#endif
  SerialPrintP(hline);
  SerialPrintQ("GLCD Lib Configuration: glcd ver: ");  //  "Версия библиотеки GLCD: "
  Serial.print(GLCD_VERSION);
  SerialPrintQ(" glcd_Device ver: ");  //  "Версия GLCD-панели: "
  Serial.print(GLCD_Device);
  SerialPrintQ(" gText ver: ");  //  "Версия gText: "
  Serial.println(GTEXT_VERSION);
#ifdef GLCD_GLCDLIB_DATESTR
  SerialPrintQ("GLCD Lib build date: ");  //  "Дата создания билда библиотеки GLCD: "
  SerialPrintQ(GLCD_GLCDLIB_DATESTR);
  Serial.println();
#endif
#ifdef GLCD_GLCDLIB_BUILDSTR
  SerialPrintQ("GLCD Lib build number: ");  //  "Номер билда библиотеки GLCD: "
  SerialPrintQ(GLCD_GLCDLIB_BUILDSTR);
  Serial.println();
#endif

/*
 * Используем ifdef, чтобы показать файлы с ручной, 
 * а не автоматической настройкой.
 */

#ifdef glcd_ConfigName
  SerialPrintQ("Config File:");  //  "Конфигурационный файл: "
  SerialPrintQ(glcd_ConfigName);
#else
  SerialPrintQ("Panel Configuration:");  //  "Настройки GLCD-панели: "
  SerialPrintQ(glcd_PanelConfigName);
  Serial.println();
  SerialPrintQ("Pin Configuration:");  //  "Конфигурация контактов: "
  SerialPrintQ(glcd_PinConfigName);
#endif
  Serial.println();
  SerialPrintP(hline);

  SerialPrintQ("GLCD:");
  SerialPrintQ(glcd_DeviceName);

//SerialPrintf("DisplayWidth:%d DisplayHeight:%d\n", GLCD.Width, GLCD.Height);
  SerialPrintQ(" DisplayWidth:");
  Serial.print((int)GLCD.Width);
  SerialPrintQ(" DisplayHeight:");
  Serial.println((int)GLCD.Height);

//SerialPrintf("Chips:%d", glcd_CHIP_COUNT);
  SerialPrintQ("Chips:");  //  "Чипы: "
  Serial.print(glcd_CHIP_COUNT);


//SerialPrintf(" ChipWidth:%3d ChipHeight:%2d\n", CHIP_WIDTH, CHIP_HEIGHT);
  SerialPrintQ(" ChipWidth:");  //  " Ширина чипа:"
  Serial.print(CHIP_WIDTH);
  SerialPrintQ(" ChipHeight:");  //  "Высота чипа:"
  Serial.println(CHIP_HEIGHT);

#ifdef glcdCSEL1
  SerialPrintQ(" CSEL1:");
  SerialPrintPINstr(glcdCSEL1);
#endif
#ifdef glcdCSEL2
  SerialPrintQ(" CSEL2:");
  SerialPrintPINstr(glcdCSEL2);
#endif
#ifdef glcdCSEL3
  SerialPrintQ(" CSEL3:");
  SerialPrintPINstr(glcdCSEL3);
#endif
#ifdef glcdCSEL4
  SerialPrintQ(" CSEL4:");
  SerialPrintPINstr(glcdCSEL4);
#endif

#if defined(glcdCSEL1) || defined(glcdCSEL2) || defined(glcdCSEL3) || defined(glcdCSEL4)
  Serial.println();
#endif


#ifdef glcdRES
  SerialPrintQ(" RES:");
  SerialPrintPINstr(glcdRES);
#endif
  SerialPrintQ(" RW:");
  SerialPrintPINstr(glcdRW);

  SerialPrintQ(" DI:");
  SerialPrintPINstr(glcdDI);

#ifdef glcdEN
  SerialPrintQ(" EN:");
  SerialPrintPINstr(glcdEN);
#endif

#ifdef glcdE1
  SerialPrintQ(" E1:");
  SerialPrintPINstr(glcdE1);
#endif
#ifdef glcdE2
  SerialPrintQ(" E2:");
  SerialPrintPINstr(glcdE2);
#endif

  Serial.println();

//  SerialPrintf(" D0:%s", GLCDdiagsPIN2STR(glcdData0Pin));
  SerialPrintQ(" D0:");
  SerialPrintPINstr(glcdData0Pin);

  SerialPrintQ(" D1:");
  SerialPrintPINstr(glcdData1Pin);

  SerialPrintQ(" D2:");
  SerialPrintPINstr(glcdData2Pin);

  SerialPrintQ(" D3:");
  SerialPrintPINstr(glcdData3Pin);

  Serial.println();

  SerialPrintQ(" D4:");
  SerialPrintPINstr(glcdData4Pin);

  SerialPrintQ(" D5:");
  SerialPrintPINstr(glcdData5Pin);

  SerialPrintQ(" D6:");
  SerialPrintPINstr(glcdData6Pin);

  SerialPrintQ(" D7:");
  SerialPrintPINstr(glcdData7Pin);

  Serial.println();

//  SerialPrintf("Delays: tDDR:%d tAS:%d tDSW:%d tWH:%d tWL: %d\n",
//  GLCD_tDDR, GLCD_tAS, GLCD_tDSW, GLCD_tWH, GLCD_tWL);

  SerialPrintQ("Delays: tDDR:");
  Serial.print(GLCD_tDDR);
  SerialPrintQ(" tAS:");
  Serial.print(GLCD_tAS);
  SerialPrintQ(" tDSW:");
  Serial.print(GLCD_tDSW);
  SerialPrintQ(" tWH:");
  Serial.print(GLCD_tWH);
  SerialPrintQ(" tWL:");
  Serial.println(GLCD_tWL);


#ifdef glcd_CHIP0
  SerialPrintQ("ChipSelects:");
  SerialPrintQ(" CHIP0:(");
  SerialPrintQ(xstr(glcd_CHIP0));
  SerialPrintQ(")");
#endif
#ifdef glcd_CHIP1
  SerialPrintQ(" CHIP1:(");
  SerialPrintQ(xstr(glcd_CHIP1));
  SerialPrintQ(")");
#endif
#ifdef glcd_CHIP2
  SerialPrintQ(" CHIP2:(");
  SerialPrintQ(xstr(glcd_CHIP2));
  SerialPrintQ(")");
#endif
#ifdef glcd_CHIP3
  SerialPrintQ(" CHIP3:(");
  SerialPrintQ(xstr(glcd_CHIP3));
  SerialPrintQ(")");
#endif

#ifdef glcd_CHIP0
  Serial.println();
#endif



#ifdef _AVRIO_AVRIO_
  /*
   * Показывает Show AVRIO GLCD data mode
   *
   * Требует серьезно повозиться в AVRIO.
   */

  SerialPrintQ("Data mode: ");  //  "Режим данных: "
  /*
   * Сначала проверяем полный 8-битный режим. 
   *
   */
  if(AVRDATA_8BIT(glcdData0Pin, glcdData1Pin, glcdData2Pin, glcdData3Pin,
  glcdData4Pin, glcdData5Pin, glcdData6Pin, glcdData7Pin))
  {
    /*
     * Полный 8-битный режим.
     */
    SerialPrintQ("byte\n");
  }
  else
  {
    SerialPrintQ("\n d0-d3:");
    if(AVRDATA_4BITHI(glcdData0Pin, glcdData1Pin, glcdData2Pin, glcdData3Pin) ||
      AVRDATA_4BITLO(glcdData0Pin, glcdData1Pin, glcdData2Pin, glcdData3Pin))
    {
      SerialPrintQ("nibble mode");  //  "полубайтный режим"
#ifndef GLCD_ATOMIC_IO
      SerialPrintQ("-Non-Atomic");  //  "-неатомарный"
#else
      SerialPrintQ("-disabled"); // теперь пользователь знает, что AVRIO отключает полубайты, когда находится в атомарном режиме 
#endif
    }
    else
    {
      SerialPrintQ("bit i/o");
    }

    SerialPrintQ("\n d4-d7:");

    if(AVRDATA_4BITHI(glcdData4Pin, glcdData5Pin, glcdData6Pin, glcdData7Pin) ||
      AVRDATA_4BITLO(glcdData4Pin, glcdData5Pin, glcdData6Pin, glcdData7Pin))
    {
      SerialPrintQ("nibble mode");  //  "полубайтный режим"
#ifndef GLCD_ATOMIC_IO
      SerialPrintQ("-Non-Atomic");  //  "-неатомарный"
#else
      SerialPrintQ("-disabled"); // теперь пользователь знает, что AVRIO отключает полубайты, когда находится в атомарном режиме
#endif
    }
    else
    {
      SerialPrintQ("bit i/o");
    }
    Serial.println();
  }

#endif // _AVRIO_AVRIO_

  /*
   * Показываем рендеринг шрифта:
   */

#ifdef GLCD_OLD_FONTDRAW
  SerialPrintQ("Text Render: ");  //  "Рендер шрифта: "
  SerialPrintQ("OLD\n");
#endif

  /*
   * Если отключено, не показываем скроллинг вниз.
   */

#ifdef GLCD_NO_SCROLLDOWN
  SerialPrintQ("NO Down Scroll\n");  //  "Скроллинг вниз отключен"
#endif

  /*
   * Если включено, показываем, кэш считывания.
   */
#ifdef GLCD_READ_CACHE
  SerialPrintQ("READ CACHE enabled\n");  //  "КЭШ СЧИТЫВАНИЯ включен\n"
#endif 


}

#ifdef _AVRIO_AVRIO_
/*
 * AVRIO-версия строки контакта также содержит AVR-порт и номер контакта.
 * В итоге получается формат PIN_Pb, где «P» – это порт A-Z, 
 * а «b» – это порт 0-7.
 */
void
_SerialPrintPINstr(uint8_t pin, uint8_t avrport, uint8_t avrbit)
{

  /*
   * Проверяем, используется pin# (Arduino) или #s (AVRPIN).
   */
  if(pin >= AVRIO_PIN(AVRIO_PORTA, 0))
  {
    
//  SerialPrintf("0x%x", pin);
    /*
     * Если используется #s (AVRPIN), печатаем номер контакта 
     * в шестнадцатеричном значении.
     */
    SerialPrintQ("0x");
    Serial.print(pin,HEX);
  }
  else
  {
//  SerialPrintf("%d", pin);
    Serial.print(pin,DEC);
  }

//SerialPrintf("(PIN_%c%d)", pin, 'A'-AVRIO_PORTA+avrport, avrbit);

  SerialPrintQ("(PIN_");
  Serial.print((char)('A' - AVRIO_PORTA+avrport));
  Serial.print((int)avrbit);
  Serial.print(')');

}
#else
void
_SerialPrintPINstr(uint16_t pin)
{
  Serial.print((int) pin);
}
#endif

/*
 * Эта функция возвращает составную «скорость» GLCD.
 * Она возвращает скорость SetDot() в 1/10 операций в секунду.
 * То есть она возвращает количество вызовов функции SetDot(), 
 * но поделенное на 10.
 */

uint16_t
getglcdspeed()
{
uint16_t iter = 0;
unsigned long startmillis;

  startmillis = millis();

  while(millis() - startmillis < 1000) // цикл будет продолжаться секунду
  {
    /*
     * Делаем 10 операций, чтобы минимизировать эффект от цикла
     * и вызова millis().
     *
     * ПРИМЕЧАНИЕ: Координаты пикселя были выбраны специально, чтобы для 
     * каждого вызова SetDot() нужно было задать столбец и страницу.
     * Смысл в том, чтобы показать скорость GLCD, т.к. каждый вызов 
     * функции SetDot() проделывает следующие операции:
     * - задает страницу
     * - задает столбец
     * - считывает байт (фиктивное считывание)
     * - считывает байт (настоящее считывание)
     * - задает столбец (для записи)
     * - записывает байт
     */

    GLCD.SetDot(GLCD.Right, GLCD.Bottom, WHITE);
    GLCD.SetDot(GLCD.Right-1, GLCD.Bottom-9, WHITE);
    GLCD.SetDot(GLCD.Right, GLCD.Bottom, WHITE);
    GLCD.SetDot(GLCD.Right-1, GLCD.Bottom-9, WHITE);
    GLCD.SetDot(GLCD.Right, GLCD.Bottom, WHITE);
    GLCD.SetDot(GLCD.Right-1, GLCD.Bottom-9, WHITE);
    GLCD.SetDot(GLCD.Right, GLCD.Bottom, WHITE);
    GLCD.SetDot(GLCD.Right-1, GLCD.Bottom-9, WHITE);
    GLCD.SetDot(GLCD.Right, GLCD.Bottom, WHITE);
    GLCD.SetDot(GLCD.Right-1, GLCD.Bottom-9, WHITE);
    iter++;
  }

  return(iter);

}

См.также

Внешние ссылки