Dozingfiretruck 2 лет назад
Родитель
Сommit
06db7a23b5
92 измененных файлов с 12267 добавлено и 1096 удалено
  1. 941 0
      components/u8g2/mui.c
  2. 609 0
      components/u8g2/mui.h
  3. 2243 0
      components/u8g2/mui_u8g2.c
  4. 307 0
      components/u8g2/mui_u8g2.h
  5. 411 14
      components/u8g2/u8g2.h
  6. 198 162
      components/u8g2/u8g2_d_memory.c
  7. 771 43
      components/u8g2/u8g2_d_setup.c
  8. 210 2
      components/u8g2/u8g2_font.c
  9. 646 422
      components/u8g2/u8g2_fonts.c
  10. 1 1
      components/u8g2/u8g2_line.c
  11. 5 5
      components/u8g2/u8g2_polygon.c
  12. 2 1
      components/u8g2/u8g2_setup.c
  13. 60 20
      components/u8g2/u8x8.h
  14. 1 0
      components/u8g2/u8x8_byte.c
  15. 2 2
      components/u8g2/u8x8_d_a2printer.c
  16. 200 0
      components/u8g2/u8x8_d_custom.c
  17. 206 0
      components/u8g2/u8x8_d_gp1247ai.c
  18. 212 0
      components/u8g2/u8x8_d_gp1287ai.c
  19. 182 0
      components/u8g2/u8x8_d_gp1294ai.c
  20. 86 3
      components/u8g2/u8x8_d_gu800.c
  21. 2 2
      components/u8g2/u8x8_d_hd44102.c
  22. 1 1
      components/u8g2/u8x8_d_il3820_296x128.c
  23. 1 1
      components/u8g2/u8x8_d_ist3020.c
  24. 280 0
      components/u8g2/u8x8_d_ist3088.c
  25. 1 1
      components/u8g2/u8x8_d_ist7920.c
  26. 2 2
      components/u8g2/u8x8_d_ks0108.c
  27. 76 4
      components/u8g2/u8x8_d_lc7981.c
  28. 163 4
      components/u8g2/u8x8_d_ld7032_60x32.c
  29. 7 7
      components/u8g2/u8x8_d_ls013b7dh03.c
  30. 4 4
      components/u8g2/u8x8_d_max7219.c
  31. 1 1
      components/u8g2/u8x8_d_pcd8544_84x48.c
  32. 1 1
      components/u8g2/u8x8_d_pcf8812.c
  33. 1 1
      components/u8g2/u8x8_d_pcf8814_hx1230.c
  34. 255 0
      components/u8g2/u8x8_d_s1d15300.c
  35. 5 1
      components/u8g2/u8x8_d_s1d15721.c
  36. 1 1
      components/u8g2/u8x8_d_s1d15e06.c
  37. 1 1
      components/u8g2/u8x8_d_sbn1661.c
  38. 185 2
      components/u8g2/u8x8_d_sed1330.c
  39. 1 1
      components/u8g2/u8x8_d_sh1106_64x32.c
  40. 1 1
      components/u8g2/u8x8_d_sh1106_72x40.c
  41. 313 5
      components/u8g2/u8x8_d_sh1107.c
  42. 74 0
      components/u8g2/u8x8_d_sh1108.c
  43. 7 4
      components/u8g2/u8x8_d_sh1122.c
  44. 68 4
      components/u8g2/u8x8_d_ssd1305.c
  45. 3 3
      components/u8g2/u8x8_d_ssd1306_128x32.c
  46. 82 3
      components/u8g2/u8x8_d_ssd1306_128x64_noname.c
  47. 1 1
      components/u8g2/u8x8_d_ssd1306_64x32.c
  48. 1 1
      components/u8g2/u8x8_d_ssd1306_64x48.c
  49. 1 1
      components/u8g2/u8x8_d_ssd1306_72x40.c
  50. 1 1
      components/u8g2/u8x8_d_ssd1306_96x16.c
  51. 328 0
      components/u8g2/u8x8_d_ssd1306_96x40.c
  52. 3 3
      components/u8g2/u8x8_d_ssd1309.c
  53. 97 1
      components/u8g2/u8x8_d_ssd1316.c
  54. 1 1
      components/u8g2/u8x8_d_ssd1317.c
  55. 1 1
      components/u8g2/u8x8_d_ssd1318.c
  56. 266 38
      components/u8g2/u8x8_d_ssd1320.c
  57. 122 2
      components/u8g2/u8x8_d_ssd1322.c
  58. 2 2
      components/u8g2/u8x8_d_ssd1325.c
  59. 1 1
      components/u8g2/u8x8_d_ssd1326.c
  60. 96 5
      components/u8g2/u8x8_d_ssd1327.c
  61. 2 2
      components/u8g2/u8x8_d_ssd1329.c
  62. 538 0
      components/u8g2/u8x8_d_ssd1362.c
  63. 1 1
      components/u8g2/u8x8_d_ssd1606_172x72.c
  64. 1 1
      components/u8g2/u8x8_d_ssd1607_200x200.c
  65. 1 1
      components/u8g2/u8x8_d_st7511.c
  66. 54 46
      components/u8g2/u8x8_d_st75160.c
  67. 221 8
      components/u8g2/u8x8_d_st75256.c
  68. 3 4
      components/u8g2/u8x8_d_st7528.c
  69. 1 1
      components/u8g2/u8x8_d_st75320.c
  70. 179 0
      components/u8g2/u8x8_d_st7539.c
  71. 13 13
      components/u8g2/u8x8_d_st7565.c
  72. 524 12
      components/u8g2/u8x8_d_st7567.c
  73. 7 4
      components/u8g2/u8x8_d_st7571.c
  74. 246 0
      components/u8g2/u8x8_d_st7586s_jlx320160.c
  75. 256 0
      components/u8g2/u8x8_d_st7586s_jlx384160.c
  76. 1 1
      components/u8g2/u8x8_d_st7588.c
  77. 114 14
      components/u8g2/u8x8_d_st7920.c
  78. 1 2
      components/u8g2/u8x8_d_stdio.c
  79. 87 6
      components/u8g2/u8x8_d_t6963.c
  80. 2 2
      components/u8g2/u8x8_d_uc1601.c
  81. 1 1
      components/u8g2/u8x8_d_uc1604.c
  82. 4 4
      components/u8g2/u8x8_d_uc1608.c
  83. 1 1
      components/u8g2/u8x8_d_uc1609.c
  84. 1 1
      components/u8g2/u8x8_d_uc1610.c
  85. 5 5
      components/u8g2/u8x8_d_uc1611.c
  86. 1 1
      components/u8g2/u8x8_d_uc1617.c
  87. 76 2
      components/u8g2/u8x8_d_uc1638.c
  88. 1 1
      components/u8g2/u8x8_d_uc1701_dogs102.c
  89. 1 1
      components/u8g2/u8x8_d_uc1701_mini12864.c
  90. 1 1
      components/u8g2/u8x8_debounce.c
  91. 3 2
      components/u8g2/u8x8_display.c
  92. 170 170
      components/u8g2/u8x8_fonts.c

+ 941 - 0
components/u8g2/mui.c

@@ -0,0 +1,941 @@
+/*
+
+  mui.c
+  
+  Monochrome minimal user interface: Core library.
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2021, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+
+  
+
+  "mui.c" is a graphical user interface, developed as part of u8g2.
+  However "mui.c" is independent of u8g2 and can be used without u8g2 code.
+  The glue code between "mui.c" and u8g2 is located in "mui_u8g2.c"
+
+  c: cmd
+  i:  ID0
+  j: ID1
+  xy: Position (x and y)
+  /text/: some text. The text can start with any delimiter (except 0 and |), but also has to end with the same delimiter
+  a: Single char argument
+  u: Single char argument with the user interface form number
+
+  "Uu" the interface                                                    --> no ID
+  
+  Manual ID:
+  "Fijxy"  Generic field: Places field with id ii at x/y        --> ID=ij
+  "Bijxy/text/"   Generic field (Button) with Text   --> ID=ij
+  "Tiixya/text/"  Generic field with argument and text --> ID = ij
+  "Aiixya"
+  
+  Fixed ID:
+  "Si" the style                                                        --> ID=@i
+  "Lxy/labeltext/"  Places a text at the specified position, field with   -     -> ID=.L, .l
+  "Gxyu/menutext/"  Go to the specified menu without placing the user interface form on the stack       --> ID=.G, .g
+  
+  
+  cijxy
+  cijxy/text/
+  cijxya/text/
+  
+  cxy/text/
+  cxya/text/
+  
+*/
+
+
+
+#include "mui.h"
+
+
+
+
+
+//#define mui_get_fds_char(s) ((uint8_t)(*s))
+
+//#include <stdio.h>
+//#define MUI_DEBUG(...) printf(__VA_ARGS__)
+#define MUI_DEBUG(...)
+
+uint8_t mui_get_fds_char(fds_t *s)
+{
+  //return (uint8_t)(*s);
+  return (uint8_t)mui_pgm_read(s);
+}
+
+
+/*
+  s must point to a valid command within FDS
+*/
+static size_t mui_fds_get_cmd_size_without_text(fds_t *s) MUI_NOINLINE;
+static size_t mui_fds_get_cmd_size_without_text(fds_t *s)
+{
+  uint8_t c = mui_get_fds_char(s);
+  c &= 0xdf; /* consider upper and lower case */
+  switch(c)
+  {
+    case 'U': return 2;         // User Form: CMD  (1 Byte), Form-Id (1 Byte)
+    case 'S': return 2;         // Style: CMD (1 Byte), Style Id (1 Byte)
+    case 'D': return 3;         // Data within Text: CMD (1 Byte), ID (2 Bytes), Text (does not count here)
+    case 'Z': return 3;         // Zero field without x, y, arg & text: CMD (1 Byte), ID (2 Bytes)
+    case 'F': return 5;         // Field without arg & text: CMD (1 Byte), ID (2 Bytes), X, Y
+    case 'B': return 5;         // Field with text: CMD (1 Byte), ID (2 Bytes), X, Y, Text (does not count here)
+    case 'T': return 6;         // Field with arg & text: CMD (1 Byte), ID (2 Bytes), X, Y, Arg, Text (does not count here)
+    case 'A': return 6;         // Field with arg (no text): CMD (1 Byte), ID (2 Bytes), X, Y, Arg, Text
+    case 'L': return 3;          // Text Label: CMD (1 Byte), X, Y (same as 'B' but with fixed ID '.L', MUIF_LABEL, MUI_LABEL)
+    case 'G': return 4;         // Goto Btutton: CMD (1Byte), X, Y, Arg, Text  (same as 'T' but with fixed ID '.G', MUIF_GOTO, MUI_GOTO)
+    case 0: return 0;
+  }
+  return 1;
+}
+
+
+
+/*
+  s must point to the string delimiter start: first '/' for "B00ab/ok/"
+    - '/' actually is 0xff
+    - return the total size of the string, including the delimiter
+    - copies the content of the string ("ok") to the ui text buffer
+
+*/
+static size_t mui_fds_parse_text(mui_t *ui, fds_t *s)
+{
+  uint8_t i = 0;
+  ui->delimiter = mui_get_fds_char(s);
+  uint8_t c;
+  fds_t *t = s;
+  
+  //printf("mui_fds_parse_text del=%d\n", delimiter);
+#ifdef MUI_CHECK_EOFDS
+  if ( ui->delimiter == 0 )
+    return 0;
+#endif 
+  t++;
+  for( ;; )
+  {
+    c = mui_get_fds_char(t);
+  //printf("mui_fds_parse_text i=%d, c=%c\n", i, c);
+#ifdef MUI_CHECK_EOFDS
+    if ( c == 0 )
+      break;
+#endif 
+    if ( c == ui->delimiter )
+    {
+      t++;
+      break;
+    }
+    if ( i < MUI_MAX_TEXT_LEN )
+    {
+      ui->text[i++] = c;
+    }
+    t++;
+  }
+  ui->text[i] = '\0' ;
+  return t-s;
+}
+
+/*
+  get the first token within a text argument.
+  The text argument may look like this:
+    "B00ab/banana|apple|peach|cherry/"
+  The outer delimiter "/" is not fixed and can be any char except "|" and "\0"
+  The inner delimiter "|" is fixed. It must be the pipe symbol.
+  This function will place "banana" into ui->text if the result is not 0
+
+  if ( mui_fds_first_token(ui) )
+  {
+    do 
+    {
+      // handle token in ui->text
+    } while ( mui_fds_next_token(ui) )
+  }
+
+*/
+
+uint8_t mui_fds_first_token(mui_t *ui)
+{
+  ui->token = ui->fds;
+  ui->token += mui_fds_get_cmd_size_without_text(ui->fds);
+  ui->delimiter = mui_get_fds_char(ui->token);
+  ui->token++;  // place ui->token on the first char of the token
+  return mui_fds_next_token(ui);
+}
+
+/*
+  The inner token delimiter "|" is fixed. It must be the pipe symbol.
+*/
+uint8_t mui_fds_next_token(mui_t *ui)
+{
+  uint8_t c;
+  uint8_t i = 0;
+  // printf("mui_fds_next_token: call, ui->token=%p\n", ui->token);
+  for( ;; )
+  {
+    c = mui_get_fds_char(ui->token);
+    // printf("mui_fds_next_token: i=%d c=%c\n", i, c);
+#ifdef MUI_CHECK_EOFDS
+    if ( c == 0 )
+      break;
+#endif 
+    if ( c == ui->delimiter )
+      break;
+    if ( c == '|'  )
+    {
+      ui->token++;  // place ui->token on the first char of the next token
+      break;
+    }
+    
+    if ( i < MUI_MAX_TEXT_LEN )
+    {
+      ui->text[i++] = c;
+    }
+    
+    ui->token++;
+  }
+  ui->text[i] = '\0' ;
+  if ( i == 0 )
+    return 0;   // no further token found
+  return 1;  // token placed in ui->text
+}
+
+/*
+  find nth token ('|' delimiter), return 0 if n exceeds the number of tokens, 1 otherwise
+  the result is stored in ui->text
+*/
+uint8_t mui_fds_get_nth_token(mui_t *ui, uint8_t n)
+{  
+  // printf("mui_fds_get_nth_token: call, n=%d\n", n);
+  if ( mui_fds_first_token(ui) )
+  {
+    do 
+    {
+      if ( n == 0 )
+      {
+        // printf("mui_fds_get_nth_token: found");
+        return 1;
+      }
+      n--;
+    } while ( mui_fds_next_token(ui) );
+  }
+  //printf("mui_fds_get_nth_token: NOT found\n");
+  return 0;
+}
+
+uint8_t mui_fds_get_token_cnt(mui_t *ui)
+{
+  uint8_t n = 0;
+  if ( mui_fds_first_token(ui) )
+  {
+    do 
+    {
+      n++;
+    } while ( mui_fds_next_token(ui) );
+  }
+  return n;
+}
+
+
+#define mui_fds_is_text(c) ( (c) == 'U' || (c) == 'S' || (c) == 'F' || (c) == 'A' || (c) == 'Z' ? 0 : 1 )
+
+/*
+  s must point to a valid command within FDS
+  return
+    The complete length of the command (including any text part)
+  sideeffect:
+    Any existing text part will be copied into ui->text
+    ui->text will be assigned to empty string if there is no text argument
+*/
+static size_t mui_fds_get_cmd_size(mui_t *ui, fds_t *s) MUI_NOINLINE;
+static size_t mui_fds_get_cmd_size(mui_t *ui, fds_t *s)
+{
+  size_t l = mui_fds_get_cmd_size_without_text(s);
+  uint8_t c = mui_get_fds_char(s);
+ ui->text[0] = '\0' ;   /* always reset the text buffer */
+ if ( mui_fds_is_text(c) )
+  {
+    l += mui_fds_parse_text(ui, s+l);
+  }
+  return l;
+}
+
+
+/*
+  mui_Init() will setup the menu system but will not activate or display anything.
+  Use mui_GotoForm() after this command, then use mui_Draw() to draw the menu on a display.
+*/
+void mui_Init(mui_t *ui, void *graphics_data, fds_t *fds, muif_t *muif_tlist, size_t muif_tcnt)
+{
+  memset(ui, 0, sizeof(mui_t));
+  ui->root_fds = fds;
+  //ui->current_form_fds = NULL;   // not required, because there was a memset before
+  ui->muif_tlist = muif_tlist;
+  ui->muif_tcnt = muif_tcnt;
+  ui->graphics_data = graphics_data;
+}
+
+int mui_find_uif(mui_t *ui, uint8_t id0, uint8_t id1)
+{
+  size_t i;
+  for( i = 0; i < ui->muif_tcnt; i++ )
+  {
+    /*
+      if ( ui->muif_tlist[i].id0 == id0 )
+        if ( ui->muif_tlist[i].id1 == id1 )
+          return i;
+    */
+      if ( muif_get_id0(ui->muif_tlist+i) == id0 )
+        if ( muif_get_id1(ui->muif_tlist+i) == id1 )
+          return i;
+  }
+  return -1;
+}
+
+
+/*
+  assumes a valid position in ui->fds and calculates all the other variables
+  some fields are always calculated like the ui->cmd and ui->len field
+  other member vars are calculated only if the return value is 1
+  will return 1 if the field id was found.
+  will return 0 if the field id was not found in uif or if ui->fds points to something else than a field
+*/
+static uint8_t mui_prepare_current_field(mui_t *ui) MUI_NOINLINE;
+static uint8_t mui_prepare_current_field(mui_t *ui)
+{
+  int muif_tidx;
+
+  ui->uif = NULL;
+  ui->dflags = 0;    
+  ui->id0 = 0;
+  ui->id1 = 0;
+  ui->arg = 0;
+
+  /* calculate the length of the command and copy the text argument */
+  /* this will also clear the text in cases where there is no text argument */
+  ui->len = mui_fds_get_cmd_size(ui, ui->fds); 
+  //printf("mui_prepare_current_field len=%d\n", ui->len);
+
+  /* get the command and check whether end of form is reached */
+  ui->cmd = mui_get_fds_char(ui->fds);
+  //printf("mui_prepare_current_field cmd='%c' len=%d\n", ui->cmd, ui->len);
+  
+  /* Copy the cmd also to second id value. This is required for some commands, others will overwrite this below */
+  ui->id1 = ui->cmd;
+  
+  /* now make the command uppercase so that both, upper and lower case are considered */
+  ui->cmd &= 0xdf; /* consider upper and lower case */
+  
+  if ( ui->cmd == 'U' || ui->cmd == 0 )
+    return 0;
+
+  /* calculate the dynamic flags */
+  if ( ui->fds == ui->cursor_focus_fds )
+    ui->dflags |= MUIF_DFLAG_IS_CURSOR_FOCUS;
+  if ( ui->fds == ui->touch_focus_fds )
+    ui->dflags |= MUIF_DFLAG_IS_TOUCH_FOCUS;
+  
+
+  /* get the id0 and id1 values */
+  if  ( ui->cmd == 'F' || ui->cmd == 'B' || ui->cmd == 'T' || ui->cmd == 'A' )
+  {
+      ui->id0 = mui_get_fds_char(ui->fds+1);
+      ui->id1 = mui_get_fds_char(ui->fds+2);
+      ui->x = mui_get_fds_char(ui->fds+3);
+      ui->y = mui_get_fds_char(ui->fds+4);
+      if ( ui->cmd == 'A' || ui->cmd == 'T' )
+      {
+        ui->arg = mui_get_fds_char(ui->fds+5);
+      }
+  }
+  else if ( ui->cmd == 'D' || ui->cmd == 'Z' )
+  {
+      ui->id0 = mui_get_fds_char(ui->fds+1);
+      ui->id1 = mui_get_fds_char(ui->fds+2);
+  }
+  else if ( ui->cmd == 'S' )
+  {
+      ui->id0 = 'S';
+      ui->id1 = mui_get_fds_char(ui->fds+1);
+  }
+  else
+  {
+      ui->id0 = '.';
+      /* note that ui->id1 contains the original cmd value */
+      ui->x = mui_get_fds_char(ui->fds+1);
+      ui->y = mui_get_fds_char(ui->fds+2);
+      if ( ui->cmd == 'G' || ui->cmd == 'M' )  /* this is also true for 'g' or 'm' */
+      {
+        ui->arg = mui_get_fds_char(ui->fds+3);
+      }
+  }
+
+  //MUI_DEBUG("mui_prepare_current_field cmd='%c' len=%d arg=%d\n", ui->cmd, ui->len, ui->arg);
+
+  
+  /* find the field  */
+  muif_tidx = mui_find_uif(ui, ui->id0, ui->id1);
+  //printf("mui_prepare_current_field: muif_tidx=%d\n", muif_tidx);
+  if ( muif_tidx >= 0 )
+  {
+    ui->uif = ui->muif_tlist + muif_tidx;
+    return 1;
+  }
+  return 0;
+}
+
+/* 
+  assumes that ui->fds has been assigned correctly 
+  and that ui->target_fds and ui->tmp_fds had been cleared if required
+
+  Usually do not call this function directly, instead use mui_loop_over_form
+
+*/
+
+static void mui_inner_loop_over_form(mui_t *ui, uint8_t (*task)(mui_t *ui)) MUI_NOINLINE;
+static void mui_inner_loop_over_form(mui_t *ui, uint8_t (*task)(mui_t *ui))
+{
+  uint8_t cmd;
+
+  //MUI_DEBUG("mui_inner_loop_over_form start %p\n", task);
+  
+  ui->fds += mui_fds_get_cmd_size(ui, ui->fds);      // skip the first entry, it is U always
+  for(;;)
+  {    
+    //printf("fds=%p *fds='%c'\n", ui->fds, ui->fds[0]);
+    /* get the command and check whether end of form is reached */
+    cmd = mui_get_fds_char(ui->fds);
+    if ( cmd == 'U' || cmd == 0 )
+      break;
+    if ( mui_prepare_current_field(ui) )  /* side effect: calculate ui->len */
+      if ( task(ui) )         /* call the task, which was provided as argument to this function */
+      {
+        //MUI_DEBUG("mui_inner_loop_over_form break by task\n");
+        break;
+      }
+    ui->fds += ui->len;
+  }
+  
+  //MUI_DEBUG("mui_inner_loop_over_form end %p\n", task);
+}
+
+static void mui_loop_over_form(mui_t *ui, uint8_t (*task)(mui_t *ui)) MUI_NOINLINE;
+static void mui_loop_over_form(mui_t *ui, uint8_t (*task)(mui_t *ui))
+{
+  if ( mui_IsFormActive(ui) == 0 )
+    return;
+  
+  ui->fds = ui->current_form_fds;
+  ui->target_fds = NULL;
+  ui->tmp_fds = NULL;
+  
+  mui_inner_loop_over_form(ui, task);  
+}
+
+/*
+  n is the form number
+*/
+fds_t *mui_find_form(mui_t *ui, uint8_t n)
+{
+  fds_t *fds = ui->root_fds;
+  uint8_t cmd;
+  
+  for( ;; )
+  {
+    cmd = mui_get_fds_char(fds);
+    if ( cmd == 0 )
+      break;
+    if ( cmd == 'U'  )
+    {
+      if (   mui_get_fds_char(fds+1) == n )
+      {
+        return fds;
+      }
+      /* not found, just coninue */
+    }
+    
+    fds += mui_fds_get_cmd_size(ui, fds);
+  }
+  return NULL;
+}
+
+/* === task procedures (arguments for mui_loop_over_form) === */
+/* ui->fds contains the current field */
+
+uint8_t mui_task_draw(mui_t *ui)
+{
+  //printf("mui_task_draw fds=%p uif=%p text=%s\n", ui->fds, ui->uif, ui->text);
+  muif_get_cb(ui->uif)(ui, MUIF_MSG_DRAW);
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_form_start(mui_t *ui)
+{
+  muif_get_cb(ui->uif)(ui, MUIF_MSG_FORM_START);
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_form_end(mui_t *ui)
+{
+  muif_get_cb(ui->uif)(ui, MUIF_MSG_FORM_END);
+  return 0;     /* continue with the loop */
+}
+
+static uint8_t mui_uif_is_cursor_selectable(mui_t *ui) MUI_NOINLINE;
+static uint8_t mui_uif_is_cursor_selectable(mui_t *ui)
+{
+  if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_CURSOR_SELECTABLE )
+  {
+    return 1;
+  }
+  return 0;
+}
+
+uint8_t mui_task_find_prev_cursor_uif(mui_t *ui)
+{
+  //if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_CURSOR_SELECTABLE )
+  if ( mui_uif_is_cursor_selectable(ui) )
+  {
+    if ( ui->fds == ui->cursor_focus_fds )
+    {
+      ui->target_fds = ui->tmp_fds;
+      return 1;         /* stop looping */
+    }
+    ui->tmp_fds = ui->fds;
+  }
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_find_first_cursor_uif(mui_t *ui)
+{
+  //if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_CURSOR_SELECTABLE )
+  if ( mui_uif_is_cursor_selectable(ui) )
+  {
+    // if ( ui->target_fds == NULL )
+    // {
+      ui->target_fds = ui->fds;
+      return 1;         /* stop looping */
+    // }
+  }
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_find_last_cursor_uif(mui_t *ui)
+{
+  //if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_CURSOR_SELECTABLE )
+  if ( mui_uif_is_cursor_selectable(ui) )
+  {
+    //ui->cursor_focus_position++;
+    ui->target_fds = ui->fds;
+  }
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_find_next_cursor_uif(mui_t *ui)
+{
+  //if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_CURSOR_SELECTABLE )
+  if ( mui_uif_is_cursor_selectable(ui) )
+  {
+    if ( ui->tmp_fds != NULL )
+    {
+      ui->target_fds = ui->fds;        
+      ui->tmp_fds = NULL;
+      return 1;         /* stop looping */
+    }
+    if ( ui->fds == ui->cursor_focus_fds )
+    {
+      ui->tmp_fds = ui->fds;
+    }
+  }
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_get_current_cursor_focus_position(mui_t *ui)
+{
+  //if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_CURSOR_SELECTABLE )
+  if ( mui_uif_is_cursor_selectable(ui) )
+  {
+    if ( ui->fds == ui->cursor_focus_fds )
+      return 1;         /* stop looping */
+    ui->tmp8++;
+  }
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_read_nth_selectable_field(mui_t *ui)
+{
+  //if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_CURSOR_SELECTABLE )
+  if ( mui_uif_is_cursor_selectable(ui) )
+  {
+    if ( ui->tmp8 == 0 )
+      return 1;         /* stop looping */
+    ui->tmp8--;
+  }
+  return 0;     /* continue with the loop */
+}
+
+uint8_t mui_task_find_execute_on_select_field(mui_t *ui)
+{
+  if ( muif_get_cflags(ui->uif) & MUIF_CFLAG_IS_EXECUTE_ON_SELECT )
+  {
+      ui->target_fds = ui->fds;
+      return 1;         /* stop looping */
+  }
+  return 0;     /* continue with the loop */
+}
+
+
+/* === utility functions for the user API === */
+
+static uint8_t mui_send_cursor_msg(mui_t *ui, uint8_t msg) MUI_NOINLINE;
+static uint8_t mui_send_cursor_msg(mui_t *ui, uint8_t msg)
+{
+  if ( ui->cursor_focus_fds )
+  {
+    ui->fds = ui->cursor_focus_fds;
+    if ( mui_prepare_current_field(ui) )
+      return muif_get_cb(ui->uif)(ui, msg);
+  }
+  return 0; /* not called, msg not handled */
+}
+
+/* === user API === */
+
+/* 
+  returns the field pos which has the current focus 
+  If the first selectable field has the focus, then 0 will be returned
+  Unselectable fields (for example labels) are skipped by this count.
+  If no fields are selectable, then 0 is returned
+
+  The return value can be used as last argument for mui_EnterForm or mui_GotoForm
+
+  WARNING: This function will destroy current fds and field information.
+*/
+uint8_t mui_GetCurrentCursorFocusPosition(mui_t *ui)
+{
+  //fds_t *fds = ui->fds;
+  ui->tmp8 = 0;  
+  mui_loop_over_form(ui, mui_task_get_current_cursor_focus_position);
+  //ui->fds = fds;
+  return ui->tmp8;
+}
+
+
+void mui_Draw(mui_t *ui)
+{
+  mui_loop_over_form(ui, mui_task_draw);
+}
+
+void mui_next_field(mui_t *ui)
+{
+  mui_loop_over_form(ui, mui_task_find_next_cursor_uif);
+  // ui->cursor_focus_position++;
+  ui->cursor_focus_fds = ui->target_fds;      // NULL is ok  
+  if ( ui->target_fds == NULL )
+  {
+    mui_loop_over_form(ui, mui_task_find_first_cursor_uif);
+    ui->cursor_focus_fds = ui->target_fds;      // NULL is ok  
+    // ui->cursor_focus_position = 0;
+  }
+}
+
+
+/*
+  this function will overwrite the ui field related member variables
+  nth_token can be 0 if the fiel text is not a option list
+  the result is stored in ui->text
+  
+  token delimiter is '|' (pipe symbol)
+  
+  fds:  The start of a field (MUI_DATA)
+  nth_token: The position of the token, which should be returned
+*/
+uint8_t mui_GetSelectableFieldTextOption(mui_t *ui, fds_t *fds, uint8_t nth_token)
+{
+  fds_t *fds_backup = ui->fds;                                // backup the current fds, so that this function can be called inside a task loop 
+  int len = ui->len;          // backup length of the current command, 26 sep 2021: probably this is not required any more
+  uint8_t is_found;
+  
+  ui->fds = fds;
+  // at this point ui->fds contains the field which contains the tokens  
+  // now get the opion string out of the text field. nth_token can be 0 if this is no opion string
+  is_found = mui_fds_get_nth_token(ui, nth_token);          // return value is ignored here
+  
+  ui->fds = fds_backup;                        // restore the previous fds position
+  ui->len = len;
+  // result is stored in ui->text
+  return is_found;
+}
+
+uint8_t mui_GetSelectableFieldOptionCnt(mui_t *ui, fds_t *fds)
+{
+  fds_t *fds_backup = ui->fds;                                // backup the current fds, so that this function can be called inside a task loop 
+  int len = ui->len;          // backup length of the current command   26 sep 2021: probably this is not required any more
+  uint8_t cnt = 0;
+  
+  ui->fds = fds;
+  // at this point ui->fds contains the field which contains the tokens  
+  // now get the opion string out of the text field. nth_token can be 0 if this is no opion string
+  cnt = mui_fds_get_token_cnt(ui); 
+  
+  ui->fds = fds_backup;                        // restore the previous fds position
+  ui->len = len;
+  // result is stored in ui->text
+  return cnt;
+}
+
+
+
+//static void mui_send_cursor_enter_msg(mui_t *ui) MUI_NOINLINE;
+static uint8_t mui_send_cursor_enter_msg(mui_t *ui)
+{
+  ui->is_mud = 0;
+  return mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_ENTER);
+}
+
+/* 
+  if called from a field function, then the current field variables are destroyed, so that call should be the last call in the field callback.
+  mui_EnterForm is similar to mui_GotoForm and differes only in the second argument (which is the form id instead of the fds pointer)
+*/
+void mui_EnterForm(mui_t *ui, fds_t *fds, uint8_t initial_cursor_position)
+{
+  /* exit any previous form, will not do anything if there is no current form */
+  mui_LeaveForm(ui);
+  
+  /* clean focus fields */
+  ui->touch_focus_fds = NULL;
+  ui->cursor_focus_fds = NULL;
+  
+  /* reset all the scoll values */
+  ui->form_scroll_top = 0;
+  ui->form_scroll_visible = 0;
+  ui->form_scroll_total = 0;
+  
+  /* assign the form, which should be entered */
+  ui->current_form_fds = fds;
+  
+  /* inform all fields that we start a new form */
+  MUI_DEBUG("mui_EnterForm: form_start, initial_cursor_position=%d\n", initial_cursor_position);
+  mui_loop_over_form(ui, mui_task_form_start);
+  
+  /* assign initional cursor focus */
+  MUI_DEBUG("mui_EnterForm: find_first_cursor_uif\n");
+  mui_loop_over_form(ui, mui_task_find_first_cursor_uif);  
+  ui->cursor_focus_fds = ui->target_fds;      // NULL is ok  
+  MUI_DEBUG("mui_EnterForm: find_first_cursor_uif target_fds=%p\n", ui->target_fds);
+  
+  while( initial_cursor_position > 0 )
+  {
+    mui_NextField(ui);          // mui_next_field(ui) is not sufficient in case of scrolling
+    initial_cursor_position--;
+  }
+  
+  while( mui_send_cursor_enter_msg(ui) == 255 )
+  {
+    mui_NextField(ui);          // mui_next_field(ui) is not sufficient in case of scrolling
+  }
+}
+
+/* input: current_form_fds */
+/*
+  if called from a field function, then the current field variables are destroyed, so that call should be the last call in the field callback.
+*/
+void mui_LeaveForm(mui_t *ui)
+{
+  if ( mui_IsFormActive(ui) == 0 )
+    return;
+  
+  mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_LEAVE);
+  ui->cursor_focus_fds = NULL;
+  
+  /* inform all fields that we leave the form */
+  MUI_DEBUG("mui_LeaveForm: form_end\n");
+  mui_loop_over_form(ui, mui_task_form_end);  
+  ui->current_form_fds = NULL;
+}
+
+/* 0: error, form not found */
+/*
+  if called from a field function, then the current field variables are destroyed, so that call should be the last call in the field callback.
+*/
+uint8_t mui_GotoForm(mui_t *ui, uint8_t form_id, uint8_t initial_cursor_position)
+{
+  fds_t *fds = mui_find_form(ui, form_id);
+  if ( fds == NULL )
+    return 0;
+  /* EnterForm will also leave any previous form */
+  mui_EnterForm(ui, fds, initial_cursor_position);
+  return 1;
+}
+
+void mui_SaveForm(mui_t *ui)
+{
+  if ( mui_IsFormActive(ui) == 0 )
+    return;
+  
+  ui->last_form_fds = ui->cursor_focus_fds;
+  ui->last_form_id = mui_get_fds_char(ui->current_form_fds+1);
+  ui->last_form_cursor_focus_position = mui_GetCurrentCursorFocusPosition(ui);
+}
+
+/*
+  if called from a field function, then the current field variables are destroyed, so that call should be the last call in the field callback.
+*/
+void mui_RestoreForm(mui_t *ui)
+{
+  mui_GotoForm(ui, ui->last_form_id, ui->last_form_cursor_focus_position);
+}
+
+/*
+  Save a cursor position for mui_GotoFormAutoCursorPosition command
+  Two such positions is stored.
+*/
+void mui_SaveCursorPosition(mui_t *ui, uint8_t cursor_position)
+{
+  uint8_t form_id = mui_get_fds_char(ui->current_form_fds+1);
+  MUI_DEBUG("mui_SaveCursorPosition form_id=%d cursor_position=%d\n", form_id, cursor_position);
+  
+  if ( form_id == ui->menu_form_id[0] )
+    ui->menu_form_last_added = 0;
+  else if ( form_id == ui->menu_form_id[1] )
+    ui->menu_form_last_added = 1;
+  else 
+    ui->menu_form_last_added ^= 1;
+  ui->menu_form_id[ui->menu_form_last_added] = form_id;
+  ui->menu_form_cursor_focus_position[ui->menu_form_last_added] = cursor_position;
+  MUI_DEBUG("mui_SaveCursorPosition ui->menu_form_last_added=%d \n", ui->menu_form_last_added);
+}
+
+/*
+  Similar to mui_GotoForm, but will jump to previously stored cursor location (mui_SaveCursorPosition) or 0 if the cursor position was not saved.
+*/
+uint8_t mui_GotoFormAutoCursorPosition(mui_t *ui, uint8_t form_id)
+{
+  uint8_t cursor_position = 0;
+  if ( form_id == ui->menu_form_id[0] )
+    cursor_position = ui->menu_form_cursor_focus_position[0];
+  if ( form_id == ui->menu_form_id[1] )
+    cursor_position = ui->menu_form_cursor_focus_position[1];
+  MUI_DEBUG("mui_GotoFormAutoCursorPosition form_id=%d cursor_position=%d\n", form_id, cursor_position);
+  return mui_GotoForm(ui, form_id, cursor_position);
+}
+
+/*
+  return current form id or -1 if the menu system is inactive
+*/
+int mui_GetCurrentFormId(mui_t *ui)
+{
+  if ( mui_IsFormActive(ui) == 0 )
+    return -1;
+  return mui_get_fds_char(ui->current_form_fds+1);
+}
+
+/*
+  updates "ui->cursor_focus_fds"
+*/
+/*
+  if called from a field function, then the current field variables are destroyed, so that call should be the last call in the field callback.
+*/
+void mui_NextField(mui_t *ui)
+{
+  do 
+  {
+    if ( mui_send_cursor_msg(ui, MUIF_MSG_EVENT_NEXT) )
+      return;
+    mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_LEAVE);
+    mui_next_field(ui);
+  } while ( mui_send_cursor_enter_msg(ui) == 255 );
+}
+
+/*
+  updates "ui->cursor_focus_fds"
+*/
+/*
+  if called from a field function, then the current field variables are destroyed, so that call should be the last call in the field callback.
+*/
+void mui_PrevField(mui_t *ui)
+{
+  do
+  {
+    if ( mui_send_cursor_msg(ui, MUIF_MSG_EVENT_PREV) )
+      return;
+    mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_LEAVE);
+ 
+    mui_loop_over_form(ui, mui_task_find_prev_cursor_uif);
+    ui->cursor_focus_fds = ui->target_fds;      // NULL is ok  
+    if ( ui->target_fds == NULL )
+    {
+      //ui->cursor_focus_position = 0;
+      mui_loop_over_form(ui, mui_task_find_last_cursor_uif);
+      ui->cursor_focus_fds = ui->target_fds;      // NULL is ok  
+    }
+  } while( mui_send_cursor_enter_msg(ui) == 255 );
+}
+
+
+void mui_SendSelect(mui_t *ui)
+{
+  mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_SELECT);  
+}
+
+/*
+  Same as mui_SendSelect(), but will try to find a field, which is marked as "execute on select" (MUIF_EXECUTE_ON_SELECT_BUTTON).
+  If such a field exists, then this field is executed, otherwise the current field will receive the select message.
+
+  MUIF_EXECUTE_ON_SELECT_BUTTON is set by muif macro MUIF_EXECUTE_ON_SELECT_BUTTON
+  
+  used by MUIInputVersatileRotaryEncoder.ino example
+*/
+void mui_SendSelectWithExecuteOnSelectFieldSearch(mui_t *ui)
+{
+  mui_loop_over_form(ui, mui_task_find_execute_on_select_field);  /* Is there a exec on select field? */
+  if ( ui->target_fds != NULL )       /* yes, found, ui->fds already points to the field */
+  {
+    fds_t *exec_on_select_field = ui->target_fds;
+    mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_LEAVE);
+    ui->cursor_focus_fds = exec_on_select_field;    /* more cursor on the "exec on select" field */
+    mui_send_cursor_enter_msg(ui);      
+    mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_SELECT);  
+  }
+  else
+  {
+    /* no "exec on select" field found, just send the select message to the field */
+    mui_send_cursor_msg(ui, MUIF_MSG_CURSOR_SELECT);  
+  }
+}
+
+
+void mui_SendValueIncrement(mui_t *ui)
+{
+  mui_send_cursor_msg(ui, MUIF_MSG_VALUE_INCREMENT);  
+}
+
+void mui_SendValueDecrement(mui_t *ui)
+{
+  mui_send_cursor_msg(ui, MUIF_MSG_VALUE_DECREMENT);  
+}

+ 609 - 0
components/u8g2/mui.h

@@ -0,0 +1,609 @@
+/*
+
+  mui.h
+
+  Monochrome minimal user interface: Core library.
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2021, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+  
+  MUIF  (Monochrome User Interface Functions)
+    n:  A number 0 to 9 without any quotes, e.g.: 5
+    id: Exactly two characters or numbers in double quotes, e.g. "G5".
+    cb: A callback function with the following prototype: "uint8_t muif_cb(mui_t *ui, uint8_t msg)"
+      There are MANY predefined callback functions, see separate list
+    var: Address of a variable. 
+    text: Normal text, but special characters might be required for some callback functions, for
+      example the text might contain a list of selectable elements separated with the '|' symbol.
+
+  MUIF_STYLE(n,cb)
+    Corresponding FDS command: MUI_STYLE(n)
+    Change the style of any other elements after MUI_STYLE(n), does not draw anything
+    
+  MUIF_RO(id,cb)
+    Corresponding FDS command: MUI_DATA(id, text) MUI_XY(id, x, y), MUI_XYT(id, x,y,text), MUI_XYA(id, x,y,a), MUI_XYAT(id, x,y,a,text)
+    Places a read only element on the form. 
+    The correct FDS command depends on the callback function.
+    
+  MUIF_LABEL(cb)
+    Corresponding FDS command: MUI_LABEL(x,y,text)
+    Places a text at the specified position, similar to MUIF_RO
+    
+  MUIF_GOTO(cb)
+    Corresponding FDS command: MUI_GOTO(x,y,n,text)
+    Places a button at the specified position, similar to MUIF_BUTTON, but does not require an ID.
+    
+  MUIF_BUTTON(id,cb)
+    Corresponding FDS command: MUI_XY(id, x, y), MUI_XYT(id, x,y,text), MUI_XYA(id, x,y,a), MUI_XYAT(id, x,y,a,text)
+    Places a selectable element on the form. 
+  
+  MUIF_VARIABLE(id,var,cb)
+    Corresponding FDS command: MUI_XY(id, x, y), MUI_XYA(id, x,y,a)
+    Places a user input element at the specified location.
+    The correct FDS command depends on the callback function.
+
+
+*/
+
+#ifndef MUI_H
+#define MUI_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#if defined(__GNUC__) && defined(__AVR__)
+#include <avr/pgmspace.h>
+#endif 
+
+
+/*==========================================*/
+/* C++ compatible */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*==========================================*/
+/* defines */
+
+#define MUI_CHECK_EOFDS
+
+
+/*==========================================*/
+/* GNUC AVR PROGMEM interface */
+
+#ifdef __GNUC__
+#  define MUI_NOINLINE __attribute__((noinline))
+#else
+#  define MUI_NOINLINE
+#endif
+
+
+#if defined(__GNUC__) && defined(__AVR__)
+#  define mui_pgm_read(adr) pgm_read_byte_near(adr)
+#  define mui_pgm_wread(adr) pgm_read_word_near(adr) 
+#  define MUI_PROGMEM PROGMEM
+#endif
+
+
+#ifndef mui_pgm_read
+#  ifndef CHAR_BIT
+#  	define mui_pgm_read(adr) (*(const uint8_t *)(adr)) 
+#  else
+#	if CHAR_BIT > 8 
+#  	  define mui_pgm_read(adr) ((*(const uint8_t *)(adr)) & 0x0ff)
+#     else
+#  	  define mui_pgm_read(adr) (*(const uint8_t *)(adr)) 
+#     endif 
+#  endif
+#endif
+
+#ifndef mui_pgm_wread
+#  	define mui_pgm_wread(adr) (*(const uint16_t *)(adr)) 
+#endif
+
+#ifndef MUI_PROGMEM
+#  define MUI_PROGMEM
+#endif
+
+
+/*=== forward declarations ===*/
+typedef struct mui_struct mui_t;
+typedef const struct muif_struct muif_t;
+typedef uint8_t (*muif_cb)(mui_t *ui, uint8_t msg);
+typedef const char fds_t MUI_PROGMEM;
+
+
+
+/*=== struct declarations === */
+
+struct muif_struct
+{
+  uint8_t id0;
+  uint8_t id1;
+  uint8_t cflags;             // config flags e.g. MUIF_CFLAG_IS_CURSOR_SELECTABLE, if so, then it will not receive any cursor/touch msgs
+  uint8_t extra;
+  void *data;                           // might be a pointer to a variable
+  muif_cb cb;                        // callback
+} MUI_PROGMEM;
+
+/* assumes that pointers are 16 bit so encapsulate the wread i another ifdef __AVR__ */
+#if defined(__GNUC__) && defined(__AVR__)
+#  define muif_get_id0(muif) mui_pgm_read(&((muif)->id0))
+#  define muif_get_id1(muif) mui_pgm_read(&((muif)->id1))
+#  define muif_get_cflags(muif) mui_pgm_read(&((muif)->cflags))
+#  define muif_get_extra(muif) mui_pgm_read(&((muif)->extra))
+#  define muif_get_data(muif) ((void *)mui_pgm_wread(&((muif)->data)))
+#  define muif_get_cb(muif) ((muif_cb)mui_pgm_wread(&((muif)->cb)))
+#else
+#  define muif_get_id0(muif) ((muif)->id0)
+#  define muif_get_id1(muif) ((muif)->id1)
+#  define muif_get_cflags(muif) ((muif)->cflags)
+#  define muif_get_extra(muif) ((muif)->extra)
+#  define muif_get_data(muif) ((muif)->data)
+#  define muif_get_cb(muif) ((muif)->cb)
+#endif
+
+
+
+#define MUIF_MSG_NONE 0
+#define MUIF_MSG_DRAW 1
+#define MUIF_MSG_FORM_START 2
+#define MUIF_MSG_FORM_END 3
+/* MUIF_MSG_CURSOR_ENTER return values: 255=skip this field, <255, continue*/
+#define MUIF_MSG_CURSOR_ENTER 4
+#define MUIF_MSG_CURSOR_SELECT 5
+
+/* optional VALUE messages, ignored by the mui core, but can be used inside the field functions  */
+/* usually MUIF_MSG_VALUE_INCREMENT behaves like  MUIF_MSG_CURSOR_SELECT */
+#define MUIF_MSG_VALUE_INCREMENT 6
+#define MUIF_MSG_VALUE_DECREMENT 7
+
+
+#define MUIF_MSG_CURSOR_LEAVE 8
+#define MUIF_MSG_TOUCH_DOWN 9
+#define MUIF_MSG_TOUCH_UP 10
+/* MUIF_MSG_EVENT_NEXT return values: 0=not handled, 1=handled, do nothing */
+/* If MUIF_MSG_EVENT_NEXT/PREV are NOT handled by the field function, then this msg will change the field */
+#define MUIF_MSG_EVENT_NEXT 11
+/* MUIF_MSG_EVENT_PREV return values: 0=not handled, 1=handled, do nothing */
+#define MUIF_MSG_EVENT_PREV 12
+
+/* dynamic flags */
+#define MUIF_DFLAG_IS_CURSOR_FOCUS 0x01
+#define MUIF_DFLAG_IS_TOUCH_FOCUS 0x02
+  
+/* config flags */
+#define MUIF_CFLAG_IS_CURSOR_SELECTABLE 0x01
+#define MUIF_CFLAG_IS_TOUCH_SELECTABLE 0x02
+#define MUIF_CFLAG_IS_EXECUTE_ON_SELECT 0x04
+
+
+/* end user MUIF entries */
+#define MUIF(id,cflags,data,cb) { id[0], id[1], cflags, 0, data, cb} 
+#define MUIF_STYLE(n,cb)  MUIF("S" #n, 0, 0, cb) 
+#define MUIF_RO(id,cb) MUIF(id,0, 0,cb)
+#define MUIF_LABEL(cb) MUIF(".L",0, 0,cb)
+#define MUIF_GOTO(cb) MUIF(".G",MUIF_CFLAG_IS_CURSOR_SELECTABLE,0,cb)
+#define MUIF_BUTTON(id,cb) MUIF(id,MUIF_CFLAG_IS_CURSOR_SELECTABLE,0,cb)
+#define MUIF_EXECUTE_ON_SELECT_BUTTON(id,cb) MUIF(id,MUIF_CFLAG_IS_CURSOR_SELECTABLE|MUIF_CFLAG_IS_EXECUTE_ON_SELECT,0,cb)
+#define MUIF_VARIABLE(id,var,cb) MUIF(id,MUIF_CFLAG_IS_CURSOR_SELECTABLE,(var),cb)
+
+
+
+/* must be smaller than or equal to 255 */
+#ifndef MUI_MAX_TEXT_LEN
+#define MUI_MAX_TEXT_LEN 41
+#endif
+
+#define MUI_MENU_CACHE_CNT 2
+
+struct mui_struct
+{
+  void *graphics_data;
+  fds_t *root_fds;  
+  
+  muif_t *muif_tlist;
+  size_t muif_tcnt;
+  
+  fds_t *current_form_fds;         // the current form, NULL if the ui is not active at the moment
+  fds_t *cursor_focus_fds;           // the field which has the current cursor focus, NULL if there is no current focus
+  fds_t *touch_focus_fds;            // the field which has touch focus
+
+  fds_t *token;             // current token position
+
+  uint16_t form_scroll_total;            // reserved for MUIF, not used by mui
+  uint16_t form_scroll_top;              // reserved for MUIF, not used by mui
+  uint8_t form_scroll_visible;          // reserved for MUIF, not used by mui
+  
+  
+  //uint8_t selected_value;   // This variable is not used by the user interface but can be used by any field function
+  uint8_t tmp8;
+  
+  /* 0: mse, 1: mud */
+  uint8_t is_mud;         // a temp variable for the MUIF function to store remember up down mode. This variable will be cleared before sending MUIF_MSG_CURSOR_ENTER
+  /* current field/style variables */
+  //uint8_t cursor_focus_position;        // the index of the field which has focus, can be used as last argument for mui_EnterForm
+  
+  uint8_t delimiter;    // outer delimiter of the text part of a field
+  uint8_t cmd;          // current cmd or field (e.g. U or F)
+  uint8_t id0;            // identifier of the field, manually provided or derived (G cmd has fixed id "FG")
+  uint8_t id1;
+  uint8_t x;               // position of the field
+  uint8_t y;
+  uint8_t dflags;
+  uint8_t arg;          // extra argument of the field. For example the G: form is put here
+  int len;          // length of the current command
+  fds_t *fds;             // current position, *fds = cmd
+  muif_t *uif;                   // user interface field or style for the given id0 / id1, assigned by mui_prepare_current_field()
+  char text[MUI_MAX_TEXT_LEN+1];
+
+  /* target  */
+  fds_t *tmp_fds;
+  fds_t *target_fds;     // used by several task functions as a return / result value
+  
+  /* last form and field, used by mui_SaveForm and mui_RestoreForm */
+  uint8_t last_form_id;
+  uint8_t last_form_cursor_focus_position;
+  fds_t *last_form_fds;           // not used by mui_RestoreForm, but can be used by field functions
+  
+  /* menu cursor position backup */
+  uint8_t menu_form_id[MUI_MENU_CACHE_CNT];
+  uint8_t menu_form_cursor_focus_position[MUI_MENU_CACHE_CNT];
+  uint8_t menu_form_last_added;
+} ;
+
+#define mui_IsCursorFocus(mui) ((mui)->dflags & MUIF_DFLAG_IS_CURSOR_FOCUS)
+#define mui_IsTouchFocus(mui) ((mui)->dflags & MUIF_CFLAG_IS_TOUCH_SELECTABLE)
+
+
+
+
+/*=== form string definitions ===*/
+
+#define MUI_0 "\x00"
+#define MUI_1 "\x01"
+#define MUI_2 "\x02"
+#define MUI_3 "\x03"
+#define MUI_4 "\x04"
+#define MUI_5 "\x05"
+#define MUI_6 "\x06"
+#define MUI_7 "\x07"
+#define MUI_8 "\x08"
+#define MUI_9 "\x09"
+#define MUI_10 "\x0a"
+#define MUI_11 "\x0b"
+#define MUI_12 "\x0c"
+#define MUI_13 "\x0d"
+#define MUI_14 "\x0e"
+#define MUI_15 "\x0f"
+#define MUI_16 "\x10"
+#define MUI_17 "\x11"
+#define MUI_18 "\x12"
+#define MUI_19 "\x13"
+#define MUI_20 "\x14"
+#define MUI_21 "\x15"
+#define MUI_22 "\x16"
+#define MUI_23 "\x17"
+#define MUI_24 "\x18"
+#define MUI_25 "\x19"
+#define MUI_26 "\x1a"
+#define MUI_27 "\x1b"
+#define MUI_28 "\x1c"
+#define MUI_29 "\x1d"
+#define MUI_30 "\x1e"
+#define MUI_31 "\x1f"
+#define MUI_32 "\x20"
+#define MUI_33 "\x21"
+#define MUI_34 "\x22"
+#define MUI_35 "\x23"
+#define MUI_36 "\x24"
+#define MUI_37 "\x25"
+#define MUI_38 "\x26"
+#define MUI_39 "\x27"
+#define MUI_40 "\x28"
+#define MUI_41 "\x29"
+#define MUI_42 "\x2a"
+#define MUI_43 "\x2b"
+#define MUI_44 "\x2c"
+#define MUI_45 "\x2d"
+#define MUI_46 "\x2e"
+#define MUI_47 "\x2f"
+#define MUI_48 "\x30"
+#define MUI_49 "\x31"
+#define MUI_50 "\x32"
+#define MUI_51 "\x33"
+#define MUI_52 "\x34"
+#define MUI_53 "\x35"
+#define MUI_54 "\x36"
+#define MUI_55 "\x37"
+#define MUI_56 "\x38"
+#define MUI_57 "\x39"
+#define MUI_58 "\x3a"
+#define MUI_59 "\x3b"
+#define MUI_60 "\x3c"
+#define MUI_61 "\x3d"
+#define MUI_62 "\x3e"
+#define MUI_63 "\x3f"
+#define MUI_64 "\x40"
+#define MUI_65 "\x41"
+#define MUI_66 "\x42"
+#define MUI_67 "\x43"
+#define MUI_68 "\x44"
+#define MUI_69 "\x45"
+#define MUI_70 "\x46"
+#define MUI_71 "\x47"
+#define MUI_72 "\x48"
+#define MUI_73 "\x49"
+#define MUI_74 "\x4a"
+#define MUI_75 "\x4b"
+#define MUI_76 "\x4c"
+#define MUI_77 "\x4d"
+#define MUI_78 "\x4e"
+#define MUI_79 "\x4f"
+#define MUI_80 "\x50"
+#define MUI_81 "\x51"
+#define MUI_82 "\x52"
+#define MUI_83 "\x53"
+#define MUI_84 "\x54"
+#define MUI_85 "\x55"
+#define MUI_86 "\x56"
+#define MUI_87 "\x57"
+#define MUI_88 "\x58"
+#define MUI_89 "\x59"
+#define MUI_90 "\x5a"
+#define MUI_91 "\x5b"
+#define MUI_92 "\x5c"
+#define MUI_93 "\x5d"
+#define MUI_94 "\x5e"
+#define MUI_95 "\x5f"
+#define MUI_96 "\x60"
+#define MUI_97 "\x61"
+#define MUI_98 "\x62"
+#define MUI_99 "\x63"
+#define MUI_100 "\x64"
+#define MUI_101 "\x65"
+#define MUI_102 "\x66"
+#define MUI_103 "\x67"
+#define MUI_104 "\x68"
+#define MUI_105 "\x69"
+#define MUI_106 "\x6a"
+#define MUI_107 "\x6b"
+#define MUI_108 "\x6c"
+#define MUI_109 "\x6d"
+#define MUI_110 "\x6e"
+#define MUI_111 "\x6f"
+#define MUI_112 "\x70"
+#define MUI_113 "\x71"
+#define MUI_114 "\x72"
+#define MUI_115 "\x73"
+#define MUI_116 "\x74"
+#define MUI_117 "\x75"
+#define MUI_118 "\x76"
+#define MUI_119 "\x77"
+#define MUI_120 "\x78"
+#define MUI_121 "\x79"
+#define MUI_122 "\x7a"
+#define MUI_123 "\x7b"
+#define MUI_124 "\x7c"
+#define MUI_125 "\x7d"
+#define MUI_126 "\x7e"
+#define MUI_127 "\x7f"
+#define MUI_128 "\x80"
+#define MUI_129 "\x81"
+#define MUI_130 "\x82"
+#define MUI_131 "\x83"
+#define MUI_132 "\x84"
+#define MUI_133 "\x85"
+#define MUI_134 "\x86"
+#define MUI_135 "\x87"
+#define MUI_136 "\x88"
+#define MUI_137 "\x89"
+#define MUI_138 "\x8a"
+#define MUI_139 "\x8b"
+#define MUI_140 "\x8c"
+#define MUI_141 "\x8d"
+#define MUI_142 "\x8e"
+#define MUI_143 "\x8f"
+#define MUI_144 "\x90"
+#define MUI_145 "\x91"
+#define MUI_146 "\x92"
+#define MUI_147 "\x93"
+#define MUI_148 "\x94"
+#define MUI_149 "\x95"
+#define MUI_150 "\x96"
+#define MUI_151 "\x97"
+#define MUI_152 "\x98"
+#define MUI_153 "\x99"
+#define MUI_154 "\x9a"
+#define MUI_155 "\x9b"
+#define MUI_156 "\x9c"
+#define MUI_157 "\x9d"
+#define MUI_158 "\x9e"
+#define MUI_159 "\x9f"
+#define MUI_160 "\xa0"
+#define MUI_161 "\xa1"
+#define MUI_162 "\xa2"
+#define MUI_163 "\xa3"
+#define MUI_164 "\xa4"
+#define MUI_165 "\xa5"
+#define MUI_166 "\xa6"
+#define MUI_167 "\xa7"
+#define MUI_168 "\xa8"
+#define MUI_169 "\xa9"
+#define MUI_170 "\xaa"
+#define MUI_171 "\xab"
+#define MUI_172 "\xac"
+#define MUI_173 "\xad"
+#define MUI_174 "\xae"
+#define MUI_175 "\xaf"
+#define MUI_176 "\xb0"
+#define MUI_177 "\xb1"
+#define MUI_178 "\xb2"
+#define MUI_179 "\xb3"
+#define MUI_180 "\xb4"
+#define MUI_181 "\xb5"
+#define MUI_182 "\xb6"
+#define MUI_183 "\xb7"
+#define MUI_184 "\xb8"
+#define MUI_185 "\xb9"
+#define MUI_186 "\xba"
+#define MUI_187 "\xbb"
+#define MUI_188 "\xbc"
+#define MUI_189 "\xbd"
+#define MUI_190 "\xbe"
+#define MUI_191 "\xbf"
+#define MUI_192 "\xc0"
+#define MUI_193 "\xc1"
+#define MUI_194 "\xc2"
+#define MUI_195 "\xc3"
+#define MUI_196 "\xc4"
+#define MUI_197 "\xc5"
+#define MUI_198 "\xc6"
+#define MUI_199 "\xc7"
+#define MUI_200 "\xc8"
+#define MUI_201 "\xc9"
+#define MUI_202 "\xca"
+#define MUI_203 "\xcb"
+#define MUI_204 "\xcc"
+#define MUI_205 "\xcd"
+#define MUI_206 "\xce"
+#define MUI_207 "\xcf"
+#define MUI_208 "\xd0"
+#define MUI_209 "\xd1"
+#define MUI_210 "\xd2"
+#define MUI_211 "\xd3"
+#define MUI_212 "\xd4"
+#define MUI_213 "\xd5"
+#define MUI_214 "\xd6"
+#define MUI_215 "\xd7"
+#define MUI_216 "\xd8"
+#define MUI_217 "\xd9"
+#define MUI_218 "\xda"
+#define MUI_219 "\xdb"
+#define MUI_220 "\xdc"
+#define MUI_221 "\xdd"
+#define MUI_222 "\xde"
+#define MUI_223 "\xdf"
+#define MUI_224 "\xe0"
+#define MUI_225 "\xe1"
+#define MUI_226 "\xe2"
+#define MUI_227 "\xe3"
+#define MUI_228 "\xe4"
+#define MUI_229 "\xe5"
+#define MUI_230 "\xe6"
+#define MUI_231 "\xe7"
+#define MUI_232 "\xe8"
+#define MUI_233 "\xe9"
+#define MUI_234 "\xea"
+#define MUI_235 "\xeb"
+#define MUI_236 "\xec"
+#define MUI_237 "\xed"
+#define MUI_238 "\xee"
+#define MUI_239 "\xef"
+#define MUI_240 "\xf0"
+#define MUI_241 "\xf1"
+#define MUI_242 "\xf2"
+#define MUI_243 "\xf3"
+#define MUI_244 "\xf4"
+#define MUI_245 "\xf5"
+#define MUI_246 "\xf6"
+#define MUI_247 "\xf7"
+#define MUI_248 "\xf8"
+#define MUI_249 "\xf9"
+#define MUI_250 "\xfa"
+#define MUI_251 "\xfb"
+#define MUI_252 "\xfc"
+#define MUI_253 "\xfd"
+#define MUI_254 "\xfe"
+#define MUI_255 "\xff"
+
+/* form: one id only */
+#define MUI_FORM(n) "U" MUI_##n
+
+/* style: one id only */
+#define MUI_STYLE(n) "S" #n
+
+#define MUI_AUX(id) "Z" id
+
+#define MUI_DATA(id, text) "D" id "\xff" text "\xff"
+
+#define MUI_XY(id, x, y) "F" id MUI_##x MUI_##y
+/* button id must be two chars, but must be unique everywhere */
+#define MUI_XYT(id, x,y,text) "B" id MUI_##x MUI_##y  "\xff" text "\xff"
+#define MUI_XYA(id, x,y,a) "A" id MUI_##x MUI_##y  MUI_##a
+#define MUI_XYAT(id, x,y,a,text) "T" id MUI_##x MUI_##y  MUI_##a "\xff" text "\xff"
+
+#define MUI_LABEL(x,y,text) "L" MUI_##x MUI_##y "\xff" text "\xff"
+#define MUI_GOTO(x,y,n,text) "G" MUI_##x MUI_##y MUI_##n "\xff" text "\xff"
+#define MUI_goto(x,y,n,text) "g" MUI_##x MUI_##y MUI_##n "\xff" text "\xff"
+
+
+uint8_t mui_get_fds_char(fds_t *s) MUI_NOINLINE;
+
+uint8_t mui_fds_first_token(mui_t *ui) MUI_NOINLINE;
+uint8_t mui_fds_next_token(mui_t *ui) MUI_NOINLINE;
+uint8_t mui_fds_get_nth_token(mui_t *ui, uint8_t n) MUI_NOINLINE;
+uint8_t mui_fds_get_token_cnt(mui_t *ui) MUI_NOINLINE;
+
+void mui_Init(mui_t *ui, void *graphics_data, fds_t *fds, muif_t *muif_tlist, size_t muif_tcnt);
+uint8_t mui_GetCurrentCursorFocusPosition(mui_t *ui) ;
+void mui_Draw(mui_t *ui);
+/* warning: The next function will overwrite the ui field variables like ui->arg, etc. 26 sep 2021: only ui->text is modified */
+uint8_t mui_GetSelectableFieldTextOption(mui_t *ui, fds_t *fds, uint8_t nth_token);
+/* warning: The next function will overwrite the ui field variables like ui->arg, etc 26 sep 2021: only ui->text is modified*/
+uint8_t mui_GetSelectableFieldOptionCnt(mui_t *ui, fds_t *fds);
+void mui_EnterForm(mui_t *ui, fds_t *fds, uint8_t initial_cursor_position);
+void mui_LeaveForm(mui_t *ui);
+uint8_t mui_GotoForm(mui_t *ui, uint8_t form_id, uint8_t initial_cursor_position);
+void mui_SaveForm(mui_t *ui);     /* Save current form+cursor position. Used together with mui_RestoreForm */
+void mui_RestoreForm(mui_t *ui);        /* Restore form and cursor position, previously saved with mui_SaveForm */
+void mui_SaveCursorPosition(mui_t *ui, uint8_t cursor_position);         /* stores a cursor position for use with mui_GotoFormAutoCursorPosition */
+uint8_t mui_GotoFormAutoCursorPosition(mui_t *ui, uint8_t form_id);
+
+int mui_GetCurrentFormId(mui_t *ui);    /* form id or -1 if the menu system is inactive */
+void mui_NextField(mui_t *ui);
+void mui_PrevField(mui_t *ui);
+void mui_SendSelect(mui_t *ui);
+void mui_SendSelectWithExecuteOnSelectFieldSearch(mui_t *ui);  /* use this if MUIF_EXECUTE_ON_SELECT_BUTTON is used */
+
+void mui_SendValueIncrement(mui_t *ui);
+void mui_SendValueDecrement(mui_t *ui);
+
+
+
+#define mui_IsFormActive(ui) ((ui)->current_form_fds != NULL) 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MUI_H */
+

+ 2243 - 0
components/u8g2/mui_u8g2.c

@@ -0,0 +1,2243 @@
+/*
+
+  mui_u8g2.c
+
+  Monochrome minimal user interface: Glue code between mui and u8g2.
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2021, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+
+*/
+
+/*
+
+  field function naming convention
+
+    action
+      draw_text:                        (rename from draw label)
+      draw_str:                      
+      btn_jmp   button jump to:                      a button which jumps to a specific form
+      btn_exit          button leave:                     a button which leaves the form and places an exit code into a uint8 variable
+      u8_value_0_9      
+      u8_chkbox
+      u8_radio
+      u8_opt_line       edit value options in the same line
+      u8_opt_parent       edit value options parent
+      u8_opt_child       edit value options child
+    
+    
+    field width (not for draw text/str)
+      wm                minimum width
+      wa                width can be provided via FDS argument
+      w1                full display width
+      w2                half display size (minus some pixel)
+      w3                one/third of the dispay width (minus some pixel)
+
+    edit mode  (not for draw text/str, buttons and checkbox)                  
+      mse       select: select event will increment the value or activate the field (buttons)
+      mud      up/down:  select will enter the up/down edit mode. Next/prev event will increment/decrement the value
+      
+    styles (not for draw text/str)
+      unselected                selected                        up/down edit                            postfix         Use for
+      plain                          invers                             invers + gap + frame            pi                      input elements
+      frame                         invers+frame                frame                                       fi                  buttons
+      
+      plain                          frame                              invers + frame                         pf               input elements
+      invers                        frame                               invers + frame                          if              buttons
+      
+      
+    mui_u8g2_[action]_[field_width]_[edit_mode]_[style]
+
+  mui _label_u8g2 --> mui_u8g2_draw_text
+  mui _goto_frame_button_invers_select_u8g2                              --> mui_u8g2_btn_goto_wm_fi
+  mui _goto_half_width_frame_button_invers_select_u8g2           --> mui_u8g2_btn_goto_w2_fi
+  mui _goto_line_button_invers_select_u8g2 -->  mui_u8g2_btn_goto_w1_fi
+  mui _leave_menu_frame_button_invers_select_u8g2 --> mui_u8g2_btn_exit_wm_fi
+  
+  mui _input_uint8_invers_select_u8g2 --> mui_u8g2_u8_value_0_9_wm_mse_pi
+  mui _single_line_option_invers_select_u8g2     --> mui_u8g2_u8_opt_line_wa_mse_pi
+  mui _select_options_parent_invers_select_u8g2  --> mui_u8g2_u8_opt_parent_wa_mse_pi
+  mui _select_options_child_invers_select_u8g2  --> mui_u8g2_u8_opt_child_wm_pi
+
+  mui _checkbox_invers_select_u8g2 --> mui_u8g2_u8_chkbox_wm_pi
+  mui _radio_invers_select_u8g2 --> mui_u8g2_u8_radio_wm_pi
+
+  mui _input_char_invers_select_u8g2 --> mui_u8g2_u8_char_wm_mud_pi
+
+
+
+  2 Buttons
+    Only use "mse", don't use "mud"
+  
+    Button      Call                            Description
+    1                mui_SendSelect()    Activate elements & change values
+    2                mui_NextField()      Goto next field
+    
+  3 Buttons
+    Use "mse" or "mud"
+    Button      Call                            Description
+    1                mui_SendSelect()    Activate elements / change values (mse) / enter "mud" mode (mud)
+    2                mui_NextField()      Goto next field, increment value (mud)
+    3                mui_PrevField()      Goto prev field, decrement value (mud)
+    
+  4 Buttons
+    Prefer "mse"
+    Button      Call                                            Description
+    1                mui_SendValueIncrement()    Activate elements / increment values (mse)
+    2                mui_SendValueDecrement()   Activate elements / decrement values (mse)
+    3                mui_NextField()                       Goto next field
+    4                mui_PrevField()                        Goto prev field
+
+  5 Buttons
+    Prefer "mse", use the MUIF_EXECUTE_ON_SELECT_BUTTON on forms to finish the form with the "form select" button 5
+    Button      Call                                                                                            Description
+    1                mui_SendValueIncrement()                                                           Activate elements / increment values (mse)
+    2                mui_SendValueDecrement()                                                         Activate elements / decrement values (mse)
+    3                mui_NextField()                                                                            Goto next field
+    4                mui_PrevField()                                                                     Goto prev field
+    5                mui_SendSelectWithExecuteOnSelectFieldSearch()             Execute the MUIF_EXECUTE_ON_SELECT_BUTTON button or activate the current element if there is no EOS button
+    
+  rotary encoder, push&release
+    Prefer "mud"
+    Button      Call                            Description
+    encoder button                 mui_SendSelect()    Activate elements / change values (mse) / enter "mud" mode (mud)
+    encoder CW                      mui_NextField()      Goto next field, increment value (mud)
+    encoder CCW                    mui_PrevField()      Goto prev field, decrement value (mud)
+  
+  rotary encoder, push&rotate
+    Prefer "mse"
+    Button                                      Call                                            Description
+    encoder CW                                  mui_SendValueIncrement()    Activate elements / increment values (mse)
+    encoder CCW                                 mui_SendValueDecrement()   Activate elements / decrement values (mse)
+    encoder CW+button press                mui_NextField()                       Goto next field
+    encoder CCW+button press                mui_PrevField()                        Goto prev field
+
+
+*/
+
+
+
+#include "mui.h"
+#include "u8g2.h"
+#include "mui_u8g2.h"
+
+/*
+
+uint8_t mui_template(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  //ui->dflags                          MUIF_DFLAG_IS_CURSOR_FOCUS       MUIF_DFLAG_IS_TOUCH_FOCUS
+  //muif_get_cflags(ui->uif)       MUIF_CFLAG_IS_CURSOR_SELECTABLE
+  //muif_get_data(ui->uif)
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_VALUE_INCREMENT:
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+*/
+
+/*=========================================================================*/
+#define MUI_U8G2_V_PADDING 1
+
+/*=========================================================================*/
+/* extra u8g2 drawing functions */
+
+static void u8g2_DrawCheckbox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t is_checked) MUI_NOINLINE;
+static void u8g2_DrawCheckbox(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t is_checked)
+{
+  u8g2_DrawFrame(u8g2, x, y-w, w, w);
+  if ( is_checked )
+  {
+    w-=4;
+    u8g2_DrawBox(u8g2, x+2, y-w-2, w, w);
+  }
+}
+
+static void u8g2_DrawValueMark(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w)
+{
+  u8g2_DrawBox(u8g2, x, y-w, w, w);
+}
+
+
+/*=========================================================================*/
+/* helper function */
+
+u8g2_uint_t mui_get_x(mui_t *ui) MUI_NOINLINE;
+u8g2_uint_t mui_get_x(mui_t *ui)
+{
+  if ( u8g2_GetDisplayWidth(mui_get_U8g2(ui)) >= 255 )
+      return ui->x * 2;
+  return ui->x;
+}
+
+u8g2_uint_t mui_get_y(mui_t *ui)
+{
+  return ui->y;
+}
+
+u8g2_t *mui_get_U8g2(mui_t *ui)
+{
+  return (u8g2_t *)(ui->graphics_data);
+}
+
+//void u8g2_DrawButtonUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t flags, u8g2_uint_t width, u8g2_uint_t padding_h, u8g2_uint_t padding_v, const char *text);
+void mui_u8g2_draw_button_utf(mui_t *ui, u8g2_uint_t flags, u8g2_uint_t width, u8g2_uint_t padding_h, u8g2_uint_t padding_v, const char *text)
+{
+  if ( text==NULL)
+    text = "";
+  u8g2_DrawButtonUTF8(mui_get_U8g2(ui), mui_get_x(ui), mui_get_y(ui), flags, width, padding_h, padding_v, text);
+}
+
+u8g2_uint_t mui_u8g2_get_pi_flags(mui_t *ui)
+{
+  u8g2_uint_t flags = 0;
+  if ( mui_IsCursorFocus(ui) )
+  {
+    flags |= U8G2_BTN_INV;
+    if ( ui->is_mud )
+    {
+      flags |= U8G2_BTN_XFRAME;
+    }      
+  }
+  return flags;
+}
+
+
+void mui_u8g2_draw_button_pi(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text)
+{
+  mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), width, padding_h , MUI_U8G2_V_PADDING, text);
+}
+
+
+u8g2_uint_t mui_u8g2_get_fi_flags(mui_t *ui)
+{
+  u8g2_uint_t flags = 1;
+  if ( mui_IsCursorFocus(ui) )
+  {
+    flags |= U8G2_BTN_INV;
+    if ( ui->is_mud )
+    {
+      flags = 1;        // undo INV
+    }      
+  }
+  return flags;
+}
+
+void mui_u8g2_draw_button_fi(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text)
+{
+  mui_u8g2_draw_button_utf(ui, mui_u8g2_get_fi_flags(ui), width, padding_h , MUI_U8G2_V_PADDING, text);
+}
+
+
+u8g2_uint_t mui_u8g2_get_pf_flags(mui_t *ui)
+{
+  u8g2_uint_t flags = 0;
+  if ( mui_IsCursorFocus(ui) )
+  {
+    flags |= 1;
+    if ( ui->is_mud )
+    {
+      flags |= U8G2_BTN_INV;
+    }      
+  }
+  return flags;
+}
+
+void mui_u8g2_draw_button_pf(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text)
+{
+  mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pf_flags(ui), width, padding_h , MUI_U8G2_V_PADDING, text);
+}
+
+
+u8g2_uint_t mui_u8g2_get_if_flags(mui_t *ui)
+{
+  u8g2_uint_t flags = 0;
+  if ( mui_IsCursorFocus(ui) )
+  {
+    if ( ui->is_mud )
+    {
+      flags |= 1;
+      flags |= U8G2_BTN_INV;
+    }
+    else
+    {
+      flags |= 1;
+    }
+  }
+  else
+  {
+      flags |= U8G2_BTN_INV;
+  }
+  return flags;
+}
+
+void mui_u8g2_draw_button_if(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text)
+{
+  mui_u8g2_draw_button_utf(ui, mui_u8g2_get_if_flags(ui), width, padding_h , MUI_U8G2_V_PADDING, text);
+}
+
+
+static uint8_t mui_u8g2_handle_scroll_next_prev_events(mui_t *ui, uint8_t msg) MUI_NOINLINE;
+static uint8_t mui_u8g2_handle_scroll_next_prev_events(mui_t *ui, uint8_t msg)
+{
+  uint8_t arg = ui->arg;
+  switch(msg)
+  {
+    case MUIF_MSG_CURSOR_ENTER:
+      if ( (arg > 0) && (ui->form_scroll_top + arg >= ui->form_scroll_total) )
+        return 255;
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( arg+1 == ui->form_scroll_visible )
+      {
+        if ( ui->form_scroll_visible + ui->form_scroll_top < ui->form_scroll_total )
+        {
+          ui->form_scroll_top++;
+          return 1;
+        }
+        else
+        {
+          ui->form_scroll_top = 0;
+        }
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( arg == 0 )
+      {
+        if ( ui->form_scroll_top > 0 )
+        {
+          ui->form_scroll_top--;
+          return 1;
+        }
+        else
+        {
+          if ( ui->form_scroll_total >  ui->form_scroll_visible  )
+          {
+            ui->form_scroll_top = ui->form_scroll_total - ui->form_scroll_visible;
+          }
+          else
+          {
+            ui->form_scroll_top = 0;
+          }
+        }
+      }
+      break;
+  }
+  return 0;
+}
+
+/*=========================================================================*/
+/* simplified style function  */
+
+/*
+Used for MUIF_U8G2_FONT_STYLE(n,font)
+*/
+
+uint8_t mui_u8g2_set_font_style_function(mui_t *ui, uint8_t msg)
+{  
+  if ( msg == MUIF_MSG_DRAW )
+  {
+    u8g2_SetFont(mui_get_U8g2(ui), (uint8_t *)muif_get_data(ui->uif));
+  }
+  return 0;
+}
+
+
+
+/*=========================================================================*/
+/* field functions */
+
+/*
+  xy: yes, arg: no, text: yes
+*/
+
+uint8_t mui_u8g2_draw_text(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      u8g2_DrawUTF8(mui_get_U8g2(ui), mui_get_x(ui), mui_get_y(ui), ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+      break;
+    case MUIF_MSG_VALUE_INCREMENT:
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+  }
+  return 0;
+}
+
+
+/*
+
+  uint8_t mui_u8g2_btn_goto_wm_fi(mui_t *ui, uint8_t msg)
+
+  Description:
+    A button with size equal to button text plus one pixel padding
+    The button has a one pixel frame around the text.
+    If the selected, then the form will change to the specified form number.
+    
+  Message Handling: DRAW, CURSOR_SELECT
+
+  Style
+    No Selection: Text + Frame
+    Cursor Selection: Inverted text + Frame
+
+  User interface field list (muif):
+    flags: MUIF_CFLAG_IS_CURSOR_SELECTABLE
+    data: not used
+
+  Field definition string (fds):
+    xy: Left position of the text (required)
+    arg: Form numner (required)
+    text: Button label
+    
+*/
+uint8_t mui_u8g2_btn_goto_wm_fi(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_utf(ui, U8G2_BTN_HCENTER |mui_u8g2_get_fi_flags(ui), 0, 1, MUI_U8G2_V_PADDING, ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      //return mui_GotoForm(ui, ui->arg, 0);
+      return mui_GotoFormAutoCursorPosition(ui, ui->arg);
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+    
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_btn_goto_wm_if(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_utf(ui, U8G2_BTN_HCENTER |mui_u8g2_get_if_flags(ui), 0, 1, MUI_U8G2_V_PADDING, ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      //return mui_GotoForm(ui, ui->arg, 0);
+      return mui_GotoFormAutoCursorPosition(ui, ui->arg);
+   case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+    
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_btn_goto_w2_fi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_utf(ui, U8G2_BTN_HCENTER | mui_u8g2_get_fi_flags(ui), u8g2_GetDisplayWidth(u8g2)/2 - 10, 0, MUI_U8G2_V_PADDING, ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      //return mui_GotoForm(ui, ui->arg, 0);
+      return mui_GotoFormAutoCursorPosition(ui, ui->arg);
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_btn_goto_w2_if(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_utf(ui, U8G2_BTN_HCENTER | mui_u8g2_get_if_flags(ui), u8g2_GetDisplayWidth(u8g2)/2 - 10, 0, MUI_U8G2_V_PADDING, ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      //return mui_GotoForm(ui, ui->arg, 0);
+      return mui_GotoFormAutoCursorPosition(ui, ui->arg);
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+  }
+  return 0;
+}
+
+/*
+
+  uint8_t mui_u8g2_btn_exit_wm_fi(mui_t *ui, uint8_t msg)
+
+  Description:
+    A button with size equal to button text plus one pixel padding
+    The button has a one pixel frame around the text.
+    If selected, then the menu system will be closed.
+    The arg value will be stored at the specified data location (if not NULL).
+    The arg value can be used as an exit value of the button.
+    
+  Message Handling: DRAW, CURSOR_SELECT
+
+  Style
+    No Selection: Text + Frame
+    Cursor Selection: Inverted text + Frame
+
+  User interface field list (muif):
+    flags: MUIF_CFLAG_IS_CURSOR_SELECTABLE
+    data: Optionally points to uint8_t value which will receive the arg value of the field.
+
+  Field definition string (fds):
+    xy: Left position of the text (required)
+    arg: Value which will be stored at *data (optional)
+    text: Button label
+    
+*/
+uint8_t mui_u8g2_btn_exit_wm_fi(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_utf(ui, U8G2_BTN_HCENTER |mui_u8g2_get_fi_flags(ui), 0, 1, MUI_U8G2_V_PADDING, ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      {
+        uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+        if ( value != NULL )
+          *value = ui->arg;
+      }
+      mui_SaveForm(ui);          // store the current form and position so that the child can jump back
+      mui_LeaveForm(ui);
+      return 1;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_btn_goto_w1_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_pi(ui, u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui) , ui->text);
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui) , MUI_U8G2_V_PADDING, ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      //return mui_GotoForm(ui, ui->arg, 0);
+      return mui_GotoFormAutoCursorPosition(ui, ui->arg);
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_btn_goto_w1_fi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_fi(ui, u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui)-1 , ui->text);
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui) , MUI_U8G2_V_PADDING, ui->text);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      //return mui_GotoForm(ui, ui->arg, 0);
+      return mui_GotoFormAutoCursorPosition(ui, ui->arg);
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;    
+  }
+  return 0;
+}
+
+/*===============================================================================*/
+
+static void mui_u8g2_u8_vmm_draw_wm_pi(mui_t *ui) MUI_NOINLINE;
+static void mui_u8g2_u8_vmm_draw_wm_pi(mui_t *ui)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_u8_min_max_t *vmm= (mui_u8g2_u8_min_max_t *)muif_get_data(ui->uif);
+  char buf[4] = "999";
+  char *s = buf;
+  uint8_t *value = mui_u8g2_u8mm_get_valptr(vmm);
+  uint8_t min = mui_u8g2_u8mm_get_min(vmm);
+  uint8_t max = mui_u8g2_u8mm_get_max(vmm);
+  uint8_t cnt = 3;
+  
+  if ( *value > max ) 
+    *value = max;
+  if ( *value <= min )
+    *value = min;
+  if ( max < 100 )
+  {
+    s++;
+    cnt--;
+  }
+  if ( max < 10 )
+  {
+    s++;
+    cnt--;
+  }
+  //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), u8g2_GetStrWidth(u8g2, s)+1, 1, MUI_U8G2_V_PADDING, u8x8_u8toa(*value, cnt));
+  mui_u8g2_draw_button_pi(ui, u8g2_GetStrWidth(u8g2, s)+1, 1, u8x8_u8toa(*value, cnt));
+}
+
+
+uint8_t mui_u8g2_u8_min_max_wm_mse_pi(mui_t *ui, uint8_t msg)
+{
+  mui_u8g2_u8_min_max_t *vmm= (mui_u8g2_u8_min_max_t *)muif_get_data(ui->uif);
+  uint8_t *value = mui_u8g2_u8mm_get_valptr(vmm);
+  uint8_t min = mui_u8g2_u8mm_get_min(vmm);
+  uint8_t max = mui_u8g2_u8mm_get_max(vmm);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_vmm_draw_wm_pi(ui);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+      (*value)++;
+      if ( *value > max ) *value = min;
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( *value > min ) (*value)--; else *value = max;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_min_max_wm_mud_pi(mui_t *ui, uint8_t msg)
+{
+  mui_u8g2_u8_min_max_t *vmm= (mui_u8g2_u8_min_max_t *)muif_get_data(ui->uif);
+  uint8_t *value = mui_u8g2_u8mm_get_valptr(vmm);
+  uint8_t min = mui_u8g2_u8mm_get_min(vmm);
+  uint8_t max = mui_u8g2_u8mm_get_max(vmm);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_vmm_draw_wm_pi(ui);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+     /* toggle between normal mode and capture next/prev mode */
+      ui->is_mud = !ui->is_mud;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( ui->is_mud )
+      {
+        (*value)++;
+        if ( *value > max )
+          *value = min;
+        return 1; 
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( ui->is_mud )
+      {
+        if ( *value <= min )
+          *value = max;
+        else
+          (*value)--;
+        return 1;
+      }
+      break;
+  }
+  return 0;
+}
+
+
+
+static void mui_u8g2_u8_vmm_draw_wm_pf(mui_t *ui) MUI_NOINLINE;
+static void mui_u8g2_u8_vmm_draw_wm_pf(mui_t *ui)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_u8_min_max_t *vmm= (mui_u8g2_u8_min_max_t *)muif_get_data(ui->uif);
+  char buf[4] = "999";
+  char *s = buf;
+  uint8_t *value = mui_u8g2_u8mm_get_valptr(vmm);
+  uint8_t min = mui_u8g2_u8mm_get_min(vmm);
+  uint8_t max = mui_u8g2_u8mm_get_max(vmm);
+  uint8_t cnt = 3;
+  
+  if ( *value > max ) 
+    *value = max;
+  if ( *value <= min )
+    *value = min;
+  if ( max < 100 )
+  {
+    s++;
+    cnt--;
+  }
+  if ( max < 10 )
+  {
+    s++;
+    cnt--;
+  }
+  //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), u8g2_GetStrWidth(u8g2, s)+1, 1, MUI_U8G2_V_PADDING, u8x8_u8toa(*value, cnt));
+  mui_u8g2_draw_button_pf(ui, u8g2_GetStrWidth(u8g2, s)+1, 1, u8x8_u8toa(*value, cnt));
+}
+
+
+uint8_t mui_u8g2_u8_min_max_wm_mse_pf(mui_t *ui, uint8_t msg)
+{
+  mui_u8g2_u8_min_max_t *vmm= (mui_u8g2_u8_min_max_t *)muif_get_data(ui->uif);
+  uint8_t *value = mui_u8g2_u8mm_get_valptr(vmm);
+  uint8_t min = mui_u8g2_u8mm_get_min(vmm);
+  uint8_t max = mui_u8g2_u8mm_get_max(vmm);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_vmm_draw_wm_pf(ui);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+      (*value)++;
+      if ( *value > max ) *value = min;
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( *value > min ) (*value)--; else *value = max;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_min_max_wm_mud_pf(mui_t *ui, uint8_t msg)
+{
+  mui_u8g2_u8_min_max_t *vmm= (mui_u8g2_u8_min_max_t *)muif_get_data(ui->uif);
+  uint8_t *value = mui_u8g2_u8mm_get_valptr(vmm);
+  uint8_t min = mui_u8g2_u8mm_get_min(vmm);
+  uint8_t max = mui_u8g2_u8mm_get_max(vmm);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_vmm_draw_wm_pf(ui);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      /* toggle between normal mode and capture next/prev mode */
+      ui->is_mud = !ui->is_mud;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( ui->is_mud )
+      {
+        (*value)++;
+        if ( *value > max )
+          *value = min;
+        return 1;
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( ui->is_mud )
+      {
+        if ( *value <= min )
+          *value = max;
+        else
+          (*value)--;
+        return 1;
+      }
+      break;
+  }
+  return 0;
+}
+
+
+/*===============================================================================*/
+
+static uint8_t mui_u8g2_u8_bar_mse_msg_handler(mui_t *ui, uint8_t msg) MUI_NOINLINE;
+static uint8_t mui_u8g2_u8_bar_mse_msg_handler(mui_t *ui, uint8_t msg)
+{
+  mui_u8g2_u8_min_max_step_t *vmms= (mui_u8g2_u8_min_max_step_t *)muif_get_data(ui->uif);
+  uint8_t *value = mui_u8g2_u8mms_get_valptr(vmms);
+  uint8_t min = mui_u8g2_u8mms_get_min(vmms);
+  uint8_t max = mui_u8g2_u8mms_get_max(vmms);
+  uint8_t step = mui_u8g2_u8mms_get_step(vmms);
+  uint8_t flags = mui_u8g2_u8mms_get_flags(vmms);
+
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+      (*value)+=step;
+      if ( *value > max )
+      {
+          if ( flags & MUI_MMS_NO_WRAP )
+            *value = max;
+          else
+            *value = min;
+      }
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( *value >= min+step ) 
+        (*value)-=step; 
+      else 
+      {
+          if ( flags & MUI_MMS_NO_WRAP )
+            *value = min;
+          else
+            *value = max;
+      }
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+static uint8_t mui_u8g2_u8_bar_mud_msg_handler(mui_t *ui, uint8_t msg) MUI_NOINLINE;
+static uint8_t mui_u8g2_u8_bar_mud_msg_handler(mui_t *ui, uint8_t msg)
+{
+  mui_u8g2_u8_min_max_step_t *vmms= (mui_u8g2_u8_min_max_step_t *)muif_get_data(ui->uif);
+  uint8_t *value = mui_u8g2_u8mms_get_valptr(vmms);
+  uint8_t min = mui_u8g2_u8mms_get_min(vmms);
+  uint8_t max = mui_u8g2_u8mms_get_max(vmms);
+  uint8_t step = mui_u8g2_u8mms_get_step(vmms);
+  uint8_t flags = mui_u8g2_u8mms_get_flags(vmms);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      /* toggle between normal mode and capture next/prev mode */
+      ui->is_mud = !ui->is_mud;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( ui->is_mud )
+      {
+        (*value)+=step;
+        if ( *value > max )
+        {
+          if ( flags & MUI_MMS_NO_WRAP )
+            *value = max;
+          else
+            *value = min;
+        }
+        return 1;
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( ui->is_mud )
+      {
+        if ( *value <= min || *value > max)
+        {
+          if ( flags & MUI_MMS_NO_WRAP )
+            *value = min;
+          else
+            *value = max;
+        }
+        else
+          (*value)-=step;
+        return 1;
+      }
+      break;
+  }
+  return 0;
+}
+
+
+
+static void mui_u8g2_u8_bar_draw_wm(mui_t *ui, uint8_t flags, uint8_t is_fixed_width) MUI_NOINLINE;
+static void mui_u8g2_u8_bar_draw_wm(mui_t *ui, uint8_t flags, uint8_t is_fixed_width)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_u8_min_max_step_t *vmms= (mui_u8g2_u8_min_max_step_t *)muif_get_data(ui->uif);
+  char buf[4] = "999";
+  char *s = buf;
+  uint8_t *value = mui_u8g2_u8mms_get_valptr(vmms);
+  uint8_t min = mui_u8g2_u8mms_get_min(vmms);
+  uint8_t max = mui_u8g2_u8mms_get_max(vmms);
+  uint8_t scale = 0;
+  //uint8_t step = mui_u8g2_u8mms_get_step(vmms);
+  uint8_t mms_flags = mui_u8g2_u8mms_get_flags(vmms);
+  uint8_t cnt = 3;
+  uint8_t height = u8g2_GetAscent(u8g2);
+  int8_t backup_descent;
+  u8g2_uint_t x = mui_get_x(ui);
+  u8g2_uint_t w = 0;
+  u8g2_uint_t v;  // the calculated pixel value
+  
+  if ( mms_flags & MUI_MMS_2X_BAR )
+    scale |= 1;
+  if ( mms_flags & MUI_MMS_4X_BAR )
+    scale |= 2;
+  
+  if ( *value > max ) 
+    *value = max;
+  if ( *value <= min )
+    *value = min;
+  if ( max < 100 )
+  {
+    s++;
+    cnt--;
+  }
+  if ( max < 10 )
+  {
+    s++;
+    cnt--;
+  }
+
+  if ( is_fixed_width == 0 )
+  {
+    w += (max<<scale);          // total width of the bar is derived from the max value
+    v = (*value)<<scale;          // pixel position for the current value
+  }
+  else
+  {
+    u8g2_uint_t width = mui_u8g2_u8mms_get_width(vmms);
+    
+    w += (width<<scale);          // total width of bar is defined by the width argument
+    v = ((u8g2_long_t)(*value) * (u8g2_long_t)(width<<scale)) / (u8g2_long_t)max;    // u8g2_long_t is int32_t if 16 bit mode is enabled
+  }
+
+  w += 2;                               // add gap for the frame
+  
+  u8g2_DrawFrame( u8g2, x, mui_get_y(ui)-height, w, height);
+  u8g2_DrawBox( u8g2, x+1, mui_get_y(ui)-height+1, v, height-2);
+  if ( mms_flags & MUI_MMS_SHOW_VALUE )
+  {
+    w += 2;
+    u8g2_DrawStr(u8g2,  x+w, mui_get_y(ui), u8x8_u8toa(*value, cnt) );
+    w += u8g2_GetStrWidth(u8g2, s);
+    w += 1; 
+  }
+  backup_descent = u8g2->font_ref_descent;
+  u8g2->font_ref_descent = 0; /* hmm... that's a low level hack so that DrawButtonFrame ignores the descent value of the font */
+  u8g2_DrawButtonFrame(u8g2, x, mui_get_y(ui), flags, w, 1, 1);
+  u8g2->font_ref_descent = backup_descent;  
+}
+
+// #define MUIF_U8G2_U8_MIN_MAX_STEP(id, valptr, min, max, step, flags, muif)
+
+uint8_t mui_u8g2_u8_bar_wm_mse_pi(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pi_flags(ui), 0);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mse_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_u8_bar_wm_mud_pi(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pi_flags(ui), 0);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mud_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_bar_wm_mse_pf(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pf_flags(ui), 0);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mse_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_bar_wm_mud_pf(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pf_flags(ui), 0);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mud_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+
+
+// #define MUIF_U8G2_U8_MIN_MAX_STEP_WIDTH(id, valptr, min, max, step, width, flags, muif) 
+
+
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mse_pi(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pi_flags(ui), 1);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mse_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mud_pi(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pi_flags(ui), 1);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mud_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mse_pf(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pf_flags(ui), 1);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mse_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mud_pf(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_u8_bar_draw_wm(ui, mui_u8g2_get_pf_flags(ui), 1);
+      break;
+    default:
+      return mui_u8g2_u8_bar_mud_msg_handler(ui, msg);
+  }
+  return 0;
+}
+
+
+
+/*===============================================================================*/
+
+static uint8_t mui_is_valid_char(uint8_t c) MUI_NOINLINE;
+uint8_t mui_is_valid_char(uint8_t c)
+{
+  if ( c == 32 )
+    return 1;
+  if ( c >= 'A' && c <= 'Z' )
+    return 1;
+  if ( c >= 'a' && c <= 'z' )
+    return 1;
+  if ( c >= '0' && c <= '9' )
+    return 1;
+  return 0;
+}
+
+
+
+uint8_t mui_u8g2_u8_char_wm_mud_pi(mui_t *ui, uint8_t msg)
+{
+  //ui->dflags                          MUIF_DFLAG_IS_CURSOR_FOCUS       MUIF_DFLAG_IS_TOUCH_FOCUS
+  //mui_get_cflags(ui->uif)       MUIF_CFLAG_IS_CURSOR_SELECTABLE
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  char buf[6];
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      while( mui_is_valid_char(*value) == 0 )
+          (*value)++;
+      buf[0] = *value;
+      buf[1] = '\0';
+      mui_u8g2_draw_button_pi(ui, u8g2_GetMaxCharWidth(u8g2), 1, buf);
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), u8g2_GetMaxCharWidth(u8g2), 1, MUI_U8G2_V_PADDING, buf);
+      //u8g2_DrawButtonUTF8(u8g2, mui_get_x(ui), mui_get_y(ui), mui_u8g2_get_pi_flags(ui), u8g2_GetMaxCharWidth(u8g2), 1, MUI_U8G2_V_PADDING, buf);
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+     case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+     /* toggle between normal mode and capture next/prev mode */
+       ui->is_mud = !ui->is_mud;
+     break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( ui->is_mud )
+      {
+        do {
+          (*value)++;
+        } while( mui_is_valid_char(*value) == 0 );
+        return 1;
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( ui->is_mud )
+      {
+        do {
+          (*value)--;
+        } while( mui_is_valid_char(*value) == 0 );
+        return 1;
+      }
+      break;
+  }
+  return 0;
+}
+
+
+
+
+
+/*
+
+  uint8_t mui_u8g2_u8_opt_line_wa_mse_pi(mui_t *ui, uint8_t msg)
+
+  Description:
+    Select one of several options. First option has value 0.
+    Only one option is visible.
+    The visible option is automatically the selected option.
+
+  Message Handling: DRAW, SELECT
+
+  Style
+    No Selection: Text only
+    Cursor Selection: Inverted text
+
+  User interface field list (muif):
+    flags: MUIF_CFLAG_IS_CURSOR_SELECTABLE
+    data: uint8_t *, pointer to a uint8_t variable, which contains the selected option 
+
+  Field definition string (fds):
+    xy: Left position of the text (required)
+    arg: total width of the selectable option (optional), 
+    text: '|' separated list of options
+    
+*/
+uint8_t mui_u8g2_u8_opt_line_wa_mse_pi(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( mui_fds_get_nth_token(ui, *value) == 0 )
+      {
+        *value = 0;
+        mui_fds_get_nth_token(ui, *value);
+      }
+      mui_u8g2_draw_button_pi(ui, ui->arg, 1, ui->text);
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), ui->arg, 1, MUI_U8G2_V_PADDING, ui->text);
+      //u8g2_DrawButtonUTF8(u8g2, mui_get_x(ui), mui_get_y(ui), mui_u8g2_get_pi_flags(ui), ui->arg, 1, MUI_U8G2_V_PADDING, ui->text);
+      
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+      (*value)++;
+      if ( mui_fds_get_nth_token(ui, *value) == 0 ) 
+        *value = 0;      
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( *value > 0 ) 
+        (*value)--;
+      else
+        (*value) = mui_fds_get_token_cnt(ui)-1;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_opt_line_wa_mse_pf(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( mui_fds_get_nth_token(ui, *value) == 0 )
+      {
+        *value = 0;
+        mui_fds_get_nth_token(ui, *value);
+      }
+      mui_u8g2_draw_button_pf(ui, ui->arg, 1, ui->text);
+      
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+      (*value)++;
+      if ( mui_fds_get_nth_token(ui, *value) == 0 ) 
+        *value = 0;      
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( *value > 0 ) 
+        (*value)--;
+      else
+        (*value) = mui_fds_get_token_cnt(ui)-1;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_opt_line_wa_mud_pi(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( mui_fds_get_nth_token(ui, *value) == 0 )
+      {
+        *value = 0;
+        mui_fds_get_nth_token(ui, *value);
+      }
+      mui_u8g2_draw_button_pi(ui, ui->arg, 1, ui->text);
+      
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      /* toggle between normal mode and capture next/prev mode */
+       ui->is_mud = !ui->is_mud;
+     break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( ui->is_mud )
+      {
+        (*value)++;
+        if ( mui_fds_get_nth_token(ui, *value) == 0 ) 
+          *value = 0;      
+        return 1;
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( ui->is_mud )
+      {
+        if ( *value == 0 )
+          *value = mui_fds_get_token_cnt(ui);
+        (*value)--;
+        return 1;
+      }
+      break;
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u8_opt_line_wa_mud_pf(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( mui_fds_get_nth_token(ui, *value) == 0 )
+      {
+        *value = 0;
+        mui_fds_get_nth_token(ui, *value);
+      }
+      mui_u8g2_draw_button_pf(ui, ui->arg, 1, ui->text);
+      
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      /* toggle between normal mode and capture next/prev mode */
+       ui->is_mud = !ui->is_mud;
+     break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( ui->is_mud )
+      {
+        (*value)++;
+        if ( mui_fds_get_nth_token(ui, *value) == 0 ) 
+          *value = 0;      
+        return 1;
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( ui->is_mud )
+      {
+        if ( *value == 0 )
+          *value = mui_fds_get_token_cnt(ui);
+        (*value)--;
+        return 1;
+      }
+      break;
+  }
+  return 0;
+}
+
+
+
+/*
+
+  uint8_t mui_u8g2_u8_chkbox_wm_pi(mui_t *ui, uint8_t msg)
+  
+  Description:
+    Checkbox with the values 0 (not selected) and 1 (selected). 
+
+  Message Handling: DRAW, SELECT
+
+  Style
+    No Selection: Plain checkbox and text
+    Cursor Selection: Checkbox and text is inverted
+
+  User interface field list (muif):
+    flags: MUIF_CFLAG_IS_CURSOR_SELECTABLE
+    data: uint8_t *, pointer to a uint8_t variable, which contains the values 0 or 1
+
+  Field definition string (fds):
+    xy: Left position of the text (required)
+    arg: not used
+    text: Optional: Text will be printed after the checkbox with a small gap
+    
+*/
+
+uint8_t mui_u8g2_u8_chkbox_wm_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  u8g2_uint_t flags = 0;
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( *value > 1 ) *value = 1;
+      if ( mui_IsCursorFocus(ui) )
+      {
+        flags |= U8G2_BTN_INV;
+      }
+      
+      {
+        u8g2_uint_t w = 0;
+        u8g2_uint_t a = u8g2_GetAscent(u8g2);
+        if ( *value )
+          u8g2_DrawCheckbox(u8g2, mui_get_x(ui), mui_get_y(ui), a, 1);
+        else
+          u8g2_DrawCheckbox(u8g2, mui_get_x(ui), mui_get_y(ui), a, 0);
+        
+        if ( ui->text[0] != '\0' )
+        {
+          w =  u8g2_GetUTF8Width(u8g2, ui->text);
+          //u8g2_SetFontMode(u8g2, 1);
+          a += 2;       /* add gap between the checkbox and the text area */
+          u8g2_DrawUTF8(u8g2, mui_get_x(ui)+a, mui_get_y(ui), ui->text);
+        }
+        
+        u8g2_DrawButtonFrame(u8g2, mui_get_x(ui), mui_get_y(ui), flags, w+a, 1, MUI_U8G2_V_PADDING);
+      }
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      (*value)++;
+      if ( *value > 1 ) *value = 0;      
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+/*
+  radio button style, arg is assigned as value
+*/
+uint8_t mui_u8g2_u8_radio_wm_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  u8g2_uint_t flags = 0;
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+       if ( mui_IsCursorFocus(ui) )
+      {
+        flags |= U8G2_BTN_INV;
+      }
+      
+      {
+        u8g2_uint_t w = 0;
+        u8g2_uint_t a = u8g2_GetAscent(u8g2);
+        if ( *value == ui->arg )
+          u8g2_DrawCheckbox(u8g2, mui_get_x(ui), mui_get_y(ui), a, 1);
+        else
+          u8g2_DrawCheckbox(u8g2, mui_get_x(ui), mui_get_y(ui), a, 0);
+        
+        if ( ui->text[0] != '\0' )
+        {
+          w =  u8g2_GetUTF8Width(u8g2, ui->text);
+          //u8g2_SetFontMode(u8g2, 1);
+          a += 2;       /* add gap between the checkbox and the text area */
+          u8g2_DrawUTF8(u8g2, mui_get_x(ui)+a, mui_get_y(ui), ui->text);
+        }
+        
+        u8g2_DrawButtonFrame(u8g2, mui_get_x(ui), mui_get_y(ui), flags, w+a, 1, MUI_U8G2_V_PADDING);
+      }
+      break;
+   case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      *value = ui->arg;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;  
+}
+
+
+uint8_t mui_u8g2_u8_opt_parent_wm_pi(mui_t *ui, uint8_t msg)
+{
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( mui_fds_get_nth_token(ui, *value) == 0 )
+      {
+        *value = 0;
+        mui_fds_get_nth_token(ui, *value);
+      }      
+      mui_u8g2_draw_button_pi(ui, 0, 1, ui->text);
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), 0, 1, MUI_U8G2_V_PADDING, ui->text);
+      
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      mui_SaveForm(ui);          // store the current form and position so that the child can jump back
+      mui_GotoForm(ui, ui->arg, *value);  // assumes that the selectable values are at the beginning of the form definition
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_u8_opt_child_mse_common(mui_t *ui, uint8_t msg)
+{
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  uint8_t arg = ui->arg;        // remember the arg value, because it might be overwritten
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      /* done by the calling function */
+      break;
+    case MUIF_MSG_FORM_START:
+      /* we can assume that the list starts at the top. It will be adjisted by cursor down events later */
+      /* ui->form_scroll_top = 0 and all other form_scroll values are set to 0 if a new form is entered in mui_EnterForm() */
+      if ( ui->form_scroll_visible <= arg )
+        ui->form_scroll_visible = arg+1;
+      if ( ui->form_scroll_total == 0 )
+          ui->form_scroll_total = mui_GetSelectableFieldOptionCnt(ui, ui->last_form_fds);
+      //printf("MUIF_MSG_FORM_START: arg=%d visible=%d top=%d total=%d\n", arg, ui->form_scroll_visible, ui->form_scroll_top, ui->form_scroll_total);
+      break;
+    case MUIF_MSG_FORM_END:  
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      return mui_u8g2_handle_scroll_next_prev_events(ui, msg);
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( value != NULL )
+        *value = ui->form_scroll_top + arg;
+      mui_RestoreForm(ui);
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      return mui_u8g2_handle_scroll_next_prev_events(ui, msg);
+    case MUIF_MSG_EVENT_PREV:
+      return mui_u8g2_handle_scroll_next_prev_events(ui, msg);
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_u8_opt_radio_child_wm_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  uint8_t arg = ui->arg;        // remember the arg value, because it might be overwritten
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      {
+        u8g2_uint_t w = 0;
+        u8g2_uint_t a = u8g2_GetAscent(u8g2) - 2;
+        u8g2_uint_t x = mui_get_x(ui);   // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        u8g2_uint_t y = mui_get_y(ui);  // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        uint8_t is_focus = mui_IsCursorFocus(ui);
+        if ( *value == arg + ui->form_scroll_top )
+          u8g2_DrawValueMark(u8g2, x, y, a);
+
+        if ( ui->text[0] == '\0' )
+        {
+          /* if the text is not provided, then try to get the text from the previous (saved) element, assuming that this contains the selection */
+          /* this will overwrite all ui member functions, so we must not access any ui members (except ui->text) any more */
+          mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, arg + ui->form_scroll_top);
+        }
+        
+        if ( ui->text[0] != '\0' )
+        {
+          w =  u8g2_GetUTF8Width(u8g2, ui->text);
+          //u8g2_SetFontMode(u8g2, 1);
+          a += 2;       /* add gap between the checkbox and the text area */
+          u8g2_DrawUTF8(u8g2, x+a, y, ui->text);
+        }        
+        if ( is_focus )
+        {
+          u8g2_DrawButtonFrame(u8g2, x, y, U8G2_BTN_INV, w+a, 1, MUI_U8G2_V_PADDING);
+        }
+      }
+      break;
+    default:
+      return mui_u8g2_u8_opt_child_mse_common(ui, msg);
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_u8_opt_radio_child_w1_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  uint8_t arg = ui->arg;        // remember the arg value, because it might be overwritten
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      {
+        //u8g2_uint_t w = 0;
+        u8g2_uint_t a = u8g2_GetAscent(u8g2) - 2;
+        u8g2_uint_t x = mui_get_x(ui);   // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        u8g2_uint_t y = mui_get_y(ui);  // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        uint8_t is_focus = mui_IsCursorFocus(ui);
+        
+        if ( *value == arg + ui->form_scroll_top )
+          u8g2_DrawValueMark(u8g2, x, y, a);
+
+        if ( ui->text[0] == '\0' )
+        {
+          /* if the text is not provided, then try to get the text from the previous (saved) element, assuming that this contains the selection */
+          /* this will overwrite all ui member functions, so we must not access any ui members (except ui->text) any more */
+          mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, arg + ui->form_scroll_top);
+        }
+        
+        if ( ui->text[0] != '\0' )
+        {
+          //w =  u8g2_GetUTF8Width(u8g2, ui->text);
+          //u8g2_SetFontMode(u8g2, 1);
+          a += 2;       /* add gap between the checkbox and the text area */
+          u8g2_DrawUTF8(u8g2, x+a, y, ui->text);
+        }        
+        if ( is_focus )
+        {
+          u8g2_DrawButtonFrame(u8g2, 0, y, U8G2_BTN_INV, u8g2_GetDisplayWidth(u8g2), 0, MUI_U8G2_V_PADDING);
+        }
+      }
+      break;
+    default:
+      return mui_u8g2_u8_opt_child_mse_common(ui, msg);
+  }
+  return 0;
+}
+
+
+uint8_t mui_u8g2_u8_opt_child_wm_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  //uint8_t *value = (uint8_t *)muif_get_data(ui->uif);
+  uint8_t arg = ui->arg;        // remember the arg value, because it might be overwritten
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      {
+        //u8g2_uint_t w = 0;
+        u8g2_uint_t x = mui_get_x(ui);   // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        u8g2_uint_t y = mui_get_y(ui);  // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        uint8_t flags = mui_u8g2_get_pi_flags(ui);
+        //if ( mui_IsCursorFocus(ui) )
+        //{
+        //  flags = U8G2_BTN_INV;
+        //}
+
+        if ( ui->text[0] == '\0' )
+        {
+          /* if the text is not provided, then try to get the text from the previous (saved) element, assuming that this contains the selection */
+          /* this will overwrite all ui member functions, so we must not access any ui members (except ui->text) any more */
+          mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, arg + ui->form_scroll_top);
+        }
+        if ( ui->text[0] != '\0' )
+        {
+          u8g2_DrawButtonUTF8(u8g2, x, y, flags, 0, 1, MUI_U8G2_V_PADDING, ui->text);
+        }        
+      }
+      break;
+    default:
+      return mui_u8g2_u8_opt_child_mse_common(ui, msg);
+  }
+  return 0;
+}
+
+/* 
+  an invisible field (which will not show anything). It should also not be selectable 
+  it just provides the menu entries, see "mui_u8g2_u8_opt_child_mse_common" and friends 
+  as a consequence it does not have width, input mode and style
+
+  MUIF: MUIF_RO()
+  FDS: MUI_DATA()
+
+  mui_u8g2_goto_parent --> mui_u8g2_goto_data
+
+  Used together with mui_u8g2_goto_form_w1_pi
+
+*/
+uint8_t mui_u8g2_goto_data(mui_t *ui, uint8_t msg)
+{
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      break;
+    case MUIF_MSG_FORM_START:
+      // store the field (and the corresponding elements) in the last_form_fds variable.
+      // last_form_fds is later used to access the elements (see mui_u8g2_u8_opt_child_mse_common and friends)
+      ui->last_form_fds = ui->fds;
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+
+/*
+mui_u8g2_goto_child_w1_mse_pi --> mui_u8g2_goto_form_w1_pi
+*/
+uint8_t mui_u8g2_goto_form_w1_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t arg = ui->arg;        // remember the arg value, because it might be overwritten  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, arg + ui->form_scroll_top) )
+        mui_u8g2_draw_button_pi(ui, u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui), ui->text+1);
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+      if ( mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, ui->arg + ui->form_scroll_top) )
+      {
+        mui_SaveCursorPosition(ui, ui->arg + ui->form_scroll_top);     // store the current cursor position, so that the user can jump back to the corresponding cursor position
+        return mui_GotoFormAutoCursorPosition(ui, (uint8_t)ui->text[0]);
+      }
+      break;
+    default:
+      return mui_u8g2_u8_opt_child_mse_common(ui, msg);
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_goto_form_w1_pf(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  uint8_t arg = ui->arg;        // remember the arg value, because it might be overwritten  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      if ( mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, arg + ui->form_scroll_top) )
+        mui_u8g2_draw_button_pf(ui, u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui)-1, ui->text+1);
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+      if ( mui_GetSelectableFieldTextOption(ui, ui->last_form_fds, ui->arg + ui->form_scroll_top) )
+      {
+        mui_SaveCursorPosition(ui, ui->arg + ui->form_scroll_top);     // store the current cursor position, so that the user can jump back to the corresponding cursor position
+        return mui_GotoFormAutoCursorPosition(ui, (uint8_t)ui->text[0]);
+     }
+      break;
+    default:
+      return mui_u8g2_u8_opt_child_mse_common(ui, msg);
+  }
+  return 0;
+}
+
+
+/*
+  data: mui_u8g2_list_t *
+*/
+uint8_t mui_u8g2_u16_list_line_wa_mse_pi(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_list_t *list = (mui_u8g2_list_t *)muif_get_data(ui->uif);
+  uint16_t *selection =  mui_u8g2_list_get_selection_ptr(list);
+  void *data = mui_u8g2_list_get_data_ptr(list);
+  mui_u8g2_get_list_element_cb element_cb =  mui_u8g2_list_get_element_cb(list);
+  mui_u8g2_get_list_count_cb count_cb = mui_u8g2_list_get_count_cb(list);
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_pi(ui, ui->arg, 1, element_cb(data, *selection));
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), ui->arg, 1, MUI_U8G2_V_PADDING, element_cb(data, *selection));
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+      (*selection)++;
+      if ( *selection >= count_cb(data) ) 
+        *selection = 0;
+      break;
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( *selection > 0 )
+        (*selection)--;
+      else
+        (*selection) = count_cb(data)-1;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u16_list_line_wa_mud_pi(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_list_t *list = (mui_u8g2_list_t *)muif_get_data(ui->uif);
+  uint16_t *selection =  mui_u8g2_list_get_selection_ptr(list);
+  void *data = mui_u8g2_list_get_data_ptr(list);
+  mui_u8g2_get_list_element_cb element_cb =  mui_u8g2_list_get_element_cb(list);
+  mui_u8g2_get_list_count_cb count_cb = mui_u8g2_list_get_count_cb(list);
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_pi(ui, ui->arg, 1, element_cb(data, *selection));
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), ui->arg, 1, MUI_U8G2_V_PADDING, element_cb(data, *selection));
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      /* toggle between normal mode and capture next/prev mode */
+       ui->is_mud = !ui->is_mud;
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      if ( ui->is_mud )
+      {
+        (*selection)++;
+        if ( *selection >= count_cb(data)  ) 
+          *selection = 0;      
+        return 1;
+      }
+      break;
+    case MUIF_MSG_EVENT_PREV:
+      if ( ui->is_mud )
+      {
+        if ( *selection == 0 )
+          *selection = count_cb(data);
+        (*selection)--;
+        return 1;
+      }
+      break;
+  }
+  return 0;
+}
+
+/*
+  MUIF: MUIF_U8G2_U16_LIST
+  FDS: MUI_XYA, arg=form id
+  data: mui_u8g2_list_t *
+*/
+uint8_t mui_u8g2_u16_list_parent_wm_pi(mui_t *ui, uint8_t msg)
+{
+  //u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_list_t *list = (mui_u8g2_list_t *)muif_get_data(ui->uif);
+  uint16_t *selection =  mui_u8g2_list_get_selection_ptr(list);
+  void *data = mui_u8g2_list_get_data_ptr(list);
+  mui_u8g2_get_list_element_cb element_cb =  mui_u8g2_list_get_element_cb(list);
+  //mui_u8g2_get_list_count_cb count_cb = mui_u8g2_list_get_count_cb(list);
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_pi(ui, 0, 1, element_cb(data, *selection));
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), ui->arg, 1, MUI_U8G2_V_PADDING, element_cb(data, *selection));
+      break;
+    case MUIF_MSG_FORM_START:
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      mui_SaveForm(ui);          // store the current form and position so that the child can jump back
+      mui_GotoForm(ui, ui->arg, *selection);  // assumes that the selectable values are at the beginning of the form definition
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+  }
+  return 0;
+}
+
+static uint8_t mui_u8g2_u16_list_child_mse_common(mui_t *ui, uint8_t msg)
+{
+  mui_u8g2_list_t *list = (mui_u8g2_list_t *)muif_get_data(ui->uif);
+  uint16_t *selection =  mui_u8g2_list_get_selection_ptr(list);
+  void *data = mui_u8g2_list_get_data_ptr(list);
+  //mui_u8g2_get_list_element_cb element_cb =  mui_u8g2_list_get_element_cb(list);
+  mui_u8g2_get_list_count_cb count_cb = mui_u8g2_list_get_count_cb(list);
+
+  uint8_t arg = ui->arg;        // remember the arg value, because it might be overwritten  
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      /* done by the calling function */
+      break;
+    case MUIF_MSG_FORM_START:
+      /* we can assume that the list starts at the top. It will be adjisted by cursor down events later */
+      ui->form_scroll_top = 0;
+      if ( ui->form_scroll_visible <= arg )
+        ui->form_scroll_visible = arg+1;
+      if ( ui->form_scroll_total == 0 )
+          ui->form_scroll_total = count_cb(data);
+      break;
+    case MUIF_MSG_FORM_END:
+      break;
+    case MUIF_MSG_CURSOR_ENTER:
+      return mui_u8g2_handle_scroll_next_prev_events(ui, msg);
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( selection != NULL )
+        *selection = ui->form_scroll_top + arg;
+      mui_RestoreForm(ui);
+      break;
+    case MUIF_MSG_CURSOR_LEAVE:
+      break;
+    case MUIF_MSG_TOUCH_DOWN:
+      break;
+    case MUIF_MSG_TOUCH_UP:
+      break;
+    case MUIF_MSG_EVENT_NEXT:
+      return mui_u8g2_handle_scroll_next_prev_events(ui, msg);
+    case MUIF_MSG_EVENT_PREV:
+      return mui_u8g2_handle_scroll_next_prev_events(ui, msg);
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u16_list_child_w1_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_list_t *list = (mui_u8g2_list_t *)muif_get_data(ui->uif);
+  uint16_t *selection =  mui_u8g2_list_get_selection_ptr(list);
+  void *data = mui_u8g2_list_get_data_ptr(list);
+  mui_u8g2_get_list_element_cb element_cb =  mui_u8g2_list_get_element_cb(list);
+  mui_u8g2_get_list_count_cb count_cb = mui_u8g2_list_get_count_cb(list);
+  uint16_t pos = ui->arg;        // remember the arg value, because it might be overwritten  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      {
+        //u8g2_uint_t w = 0;
+        u8g2_uint_t a = u8g2_GetAscent(u8g2) - 2;
+        u8g2_uint_t x = mui_get_x(ui);   // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        u8g2_uint_t y = mui_get_y(ui);  // if mui_GetSelectableFieldTextOption is called, then field vars are overwritten, so get the value
+        uint8_t is_focus = mui_IsCursorFocus(ui);
+
+        pos += ui->form_scroll_top;
+        
+        if ( *selection == pos )
+          u8g2_DrawValueMark(u8g2, x, y, a);
+
+        //u8g2_SetFontMode(u8g2, 1);
+        a += 2;       /* add gap between the checkbox and the text area */
+        if ( pos < count_cb(data) )
+          u8g2_DrawUTF8(u8g2, x+a, y, element_cb(data, pos));
+        if ( is_focus )
+        {
+          u8g2_DrawButtonFrame(u8g2, 0, y, U8G2_BTN_INV, u8g2_GetDisplayWidth(u8g2), 0, MUI_U8G2_V_PADDING);
+        }
+      }
+      break;
+    default:
+      return mui_u8g2_u16_list_child_mse_common(ui, msg);
+  }
+  return 0;
+}
+
+uint8_t mui_u8g2_u16_list_goto_w1_pi(mui_t *ui, uint8_t msg)
+{
+  u8g2_t *u8g2 = mui_get_U8g2(ui);
+  mui_u8g2_list_t *list = (mui_u8g2_list_t *)muif_get_data(ui->uif);
+  uint16_t *selection =  mui_u8g2_list_get_selection_ptr(list);
+  void *data = mui_u8g2_list_get_data_ptr(list);
+  mui_u8g2_get_list_element_cb element_cb =  mui_u8g2_list_get_element_cb(list);
+  //mui_u8g2_get_list_count_cb count_cb = mui_u8g2_list_get_count_cb(list);
+
+  uint16_t pos = ui->arg;        // remember the arg value, because it might be overwritten  
+  pos += ui->form_scroll_top;
+  
+  switch(msg)
+  {
+    case MUIF_MSG_DRAW:
+      mui_u8g2_draw_button_pi(ui, u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui), element_cb(data, pos)+1);
+      //mui_u8g2_draw_button_utf(ui, mui_u8g2_get_pi_flags(ui), u8g2_GetDisplayWidth(u8g2)-mui_get_x(ui)*2, mui_get_x(ui), MUI_U8G2_V_PADDING, element_cb(data, pos)+1);
+      break;
+    case MUIF_MSG_CURSOR_SELECT:
+    case MUIF_MSG_VALUE_INCREMENT:
+    case MUIF_MSG_VALUE_DECREMENT:
+      if ( selection != NULL )
+        *selection = pos;
+      mui_SaveCursorPosition(ui, pos >= 255 ? 0 : pos);     // store the current cursor position, so that the user can jump back to the corresponding cursor position
+      mui_GotoFormAutoCursorPosition(ui, (uint8_t)element_cb(data, pos)[0]); 
+      break;
+    default:
+      return mui_u8g2_u16_list_child_mse_common(ui, msg);
+  }
+  return 0;
+}

+ 307 - 0
components/u8g2/mui_u8g2.h

@@ -0,0 +1,307 @@
+/*
+
+  mui_u8g2.h
+
+  Monochrome minimal user interface: Glue code between mui and u8g2.
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2021, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+
+  Reference Manual:
+    https://github.com/olikraus/u8g2/wiki/muiref
+
+  MUIF_U8G2_LABEL()  
+    replacement for MUIF_LABEL(mui_u8g2_draw_text), 
+    used by MUI_LABEL(x,y,"text")
+    Supports UTF8
+    
+  MUIF_U8G2_FONT_STYLE(n, font) 
+    A special u8g2 style function, which replaces MUIF_STYLE, but restricts the style change to the
+    specific font argument (however, this should be good enough in most cases).
+    As usual, the style "n" can be activated with MUI_STYLE(n) in FDS.
+    Example:
+      muif_t muif_list[]  MUI_PROGMEM = {  
+          MUIF_U8G2_LABEL(),
+          MUIF_U8G2_FONT_STYLE(0, u8g2_font_5x8_tr) 
+        };
+        fds_t fds[] MUI_PROGMEM  =
+        MUI_FORM(1)
+        MUI_STYLE(0)
+        MUI_LABEL(5,12, "5x8 Font")
+        ;
+
+    
+
+
+
+*/
+
+#ifndef MUI_U8G2_H
+#define MUI_U8G2_H
+
+#include "mui.h"
+
+/*==========================================*/
+/* C++ compatible */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define MUI_U8G2_COMMA ,
+
+typedef const char * (*mui_u8g2_get_list_element_cb)(void *data, uint16_t index);
+typedef uint16_t (*mui_u8g2_get_list_count_cb)(void *data);
+
+struct mui_u8g2_list_struct
+{
+  uint16_t *selection;
+  void *data;
+  mui_u8g2_get_list_element_cb get_list_element;
+  mui_u8g2_get_list_count_cb get_list_count;  
+} MUI_PROGMEM;
+
+typedef const struct mui_u8g2_list_struct mui_u8g2_list_t;
+
+#if defined(__GNUC__) && defined(__AVR__)
+#  define mui_u8g2_list_get_selection_ptr(list)         ((uint16_t *)mui_pgm_wread(&((list)->selection)))
+#  define mui_u8g2_list_get_data_ptr(list)                ((void *)mui_pgm_wread(&((list)->data)))
+#  define mui_u8g2_list_get_element_cb(list)          ((mui_u8g2_get_list_element_cb)mui_pgm_wread(&((list)->get_list_element)))
+#  define mui_u8g2_list_get_count_cb(list)              ((mui_u8g2_get_list_count_cb)mui_pgm_wread(&((list)->get_list_count)))
+#else
+#  define mui_u8g2_list_get_selection_ptr(list)                 ((list)->selection)
+#  define mui_u8g2_list_get_data_ptr(list)                         ((list)->data)
+#  define mui_u8g2_list_get_element_cb(list)                   ((list)->get_list_element)
+#  define mui_u8g2_list_get_count_cb(list)                      ((list)->get_list_count)
+#endif
+
+
+struct mui_u8g2_u8_min_max_struct
+{
+  uint8_t *value;
+  uint8_t min;
+  uint8_t max;
+} MUI_PROGMEM;
+
+typedef const struct mui_u8g2_u8_min_max_struct mui_u8g2_u8_min_max_t;
+
+#if defined(__GNUC__) && defined(__AVR__)
+#  define mui_u8g2_u8mm_get_min(u8mm) mui_pgm_read(&((u8mm)->min))
+#  define mui_u8g2_u8mm_get_max(u8mm) mui_pgm_read(&((u8mm)->max))
+#  define mui_u8g2_u8mm_get_valptr(u8mm) ((uint8_t *)mui_pgm_wread(&((u8mm)->value)))
+#else
+#  define mui_u8g2_u8mm_get_min(u8mm) ((u8mm)->min)
+#  define mui_u8g2_u8mm_get_max(u8mm) ((u8mm)->max)
+#  define mui_u8g2_u8mm_get_valptr(u8mm) ((u8mm)->value)
+#endif
+
+
+struct mui_u8g2_u8_min_max_step_struct
+{
+  uint8_t *value;
+  uint8_t min;
+  uint8_t max;
+  uint8_t step;
+  uint8_t flags;
+  uint8_t width;        // added with issue 2200, might not be used by all bar graph functions
+} MUI_PROGMEM;
+
+typedef const struct mui_u8g2_u8_min_max_step_struct mui_u8g2_u8_min_max_step_t;
+
+/* list of bit values for the "flags" variable */
+#define MUI_MMS_2X_BAR 0x01
+#define MUI_MMS_4X_BAR 0x02
+#define MUI_MMS_SHOW_VALUE 0x04
+#define MUI_MMS_NO_WRAP 0x08
+
+#if defined(__GNUC__) && defined(__AVR__)
+#  define mui_u8g2_u8mms_get_width(u8mm) mui_pgm_read(&((u8mm)->width))
+#  define mui_u8g2_u8mms_get_step(u8mm) mui_pgm_read(&((u8mm)->step))
+#  define mui_u8g2_u8mms_get_flags(u8mm) mui_pgm_read(&((u8mm)->flags))
+#  define mui_u8g2_u8mms_get_min(u8mm) mui_pgm_read(&((u8mm)->min))
+#  define mui_u8g2_u8mms_get_max(u8mm) mui_pgm_read(&((u8mm)->max))
+#  define mui_u8g2_u8mms_get_valptr(u8mm) ((uint8_t *)mui_pgm_wread(&((u8mm)->value)))
+#else
+#  define mui_u8g2_u8mms_get_width(u8mm) ((u8mm)->width)
+#  define mui_u8g2_u8mms_get_step(u8mm) ((u8mm)->step)
+#  define mui_u8g2_u8mms_get_flags(u8mm) ((u8mm)->flags)
+#  define mui_u8g2_u8mms_get_min(u8mm) ((u8mm)->min)
+#  define mui_u8g2_u8mms_get_max(u8mm) ((u8mm)->max)
+#  define mui_u8g2_u8mms_get_valptr(u8mm) ((u8mm)->value)
+#endif
+
+
+
+
+/* helper functions */
+
+u8g2_uint_t mui_get_x(mui_t *ui);
+u8g2_uint_t mui_get_y(mui_t *ui);
+u8g2_t *mui_get_U8g2(mui_t *ui);
+
+void mui_u8g2_draw_button_utf(mui_t *ui, u8g2_uint_t flags, u8g2_uint_t width, u8g2_uint_t padding_h, u8g2_uint_t padding_v, const char *text);
+u8g2_uint_t mui_u8g2_get_pi_flags(mui_t *ui);
+void mui_u8g2_draw_button_pi(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text);
+u8g2_uint_t mui_u8g2_get_fi_flags(mui_t *ui);
+void mui_u8g2_draw_button_fi(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text);
+u8g2_uint_t mui_u8g2_get_pf_flags(mui_t *ui);
+void mui_u8g2_draw_button_pf(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text);
+u8g2_uint_t mui_u8g2_get_if_flags(mui_t *ui);
+void mui_u8g2_draw_button_if(mui_t *ui, u8g2_uint_t width, u8g2_uint_t padding_h, const char *text);
+
+
+
+/* ready to use field functions */
+
+uint8_t mui_u8g2_draw_text(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_btn_goto_wm_fi(mui_t *ui, uint8_t msg);        /* GIF */
+uint8_t mui_u8g2_btn_goto_wm_if(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_btn_goto_w2_fi(mui_t *ui, uint8_t msg);         /* GIF */
+uint8_t mui_u8g2_btn_goto_w2_if(mui_t *ui, uint8_t msg);
+
+uint8_t mui_u8g2_btn_goto_w1_pi(mui_t *ui, uint8_t msg);        /* GIF */
+uint8_t mui_u8g2_btn_goto_w1_fi(mui_t *ui, uint8_t msg);        /* GIF */
+
+uint8_t mui_u8g2_btn_exit_wm_fi(mui_t *ui, uint8_t msg);        /* similar to 'mui_u8g2_btn_goto_wm_fi' but will exit the menu system */
+
+uint8_t mui_u8g2_u8_chkbox_wm_pi(mui_t *ui, uint8_t msg);       /* GIF, MUIF_VARIABLE, MUI_XY */
+uint8_t mui_u8g2_u8_radio_wm_pi(mui_t *ui, uint8_t msg);        /* GIF, MUIF_VARIABLE,MUI_XYAT */
+
+
+
+uint8_t mui_u8g2_u8_opt_line_wa_mse_pi(mui_t *ui, uint8_t msg); /* GIF, MUIF_VARIABLE,MUI_XYAT */
+uint8_t mui_u8g2_u8_opt_line_wa_mse_pf(mui_t *ui, uint8_t msg); /* GIF, MUIF_VARIABLE,MUI_XYAT */
+uint8_t mui_u8g2_u8_opt_line_wa_mud_pi(mui_t *ui, uint8_t msg); /* GIF, MUIF_VARIABLE,MUI_XYAT */
+uint8_t mui_u8g2_u8_opt_line_wa_mud_pf(mui_t *ui, uint8_t msg); /* GIF, MUIF_VARIABLE,MUI_XYAT */
+
+/* dropdown list / combo box */
+/* The text part of the parent defines a '|' separated list of elements, which can be selected by the child. */
+/* Argument is a form number where the child element is placed multiple times */ 
+/* The child form does not require the ok button, because the child function will return to the parent with the select element */
+uint8_t mui_u8g2_u8_opt_parent_wm_pi(mui_t *ui, uint8_t msg);       /* GIF, MUIF_VARIABLE, MUI_XYAT */
+uint8_t mui_u8g2_u8_opt_radio_child_wm_pi(mui_t *ui, uint8_t msg);        /* GIF, MUIF_VARIABLE, MUI_XYA */
+uint8_t mui_u8g2_u8_opt_radio_child_w1_pi(mui_t *ui, uint8_t msg);          /* GIF, MUIF_VARIABLE, MUI_XYA */
+uint8_t mui_u8g2_u8_opt_child_wm_pi(mui_t *ui, uint8_t msg);                /* MUIF_VARIABLE, MUI_XYA */ 
+/* Note: there is no opt_child_goto muif, because this can be done with mui_u8g2_goto_form_w1_pi */
+
+/* (scrollable) jump menu */
+/* The text part of the parent defines a '|' separated list of elements, which can be selected goto_form functions. */
+/* Each '|' separated element must be prefixed with the form number (MUI_x) */
+uint8_t mui_u8g2_goto_data(mui_t *ui, uint8_t msg);                        /* REF, MUIF_RO, MUI_DATA (WARNING: Must appear only once per form!!! */
+uint8_t mui_u8g2_goto_form_w1_pi(mui_t *ui, uint8_t msg);          /* REF, MUIF_BUTTON, MUI_XYA */
+uint8_t mui_u8g2_goto_form_w1_pf(mui_t *ui, uint8_t msg);           /* REF, MUIF_BUTTON, MUI_XYA */
+
+
+/* character input */
+uint8_t mui_u8g2_u8_char_wm_mud_pi(mui_t *ui, uint8_t msg);     /* GIF, MUIF_VARIABLE,MUI_XY, usually requires a monospaced font line profont12 */
+
+
+/*===== MUIF U8g2 Label  =====*/
+
+#define MUIF_U8G2_LABEL()  MUIF_LABEL(mui_u8g2_draw_text)
+
+
+/*===== data = u8g2 font data  =====*/
+
+//#define MUIF_U8G2_FONT_STYLE(n,font)  MUIF("S" #n, 0, (void *)(font), mui_u8g2_set_font_style_function) 
+#define MUIF_U8G2_FONT_STYLE(n, font) { 'S', #n[0], 0, 0, (void *)(font), mui_u8g2_set_font_style_function} 
+
+
+uint8_t mui_u8g2_set_font_style_function(mui_t *ui, uint8_t msg);
+
+
+/*===== data = mui_u8g2_u8_min_max_t*  =====*/
+
+/* gcc note: the macro uses array compound literals to extend the lifetime in C++, see last section in https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html */
+#define MUIF_U8G2_U8_MIN_MAX(id, valptr, min, max, muif) \
+  MUIF(id, MUIF_CFLAG_IS_CURSOR_SELECTABLE,  \
+  (void *)((mui_u8g2_u8_min_max_t [] ) {{ (valptr) MUI_U8G2_COMMA (min) MUI_U8G2_COMMA (max)}}), \
+  (muif))
+
+uint8_t mui_u8g2_u8_min_max_wm_mse_pi(mui_t *ui, uint8_t msg);   /* GIF, MUIF_U8G2_U8_MIN_MAX, MUI_XY */
+uint8_t mui_u8g2_u8_min_max_wm_mud_pi(mui_t *ui, uint8_t msg);  /* GIF, MUIF_U8G2_U8_MIN_MAX, MUI_XY */
+
+uint8_t mui_u8g2_u8_min_max_wm_mse_pf(mui_t *ui, uint8_t msg);  /* GIF, MUIF_U8G2_U8_MIN_MAX, MUI_XY */
+uint8_t mui_u8g2_u8_min_max_wm_mud_pf(mui_t *ui, uint8_t msg);  /* GIF, MUIF_U8G2_U8_MIN_MAX, MUI_XY */
+
+/*===== data = mui_u8g2_u8_min_max_step_t*  =====*/
+
+/* gcc note: the macro uses array compound literals to extend the lifetime in C++, see last section in https://gcc.gnu.org/onlinedocs/gcc/Compound-Literals.html */
+#define MUIF_U8G2_U8_MIN_MAX_STEP(id, valptr, min, max, step, flags, muif) \
+  MUIF(id, MUIF_CFLAG_IS_CURSOR_SELECTABLE,  \
+  (void *)((mui_u8g2_u8_min_max_step_t [] ) {{ (valptr) MUI_U8G2_COMMA (min) MUI_U8G2_COMMA (max) MUI_U8G2_COMMA (step) MUI_U8G2_COMMA (flags) MUI_U8G2_COMMA (0) }}), \
+  (muif))
+  
+
+uint8_t mui_u8g2_u8_bar_wm_mse_pi(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_u8_bar_wm_mud_pi(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_u8_bar_wm_mse_pf(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_u8_bar_wm_mud_pf(mui_t *ui, uint8_t msg);
+
+
+#define MUIF_U8G2_U8_MIN_MAX_STEP_WIDTH(id, valptr, min, max, step, width, flags, muif) \
+  MUIF(id, MUIF_CFLAG_IS_CURSOR_SELECTABLE,  \
+  (void *)((mui_u8g2_u8_min_max_step_t [] ) {{ (valptr) MUI_U8G2_COMMA (min) MUI_U8G2_COMMA (max) MUI_U8G2_COMMA (step) MUI_U8G2_COMMA (flags) MUI_U8G2_COMMA (width) }}), \
+  (muif))
+  
+
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mse_pi(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mud_pi(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mse_pf(mui_t *ui, uint8_t msg);
+uint8_t mui_u8g2_u8_fixed_width_bar_wm_mud_pf(mui_t *ui, uint8_t msg);
+
+
+
+/*===== data = mui_u8g2_list_t*  =====*/
+/* similar to mui_u8g2_u8_opt_line, but u16 and dynamic list */
+
+
+#define MUIF_U8G2_U16_LIST(id, valptr, dataptr, getcb, cntcb, muif) \
+  MUIF(id, MUIF_CFLAG_IS_CURSOR_SELECTABLE,  \
+  (void *)((mui_u8g2_list_t [] ) {{ (valptr) MUI_U8G2_COMMA (dataptr) MUI_U8G2_COMMA (getcb) MUI_U8G2_COMMA (cntcb)}}), \
+  (muif))
+  
+uint8_t mui_u8g2_u16_list_line_wa_mse_pi(mui_t *ui, uint8_t msg);       /* GIF, MUIF_U8G2_U16_LIST, MUI_XYA, arg=pixel fieldsize */
+uint8_t mui_u8g2_u16_list_line_wa_mud_pi(mui_t *ui, uint8_t msg);       /* GIF, MUIF_U8G2_U16_LIST, MUI_XYA, arg=pixel fieldsize */
+
+
+/* dropdown list / combo box with 16 size and callback functions for MUIF_U8G2_U16_LIST */
+uint8_t mui_u8g2_u16_list_parent_wm_pi(mui_t *ui, uint8_t msg);     /* GIF, MUIF_U8G2_U16_LIST, MUI_XYA, arg=subform */
+uint8_t mui_u8g2_u16_list_child_w1_pi(mui_t *ui, uint8_t msg);      /* GIF, MUIF_U8G2_U16_LIST, MUI_XYA, arg=sub element number */
+uint8_t mui_u8g2_u16_list_goto_w1_pi(mui_t *ui, uint8_t msg);               /* REF, MUIF_U8G2_U16_LIST first char of the string denotes the target form */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* MUI_U8G2_H */
+

+ 411 - 14
components/u8g2/u8g2.h

@@ -174,7 +174,7 @@
   A frame of width 9 would place the C a little bit more to the right (width of that "C" are 6 pixel).
   If U8G2_BALANCED_STR_WIDTH_CALCULATION is defined, the width of "C" is returned as 8.
   
-  Not defining U8G2_BALANCED_STR_WIDTH_CALCULATION would fall back to the old bahavior.
+  Not defining U8G2_BALANCED_STR_WIDTH_CALCULATION would fall back to the old behavior.
 */
 #ifndef U8G2_NO_BALANCED_STR_WIDTH_CALCULATION 
 #define U8G2_BALANCED_STR_WIDTH_CALCULATION
@@ -343,9 +343,9 @@ struct u8g2_struct
   u8g2_uint_t width;
   u8g2_uint_t height;
   
-  /* ths is the clip box for the user to check if a specific box has an intersection */
+  /* this is the clip box for the user to check if a specific box has an intersection */
   /* use u8g2_IsIntersection from u8g2_intersection.c to test against this intersection */
-  /* actually, this window describes the positon of the current page */
+  /* actually, this window describes the position of the current page */
   u8g2_uint_t user_x0;	/* left corner of the buffer */
   u8g2_uint_t user_x1;	/* right corner of the buffer (excluded) */
   u8g2_uint_t user_y0;	/* upper edge of the buffer */
@@ -450,8 +450,8 @@ extern const u8g2_cb_t u8g2_cb_mirror_vertical;
 #define U8G2_MIRROR	(&u8g2_cb_mirror)
 #define U8G2_MIRROR_VERTICAL	(&u8g2_cb_mirror_vertical)
 /*
-  u8g2:			A new, not yet initialized u8g2 memory areay
-  buf:			Memory are of size tile_buf_height*<width of the display in pixel>
+  u8g2:			A new, not yet initialized u8g2 memory area
+  buf:			Memory area of size tile_buf_height*<width of the display in pixel>
   tile_buf_height:	Number of full lines
   ll_hvline_cb:		one of:
     u8g2_ll_hvline_vertical_top_lsb
@@ -485,6 +485,9 @@ uint8_t *u8g2_m_255_2_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_9_5_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_9_5_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_9_5_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_12_5_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_12_5_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_12_5_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_8_4_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_8_4_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_8_4_f(uint8_t *page_cnt);
@@ -500,6 +503,9 @@ uint8_t *u8g2_m_10_16_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_16_16_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_16_16_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_16_16_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_16_20_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_16_20_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_16_20_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_20_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_20_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_20_f(uint8_t *page_cnt);
@@ -518,6 +524,9 @@ uint8_t *u8g2_m_6_8_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_12_2_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_12_2_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_12_2_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_12_4_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_12_4_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_12_4_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_16_12_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_16_12_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_16_12_f(uint8_t *page_cnt);
@@ -527,6 +536,15 @@ uint8_t *u8g2_m_32_4_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_12_8_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_12_8_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_12_8_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_16_5_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_16_5_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_16_5_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_18_4_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_18_4_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_18_4_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_20_4_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_20_4_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_20_4_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_24_4_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_24_4_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_24_4_f(uint8_t *page_cnt);
@@ -581,9 +599,18 @@ uint8_t *u8g2_m_17_4_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_17_8_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_17_8_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_17_8_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_17_9_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_17_9_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_17_9_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_48_17_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_48_17_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_48_17_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_48_20_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_48_20_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_48_20_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_42_20_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_42_20_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_42_20_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_12_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_12_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_12_f(uint8_t *page_cnt);
@@ -593,18 +620,18 @@ uint8_t *u8g2_m_32_20_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_22_13_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_22_13_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_22_13_f(uint8_t *page_cnt);
-uint8_t *u8g2_m_19_4_1(uint8_t *page_cnt);
-uint8_t *u8g2_m_19_4_2(uint8_t *page_cnt);
-uint8_t *u8g2_m_19_4_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_10_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_10_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_10_f(uint8_t *page_cnt);
-uint8_t *u8g2_m_20_4_1(uint8_t *page_cnt);
-uint8_t *u8g2_m_20_4_2(uint8_t *page_cnt);
-uint8_t *u8g2_m_20_4_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_19_4_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_19_4_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_19_4_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_17_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_17_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_20_17_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_26_5_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_26_5_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_26_5_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_22_9_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_22_9_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_22_9_f(uint8_t *page_cnt);
@@ -614,6 +641,9 @@ uint8_t *u8g2_m_25_25_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_37_16_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_37_16_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_37_16_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_40_25_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_40_25_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_40_25_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_8_1_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_8_1_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_8_1_f(uint8_t *page_cnt);
@@ -623,6 +653,15 @@ uint8_t *u8g2_m_4_1_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_1_1_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_1_1_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_1_1_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_20_2_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_20_2_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_20_2_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_32_7_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_32_7_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_32_7_f(uint8_t *page_cnt);
+uint8_t *u8g2_m_32_6_1(uint8_t *page_cnt);
+uint8_t *u8g2_m_32_6_2(uint8_t *page_cnt);
+uint8_t *u8g2_m_32_6_f(uint8_t *page_cnt);
 uint8_t *u8g2_m_48_30_1(uint8_t *page_cnt);
 uint8_t *u8g2_m_48_30_2(uint8_t *page_cnt);
 uint8_t *u8g2_m_48_30_f(uint8_t *page_cnt);
@@ -677,12 +716,30 @@ void u8g2_Setup_ssd1306_i2c_128x64_alt0_2(u8g2_t *u8g2, const u8g2_cb_t *rotatio
 void u8g2_Setup_ssd1306_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_i2c_128x64_vcomh0_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_i2c_128x64_alt0_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1312_128x64_noname_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1312_128x64_noname_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1312_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1312_i2c_128x64_noname_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1312_i2c_128x64_noname_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1312_i2c_128x64_noname_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_72x40_er_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_72x40_er_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_72x40_er_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_i2c_72x40_er_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_i2c_72x40_er_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1306_i2c_72x40_er_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_96x40_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_96x39_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_96x40_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_96x39_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_96x40_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_96x39_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_i2c_96x40_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_i2c_96x39_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_i2c_96x40_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_i2c_96x39_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_i2c_96x40_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1306_i2c_96x39_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1106_128x64_noname_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1106_128x64_vcomh0_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1106_128x64_winstar_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -720,17 +777,29 @@ void u8g2_Setup_sh1107_i2c_64x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x
 void u8g2_Setup_sh1107_i2c_64x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_64x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_seeed_96x96_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_hjr_oel1m0201_96x96_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_seeed_96x96_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_hjr_oel1m0201_96x96_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_seeed_96x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_hjr_oel1m0201_96x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_seeed_96x96_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_i2c_hjr_oel1m0201_96x96_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_seeed_96x96_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_i2c_hjr_oel1m0201_96x96_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_seeed_96x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_i2c_hjr_oel1m0201_96x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_128x80_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_tk078f288_80x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_128x80_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_tk078f288_80x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_128x80_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_tk078f288_80x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_128x80_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_i2c_tk078f288_80x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_128x80_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_i2c_tk078f288_80x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_128x80_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1107_i2c_tk078f288_80x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_pimoroni_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_seeed_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -749,6 +818,12 @@ void u8g2_Setup_sh1107_i2c_seeed_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotati
 void u8g2_Setup_sh1107_i2c_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_pimoroni_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1107_i2c_seeed_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1108_128x160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1108_128x160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1108_128x160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1108_i2c_128x160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1108_i2c_128x160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sh1108_i2c_128x160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1108_160x160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1108_160x160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sh1108_160x160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -833,6 +908,12 @@ void u8g2_Setup_ssd1316_128x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_m
 void u8g2_Setup_ssd1316_i2c_128x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1316_i2c_128x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1316_i2c_128x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1316_96x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1316_96x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1316_96x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1316_i2c_96x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1316_i2c_96x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1316_i2c_96x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1317_96x96_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1317_96x96_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1317_96x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -883,12 +964,15 @@ void u8g2_Setup_ssd1327_i2c_seeed_96x96_2(u8g2_t *u8g2, const u8g2_cb_t *rotatio
 void u8g2_Setup_ssd1327_i2c_seeed_96x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_ea_w128128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_midas_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1327_zjy_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_ws_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_ea_w128128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_midas_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1327_zjy_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_ws_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_ea_w128128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_midas_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1327_zjy_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_ws_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_i2c_ea_w128128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1327_i2c_midas_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -923,6 +1007,12 @@ void u8g2_Setup_ld7032_i2c_60x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8
 void u8g2_Setup_ld7032_i2c_60x32_alt_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ld7032_i2c_60x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ld7032_i2c_60x32_alt_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ld7032_128x36_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ld7032_128x36_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ld7032_128x36_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ld7032_i2c_128x36_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ld7032_i2c_128x36_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ld7032_i2c_128x36_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_p_256x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_p_256x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_p_256x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -932,6 +1022,24 @@ void u8g2_Setup_st7920_256x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_ms
 void u8g2_Setup_st7920_s_256x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_s_256x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_s_256x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_p_144x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_p_144x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_p_144x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_144x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_144x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_144x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_s_144x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_s_144x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_s_144x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_p_160x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_p_160x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_p_160x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_160x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_160x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_160x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_s_160x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_s_160x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7920_s_160x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_p_192x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_p_192x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7920_p_192x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1022,6 +1130,12 @@ void u8g2_Setup_uc1638_192x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_ms
 void u8g2_Setup_uc1638_i2c_192x96_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1638_i2c_192x96_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1638_i2c_192x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_uc1638_240x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_uc1638_240x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_uc1638_240x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_uc1638_i2c_240x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_uc1638_i2c_240x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_uc1638_i2c_240x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1610_ea_dogxl160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1610_ea_dogxl160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1610_ea_dogxl160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1115,6 +1229,12 @@ void u8g2_Setup_st7565_jlx12864_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_
 void u8g2_Setup_st7565_nhd_c12832_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7565_nhd_c12832_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7565_nhd_c12832_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7539_192x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7539_192x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7539_192x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7539_i2c_192x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7539_i2c_192x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7539_i2c_192x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1601_128x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1601_128x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_uc1601_128x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1133,6 +1253,9 @@ void u8g2_Setup_st7565_ea_dogm132_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x
 void u8g2_Setup_st7567_pi_132x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_pi_132x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_pi_132x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_pi_132x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_pi_132x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_pi_132x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_jlx12864_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_enh_dg128064_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_enh_dg128064i_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1145,6 +1268,30 @@ void u8g2_Setup_st7567_jlx12864_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_
 void u8g2_Setup_st7567_enh_dg128064_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_enh_dg128064i_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_os12864_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_jlx12864_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_enh_dg128064_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_enh_dg128064i_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_os12864_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_jlx12864_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_enh_dg128064_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_enh_dg128064i_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_os12864_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_jlx12864_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_enh_dg128064_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_enh_dg128064i_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_os12864_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_erc13232_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_erc13232_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_erc13232_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_erc13232_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_erc13232_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_erc13232_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_122x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_122x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_122x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_122x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_122x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_122x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_64x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_hem6432_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_64x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1157,6 +1304,12 @@ void u8g2_Setup_st7567_i2c_64x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8
 void u8g2_Setup_st7567_i2c_hem6432_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_i2c_64x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7567_i2c_hem6432_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_lw12832_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_lw12832_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_lw12832_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_lw12832_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_lw12832_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7567_i2c_lw12832_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7571_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7571_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7571_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1172,12 +1325,18 @@ void u8g2_Setup_st7571_i2c_128x96_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x
 void u8g2_Setup_st7586s_s028hn118a_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_s028hn118a_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_s028hn118a_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7586s_jlx384160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7586s_jlx384160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7586s_jlx384160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_erc240160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_ymc240160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_erc240160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_ymc240160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_erc240160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7586s_ymc240160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7586s_jlx320160_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7586s_jlx320160_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st7586s_jlx320160_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7588_jlx12864_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7588_jlx12864_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st7588_jlx12864_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1244,6 +1403,12 @@ void u8g2_Setup_st75256_jlx19296_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8
 void u8g2_Setup_st75256_i2c_jlx19296_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st75256_i2c_jlx19296_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st75256_i2c_jlx19296_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st75256_jlx16080_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st75256_jlx16080_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st75256_jlx16080_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st75256_i2c_jlx16080_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st75256_i2c_jlx16080_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_st75256_i2c_jlx16080_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st75320_jlx320240_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st75320_jlx320240_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_st75320_jlx320240_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1256,6 +1421,9 @@ void u8g2_Setup_nt7534_tg12864r_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_
 void u8g2_Setup_ist3020_erc19264_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ist3020_erc19264_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ist3020_erc19264_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ist3088_320x240_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ist3088_320x240_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ist3088_320x240_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ist7920_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ist7920_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ist7920_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1289,6 +1457,9 @@ void u8g2_Setup_lc7981_240x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_m
 void u8g2_Setup_lc7981_240x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_lc7981_240x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_lc7981_240x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_lc7981_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_lc7981_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_lc7981_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_t6963_240x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_t6963_240x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_t6963_240x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1307,18 +1478,42 @@ void u8g2_Setup_t6963_128x64_alt_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8
 void u8g2_Setup_t6963_160x80_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_t6963_160x80_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_t6963_160x80_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_t6963_128x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_t6963_128x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_t6963_128x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1320_160x32_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1320_160x32_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1320_160x32_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1320_160x132_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1320_160x132_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1320_160x132_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1320_160x80_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1320_160x80_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1320_160x80_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1320_i2c_160x80_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1320_i2c_160x80_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1320_i2c_160x80_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1322_240x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1322_240x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1322_240x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1322_nhd_256x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1322_nhd_256x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1322_nhd_256x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1322_nhd_128x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1322_nhd_128x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1322_nhd_128x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_256x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_256x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_256x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_i2c_256x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_i2c_256x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_i2c_256x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_206x36_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_206x36_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_206x36_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_i2c_206x36_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_i2c_206x36_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_ssd1362_i2c_206x36_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1606_172x72_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1606_172x72_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ssd1606_172x72_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1340,12 +1535,18 @@ void u8g2_Setup_il3820_v2_296x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x
 void u8g2_Setup_sed1330_240x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sed1330_240x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_sed1330_240x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sed1330_256x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sed1330_256x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sed1330_256x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ra8835_nhd_240x128_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ra8835_nhd_240x128_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ra8835_nhd_240x128_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ra8835_320x240_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ra8835_320x240_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_ra8835_320x240_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sed1330_320x200_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sed1330_320x200_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_sed1330_320x200_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_max7219_64x8_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_max7219_64x8_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_max7219_64x8_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1355,6 +1556,9 @@ void u8g2_Setup_max7219_32x8_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg
 void u8g2_Setup_max7219_8x8_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_max7219_8x8_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_max7219_8x8_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_s1d15300_lm6023_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_s1d15300_lm6023_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_s1d15300_lm6023_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_s1d15e06_160100_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_s1d15e06_160100_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_s1d15e06_160100_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1364,6 +1568,18 @@ void u8g2_Setup_s1d15721_240x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_
 void u8g2_Setup_gu800_128x64_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_gu800_128x64_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_gu800_128x64_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gu800_160x16_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gu800_160x16_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gu800_160x16_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1287ai_256x50_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1287ai_256x50_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1287ai_256x50_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1247ai_253x63_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1247ai_253x63_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1247ai_253x63_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1294ai_256x48_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1294ai_256x48_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
+void u8g2_Setup_gp1294ai_256x48_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_a2printer_384x240_1(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_a2printer_384x240_2(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
 void u8g2_Setup_a2printer_384x240_f(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
@@ -1416,7 +1632,7 @@ void u8g2_WriteBufferXBM2(u8g2_t *u8g2, void (*out)(const char *s));
   len		length of the line in pixel, len must not be 0
   dir		0: horizontal line (left to right)
 		1: vertical line (top to bottom)
-  asumption: 
+  assumption: 
     all clipping done
 */
 
@@ -1546,11 +1762,14 @@ void u8g2_SetFontMode(u8g2_t *u8g2, uint8_t is_transparent);
 uint8_t u8g2_IsGlyph(u8g2_t *u8g2, uint16_t requested_encoding);
 int8_t u8g2_GetGlyphWidth(u8g2_t *u8g2, uint16_t requested_encoding);
 u8g2_uint_t u8g2_DrawGlyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding);
+u8g2_uint_t u8g2_DrawGlyphX2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding);
 int8_t u8g2_GetStrX(u8g2_t *u8g2, const char *s);	/* for u8g compatibility */
 
 void u8g2_SetFontDirection(u8g2_t *u8g2, uint8_t dir);
 u8g2_uint_t u8g2_DrawStr(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str);
+u8g2_uint_t u8g2_DrawStrX2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str);
 u8g2_uint_t u8g2_DrawUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str);
+u8g2_uint_t u8g2_DrawUTF8X2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str);
 u8g2_uint_t u8g2_DrawExtendedUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint8_t to_left, u8g2_kerning_t *kerning, const char *str);
 u8g2_uint_t u8g2_DrawExtUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint8_t to_left, const uint16_t *kerning_table, const char *str);
 
@@ -1613,6 +1832,10 @@ void u8g2_SetupBuffer_TGA_LCD(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb);
 /* u8x8_d_bitmap.c */
 void u8g2_SetupBitmap(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb, uint16_t pixel_width, uint16_t pixel_height);
 
+/*==========================================*/
+/* u8x8_d_framebuffer.c */
+void u8g2_SetupLinuxFb(u8g2_t *u8g2, const u8g2_cb_t *u8g2_cb, const char *fb_device);
+
 
 /*==========================================*/
 /* u8x8_d_utf8.c */
@@ -1649,11 +1872,18 @@ extern const uint8_t u8g2_font_squeezed_r7_tr[] U8G2_FONT_SECTION("u8g2_font_squ
 extern const uint8_t u8g2_font_squeezed_r7_tn[] U8G2_FONT_SECTION("u8g2_font_squeezed_r7_tn");
 extern const uint8_t u8g2_font_squeezed_b7_tr[] U8G2_FONT_SECTION("u8g2_font_squeezed_b7_tr");
 extern const uint8_t u8g2_font_squeezed_b7_tn[] U8G2_FONT_SECTION("u8g2_font_squeezed_b7_tn");
+extern const uint8_t u8g2_font_percent_circle_25_hn[] U8G2_FONT_SECTION("u8g2_font_percent_circle_25_hn");
 extern const uint8_t u8g2_font_freedoomr10_tu[] U8G2_FONT_SECTION("u8g2_font_freedoomr10_tu");
 extern const uint8_t u8g2_font_freedoomr10_mu[] U8G2_FONT_SECTION("u8g2_font_freedoomr10_mu");
 extern const uint8_t u8g2_font_freedoomr25_tn[] U8G2_FONT_SECTION("u8g2_font_freedoomr25_tn");
 extern const uint8_t u8g2_font_freedoomr25_mn[] U8G2_FONT_SECTION("u8g2_font_freedoomr25_mn");
 extern const uint8_t u8g2_font_7Segments_26x42_mn[] U8G2_FONT_SECTION("u8g2_font_7Segments_26x42_mn");
+extern const uint8_t u8g2_font_7_Seg_33x19_mn[] U8G2_FONT_SECTION("u8g2_font_7_Seg_33x19_mn");
+extern const uint8_t u8g2_font_7_Seg_41x21_mn[] U8G2_FONT_SECTION("u8g2_font_7_Seg_41x21_mn");
+extern const uint8_t u8g2_font_tiny5_tf[] U8G2_FONT_SECTION("u8g2_font_tiny5_tf");
+extern const uint8_t u8g2_font_tiny5_tr[] U8G2_FONT_SECTION("u8g2_font_tiny5_tr");
+extern const uint8_t u8g2_font_04b_03b_tr[] U8G2_FONT_SECTION("u8g2_font_04b_03b_tr");
+extern const uint8_t u8g2_font_04b_03_tr[] U8G2_FONT_SECTION("u8g2_font_04b_03_tr");
 extern const uint8_t u8g2_font_amstrad_cpc_extended_8f[] U8G2_FONT_SECTION("u8g2_font_amstrad_cpc_extended_8f");
 extern const uint8_t u8g2_font_amstrad_cpc_extended_8r[] U8G2_FONT_SECTION("u8g2_font_amstrad_cpc_extended_8r");
 extern const uint8_t u8g2_font_amstrad_cpc_extended_8n[] U8G2_FONT_SECTION("u8g2_font_amstrad_cpc_extended_8n");
@@ -1825,6 +2055,7 @@ extern const uint8_t u8g2_font_10x20_t_greek[] U8G2_FONT_SECTION("u8g2_font_10x2
 extern const uint8_t u8g2_font_10x20_t_cyrillic[] U8G2_FONT_SECTION("u8g2_font_10x20_t_cyrillic");
 extern const uint8_t u8g2_font_10x20_t_arabic[] U8G2_FONT_SECTION("u8g2_font_10x20_t_arabic");
 extern const uint8_t u8g2_font_siji_t_6x10[] U8G2_FONT_SECTION("u8g2_font_siji_t_6x10");
+extern const uint8_t u8g2_font_waffle_t_all[] U8G2_FONT_SECTION("u8g2_font_waffle_t_all");
 extern const uint8_t u8g2_font_tom_thumb_4x6_t_all[] U8G2_FONT_SECTION("u8g2_font_tom_thumb_4x6_t_all");
 extern const uint8_t u8g2_font_tom_thumb_4x6_tf[] U8G2_FONT_SECTION("u8g2_font_tom_thumb_4x6_tf");
 extern const uint8_t u8g2_font_tom_thumb_4x6_tr[] U8G2_FONT_SECTION("u8g2_font_tom_thumb_4x6_tr");
@@ -1834,6 +2065,18 @@ extern const uint8_t u8g2_font_tom_thumb_4x6_mf[] U8G2_FONT_SECTION("u8g2_font_t
 extern const uint8_t u8g2_font_tom_thumb_4x6_mr[] U8G2_FONT_SECTION("u8g2_font_tom_thumb_4x6_mr");
 extern const uint8_t u8g2_font_tom_thumb_4x6_mn[] U8G2_FONT_SECTION("u8g2_font_tom_thumb_4x6_mn");
 extern const uint8_t u8g2_font_tom_thumb_4x6_me[] U8G2_FONT_SECTION("u8g2_font_tom_thumb_4x6_me");
+extern const uint8_t u8g2_font_mystery_quest_24_tf[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_24_tf");
+extern const uint8_t u8g2_font_mystery_quest_24_tr[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_24_tr");
+extern const uint8_t u8g2_font_mystery_quest_24_tn[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_24_tn");
+extern const uint8_t u8g2_font_mystery_quest_28_tf[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_28_tf");
+extern const uint8_t u8g2_font_mystery_quest_28_tr[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_28_tr");
+extern const uint8_t u8g2_font_mystery_quest_28_tn[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_28_tn");
+extern const uint8_t u8g2_font_mystery_quest_32_tr[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_32_tr");
+extern const uint8_t u8g2_font_mystery_quest_32_tn[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_32_tn");
+extern const uint8_t u8g2_font_mystery_quest_36_tn[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_36_tn");
+extern const uint8_t u8g2_font_mystery_quest_42_tn[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_42_tn");
+extern const uint8_t u8g2_font_mystery_quest_48_tn[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_48_tn");
+extern const uint8_t u8g2_font_mystery_quest_56_tn[] U8G2_FONT_SECTION("u8g2_font_mystery_quest_56_tn");
 extern const uint8_t u8g2_font_t0_11_tf[] U8G2_FONT_SECTION("u8g2_font_t0_11_tf");
 extern const uint8_t u8g2_font_t0_11_tr[] U8G2_FONT_SECTION("u8g2_font_t0_11_tr");
 extern const uint8_t u8g2_font_t0_11_tn[] U8G2_FONT_SECTION("u8g2_font_t0_11_tn");
@@ -2259,6 +2502,8 @@ extern const uint8_t u8g2_font_secretaryhand_tf[] U8G2_FONT_SECTION("u8g2_font_s
 extern const uint8_t u8g2_font_secretaryhand_tr[] U8G2_FONT_SECTION("u8g2_font_secretaryhand_tr");
 extern const uint8_t u8g2_font_secretaryhand_tn[] U8G2_FONT_SECTION("u8g2_font_secretaryhand_tn");
 extern const uint8_t u8g2_font_secretaryhand_t_all[] U8G2_FONT_SECTION("u8g2_font_secretaryhand_t_all");
+extern const uint8_t u8g2_font_garbagecan_tf[] U8G2_FONT_SECTION("u8g2_font_garbagecan_tf");
+extern const uint8_t u8g2_font_garbagecan_tr[] U8G2_FONT_SECTION("u8g2_font_garbagecan_tr");
 extern const uint8_t u8g2_font_beanstalk_mel_tr[] U8G2_FONT_SECTION("u8g2_font_beanstalk_mel_tr");
 extern const uint8_t u8g2_font_beanstalk_mel_tn[] U8G2_FONT_SECTION("u8g2_font_beanstalk_mel_tn");
 extern const uint8_t u8g2_font_cube_mel_tr[] U8G2_FONT_SECTION("u8g2_font_cube_mel_tr");
@@ -2292,6 +2537,8 @@ extern const uint8_t u8g2_font_squirrel_tu[] U8G2_FONT_SECTION("u8g2_font_squirr
 extern const uint8_t u8g2_font_diodesemimono_tr[] U8G2_FONT_SECTION("u8g2_font_diodesemimono_tr");
 extern const uint8_t u8g2_font_questgiver_tr[] U8G2_FONT_SECTION("u8g2_font_questgiver_tr");
 extern const uint8_t u8g2_font_seraphimb1_tr[] U8G2_FONT_SECTION("u8g2_font_seraphimb1_tr");
+extern const uint8_t u8g2_font_resoledbold_tr[] U8G2_FONT_SECTION("u8g2_font_resoledbold_tr");
+extern const uint8_t u8g2_font_resoledmedium_tr[] U8G2_FONT_SECTION("u8g2_font_resoledmedium_tr");
 extern const uint8_t u8g2_font_jinxedwizards_tr[] U8G2_FONT_SECTION("u8g2_font_jinxedwizards_tr");
 extern const uint8_t u8g2_font_lastpriestess_tr[] U8G2_FONT_SECTION("u8g2_font_lastpriestess_tr");
 extern const uint8_t u8g2_font_lastpriestess_tu[] U8G2_FONT_SECTION("u8g2_font_lastpriestess_tu");
@@ -2324,6 +2571,9 @@ extern const uint8_t u8g2_font_tenthinnerguys_tn[] U8G2_FONT_SECTION("u8g2_font_
 extern const uint8_t u8g2_font_tenthinnerguys_tu[] U8G2_FONT_SECTION("u8g2_font_tenthinnerguys_tu");
 extern const uint8_t u8g2_font_tenthinnerguys_t_all[] U8G2_FONT_SECTION("u8g2_font_tenthinnerguys_t_all");
 extern const uint8_t u8g2_font_twelvedings_t_all[] U8G2_FONT_SECTION("u8g2_font_twelvedings_t_all");
+extern const uint8_t u8g2_font_frigidaire_mr[] U8G2_FONT_SECTION("u8g2_font_frigidaire_mr");
+extern const uint8_t u8g2_font_lord_mr[] U8G2_FONT_SECTION("u8g2_font_lord_mr");
+extern const uint8_t u8g2_font_abel_mr[] U8G2_FONT_SECTION("u8g2_font_abel_mr");
 extern const uint8_t u8g2_font_fewture_tf[] U8G2_FONT_SECTION("u8g2_font_fewture_tf");
 extern const uint8_t u8g2_font_fewture_tr[] U8G2_FONT_SECTION("u8g2_font_fewture_tr");
 extern const uint8_t u8g2_font_fewture_tn[] U8G2_FONT_SECTION("u8g2_font_fewture_tn");
@@ -2362,9 +2612,104 @@ extern const uint8_t u8g2_font_fancypixels_tf[] U8G2_FONT_SECTION("u8g2_font_fan
 extern const uint8_t u8g2_font_fancypixels_tr[] U8G2_FONT_SECTION("u8g2_font_fancypixels_tr");
 extern const uint8_t u8g2_font_heavybottom_tr[] U8G2_FONT_SECTION("u8g2_font_heavybottom_tr");
 extern const uint8_t u8g2_font_iconquadpix_m_all[] U8G2_FONT_SECTION("u8g2_font_iconquadpix_m_all");
-extern const uint8_t u8g2_font_lastapprenticebold_tr[] U8G2_FONT_SECTION("u8g2_font_lastapprenticebold_tr");
-extern const uint8_t u8g2_font_lastapprenticethin_tr[] U8G2_FONT_SECTION("u8g2_font_lastapprenticethin_tr");
 extern const uint8_t u8g2_font_tallpix_tr[] U8G2_FONT_SECTION("u8g2_font_tallpix_tr");
+extern const uint8_t u8g2_font_botmaker_te[] U8G2_FONT_SECTION("u8g2_font_botmaker_te");
+extern const uint8_t u8g2_font_efraneextracondensed_te[] U8G2_FONT_SECTION("u8g2_font_efraneextracondensed_te");
+extern const uint8_t u8g2_font_3x3basic_tr[] U8G2_FONT_SECTION("u8g2_font_3x3basic_tr");
+extern const uint8_t u8g2_font_tiny_gk_tr[] U8G2_FONT_SECTION("u8g2_font_tiny_gk_tr");
+extern const uint8_t u8g2_font_threepix_tr[] U8G2_FONT_SECTION("u8g2_font_threepix_tr");
+extern const uint8_t u8g2_font_eventhrees_tr[] U8G2_FONT_SECTION("u8g2_font_eventhrees_tr");
+extern const uint8_t u8g2_font_fourmat_tf[] U8G2_FONT_SECTION("u8g2_font_fourmat_tf");
+extern const uint8_t u8g2_font_fourmat_tr[] U8G2_FONT_SECTION("u8g2_font_fourmat_tr");
+extern const uint8_t u8g2_font_fourmat_te[] U8G2_FONT_SECTION("u8g2_font_fourmat_te");
+extern const uint8_t u8g2_font_tiny_simon_tr[] U8G2_FONT_SECTION("u8g2_font_tiny_simon_tr");
+extern const uint8_t u8g2_font_tiny_simon_mr[] U8G2_FONT_SECTION("u8g2_font_tiny_simon_mr");
+extern const uint8_t u8g2_font_smolfont_tf[] U8G2_FONT_SECTION("u8g2_font_smolfont_tf");
+extern const uint8_t u8g2_font_smolfont_tr[] U8G2_FONT_SECTION("u8g2_font_smolfont_tr");
+extern const uint8_t u8g2_font_smolfont_te[] U8G2_FONT_SECTION("u8g2_font_smolfont_te");
+extern const uint8_t u8g2_font_tinyunicode_tf[] U8G2_FONT_SECTION("u8g2_font_tinyunicode_tf");
+extern const uint8_t u8g2_font_tinyunicode_tr[] U8G2_FONT_SECTION("u8g2_font_tinyunicode_tr");
+extern const uint8_t u8g2_font_tinyunicode_te[] U8G2_FONT_SECTION("u8g2_font_tinyunicode_te");
+extern const uint8_t u8g2_font_tinypixie2_tr[] U8G2_FONT_SECTION("u8g2_font_tinypixie2_tr");
+extern const uint8_t u8g2_font_standardized3x5_tr[] U8G2_FONT_SECTION("u8g2_font_standardized3x5_tr");
+extern const uint8_t u8g2_font_fivepx_tr[] U8G2_FONT_SECTION("u8g2_font_fivepx_tr");
+extern const uint8_t u8g2_font_3x5im_tr[] U8G2_FONT_SECTION("u8g2_font_3x5im_tr");
+extern const uint8_t u8g2_font_3x5im_te[] U8G2_FONT_SECTION("u8g2_font_3x5im_te");
+extern const uint8_t u8g2_font_3x5im_mr[] U8G2_FONT_SECTION("u8g2_font_3x5im_mr");
+extern const uint8_t u8g2_font_wedge_tr[] U8G2_FONT_SECTION("u8g2_font_wedge_tr");
+extern const uint8_t u8g2_font_kibibyte_tr[] U8G2_FONT_SECTION("u8g2_font_kibibyte_tr");
+extern const uint8_t u8g2_font_kibibyte_te[] U8G2_FONT_SECTION("u8g2_font_kibibyte_te");
+extern const uint8_t u8g2_font_tinyface_tr[] U8G2_FONT_SECTION("u8g2_font_tinyface_tr");
+extern const uint8_t u8g2_font_tinyface_te[] U8G2_FONT_SECTION("u8g2_font_tinyface_te");
+extern const uint8_t u8g2_font_smallsimple_tr[] U8G2_FONT_SECTION("u8g2_font_smallsimple_tr");
+extern const uint8_t u8g2_font_smallsimple_te[] U8G2_FONT_SECTION("u8g2_font_smallsimple_te");
+extern const uint8_t u8g2_font_simple1_tf[] U8G2_FONT_SECTION("u8g2_font_simple1_tf");
+extern const uint8_t u8g2_font_simple1_tr[] U8G2_FONT_SECTION("u8g2_font_simple1_tr");
+extern const uint8_t u8g2_font_simple1_te[] U8G2_FONT_SECTION("u8g2_font_simple1_te");
+extern const uint8_t u8g2_font_likeminecraft_te[] U8G2_FONT_SECTION("u8g2_font_likeminecraft_te");
+extern const uint8_t u8g2_font_medsans_tr[] U8G2_FONT_SECTION("u8g2_font_medsans_tr");
+extern const uint8_t u8g2_font_heisans_tr[] U8G2_FONT_SECTION("u8g2_font_heisans_tr");
+extern const uint8_t u8g2_font_originalsans_tr[] U8G2_FONT_SECTION("u8g2_font_originalsans_tr");
+extern const uint8_t u8g2_font_minicute_tr[] U8G2_FONT_SECTION("u8g2_font_minicute_tr");
+extern const uint8_t u8g2_font_minicute_te[] U8G2_FONT_SECTION("u8g2_font_minicute_te");
+extern const uint8_t u8g2_font_scrum_tf[] U8G2_FONT_SECTION("u8g2_font_scrum_tf");
+extern const uint8_t u8g2_font_scrum_tr[] U8G2_FONT_SECTION("u8g2_font_scrum_tr");
+extern const uint8_t u8g2_font_scrum_te[] U8G2_FONT_SECTION("u8g2_font_scrum_te");
+extern const uint8_t u8g2_font_stylishcharm_tr[] U8G2_FONT_SECTION("u8g2_font_stylishcharm_tr");
+extern const uint8_t u8g2_font_stylishcharm_te[] U8G2_FONT_SECTION("u8g2_font_stylishcharm_te");
+extern const uint8_t u8g2_font_sisterserif_tr[] U8G2_FONT_SECTION("u8g2_font_sisterserif_tr");
+extern const uint8_t u8g2_font_princess_tr[] U8G2_FONT_SECTION("u8g2_font_princess_tr");
+extern const uint8_t u8g2_font_princess_te[] U8G2_FONT_SECTION("u8g2_font_princess_te");
+extern const uint8_t u8g2_font_dystopia_tr[] U8G2_FONT_SECTION("u8g2_font_dystopia_tr");
+extern const uint8_t u8g2_font_dystopia_te[] U8G2_FONT_SECTION("u8g2_font_dystopia_te");
+extern const uint8_t u8g2_font_lastapprenticethin_tr[] U8G2_FONT_SECTION("u8g2_font_lastapprenticethin_tr");
+extern const uint8_t u8g2_font_lastapprenticethin_te[] U8G2_FONT_SECTION("u8g2_font_lastapprenticethin_te");
+extern const uint8_t u8g2_font_lastapprenticebold_tr[] U8G2_FONT_SECTION("u8g2_font_lastapprenticebold_tr");
+extern const uint8_t u8g2_font_lastapprenticebold_te[] U8G2_FONT_SECTION("u8g2_font_lastapprenticebold_te");
+extern const uint8_t u8g2_font_bpixel_tr[] U8G2_FONT_SECTION("u8g2_font_bpixel_tr");
+extern const uint8_t u8g2_font_bpixel_te[] U8G2_FONT_SECTION("u8g2_font_bpixel_te");
+extern const uint8_t u8g2_font_bpixeldouble_tr[] U8G2_FONT_SECTION("u8g2_font_bpixeldouble_tr");
+extern const uint8_t u8g2_font_mildras_tr[] U8G2_FONT_SECTION("u8g2_font_mildras_tr");
+extern const uint8_t u8g2_font_mildras_te[] U8G2_FONT_SECTION("u8g2_font_mildras_te");
+extern const uint8_t u8g2_font_minuteconsole_mr[] U8G2_FONT_SECTION("u8g2_font_minuteconsole_mr");
+extern const uint8_t u8g2_font_minuteconsole_tr[] U8G2_FONT_SECTION("u8g2_font_minuteconsole_tr");
+extern const uint8_t u8g2_font_busdisplay11x5_tr[] U8G2_FONT_SECTION("u8g2_font_busdisplay11x5_tr");
+extern const uint8_t u8g2_font_busdisplay11x5_te[] U8G2_FONT_SECTION("u8g2_font_busdisplay11x5_te");
+extern const uint8_t u8g2_font_busdisplay8x5_tr[] U8G2_FONT_SECTION("u8g2_font_busdisplay8x5_tr");
+extern const uint8_t u8g2_font_sticker100complete_tr[] U8G2_FONT_SECTION("u8g2_font_sticker100complete_tr");
+extern const uint8_t u8g2_font_sticker100complete_te[] U8G2_FONT_SECTION("u8g2_font_sticker100complete_te");
+extern const uint8_t u8g2_font_doomalpha04_tr[] U8G2_FONT_SECTION("u8g2_font_doomalpha04_tr");
+extern const uint8_t u8g2_font_doomalpha04_te[] U8G2_FONT_SECTION("u8g2_font_doomalpha04_te");
+extern const uint8_t u8g2_font_greenbloodserif2_tr[] U8G2_FONT_SECTION("u8g2_font_greenbloodserif2_tr");
+extern const uint8_t u8g2_font_eckpixel_tr[] U8G2_FONT_SECTION("u8g2_font_eckpixel_tr");
+extern const uint8_t u8g2_font_elispe_tr[] U8G2_FONT_SECTION("u8g2_font_elispe_tr");
+extern const uint8_t u8g2_font_neuecraft_tr[] U8G2_FONT_SECTION("u8g2_font_neuecraft_tr");
+extern const uint8_t u8g2_font_neuecraft_te[] U8G2_FONT_SECTION("u8g2_font_neuecraft_te");
+extern const uint8_t u8g2_font_8bitclassic_tf[] U8G2_FONT_SECTION("u8g2_font_8bitclassic_tf");
+extern const uint8_t u8g2_font_8bitclassic_tr[] U8G2_FONT_SECTION("u8g2_font_8bitclassic_tr");
+extern const uint8_t u8g2_font_8bitclassic_te[] U8G2_FONT_SECTION("u8g2_font_8bitclassic_te");
+extern const uint8_t u8g2_font_littlemissloudonbold_tr[] U8G2_FONT_SECTION("u8g2_font_littlemissloudonbold_tr");
+extern const uint8_t u8g2_font_littlemissloudonbold_te[] U8G2_FONT_SECTION("u8g2_font_littlemissloudonbold_te");
+extern const uint8_t u8g2_font_commodore64_tr[] U8G2_FONT_SECTION("u8g2_font_commodore64_tr");
+extern const uint8_t u8g2_font_new3x9pixelfont_tf[] U8G2_FONT_SECTION("u8g2_font_new3x9pixelfont_tf");
+extern const uint8_t u8g2_font_new3x9pixelfont_tr[] U8G2_FONT_SECTION("u8g2_font_new3x9pixelfont_tr");
+extern const uint8_t u8g2_font_new3x9pixelfont_te[] U8G2_FONT_SECTION("u8g2_font_new3x9pixelfont_te");
+extern const uint8_t u8g2_font_sonicmania_tr[] U8G2_FONT_SECTION("u8g2_font_sonicmania_tr");
+extern const uint8_t u8g2_font_sonicmania_te[] U8G2_FONT_SECTION("u8g2_font_sonicmania_te");
+extern const uint8_t u8g2_font_bytesize_tf[] U8G2_FONT_SECTION("u8g2_font_bytesize_tf");
+extern const uint8_t u8g2_font_bytesize_tr[] U8G2_FONT_SECTION("u8g2_font_bytesize_tr");
+extern const uint8_t u8g2_font_bytesize_te[] U8G2_FONT_SECTION("u8g2_font_bytesize_te");
+extern const uint8_t u8g2_font_pixzillav1_tf[] U8G2_FONT_SECTION("u8g2_font_pixzillav1_tf");
+extern const uint8_t u8g2_font_pixzillav1_tr[] U8G2_FONT_SECTION("u8g2_font_pixzillav1_tr");
+extern const uint8_t u8g2_font_pixzillav1_te[] U8G2_FONT_SECTION("u8g2_font_pixzillav1_te");
+extern const uint8_t u8g2_font_ciircle13_tr[] U8G2_FONT_SECTION("u8g2_font_ciircle13_tr");
+extern const uint8_t u8g2_font_pxclassic_tf[] U8G2_FONT_SECTION("u8g2_font_pxclassic_tf");
+extern const uint8_t u8g2_font_pxclassic_tr[] U8G2_FONT_SECTION("u8g2_font_pxclassic_tr");
+extern const uint8_t u8g2_font_pxclassic_te[] U8G2_FONT_SECTION("u8g2_font_pxclassic_te");
+extern const uint8_t u8g2_font_moosenooks_tr[] U8G2_FONT_SECTION("u8g2_font_moosenooks_tr");
+extern const uint8_t u8g2_font_tallpixelextended_tf[] U8G2_FONT_SECTION("u8g2_font_tallpixelextended_tf");
+extern const uint8_t u8g2_font_tallpixelextended_tr[] U8G2_FONT_SECTION("u8g2_font_tallpixelextended_tr");
+extern const uint8_t u8g2_font_tallpixelextended_te[] U8G2_FONT_SECTION("u8g2_font_tallpixelextended_te");
 extern const uint8_t u8g2_font_BBSesque_tf[] U8G2_FONT_SECTION("u8g2_font_BBSesque_tf");
 extern const uint8_t u8g2_font_BBSesque_tr[] U8G2_FONT_SECTION("u8g2_font_BBSesque_tr");
 extern const uint8_t u8g2_font_BBSesque_te[] U8G2_FONT_SECTION("u8g2_font_BBSesque_te");
@@ -2382,6 +2727,8 @@ extern const uint8_t u8g2_font_ImpactBits_tr[] U8G2_FONT_SECTION("u8g2_font_Impa
 extern const uint8_t u8g2_font_IPAandRUSLCD_tf[] U8G2_FONT_SECTION("u8g2_font_IPAandRUSLCD_tf");
 extern const uint8_t u8g2_font_IPAandRUSLCD_tr[] U8G2_FONT_SECTION("u8g2_font_IPAandRUSLCD_tr");
 extern const uint8_t u8g2_font_IPAandRUSLCD_te[] U8G2_FONT_SECTION("u8g2_font_IPAandRUSLCD_te");
+extern const uint8_t u8g2_font_PixelTheatre_tr[] U8G2_FONT_SECTION("u8g2_font_PixelTheatre_tr");
+extern const uint8_t u8g2_font_PixelTheatre_te[] U8G2_FONT_SECTION("u8g2_font_PixelTheatre_te");
 extern const uint8_t u8g2_font_HelvetiPixel_tr[] U8G2_FONT_SECTION("u8g2_font_HelvetiPixel_tr");
 extern const uint8_t u8g2_font_TimesNewPixel_tr[] U8G2_FONT_SECTION("u8g2_font_TimesNewPixel_tr");
 extern const uint8_t u8g2_font_BitTypeWriter_tr[] U8G2_FONT_SECTION("u8g2_font_BitTypeWriter_tr");
@@ -2393,6 +2740,56 @@ extern const uint8_t u8g2_font_Wizzard_tr[] U8G2_FONT_SECTION("u8g2_font_Wizzard
 extern const uint8_t u8g2_font_HelvetiPixelOutline_tr[] U8G2_FONT_SECTION("u8g2_font_HelvetiPixelOutline_tr");
 extern const uint8_t u8g2_font_HelvetiPixelOutline_te[] U8G2_FONT_SECTION("u8g2_font_HelvetiPixelOutline_te");
 extern const uint8_t u8g2_font_Untitled16PixelSansSerifBitmap_tr[] U8G2_FONT_SECTION("u8g2_font_Untitled16PixelSansSerifBitmap_tr");
+extern const uint8_t u8g2_font_UnnamedDOSFontIV_tr[] U8G2_FONT_SECTION("u8g2_font_UnnamedDOSFontIV_tr");
+extern const uint8_t u8g2_font_Terminal_tr[] U8G2_FONT_SECTION("u8g2_font_Terminal_tr");
+extern const uint8_t u8g2_font_Terminal_te[] U8G2_FONT_SECTION("u8g2_font_Terminal_te");
+extern const uint8_t u8g2_font_NokiaLargeBold_tf[] U8G2_FONT_SECTION("u8g2_font_NokiaLargeBold_tf");
+extern const uint8_t u8g2_font_NokiaLargeBold_tr[] U8G2_FONT_SECTION("u8g2_font_NokiaLargeBold_tr");
+extern const uint8_t u8g2_font_NokiaLargeBold_te[] U8G2_FONT_SECTION("u8g2_font_NokiaLargeBold_te");
+extern const uint8_t u8g2_font_NokiaSmallBold_tf[] U8G2_FONT_SECTION("u8g2_font_NokiaSmallBold_tf");
+extern const uint8_t u8g2_font_NokiaSmallBold_tr[] U8G2_FONT_SECTION("u8g2_font_NokiaSmallBold_tr");
+extern const uint8_t u8g2_font_NokiaSmallBold_te[] U8G2_FONT_SECTION("u8g2_font_NokiaSmallBold_te");
+extern const uint8_t u8g2_font_NokiaSmallPlain_tf[] U8G2_FONT_SECTION("u8g2_font_NokiaSmallPlain_tf");
+extern const uint8_t u8g2_font_NokiaSmallPlain_tr[] U8G2_FONT_SECTION("u8g2_font_NokiaSmallPlain_tr");
+extern const uint8_t u8g2_font_NokiaSmallPlain_te[] U8G2_FONT_SECTION("u8g2_font_NokiaSmallPlain_te");
+extern const uint8_t u8g2_font_12x6LED_tf[] U8G2_FONT_SECTION("u8g2_font_12x6LED_tf");
+extern const uint8_t u8g2_font_12x6LED_tr[] U8G2_FONT_SECTION("u8g2_font_12x6LED_tr");
+extern const uint8_t u8g2_font_12x6LED_mn[] U8G2_FONT_SECTION("u8g2_font_12x6LED_mn");
+extern const uint8_t u8g2_font_9x6LED_tf[] U8G2_FONT_SECTION("u8g2_font_9x6LED_tf");
+extern const uint8_t u8g2_font_9x6LED_tr[] U8G2_FONT_SECTION("u8g2_font_9x6LED_tr");
+extern const uint8_t u8g2_font_9x6LED_mn[] U8G2_FONT_SECTION("u8g2_font_9x6LED_mn");
+extern const uint8_t u8g2_font_calblk36_tr[] U8G2_FONT_SECTION("u8g2_font_calblk36_tr");
+extern const uint8_t u8g2_font_callite24_tr[] U8G2_FONT_SECTION("u8g2_font_callite24_tr");
+extern const uint8_t u8g2_font_spleen5x8_mf[] U8G2_FONT_SECTION("u8g2_font_spleen5x8_mf");
+extern const uint8_t u8g2_font_spleen5x8_mr[] U8G2_FONT_SECTION("u8g2_font_spleen5x8_mr");
+extern const uint8_t u8g2_font_spleen5x8_mn[] U8G2_FONT_SECTION("u8g2_font_spleen5x8_mn");
+extern const uint8_t u8g2_font_spleen5x8_mu[] U8G2_FONT_SECTION("u8g2_font_spleen5x8_mu");
+extern const uint8_t u8g2_font_spleen5x8_me[] U8G2_FONT_SECTION("u8g2_font_spleen5x8_me");
+extern const uint8_t u8g2_font_spleen6x12_mf[] U8G2_FONT_SECTION("u8g2_font_spleen6x12_mf");
+extern const uint8_t u8g2_font_spleen6x12_mr[] U8G2_FONT_SECTION("u8g2_font_spleen6x12_mr");
+extern const uint8_t u8g2_font_spleen6x12_mn[] U8G2_FONT_SECTION("u8g2_font_spleen6x12_mn");
+extern const uint8_t u8g2_font_spleen6x12_mu[] U8G2_FONT_SECTION("u8g2_font_spleen6x12_mu");
+extern const uint8_t u8g2_font_spleen6x12_me[] U8G2_FONT_SECTION("u8g2_font_spleen6x12_me");
+extern const uint8_t u8g2_font_spleen8x16_mf[] U8G2_FONT_SECTION("u8g2_font_spleen8x16_mf");
+extern const uint8_t u8g2_font_spleen8x16_mr[] U8G2_FONT_SECTION("u8g2_font_spleen8x16_mr");
+extern const uint8_t u8g2_font_spleen8x16_mn[] U8G2_FONT_SECTION("u8g2_font_spleen8x16_mn");
+extern const uint8_t u8g2_font_spleen8x16_mu[] U8G2_FONT_SECTION("u8g2_font_spleen8x16_mu");
+extern const uint8_t u8g2_font_spleen8x16_me[] U8G2_FONT_SECTION("u8g2_font_spleen8x16_me");
+extern const uint8_t u8g2_font_spleen12x24_mf[] U8G2_FONT_SECTION("u8g2_font_spleen12x24_mf");
+extern const uint8_t u8g2_font_spleen12x24_mr[] U8G2_FONT_SECTION("u8g2_font_spleen12x24_mr");
+extern const uint8_t u8g2_font_spleen12x24_mn[] U8G2_FONT_SECTION("u8g2_font_spleen12x24_mn");
+extern const uint8_t u8g2_font_spleen12x24_mu[] U8G2_FONT_SECTION("u8g2_font_spleen12x24_mu");
+extern const uint8_t u8g2_font_spleen12x24_me[] U8G2_FONT_SECTION("u8g2_font_spleen12x24_me");
+extern const uint8_t u8g2_font_spleen16x32_mf[] U8G2_FONT_SECTION("u8g2_font_spleen16x32_mf");
+extern const uint8_t u8g2_font_spleen16x32_mr[] U8G2_FONT_SECTION("u8g2_font_spleen16x32_mr");
+extern const uint8_t u8g2_font_spleen16x32_mn[] U8G2_FONT_SECTION("u8g2_font_spleen16x32_mn");
+extern const uint8_t u8g2_font_spleen16x32_mu[] U8G2_FONT_SECTION("u8g2_font_spleen16x32_mu");
+extern const uint8_t u8g2_font_spleen16x32_me[] U8G2_FONT_SECTION("u8g2_font_spleen16x32_me");
+extern const uint8_t u8g2_font_spleen32x64_mf[] U8G2_FONT_SECTION("u8g2_font_spleen32x64_mf");
+extern const uint8_t u8g2_font_spleen32x64_mr[] U8G2_FONT_SECTION("u8g2_font_spleen32x64_mr");
+extern const uint8_t u8g2_font_spleen32x64_mn[] U8G2_FONT_SECTION("u8g2_font_spleen32x64_mn");
+extern const uint8_t u8g2_font_spleen32x64_mu[] U8G2_FONT_SECTION("u8g2_font_spleen32x64_mu");
+extern const uint8_t u8g2_font_spleen32x64_me[] U8G2_FONT_SECTION("u8g2_font_spleen32x64_me");
 extern const uint8_t u8g2_font_nokiafc22_tf[] U8G2_FONT_SECTION("u8g2_font_nokiafc22_tf");
 extern const uint8_t u8g2_font_nokiafc22_tr[] U8G2_FONT_SECTION("u8g2_font_nokiafc22_tr");
 extern const uint8_t u8g2_font_nokiafc22_tn[] U8G2_FONT_SECTION("u8g2_font_nokiafc22_tn");

Разница между файлами не показана из-за своего большого размера
+ 198 - 162
components/u8g2/u8g2_d_memory.c


Разница между файлами не показана из-за своего большого размера
+ 771 - 43
components/u8g2/u8g2_d_setup.c


+ 210 - 2
components/u8g2/u8g2_font.c

@@ -477,11 +477,104 @@ void u8g2_font_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground)
   }
   lx += cnt;
   
+  decode->x = lx;
+  decode->y = ly;  
+}
+
+
+void u8g2_font_2x_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground)
+{
+  uint8_t cnt;	/* total number of remaining pixels, which have to be drawn */
+  uint8_t rem; 	/* remaining pixel to the right edge of the glyph */
+  uint8_t current;	/* number of pixels, which need to be drawn for the draw procedure */
+    /* current is either equal to cnt or equal to rem */
+  
+  /* local coordinates of the glyph */
+  uint8_t lx,ly;
+  
+  /* target position on the screen */
+  u8g2_uint_t x, y;
+  
+  u8g2_font_decode_t *decode = &(u8g2->font_decode);
+  
+  cnt = len;
+  
+  /* get the local position */
+  lx = decode->x;
+  ly = decode->y;
+  
+  for(;;)
+  {
+    /* calculate the number of pixel to the right edge of the glyph */
+    rem = decode->glyph_width;
+    rem -= lx;
+    
+    /* calculate how many pixel to draw. This is either to the right edge */
+    /* or lesser, if not enough pixel are left */
+    current = rem;
+    if ( cnt < rem )
+      current = cnt;
+    
+    
+    /* now draw the line, but apply the rotation around the glyph target position */
+    //u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
+
+    /* get target position */
+    x = decode->target_x;
+    y = decode->target_y;
+
+    x += lx*2;
+    y += ly*2;
+    
+    /* draw foreground and background (if required) */
+    if ( is_foreground )
+    {
+      u8g2->draw_color = decode->fg_color;			/* draw_color will be restored later */
+      u8g2_DrawHVLine(u8g2, 
+	x, 
+	y, 
+	current*2, 
+	0
+      );
+      u8g2_DrawHVLine(u8g2, 
+	x, 
+	y+1, 
+	current*2, 
+	0
+      );
+    }
+    else if ( decode->is_transparent == 0 )    
+    {
+      u8g2->draw_color = decode->bg_color;			/* draw_color will be restored later */
+      u8g2_DrawHVLine(u8g2, 
+	x, 
+	y, 
+	current*2, 
+	0
+      );   
+      u8g2_DrawHVLine(u8g2, 
+	x, 
+	y+1, 
+	current*2, 
+	0
+      );   
+    }
+    
+    /* check, whether the end of the run length code has been reached */
+    if ( cnt < rem )
+      break;
+    cnt -= rem;
+    lx = 0;
+    ly++;
+  }
+  lx += cnt;
+  
   decode->x = lx;
   decode->y = ly;
   
 }
 
+
 static void u8g2_font_setup_decode(u8g2_t *u8g2, const uint8_t *glyph_data)
 {
   u8g2_font_decode_t *decode = &(u8g2->font_decode);
@@ -616,6 +709,68 @@ int8_t u8g2_font_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data)
   return d;
 }
 
+
+int8_t u8g2_font_2x_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data)
+{
+  uint8_t a, b;
+  int8_t x, y;
+  int8_t d;
+  int8_t h;
+  u8g2_font_decode_t *decode = &(u8g2->font_decode);
+    
+  u8g2_font_setup_decode(u8g2, glyph_data);     /* set values in u8g2->font_decode data structure */
+  h = u8g2->font_decode.glyph_height;
+  
+  x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x);
+  y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
+  d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
+  
+  if ( decode->glyph_width > 0 )
+  {
+    decode->target_x += x;
+    decode->target_y -= 2*h+y;
+
+#ifdef U8G2_WITH_INTERSECTION
+    {
+      u8g2_uint_t x0, x1, y0, y1;
+      x0 = decode->target_x;
+      y0 = decode->target_y;
+      x1 = x0;
+      y1 = y0;
+      
+      x1 += 2*decode->glyph_width;
+      y1 += 2*h;      
+      
+      if ( u8g2_IsIntersection(u8g2, x0, y0, x1, y1) == 0 ) 
+	return 2*d;
+    }
+#endif /* U8G2_WITH_INTERSECTION */
+   
+    /* reset local x/y position */
+    decode->x = 0;
+    decode->y = 0;
+    
+    /* decode glyph */
+    for(;;)
+    {
+      a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
+      b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
+      do
+      {
+	u8g2_font_2x_decode_len(u8g2, a, 0);
+	u8g2_font_2x_decode_len(u8g2, b, 1);
+      } while( u8g2_font_decode_get_unsigned_bits(decode, 1) != 0 );
+
+      if ( decode->y >= h )
+	break;
+    }
+    
+    /* restore the u8g2 draw color, because this is modified by the decode algo */
+    u8g2->draw_color = decode->fg_color;
+  }
+  return d*2;
+}
+
 /*
   Description:
     Find the starting point of the glyph data.
@@ -726,6 +881,19 @@ static u8g2_uint_t u8g2_font_draw_glyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t
   return dx;
 }
 
+static u8g2_uint_t u8g2_font_2x_draw_glyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
+{
+  u8g2_uint_t dx = 0;
+  u8g2->font_decode.target_x = x;
+  u8g2->font_decode.target_y = y;
+  const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
+  if ( glyph_data != NULL )
+  {
+    dx = u8g2_font_2x_decode_glyph(u8g2, glyph_data);
+  }
+  return dx;
+}
+
 
 
 uint8_t u8g2_IsGlyph(u8g2_t *u8g2, uint16_t requested_encoding)
@@ -789,6 +957,12 @@ u8g2_uint_t u8g2_DrawGlyph(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t
   return u8g2_font_draw_glyph(u8g2, x, y, encoding);
 }
 
+u8g2_uint_t u8g2_DrawGlyphX2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint16_t encoding)
+{
+  y += 2*u8g2->font_calc_vref(u8g2);
+  return u8g2_font_2x_draw_glyph(u8g2, x, y, encoding);
+}
+
 static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str) U8G2_NOINLINE;
 static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
 {
@@ -839,12 +1013,41 @@ static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y,
   return sum;
 }
 
+static u8g2_uint_t u8g2_draw_string_2x(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str) U8G2_NOINLINE;
+static u8g2_uint_t u8g2_draw_string_2x(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
+{
+  uint16_t e;
+  u8g2_uint_t delta, sum;
+  u8x8_utf8_init(u8g2_GetU8x8(u8g2));
+  sum = 0;
+  for(;;)
+  {
+    e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
+    if ( e == 0x0ffff )
+      break;
+    str++;
+    if ( e != 0x0fffe )
+    {
+      delta = u8g2_DrawGlyphX2(u8g2, x, y, e);
+      x += delta;
+      sum += delta;    
+    }
+  }
+  return sum;
+}
+
 u8g2_uint_t u8g2_DrawStr(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
 {
   u8g2->u8x8.next_cb = u8x8_ascii_next;
   return u8g2_draw_string(u8g2, x, y, str);
 }
 
+u8g2_uint_t u8g2_DrawStrX2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
+{
+  u8g2->u8x8.next_cb = u8x8_ascii_next;
+  return u8g2_draw_string_2x(u8g2, x, y, str);
+}
+
 /*
 source: https://en.wikipedia.org/wiki/UTF-8
 Bits	from 		to			bytes	Byte 1 		Byte 2 		Byte 3 		Byte 4 		Byte 5 		Byte 6
@@ -861,6 +1064,11 @@ u8g2_uint_t u8g2_DrawUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char
   return u8g2_draw_string(u8g2, x, y, str);
 }
 
+u8g2_uint_t u8g2_DrawUTF8X2(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
+{
+  u8g2->u8x8.next_cb = u8x8_utf8_next;
+  return u8g2_draw_string_2x(u8g2, x, y, str);
+}
 
 
 u8g2_uint_t u8g2_DrawExtendedUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, uint8_t to_left, u8g2_kerning_t *kerning, const char *str)
@@ -1185,9 +1393,9 @@ static void u8g2_GetGlyphHorizontalProperties(u8g2_t *u8g2, uint16_t requested_e
 /* u8g compatible GetStrX function */
 int8_t u8g2_GetStrX(u8g2_t *u8g2, const char *s)
 {
-  uint8_t w = 0;
+  uint8_t w;
+  int8_t dx;
   int8_t ox = 0;
-  int8_t dx = 0;
   u8g2_GetGlyphHorizontalProperties(u8g2, *s, &w, &ox, &dx);
   return ox;
 }

Разница между файлами не показана из-за своего большого размера
+ 646 - 422
components/u8g2/u8g2_fonts.c


+ 1 - 1
components/u8g2/u8g2_line.c

@@ -81,7 +81,7 @@ void u8g2_DrawLine(u8g2_t *u8g2, u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2,
       u8g2_DrawPixel(u8g2, x, y); 
     else 
       u8g2_DrawPixel(u8g2, y, x); 
-    err -= (uint8_t)dy;
+    err -= (u8g2_uint_t)dy;
     if ( err < 0 ) 
     {
       y += (u8g2_uint_t)ystep;

+ 5 - 5
components/u8g2/u8g2_polygon.c

@@ -216,17 +216,17 @@ static void pg_hline(pg_struct *pg, u8g2_t *u8g2)
   
   if ( y < 0 )
     return;
-  if ( y >= u8g2_GetDisplayHeight(u8g2) )  // does not work for 256x64 display???
+  if ( y >= (pg_word_t)u8g2_GetDisplayHeight(u8g2) )  // does not work for 256x64 display???
     return;
   if ( x1 < x2 )
   {
     if ( x2 < 0 )
       return;
-    if ( x1 >= u8g2_GetDisplayWidth(u8g2) )
+    if ( x1 >= (pg_word_t)u8g2_GetDisplayWidth(u8g2) )
       return;
     if ( x1 < 0 )
       x1 = 0;
-    if ( x2 >= u8g2_GetDisplayWidth(u8g2) )
+    if ( x2 >= (pg_word_t)u8g2_GetDisplayWidth(u8g2) )
       x2 = u8g2_GetDisplayWidth(u8g2);
     u8g2_DrawHLine(u8g2, x1, y, x2 - x1);
   }
@@ -234,11 +234,11 @@ static void pg_hline(pg_struct *pg, u8g2_t *u8g2)
   {
     if ( x1 < 0 )
       return;
-    if ( x2 >= u8g2_GetDisplayWidth(u8g2) )
+    if ( x2 >= (pg_word_t)u8g2_GetDisplayWidth(u8g2) )
       return;
     if ( x2 < 0 )
       x1 = 0;
-    if ( x1 >= u8g2_GetDisplayWidth(u8g2) )
+    if ( x1 >= (pg_word_t)u8g2_GetDisplayWidth(u8g2) )
       x1 = u8g2_GetDisplayWidth(u8g2);
     u8g2_DrawHLine(u8g2, x2, y, x1 - x2);
   }

+ 2 - 1
components/u8g2/u8g2_setup.c

@@ -85,6 +85,7 @@ void u8g2_SetupBuffer(u8g2_t *u8g2, uint8_t *buf, uint8_t tile_buf_height, u8g2_
   u8g2->font_decode.is_transparent = 0; /* issue 443 */
   u8g2->bitmap_transparency = 0;
   
+  u8g2->font_height_mode = 0; /* issue 2046 */
   u8g2->draw_color = 1;
   u8g2->is_auto_page_clear = 1;
   
@@ -465,4 +466,4 @@ void u8g2_Setup_null(u8g2_t *u8g2, const u8g2_cb_t *rotation, u8x8_msg_cb byte_c
 
 
   
-  
+  

+ 60 - 20
components/u8g2/u8x8.h

@@ -4,7 +4,7 @@
   
   Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
 
-  Copyright (c) 2016, olikraus@gmail.com
+  Copyright (c) 2016, olikraus@gmail.  
   All rights reserved.
 
   Redistribution and use in source and binary forms, with or without modification, 
@@ -34,11 +34,11 @@
   
   
   U8glib has several layers. Each layer is implemented with a callback function. 
-  This callback function handels the messages for the layer.
+  This callback function handles the messages for the layer.
 
   The topmost level is the display layer. It includes the following messages:
   
-    U8X8_MSG_DISPLAY_SETUP_MEMORY			no communicaation with the display, setup memory ony
+    U8X8_MSG_DISPLAY_SETUP_MEMORY			no communication with the display, setup memory only
     U8X8_MSG_DISPLAY_INIT
     U8X8_MSG_DISPLAY_SET_FLIP_MODE
     U8X8_MSG_DISPLAY_SET_POWER_SAVE
@@ -94,7 +94,7 @@
 #endif
 
 /* Define this for an additional user pointer inside the u8x8 data struct */
-//#define U8X8_WITH_USER_PTR
+#define U8X8_WITH_USER_PTR
 
 
 /* Undefine this to remove u8x8_SetFlipMode function */
@@ -102,7 +102,7 @@
 //#define U8X8_WITH_SET_FLIP_MODE
 
 /* Select 0 or 1 for the default flip mode. This is not affected by U8X8_WITH_FLIP_MODE */
-/* Note: Not all display types support a mirror functon for the frame buffer */
+/* Note: Not all display types support a mirror function for the frame buffer */
 /* 26 May 2016: Obsolete */
 //#define U8X8_DEFAULT_FLIP_MODE 0
 
@@ -352,7 +352,7 @@ struct u8x8_struct
   uint16_t encoding;		/* encoding result for utf8 decoder in next_cb */
   uint8_t x_offset;	/* copied from info struct, can be modified in flip mode */
   uint8_t is_font_inverse_mode; 	/* 0: normal, 1: font glyphs are inverted */
-  uint8_t i2c_address;	/* a valid i2c adr. Initially this is 255, but this is set to something usefull during DISPLAY_INIT */
+  uint8_t i2c_address;	/* a valid i2c adr. Initially this is 255, but this is set to something useful during DISPLAY_INIT */
 					/* i2c_address is the address for writing data to the display */
 					/* usually, the lowest bit must be zero for a valid address */
   uint8_t i2c_started;	/* for i2c interface */
@@ -367,7 +367,7 @@ struct u8x8_struct
   void *user_ptr;
 #endif
 #ifdef U8X8_USE_PINS 
-  uint8_t pins[U8X8_PIN_CNT];	/* defines a pinlist: Mainly a list of pins for the Arduino Envionment, use U8X8_PIN_xxx to access */
+  uint8_t pins[U8X8_PIN_CNT];	/* defines a pinlist: Mainly a list of pins for the Arduino Environment, use U8X8_PIN_xxx to access */
 #endif
 };
 
@@ -416,7 +416,7 @@ struct u8log_struct
   void *aux_data;		/* pointer to u8x8 or u8g2 */
   uint8_t width, height;	/* size of the terminal */
   u8log_cb cb;			/* callback redraw function */
-  uint8_t *screen_buffer;	/* size must be width*heigh bytes */
+  uint8_t *screen_buffer;	/* size must be width*height bytes */
   uint8_t is_redraw_line_for_each_char;
   int8_t line_height_offset;		/* extra offset for the line height (u8g2 only) */
   
@@ -477,7 +477,7 @@ void u8x8_d_helper_display_init(u8x8_t *u8g2);
   Name: 	U8X8_MSG_DISPLAY_SET_FLIP_MODE
   Args:	arg_int: 0: normal mode, 1: flipped HW screen (180 degree)
   Tasks:
-    Reprogramms the display controller to rotate the display by 
+    Reprograms the display controller to rotate the display by 
     180 degree (arg_int = 1) or not (arg_int = 0)
     This may change u8g2->x_offset if the display is smaller than the controller ram
     This message should only be supported if U8X8_WITH_FLIP_MODE is defined.
@@ -639,6 +639,7 @@ void u8x8_SendF(u8x8_t * u8x8, const char *fmt, ...);
 #define U8X8_A(a0)				(U8X8_MSG_CAD_SEND_ARG), (a0)
 #define U8X8_CA(c0,a0)			(U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_ARG), (a0)
 #define U8X8_CAA(c0,a0,a1)		(U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1)
+#define U8X8_CCAA(c0,c1,a0, a1)	(U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_CMD), (c1), (U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1)
 #define U8X8_CAAA(c0,a0,a1, a2)	(U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1), (U8X8_MSG_CAD_SEND_ARG), (a2)
 #define U8X8_CAAAA(c0,a0,a1,a2,a3)		(U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1), (U8X8_MSG_CAD_SEND_ARG), (a2), (U8X8_MSG_CAD_SEND_ARG), (a3)
 #define U8X8_AAC(a0,a1,c0)		(U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1), (U8X8_MSG_CAD_SEND_CMD), (c0)
@@ -814,6 +815,11 @@ void u8x8_SaveBitmapTGA(u8x8_t *u8x8, const char *filename);
 void u8x8_SetupBitmap(u8x8_t *u8x8, uint16_t pixel_width, uint16_t pixel_height);
 uint8_t u8x8_ConnectBitmapToU8x8(u8x8_t *u8x8);
 
+/*==========================================*/
+/* u8x8_d_framebuffer.c */
+void u8x8_SetupLinuxFb(u8x8_t *u8x8, int fbfd);
+void u8x8_LinuxFbSetActiveColor(uint32_t color);
+
 /*==========================================*/
 /* u8x8_d_utf8.c */
 void u8x8_Setup_Utf8(u8x8_t *u8x8);	/* stdout UTF-8 display */
@@ -830,6 +836,7 @@ uint8_t u8x8_d_uc1701_ea_dogs102(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, voi
 uint8_t u8x8_d_uc1701_mini12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1305_128x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1305_128x32_adafruit(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+/*uint8_t u8x8_d_ssd1305_128x32_waveshare(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);*/
 uint8_t u8x8_d_ssd1305_128x64_adafruit(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1305_128x64_raystar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1306_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
@@ -837,6 +844,19 @@ uint8_t u8x8_d_ssd1306_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
 uint8_t u8x8_d_ssd1306_128x64_alt0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1309_128x64_noname0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1309_128x64_noname2(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1312_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_2040x16(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_128x32_univision(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_128x32_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_102x64_ea_oleds102(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);  /* u8x8_ssd1309.c */
+uint8_t u8x8_d_ssd1306_64x48_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_48x64_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_64x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_64x32_1f(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_96x16_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_96x40(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_96x39(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1306_72x40_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sh1106_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sh1106_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sh1106_128x64_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
@@ -849,21 +869,16 @@ uint8_t u8x8_d_sh1107_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *
 uint8_t u8x8_d_sh1107_128x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sh1107_pimoroni_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sh1107_seeed_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_sh1107_hjr_oel1m0201_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_sh1107_tk078f288_80x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_sh1108_128x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sh1108_160x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sh1122_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_st7920_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7920_144x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7920_160x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7920_192x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7920_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7920_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_2040x16(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_128x32_univision(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_128x32_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_102x64_ea_oleds102(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);  /* u8x8_ssd1309.c */
-uint8_t u8x8_d_ssd1306_64x48_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_48x64_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_64x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_64x32_1f(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_96x16_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
-uint8_t u8x8_d_ssd1306_72x40_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ls013b7dh03_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ls027b7dh01_400x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ls027b7dh01_m0_400x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
@@ -871,6 +886,7 @@ uint8_t u8x8_d_ls013b7dh05_144x168(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, v
 uint8_t u8x8_d_st7511_avd_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7528_nhd_c160100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7528_erc16064(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7539_192x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7565_ea_dogm128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7565_lm6063(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7565_64128n(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
@@ -886,16 +902,21 @@ uint8_t u8x8_d_st7565_erc12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
 uint8_t u8x8_d_st7565_erc12864_alt(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);  /* issue #790 */
 uint8_t u8x8_d_st7567_pi_132x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7567_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7567_enh_dg128064(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7567_enh_dg128064i(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7567_64x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7567_hem6432(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7567_os12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7567_erc13232(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7567_lw12832(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7571_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7571_128x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7586s_s028hn118a(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7586s_jlx384160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7586s_erc240160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7586s_ymc240160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st7586s_jlx320160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7588_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st75160_jm16096(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st75256_jlx256128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
@@ -907,26 +928,36 @@ uint8_t u8x8_d_st75256_jlx240160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, voi
 uint8_t u8x8_d_st75256_jlx25664(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st75256_jlx172104(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st75256_jlx19296(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_st75256_jlx16080(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st75320_jlx320240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);	/* https://github.com/olikraus/u8g2/issues/921 */
 uint8_t u8x8_d_nt7534_tg12864r(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); /* u8x8_d_st7565.c */
 uint8_t u8x8_d_ld7032_60x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ld7032_60x32_alt(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ld7032_128x36(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_t6963_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_t6963_240x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_t6963_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_t6963_128x64_alt(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_t6963_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_t6963_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_t6963_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1316_128x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1316_96x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1317_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1318_128x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1318_128x96_xcp(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1320_160x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1320_160x132(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1320_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1322_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1322_nhd_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1322_nhd_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1362_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1362_206x36(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_a2printer_384x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_sed1330_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_sed1330_256x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_sed1330_320x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ra8835_nhd_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ra8835_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1325_nhd_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
@@ -935,6 +966,7 @@ uint8_t u8x8_d_ssd1327_ws_96x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
 uint8_t u8x8_d_ssd1327_seeed_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1327_ea_w128128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1327_midas_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ssd1327_zjy_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1327_ws_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1327_visionox_128x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ssd1326_er_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
@@ -957,6 +989,7 @@ uint8_t u8x8_d_uc1617_jlx128128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
 uint8_t u8x8_d_uc1611_ids4073(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); /* 256x128 */
 uint8_t u8x8_d_uc1638_160x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_uc1638_192x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_uc1638_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ks0108_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ks0108_erm19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_t7932_150x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); /* t7932 and hd44102 are compatible */
@@ -977,15 +1010,22 @@ uint8_t u8x8_d_lc7981_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
 uint8_t u8x8_d_lc7981_160x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_lc7981_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_lc7981_240x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_lc7981_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ist3020_erc19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_ist3088_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_ist7920_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_max7219_64x8(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_max7219_32x8(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_max7219_16x16(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_max7219_8x8(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_s1d15e06_160100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_s1d15300_lm6023(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_s1d15721_240x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_gu800_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_gu800_160x16(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_gp1287ai_256x50(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_gp1247ai_253x63(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
+uint8_t u8x8_d_gp1294ai_256x48(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
 uint8_t u8x8_d_st7565_jlx12864g109pc(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); // 2023年8月4日 晶联讯12864G-109-PC,12864G-139-P
 
 

+ 1 - 0
components/u8g2/u8x8_byte.c

@@ -437,6 +437,7 @@ uint8_t u8x8_byte_sed1520(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_
     case U8X8_MSG_BYTE_START_TRANSFER:
       /* cs lines are not supported for the SED1520/SBN1661 */
       /* instead, this will select the E1 or E2 line */ 
+      /* arg_int is set by u8x8_d_sbn1661_122x32() function */
       enable_pin = U8X8_MSG_GPIO_E;
       if ( arg_int != 0 )
 	enable_pin = U8X8_MSG_GPIO_CS;

+ 2 - 2
components/u8g2/u8x8_d_a2printer.c

@@ -155,7 +155,7 @@ static const u8x8_display_info_t u8x8_a2printer_384x240_display_info =
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
   /* tile_width = */ 48,
-  /* tile_hight = */ 30,
+  /* tile_height = */ 30,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 384,
@@ -179,4 +179,4 @@ uint8_t u8x8_d_a2printer_384x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, voi
 
   
 
-  
+  

+ 200 - 0
components/u8g2/u8x8_d_custom.c

@@ -0,0 +1,200 @@
+/*
+
+  u8x8_d_custom.c
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+  
+*/
+
+
+#include "u8x8.h"
+
+
+
+
+static const uint8_t u8x8_d_custom_powersave0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0af),		                /* display on */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_custom_powersave1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_custom_128x32_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CA(0x0d3, 32),			/* display offset to 32 */
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_custom_128x32_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CA(0x0d3, 0),			/* display offset to  */
+  U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+
+static uint8_t u8x8_d_custom_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x *= 8;
+      x += u8x8->x_offset;
+    
+      u8x8_cad_SendCmd(u8x8, 0x040 );	/* set line offset to 0 */
+    
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
+      u8x8_cad_SendArg(u8x8, 0x000 | ((x&15)));
+      u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)   );
+
+    
+      do
+      {
+	c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+	u8x8_cad_SendData(u8x8, c*8, ptr); 	/* note: SendData can not handle more than 255 bytes */
+	/*
+	do
+	{
+	  u8x8_cad_SendData(u8x8, 8, ptr);
+	  ptr += 8;
+	  c--;
+	} while( c > 0 );
+	*/
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_custom_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_custom_powersave1_seq);
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* custom has range from 0 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+/* timing from SSD1306 */
+static const u8x8_display_info_t u8x8_custom_128x32_noname_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* SSD1306: 3 us */
+  /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,
+  /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 16,
+  /* tile_height = */ 4,
+  /* default_x_offset = */ 2,
+  /* flipmode_x_offset = */ 2,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 32
+};
+
+
+static const uint8_t u8x8_d_custom_128x32_noname_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_CA(0x0d5, 0x080),		/* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
+  U8X8_CA(0x0a8, 0x03f),		/* multiplex ratio */
+  U8X8_CA(0x0d3, 32),			/* display offset to 32 */
+  U8X8_C(0x040),		        	/* set display start line to 0 */
+  U8X8_CA(0x020, 0x000),		/* horizontal addressing mode */
+  
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse */
+  // Flipmode
+  // U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  // U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  
+  U8X8_CA(0x0da, 0x012),		/* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
+
+  U8X8_CA(0x081, 0x0cf), 		/* [2] set contrast control */
+  U8X8_CA(0x0d9, 0x0f1), 		/* [2] pre-charge period 0x022/f1*/
+  U8X8_CA(0x0db, 0x040), 		/* vcomh deselect level */  
+  // if vcomh is 0, then this will give the biggest range for contrast control issue #98
+  // restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
+  
+  U8X8_C(0x02e),				/* Deactivate scroll */ 
+  U8X8_C(0x0a4),				/* output ram to display */
+  U8X8_C(0x0a6),				/* none inverted normal display mode */
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+uint8_t u8x8_d_custom(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    
+  if ( u8x8_d_custom_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_custom_128x32_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_custom_128x32_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_custom_128x32_noname_init_seq);    
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_custom_128x32_noname_display_info);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+

+ 206 - 0
components/u8g2/u8x8_d_gp1247ai.c

@@ -0,0 +1,206 @@
+/*
+
+  u8x8_d_gp1247ai.c
+  
+  252x64
+  
+  https://github.com/olikraus/u8g2/issues/1907
+  https://github.com/olikraus/u8g2/pull/1892  
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2022, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification,
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list
+  of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "u8x8.h"
+
+#define SWAP8(a) ((((a)&0x80) >> 7) | (((a)&0x40) >> 5) | (((a)&0x20) >> 3) | (((a)&0x10) >> 1) | (((a)&0x08) << 1) | (((a)&0x04) << 3) | (((a)&0x02) << 5) | (((a)&0x01) << 7))
+
+/* ========== GP1247AI ========== */
+static const u8x8_display_info_t u8x8_gp1247ai_display_info = {
+    /* chip_enable_level = */ 0,
+    /* chip_disable_level = */ 1,
+
+    /* post_chip_enable_wait_ns = */ 240, /* tCS-CLK */
+    /* pre_chip_disable_wait_ns = */ 120, /* tCLK-CS */
+    /* reset_pulse_width_ms = */ 1,       /* Trw     */
+    /* post_reset_wait_ms = */ 1,         /* Trth    */
+    /* sda_setup_time_ns = */ 60,         /* tsu     */
+    /* sck_pulse_width_ns = */ 120,       /* tcyc/2  */
+    /* sck_clock_hz = */ 4000000UL,       /* MAX 4.16 MHz */
+    /* spi_mode = */ 3,                   /* active low, falling edge, MSBFIRST */
+    /* i2c_bus_clock_100kHz = */ 4,       /*         */
+    /* data_setup_time_ns = */ 60,        /* tsu     */
+    /* write_pulse_width_ns = */ 120,     /* tcyc/2  */
+    /* tile_width = */ 32,                /* 32*8=256 memory size */
+    /* tile_height = */ 8,                 /* 8*8=64 memory size */
+    /* default_x_offset = */ 0,           /*         */
+    /* flipmode_x_offset = */ 0,          /*         */
+    /* pixel_width = */ 253,              /* display size */
+    /* pixel_height = */ 63               /* display size */
+};
+static const uint8_t u8x8_d_gp1247ai_init_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x0AA)), /* Software reset */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(1), /* Wait for reset */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x078), SWAP8(0x008)), /* Oscillation Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0CC), SWAP8(0x005), SWAP8(0x000)), /* VFD Mode Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAAA(SWAP8(0x0E0), SWAP8(0x0FC), SWAP8(0x03E), SWAP8(0x000)), /* Display Area Setting */
+    U8X8_A4(SWAP8(0x020), SWAP8(0x080), SWAP8(0x080), SWAP8(0x080)),   /* Display Area Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAAAA(SWAP8(0x0B1), SWAP8(0x020), SWAP8(0x03F), SWAP8(0x000), SWAP8(0x001)), /* Internal Speed Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0A0), SWAP8(0x000), SWAP8(0x028)), /* Dimming level Setting (1024 level, 0x3FF max) */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x055)), /* Memory Map Clear */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(15), /* Wait for memory clear */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0C0), SWAP8(0x000), SWAP8(0x000)), /* DW1 position setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0D0), SWAP8(0x000), SWAP8(0x040)), /* DW2 position setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x080), SWAP8(0x080)), /* Display Mode Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x061)), /* Standby Mode */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+static const uint8_t u8x8_d_gp1247ai_standby_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x061)), /* Standby */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+static const uint8_t u8x8_d_gp1247ai_wakeup_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x06D)), /* Wake up */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(1), /* Wait for OSC stabilize */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x080), SWAP8(0x080)), /* After entering standby mode, the SC bit will be automatically cleared */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+uint8_t u8x8_d_gp1247ai_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    uint8_t *ptr;
+    uint8_t x, y;
+    uint16_t tx_cnt;
+    uint8_t swapped_byte;
+    switch (msg)
+    {
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+        if (arg_int == 0)
+            u8x8_cad_SendSequence(u8x8, u8x8_d_gp1247ai_wakeup_seq);
+        else
+            u8x8_cad_SendSequence(u8x8, u8x8_d_gp1247ai_standby_seq);
+        break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+        u8x8_cad_StartTransfer(u8x8);
+        u8x8_cad_SendCmd(u8x8, SWAP8(0x0A0));
+        u8x8_cad_SendArg(u8x8, SWAP8((arg_int * 4) >> 8));   /* Dimming level */
+        u8x8_cad_SendArg(u8x8, SWAP8((arg_int * 4) & 0xFF)); /* Dimming level */
+        u8x8_cad_EndTransfer(u8x8);
+        break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+        x = ((u8x8_tile_t *)arg_ptr)->x_pos * 8;
+        y = ((u8x8_tile_t *)arg_ptr)->y_pos * 8;
+
+        u8x8_cad_StartTransfer(u8x8);
+
+        u8x8_cad_SendCmd(u8x8, SWAP8(0x0F0));
+        u8x8_cad_SendArg(u8x8, SWAP8(x));
+        u8x8_cad_SendArg(u8x8, SWAP8(y));
+        u8x8_cad_SendArg(u8x8, SWAP8(0x007)); /* return every 8 pixels */
+        do
+        {
+            ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+            tx_cnt = ((u8x8_tile_t *)arg_ptr)->cnt * 8;
+            while (tx_cnt > 0)
+            {
+                swapped_byte = SWAP8(*ptr);
+                u8x8_cad_SendData(u8x8, 1, &swapped_byte);
+                ptr += 1;
+                tx_cnt -= 1;
+            }
+            arg_int--;
+        } while (arg_int > 0);
+
+        u8x8_cad_EndTransfer(u8x8);
+        break;
+    default:
+        return 0;
+    }
+    return 1;
+}
+uint8_t u8x8_d_gp1247ai_253x63(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    switch (msg)
+    {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+        u8x8_d_helper_display_setup_memory(u8x8, &u8x8_gp1247ai_display_info);
+        break;
+    case U8X8_MSG_DISPLAY_INIT:
+        u8x8_d_helper_display_init(u8x8);
+        u8x8_cad_SendSequence(u8x8, u8x8_d_gp1247ai_init_seq);
+        break;
+    default:
+        return u8x8_d_gp1247ai_common(u8x8, msg, arg_int, arg_ptr);
+    }
+    return 1;
+}

+ 212 - 0
components/u8g2/u8x8_d_gp1287ai.c

@@ -0,0 +1,212 @@
+/*
+
+  u8x8_d_gp1287ai.c
+  
+  https://github.com/olikraus/u8g2/issues/1907
+  https://github.com/olikraus/u8g2/pull/1892  
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2022, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification,
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list
+  of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "u8x8.h"
+
+#define SWAP8(a) ((((a)&0x80) >> 7) | (((a)&0x40) >> 5) | (((a)&0x20) >> 3) | (((a)&0x10) >> 1) | (((a)&0x08) << 1) | (((a)&0x04) << 3) | (((a)&0x02) << 5) | (((a)&0x01) << 7))
+
+/* ========== GP1287AI ========== */
+static const u8x8_display_info_t u8x8_gp1287ai_display_info = {
+    /* chip_enable_level = */ 0,
+    /* chip_disable_level = */ 1,
+
+    /* post_chip_enable_wait_ns = */ 240, /* tCS-CLK */
+    /* pre_chip_disable_wait_ns = */ 120, /* tCLK-CS */
+    /* reset_pulse_width_ms = */ 1,       /* Trw     */
+    /* post_reset_wait_ms = */ 1,         /* Trth    */
+    /* sda_setup_time_ns = */ 60,         /* tsu     */
+    /* sck_pulse_width_ns = */ 120,       /* tcyc/2  */
+    /* sck_clock_hz = */ 4000000UL,       /* MAX 4.16 MHz */
+    /* spi_mode = */ 3,                   /* active low, falling edge, MSBFIRST */
+    /* i2c_bus_clock_100kHz = */ 4,       /*         */
+    /* data_setup_time_ns = */ 60,        /* tsu     */
+    /* write_pulse_width_ns = */ 120,     /* tcyc/2  */
+    /* tile_width = */ 32,                /* 32*8=256 memory size */
+    /* tile_height = */ 7,                 /* 7*8=56 memory size */
+    /* default_x_offset = */ 0,           /*         */
+    /* flipmode_x_offset = */ 0,          /*         */
+    /* pixel_width = */ 256,              /* display size */
+    /* pixel_height = */ 50               /* display size */
+};
+static const uint8_t u8x8_d_gp1287ai_init_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x0AA)), /* Software reset */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(1), /* Wait for reset */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x078), SWAP8(0x008)), /* Oscillation Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0CC), SWAP8(0x002), SWAP8(0x000)), /* VFD Mode Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAAA(SWAP8(0x0E0), SWAP8(0x0FF), SWAP8(0x031), SWAP8(0x000)), /* Display Area Setting */
+    U8X8_A4(SWAP8(0x020), SWAP8(0x000), SWAP8(0x000), SWAP8(0x080)),   /* Display Area Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAAAA(SWAP8(0x0B1), SWAP8(0x020), SWAP8(0x03F), SWAP8(0x000), SWAP8(0x001)), /* Internal Speed Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0A0), SWAP8(0x000), SWAP8(0x028)), /* Dimming level Setting (1024 level, 0x3FF max) */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x055)), /* Memory Map Clear */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(15), /* Waiting for memory clear */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0C0), SWAP8(0x000), SWAP8(0x004)), /* DW1 position setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0D0), SWAP8(0x000), SWAP8(0x03C)), /* DW2 position setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x090), SWAP8(0x000)), /* Internal Command */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x008), SWAP8(0x000)), /* T1 INT Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x080), SWAP8(0x000)), /* Display Mode Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x061)), /* Standby Mode */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+static const uint8_t u8x8_d_gp1287ai_standby_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x061)), /* Standby */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+static const uint8_t u8x8_d_gp1287ai_wakeup_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x06D)), /* Wake up */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(1), /* Wait for OSC stabilize */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x080), SWAP8(0x000)), /* After entering standby mode, the SC bit will be automatically cleared */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+uint8_t u8x8_d_gp1287ai_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    uint8_t *ptr;
+    uint8_t x, y;
+    uint16_t tx_cnt;
+    uint8_t swapped_byte;
+    switch (msg)
+    {
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+        if (arg_int == 0)
+            u8x8_cad_SendSequence(u8x8, u8x8_d_gp1287ai_wakeup_seq);
+        else
+            u8x8_cad_SendSequence(u8x8, u8x8_d_gp1287ai_standby_seq);
+        break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+        u8x8_cad_StartTransfer(u8x8);
+        u8x8_cad_SendCmd(u8x8, SWAP8(0x0A0));
+        u8x8_cad_SendArg(u8x8, SWAP8((arg_int * 4) >> 8));   /* Dimming level */
+        u8x8_cad_SendArg(u8x8, SWAP8((arg_int * 4) & 0xFF)); /* Dimming level */
+        u8x8_cad_EndTransfer(u8x8);
+        break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+        x = ((u8x8_tile_t *)arg_ptr)->x_pos * 8;
+        y = ((u8x8_tile_t *)arg_ptr)->y_pos * 8 + 4;
+
+        u8x8_cad_StartTransfer(u8x8);
+
+        u8x8_cad_SendCmd(u8x8, SWAP8(0x0F0));
+        u8x8_cad_SendArg(u8x8, SWAP8(x));
+        u8x8_cad_SendArg(u8x8, SWAP8(y));
+        u8x8_cad_SendArg(u8x8, SWAP8(0x007)); /* return every 8 pixels */
+        do
+        {
+            ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+            tx_cnt = ((u8x8_tile_t *)arg_ptr)->cnt * 8;
+            while (tx_cnt > 0)
+            {
+                swapped_byte = SWAP8(*ptr);
+                u8x8_cad_SendData(u8x8, 1, &swapped_byte);
+                ptr += 1;
+                tx_cnt -= 1;
+            }
+            arg_int--;
+        } while (arg_int > 0);
+
+        u8x8_cad_EndTransfer(u8x8);
+        break;
+    default:
+        return 0;
+    }
+    return 1;
+}
+uint8_t u8x8_d_gp1287ai_256x50(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    switch (msg)
+    {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+        u8x8_d_helper_display_setup_memory(u8x8, &u8x8_gp1287ai_display_info);
+        break;
+    case U8X8_MSG_DISPLAY_INIT:
+        u8x8_d_helper_display_init(u8x8);
+        u8x8_cad_SendSequence(u8x8, u8x8_d_gp1287ai_init_seq);
+        break;
+    default:
+        return u8x8_d_gp1287ai_common(u8x8, msg, arg_int, arg_ptr);
+    }
+    return 1;
+}

+ 182 - 0
components/u8g2/u8x8_d_gp1294ai.c

@@ -0,0 +1,182 @@
+/*
+
+  u8x8_d_gp1294ai.c
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2023, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification,
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list
+  of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include "u8x8.h"
+
+#define SWAP8(a) ((((a)&0x80) >> 7) | (((a)&0x40) >> 5) | (((a)&0x20) >> 3) | (((a)&0x10) >> 1) | (((a)&0x08) << 1) | (((a)&0x04) << 3) | (((a)&0x02) << 5) | (((a)&0x01) << 7))
+
+/* ========== GP1294AI ========== */
+static const u8x8_display_info_t u8x8_gp1294ai_display_info = {
+    /* chip_enable_level = */ 0,
+    /* chip_disable_level = */ 1,
+
+    /* post_chip_enable_wait_ns = */ 240, /* tCS-CLK */
+    /* pre_chip_disable_wait_ns = */ 120, /* tCLK-CS */
+    /* reset_pulse_width_ms = */ 1,       /* Trw     */
+    /* post_reset_wait_ms = */ 1,         /* Trth    */
+    /* sda_setup_time_ns = */ 60,         /* tsu     */
+    /* sck_pulse_width_ns = */ 120,       /* tcyc/2  */
+    /* sck_clock_hz = */ 4000000UL,       /* MAX 4.16 MHz */
+    /* spi_mode = */ 3,                   /* active low, falling edge, MSBFIRST */
+    /* i2c_bus_clock_100kHz = */ 4,       /*         */
+    /* data_setup_time_ns = */ 60,        /* tsu     */
+    /* write_pulse_width_ns = */ 120,     /* tcyc/2  */
+    /* tile_width = */ 32,                /* 32*8=256 memory size */
+    /* tile_height = */ 6,                /* 6*8=48 memory size */
+    /* default_x_offset = */ 0,           /*         */
+    /* flipmode_x_offset = */ 0,          /*         */
+    /* pixel_width = */ 256,              /* display size */
+    /* pixel_height = */ 48               /* display size */
+};
+static const uint8_t u8x8_d_gp1294ai_init_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x0AA)), /* Software reset */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(1), /* Wait for reset */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAAA(SWAP8(0x0CC), SWAP8(0x001), SWAP8(0x01F), SWAP8(0x000)), /* VFD Mode Setting */
+    U8X8_A4(SWAP8(0x0FF), SWAP8(0x02F), SWAP8(0x000), SWAP8(0x020)),
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0A0), SWAP8(0x028), SWAP8(0x000)), /* Dimming level Setting (1024 level, 0x3FF max) */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CAA(SWAP8(0x0C0), SWAP8(0x000), SWAP8(0x000)), /* DW1 position setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x080), SWAP8(0x010)), /* Display Mode Setting (Scan STOP) */
+    U8X8_END_TRANSFER(),
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x008), SWAP8(0x000)), /* T1 INT Setting */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+static const uint8_t u8x8_d_gp1294ai_standby_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x061)), /* Standby */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+static const uint8_t u8x8_d_gp1294ai_wakeup_seq[] = {
+    U8X8_START_TRANSFER(),
+    U8X8_C(SWAP8(0x06D)), /* Wake up */
+    U8X8_END_TRANSFER(),
+    U8X8_DLY(1), /* Wait for OSC stabilize */
+
+    U8X8_START_TRANSFER(),
+    U8X8_CA(SWAP8(0x080), SWAP8(0x000)), /* After entering standby mode, the SC bit will be automatically cleared */
+    U8X8_END_TRANSFER(),
+
+    U8X8_END() /* end of sequence */
+};
+uint8_t u8x8_d_gp1294ai_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    uint8_t *ptr;
+    uint8_t x, y;
+    uint16_t tx_cnt;
+    uint8_t swapped_byte;
+    switch (msg)
+    {
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+        if (arg_int == 0)
+            u8x8_cad_SendSequence(u8x8, u8x8_d_gp1294ai_wakeup_seq);
+        else
+            u8x8_cad_SendSequence(u8x8, u8x8_d_gp1294ai_standby_seq);
+        break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+        u8x8_cad_StartTransfer(u8x8);
+        u8x8_cad_SendCmd(u8x8, SWAP8(0x0A0));
+        u8x8_cad_SendArg(u8x8, SWAP8((arg_int * 4) & 0xFF)); /* Dimming level */
+        u8x8_cad_SendArg(u8x8, SWAP8((arg_int * 4) >> 8));   /* Dimming level */
+        u8x8_cad_EndTransfer(u8x8);
+        break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+        x = ((u8x8_tile_t *)arg_ptr)->x_pos * 8;
+        y = ((u8x8_tile_t *)arg_ptr)->y_pos * 8 + 4;
+
+        u8x8_cad_StartTransfer(u8x8);
+
+        u8x8_cad_SendCmd(u8x8, SWAP8(0x0F0));
+        u8x8_cad_SendArg(u8x8, SWAP8(x));
+        u8x8_cad_SendArg(u8x8, SWAP8(y));
+        u8x8_cad_SendArg(u8x8, SWAP8(0x007)); /* return every 8 pixels */
+        do
+        {
+            ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+            tx_cnt = ((u8x8_tile_t *)arg_ptr)->cnt * 8;
+            while (tx_cnt > 0)
+            {
+                swapped_byte = SWAP8(*ptr);
+                u8x8_cad_SendData(u8x8, 1, &swapped_byte);
+                ptr += 1;
+                tx_cnt -= 1;
+            }
+            arg_int--;
+        } while (arg_int > 0);
+
+        u8x8_cad_EndTransfer(u8x8);
+        break;
+    default:
+        return 0;
+    }
+    return 1;
+}
+uint8_t u8x8_d_gp1294ai_256x48(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    switch (msg)
+    {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+        u8x8_d_helper_display_setup_memory(u8x8, &u8x8_gp1294ai_display_info);
+        break;
+    case U8X8_MSG_DISPLAY_INIT:
+        u8x8_d_helper_display_init(u8x8);
+        u8x8_cad_SendSequence(u8x8, u8x8_d_gp1294ai_init_seq);
+        u8x8_ClearDisplay(u8x8); /* GP1294AI does not have the command to clear the memory and needs to be cleared manually  */
+        u8x8_cad_SendSequence(u8x8, u8x8_d_gp1294ai_standby_seq);
+        break;
+    default:
+        return u8x8_d_gp1294ai_common(u8x8, msg, arg_int, arg_ptr);
+    }
+    return 1;
+}

+ 86 - 3
components/u8g2/u8x8_d_gu800.c

@@ -103,7 +103,7 @@ uint8_t u8x8_d_gu800_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *ar
 #endif
 #ifdef U8X8_WITH_SET_CONTRAST
     case U8X8_MSG_DISPLAY_SET_CONTRAST:
-      u8x8_cad_SendCmd(u8x8, 0x40 | (arg_int >> 4) );	/* GU800 has range from 0..15 */
+      u8x8_cad_SendCmd(u8x8, 0x4f - ((arg_int >> 4)&0x0f) );	/* GU800 has range from 0..15, max brightness is 0x040  */
       break;
 #endif
     case U8X8_MSG_DISPLAY_DRAW_TILE:
@@ -137,6 +137,8 @@ uint8_t u8x8_d_gu800_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *ar
   return 1;
 }
 
+/*=================================================*/
+
 static const uint8_t u8x8_d_gu800_128x64_init_seq[] = {
     
   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
@@ -156,7 +158,7 @@ static const uint8_t u8x8_d_gu800_128x64_init_seq[] = {
   
   U8X8_CA(0x70, 0),                             /* horizontal shift */
   U8X8_C(0xb0),                                 /* vertical shift */  
-  U8X8_C(0x4f),                                 /* max brightness */
+  U8X8_C(0x40),                                 /* min (0x04f) / max (0x040) brightness */
   U8X8_C(0x84),                                 /* x increment */
   
   // U8X8_CA(0x024, 0x040)              /* display on */
@@ -183,7 +185,7 @@ static const u8x8_display_info_t u8x8_d_gu800_128x64_display_info =
   /* data_setup_time_ns = */ 40,    /* GU800: Min 40ns per datasheet */
   /* write_pulse_width_ns = */ 150, /* GU800: Min 150ns per datasheet */
   /* tile_width = */ 16,            /* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -211,3 +213,84 @@ uint8_t u8x8_d_gu800_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *ar
   }
   return 1;
 }
+
+/*=================================================*/
+/* https://github.com/olikraus/u8g2/issues/1970 */
+
+static const uint8_t u8x8_d_gu800_160x16_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_C(0x05f),                                /* clear all RAM, clear address counters */
+  U8X8_DLY(1),                                  /* delay for 1 ms (see datasheet) */
+  
+  /* configure all area as graphics RAM */
+  U8X8_CA(0x62,0), U8X8_D1(0xff),
+  U8X8_CA(0x62,1), U8X8_D1(0xff),
+  U8X8_CA(0x62,2), U8X8_D1(0xff),
+  U8X8_CA(0x62,3), U8X8_D1(0xff),
+  U8X8_CA(0x62,4), U8X8_D1(0xff),
+  U8X8_CA(0x62,5), U8X8_D1(0xff),
+  U8X8_CA(0x62,6), U8X8_D1(0xff),
+  U8X8_CA(0x62,7), U8X8_D1(0xff),
+  
+  U8X8_CA(0x70, 0),                             /* horizontal shift */
+  U8X8_C(0xb0),                                 /* vertical shift */  
+  U8X8_C(0x40),                                 /* min (0x04f) / max (0x040) brightness */
+  U8X8_C(0x84),                                 /* x increment */
+  
+  // U8X8_CA(0x024, 0x040)              /* display on */
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+static const u8x8_display_info_t u8x8_d_gu800_160x16_display_info =
+{
+  /* chip_enable_level = */ 0,      /* GU800: CSS signal */
+  /* chip_disable_level = */ 1,     /* GU800: CSS signal */
+  
+  /* post_chip_enable_wait_ns = */ 40,
+  /* pre_chip_disable_wait_ns = */ 150,
+  /* reset_pulse_width_ms = */ 2,   /* GU800: Unspecified in datasheet */
+  /* post_reset_wait_ms = */ 2,     /* GU800: Min 1.5ms per datasheet */
+  /* sda_setup_time_ns = */ 40,     /* GU800: 40ns according to the timing diagram */
+  /* sck_pulse_width_ns = */ 80,    /* GU800: Min 80ns per datasheet */
+  /* sck_clock_hz = */ 4000000UL,
+  /* spi_mode = */ 3,               /* active high, rising edge, ISSUE 1970 */
+  /* i2c_bus_clock_100kHz = */ 4,   /* GU800: Not used */
+  /* data_setup_time_ns = */ 40,    /* GU800: Min 40ns per datasheet */
+  /* write_pulse_width_ns = */ 150, /* GU800: Min 150ns per datasheet */
+  /* tile_width = */ 20,            /* width of 8*20=160 pixel */
+  /* tile_height = */ 2,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 160,
+  /* pixel_height = */ 16
+};
+
+
+uint8_t u8x8_d_gu800_160x16(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  
+  if ( u8x8_d_gu800_common(u8x8, msg, arg_int, arg_ptr) )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_d_gu800_160x16_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_gu800_160x16_init_seq);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+/*=================================================*/
+

+ 2 - 2
components/u8g2/u8x8_d_hd44102.c

@@ -165,7 +165,7 @@ static const u8x8_display_info_t u8x8_hd44102_150x32_display_info =
   /* data_setup_time_ns = */ 200,
   /* write_pulse_width_ns = */ 250,	/* KS0108/HD44102: actially 450 ns, but additional 200 ns are added by the byte transfer function */
   /* tile_width = */ 19,		/* width of 19*8=152 pixel */
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 150,
@@ -260,7 +260,7 @@ static const u8x8_display_info_t u8x8_hd44102_100x64_display_info =
   /* data_setup_time_ns = */ 200,
   /* write_pulse_width_ns = */ 250,	/* KS0108/HD44102: actially 450 ns, but additional 200 ns are added by the byte transfer function */
   /* tile_width = */ 13,		/* width of 13*8=104 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 100,

+ 1 - 1
components/u8g2/u8x8_d_il3820_296x128.c

@@ -156,7 +156,7 @@ static const u8x8_display_info_t u8x8_il3820_296x128_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 37,		/* 37*8 = 296 */
-  /* tile_hight = */ 16,		/* 16*8 = 128 */	
+  /* tile_height = */ 16,		/* 16*8 = 128 */	
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 296,

+ 1 - 1
components/u8g2/u8x8_d_ist3020.c

@@ -88,7 +88,7 @@ static const u8x8_display_info_t u8x8_ist3020_erc19264_display_info =
   /* data_setup_time_ns = */ 40,	/* IST3020 datasheet, page 54 */
   /* write_pulse_width_ns = */ 60,	/* IST3020 datasheet, page 54 */
   /* tile_width = */ 24,		/* width of 24*8=192 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 64,
   /* pixel_width = */ 192,

+ 280 - 0
components/u8g2/u8x8_d_ist3088.c

@@ -0,0 +1,280 @@
+/*
+
+  u8x8_d_ist3088.c
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2019, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+
+
+  IST3088: 320x240 monochrome LCD, 16 gray levels with B/W mode
+  
+  https://github.com/olikraus/u8g2/issues/1887
+  
+  CAD: 011
+  commands and arg/data are always 16 bit, MSB first
+  
+*/
+
+
+#include "u8x8.h"
+
+/* powersave: maybe we could go to sleep mode, see register 3 */
+static const uint8_t u8x8_d_ist3088_320x240_powersave0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CCAA(0x0, 0x07, 0x00, 0x01), 			// Display Control Bit 2: BW, 1: Invert, 0: Display enable
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ist3088_320x240_powersave1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CCAA(0x0, 0x07, 0x00, 0x00), 			// Display Control Bit 2: BW, 1: Invert, 0: Display enable
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ist3088_320x240_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CCAA(0x0, 0x01, 0x00, 0x00), 			// Driver Control, 1/240 Duty
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ist3088_320x240_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CCAA(0x0, 0x01, 0x00, 0x00), 			// Driver Control, 1/240 Duty
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+
+
+/*===================================================*/
+
+static uint8_t u8x8_d_ist3088_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  //uint16_t x;
+  int i;
+  uint8_t y;
+  uint8_t c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ist3088_320x240_display_info);
+      break;
+    */
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ist3088_320x240_init_seq);    
+      break;
+    */
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ist3088_320x240_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ist3088_320x240_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ist3088_320x240_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ist3088_320x240_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x00 );
+      u8x8_cad_SendCmd(u8x8, 0x05 );
+      u8x8_cad_SendArg(u8x8, 0 );	
+      u8x8_cad_SendArg(u8x8, arg_int );	
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      /*
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x *= 8;
+      x += u8x8->x_offset;
+    */
+
+      y = (((u8x8_tile_t *)arg_ptr)->y_pos);
+      y*=8;
+
+      u8x8_cad_StartTransfer(u8x8);
+    
+    
+        c = ((u8x8_tile_t *)arg_ptr)->cnt;	/* number of tiles */
+        ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;	/* data ptr to the tiles */
+        for( i = 0; i < 8; i++ )
+        {
+          u8x8_cad_SendCmd(u8x8, 0x0);
+          u8x8_cad_SendCmd(u8x8, 0x8);
+          u8x8_cad_SendArg(u8x8, y); 
+          u8x8_cad_SendArg(u8x8, 0 );
+
+
+          u8x8_cad_SendCmd(u8x8, 0x0);		// write data 
+          u8x8_cad_SendCmd(u8x8, 0x9);		// write data 
+          
+          
+          //c = ((u8x8_tile_t *)arg_ptr)->cnt;	/* number of tiles */
+          u8x8_cad_SendData(u8x8, c, ptr);	/* note: SendData can not handle more than 255 bytes, send one line of data */
+          
+          ptr += u8x8->display_info->tile_width;
+          y ++;
+        }
+
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+/*===================================================*/
+
+/*
+    SdCmd(0x01);                // driver control
+	SdData(0x00); SdData(0x00); // c1-->c240 s1-->s240 duty=1/240
+    SdCmd(0x02);                // driver control
+	SdData(0x01); SdData(0x4c);	//0x15
+    SdCmd(0x03);                // power control
+	SdData(0x00); SdData(0x70); // VC VR Vf=1
+    SdCmd(0x04);                // power control
+	SdData(0x04); SdData(0x61); //0x61  //1/14b
+    SdCmd(0x05);                // CT control
+	SdData(0x00); SdData(0x6a); // 0X76 
+    SdCmd(0x06);                // CT control
+	SdData(0x00); SdData(0x03); 
+    SdCmd(0x23);                // B/W MODE,16G NEED REMOVE
+	SdData(0x00); SdData(0x04); //04:mono
+    SdCmd(0x28);                // OSC
+	SdData(0x00); SdData(0x0c);
+    SdCmd(0x37);                
+        SdData(0x00); SdData(0x12);
+    SdCmd(0x07);                
+        SdData(0x00); SdData(0x01);
+*/
+
+/* https://github.com/olikraus/u8g2/issues/1887 */
+static const uint8_t u8x8_d_ist3088_320x240_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+
+  /* disableLCD */
+  U8X8_CCAA(0x0, 0x07, 0x00, 0x00), 			// Display Control Bit 2: BW, 1: Invert, 0: Display enable
+
+  U8X8_CCAA(0x0, 0x01, 0x00, 0x00), 			// Driver Control, 1/240 Duty
+  U8X8_CCAA(0x0, 0x02, 0x01, 0x4c), 			// Polarity Control
+
+  U8X8_CCAA(0x0, 0x06, 0x00, 0x03), 			// Entry mode: h/v increment  
+  //U8X8_CCAA(0x0, 0x04, 0x07, 0x61), 			// Power Control 2: 0x07: 1/16 Bias, Vout1 x 4
+  U8X8_CCAA(0x0, 0x04, 0x04, 0x61), 			// Power Control 2: 0x07: 1/16 Bias, Vout1 x 4
+  U8X8_CCAA(0x0, 0x05, 0x00, 0x6a), 			// Contrast, 0..255, 
+
+  U8X8_CCAA(0x0, 0x03, 0x00, 0x40), 			// Enable voltage converter 
+  U8X8_DLY(10),
+  U8X8_CCAA(0x0, 0x03, 0x00, 0x60), 			// Enable voltage regulator 
+  U8X8_DLY(10),
+  U8X8_CCAA(0x0, 0x03, 0x00, 0x70), 			// Enable voltage follower 
+  U8X8_DLY(10),
+
+  U8X8_CCAA(0x0, 0x23, 0x00, 0x04), 			// Monochrome mode
+  U8X8_CCAA(0x0, 0x28, 0x00, 0x0c), 			// Frame Rate Control
+  U8X8_CCAA(0x0, 0x37, 0x00, 0x01), 			// Frame Rate Control
+  U8X8_CCAA(0x0, 0x0d, 39, 0x00), 			// X End and X Start
+  
+  U8X8_CCAA(0x0, 0x0e, 239, 0x00), 			// Y End and Y Start
+
+  /* enable LCD (will be done by powersave0) */
+  //U8X8_CCAA(0x0, 0x07, 0x00, 0x01), 			// Display Control Bit 2: BW, 1: Invert, 0: Display enable
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()           			/* end of sequence */
+};
+
+
+
+
+static const u8x8_display_info_t u8x8_ist3088_320x240_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 110,
+  /* pre_chip_disable_wait_ns = */ 110,
+  /* reset_pulse_width_ms = */ 10, 	
+  /* post_reset_wait_ms = */ 10, 		/**/
+  /* sda_setup_time_ns = */ 110,		/* */
+  /* sck_pulse_width_ns = */ 125,	/*  */
+  /* sck_clock_hz = */ 4000000UL,	/* 250ns cycle, see page 49 of the IST3088 datasheet*/
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,	/* 400KHz, IST8033 das not include a I2C interface */
+  /* data_setup_time_ns = */ 70,
+  /* write_pulse_width_ns = */ 60,	
+  /* tile_width = */ 40,
+  /* tile_height = */ 30,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 320,
+  /* pixel_height = */ 240
+};
+
+uint8_t u8x8_d_ist3088_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    
+  if ( u8x8_d_ist3088_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ist3088_320x240_init_seq);    
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ist3088_320x240_display_info);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}

+ 1 - 1
components/u8g2/u8x8_d_ist7920.c

@@ -86,7 +86,7 @@ static const u8x8_display_info_t u8x8_ist7920_128x128_display_info =
   /* data_setup_time_ns = */ 60,	/* IST7920 datasheet, page 47 */
   /* write_pulse_width_ns = */ 150,	/* IST7920 datasheet, page 47 */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,

+ 2 - 2
components/u8g2/u8x8_d_ks0108.c

@@ -120,7 +120,7 @@ static const u8x8_display_info_t u8x8_ks0108_128x64_display_info =
   /* data_setup_time_ns = */ 200,
   /* write_pulse_width_ns = */ 250,	/* KS0108: actially 450 ns, but additional 200 ns are added by the byte transfer function */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -227,7 +227,7 @@ static const u8x8_display_info_t u8x8_ks0108_192x64_display_info =
   /* data_setup_time_ns = */ 200,
   /* write_pulse_width_ns = */ 250,	/* KS0108: actially 450 ns, but additional 200 ns are added by the byte transfer function */
   /* tile_width = */ 24,		/* width of 24*8=192 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 192,

+ 76 - 4
components/u8g2/u8x8_d_lc7981.c

@@ -203,7 +203,7 @@ static const u8x8_display_info_t u8x8_lc7981_160x80_display_info =
   /* data_setup_time_ns = */ 220,	
   /* write_pulse_width_ns = */ 20,	
   /* tile_width = */ 20,		/* width of 20*8=160 pixel */
-  /* tile_hight = */ 10,
+  /* tile_height = */ 10,
   /* default_x_offset = */ 0,	
   /* flipmode_x_offset = */ 0,	
   /* pixel_width = */ 160,
@@ -275,7 +275,7 @@ static const u8x8_display_info_t u8x8_lc7981_160x160_display_info =
   /* data_setup_time_ns = */ 220,	
   /* write_pulse_width_ns = */ 20,	
   /* tile_width = */ 20,		/* width of 20*8=160 pixel */
-  /* tile_hight = */ 20,
+  /* tile_height = */ 20,
   /* default_x_offset = */ 0,	
   /* flipmode_x_offset = */ 0,	
   /* pixel_width = */ 160,
@@ -347,7 +347,7 @@ static const u8x8_display_info_t u8x8_lc7981_240x128_display_info =
   /* data_setup_time_ns = */ 220,	
   /* write_pulse_width_ns = */ 20,	
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,	
   /* flipmode_x_offset = */ 0,	
   /* pixel_width = */ 240,
@@ -420,7 +420,7 @@ static const u8x8_display_info_t u8x8_lc7981_240x64_display_info =
   /* data_setup_time_ns = */ 220,	
   /* write_pulse_width_ns = */ 20,	
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,	
   /* flipmode_x_offset = */ 0,	
   /* pixel_width = */ 240,
@@ -468,3 +468,75 @@ uint8_t u8x8_d_lc7981_240x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
   return 1;
 }
 
+
+/*================================================*/
+/* LC7981 128x128 LCD, https://github.com/olikraus/u8g2/issues/1913*/
+
+static const u8x8_display_info_t u8x8_lc7981_128x128_display_info =
+{
+  /* chip_enable_level = */ 0,	/* LC7981 has a low active CS*/
+  /* chip_disable_level = */ 1,
+  
+  /* from here... */
+  /* post_chip_enable_wait_ns = */ 20,	
+  /* pre_chip_disable_wait_ns = */ 20,	
+  /* reset_pulse_width_ms = */ 1, 	
+  /* post_reset_wait_ms = */ 10, 	
+  /* sda_setup_time_ns = */ 30,		
+  /* sck_pulse_width_ns = */ 65,	/* half of cycle time  */
+  /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* ... to here, values are ignored, because this is a parallel interface only */
+  
+  /* data_setup_time_ns = */ 220,	
+  /* write_pulse_width_ns = */ 20,	
+  /* tile_width = */ 16,		/* width of 16*8=128 pixel */
+  /* tile_height = */ 16,
+  /* default_x_offset = */ 0,	
+  /* flipmode_x_offset = */ 0,	
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 128
+};
+
+static const uint8_t u8x8_d_lc7981_128x128_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_DLY(50),
+
+  U8X8_CA(0x00, 0x32),			/* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
+  U8X8_CA(0x01, 0x07),			/* character/bits per pixel pitch */
+  U8X8_CA(0x02, 128/8-1),		/* number of chars/byte width of the screen */
+  U8X8_CA(0x03, 128),			/* time division, issue https://github.com/olikraus/u8g2/issues/1581 */
+  U8X8_CA(0x08, 0x00),			/* display start low */
+  U8X8_CA(0x09, 0x00),			/* display start high */
+
+  U8X8_DLY(10),
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+uint8_t u8x8_d_lc7981_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  /* call common procedure first and handle messages there */
+  if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
+  {
+    /* msg not handled, then try here */
+    switch(msg)
+    {
+      case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+	u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_128x128_display_info);
+	break;
+      case U8X8_MSG_DISPLAY_INIT:
+	u8x8_d_helper_display_init(u8x8);
+	u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_128x128_init_seq);
+	break;
+      default:
+	return 0;		/* msg unknown */
+    }
+  }
+  return 1;
+}
+

+ 163 - 4
components/u8g2/u8x8_d_ld7032_60x32.c

@@ -2,10 +2,12 @@
 
   u8x8_d_ld7032_60x32.c
   Note: Flip Mode is NOT supported
+  
+  Also contains 128x36 OLED variant
 
   Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
 
-  Copyright (c) 2016, olikraus@gmail.com
+  Copyright (c) 2023, olikraus@gmail.com
   All rights reserved.
 
   Redistribution and use in source and binary forms, with or without modification, 
@@ -223,7 +225,7 @@ static const u8x8_display_info_t u8x8_ld7032_60x32_display_info =
   /* data_setup_time_ns = */ 20,
   /* write_pulse_width_ns = */ 40,	
   /* tile_width = */ 8,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 60,
@@ -272,11 +274,13 @@ static const uint8_t u8x8_d_ld7032_60x32_alt_init_seq[] = {
   U8X8_CA(0x48, 0x03),		  	
   U8X8_CA(0x17, 0x00),         
   U8X8_CA(0x13, 0x01),        
-  U8X8_CA(0x3F, 0x11),
+  U8X8_CA(0x3F, 0x11),          // internal regulator enabled, vcc_c * 0.7 
   U8X8_CA(0x3D, 0x00),
 
   U8X8_END_TRANSFER(),             	/* disable chip */
-  U8X8_END()             			/* end of sequence */};
+  U8X8_END()             			/* end of sequence */
+  
+  };
 
 uint8_t u8x8_d_ld7032_60x32_alt(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
@@ -296,3 +300,158 @@ uint8_t u8x8_d_ld7032_60x32_alt(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
     return u8x8_d_ld7032_generic(u8x8, msg, arg_int, arg_ptr);
 }
 
+/*==========================================*/
+/*
+  128x36 Flip Mode is NOT supported
+  see https://github.com/olikraus/u8g2/issues/2135
+*/
+
+static uint8_t u8x8_d_ld7032_128_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ld7032_60x32_display_info);
+      break;
+    */
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_init_seq);    
+      break;
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x012 );
+      if ( arg_int > 0x07f )			/* default is 0x040, limit to 0x07f to be on the safe side (hopefully) */
+	arg_int= 0x07f;
+      u8x8_cad_SendArg(u8x8, arg_int );	/* values from 0x00 to 0x0ff are allowed, bit will all values be safe??? */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x += u8x8->x_offset/8;
+      u8x8_cad_SendCmd(u8x8, 0x034 );
+      u8x8_cad_SendArg(u8x8, x );
+      u8x8_cad_SendCmd(u8x8, 0x035 );
+      u8x8_cad_SendArg(u8x8, 0x00f );
+      u8x8_cad_SendCmd(u8x8, 0x036 );
+      u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos)*8 );
+      u8x8_cad_SendCmd(u8x8, 0x037 );
+      u8x8_cad_SendArg(u8x8, 0x027 );
+      u8x8_cad_SendCmd(u8x8, 0x008 );
+    
+      
+      do
+      {
+	c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+	u8x8_cad_SendData(u8x8, c*8, ptr); 	/* note: SendData can not handle more than 255 bytes */
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+
+static const u8x8_display_info_t u8x8_ld7032_128x36_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 15,
+  /* pre_chip_disable_wait_ns = */ 20,
+  /* reset_pulse_width_ms = */ 100, 	
+  /* post_reset_wait_ms = */ 100, 
+  /* sda_setup_time_ns = */ 30,		/* 20ns, but cycle time is 60ns, so use 60/2 */
+  /* sck_pulse_width_ns = */ 30,	/* 20ns, but cycle time is 60ns, so use 60/2  */
+  /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 20,
+  /* write_pulse_width_ns = */ 40,	
+  /* tile_width = */ 16,
+  /* tile_height = */ 5,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 36
+};
+
+static const uint8_t u8x8_d_ld7032_128x36_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+
+  U8X8_CA(0x14, 0x00),		  		// standby mode
+  U8X8_CA(0x02, 0x00),		  		// display off
+  U8X8_CA(0x1A, 0x05),		  		// frame frequency
+  U8X8_CA(0x1D, 0x00),		  	        // data write direction (datasheet: 1d 0b
+  U8X8_CA(0x09, 0x00),	      		        // scan direction
+  U8X8_CAA(0x30, 0x00, 0x7F),             // column driver active range 
+  U8X8_CAA(0x32, 0x04, 0x27),           // row driver active range
+  U8X8_CA(0x34, 0x00),				// start line
+  U8X8_CA(0x35, 0x0f),		                // end line
+  U8X8_CA(0x36, 0x04),	                        // row start line
+  U8X8_CA(0x37, 0x27),			        // row end line
+  U8X8_CA(0x38, 0x00),                          // x disp start, default 0        
+  U8X8_CA(0x39, 0x00),                          // y disp start, default 0
+  U8X8_CA(0x10, 0x1f),		  	        // peak pulse width
+  U8X8_CA(0x16, 0x05),		                // pulse delay width  	
+  U8X8_CA(0x18, 0x1f),		  		// pre charge width
+  U8X8_CA(0x12, 0x3F),		  	        // contrast control
+  U8X8_CA(0x44, 0x02),		  		// PreC select, default: 2
+  //U8X8_CA(0x48, 0x00),		  	        // row overlap, default: 0 (was 3)
+  U8X8_CA(0x17, 0x00),                          // row scan, default: 0
+  U8X8_CA(0x13, 0x01),                          // scan mode sequence
+  //U8X8_CA(0x3F, 0x11),                         // VCC R Selection, default: 0 (int. reg. disabled, vcc_c*0.8)
+  U8X8_CA(0x3D, 0x01),                          // vdd selection 0: 2.8V-3.5, 1: 1.8V (1.65-2.5V)
+
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+  
+  };
+
+uint8_t u8x8_d_ld7032_128x36(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
+    {
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ld7032_128x36_display_info);
+      return 1;
+    }
+
+    if ( msg ==U8X8_MSG_DISPLAY_INIT )
+    {
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_128x36_init_seq);    
+      return 1;
+    }
+    
+    return u8x8_d_ld7032_128_generic(u8x8, msg, arg_int, arg_ptr);
+}

+ 7 - 7
components/u8g2/u8x8_d_ls013b7dh03.c

@@ -55,12 +55,12 @@ static const u8x8_display_info_t u8x8_ls013b7dh03_128x128_display_info =
   /* sda_setup_time_ns = */ 227,	/* 227 nsec according to the datasheet */		
   /* sck_pulse_width_ns = */  255,	/* 450 nsec according to the datasheet */
   /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
-  /* spi_mode = */ 2,		/* active low, rising edge */
+  /* spi_mode = */ 0,		/* changed from 2 to 0 (https://github.com/olikraus/u8g2/issues/1771) */
   /* i2c_bus_clock_100kHz = */ 4,
   /* data_setup_time_ns = */ 100,
   /* write_pulse_width_ns = */ 100,
   /* tile_width = */ 16,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -133,12 +133,12 @@ static const u8x8_display_info_t u8x8_ls027b7dh01_400x240_display_info =
   /* sda_setup_time_ns = */ 227,	/* 227 nsec according to the datasheet */		
   /* sck_pulse_width_ns = */  255,	/* 450 nsec according to the datasheet */
   /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
-  /* spi_mode = */ 2,		/* active low, rising edge */
+  /* spi_mode = */ 0,		/* changed from 2 to 0 (https://github.com/olikraus/u8g2/issues/1771) */
   /* i2c_bus_clock_100kHz = */ 4,
   /* data_setup_time_ns = */ 100,
   /* write_pulse_width_ns = */ 100,
   /* tile_width = */ 50,
-  /* tile_hight = */ 30,
+  /* tile_height = */ 30,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 400,
@@ -174,7 +174,7 @@ static const u8x8_display_info_t u8x8_ls027b7dh01_m0_400x240_display_info =
   /* data_setup_time_ns = */ 100,
   /* write_pulse_width_ns = */ 100,
   /* tile_width = */ 50,
-  /* tile_hight = */ 30,
+  /* tile_height = */ 30,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 400,
@@ -206,12 +206,12 @@ static const u8x8_display_info_t u8x8_ls013b7dh05_144x168_display_info =
   /* sda_setup_time_ns = */ 227,	/* 227 nsec according to the datasheet */		
   /* sck_pulse_width_ns = */  255,	/* 450 nsec according to the datasheet */
   /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
-  /* spi_mode = */ 2,		/* active low, rising edge */
+  /* spi_mode = */ 0,		/* changed from 2 to 0 (https://github.com/olikraus/u8g2/issues/1771) */
   /* i2c_bus_clock_100kHz = */ 4,
   /* data_setup_time_ns = */ 100,
   /* write_pulse_width_ns = */ 100,
   /* tile_width = */ 18,
-  /* tile_hight = */ 21,
+  /* tile_height = */ 21,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 144,

+ 4 - 4
components/u8g2/u8x8_d_max7219.c

@@ -185,7 +185,7 @@ static const u8x8_display_info_t u8x8_max7219_32x8_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 4,
-  /* tile_hight = */ 1,
+  /* tile_height = */ 1,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 32,
@@ -232,7 +232,7 @@ static const u8x8_display_info_t u8x8_max7219_16x16_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 2,
-  /* tile_hight = */ 2,
+  /* tile_height = */ 2,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 16,
@@ -287,7 +287,7 @@ static const u8x8_display_info_t u8x8_max7219_8x8_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 1,
-  /* tile_hight = */ 1,
+  /* tile_height = */ 1,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 8,
@@ -428,7 +428,7 @@ static const u8x8_display_info_t u8x8_max7219_64x8_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 8,
-  /* tile_hight = */ 1,
+  /* tile_height = */ 1,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 64,

+ 1 - 1
components/u8g2/u8x8_d_pcd8544_84x48.c

@@ -91,7 +91,7 @@ static const u8x8_display_info_t u8x8_pcd8544_84x48_display_info =
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
   /* tile_width = */ 11,		/* width of 11*8=88 pixel */
-  /* tile_hight = */ 6,
+  /* tile_height = */ 6,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 84,

+ 1 - 1
components/u8g2/u8x8_d_pcf8812.c

@@ -173,7 +173,7 @@ static const u8x8_display_info_t u8x8_pcf8812_96x65_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 12,
-  /* tile_hight = */ 9,
+  /* tile_height = */ 9,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 96,

+ 1 - 1
components/u8g2/u8x8_d_pcf8814_hx1230.c

@@ -178,7 +178,7 @@ static const u8x8_display_info_t u8x8_hx1230_96x68_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 12,
-  /* tile_hight = */ 9,
+  /* tile_height = */ 9,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 96,

+ 255 - 0
components/u8g2/u8x8_d_s1d15300.c

@@ -0,0 +1,255 @@
+/*
+
+  u8x8_d_s1d15300.c
+  
+  WARNING: As of today, flip mode 1 doesn't seem to work (see issue 2063)
+  
+  Created as a copy of u8x8_d_st7565.c, see https://github.com/olikraus/u8g2/issues/2063
+  
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2022, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+
+  
+*/
+#include "u8x8.h"
+
+
+
+
+
+static const uint8_t u8x8_d_s1d15300_powersave0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a4),		                /* all pixel off, see datasheet for the s1d15300 */
+  U8X8_C(0x0af),		                /* display on */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_s1d15300_powersave1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x0a5),		                /* enter powersafe, see datasheet for the s1d15300 */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_s1d15300_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_s1d15300_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+uint8_t u8x8_d_s1d15300_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+    
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
+      x *= 8;
+      x += u8x8->x_offset;
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
+    
+      c = ((u8x8_tile_t *)arg_ptr)->cnt;
+      c *= 8;
+      ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+      /* 
+	The following if condition checks the hardware limits of the st7565 
+	controller: It is not allowed to write beyond the display limits.
+	This is in fact an issue within flip mode.
+      */
+      if ( c + x > 132u )
+      {
+	c = 132u;
+	c -= x;
+      }
+      do
+      {
+	u8x8_cad_SendData(u8x8, c, ptr);	/* note: SendData can not handle more than 255 bytes */
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_powersave1_seq);
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x080 |  (arg_int >> 3) ); /* s1d15300 has only 5 bits for contrast */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+
+/*================================================*/
+/* LM6023, S1D15300 controller, issue 2063 */
+
+static const u8x8_display_info_t u8x8_s1d15300_lm6023_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 250,	/*  */
+  /* pre_chip_disable_wait_ns = */ 120,	/*  */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 1, 
+  /* sda_setup_time_ns = */ 200,		/* */
+  /* sck_pulse_width_ns = */ 200,	/* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 200,	/* st7565 datasheet, table 24, tds8 */
+  /* write_pulse_width_ns = */ 200,	/* st7565 datasheet, table 24, tcclw */
+  /* tile_width = */ 16,		/* width of 16*8=128 pixel */
+  /* tile_height = */ 8,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 4,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 64
+};
+
+
+static const uint8_t u8x8_d_s1d15300_lm6023_init_seq[] = {
+
+#ifdef OBSOLETE  
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_C(0x0e2),            			/* soft reset */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  
+  U8X8_C(0x0a1),		                /* ADC set to reverse */
+  U8X8_C(0x0c0),		                /* common output mode */
+  // Flipmode
+  //U8X8_C(0x0a0),		                /* ADC set to reverse */
+  //U8X8_C(0x0c8),		                /* common output mode */
+  
+  U8X8_C(0x0a6),		                /* display normal, bit val 0: LCD pixel off. */
+  U8X8_C(0x0a2),		                /* LCD bias 1/9 */
+  U8X8_C(0x02f),		                /* all power  control circuits on */
+  U8X8_CA(0x0f8, 0x000),		/* set booster ratio to 4x */
+  U8X8_C(0x025),		                /* set V0 voltage resistor ratio to large,  issue 1678: changed from 0x23 to 0x25 */
+  U8X8_CA(0x081, 170),			/* set contrast, contrast value NHD C12864, see issue 186, increased contrast to 180 (issue 219), reduced to 170 (issue 1678) */
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x0a5),		                /* enter powersafe: all pixel on, issue 142 */
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+#endif
+  
+
+    U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
+
+    U8X8_C(0x0e2), /* soft reset */
+
+    U8X8_C(0x0ae), /* display off */
+    U8X8_C(0x040), /* set display start line to 0 */
+    U8X8_C(0x0a0), /* ADC set to normal */
+    U8X8_C(0x0a6), /* Display normal */
+    U8X8_C(0x0a4), /* all point normal */
+
+    U8X8_C(0x0a2), /* LCD bias 1/8 */
+    U8X8_C(0x0c0), /* common output mode */
+    U8X8_C(0x02f), /* all power control circuits on */
+
+
+    U8X8_C(0x090), /* set contrast */
+    //U8X8_C(0x0af), /* display on */
+
+    U8X8_C(0x0b0), /* set page address */
+    U8X8_C(0x01f), /* set column address upper */
+    U8X8_C(0x000), /* set column address lower */
+
+    U8X8_END_TRANSFER(), /* disable chip */
+    U8X8_END()           /* end of sequence */  
+};
+
+uint8_t u8x8_d_s1d15300_lm6023(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  /* call common procedure first and handle messages there */
+  if ( u8x8_d_s1d15300_common(u8x8, msg, arg_int, arg_ptr) == 0 )
+  {
+    /* msg not handled, then try here */
+    switch(msg)
+    {
+      case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+	u8x8_d_helper_display_setup_memory(u8x8, &u8x8_s1d15300_lm6023_display_info);
+	break;
+      case U8X8_MSG_DISPLAY_INIT:
+	u8x8_d_helper_display_init(u8x8);
+	u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_lm6023_init_seq);
+	break;
+      case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+	if ( arg_int == 0 )
+	{
+	  u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip0_seq);
+	  u8x8->x_offset = u8x8->display_info->default_x_offset;
+	}
+	else
+	{
+	  u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip1_seq);
+	  u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+	}	
+	break;
+      default:
+	return 0;		/* msg unknown */
+    }
+  }
+  return 1;
+}
+
+/*================================================*/
+
+

+ 5 - 1
components/u8g2/u8x8_d_s1d15721.c

@@ -87,6 +87,10 @@ uint8_t u8x8_d_s1d15721_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
       u8x8_cad_SendCmd(u8x8, 0x13);	/* col */
       u8x8_cad_SendArg(u8x8, x);
 
+      /* 4 Mar 2022: added the missing page address, issue 1802 */
+      u8x8_cad_SendCmd(u8x8, 0xb1);	/* page address */
+      u8x8_cad_SendArg(u8x8, y);
+
 	  u8x8_cad_SendCmd(u8x8, 0x1D );	//Data Write
 
       c = ((u8x8_tile_t *)arg_ptr)->cnt;
@@ -157,7 +161,7 @@ static const u8x8_display_info_t u8x8_s1d15721_240x64_display_info =
   /* data_setup_time_ns = */ 30,	         /*  */
   /* write_pulse_width_ns = */ 65,	/* */
   /* tile_width = */ 30,		                /* width of 20*8=160 pixel (30*8 = 240) */
-  /* tile_hight = */ 8,                 /* height 8*8 = 64*/
+  /* tile_height = */ 8,                 /* height 8*8 = 64*/
   /* default_x_offset = */ 1,	
   /* flipmode_x_offset = */ 1,	
   /* pixel_width = */ 240,

+ 1 - 1
components/u8g2/u8x8_d_s1d15e06.c

@@ -157,7 +157,7 @@ static const u8x8_display_info_t u8x8_s1d15e06_160100_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1608 datasheet, page 39 */
   /* write_pulse_width_ns = */ 65,	/* uc1608 datasheet, page 39 */
   /* tile_width = */ 20,		/* width of 20*8=160 pixel */
-  /* tile_hight = */ 13,
+  /* tile_height = */ 13,
   /* default_x_offset = */ 0,	/* reused as y page offset */
   /* flipmode_x_offset = */ 0,	/* reused as y page offset */
   /* pixel_width = */ 160,

+ 1 - 1
components/u8g2/u8x8_d_sbn1661.c

@@ -128,7 +128,7 @@ static const u8x8_display_info_t u8x8_sbn1661_122x32_display_info =
   /* data_setup_time_ns = */ 200,
   /* write_pulse_width_ns = */ 200,	/*  */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 122,

+ 185 - 2
components/u8g2/u8x8_d_sed1330.c

@@ -141,7 +141,7 @@ static const u8x8_display_info_t u8x8_sed1330_240x128_display_info =
   /* data_setup_time_ns = */ 120,		/* G242CX Datasheet p5 */
   /* write_pulse_width_ns = */ 220,		/* G242CX Datasheet p5 */
   /* tile_width = */ 0x01e,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 240,
@@ -286,7 +286,7 @@ static const u8x8_display_info_t u8x8_sed1330_320x240_display_info =
   /* data_setup_time_ns = */ 120,		/* G242CX Datasheet p5 */
   /* write_pulse_width_ns = */ 220,		/* G242CX Datasheet p5 */
   /* tile_width = */ 40,
-  /* tile_hight = */ 30,
+  /* tile_height = */ 30,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 320,
@@ -349,3 +349,186 @@ uint8_t u8x8_d_ra8835_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *
   }
   return 1;
 }
+
+/*=============================================*/
+/*
+https://github.com/olikraus/u8g2/issues/1908
+https://www.allelectronics.com/mas_assets/media/allelectronics2018/spec/LCD-101.pdf
+*/
+
+static const u8x8_display_info_t u8x8_sed1330_256x128_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 30,	/* G242CX Datasheet p5 */
+  /* pre_chip_disable_wait_ns = */ 10,	/* G242CX Datasheet p5 */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 6, 
+  /* sda_setup_time_ns = */ 20,		
+  /* sck_pulse_width_ns = */  140,	
+  /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 120,		/* G242CX Datasheet p5 */
+  /* write_pulse_width_ns = */ 220,		/* G242CX Datasheet p5 */
+  /* tile_width = */ 32,
+  /* tile_height = */ 16,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 256,
+  /* pixel_height = */ 128
+};
+
+
+/* 256x128 Hyundai HG25604  (HG25504???) */
+static const uint8_t u8x8_d_sed1330_256x128_init_seq[] = {
+  U8X8_DLY(100),
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_DLY(100),
+
+  /* system init command, see also u8x8_d_sed1330_powersave0_seq */
+  U8X8_CA(0x040, 0x030),		/* sys init (0x040) with one arg, where 0x030 is a wild guess */
+  /* system init has total 8 parameters, so 7 more are here */
+  U8X8_A(0x087),				/* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
+  U8X8_A(0x007),				/* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
+  U8X8_A(0x01f),		/* 32-1*/  /* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
+  U8X8_A(0x050),					/* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
+  U8X8_A(0x080),				/* L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
+  U8X8_A(0x020),		/* 32 */	/* Low byte of the virtual screen size. (Value confirmed with app notes p41)   */
+  U8X8_A(0),					/* High byte of the virtual screen size, see also section 9.1.2 */
+	
+  U8X8_C(0x044),				/* SCROLL, 11 Bytes in total */
+  U8X8_A(0x000),				
+  U8X8_A(0x000),				
+  U8X8_A(0x080),
+  U8X8_A(0x000),
+  U8X8_A(0x040),
+  U8X8_A(0x080),
+  U8X8_A(0x000),
+  U8X8_A(0x000),
+  U8X8_A(0x000),
+  U8X8_A(0x000),
+	
+  U8X8_CA(0x05a, 0),			/* HDOT SCR: Horizontal dotwise scroll... set to 0 */
+	
+  U8X8_CA(0x05b, 0x0c),			/* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
+
+
+  U8X8_DLY(100),
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_DLY(100),
+};
+
+uint8_t u8x8_d_sed1330_256x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_256x128_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_256x128_init_seq);
+      break;
+    default:
+      return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}
+
+
+
+
+
+
+
+/*=============================================*/
+
+/*
+https://github.com/olikraus/u8g2/issues/1086
+*/
+
+static const u8x8_display_info_t u8x8_sed1330_320x200_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 30,	/* G242CX Datasheet p5 */
+  /* pre_chip_disable_wait_ns = */ 10,	/* G242CX Datasheet p5 */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 6, 
+  /* sda_setup_time_ns = */ 20,		
+  /* sck_pulse_width_ns = */  140,	
+  /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 120,		/* G242CX Datasheet p5 */
+  /* write_pulse_width_ns = */ 220,		/* G242CX Datasheet p5 */
+  /* tile_width = */ 40,
+  /* tile_height = */ 25,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 320,
+  /* pixel_height = */ 200
+};
+
+static const uint8_t u8x8_d_sed1330_320x200_init_seq[] = {
+  U8X8_DLY(100),
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_DLY(100),
+
+  /* system init command, see also u8x8_d_sed1330_powersave0_seq */
+  U8X8_CA(0x040, 0x030),		/* sys init (0x040) with one arg, where 0x030 is a wild guess */
+  /* system init has total 8 parameters, so 7 more are here */
+	
+  U8X8_A(0x087),				/* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
+  U8X8_A(0x007),				/* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
+  U8X8_A(0x027),	/* 40-1 */		/* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
+  U8X8_A(0x02F),				/* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
+  U8X8_A(0x0c7),				/* 0xc7=199, L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
+  U8X8_A(0x028),				/* Low byte of the virtual screen size. (Value confirmed with app notes p41)   */
+  U8X8_A(0x000),				/* High byte of the virtual screen size, see also section 9.1.2 */
+	
+  U8X8_C(0x044),				/* SCROLL, 11 Bytes in total */
+  U8X8_A(0x000),				/* Screen 1 Start Address (Low) = 00H */
+  U8X8_A(0x000),				/* Screen 1 Start Address (High) = 00H */
+  U8X8_A(0x0c7),                                /* Screen Layer 1 Number of lines = 200d */ 
+  U8X8_A(0x0b0),                                /* Screen 2 Start Address (Low) = 00H */
+  U8X8_A(0x005),                                /* Screen 2 Start Address (High) = 00H */
+  U8X8_A(0x0c7),                                /* Screen Layer 2 Number of lines = 200d */
+  U8X8_C(0x04C),                                /* Cursor Direction 0,0 Shift Direction = Right */
+  U8X8_A(0x000),
+  U8X8_A(0x000),
+  U8X8_A(0x000),
+
+  U8X8_CA(0x05a, 0),			/* HDOT SCR: Horizontal dotwise scroll... set to 0 */
+	
+  U8X8_CA(0x05b, 0x0c),			/* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
+
+
+  U8X8_DLY(100),
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_DLY(100),
+};
+
+
+
+uint8_t u8x8_d_sed1330_320x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_320x200_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_320x200_init_seq);
+      break;
+    default:
+      return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}
+
+

+ 1 - 1
components/u8g2/u8x8_d_sh1106_64x32.c

@@ -189,7 +189,7 @@ static const u8x8_display_info_t u8x8_sh1106_64x32_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 8,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 32,
   /* flipmode_x_offset = */ 36,
   /* pixel_width = */ 64,

+ 1 - 1
components/u8g2/u8x8_d_sh1106_72x40.c

@@ -189,7 +189,7 @@ static const u8x8_display_info_t u8x8_sh1106_72x40_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 9,
-  /* tile_hight = */ 5,
+  /* tile_height = */ 5,
   /* default_x_offset = */ 30,
   /* flipmode_x_offset = */ 30,
   /* pixel_width = */ 72,

+ 313 - 5
components/u8g2/u8x8_d_sh1107.c

@@ -70,6 +70,87 @@ static const uint8_t u8x8_d_sh1107_64x128_noname_flip1_seq[] = {
   U8X8_END()             			/* end of sequence */
 };
 
+static uint8_t u8x8_d_sh1107_HJR_OEL1M0201_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1107_64x128_noname_display_info);
+      break;
+    */
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_init_seq);    
+      break;
+    */
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* sh1107 has range from 0 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x *= 8;
+      x += u8x8->x_offset;
+
+      //u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
+
+      // set column address
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4));
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x & 15))); /* probably wrong, should be SendCmd */
+      
+      // set page address
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (2+(((u8x8_tile_t *)arg_ptr)->y_pos)));  /* probably wrong, should be SendCmd */
+    
+      do
+      {
+	c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+	u8x8_cad_SendData(u8x8, c*8, ptr); 	/* note: SendData can not handle more than 255 bytes */
+	/*
+	do
+	{
+	  u8x8_cad_SendData(u8x8, 8, ptr);
+	  ptr += 8;
+	  c--;
+	} while( c > 0 );
+	*/
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
 
 static uint8_t u8x8_d_sh1107_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
@@ -288,7 +369,7 @@ static const u8x8_display_info_t u8x8_sh1107_seeed_96x96_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* sh1107: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 12,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 96,
@@ -317,6 +398,70 @@ uint8_t u8x8_d_sh1107_seeed_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, vo
 }
 
 
+
+
+static const uint8_t u8x8_d_sh1107_HJR_OEL1M0201_96x96_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+
+	U8X8_C(0xAE),//
+	
+	U8X8_C(0x0F),//
+	U8X8_C(0x17),//
+	
+	
+	U8X8_C(0xD9),//
+	U8X8_C(0x89), //
+	
+  U8X8_CA(0x0d3, 0x000),		/* display offset */
+  U8X8_CA(0x0dc, 0x070),		/* start line */
+	
+  U8X8_C(0x0a0),				/* segment remap a0/a1 A0��??A1?���?a|��1D����*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+	
+	U8X8_C(0xD5),//
+	U8X8_C(0xB0),//
+	
+	U8X8_C(0x20),//
+	
+	U8X8_C(0xDB),//
+	U8X8_C(0x35),//
+	
+	U8X8_C(0x81),//
+	
+	U8X8_C(0xC7),//
+	
+	U8X8_C(0xA4),//A5����????��
+	
+	U8X8_C(0xA6),//A6��??A7?���?a?��??��|?
+	
+	U8X8_C(0xAD),//
+	U8X8_C(0x80),//
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+uint8_t u8x8_d_sh1107_hjr_oel1m0201_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{ 
+  if ( u8x8_d_sh1107_HJR_OEL1M0201_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_HJR_OEL1M0201_96x96_init_seq);    
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1107_seeed_96x96_display_info);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
 /*==================================================*/
 /* 128x128 OLED: this display has a very strange x offset */
 
@@ -370,7 +515,7 @@ static const u8x8_display_info_t u8x8_sh1107_128x128_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* sh1107: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 96,
   /* flipmode_x_offset = */ 96,
   /* pixel_width = */ 128,
@@ -421,7 +566,7 @@ static const u8x8_display_info_t u8x8_sh1107_128x80_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* sh1107: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 10,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 24,
   /* flipmode_x_offset = */ 24,
   /* pixel_width = */ 80,
@@ -469,7 +614,7 @@ static const u8x8_display_info_t u8x8_sh1107_pimoroni_128x128_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* sh1107: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -523,7 +668,7 @@ static const u8x8_display_info_t u8x8_seeed_128x128_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* sh1107: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -550,3 +695,166 @@ uint8_t u8x8_d_sh1107_seeed_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
   }
   return 1;
 }
+static const uint8_t u8x8_d_sh1107_80x128_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0xAE), /*display off*/
+	U8X8_C(0x00), /*set lower column address*/
+	U8X8_C(0x10), /*set higher column address*/
+	U8X8_C(0x20), /* Set Memory addressing mode (0x20/0x21) */
+	U8X8_C(0x81), /*contract control*/
+	U8X8_C(0x6f), /*b0*/
+	U8X8_C(0xA0), /*set segment remap*/
+	U8X8_C(0xC0), /*Com scan direction*/
+	U8X8_C(0xA4), /*Disable Entire Display On (0xA4/0xA5)*/
+	U8X8_C(0xA6), /*normal / reverse*/
+	U8X8_C(0xD5), /*set osc division*/
+	U8X8_C(0x91),
+	U8X8_C(0xD9), /*set pre-charge period*/
+	U8X8_C(0x22),
+	U8X8_C(0xdb), /*set vcomh*/
+	U8X8_C(0x3f),
+	U8X8_C(0xA8), /*multiplex ratio*/
+	U8X8_C(0x4F), /*duty = 1/80*/
+	U8X8_C(0xD3), /*set display offset*/
+	U8X8_C(0x68), /*18*/
+	U8X8_C(0xdc), /*Set Display Start Line*/
+	U8X8_C(0x00),
+	U8X8_C(0xad), /*set charge pump enable*/
+	U8X8_C(0x8a), /*Set DC-DC enable (a=0:disable, a=1:enable) */
+//	OLED_Clear(),
+	U8X8_C(0xAF), /*display ON*/ 
+ 
+
+
+  //U8X8_CA(0x0dc, 0x000),		/* start line */
+ // U8X8_CA(0x081, 0x02f), 		/* [2] set contrast control */
+
+
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+static uint8_t u8x8_d_sh1107_TK078F288_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1107_64x128_noname_display_info);
+      break;
+    */
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_init_seq);    
+      break;
+    */
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_64x128_noname_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* sh1107 has range from 0 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x *= 8;
+      x += u8x8->x_offset;
+
+      //u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
+
+      // set column address
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4));
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x & 15))); /* probably wrong, should be SendCmd */
+      
+      // set page address
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));  /* probably wrong, should be SendCmd */
+    
+      do
+      {
+	c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+	u8x8_cad_SendData(u8x8, c*8, ptr); 	/* note: SendData can not handle more than 255 bytes */
+	/*
+	do
+	{
+	  u8x8_cad_SendData(u8x8, 8, ptr);
+	  ptr += 8;
+	  c--;
+	} while( c > 0 );
+	*/
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+static const u8x8_display_info_t u8x8_TK078F288_80x128_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* */
+  /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 100,		/* cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 100,	/* cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 2,		// 400kHz does not work, but 200kHz seems to be ok
+  /* data_setup_time_ns = */ 40,
+  /* write_pulse_width_ns = */ 150,	/* sh1107: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 10,
+  /* tile_height = */ 16,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 80,
+  /* pixel_height = */ 128
+};
+uint8_t u8x8_d_sh1107_tk078f288_80x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    
+  if ( u8x8_d_sh1107_TK078F288_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_sh1107_80x128_init_seq); 
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_TK078F288_80x128_display_info);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}

+ 74 - 0
components/u8g2/u8x8_d_sh1108.c

@@ -223,3 +223,77 @@ uint8_t u8x8_d_sh1108_160x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *
 }
 
 /*==================================================*/
+
+
+/* issue #1998, 128x160 OLED */
+static const uint8_t u8x8_d_sh1108_128x160_noname_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+    
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_CA(0x0d5, 0x060),		/* clock divide ratio and oscillator frequency */
+  U8X8_CA(0x0a9, 0x003), 		/* set display resolution, 0=64x160, 1=96x160, 2=128x160, 3=160x160 */
+  U8X8_C(0x020),		                /* addressing mode */
+  U8X8_CA(0x081, 0x01f), 		/* set contrast control */
+  U8X8_CA(0x0ad, 0x80),			/* DC/DC control 80=Use external Vpp, 89=Use internal DC/DC*/
+  U8X8_C(0x030),				/* set discharge VSL level, 0x030..0x03f */
+  U8X8_CA(0x0d9, 0x028), 		/* pre-charge period */
+  U8X8_CA(0x0db, 0x035), 		/* vcomh deselect level */    
+  U8X8_CA(0x0dc, 0x035),		/* VSEGM Deselect Level */
+
+  U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  
+  U8X8_C(0x0a4),				/* output ram to display */
+  U8X8_C(0x0a6),				/* none inverted normal display mode */
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const u8x8_display_info_t u8x8_sh1108_128x160_noname_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 60,
+  /* pre_chip_disable_wait_ns = */ 120,
+  /* reset_pulse_width_ms = */ 100, 	/* sh1108: 3 us */
+  /* post_reset_wait_ms = */ 100, /* sometimes OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 100,		/* sh1108: 100ns */
+  /* sck_pulse_width_ns = */ 100,	/* sh1108: 100ns */
+  /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,
+  /* write_pulse_width_ns = */ 150,	/* sh1108: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 16,
+  /* tile_height = */ 20,
+  /* default_x_offset = */ 16,
+  /* flipmode_x_offset = */ 16,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 160
+};
+
+uint8_t u8x8_d_sh1108_128x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    
+  if ( u8x8_d_sh1108_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_sh1108_128x160_noname_init_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1108_128x160_noname_display_info);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+/*==================================================*/

+ 7 - 4
components/u8g2/u8x8_d_sh1122.c

@@ -32,8 +32,11 @@
   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 
 
-  Copied from sh1122 mostly because of the similar RAM architecture.
-  However: Commands are very different!
+  Idea: SH1122 is a horizontal device, which doesn't support u8x8
+  However in the similar SSD1362 device, we do the correct tile conversion,
+    so maybe takeover code from SSD1362 to SH1122, so that SH1122 can also
+    support u8x8
+
   
 */
 #include "u8x8.h"
@@ -147,7 +150,7 @@ uint8_t u8x8_d_sh1122_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
     case U8X8_MSG_DISPLAY_DRAW_TILE:
       u8x8_cad_StartTransfer(u8x8);
       x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
-      x *= 2;		// only every 4th col can be addressed
+      x *= 2;		// 4 Mar 2022: probably this needs to be 4, but this device is call with x=0 only
       x += u8x8->x_offset;		
     
       y = (((u8x8_tile_t *)arg_ptr)->y_pos);
@@ -219,7 +222,7 @@ static const u8x8_display_info_t u8x8_sh1122_256x64_display_info =
   /* data_setup_time_ns = */ 10,
   /* write_pulse_width_ns = */ 150,	/* sh1122: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 32,		/* 256 pixel, so we require 32 bytes for this */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 256,

+ 68 - 4
components/u8g2/u8x8_d_ssd1305.c

@@ -148,7 +148,7 @@ static const u8x8_display_info_t u8x8_ssd1305_128x32_noname_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 2,
   /* flipmode_x_offset = */ 2,
   /* pixel_width = */ 128,
@@ -224,6 +224,70 @@ uint8_t u8x8_d_ssd1305_128x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
   return 1;
 }
 
+/*================================================*/
+/* issue 2002: Waveshare */
+
+#ifdef SAME_AS_ADAFRUIT
+/* timing from SSD1306 */
+static const u8x8_display_info_t u8x8_ssd1305_128x32_waveshare_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* SSD1306: 3 us */
+  /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,
+  /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 16,
+  /* tile_height = */ 4,
+  /* default_x_offset = */ 4,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 32
+};
+
+uint8_t u8x8_d_ssd1305_128x32_waveshare(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    
+  if ( u8x8_d_ssd1305_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_noname_init_seq);    
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1305_128x32_waveshare_display_info);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+#endif
+
+
 /*================================================*/
 /* adafruit 128x32 SSD1305 OLED, https://www.adafruit.com/product/2675 */
 /* issue 724 */
@@ -246,7 +310,7 @@ static const u8x8_display_info_t u8x8_ssd1305_128x32_adafruit_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -311,7 +375,7 @@ static const u8x8_display_info_t u8x8_ssd1305_128x64_adafruit_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 2,
   /* flipmode_x_offset = */ 2,
   /* pixel_width = */ 128,
@@ -409,7 +473,7 @@ static const u8x8_display_info_t u8x8_ssd1305_128x64_raystar_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,

+ 3 - 3
components/u8g2/u8x8_d_ssd1306_128x32.c

@@ -194,7 +194,7 @@ static const u8x8_display_info_t u8x8_ssd1306_128x32_univision_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -234,7 +234,7 @@ static const u8x8_display_info_t u8x8_ssd1306_128x32_winstar_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 125,
   /* flipmode_x_offset = */ 125,
   /* pixel_width = */ 128,
@@ -297,7 +297,7 @@ static const u8x8_display_info_t u8x8_d_sh1106_128x32_visionox_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 2,
   /* flipmode_x_offset = */ 2,
   /* pixel_width = */ 128,

+ 82 - 3
components/u8g2/u8x8_d_ssd1306_128x64_noname.c

@@ -172,6 +172,38 @@ static const uint8_t u8x8_d_sh1106_128x64_winstar_init_seq[] = {
   U8X8_END()             			/* end of sequence */
 };
 
+static const uint8_t u8x8_d_ssd1312_128x64_noname_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_CA(0x0d5, 0x080),		/* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
+  U8X8_CA(0x0a8, 0x03f),		/* multiplex ratio */
+  U8X8_CA(0x0d3, 0x000),		/* display offset */
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  U8X8_CA(0x08d, 0x014),		/* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, SSD1306 only, should be removed for SH1106 */
+  U8X8_CA(0x020, 0x000),		/* horizontal addressing mode */
+  
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  
+  U8X8_CA(0x0da, 0x012),		/* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
+
+  U8X8_CA(0x081, 0x0cf), 		/* [2] set contrast control */
+  U8X8_CA(0x0d9, 0x0f1), 		/* [2] pre-charge period 0x022/f1*/
+  U8X8_CA(0x0db, 0x040), 		/* vcomh deselect level */  
+  // if vcomh is 0, then this will give the biggest range for contrast control issue #98
+  // restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
+  
+  U8X8_C(0x02e),				/* Deactivate scroll */ 
+  U8X8_C(0x0a4),				/* output ram to display */
+  U8X8_C(0x0a6),				/* none inverted normal display mode */
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
 
 static const uint8_t u8x8_d_ssd1306_128x64_noname_powersave0_seq[] = {
   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
@@ -203,6 +235,21 @@ static const uint8_t u8x8_d_ssd1306_128x64_noname_flip1_seq[] = {
   U8X8_END()             			/* end of sequence */
 };
 
+static const uint8_t u8x8_d_ssd1312_128x64_noname_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1312_128x64_noname_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
 
 static uint8_t u8x8_d_ssd1306_sh1106_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
@@ -302,7 +349,7 @@ static const u8x8_display_info_t u8x8_ssd1306_128x64_noname_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -330,6 +377,38 @@ uint8_t u8x8_d_ssd1306_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
   return 1;
 }
 
+uint8_t u8x8_d_ssd1312_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1312_128x64_noname_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1312_128x64_noname_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1312_128x64_noname_init_seq);    /* update 27 mar 2022 */
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
+      break;
+    default:
+      if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+        return 1;
+  }
+  return 1;
+}
+
+
+
 uint8_t u8x8_d_ssd1306_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
     
@@ -385,12 +464,12 @@ static const u8x8_display_info_t u8x8_sh1106_128x64_noname_display_info =
   /* sda_setup_time_ns = */ 50,		/* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
   /* sck_pulse_width_ns = */ 50,	/* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
   /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
-  /* spi_mode = */ 3,		/* active low (clock is high by default), rising edge, this seems to be a difference to the ssd1306 */
+  /* spi_mode = */ 0,		/* issue 1901: changed mode from 3 to 0 */
   /* i2c_bus_clock_100kHz = */ 4,
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 2,
   /* flipmode_x_offset = */ 2,
   /* pixel_width = */ 128,

+ 1 - 1
components/u8g2/u8x8_d_ssd1306_64x32.c

@@ -155,7 +155,7 @@ static const u8x8_display_info_t u8x8_ssd1306_64x32_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 8,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 32,
   /* flipmode_x_offset = */ 32,
   /* pixel_width = */ 64,

+ 1 - 1
components/u8g2/u8x8_d_ssd1306_64x48.c

@@ -186,7 +186,7 @@ static const u8x8_display_info_t u8x8_ssd1306_64x48_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 8,
-  /* tile_hight = */ 6,
+  /* tile_height = */ 6,
   /* default_x_offset = */ 32,
   /* flipmode_x_offset = */ 32,
   /* pixel_width = */ 64,

+ 1 - 1
components/u8g2/u8x8_d_ssd1306_72x40.c

@@ -236,7 +236,7 @@ static const u8x8_display_info_t u8x8_ssd1306_72x40_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 9,
-  /* tile_hight = */ 5,
+  /* tile_height = */ 5,
   /* default_x_offset = */ 28,
   /* flipmode_x_offset = */ 28,
   /* pixel_width = */ 72,

+ 1 - 1
components/u8g2/u8x8_d_ssd1306_96x16.c

@@ -186,7 +186,7 @@ static const u8x8_display_info_t u8x8_ssd1306_96x16_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 12,
-  /* tile_hight = */ 2,
+  /* tile_height = */ 2,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 32,
   /* pixel_width = */ 96,

+ 328 - 0
components/u8g2/u8x8_d_ssd1306_96x40.c

@@ -0,0 +1,328 @@
+/*
+
+  u8x8_d_ssd1306_96x40.c
+
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2016, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+  
+  takeover from 96x16 OLED
+  
+  21 Sep 2022: Also added the 96x39 variant here....
+  
+*/
+
+
+#include "u8x8.h"
+
+
+
+static const uint8_t u8x8_d_ssd1306_96x40_powersave0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0af),		                /* display on */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1306_96x40_powersave1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1306_96x40_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1306_96x40_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+static uint8_t u8x8_d_ssd1306_96x40_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* handled by the calling function
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_96x40_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x40_er_init_seq);    
+      break;
+    */
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x40_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x40_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x40_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x40_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* ssd1306 has range from 0 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x *= 8;
+      x += u8x8->x_offset;
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
+      
+      do
+      {
+	c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+	u8x8_cad_SendData(u8x8, c*8, ptr); 	/* note: SendData can not handle more than 255 bytes */
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+/*===============================================*/
+
+/* https://github.com/olikraus/u8g2/issues/1812 */
+static const uint8_t u8x8_d_ssd1306_96x40_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_CA(0x0d5, 0x080),		/* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
+  U8X8_CA(0x0a8, 0x027),		/* multiplex ratio */
+  U8X8_CA(0x0d3, 0x000),		/* display offset  */
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  U8X8_CA(0x08d, 0x014),		/* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, 0.66 OLED  0x14*/
+  U8X8_CA(0x020, 0x000),		/* horizontal addressing mode */
+  
+  U8X8_C(0x0a1),				/* segment remap a0/a1, 0.66 OLED  */
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse, 0.66 OLED  */
+  // Flipmode
+  // U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  // U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  
+  U8X8_CA(0x0da, 0x002),		/* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.66 OLED */
+  U8X8_CA(0x081, 0x0af),		/* [2] set contrast control */
+  U8X8_CA(0x0d9, 0x0f1),		/* [2] pre-charge period 0x0f1 */
+  U8X8_CA(0x0db, 0x020),		/* vcomh deselect level */
+  
+  U8X8_C(0x02e),				/* Deactivate scroll */ 
+  U8X8_C(0x0a4),				/* output ram to display */
+  U8X8_C(0x0a6),				/* none inverted normal display mode */
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+
+static const u8x8_display_info_t u8x8_ssd1306_96x40_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* SSD1306: 3 us */
+  /* post_reset_wait_ms = */ 100, 	/* OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 8000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,
+  /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 12,
+  /* tile_height = */ 5,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 32,
+  /* pixel_width = */ 96,
+  /* pixel_height = */ 40
+};
+
+uint8_t u8x8_d_ssd1306_96x40(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
+    {
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_96x40_display_info);
+      return 1;
+    }
+    else if ( msg == U8X8_MSG_DISPLAY_INIT )
+    {
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x40_init_seq);    
+      return 1;
+    }
+    return u8x8_d_ssd1306_96x40_generic(u8x8, msg, arg_int, arg_ptr);
+}
+
+/*===============================================*/
+
+/* 96x39 OLED */
+/* https://github.com/olikraus/u8g2/issues/1959 */
+static const uint8_t u8x8_d_ssd1306_96x39_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_CA(0x0d5, 0x080),		/* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
+  U8X8_CA(0x0a8, 0x027),		/* multiplex ratio */
+  U8X8_CA(0x0d3, 0),		        /* display offset, issue 1959 */
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  U8X8_CA(0x08d, 0x014),		/* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, 0.66 OLED  0x14*/
+  U8X8_CA(0x020, 0x000),		/* horizontal addressing mode */
+  
+  U8X8_C(0x0a1),				/* segment remap a0/a1, 0.66 OLED  */
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse, 0.66 OLED  */
+  // Flipmode
+  // U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  // U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  
+  U8X8_CA(0x0da, 0x010),		/* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), issue 1959: 0x010 */
+  U8X8_CA(0x081, 0x0af),		/* [2] set contrast control */
+  U8X8_CA(0x0d9, 0x0f1),		/* [2] pre-charge period 0x0f1 */
+  U8X8_CA(0x0db, 0x020),		/* vcomh deselect level */
+  
+  U8X8_C(0x02e),				/* Deactivate scroll */ 
+  U8X8_C(0x0a4),				/* output ram to display */
+  U8X8_C(0x0a6),				/* none inverted normal display mode */
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1306_96x39_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse */
+  U8X8_C(0x07f),		                /* set display start line to -1 (not exactly sure why...) */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1306_96x39_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+static const u8x8_display_info_t u8x8_ssd1306_96x39_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* SSD1306: 3 us */
+  /* post_reset_wait_ms = */ 100, 	/* OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 8000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,
+  /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 12,
+  /* tile_height = */ 5,
+  /* default_x_offset = */ 32,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 96,
+  /* pixel_height = */ 39
+};
+
+uint8_t u8x8_d_ssd1306_96x39(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
+    {
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_96x39_display_info);
+      return 1;
+    }
+    else if ( msg == U8X8_MSG_DISPLAY_INIT )
+    {
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x39_init_seq);    
+      return 1;
+    }
+    else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
+    {
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x39_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x39_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+    }
+    return u8x8_d_ssd1306_96x40_generic(u8x8, msg, arg_int, arg_ptr);
+}
+
+/*===============================================*/
+

+ 3 - 3
components/u8g2/u8x8_d_ssd1309.c

@@ -148,7 +148,7 @@ static const u8x8_display_info_t u8x8_ssd1309_128x64_noname2_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 2,
   /* flipmode_x_offset = */ 2,
   /* pixel_width = */ 128,
@@ -247,7 +247,7 @@ static const u8x8_display_info_t u8x8_ssd1309_128x64_noname0_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -335,7 +335,7 @@ static const u8x8_display_info_t u8x8_ssd1309_102x64_ea_oleds102_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 13,  /* width of 13*8=104 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 13, 
   /* flipmode_x_offset = */ 13,
   /* pixel_width = */ 102,

+ 97 - 1
components/u8g2/u8x8_d_ssd1316.c

@@ -207,7 +207,7 @@ static const u8x8_display_info_t u8x8_ssd1316_128x32_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -234,3 +234,99 @@ uint8_t u8x8_d_ssd1316_128x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *
   }
   return 1;
 }
+
+
+/*===================================================*/
+/*
+QG-9632TLBZG02
+https://datasheet.lcsc.com/lcsc/1804162033_Shenzhen-Allvision-Tech-QG-9632TLBZG02_C91216.pdf
+https://github.com/olikraus/u8g2/issues/1938
+
+96x32
+*/
+
+static const uint8_t u8x8_d_ssd1316_96x32_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  
+  U8X8_C(0x0ae),		        /* display off */
+  U8X8_C(0x040),		        /* start line */
+  U8X8_CA(0x081, 0x045), 		/* QG-2832TSWZG02 datasheet: 0x081, 0x45 */
+                                                        /* QG-9632: 0x81, 0x60 */
+
+  U8X8_C(0x0a6),			/* none inverted normal display mode */
+  U8X8_CA(0x0a8, 0x01f),		/* multiplex ratio, duty = 1/32 */
+
+  U8X8_C(0x0a1),			/* segment remap a0/a1*/
+  U8X8_C(0x0c0),			/* c0: scan dir normal, c8: reverse */
+
+  U8X8_CA(0x0d3, 0x000),		/* display offset */
+  U8X8_CA(0x0d5, 0x080),		/* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
+  U8X8_CA(0x0d9, 0x022), 		/* [2] pre-charge period 0x022/f1*/
+  U8X8_CA(0x0da, 0x012),		/* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
+  U8X8_CA(0x0db, 0x020), 		/* vcomh deselect level */  
+  U8X8_CA(0x08d, 0x015),		/* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, */
+                                                        /* QG-9632: 0x8d, 0x10 */
+  
+  //U8X8_CA(0x0a2, 0x000),		/* set display start line to 0 */
+  //U8X8_CA(0x020, 0x000),		/* horizontal addressing mode */
+  
+  
+  // Flipmode
+  //U8X8_C(0x0a1),			/* segment remap a0/a1*/
+  //U8X8_C(0x0c0),			/* c0: scan dir normal, c8: reverse */
+  
+  U8X8_C(0x02e),			/* Deactivate scroll */ 
+  //U8X8_C(0x0a4),			/* output ram to display */
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()           			/* end of sequence */
+};
+
+
+static const u8x8_display_info_t u8x8_ssd1316_96x32_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* reset time */
+  /* post_reset_wait_ms = */ 100, /* reset delay */
+  /* sda_setup_time_ns = */ 50,		/* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 8000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,
+  /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 12,
+  /* tile_height = */ 4,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 96,
+  /* pixel_height = */ 32
+};
+
+uint8_t u8x8_d_ssd1316_96x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+    
+  if ( u8x8_d_ssd1316_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1316_96x32_init_seq);    
+      break;
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1316_96x32_display_info);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+

+ 1 - 1
components/u8g2/u8x8_d_ssd1317.c

@@ -212,7 +212,7 @@ static const u8x8_display_info_t u8x8_ssd1317_96x96_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 12,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 16,
   /* flipmode_x_offset = */ 16,
   /* pixel_width = */ 96,

+ 1 - 1
components/u8g2/u8x8_d_ssd1318.c

@@ -267,7 +267,7 @@ static const u8x8_display_info_t u8x8_ssd1318_128x96_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	/* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,

+ 266 - 38
components/u8g2/u8x8_d_ssd1320.c

@@ -40,7 +40,10 @@
   Adapted from u8x8_d_ssd1322.c with the command set of the SSD1320 controller
   "official" procedure is described here: https://github.com/olikraus/u8g2/wiki/internal
   
-  NOTE: U8x8 does NOT work!
+  NOTE: U8x8 does NOT work! --> not clear, needs to be checked
+  
+  
+  https://github.com/olikraus/u8g2/issues/1816
   
 */
 
@@ -67,12 +70,12 @@ static const uint8_t u8x8_d_ssd1320_cs1_160x132_nhd_powersave1_seq[] = {
   output:
     Tile for SSD1320 (32 Bytes)
 
-  The origin of the display seems to be in the upper right-hand corner. Therefore
-  compared to SSD1322, the order inside each byte is swapped.
 */
 
 static uint8_t u8x8_ssd1320_to32_dest_buf[32];
 
+
+
 static uint8_t *u8x8_ssd1320_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
 {
   uint8_t v;
@@ -98,12 +101,10 @@ static uint8_t *u8x8_ssd1320_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
       a >>= 1;
       b >>= 1;
     }
-  }
-  
+  }  
   return u8x8_ssd1320_to32_dest_buf;
 }
 
-
 uint8_t u8x8_d_ssd1320_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
   uint8_t x; 
@@ -178,6 +179,113 @@ uint8_t u8x8_d_ssd1320_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *
   return 1;
 }
 
+
+
+
+static uint8_t *u8x8_ssd1320_8to32_2(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
+{
+  uint8_t v;
+  uint8_t a,b;
+  uint8_t i, j;
+  uint8_t *dest;
+  
+  for( j = 0; j < 4; j++ )
+  {
+    dest = u8x8_ssd1320_to32_dest_buf;
+    dest += j;
+    a =*ptr;
+    ptr++;
+    b = *ptr;
+    ptr++;
+    for( i = 0; i < 8; i++ )
+    {
+      v = 0;
+      if ( a&1 ) v |= 0xf0;     // changed from 0x0f to 0xf0, https://github.com/olikraus/u8g2/issues/1816
+      if ( b&1 ) v |= 0x0f;     // changed from 0xf0 to 0x0f, https://github.com/olikraus/u8g2/issues/1816
+      *dest = v;
+      dest+=4;
+      a >>= 1;
+      b >>= 1;
+    }
+  }
+  return u8x8_ssd1320_to32_dest_buf;
+}
+
+uint8_t u8x8_d_ssd1320_common_2(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x; 
+  uint8_t y, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
+    /*
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1320_256x64_init_seq);
+      break;
+    */
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1320_cs1_160x132_nhd_powersave0_seq);
+      else
+	      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1320_cs1_160x132_nhd_powersave1_seq);
+      break;
+
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* ssd1320 has range from 1 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      y = (((u8x8_tile_t *)arg_ptr)->y_pos);
+      x += u8x8->x_offset;		
+    
+      y *= 8;
+    
+      
+      u8x8_cad_SendCmd(u8x8, 0x022 );	/* set row address, moved out of the loop (issue 302) */
+      u8x8_cad_SendArg(u8x8, y);
+      u8x8_cad_SendArg(u8x8, y+7);
+      
+      do {
+	      c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	      ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+
+        do {
+          u8x8_cad_SendCmd(u8x8, 0x021 );	/* set column address */
+          u8x8_cad_SendArg(u8x8, x );	/* start */
+          u8x8_cad_SendArg(u8x8, x+3 );	/* end */
+          
+          u8x8_cad_SendData(u8x8, 32, u8x8_ssd1320_8to32_2(u8x8, ptr));
+          
+          ptr += 8;
+          x += 4;
+          c--;
+        } while( c > 0 );
+      
+      //x += 2;
+      arg_int--;
+    } while( arg_int > 0 );
+    
+    u8x8_cad_EndTransfer(u8x8);
+    break;
+
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+
 /*=========================================================*/
 /* 160x32 */
 
@@ -212,7 +320,7 @@ static const u8x8_display_info_t u8x8_d_ssd1320_cs1_160x32_display_info =
   /* data_setup_time_ns = */ 10,
   /* write_pulse_width_ns = */ 150,	/* ssd1320: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 20,		/* 160 pixel, so we require 20 bytes for this */
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 160,
@@ -327,7 +435,7 @@ static const u8x8_display_info_t u8x8_d_ssd1320_cs1_160x132_display_info =
   /* data_setup_time_ns = */ 10,
   /* write_pulse_width_ns = */ 150,	/* ssd1320: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 20,		/* 160 pixel, so we require 20 bytes for this */
-  /* tile_hight = */ 17,
+  /* tile_height = */ 17,
   /* default_x_offset = */ 0,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 160,
@@ -336,42 +444,45 @@ static const u8x8_display_info_t u8x8_d_ssd1320_cs1_160x132_display_info =
 
 
 /* the following sequence will work, but requires contrast to be very high */
-// static const uint8_t u8x8_d_ssd1320_cs1_160x132_init_seq[] = {
+/* added #ifdef to avoid compiler warning, issue 1802 */
+#ifdef NOT_USED
+static const uint8_t u8x8_d_ssd1320_cs1_160x132_init_seq[] = {
     
-//     U8X8_DLY(1),
-//     U8X8_START_TRANSFER(),    /* enable chip, delay is part of the transfer start */
-//     U8X8_DLY(1),
+    U8X8_DLY(1),
+    U8X8_START_TRANSFER(),    /* enable chip, delay is part of the transfer start */
+    U8X8_DLY(1),
     
-//     U8X8_C(0xae),		          /* display off */
-//     U8X8_CA(0xd5, 0xC2),			/* set display clock divide ratio/oscillator frequency (set clock as 80 frames/sec)  */  
-//     U8X8_CA(0xa8, 0x83),			/* multiplex ratio 1/132 Duty  */  
-//     U8X8_CA(0xa2, 0x00),			/* display start line */  
+    U8X8_C(0xae),		          /* display off */
+    U8X8_CA(0xd5, 0xC2),			/* set display clock divide ratio/oscillator frequency (set clock as 80 frames/sec)  */  
+    U8X8_CA(0xa8, 0x83),			/* multiplex ratio 1/132 Duty  */  
+    U8X8_CA(0xa2, 0x00),			/* display start line */  
 
-//     U8X8_C(0xa0),	                /* Set Segment Re-Map: column address 0 mapped to SEG0  CS1 */ 
-//     // U8X8_C(0xa1),	                /* Set Segment Re-Map: column address 0 mapped to SEG0  CS2 */ 
+    U8X8_C(0xa0),	                /* Set Segment Re-Map: column address 0 mapped to SEG0  CS1 */ 
+    // U8X8_C(0xa1),	                /* Set Segment Re-Map: column address 0 mapped to SEG0  CS2 */ 
 
-//     U8X8_C(0xc8),	             /* Set COM Output Scan Direction: normal mode CS1 */
-//     // U8X8_C(0xc0),			        /* Set COM Output Scan Direction: normal mode CS2 */
+    U8X8_C(0xc8),	             /* Set COM Output Scan Direction: normal mode CS1 */
+    // U8X8_C(0xc0),			        /* Set COM Output Scan Direction: normal mode CS2 */
   
-//     U8X8_CA(0xd3, 0x0e),        /* CS1 */
-//     // U8X8_CA(0xd3, 0x92),        /* CS2 */
+    U8X8_CA(0xd3, 0x0e),        /* CS1 */
+    // U8X8_CA(0xd3, 0x92),        /* CS2 */
     
-//     U8X8_CA(0xda, 0x12),	    /* Set SEG Pins Hardware Configuration:  */  
-//     U8X8_CA(0x81, 0x5a),			/* contrast */  
-//     U8X8_CA(0xd9, 0x22),			/* Set Phase Length */  
-//     U8X8_CA(0xdb, 0x30),		  /* VCOMH Deselect Level */
-//     U8X8_CA(0xad, 0x10),			/* Internal IREF Enable */  
-//     U8X8_CA(0x20, 0x00),	    /* Memory Addressing Mode: Horizontal */  
-//     U8X8_CA(0x8d, 0x01),			/* disable internal charge pump 1 */  
-//     U8X8_CA(0xac, 0x00),			/* disable internal charge pump 2 */  
-//     U8X8_C(0xa4),		        	/* display on */  
-//     U8X8_C(0xa6),		          /* normal display */
-
-//     U8X8_DLY(1),					/* delay 2ms */
-
-//     U8X8_END_TRANSFER(),             	/* disable chip */
-//     U8X8_END()             			/* end of sequence */
-// };
+    U8X8_CA(0xda, 0x12),	    /* Set SEG Pins Hardware Configuration:  */  
+    U8X8_CA(0x81, 0x5a),			/* contrast */  
+    U8X8_CA(0xd9, 0x22),			/* Set Phase Length */  
+    U8X8_CA(0xdb, 0x30),		  /* VCOMH Deselect Level */
+    U8X8_CA(0xad, 0x10),			/* Internal IREF Enable */  
+    U8X8_CA(0x20, 0x00),	    /* Memory Addressing Mode: Horizontal */  
+    U8X8_CA(0x8d, 0x01),			/* disable internal charge pump 1 */  
+    U8X8_CA(0xac, 0x00),			/* disable internal charge pump 2 */  
+    U8X8_C(0xa4),		        	/* display on */  
+    U8X8_C(0xa6),		          /* normal display */
+
+    U8X8_DLY(1),					/* delay 2ms */
+
+    U8X8_END_TRANSFER(),             	/* disable chip */
+    U8X8_END()             			/* end of sequence */
+};
+#endif
 
 /*
 OLED_WR_Byte(0xae,OLED_CMD);//Display OFF
@@ -492,3 +603,120 @@ uint8_t u8x8_d_ssd1320_160x132(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
   return 1;
 }
 
+
+
+
+/*=========================================================*/
+/* https://github.com/olikraus/u8g2/issues/1816 */
+/* 160x80, https://de.aliexpress.com/item/1005003510267760.html */
+
+static const uint8_t u8x8_d_ssd1320_160x80_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a0),		/* remap */
+  U8X8_C(0xc8),	             /* Set COM Output Scan Direction: normal mode CS1 */
+  U8X8_CA(0xd3, 39),        /* display offset */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1320_160x80_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0a1),		/* remap */
+  U8X8_C(0xc0),	             /* Set COM Output Scan Direction: normal mode CS1 */
+  U8X8_CA(0xd3, 120),        /* display offset */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const u8x8_display_info_t u8x8_d_ssd1320_160x80_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* ssd1320: 2 us */
+  /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* ssd1320: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* ssd1320: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 10000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215), 10 MHz (issue 301) */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 10,
+  /* write_pulse_width_ns = */ 150,	/* ssd1320: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 20,		/* 160 pixel, so we require 20 bytes for this */
+  /* tile_height = */ 10,
+  /* default_x_offset = */ 0,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 160,
+  /* pixel_height = */ 80
+};
+
+
+
+static const uint8_t u8x8_d_ssd1320_160x80_init_seq[] = {
+    U8X8_DLY(1),
+    U8X8_START_TRANSFER(),    /* enable chip, delay is part of the transfer start */
+    U8X8_DLY(1),
+    
+    U8X8_C(0xae),		          /* display off */
+    U8X8_CA(0xa8, 80),	/* multiplex ratio 1/80 Duty  */  
+    U8X8_CA(0xa2, 0),	/* display start line */  
+
+    U8X8_C(0xa0),	                /* Set Segment Re-Map */
+    U8X8_C(0xc8),	             	/* Set COM Output Scan Direction: normal mode */
+
+    U8X8_CA(0xad, 0x10), 		/* select Iref: 0x00 external (reset default), 0x10 internal */
+    U8X8_CA(0xbc, 0x1e), 		/* pre-charge voltage level 0x00..0x1f, reset default: 0x1e */
+    U8X8_C(0xbf),		        	/* select linear LUT */  
+    U8X8_CA(0xd5, 0xc2), 		/* Bit 0..3: clock ratio 1, 2, 4, 8, ...256, reset=0x1, Bit 4..7: F_osc 0..15 */
+    U8X8_CA(0xd9, 0x72),		/* Set Phase 1&2 Length, Bit 0..3: Phase 1, Bit 4..7: Phase 2, reset default 0x72 */  
+
+    U8X8_CA(0xd3, 39),        /* display offset */
+    
+    U8X8_CA(0xda, 0x12),	/* Set SEG Pins Hardware Configuration:  */  
+    U8X8_CA(0x81, 0x70),			/* contrast */  
+    U8X8_CA(0x20, 0x00),	    /* Memory Addressing Mode: Horizontal */  
+    
+    U8X8_C(0xa4),		        	/* display RAM on */  
+    U8X8_C(0xa6),		          /* normal display */
+
+    U8X8_DLY(1),					/* delay 2ms */
+
+    U8X8_END_TRANSFER(),             	/* disable chip */
+    U8X8_END()             			/* end of sequence */
+};
+
+uint8_t u8x8_d_ssd1320_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  
+  if ( u8x8_d_ssd1320_common_2(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+        u8x8_d_helper_display_setup_memory(u8x8, &u8x8_d_ssd1320_160x80_display_info);
+      break;
+
+    case U8X8_MSG_DISPLAY_INIT:
+        u8x8_d_helper_display_init(u8x8);
+        u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1320_160x80_init_seq);
+      break;
+
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 ){
+        u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1320_160x80_flip0_seq);
+        u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else{
+        u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1320_160x80_flip1_seq);
+        u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+    
+    default:
+      break;
+  }
+  return 1;
+}

+ 122 - 2
components/u8g2/u8x8_d_ssd1322.c

@@ -256,7 +256,7 @@ static const u8x8_display_info_t u8x8_ssd1322_256x64_display_info =
   /* data_setup_time_ns = */ 10,
   /* write_pulse_width_ns = */ 150,	/* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 32,		/* 256 pixel, so we require 32 bytes for this */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0x01c,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
   /* flipmode_x_offset = */ 0x01c,
   /* pixel_width = */ 256,
@@ -330,6 +330,103 @@ uint8_t u8x8_d_ssd1322_nhd_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, vo
   return 1;
 }
 
+/*=========================================================*/
+/*
+https://github.com/olikraus/u8g2/issues/2092
+*/
+
+
+static const u8x8_display_info_t u8x8_ssd1322_240x128_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* SSD1322: 2 us */
+  /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* SSD1322: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* SSD1322: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 10000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215), 10 MHz (issue 301) */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 10,
+  /* write_pulse_width_ns = */ 150,	/* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 30,		/* 256 pixel, so we require 32 bytes for this */
+  /* tile_height = */ 16,
+  /* default_x_offset = */ 24,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
+  /* flipmode_x_offset = */ 0x000,
+  /* pixel_width = */ 240,
+  /* pixel_height = */ 128
+};
+
+
+static const uint8_t u8x8_d_ssd1322_240x128_init_seq[] = {
+    
+  U8X8_DLY(1),
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_DLY(1),
+  
+  U8X8_CA(0xfd, 0x12),            	/* unlock */
+  U8X8_C(0xae),		                /* display off */
+  U8X8_CA(0xb3, 0x91),			/* set display clock divide ratio/oscillator frequency (set clock as 80 frames/sec)  */  
+  U8X8_CA(0xca, 0x7f),			/* multiplex ratio 1/128 Duty (0x0F~0x7F) */  
+  U8X8_CA(0xa2, 0x00),			/* display offset, shift mapping ram counter */  
+  U8X8_CA(0xa1, 0x00),			/* display start line */  
+  //U8X8_CAA(0xa0, 0x14, 0x11),	/* Set Re-Map / Dual COM Line Mode */  
+  U8X8_CAA(0xa0, 0x36, 0x011),	/* Set Re-Map / Dual COM Line Mode */  
+  U8X8_CA(0xab, 0x01),			/* Enable Internal VDD Regulator */  
+  U8X8_CAA(0xb4, 0xa0, 0x005|0x0fd),	/* Display Enhancement A */  
+  U8X8_CA(0xc1, 0x9f),			/* contrast */  
+  U8X8_CA(0xc7, 0x0f),			/* Set Scale Factor of Segment Output Current Control */  
+  U8X8_C(0xb9),		                /* linear grayscale */
+  U8X8_CA(0xb1, 0xe2),			/* Phase 1 (Reset) & Phase 2 (Pre-Charge) Period Adjustment */  
+  U8X8_CAA(0xd1, 0x082|0x020, 0x020),	/* Display Enhancement B */  
+  U8X8_CA(0xbb, 0x1f),			/* precharge  voltage */  
+  U8X8_CA(0xb6, 0x08),			/* precharge  period */  
+  U8X8_CA(0xbe, 0x07),			/* vcomh */  
+  U8X8_C(0xa6),		                /* normal display */
+  U8X8_C(0xa9),		                /* exit partial display */
+
+
+  U8X8_DLY(1),					/* delay 2ms */
+
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+uint8_t u8x8_d_ssd1322_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1322_240x128_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_240x128_init_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+    
+    default:
+      return u8x8_d_ssd1322_common(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}
+
 /*=========================================================*/
 /* 
   NHD-2.7-12864WDW3-M 
@@ -454,7 +551,7 @@ static const u8x8_display_info_t u8x8_ssd1322_128x64_display_info =
   /* data_setup_time_ns = */ 10,
   /* write_pulse_width_ns = */ 150,	/* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
   /* tile_width = */ 16,		/* 128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 28,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
   /* flipmode_x_offset = */ 28,
   /* pixel_width = */ 128,
@@ -476,6 +573,29 @@ static const uint8_t u8x8_d_ssd1322_128x64_init_seq[] = {
 
   U8X8_CA(0xa1, 0x00),			/* display start line */  
   U8X8_CA(0xab, 0x01),			/* Enable Internal VDD Regulator */  
+/*
+	A[0]=0b, Horizontal address increment [reset]    ***
+	A[0]=1b, Vertical address increment
+	
+	A[1]=0b, Disable Column Address Re-map [reset]
+	A[1]=1b, Enable Column Address Re-map		***
+	
+	A[2]=0b, Disable Nibble Re-map [reset]
+	A[2]=1b, Enable Nibble Re-map			***
+	
+	A[4]=0b, Scan from COM0 to COM[N –1] [reset]	
+	A[4]=1b, Scan from COM[N-1] to COM0, where N is the	***
+	
+	Multiplex ratio
+	A[5]=0b, Disable COM Split Odd Even [reset]	***
+	A[5]=1b, Enable COM Split Odd Even
+	
+	B[4], Enable / disable Dual COM Line mode
+	0b, Disable Dual COM mode [reset]
+	1b, Enable Dual COM mode (MUX ≤ 63)
+	
+	0x16 = 00010110
+*/
   //U8X8_CAA(0xa0, 0x14, 0x11),	/* Set Re-Map / Dual COM Line Mode */  
   //U8X8_CAA(0xa0, 0x06, 0x011),	/* Set Re-Map / Dual COM Line Mode */  
   U8X8_CAA(0xa0, 0x16, 0x011),	/* Set Re-Map / Dual COM Line Mode (NHD-2.7-12864WDW3-M datasheet) */  

+ 2 - 2
components/u8g2/u8x8_d_ssd1325.c

@@ -282,7 +282,7 @@ static const u8x8_display_info_t u8x8_nhd_ssd1325_128x64_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	/* SSD1325 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,		/* x_offset is used as y offset for the SSD1325 */
   /* flipmode_x_offset = */ 8,		/* x_offset is used as y offset for the SSD1325 */
   /* pixel_width = */ 128,
@@ -394,7 +394,7 @@ static const u8x8_display_info_t u8x8_ssd0323_os128064_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	/* SSD1325 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,		/* x_offset is used as y offset for the SSD1325 */
   /* flipmode_x_offset = */ 0,		/* x_offset is used as y offset for the SSD1325 */
   /* pixel_width = */ 128,

+ 1 - 1
components/u8g2/u8x8_d_ssd1326.c

@@ -257,7 +257,7 @@ static const u8x8_display_info_t u8x8_ssd1326_256x32_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	/* ssd1326 */
   /* tile_width = */ 32,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1326 */
   /* flipmode_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1326 */
   /* pixel_width = */ 256,

+ 96 - 5
components/u8g2/u8x8_d_ssd1327.c

@@ -227,7 +227,7 @@ static const u8x8_display_info_t u8x8_ssd1327_winstar_96x64_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	
   /* tile_width = */ 12,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 16,		/* changed to 16, issue 1050 */
   /* flipmode_x_offset = */ 16,		/* changed to 16, issue 1050 */
   /* pixel_width = */ 96,
@@ -355,7 +355,7 @@ static const u8x8_display_info_t u8x8_ssd1327_96x96_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	
   /* tile_width = */ 12,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 16,
   /* flipmode_x_offset = */ 16,		
   /* pixel_width = */ 96,
@@ -479,7 +479,7 @@ static const u8x8_display_info_t u8x8_ssd1327_ea_w128128_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	
   /* tile_width = */ 16,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,		
   /* pixel_width = */ 128,
@@ -599,7 +599,7 @@ static const u8x8_display_info_t u8x8_ssd1327_128x128_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	
   /* tile_width = */ 16,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,		
   /* pixel_width = */ 128,
@@ -719,6 +719,97 @@ uint8_t u8x8_d_ssd1327_midas_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
   return 0;
 }
 
+/*=============================================*/
+/*
+
+  ZJY-M150 128x128 
+
+  https://aliexpress.com/item/1005003784174529.html
+  https://github.com/olikraus/u8g2/issues/1960
+
+  Mostly like the MIDAS version, but requires the GPIO enabled.
+
+*/
+
+static const uint8_t u8x8_d_ssd1327_zjy_128x128_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+
+	
+  U8X8_CA(0x0fd, 0x012),		/* unlock display, usually not required because the display is unlocked after reset */
+  U8X8_C(0x0ae),		                /* display off */
+  //U8X8_CA(0x0a8, 0x03f),		/* multiplex ratio: 0x03f * 1/64 duty */
+  //U8X8_CA(0x0a8, 0x05f),		/* multiplex ratio: 0x05f * 1/64 duty */
+  U8X8_CA(0x0a8, 0x07f),       		 /* multiplex ratio: 0x05f * 1/128duty */
+  U8X8_CA(0x0a1, 0x000),		/* display start line */
+  //U8X8_CA(0x0a2, 0x04c),		/* display offset, shift mapping ram counter */
+  
+  U8X8_CA(0x0a2, 0x000),		/* display offset, shift mapping ram counter */
+  U8X8_CA(0x0a0, 0x051),		/* remap configuration */
+  
+  
+  U8X8_CA(0x0ab, 0x001),		/* Enable internal VDD regulator (RESET) */
+  //U8X8_CA(0x081, 0x070),		/* contrast, brightness, 0..128 */
+  U8X8_CA(0x081, 0x053),		/* contrast, brightness, 0..128 */
+  //U8X8_CA(0x0b1, 0x055),                    /* phase length */
+  U8X8_CA(0x0b1, 0x051),                    /* phase length */  
+  //U8X8_CA(0x0b3, 0x091),		/* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */			
+  U8X8_CA(0x0b3, 0x001),		/* set display clock divide ratio/oscillator frequency  */			
+  
+  //? U8X8_CA(0x0ad, 0x002),		/* master configuration: disable embedded DC-DC, enable internal VCOMH */
+  //? U8X8_C(0x086),				/* full current range (0x084, 0x085, 0x086) */
+  
+  U8X8_C(0x0b9),				/* use linear lookup table */
+
+  //U8X8_CA(0x0bc, 0x010),                    /* pre-charge voltage level */
+  U8X8_CA(0x0bc, 0x008),                    /* pre-charge voltage level */
+  //U8X8_CA(0x0be, 0x01c),                     /* VCOMH voltage */
+  U8X8_CA(0x0be, 0x007),                     /* VCOMH voltage */
+  
+  U8X8_CA(0x0b6, 0x001),		/* second precharge */
+  U8X8_CA(0x0d5, 0x062),		/* enable second precharge, internal vsl (bit0 = 0) */
+  
+  U8X8_CA(0x0b5, 0x003),		/* Enable GPIO, issue 1960 */
+  
+  
+  U8X8_C(0x0a4),				/* normal display mode */
+    
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+uint8_t u8x8_d_ssd1327_zjy_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  /* call the 96x96 procedure at the moment */
+  if ( u8x8_d_ssd1327_96x96_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
+    return 1;
+  if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
+  {
+    u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_128x128_display_info);
+    return 1;
+  }
+  else if ( msg == U8X8_MSG_DISPLAY_INIT )
+  {
+    u8x8_d_helper_display_init(u8x8);
+    u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_zjy_128x128_init_seq); 
+    return 1;
+  }
+  else if  ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
+  {
+    if ( arg_int == 0 )
+    {
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_flip0_seq);
+      u8x8->x_offset = u8x8->display_info->default_x_offset;
+    }
+    else
+    {
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_flip1_seq);
+      u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+    }
+    return 1;
+  }
+  return 0;
+}
 
 /*=============================================*/
 /*  
@@ -833,7 +924,7 @@ static const u8x8_display_info_t u8x8_ssd1327_128x96_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	
   /* tile_width = */ 16,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,		
   /* pixel_width = */ 128,

+ 2 - 2
components/u8g2/u8x8_d_ssd1329.c

@@ -278,7 +278,7 @@ static const u8x8_display_info_t u8x8_ssd1329_128x96_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	/* ssd1329 */
   /* tile_width = */ 16,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1329 */
   /* flipmode_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1329 */
   /* pixel_width = */ 128,
@@ -495,7 +495,7 @@ static const u8x8_display_info_t u8x8_ssd1329_96x96_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 60,	/* ssd1329 */
   /* tile_width = */ 12,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */  0,          /* x offset for flip mode 0 */
   /* flipmode_x_offset = */ 16,		/* x offset for flip mode 1 */ 
   /* pixel_width = */ 96,

+ 538 - 0
components/u8g2/u8x8_d_ssd1362.c

@@ -0,0 +1,538 @@
+/*
+
+  u8x8_d_ssd1362.c
+  
+  https://github.com/olikraus/u8g2/issues/2051
+  
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2022, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+
+
+  SSD1362: 
+    256 x 64 (ssd1322: 480 x 128)
+    16 gray scale
+
+
+  Note: Currently the external IREF is activated.
+  Maybe we need a constructor with internal IREF
+  
+*/
+#include "u8x8.h"
+
+
+
+
+static const uint8_t u8x8_d_ssd1362_powersave0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0af),		                /* ssd1362: display on */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1362_powersave1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0ae),		                /* ssd1362: display off */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+
+
+/*
+  input:
+    one tile (8 Bytes)
+  output:
+    Tile for SSD1362 (32 Bytes)
+*/
+
+static uint8_t u8x8_ssd1362_to32_dest_buf[32];
+
+static uint8_t *u8x8_ssd1362_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
+{
+  uint8_t v;
+  uint8_t a,b;
+  uint8_t i, j;
+  uint8_t *dest;
+  
+  for( j = 0; j < 4; j++ )
+  {
+    dest = u8x8_ssd1362_to32_dest_buf;
+    dest += j;
+    a =*ptr;
+    ptr++;
+    b = *ptr;
+    ptr++;
+    for( i = 0; i < 8; i++ )
+    {
+      v = 0;
+      if ( a&1 ) v |= 0xf0;
+      if ( b&1 ) v |= 0x0f;
+      *dest = v;
+      dest+=4;
+      a >>= 1;
+      b >>= 1;
+    }
+  }
+  
+  return u8x8_ssd1362_to32_dest_buf;
+}
+
+/* special case for the 206x36 display: send only half of the last tile */
+static uint8_t *u8x8_ssd1362_8to24(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
+{
+  uint8_t v;
+  uint8_t a,b;
+  uint8_t i, j;
+  uint8_t *dest;
+  
+  for( j = 0; j < 3; j++ )
+  {
+    dest = u8x8_ssd1362_to32_dest_buf;
+    dest += j;
+    a =*ptr;
+    ptr++;
+    b = *ptr;
+    ptr++;
+    for( i = 0; i < 8; i++ )
+    {
+      v = 0;
+      if ( a&1 ) v |= 0xf0;
+      if ( b&1 ) v |= 0x0f;
+      *dest = v;
+      dest+=3;
+      a >>= 1;
+      b >>= 1;
+    }
+  }
+  
+  return u8x8_ssd1362_to32_dest_buf;
+}
+
+
+uint8_t u8x8_d_ssd1362_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x; 
+  uint8_t y, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
+    /*
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_256x64_init_seq);
+      break;
+    */
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_powersave1_seq);
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* ssd1362 has range from 0 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x *= 4;		// convert from tile pos to display column
+      x += u8x8->x_offset;		
+    
+      y = (((u8x8_tile_t *)arg_ptr)->y_pos);
+      y *= 8;
+    
+      
+      u8x8_cad_SendCmd(u8x8, 0x075 );	/* set row address, moved out of the loop (issue 302) */
+      u8x8_cad_SendArg(u8x8, y);
+      u8x8_cad_SendArg(u8x8, y+7);
+      
+      do
+      {
+	c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+
+	do
+	{
+	  u8x8_cad_SendCmd(u8x8, 0x015 );	/* set column address */
+          u8x8_cad_SendArg(u8x8, x );	/* start */
+          u8x8_cad_SendArg(u8x8, x+3 );	/* end */
+          u8x8_cad_SendData(u8x8, 32, u8x8_ssd1362_8to32(u8x8, ptr));
+	  
+	  ptr += 8;
+	  x += 4;
+	  c--;
+	} while( c > 0 );
+	
+	arg_int--;
+        
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+
+uint8_t u8x8_d_ssd1362_common_0_75(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x; 
+  uint8_t y, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    /* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
+    /*
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_256x64_init_seq);
+      break;
+    */
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_powersave1_seq);
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* ssd1362 has range from 0 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+      x *= 4;		// convert from tile pos to display column
+      x += u8x8->x_offset;		
+    
+      y = (((u8x8_tile_t *)arg_ptr)->y_pos);
+      y *= 8;
+    
+      
+      u8x8_cad_SendCmd(u8x8, 0x075 );	/* set row address, moved out of the loop (issue 302) */
+      u8x8_cad_SendArg(u8x8, y);
+      u8x8_cad_SendArg(u8x8, y+7);
+      
+      do
+      {
+	c = ((u8x8_tile_t *)arg_ptr)->cnt;
+	ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+
+	do
+	{
+	  u8x8_cad_SendCmd(u8x8, 0x015 );	/* set column address */
+          if ( x < 123 )
+          {
+            u8x8_cad_SendArg(u8x8, x );	/* start */
+            u8x8_cad_SendArg(u8x8, x+3 );	/* end */
+            u8x8_cad_SendData(u8x8, 32, u8x8_ssd1362_8to32(u8x8, ptr));
+          }
+          else
+          {
+            u8x8_cad_SendArg(u8x8, x );	/* start */
+            u8x8_cad_SendArg(u8x8, x+2 );	/* end */
+            u8x8_cad_SendData(u8x8, 24, u8x8_ssd1362_8to24(u8x8, ptr));
+          }
+	  
+	  ptr += 8;
+	  x += 4;
+	  c--;
+	} while( c > 0 );
+	
+	arg_int--;
+        
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+
+
+/*=========================================================*/
+
+static const uint8_t u8x8_d_ssd1362_256x64_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CA(0xa0, 0xc3), //Set Remap c3 = 11000011  
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_ssd1362_256x64_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_CA(0xa0, 0xd0), 
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const u8x8_display_info_t u8x8_ssd1362_256x64_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* ssd1362: 2 us */
+  /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* ssd1362: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* ssd1362: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 10000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215), 10 MHz (issue 301) */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 10,
+  /* write_pulse_width_ns = */ 150,	/* ssd1362: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 32,		/* 256 pixel, so we require 32 bytes for this */
+  /* tile_height = */ 8,
+  /* default_x_offset = */ 0,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 256,
+  /* pixel_height = */ 64
+};
+
+
+/* https://github.com/olikraus/u8g2/issues/2051 */
+static const uint8_t u8x8_d_ssd1362_256x64_init_seq[] = {
+    
+  U8X8_DLY(1),
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_DLY(1),
+  
+  U8X8_CA(0xfd, 0x12),            	/* unlock */
+  U8X8_C(0xae),		                /* display off */
+  U8X8_CA(0x23, 0x00), //POR 0x00; Disable fade mode
+  U8X8_CA(0x81, 0x9f), //Set contrast
+  
+/*
+Re- map setting in Graphic Display Data RAM
+(GDDRAM)
+
+A[0] = 0b, Disable Column Address Re-map (RESET)
+A[0] = 1b, Enable Column Address Re-map			***
+
+A[1] = 0b, Disable Nibble Re-map (RESET)
+A[1] = 1b, Enable Nibble Re-map				***
+
+A[2] = 0b, Enable Horizontal Address Increment (RESET)   ***
+A[2] = 1b, Enable Vertical Address Increment
+
+A[4] = 0b, Disable COM Re-map (RESET)
+A[4] = 1b, Enable COM Re-map
+
+A[6] = 0b, Disable SEG Split Odd Even			***
+A[6] = 1b, Enable SEG Split Odd Even (RESET)
+
+A[7] = 0b, Disable SEG left/right remap (RESET)
+A[7] = 1b, Enable SEG left/right remap
+
+*/
+  U8X8_CA(0xa0, 0xc3), 
+  U8X8_CA(0xa1, 0), //Set Display Start Line
+  U8X8_CA(0xa2, 0), //Set Display Offset
+  U8X8_C(0xa4), //Normal Display
+  U8X8_CA(0xa8, 63), //Set Multiplex Ratio: (63 rows)
+  U8X8_CA(0xab, 1), //Set VDD regulator
+  U8X8_CA(0xad, 0x8e), //External /Internal IREF Selection, 9e: internal, 8e: external
+  U8X8_CA(0xb1, 0x22), //Set Phase Length, reset: 0x82
+  U8X8_CA(0xb3, 0xa0), //Display clock Divider
+  U8X8_CA(0xb6, 0x04), //Set Second precharge Period
+  U8X8_C(0xb9), //Set Linear LUT
+  U8X8_CA(0xbc, 0x1f), //Set pre-charge voltage level, 0..0x1f, 0x1f = 0.51*Vcc
+  U8X8_CA(0xbd, 1), //Pre-charge voltage capacitor Selection, 0: without, 1: with Vp capacitor
+  U8X8_CA(0xbe, 7), //Set cOM deselect voltage level, 7 = 0.86*Vcc
+  U8X8_DLY(1),					/* delay 1ms */
+
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+uint8_t u8x8_d_ssd1362_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1362_256x64_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_256x64_init_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_256x64_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_256x64_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+    
+    default:
+      return u8x8_d_ssd1362_common(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}
+
+/*=========================================================*/
+
+static const u8x8_display_info_t u8x8_ssd1362_206x36_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 10,
+  /* reset_pulse_width_ms = */ 100, 	/* ssd1362: 2 us */
+  /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
+  /* sda_setup_time_ns = */ 50,		/* ssd1362: 15ns, but cycle time is 100ns, so use 100/2 */
+  /* sck_pulse_width_ns = */ 50,	/* ssd1362: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
+  /* sck_clock_hz = */ 10000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215), 10 MHz (issue 301) */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 10,
+  /* write_pulse_width_ns = */ 150,	/* ssd1362: cycle time is 300ns, so use 300/2 = 150 */
+  /* tile_width = */ 26,		/* 26*8 = 208 */
+  /* tile_height = */ 5,                /* 5*8 = 40 */
+  /* default_x_offset = */ 0,	/* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
+  /* flipmode_x_offset = */ 25, 
+  /* pixel_width = */ 206,
+  /* pixel_height = */ 36
+};
+
+
+/* https://github.com/olikraus/u8g2/issues/2051 */
+static const uint8_t u8x8_d_ssd1362_206x36_init_seq[] = {
+    
+  U8X8_DLY(1),
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_DLY(1),
+  
+  U8X8_CA(0xfd, 0x12),            	/* unlock */
+  U8X8_C(0xae),		                /* display off */
+  U8X8_CA(0x23, 0x00), //POR 0x00; Disable fade mode
+  U8X8_CA(0x81, 0x9f), //Set contrast
+  
+/*
+Re- map setting in Graphic Display Data RAM
+(GDDRAM)
+
+A[0] = 0b, Disable Column Address Re-map (RESET)
+A[0] = 1b, Enable Column Address Re-map			***
+
+A[1] = 0b, Disable Nibble Re-map (RESET)
+A[1] = 1b, Enable Nibble Re-map				***
+
+A[2] = 0b, Enable Horizontal Address Increment (RESET)   ***
+A[2] = 1b, Enable Vertical Address Increment
+
+A[4] = 0b, Disable COM Re-map (RESET)
+A[4] = 1b, Enable COM Re-map
+
+A[6] = 0b, Disable SEG Split Odd Even			***
+A[6] = 1b, Enable SEG Split Odd Even (RESET)
+
+A[7] = 0b, Disable SEG left/right remap (RESET)
+A[7] = 1b, Enable SEG left/right remap
+
+*/
+  U8X8_CA(0xa0, 0xc3), 
+  U8X8_CA(0xa1, 50), //Set Display Start Line
+  U8X8_CA(0xa2, 0), //Set Display Offset
+  U8X8_C(0xa4), //Normal Display
+  U8X8_CA(0xa8, 63), //Set Multiplex Ratio
+  U8X8_CA(0xab, 1), //Set VDD regulator
+  U8X8_CA(0xad, 0x8e), //External /Internal IREF Selection, 9e: internal, 8e: external
+  U8X8_CA(0xb1, 0x22), //Set Phase Length, reset: 0x82
+  U8X8_CA(0xb3, 0xa0), //Display clock Divider
+  U8X8_CA(0xb6, 0x04), //Set Second precharge Period
+  U8X8_C(0xb9), //Set Linear LUT
+  U8X8_CA(0xbc, 0x1f), //Set pre-charge voltage level, 0..0x1f, 0x1f = 0.51*Vcc
+  U8X8_CA(0xbd, 1), //Pre-charge voltage capacitor Selection, 0: without, 1: with Vp capacitor
+  U8X8_CA(0xbe, 7), //Set cOM deselect voltage level, 7 = 0.86*Vcc
+  U8X8_DLY(1),					/* delay 1ms */
+
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+uint8_t u8x8_d_ssd1362_206x36(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1362_206x36_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_206x36_init_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_256x64_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1362_256x64_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }
+      break;
+    
+    default:
+      return u8x8_d_ssd1362_common_0_75(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}

+ 1 - 1
components/u8g2/u8x8_d_ssd1606_172x72.c

@@ -374,7 +374,7 @@ static const u8x8_display_info_t u8x8_ssd1606_172x72_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 22,		/* 22*8 = 176 */
-  /* tile_hight = */ 9,		/* 9*8 = 72 */
+  /* tile_height = */ 9,		/* 9*8 = 72 */
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 172,

+ 1 - 1
components/u8g2/u8x8_d_ssd1607_200x200.c

@@ -80,7 +80,7 @@ static const u8x8_display_info_t u8x8_ssd1607_200x200_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 150,	
   /* tile_width = */ 25,		/* 25*8 = 200 */
-  /* tile_hight = */ 25,		
+  /* tile_height = */ 25,		
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 200,

+ 1 - 1
components/u8g2/u8x8_d_st7511.c

@@ -94,7 +94,7 @@ static const u8x8_display_info_t u8x8_st7511_320x240_display_info =
   /* data_setup_time_ns = */ 200,	/* */
   /* write_pulse_width_ns = */ 250,	/* ST7511 Datasheet: 500ns */
   /* tile_width = */ 40,		/* width of 17*8=136 pixel */
-  /* tile_hight = */ 30,
+  /* tile_height = */ 30,
   /* default_x_offset = */ 160,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 320,

+ 54 - 46
components/u8g2/u8x8_d_st75160.c

@@ -31,7 +31,10 @@
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 
-  https://github.com/olikraus/u8g2/issues/1642
+  REQUESTED IN
+    https://github.com/olikraus/u8g2/issues/1642
+    
+  STATUS 13 Aug 2022: NOT TESTED, MAY NOT WORK..
 
 
   0x030	ext 00
@@ -84,29 +87,32 @@ static const uint8_t u8x8_d_st75256_256x128_powersave1_seq[] = {
   U8X8_END()             			/* end of sequence */
 };
 
-// static const uint8_t u8x8_d_st75256_jlx256128_flip0_seq[] = {
-//   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
-//   U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_CA( 0xbc, 0x00 ),			/* data scan dir */
-//   U8X8_A( 0xa6 ),				/* ??? */
-
-//   //U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_C( 0x00c ),				/* data format LSB top */
-//   U8X8_END_TRANSFER(),             	/* disable chip */
-//   U8X8_END()             			/* end of sequence */
-// };
-
-// static const uint8_t u8x8_d_st75256_jlx256128_flip1_seq[] = {
-//   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
-//   U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_CA( 0xbc, 0x03 ),			/* data scan dir */
-//   U8X8_A( 0xa6 ),				/* ??? */
-
-//   //U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_C( 0x008 ),				/* data format MSB top */
-//   U8X8_END_TRANSFER(),             	/* disable chip */
-//   U8X8_END()             			/* end of sequence */
-// };
+/* marked as unused to avoid compiler warning, issue 1802 */
+#ifdef NOT_USED
+static const uint8_t u8x8_d_st75256_jlx256128_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CA( 0xbc, 0x00 ),			/* data scan dir */
+  U8X8_A( 0xa6 ),				/* ??? */
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_C( 0x00c ),				/* data format LSB top */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_st75256_jlx256128_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CA( 0xbc, 0x03 ),			/* data scan dir */
+  U8X8_A( 0xa6 ),				/* ??? */
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_C( 0x008 ),				/* data format MSB top */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+#endif
 
 static const uint8_t u8x8_d_st75256_jlx172104_flip0_seq[] = {
   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
@@ -132,30 +138,32 @@ static const uint8_t u8x8_d_st75256_jlx172104_flip1_seq[] = {
   U8X8_END()             			/* end of sequence */
 };
 
-// static const uint8_t u8x8_d_st75256_jlx256160_flip0_seq[] = {
-//   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
-//   U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_CA( 0xbc, 0x00 ),			/* data scan dir */
-//   U8X8_A( 0xa6 ),				/* ??? */
-
-//   //U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_C( 0x00c ),				/* data format LSB top */
-//   U8X8_END_TRANSFER(),             	/* disable chip */
-//   U8X8_END()             			/* end of sequence */
-// };
+/* marked as unused to avoid compiler warning, issue 1802 */
+#ifdef NOT_USED
+static const uint8_t u8x8_d_st75256_jlx256160_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CA( 0xbc, 0x00 ),			/* data scan dir */
+  U8X8_A( 0xa6 ),				/* ??? */
 
-// static const uint8_t u8x8_d_st75256_jlx256160_flip1_seq[] = {
-//   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
-//   U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_CA( 0xbc, 0x03 ),			/* data scan dir */
-//   U8X8_A( 0xa6 ),				/* ??? */
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_C( 0x00c ),				/* data format LSB top */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
 
-//   //U8X8_C( 0x030 ),				/* select 00 commands */
-//   U8X8_C( 0x008 ),				/* data format MSB top */
-//   U8X8_END_TRANSFER(),             	/* disable chip */
-//   U8X8_END()             			/* end of sequence */
-// };
+static const uint8_t u8x8_d_st75256_jlx256160_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CA( 0xbc, 0x03 ),			/* data scan dir */
+  U8X8_A( 0xa6 ),				/* ??? */
 
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_C( 0x008 ),				/* data format MSB top */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+#endif
 
 
 /*=============================================*/
@@ -178,7 +186,7 @@ static const u8x8_display_info_t u8x8_st75160_jm16096_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 20,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 0,	/*  x offset in flipmode 0 */
   /* flipmode_x_offset = */ 0,		/* */
   /* pixel_width = */ 160,

+ 221 - 8
components/u8g2/u8x8_d_st75256.c

@@ -251,7 +251,7 @@ static const u8x8_display_info_t u8x8_st75256_256x128_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 32,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,	/* must be 0, because this is checked also for normal mode */
   /* flipmode_x_offset = */ 5,		/* used as y offset */
   /* pixel_width = */ 256,
@@ -386,7 +386,7 @@ static const u8x8_display_info_t u8x8_st75256_wo256x128_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 32,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 5,	/* must be 0, because this is checked also for normal mode */
   /* flipmode_x_offset = */ 0,		/* used as y offset */
   /* pixel_width = */ 256,
@@ -520,7 +520,7 @@ static const u8x8_display_info_t u8x8_st75256_256x64_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 32,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,	/* must be 0, because this is checked also for normal mode */
   /* flipmode_x_offset = */ 13,		/* used as y offset */
   /* pixel_width = */ 256,
@@ -654,7 +654,7 @@ static const u8x8_display_info_t u8x8_st75256_172x104_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 22,			/* 22=176 */
-  /* tile_hight = */ 13,
+  /* tile_height = */ 13,
   /* default_x_offset = */ 84,	/*  */
   /* flipmode_x_offset = */ 0,		
   /* pixel_width = */ 172,
@@ -845,7 +845,7 @@ static const u8x8_display_info_t u8x8_st75256_240x160_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 30,
-  /* tile_hight = */ 20,
+  /* tile_height = */ 20,
   /* default_x_offset = */ 16,	/*  x offset in flipmode 0 */
   /* flipmode_x_offset = */ 0,		/* */
   /* pixel_width = */ 240,
@@ -1040,7 +1040,7 @@ static const u8x8_display_info_t u8x8_st75256_256x160_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 32,
-  /* tile_hight = */ 20,
+  /* tile_height = */ 20,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 1,	/* x offset is used as y offset in flipmode */
   /* pixel_width = */ 256,
@@ -1399,7 +1399,7 @@ static const u8x8_display_info_t u8x8_st75256_256x160_alt_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 32,
-  /* tile_hight = */ 20,
+  /* tile_height = */ 20,
   /* default_x_offset = */ 0,	/*  x offset in flipmode 0 */
   /* flipmode_x_offset = */ 0,		/* */
   /* pixel_width = */ 256,
@@ -1591,7 +1591,7 @@ static const u8x8_display_info_t u8x8_st75256_192x96_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 24,	
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 0,	/*  */
   /* flipmode_x_offset = */ 64,
   /* pixel_width = */ 192,
@@ -1729,7 +1729,220 @@ uint8_t u8x8_d_st75256_jlx19296(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
                 u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave0_seq);
               else
                 u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave1_seq);
+              return 1;
+	case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+	    if ( arg_int == 0 )
+	    {
+	      u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx256160_flip0_seq);
+	      u8x8->x_offset = u8x8->display_info->default_x_offset;
+	    }
+	    else
+	    {
+	      u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx256160_flip1_seq);
+	      u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+	    }
+	    return 1;
+	    /*
+	    if ( arg_int == 0 )
+	    {
+	      u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx172104_flip0_seq);
+	      u8x8->x_offset = u8x8->display_info->default_x_offset;
+	    }
+	    else
+	    {
+	      u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx172104_flip1_seq); 
+	      u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+	    }
+	    return 1;
+	    */
+		
+#ifdef U8X8_WITH_SET_CONTRAST
+        case U8X8_MSG_DISPLAY_SET_CONTRAST:
+
+              u8x8_cad_StartTransfer(u8x8);
+              
+              u8x8_cad_SendCmd(u8x8, 0x030 );
+              u8x8_cad_SendCmd(u8x8, 0x081 );  /* there are 9 bit for the volume control */
+              u8x8_cad_SendArg(u8x8, (arg_int & 0x1f)<<1 );	/* lower 6 bit */
+              u8x8_cad_SendArg(u8x8, (arg_int>>5));		/* upper 3 bit */
+              
+              u8x8_cad_EndTransfer(u8x8);
+              return 1;
+#endif
+  }
+  return 0;
+}
+
+
+
+/*=============================================*/
+/* 
+  JLX16080 LCD 
+
+  https://github.com/olikraus/u8g2/issues/2058
+
+  WARNING: NOT FULLY TESTED in issue 2058!
+*/
+
+static const u8x8_display_info_t u8x8_st75256_jlx16080_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 20,
+  /* pre_chip_disable_wait_ns = */ 20,
+  /* reset_pulse_width_ms = */ 5, 	
+  /* post_reset_wait_ms = */ 5, 		/**/
+  /* sda_setup_time_ns = */ 20,		/* */
+  /* sck_pulse_width_ns = */ 40,	/*  */
+  /* sck_clock_hz = */ 4000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,	/* 400KHz */
+  /* data_setup_time_ns = */ 15,
+  /* write_pulse_width_ns = */ 70,	
+  /* tile_width = */ 20,	
+  /* tile_height = */ 10,
+  /* default_x_offset = */ 0,	/*  */
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 160,
+  /* pixel_height = */ 80
+};
+
+static const uint8_t u8x8_d_st75256_jlx16080_init_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_DLY(20),
+
+  U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_C( 0x094 ),				/* sleep out */
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_C( 0x0ae ),				/* display off */
+
+  U8X8_C( 0x031 ),				/* select 01 commands */
+  U8X8_CA( 0x0d7, 0x09f ),		/* disable auto read */  
+
+  //U8X8_C( 0x031 ),				/* select 01 commands */
+  U8X8_C( 0x032 ),				/* analog circuit set */
+  U8X8_A( 0x000 ),				/* code example: OSC Frequency adjustment */
+  U8X8_A( 0x001 ),				/* Frequency on booster capacitors 1 = 6KHz? */
+  U8X8_A( 0x003 ),				/* Bias: 1: 1/13, 2: 1/12, 3: 1/11, 4:1/10, 5:1/9 */
+    
+  //U8X8_C( 0x031 ),				/* select 01 commands */
+  U8X8_C( 0x020 ),				/* gray levels */
+  U8X8_A( 0x01 ),
+  U8X8_A( 0x03 ),
+  U8X8_A( 0x05 ),
+  U8X8_A( 0x07 ),
+  U8X8_A( 0x09),
+  U8X8_A( 0x0b ),
+  U8X8_A( 0x0d ),
+  U8X8_A( 0x10 ),
+  U8X8_A( 0x11 ),
+  U8X8_A( 0x13 ),
+  U8X8_A( 0x15 ),
+  U8X8_A( 0x17 ),
+  U8X8_A( 0x19 ),
+  U8X8_A( 0x1b ),
+  U8X8_A( 0x1d ),
+  U8X8_A( 0x1f ),
+ 
+  
+  U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CAA(0x75, 0, 0x4f),		/* row range */
+  U8X8_CAA(0x15, 0, 255),		/* col range */
+  
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CA( 0xbc, 0x00 ),			/* data scan dir */
+  U8X8_A( 0xa6 ),				/* ??? */
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_C( 0x00c ),				/* data format LSB top */
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */ 
+  U8X8_C( 0xca ),				/* display control, 3 args follow  */
+  U8X8_A( 0x00 ),				/* 0x00: no clock division, 0x04: devide clock */
+  U8X8_A( 0x9f ),				/* 1/160 duty value from the DS example code */
+  U8X8_A( 0x20 ),				/* nline off */ 
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */ 
+  U8X8_CA( 0x0f0, 0x010 ),		/* monochrome mode  = 0x010*/
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CAA( 0x81, 0x2e, 0x03 ),	/* Volume control */
+
+  //U8X8_C( 0x030 ),				/* select 00 commands */
+  U8X8_CA( 0x020, 0x00b ),		/* Power control: Regulator, follower & booster on */
+  U8X8_DLY(100),
+
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};    
+
+
+uint8_t u8x8_d_st75256_jlx16080(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+
+  switch(msg)
+  {
+            case U8X8_MSG_DISPLAY_DRAW_TILE:
+              
+              u8x8_cad_StartTransfer(u8x8);
+              x = ((u8x8_tile_t *)arg_ptr)->x_pos;    
+              x *= 8;
+              
+              u8x8_cad_SendCmd(u8x8, 0x030 );	/* select command set */
+              u8x8_cad_SendCmd(u8x8, 0x075 );	/* row */
+            
+            
+	      //if ( u8x8->x_offset == 0 )		/* 0 means flip mode 1, then adjust y value */
+		//u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos));
+	      //else
+		u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos));
+              
+              
+              u8x8_cad_SendArg(u8x8, 0x04f);
+              //u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos));
+              u8x8_cad_SendCmd(u8x8, 0x015 );	/* col */
+              u8x8_cad_SendArg(u8x8, x+u8x8->x_offset);
+              u8x8_cad_SendArg(u8x8, 255);
+              u8x8_cad_SendCmd(u8x8, 0x05c );	
+            
+              
+              do
+              {
+                c = ((u8x8_tile_t *)arg_ptr)->cnt;
+                ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+                c *= 8;
 
+                if ( c + x > 192u )
+                {
+                        c = 192u;
+                        c -= x;
+                }
+                      
+                u8x8_cad_SendData(u8x8, c, ptr); 	
+                x += c;
+                arg_int--;
+              } while( arg_int > 0 );
+              
+              u8x8_cad_EndTransfer(u8x8);
+              return 1;
+        case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+            //u8x8_SetI2CAddress(u8x8, 0x078);		/* lowest I2C adr of the ST75256 */
+            u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st75256_jlx16080_display_info);
+            return 1;
+        case U8X8_MSG_DISPLAY_INIT:
+            u8x8_d_helper_display_init(u8x8);
+            u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx16080_init_seq);
+            return 1;
+        case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+              if ( arg_int == 0 )
+                u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave0_seq);
+              else
+                u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave1_seq);
               return 1;
 	case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
 	    if ( arg_int == 0 )

+ 3 - 4
components/u8g2/u8x8_d_st7528.c

@@ -243,6 +243,7 @@ static const uint8_t u8x8_d_st7528_nhd_c160100_init_seq[] = {
   U8X8_C(0x0a0),		                /* ADC */
   U8X8_C(0x0c8),		                /* SHL */
   U8X8_CA(0x044, 0x000),		/* initial Com0 */
+  U8X8_CA(0x040, 0x000),		/* y shift, issue https://github.com/olikraus/u8g2/issues/1828 */
   U8X8_C(0x0ab),		                /* start oscillator */
   U8X8_C(0x026),		                /* Select the internal resistance ratio of the regulator resistor */
   U8X8_CA(0x081, 0x015),		/* volumn */
@@ -262,8 +263,6 @@ static const uint8_t u8x8_d_st7528_nhd_c160100_init_seq[] = {
   U8X8_END()             			/* end of sequence */
 };
 
-
-
 static const u8x8_display_info_t u8x8_st7528_160x100_display_info =
 {
   /* chip_enable_level = */ 0,
@@ -282,7 +281,7 @@ static const u8x8_display_info_t u8x8_st7528_160x100_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 80,	/* st7528 */
   /* tile_width = */ 20,
-  /* tile_hight = */ 13,
+  /* tile_height = */ 13,
   /* default_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1326 */
   /* flipmode_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1326 */
   /* pixel_width = */ 160,
@@ -434,7 +433,7 @@ static const u8x8_display_info_t u8x8_st7528_erc16064_display_info =
   /* data_setup_time_ns = */ 40,
   /* write_pulse_width_ns = */ 80,	/* st7528 */
   /* tile_width = */ 20,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1326 */
   /* flipmode_x_offset = */ 0,		/* x_offset is used as y offset for the ssd1326 */
   /* pixel_width = */ 160,

+ 1 - 1
components/u8g2/u8x8_d_st75320.c

@@ -242,7 +242,7 @@ static const u8x8_display_info_t u8x8_st75320_jlx320240_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 40,
-  /* tile_hight = */ 30,
+  /* tile_height = */ 30,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 320,

+ 179 - 0
components/u8g2/u8x8_d_st7539.c

@@ -0,0 +1,179 @@
+/*
+
+  u8x8_d_st7539.c
+  
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+
+  Copyright (c) 2023, olikraus@gmail.com
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+
+  
+*/
+#include "u8x8.h"
+
+
+
+
+static const uint8_t u8x8_d_st7539_192x64_powersave0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0af),		                /* display on */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7539_192x64_powersave1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7539_192x64_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0c2),				/* bit 1: MX, bit 2: MY */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7539_192x64_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x0c4),				/* bit 1: MX, bit 2: MY */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+
+static const u8x8_display_info_t u8x8_st7539_192x64_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 1,	/* st7539 datasheet, page 46 */
+  /* pre_chip_disable_wait_ns = */ 5,	/* st7539 datasheet, page 46 */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 6, 
+  /* sda_setup_time_ns = */ 12,		/* st7539 datasheet, page 44 */
+  /* sck_pulse_width_ns = */ 15,	/* st7539 datasheet, page 44 */
+  /* sck_clock_hz = */ 2000000UL,	/* */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 1,
+  /* data_setup_time_ns = */ 60,	/* st7539 datasheet, page 43 */
+  /* write_pulse_width_ns = */ 80,	/* st7539 datasheet, page 43 */
+  /* tile_width = */ 24,		
+  /* tile_height = */ 8,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 192,
+  /* pixel_height = */ 64
+};
+
+static const uint8_t u8x8_d_st7539_192x64_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_C(0x0e2),            			/* soft reset */
+  U8X8_C(0x0a0),            			/* 76Hz FPS*/
+  U8X8_C(0x0eb),            			/* LCD Bias: 0xe8: 6, 0xe9: 7, 0xea: 8, 0xeb: 9 */
+  U8X8_C(0x0c2),		                /* RAM mapping ctrl */
+  U8X8_CA(0x081, 145),		/* set contrast */
+  U8X8_C(0x02e),            			/* LCD Load + Internal Charge Pump (default: 0x2e) */	
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  
+  U8X8_C(0x0a6),		                /* normal display */
+   
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+// https://github.com/olikraus/u8g2/issues/2146
+
+uint8_t u8x8_d_st7539_192x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7539_192x64_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7539_192x64_init_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7539_192x64_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7539_192x64_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7539_192x64_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7539_192x64_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }	
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int );	/* st7539 has range from 0 to 255 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+    
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
+      x *= 8;
+      x += u8x8->x_offset;
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
+    
+      c = ((u8x8_tile_t *)arg_ptr)->cnt;
+      c *= 8;
+      ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+      do
+      {
+	u8x8_cad_SendData(u8x8, c, ptr);	/* note: SendData can not handle more than 255 bytes */
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+

+ 13 - 13
components/u8g2/u8x8_d_st7565.c

@@ -105,7 +105,7 @@ static const u8x8_display_info_t u8x8_st7565_128x64_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 4,
   /* pixel_width = */ 128,
@@ -393,7 +393,7 @@ static const u8x8_display_info_t u8x8_st7565_64128n_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -521,7 +521,7 @@ static const u8x8_display_info_t u8x8_st7565_128x32_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -611,7 +611,7 @@ static const u8x8_display_info_t u8x8_st7565_nhd_c12864_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -637,8 +637,8 @@ static const uint8_t u8x8_d_st7565_nhd_c12864_init_seq[] = {
   U8X8_C(0x0a2),		                /* LCD bias 1/9 */
   U8X8_C(0x02f),		                /* all power  control circuits on */
   U8X8_CA(0x0f8, 0x000),		/* set booster ratio to 4x */
-  U8X8_C(0x023),		                /* set V0 voltage resistor ratio to large*/
-  U8X8_CA(0x081, 180),			/* set contrast, contrast value NHD C12864, see issue 186, increased contrast to 180 (issue 219) */
+  U8X8_C(0x025),		                /* set V0 voltage resistor ratio to large,  issue 1678: changed from 0x23 to 0x25 */
+  U8X8_CA(0x081, 170),			/* set contrast, contrast value NHD C12864, see issue 186, increased contrast to 180 (issue 219), reduced to 170 (issue 1678) */
   
   U8X8_C(0x0ae),		                /* display off */
   U8X8_C(0x0a5),		                /* enter powersafe: all pixel on, issue 142 */
@@ -739,7 +739,7 @@ static const u8x8_display_info_t u8x8_st7565_lm6059_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 1,	/* not sure... */
   /* flipmode_x_offset = */ 3,
   /* pixel_width = */ 128,
@@ -819,12 +819,12 @@ uint8_t u8x8_d_st7565_ks0713(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
       case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
 	if ( arg_int == 0 )
 	{
-	  u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
+	  u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_zflip1_seq);
 	  u8x8->x_offset = u8x8->display_info->default_x_offset;
 	}
 	else
 	{
-	  u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
+	  u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_zflip0_seq);
 	  u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
 	}	
 	break;
@@ -886,7 +886,7 @@ static const u8x8_display_info_t u8x8_st7565_lx12864_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 1,	/* not sure... */
   /* flipmode_x_offset = */ 3,
   /* pixel_width = */ 128,
@@ -978,7 +978,7 @@ static const u8x8_display_info_t u8x8_st7565_erc12864_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 4,
   /* pixel_width = */ 128,
@@ -1210,7 +1210,7 @@ static const u8x8_display_info_t u8x8_st7565_dogm132_display_info =
   /* data_setup_time_ns = */ 40,	/* st7565 datasheet, table 24, tds8 */
   /* write_pulse_width_ns = */ 80,	/* st7565 datasheet, table 24, tcclw */
   /* tile_width = */ 17,		/* width of 16*8=136 pixel */
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 132,
@@ -1336,4 +1336,4 @@ uint8_t u8x8_d_st7565_jlx12864g109pc(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
     }
   }
   return 1;
-}
+}

+ 524 - 12
components/u8g2/u8x8_d_st7567.c

@@ -30,6 +30,9 @@
   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+  
+  
+  ST7567: 65x132 controller
 
   
 */
@@ -108,7 +111,7 @@ static const u8x8_display_info_t u8x8_st7567_132x64_display_info =
   /* data_setup_time_ns = */ 40,	/* */
   /* write_pulse_width_ns = */ 80,	/* */
   /* tile_width = */ 17,		/* width of 17*8=136 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 132,
@@ -232,9 +235,6 @@ uint8_t u8x8_d_st7567_pi_132x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
 /*=====================================================*/
 
 
-
-
-
 static const u8x8_display_info_t u8x8_st7567_jlx12864_display_info =
 {
   /* chip_enable_level = */ 0,
@@ -252,7 +252,7 @@ static const u8x8_display_info_t u8x8_st7567_jlx12864_display_info =
   /* data_setup_time_ns = */ 40,	/* */
   /* write_pulse_width_ns = */ 80,	/* */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -371,6 +371,169 @@ uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
 }
 
 
+/*=====================================================*/
+
+/* Sinda Display (sindadisplay.com), SDGG 2232-07 */
+/* Issue 1759, 122x32 display, https://github.com/olikraus/u8g2/files/7894362/SDGG12232-07.pdf */
+/* copied from jlx12864 */
+
+static const uint8_t u8x8_d_st7567_122x32_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x040+32),		                /* set display start line to 32 */
+  U8X8_C(0x0a1),				/* segment remap a0/a1*/
+  U8X8_C(0x0c0),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7567_122x32_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x040+0),		                /* set display start line to 0 */
+  U8X8_C(0x0a0),				/* segment remap a0/a1*/
+  U8X8_C(0x0c8),				/* c0: scan dir normal, c8: reverse */
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const u8x8_display_info_t u8x8_st7567_122x32_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 150,	/* */
+  /* pre_chip_disable_wait_ns = */ 50,	/* */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 1, 
+  /* sda_setup_time_ns = */ 50,		/* */
+  /* sck_pulse_width_ns = */ 120,	/* */
+  /* sck_clock_hz = */ 4000000UL,	/* */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,	/* */
+  /* write_pulse_width_ns = */ 80,	/* */
+  /* tile_width = */ 16,		/* width of 16*8=128 pixel */
+  /* tile_height = */ 4,
+  /* default_x_offset = */ 4,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 122,
+  /* pixel_height = */ 32
+};
+
+static const uint8_t u8x8_st7567_122x32_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_C(0x0e2),            			/* soft reset */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x040+32),		                /* set display start line to 32 */
+  
+  U8X8_C(0x0a1),		                /* ADC set to reverse */
+  U8X8_C(0x0c0),		                /* common output mode */
+  // Flipmode
+  //U8X8_C(0x0a0),		                /* ADC set to reverse */
+  //U8X8_C(0x0c8),		                /* common output mode */
+  
+  U8X8_C(0x0a6),		                /* display normal, bit val 0: LCD pixel off. */
+  
+  
+  /* I think datasheet of the 122x32 display suggest to use 0x0a2 instead of 0xa3 here */
+  U8X8_C(0x0a2),		                /* LCD bias 1/6 @1/33 duty */
+  /* power on sequence from paxinstruments */
+  U8X8_C(0x028|4),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  U8X8_C(0x028|6),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  U8X8_C(0x028|7),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  
+  U8X8_C(0x023),		                /* v0 voltage resistor ratio */
+  U8X8_CA(0x081, 42>>2),		/* set contrast, contrast value*/
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x0a5),		                /* enter powersafe: all pixel on, issue 142 */
+   
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+/* 122x32 display, issue 1759 */
+uint8_t u8x8_d_st7567_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_122x32_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_st7567_122x32_init_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_122x32_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_122x32_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }	
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int >> 2 );	/* st7567 has range from 0 to 63 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+    
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
+      x *= 8;
+      x += u8x8->x_offset;
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
+    
+      c = ((u8x8_tile_t *)arg_ptr)->cnt;
+      c *= 8;
+      ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+      /* 
+	The following if condition checks the hardware limits of the st7567 
+	controller: It is not allowed to write beyond the display limits.
+	This is in fact an issue within flip mode.
+      */
+      if ( c + x > 132u )
+      {
+	c = 132u;
+	c -= x;
+      }
+      do
+      {
+	u8x8_cad_SendData(u8x8, c, ptr);	/* note: SendData can not handle more than 255 bytes */
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+
 /*=====================================================*/
 
 
@@ -392,7 +555,7 @@ static const u8x8_display_info_t u8x8_st7567_enh_dg128064_display_info =
   /* data_setup_time_ns = */ 40,	/* */
   /* write_pulse_width_ns = */ 80,	/* */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 4,
   /* pixel_width = */ 128,
@@ -416,7 +579,7 @@ static const u8x8_display_info_t u8x8_st7567_enh_dg128064i_display_info =
   /* data_setup_time_ns = */ 40,	/* */
   /* write_pulse_width_ns = */ 80,	/* */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -593,7 +756,7 @@ static const u8x8_display_info_t u8x8_st7567_64x32_display_info =
   /* data_setup_time_ns = */ 40,	/* */
   /* write_pulse_width_ns = */ 80,	/* */
   /* tile_width = */ 8,		
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 32,
   /* flipmode_x_offset = */ 32,
   /* pixel_width = */ 64,
@@ -733,7 +896,7 @@ static const u8x8_display_info_t u8x8_st7567_hem6432_display_info =
   /* data_setup_time_ns = */ 40,	/* */
   /* write_pulse_width_ns = */ 80,	/* */
   /* tile_width = */ 8,		
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 36,		/* issue 1159 */
   /* flipmode_x_offset = */ 32,		/* issue 1159 */
   /* pixel_width = */ 64,
@@ -860,8 +1023,6 @@ uint8_t u8x8_d_st7567_hem6432(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *
 
 
 
-
-
 static const u8x8_display_info_t u8x8_st7567_os12864_display_info =
 {
   /* chip_enable_level = */ 0,
@@ -879,7 +1040,7 @@ static const u8x8_display_info_t u8x8_st7567_os12864_display_info =
   /* data_setup_time_ns = */ 40,	/* */
   /* write_pulse_width_ns = */ 80,	/* */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 4,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -998,3 +1159,354 @@ uint8_t u8x8_d_st7567_os12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *
 }
 
 
+/*=====================================================*/
+/*
+
+  https://github.com/olikraus/u8g2/discussions/1868
+  https://github.com/olikraus/u8g2/issues/1869
+  https://www.buydisplay.com/cog-serial-spi-132x32-graphic-lcd-display-no-backlight-st7567a
+
+  ERC13232
+
+  copied from U8G2_ST7567_PI_132X64
+
+*/
+
+static const u8x8_display_info_t u8x8_st7567_132x32_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 150,	/* */
+  /* pre_chip_disable_wait_ns = */ 50,	/* */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 1, 
+  /* sda_setup_time_ns = */ 50,		/* */
+  /* sck_pulse_width_ns = */ 120,	/* */
+  /* sck_clock_hz = */ 4000000UL,	/* */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,	/* */
+  /* write_pulse_width_ns = */ 80,	/* */
+  /* tile_width = */ 17,		/* width of 17*8=136 pixel */
+  /* tile_height = */ 4,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 132,
+  /* pixel_height = */ 32
+};
+
+static const uint8_t u8x8_d_st7567_erc13232_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_C(0x0e2),            			/* soft reset */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  
+  U8X8_C(0x0a1),		                /* ADC set to reverse */
+  U8X8_C(0x0c0),		                /* common output mode */
+  // Flipmode
+  //U8X8_C(0x0a0),		                /* ADC set to reverse */
+  //U8X8_C(0x0c8),		                /* common output mode */
+  
+  U8X8_C(0x0a6),		                /* display normal, bit val 0: LCD pixel off. */
+  U8X8_C(0x0a3),		                /* LCD bias 1/7 */
+  /* power on sequence from paxinstruments */
+  U8X8_C(0x028|4),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  U8X8_C(0x028|6),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  U8X8_C(0x028|7),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  
+  U8X8_C(0x026),		                /* v0 voltage resistor ratio */
+  U8X8_CA(0x081, 0x027),		/* set contrast, contrast value*/
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x0a5),		                /* enter powersafe: all pixel on, issue 142 */
+   
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+/* ERC13232 */
+uint8_t u8x8_d_st7567_erc13232(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_132x32_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_erc13232_init_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }	
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int >> 2 );	/* st7567 has range from 0 to 63 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+    
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
+      x *= 8;
+      x += u8x8->x_offset;
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
+    
+      c = ((u8x8_tile_t *)arg_ptr)->cnt;
+      c *= 8;
+      ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+      /* 
+	The following if condition checks the hardware limits of the st7567 
+	controller: It is not allowed to write beyond the display limits.
+	This is in fact an issue within flip mode.
+      */
+      if ( c + x > 132u )
+      {
+	c = 132u;
+	c -= x;
+      }
+      do
+      {
+	u8x8_cad_SendData(u8x8, c, ptr);	/* note: SendData can not handle more than 255 bytes */
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+
+
+/*=====================================================*/
+
+/* LW12864 display, 128x32 (actually 142x36, but with border of weird behavior) */
+/* copied from jlx12864 */
+
+static const u8x8_display_info_t u8x8_st7567_lw12832_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 150,	/* */
+  /* pre_chip_disable_wait_ns = */ 50,	/* */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 1, 
+  /* sda_setup_time_ns = */ 50,		/* */
+  /* sck_pulse_width_ns = */ 120,	/* */
+  /* sck_clock_hz = */ 4000000UL,	/* */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 40,	/* */
+  /* write_pulse_width_ns = */ 80,	/* */
+  /* tile_width = */ 17,		/* rounded up to 17 tiles */
+  /* tile_height = */ 9,    /* also rounded */
+  /* default_x_offset = */ 4,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 32
+};
+
+static const uint8_t u8x8_st7567_lw12832_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  
+  U8X8_C(0x0e2),            			/* soft reset */
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x040),		                /* set display start line to 0 */
+  
+  U8X8_C(0x0a1),		                /* ADC set to reverse */
+  U8X8_C(0x0c0),		                /* common output mode */
+  // Flipmode
+  //U8X8_C(0x0a0),		                /* ADC set to reverse */
+  //U8X8_C(0x0c8),		                /* common output mode */
+  
+  U8X8_C(0x0a6),		                /* display normal, bit val 0: LCD pixel off. */
+  U8X8_C(0x0a3),		                /* LCD bias 1/7 */
+  /* power on sequence from paxinstruments */
+  U8X8_C(0x028|4),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  U8X8_C(0x028|6),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  U8X8_C(0x028|7),		                /* all power  control circuits on */
+  U8X8_DLY(50),
+  
+  U8X8_C(0x023),		                /* v0 voltage resistor ratio */
+  U8X8_CA(0x081, 42>>2),		/* set contrast, contrast value*/
+  
+  U8X8_C(0x0ae),		                /* display off */
+  U8X8_C(0x0a5),		                /* enter powersafe: all pixel on, issue 142 */
+   
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static void st7567_lw12832_clear_ddram(u8x8_t *u8x8)
+{
+  // A combination of
+  //     - void u8x8_ClearDisplayWithTile(u8x8_t *u8x8, const uint8_t *buf)
+  // and
+  //     - uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+
+  uint8_t buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+  uint8_t h = u8x8->display_info->tile_height;
+
+  u8x8_tile_t tile;
+  tile.x_pos = 0;
+  tile.y_pos = 0;
+  tile.cnt = 1;
+  tile.tile_ptr = buf;
+
+  do
+  {
+    // Args
+    uint8_t arg_int = u8x8->display_info->tile_width;
+    void *arg_ptr = (void *)&tile;
+
+    // ---------------- START OF u8x8_d_st7567_jlx12864 case U8X8_MSG_DISPLAY_DRAW_TILE ----------------
+    uint8_t x, c;
+    uint8_t *ptr;
+
+    u8x8_cad_StartTransfer(u8x8);
+
+    x = ((u8x8_tile_t *)arg_ptr)->x_pos;
+    x *= 8;
+    /* x += u8x8->x_offset; */                                         // Note that this is removed intentionally
+    u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4));                          // Set Column Address (MSB)
+    u8x8_cad_SendCmd(u8x8, 0x000 | ((x & 15)));                        // Set Column Address (LSB)
+    u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)); // Set Page Address
+
+    c = ((u8x8_tile_t *)arg_ptr)->cnt;
+    c *= 8;
+    ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+    /*
+    The following if condition checks the hardware limits of the st7567
+    controller: It is not allowed to write beyond the display limits.
+    This is in fact an issue within flip mode.
+    */
+    if (c + x > 132u)
+    {
+      c = 132u;
+      c -= x;
+    }
+    do
+    {
+      u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
+      arg_int--;
+    } while (arg_int > 0);
+
+    u8x8_cad_EndTransfer(u8x8);
+    // ---------------- END OF u8x8_d_st7567_jlx12864 case U8X8_MSG_DISPLAY_DRAW_TILE  ----------------
+
+    tile.y_pos++;
+  } while (tile.y_pos < h);
+}
+
+/* LW12832 display */
+uint8_t u8x8_d_st7567_lw12832(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  uint8_t x, c;
+  uint8_t *ptr;
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_lw12832_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_st7567_lw12832_init_seq);
+      st7567_lw12832_clear_ddram(u8x8);
+      break;
+    case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+      if ( arg_int == 0 )
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
+      else
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
+      break;
+    case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+      if ( arg_int == 0 )
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
+	u8x8->x_offset = u8x8->display_info->default_x_offset;
+      }
+      else
+      {
+	u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
+	u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+      }	
+      break;
+#ifdef U8X8_WITH_SET_CONTRAST
+    case U8X8_MSG_DISPLAY_SET_CONTRAST:
+      u8x8_cad_StartTransfer(u8x8);
+      u8x8_cad_SendCmd(u8x8, 0x081 );
+      u8x8_cad_SendArg(u8x8, arg_int >> 2 );	/* st7567 has range from 0 to 63 */
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+#endif
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+      u8x8_cad_StartTransfer(u8x8);
+    
+      x = ((u8x8_tile_t *)arg_ptr)->x_pos;
+      x *= 8;
+      x += u8x8->x_offset;
+      u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
+      u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
+      u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
+    
+      c = ((u8x8_tile_t *)arg_ptr)->cnt;
+      c *= 8;
+      ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
+      /* 
+	The following if condition checks the hardware limits of the st7567 
+	controller: It is not allowed to write beyond the display limits.
+	This is in fact an issue within flip mode.
+      */
+      if ( c + x > 132u )
+      {
+	c = 132u;
+	c -= x;
+      }
+      do
+      {
+	u8x8_cad_SendData(u8x8, c, ptr);	/* note: SendData can not handle more than 255 bytes */
+	arg_int--;
+      } while( arg_int > 0 );
+      
+      u8x8_cad_EndTransfer(u8x8);
+      break;
+    default:
+      return 0;
+  }
+  return 1;
+}
+

+ 7 - 4
components/u8g2/u8x8_d_st7571.c

@@ -168,6 +168,7 @@ static uint8_t u8x8_d_st7571_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int,
 
 
 /* QT-2832TSWUG02/ZJY-2832TSWZG02 */
+/* fixed the 0x40 and 0x48 commands, verified with FlipMode example: All ok */
 static const uint8_t u8x8_d_st7571_128x128_init_seq[] = {
     
   U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
@@ -181,14 +182,16 @@ static const uint8_t u8x8_d_st7571_128x128_init_seq[] = {
   U8X8_C(0xA0), 				// ADC select
   U8X8_C(0xC8), 				// SHL select
   U8X8_CA(0x44, 0x00), 		// COM0 register  
-  U8X8_CA(0x40, 0x7f), 		// initial display line  (0x7f... strange but ok... maybe specific for the JLX128128)
+  U8X8_CA(0x40, 0x0), 		// initial display line  (0x7f... strange but ok... maybe specific for the JLX128128)
                                                         // 2 sep 2021: maybe this also wrong because the 0x44 command is overwritten later.
+                                                        // 4 Mar 2022: Changed to 0
   
   U8X8_C(0xAB), 				// OSC ON  
   U8X8_C(0x25), 				// Voltage regulator
   U8X8_CA(0x81, 0x33), 		// Volume
   U8X8_C(0x54), 				// LCD Bias: 0x056=1/11 (1/11 according to JLX128128 datasheet), 0x054=1/9
-  U8X8_CA(0x44, 0x7f), 		// Duty 1/128   // 2 Sep 2021: Should this be 00x48???
+  U8X8_CA(0x48, 0x80), 		// Duty 1/128   // 2 Sep 2021: Should this be 00x48???  
+                                                        // 4 Mar 2022, cmd changed to 0x48, arg changed to 0x80
   
   U8X8_C(0x2C), 				// Power Control, VC: ON, VR: OFF, VF: OFF
   U8X8_DLY(200),
@@ -232,7 +235,7 @@ static const u8x8_display_info_t u8x8_st7571_128x128_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 16,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -331,7 +334,7 @@ static const u8x8_display_info_t u8x8_st7571_128x96_display_info =
   /* data_setup_time_ns = */ 15,
   /* write_pulse_width_ns = */ 70,	
   /* tile_width = */ 16,
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,

+ 246 - 0
components/u8g2/u8x8_d_st7586s_jlx320160.c

@@ -0,0 +1,246 @@
+/*
+  u8x8_d_st7586s_jlx320160.c
+
+  Display: 320x160 pixel
+  ST7586s: 384 x 160 x 2
+
+  takeover from https://github.com/olikraus/u8g2/issues/1183
+  
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+  
+  Copyright (c) 2023, olikraus@gmail.com
+  
+  All rights reserved.
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+  
+*/
+
+#include "u8g2.h"
+
+
+static const uint8_t u8x8_d_st7586s_sleep_on[] = {
+  U8X8_START_TRANSFER(),  /* enable chip, delay is part of the transfer start */
+  U8X8_C(0x010), /* set power save mode */
+  U8X8_END_TRANSFER(),  /* disable chip */
+  U8X8_END()                  /* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7586s_sleep_off[] = {
+  U8X8_START_TRANSFER(),  /* enable chip, delay is part of the transfer start */
+  U8X8_C(0x011), //Sleep out
+  U8X8_DLY(50), /* delay 50 ms */
+  U8X8_END_TRANSFER(),  /* disable chip */
+  U8X8_END()                  /* end of sequence */
+};
+
+
+static const uint8_t u8x8_d_st7586s_jlx320160_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x036),  /* Scan Direction Setting */
+  U8X8_A(0x000),	/* COM159 -> COM0 SEG383 -> SEG0 */
+  U8X8_C(0x037),	/* Start line 0 */
+  U8X8_A(0x000),
+  U8X8_END_TRANSFER(),  /* disable chip */
+  U8X8_END()           	/* end of sequence */
+};
+
+/* Flip Mode is not supported, use u8g2 rotation instead */
+
+static const uint8_t u8x8_d_st7586s_jlx320160_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x036),  /* Scan Direction Setting */
+  U8X8_A(0x000),  /* COM0 -> COM159 SEG0 -> SEG383 */
+  U8X8_C(0x037),  /* Start line 0 */
+  U8X8_A(0x000),
+  U8X8_END_TRANSFER(),  /* disable chip */
+  U8X8_END()            /* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7586s_jlx320160_init_seq[] = {
+  U8X8_START_TRANSFER(),/* enable chip */
+  U8X8_END_TRANSFER(),/* disable chip */
+ // U8G_ESC_RST(1), /* hardware reset */
+  U8X8_DLY(60),   /* Delay 60 ms */
+  U8X8_START_TRANSFER(),/* enable chip */
+
+  U8X8_C(0x001), // Soft reset
+  U8X8_DLY(60), // Delay 120 ms
+
+  U8X8_C(0x011), // Sleep Out
+  U8X8_C(0x028), // Display OFF
+  U8X8_DLY(25), // Delay 50 ms
+
+  U8X8_CAA(0x0C0,70,1),// Vop
+
+  U8X8_CA(0x0C3,0x002), // BIAS: 0 = 1/14, 2 = 1/12
+
+  U8X8_CA(0x0C4,0x007), // Booster = x8
+
+  U8X8_CA(0x0D0,0x01D), // Enable Analog Circuit
+
+  U8X8_CA(0x0B3,0x000), // Set FOSC divider
+
+  U8X8_CA(0x0B5,0x000), // N-Line = 0
+
+  U8X8_C(0x039), // 0x39 Monochrome mode. 0x38 - gray Mode
+
+  U8X8_C(0x03A), // Enable DDRAM Interface
+  U8X8_A(0x002), // monochrome and 4-level
+
+  U8X8_C(0x036), // Scan Direction Setting
+  U8X8_A(0x000), // COM:C159->C0   SEG: SEG383->SEG0
+
+  U8X8_C(0x0B1), // First output COM
+  U8X8_A(0x000), // 
+  
+  U8X8_C(0x0B0), // Duty Setting (num rows - 1)
+  U8X8_A(0x09F), 
+
+  U8X8_C(0x020), // Display inversion off
+
+  U8X8_C(0x02A), // Column Address Setting
+  U8X8_A(0), // COL0 -> COL127
+  U8X8_A(0), // 
+  U8X8_A(0), //
+  U8X8_A(112-1), // 112*3=336 pixels
+
+  U8X8_C(0x02B), // Row Address Setting
+  U8X8_A(0x000), // ROW0 -> ROW159
+  U8X8_A(0x000), //
+  U8X8_A(0x000), //
+  U8X8_A(0x09F), // 160 pixels
+
+  U8X8_C(0x029), // Display ON
+  U8X8_END_TRANSFER(),/* disable chip */
+  U8X8_END()  /* end of sequence */
+};
+
+static const u8x8_display_info_t u8x8_st7586s_jlx320160_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+
+  /* post_chip_enable_wait_ns = */ 5,
+  /* pre_chip_disable_wait_ns = */ 5,
+  /* reset_pulse_width_ms = */ 1,
+  /* post_reset_wait_ms = */ 6,
+  /* sda_setup_time_ns = */ 20,
+  /* sck_pulse_width_ns = */  100,  /* datasheet ST7586S */
+  /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* ST7586+Atmega128RFA1 works with 8MHz */
+  /* spi_mode = */ 3,   /* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 20, /* datasheet suggests min 20 */
+  /* write_pulse_width_ns = */ 40,
+  /* tile_width = */ 42,
+  /* tile_height = */ 20,
+  /* default_x_offset = */ 0,  /* abused as flag to know if we are flipped */
+  /* flipmode_x_offset = */ 1, /* as pixel order different for normal/flipped  */
+  /* pixel_width = */ 320,
+  /* pixel_height = */ 160
+};
+
+/*  https://github.com/olikraus/u8g2/issues/2186 */
+uint8_t u8x8_d_st7586s_jlx320160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) 
+{  
+  uint16_t c;
+  uint8_t *ptr;
+  uint8_t i, byte;
+  uint32_t input;
+  uint8_t output[8];
+//  uint8_t output[4];
+  switch (msg) {
+    case U8X8_MSG_DISPLAY_DRAW_TILE:
+    u8x8_cad_StartTransfer(u8x8); // OK Start transfer
+    u8x8_cad_SendCmd(u8x8, 0x02B);  /* Row Address Setting */
+    u8x8_cad_SendArg(u8x8, 0x000);
+    u8x8_cad_SendArg(u8x8, 0x008 * ((u8x8_tile_t *)arg_ptr)->y_pos);
+    u8x8_cad_SendArg(u8x8, 0x000);
+//    u8x8_cad_SendArg(u8x8, 0x09F); // should set end row based on display dimensions
+    u8x8_cad_SendArg(u8x8, u8x8->display_info->pixel_height - 1);  /* should this be u8x8->display_info->pixel_height - 1 */
+    u8x8_cad_SendCmd(u8x8, 0x02C);  /* cmd write display data to ram */
+    c = ((u8x8_tile_t *) arg_ptr)->cnt; //
+    c *= 8;
+    ptr = ((u8x8_tile_t *) arg_ptr)->tile_ptr;  //
+
+    while (c > 0) 
+    {
+      input = (((uint32_t)ptr[0] << 16) | ((uint32_t)ptr[1] << 8) | (uint32_t)ptr[2]);
+      for (i=0; i<8; i++)
+      {
+        byte = 0;
+        if (input & 0x800000)          // if bit 23
+            byte = byte | 0xC0;  //set pixel 1
+        if (input & 0x400000)          // if bit 22
+            byte = byte | 0x18;  //set pixel 2
+        if (input & 0x200000)          // if bit 22
+            byte = byte | 0x3;  //set pixel 3
+        output[i] = byte;
+        input <<= 3;
+      }
+      u8x8_cad_SendData(u8x8, 8, output);
+      ptr += 3;
+      c -= 3;
+    }
+    u8x8_cad_EndTransfer(u8x8); 
+    break;
+  case U8X8_MSG_DISPLAY_INIT:
+    u8x8_d_helper_display_init(u8x8);
+    u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_jlx320160_init_seq);
+    break;
+  case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+    u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7586s_jlx320160_display_info);
+    break;
+  case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+  	if ( arg_int == 0 )
+    {
+       u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_jlx320160_flip0_seq);
+       u8x8->x_offset = u8x8->display_info->default_x_offset;
+    }
+    else
+    {
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_jlx320160_flip1_seq);
+      u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+    }	
+    break;
+  case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+    if (arg_int == 0)
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_sleep_off);
+    else
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_sleep_on);
+    break;
+#ifdef U8X8_WITH_SET_CONTRAST
+  case U8X8_MSG_DISPLAY_SET_CONTRAST:
+    u8x8_cad_StartTransfer(u8x8);
+    u8x8_cad_SendCmd(u8x8, 0x0C0);
+    u8x8_cad_SendArg(u8x8, arg_int);
+    u8x8_cad_SendArg(u8x8, 1);
+    u8x8_cad_EndTransfer(u8x8);
+    break;
+#endif
+  default:
+    return 0;
+  }
+  return 1;
+}
+

+ 256 - 0
components/u8g2/u8x8_d_st7586s_jlx384160.c

@@ -0,0 +1,256 @@
+/*
+  u8x8_d_st7586s_jlx384160.c
+  
+  copyied from u8x8_d_st7586s_s028hn118a.c
+  
+  Display: 384x160 pixel, https://github.com/olikraus/u8g2/issues/1932
+  ST7586s: 384 x 160 x 2
+  
+  Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
+  
+  Copyright (c) 2022, olikraus@gmail.com
+  
+  All rights reserved.
+  Redistribution and use in source and binary forms, with or without modification, 
+  are permitted provided that the following conditions are met:
+  * Redistributions of source code must retain the above copyright notice, this list 
+    of conditions and the following disclaimer.
+    
+  * Redistributions in binary form must reproduce the above copyright notice, this 
+    list of conditions and the following disclaimer in the documentation and/or other 
+    materials provided with the distribution.
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
+  CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
+  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
+  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
+  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
+  
+*/
+
+#include "u8g2.h"
+
+
+static const uint8_t u8x8_d_st7586s_sleep_on[] = {
+  U8X8_START_TRANSFER(),  /* enable chip, delay is part of the transfer start */
+  U8X8_C(0x010), /* set power save mode */
+  U8X8_END_TRANSFER(),  /* disable chip */
+  U8X8_END()                  /* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7586s_sleep_off[] = {
+  U8X8_START_TRANSFER(),  /* enable chip, delay is part of the transfer start */
+  U8X8_C(0x011), //Sleep out
+  U8X8_DLY(50), /* delay 50 ms */
+  U8X8_END_TRANSFER(),  /* disable chip */
+  U8X8_END()                  /* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7586s_jlx384160_flip0_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x036),				/* Scan Direction Setting */
+  U8X8_A(0x000),				/* COM0 -> COM159 SEG0 -> SEG384 */
+  U8X8_C(0x037),				/* Start line 0 */
+  U8X8_A(0x000),
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static const uint8_t u8x8_d_st7586s_jlx384160_flip1_seq[] = {
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_C(0x036),				/* Scan Direction Setting */
+  U8X8_A(0x0C8),				/* COM159 -> COM0 SEG384 -> SEG0 */
+  U8X8_C(0x037),				/* Start line 0 */
+  U8X8_A(0x000),
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+static uint8_t u8x8_d_st7586s_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
+  uint8_t c;
+  uint8_t *ptr;
+  uint8_t i, byte;
+  uint32_t input;
+  uint8_t output[8];
+  switch (msg) {
+  case U8X8_MSG_DISPLAY_DRAW_TILE:
+    u8x8_cad_StartTransfer(u8x8); // OK Start transfer
+    u8x8_cad_SendCmd(u8x8, 0x02B);  /* Row Address Setting */
+    u8x8_cad_SendArg(u8x8, 0x000);
+    u8x8_cad_SendArg(u8x8, 0x008 * ((u8x8_tile_t *)arg_ptr)->y_pos);
+    u8x8_cad_SendArg(u8x8, 0x000);
+    u8x8_cad_SendArg(u8x8, u8x8->display_info->pixel_height - 1);  /* should this be u8x8->display_info->pixel_height - 1 */
+    u8x8_cad_SendCmd(u8x8, 0x02C);  /* cmd write display data to ram */
+    c = ((u8x8_tile_t *) arg_ptr)->cnt; //
+    c *= 8;
+    ptr = ((u8x8_tile_t *) arg_ptr)->tile_ptr;  //
+
+// The ST7586S has an unusual 3 pixels per byte format so here we read in 3 bytes (24 pixels) and
+// pack that into 8 bytes of 3 pixels each 	
+	while (c > 0) {
+      input = (((uint32_t)ptr[0] << 16) | ((uint32_t)ptr[1] << 8) | (uint32_t)ptr[2]);
+      for (i=0; i<8; i++)
+      {
+        byte = 0;
+        if (input & 0x800000)          // if bit 23
+            byte = byte | 0xC0;  //set pixel 1
+        if (input & 0x400000)          // if bit 22
+            byte = byte | 0x18;  //set pixel 2
+		if (input & 0x200000)          // if bit 22
+			byte = byte | 0x3;  //set pixel 3
+		output[i] = byte;
+        input <<= 3;
+      }
+      u8x8_cad_SendData(u8x8, 8, output);
+      ptr += 3;
+      c -= 3;
+    }
+    u8x8_cad_EndTransfer(u8x8);
+    break;
+  case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
+    if (arg_int == 0)
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_sleep_off);
+    else
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_sleep_on);
+    break;
+#ifdef U8X8_WITH_SET_CONTRAST
+  case U8X8_MSG_DISPLAY_SET_CONTRAST:
+    u8x8_cad_StartTransfer(u8x8);
+    u8x8_cad_SendCmd(u8x8, 0x0C0);
+    u8x8_cad_SendArg(u8x8, arg_int);
+    u8x8_cad_SendArg(u8x8, 0);
+    u8x8_cad_EndTransfer(u8x8);
+    break;
+#endif
+  default:
+    return 0;
+  }
+  return 1;
+}
+
+static const uint8_t u8x8_d_st7586s_jlx384160_init_seq[] = {
+  U8X8_START_TRANSFER(),/* enable chip */
+  U8X8_END_TRANSFER(),/* disable chip */
+//  U8G_ESC_RST(15), /* hardware reset */
+  U8X8_DLY(60),   /* Delay 60 ms */
+  U8X8_START_TRANSFER(),/* enable chip */
+
+  U8X8_C(0x001), // Soft reset
+  U8X8_DLY(60), // Delay 120 ms
+
+  U8X8_C(0x011), // Sleep Out
+  U8X8_C(0x028), // Display OFF
+  U8X8_DLY(25), // Delay 50 ms
+
+  U8X8_CAA(0x0C0,0x0E5,0x00),// Vop = F0h in trace a bit too dark
+
+  U8X8_CA(0x0C3,0x004), // BIAS = 1/10 0x04 in trace
+
+  U8X8_CA(0x0C4,0x005), // Booster = x6 0x05 in trace
+
+  U8X8_CA(0x0D0,0x01D), // Enable Analog Circuit
+
+  U8X8_CA(0x0B3,0x000), // Set FOSC divider
+
+  U8X8_CA(0x0B5,0x08B), // N-Line = 0
+
+  U8X8_C(0x039), // 0x39 Monochrome mode. 0x38 - gray Mode
+
+  U8X8_C(0x03A), // Enable DDRAM Interface
+  U8X8_A(0x002), // monochrome and 4-level
+
+  U8X8_C(0x036), // Scan Direction Setting
+  U8X8_A(0x000), // COM0 -> COM159 SEG0 -> SEG384
+
+  U8X8_C(0x0B0), // Duty Setting (num rows - 1)
+  U8X8_A(0x09f), // 160-1
+
+  U8X8_C(0x020), // Display inversion off
+
+  U8X8_C(0x02A), // Column Address Setting
+  U8X8_A(0x000), // COL0 -> COL127
+  U8X8_A(0x000), // 
+  U8X8_A(0x000), //
+  U8X8_A(0x07f), // 128*3=384 pixels
+
+  U8X8_C(0x02B), // Row Address Setting
+  U8X8_A(0x000), // ROW0 -> ROW135
+  U8X8_A(0x000), //
+  U8X8_A(0x000), //
+  U8X8_A(159), // 160 pixels
+
+  U8X8_C(0x0F1), // Frame rate monochrome
+  U8X8_A(0x00C), // The factory firmware set this to 49.0 Hz 0x07
+  U8X8_A(0x00C), // This caused a shimmer under 50Hz LED lights
+  U8X8_A(0x00C), // 69.0 Hz (0x0C) fixes this and should avoid the
+  U8X8_A(0x00C), // issue in the US too
+  
+  U8X8_C(0x029), // Display ON
+  U8X8_END_TRANSFER(),/* disable chip */
+  U8X8_END()  /* end of sequence */
+};
+
+static const u8x8_display_info_t u8x8_st7586s_jlx384160_display_info =
+{
+  /* chip_enable_level = */ 0,
+  /* chip_disable_level = */ 1,
+
+  /* post_chip_enable_wait_ns = */ 5,
+  /* pre_chip_disable_wait_ns = */ 5,
+  /* reset_pulse_width_ms = */ 1,
+  /* post_reset_wait_ms = */ 6,
+  /* sda_setup_time_ns = */ 20,
+  /* sck_pulse_width_ns = */  100,  /* datasheet ST7586S */
+  /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* ST7586+Atmega128RFA1 works with 8MHz */
+  /* spi_mode = */ 3,   /* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 20, /* datasheet suggests min 20 */
+  /* write_pulse_width_ns = */ 40,
+  /* tile_width = */ 48,
+  /* tile_height = */ 20,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 384,
+  /* pixel_height = */ 160
+};
+
+/*******************************************************************************
+ * st7586s_jlx384160 driver. This is the display in the SMART Response XE. This requires 16 bit mode.
+ ******************************************************************************/
+uint8_t u8x8_d_st7586s_jlx384160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
+  if (u8x8_d_st7586s_common(u8x8, msg, arg_int, arg_ptr) != 0)
+    return 1;
+  
+  switch (msg) {
+  case U8X8_MSG_DISPLAY_INIT:
+    u8x8_d_helper_display_init(u8x8);
+    u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_jlx384160_init_seq);
+    break;
+  case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+    u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7586s_jlx384160_display_info);
+    break;
+  case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
+  	if ( arg_int == 0 )
+    {
+       u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_jlx384160_flip0_seq);
+       u8x8->x_offset = u8x8->display_info->default_x_offset;
+    }
+    else
+    {
+      u8x8_cad_SendSequence(u8x8, u8x8_d_st7586s_jlx384160_flip1_seq);
+      u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
+    }	
+    break;
+  default:
+    return 0;
+  }
+  return 1;
+}

+ 1 - 1
components/u8g2/u8x8_d_st7588.c

@@ -166,7 +166,7 @@ static const u8x8_display_info_t u8x8_st7588_128x64_display_info =
   /* data_setup_time_ns = */ 80,
   /* write_pulse_width_ns = */ 50,	
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,	/* must be 0, because this is checked also for normal mode */
   /* flipmode_x_offset = */ 4,		
   /* pixel_width = */ 128,

+ 114 - 14
components/u8g2/u8x8_d_st7920.c

@@ -152,7 +152,11 @@ uint8_t u8x8_d_st7920_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
   return 1;
 }
 
-static const u8x8_display_info_t u8x8_st7920_192x32_display_info =
+
+/*=== 144x32 === */
+/* https://github.com/olikraus/u8g2/issues/209 */
+
+static const u8x8_display_info_t u8x8_st7920_144x32_display_info =
 {
   /* chip_enable_level = */ 1,
   /* chip_disable_level = */ 0,
@@ -169,15 +173,40 @@ static const u8x8_display_info_t u8x8_st7920_192x32_display_info =
   /* i2c_bus_clock_100kHz = */ 4,
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
-  /* tile_width = */ 24,
-  /* tile_hight = */ 4,
+  /* tile_width = */ 18,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
-  /* pixel_width = */ 192,
+  /* pixel_width = */ 144,
   /* pixel_height = */ 32
 };
 
-static const u8x8_display_info_t u8x8_st7920_128x64_display_info =
+
+uint8_t u8x8_d_st7920_144x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_144x32_display_info);
+      break;
+    default:
+      return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}
+
+
+
+
+
+
+
+
+
+/*=== 160x32 === */
+/* https://github.com/olikraus/u8g2/issues/1873, POWERTIP PG-16032LRU-BWH-H-P2 */
+
+static const u8x8_display_info_t u8x8_st7920_160x32_display_info =
 {
   /* chip_enable_level = */ 1,
   /* chip_disable_level = */ 0,
@@ -189,20 +218,62 @@ static const u8x8_display_info_t u8x8_st7920_128x64_display_info =
   /* sda_setup_time_ns = */ 20,		
   /* sck_pulse_width_ns = */  140,	/* datasheet ST7920 */
   /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
-  /* ST7920+Due work with 1MHz but not with 2MHz, ST7920+Uno works with 2MHz */
-  /* spi_mode = */ 3,		/* active high, rising edge, 18 Aug 16: changed from 1 to 3 which works for 101  */
-  /* in theory mode 3 should be correct  */
+  /* spi_mode = */ 3,		/* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0), 18 Aug 16: changed from 1 to 3 which works for 101 */
+	/* Arduino mode 3: aktive low clock, but use rising edge */
   /* i2c_bus_clock_100kHz = */ 4,
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
-  /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_width = */ 20,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
-  /* pixel_width = */ 128,
-  /* pixel_height = */ 64
+  /* pixel_width = */ 160,
+  /* pixel_height = */ 32
+};
+
+
+uint8_t u8x8_d_st7920_160x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_160x32_display_info);
+      break;
+    default:
+      return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}
+
+
+/*=== 192x32 === */
+
+static const u8x8_display_info_t u8x8_st7920_192x32_display_info =
+{
+  /* chip_enable_level = */ 1,
+  /* chip_disable_level = */ 0,
+  
+  /* post_chip_enable_wait_ns = */ 5,
+  /* pre_chip_disable_wait_ns = */ 5,
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 6, 
+  /* sda_setup_time_ns = */ 20,		
+  /* sck_pulse_width_ns = */  140,	/* datasheet ST7920 */
+  /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 3,		/* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0), 18 Aug 16: changed from 1 to 3 which works for 101 */
+	/* Arduino mode 3: aktive low clock, but use rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 30,
+  /* write_pulse_width_ns = */ 40,
+  /* tile_width = */ 24,
+  /* tile_height = */ 4,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 192,
+  /* pixel_height = */ 32
 };
 
+
 uint8_t u8x8_d_st7920_192x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
   switch(msg)
@@ -216,6 +287,34 @@ uint8_t u8x8_d_st7920_192x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
   return 1;
 }
 
+/*=== 128x64 === */
+
+static const u8x8_display_info_t u8x8_st7920_128x64_display_info =
+{
+  /* chip_enable_level = */ 1,
+  /* chip_disable_level = */ 0,
+  
+  /* post_chip_enable_wait_ns = */ 5,
+  /* pre_chip_disable_wait_ns = */ 5,
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 6, 
+  /* sda_setup_time_ns = */ 20,		
+  /* sck_pulse_width_ns = */  140,	/* datasheet ST7920 */
+  /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* ST7920+Due work with 1MHz but not with 2MHz, ST7920+Uno works with 2MHz */
+  /* spi_mode = */ 3,		/* active high, rising edge, 18 Aug 16: changed from 1 to 3 which works for 101  */
+  /* in theory mode 3 should be correct  */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 30,
+  /* write_pulse_width_ns = */ 40,
+  /* tile_width = */ 16,
+  /* tile_height = */ 8,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 64
+};
+
 uint8_t u8x8_d_st7920_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
 {
   switch(msg)
@@ -229,6 +328,7 @@ uint8_t u8x8_d_st7920_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
   return 1;
 }
 
+/*=== 256x32 === */
 /* https://github.com/olikraus/u8g2/issues/1593 */
 
 static const u8x8_display_info_t u8x8_st7920_256x32_display_info =
@@ -250,7 +350,7 @@ static const u8x8_display_info_t u8x8_st7920_256x32_display_info =
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
   /* tile_width = */ 32,
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 256,
@@ -269,4 +369,4 @@ uint8_t u8x8_d_st7920_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
 	  return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
   }
   return 1;
-}
+}

+ 1 - 2
components/u8g2/u8x8_d_stdio.c

@@ -32,7 +32,7 @@
   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
 
 */
-#if 0
+
 #include "u8x8.h"
 
 #include <stdio.h>
@@ -99,4 +99,3 @@ void u8x8_SetupStdio(u8x8_t *u8x8)
   u8x8->display_cb = u8x8_d_stdio;
 }
 
-#endif

+ 87 - 6
components/u8g2/u8x8_d_t6963.c

@@ -140,7 +140,7 @@ static const u8x8_display_info_t u8x8_t6963_240x128_display_info =
   /* data_setup_time_ns = */ 80,
   /* write_pulse_width_ns = */ 80,
   /* tile_width = */ 30,
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 240,
@@ -224,7 +224,7 @@ static const u8x8_display_info_t u8x8_t6963_240x64_display_info =
   /* data_setup_time_ns = */ 80,
   /* write_pulse_width_ns = */ 80,
   /* tile_width = */ 30,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 240,
@@ -311,7 +311,7 @@ static const u8x8_display_info_t u8x8_t6963_256x64_display_info =
   /* data_setup_time_ns = */ 80,
   /* write_pulse_width_ns = */ 80,
   /* tile_width = */ 32,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 256,
@@ -394,7 +394,7 @@ static const u8x8_display_info_t u8x8_t6963_128x64_display_info =
   /* data_setup_time_ns = */ 80,
   /* write_pulse_width_ns = */ 80,
   /* tile_width = */ 16,
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,
@@ -476,7 +476,7 @@ static const u8x8_display_info_t u8x8_t6963_160x80_display_info =
   /* data_setup_time_ns = */ 80,
   /* write_pulse_width_ns = */ 80,
   /* tile_width = */ 20,
-  /* tile_hight = */ 10,
+  /* tile_height = */ 10,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 160,
@@ -559,6 +559,87 @@ uint8_t u8x8_d_t6963_128x64_alt(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void
 }
 
 
+/*=============================================*/
+
+static const u8x8_display_info_t u8x8_t6963_128x128_display_info =
+{
+  /* chip_enable_level = */ 1,
+  /* chip_disable_level = */ 0,
+  
+  /* post_chip_enable_wait_ns = */ 10,	/* T6963 Datasheet p30 */
+  /* pre_chip_disable_wait_ns = */ 100,	/* T6963 Datasheet p30 */
+  /* reset_pulse_width_ms = */ 1, 
+  /* post_reset_wait_ms = */ 6, 
+  /* sda_setup_time_ns = */ 20,		
+  /* sck_pulse_width_ns = */  140,	
+  /* sck_clock_hz = */ 1000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 80,
+  /* write_pulse_width_ns = */ 80,
+  /* tile_width = */ 16,
+  /* tile_height = */ 16,
+  /* default_x_offset = */ 0,
+  /* flipmode_x_offset = */ 0,
+  /* pixel_width = */ 128,
+  /* pixel_height = */ 128
+};
+
+/* 128x64 */
+static const uint8_t u8x8_d_t6963_128x128_init_seq[] = {
+  U8X8_DLY(100),
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+  U8X8_DLY(100),
+  
+  U8X8_AAC(0x00,0x00,0x021),	/* low, high, set cursor pos */
+  U8X8_AAC(0x00,0x00,0x022),	/* low, high, set offset */
+  U8X8_AAC(0x00,0x00,0x040),	/* low, high, set text home */
+  U8X8_AAC(128/8,0x00,0x041),	/* low, high, set text columns */
+  U8X8_AAC(0x00,0x00,0x042),	/* low, high, graphics home */  
+  U8X8_AAC(128/8,0x00,0x043),	/* low, high, graphics columns */
+  U8X8_DLY(2),					/* delay 2ms */
+  // mode set
+  // 0x080: Internal CG, OR Mode
+  // 0x081: Internal CG, EXOR Mode
+  // 0x083: Internal CG, AND Mode
+  // 0x088: External CG, OR Mode
+  // 0x089: External CG, EXOR Mode
+  // 0x08B: External CG, AND Mode
+  U8X8_C(0x080),            			/* mode register: OR Mode, Internal Character Mode */
+  // display mode
+  // 0x090: Display off
+  // 0x094: Graphic off, text on, cursor off, blink off
+  // 0x096: Graphic off, text on, cursor on, blink off
+  // 0x097: Graphic off, text on, cursor on, blink on
+  // 0x098: Graphic on, text off, cursor off, blink off
+  // 0x09a: Graphic on, text off, cursor on, blink off
+  // ...
+  // 0x09c: Graphic on, text on, cursor off, blink off
+  // 0x09f: Graphic on, text on, cursor on, blink on
+  U8X8_C(0x090),                             /* All Off */
+  U8X8_AAC(0x00,0x00,0x024),	/* low, high, set adr pointer */
+  
+  U8X8_DLY(100),
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_DLY(100),
+};
+
+uint8_t u8x8_d_t6963_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  switch(msg)
+  {
+    case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+      u8x8_d_helper_display_setup_memory(u8x8, &u8x8_t6963_128x128_display_info);
+      break;
+    case U8X8_MSG_DISPLAY_INIT:
+      u8x8_d_helper_display_init(u8x8);
+      u8x8_cad_SendSequence(u8x8, u8x8_d_t6963_128x128_init_seq);
+      break;
+    default:
+      return u8x8_d_t6963_common(u8x8, msg, arg_int, arg_ptr);
+  }
+  return 1;
+}
   
 
-  
+  

+ 2 - 2
components/u8g2/u8x8_d_uc1601.c

@@ -88,7 +88,7 @@ static const u8x8_display_info_t u8x8_uc1601_128x32_display_info =
   /* data_setup_time_ns = */ 60,	/* uc1601 datasheet, page 43 */
   /* write_pulse_width_ns = */ 80,	/* uc1601 datasheet, page 43 */
   /* tile_width = */ 16,		
-  /* tile_hight = */ 4,
+  /* tile_height = */ 4,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 4,
   /* pixel_width = */ 128,
@@ -228,7 +228,7 @@ static const u8x8_display_info_t u8x8_uc1601_128x64_display_info =
   /* data_setup_time_ns = */ 60,	/* uc1601 datasheet, page 43 */
   /* write_pulse_width_ns = */ 80,	/* uc1601 datasheet, page 43 */
   /* tile_width = */ 16,		
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 2,
   /* flipmode_x_offset = */ 4,  /* IS THIS CORRECT? */
   /* pixel_width = */ 128,

+ 1 - 1
components/u8g2/u8x8_d_uc1604.c

@@ -172,7 +172,7 @@ static const u8x8_display_info_t u8x8_uc1604_192x64_display_info =
   /* data_setup_time_ns = */ 30,	
   /* write_pulse_width_ns = */ 35,	
   /* tile_width = */ 24,		/* width of 24*8=192 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,	/* reused as y page offset */
   /* flipmode_x_offset = */ 0,	/* reused as y page offset */
   /* pixel_width = */ 192,

+ 4 - 4
components/u8g2/u8x8_d_uc1608.c

@@ -165,7 +165,7 @@ static const u8x8_display_info_t u8x8_uc1608_240x64_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1608 datasheet, page 39 */
   /* write_pulse_width_ns = */ 35,	/* uc1608 datasheet, page 39 */
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,	/* reused as y page offset */
   /* flipmode_x_offset = */ 4,	/* reused as y page offset */
   /* pixel_width = */ 240,
@@ -246,7 +246,7 @@ static const u8x8_display_info_t u8x8_uc1608_240x128_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1608 datasheet, page 39 */
   /* write_pulse_width_ns = */ 35,	/* uc1608 datasheet, page 39 */
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,	/* reused as y page offset */
   /* flipmode_x_offset = */ 0,	/* reused as y page offset */
   /* pixel_width = */ 240,
@@ -327,7 +327,7 @@ static const u8x8_display_info_t u8x8_uc1608_erc240120_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1608 datasheet, page 39 */
   /* write_pulse_width_ns = */ 35,	/* uc1608 datasheet, page 39 */
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 15,
+  /* tile_height = */ 15,
   /* default_x_offset = */ 1,	/* reused as y page offset */
   /* flipmode_x_offset = */ 0,	/* reused as y page offset */
   /* pixel_width = */ 240,
@@ -411,7 +411,7 @@ static const u8x8_display_info_t u8x8_uc1608_dem240064_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1608 datasheet, page 39 */
   /* write_pulse_width_ns = */ 35,	/* uc1608 datasheet, page 39 */
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 1,	/* reused as y page offset */
   /* flipmode_x_offset = */ 0,	/* reused as y page offset */
   /* pixel_width = */ 240,

+ 1 - 1
components/u8g2/u8x8_d_uc1609.c

@@ -131,7 +131,7 @@ static const u8x8_display_info_t u8x8_uc1609_19264_display_info =
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
   /* tile_width = */ 24,		
-  /* tile_hight = */ 8,		
+  /* tile_height = */ 8,		
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 192,

+ 1 - 1
components/u8g2/u8x8_d_uc1610.c

@@ -158,7 +158,7 @@ static const u8x8_display_info_t u8x8_uc1610_display_info =
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
   /* tile_width = */ 20,		
-  /* tile_hight = */ 13,		/* height of 13*8=104 pixel */
+  /* tile_height = */ 13,		/* height of 13*8=104 pixel */
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 160,

+ 5 - 5
components/u8g2/u8x8_d_uc1611.c

@@ -162,7 +162,7 @@ static const u8x8_display_info_t u8x8_uc1611_240x64_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1611 datasheet, page 60 */
   /* write_pulse_width_ns = */ 80,	/* uc1611 datasheet, page 60 */
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 240,
@@ -280,7 +280,7 @@ static const u8x8_display_info_t u8x8_uc1611_240x128_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1611 datasheet, page 60 */
   /* write_pulse_width_ns = */ 80,	/* uc1611 datasheet, page 60 */
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 240,
@@ -373,7 +373,7 @@ static const u8x8_display_info_t u8x8_uc1611_ew50850_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1611 datasheet, page 60 */
   /* write_pulse_width_ns = */ 80,	/* uc1611 datasheet, page 60 */
   /* tile_width = */ 30,		/* width of 30*8=240 pixel */
-  /* tile_hight = */ 20,		/* height: 160 pixel */
+  /* tile_height = */ 20,		/* height: 160 pixel */
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 240,
@@ -530,7 +530,7 @@ static const u8x8_display_info_t u8x8_uc1611_cg160160_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1611 datasheet, page 60 */
   /* write_pulse_width_ns = */ 80,	/* uc1611 datasheet, page 60 */
   /* tile_width = */ 20,		/* width of 20*8=160 pixel */
-  /* tile_hight = */ 20,
+  /* tile_height = */ 20,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 160,
@@ -680,7 +680,7 @@ static const u8x8_display_info_t u8x8_uc1611_256x128_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1611 datasheet, page 60 */
   /* write_pulse_width_ns = */ 80,	/* uc1611 datasheet, page 60 */
   /* tile_width = */ 32,		/* width of 32*8=256 pixel */
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 256,

+ 1 - 1
components/u8g2/u8x8_d_uc1617.c

@@ -294,7 +294,7 @@ static const u8x8_display_info_t u8x8_uc1617_128x128_display_info =
   /* data_setup_time_ns = */ 30,	/* uc1617 datasheet, page 52 */
   /* write_pulse_width_ns = */ 65,	/* uc1617 datasheet, page 52 */
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 0,
   /* pixel_width = */ 128,

+ 76 - 2
components/u8g2/u8x8_d_uc1638.c

@@ -175,7 +175,7 @@ static const u8x8_display_info_t u8x8_uc1638_160x128_display_info =
   /* data_setup_time_ns = */ 30,	/*  */
   /* write_pulse_width_ns = */ 35,	/*  */
   /* tile_width = */ 20,		/* width of 20*8=160 pixel */
-  /* tile_hight = */ 16,
+  /* tile_height = */ 16,
   /* default_x_offset = */ 0,	/* lower nibble: x offset, upper nibble: y offset */
   /* flipmode_x_offset = */ 0,	/* lower nibble: x offset, upper nibble: y offset */
   /* pixel_width = */ 160,
@@ -252,7 +252,7 @@ static const u8x8_display_info_t u8x8_uc1638_192x96_display_info =
   /* data_setup_time_ns = */ 30,	/*  */
   /* write_pulse_width_ns = */ 35,	/*  */
   /* tile_width = */ 24,		/* width of 24*8=192 pixel */
-  /* tile_hight = */ 12,
+  /* tile_height = */ 12,
   /* default_x_offset = */ 8*16+0,	/* lower nibble: x offset, upper nibble: y offset */
   /* flipmode_x_offset = */ 0*16+6,	/* lower nibble: x offset, upper nibble: y offset */
   /* pixel_width = */ 192,
@@ -304,3 +304,77 @@ uint8_t u8x8_d_uc1638_192x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
   }
   return 1;
 }
+
+/*================================================*/
+/* issue https://github.com/olikraus/u8g2/issues/2075 */
+
+static const u8x8_display_info_t u8x8_uc1638_240x128_display_info =
+{
+  /* chip_enable_level = */ 0,	/* low active CS for this display */
+  /* chip_disable_level = */ 1,
+  
+  /* post_chip_enable_wait_ns = */ 10,	/* */
+  /* pre_chip_disable_wait_ns = */ 20,	/* */
+  /* reset_pulse_width_ms = */ 5, 	/* */
+  /* post_reset_wait_ms = */ 150, 	
+  /* sda_setup_time_ns = */ 25,		/* */
+  /* sck_pulse_width_ns = */ 65,	/* */
+  /* sck_clock_hz = */ 2000000UL,	/* since Arduino 1.6.0, the SPI bus speed in Hz. Should be  1000000000/sck_pulse_width_ns */
+  /* spi_mode = */ 0,		/* active high, rising edge */
+  /* i2c_bus_clock_100kHz = */ 4,
+  /* data_setup_time_ns = */ 30,	/*  */
+  /* write_pulse_width_ns = */ 35,	/*  */
+  /* tile_width = */ 30,		/* width of 30*8=240 pixel */
+  /* tile_height = */ 16,
+  /* default_x_offset = */ 0*16+0,	/* lower nibble: x offset, upper nibble: y offset */
+  /* flipmode_x_offset = */ 4*16+0,	/* lower nibble: x offset, upper nibble: y offset */
+  /* pixel_width = */ 240,
+  /* pixel_height = */ 128
+};
+
+static const uint8_t u8x8_d_uc1638_240x128_init_seq[] = {
+    
+  U8X8_START_TRANSFER(),             	/* enable chip, delay is part of the transfer start */
+
+  U8X8_CA(0x0e1, 0x0e2),		/* software reset */    /* UC1638*/
+  U8X8_DLY(5),					/* 5 ms */	
+
+  U8X8_C(0x024),            		/*	 set temp comp*/
+  U8X8_C(0x0c2),            		/*	mirror y and mirror x */ 
+  U8X8_C(0x0a2),            		/*	line rate */
+  //U8X8_C(0x02d),            		/*	charge pump, issue 2075: not used */
+  U8X8_C(0x0eb),            		/*	 set bias, issue 2075: 0x0eb*/
+  U8X8_CA(0x081, 120),            	/*	 set contrast, issue 2075 */
+  //U8X8_C(0x0d6),            		/*	gray scale 2 */
+  U8X8_C(0x095),            		/*	 set 1 bit per pixel, pattern 0*/
+  //U8X8_C(0x086),            		/*	 COM scan, issue 2075: not used */
+  //U8X8_CA(0x0f1, 159),            	/*	 COM End, issue 2075: not used */
+  U8X8_C(0x089),            		/*	 set auto increment, low bits are AC2 AC1 AC0 */  /* WAS 89 */
+  //U8X8_C(0x086),            		/*	 scan function 0x86 or 0x87: no effect*/
+  
+  U8X8_END_TRANSFER(),             	/* disable chip */
+  U8X8_END()             			/* end of sequence */
+};
+
+uint8_t u8x8_d_uc1638_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
+{
+  /* call common procedure first and handle messages there */
+  if ( u8x8_d_uc1638_common(u8x8, msg, arg_int, arg_ptr) == 0 )
+  {
+    /* msg not handled, then try here */
+    switch(msg)
+    {
+      case U8X8_MSG_DISPLAY_SETUP_MEMORY:
+	u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1638_240x128_display_info);
+	break;
+      case U8X8_MSG_DISPLAY_INIT:
+	u8x8_d_helper_display_init(u8x8);
+          u8x8_cad_SendSequence(u8x8, u8x8_d_uc1638_240x128_init_seq);
+	break;
+      default:
+	return 0;		/* msg unknown */
+    }
+  }
+  return 1;
+}
+

+ 1 - 1
components/u8g2/u8x8_d_uc1701_dogs102.c

@@ -117,7 +117,7 @@ static const u8x8_display_info_t u8x8_uc1701_display_info =
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
   /* tile_width = */ 13,		/* width of 13*8=104 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 30,
   /* pixel_width = */ 102,

+ 1 - 1
components/u8g2/u8x8_d_uc1701_mini12864.c

@@ -117,7 +117,7 @@ static const u8x8_display_info_t u8x8_uc1701_display_info =
   /* data_setup_time_ns = */ 30,
   /* write_pulse_width_ns = */ 40,
   /* tile_width = */ 16,		/* width of 16*8=128 pixel */
-  /* tile_hight = */ 8,
+  /* tile_height = */ 8,
   /* default_x_offset = */ 0,
   /* flipmode_x_offset = */ 4,
   /* pixel_width = */ 128,

+ 1 - 1
components/u8g2/u8x8_debounce.c

@@ -136,7 +136,7 @@ uint8_t u8x8_GetMenuEvent(u8x8_t *u8x8)
 #define U8X8_DEBOUNCE_WAIT 2
 /* do debounce and return a GPIO msg which indicates the event */
 /* returns 0, if there is no event */
-#if defined(__GNUC__) && !defined(__CYGWIN__)
+#if defined(__GNUC__) && !defined(_WIN32)
 # pragma weak  u8x8_GetMenuEvent
 #endif
 uint8_t u8x8_GetMenuEvent(u8x8_t *u8x8)

+ 3 - 2
components/u8g2/u8x8_display.c

@@ -134,7 +134,8 @@ void u8x8_InitInterface(u8x8_t *u8x8)
 */
 void u8x8_InitDisplay(u8x8_t *u8x8)
 {
-  u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_INIT, 0, NULL);  
+  u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_INIT, 0, NULL);       /* this will call u8x8_d_helper_display_init() and send the init seqence to the display */
+  /* u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_SET_FLIP_MODE, 0, NULL);  */ /* It would make sense to call flip mode 0 here after U8X8_MSG_DISPLAY_INIT */
 }
 
 void u8x8_SetPowerSave(u8x8_t *u8x8, uint8_t is_enable)
@@ -199,4 +200,4 @@ void u8x8_ClearLine(u8x8_t *u8x8, uint8_t line)
     tile.tile_ptr = (uint8_t *)buf;		/* tile_ptr should be const, but isn't */
     u8x8->display_cb(u8x8, U8X8_MSG_DISPLAY_DRAW_TILE, u8x8->display_info->tile_width, (void *)&tile);
   }  
-}
+}

Разница между файлами не показана из-за своего большого размера
+ 170 - 170
components/u8g2/u8x8_fonts.c


Некоторые файлы не были показаны из-за большого количества измененных файлов