Library to control a Graphics TFT connected to 4-wire SPI - revised for the Raio RA8875 Display Controller.

Dependents:   FRDM_RA8875_mPaint RA8875_Demo RA8875_KeyPadDemo SignalGenerator ... more

Fork of SPI_TFT by Peter Drescher

See Components - RA8875 Based Display

Enhanced touch-screen support - where it previous supported both the Resistive Touch and Capacitive Touch based on the FT5206 Touch Controller, now it also has support for the GSL1680 Touch Controller.

Offline Help Manual (Windows chm)

/media/uploads/WiredHome/ra8875.zip.bin (download, rename to .zip and unzip)

Revision:
75:ca78388cfd77
Parent:
74:686faa218914
Child:
77:9206c13aa527
--- a/RA8875.cpp	Sun Nov 09 20:38:49 2014 +0000
+++ b/RA8875.cpp	Fri Nov 28 22:37:53 2014 +0000
@@ -69,6 +69,15 @@
 // uSec should it wait between each polling activity.
 #define POLLWAITuSec 10
 
+// Private RawKeyMap for the Keyboard interface
+static const uint8_t KeyMap[22] = 
+    {
+     0, 
+     1,  2,  3,  4,  5,  6,  7,  8,  9, 10,
+    11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+    255
+    };
+
 
 RA8875::RA8875(PinName mosi, PinName miso, PinName sclk, PinName csel, PinName reset, const char *name)
     : GraphicsDisplay(name)
@@ -82,6 +91,7 @@
     Reset();
     Power(true);
     Backlight_u8(255);
+    pKeyMap = KeyMap;
 #ifdef PERF_METRICS
     performance.start();
     ClearPerformance();
@@ -265,49 +275,112 @@
 // #### end of touch panel code additions
 
 
-RetCode_t RA8875::KeypadInit(bool scanEnable, bool longDetect, uint8_t sampleTime, uint8_t scanFrequency,
-                             uint8_t longTimeAdjustment, bool interruptEnable, bool wakeupEnable)
+RetCode_t RA8875::KeypadInit(bool scanEnable, bool longDetect, uint8_t sampleTime, uint8_t scanFrequency, 
+    uint8_t longTimeAdjustment, bool interruptEnable, bool wakeupEnable)
 {
     uint8_t value = 0;
-
+    
     if (sampleTime > 3 || scanFrequency > 7 || longTimeAdjustment  > 3)
         return bad_parameter;
     value |= (scanEnable) ? 0x80 : 0x00;
     value |= (longDetect) ? 0x40 : 0x00;
     value |= (sampleTime & 0x03) << 4;
     value |= (scanFrequency & 0x07);
-    WriteCommand(0xC0, value);   // Enable Key Scan (and ignore possibility of an error)
-
+    WriteCommand(0xC0, value);   // KSCR1 - Enable Key Scan (and ignore possibility of an error)
+    
     value = 0;
     value |= (wakeupEnable) ? 0x80 : 0x00;
     value |= (longTimeAdjustment & 0x03) << 2;
-    WriteCommand(0xC1, value);  // (and ignore possibility of an error)
-
-    value = ReadCommand(0xF0);  // (and ignore possibility of an error)
+    WriteCommand(0xC1, value);  // KSCR2 - (and ignore possibility of an error)
+    
+    value = ReadCommand(0xF0);          // (and ignore possibility of an error)
     value &= ~0x10;
     value |= (interruptEnable) ? 0x10 : 0x00;
-    return WriteCommand(0xF0, value);
+    return WriteCommand(0xF0, value);   // INT
 }
 
-bool RA8875::_kbhit(void)
+RetCode_t RA8875::SetKeyMap(const uint8_t * CodeList)
+{
+    pKeyMap = CodeList;
+    return noerror;
+}
+
+bool RA8875::readable(void)
 {
     return (ReadCommand(0xF1) & 0x10);  // check KS status - true if kbhit
 }
 
-uint8_t RA8875::_getch(void)
+uint8_t RA8875::getc(void)
 {
-    while (!_kbhit()) {
+    //#define GETC_DEV
+    #ifdef GETC_DEV
+    uint8_t keyCode1, keyCode2;
+    #endif
+    uint8_t keyCode3;
+    static uint8_t count = 0;
+    uint8_t col, row;
+    uint8_t key;
+    
+    while (!readable()) {
         wait_us(POLLWAITuSec);
-        COUNTIDLETIME(POLLWAITuSec);
+        // COUNTIDLETIME(POLLWAITuSec);     // As it is voluntary to call the getc and pend. Don't tally it.
     }
-
     // read the key press number
     uint8_t keyNumReg = ReadCommand(0xC1) & 0x03;
-    // read the key code
-    uint8_t keyCode = ReadCommand(0xC2 + keyNumReg);
-    // Clear KS status
-    WriteCommand(0xF1, 0x10);
-    return keyCode;
+    count++;
+    switch (keyNumReg) {
+        case 0x01:      // one key
+            keyCode3 = ReadCommand(0xC2);
+            #ifdef GETC_DEV
+            keyCode2 = 0;
+            keyCode1 = 0;
+            #endif
+            break;
+        case 0x02:      // two keys
+            keyCode3 = ReadCommand(0xC3);
+            #ifdef GETC_DEV
+            keyCode2 = ReadCommand(0xC2);
+            keyCode1 = 0;
+            #endif
+            break;
+        case 0x03:      // three keys
+            keyCode3 = ReadCommand(0xC4);
+            #ifdef GETC_DEV
+            keyCode2 = ReadCommand(0xC3);
+            keyCode1 = ReadCommand(0xC2);
+            #endif
+            break;
+        default:         // no keys (key released)
+            keyCode3 = 0xFF;
+            #ifdef GETC_DEV
+            keyCode2 = 0;
+            keyCode1 = 0;
+            #endif
+            break;
+    }
+    if (keyCode3 == 0xFF)
+        key = pKeyMap[0];                    // Key value 0
+    else {
+        row = (keyCode3 >> 4) & 0x03;
+        col = (keyCode3 &  7);
+        key = row * 5 + col + 1;    // Keys value 1 - 20
+        if (key > 21) {
+            key = 21;
+        }
+        key = pKeyMap[key];
+        key |= (keyCode3 & 0x80);   // combine the key held flag
+    }
+    #if GETC_DEV // for Development only
+    SetTextCursor(0, 20);
+    printf("   Reg: %02x\r\n", keyNumReg);
+    printf("  key1: %02x\r\n", keyCode1);
+    printf("  key2: %02x\r\n", keyCode2);
+    printf("  key3: %02x\r\n", keyCode3);
+    printf(" count: %02X\r\n", count);
+    printf("   key: %02X\r\n", key);
+    #endif
+    WriteCommand(0xF1, 0x10);       // Clear KS status
+    return key;
 }
 
 #ifdef PERF_METRICS
@@ -315,7 +388,7 @@
 {
     for (int i=0; i<METRICCOUNT; i++)
         metrics[i] = 0;
-    idlecounter = 0;
+    idletime_usec = 0;
 }
 
 void RA8875::RegisterPerformance(method_e method)
@@ -328,7 +401,7 @@
 
 void RA8875::CountIdleTime(uint32_t t)
 {
-    idlecounter += t;
+    idletime_usec += t;
 }
 
 void RA8875::ReportPerformance(Serial & pc)
@@ -337,7 +410,7 @@
     for (int i=0; i<METRICCOUNT; i++) {
         pc.printf("%10d uS %s\r\n", metrics[i], metricsName[i]);
     }
-    pc.printf("%10d uS Idle time polling display for ready.\r\n", idlecounter);
+    pc.printf("%10d uS Idle time polling display for ready.\r\n", idletime_usec);
 }
 #endif
 
@@ -533,8 +606,8 @@
 
 RetCode_t RA8875::SetTextCursor(loc_t x, loc_t y)
 {
-    cursor_x = x;
-    cursor_y = y;     // for non-internal fonts
+    cursor_x = x;     // set these values for non-internal fonts
+    cursor_y = y;
     WriteCommandW(0x2A, x);
     WriteCommandW(0x2C, y);
     return noerror;
@@ -1625,9 +1698,9 @@
 //     /__/      /_____________/ /_____________/       /__/
 //
 //    Everything from here down is test code.
+//
 bool SuppressSlowStuff = false;
 
-
 void TextWrapTest(RA8875 & display, Serial & pc)
 {
     if (!SuppressSlowStuff)
@@ -1646,11 +1719,97 @@
         wait_ms(3000);
 }
 
+
+void ShowKey(RA8875 & display, int key)
+{
+    loc_t col, row;
+    dim_t r1 = 25;
+    color_t color = (key & 0x80) ? Red : Green;
+
+    key &= 0x7F;        // remove the long-press flag
+    row = (key - 1) / 5;
+    col = (key - 1) % 5;
+    if (col > 5) col = 5;
+    if (row > 4) row = 4;
+    display.circle(450 - + (2 * r1) * col, 200 - (2 * r1) * row, r1-2, color, FILL);
+}
+
+void HideKey(RA8875 & display, int key)
+{
+    loc_t col, row;
+    dim_t r1 = 25;
+
+    row = (key - 1) / 5;
+    col = (key - 1) % 5;
+    if (col > 5) col = 5;
+    if (row > 4) row = 4;
+    display.background(Black);
+    display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Black, FILL);
+    display.circle(450 - (2 * r1) * col, 200 - (2 * r1) * row, r1-2, Blue);
+}
+
+void KeyPadTest(RA8875 & display, Serial & pc)
+{
+    const uint8_t myMap[22] = {
+        0, 
+        'a', 'b', 'c', 'd', 'e',
+        'f', 'g', 'h', 'i', 'j',
+        'k', 'l', 'm', 'n', 'o',
+        'p', 'q', 'r', 's', 't',
+        'x'
+    };
+    
+    display.background(Black);
+    display.foreground(Blue);
+    display.cls();
+    display.Backlight_u8(255);
+    display.puts(0,0, "KeyPad Test. Touch the keypad...");
+    pc.printf("\r\n"
+              "Raw KeyPad Test. Keypad returns the key-number.\r\n"
+              "Press [most] any PC keyboard key to advance to next test.\r\n");
+    RetCode_t ret = display.KeypadInit(true, true, 3, 7, 3);
+    if (ret != noerror)
+        pc.printf("returncode from KeypadInit is %d\r\n", ret);
+    int lastKey = 0;
+    while (!pc.readable()) {
+        if (display.readable()) {
+            int key = display.getc();
+            if (key) {
+                if (((key & 0x7F) != lastKey) && (lastKey != 0))
+                    HideKey(display, lastKey);
+                ShowKey(display, key);
+                lastKey = key & 0x7F;
+            } else {
+                // erase the last one
+                if (lastKey)
+                    HideKey(display, lastKey);
+            }
+        }
+    }
+    (void)pc.getc();
+    pc.printf("\r\n"
+              "Map KeyPad Test. Keypad returns the remapped key 'a' - 't'.\r\n"
+              "Press [most] any PC keyboard key to advance to exit test.\r\n");
+    display.SetKeyMap(myMap);
+    while (!pc.readable()) {
+        if (display.readable()) {
+            int key = display.getc();
+            bool longPress = key & 0x80;
+            display.SetTextCursor(0, 120);
+            display.printf("Long Press: %d\r\n", longPress);
+            display.printf("  Remapped: %c %02X\r\n", (key) ? key & 0x7F : ' ', key);
+        }
+    }
+    (void)pc.getc();
+    display.SetKeyMap();
+    pc.printf("\r\n");
+}
+
 void TextCursorTest(RA8875 & display, Serial & pc)
 {
-    const char * iCursor = "The I-Beam cursor should be visible for this text.\r\n";
-    const char * uCursor = "The Underscore cursor should be visible for this text.\r\n";
-    const char * bCursor = "The Block cursor should be visible for this text.\r\n";
+    const char * iCursor  = "The I-Beam cursor should be visible for this text.\r\n";
+    const char * uCursor  = "The Underscore cursor should be visible for this text.\r\n";
+    const char * bCursor  = "The Block cursor should be visible for this text.\r\n";
     const char * bbCursor = "The Blinking Block cursor should be visible for this text.\r\n";
     const char * p;
     int delay = 100;
@@ -2198,6 +2357,7 @@
                   "T - Triangles         P - Pixels  \r\n"
                   "C - Circles           E - Ellipses\r\n"
                   "A - Auto Test mode    S - Speed Test\r\n"
+                  "K - Keypad Test\r\n"
                   "p - print screen      r - reset  \r\n"
                   "l - layer test        w - wrapping text \r\n"
 #ifdef PERF_METRICS
@@ -2233,6 +2393,9 @@
             case 'D':
                 DOSColorTest(lcd, pc);
                 break;
+            case 'K':
+                KeyPadTest(lcd, pc);
+                break;
             case 'W':
                 WebColorTest(lcd, pc);
                 break;
@@ -2283,6 +2446,8 @@
                 wait_ms(20);
                 mbed_reset();
                 break;
+            case ' ':
+                break;
             default:
                 printf("huh?\n");
                 break;