Spidey Wall is the name for a physical wall lit up by multiple addressable LED strips. This program is an LPC1768 web server to control the wall from a browser.

Dependencies:   EthernetInterfacePlusHostname RdWebServer mbed-rtos mbed

This project is part of a Light-Wall using addressable LED strips (WS2801). I have published a few posts on my blog about the construction of the wall and building a game to play on it (PacMan). I have also had a guest post from a friend who has set his children the task of producing some interesting animations. The original post is http://robdobson.com/2015/07/spidey-wall/ /media/uploads/Bobty/20130722_112945_img_9674_62895-1184x1579.jpg

So far, however, I hadn't fully connected the physical (and electronic) wall with the web-browser creations to drive it. This project is hopefully the final link. A fast and reliable web server using REST commands to drive the 1686 LEDs in the Spidey Wall from code running in a browser (say on an iPad while you are playing a game).

The approach taken here results in the ability to control the RGB values of all 1686 LEDs at a rate of 20 frames per second.

A blog post describing the whole thing is here:

http://robdobson.com/2015/08/a-reliable-mbed-webserver/

Files at this revision

API Documentation at this revision

Comitter:
Bobty
Date:
Mon Aug 31 15:21:47 2015 +0000
Parent:
3:e5ea80fae61d
Child:
5:910909f34907
Commit message:
Tidied up and removed unnecessary code

Changed in this revision

DrawingManager.cpp Show annotated file Show diff for this revision Revisions of this file
DrawingManager.h Show annotated file Show diff for this revision Revisions of this file
EthernetInterface.lib Show annotated file Show diff for this revision Revisions of this file
RdWebServer.lib Show annotated file Show diff for this revision Revisions of this file
cmdmsg.cpp Show diff for this revision Revisions of this file
cmdmsg.h Show diff for this revision Revisions of this file
ledstrip.cpp Show annotated file Show diff for this revision Revisions of this file
ledstrip.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/DrawingManager.cpp	Mon Aug 31 09:03:15 2015 +0000
+++ b/DrawingManager.cpp	Mon Aug 31 15:21:47 2015 +0000
@@ -1,5 +1,5 @@
 //
-// Drawing Manager for Pancake Drawbot
+// Drawing Manager for LightWall
 // Rob Dobson 2015
 //
 
@@ -12,7 +12,7 @@
     isBusy = false;
 }
 
-void DrawingManager::init(int numLeds, int splitPoint)
+void DrawingManager::Init(int numLeds, int splitPoint)
 {
     pLedStrip = new ledstrip(numLeds, splitPoint);
     Thread::wait(100);
@@ -21,18 +21,58 @@
     
 }
 
-char* DrawingManager::start(const unsigned char* cmdBuf, int cmdLen)
+void DrawingManager::Clear()
+{
+//    printf("CLEAR\r\n");
+    if (pLedStrip)
+        pLedStrip->Clear();
+}
+
+void DrawingManager::RawFill(char* args, unsigned char* payload, int payloadLen, int payloadOffset)
 {
-    if (!pLedStrip)
-        return "NOINIT";
-    if (isBusy)
-        return "BUSY";
-    isBusy = true;
-    char* respStr = cmdmsg::Interpret(cmdBuf, cmdLen, pLedStrip);
-    isBusy = false;
-    return respStr;
+//    printf("RAWFILL %s payloadLen %d, payloadOffset %d\r\n", args, payloadLen, payloadOffset);
+    int startLed = GetIntFromNameValPair(args, "start=", -1);
+    if (startLed != -1 && payloadLen > 0)
+    {
+        int numLeds = payloadLen / 3;
+        int fromLed = startLed + (payloadOffset / 3);
+//        printf("RAWFILL fromLed %d numLeds %d\r\n", fromLed, numLeds);
+        pLedStrip->RawFill(fromLed, numLeds, payload);
+    }
 }
 
-void DrawingManager::service()
+void DrawingManager::Fill(char* args)
 {
+//    printf("FILL %s\r\n", args);
+    int startLed = GetIntFromNameValPair(args, "start=", -1);
+    int numLeds = GetIntFromNameValPair(args, "len=", -1);
+    int r1 = GetIntFromNameValPair(args, "r1=", -1);
+    int g1 = GetIntFromNameValPair(args, "g1=", -1);
+    int b1 = GetIntFromNameValPair(args, "b1=", -1);
+    int r2 = GetIntFromNameValPair(args, "r2=", -1);
+    int g2 = GetIntFromNameValPair(args, "g2=", -1);
+    int b2 = GetIntFromNameValPair(args, "b2=", -1);
+    if (startLed != -1 && numLeds != -1 && r1 != -1 && g1 != -1 && b1 != -1)
+    {
+        if (r2 == -1 || g2 == -1 || b2 == -1)
+            pLedStrip->Fill(startLed, numLeds, r1, g1, b1);
+        else
+            pLedStrip->Fill(startLed, numLeds, r1, g1, b1, r2, g2, b2);
+    }
 }
+
+void DrawingManager::ShowLeds()
+{
+//    printf("SHOWLEDS\r\n");
+    if (pLedStrip)
+        pLedStrip->ShowLeds();
+}
+
+int DrawingManager::GetIntFromNameValPair(char* buf, char* name, int invalidVal)
+{
+    int val = invalidVal;
+    char* pFnd = strstr(buf, name);
+    if (pFnd)
+        val = atoi(pFnd + strlen(name));
+    return val;
+}
--- a/DrawingManager.h	Mon Aug 31 09:03:15 2015 +0000
+++ b/DrawingManager.h	Mon Aug 31 15:21:47 2015 +0000
@@ -1,21 +1,29 @@
 #ifndef DRAWING_MANAGER
 #define DRAWING_MANAGER
 
+//
+// Drawing Manager for LightWall
+// Rob Dobson 2015
+//
+
 #include "mbed.h"
 #include "ledstrip.h"
-#include "cmdmsg.h"
 
 class DrawingManager
 {
 public:
     DrawingManager();
-    void init(int numLeds, int splitPoint);
-    void service();
-    char* start(const unsigned char* cmdBuf, int cmdLen);
+    void Init(int numLeds, int splitPoint);
+    void Clear();
+    void RawFill(char* args, unsigned char* payload, int payloadLen, int payloadOffset);
+    void Fill(char* args);
+    void ShowLeds();
+    
 
 private:
     ledstrip* pLedStrip;
     bool isBusy;
+    int GetIntFromNameValPair(char* buf, char* name, int invalidVal);
 };
 
 #endif
--- a/EthernetInterface.lib	Mon Aug 31 09:03:15 2015 +0000
+++ b/EthernetInterface.lib	Mon Aug 31 15:21:47 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/EthernetInterface/#8e692841213c
+https://developer.mbed.org/users/Bobty/code/EthernetInterfacePlusHostname/#8e692841213c
--- a/RdWebServer.lib	Mon Aug 31 09:03:15 2015 +0000
+++ b/RdWebServer.lib	Mon Aug 31 15:21:47 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/Bobty/code/RdWebServer/#0fc3d7b5e596
+http://mbed.org/users/Bobty/code/RdWebServer/#27800de38eab
--- a/cmdmsg.cpp	Mon Aug 31 09:03:15 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,361 +0,0 @@
-#include "mbed.h"
-#include "cmdmsg.h"
-#include "ledstrip.h"
-//#define DETECT_LEDS
-#ifdef DETECT_LEDS
-#include "detectled.h"
-#endif
-//#define USE_SPIDEY_GEOM
-#ifdef USE_SPIDEY_GEOM
-#include "spideyGeometry.h"
-#endif
-/*
-
-Message format is:
-    <SEQ><CMD><CMD><CMD> ... <ZERO>
-    
-Where:
-    <SEQ> is a two byte sequence count
-    <CMD> is a series of bytes as follows:
-        <LEN><COD><PARAMS>
-        
-Where:
-    <LEN> is a two byte with value 1..65535 depicting msg len
-    <COD> is a one byte command code - see below
-    <PARAMS> are a series of bytes containing the parameters for the command
-    
-<COD> values:
-
-    NOTE MSB of COD is used to indicate that no response is required on success
-         i.e. if MSB of COD is 1 then no response is required on success
-         
-    (COD & 0x7f) ....
-    0x01:
-        Clear the entire strip
-        There are no parameters
-    0x02:
-        Fill a series of leds with RGB values
-        <PARAMS> := <START><NUM><RGB1><RGB2>
-        Where:
-            <START> is a two byte value (bigendian) for led to start series
-            <NUM> is a two byte (bigendian) number of leds to set
-            <RGB1> is the starting RGB value (24bits)
-            <RGB2> is the ending RGB value (24bits) - OPTIONAL
-        The RGB2 value is optional - the LEN value determines whether it is present or not
-        - if present the colour values are interpolated (HSV) between RGB1 and RGB2
-        - if not present all leds are set to colour RGB1
-    0x03:
-        Detect LED with opto-sensor (put opto-sensor on LED and run command)
-        Sensor must be attached to p20 - currently using BPX65 with 470K pullup
-        Returns string with LED number
-    0x04:
-        Set number of leds and split point
-        <PARAMS> := <NUMLEDS><SPLITPOINT>
-        Where:
-            <NUMLEDS> is a two byte (bigendian) value for number of leds in strip
-            <SPLITPOINT> is a two byte (bigendian) value for point at which DigitalOut(p10) is used instead of p12 for data
-                    (this is because the spidey wall is two parallel chains of LEDS)
-    0x05:
-        Raw RGB values for a series of leds
-        <PARAMS> := <START><NUM><RGB1><RGB2><RGB2>....<RGBn>
-        Where:
-            <START> is a two byte value (bigendian) for led to start series
-            <NUM> is a two byte (bigendian) number of leds to set
-            <RGB1> is the RGB value for 1st LED (24bits)
-            <RGB2> is the RGB value for 2nd LED (24bits)
-            <RGBn> is the RGB value for nth LED (24bits)
-    0x06:
-        Set colour for leds on a pad
-        <PARAMS> := <PAD><RGB1><RGB2>
-        Where:
-            <PAD> is the pad number (1 byte)
-            <RGB1> is the starting RGB value (24bits)
-            <RGB2> is the ending RGB value (24bits) - OPTIONAL
-        The RGB2 value is optional - the LEN value determines whether it is present or not
-        - if present the colour values are interpolated (HSV) between RGB1 and RGB2
-        - if not present all leds are set to colour RGB1
-    0x07:
-        Set node and link info
-        <PARAMS> := <NODE><NODEFLAGS><NODERGB><LINKIDX><LINKLEDSTART><LINKNUMLEDS><LINKRGB>
-        Where:
-            <NODE> is the node number (1 byte)
-            <NODEFLAGS> LSB is 0 if the RGB value for the node is not to be changed, or 1 otherwise (1 byte)
-            <NODERGB> is the RBG value for the leds in the node itself (3 bytes)
-            <LINKIDX> is the index of the link (edge) from this node to control (1 byte)
-            <LINKLEDSTART> is the LED along the link to start controlling (1 byte)
-            <LINKNUMLEDS> is the number of LEDs to control (1 byte)
-            <LINKRGB> is the colour to make the link LEDs (3 bytes)
-        
-    0x08:
-        Raw HSV values for a series of leds
-        <PARAMS> := <START><NUM><HSV1><HSV2><HSV3>....<HSVn>
-        Where:
-            <START> is a two byte value (bigendian) for led to start series
-            <NUM> is a two byte (bigendian) number of leds to set
-            <HSV1> is the RGB value for 1st LED (16bits) - first 8 bits = H, upper 4 (bigendian) = S / 16, lower 4 = V / 16
-            <HSV2> is the RGB value for 2nd LED
-            <HSVn> is the RGB value for nth LED
-            
-    0x09:
-        ShowLeds
-        Until this command is sent all other commands simply "paint" into the buffer and don't actually change the LEDs
-        There are no parameters
-
-*/
-
-#ifdef USE_SPIDEY_GEOM
-int cmdmsg::getLedNumFromSeq(const int* edgeLeds, int numLedsInSeq, int seqIdx)
-{
-    if (seqIdx >= numLedsInSeq)
-        return -1;
-    int curSeqPos = 0;
-    bool reverseSeq = false;
-    for (int i = 0; i < MAX_SPIDEY_LINK_ELS/2; i++)
-    {
-        int startLedIdx = edgeLeds[i * 2];
-        int endLedIdx = edgeLeds[i * 2 + 1];
-        int nLeds = endLedIdx - startLedIdx + 1;
-        if (startLedIdx > endLedIdx)
-        {
-            reverseSeq = true;
-            nLeds = startLedIdx - endLedIdx + 1;
-        }
-        if (seqIdx - curSeqPos < nLeds)
-        {
-            if (reverseSeq)
-                return startLedIdx - seqIdx;
-            return startLedIdx + seqIdx;
-        }
-        curSeqPos = nLeds;
-    }
-    return -1;
-}
-#endif
-
-char* cmdmsg::Interpret(const unsigned char* msg, int msgLen, ledstrip* pLedStrip)
-{
-    // Get message details
-    static char responseStr[50];
-    unsigned char* ledStrip = pLedStrip->GetBuffer();
-    int nBytesLeft = msgLen - 2;
-    int seqCount = (msg[0] * 256) + msg[1];
-    msg += 2;
-    while (nBytesLeft > 0)
-    {
-        // Length of chunk
-        int chunkLen = (msg[0] * 256) + msg[1];
-        if (chunkLen == 0)
-            break;
-        
-        // Params length
-        int paramsLen = chunkLen - 1;
-//        printf("Chunklen = %d, Paramslen = %d\r\n", chunkLen, paramsLen);
-        
-        // Command and whether response required on success
-        int cmdCode = msg[2];
-        if ((cmdCode & 0x80) == 0)
-            sprintf(responseStr, "%04x OK", seqCount);
-        else
-            strcpy(responseStr, "");
-        
-        // Move message pointer to assist in decoding the payload
-        msg += 3;
-        switch(cmdCode & 0x7f)
-        {
-            case 0x01: // Clear
-            {
-//                printf("Clear - nextbyte %d\r\n", msg[0]);
-                pLedStrip->Clear();
-                break;
-            }
-            case 0x02: // Fill
-            {
-//                printf("Fill\r\n");
-
-                int startLed = (msg[0] * 256) + msg[1];
-                int numLeds = (msg[2] * 256) + msg[3];
-//                printf("F Q%04x S%d N%d Pa%d Ln%d\r\n", seqCount, startLed, numLeds, paramsLen, msgLen);
-                if (paramsLen == 10)  // RGB2 is provided
-                {
-                    pLedStrip->Fill(startLed, numLeds, msg[4], msg[5], msg[6], msg[7], msg[8], msg[9]);
-                } else if (paramsLen == 7) // only RGB1 - so solid colour fill
-                {
-                    pLedStrip->Fill(startLed, numLeds, msg[4], msg[5], msg[6]);
-                }
-                break;
-            }
-            case 0x03: // Detect LED
-            {
-#ifdef DETECT_LEDS
-                detectled ledDetector(p20);
-                int selectedLed = ledDetector.DetectSelectedLed(pLedStrip);
-                sprintf(responseStr, "%02x OK LED %d", seqCount, selectedLed);
-#endif
-                break;
-            }
-            case 0x04: // Set numleds and splitpoint
-            {
-//                printf("Set numleds and splitpoint\r\n");
-
-                if (paramsLen == 4)
-                {
-                    int numLeds = (msg[0] * 256) + msg[1];
-                    int splitPoint = (msg[2] * 256) + msg[3];
-                    pLedStrip->Resize(numLeds, splitPoint);
-                }
-                sprintf(responseStr, "%04x OK Resized", seqCount);
-                break;
-            }
-            case 0x05: // Raw - set LEDs to RGB values from buffer
-            {
-                if (paramsLen > 4)
-                {
-                    int startLed = (msg[0] * 256) + msg[1];
-                    int numLeds = (msg[2] * 256) + msg[3];
-                    if (paramsLen >= numLeds * 3 + 4)
-                    {
-                        pLedStrip->RawFill(startLed, numLeds, msg+4);
-//                        printf("R Q%04x S%d N%d Pa%d Ln%d\r\n", seqCount, startLed, numLeds, paramsLen, mMsgLen);
-                    }
-                    else
-                    {
-                        sprintf(responseStr, "%04x RAW FILL - BufLengthMismatch %d", seqCount, paramsLen);
-                    }
-                }
-                else
-                {
-                    sprintf(responseStr, "%04x RAW FILL - ParamsLen Error %d", seqCount, paramsLen);            
-                }
-                break;
-            }
-            case 0x06: // Set pad leds to a colour
-            {
-#ifdef USE_SPIDEY_GEOM
-                printf("Pad\r\n");
-
-                if (paramsLen > 2)
-                {
-                    int padIdx = msg[0];
-                    if (padIdx < sizeof(_spideyPads)/sizeof(SpideyPadInfo))
-                    {
-                        int firstLed = _spideyPads[padIdx].padLeds[0];
-                        int numLeds = _spideyPads[padIdx].padLeds[1] - _spideyPads[padIdx].padLeds[0] + 1;
-                        if (paramsLen == 4) // Only 1 RGB value
-                            pLedStrip->Fill(firstLed, numLeds, msg[1], msg[2], msg[3]);
-                        else if (paramsLen == 7) // Two RGB values
-                            pLedStrip->Fill(firstLed, numLeds, msg[1], msg[2], msg[3], msg[4], msg[5], msg[6]);
-                    }
-                }
-#endif
-                break;
-            }
-            case 0x07: // Control node
-            {
-#ifdef USE_SPIDEY_GEOM
-                printf("Node\r\n");
-
-                if (paramsLen == 11)
-                {
-                    int nodeIdx = msg[0];
-                    if (nodeIdx < sizeof(_spideyNodes)/sizeof(SpideyNodeInfo))
-                    {
-                        const SpideyNodeInfo& sni = _spideyNodes[nodeIdx];
-                        
-                        // Handle the node leds
-                        printf("Node %d leds %d colour %d,%d,%d ... ", nodeIdx, sni.numNodeLeds, msg[2], msg[3], msg[4]);
-                        bool setNodeRGB = ((msg[1] & 0x01) != 0);
-                        if (setNodeRGB)
-                        {
-                            for (int i = 0; (i < sni.numNodeLeds) && (i < MAX_SPIDEY_NODE_LEDS); i++)
-                            {
-                                pLedStrip->Fill(sni.nodeLeds[i], 1, msg[2], msg[3], msg[4]);
-                                printf("Led %d", sni.nodeLeds[i]);
-                            }
-                        }
-                        printf("\r\n");
-                        
-                        // Handle the link leds
-                        int linkIdx = msg[5];
-                        int linkLedStart = msg[6];
-                        int linkNumLeds = msg[7];
-                        printf("Link %d st %d num %d colour %d,%d,%d ... ", linkIdx, linkLedStart, linkNumLeds, msg[8], msg[9], msg[10]);
-                        if ((linkIdx < sni.numLinks) && (linkIdx < MAX_SPIDEY_NODE_LINKS))
-                        {
-                            const SpideyLinkInfo* pSli = sni.nodeLinks[linkIdx];
-                            for (int i = 0; i < linkNumLeds; i++)
-                            {
-                                int ledIdx = linkLedStart + i;
-                                int ledNumA = getLedNumFromSeq(pSli->edgeLedsA, pSli->edgeLengthA, ledIdx);
-                                if (ledNumA >= 0)
-                                {
-                                    pLedStrip->Fill(ledNumA, 1, msg[8], msg[9], msg[10]);
-                                    printf("A=%d/", ledNumA);
-                                }
-                                int ledNumB = getLedNumFromSeq(pSli->edgeLedsB, pSli->edgeLengthB, ledIdx);
-                                if (ledNumB >= 0)
-                                {
-                                    pLedStrip->Fill(ledNumB, 1, msg[8], msg[9], msg[10]);
-                                    printf("B=%d, ", ledNumB);
-                                }
-                            }
-                        }
-                        else
-                        {
-                            sprintf(responseStr, "%04x NODE - linkInvalid %d", seqCount, linkIdx);                    
-                        }
-                        printf("\r\n");
-                    }
-                    else
-                    {
-                        sprintf(responseStr, "%04x NODE - nodeInvalid %d", seqCount, nodeIdx);                    
-                    }
-                }
-                else
-                {
-                    sprintf(responseStr, "%04x NODE - BufLengthMismatch %d", seqCount, paramsLen);                    
-                }
-#endif
-                break;
-            }
-            case 0x08: // Raw HSV 
-            {
-                if (paramsLen > 4)
-                {
-                    int startLed = (msg[0] * 256) + msg[1];
-                    int numLeds = (msg[2] * 256) + msg[3];
-                    if (paramsLen >= numLeds * 2 + 4)
-                    {
-                        pLedStrip->HsvFill(startLed, numLeds, msg+4);
-//                        printf("R Q%04x S%d N%d Pa%d\r\n", seqCount, startLed, numLeds, paramsLen);
-                    }
-                    else
-                    {
-                        sprintf(responseStr, "%04x HSV FILL - BufLengthMismatch %d", seqCount, paramsLen);
-                    }
-                }
-                else
-                {
-                    sprintf(responseStr, "%04x HSV FILL - ParamsLen Error %d", seqCount, paramsLen);            
-                }
-                break;
-            }
-            case 0x09: // ShowLeds
-            {
-//                printf("ShowLeds - nextbyte %d\r\n", msg[0]);
-                pLedStrip->ShowLeds();
-                break;
-            }
-            default:
-            {
-                sprintf(responseStr, "%04x CMD %02x UNKNOWN", seqCount, cmdCode);
-                break;
-            }
-        }
-        
-        // Move to next chunk
-        nBytesLeft = nBytesLeft - chunkLen - 2;
-        msg += paramsLen;
-//        printf("Bytesleft = %d, msg[0] = %d\r\n", nBytesLeft, msg[0]);
-   }
-   return responseStr;
-}
--- a/cmdmsg.h	Mon Aug 31 09:03:15 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-
-class ledstrip;
-
-class cmdmsg
-{
-    private:
-//        static char responseStr[50];
-//        unsigned char* mpMsgBuf;
-//        int mMaxMsgLen;
-//        int mMsgLen;
-        int getLedNumFromSeq(const int* edgeLeds, int numLedsInSeq, int seqIdx);
-        
-    public:
-        cmdmsg()
-        {
-//            mMsgLen = 0;
-//            mMaxMsgLen = 5200;
-//            mpMsgBuf = new unsigned char [mMaxMsgLen]();
-//            responseStr[0] = 0;
-        }
-        
-//        ~cmdmsg()
-//        {
-//            delete mpMsgBuf;
-//        }
-//        
-//        char* GetBuffer()
-//        {
-//            return (char*)mpMsgBuf;
-//        }
-//        int GetMaxMsgLen()
-//        {
-//            return mMaxMsgLen;
-//        }
-//        
-//        void SetMsgLen(int n)
-//        {
-//            mMsgLen = n;
-//        }
-//        char* Interpret(ledstrip* pLedStrip);
-//        
-        static char* Interpret(const unsigned char* msgBuf, int msgLen, ledstrip* pLedStrip);
-};
-
--- a/ledstrip.cpp	Mon Aug 31 09:03:15 2015 +0000
+++ b/ledstrip.cpp	Mon Aug 31 15:21:47 2015 +0000
@@ -1,3 +1,4 @@
+
 // LED Strip using WS2801 with two ISRs for two SPI connected 
 // LED strips running in parallel
 // Rob Dobson 2013-2014
--- a/ledstrip.h	Mon Aug 31 09:03:15 2015 +0000
+++ b/ledstrip.h	Mon Aug 31 15:21:47 2015 +0000
@@ -1,6 +1,10 @@
 #ifndef LEDSTRIP__H
 #define LEDSTRIP__H
 
+// LED Strip using WS2801 with two ISRs for two SPI connected 
+// LED strips running in parallel
+// Rob Dobson 2013-2014
+
 #include "mbed.h"
 
 class ledstrip
--- a/main.cpp	Mon Aug 31 09:03:15 2015 +0000
+++ b/main.cpp	Mon Aug 31 15:21:47 2015 +0000
@@ -1,7 +1,10 @@
 // 
 // LightWall WebServer
 // 
-// Rob Dobson 2015
+// Rob Dobson (C) 2015
+// 
+// See http://robdobson.com/2015/07/spidey-wall/ and http://robdobson.com/2015/08/a-reliable-mbed-webserver/
+//
 
 #include "mbed.h"
 #include "EthernetInterface.h"
@@ -27,180 +30,57 @@
 // Drawing Manager
 DrawingManager drawingManager;
 
-//int ledsCount = 904;
-//int ledSplitPoint = 448;
-//ledstrip* pLedStrip = NULL;
-//
-//char* indexHtmName = "index.htm";
-//
-//const int TICK_MS = 100;
-//LedCmdHandler* pLedCmdHandler = NULL;
-//int blinkCtr = 0;
-//
-//void ledTickfunc()
-//{
-//    if(webServer.isListening())
-//    {
-//        blinkCtr++;
-//        if (blinkCtr > 1)
-//        {
-//            led1 = !led1;
-//            blinkCtr = 0;
-//        }
-//    }
-//    else
-//    {
-//        led1 = false;
-//    }
-//    
-//    if (pLedCmdHandler != NULL)
-//        pLedCmdHandler->NextGen();
-//}
-//
-//void handleCmd_ledControl(char* cmdStr, char* argStr)
-//{
-//    printf("LEDS COMMAND %s %s\r\n", cmdStr, argStr);
-//    if (argStr == NULL)
-//        return;
-//    pLedCmdHandler->DoCommand(argStr);
-//    
-//    // Store last command
-//    LocalFileSystem local("local");
-//    FILE* fp = fopen("/local/lastcmd.inf", "w");
-//    if (fp != NULL)
-//    {
-//        fwrite(argStr, 1, strlen(argStr)+1, fp);
-//        fclose(fp);
-//    }    
-//}
-//
-//void reRunLastCommand()
-//{
-//    // Store last command
-//    LocalFileSystem local("local");
-//    FILE* fp = fopen("/local/lastcmd.inf", "r");
-//    if (fp != NULL)
-//    {
-//        char buf[501];
-//        buf[sizeof(buf)-1] = 0;
-//        int nread = fread(buf, 1, sizeof(buf), fp);
-//        fclose(fp);
-//        if (nread > 0 && nread <= sizeof(buf))
-//        {
-//            buf[nread] = 0;
-//            pLedCmdHandler->DoCommand(buf);
-//        }
-//    }    
-//}
-//
-//#include "colourconverters.h"
-//
-//void BodgeSmooth(ledstrip* pLedStrip)
-//{
-//    pLedStrip->Clear();
-//    pLedStrip->ShowLeds();
-//
-//
-//    RgbColor startRGB(50,0,0);
-//    HsvColor curHsv = RgbToHsv(startRGB);
-//    while(1)
-//    for (int k = 0; k < 1000; k++)
-//    for (int j = 0; j < 255; j++)
-//    {
-//        pLedStrip->Clear();
-//        RgbColor colrVal = HsvToRgb(curHsv);        
-//        pLedStrip->Fill(0,pLedStrip->GetNumLeds(),colrVal.r, colrVal.g, colrVal.b);
-//        pLedStrip->ShowLeds();
-//        wait_ms(250);
-//        curHsv.h++;
-//    }
-//}
-//
-//void setLightsConfig()
-//{
-//    printf("Rob LightWall - Configured for ");
-//    // Check for a config file on the local file system
-//    strcpy(nameOfLights, "Spidey");
-//    LocalFileSystem local("local");
-//    FILE* fp = fopen("/local/spidey.cnf", "r");
-//    if (fp != NULL)
-//    {
-//        char buf[201];
-//        buf[sizeof(buf)-1] = 0;
-//        int nread = fread(buf, 1, sizeof(buf), fp);
-//        if (nread > 0 && nread <= sizeof(buf))
-//        {
-//            buf[nread] = 0;
-//            sscanf(buf, "%s %d %d", nameOfLights, &ledsCount, &ledSplitPoint);
-//        }
-//        fclose(fp);
-//        printf("%s (%d LEDs, Split at %d)", nameOfLights, ledsCount, ledSplitPoint);
-//        printf("\n\r");
-//    }
-//    
-//    // Leds setup
-//    pLedStrip = new ledstrip(ledsCount, ledSplitPoint);
-//    wait_ms(100);
-//    pLedStrip->Clear();
-//    pLedStrip->ShowLeds();
-//
-//    // Cmd handler
-//    pLedCmdHandler = new LedCmdHandler(pLedStrip);
-//}
+// General response string for REST requests
+char* generalRespStr = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: POST, GET, OPTIONS\r\nAccess-Control-Allow-Headers:accept, content-type\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\n\r\n";
 
-//int main (void)
-//{
-//    pc.baud(115200);
-//    
-//    setLightsConfig();
-//    
-//    BodgeSmooth(pLedStrip);
-//    
-//    ledTick.attach(&ledTickfunc,TICK_MS / 1000.0);
-//
-////    reRunLastCommand();
-//    
-//    // setup ethernet interface
-//    eth.init(); //Use DHCP
-//    eth.connect();
-//    printf("IP Address is %s\n\r", eth.getIPAddress());
-//
-//    webServer.addCommand("", RdWebServerCmdDef::CMD_LOCALFILE, NULL, indexHtmName, true);
-//    webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &handleCmd_ledControl);
-//    webServer.init(PORT, &led2);
-//    webServer.run();
-//}
-
-// Handle a command
-char* lightwallCmd(int method, char* cmdStr, char* argStr, char* msgBuf)
-{
-    // Blink LED
-    led1 = !led1;
-    
-    // Get message payload
-    int cmdLen = RdWebServer::getPayloadLengthFromMsg(msgBuf);
-    unsigned char* cmdBuf = RdWebServer::getPayloadDataFromMsg(msgBuf);
-    
-    // Check if the command length is 0 - in this case respond ok as it might be a
-    // pre-flight check on a Cross Domain request - https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
-    char* respStr = "HTTP/1.1 200 OK\r\nConnection: keep-alive\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: POST, GET, OPTIONS\r\nAccess-Control-Allow-Headers:accept, content-type\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\n\r\n";
-    if (cmdLen != 0)
-    {
-        // Process command
-        drawingManager.start(cmdBuf, cmdLen);
-    }
-    return respStr;
-}
-
-// Get system name
-char* lightwallGetSystemName(int method, char* cmdStr, char* argStr, char* msgBuf)
+// Get system name - No arguments required
+char* lightwallGetSystemName(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
+                int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
 {
     // Return the system name
     return systemName;
 }
 
+// Clear LEDS - No arguments required
+char* lightwallClear(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
+                int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+    drawingManager.Clear();
+    return generalRespStr;
+}
+
+// RawFill - arguments for start LED (e.g. /rawfill?start=0)
+//         - payload of message contains binary data for RGB (1 byte for each) for each LED to be set
+char* lightwallRawFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
+                int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+    drawingManager.RawFill(argStr, pPayload, payloadLen, splitPayloadPos);
+    return generalRespStr;
+}
+
+// Fill - arguments for start, numLeds, initial-R/G/B and ending-R/G/B (optional)
+//      - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50
+//      - e.g. /fill?start=0&len=100&r1=20&g1=30&b1=50&r2=50&g2=100&b2=23
+char* lightwallFill(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
+                int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+    drawingManager.Fill(argStr);
+    return generalRespStr;
+}
+
+// ShowLeds - no arguments
+char* lightwallShowLeds(int method, char*cmdStr, char* argStr, char* msgBuffer, int msgLen, 
+                int contentLen, unsigned char* pPayload, int payloadLen, int splitPayloadPos)
+{
+    // Blink LED
+    led1 = !led1;
+    // Show LEDS
+    drawingManager.ShowLeds();
+    return generalRespStr;
+}
+
 // Create, configure and run the web server
-void http_thread(void const* arg)
+void http_server(void const* arg)
 {
     // Init the web server
     pc.printf("Starting web server\r\n");
@@ -212,8 +92,11 @@
     webServer.addCommand("favicon.ico", RdWebServerCmdDef::CMD_LOCALFILE, NULL, NULL, true);
     
     // Add the lightwall control commands
-    webServer.addCommand("cmd", RdWebServerCmdDef::CMD_CALLBACK, &lightwallCmd);
     webServer.addCommand("name", RdWebServerCmdDef::CMD_CALLBACK, &lightwallGetSystemName);
+    webServer.addCommand("clear", RdWebServerCmdDef::CMD_CALLBACK, &lightwallClear);
+    webServer.addCommand("rawfill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallRawFill);
+    webServer.addCommand("fill", RdWebServerCmdDef::CMD_CALLBACK, &lightwallFill);
+    webServer.addCommand("showleds", RdWebServerCmdDef::CMD_CALLBACK, &lightwallShowLeds);
     
     // Start the server
     webServer.init(WEBPORT, &led4, baseWebFolder);
@@ -253,7 +136,7 @@
     getSystemConfig();
 
     // Drawing manager controls the LEDs
-    drawingManager.init(systemNumLEDS, systemLEDSSplitPoint);
+    drawingManager.Init(systemNumLEDS, systemLEDSSplitPoint);
 
     // Setup ethernet interface
     char macAddr[6];
@@ -276,8 +159,8 @@
     // http://robdobson.com/2015/08/a-reliable-mbed-webserver/
     // Fortunately it doesn't matter as the LED code is all interrupt driven
     // This is the previous code...
-    // Thread httpServer(&http_thread, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
-    http_thread("");
+    // Thread httpServer(&http_server, NULL, osPriorityNormal, (DEFAULT_STACK_SIZE * 3));
+    http_server("");
       
     // Forever - actually it won't even get here as the server has a forever loop in it too
     while(true)