8x8x8 Led Cube driven by 4x PCF8575 for the columns and 1x PCF8574 for the layers
led_cube.cpp@1:e08a4d27f534, 2012-11-01 (annotated)
- Committer:
- Bas
- Date:
- Thu Nov 01 22:31:54 2012 +0000
- Revision:
- 1:e08a4d27f534
- Parent:
- 0:920c5ed65a45
Added several simple graphic functions helping to create animations
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Bas | 0:920c5ed65a45 | 1 | #include "led_cube.h" |
Bas | 0:920c5ed65a45 | 2 | |
Bas | 0:920c5ed65a45 | 3 | LED_CUBE::LED_CUBE(I2C* _interface) |
Bas | 0:920c5ed65a45 | 4 | : row(_interface, 0x07,PCF8574_TYPE), |
Bas | 0:920c5ed65a45 | 5 | colums_0_1(_interface, 0x00), |
Bas | 0:920c5ed65a45 | 6 | colums_2_3(_interface, 0x01), |
Bas | 0:920c5ed65a45 | 7 | colums_4_5(_interface, 0x02), |
Bas | 0:920c5ed65a45 | 8 | colums_6_7(_interface, 0x03) |
Bas | 0:920c5ed65a45 | 9 | { |
Bas | 0:920c5ed65a45 | 10 | _interface->frequency(400000); //400KHz |
Bas | 0:920c5ed65a45 | 11 | duty.attach_us(this, &LED_CUBE::UpdateRow,1250);// each row = 1/8 duty |
Bas | 0:920c5ed65a45 | 12 | } |
Bas | 0:920c5ed65a45 | 13 | |
Bas | 0:920c5ed65a45 | 14 | LED_CUBE::~LED_CUBE() {} |
Bas | 0:920c5ed65a45 | 15 | |
Bas | 0:920c5ed65a45 | 16 | void LED_CUBE::UpdateRow() |
Bas | 0:920c5ed65a45 | 17 | { |
Bas | 0:920c5ed65a45 | 18 | static int rownr = 0; |
Bas | 0:920c5ed65a45 | 19 | |
Bas | 0:920c5ed65a45 | 20 | if (rownr < 0 || rownr > 7) { |
Bas | 0:920c5ed65a45 | 21 | rownr = 0; |
Bas | 0:920c5ed65a45 | 22 | } |
Bas | 0:920c5ed65a45 | 23 | row.WriteByte(0xFF); // switch off all rows before updating next colums to avoid ghost data from previous colums |
Bas | 0:920c5ed65a45 | 24 | colums_0_1.WriteBytes(~cubeData[8 * rownr + 0],~cubeData[8 * rownr + 2]); //update the columns |
Bas | 0:920c5ed65a45 | 25 | colums_2_3.WriteBytes(~cubeData[8 * rownr + 1],~cubeData[8 * rownr + 3]); |
Bas | 0:920c5ed65a45 | 26 | colums_4_5.WriteBytes(~cubeData[8 * rownr + 6],~cubeData[8 * rownr + 4]); |
Bas | 0:920c5ed65a45 | 27 | colums_6_7.WriteBytes(~cubeData[8 * rownr + 7],~cubeData[8 * rownr + 5]); |
Bas | 0:920c5ed65a45 | 28 | row.WriteByte(~(1<<rownr)); // now display the row |
Bas | 0:920c5ed65a45 | 29 | rownr++; |
Bas | 0:920c5ed65a45 | 30 | } |
Bas | 0:920c5ed65a45 | 31 | |
Bas | 0:920c5ed65a45 | 32 | //clear everything |
Bas | 1:e08a4d27f534 | 33 | void LED_CUBE::clear_cube(void) |
Bas | 1:e08a4d27f534 | 34 | { |
Bas | 0:920c5ed65a45 | 35 | row.WriteByte(0xFF); |
Bas | 0:920c5ed65a45 | 36 | colums_0_1.WriteBytes(0xFF,0xFF); |
Bas | 0:920c5ed65a45 | 37 | colums_2_3.WriteBytes(0xFF,0xFF); |
Bas | 0:920c5ed65a45 | 38 | colums_4_5.WriteBytes(0xFF,0xFF); |
Bas | 0:920c5ed65a45 | 39 | colums_6_7.WriteBytes(0xFF,0xFF); |
Bas | 0:920c5ed65a45 | 40 | clearVoxels(); |
Bas | 0:920c5ed65a45 | 41 | } |
Bas | 0:920c5ed65a45 | 42 | |
Bas | 1:e08a4d27f534 | 43 | //set a voxel in the cube array |
Bas | 1:e08a4d27f534 | 44 | void LED_CUBE::setVoxel(unsigned char x, unsigned char y, unsigned char z) |
Bas | 1:e08a4d27f534 | 45 | { |
Bas | 1:e08a4d27f534 | 46 | if (inrange(x, y, z)) |
Bas | 1:e08a4d27f534 | 47 | cubeData[z*8 + x] |= 0x01<<y; |
Bas | 0:920c5ed65a45 | 48 | } |
Bas | 0:920c5ed65a45 | 49 | |
Bas | 1:e08a4d27f534 | 50 | //clear a single voxel in the cube array |
Bas | 1:e08a4d27f534 | 51 | void LED_CUBE::clearVoxel(unsigned char x, unsigned char y, unsigned char z) |
Bas | 1:e08a4d27f534 | 52 | { |
Bas | 1:e08a4d27f534 | 53 | if (inrange(x, y, z)) |
Bas | 1:e08a4d27f534 | 54 | cubeData[z*8 + x] &= ~(0x01<<y); |
Bas | 0:920c5ed65a45 | 55 | } |
Bas | 0:920c5ed65a45 | 56 | |
Bas | 1:e08a4d27f534 | 57 | //return the value of a single voxel in the cube array |
Bas | 1:e08a4d27f534 | 58 | unsigned char LED_CUBE::getVoxel(unsigned char x, unsigned char y, unsigned char z) |
Bas | 1:e08a4d27f534 | 59 | { |
Bas | 1:e08a4d27f534 | 60 | if (inrange(x, y, z)) { |
Bas | 1:e08a4d27f534 | 61 | if(cubeData[z*8 + x] & 0x01<<y) { |
Bas | 1:e08a4d27f534 | 62 | return 1; |
Bas | 1:e08a4d27f534 | 63 | } else { |
Bas | 1:e08a4d27f534 | 64 | return 0; |
Bas | 1:e08a4d27f534 | 65 | } |
Bas | 1:e08a4d27f534 | 66 | } else { |
Bas | 0:920c5ed65a45 | 67 | return 0; |
Bas | 0:920c5ed65a45 | 68 | } |
Bas | 0:920c5ed65a45 | 69 | } |
Bas | 0:920c5ed65a45 | 70 | |
Bas | 1:e08a4d27f534 | 71 | void LED_CUBE::copyColumn(unsigned char x, unsigned char y, unsigned char col) |
Bas | 1:e08a4d27f534 | 72 | { |
Bas | 1:e08a4d27f534 | 73 | for(unsigned char z = 0; z < 8; z++) { |
Bas | 1:e08a4d27f534 | 74 | if(col&(0x01<<z)) { |
Bas | 0:920c5ed65a45 | 75 | setVoxel(x, y, z); |
Bas | 1:e08a4d27f534 | 76 | } else { |
Bas | 0:920c5ed65a45 | 77 | clearVoxel(x, y, z); |
Bas | 0:920c5ed65a45 | 78 | } |
Bas | 0:920c5ed65a45 | 79 | } |
Bas | 0:920c5ed65a45 | 80 | } |
Bas | 1:e08a4d27f534 | 81 | |
Bas | 1:e08a4d27f534 | 82 | // In some effect we want to just take bool and write it to a voxel |
Bas | 1:e08a4d27f534 | 83 | // this function calls the apropriate voxel manipulation function. |
Bas | 1:e08a4d27f534 | 84 | void LED_CUBE::alterVoxel(unsigned char x, unsigned char y, unsigned char z, unsigned char state) |
Bas | 1:e08a4d27f534 | 85 | { |
Bas | 1:e08a4d27f534 | 86 | if (state == 1) { |
Bas | 1:e08a4d27f534 | 87 | setVoxel(x,y,z); |
Bas | 1:e08a4d27f534 | 88 | } else { |
Bas | 1:e08a4d27f534 | 89 | clearVoxel(x,y,z); |
Bas | 1:e08a4d27f534 | 90 | } |
Bas | 1:e08a4d27f534 | 91 | } |
Bas | 1:e08a4d27f534 | 92 | |
Bas | 1:e08a4d27f534 | 93 | // Flip the state of a voxel. |
Bas | 1:e08a4d27f534 | 94 | // If the voxel is 1, its turned into a 0, and vice versa. |
Bas | 1:e08a4d27f534 | 95 | void LED_CUBE::flipVoxel(unsigned char x, unsigned char y, unsigned char z) |
Bas | 1:e08a4d27f534 | 96 | { |
Bas | 1:e08a4d27f534 | 97 | if (inrange(x, y, z)) |
Bas | 1:e08a4d27f534 | 98 | cubeData[z*8 + x] ^= (1 << y); |
Bas | 1:e08a4d27f534 | 99 | } |
Bas | 1:e08a4d27f534 | 100 | |
Bas | 1:e08a4d27f534 | 101 | void LED_CUBE::setPlane_x (int x) |
Bas | 1:e08a4d27f534 | 102 | { |
Bas | 1:e08a4d27f534 | 103 | int z; |
Bas | 1:e08a4d27f534 | 104 | |
Bas | 1:e08a4d27f534 | 105 | if (x>=0 && x<8) { |
Bas | 1:e08a4d27f534 | 106 | for (z=0; z<8; z++) |
Bas | 1:e08a4d27f534 | 107 | cubeData[z*8 + x] = 0xFF; |
Bas | 1:e08a4d27f534 | 108 | } |
Bas | 1:e08a4d27f534 | 109 | } |
Bas | 1:e08a4d27f534 | 110 | |
Bas | 1:e08a4d27f534 | 111 | void LED_CUBE::clearPlane_x (int x) |
Bas | 1:e08a4d27f534 | 112 | { |
Bas | 1:e08a4d27f534 | 113 | int z; |
Bas | 1:e08a4d27f534 | 114 | |
Bas | 1:e08a4d27f534 | 115 | if (x>=0 && x<8) { |
Bas | 1:e08a4d27f534 | 116 | for (z=0; z<8; z++) |
Bas | 1:e08a4d27f534 | 117 | cubeData[z*8 + x] = 0x00; |
Bas | 1:e08a4d27f534 | 118 | } |
Bas | 1:e08a4d27f534 | 119 | } |
Bas | 1:e08a4d27f534 | 120 | |
Bas | 1:e08a4d27f534 | 121 | void LED_CUBE::setPlane_y (int y) |
Bas | 1:e08a4d27f534 | 122 | { |
Bas | 1:e08a4d27f534 | 123 | int z; |
Bas | 1:e08a4d27f534 | 124 | int x; |
Bas | 1:e08a4d27f534 | 125 | |
Bas | 1:e08a4d27f534 | 126 | if (y>=0 && y<8) { |
Bas | 1:e08a4d27f534 | 127 | for (z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 128 | for (x=0; x<8; x++) { |
Bas | 1:e08a4d27f534 | 129 | cubeData[z*8 + x] |= (1 << y); |
Bas | 1:e08a4d27f534 | 130 | } |
Bas | 1:e08a4d27f534 | 131 | } |
Bas | 1:e08a4d27f534 | 132 | } |
Bas | 1:e08a4d27f534 | 133 | } |
Bas | 1:e08a4d27f534 | 134 | |
Bas | 1:e08a4d27f534 | 135 | void LED_CUBE::clearPlane_y (int y) |
Bas | 1:e08a4d27f534 | 136 | { |
Bas | 1:e08a4d27f534 | 137 | int z; |
Bas | 1:e08a4d27f534 | 138 | int x; |
Bas | 1:e08a4d27f534 | 139 | |
Bas | 1:e08a4d27f534 | 140 | if (y>=0 && y<8) { |
Bas | 1:e08a4d27f534 | 141 | for (z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 142 | for (x=0; x<8; x++) { |
Bas | 1:e08a4d27f534 | 143 | cubeData[z*8 + x] &= ~(1 << y); |
Bas | 1:e08a4d27f534 | 144 | } |
Bas | 1:e08a4d27f534 | 145 | } |
Bas | 1:e08a4d27f534 | 146 | } |
Bas | 1:e08a4d27f534 | 147 | } |
Bas | 1:e08a4d27f534 | 148 | // Sets all voxels along a X/Y plane at a given point |
Bas | 1:e08a4d27f534 | 149 | // on axis Z |
Bas | 1:e08a4d27f534 | 150 | void LED_CUBE::setPlane_z (int z) |
Bas | 1:e08a4d27f534 | 151 | { |
Bas | 1:e08a4d27f534 | 152 | int i; |
Bas | 1:e08a4d27f534 | 153 | |
Bas | 1:e08a4d27f534 | 154 | if (z>=0 && z<8) { |
Bas | 1:e08a4d27f534 | 155 | for (i=0; i<8; i++) |
Bas | 1:e08a4d27f534 | 156 | cubeData[z*8 + i] = 0xFF; |
Bas | 1:e08a4d27f534 | 157 | } |
Bas | 1:e08a4d27f534 | 158 | } |
Bas | 1:e08a4d27f534 | 159 | |
Bas | 1:e08a4d27f534 | 160 | // Clears voxels in the same manner as above |
Bas | 1:e08a4d27f534 | 161 | void LED_CUBE::clearPlane_z (int z) |
Bas | 1:e08a4d27f534 | 162 | { |
Bas | 1:e08a4d27f534 | 163 | int i; |
Bas | 1:e08a4d27f534 | 164 | |
Bas | 1:e08a4d27f534 | 165 | if (z>=0 && z<8) { |
Bas | 1:e08a4d27f534 | 166 | for (i=0; i<8; i++) |
Bas | 1:e08a4d27f534 | 167 | cubeData[z*8 + i] = 0x00; |
Bas | 1:e08a4d27f534 | 168 | } |
Bas | 1:e08a4d27f534 | 169 | } |
Bas | 1:e08a4d27f534 | 170 | |
Bas | 1:e08a4d27f534 | 171 | void LED_CUBE::setPlane (char axis, unsigned char i) |
Bas | 1:e08a4d27f534 | 172 | { |
Bas | 1:e08a4d27f534 | 173 | switch (axis) { |
Bas | 1:e08a4d27f534 | 174 | case AXIS_X: |
Bas | 1:e08a4d27f534 | 175 | setPlane_x(i); |
Bas | 1:e08a4d27f534 | 176 | break; |
Bas | 1:e08a4d27f534 | 177 | case AXIS_Y: |
Bas | 1:e08a4d27f534 | 178 | setPlane_y(i); |
Bas | 1:e08a4d27f534 | 179 | break; |
Bas | 1:e08a4d27f534 | 180 | case AXIS_Z: |
Bas | 1:e08a4d27f534 | 181 | setPlane_z(i); |
Bas | 1:e08a4d27f534 | 182 | break; |
Bas | 1:e08a4d27f534 | 183 | } |
Bas | 1:e08a4d27f534 | 184 | } |
Bas | 1:e08a4d27f534 | 185 | |
Bas | 1:e08a4d27f534 | 186 | void LED_CUBE::clearPlane (char axis, unsigned char i) |
Bas | 1:e08a4d27f534 | 187 | { |
Bas | 1:e08a4d27f534 | 188 | switch (axis) { |
Bas | 1:e08a4d27f534 | 189 | case AXIS_X: |
Bas | 1:e08a4d27f534 | 190 | clearPlane_x(i); |
Bas | 1:e08a4d27f534 | 191 | break; |
Bas | 1:e08a4d27f534 | 192 | case AXIS_Y: |
Bas | 1:e08a4d27f534 | 193 | clearPlane_y(i); |
Bas | 1:e08a4d27f534 | 194 | break; |
Bas | 1:e08a4d27f534 | 195 | case AXIS_Z: |
Bas | 1:e08a4d27f534 | 196 | clearPlane_z(i); |
Bas | 1:e08a4d27f534 | 197 | break; |
Bas | 1:e08a4d27f534 | 198 | } |
Bas | 1:e08a4d27f534 | 199 | } |
Bas | 1:e08a4d27f534 | 200 | void LED_CUBE::setSlope_XY(int x1, int y1, int x2, int y2) |
Bas | 1:e08a4d27f534 | 201 | { |
Bas | 1:e08a4d27f534 | 202 | float slope, offset; |
Bas | 1:e08a4d27f534 | 203 | int x,y,z; |
Bas | 1:e08a4d27f534 | 204 | |
Bas | 1:e08a4d27f534 | 205 | if (x1>x2) { |
Bas | 1:e08a4d27f534 | 206 | int tmp; |
Bas | 1:e08a4d27f534 | 207 | tmp = x2; |
Bas | 1:e08a4d27f534 | 208 | x2 = x1; |
Bas | 1:e08a4d27f534 | 209 | x1 = tmp; |
Bas | 1:e08a4d27f534 | 210 | tmp = y2; |
Bas | 1:e08a4d27f534 | 211 | y2 = y1; |
Bas | 1:e08a4d27f534 | 212 | y1 = tmp; |
Bas | 1:e08a4d27f534 | 213 | } |
Bas | 1:e08a4d27f534 | 214 | |
Bas | 1:e08a4d27f534 | 215 | slope=float(y2-y1)/float(x2-x1); |
Bas | 1:e08a4d27f534 | 216 | offset=-x1*slope +y1; |
Bas | 1:e08a4d27f534 | 217 | |
Bas | 1:e08a4d27f534 | 218 | if ((x2-x1)>=7) { |
Bas | 1:e08a4d27f534 | 219 | for(x=0; x<8; x++) { |
Bas | 1:e08a4d27f534 | 220 | y = floor((x*slope + offset)+0.5); |
Bas | 1:e08a4d27f534 | 221 | for(z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 222 | setVoxel(x,y,z); |
Bas | 1:e08a4d27f534 | 223 | } |
Bas | 1:e08a4d27f534 | 224 | } |
Bas | 1:e08a4d27f534 | 225 | } else if(x1==x2) { |
Bas | 1:e08a4d27f534 | 226 | for(y=0; y<8; y++) { |
Bas | 1:e08a4d27f534 | 227 | for(z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 228 | setVoxel(x1,y,z); |
Bas | 1:e08a4d27f534 | 229 | } |
Bas | 1:e08a4d27f534 | 230 | } |
Bas | 1:e08a4d27f534 | 231 | } else { |
Bas | 1:e08a4d27f534 | 232 | for(y=0; y<8; y++) { |
Bas | 1:e08a4d27f534 | 233 | x = floor(((y-offset)/slope)+0.5); |
Bas | 1:e08a4d27f534 | 234 | for(z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 235 | setVoxel(x,y,z); |
Bas | 1:e08a4d27f534 | 236 | } |
Bas | 1:e08a4d27f534 | 237 | |
Bas | 1:e08a4d27f534 | 238 | } |
Bas | 1:e08a4d27f534 | 239 | } |
Bas | 1:e08a4d27f534 | 240 | } |
Bas | 1:e08a4d27f534 | 241 | |
Bas | 1:e08a4d27f534 | 242 | void LED_CUBE::setSlope_XZ(int x1, int z1, int x2, int z2) |
Bas | 1:e08a4d27f534 | 243 | { |
Bas | 1:e08a4d27f534 | 244 | float slope, offset; |
Bas | 1:e08a4d27f534 | 245 | int x,z; |
Bas | 1:e08a4d27f534 | 246 | |
Bas | 1:e08a4d27f534 | 247 | if (x1>x2) { |
Bas | 1:e08a4d27f534 | 248 | int tmp; |
Bas | 1:e08a4d27f534 | 249 | tmp = x2; |
Bas | 1:e08a4d27f534 | 250 | x2 = x1; |
Bas | 1:e08a4d27f534 | 251 | x1 = tmp; |
Bas | 1:e08a4d27f534 | 252 | tmp = z2; |
Bas | 1:e08a4d27f534 | 253 | z2 = z1; |
Bas | 1:e08a4d27f534 | 254 | z1 = tmp; |
Bas | 1:e08a4d27f534 | 255 | } |
Bas | 1:e08a4d27f534 | 256 | |
Bas | 1:e08a4d27f534 | 257 | slope=float(z2-z1)/float(x2-x1); |
Bas | 1:e08a4d27f534 | 258 | offset=-x1*slope +z1; |
Bas | 1:e08a4d27f534 | 259 | |
Bas | 1:e08a4d27f534 | 260 | if ((x2-x1)>=7) { |
Bas | 1:e08a4d27f534 | 261 | for(x=0; x<8; x++) { |
Bas | 1:e08a4d27f534 | 262 | z = floor((x*slope + offset)+0.5); |
Bas | 1:e08a4d27f534 | 263 | cubeData[z*8 + x] = 0xFF; |
Bas | 1:e08a4d27f534 | 264 | |
Bas | 1:e08a4d27f534 | 265 | } |
Bas | 1:e08a4d27f534 | 266 | } else if(x1==x2) { |
Bas | 1:e08a4d27f534 | 267 | for(z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 268 | cubeData[z*8 + x1] = 0xFF; |
Bas | 1:e08a4d27f534 | 269 | |
Bas | 1:e08a4d27f534 | 270 | } |
Bas | 1:e08a4d27f534 | 271 | } else { |
Bas | 1:e08a4d27f534 | 272 | for(z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 273 | x = floor(((z-offset)/slope)+0.5); |
Bas | 1:e08a4d27f534 | 274 | cubeData[z*8 + x] = 0xFF; |
Bas | 1:e08a4d27f534 | 275 | |
Bas | 1:e08a4d27f534 | 276 | } |
Bas | 1:e08a4d27f534 | 277 | |
Bas | 1:e08a4d27f534 | 278 | } |
Bas | 1:e08a4d27f534 | 279 | } |
Bas | 1:e08a4d27f534 | 280 | |
Bas | 1:e08a4d27f534 | 281 | |
Bas | 1:e08a4d27f534 | 282 | void LED_CUBE::setSlope_YZ(int y1, int z1, int y2, int z2) |
Bas | 1:e08a4d27f534 | 283 | { |
Bas | 1:e08a4d27f534 | 284 | float slope, offset; |
Bas | 1:e08a4d27f534 | 285 | int x,y,z; |
Bas | 1:e08a4d27f534 | 286 | |
Bas | 1:e08a4d27f534 | 287 | if (y1>y2) { |
Bas | 1:e08a4d27f534 | 288 | int tmp; |
Bas | 1:e08a4d27f534 | 289 | tmp = y2; |
Bas | 1:e08a4d27f534 | 290 | y2 = y1; |
Bas | 1:e08a4d27f534 | 291 | y1 = tmp; |
Bas | 1:e08a4d27f534 | 292 | tmp = z2; |
Bas | 1:e08a4d27f534 | 293 | z2 = z1; |
Bas | 1:e08a4d27f534 | 294 | z1 = tmp; |
Bas | 1:e08a4d27f534 | 295 | } |
Bas | 1:e08a4d27f534 | 296 | |
Bas | 1:e08a4d27f534 | 297 | slope=float(z2-z1)/float(y2-y1); |
Bas | 1:e08a4d27f534 | 298 | offset=-y1*slope +z1; |
Bas | 1:e08a4d27f534 | 299 | |
Bas | 1:e08a4d27f534 | 300 | if ((y2-y1)>=7) { |
Bas | 1:e08a4d27f534 | 301 | for(y=0; y<8; y++) { |
Bas | 1:e08a4d27f534 | 302 | z = floor((y*slope + offset)+0.5); |
Bas | 1:e08a4d27f534 | 303 | for(x=0; x<8; x++) { |
Bas | 1:e08a4d27f534 | 304 | setVoxel(x,y,z); |
Bas | 1:e08a4d27f534 | 305 | } |
Bas | 1:e08a4d27f534 | 306 | } |
Bas | 1:e08a4d27f534 | 307 | } else if(y1==y2) { |
Bas | 1:e08a4d27f534 | 308 | for(z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 309 | for(x=0; x<8; x++) { |
Bas | 1:e08a4d27f534 | 310 | setVoxel(x,y1,z); |
Bas | 1:e08a4d27f534 | 311 | } |
Bas | 1:e08a4d27f534 | 312 | } |
Bas | 1:e08a4d27f534 | 313 | } else { |
Bas | 1:e08a4d27f534 | 314 | for(z=0; z<8; z++) { |
Bas | 1:e08a4d27f534 | 315 | y = floor(((z-offset)/slope)+0.5); |
Bas | 1:e08a4d27f534 | 316 | for(x=0; x<8; x++) { |
Bas | 1:e08a4d27f534 | 317 | setVoxel(x,y,z); |
Bas | 1:e08a4d27f534 | 318 | } |
Bas | 1:e08a4d27f534 | 319 | } |
Bas | 1:e08a4d27f534 | 320 | |
Bas | 1:e08a4d27f534 | 321 | } |
Bas | 1:e08a4d27f534 | 322 | } |
Bas | 1:e08a4d27f534 | 323 | |
Bas | 0:920c5ed65a45 | 324 | //clear all the voxels in the array |
Bas | 1:e08a4d27f534 | 325 | void LED_CUBE::clearVoxels(void) |
Bas | 1:e08a4d27f534 | 326 | { |
Bas | 0:920c5ed65a45 | 327 | memset(cubeData, 0, 64*sizeof(unsigned char)); |
Bas | 1:e08a4d27f534 | 328 | } |
Bas | 1:e08a4d27f534 | 329 | |
Bas | 1:e08a4d27f534 | 330 | // Fill a value into all 64 byts of the cube buffer |
Bas | 1:e08a4d27f534 | 331 | // Mostly used for clearing. fill(0xr0) |
Bas | 1:e08a4d27f534 | 332 | // or setting all on. fill(0xff) |
Bas | 1:e08a4d27f534 | 333 | void LED_CUBE::fill (unsigned char pattern) |
Bas | 1:e08a4d27f534 | 334 | { |
Bas | 1:e08a4d27f534 | 335 | memset(cubeData, pattern, 64*sizeof(unsigned char)); |
Bas | 1:e08a4d27f534 | 336 | } |
Bas | 1:e08a4d27f534 | 337 | |
Bas | 1:e08a4d27f534 | 338 | // Draw a box with all walls drawn and all voxels inside set |
Bas | 1:e08a4d27f534 | 339 | void LED_CUBE::box_filled(int x1, int y1, int z1, int x2, int y2, int z2) |
Bas | 1:e08a4d27f534 | 340 | { |
Bas | 1:e08a4d27f534 | 341 | int ix; |
Bas | 1:e08a4d27f534 | 342 | int iz; |
Bas | 1:e08a4d27f534 | 343 | |
Bas | 1:e08a4d27f534 | 344 | argorder(x1, x2, &x1, &x2); |
Bas | 1:e08a4d27f534 | 345 | argorder(y1, y2, &y1, &y2); |
Bas | 1:e08a4d27f534 | 346 | argorder(z1, z2, &z1, &z2); |
Bas | 1:e08a4d27f534 | 347 | for (iz=z1; iz<=z2; iz++) { |
Bas | 1:e08a4d27f534 | 348 | for (ix=x1; ix<=x2; ix++) { |
Bas | 1:e08a4d27f534 | 349 | cubeData[iz*8 + ix] |= byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 350 | } |
Bas | 1:e08a4d27f534 | 351 | } |
Bas | 1:e08a4d27f534 | 352 | } |
Bas | 1:e08a4d27f534 | 353 | |
Bas | 1:e08a4d27f534 | 354 | // Draw a hollow box with side walls. |
Bas | 1:e08a4d27f534 | 355 | void LED_CUBE::box_walls(int x1, int y1, int z1, int x2, int y2, int z2) |
Bas | 1:e08a4d27f534 | 356 | { |
Bas | 1:e08a4d27f534 | 357 | int ix; |
Bas | 1:e08a4d27f534 | 358 | int iz; |
Bas | 1:e08a4d27f534 | 359 | |
Bas | 1:e08a4d27f534 | 360 | argorder(x1, x2, &x1, &x2); |
Bas | 1:e08a4d27f534 | 361 | argorder(y1, y2, &y1, &y2); |
Bas | 1:e08a4d27f534 | 362 | argorder(z1, z2, &z1, &z2); |
Bas | 1:e08a4d27f534 | 363 | for (iz=z1; iz<=z2; iz++) { |
Bas | 1:e08a4d27f534 | 364 | for (ix=x1; ix<=x2; ix++) { |
Bas | 1:e08a4d27f534 | 365 | if (ix == x1 || ix == x2 || iz == z1 || iz == z2) { |
Bas | 1:e08a4d27f534 | 366 | cubeData[iz*8 + ix] = byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 367 | } else { |
Bas | 1:e08a4d27f534 | 368 | cubeData[iz*8 + ix] |= ((0x01 << y1) | (0x01 << y2)); |
Bas | 1:e08a4d27f534 | 369 | } |
Bas | 1:e08a4d27f534 | 370 | } |
Bas | 1:e08a4d27f534 | 371 | } |
Bas | 1:e08a4d27f534 | 372 | } |
Bas | 1:e08a4d27f534 | 373 | |
Bas | 1:e08a4d27f534 | 374 | // Draw a wireframe box. This only draws the corners and edges, |
Bas | 1:e08a4d27f534 | 375 | // no walls. |
Bas | 1:e08a4d27f534 | 376 | void LED_CUBE::box_wireframe(int x1, int y1, int z1, int x2, int y2, int z2) |
Bas | 1:e08a4d27f534 | 377 | { |
Bas | 1:e08a4d27f534 | 378 | int ix; |
Bas | 1:e08a4d27f534 | 379 | int iz; |
Bas | 1:e08a4d27f534 | 380 | |
Bas | 1:e08a4d27f534 | 381 | argorder(x1, x2, &x1, &x2); |
Bas | 1:e08a4d27f534 | 382 | argorder(y1, y2, &y1, &y2); |
Bas | 1:e08a4d27f534 | 383 | argorder(z1, z2, &z1, &z2); |
Bas | 1:e08a4d27f534 | 384 | // Lines along Y axis |
Bas | 1:e08a4d27f534 | 385 | cubeData[z1*8 + x1] |= byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 386 | cubeData[z1*8 + x2] |= byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 387 | cubeData[z2*8 + x1] |= byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 388 | cubeData[z2*8 + x2] |= byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 389 | // Lines along X axis |
Bas | 1:e08a4d27f534 | 390 | for (ix=x1; ix<=x2; ix++) { |
Bas | 1:e08a4d27f534 | 391 | setVoxel(ix,y1,z1); |
Bas | 1:e08a4d27f534 | 392 | setVoxel(ix,y1,z2); |
Bas | 1:e08a4d27f534 | 393 | setVoxel(ix,y2,z1); |
Bas | 1:e08a4d27f534 | 394 | setVoxel(ix,y2,z2); |
Bas | 1:e08a4d27f534 | 395 | } |
Bas | 1:e08a4d27f534 | 396 | // Lines along Z axis |
Bas | 1:e08a4d27f534 | 397 | for (iz=z1; iz<=z2; iz++) { |
Bas | 1:e08a4d27f534 | 398 | setVoxel(x1,y1,iz); |
Bas | 1:e08a4d27f534 | 399 | setVoxel(x1,y2,iz); |
Bas | 1:e08a4d27f534 | 400 | setVoxel(x2,y1,iz); |
Bas | 1:e08a4d27f534 | 401 | setVoxel(x2,y2,iz); |
Bas | 1:e08a4d27f534 | 402 | } |
Bas | 1:e08a4d27f534 | 403 | } |
Bas | 1:e08a4d27f534 | 404 | |
Bas | 1:e08a4d27f534 | 405 | // Draw a line between any coordinates in 3d space. |
Bas | 1:e08a4d27f534 | 406 | // Uses integer values for input, so dont expect smooth animations. |
Bas | 1:e08a4d27f534 | 407 | void LED_CUBE::line(int x1, int y1, int z1, int x2, int y2, int z2) |
Bas | 1:e08a4d27f534 | 408 | { |
Bas | 1:e08a4d27f534 | 409 | float xy; |
Bas | 1:e08a4d27f534 | 410 | // how many voxels do we move on the y axis for each step on the x axis |
Bas | 1:e08a4d27f534 | 411 | float xz; |
Bas | 1:e08a4d27f534 | 412 | // how many voxels do we move on the y axis for each step on the x axis |
Bas | 1:e08a4d27f534 | 413 | unsigned char x,y,z; |
Bas | 1:e08a4d27f534 | 414 | // We always want to draw the line from x=0 to x=7. |
Bas | 1:e08a4d27f534 | 415 | // If x1 is bigget than x2, we need to flip all the values. |
Bas | 1:e08a4d27f534 | 416 | if (x1>x2) { |
Bas | 1:e08a4d27f534 | 417 | int tmp; |
Bas | 1:e08a4d27f534 | 418 | tmp = x2; |
Bas | 1:e08a4d27f534 | 419 | x2 = x1; |
Bas | 1:e08a4d27f534 | 420 | x1 = tmp; |
Bas | 1:e08a4d27f534 | 421 | tmp = y2; |
Bas | 1:e08a4d27f534 | 422 | y2 = y1; |
Bas | 1:e08a4d27f534 | 423 | y1 = tmp; |
Bas | 1:e08a4d27f534 | 424 | tmp = z2; |
Bas | 1:e08a4d27f534 | 425 | z2 = z1; |
Bas | 1:e08a4d27f534 | 426 | z1 = tmp; |
Bas | 1:e08a4d27f534 | 427 | } |
Bas | 1:e08a4d27f534 | 428 | if (y1>y2) { |
Bas | 1:e08a4d27f534 | 429 | xy = (float)(y1-y2)/(float)(x2-x1); |
Bas | 1:e08a4d27f534 | 430 | } else { |
Bas | 1:e08a4d27f534 | 431 | xy = (float)(y2-y1)/(float)(x2-x1); |
Bas | 1:e08a4d27f534 | 432 | } |
Bas | 1:e08a4d27f534 | 433 | if (z1>z2) { |
Bas | 1:e08a4d27f534 | 434 | xz = (float)(z1-z2)/(float)(x2-x1); |
Bas | 1:e08a4d27f534 | 435 | } else { |
Bas | 1:e08a4d27f534 | 436 | xz = (float)(z2-z1)/(float)(x2-x1); |
Bas | 1:e08a4d27f534 | 437 | } |
Bas | 1:e08a4d27f534 | 438 | // For each step of x, y increments by: |
Bas | 1:e08a4d27f534 | 439 | for (x = x1; x<=x2; x++) { |
Bas | 1:e08a4d27f534 | 440 | y = (xy*(x-x1))+y1; |
Bas | 1:e08a4d27f534 | 441 | z = (xz*(x-x1))+z1; |
Bas | 1:e08a4d27f534 | 442 | setVoxel(x,y,z); |
Bas | 1:e08a4d27f534 | 443 | } |
Bas | 1:e08a4d27f534 | 444 | } |
Bas | 1:e08a4d27f534 | 445 | void LED_CUBE::circle(int xr, int yr, int zr, int d ,char axis) |
Bas | 1:e08a4d27f534 | 446 | { |
Bas | 1:e08a4d27f534 | 447 | if (d%2) { // odd diameter, place center on half pixels |
Bas | 1:e08a4d27f534 | 448 | // later |
Bas | 1:e08a4d27f534 | 449 | } else { // use midpoint circle algorithm |
Bas | 1:e08a4d27f534 | 450 | int r = d/2; |
Bas | 1:e08a4d27f534 | 451 | int f = 1 - r; |
Bas | 1:e08a4d27f534 | 452 | int ddF_x = 1; |
Bas | 1:e08a4d27f534 | 453 | int ddF_y = -2 * r; |
Bas | 1:e08a4d27f534 | 454 | int x = 0; |
Bas | 1:e08a4d27f534 | 455 | int y = r; |
Bas | 1:e08a4d27f534 | 456 | |
Bas | 1:e08a4d27f534 | 457 | setVoxel(xr, yr+r, zr); |
Bas | 1:e08a4d27f534 | 458 | setVoxel(xr, yr-r, zr); |
Bas | 1:e08a4d27f534 | 459 | setVoxel(xr+r, yr, zr); |
Bas | 1:e08a4d27f534 | 460 | setVoxel(xr-r, yr, zr); |
Bas | 1:e08a4d27f534 | 461 | while (x<y) { |
Bas | 1:e08a4d27f534 | 462 | if (f >= 0) { |
Bas | 1:e08a4d27f534 | 463 | y--; |
Bas | 1:e08a4d27f534 | 464 | ddF_y += 2; |
Bas | 1:e08a4d27f534 | 465 | f += ddF_y; |
Bas | 1:e08a4d27f534 | 466 | } |
Bas | 1:e08a4d27f534 | 467 | x++; |
Bas | 1:e08a4d27f534 | 468 | ddF_x += 2; |
Bas | 1:e08a4d27f534 | 469 | f += ddF_x; |
Bas | 1:e08a4d27f534 | 470 | |
Bas | 1:e08a4d27f534 | 471 | setVoxel(xr + x, yr + y, zr); |
Bas | 1:e08a4d27f534 | 472 | setVoxel(xr - x, yr + y, zr); |
Bas | 1:e08a4d27f534 | 473 | setVoxel(xr + x, yr - y, zr); |
Bas | 1:e08a4d27f534 | 474 | setVoxel(xr - x, yr - y, zr); |
Bas | 1:e08a4d27f534 | 475 | setVoxel(xr + y, yr + x, zr); |
Bas | 1:e08a4d27f534 | 476 | setVoxel(xr - y, yr + x, zr); |
Bas | 1:e08a4d27f534 | 477 | setVoxel(xr + y, yr - x, zr); |
Bas | 1:e08a4d27f534 | 478 | setVoxel(xr - y, yr - x, zr); |
Bas | 1:e08a4d27f534 | 479 | } |
Bas | 1:e08a4d27f534 | 480 | } |
Bas | 1:e08a4d27f534 | 481 | } |
Bas | 1:e08a4d27f534 | 482 | |
Bas | 1:e08a4d27f534 | 483 | void LED_CUBE::CopyBlock(int x1, int y1, int z1, int x2, int y2, int z2, int xc, int yc, int zc) |
Bas | 1:e08a4d27f534 | 484 | { |
Bas | 1:e08a4d27f534 | 485 | int ix; |
Bas | 1:e08a4d27f534 | 486 | int iz; |
Bas | 1:e08a4d27f534 | 487 | int nx; |
Bas | 1:e08a4d27f534 | 488 | int nz=0; |
Bas | 1:e08a4d27f534 | 489 | unsigned char tmp_data[64]; |
Bas | 1:e08a4d27f534 | 490 | |
Bas | 1:e08a4d27f534 | 491 | argorder(x1, x2, &x1, &x2); |
Bas | 1:e08a4d27f534 | 492 | argorder(y1, y2, &y1, &y2); |
Bas | 1:e08a4d27f534 | 493 | argorder(z1, z2, &z1, &z2); |
Bas | 1:e08a4d27f534 | 494 | |
Bas | 1:e08a4d27f534 | 495 | for (iz=z1; iz<=z2; iz++) { |
Bas | 1:e08a4d27f534 | 496 | nx=0; |
Bas | 1:e08a4d27f534 | 497 | for (ix=x1; ix<=x2; ix++) { |
Bas | 1:e08a4d27f534 | 498 | //copy block data into tmp array and mask. |
Bas | 1:e08a4d27f534 | 499 | tmp_data[iz*8 + ix] = cubeData[iz*8 + ix] & byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 500 | //shift the tmp data to the new y location |
Bas | 1:e08a4d27f534 | 501 | if (yc >= y1) { |
Bas | 1:e08a4d27f534 | 502 | tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] << (yc-y1); |
Bas | 1:e08a4d27f534 | 503 | } else { |
Bas | 1:e08a4d27f534 | 504 | tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] >> (y1-yc); |
Bas | 1:e08a4d27f534 | 505 | } |
Bas | 1:e08a4d27f534 | 506 | //alter the cubedata on the new x and z location with the tmp data. use old y location and copy to the new location |
Bas | 1:e08a4d27f534 | 507 | cubeData[(zc+nz)*8 + xc+nx] = (cubeData[(zc+nz)*8 + xc+nx] & (~byteline(yc,yc+y2-y1))) | tmp_data[iz*8 + ix]; |
Bas | 1:e08a4d27f534 | 508 | nx++; |
Bas | 1:e08a4d27f534 | 509 | } |
Bas | 1:e08a4d27f534 | 510 | nz++; |
Bas | 1:e08a4d27f534 | 511 | } |
Bas | 1:e08a4d27f534 | 512 | } |
Bas | 1:e08a4d27f534 | 513 | |
Bas | 1:e08a4d27f534 | 514 | void LED_CUBE::MoveBlock(int x1, int y1, int z1, int x2, int y2, int z2, int xm, int ym, int zm) |
Bas | 1:e08a4d27f534 | 515 | { |
Bas | 1:e08a4d27f534 | 516 | int ix; |
Bas | 1:e08a4d27f534 | 517 | int iz; |
Bas | 1:e08a4d27f534 | 518 | int nx; |
Bas | 1:e08a4d27f534 | 519 | int nz=0; |
Bas | 1:e08a4d27f534 | 520 | unsigned char tmp_data[64]; |
Bas | 1:e08a4d27f534 | 521 | |
Bas | 1:e08a4d27f534 | 522 | argorder(x1, x2, &x1, &x2); |
Bas | 1:e08a4d27f534 | 523 | argorder(y1, y2, &y1, &y2); |
Bas | 1:e08a4d27f534 | 524 | argorder(z1, z2, &z1, &z2); |
Bas | 1:e08a4d27f534 | 525 | |
Bas | 1:e08a4d27f534 | 526 | for (iz=z1; iz<=z2; iz++) { |
Bas | 1:e08a4d27f534 | 527 | for (ix=x1; ix<=x2; ix++) { |
Bas | 1:e08a4d27f534 | 528 | //copy block data into tmp array and mask. |
Bas | 1:e08a4d27f534 | 529 | tmp_data[iz*8 + ix] = cubeData[iz*8 + ix] & byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 530 | //clear the original voxels |
Bas | 1:e08a4d27f534 | 531 | cubeData[iz*8 + ix] &= ~byteline(y1,y2); |
Bas | 1:e08a4d27f534 | 532 | //shift the tmp data to the new y location |
Bas | 1:e08a4d27f534 | 533 | if (ym >= y1) { |
Bas | 1:e08a4d27f534 | 534 | tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] << (ym-y1); |
Bas | 1:e08a4d27f534 | 535 | } else { |
Bas | 1:e08a4d27f534 | 536 | tmp_data[iz*8 + ix] = tmp_data[iz*8 + ix] >> (y1-ym); |
Bas | 1:e08a4d27f534 | 537 | } |
Bas | 1:e08a4d27f534 | 538 | } |
Bas | 1:e08a4d27f534 | 539 | } |
Bas | 1:e08a4d27f534 | 540 | |
Bas | 1:e08a4d27f534 | 541 | for (iz=z1; iz<=z2; iz++) { |
Bas | 1:e08a4d27f534 | 542 | nx=0; |
Bas | 1:e08a4d27f534 | 543 | for (ix=x1; ix<=x2; ix++) { |
Bas | 1:e08a4d27f534 | 544 | |
Bas | 1:e08a4d27f534 | 545 | //alter the cubedata on the new x and z location with the tmp data. use old y location and copy to the new location |
Bas | 1:e08a4d27f534 | 546 | cubeData[(zm+nz)*8 + xm+nx] = (cubeData[(zm+nz)*8 + xm+nx] & (~byteline(ym,ym+y2-y1))) | tmp_data[iz*8 + ix]; |
Bas | 1:e08a4d27f534 | 547 | nx++; |
Bas | 1:e08a4d27f534 | 548 | } |
Bas | 1:e08a4d27f534 | 549 | nz++; |
Bas | 1:e08a4d27f534 | 550 | } |
Bas | 1:e08a4d27f534 | 551 | } |
Bas | 1:e08a4d27f534 | 552 | |
Bas | 1:e08a4d27f534 | 553 | char LED_CUBE::byteline (int start, int end) |
Bas | 1:e08a4d27f534 | 554 | { |
Bas | 1:e08a4d27f534 | 555 | char line=0; |
Bas | 1:e08a4d27f534 | 556 | int bitnr; |
Bas | 1:e08a4d27f534 | 557 | |
Bas | 1:e08a4d27f534 | 558 | for (bitnr=0; bitnr<8; bitnr++) { |
Bas | 1:e08a4d27f534 | 559 | if (bitnr>=start && bitnr<=end) { |
Bas | 1:e08a4d27f534 | 560 | line |= (1<<bitnr); |
Bas | 1:e08a4d27f534 | 561 | } |
Bas | 1:e08a4d27f534 | 562 | } |
Bas | 1:e08a4d27f534 | 563 | return line; |
Bas | 1:e08a4d27f534 | 564 | } |
Bas | 1:e08a4d27f534 | 565 | |
Bas | 1:e08a4d27f534 | 566 | // This function validates that we are drawing inside the cube. |
Bas | 1:e08a4d27f534 | 567 | unsigned char LED_CUBE::inrange(int x, int y, int z) |
Bas | 1:e08a4d27f534 | 568 | { |
Bas | 1:e08a4d27f534 | 569 | if (x >= 0 && x < 8 && y >= 0 && y < 8 && z >= 0 && z < 8) { |
Bas | 1:e08a4d27f534 | 570 | return 0x01; |
Bas | 1:e08a4d27f534 | 571 | } else { |
Bas | 1:e08a4d27f534 | 572 | // One of the coordinates was outside the cube. |
Bas | 1:e08a4d27f534 | 573 | return 0x00; |
Bas | 1:e08a4d27f534 | 574 | } |
Bas | 1:e08a4d27f534 | 575 | } |
Bas | 1:e08a4d27f534 | 576 | |
Bas | 1:e08a4d27f534 | 577 | void LED_CUBE::argorder(int ix1, int ix2, int *ox1, int *ox2) |
Bas | 1:e08a4d27f534 | 578 | { |
Bas | 1:e08a4d27f534 | 579 | if (ix1>ix2) { |
Bas | 1:e08a4d27f534 | 580 | int tmp; |
Bas | 1:e08a4d27f534 | 581 | tmp = ix1; |
Bas | 1:e08a4d27f534 | 582 | ix1= ix2; |
Bas | 1:e08a4d27f534 | 583 | ix2 = tmp; |
Bas | 1:e08a4d27f534 | 584 | } |
Bas | 1:e08a4d27f534 | 585 | *ox1 = ix1; |
Bas | 1:e08a4d27f534 | 586 | *ox2 = ix2; |
Bas | 1:e08a4d27f534 | 587 | } |
Bas | 1:e08a4d27f534 | 588 | |
Bas | 1:e08a4d27f534 | 589 | double LED_CUBE::map(double in, double inMin, double inMax, double outMin, double outMax) |
Bas | 1:e08a4d27f534 | 590 | { |
Bas | 1:e08a4d27f534 | 591 | double out; |
Bas | 1:e08a4d27f534 | 592 | out = (in-inMin)/(inMax-inMin)*(outMax-outMin) + outMin; |
Bas | 1:e08a4d27f534 | 593 | return out; |
Bas | 0:920c5ed65a45 | 594 | } |