Arnaud VALLEY / Mbed 2 deprecated Pinscape_Controller_V2_arnoz

Dependencies:   mbed FastIO FastPWM USBDevice

Revision:
39:b3815a1c3802
Parent:
38:091e511ce8a0
Child:
40:cc0d9814522b
--- a/USBJoystick/USBJoystick.h	Tue Jan 05 05:23:07 2016 +0000
+++ b/USBJoystick/USBJoystick.h	Mon Jan 11 21:08:36 2016 +0000
@@ -8,12 +8,20 @@
  
 #include "USBHID.h"
 
+// Bufferd incoming LedWiz message structure
 struct LedWizMsg
 {
     uint8_t data[8];
 };
 
-// circular buffer for incoming reports
+// Circular buffer for incoming reports.  We write reports in the IRQ
+// handler, and we read reports in the main loop in normal application
+// (non-IRQ) context.  
+// 
+// The design is organically safe for IRQ threading; there are no critical 
+// sections.  The IRQ context has exclusive access to the write pointer, 
+// and the application context has exclusive access to the read pointer, 
+// so there are no test-and-set or read-and-modify race conditions.
 template<class T, int cnt> class CircBuf
 {
 public:
@@ -23,11 +31,13 @@
     }
 
     // Read an item from the buffer.  Returns true if an item was available,
-    // false if the buffer was empty.
+    // false if the buffer was empty.  (Called in the main loop, in application
+    // context.)
     bool read(T &result) 
     {
         if (iRead != iWrite)
         {
+            //{uint8_t *d = buf[iRead].data; printf("circ read [%02x %02x %02x %02x %02x %02x %02x %02x]\r\n", d[0],d[1],d[2],d[3],d[4],d[5],d[6],d[7]);}
             memcpy(&result, &buf[iRead], sizeof(T));
             iRead = advance(iRead);
             return true;
@@ -36,12 +46,14 @@
             return false;
     }
     
+    // Write an item to the buffer.  (Called in the IRQ handler, in interrupt
+    // context.)
     bool write(const T &item)
     {
         int nxt = advance(iWrite);
         if (nxt != iRead)
         {
-            memcpy(&buf[nxt], &item, sizeof(T));
+            memcpy(&buf[iWrite], &item, sizeof(T));
             iWrite = nxt;
             return true;
         }
@@ -52,7 +64,8 @@
 private:
     int advance(int i)
     {
-        return i + 1 >= cnt ? 0 : i + 1;
+        ++i;
+        return i < cnt ? i : 0;
     } 
     
     int iRead;
@@ -60,6 +73,10 @@
     T buf[cnt];
 };
 
+// interface IDs
+const uint8_t IFC_ID_JS = 0;        // joystick + LedWiz interface
+const uint8_t IFC_ID_KB = 1;        // keyboard interface
+
 // keyboard interface report IDs 
 const uint8_t REPORT_ID_KB = 1;
 const uint8_t REPORT_ID_MEDIA = 2;
@@ -151,7 +168,6 @@
              _init();
              this->useKB = useKB;
              this->enableJoystick = enableJoystick;
-             reqTimer.start();
              connect(waitForConnect);
          };
 
@@ -161,6 +177,11 @@
              return lwbuf.read(msg);
          }
          
+         /* get the idle time settings, in milliseconds */
+         uint32_t getKbIdle() const { return kbIdleTime * 4UL; }
+         uint32_t getMediaIdle() const { return mediaIdleTime * 4UL; }
+         
+
          /**
           * Send a keyboard report.  The argument gives the key state, in the standard
           * 6KRO USB keyboard report format: byte 0 is the modifier key bit mask, byte 1
@@ -251,6 +272,35 @@
          virtual uint8_t *stringIserialDesc();
          virtual uint8_t *stringIproductDesc();
          
+         /* set/get idle time */
+         virtual void setIdleTime(int ifc, int rptid, int t)
+         {
+             // Remember the new value if operating on the keyboard.  Remember
+             // separate keyboard and media control idle times, in case the
+             // host wants separate report rates.
+             if (ifc == IFC_ID_KB)
+             {
+                if (rptid == REPORT_ID_KB)
+                    kbIdleTime = t;
+                else if (rptid == REPORT_ID_MEDIA)
+                    mediaIdleTime = t;
+            }
+         }
+         virtual uint8_t getIdleTime(int ifc, int rptid)
+         {
+             // Return the kb idle time if the kb interface is the one requested.
+             if (ifc == IFC_ID_KB)
+             {
+                 if (rptid == REPORT_ID_KB)
+                    return kbIdleTime;
+                 if (rptid == REPORT_ID_MEDIA)
+                    return mediaIdleTime;
+             }
+             
+             // we don't use idle times for other interfaces or report types
+             return 0;
+         }
+         
          /* callback overrides */
          virtual bool USBCallback_setConfiguration(uint8_t configuration);
          virtual bool USBCallback_setInterface(uint16_t interface, uint8_t alternate)
@@ -260,9 +310,14 @@
          virtual bool EP4_OUT_callback();
          
      private:
-         Timer reqTimer;
+
+         // Incoming LedWiz message buffer.  Each LedWiz message is exactly 8 bytes.
+         CircBuf<LedWizMsg, 64> lwbuf;
+         
          bool enableJoystick;
          bool useKB;
+         uint8_t kbIdleTime;
+         uint8_t mediaIdleTime;
          int16_t _x;                       
          int16_t _y;     
          int16_t _z;
@@ -270,9 +325,6 @@
          uint16_t _buttonsHi;
          uint16_t _status;
 
-         // Incoming LedWiz message buffer.  Each LedWiz message is exactly 8 bytes.
-         CircBuf<LedWizMsg, 64> lwbuf;
-         
          void _init();                 
 };