LPC800-MAX RGB demo using SCT and MRT

LPC800-MAX RGB demo using State-Configurable Timer(SCT) and Multi-Rate Timer(MRT).
http://www.youtube.com/watch?v=PABxoWZB0YM

Revision:
1:4e19f154ec21
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SCT_PWM.cpp	Mon Oct 14 03:59:30 2013 +0000
@@ -0,0 +1,99 @@
+#include "SCT_PWM.h"
+
+#define BIT_ON(A) (1<<A)
+
+// http://www.lpcware.com/content/nxpfile/lpc80-sct-cookbook-and-tutorial-code-examples
+
+SCT_PWM::SCT_PWM(int pin, int channel) : ch(channel)
+{
+    static bool insted = false;
+
+    if (!insted) {
+        inst();
+        insted = true;
+    }
+    swm(pin);
+
+    LPC_SCT->EVENT[ch + 1].STATE = LPC_SCT->EVENT[0].STATE;
+    LPC_SCT->EVENT[ch + 1].CTRL = LPC_SCT->EVENT[0].CTRL | (ch+1)<<0; // match 1...5
+
+    LPC_SCT->OUT[ch].SET = BIT_ON(0); // event 0
+    LPC_SCT->OUT[ch].CLR = BIT_ON(ch+1); // event 1...5
+}
+
+void SCT_PWM::inst()
+{
+    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<8); // enable SCT
+    LPC_SYSCON->PRESETCTRL |= (1<<8); // reset SCT
+
+    LPC_SCT->EVENT[0].STATE = BIT_ON(0); // state 0
+    LPC_SCT->EVENT[0].CTRL = (1<<12) | (1<<14);
+
+    LPC_SCT->LIMIT_L |= BIT_ON(0); // event 0
+
+    LPC_SCT->CONFIG |= (1<<0) | (1<<17); // unify, auto limit
+    LPC_SCT->CTRL_L |= (SystemCoreClock/1000000-1)<<5; // set prescaler, SCT clock = 1 MHz
+
+    LPC_SCT->CTRL_L &= ~(1<<2); // unhalt it by clearing bit 2 of CTRL reg
+}
+
+void SCT_PWM::swm(int pin)
+{
+    switch(ch) {
+        case 0: // CTOUT_0
+            LPC_SWM->PINASSIGN6 = (LPC_SWM->PINASSIGN6 & 0x00ffffff) | pin<<24;
+            break;
+        case 1: // CTOUT_1
+            LPC_SWM->PINASSIGN7 = (LPC_SWM->PINASSIGN7 & 0xffffff00) | pin<<0;
+            break;
+        case 2: // CTOUT_2
+            LPC_SWM->PINASSIGN7 = (LPC_SWM->PINASSIGN7 & 0xffff00ff) | pin<<8;
+            break;
+        case 3: // CTOUT_3
+            LPC_SWM->PINASSIGN7 = (LPC_SWM->PINASSIGN7 & 0xff00ffff) | pin<<16;
+            break;
+    }
+}
+
+void SCT_PWM::period(float seconds)
+{
+    period_us(seconds * 1000000);
+}
+
+void SCT_PWM::period_ms(int ms)
+{
+    period_us(ms * 1000);
+}
+
+void SCT_PWM::period_us(int us)
+{
+    LPC_SCT->MATCHREL[0].U = us - 1;
+}
+
+void SCT_PWM::pulsewidth(float seconds)
+{
+    pulsewidth_us(seconds * 1000000);
+}
+
+void SCT_PWM::pulsewidth_ms(int ms)
+{
+    pulsewidth_us(ms * 1000);
+}
+
+void SCT_PWM::pulsewidth_us(int us)
+{
+    LPC_SCT->MATCHREL[ch + 1].U = us;
+}
+
+void SCT_PWM::write(float value)
+{
+    LPC_SCT->MATCHREL[ch + 1].U = value * LPC_SCT->MATCHREL[0].U;
+}
+
+float SCT_PWM::read()
+{
+    if (LPC_SCT->MATCHREL[0].U == 0) {
+        return 0.0;
+    }
+    return (float)LPC_SCT->MATCHREL[ch + 1].U / LPC_SCT->MATCHREL[0].U;
+}