Due GUI (Graphical user interface) - [now community project]

I hope it comes over as very simple to follow…

This is the basic program, all this one does is create a single screen called main_menu, a panel displayed on all screens:

A full demo showing the objects in action is in the download.

//////////////////////////////////////////////////////////////////////////////////////////
//                          Due GUI Object demonstration sketch
//////////////////////////////////////////////////////////////////////////////////////////
//
//  (c) 2013 Darren Hill (Cowasaki)
//
//  Version 0.10
//
//  This program is not as yet complete.  There are a number of missing features and features not fully implemented.
//  There is also the possibility that anything implemented in this pre-release version may be implemented in a different
//  way in any subsequent version
//
//  Many thanks to those persons that created the original UTFT library - Henning 
//
// BASIC PROGRAM.



//////////////////////////////////////////////////////////////////////////////////////////
//                          Setup and initialise DUEGUI
//////////////////////////////////////////////////////////////////////////////////////////
//
#include <DUEGUI.h>
DUEGUI DueGUI(CTE70);   // which is: DUEGUI TFT1(CTE70,25,26,27,28); 

//////////////////////////////////////////////////////////////////////////////////////////
//                          Setup for the external RTC library
//////////////////////////////////////////////////////////////////////////////////////////
//
#include <rtc_clock.h>
RTC_clock rtc_clock(RC); 
char* daynames[]={"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
int hh,mm,ss,dow,dd,mon,yyyy;

//////////////////////////////////////////////////////////////////////////////////////////
//                          Setup variables for Due GUI
//////////////////////////////////////////////////////////////////////////////////////////
//

// variables for screens etc
int DueGUI_currentlyDisplayedScreen=0;
#define URNnull 0

// Every screen
int pnlTitle;

//
// Main menu screen
#define main_menu 1

/
//////////////////////////////////////////////////////////////////////////////////////////
//                          Due GUI Interupt routine and variables
//////////////////////////////////////////////////////////////////////////////////////////
//
// fast ticks for Due GUI interupt
volatile int l;
volatile int btnFound;
//
//  DueGUI Interupt handler routine
//
void DueGUI_tickHandler(){
  //
  // We don't want timer called whilst it's being handled.
  //
  DueGUI.stopTimer(DueGUI_timer);
  //
  // routine is called several times per second ie "ticksPerSecond".
  // l is incremented each time and by checking this against "ticksPerSecond"
  // we can make sure that once a second events are only called once per second.
  //
  l+=1;
  //
  // This is the "once per second" event routine.
  //
  if (l==ticksPerSecond){
    // second passed
    l=0;
    if (DueGUI.anyClockVisible) {
      rtc_clock.get_time(&hh,&mm,&ss);
      rtc_clock.get_date(&dow,&yyyy,&mon,&dd);
      //
      // Insert below the set and redraw clock functions:
      //
      //  Clocks that are only shown on some screens
      
      if (DueGUI_currentlyDisplayedScreen==main_menu){  
      }
    }
  }
  
  if ((DueGUI.dataAvailable()==true) || (DueGUI.anyButtonPressed==true)){
    btnFound=DueGUI.checkAllButtons();
    if (btnFound!=-1){
      DueGUI_OnButtonPress(btnFound);
    }
  }
  
  // Ok interupt handler is finished. 
  //
  TC_GetStatus(TC1, 0);
  DueGUI.restartTimer(DueGUI_timer);
}



//////////////////////////////////////////////////////////////////////////////////////////
//                          DueGUI On button press routine
//////////////////////////////////////////////////////////////////////////////////////////
//
void DueGUI_OnButtonPress(int btnFound){
//  Serial.print("Button found : ");
//  Serial.println(btnFound);
  //
  //  Find the URN of the button that was found.
  //
  int URN=DueGUI.GUIobject_UniqueReference[btnFound];


}

//////////////////////////////////////////////////////////////////////////////////////////
//                          DueGUI display a new screen
//////////////////////////////////////////////////////////////////////////////////////////
//
void DueGUI_createScreen(int screen){

  // First stop interupts whilst we build screen
  DueGUI.stopTimer(DueGUI_timer);

  // Set global variable to record which screen is in view
  DueGUI_currentlyDisplayedScreen=screen; 

  // Clear all the data and the screen
  DueGUI.clearAllObjects();
  DueGUI.clrScr();
  
  // Setup anything that is on EVERY screen
  // NOTE: pnlTitle's text is left blank as it is filled in by each screens functions.
  pnlTitle=     DueGUI.addPanel(0,0,799,50,clrBlue,clrWhite,clrWhite,2,"",280,8,BVS_34,optVisible,URNnull); 
  
  if (DueGUI_currentlyDisplayedScreen==main_menu){
    Serial.println("Setup: main_menu");
    DueGUI.GUIobject_top[pnlTitle]="Main  Menu";
  }


  // ok draw all the new objects that are supposed to be visible
  DueGUI.redrawAllObjects();
  // we can restart the interupts now
  DueGUI.restartTimer(DueGUI_timer);
};



//////////////////////////////////////////////////////////////////////////////////////////
//                          DueGUI demo setup() function
//////////////////////////////////////////////////////////////////////////////////////////
//
void setup(){ 
  //
  // Initialise serial on the programming port (this section is for debugging)....
  Serial.begin(115200); Serial.println("\n\nSERIAL CONNECTED AT 115200\n\n");

  //
  // Initialise for RTC
  rtc_clock.init(); rtc_clock.set_time(__TIME__); rtc_clock.set_date(__DATE__);
  
  //
  // Initialise DueGUI
  DueGUI.InitGUI(6,5,32,3,2,52,2,51);
  
  // Display "main_menu" screen
  DueGUI_createScreen(main_menu);
  
 }


//////////////////////////////////////////////////////////////////////////////////////////
//                          DueGUI demo loop() function
//////////////////////////////////////////////////////////////////////////////////////////
//
void loop(){
  // Do things here :-)
 
}

Here is an example of creating a screen:

This screen displays four cycle buttons and four check boxes plus a button to return to the main menu…

  if (DueGUI_currentlyDisplayedScreen==fan_screen){
    Serial.println("Setup: fan_screen");
    btnFBspeed0=DueGUI.addCycleButton(300,100,249,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Speed",20,posCentre,BVS_28,valFBspeed[0],0,9000,500,75,0,optVisible,URNnull); 
    btnFBspeed1=DueGUI.addCycleButton(300,175,249,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Speed",20,posCentre,BVS_28,valFBspeed[1],0,9000,500,75,0,optVisible,URNnull); 
    btnFBspeed2=DueGUI.addCycleButton(300,250,249,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Speed",20,posCentre,BVS_28,valFBspeed[2],0,9000,500,75,0,optVisible,URNnull); 
    btnFBspeed3=DueGUI.addCycleButton(300,325,249,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Speed",20,posCentre,BVS_28,valFBspeed[3],0,9000,500,75,0,optVisible,URNnull); 
    btnFBonoff0=DueGUI.addCheckBox(50,100,199,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Fan on",20,posCentre,BVS_28,valFBonoff[0],cycCHECKBOX,optVisible,URNnull); 
    btnFBonoff1=DueGUI.addCheckBox(50,175,199,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Fan on",20,posCentre,BVS_28,valFBonoff[1],cycCHECKBOX,optVisible,URNnull); 
    btnFBonoff2=DueGUI.addCheckBox(50,250,199,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Fan on",20,posCentre,BVS_28,valFBonoff[2],cycCHECKBOX,optVisible,URNnull); 
    btnFBonoff3=DueGUI.addCheckBox(50,325,199,50,clrBlue,clrWhite ,clrWhite,clrRed,clrWhite,2,"Fan on",20,posCentre,BVS_28,valFBonoff[3],cycCHECKBOX,optVisible,URNnull); 
    DueGUI.addButton(600,400,150,50,clrBlue,clrWhite,clrWhite,clrRed,clrWhite,2,"Main Menu",20,posCentre,BVS_28,optVisible,URNFBmainmenu); 
    // Change the text in the header panel
    DueGUI.GUIobject_top[pnlTitle]="Fan  Screen";
  }

it requires a small amount of setup in the variables section as well:

//
// Fan screen
//
// setup the fan screen's screen number definition:
#define fan_screen 2
//
//
// The following line could be byte types but they are basically variables to store the object's object number.  This is purely to make things easier, you don't actually have to remember the object's number in a variable you can get the object's number from the URN using the function "findObjectByURL(URNname);".
//
int btnFBonoff0,btnFBspeed0,btnFBonoff1,btnFBspeed1,btnFBonoff2,btnFBspeed2,btnFBonoff3,btnFBspeed3;
//
//
// Here we actually setup a URN for the main menu return button.  The number can be anything that fits in an integer but for ease I will be using numbers 100-199 for the main menu (screen 1), 200-299 for screen 2 etc etc
//
#define URNFBmainmenu 209
//
//
// Here we setup the arrays used to store the values of the objects starting with the defaults.
//
int valFBspeed[] = {4000,3000,500,0};
boolean valFBonoff[] = {true,false,false,true};

As the user clicks the main menu button you need to save the values of the inputs back to the arrays:

The following is added to the on button event function. You can see the URN is being checked and it is the URN defined above.

  if (URN==URNFBmainmenu){
    // Grab the data BEFORE you switch screens.
    //
    // Note the objects were created in order so we know that btnFBonoff1 is 1 more than btnFBonoff0 etc.  We can use this
    // to calculate object values in order to place in loops etc.
    //
    // store the values of the cycBoxes in variables ready to use again later
    for (int i = 0; i < 4; i++){
      valFBspeed[i]=DueGUI.returnIntValue(btnFBspeed0+i);
      valFBonoff[i]=DueGUI.returnBoolValue(btnFBonoff0+i);
    }
    printvariables();
    DueGUI_createScreen(main_menu);
  }

To do:

Hardware

SDcard integration
Hardware RTC integration

Objects (these are all to be added but just what I’ve thought of so far):

Progress bar (vertical and horizontal)
Rev counter (like a progress bar but looking like a car rev counter)
Cyclebutton using an array of Strings.
ButtonLED (like a check box but looks like an LED being switched on and off)
LED (like the above Button LED but just as an output)
StringBox (Box containing text)

Shapes

needs quite a few adding
plus transform function to rotate a shape

Functions

modify AddImage to work with data and SDcard files as well as files in the EEPROM.
finish CycleBox in order to use more options allowing the cycling text to be formatted to the user’s preference.

General

add more colours
make sure everything is in the keywords.txt file
finish manual
add more clock options
add more formatting options for objects
add calibrate function (allowing you to add a calibrate option to your program which will store the values on EEPROM/SDcard etc) this will take into account the accuracy and sweep range

Version 0.11 of library now available with addition of progress bar and a demonstration video (see post 1)

Video page is empty for me :/

jake1981: Video page is empty for me :/

It is uploaded there and is supposed to be public but I can't see it when I try to either (unless logged in as me).

I'm just uploading it to youtube as we speak so it should be there in half an hour or so......

Video now working on youtube

If you watch the video, one of the coordinates for the stylus appears on the main menu, a little bug in the demo program - easily sorted :D

Another issue that has been reported by one person taking a look was the keyboard accepting two button presses if held the stylus is not removed from the button quick enough. This is a fault I though of yesterday and will be fixed today with a setting changing the minimum amount of time between key presses to denounce it.

After that, a slider was mentioned by another user and that would be a useful addition as would support for a bluetooth keyboard and maybe eventually a keyboard/mouse combo.

A menu object is a obvious choice for a new addition too and this will be added.

A numeric/array input with + and - buttons was also mentioned and something I will look at BUT I have started to include a link on a button to allow it to automatically increment a value on another object which would allow you to easily accomplish this by the creation of 2 buttons and a panel - I will think about this one a little more.

I also want to make the calibration screen into a function that the user can just simply call and would finish with writing the calibration data to the EEPROM (subject to the screen or shield having one!) this would mean that you could simply add it as a menu option and your users could simply call it.

Anyway lots to do with it yet before it's finished

Bug latest: (not yet release though)

  • FIXED: Popup keyboard debounce added and working.
  • On occasion screen goes haywire when analogue clock drawn (sure this is due to trying to clear old hand pos when there isn't one so looking up a ridiculous value in the cosine/sine table - off to work now so will fix later!)
  • Spurious values from calibration screen sometimes appear on the main menu (again I can fix this in a few minutes but no time now).

Hopefully release bug fix later and then onto slider or calibration object.....

Bug latest:

  • FIXED: Popup keyboard debounce added and working.
  • FIXED: On occasion screen goes haywire when analogue clock drawn.
  • FIXED: Spurious values from calibration screen sometimes appear on the main menu.

Changes:

  • ADDITION: showCalibration() - This shows the calibration screen with no further code with a new "SAVE" button which will soon write the calibration data to a special data sector within the EEPROM of the screen.
  • CHANGE: Addition of two new functions HandleShowButtons(int URN) & HandleShowLoopStuff() - these functions pass control to the library during the loop function and button handler allowing the library to create it's own objects and handle them.
  • CHANGE: Removal of the calibration screen code from the demo program and switch to using the showCalibration() function which does the same thing.

version 0.12 uploaded.

Already some bits towards 1.13 but I'm going off on a tangent at the moment as I work out how to do SDcard image file to LCD, copy flash to SDcard and vice versa.......

Oh and if anyone is using the CTE shield with a Mac I've converted their Windows only image uploader to MacOS using wine :D

Version 1.13 news....

I will upload over the next few days but added:

GhostButton

Basically this is an area of the screen which acts as a button. This can be used for detecting if someone has touched part of the screen so you could draw a menu and store it as a graphic then update the whole screen with this graphic and then use this button to detect the user pressing parts of it.

ImageButton

This takes 1, 2 or 3 images.... image, pressed image and alternative image

If image only is used then it displays that image and if it is clicked it registers If pressed image is set then when the image is pressed it changes to the pressed image momentarily to signify being pressed If alternative image is set then the image changes between image and alternative image acting like a checkbox.

Version 1.13 further news....

Cycle button now has it's first option (bit 1)

if set then you can cycle in either direction by pressing first half of button or second half of button (by setting increment - or + you can alter whether 1st half is up/down with 2nd half always opposite).

AND now

(bit 2)

if set then it does the same for top/bottom half of button

Version 0.13 now uploaded with much better manual (still needs lots of work but the objects are all listed).

Addition of new objects:

The cycle button is supplemented with a cycleTEXTbutton which allows you to use an array of Strings as the list of options to select! You can also change the array once the object is drawn!

New ImageButton which allows lots of options of how it works: 1) Just as an image that can do something when clicked 2) As an image that changes momentarily when you click it and you can do something when clicked 3) As an image that changes momentarily then switches to an alternative image and vice versa allowing a boolean on/off which works automatically 4) As above without the momentary alternative image.

Now I've got the hang of recording the array's pointer so as to use the user's own array of strings I will be using this technique to produce a "menu" object, "list box" object and maybe a few more.

cowasaki:

Michael__MA: Hi and Many thanks for your extensive efforts -

is there any downloadable form or repository where i can download the files for testing and verifying - would be great as you really hit the spot by combining the essential libs to one Gui tooolbox i'm thinking about an Dali based lighting control with an Due and 5" touch display which i will put on the playgroud once i have everything put together - your toolbox would be very helpfull for this project.

Kind regards, Mike

I have got checkboxs and a variant of them called cycleboxs working. I am just working on an input box for text and will then release a downloadable version for testing whilst I finish the other planned bits.I have a demo running here that has three pages and allows people to switch between them and keep the variables consistent etc. The input box effectively scrolls up the part of the screen with the input and creates a keyboard across the bottom half of the screen so quite a bit of work... I will also be adding the option of PS2 and bluetooth keyboard support etc but that is for later.......

Now After returning from my trip i've downloaded and tested the UTFT lib with my CTE shield and 5"display - all demos were running without prob - then i dwonloaded and installed the DueGui 013 files and tested them -but did not succeed so far - assuming there is some missconfiguration from my side the question is, where do i have to change the physical wire definition for the display and the touch ..

on the UTFT 2.41 and CTE combination i had to change the following: 1.uncomment "#define CTE_DUE_SHIELD 1" in the HW_ARM_defines.h in the \hardware\arm folder of the UTFT library 2.Change the pinout to : UTFT myGLCD(CTE50,25,26,27,28); and UTouch myTouch(76,5,74,75,2);

to make the touch interface and display working - but where do i have to change this in the DueGUI - i didn't had the time to look throuch all the files to find it myself - so if someone has an idea, i'd really preciate some help.

kind regards, Mike

I’m not in front of my computer at the moment but in the demo there is a line which initialises everything, something like initGui or something like that. I’ll have a look tomorrow and give you a definite answer.

Ok…

Here we go…

at the start we have:

#include <DUEGUI.h>
DUEGUI DueGUI(CTE70); // which is: DUEGUI TFT1(CTE70,25,26,27,28);

Where we setup which screen and if necessary alternative pin outs…

Then inside the SETUP function we have:

DueGUI.InitGUI(6,5,32,3,2,52,2,51);

Where we setup the pin-outs for the touch, SDcard and eeprom

void InitGUI(byte tclk, byte tcs, byte tdin, byte dout, byte irq,int CS_pin, int Rate,int SD_pin);

Hi, I am trying to get this library to work with the Itead Studio ITDB02-5.0. Should I have to make a lot of changes or is there just some pin configs that I am getting wrong?

Hi All.

I just received my 5.00" CTE LCD and a CTE Due shield.. Loaded version 0.13 of the great Due GUI and ran the example demo 02...looks great..one problem was that there was no touch response....bummer...want I found was that touch was working but the Y axis was inverted!

Hmm.... checked the jumpers on the shield and they looked OK, at least from what I could find on the CTE website...so I poked around in the source for Due Gui and found there is a function for both X and y axis reversing....

I added this-- DueGUI.setReverseY(true) to setup:

 // Initialise DueGUI
  DueGUI.InitGUI(6,5,32,3,2,52,2,51);
  DueGUI.setReverseY(true);

Works now..

Can't wait until this is complete it is really very nicely done. I have written a fairly complicated (graphically) 4 screen GUI using the original work by Mr. Karlsen for the Uno32 by Chipkit...sorry Arduino , but I needed the speed for the screen redraws!..

Feature Request:

Add the ability to define line width in DrawLine.. I need fatter lines! It can be done by drawing offset multiple lines but, that's a pain....

thanks for all your hard work!

David Garrison Gaithersburg, MD USA