Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: EthernetInterfacePlusHostname RdWebServer mbed-rtos mbed
ledstrip.cpp
00001 00002 // LED Strip using WS2801 with two ISRs for two SPI connected 00003 // LED strips running in parallel 00004 // Rob Dobson 2013-2014 00005 00006 #include "ledstrip.h" 00007 #include "colourconverters.h" 00008 #include "stddef.h" 00009 00010 #define SPIF 0 // SPI interrupt flag bit 00011 #define SSP_IMSC_TX_RDY 3 00012 #define SSP_IMSC_BITMASK 0x0f 00013 00014 volatile int mCurPos0 = 0; 00015 int mEndPos0 = 0; 00016 volatile bool isr0Busy = false; 00017 unsigned char* pLedValues0 = NULL; 00018 00019 extern "C" void spi0_isr() 00020 { 00021 if (mCurPos0 < mEndPos0) 00022 { 00023 LPC_SSP0->DR = pLedValues0[mCurPos0]; // write to FIFO data register 00024 mCurPos0++; 00025 } 00026 else 00027 { 00028 // Turn off interrupts 00029 LPC_SSP0->IMSC = 0; 00030 isr0Busy = false; 00031 } 00032 } 00033 00034 volatile int mCurPos1 = 0; 00035 int mEndPos1 = 0; 00036 volatile bool isr1Busy = false; 00037 unsigned char* pLedValues1 = NULL; 00038 00039 extern "C" void spi1_isr() 00040 { 00041 if (mCurPos1 < mEndPos1) 00042 { 00043 LPC_SSP1->DR = pLedValues1[mCurPos1]; // write to FIFO data register 00044 mCurPos1++; 00045 } 00046 else 00047 { 00048 // Turn off interrupts 00049 LPC_SSP1->IMSC = 0; 00050 isr1Busy = false; 00051 } 00052 } 00053 00054 ledstrip::ledstrip(int length, int splitPoint) 00055 { 00056 mpLedValuesA = NULL; 00057 mpLedValuesB = NULL; 00058 mpCurLedValues = NULL; 00059 00060 // SPI0 (using SSP 0 in 1768 chip) 00061 mpSPI0 = new SPI(p11, NC, p13); 00062 mpSPI0->format(8,0); 00063 mpSPI0->frequency(500000); 00064 LPC_SSP0->IMSC = 0; // initially no interrupts requested 00065 NVIC_SetVector(SSP0_IRQn,( uint32_t ) spi0_isr); 00066 NVIC_ClearPendingIRQ(SSP0_IRQn); 00067 NVIC_SetPriority(SSP0_IRQn, 2); 00068 NVIC_EnableIRQ(SSP0_IRQn); 00069 00070 // SPI1 (using SSP 1 in 1768 chip) 00071 mpSPI1 = new SPI(p5, NC, p7); 00072 mpSPI1->format(8,0); 00073 mpSPI1->frequency(500000); 00074 LPC_SSP1->IMSC = 0; // initially no interrupts requested 00075 NVIC_SetVector(SSP1_IRQn,( uint32_t ) spi1_isr); 00076 NVIC_ClearPendingIRQ(SSP1_IRQn); 00077 NVIC_SetPriority(SSP1_IRQn, 2); 00078 NVIC_EnableIRQ(SSP1_IRQn); 00079 00080 // Resize the string length 00081 Resize(length, splitPoint); 00082 } 00083 00084 ledstrip::~ledstrip() 00085 { 00086 delete mpLedValuesA; 00087 delete mpLedValuesB; 00088 } 00089 00090 bool ledstrip::Resize(int length, int splitPoint) 00091 { 00092 if (isr0Busy || isr1Busy) 00093 return false; 00094 if (mpLedValuesA != NULL) 00095 delete mpLedValuesA; 00096 if (mpLedValuesB != NULL) 00097 delete mpLedValuesB; 00098 mLedsBufSize = length*mColoursPerLed; 00099 mpLedValuesA = new unsigned char[mLedsBufSize]; 00100 mpLedValuesB = new unsigned char[mLedsBufSize]; 00101 mpCurLedValues = mpLedValuesA; 00102 mLedsInStrip = length; 00103 mSplitPoint = splitPoint; 00104 Clear(); 00105 return true; 00106 } 00107 00108 void ledstrip::Clear() 00109 { 00110 /* Timer timr; 00111 timr.start(); 00112 for (int i = 0; i < mLedsInStrip*mColoursPerLed; i++) 00113 mpCurLedValues[i] = 0; 00114 timr.stop(); 00115 printf("ClearTime loop %d\n", timr.read_us()); // Result is 863uS for 2500 x 3colour LEDS 00116 timr.reset(); 00117 timr.start(); 00118 */ 00119 memset(mpCurLedValues, 0, mLedsBufSize); 00120 /* timr.stop(); 00121 printf("ClearTime memset %d\n", timr.read_us()); // Result is 35uS for 2500 x 3 colour LEDS 00122 */ 00123 } 00124 00125 unsigned char* ledstrip::GetBuffer() 00126 { 00127 return mpCurLedValues; 00128 } 00129 00130 int ledstrip::GetBufferSizeinBytes() 00131 { 00132 return mLedsBufSize; 00133 } 00134 00135 bool ledstrip::IsBusy() 00136 { 00137 return isr0Busy || isr1Busy; 00138 } 00139 00140 void ledstrip::RawFill(int startLed, int numLeds, const unsigned char* pLedVals) 00141 { 00142 if ((startLed < 0) || (startLed >= mLedsInStrip)) 00143 return; 00144 if (numLeds >= mLedsInStrip - startLed) 00145 numLeds = mLedsInStrip - startLed; 00146 int pos = startLed * mColoursPerLed; 00147 unsigned char* pBuf = GetBuffer() + pos; 00148 memcpy(pBuf, pLedVals, numLeds * mColoursPerLed); 00149 } 00150 00151 void ledstrip::HsvFill(int startLed, int numLeds, const unsigned char* pLedVals) 00152 { 00153 if ((startLed < 0) || (startLed >= mLedsInStrip)) 00154 return; 00155 if (numLeds >= mLedsInStrip - startLed) 00156 numLeds = mLedsInStrip - startLed; 00157 int pos = startLed * mColoursPerLed; 00158 unsigned char* pBuf = GetBuffer() + pos; 00159 00160 // Copy over the values converting each to RGB 00161 for (int i = 0; i < numLeds; i++) 00162 { 00163 RgbColor colrVal(0,0,0); 00164 HsvToRgb(HsvColor(pLedVals[0],pLedVals[1] & 0xf0, (pLedVals[1] << 4) & 0xf0), colrVal); 00165 pBuf[pos] = colrVal.r; 00166 pBuf[pos+1] = colrVal.g; 00167 pBuf[pos+2] = colrVal.b; 00168 // 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); 00169 pos += mColoursPerLed; 00170 pLedVals += 2; 00171 } 00172 } 00173 00174 // Fill - solid colour 00175 void ledstrip::Fill(int startLed, int numLeds, 00176 int r1, int g1, int b1) 00177 { 00178 /* Timer timr; 00179 timr.start(); 00180 */ 00181 if ((startLed < 0) || (startLed >= mLedsInStrip)) 00182 return; 00183 if (numLeds >= mLedsInStrip - startLed) 00184 numLeds = mLedsInStrip - startLed; 00185 int pos = startLed * mColoursPerLed; 00186 unsigned char* pBuf = GetBuffer(); 00187 for (int i = 0; i < numLeds; i++) 00188 { 00189 pBuf[pos] = (unsigned char) r1; 00190 pBuf[pos+1] = (unsigned char) g1; 00191 pBuf[pos+2] = (unsigned char) b1; 00192 pos += mColoursPerLed; 00193 } 00194 /* timr.stop(); 00195 printf("Fill solid %d\n", timr.read_us()); // Fill 50 LEDS solid colour = 11uS 00196 */ 00197 } 00198 00199 // Fill - with interpolation of colours using HSV colour space 00200 void ledstrip::Fill(int startLed, int numLeds, 00201 int r1, int g1, int b1, 00202 int r2, int g2, int b2) 00203 { 00204 /* Timer timr; 00205 timr.start(); 00206 */ 00207 if ((startLed < 0) || (startLed >= mLedsInStrip)) 00208 return; 00209 if (numLeds >= mLedsInStrip - startLed) 00210 numLeds = mLedsInStrip - startLed; 00211 int pos = startLed * mColoursPerLed; 00212 RgbColor startRGB(r1,g1,b1); 00213 HsvColor startHsv(0,0,0); 00214 RgbToHsv(startRGB, startHsv); 00215 RgbColor endRGB(r2,g2,b2); 00216 HsvColor endHsv(0,0,0); 00217 RgbToHsv(endRGB, endHsv); 00218 int curH = startHsv.h << 16; 00219 int curS = startHsv.s << 16; 00220 int curV = startHsv.v << 16; 00221 int interpSteps = numLeds - 1; 00222 if (interpSteps < 1) 00223 interpSteps = 1; 00224 int incH = ((endHsv.h - startHsv.h) << 16) / interpSteps; 00225 int incS = ((endHsv.s - startHsv.s) << 16) / interpSteps; 00226 int incV = ((endHsv.v - startHsv.v) << 16) / interpSteps; 00227 // Since H is a polar value we need to find out if it is best to go clockwise or anti-clockwise 00228 if (endHsv.h > startHsv.h) 00229 { 00230 if (endHsv.h-startHsv.h > 128) 00231 incH = ((startHsv.h-endHsv.h) << 16) / interpSteps; 00232 } 00233 else 00234 { 00235 // Go "round the top" using modulo result 00236 if (startHsv.h-endHsv.h > 128) 00237 incH = ((endHsv.h + 255 - startHsv.h) << 16) / interpSteps; 00238 } 00239 00240 // 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); 00241 unsigned char* pBuf = GetBuffer(); 00242 for (int i = 0; i < numLeds; i++) 00243 { 00244 RgbColor colrVal(0,0,0); 00245 HsvToRgb(HsvColor((curH>>16)&0xff,curS>>16,curV>>16), colrVal); 00246 pBuf[pos] = colrVal.r; 00247 pBuf[pos+1] = colrVal.g; 00248 pBuf[pos+2] = colrVal.b; 00249 // printf("HSV %d %d %d RGB %d %d %d\n", curH>>16, curS>>16, curV>>16, colrVal.r, colrVal.g, colrVal.b); 00250 pos += mColoursPerLed; 00251 curH = curH + incH; 00252 curS = curS + incS; 00253 curV = curV + incV; 00254 } 00255 /* 00256 timr.stop(); 00257 printf("Fill gradient %d\n", timr.read_us()); // Fill gradient 50 LEDS = 64uS 00258 */ 00259 } 00260 00261 void ledstrip::ShowLeds() 00262 { 00263 // Check if busy 00264 while (isr0Busy || isr1Busy) 00265 wait_us(2000); 00266 // wait_us(2000); 00267 00268 // Set up start points 00269 mCurPos0 = 0; 00270 mEndPos0 = mSplitPoint*mColoursPerLed; 00271 mCurPos1 = mSplitPoint*mColoursPerLed; 00272 mEndPos1 = mLedsInStrip*mColoursPerLed; 00273 00274 // Set the buffer for the ISRs 00275 pLedValues0 = mpCurLedValues; 00276 pLedValues1 = mpCurLedValues; 00277 00278 // Flip the current buffer to the alternate one for interleaved writing 00279 if (mpCurLedValues == mpLedValuesA) 00280 { 00281 memcpy(mpLedValuesB, mpLedValuesA, mLedsBufSize); 00282 mpCurLedValues = mpLedValuesB; 00283 } 00284 else 00285 { 00286 memcpy(mpLedValuesA, mpLedValuesB, mLedsBufSize); 00287 mpCurLedValues = mpLedValuesA; 00288 } 00289 00290 // Enable interrupts 00291 isr0Busy = true; 00292 if (mSplitPoint < mLedsInStrip) 00293 isr1Busy = true; 00294 00295 // Check if second strip is used 00296 LPC_SSP0->IMSC = (1 << SSP_IMSC_TX_RDY) & SSP_IMSC_BITMASK; 00297 if (mSplitPoint < mLedsInStrip && mSplitPoint > 0) 00298 LPC_SSP1->IMSC = (1 << SSP_IMSC_TX_RDY) & SSP_IMSC_BITMASK; 00299 }
Generated on Wed Jul 13 2022 23:44:38 by
1.7.2