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.
Revision 1:e08a4d27f534, committed 2012-11-01
- Comitter:
- Bas
- Date:
- Thu Nov 01 22:31:54 2012 +0000
- Parent:
- 0:920c5ed65a45
- Commit message:
- Added several simple graphic functions helping to create animations
Changed in this revision
| led_cube.cpp | Show annotated file Show diff for this revision Revisions of this file |
| led_cube.h | Show annotated file Show diff for this revision Revisions of this file |
--- a/led_cube.cpp Sat Sep 08 22:14:10 2012 +0000
+++ b/led_cube.cpp Thu Nov 01 22:31:54 2012 +0000
@@ -30,7 +30,8 @@
}
//clear everything
-void LED_CUBE::clear_cube(void){
+void LED_CUBE::clear_cube(void)
+{
row.WriteByte(0xFF);
colums_0_1.WriteBytes(0xFF,0xFF);
colums_2_3.WriteBytes(0xFF,0xFF);
@@ -39,35 +40,555 @@
clearVoxels();
}
-//set a voxel in my space saver cube array
-void LED_CUBE::setVoxel(unsigned char x, unsigned char y, unsigned char z){
- cubeData[z*8 + y] |= 0x01<<x;
+//set a voxel in the cube array
+void LED_CUBE::setVoxel(unsigned char x, unsigned char y, unsigned char z)
+{
+ if (inrange(x, y, z))
+ cubeData[z*8 + x] |= 0x01<<y;
}
-//clear a single voxel in my space saver cube array
-void LED_CUBE::clearVoxel(unsigned char x, unsigned char y, unsigned char z){
- cubeData[z*8 + y] &= ~(0x01<<x);
+//clear a single voxel in the cube array
+void LED_CUBE::clearVoxel(unsigned char x, unsigned char y, unsigned char z)
+{
+ if (inrange(x, y, z))
+ cubeData[z*8 + x] &= ~(0x01<<y);
}
-//return the value of the voxel in my cube array
-unsigned char LED_CUBE::getVoxel(unsigned char x, unsigned char y, unsigned char z){
- if(cubeData[z*8 + y] & 0x01<<x){
- return 1;
- }else{
+//return the value of a single voxel in the cube array
+unsigned char LED_CUBE::getVoxel(unsigned char x, unsigned char y, unsigned char z)
+{
+ if (inrange(x, y, z)) {
+ if(cubeData[z*8 + x] & 0x01<<y) {
+ return 1;
+ } else {
+ return 0;
+ }
+ } else {
return 0;
}
}
-void LED_CUBE::copyColumn(unsigned char x, unsigned char y, unsigned char col){
- for(unsigned char z = 0; z < Zd; z++){
- if(col&(0x01<<z)){
+void LED_CUBE::copyColumn(unsigned char x, unsigned char y, unsigned char col)
+{
+ for(unsigned char z = 0; z < 8; z++) {
+ if(col&(0x01<<z)) {
setVoxel(x, y, z);
- }else{
+ } else {
clearVoxel(x, y, z);
}
}
}
+
+// In some effect we want to just take bool and write it to a voxel
+// this function calls the apropriate voxel manipulation function.
+void LED_CUBE::alterVoxel(unsigned char x, unsigned char y, unsigned char z, unsigned char state)
+{
+ if (state == 1) {
+ setVoxel(x,y,z);
+ } else {
+ clearVoxel(x,y,z);
+ }
+}
+
+// Flip the state of a voxel.
+// If the voxel is 1, its turned into a 0, and vice versa.
+void LED_CUBE::flipVoxel(unsigned char x, unsigned char y, unsigned char z)
+{
+ if (inrange(x, y, z))
+ cubeData[z*8 + x] ^= (1 << y);
+}
+
+void LED_CUBE::setPlane_x (int x)
+{
+ int z;
+
+ if (x>=0 && x<8) {
+ for (z=0; z<8; z++)
+ cubeData[z*8 + x] = 0xFF;
+ }
+}
+
+void LED_CUBE::clearPlane_x (int x)
+{
+ int z;
+
+ if (x>=0 && x<8) {
+ for (z=0; z<8; z++)
+ cubeData[z*8 + x] = 0x00;
+ }
+}
+
+void LED_CUBE::setPlane_y (int y)
+{
+ int z;
+ int x;
+
+ if (y>=0 && y<8) {
+ for (z=0; z<8; z++) {
+ for (x=0; x<8; x++) {
+ cubeData[z*8 + x] |= (1 << y);
+ }
+ }
+ }
+}
+
+void LED_CUBE::clearPlane_y (int y)
+{
+ int z;
+ int x;
+
+ if (y>=0 && y<8) {
+ for (z=0; z<8; z++) {
+ for (x=0; x<8; x++) {
+ cubeData[z*8 + x] &= ~(1 << y);
+ }
+ }
+ }
+}
+// Sets all voxels along a X/Y plane at a given point
+// on axis Z
+void LED_CUBE::setPlane_z (int z)
+{
+ int i;
+
+ if (z>=0 && z<8) {
+ for (i=0; i<8; i++)
+ cubeData[z*8 + i] = 0xFF;
+ }
+}
+
+// Clears voxels in the same manner as above
+void LED_CUBE::clearPlane_z (int z)
+{
+ int i;
+
+ if (z>=0 && z<8) {
+ for (i=0; i<8; i++)
+ cubeData[z*8 + i] = 0x00;
+ }
+}
+
+void LED_CUBE::setPlane (char axis, unsigned char i)
+{
+ switch (axis) {
+ case AXIS_X:
+ setPlane_x(i);
+ break;
+ case AXIS_Y:
+ setPlane_y(i);
+ break;
+ case AXIS_Z:
+ setPlane_z(i);
+ break;
+ }
+}
+
+void LED_CUBE::clearPlane (char axis, unsigned char i)
+{
+ switch (axis) {
+ case AXIS_X:
+ clearPlane_x(i);
+ break;
+ case AXIS_Y:
+ clearPlane_y(i);
+ break;
+ case AXIS_Z:
+ clearPlane_z(i);
+ break;
+ }
+}
+void LED_CUBE::setSlope_XY(int x1, int y1, int x2, int y2)
+{
+ float slope, offset;
+ int x,y,z;
+
+ if (x1>x2) {
+ int tmp;
+ tmp = x2;
+ x2 = x1;
+ x1 = tmp;
+ tmp = y2;
+ y2 = y1;
+ y1 = tmp;
+ }
+
+ slope=float(y2-y1)/float(x2-x1);
+ offset=-x1*slope +y1;
+
+ if ((x2-x1)>=7) {
+ for(x=0; x<8; x++) {
+ y = floor((x*slope + offset)+0.5);
+ for(z=0; z<8; z++) {
+ setVoxel(x,y,z);
+ }
+ }
+ } else if(x1==x2) {
+ for(y=0; y<8; y++) {
+ for(z=0; z<8; z++) {
+ setVoxel(x1,y,z);
+ }
+ }
+ } else {
+ for(y=0; y<8; y++) {
+ x = floor(((y-offset)/slope)+0.5);
+ for(z=0; z<8; z++) {
+ setVoxel(x,y,z);
+ }
+
+ }
+ }
+}
+
+void LED_CUBE::setSlope_XZ(int x1, int z1, int x2, int z2)
+{
+ float slope, offset;
+ int x,z;
+
+ if (x1>x2) {
+ int tmp;
+ tmp = x2;
+ x2 = x1;
+ x1 = tmp;
+ tmp = z2;
+ z2 = z1;
+ z1 = tmp;
+ }
+
+ slope=float(z2-z1)/float(x2-x1);
+ offset=-x1*slope +z1;
+
+ if ((x2-x1)>=7) {
+ for(x=0; x<8; x++) {
+ z = floor((x*slope + offset)+0.5);
+ cubeData[z*8 + x] = 0xFF;
+
+ }
+ } else if(x1==x2) {
+ for(z=0; z<8; z++) {
+ cubeData[z*8 + x1] = 0xFF;
+
+ }
+ } else {
+ for(z=0; z<8; z++) {
+ x = floor(((z-offset)/slope)+0.5);
+ cubeData[z*8 + x] = 0xFF;
+
+ }
+
+ }
+}
+
+
+void LED_CUBE::setSlope_YZ(int y1, int z1, int y2, int z2)
+{
+ float slope, offset;
+ int x,y,z;
+
+ if (y1>y2) {
+ int tmp;
+ tmp = y2;
+ y2 = y1;
+ y1 = tmp;
+ tmp = z2;
+ z2 = z1;
+ z1 = tmp;
+ }
+
+ slope=float(z2-z1)/float(y2-y1);
+ offset=-y1*slope +z1;
+
+ if ((y2-y1)>=7) {
+ for(y=0; y<8; y++) {
+ z = floor((y*slope + offset)+0.5);
+ for(x=0; x<8; x++) {
+ setVoxel(x,y,z);
+ }
+ }
+ } else if(y1==y2) {
+ for(z=0; z<8; z++) {
+ for(x=0; x<8; x++) {
+ setVoxel(x,y1,z);
+ }
+ }
+ } else {
+ for(z=0; z<8; z++) {
+ y = floor(((z-offset)/slope)+0.5);
+ for(x=0; x<8; x++) {
+ setVoxel(x,y,z);
+ }
+ }
+
+ }
+}
+
//clear all the voxels in the array
-void LED_CUBE::clearVoxels(void){
+void LED_CUBE::clearVoxels(void)
+{
memset(cubeData, 0, 64*sizeof(unsigned char));
+}
+
+// Fill a value into all 64 byts of the cube buffer
+// Mostly used for clearing. fill(0xr0)
+// or setting all on. fill(0xff)
+void LED_CUBE::fill (unsigned char pattern)
+{
+ memset(cubeData, pattern, 64*sizeof(unsigned char));
+}
+
+// Draw a box with all walls drawn and all voxels inside set
+void LED_CUBE::box_filled(int x1, int y1, int z1, int x2, int y2, int z2)
+{
+ int ix;
+ int iz;
+
+ argorder(x1, x2, &x1, &x2);
+ argorder(y1, y2, &y1, &y2);
+ argorder(z1, z2, &z1, &z2);
+ for (iz=z1; iz<=z2; iz++) {
+ for (ix=x1; ix<=x2; ix++) {
+ cubeData[iz*8 + ix] |= byteline(y1,y2);
+ }
+ }
+}
+
+// Draw a hollow box with side walls.
+void LED_CUBE::box_walls(int x1, int y1, int z1, int x2, int y2, int z2)
+{
+ int ix;
+ int iz;
+
+ argorder(x1, x2, &x1, &x2);
+ argorder(y1, y2, &y1, &y2);
+ argorder(z1, z2, &z1, &z2);
+ for (iz=z1; iz<=z2; iz++) {
+ for (ix=x1; ix<=x2; ix++) {
+ if (ix == x1 || ix == x2 || iz == z1 || iz == z2) {
+ cubeData[iz*8 + ix] = byteline(y1,y2);
+ } else {
+ cubeData[iz*8 + ix] |= ((0x01 << y1) | (0x01 << y2));
+ }
+ }
+ }
+}
+
+// Draw a wireframe box. This only draws the corners and edges,
+// no walls.
+void LED_CUBE::box_wireframe(int x1, int y1, int z1, int x2, int y2, int z2)
+{
+ int ix;
+ int iz;
+
+ argorder(x1, x2, &x1, &x2);
+ argorder(y1, y2, &y1, &y2);
+ argorder(z1, z2, &z1, &z2);
+ // Lines along Y axis
+ cubeData[z1*8 + x1] |= byteline(y1,y2);
+ cubeData[z1*8 + x2] |= byteline(y1,y2);
+ cubeData[z2*8 + x1] |= byteline(y1,y2);
+ cubeData[z2*8 + x2] |= byteline(y1,y2);
+ // Lines along X axis
+ for (ix=x1; ix<=x2; ix++) {
+ setVoxel(ix,y1,z1);
+ setVoxel(ix,y1,z2);
+ setVoxel(ix,y2,z1);
+ setVoxel(ix,y2,z2);
+ }
+ // Lines along Z axis
+ for (iz=z1; iz<=z2; iz++) {
+ setVoxel(x1,y1,iz);
+ setVoxel(x1,y2,iz);
+ setVoxel(x2,y1,iz);
+ setVoxel(x2,y2,iz);
+ }
+}
+
+// Draw a line between any coordinates in 3d space.
+// Uses integer values for input, so dont expect smooth animations.
+void LED_CUBE::line(int x1, int y1, int z1, int x2, int y2, int z2)
+{
+ float xy;
+ // how many voxels do we move on the y axis for each step on the x axis
+ float xz;
+ // how many voxels do we move on the y axis for each step on the x axis
+ unsigned char x,y,z;
+ // We always want to draw the line from x=0 to x=7.
+ // If x1 is bigget than x2, we need to flip all the values.
+ if (x1>x2) {
+ int tmp;
+ tmp = x2;
+ x2 = x1;
+ x1 = tmp;
+ tmp = y2;
+ y2 = y1;
+ y1 = tmp;
+ tmp = z2;
+ z2 = z1;
+ z1 = tmp;
+ }
+ if (y1>y2) {
+ xy = (float)(y1-y2)/(float)(x2-x1);
+ } else {
+ xy = (float)(y2-y1)/(float)(x2-x1);
+ }
+ if (z1>z2) {
+ xz = (float)(z1-z2)/(float)(x2-x1);
+ } else {
+ xz = (float)(z2-z1)/(float)(x2-x1);
+ }
+ // For each step of x, y increments by:
+ for (x = x1; x<=x2; x++) {
+ y = (xy*(x-x1))+y1;
+ z = (xz*(x-x1))+z1;
+ setVoxel(x,y,z);
+ }
+}
+void LED_CUBE::circle(int xr, int yr, int zr, int d ,char axis)
+{
+ if (d%2) { // odd diameter, place center on half pixels
+// later
+ } else { // use midpoint circle algorithm
+ int r = d/2;
+ int f = 1 - r;
+ int ddF_x = 1;
+ int ddF_y = -2 * r;
+ int x = 0;
+ int y = r;
+
+ setVoxel(xr, yr+r, zr);
+ setVoxel(xr, yr-r, zr);
+ setVoxel(xr+r, yr, zr);
+ setVoxel(xr-r, yr, zr);
+ while (x<y) {
+ if (f >= 0) {
+ y--;
+ ddF_y += 2;
+ f += ddF_y;
+ }
+ x++;
+ ddF_x += 2;
+ f += ddF_x;
+
+ setVoxel(xr + x, yr + y, zr);
+ setVoxel(xr - x, yr + y, zr);
+ setVoxel(xr + x, yr - y, zr);
+ setVoxel(xr - x, yr - y, zr);
+ setVoxel(xr + y, yr + x, zr);
+ setVoxel(xr - y, yr + x, zr);
+ setVoxel(xr + y, yr - x, zr);
+ setVoxel(xr - y, yr - x, zr);
+ }
+ }
+}
+
+void LED_CUBE::CopyBlock(int x1, int y1, int z1, int x2, int y2, int z2, int xc, int yc, int zc)
+{
+ int ix;
+ int iz;
+ int nx;
+ int nz=0;
+ unsigned char tmp_data[64];
+
+ argorder(x1, x2, &x1, &x2);
+ argorder(y1, y2, &y1, &y2);
+ argorder(z1, z2, &z1, &z2);
+
+ for (iz=z1; iz<=z2; iz++) {
+ nx=0;
+ for (ix=x1; ix<=x2; ix++) {
+ //copy block data into tmp array and mask.
+ tmp_data[iz*8 + ix] = cubeData[iz*8 + ix] & byteline(y1,y2);
+ //shift the tmp data to the new y location
+ if (yc >= y1) {
+ tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] << (yc-y1);
+ } else {
+ tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] >> (y1-yc);
+ }
+ //alter the cubedata on the new x and z location with the tmp data. use old y location and copy to the new location
+ cubeData[(zc+nz)*8 + xc+nx] = (cubeData[(zc+nz)*8 + xc+nx] & (~byteline(yc,yc+y2-y1))) | tmp_data[iz*8 + ix];
+ nx++;
+ }
+ nz++;
+ }
+}
+
+void LED_CUBE::MoveBlock(int x1, int y1, int z1, int x2, int y2, int z2, int xm, int ym, int zm)
+{
+ int ix;
+ int iz;
+ int nx;
+ int nz=0;
+ unsigned char tmp_data[64];
+
+ argorder(x1, x2, &x1, &x2);
+ argorder(y1, y2, &y1, &y2);
+ argorder(z1, z2, &z1, &z2);
+
+ for (iz=z1; iz<=z2; iz++) {
+ for (ix=x1; ix<=x2; ix++) {
+ //copy block data into tmp array and mask.
+ tmp_data[iz*8 + ix] = cubeData[iz*8 + ix] & byteline(y1,y2);
+ //clear the original voxels
+ cubeData[iz*8 + ix] &= ~byteline(y1,y2);
+ //shift the tmp data to the new y location
+ if (ym >= y1) {
+ tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] << (ym-y1);
+ } else {
+ tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] >> (y1-ym);
+ }
+ }
+ }
+
+ for (iz=z1; iz<=z2; iz++) {
+ nx=0;
+ for (ix=x1; ix<=x2; ix++) {
+
+ //alter the cubedata on the new x and z location with the tmp data. use old y location and copy to the new location
+ cubeData[(zm+nz)*8 + xm+nx] = (cubeData[(zm+nz)*8 + xm+nx] & (~byteline(ym,ym+y2-y1))) | tmp_data[iz*8 + ix];
+ nx++;
+ }
+ nz++;
+ }
+}
+
+char LED_CUBE::byteline (int start, int end)
+{
+ char line=0;
+ int bitnr;
+
+ for (bitnr=0; bitnr<8; bitnr++) {
+ if (bitnr>=start && bitnr<=end) {
+ line |= (1<<bitnr);
+ }
+ }
+ return line;
+}
+
+// This function validates that we are drawing inside the cube.
+unsigned char LED_CUBE::inrange(int x, int y, int z)
+{
+ if (x >= 0 && x < 8 && y >= 0 && y < 8 && z >= 0 && z < 8) {
+ return 0x01;
+ } else {
+ // One of the coordinates was outside the cube.
+ return 0x00;
+ }
+}
+
+void LED_CUBE::argorder(int ix1, int ix2, int *ox1, int *ox2)
+{
+ if (ix1>ix2) {
+ int tmp;
+ tmp = ix1;
+ ix1= ix2;
+ ix2 = tmp;
+ }
+ *ox1 = ix1;
+ *ox2 = ix2;
+}
+
+double LED_CUBE::map(double in, double inMin, double inMax, double outMin, double outMax)
+{
+ double out;
+ out = (in-inMin)/(inMax-inMin)*(outMax-outMin) + outMin;
+ return out;
}
\ No newline at end of file
--- a/led_cube.h Sat Sep 08 22:14:10 2012 +0000
+++ b/led_cube.h Thu Nov 01 22:31:54 2012 +0000
@@ -1,46 +1,66 @@
-#ifndef __LED_CUBE_H
-#define __LED_CUBE_H
-
-#define VERSION 1.0
-
-#include <mbed.h>
-#include "pcf8574.h"
-#include "pcf8575.h"
-
-#define PI 3.14159
-#define Xd 8
-#define Yd 8
-#define Zd 8
-#define centre 3.5
-#define Vd Xd*Yd*Zd
-
-#define SB(x,n) (x|=(1<<n))
-#define CB(x,n) (x&=~(1<<n))
-#define TB(x,n) (x^=(1<<n))
-#define PB(x,n) do{SB(x,n);CB(x,n);}while(0)
-
-class LED_CUBE
-{
-public:
- LED_CUBE(I2C* _interface);
- ~LED_CUBE(void);
-
- void clear_cube(void);
- void setVoxel(unsigned char x, unsigned char y, unsigned char z);
- void clearVoxel(unsigned char x, unsigned char y, unsigned char z);
- unsigned char getVoxel(unsigned char x, unsigned char y, unsigned char z);
- void copyColumn(unsigned char x, unsigned char y, unsigned char col);
- void clearVoxels(void);
-
-private:
- PCF8574 row;
- PCF8575 colums_0_1;
- PCF8575 colums_2_3;
- PCF8575 colums_4_5;
- PCF8575 colums_6_7;
- unsigned char cubeData[64];
- Ticker duty;
- void UpdateRow(void);
-
-};
+#ifndef __LED_CUBE_H
+#define __LED_CUBE_H
+
+#define VERSION 1.0
+
+#include <mbed.h>
+#include "pcf8574.h"
+#include "pcf8575.h"
+
+#define AXIS_X 1
+#define AXIS_Y 2
+#define AXIS_Z 3
+#define PI 3.14159265
+#define center 3.5
+#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
+
+class LED_CUBE
+{
+public:
+ LED_CUBE(I2C* _interface);
+ ~LED_CUBE(void);
+
+ void clear_cube(void);
+ void setVoxel(unsigned char x, unsigned char y, unsigned char z);
+ void clearVoxel(unsigned char x, unsigned char y, unsigned char z);
+ unsigned char getVoxel(unsigned char x, unsigned char y, unsigned char z);
+ void copyColumn(unsigned char x, unsigned char y, unsigned char col);
+ void alterVoxel(unsigned char x, unsigned char y, unsigned char z, unsigned char state);
+ void flipVoxel(unsigned char x, unsigned char y, unsigned char z);
+ void setPlane_x (int x);
+ void clearPlane_x (int x);
+ void setPlane_y (int y);
+ void clearPlane_y (int y);
+ void setPlane_z (int z);
+ void clearPlane_z (int z);
+ void setPlane (char axis, unsigned char i);
+ void clearPlane (char axis, unsigned char i);
+ void setSlope_XY(int x1, int y1, int x2, int y2);
+ void setSlope_XZ(int x1, int z1, int x2, int z2);
+ void setSlope_YZ(int y1, int z1, int y2, int z2);
+ void clearVoxels(void);
+ void fill (unsigned char pattern);
+ void box_filled(int x1, int y1, int z1, int x2, int y2, int z2);
+ void box_walls(int x1, int y1, int z1, int x2, int y2, int z2);
+ void box_wireframe(int x1, int y1, int z1, int x2, int y2, int z2);
+ void line(int x1, int y1, int z1, int x2, int y2, int z2);
+ void circle(int xr, int yr, int zr, int d ,char axis);
+ void CopyBlock(int x1, int y1, int z1, int x2, int y2, int z2, int xc, int yc, int zc);
+ void MoveBlock(int x1, int y1, int z1, int x2, int y2, int z2, int xm, int ym, int zm);
+ void RotateBlock(int x1, int y1, int height, char axis, char dir);
+
+private:
+ PCF8574 row;
+ PCF8575 colums_0_1;
+ PCF8575 colums_2_3;
+ PCF8575 colums_4_5;
+ PCF8575 colums_6_7;
+ unsigned char cubeData[64];
+ Ticker duty;
+ void UpdateRow(void);
+ char byteline (int start, int end);
+ unsigned char inrange(int x, int y, int z);
+ void argorder(int ix1, int ix2, int *ox1, int *ox2);
+ double map(double in, double inMin, double inMax, double outMin, double outMax);
+ };
#endif
\ No newline at end of file