LCD LIB

Dependents:   HagridOS5

Fork of RA8875 by David Smart

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Mon Jul 25 10:55:58 2016 +0000
Parent:
122:79e431f98fa9
Child:
124:1690a7ae871c
Commit message:
Added idle callback - when the RA8875 driver is stuck waiting on the HW, or on a long timeout, it can call an optional callback. This could be used for maintaining the Watchdog, or other activities.

Changed in this revision

DisplayDefs.h Show annotated file Show diff for this revision Revisions of this file
RA8875.cpp Show annotated file Show diff for this revision Revisions of this file
RA8875.h Show annotated file Show diff for this revision Revisions of this file
RA8875_Touch.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/DisplayDefs.h	Tue May 17 22:33:06 2016 +0000
+++ b/DisplayDefs.h	Mon Jul 25 10:55:58 2016 +0000
@@ -3,7 +3,6 @@
 
 #define RGB(r,g,b) ( ((r<<8)&0xF800) | ((g<<3)&0x07E0) | (b>>3) )
 
-typedef uint16_t color_t;
 
 /// return values from functions. Use this number, or use the 
 /// lookup function to get a text string. @see GetErrorMessage.
--- a/RA8875.cpp	Tue May 17 22:33:06 2016 +0000
+++ b/RA8875.cpp	Mon Jul 25 10:55:58 2016 +0000
@@ -100,6 +100,7 @@
     c_callback = NULL;
     obj_callback = NULL;
     method_callback = NULL;
+    idle_callback = NULL;
 }
 
 //RA8875::~RA8875()
@@ -324,10 +325,15 @@
     static uint8_t count = 0;
     uint8_t col, row;
     uint8_t key;
-
+    
     while (!readable()) {
         wait_us(POLLWAITuSec);
         // COUNTIDLETIME(POLLWAITuSec);     // As it is voluntary to call the getc and pend. Don't tally it.
+        if (idle_callback) {
+            if (external_abort == (*idle_callback)(getc_wait)) {
+                return 0;
+            }
+        }
     }
     // read the key press number
     uint8_t keyNumReg = ReadCommand(0xC1) & 0x03;
@@ -544,6 +550,11 @@
     while (i-- && ReadStatus() & mask) {
         wait_us(POLLWAITuSec);
         COUNTIDLETIME(POLLWAITuSec);
+        if (idle_callback) {
+            if (external_abort == (*idle_callback)(status_wait)) {
+                return false;
+            }
+        }
     }
     if (i)
         return true;
@@ -561,6 +572,11 @@
     while (i-- && ReadCommand(reg) & mask) {
         wait_us(POLLWAITuSec);
         COUNTIDLETIME(POLLWAITuSec);
+        if (idle_callback) {
+            if (external_abort == (*idle_callback)(command_wait)) {
+                return false;
+            }
+        }
     }
     if (i)
         return true;
--- a/RA8875.h	Tue May 17 22:33:06 2016 +0000
+++ b/RA8875.h	Mon Jul 25 10:55:58 2016 +0000
@@ -272,9 +272,34 @@
     /// @param cmd is the command to execute. See @ref filecmd_t.
     /// @param buffer is a pointer to the buffer being passed.
     /// @param size is the number of bytes in the buffer.
+    /// @returns the noerror signal.
     ///
     typedef RetCode_t (* PrintCallback_T)(filecmd_t cmd, uint8_t * buffer, uint16_t size);
     
+    typedef enum {
+        unknown,            ///< reason has not been assigned (this should not happen)
+        status_wait,        ///< driver is polling the status register while busy
+        command_wait,       ///< driver is polling the command register while busy
+        getc_wait,          ///< user has called the getc function
+        touch_wait,         ///< user has called the touch function
+        touchcal_wait       ///< driver is performing a touch calibration
+    } IdleReason_T;
+    
+    /// Idle Callback 
+    ///
+    /// This defines the interface for an idle callback. That is, when the 
+    /// driver is held up, pending some event, it can call a registered
+    /// idle function. This could be most useful for servicing a watchdog.
+    ///
+    /// The user code, which is notified via this API, can force the idle
+    /// to abort, by returning the external_abort value back to the driver.
+    ///
+    /// @param info informs the callback why it is idle.
+    /// @returns noerror to allow the driver continue waiting.
+    /// @returns external_abort if the pending action should be aborted.
+    ///
+    typedef RetCode_t (* IdleCallback_T)(IdleReason_T info);
+
     /// Constructor for a display based on the RAiO RA8875 
     /// display controller.
     ///
@@ -518,6 +543,38 @@
     RetCode_t TouchPanelInit(uint8_t bTpEnable, uint8_t bTpAutoManual, uint8_t bTpDebounce, 
         uint8_t bTpManualMode, uint8_t bTpAdcClkDiv, uint8_t bTpAdcSampleTime);
     
+    
+    /// Get the screen calibrated point of touch.
+    ///
+    /// This method determines if there is a touch and if so it will provide
+    /// the screen-relative touch coordinates. This method can be used in
+    /// a manner similar to Serial.readable(), to determine if there was a 
+    /// touch and indicate that - but not care about the coordinates. Alternately,
+    /// if a valid pointer to a point_t is provided, then if a touch is detected
+    /// the point_t will be populated with data. 
+    ///
+    /// @code
+    ///     Timer t;
+    ///     t.start();
+    ///     do {
+    ///        point_t point = {0, 0};
+    ///        if (display.TouchPanelReadable(&point)) {
+    ///            display.pixel(point, Red);
+    ///        }
+    ///    } while (t.read_ms() < 30000);
+    /// @endcode
+    ///
+    /// @param[out] TouchPoint is a pointer to a point_t, which is set as the touch point, if a touch is registered.
+    /// @returns a value indicating the state of the touch,
+    ///         - no_cal:   no calibration matrix is available, touch coordinates are not returned.
+    ///         - no_touch: no touch is detected, touch coordinates are not returned.
+    ///         - touch:    touch is detected, touch coordinates are returned.
+    ///         - held:     held after touch, touch coordinates are returned.
+    ///         - release:  indicates a release, touch coordinates are returned.
+    ///
+    TouchCode_t TouchPanelReadable(point_t * TouchPoint = NULL);
+
+
     /// Poll the TouchPanel and on a touch event return the a to d filtered x, y coordinates.
     ///
     /// This method reads the touch controller, which has a 10-bit range for each the
@@ -563,37 +620,6 @@
     ///
     TouchCode_t TouchPanelA2DRaw(int *x, int *y);
     
-    /// Get the screen calibrated point of touch.
-    ///
-    /// This method determines if there is a touch and if so it will provide
-    /// the screen-relative touch coordinates. This method can be used in
-    /// a manner similar to Serial.readable(), to determine if there was a 
-    /// touch and indicate that - but not care about the coordinates. Alternately,
-    /// if a valid pointer to a point_t is provided, then if a touch is detected
-    /// the point_t will be populated with data. 
-    ///
-    /// @code
-    ///     Timer t;
-    ///     t.start();
-    ///     do {
-    ///        point_t point = {0, 0};
-    ///        if (display.TouchPanelReadable(&point)) {
-    ///            display.pixel(point, Red);
-    ///        }
-    ///    } while (t.read_ms() < 30000);
-    /// @endcode
-    ///
-    /// @param[in, out] TouchPoint is a pointer to a point_t, which is set as the touch point, if a touch is registered.
-    /// @returns a value indicating the state of the touch,
-    ///         - no_cal:   no calibration matrix is available, touch coordinates are not returned.
-    ///         - no_touch: no touch is detected, touch coordinates are not returned.
-    ///         - touch:    touch is detected, touch coordinates are returned.
-    ///         - held:     held after touch, touch coordinates are returned.
-    ///         - release:  indicates a release, touch coordinates are returned.
-    ///
-    TouchCode_t TouchPanelReadable(point_t * TouchPoint = NULL);
-
-
     /// Wait for a touch panel touch and return it.
     /// 
     /// This method is similar to Serial.getc() in that it will wait for a touch
@@ -2023,9 +2049,10 @@
     /// Then, the PrintScreen(x,y,w,h) method is called. Each chunk of data in the
     /// BMP file to be created is passed to this callback.
     /// 
-    /// @param callback is the callback function.
+    /// @param callback is the optional callback function. Without a callback function
+    ///     it will unregister the handler.
     ///
-    void AttachPrintHandler(PrintCallback_T callback) { c_callback = callback; }
+    void AttachPrintHandler(PrintCallback_T callback = NULL) { c_callback = callback; }
 
     /// PrintScreen callback registration.
     ///
@@ -2063,6 +2090,18 @@
     ///
     RetCode_t PrintScreen(uint16_t layer, loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP);
     
+    /// idle callback registration.
+    ///
+    /// This method attaches a simple c-compatible callback of type XXXXXXXXXXX.
+    /// Then, at any time when the display driver is waiting, it will call the
+    /// registered function. This is probably most useful if you want to service
+    /// a watchdog, when you may have called an API that will "hang" waiting
+    /// on the user.
+    ///
+    /// @param callback is the idle callback function. Without a callback function
+    ///     it will unregister the handler.
+    ///
+    void AttachIdleHandler(IdleCallback_T callback = NULL) { idle_callback = callback; }
 
 #ifdef PERF_METRICS
     /// Clear the performance metrics to zero.
@@ -2281,6 +2320,8 @@
     RetCode_t (* c_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size);
     FPointerDummy  *obj_callback;
     RetCode_t (FPointerDummy::*method_callback)(filecmd_t cmd, uint8_t * buffer, uint16_t size);
+    
+    RetCode_t (* idle_callback)(IdleReason_T reason);
 };
 
 
--- a/RA8875_Touch.cpp	Tue May 17 22:33:06 2016 +0000
+++ b/RA8875_Touch.cpp	Mon Jul 25 10:55:58 2016 +0000
@@ -6,8 +6,6 @@
 #define NOTOUCH_TIMEOUT_uS 100000
 #define TOUCH_TICKER_uS      1000
 
-// ### Touch Panel support code additions begin here
-
 RetCode_t RA8875::TouchPanelInit(void)
 {
     //TPCR0: Set enable bit, default sample time, wakeup, and ADC clock
@@ -67,13 +65,11 @@
     // |                                                    |
     // +----------------------------------------------------+
 
-
 RetCode_t RA8875::TouchPanelCalibrate(tpMatrix_t * matrix)
 {
     return TouchPanelCalibrate(NULL, matrix);
 }
 
-
 RetCode_t RA8875::TouchPanelCalibrate(const char * msg, tpMatrix_t * matrix, int maxwait_s)
 {
     point_t pTest[3];
@@ -82,8 +78,14 @@
     Timer timeout;  // timeout guards for not-installed, stuck, user not present...
     
     timeout.start();
-    while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s)
+    while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) {
         wait_ms(20);
+        if (idle_callback) {
+            if (external_abort == (*idle_callback)(touchcal_wait)) {
+                return external_abort;
+            }
+        }
+    }
     cls();
     if (msg)
         puts(msg);
@@ -97,17 +99,36 @@
         printf(" (%3d,%3d) => ", pTest[i].x, pTest[i].y);
         line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, White);
         line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, White);
-        while (!TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s)
+        while (!TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) {
             wait_ms(20);
+            if (idle_callback) {
+                if (external_abort == (*idle_callback)(touchcal_wait)) {
+                    return external_abort;
+                }
+            }
+        }
         pSample[i].x = x;
         pSample[i].y = y;
         line(pTest[i].x-10, pTest[i].y, pTest[i].x+10, pTest[i].y, Black);
         line(pTest[i].x, pTest[i].y-10, pTest[i].x, pTest[i].y+10, Black);
         foreground(Blue);
         printf(" (%4d,%4d)\r\n", x,y);
-        while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s)
+        while (TouchPanelA2DFiltered(&x, &y) && timeout.read() < maxwait_s) {
             wait_ms(20);
-        wait(2);
+            if (idle_callback) {
+                if (external_abort == (*idle_callback)(touchcal_wait)) {
+                    return external_abort;
+                }
+            }
+        }
+        for (int t=0; t<100; t++) {
+            wait_ms(20);
+            if (idle_callback) {
+                if (external_abort == (*idle_callback)(touchcal_wait)) {
+                    return external_abort;
+                }
+            }
+        }
     }
     if (timeout.read() >= maxwait_s)
         return touch_cal_timeout;
@@ -118,7 +139,7 @@
 
 /**********************************************************************
  *
- *     Function: getDisplayPoint()
+ *     Function: TouchPanelReadable()
  *
  *  Description: Given a valid set of calibration factors and a point
  *                value reported by the touch screen, this function
@@ -204,14 +225,24 @@
 
 TouchCode_t RA8875::TouchPanelGet(point_t * TouchPoint)
 {
-    TouchCode_t t;
+    TouchCode_t t = no_touch;
     
-    do {
+    while (true) {
         t = TouchPanelReadable(TouchPoint);
-    } while (t == no_touch);
+        if (t != no_touch)
+            break;
+        if (idle_callback) {
+            if (external_abort == (*idle_callback)(touch_wait)) {
+                return no_touch;
+            }
+        }
+    }
     return t;
 }
 
+// Below here are primarily "helper" functions. While many are accessible
+// to the user code, they usually don't need to be called.
+
 RetCode_t RA8875::TouchPanelSetMatrix(tpMatrix_t * matrixPtr)
 {
     if (matrixPtr == NULL || matrixPtr->Divider == 0)
@@ -221,7 +252,6 @@
     return noerror;
 }
 
-
 static void InsertionSort(int * buf, int bufsize)
 {
     int i, j;