David Smart / RA8875_L

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Sun Aug 31 14:37:37 2014 +0000
Parent:
62:ba5d33438fda
Child:
67:9f834f0ff97d
Commit message:
Increase the SPI clock rate by splitting the write from the read to better match the RA8875 display capabilities.

Changed in this revision

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
--- a/RA8875.cpp	Sun Aug 17 15:38:51 2014 +0000
+++ b/RA8875.cpp	Sun Aug 31 14:37:37 2014 +0000
@@ -241,6 +241,7 @@
 {
     for (int i=0; i<METRICCOUNT; i++)
         metrics[i] = 0;
+    idlecounter = 0;
 }
 
 
@@ -252,13 +253,18 @@
         metrics[method] = elapsed;
 }
 
+void RA8875::CountIdleTime(uint32_t t)
+{
+    idlecounter += t;
+}
 
 void RA8875::ReportPerformance(Serial & pc)
 {
     pc.printf("\r\nPerformance Metrics\r\n");
     for (int i=0; i<METRICCOUNT; i++) {
         pc.printf("%10d uS %s\r\n", metrics[i], metricsName[i]);
-    }    
+    }
+    pc.printf("Idle Counter: %u\r\n", idlecounter);
 }
 #endif
 
@@ -355,12 +361,41 @@
     unsigned char data;
     
     select(true);
-    spiwrite(0xC0);
+    spiwrite(0xC0);         // These two bits are for the special "Status Read" [STSR]
     data = spiread();
     select(false);
     return data;
 }
 
+/// @todo add a timeout and return false, but how long
+/// to wait since some operations can be very long.
+bool RA8875::_WaitWhileBusy(uint8_t mask)
+{
+    int i = 20000/POLLWAITuSec; // 20 msec max
+
+    while (i-- && ReadStatus() & mask)
+        wait_us(POLLWAITuSec);
+    if (i)
+        return true;
+    else
+        return false;
+}
+
+/// @todo add a timeout and return false, but how long
+/// to wait since some operations can be very long.
+bool RA8875::_WaitWhileReg(uint8_t reg, uint8_t mask)
+{
+    int i = 20000/POLLWAITuSec; // 20 msec max
+
+    while (i-- && ReadCommand(reg) & mask)
+        wait_us(POLLWAITuSec);
+    if (i)
+        return true;
+    else
+        return false;
+}
+
+
 
 dim_t RA8875::fontwidth(void)
 {
@@ -599,8 +634,7 @@
             WriteCommand(0x02);                 // RA8875 Internal Fonts
             select(true);
             WriteData(c);
-            while (ReadStatus() & 0x80)
-                wait_us(POLLWAITuSec);          // Chk_Busy();
+            _WaitWhileBusy(0x80);
             select(false);
         }
     }
@@ -657,8 +691,7 @@
         while (*string != '\0') {
             WriteData(*string);
             ++string;
-            while (ReadStatus() & 0x80)
-                wait_us(POLLWAITuSec);            // Chk_Busy();
+            _WaitWhileBusy(0x80);
         }
         select(false);
         #endif
@@ -729,8 +762,7 @@
 {
     PERFORMANCE_RESET;
     WriteCommand(0x8E, (region == ACTIVEWINDOW) ? 0xC0 : 0x80);
-    while (ReadCommand(0x8E) & 0x80)
-        wait_us(POLLWAITuSec);
+    _WaitWhileReg(0x8E, 0x80);
     REGISTERPERFORMANCE(PRF_CLS);
     return noerror;
 }
@@ -854,8 +886,7 @@
         unsigned char drawCmd = 0x00;       // Line
         WriteCommand(0x90, drawCmd);
         WriteCommand(0x90, 0x80 + drawCmd); // Start drawing.
-        while (ReadCommand(0x90) & 0x80)    // await completion.
-            wait_us(POLLWAITuSec);
+        _WaitWhileReg(0x90, 0x80);
     }
     REGISTERPERFORMANCE(PRF_DRAWLINE);
     return noerror;
@@ -897,8 +928,7 @@
             drawCmd |= 0x20;
         WriteCommand(0x90, drawCmd);
         WriteCommand(0x90, 0x80 + drawCmd); // Start drawing.
-        while (ReadCommand(0x90) & 0x80)    // await completion.
-            wait_us(POLLWAITuSec);
+        _WaitWhileReg(0x90, 0x80);
     }
     REGISTERPERFORMANCE(PRF_DRAWRECTANGLE);
     return noerror;
@@ -950,9 +980,7 @@
             drawCmd |= 0x40;
         WriteCommand(0xA0, drawCmd);
         WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing.
-        while (ReadCommand(0xA0) & 0x80) {   // await completion.
-            wait_us(POLLWAITuSec);
-        }
+        _WaitWhileReg(0xA0, 0x80);
     }
     REGISTERPERFORMANCE(PRF_DRAWROUNDEDRECTANGLE);
     return ret;
@@ -1001,8 +1029,7 @@
             drawCmd |= 0x20;
         WriteCommand(0x90, drawCmd);
         WriteCommand(0x90, 0x80 + drawCmd); // Start drawing.
-        while (ReadCommand(0x90) & 0x80)    // await completion.
-            wait_us(POLLWAITuSec);
+        _WaitWhileReg(0x90, 0x80);
     }
     REGISTERPERFORMANCE(PRF_DRAWTRIANGLE);
     return ret;
@@ -1042,8 +1069,7 @@
             drawCmd |= 0x20;
         WriteCommand(0x90, drawCmd);
         WriteCommand(0x90, 0x40 + drawCmd); // Start drawing.
-        while (ReadCommand(0x90) & 0x40)    // await completion.
-            wait_us(POLLWAITuSec);
+        _WaitWhileReg(0x90, 0x40);
     }
     REGISTERPERFORMANCE(PRF_DRAWCIRCLE);
     return ret;
@@ -1083,8 +1109,7 @@
             drawCmd |= 0x40;
         WriteCommand(0xA0, drawCmd);
         WriteCommand(0xA0, 0x80 + drawCmd); // Start drawing.
-        while (ReadCommand(0xA0) & 0x80)    // await completion.
-            wait_us(POLLWAITuSec);
+        _WaitWhileReg(0xA0, 0x80);
     }
     REGISTERPERFORMANCE(PRF_DRAWELLIPSE);
     return ret;
@@ -1093,6 +1118,8 @@
 
 RetCode_t RA8875::frequency(unsigned long Hz)
 {
+    spiwritefreq = Hz;
+    spireadfreq = Hz/2;
     spi.frequency(Hz);
     //       __   ___
     // Clock   ___A     Rising edge latched
@@ -1265,7 +1292,9 @@
     unsigned char retval;
     unsigned char data = 0;
     
+    spi.frequency(spireadfreq);
     retval = spi.write(data);
+    spi.frequency(spiwritefreq);
     return retval;
 }
 
@@ -1280,7 +1309,7 @@
 RetCode_t RA8875::init(int width, int height, int color_bpp)
 {
     Backlight_u8(0);
-    WriteCommand(0x88, 0x0a);                   // PLLC1 - Phase Lock Loop registers
+    WriteCommand(0x88, 0x0B);                   // PLLC1 - Phase Lock Loop registers
     wait_ms(1);
     WriteCommand(0x89, 0x02);
     wait_ms(1);
--- a/RA8875.h	Sun Aug 17 15:38:51 2014 +0000
+++ b/RA8875.h	Sun Aug 31 14:37:37 2014 +0000
@@ -85,7 +85,6 @@
 ///
 /// @todo Add Scroll support for text.
 /// @todo Improve sync between internal and external font support - cursor, window, scroll.
-/// @todo Find out why it can't shift frequency after constructor runs.
 /// @todo Add Hardware reset signal.
 /// @todo Add Keypad Support.
 /// @todo Add high level objects - x-y graph, meter, others... but these will
@@ -1200,17 +1199,23 @@
 
     /// Set the SPI port frequency (in Hz).
     ///
-    /// @note attempts to call this API at runtime, with the display
-    ///         already online, cause the system to lockup. 
-    ///         Investigation continues.
+    /// This uses the mbed SPI driver, and is therefore dependent on
+    /// its capabilities. The RA8875 can accept writes via SPI faster
+    /// than a read can be performed. The frequency set by this API
+    /// is for the SPI writes. It will automatically reduce the SPI
+    /// clock rate when a read is performed, and restore it for the 
+    /// next write.
     ///
-    /// This uses the mbed SPI driver, and is therefore dependent on
-    /// its capabilities. Limited tests were performed for the display
-    /// in the range of 1,000,000 to 10,000,000 Hz. The display was
-    /// a bit erratic above 5,000,000 Hz, so this became the default,
-    /// even though it might have been the bench-level wiring that posed
-    /// the limit.
+    /// @note The primary effect of this is to recover more CPU cycles
+    ///     for your application code. Keep in mind that when more than
+    ///     one command is sent to the display controller, that it
+    ///     will wait for the controller to finish the prior command.
+    ///     In this case, the performance is limited by the RA8875.
     ///
+    /// @param Hz is the frequency in Hz, tested range includes the
+    ///     range from 1,000,000 (1MHz) to 10,000,000 (10 MHz). Values
+    ///     outside this range will be accepted, but operation may
+    ///     be unreliable.
     /// @returns success/failure code. @see RetCode_t.
     ///
     RetCode_t frequency(unsigned long Hz = RA8875_DEFAULT_SPI_FREQ);
@@ -1220,6 +1225,12 @@
     /// Clear the performance metrics to zero.
     void ClearPerformance();
     
+    /// Count idle time.
+    ///
+    /// @param t is the amount of idle time to accumulate.
+    ///
+    void CountIdleTime(uint32_t t);
+    
     /// Report the performance metrics for drawing functions using
     /// the available serial channel.
     ///
@@ -1337,6 +1348,23 @@
     ///
     RetCode_t select(bool chipsel);
 
+    /// Wait while the status register indicates the controller is busy.
+    ///
+    /// @param mask is the mask of bits to monitor.
+    /// @returns true if a normal exit.
+    /// @returns false if a timeout exit.
+    ///
+    bool _WaitWhileBusy(uint8_t mask);
+
+    /// Wait while the the register anded with the mask is true.
+    ///
+    /// @param reg is the register to monitor
+    /// @param mask is the bit mask to monitor
+    /// @returns true if it was a normal exit
+    /// @returns false if it was a timeout that caused the exit.
+    ///
+    bool _WaitWhileReg(uint8_t reg, uint8_t mask);
+
     /// The most primitive - to write a data value to the SPI interface.
     ///
     /// @param data is the value to write.
@@ -1356,6 +1384,8 @@
     unsigned char spiread();
     
     SPI spi;                        ///< spi port
+    unsigned long spiwritefreq;          ///< saved write freq
+    unsigned long spireadfreq;      ///< saved read freq
     DigitalOut cs;                  ///< chip select pin, assumed active low
     DigitalOut res;                 ///< reset pin, assumed active low
     const unsigned char * font;     ///< reference to an external font somewhere in memory
@@ -1378,6 +1408,7 @@
         METRICCOUNT
     } method_e;
     unsigned long metrics[METRICCOUNT];
+    unsigned long idlecounter;
     void RegisterPerformance(method_e method);
     Timer performance;
     #endif