I have continued working on controlling the WS2812B leds and enhanced the source with a few neat features like draw line, circle and alpha blending.
This code has been tested with a Microchip PIC32MX250F128B micro controller, and XC32 C++ with optimization set to 1
Running this code you should get something like this:
/* * File: main.cpp * Author: Henrik Thulin * * Created on den 2 may 2014, 02:26 * * xc32-g++ optimizer should be set to 1 */ #pragma config POSCMOD=XT #pragma config FSOSCEN=OFF #pragma config FNOSC=PRIPLL #pragma config OSCIOFNC=ON #pragma config FPLLODIV=DIV_1 #pragma config FPLLMUL=MUL_20 #pragma config FPLLIDIV=DIV_1 #pragma config FWDTEN=OFF #pragma config FPBDIV=DIV_1 #pragma config CP=OFF #pragma config BWP=OFF #pragma config PWP=OFF #define SYS_FREQ (80000000L) #define GetPeripheralClock() (FYC/(1 << OSCCONbits.PBDIV)) #define GetInstructionClock() (FYC) // For 8x8 leds #define ROWS 8 #define COLS 8 // B5 is here used as output pin #define LEDPORT IOPORT_B #define LEDPIN BIT_5 #define LEDHIGH mPORTBSetBits(LEDPIN); #define LEDLOW mPORTBClearBits(LEDPIN); #include #include unsigned int bitmapBuffer[ROWS*COLS]; // For these timings to be correct, optimization 1 should be used void sendBitmapPixel(unsigned int x) { char i = 24; do { if ((x >> --i) & 1) { LEDHIGH Nop(); Nop(); Nop(); Nop(); Nop(); LEDLOW } else { LEDHIGH Nop(); Nop(); LEDLOW Nop(); Nop(); Nop(); Nop(); } } while (i > 0); } void sendBitmapBuffer() { for (int i = 0; i < COLS * ROWS; i++) sendBitmapPixel(bitmapBuffer[i]); } // returns alpha, green, red, blue that'll work with the WS2811, but for simplicity is called ARGB unsigned int getARGB(unsigned char alpha, unsigned char r, unsigned char g, unsigned char b) { return (alpha << 24) | (g << 16) | (r << 8) | b; } // converts alpha, red, green and blue to alpha, green, red and blue unsigned int getARGB(unsigned int i) { return (i & 0xff000000) | ((i & 0x00ff0000) >> 8) | ((i & 0x0000ff00) << 8) | (i & 0x000000ff); } unsigned int getPixel(char x, char y) { return bitmapBuffer[y * COLS + x]; } unsigned int addAlphaColor(char x, char y, unsigned int add) { unsigned int original = getPixel(x, y); float alpha = (float) ((add & 0xff000000) >> 24) / 0xff; unsigned char green = (((float) ((original >> 16) & 0xff) * (1 - alpha)) + ((float) ((add >> 16) & 0xff) * alpha)); unsigned char red = (((float) ((original >> 8) & 0xff) * (1 - alpha)) + (((float) ((add >> 8) & 0xff)) * alpha)); unsigned char blue = (((float) (original & 0xff) * (1 - alpha)) + ((float) ((add & 0xff) * alpha))); return (green << 16 | red << 8 | blue); } void setPixel(char x, char y, unsigned int color) { if (x < 0 || y < 0 || x >= COLS || y >= ROWS) return; // pixels outside the boundaries are ignored if (color >> 24 == 0xff) // when full alpha, no need to do any RGB calculations bitmapBuffer[y * COLS + x] = color; else bitmapBuffer[y * COLS + x] = addAlphaColor(x, y, color); } void setBackground(unsigned int color) { for (int i = 0; i < COLS * ROWS; i++) bitmapBuffer[i] = color; } void fillRectangle(char x1, char y1, char x2, char y2, unsigned int color) { for (int x = x1; x <= x2; x++) for (int y = y1; y <= y2; y++) setPixel(x, y, color); } void drawLine(char x1, char y1, char x2, char y2, unsigned int color) { if (x2 < x1) { char temp = x1; x1 = x2; x2 = temp; } if (y2 < y1) { char temp = y1; y1 = y2; y2 = temp; } float xPosInc = (x2 - x1 > y2 - y1) ? 1 : (float) (x2 - x1) / (float) (y2 - y1); float yPosInc = (y2 - y1 > x2 - x1) ? 1 : (float) (y2 - y1) / (float) (x2 - x1); float xpos = x1; float ypos = y1; for (int i = 0; i <= ((x2 - x1) > (y2 - y1) ? x2 - x1 : y2 - y1); i++) { setPixel(xpos, ypos, color); xpos += xPosInc; ypos += yPosInc; } } void drawRectangle(char x1, char y1, char x2, char y2, unsigned int color) { drawLine(x1, y1, x2, y1, color); // top drawLine(x1, y2, x2, y2, color); // bottom drawLine(x1, y1, x1, y2, color); // left drawLine(x2, y1, x2, y2, color); // right } // Not optimized but does the job void drawCircle(char x, char y, char radius, unsigned int color) { for (float angle = 0; angle < 3.142 * 2; angle += 0.1) { setPixel(x + round(radius * cos(angle)), y + round(radius * sin(angle)), color); } } int main() { SYSTEMConfigPerformance(80000000L); SYSTEMConfig(SYS_FREQ, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); mJTAGPortEnable(DEBUG_JTAGPORT_OFF); PORTSetPinsDigitalOut(LEDPORT, LEDPIN); OpenTimer1(T1_ON | T1_PS_1_256, 0xffffff); unsigned char r[ROWS][COLS]; unsigned char i; while (1) { WriteTimer1(0); setBackground(getARGB(0xff000002)); if (i++ % 2) { char s1 = rand() % COLS; char s2 = rand() % ROWS; if (r[s1][s2] == 0) r[s1][s2] = 1; } for (int y = 0; y < ROWS; y++) for (int x = 0; x < COLS; x++) { if (r[y][x] > 0) { r[y][x]++; if (r[y][x] < 128) setPixel(x, y, getARGB(r[y][x], 0, 155, 0)); else setPixel(x, y, getARGB(0xff - r[y][x], 0, 155, 0)); } } sendBitmapBuffer(); while (ReadTimer1() < 0x3ff) Nop(); } return 0; }