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/

Committer:
Bobty
Date:
Thu Aug 20 07:41:02 2015 +0000
Revision:
1:362331cec9b7
Parent:
0:887096209439
Child:
2:99eb4c6e9ea4
Implemented a command protocol using HTTP POST

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bobty 1:362331cec9b7 1 // LED Strip using WS2801 with two ISRs for two SPI connected
Bobty 1:362331cec9b7 2 // LED strips running in parallel
Bobty 1:362331cec9b7 3 // Rob Dobson 2013-2014
Bobty 1:362331cec9b7 4
Bobty 0:887096209439 5 #include "ledstrip.h"
Bobty 0:887096209439 6 #include "colourconverters.h"
Bobty 0:887096209439 7 #include "stddef.h"
Bobty 0:887096209439 8
Bobty 0:887096209439 9 #define SPIF 0 // SPI interrupt flag bit
Bobty 0:887096209439 10 #define SSP_IMSC_TX_RDY 3
Bobty 0:887096209439 11 #define SSP_IMSC_BITMASK 0x0f
Bobty 0:887096209439 12
Bobty 1:362331cec9b7 13 volatile int mCurPos0 = 0;
Bobty 1:362331cec9b7 14 int mEndPos0 = 0;
Bobty 1:362331cec9b7 15 volatile bool isr0Busy = false;
Bobty 1:362331cec9b7 16 unsigned char* pLedValues0 = NULL;
Bobty 0:887096209439 17
Bobty 0:887096209439 18 extern "C" void spi0_isr()
Bobty 0:887096209439 19 {
Bobty 0:887096209439 20 if (mCurPos0 < mEndPos0)
Bobty 0:887096209439 21 {
Bobty 1:362331cec9b7 22 LPC_SSP0->DR = pLedValues0[mCurPos0]; // write to FIFO data register
Bobty 0:887096209439 23 mCurPos0++;
Bobty 0:887096209439 24 }
Bobty 0:887096209439 25 else
Bobty 0:887096209439 26 {
Bobty 0:887096209439 27 // Turn off interrupts
Bobty 0:887096209439 28 LPC_SSP0->IMSC = 0;
Bobty 1:362331cec9b7 29 isr0Busy = false;
Bobty 0:887096209439 30 }
Bobty 0:887096209439 31 }
Bobty 0:887096209439 32
Bobty 1:362331cec9b7 33 volatile int mCurPos1 = 0;
Bobty 1:362331cec9b7 34 int mEndPos1 = 0;
Bobty 1:362331cec9b7 35 volatile bool isr1Busy = false;
Bobty 1:362331cec9b7 36 unsigned char* pLedValues1 = NULL;
Bobty 1:362331cec9b7 37
Bobty 0:887096209439 38 extern "C" void spi1_isr()
Bobty 0:887096209439 39 {
Bobty 0:887096209439 40 if (mCurPos1 < mEndPos1)
Bobty 0:887096209439 41 {
Bobty 1:362331cec9b7 42 LPC_SSP1->DR = pLedValues1[mCurPos1]; // write to FIFO data register
Bobty 0:887096209439 43 mCurPos1++;
Bobty 0:887096209439 44 }
Bobty 0:887096209439 45 else
Bobty 0:887096209439 46 {
Bobty 0:887096209439 47 // Turn off interrupts
Bobty 0:887096209439 48 LPC_SSP1->IMSC = 0;
Bobty 1:362331cec9b7 49 isr1Busy = false;
Bobty 0:887096209439 50 }
Bobty 0:887096209439 51 }
Bobty 0:887096209439 52
Bobty 0:887096209439 53 ledstrip::ledstrip(int length, int splitPoint)
Bobty 0:887096209439 54 {
Bobty 1:362331cec9b7 55 mpLedValuesA = NULL;
Bobty 1:362331cec9b7 56 mpLedValuesB = NULL;
Bobty 1:362331cec9b7 57 mpCurLedValues = NULL;
Bobty 0:887096209439 58
Bobty 0:887096209439 59 // SPI0 (using SSP 0 in 1768 chip)
Bobty 0:887096209439 60 mpSPI0 = new SPI(p11, NC, p13);
Bobty 0:887096209439 61 mpSPI0->format(8,0);
Bobty 0:887096209439 62 mpSPI0->frequency(500000);
Bobty 0:887096209439 63 LPC_SSP0->IMSC = 0; // initially no interrupts requested
Bobty 0:887096209439 64 NVIC_SetVector(SSP0_IRQn,( uint32_t ) spi0_isr);
Bobty 0:887096209439 65 NVIC_ClearPendingIRQ(SSP0_IRQn);
Bobty 0:887096209439 66 NVIC_SetPriority(SSP0_IRQn, 2);
Bobty 0:887096209439 67 NVIC_EnableIRQ(SSP0_IRQn);
Bobty 0:887096209439 68
Bobty 0:887096209439 69 // SPI1 (using SSP 1 in 1768 chip)
Bobty 0:887096209439 70 mpSPI1 = new SPI(p5, NC, p7);
Bobty 0:887096209439 71 mpSPI1->format(8,0);
Bobty 0:887096209439 72 mpSPI1->frequency(500000);
Bobty 0:887096209439 73 LPC_SSP1->IMSC = 0; // initially no interrupts requested
Bobty 0:887096209439 74 NVIC_SetVector(SSP1_IRQn,( uint32_t ) spi1_isr);
Bobty 0:887096209439 75 NVIC_ClearPendingIRQ(SSP1_IRQn);
Bobty 0:887096209439 76 NVIC_SetPriority(SSP1_IRQn, 2);
Bobty 0:887096209439 77 NVIC_EnableIRQ(SSP1_IRQn);
Bobty 1:362331cec9b7 78
Bobty 0:887096209439 79 // Resize the string length
Bobty 0:887096209439 80 Resize(length, splitPoint);
Bobty 0:887096209439 81 }
Bobty 0:887096209439 82
Bobty 0:887096209439 83 ledstrip::~ledstrip()
Bobty 0:887096209439 84 {
Bobty 0:887096209439 85 delete mpLedValuesA;
Bobty 0:887096209439 86 delete mpLedValuesB;
Bobty 0:887096209439 87 }
Bobty 0:887096209439 88
Bobty 0:887096209439 89 bool ledstrip::Resize(int length, int splitPoint)
Bobty 0:887096209439 90 {
Bobty 1:362331cec9b7 91 if (isr0Busy || isr1Busy)
Bobty 0:887096209439 92 return false;
Bobty 1:362331cec9b7 93 if (mpLedValuesA != NULL)
Bobty 0:887096209439 94 delete mpLedValuesA;
Bobty 1:362331cec9b7 95 if (mpLedValuesB != NULL)
Bobty 0:887096209439 96 delete mpLedValuesB;
Bobty 0:887096209439 97 mLedsBufSize = length*mColoursPerLed;
Bobty 0:887096209439 98 mpLedValuesA = new unsigned char[mLedsBufSize];
Bobty 0:887096209439 99 mpLedValuesB = new unsigned char[mLedsBufSize];
Bobty 0:887096209439 100 mpCurLedValues = mpLedValuesA;
Bobty 0:887096209439 101 mLedsInStrip = length;
Bobty 0:887096209439 102 mSplitPoint = splitPoint;
Bobty 0:887096209439 103 Clear();
Bobty 0:887096209439 104 return true;
Bobty 0:887096209439 105 }
Bobty 0:887096209439 106
Bobty 0:887096209439 107 void ledstrip::Clear()
Bobty 0:887096209439 108 {
Bobty 0:887096209439 109 /* Timer timr;
Bobty 0:887096209439 110 timr.start();
Bobty 0:887096209439 111 for (int i = 0; i < mLedsInStrip*mColoursPerLed; i++)
Bobty 0:887096209439 112 mpCurLedValues[i] = 0;
Bobty 0:887096209439 113 timr.stop();
Bobty 0:887096209439 114 printf("ClearTime loop %d\n", timr.read_us()); // Result is 863uS for 2500 x 3colour LEDS
Bobty 0:887096209439 115 timr.reset();
Bobty 0:887096209439 116 timr.start();
Bobty 0:887096209439 117 */
Bobty 0:887096209439 118 memset(mpCurLedValues, 0, mLedsBufSize);
Bobty 0:887096209439 119 /* timr.stop();
Bobty 0:887096209439 120 printf("ClearTime memset %d\n", timr.read_us()); // Result is 35uS for 2500 x 3 colour LEDS
Bobty 0:887096209439 121 */
Bobty 0:887096209439 122 }
Bobty 0:887096209439 123
Bobty 0:887096209439 124 unsigned char* ledstrip::GetBuffer()
Bobty 0:887096209439 125 {
Bobty 0:887096209439 126 return mpCurLedValues;
Bobty 0:887096209439 127 }
Bobty 0:887096209439 128
Bobty 0:887096209439 129 int ledstrip::GetBufferSizeinBytes()
Bobty 0:887096209439 130 {
Bobty 0:887096209439 131 return mLedsBufSize;
Bobty 0:887096209439 132 }
Bobty 0:887096209439 133
Bobty 0:887096209439 134 bool ledstrip::IsBusy()
Bobty 0:887096209439 135 {
Bobty 1:362331cec9b7 136 return isr0Busy || isr1Busy;
Bobty 0:887096209439 137 }
Bobty 0:887096209439 138
Bobty 1:362331cec9b7 139 void ledstrip::RawFill(int startLed, int numLeds, const unsigned char* pLedVals)
Bobty 1:362331cec9b7 140 {
Bobty 1:362331cec9b7 141 if ((startLed < 0) || (startLed >= mLedsInStrip))
Bobty 1:362331cec9b7 142 return;
Bobty 1:362331cec9b7 143 if (numLeds >= mLedsInStrip - startLed)
Bobty 1:362331cec9b7 144 numLeds = mLedsInStrip - startLed;
Bobty 1:362331cec9b7 145 int pos = startLed * mColoursPerLed;
Bobty 1:362331cec9b7 146 unsigned char* pBuf = GetBuffer() + pos;
Bobty 1:362331cec9b7 147 memcpy(pBuf, pLedVals, numLeds * mColoursPerLed);
Bobty 1:362331cec9b7 148 }
Bobty 1:362331cec9b7 149
Bobty 0:887096209439 150 // Fill - solid colour
Bobty 0:887096209439 151 void ledstrip::Fill(int startLed, int numLeds,
Bobty 0:887096209439 152 int r1, int g1, int b1)
Bobty 0:887096209439 153 {
Bobty 0:887096209439 154 /* Timer timr;
Bobty 0:887096209439 155 timr.start();
Bobty 0:887096209439 156 */
Bobty 0:887096209439 157 if ((startLed < 0) || (startLed >= mLedsInStrip))
Bobty 0:887096209439 158 return;
Bobty 0:887096209439 159 if (numLeds >= mLedsInStrip - startLed)
Bobty 0:887096209439 160 numLeds = mLedsInStrip - startLed;
Bobty 0:887096209439 161 int pos = startLed * mColoursPerLed;
Bobty 0:887096209439 162 unsigned char* pBuf = GetBuffer();
Bobty 0:887096209439 163 for (int i = 0; i < numLeds; i++)
Bobty 0:887096209439 164 {
Bobty 0:887096209439 165 pBuf[pos] = (unsigned char) r1;
Bobty 0:887096209439 166 pBuf[pos+1] = (unsigned char) g1;
Bobty 0:887096209439 167 pBuf[pos+2] = (unsigned char) b1;
Bobty 0:887096209439 168 pos += mColoursPerLed;
Bobty 0:887096209439 169 }
Bobty 0:887096209439 170 /* timr.stop();
Bobty 0:887096209439 171 printf("Fill solid %d\n", timr.read_us()); // Fill 50 LEDS solid colour = 11uS
Bobty 0:887096209439 172 */
Bobty 0:887096209439 173 }
Bobty 0:887096209439 174
Bobty 0:887096209439 175 // Fill - with interpolation of colours using HSV colour space
Bobty 0:887096209439 176 void ledstrip::Fill(int startLed, int numLeds,
Bobty 0:887096209439 177 int r1, int g1, int b1,
Bobty 0:887096209439 178 int r2, int g2, int b2)
Bobty 0:887096209439 179 {
Bobty 0:887096209439 180 /* Timer timr;
Bobty 0:887096209439 181 timr.start();
Bobty 0:887096209439 182 */
Bobty 0:887096209439 183 if ((startLed < 0) || (startLed >= mLedsInStrip))
Bobty 0:887096209439 184 return;
Bobty 0:887096209439 185 if (numLeds >= mLedsInStrip - startLed)
Bobty 0:887096209439 186 numLeds = mLedsInStrip - startLed;
Bobty 0:887096209439 187 int pos = startLed * mColoursPerLed;
Bobty 0:887096209439 188 RgbColor startRGB(r1,g1,b1);
Bobty 0:887096209439 189 HsvColor startHsv = RgbToHsv(startRGB);
Bobty 0:887096209439 190 RgbColor endRGB(r2,g2,b2);
Bobty 0:887096209439 191 HsvColor endHsv = RgbToHsv(endRGB);
Bobty 0:887096209439 192 int curH = startHsv.h << 16;
Bobty 0:887096209439 193 int curS = startHsv.s << 16;
Bobty 0:887096209439 194 int curV = startHsv.v << 16;
Bobty 0:887096209439 195 int interpSteps = numLeds - 1;
Bobty 0:887096209439 196 if (interpSteps < 1)
Bobty 0:887096209439 197 interpSteps = 1;
Bobty 0:887096209439 198 int incH = ((endHsv.h - startHsv.h) << 16) / interpSteps;
Bobty 0:887096209439 199 int incS = ((endHsv.s - startHsv.s) << 16) / interpSteps;
Bobty 0:887096209439 200 int incV = ((endHsv.v - startHsv.v) << 16) / interpSteps;
Bobty 0:887096209439 201 // Since H is a polar value we need to find out if it is best to go clockwise or anti-clockwise
Bobty 0:887096209439 202 if (endHsv.h > startHsv.h)
Bobty 0:887096209439 203 {
Bobty 0:887096209439 204 if (endHsv.h-startHsv.h > 128)
Bobty 0:887096209439 205 incH = ((startHsv.h-endHsv.h) << 16) / interpSteps;
Bobty 0:887096209439 206 }
Bobty 0:887096209439 207 else
Bobty 0:887096209439 208 {
Bobty 0:887096209439 209 // Go "round the top" using modulo result
Bobty 0:887096209439 210 if (startHsv.h-endHsv.h > 128)
Bobty 0:887096209439 211 incH = ((endHsv.h + 255 - startHsv.h) << 16) / interpSteps;
Bobty 0:887096209439 212 }
Bobty 0:887096209439 213
Bobty 0:887096209439 214 // printf("StartHSV %d %d %d EndHSV %d %d %d IncHSV %d %d %d\n", startHsv.h, startHsv.s, startHsv.v, endHsv.h, endHsv.s, endHsv.v, incH, incS, incV);
Bobty 0:887096209439 215 unsigned char* pBuf = GetBuffer();
Bobty 0:887096209439 216 for (int i = 0; i < numLeds; i++)
Bobty 0:887096209439 217 {
Bobty 0:887096209439 218 RgbColor colrVal = HsvToRgb(HsvColor((curH>>16)&0xff,curS>>16,curV>>16));
Bobty 0:887096209439 219 pBuf[pos] = colrVal.r;
Bobty 0:887096209439 220 pBuf[pos+1] = colrVal.g;
Bobty 0:887096209439 221 pBuf[pos+2] = colrVal.b;
Bobty 0:887096209439 222 // printf("HSV %d %d %d RGB %d %d %d\n", curH>>16, curS>>16, curV>>16, colrVal.r, colrVal.g, colrVal.b);
Bobty 0:887096209439 223 pos += mColoursPerLed;
Bobty 0:887096209439 224 curH = curH + incH;
Bobty 0:887096209439 225 curS = curS + incS;
Bobty 0:887096209439 226 curV = curV + incV;
Bobty 0:887096209439 227 }
Bobty 0:887096209439 228 /*
Bobty 0:887096209439 229 timr.stop();
Bobty 0:887096209439 230 printf("Fill gradient %d\n", timr.read_us()); // Fill gradient 50 LEDS = 64uS
Bobty 0:887096209439 231 */
Bobty 0:887096209439 232 }
Bobty 0:887096209439 233
Bobty 0:887096209439 234 void ledstrip::ShowLeds()
Bobty 0:887096209439 235 {
Bobty 0:887096209439 236 // Check if busy
Bobty 1:362331cec9b7 237 while (isr0Busy || isr1Busy)
Bobty 1:362331cec9b7 238 wait_us(2000);
Bobty 1:362331cec9b7 239 wait_us(2000);
Bobty 0:887096209439 240
Bobty 0:887096209439 241 // Set up start points
Bobty 0:887096209439 242 mCurPos0 = 0;
Bobty 0:887096209439 243 mEndPos0 = mSplitPoint*mColoursPerLed;
Bobty 0:887096209439 244 mCurPos1 = mSplitPoint*mColoursPerLed;
Bobty 0:887096209439 245 mEndPos1 = mLedsInStrip*mColoursPerLed;
Bobty 0:887096209439 246
Bobty 0:887096209439 247 // Set the buffer for the ISRs
Bobty 1:362331cec9b7 248 pLedValues0 = mpCurLedValues;
Bobty 1:362331cec9b7 249 pLedValues1 = mpCurLedValues;
Bobty 1:362331cec9b7 250
Bobty 0:887096209439 251 // Flip the current buffer to the alternate one for interleaved writing
Bobty 0:887096209439 252 if (mpCurLedValues == mpLedValuesA)
Bobty 1:362331cec9b7 253 {
Bobty 1:362331cec9b7 254 memcpy(mpLedValuesB, mpLedValuesA, mLedsBufSize);
Bobty 0:887096209439 255 mpCurLedValues = mpLedValuesB;
Bobty 1:362331cec9b7 256 }
Bobty 0:887096209439 257 else
Bobty 1:362331cec9b7 258 {
Bobty 1:362331cec9b7 259 memcpy(mpLedValuesA, mpLedValuesB, mLedsBufSize);
Bobty 0:887096209439 260 mpCurLedValues = mpLedValuesA;
Bobty 1:362331cec9b7 261 }
Bobty 0:887096209439 262
Bobty 0:887096209439 263 // Enable interrupts
Bobty 1:362331cec9b7 264 isr0Busy = true;
Bobty 1:362331cec9b7 265 if (mSplitPoint < mLedsInStrip)
Bobty 1:362331cec9b7 266 isr1Busy = true;
Bobty 0:887096209439 267
Bobty 0:887096209439 268 // Check if second strip is used
Bobty 1:362331cec9b7 269 LPC_SSP0->IMSC = (1 << SSP_IMSC_TX_RDY) & SSP_IMSC_BITMASK;
Bobty 0:887096209439 270 if (mSplitPoint < mLedsInStrip)
Bobty 0:887096209439 271 LPC_SSP1->IMSC = (1 << SSP_IMSC_TX_RDY) & SSP_IMSC_BITMASK;
Bobty 0:887096209439 272 }