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:
Tue Aug 18 16:03:29 2015 +0000
Revision:
0:887096209439
Child:
1:362331cec9b7
Initial - unchanged since 2013

Who changed what in which revision?

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