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 Sep 03 20:17:23 2015 +0000
Revision:
6:8df79fe1afcd
Parent:
4:b521815f2657
Fixed an unforeseen problem with messages not aligned on RGB boundaries; Fixed potential hanging pointer problem in colourconverters; Changed Idle screen to a set of colourful snakes

Who changed what in which revision?

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