Blinking cursor with GLCD(ks0108)? Suggestions?

Dear Community

I'm working on a little arduino-powered handheld mathtrainer for my kids which includes a big keypad (Keypad.h) and a graphic lcd (GLCD) with a ks0108-controller (ks0108.h).

Since the device will sometimes be waiting for user-input, I would really like the user to indicate that the device is expecting input, hence use something like the cursor blink/noBlink-functionality I know from the character-based LCDs.

Has anyone thought of a similar functionality or even already extended mems glcd-library in that direction? I would appreciate inputs on what the blinkingCursor-functionality would have to be like or inputs on how to implement this as an extension to the working library.

Thanks! Dani

Hi Dani, a blinking cursor would be cool but the ks0108 hardware does not have built in support for this so the blinking would need to be done by the Arduino.

If you only wanted the blinking to happen when the sketch was waiting for input, perhaps one approach would be to have your input function alternately draw and erase an underline character at the cursor position. '_' (ASCII 95) is the underline character.

If you post a code fragment showing how you get input, perhaps I can help you to add functionality to blink a cursor while this function is waiting.

I use something like the following to read in data from the Keypad (using methods from Keypad.h):

        char key;
        int answer;
        int cursor_position_of_answer;

        do { key = kpd.getKey();
          if (key >= 48 && key <= 58){GLCD.PutChar(key); answer = answer*10 + key-48;}
          if (key == '.'){ // Clear-Button pressed.
            answer = 0; 
            GLCD.CursorTo(cursor_position_of_answer,0); 
            GLCD.Puts("          "); // Clear already written Input, reset CursorPosition
            GLCD.CursorTo(cursor_position_of_answer,0);
          }  
        } while (key != '?'); // Beenden der Eingabemaske

Is there a way to determine the current CursorPosition or do I have to keep track of it myself?
Can I move the cursor relatively (back/forward) using control characters?

Thanks, Dani

Currently there is no library method to return the cursor position, although it adding a method to move the curser back by one or more characters is high up the list of things to add for the next release.

But for now, here is some untested code that hints at what you can do in your sketch to control the cursor with the current library.

char myGetKey(byte column, byte row, char cursorChar)
{
  char key;  
  boolean cursorOn;
  do
  { 
      key = kpd.getKey();
     GLCD.CursorTo(column, row);
     if( cursorOn)     
        GLCD.PutChar(' '); //erease cursor     
     else
        GLCD.PutChar(cursorChar); //show cursor
     cursorOn = !cursorOn; // toggle state   
     delay(200); // a crude delay       
  }
  while (key ==NO_KEY);
  
  GLCD.CursorTo(column, row);
  GLCD.PutChar(' '); //erease cursor
  return key;   
}

Call myGetkey where you currently have the call to kpd.getKey: myGetKey(cursor_position_of_answer,0, '-');

If this does what you want, then you may want to replace the delay with more sophisticated code that uses the millis timer to make it more responsive to keystrokes

Thanks for the idea with the encapsulation of the getKey-function. I especially like the functionality of being able to use any character as cursor.

I tried the following code using the millis()-timer and am very happy with the result. All that has to be done is keeping track of where the cursor is.

char getKey_and_blink(byte column, byte row, char cursorChar){ 
    char key;  
    int cursor_blinktime = 500; // Blinktime in ms
    static long cursor_memorytime;      // Keeps track of time of last cursor-change (millis())
    static boolean cursorOn = false;

    key = kpd.getKey();

    if (cursor_memorytime + cursor_blinktime < millis()){ // Change blinkstatus
      cursorOn = !cursorOn;
      cursor_memorytime = millis();
      GLCD.CursorTo(column, row);
      if (cursorOn){ GLCD.PutChar(cursorChar); }
      else         { GLCD.PutChar(' '); }
      GLCD.CursorTo(column, row);
    }
    if (key != NO_KEY){GLCD.CursorTo(column, row); GLCD.PutChar(' '); GLCD.CursorTo(column, row);} 
    // Clear the cursor when a key is pressed.
    return key;
} // End of getKey_and_blink();

Cheers, Dani

Maybe consider the following change in the code when calculating the intervaltime:

char getKey_and_blink(byte column, byte row, char cursorChar){
    char key;  
    int cursor_blinktime = 500; // Blinktime in ms
    static long cursor_memorytime;      // Keeps track of time of last cursor-change (millis())
    static boolean cursorOn = false;

    key = kpd.getKey();

    if (cursor_memorytime < millis()){ // Change blinkstatus
      cursorOn = !cursorOn;
      cursor_memorytime = millis() + cursor_blinktime;
      GLCD.CursorTo(column, row);
      if (cursorOn){ GLCD.PutChar(cursorChar); }
      else         { GLCD.PutChar(' '); }
      GLCD.CursorTo(column, row);
    }
    if (key != NO_KEY){GLCD.CursorTo(column, row); GLCD.PutChar(' '); GLCD.CursorTo(column, row);}
    // Clear the cursor when a key is pressed.
    return key;
} // End of getKey_and_blink();

That way, there is less calculating, since only numbers are compared at the if()-clause.

And if you wanted to enter several keys in a row (let’s say if you wanted to enter «1234») and wished that the cursor appears instantly at the new cursor position when a key has been pressed, you could reset the variables cursor_memorytime = 0; cursorOn = false; in the case of the key != NO_KEY.

Complete function now:

char getKey_and_blink(byte column, byte row, char cursorChar){
    char key;  
    int cursor_blinktime = 500; // Blinktime in ms
    static long cursor_memorytime;      // Keeps track of time of last cursor-change (millis())
    static boolean cursorOn = false;

    key = kpd.getKey();

    if (cursor_memorytime < millis()){ // Change blinkstatus
      cursorOn = !cursorOn;
      cursor_memorytime = millis() + cursor_blinktime;
      GLCD.CursorTo(column, row);
      if (cursorOn){ GLCD.PutChar(cursorChar); }
      else         { GLCD.PutChar(' '); }
      GLCD.CursorTo(column, row);
    }
    if (key != NO_KEY){GLCD.CursorTo(column, row); GLCD.PutChar(' '); GLCD.CursorTo(column, row); cursor_memorytime = 0; cursorOn = false}
    // Clear the cursor when a key is pressed.
    return key;
} // End of getKey_and_blink();