![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
Cubic Hand project for EECS 249A course.
Dependencies: MMA8451Q TSI cc3000_hostdriver_mbedsocket NVIC_set_all_priorities mbed Multi_WS2811
Diff: LedCube.cpp
- Revision:
- 56:f95ec9baa4cb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LedCube.cpp Mon Dec 15 23:55:15 2014 +0000 @@ -0,0 +1,298 @@ +/* + * Neopixel LED Cube library + * by Robert Bui and Jose Oyola + * UC Berkeley 2014 + */ + +#include "mbed.h" +#include "WS2811.h" +#include "Colors.h" +#include "TSISensor.h" +#include "MMA8451Q.h" +#include "LedCube.h" + + +#define MMA8451_I2C_ADDRESS (0x1d<<1) + +#define PANEL1 0 +#define PANEL2 1 +#define PANEL3 2 +#define nLEDs 200 //MAX_LEDS_PER_STRIP; +#define MAX_SIZE 10 +#define nROWs 10 //number of rows per cube panel +#define nCOLs 10 //number of columns per cube panel +#define DATA_OUT_PIN1 2 // PTD2 +#define DATA_OUT_PIN2 3 // PTD3 + + +LedCube::LedCube():X(0),Y(1),Z(2),ledStrip1(nLEDs, DATA_OUT_PIN1),ledStrip2(nLEDs/2, DATA_OUT_PIN2) +{ +} + +LedCube::~LedCube() +{ +} + +/*Sets the initial size and position of the lighted cube*/ +void LedCube::Init(int x, int y, int z) +{ + size = 2; + prevSize = size; + pos[X] = prevPos[X] = x; + pos[Y] = prevPos[Y] = y; + pos[Z] = prevPos[Z] = z; + r = 255*0.1; + g = 255*0.1; + b = 255*0.1; + + brightness = 0.5/8; + saturation = 1.0; + + ledStrip1.begin(); + ledStrip2.begin(); +} + +/* Returns the index of the LED given the cartesian + * coordinates of the LED on a given panel. The origin + * is the led at the bottom left of panel 1 when using + * a three panel cube. + ________ + / /| + / 3 / | + /_______/ 2| + | | | + | 1 | / + | | + -------- + + Z Y + | / + | / + | / + |/ + -------X + + */ +int LedCube::getLedIndex(int panel, int x, int y) { + if (panel == PANEL1) { + if (y % 2 == 0) { + return nCOLs*2 * y + x; + } + else { + return nCOLs*2 * y + nCOLs + ((nCOLs - 1) - x); + } + } + + if (panel == PANEL2) { + if (y % 2 == 0) { + return nCOLs*2 * y + nCOLs + x; + } + else { + return nCOLs*2 * y + ((nCOLs - 1) - x); + } + } + + if (panel == PANEL3) { + if (y % 2 == 0) { + return nCOLs * y + x; + } + else { + return nCOLs * y + ((nCOLs - 1) - x); + } + } + + else return -1; +} + +/* + * Lights up (if on) or turns off (if !on) the LEDs on the LED cube + * corresponding to the location of the square. All panels will show + * the cube, with brightness depending on the distance from the + * square to the panel. + */ +void LedCube::updateLEDs(bool on, int size, int x, int y, int z) { + //Panel 1 + double bright; + bright = 1.0 / ((y + 1) * (y + 1)); + for(int i = x; i < x + size; i++) { + for(int j = z; j < z + size; j++) { + int led = getLedIndex(PANEL1, i, j); + if(on) { + ledStrip1.setPixelColor(led, r*bright, g*bright, b*bright); + } else { + ledStrip1.setPixelColor(led, 0, 0, 0); + } + } + } + + //Panel 2 + bright = 1.0 / (((nCOLs-1) - x - (size-1) + 1) * ((nCOLs-1) - x - (size-1) + 1)); + for(int i = y; i < y + size; i++) { + for(int j = z; j < z + size; j++) { + int led = getLedIndex(PANEL2, i, j); + if(on) { + ledStrip1.setPixelColor(led, r*bright, g*bright, b*bright); + } else { + ledStrip1.setPixelColor(led, 0, 0, 0); + } + } + } + + //Panel 3 + bright = 1.0 / (((nCOLs-1) - z - (size-1) + 1) * ((nCOLs-1) - z - (size-1) + 1)); + for(int i = x; i < x + size; i++) { + for(int j = y; j < y + size; j++) { + int led = getLedIndex(PANEL3, i, j); + if(on) { + ledStrip2.setPixelColor(led, r*bright, g*bright, b*bright); + } else { + ledStrip2.setPixelColor(led, 0, 0, 0); + } + } + } +} + +void LedCube::updateLEDsOld(bool on, int size, int x, int y, int z) { + //Panel 1 + if(y == 0) { + for(int i = x; i < x + size; i++) { + for(int j = z; j < z + size; j++) { + int led = getLedIndex(PANEL1, i, j); + if(on) { + ledStrip1.setPixelColor(led, r, g, b); + } else { + ledStrip1.setPixelColor(led, 0, 0, 0); + } + } + } + } + + //Panel 2 + if(x + size - 1 == (nCOLs - 1)) { + for(int i = y; i < y + size; i++) { + for(int j = z; j < z + size; j++) { + int led = getLedIndex(PANEL2, i, j); + if(on) { + ledStrip1.setPixelColor(led, r, g, b); + } else { + ledStrip1.setPixelColor(led, 0, 0, 0); + } + } + } + } + + //Panel 3 + if(z + size - 1 == (nCOLs - 1)) { + for(int i = x; i < x + size; i++) { + for(int j = y; j < y + size; j++) { + int led = getLedIndex(PANEL3, i, j); + if(on) { + ledStrip2.setPixelColor(led, r, g, b); + } else { + ledStrip2.setPixelColor(led, 0, 0, 0); + } + } + } + } +} + +/* + * Updates the LED cube. + */ +void LedCube::cubeUpdate() { + updateLEDs(false, prevSize, prevPos[X], prevPos[Y], prevPos[Z]); //Turn off LEDs from previous state + updateLEDs(true, size, pos[X], pos[Y], pos[Z]); //Turn on new LEDs for new state + prevSize = size; + prevPos[X] = pos[X]; + prevPos[Y] = pos[Y]; + prevPos[Z] = pos[Z]; + ledStrip1.show(); + ledStrip2.show(); + ledStrip1.startDMA(); + ledStrip2.startDMA(); +} + +/* + * Moves the square inside the cube by deltaX in the x-axis, + * by deltaY in the y-axis, and deltaZ in the z-axis. Returns + * 1 if movement occured, and -1 if no movement occured. + */ +int LedCube::move(int deltaX, int deltaY, int deltaZ) { + int retVal = -1; + //Moving in X direction + if((pos[X] + size + deltaX - 1) < nCOLs && (pos[X] + deltaX) >= 0) { + pos[X] += deltaX; + if (deltaX != 0) retVal = 1; + } + + //Moving in Y direction + if((pos[Y] + size + deltaY - 1) < nCOLs && (pos[Y] + deltaY) >= 0) { + pos[Y] += deltaY; + if (deltaY != 0) retVal = 1; + } + + //Moving in Z direction + if((pos[Z] + size + deltaZ - 1) < nCOLs && (pos[Z] + deltaZ) >= 0) { + pos[Z] += deltaZ; + if (deltaZ != 0) retVal = 1; + } + return retVal; +} + +/* + * Changes the color of the square in the LED cube to the given hue. + */ +void LedCube::changeColor(float hue){ + Colors::HSBtoRGB(hue, saturation, brightness, &r, &g, &b); +} + +/* + * Changes the size of the square in the LED cube to the given size. + * The minimum size is 1, corresponding to a square of a single LED. + * A size of 2 corresponds to a 2x2 LED square, 3 corresponds to 3x3 + * and so forth. If square is on an edge, it moves accordingly in + * order to be able to increase size. + */ +void LedCube::changeSize(int newSize) { + if(newSize > 0 && newSize <= MAX_SIZE) { + if ((pos[X] + newSize) <= nCOLs && (pos[Y] + newSize) <= nCOLs && (pos[Z] + newSize) <= nCOLs) { + size = newSize; + return; + } + else { + int delta_x = 0; + int delta_y = 0; + int delta_z = 0; + if ((pos[X] + newSize) > nCOLs) { + delta_x = nCOLs - (pos[X] + newSize); + } + if ((pos[Y] + newSize) > nCOLs) { + delta_y = nCOLs - (pos[Y] + newSize); + } + if ((pos[Z] + newSize) > nCOLs) { + delta_z = nCOLs - (pos[Z] + newSize); + } + move(delta_x, delta_y, delta_z); + size = newSize; + return; + } + } +} + +/* + * Updates the LED cube given the size, hue and offsets in the X, Y and Z axes. + */ +void LedCube::UpdateCube(int ledSize, int deltaX, int deltaY, int deltaZ, float hue) { + changeSize(ledSize); + move(deltaX, deltaY, deltaZ); + changeColor(hue); + cubeUpdate(); +} + +/* + * Updates the LED cube given parameters in a CubeUpdateParameters struct. + */ +void LedCube::UpdateCube2(CubeUpdateParameters cubeParams){ + UpdateCube(cubeParams.size, cubeParams.deltaX, cubeParams.deltaY, cubeParams.deltaZ, cubeParams.hue); +} +