Celkem zajímavý projekt grafického uživatelského prostředí pro displej s řadičem T6963 jsem nalezl na foru microcontroller.net. Projekt jsem netestoval, neb se mi tu nepovaluje žádný LCD s tímto řadičem. Popravdě jsem ani nestudoval zdrojový kód. To přenechám na vás a věřím že se to bude někomu hodit.

#include <stdlib.h> //
#include <stdio.h> //
#include <string.h>  //
#include <avr/io.h>  //
#include <avr/interrupt.h>  //
#include <avr/eeprom.h>  //
#include <util/delay.h>  //
#include <avr/pgmspace.h>  //
#include <avr/wdt.h>  //
#include <math.h> //

#include "include/config.h"
#include "include/general.h"
#include "include/t6963c.h"
#include "include/graphics.h"
#include "include/inputs.h"
#include "include/mem_check.h"
#include "include/font.h"
#include "data/fonts/font_def.h"
#include "include/gui.h"
#include "include/timer.h"

#include "data/gfx/button_no_msg.xbm"
#include "data/gfx/button_new_msg.xbm"

#ifdef DEBUG
void callback_timer_show_ram(void)
{
  char buffer[20];
  GUI_TIMER_REMOVE( callback_timer_show_ram );
  sprintf(buffer,"Free ram : %3d",GET_FREE_RAM());
  GLCD_PRINT(0,GLCD_YMAX-(GLCD_GET_FONT_HEIGHT(NORMAL_FONT)*3),buffer,NORMAL_FONT,FALSE);
  sprintf(buffer,"Unused ram : %3d",GET_UNUSED_RAM());
  GLCD_PRINT(0,GLCD_YMAX-(GLCD_GET_FONT_HEIGHT(NORMAL_FONT)*2),buffer,NORMAL_FONT,FALSE);
  GUI_TIMER_ADD( callback_timer_show_ram, SECONDS( 5 ) );
}
#endif

const char str1[] PROGMEM ="TEE 103";
const char str2[] PROGMEM ="TEE 120";
const char str3[] PROGMEM ="BR 218 Blue";
const char str4[] PROGMEM ="BR 218 Red";
const char str5[] PROGMEM ="T3";
const char str6[] PROGMEM ="Koef II";

PGM_P liste[6] PROGMEM = {str1,str2,str3,str4,str5,str6};

// All objects that are used later again, will be global
GUI_OBJECT LIST_LOKOMOTIVES;            // For selecting a loko
GUI_OBJECT VMIN_BAR;                    // Minimum V for loko
GUI_OBJECT VMAX_BAR;                    // Maximum V for loko
GUI_OBJECT V_BAR;                       // Real speed of loko
uint8_t VMIN=0;
uint8_t VMAX=0;
uint8_t V_REAL=0;

GUI_OBJECT LIST_SLAVE;                  // For select a slave
GUI_OBJECT LIST_SLAVE_TYPE_LABEL;       // for to show type of slave

GUI_OBJECT BUTTON_MSG;                  // Message button in the main menu

void GUI_MAIN_MENU_SHOW(void);
void DIALOG_SELECT_LOKO_SHOW(void);
void DIALOG_DRIVE_LOKOMOTIVE_SHOW(char *text);
void DIALOG_SELECT_SLAVE(void);
//void TEST_DIALOG_SHOW(void);
void callback_timer_check_message(void);


void callback_timer_counter(void)
{
  char buffer[20];
  static int t=0;
  GUI_TIMER_REMOVE( callback_timer_counter );
  if(t>1000)
  {
    MESSAGE_COUNTER++;
    t=0;
  }
  t++;
  GUI_TIMER_ADD( callback_timer_counter, SECONDS( 5 ) );
}

void INIT_ALL(void)
{
  // Set the fonts for the gui system
  GUI_SET_NORMAL_FONT(&Arial__8);
  GUI_SET_SMALL_FONT(&Verdana__6);
  GUI_SET_BIG_FONT(&Fully);
 
  // Init the low level graphic driver
  GLCD_INIT();
  GLCD_CLEAR();
 
  // Init the key and rotary switch system
  INIT_INPUTS();
  GUI_TIMER_INIT();
  // finaly enable interrupts
  sei();

  GUI_TIMER_ADD( callback_timer_check_message, SECONDS( 10 ) );
  GUI_TIMER_ADD( callback_timer_counter, SECONDS( 5 ) );
 
#ifdef DEBUG
  GUI_TIMER_ADD( callback_timer_show_ram, SECONDS( 5 ) );
#endif
}

/** *************************************************************
@brief  Callback of timer to check for new messages
*****************************************************************/

void callback_timer_check_message(void)
{
  GUI_TIMER_REMOVE( callback_timer_check_message );
  if(MESSAGE_COUNTER>0)
  {
    char buffer[20];
    sprintf(buffer,"%2d new messages",MESSAGE_COUNTER);
    GUI_OBJECT_SET_HELP(&BUTTON_MSG,buffer);
    GUI_OBJECT_SET_XBM(&BUTTON_MSG,button_new_msg_bits);
  }
  GUI_TIMER_ADD( callback_timer_check_message, SECONDS( 10 ) );
}

/** *************************************************************
@brief  Callback from Main menu to invoke test dialog
*****************************************************************/

/*
uint8_t callback_main_menu_test(void)
{
  TEST_DIALOG_SHOW();
  return 0;
}
*/

/** *************************************************************
@brief  Callback from Main menu to message system
*****************************************************************/

uint8_t callback_main_menu_msg(void)
{
//  DIALOG_MESSAGE();
  return 0;
}
/** *************************************************************
@brief  Callback from Main menu to drive a loko dialog
*****************************************************************/

uint8_t callback_main_menu_drive_lokomotive(void)
{
  DIALOG_SELECT_LOKO_SHOW();
  return 0;
}
/** *************************************************************
@brief  Callback from Main menu to setup a slave
*****************************************************************/

uint8_t callback_main_menu_setup_slave(void)
{
  DIALOG_SELECT_SLAVE();
  return 0;
}
/** *************************************************************
@brief  Callback from select loko dialog to invoke driving
*****************************************************************/

uint8_t callback_select_lokomotive_ok_button(void)
{
  char tempstring[20];
  int x=GUI_OBJECT_LIST_GET_INDEX(&LIST_LOKOMOTIVES);
 
  strcpy_P(tempstring, (PGM_P)pgm_read_word(&(liste[x])));
  DIALOG_DRIVE_LOKOMOTIVE_SHOW(tempstring);
  return 0;
}
/** *************************************************************
@brief  Callback from select loko dialog to get back to main menu
*****************************************************************/

uint8_t callback_select_lokomotive_cancel_button(void)
{
  GUI_MAIN_MENU_SHOW();
  return 0;
}

/** *************************************************************
@brief  Callback from min speed bar while driving a loko
*****************************************************************/

uint8_t callback_drive_lokomotive_vmin(void)
{
  VMIN=GUI_OBJECT_GET_VALUE(&VMIN_BAR);
#ifdef DEBUG
  char buffer[10];
  sprintf(buffer,"%3d",VMIN);
  GLCD_PRINT(100,GLCD_YMAX-(GLCD_GET_FONT_HEIGHT(NORMAL_FONT)*2),buffer,NORMAL_FONT,TRUE);
#endif
  return 0;
}
/** *************************************************************
@brief  Callback from max speed bar while driving a loko
*****************************************************************/

uint8_t callback_drive_lokomotive_vmax(void)
{
  VMAX=GUI_OBJECT_GET_VALUE(&VMAX_BAR);
#ifdef DEBUG
  char buffer[10];
  sprintf(buffer,"%3d",VMAX);
  GLCD_PRINT(100,GLCD_YMAX-(GLCD_GET_FONT_HEIGHT(NORMAL_FONT)*2),buffer,NORMAL_FONT,TRUE);
#endif
  return 0;
}
/** *************************************************************
@brief  Callback from actuall driving speed bar
*****************************************************************/

uint8_t callback_drive_lokomotive_v(void)
{
  V_REAL=GUI_OBJECT_GET_VALUE(&V_BAR);
#ifdef DEBUG
  char buffer[10];
  sprintf(buffer,"%3d",V_REAL);
  GLCD_PRINT(100,GLCD_YMAX-(GLCD_GET_FONT_HEIGHT(NORMAL_FONT)*2),buffer,NORMAL_FONT,TRUE);
#endif
  return 0;
}
/** *************************************************************
@brief  Callback driving a loko quit to main menu
*****************************************************************/

uint8_t callback_drive_lokomotive_cancel_button(void)
{
  GUI_MAIN_MENU_SHOW();
  return 0;
}


/** *************************************************************
@brief  Callback from select slave dialog
*****************************************************************/

uint8_t callback_select_slave_ok_button(void)
{
  uint8_t x=GUI_OBJECT_LIST_GET_INDEX(&LIST_SLAVE);
  char buffer[10];
  sprintf(buffer,"%3d",x);
  GUI_OBJECT_SET_LABEL(&LIST_SLAVE_TYPE_LABEL,buffer);
  GUI_OBJECT_REFRESH(&LIST_SLAVE_TYPE_LABEL);

  return 0;
}
/** *************************************************************
@brief  Callback from select slave dialog to get back to main menu
*****************************************************************/

uint8_t callback_select_slave_cancel_button(void)
{
  GUI_MAIN_MENU_SHOW();
  return 0;
}

/** *************************************************************
@brief  Callback from test dialog to get back to main menu
*****************************************************************/

uint8_t callback_cancel_button(void)
{
  GUI_MAIN_MENU_SHOW();
  return 0;
}


#include "data/gfx/button_loko.xbm"
//#include "data/gfx/button_test.xbm"
#include "data/gfx/button_setup_slave.xbm"

/** *************************************************************
@brief  Show the select slave dialog
*****************************************************************/

void DIALOG_SELECT_SLAVE(void)
{
  GUI_DIALOG dialog;
  GUI_OBJECT label;
  GUI_OBJECT label2;
  GUI_OBJECT ok_button;
  GUI_OBJECT cancel_button;
 
  // The dialog with out any kind of frame
  dialog=GUI_DIALOG_NEW();
    // All
    label=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_LABEL, 5, 5, 120, 14, "Select Slave");
    label2=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_LABEL, 50, 25, 75, 14, "Slave type");
    LIST_SLAVE_TYPE_LABEL=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_LABEL, 50, 40, 75, 14, "none");
    LIST_SLAVE=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_NLIST,5,25,40,40,"");
    ok_button=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_BUTTON,20,75,40,14,"OK");
    cancel_button=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_BUTTON,65,75,40,14,"Cancel");
   
    // Set the help texts
    GUI_OBJECT_SET_HELP_P(&ok_button,"Click to start");
    GUI_OBJECT_SET_HELP_P(&cancel_button,"Click to go back");
    GUI_OBJECT_SET_HELP_P(&LIST_SLAVE,"Select a slave");

    GUI_OBJECT_INSERT_NLIST(&LIST_SLAVE, 10, 120);
   
    GUI_OBJECT_SET_FRAME(&label,TRUE);
    GUI_OBJECT_SET_FRAME(&label2,TRUE);
    GUI_OBJECT_SET_FRAME(&LIST_SLAVE_TYPE_LABEL,TRUE);
   
    // All callbacks
    GUI_OBJECT_SET_CALLBACK(&ok_button,callback_select_slave_ok_button,GUI_CB_RETURN);
    GUI_OBJECT_SET_CALLBACK(&LIST_SLAVE,callback_select_slave_ok_button,GUI_CB_RETURN);
    GUI_OBJECT_SET_CALLBACK(&cancel_button,callback_select_slave_cancel_button,GUI_CB_RETURN);
   
    // Insert all objects into dialog
    GUI_DIALOG_INSERT_OBJECT(&dialog,&label);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&label2);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&LIST_SLAVE_TYPE_LABEL);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&LIST_SLAVE);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&ok_button);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&cancel_button);
   
    // Show the dialog
    GUI_DIALOG_DISPLAY(&dialog);
}

/** *************************************************************
@brief  Show the select loko dialog
*****************************************************************/

void DIALOG_SELECT_LOKO_SHOW(void)
{
  GUI_DIALOG dialog;
  GUI_OBJECT label;
  GUI_OBJECT ok_button;
  GUI_OBJECT cancel_button;
 
  // The dialog with out any kind of frame
  dialog=GUI_DIALOG_NEW();
    // All
    label=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_LABEL, 5, 5, 120, 14, "Select Lokomotive");
    LIST_LOKOMOTIVES=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_FLIST,5,25,120,40,"");
    ok_button=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_BUTTON,20,75,40,14,"OK");
    cancel_button=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_BUTTON,65,75,40,14,"Cancel");
   
    // Set the help texts
    GUI_OBJECT_SET_HELP_P(&ok_button,"Click to start");
    GUI_OBJECT_SET_HELP_P(&cancel_button,"Click to go back");
    GUI_OBJECT_SET_HELP_P(&LIST_LOKOMOTIVES,"Select the lokomotive");

    GUI_OBJECT_INSERT_LIST_P(&LIST_LOKOMOTIVES, liste, 6);
   
    GUI_OBJECT_SET_FRAME(&label,TRUE);
   
    // All callbacks
    GUI_OBJECT_SET_CALLBACK(&ok_button,callback_select_lokomotive_ok_button,GUI_CB_RETURN);
    GUI_OBJECT_SET_CALLBACK(&LIST_LOKOMOTIVES,callback_select_lokomotive_ok_button,GUI_CB_RETURN);
    GUI_OBJECT_SET_CALLBACK(&cancel_button,callback_select_lokomotive_cancel_button,GUI_CB_RETURN);
   
    // Insert all objects into dialog
    GUI_DIALOG_INSERT_OBJECT(&dialog,&label);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&LIST_LOKOMOTIVES);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&ok_button);
    GUI_DIALOG_INSERT_OBJECT(&dialog,&cancel_button);
   
    // Show the dialog
    GUI_DIALOG_DISPLAY(&dialog);
}

void DIALOG_DRIVE_LOKOMOTIVE_SHOW(char *text)
{
  GUI_DIALOG dialog_drive;
  GUI_OBJECT label;
  GUI_OBJECT label2;
  GUI_OBJECT button;
 
  dialog_drive=GUI_DIALOG_NEW();
    label=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_LABEL, 5, 5, 120, 14, text);
    VMIN_BAR=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_VBAR, 10, 20, 14, 80, "");
    VMAX_BAR=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_VBAR, 30, 20, 14, 80, "");
    V_BAR=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_VBAR, 50, 20, 14, 80, "");
    button=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_BUTTON, 75, 80, 30, 14, "QUIT");
    label2=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_LABEL, 5, 100, 120, 14, " MIN MAX  V");
    GUI_OBJECT_SET_FONT(&label2,SMALL_FONT);
   
    GUI_OBJECT_SET_FRAME(&label,TRUE);
    GUI_OBJECT_SET_CALLBACK(&VMIN_BAR,callback_drive_lokomotive_vmin,GUI_CB_ALLWAYS);
    GUI_OBJECT_SET_CALLBACK(&VMAX_BAR,callback_drive_lokomotive_vmax,GUI_CB_ALLWAYS);
    GUI_OBJECT_SET_CALLBACK(&V_BAR,callback_drive_lokomotive_v,GUI_CB_ALLWAYS);
    GUI_OBJECT_SET_CALLBACK(&button,callback_drive_lokomotive_cancel_button,GUI_CB_RETURN);
   
    GUI_OBJECT_SET_HELP_P(&button,"Click to exit");
   
    GUI_OBJECT_SET_VALUES(&VMIN_BAR, 0, 0, 127, 1);
    GUI_OBJECT_SET_VALUES(&VMAX_BAR, 0, 0, 127, 1);
    GUI_OBJECT_SET_VALUES(&V_BAR, 0, 0, 127, 1);
   
    GUI_OBJECT_SET_VALUE(&VMIN_BAR, VMIN);
    GUI_OBJECT_SET_VALUE(&VMAX_BAR, VMAX);
    GUI_OBJECT_SET_VALUE(&V_BAR, V_REAL);
   
    GUI_DIALOG_INSERT_OBJECT(&dialog_drive,&label);
    GUI_DIALOG_INSERT_OBJECT(&dialog_drive,&VMIN_BAR);
    GUI_DIALOG_INSERT_OBJECT(&dialog_drive,&VMAX_BAR);
    GUI_DIALOG_INSERT_OBJECT(&dialog_drive,&V_BAR);
    GUI_DIALOG_INSERT_OBJECT(&dialog_drive,&label2);
    GUI_DIALOG_INSERT_OBJECT(&dialog_drive,&button);

    // Show the dialog
    GUI_DIALOG_DISPLAY(&dialog_drive);
}

/** *************************************************************
@brief  Show the main menu
*****************************************************************/

void GUI_MAIN_MENU_SHOW(void)
{
 
  GUI_DIALOG MAIN_MENU;
  GUI_OBJECT BUTTON_SETUP_SLAVE;
  GUI_OBJECT BUTTON_LOKO;
//  GUI_OBJECT BUTTON_TEST;
 
  // The dialog with out any kind of frame
  MAIN_MENU=GUI_DIALOG_NEW();
    // All buttons
    BUTTON_MSG=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_XBM_BUTTON, 10, 10, 32, 32, "");
    BUTTON_SETUP_SLAVE=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_XBM_BUTTON, 45, 10, 32, 32, "");
    BUTTON_LOKO=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_XBM_BUTTON, 80, 10, 32, 32, "");
//    BUTTON_TEST=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_XBM_BUTTON, 10, 45, 32, 32, "");
   
    // Set the xbms
    GUI_OBJECT_SET_XBM(&BUTTON_MSG,button_no_msg_bits);
    GUI_OBJECT_SET_XBM(&BUTTON_SETUP_SLAVE,button_setup_slave_bits);
    GUI_OBJECT_SET_XBM(&BUTTON_LOKO,button_loko_bits);
//    GUI_OBJECT_SET_XBM(&BUTTON_TEST,button_test_bits);
   
    // Set the help texts
    GUI_OBJECT_SET_HELP_P(&BUTTON_MSG,"No new message");
    GUI_OBJECT_SET_HELP_P(&BUTTON_SETUP_SLAVE,"Setup Slave");
    GUI_OBJECT_SET_HELP_P(&BUTTON_LOKO,"Drive a lokomotive");
//    GUI_OBJECT_SET_HELP_P(&BUTTON_TEST,"Invoke test dialog");
   
    // Set another help text for message button, if message avaiable
    if(MESSAGE_COUNTER>0)
    {
      char buffer[20];
      sprintf(buffer,"%2d new messages",MESSAGE_COUNTER);
      GUI_OBJECT_SET_HELP(&BUTTON_MSG,buffer);
      GUI_OBJECT_SET_XBM(&BUTTON_MSG,button_new_msg_bits);
    }
   
    // All callbacks
    GUI_OBJECT_SET_CALLBACK(&BUTTON_MSG,callback_main_menu_msg,GUI_CB_RETURN);
    GUI_OBJECT_SET_CALLBACK(&BUTTON_SETUP_SLAVE,callback_main_menu_setup_slave,GUI_CB_RETURN);
    GUI_OBJECT_SET_CALLBACK(&BUTTON_LOKO,callback_main_menu_drive_lokomotive,GUI_CB_RETURN);
//    GUI_OBJECT_SET_CALLBACK(&BUTTON_TEST,callback_main_menu_test,GUI_CB_RETURN);
   
    // Insert all objects into dialog
    GUI_DIALOG_INSERT_OBJECT(&MAIN_MENU,&BUTTON_MSG);
    GUI_DIALOG_INSERT_OBJECT(&MAIN_MENU,&BUTTON_SETUP_SLAVE);
    GUI_DIALOG_INSERT_OBJECT(&MAIN_MENU,&BUTTON_LOKO);
//    GUI_DIALOG_INSERT_OBJECT(&MAIN_MENU,&BUTTON_TEST);
   
    // Show the dialog
    GUI_DIALOG_DISPLAY(&MAIN_MENU);
}
/*
void TEST_DIALOG_SHOW(void)
{
  GUI_DIALOG dialog;
  GUI_OBJECT test_list;
  GUI_OBJECT button;
 
  dialog=GUI_DIALOG_NEW();
  test_list=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_LIST, 5, 5, 110, 55, "");
  button=GUI_OBJECT_NEW(GUI_OBJECT_TYPE_BUTTON, 55, 90, 40, 14, "QUIT");
 
  // Prepare the ram list array
  sprintf(ram_list[0],"ram list 1");
  sprintf(ram_list[1],"Entry num 2");
  sprintf(ram_list[2],"The thirt");
  GUI_OBJECT_INSERT_LIST(&test_list ,3);
 
  GUI_OBJECT_SET_CALLBACK(&button,callback_cancel_button, GUI_CB_RETURN);
 
  GUI_OBJECT_SET_HELP_P(&test_list,"Select from list");
  GUI_OBJECT_SET_HELP_P(&button,"Click to close");

  GUI_DIALOG_INSERT_OBJECT(&dialog,&test_list);
  GUI_DIALOG_INSERT_OBJECT(&dialog,&button);
  GUI_DIALOG_DISPLAY(&dialog);
}
*/

int main(void)
{
  INIT_ALL();
 
  GUI_MAIN_MENU_SHOW();

  GUI_RUN();
 
  while(1)      // This will never been reached. All actions will handled in the callback functions
  {
   
  }
   
  return 0;
}