NeoPixel NeoMatrix 8x8 RGB LED library. Product found at https://www.adafruit.com/products/1487. NeoCore.s from Allen Wild's NeoStrip library: http://developer.mbed.org/users/aswild/code/NeoStrip/

Dependents:   NeoMatrix_Demo

Fork of NeoStrip by Allen Wild

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NeoMatrix.cpp Source File

NeoMatrix.cpp

00001 /**********************************************
00002  * NeoMatrix.cpp
00003  *
00004  * Taylor Powell
00005  * March 2015
00006  *
00007  *  Controls an Adafruit Neopixel NeoMatrix 8x8
00008  *  Because of the global nature of the IO register and bitmask variables, only one contiguous chain of NeoMatrix Arrays can be connected
00009  *  A large number of NeoMatrix arrays can be chained together by tying Din to Dout of sucessive arrays, but an external power sourece may be required
00010  *
00011  *  This library supports only the NXP LPC1768
00012  */
00013 
00014 #include "mbed.h"
00015 #include "NeoMatrix.h"
00016 #include "font.h"
00017 
00018 
00019 // FastIO register address and bitmask for the GPIO pin
00020 // because these are imported in the assembly
00021 uint32_t neo_fio_reg;
00022 uint32_t neo_bitmask;
00023 
00024 // function to write to the strip, implemented in ARM assembly
00025 extern "C" void neo_out(NeoColor*, int);
00026 
00027  #define max(a,b) \
00028    ({ __typeof__ (a) _a = (a); \
00029        __typeof__ (b) _b = (b); \
00030      _a > _b ? _a : _b; })
00031      
00032      #define min(a,b) \
00033    ({ __typeof__ (a) _a = (a); \
00034        __typeof__ (b) _b = (b); \
00035      _a < _b ? _a : _b; })
00036      
00037 
00038 
00039 NeoArr::NeoArr(PinName pin, int N) : N(N)
00040 {
00041     bright = 0.5;
00042     Nbytes = N * 64 * 3;
00043     arr = (NeoColor*)malloc(N * 64 * sizeof(NeoColor));
00044     if (arr == NULL)
00045     {
00046         printf("NeoArr: ERROR unable to malloc pixel array data");
00047         N = 0;
00048     }
00049     
00050     gpio_init(&gpio, pin, PIN_OUTPUT);      // initialize GPIO registers
00051     neo_fio_reg = (uint32_t)gpio.reg_dir;   // set registers and bitmask for
00052     neo_bitmask = 1 << ((int)pin & 0x1F);   // the assembly to use
00053 }
00054 
00055 void NeoArr::setBrightness(float bright)
00056 {
00057     this->bright = bright;
00058 }
00059 
00060 
00061 void NeoArr::setPixel(int idx, int x, int y, int color)
00062 {    
00063     int red = (color & 0xFF0000) >> 16;
00064     int green = (color & 0x00FF00) >> 8;
00065     int blue = (color & 0x0000FF);
00066     
00067     setPixel(idx, x, y, red, green, blue);
00068 }
00069 
00070 void NeoArr::setPixel(int idx, int x, int y, uint8_t red, uint8_t green, uint8_t blue)
00071 {
00072     int pixel = idx*64 + x*8 + y;   // specify pixel based on board index, x, and y values
00073     // modulate pixel by the total number of pixels
00074     arr[pixel % (N*64)].red = (uint8_t)(red * bright);
00075     arr[pixel % (N*64)].green = (uint8_t)(green * bright);
00076     arr[pixel % (N*64)].blue = (uint8_t)(blue * bright);
00077 }
00078 
00079 void NeoArr::drawLine(int idx, int x1, int y1, int x2, int y2, int color)
00080 {    
00081     int red = (color & 0xFF0000) >> 16;
00082     int green = (color & 0x00FF00) >> 8;
00083     int blue = (color & 0x0000FF);
00084     
00085     drawLine(idx, x1, y1, x2,y2, red, green, blue);
00086 }
00087 
00088 void NeoArr::drawLine(int idx, int x1, int y1, int x2, int y2, uint8_t red, uint8_t green, uint8_t blue)
00089 {
00090     float k;
00091     int j = rint(sqrt(pow((x1-x2),2.0) + pow((y1-y2),2.0)));    // calculates magnitude of line
00092     if(x1 != x2)  // handle infinite case
00093         k = atan2( (float)(y2-y1),(float) ( x2-x1));    // calculates angle of line
00094     else
00095         k = acos(0.0);
00096         
00097     for(float n=0; n<=j; n++)   // set a number pixels equal to the magnitude of the line along the closest (rounded) line
00098         if((x1+ rint(n*cos(k))) >=0 && (x1+rint( n*cos(k))) <=7 &&  (y1+rint(n*sin(k)))>=0 &&  (y1+rint(n*sin(k)))<=7)
00099             setPixel(idx, x1+ rint(n*cos(k)), y1+ rint(n*sin(k)), red, green, blue);
00100         
00101     
00102 }
00103 
00104 void NeoArr::drawRect(int idx, int x1, int y1, int x2, int y2, int color)
00105 {    
00106     int red = (color & 0xFF0000) >> 16;
00107     int green = (color & 0x00FF00) >> 8;
00108     int blue = (color & 0x0000FF);
00109     
00110     drawRect(idx, x1, y1, x2,y2, red, green, blue);
00111 }
00112 
00113 void NeoArr::drawRect(int idx, int x1, int y1, int x2, int y2, uint8_t red, uint8_t green, uint8_t blue)
00114 {
00115     // note: drawRect does not use drawLine function because the angles will always be 90 degrees and so for these for loops are faster
00116     for(int i=0; i<=(abs(x2-x1)); i++){ // draws horizontal lines
00117         if ((max(x1,x2)-i) >= 0 && max(x1, x2) -i <=7){
00118             if(max(y1,y2) <= 7)
00119                 setPixel(idx, max(x1,x2)-i, max(y1,y2), red, green, blue);
00120             
00121             if(min(y1,y2) >= 0)
00122                 setPixel(idx, max(x1,x2)-i, min(y1,y2), red, green, blue);
00123             }
00124         }
00125         
00126     for(int i=0; i<=(abs(y2-y1)); i++){ // draws verticle lines
00127         if ((max(y1,y2)-i) >= 0 && max(y1, y2) -i <=7){
00128             if(max(x1,x2) <= 7)
00129                 setPixel(idx, max(x1,x2), max(y1,y2)-i, red, green, blue);
00130             
00131             if(min(x1,x2) >= 0)
00132                 setPixel(idx, min(x1,x2), max(y1,y2)-i, red, green, blue);
00133             }
00134         }
00135 }
00136 
00137 
00138 void NeoArr::drawFilledRect(int idx, int x1, int y1, int x2, int y2, int color)
00139 {    
00140     int red = (color & 0xFF0000) >> 16;
00141     int green = (color & 0x00FF00) >> 8;
00142     int blue = (color & 0x0000FF);
00143     
00144     drawFilledRect(idx, x1, y1, x2,y2, red, green, blue);
00145 }
00146 
00147 void NeoArr::drawFilledRect(int idx, int x1, int y1, int x2, int y2, uint8_t red, uint8_t green, uint8_t blue)
00148 {
00149     for(int i=0; i<=(abs(x2-x1)); i++){
00150         if ((max(x1,x2)-i) >= 0 && max(x1, x2) -i <=7){
00151             for(int n=0; n<=(abs(y2-y1)); n++){
00152                 if((max(y1,y2)-n) >= 0 && max(y1, y2)-n <=7){
00153                     setPixel(idx, max(x1,x2)-i, max(y1,y2)-n, red, green, blue);
00154                 }
00155             }
00156         }
00157     }
00158     
00159 }
00160 
00161 void NeoArr::fillScreen(int idx, int color)
00162 {    
00163     int red = (color & 0xFF0000) >> 16;
00164     int green = (color & 0x00FF00) >> 8;
00165     int blue = (color & 0x0000FF);
00166     
00167     fillScreen(idx, red, green, blue);
00168 }
00169 
00170 void NeoArr::fillScreen(int idx,uint8_t red, uint8_t green, uint8_t blue)
00171 {    
00172    for(int i=0; i<8; i++)
00173         for(int n=0; n<8; n++)
00174             setPixel(idx, i, n, red, green, blue);
00175 }
00176 
00177 
00178 void NeoArr::drawTriangle(int idx, int x1, int y1, int x2, int y2, int x3, int y3, int color)
00179 {    
00180     int red = (color & 0xFF0000) >> 16;
00181     int green = (color & 0x00FF00) >> 8;
00182     int blue = (color & 0x0000FF);
00183     
00184     drawTriangle(idx, x1, y1, x2,y2, x3, y3, red, green, blue);
00185 }
00186 
00187 void NeoArr::drawTriangle(int idx, int x1, int y1, int x2, int y2, int x3, int y3, uint8_t red, uint8_t green, uint8_t blue)
00188 {
00189     
00190     drawLine(idx, x1, y1, x2, y2, red, green, blue);
00191     drawLine(idx, x2, y2, x3, y3, red, green, blue);
00192     drawLine(idx, x3, y3, x1, y1, red, green, blue);
00193     
00194 }
00195 
00196 void NeoArr::drawFilledTriangle(int idx, int x1, int y1, int x2, int y2, int x3, int y3, int color)
00197 {    
00198     int red = (color & 0xFF0000) >> 16;
00199     int green = (color & 0x00FF00) >> 8;
00200     int blue = (color & 0x0000FF);
00201     
00202     drawFilledTriangle(idx, x1, y1, x2,y2, x3, y3, red, green, blue);
00203 }
00204 
00205 void NeoArr::drawFilledTriangle(int idx, int x1, int y1, int x2, int y2, int x3, int y3, uint8_t red, uint8_t green, uint8_t blue)
00206 {
00207     // note: drawFilledTriangle draws two legs of the triangle and then draws lines from their corner to each point on the opposite leg
00208     drawLine(idx, x1, y1, x2, y2, red, green, blue);
00209     drawLine(idx, x2, y2, x3, y3, red, green, blue);
00210     
00211     
00212     float k;
00213     int j = rint(sqrt(pow((x1-x3),2.0) + pow((y1-y3),2.0)));    // magnitude of opposite leg
00214     if(x1 != x3)
00215         k = atan2( (float)(y3-y1),(float) ( x3-x1));    // angle of line of opposite leg
00216     else
00217         k = acos(0.0);
00218         
00219     for(float n=0; n<=j; n++)
00220         if((x1+ rint(n*cos(k))) >=0 && (x1+rint( n*cos(k))) <=7 &&  (y1+rint(n*sin(k)))>=0 &&  (y1+rint(n*sin(k)))<=7)
00221             drawLine(idx, x1+ rint(n*cos(k)), y1+ rint(n*sin(k)), x2, y2, red, green, blue);    // draw line from corner to each point on opposite leg
00222 }
00223 
00224 void NeoArr::drawChar(int idx, int x, int y, char c, int color)
00225 {    
00226     int red = (color & 0xFF0000) >> 16;
00227     int green = (color & 0x00FF00) >> 8;
00228     int blue = (color & 0x0000FF);
00229     
00230     drawChar(idx, x, y, c, red, green, blue);
00231 }
00232 
00233 void NeoArr::drawChar(int idx, int x, int y, char c, uint8_t red, uint8_t green, uint8_t blue)
00234 {
00235     uint8_t i,j;
00236     
00237     c = c & 0x7F;  // mask c to avoid errors
00238     
00239     if (c < ' ') {  // convert c into index of font array
00240         c = 0;
00241     } else {
00242         c -= ' ';
00243     }
00244 
00245     // font is BMplain, a 96x6 array stored in font.h, many free available fonts are online and can be swapped into this font
00246     const uint8_t* chr = font[c];
00247 
00248     for (j=0; j<6; j++) {   // character width is 6
00249         for (i=0; i<8; i++) {   // character height is 8
00250             if (chr[j] & (1<<i)) {  // if there is a pixel in the vertical line, set pixel on board
00251                 if((x+j) <= 7 && (x+j)>=0 && (y+7-i)>=0 && (y+7-i) <=7)
00252                      setPixel(0, x+j, y+ 7-i, red,green,blue);
00253             }
00254         }
00255     }
00256 }
00257 
00258 void NeoArr::showImage(int idx, const int *img)
00259 {
00260     int r, g, b;
00261     for (int i = 0; i < 8; i++)
00262         for(int n=0; n<8;n++){
00263         r = (img[i] & 0xFF0000) >> 16;
00264         g = (img[i] & 0x00FF00) >>8;
00265         b = img[i] & 0x0000FF;
00266         setPixel(idx,i,n, r, g, b);
00267     }
00268 }
00269 
00270 void NeoArr::clear()
00271 {
00272     for (int i = 0; i < (N*64); i++)
00273     {
00274         arr[i].red = 0;
00275         arr[i].green = 0;
00276         arr[i].blue = 0;
00277     }
00278 }
00279 
00280 void NeoArr::write()
00281 {
00282     __disable_irq();        // disable interrupts
00283     neo_out(arr, Nbytes); // output to the strip
00284     __enable_irq();         // enable interrupts
00285     wait_us(50);            // wait 50us for the reset pulse
00286 }
00287 
00288