diff options
Diffstat (limited to 'avr-test2/src')
-rw-r--r-- | avr-test2/src/cube.h | 32 | ||||
-rw-r--r-- | avr-test2/src/draw.cpp | 559 | ||||
-rw-r--r-- | avr-test2/src/draw.h | 71 | ||||
-rw-r--r-- | avr-test2/src/effect.cpp | 1331 | ||||
-rw-r--r-- | avr-test2/src/effect.h | 54 | ||||
-rw-r--r-- | avr-test2/src/font.cpp | 104 | ||||
-rw-r--r-- | avr-test2/src/font.h | 13 | ||||
-rw-r--r-- | avr-test2/src/fuses.txt | 6 | ||||
-rw-r--r-- | avr-test2/src/gameoflife.cpp | 135 | ||||
-rw-r--r-- | avr-test2/src/gameoflife.h | 9 | ||||
-rw-r--r-- | avr-test2/src/launch_effect.cpp | 182 | ||||
-rw-r--r-- | avr-test2/src/launch_effect.h | 15 | ||||
-rw-r--r-- | avr-test2/src/lisence.txt | 5 | ||||
-rw-r--r-- | avr-test2/src/main.cpp | 450 | ||||
-rw-r--r-- | avr-test2/src/main.cpp.bakup | 447 | ||||
-rw-r--r-- | avr-test2/src/main.h | 50 |
16 files changed, 3463 insertions, 0 deletions
diff --git a/avr-test2/src/cube.h b/avr-test2/src/cube.h new file mode 100644 index 0000000..01f19da --- /dev/null +++ b/avr-test2/src/cube.h @@ -0,0 +1,32 @@ +#ifndef CUBE_H +#define CUBE_H + +// Some of the functions are created to be portable +// These functions will work on cubes of different sizes by +// changing this constant +#define CUBE_SIZE 8 +#define CUBE_BYTES 64 + +// If you change this to anything greather than 8, you also have +// change how the cube buffer works and probably all the functions +// in draw.c + +// Cube buffer +// Data from this array is loaded onto the cube for each duty cycle +extern volatile unsigned char cube[CUBE_SIZE][CUBE_SIZE]; + +// Framebuffer +// Animations that take a lot of time to compute are temporarily +// stored to this array, then loaded into cube[8][8] when the image +// is ready to be displayed +extern volatile unsigned char fb[CUBE_SIZE][CUBE_SIZE]; + +// Some effects can render on different axis +// for example send pixels along an axis +// for better readability, we use the following predefined constants +#define AXIS_X 0x78 +#define AXIS_Y 0x79 +#define AXIS_Z 0x7a + +#endif + diff --git a/avr-test2/src/draw.cpp b/avr-test2/src/draw.cpp new file mode 100644 index 0000000..faaa346 --- /dev/null +++ b/avr-test2/src/draw.cpp @@ -0,0 +1,559 @@ +#include "draw.h" +#include "string.h" + +// Set a single voxel to ON +void setvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + cube[z][y] |= (1 << x); +} + +// Set a single voxel in the temporary cube buffer to ON +void tmpsetvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + fb[z][y] |= (1 << x); +} + +// Set a single voxel to OFF +void clrvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + cube[z][y] &= ~(1 << x); +} + +// Set a single voxel to OFF +void tmpclrvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + fb[z][y] &= ~(1 << x); +} + +// This function validates that we are drawing inside the cube. +unsigned char inrange(int x, int y, int z) +{ + if (x >= 0 && x < CUBE_SIZE && y >= 0 && y < CUBE_SIZE && z >= 0 && z < CUBE_SIZE) + { + return 1; + } else + { + // One of the coordinates was outside the cube. + return 0; + } +} + +// Get the current status of a voxel +unsigned char getvoxel(int x, int y, int z) +{ + if (inrange(x,y,z)) + { + if (cube[z][y] & (1 << x)) + { + return 1; + } else + { + return 0; + } + } else + { + return 0; + } +} + +// In some effect we want to just take bool and write it to a voxel +// this function calls the apropriate voxel manipulation function. +void altervoxel(int x, int y, int z, int state) +{ + if (state == 1) + { + setvoxel(x,y,z); + } else + { + clrvoxel(x,y,z); + } +} + +// Flip the state of a voxel. +// If the voxel is 1, its turned into a 0, and vice versa. +void flpvoxel(int x, int y, int z) +{ + if (inrange(x, y, z)) + cube[z][y] ^= (1 << x); +} + +// Makes sure x1 is alwas smaller than x2 +// This is usefull for functions that uses for loops, +// to avoid infinite loops +void argorder(int ix1, int ix2, int *ox1, int *ox2) +{ + if (ix1>ix2) + { + int tmp; + tmp = ix1; + ix1= ix2; + ix2 = tmp; + } + *ox1 = ix1; + *ox2 = ix2; +} + +// Sets all voxels along a X/Y plane at a given point +// on axis Z +void setplane_z (int z) +{ + int i; + if (z>=0 && z<CUBE_SIZE) + { + for (i=0;i<CUBE_SIZE;i++) + cube[z][i] = 0xff; + } +} + +// Clears voxels in the same manner as above +void clrplane_z (int z) +{ + int i; + if (z>=0 && z<CUBE_SIZE) + { + for (i=0;i<CUBE_SIZE;i++) + cube[z][i] = 0x00; + } +} + +void setplane_x (int x) +{ + int z; + int y; + if (x>=0 && x<CUBE_SIZE) + { + for (z=0;z<CUBE_SIZE;z++) + { + for (y=0;y<CUBE_SIZE;y++) + { + cube[z][y] |= (1 << x); + } + } + } +} + +void clrplane_x (int x) +{ + int z; + int y; + if (x>=0 && x<CUBE_SIZE) + { + for (z=0;z<CUBE_SIZE;z++) + { + for (y=0;y<CUBE_SIZE;y++) + { + cube[z][y] &= ~(1 << x); + } + } + } +} + +void setplane_y (int y) +{ + int z; + if (y>=0 && y<CUBE_SIZE) + { + for (z=0;z<CUBE_SIZE;z++) + cube[z][y] = 0xff; + } +} + +void clrplane_y (int y) +{ + int z; + if (y>=0 && y<CUBE_SIZE) + { + for (z=0;z<CUBE_SIZE;z++) + cube[z][y] = 0x00; + } +} + +void 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 clrplane (char axis, unsigned char i) +{ + switch (axis) + { + case AXIS_X: + clrplane_x(i); + break; + + case AXIS_Y: + clrplane_y(i); + break; + + case AXIS_Z: + clrplane_z(i); + break; + } +} + +// Fill a value into all 64 byts of the cube buffer +// Mostly used for clearing. fill(0x00) +// or setting all on. fill(0xff) +void fill (unsigned char pattern) +{ + int z; + int y; + for (z=0;z<CUBE_SIZE;z++) + { + for (y=0;y<CUBE_SIZE;y++) + { + cube[z][y] = pattern; + } + } +} + +void tmpfill (unsigned char pattern) +{ + int z; + int y; + for (z=0;z<CUBE_SIZE;z++) + { + for (y=0;y<CUBE_SIZE;y++) + { + fb[z][y] = pattern; + } + } +} + +// Draw a box with all walls drawn and all voxels inside set +void box_filled(int x1, int y1, int z1, int x2, int y2, int z2) +{ + int iy; + int iz; + + argorder(x1, x2, &x1, &x2); + argorder(y1, y2, &y1, &y2); + argorder(z1, z2, &z1, &z2); + + for (iz=z1;iz<=z2;iz++) + { + for (iy=y1;iy<=y2;iy++) + { + cube[iz][iy] |= byteline(x1,x2); + } + } + +} + +// Darw a hollow box with side walls. +void box_walls(int x1, int y1, int z1, int x2, int y2, int z2) +{ + int iy; + int iz; + + argorder(x1, x2, &x1, &x2); + argorder(y1, y2, &y1, &y2); + argorder(z1, z2, &z1, &z2); + + for (iz=z1;iz<=z2;iz++) + { + for (iy=y1;iy<=y2;iy++) + { + if (iy == y1 || iy == y2 || iz == z1 || iz == z2) + { + cube[iz][iy] = byteline(x1,x2); + } else + { + cube[iz][iy] |= ((0x01 << x1) | (0x01 << x2)); + } + } + } + +} + +// Draw a wireframe box. This only draws the corners and edges, +// no walls. +void box_wireframe(int x1, int y1, int z1, int x2, int y2, int z2) +{ + int iy; + int iz; + + argorder(x1, x2, &x1, &x2); + argorder(y1, y2, &y1, &y2); + argorder(z1, z2, &z1, &z2); + + // Lines along X axis + cube[z1][y1] = byteline(x1,x2); + cube[z1][y2] = byteline(x1,x2); + cube[z2][y1] = byteline(x1,x2); + cube[z2][y2] = byteline(x1,x2); + + // Lines along Y axis + for (iy=y1;iy<=y2;iy++) + { + setvoxel(x1,iy,z1); + setvoxel(x1,iy,z2); + setvoxel(x2,iy,z1); + setvoxel(x2,iy,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); + } + +} + +// Returns a byte with a row of 1's drawn in it. +// byteline(2,5) gives 0b00111100 +char byteline (int start, int end) +{ + return ((0xff<<start) & ~(0xff<<(end+1))); +} + +// Flips a byte 180 degrees. +// MSB becomes LSB, LSB becomes MSB. +char flipbyte (char byte) +{ + char flop = 0x00; + + flop = (flop & 0b11111110) | (0b00000001 & (byte >> 7)); + flop = (flop & 0b11111101) | (0b00000010 & (byte >> 5)); + flop = (flop & 0b11111011) | (0b00000100 & (byte >> 3)); + flop = (flop & 0b11110111) | (0b00001000 & (byte >> 1)); + flop = (flop & 0b11101111) | (0b00010000 & (byte << 1)); + flop = (flop & 0b11011111) | (0b00100000 & (byte << 3)); + flop = (flop & 0b10111111) | (0b01000000 & (byte << 5)); + flop = (flop & 0b01111111) | (0b10000000 & (byte << 7)); + return flop; +} + +// Draw a line between any coordinates in 3d space. +// Uses integer values for input, so dont expect smooth animations. +void 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; + unsigned char lasty,lastz; + + // 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); + lasty = y2; + } else + { + xy = (float)(y2-y1)/(float)(x2-x1); + lasty = y1; + } + + if (z1>z2) + { + xz = (float)(z1-z2)/(float)(x2-x1); + lastz = z2; + } else + { + xz = (float)(z2-z1)/(float)(x2-x1); + lastz = z1; + } + + + + // 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); + } + +} + +// Delay loop. +// This is not calibrated to milliseconds, +// but we had allready made to many effects using this +// calibration when we figured it might be a good idea +// to calibrate it. +void delay_ms(uint16_t x) +{ + uint8_t y, z; + for ( ; x > 0 ; x--){ + for ( y = 0 ; y < 90 ; y++){ + for ( z = 0 ; z < 6 ; z++){ + asm volatile ("nop"); + } + } + } +} + +// Copies the contents of fb (temp cube buffer) into the rendering buffer +void tmp2cube (void) +{ + memcpy((void*)cube, (const void*)fb, 64); // copy the current cube into a buffer. +} + +// Shift the entire contents of the cube along an axis +// This is great for effects where you want to draw something +// on one side of the cube and have it flow towards the other +// side. Like rain flowing down the Z axiz. +void shift (char axis, int direction) +{ + int i, x ,y; + int ii, iii; + int state; + + for (i = 0; i < CUBE_SIZE; i++) + { + if (direction == -1) + { + ii = i; + } else + { + ii = (7-i); + } + + + for (x = 0; x < CUBE_SIZE; x++) + { + for (y = 0; y < CUBE_SIZE; y++) + { + if (direction == -1) + { + iii = ii+1; + } else + { + iii = ii-1; + } + + if (axis == AXIS_Z) + { + state = getvoxel(x,y,iii); + altervoxel(x,y,ii,state); + } + + if (axis == AXIS_Y) + { + state = getvoxel(x,iii,y); + altervoxel(x,ii,y,state); + } + + if (axis == AXIS_X) + { + state = getvoxel(iii,y,x); + altervoxel(ii,y,x,state); + } + } + } + } + + if (direction == -1) + { + i = 7; + } else + { + i = 0; + } + + for (x = 0; x < CUBE_SIZE; x++) + { + for (y = 0; y < CUBE_SIZE; y++) + { + if (axis == AXIS_Z) + clrvoxel(x,y,i); + + if (axis == AXIS_Y) + clrvoxel(x,i,y); + + if (axis == AXIS_X) + clrvoxel(i,y,x); + } + } +} + +// Flip the cube 180 degrees along the y axis. +void mirror_y (void) +{ + unsigned char buffer[CUBE_SIZE][CUBE_SIZE]; + unsigned char x,y,z; + + memcpy(buffer, (const void*)cube, CUBE_BYTES); // copy the current cube into a buffer. + + fill(0x00); + for (z=0; z<CUBE_SIZE; z++) + { + for (y=0; y<CUBE_SIZE; y++) + { + for (x=0; x<CUBE_SIZE; x++) + { + if (buffer[z][y] & (0x01 << x)) + setvoxel(x,CUBE_SIZE-1-y,z); + } + } + } + +} + +// Flip the cube 180 degrees along the x axis +void mirror_x (void) +{ + unsigned char buffer[CUBE_SIZE][CUBE_SIZE]; + unsigned char y,z; + + memcpy(buffer, (const void*)cube, CUBE_BYTES); // copy the current cube into a buffer. + + fill(0x00); + + for (z=0; z<CUBE_SIZE; z++) + { + for (y=0; y<CUBE_SIZE; y++) + { + // This will break with different buffer sizes.. + cube[z][y] = flipbyte(buffer[z][y]); + } + } +} + +// flip the cube 180 degrees along the z axis +void mirror_z (void) +{ + unsigned char buffer[CUBE_SIZE][CUBE_SIZE]; + unsigned char z, y; + + memcpy(buffer, (const void*)cube, CUBE_BYTES); // copy the current cube into a buffer. + + for (y=0; y<CUBE_SIZE; y++) + { + for (z=0; z<CUBE_SIZE; z++) + { + cube[CUBE_SIZE-1-z][y] = buffer[z][y]; + } + } +} + diff --git a/avr-test2/src/draw.h b/avr-test2/src/draw.h new file mode 100644 index 0000000..abe93d2 --- /dev/null +++ b/avr-test2/src/draw.h @@ -0,0 +1,71 @@ +#ifndef DRAW_H +#define DRAW_H + +#include <avr/io.h> +#include <avr/pgmspace.h> + +#include "cube.h" + +extern const unsigned char font[480]; + +// Red led on D2 +#define LED_RED 0x04 +// Green led D3 +#define LED_GREEN 0x08 +// Program led on D4 +#define LED_PGM 0x10; +// Leds connected to port D +#define LED_PORT PORTD +// Programming button on D5 +#define PGM_BTN 0x20 + +void delay_ms (uint16_t x); + + +void setvoxel(int x, int y, int z); +void clrvoxel(int x, int y, int z); +void tmpsetvoxel(int x, int y, int z); +void tmpclrvoxel(int x, int y, int z); + +unsigned char inrange(int x, int y, int z); +unsigned char getvoxel(int x, int y, int z); +void flpvoxel(int x, int y, int z); + +void altervoxel(int x, int y, int z, int state); +void setplane_z(int z); +void clrplane_z(int z); +void setplane_x(int x); +void clrplane_x(int x); +void setplane_y(int y); +void clrplane_y(int y); + +void setplane (char axis, unsigned char i); +void clrplane (char axis, unsigned char i); + +void setline_z(int x, int y, int z1, int z2); +void setline_x(int z, int y, int x1, int x2); +void setline_y(int z, int x, int y1, int y2); +void clrline_z(int x, int y, int z1, int z2); +void clrline_x(int z, int y, int x1, int x2); +void clrline_y(int z, int x, int y1, int y2); +void fill(unsigned char pattern); +void tmpfill(unsigned char pattern); +void line(int x1, int y1, int z1, int x2, int y2, int z2); +void drawchar(char chr, int offset, int layer); +char flipbyte(char byte); +void charfly (char chr, int direction, char axis, int mode, uint16_t delay); +void strfly (char * str, int direction, char axis, int mode, uint16_t delay, uint16_t pause); +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); +char byteline (int start, int end); + +void tmp2cube (void); +void shift (char axis, int direction); + +void mirror_x(void); +void mirror_y(void); +void mirror_z(void); + +#endif + diff --git a/avr-test2/src/effect.cpp b/avr-test2/src/effect.cpp new file mode 100644 index 0000000..d44da4d --- /dev/null +++ b/avr-test2/src/effect.cpp @@ -0,0 +1,1331 @@ +#include "effect.h" +#include "draw.h" +#include "font.h" +#include <math.h> +#include <avr/interrupt.h> + +void effect_test (void) +{ + + int x,y,i; + + for (i=0;i<1000;i++) + { + x = sin(i/8)*2+3.5; + y = cos(i/8)*2+3.5; + + setvoxel(x,y,1); + setvoxel(x,y,1); + delay_ms(1000); + fill(0x00); + } + +} + + +void effect_stringfly2(const char * str) +{ + int x,y,i; + unsigned char chr[5]; + + while (*str) + { + font_getchar(*str++, chr); + + // Put a character on the back of the cube + for (x = 0; x < 5; x++) + { + for (y = 0; y < 8; y++) + { + if ((chr[x] & (0x80>>y))) + { + setvoxel(7,x+2,y); + } + } + } + + // Shift the entire contents of the cube forward by 6 steps + // before placing the next character + for (i = 0; i<6; i++) + { + delay_ms(1000); + shift(AXIS_X,-1); + } + } + // Shift the last character out of the cube. + for (i = 0; i<8; i++) + { + delay_ms(1000); + shift(AXIS_X,-1); + } + +} + +// Draw a plane on one axis and send it back and forth once. +void effect_planboing (int plane, int speed) +{ + int i; + for (i=0;i<8;i++) + { + fill(0x00); + setplane(plane, i); + delay_ms(speed); + } + + for (i=7;i>=0;i--) + { + fill(0x00); + setplane(plane,i); + delay_ms(speed); + } +} + +void effect_blinky2() +{ + int i,r; + fill(0x00); + + for (r=0;r<2;r++) + { + i = 750; + while (i>0) + { + fill(0x00); + delay_ms(i); + + fill(0xff); + delay_ms(100); + + i = i - (15+(1000/(i/10))); + } + + delay_ms(1000); + + i = 750; + while (i>0) + { + fill(0x00); + delay_ms(751-i); + + fill(0xff); + delay_ms(100); + + i = i - (15+(1000/(i/10))); + } + } + +} + +void effect_box_shrink_grow (int iterations, int rot, int flip, uint16_t delay) +{ + int x, i, xyz; + for (x=0;x<iterations;x++) + { + for (i=0;i<16;i++) + { + xyz = 7-i; // This reverses counter i between 0 and 7. + if (i > 7) + xyz = i-8; // at i > 7, i 8-15 becomes xyz 0-7. + + fill(0x00); delay_ms(1); + cli(); // disable interrupts while the cube is being rotated + box_wireframe(0,0,0,xyz,xyz,xyz); + + if (flip > 0) // upside-down + mirror_z(); + + if (rot == 1 || rot == 3) + mirror_y(); + + if (rot == 2 || rot == 3) + mirror_x(); + + sei(); // enable interrupts + delay_ms(delay); + fill(0x00); + } + } +} + +// Creates a wireframe box that shrinks or grows out from the center of the cube. +void effect_box_woopwoop (int delay, int grow) +{ + int i,ii; + + fill(0x00); + for (i=0;i<4;i++) + { + ii = i; + if (grow > 0) + ii = 3-i; + + box_wireframe(4+ii,4+ii,4+ii,3-ii,3-ii,3-ii); + delay_ms(delay); + fill(0x00); + } +} + + +// Send a voxel flying from one side of the cube to the other +// If its at the bottom, send it to the top.. +void sendvoxel_z (unsigned char x, unsigned char y, unsigned char z, int delay) +{ + int i, ii; + for (i=0; i<8; i++) + { + if (z == 7) + { + ii = 7-i; + clrvoxel(x,y,ii+1); + } else + { + ii = i; + clrvoxel(x,y,ii-1); + } + setvoxel(x,y,ii); + delay_ms(delay); + } +} + +// Send all the voxels from one side of the cube to the other +// Start at z and send to the opposite side. +// Sends in random order. +void sendplane_rand_z (unsigned char z, int delay, int wait) +{ + unsigned char loop = 16; + unsigned char x, y; + + fill(0x00); + + setplane_z(z); + + // Send voxels at random untill all 16 have crossed the cube. + while(loop) + { + x = rand()%4; + y = rand()%4; + if (getvoxel(x,y,z)) + { + // Send the voxel flying + sendvoxel_z(x,y,z,delay); + delay_ms(wait); + loop--; // one down, loop-- to go. when this hits 0, the loop exits. + } + } +} + +// For each coordinate along X and Y, a voxel is set either at level 0 or at level 7 +// for n iterations, a random voxel is sent to the opposite side of where it was. +void sendvoxels_rand_z (int iterations, int delay, int wait) +{ + unsigned char x, y, last_x = 0, last_y = 0, i; + + fill(0x00); + + // Loop through all the X and Y coordinates + for (x=0;x<8;x++) + { + for (y=0;y<8;y++) + { + // Then set a voxel either at the top or at the bottom + // rand()%2 returns either 0 or 1. multiplying by 7 gives either 0 or 7. + setvoxel(x,y,((rand()%2)*7)); + } + } + + for (i=0;i<iterations;i++) + { + // Pick a random x,y position + x = rand()%8; + y = rand()%8; + // but not the sameone twice in a row + if (y != last_y && x != last_x) + { + // If the voxel at this x,y is at the bottom + if (getvoxel(x,y,0)) + { + // send it to the top + sendvoxel_z(x,y,0,delay); + } else + { + // if its at the top, send it to the bottom + sendvoxel_z(x,y,7,delay); + } + delay_ms(wait); + + // Remember the last move + last_y = y; + last_x = x; + } + } + +} + + +// Big ugly function :p but it looks pretty +void boingboing(uint16_t iterations, int delay, unsigned char mode, unsigned char drawmode) +{ + fill(0x00); // Blank the cube + + int x, y, z; // Current coordinates for the point + int dx, dy, dz; // Direction of movement + int lol, i; // lol? + unsigned char crash_x, crash_y, crash_z; + + y = rand()%8; + x = rand()%8; + z = rand()%8; + + // Coordinate array for the snake. + int snake[8][3]; + for (i=0;i<8;i++) + { + snake[i][0] = x; + snake[i][1] = y; + snake[i][2] = z; + } + + + dx = 1; + dy = 1; + dz = 1; + + while(iterations) + { + crash_x = 0; + crash_y = 0; + crash_z = 0; + + + // Let's mix things up a little: + if (rand()%3 == 0) + { + // Pick a random axis, and set the speed to a random number. + lol = rand()%3; + if (lol == 0) + dx = rand()%3 - 1; + + if (lol == 1) + dy = rand()%3 - 1; + + if (lol == 2) + dz = rand()%3 - 1; + } + + // The point has reached 0 on the x-axis and is trying to go to -1 + // aka a crash + if (dx == -1 && x == 0) + { + crash_x = 0x01; + if (rand()%3 == 1) + { + dx = 1; + } else + { + dx = 0; + } + } + + // y axis 0 crash + if (dy == -1 && y == 0) + { + crash_y = 0x01; + if (rand()%3 == 1) + { + dy = 1; + } else + { + dy = 0; + } + } + + // z axis 0 crash + if (dz == -1 && z == 0) + { + crash_z = 0x01; + if (rand()%3 == 1) + { + dz = 1; + } else + { + dz = 0; + } + } + + // x axis 7 crash + if (dx == 1 && x == 7) + { + crash_x = 0x01; + if (rand()%3 == 1) + { + dx = -1; + } else + { + dx = 0; + } + } + + // y axis 7 crash + if (dy == 1 && y == 7) + { + crash_y = 0x01; + if (rand()%3 == 1) + { + dy = -1; + } else + { + dy = 0; + } + } + + // z azis 7 crash + if (dz == 1 && z == 7) + { + crash_z = 0x01; + if (rand()%3 == 1) + { + dz = -1; + } else + { + dz = 0; + } + } + + // mode bit 0 sets crash action enable + if (mode | 0x01) + { + if (crash_x) + { + if (dy == 0) + { + if (y == 7) + { + dy = -1; + } else if (y == 0) + { + dy = +1; + } else + { + if (rand()%2 == 0) + { + dy = -1; + } else + { + dy = 1; + } + } + } + if (dz == 0) + { + if (z == 7) + { + dz = -1; + } else if (z == 0) + { + dz = 1; + } else + { + if (rand()%2 == 0) + { + dz = -1; + } else + { + dz = 1; + } + } + } + } + + if (crash_y) + { + if (dx == 0) + { + if (x == 7) + { + dx = -1; + } else if (x == 0) + { + dx = 1; + } else + { + if (rand()%2 == 0) + { + dx = -1; + } else + { + dx = 1; + } + } + } + if (dz == 0) + { + if (z == 3) + { + dz = -1; + } else if (z == 0) + { + dz = 1; + } else + { + if (rand()%2 == 0) + { + dz = -1; + } else + { + dz = 1; + } + } + } + } + + if (crash_z) + { + if (dy == 0) + { + if (y == 7) + { + dy = -1; + } else if (y == 0) + { + dy = 1; + } else + { + if (rand()%2 == 0) + { + dy = -1; + } else + { + dy = 1; + } + } + } + if (dx == 0) + { + if (x == 7) + { + dx = -1; + } else if (x == 0) + { + dx = 1; + } else + { + if (rand()%2 == 0) + { + dx = -1; + } else + { + dx = 1; + } + } + } + } + } + + // mode bit 1 sets corner avoid enable + if (mode | 0x02) + { + if ( // We are in one of 8 corner positions + (x == 0 && y == 0 && z == 0) || + (x == 0 && y == 0 && z == 7) || + (x == 0 && y == 7 && z == 0) || + (x == 0 && y == 7 && z == 7) || + (x == 7 && y == 0 && z == 0) || + (x == 7 && y == 0 && z == 7) || + (x == 7 && y == 7 && z == 0) || + (x == 7 && y == 7 && z == 7) + ) + { + // At this point, the voxel would bounce + // back and forth between this corner, + // and the exact opposite corner + // We don't want that! + + // So we alter the trajectory a bit, + // to avoid corner stickyness + lol = rand()%3; + if (lol == 0) + dx = 0; + + if (lol == 1) + dy = 0; + + if (lol == 2) + dz = 0; + } + } + + // one last sanity check + if (x == 0 && dx == -1) + dx = 1; + + if (y == 0 && dy == -1) + dy = 1; + + if (z == 0 && dz == -1) + dz = 1; + + if (x == 7 && dx == 1) + dx = -1; + + if (y == 7 && dy == 1) + dy = -1; + + if (z == 7 && dz == 1) + dz = -1; + + + // Finally, move the voxel. + x = x + dx; + y = y + dy; + z = z + dz; + + if (drawmode == 0x01) // show one voxel at time + { + setvoxel(x,y,z); + delay_ms(delay); + clrvoxel(x,y,z); + } else if (drawmode == 0x02) // flip the voxel in question + { + flpvoxel(x,y,z); + delay_ms(delay); + } if (drawmode == 0x03) // draw a snake + { + for (i=7;i>=0;i--) + { + snake[i][0] = snake[i-1][0]; + snake[i][1] = snake[i-1][1]; + snake[i][2] = snake[i-1][2]; + } + snake[0][0] = x; + snake[0][1] = y; + snake[0][2] = z; + + for (i=0;i<8;i++) + { + setvoxel(snake[i][0],snake[i][1],snake[i][2]); + } + delay_ms(delay); + for (i=0;i<8;i++) + { + clrvoxel(snake[i][0],snake[i][1],snake[i][2]); + } + } + + + iterations--; + } +} + +// Set or clear exactly 512 voxels in a random order. +void effect_random_filler (int delay, int state) +{ + int x,y,z; + int loop = 0; + + + if (state == 1) + { + fill(0x00); + } else + { + fill(0xff); + } + + while (loop<511) + { + x = rand()%8; + y = rand()%8; + z = rand()%8; + + if ((state == 0 && getvoxel(x,y,z) == 0x01) || (state == 1 && getvoxel(x,y,z) == 0x00)) + { + altervoxel(x,y,z,state); + delay_ms(delay); + loop++; + } + } +} + + +void effect_rain (int iterations) +{ + int i, ii; + int rnd_x; + int rnd_y; + int rnd_num; + + for (ii=0;ii<iterations;ii++) + { + rnd_num = rand()%4; + + for (i=0; i < rnd_num;i++) + { + rnd_x = rand()%8; + rnd_y = rand()%8; + setvoxel(rnd_x,rnd_y,7); + } + + delay_ms(1000); + shift(AXIS_Z,-1); + } +} + +void effect_z_updown (int iterations, int delay) +{ + unsigned char positions[64]; + unsigned char destinations[64]; + + int i,y,move; + + for (i=0; i<64; i++) + { + positions[i] = 4; + destinations[i] = rand()%8; + } + + for (i=0; i<8; i++) + { + effect_z_updown_move(positions, destinations, AXIS_Z); + delay_ms(delay); + } + + for (i=0;i<iterations;i++) + { + for (move=0;move<8;move++) + { + effect_z_updown_move(positions, destinations, AXIS_Z); + delay_ms(delay); + } + + delay_ms(delay*4); + + + for (y=0;y<32;y++) + { + destinations[rand()%64] = rand()%8; + } + + } + +} + +void effect_z_updown_move (unsigned char positions[64], unsigned char destinations[64], char axis) +{ + int px; + for (px=0; px<64; px++) + { + if (positions[px]<destinations[px]) + { + positions[px]++; + } + if (positions[px]>destinations[px]) + { + positions[px]--; + } + } + + draw_positions_axis (AXIS_Z, positions,0); +} + +void effect_axis_updown_randsuspend (char axis, int delay, int sleep, int invert) +{ + unsigned char positions[64]; + unsigned char destinations[64]; + + int i,px; + + // Set 64 random positions + for (i=0; i<64; i++) + { + positions[i] = 0; // Set all starting positions to 0 + destinations[i] = rand()%8; + } + + // Loop 8 times to allow destination 7 to reach all the way + for (i=0; i<8; i++) + { + // For every iteration, move all position one step closer to their destination + for (px=0; px<64; px++) + { + if (positions[px]<destinations[px]) + { + positions[px]++; + } + } + // Draw the positions and take a nap + draw_positions_axis (axis, positions,invert); + delay_ms(delay); + } + + // Set all destinations to 7 (opposite from the side they started out) + for (i=0; i<64; i++) + { + destinations[i] = 7; + } + + // Suspend the positions in mid-air for a while + delay_ms(sleep); + + // Then do the same thing one more time + for (i=0; i<8; i++) + { + for (px=0; px<64; px++) + { + if (positions[px]<destinations[px]) + { + positions[px]++; + } + if (positions[px]>destinations[px]) + { + positions[px]--; + } + } + draw_positions_axis (axis, positions,invert); + delay_ms(delay); + } +} + +void draw_positions_axis (char axis, unsigned char positions[64], int invert) +{ + int x, y, p; + + fill(0x00); + + for (x=0; x<8; x++) + { + for (y=0; y<8; y++) + { + if (invert) + { + p = (7-positions[(x*8)+y]); + } else + { + p = positions[(x*8)+y]; + } + + if (axis == AXIS_Z) + setvoxel(x,y,p); + + if (axis == AXIS_Y) + setvoxel(x,p,y); + + if (axis == AXIS_X) + setvoxel(p,y,x); + } + } + +} + + +void effect_boxside_randsend_parallel (char axis, int origin, int delay, int mode) +{ + int i; + int done; + unsigned char cubepos[64]; + unsigned char pos[64]; + int notdone = 1; + int notdone2 = 1; + int sent = 0; + + for (i=0;i<64;i++) + { + pos[i] = 0; + } + + while (notdone) + { + if (mode == 1) + { + notdone2 = 1; + while (notdone2 && sent<64) + { + i = rand()%64; + if (pos[i] == 0) + { + sent++; + pos[i] += 1; + notdone2 = 0; + } + } + } else if (mode == 2) + { + if (sent<64) + { + pos[sent] += 1; + sent++; + } + } + + done = 0; + for (i=0;i<64;i++) + { + if (pos[i] > 0 && pos[i] <7) + { + pos[i] += 1; + } + + if (pos[i] == 7) + done++; + } + + if (done == 64) + notdone = 0; + + for (i=0;i<64;i++) + { + if (origin == 0) + { + cubepos[i] = pos[i]; + } else + { + cubepos[i] = (7-pos[i]); + } + } + + + delay_ms(delay); + draw_positions_axis(axis,cubepos,0); + LED_PORT ^= LED_RED; + } + +} + + + + +// Light all leds layer by layer, +// then unset layer by layer +void effect_loadbar(int delay) +{ + fill(0x00); + + int z,y; + + for (z=0;z<8;z++) + { + for (y=0;y<8;y++) + cube[z][y] = 0xff; + + delay_ms(delay); + } + + delay_ms(delay*3); + + for (z=0;z<8;z++) + { + for (y=0;y<8;y++) + cube[z][y] = 0x00; + + delay_ms(delay); + } +} + + +// Set n number of voxels at random positions +void effect_random_sparkle_flash (int iterations, int voxels, int delay) +{ + int i; + int v; + for (i = 0; i < iterations; i++) + { + for (v=0;v<=voxels;v++) + setvoxel(rand()%8,rand()%8,rand()%8); + + delay_ms(delay); + fill(0x00); + } +} + +// blink 1 random voxel, blink 2 random voxels..... blink 20 random voxels +// and back to 1 again. +void effect_random_sparkle (void) +{ + int i; + + for (i=1;i<20;i++) + { + effect_random_sparkle_flash(5,i,200); + } + + for (i=20;i>=1;i--) + { + effect_random_sparkle_flash(5,i,200); + } + +} + +int effect_telcstairs_do(int x, int val, int delay) +{ + int y,z; + + for(y = 0, z = x; y <= z; y++, x--) + { + if(x < CUBE_SIZE && y < CUBE_SIZE) + { + cube[x][y] = val; + } + } + delay_ms(delay); + return z; +} + +void effect_telcstairs (int invert, int delay, int val) +{ + int x; + + if(invert) + { + for(x = CUBE_SIZE*2; x >= 0; x--) + { + x = effect_telcstairs_do(x,val,delay); + } + } + else + { + for(x = 0; x < CUBE_SIZE*2; x++) + { + x = effect_telcstairs_do(x,val,delay); + } + } +} + +void effect_wormsqueeze (int size, int axis, int direction, int iterations, int delay) +{ + int x, y, i,j,k, dx, dy; + int cube_size; + int origin = 0; + + if (direction == -1) + origin = 7; + + cube_size = 8-(size-1); + + x = rand()%cube_size; + y = rand()%cube_size; + + for (i=0; i<iterations; i++) + { + dx = ((rand()%3)-1); + dy = ((rand()%3)-1); + + if ((x+dx) > 0 && (x+dx) < cube_size) + x += dx; + + if ((y+dy) > 0 && (y+dy) < cube_size) + y += dy; + + shift(axis, direction); + + + for (j=0; j<size;j++) + { + for (k=0; k<size;k++) + { + if (axis == AXIS_Z) + setvoxel(x+j,y+k,origin); + + if (axis == AXIS_Y) + setvoxel(x+j,origin,y+k); + + if (axis == AXIS_X) + setvoxel(origin,y+j,x+k); + } + } + + delay_ms(delay); + } +} + +void effect_smileyspin (int count, int delay, char bitmap) +{ + unsigned char dybde[] = {0,1,2,3,4,5,6,7,1,1,2,3,4,5,6,6,2,2,3,3,4,4,5,5,3,3,3,3,4,4,4,4}; + int d = 0; + int flip = 0; + int x, y, off; + for(int i = 0; i<count; i++) + { + flip = 0; + d = 0; + off = 0; + // front: + for (int s=0;s<7;s++){ + if(!flip){ + off++; + if (off == 4){ + flip = 1; + off = 0; + } + } else { + off++; + } + for (x=0; x<8; x++) + { + d = 0; + for (y=0; y<8; y++) + { + if (font_getbitmappixel ( bitmap, 7-x, y)){ + if (!flip) + setvoxel(y,dybde[8 * off + d++],x); + else + setvoxel(y,dybde[31 - 8 * off - d++],x); + } else { + d++; + } + } + } + delay_ms(delay); + fill(0x00); + } + + // side: + off = 0; + flip = 0; + d = 0; + for (int s=0;s<7;s++){ + if(!flip){ + off++; + if (off == 4){ + flip = 1; + off = 0; + } + } else { + off++; + } + for (x=0; x<8; x++) + { + d = 0; + for (y=0; y<8; y++) + { + if (font_getbitmappixel ( bitmap, 7-x, y)){ + if (!flip) + setvoxel(dybde[8 * off + d++], 7 - y,x); + else + setvoxel(dybde[31 - 8 * off - d++],7 - y,x); + } else { + d++; + } + } + } + delay_ms(delay); + fill(0x00); + } + + + flip = 0; + d = 0; + off = 0; + // back: + for (int s=0;s<7;s++){ + if(!flip){ + off++; + if (off == 4){ + flip = 1; + off = 0; + } + } else { + off++; + } + for (x=0; x<8; x++) + { + d = 0; + for (y=0; y<8; y++) + { + if (font_getbitmappixel ( bitmap, 7-x, 7-y)){ + if (!flip) + setvoxel(y,dybde[8 * off + d++],x); + else + setvoxel(y,dybde[31 - 8 * off - d++],x); + } else { + d++; + } + } + } + delay_ms(delay); + fill(0x00); + } + + // other side: + off = 0; + flip = 0; + d = 0; + for (int s=0;s<7;s++){ + if(!flip){ + off++; + if (off == 4){ + flip = 1; + off = 0; + } + } else { + off++; + } + for (x=0; x<8; x++) + { + d = 0; + for (y=0; y<8; y++) + { + if (font_getbitmappixel ( bitmap, 7-x, 7-y)){ + if (!flip) + setvoxel(dybde[8 * off + d++], 7 - y,x); + else + setvoxel(dybde[31 - 8 * off - d++],7 - y,x); + } else { + d++; + } + } + } + delay_ms(delay); + fill(0x00); + } + + } +} + + +void effect_pathmove (unsigned char *path, int length) +{ + int i,z; + unsigned char state; + + for (i=(length-1);i>=1;i--) + { + for (z=0;z<8;z++) + { + + state = getvoxel(((path[(i-1)]>>4) & 0x0f), (path[(i-1)] & 0x0f), z); + altervoxel(((path[i]>>4) & 0x0f), (path[i] & 0x0f), z, state); + } + } + for (i=0;i<8;i++) + clrvoxel(((path[0]>>4) & 0x0f), (path[0] & 0x0f),i); +} + +void effect_rand_patharound (int iterations, int delay) +{ + int z, dz, i; + z = 4; + unsigned char path[28]; + + font_getpath(0,path,28); + + for (i = 0; i < iterations; i++) + { + dz = ((rand()%3)-1); + z += dz; + + if (z>7) + z = 7; + + if (z<0) + z = 0; + + effect_pathmove(path, 28); + setvoxel(0,7,z); + delay_ms(delay); + } +} + +void effect_pathspiral (int iterations, int delay) +{ + int z, i; + z = 4; + unsigned char path[16]; + + font_getpath(1,path,16); + + for (i = 0; i < iterations; i++) + { + setvoxel(4,0,i%8); + delay_ms(delay); + effect_pathmove(path, 28); + + } +} + +void effect_path_text (int delay, char *str) +{ + int z, i,ii; + z = 4; + unsigned char path[28]; + font_getpath(0,path,28); + + unsigned char chr[5]; + unsigned char stripe; + + while (*str) + { + //charfly(*str++, direction, axis, mode, delay); + + + font_getchar(*str++, chr); + + for (ii=0;ii<5;ii++) + { + //stripe = pgm_read_byte(&font[(chr*5)+ii]); + stripe = chr[ii]; + + for (z=0;z<8;z++) + { + if ((stripe>>(7-z)) & 0x01) + { + setvoxel(0,7,z); + } else + { + clrvoxel(0,7,z); + } + + } + effect_pathmove(path, 28); + delay_ms(delay); + } + + effect_pathmove(path, 28); + delay_ms(delay); + } + for (i=0;i<28;i++) + { + effect_pathmove(path, 28); + delay_ms(delay); + } +} + +void effect_path_bitmap (int delay, char bitmap, int iterations) +{ + int z, i, ii; + z = 4; + unsigned char path[28]; + font_getpath(0,path,28); + + for (i=0; i < iterations; i++) + { + for (ii=0;ii<8;ii++) + { + for (z=0;z<8;z++) + { + if (font_getbitmappixel(bitmap,(7-z),ii)) + { + setvoxel(0,7,z); + } else + { + clrvoxel(0,7,z); + } + + } + delay_ms(delay); + effect_pathmove(path, 28); + } + + for (ii=0;ii<20;ii++) + { + delay_ms(delay); + effect_pathmove(path, 28); + } + } + for (ii=0;ii<10;ii++) + { + delay_ms(delay); + effect_pathmove(path, 28); + } +} + + + diff --git a/avr-test2/src/effect.h b/avr-test2/src/effect.h new file mode 100644 index 0000000..2622acc --- /dev/null +++ b/avr-test2/src/effect.h @@ -0,0 +1,54 @@ +#ifndef EFFECT_H +#define EFFECT_H + +#include <avr/io.h> +#include <avr/pgmspace.h> +#include <stdlib.h> + +#include "cube.h" + +void effect_box_shrink_grow (int iterations, int rot, int flip, uint16_t delay); + +void effect_hollow_1 (int iterations, uint16_t delay); +void effect_hollow_2 (int iterations, int corner, uint16_t delay); + +void sendvoxel_z (unsigned char x, unsigned char y, unsigned char z, int delay); +void sendplane_rand_z (unsigned char z, int delay, int wait); +void sendvoxels_rand_z (int iterations, int delay, int wait); +void boingboing(uint16_t iterations, int delay, unsigned char mode, unsigned char drawmode); + +void effect_planboing (int plane, int speed); + +void effect_random_filler (int delay, int state); + +void effect_z_updown (int iterations, int delay); +void effect_rain(int iterations); +void effect_stringfly2(const char * str); +void effect_blinky2(void); +void draw_positions_axis (char axis, unsigned char positions[64], int invert); +void effect_axis_updown_randsuspend (char axis, int delay, int sleep, int invert); + +void effect_random_sparkle_flash (int iterations, int voxels, int delay); +void effect_random_sparkle (void); + +void effect_box_woopwoop (int delay, int grow); +void effect_telcstairs (int invert, int delay, int val); +void effect_loadbar(int delay); + +void effect_boxside_randsend_parallel (char axis, int origin, int delay, int mode); +void effect_smileyspin (int count, int delay, char bitmap); +void effect_pathmove (unsigned char *path, int length); +void effect_rand_patharound (int iterations, int delay); +void effect_pathspiral (int iterations, int delay); +void effect_path_text (int delay, char *str); +void effect_path_bitmap (int delay, char bitmap, int iterations); +void effect_wormsqueeze (int size, int axis, int direction, int iterations, int delay); + +void effect_z_updown (int iterations, int delay); +void effect_z_updown_move (unsigned char positions[64], unsigned char destinations[64], char axis); + + + + +#endif + diff --git a/avr-test2/src/font.cpp b/avr-test2/src/font.cpp new file mode 100644 index 0000000..ffb5185 --- /dev/null +++ b/avr-test2/src/font.cpp @@ -0,0 +1,104 @@ +#include "font.h" +#include <avr/eeprom.h> + +volatile const unsigned char font[455] EEMEM = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x5f,0x5f,0x00,0x00, // ! + 0x00,0x03,0x00,0x03,0x00,0x14,0x7f,0x14,0x7f,0x14, // "# + 0x24,0x2a,0x7f,0x2a,0x12,0x23,0x13,0x08,0x64,0x62, // $% + 0x36,0x49,0x55,0x22,0x50,0x00,0x05,0x03,0x00,0x00, // &' + 0x00,0x1c,0x22,0x41,0x00,0x00,0x41,0x22,0x1c,0x00, // () + 0x14,0x08,0x3e,0x08,0x14,0x08,0x08,0x3e,0x08,0x08, // *+ + 0x00,0x50,0x30,0x00,0x00,0x08,0x08,0x08,0x08,0x08, // ,- + 0x00,0x60,0x60,0x00,0x00,0x20,0x10,0x08,0x04,0x02, // ./ + 0x3e,0x51,0x49,0x45,0x3e,0x00,0x42,0x7f,0x40,0x00, // 01 + 0x42,0x61,0x51,0x49,0x46,0x21,0x41,0x45,0x4b,0x31, // 23 + 0x18,0x14,0x12,0x7f,0x10,0x27,0x45,0x45,0x45,0x39, // 45 + 0x3c,0x4a,0x49,0x49,0x30,0x01,0x71,0x09,0x05,0x03, // 67 + 0x36,0x49,0x49,0x49,0x36,0x06,0x49,0x49,0x29,0x1e, // 89 + 0x00,0x36,0x36,0x00,0x00,0x00,0x56,0x36,0x00,0x00, // :; + 0x08,0x14,0x22,0x41,0x00,0x14,0x14,0x14,0x14,0x14, // <= + 0x00,0x41,0x22,0x14,0x08,0x02,0x01,0x51,0x09,0x06, // >? + 0x32,0x49,0x79,0x41,0x3e,0x7e,0x11,0x11,0x11,0x7e, // @A + 0x7f,0x49,0x49,0x49,0x36,0x3e,0x41,0x41,0x41,0x22, // BC + 0x7f,0x41,0x41,0x22,0x1c,0x7f,0x49,0x49,0x49,0x41, // DE + 0x7f,0x09,0x09,0x09,0x01,0x3e,0x41,0x49,0x49,0x7a, // FG + 0x7f,0x08,0x08,0x08,0x7f,0x00,0x41,0x7f,0x41,0x00, // HI + 0x20,0x40,0x41,0x3f,0x01,0x7f,0x08,0x14,0x22,0x41, // JK + 0x7f,0x40,0x40,0x40,0x40,0x7f,0x02,0x0c,0x02,0x7f, // LM + 0x7f,0x04,0x08,0x10,0x7f,0x3e,0x41,0x41,0x41,0x3e, // NO + 0x7f,0x09,0x09,0x09,0x06,0x3e,0x41,0x51,0x21,0x5e, // PQ + 0x7f,0x09,0x19,0x29,0x46,0x46,0x49,0x49,0x49,0x31, // RS + 0x01,0x01,0x7f,0x01,0x01,0x3f,0x40,0x40,0x40,0x3f, // TU + 0x1f,0x20,0x40,0x20,0x1f,0x3f,0x40,0x38,0x40,0x3f, // VW + 0x63,0x14,0x08,0x14,0x63,0x07,0x08,0x70,0x08,0x07, // XY + 0x61,0x51,0x49,0x45,0x43,0x00,0x7f,0x41,0x41,0x00, // Z[ + 0x02,0x04,0x08,0x10,0x20,0x00,0x41,0x41,0x7f,0x00, // \] + 0x04,0x02,0x01,0x02,0x04,0x40,0x40,0x40,0x40,0x40, // ^_ + 0x00,0x01,0x02,0x04,0x00,0x20,0x54,0x54,0x54,0x78, // `a + 0x7f,0x48,0x44,0x44,0x38,0x38,0x44,0x44,0x44,0x20, // bc + 0x38,0x44,0x44,0x48,0x7f,0x38,0x54,0x54,0x54,0x18, // de + 0x08,0x7e,0x09,0x01,0x02,0x0c,0x52,0x52,0x52,0x3e, // fg + 0x7f,0x08,0x04,0x04,0x78,0x00,0x44,0x7d,0x40,0x00, // hi + 0x20,0x40,0x44,0x3d,0x00,0x7f,0x10,0x28,0x44,0x00, // jk + 0x00,0x41,0x7f,0x40,0x00,0x7c,0x04,0x18,0x04,0x78, // lm + 0x7c,0x08,0x04,0x04,0x78,0x38,0x44,0x44,0x44,0x38, // no + 0x7c,0x14,0x14,0x14,0x08,0x08,0x14,0x14,0x18,0x7c, // pq + 0x7c,0x08,0x04,0x04,0x08,0x48,0x54,0x54,0x54,0x20, // rs + 0x04,0x3f,0x44,0x40,0x20,0x3c,0x40,0x40,0x20,0x7c, // tu + 0x1c,0x20,0x40,0x20,0x1c,0x3c,0x40,0x30,0x40,0x3c, // vw + 0x44,0x28,0x10,0x28,0x44,0x0c,0x50,0x50,0x50,0x3c, // xy + 0x44,0x64,0x54,0x4c,0x44 // z +}; + + +volatile const unsigned char bitmaps[6][8] EEMEM = { + {0xc3,0xc3,0x00,0x18,0x18,0x81,0xff,0x7e}, // smiley 3 small + {0x3c,0x42,0x81,0x81,0xc3,0x24,0xa5,0xe7}, // Omega + {0x00,0x04,0x06,0xff,0xff,0x06,0x04,0x00}, // Arrow + {0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81}, // X + {0xBD,0xA1,0xA1,0xB9,0xA1,0xA1,0xA1,0x00}, // ifi + {0xEF,0x48,0x4B,0x49,0x4F,0x00,0x00,0x00} // TG +}; + +const unsigned char paths[44] /* PROGMEM */ = {0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x67,0x57,0x47,0x37,0x27,0x17, +0x04,0x03,0x12,0x21,0x30,0x40,0x51,0x62,0x73,0x74,0x65,0x56,0x47,0x37,0x26,0x15}; // circle, len 16, offset 28 + +void font_getpath (unsigned char path, unsigned char *destination, int length) +{ + int i; + int offset = 0; + + if (path == 1) + offset=28; + + for (i = 0; i < length; i++) + destination[i] = pgm_read_byte(&paths[i+offset]); +} + +void font_getchar (char chr, unsigned char dst[5]) +{ + uint8_t i; + chr -= 32; // our bitmap font starts at ascii char 32. + + for (i = 0; i < 5; i++) + dst[i] = (unsigned char)eeprom_read_byte((uint8_t*)&font[(chr*5)+i]); +} + +void font_getbitmap (char bitmap, unsigned char dst[8]) +{ + int i; + + for (i = 0; i < 8; i++) + dst[i] = (unsigned char)eeprom_read_byte((uint8_t*)&bitmaps[(uint8_t)bitmap][(uint8_t)i]); + +} + +unsigned char font_getbitmappixel ( char bitmap, char x, char y) +{ + uint8_t tmp = eeprom_read_byte((uint8_t*)&bitmaps[(uint8_t)bitmap][(uint8_t)x]); + return (tmp >> y) & 0x01; +} + + + + diff --git a/avr-test2/src/font.h b/avr-test2/src/font.h new file mode 100644 index 0000000..006414b --- /dev/null +++ b/avr-test2/src/font.h @@ -0,0 +1,13 @@ +#ifndef FONT_H +#define FONT_H + +#include <avr/pgmspace.h> + +void font_getchar (char chr, unsigned char dst[5]); +void font_getpath (unsigned char path, unsigned char *destination, int length); +void font_getbitmap (char bitmap, unsigned char dst[8]); +unsigned char font_getbitmappixel ( char bitmap, char x, char y); + + + +#endif diff --git a/avr-test2/src/fuses.txt b/avr-test2/src/fuses.txt new file mode 100644 index 0000000..f24e5f5 --- /dev/null +++ b/avr-test2/src/fuses.txt @@ -0,0 +1,6 @@ + +lfuse: 0b11101111 +hfuse: 0b11001001 + + + diff --git a/avr-test2/src/gameoflife.cpp b/avr-test2/src/gameoflife.cpp new file mode 100644 index 0000000..0a3683a --- /dev/null +++ b/avr-test2/src/gameoflife.cpp @@ -0,0 +1,135 @@ +#include <avr/io.h> +#include "gameoflife.h" +#include "cube.h" +#include "draw.h" + +// Game of Life for the 4x4x4 and 8x8x8 led cube + +#define GOL_CREATE_MIN 3 +#define GOL_CREATE_MAX 3 + +#define GOL_TERMINATE_LONELY 1 +#define GOL_TERMINATE_CROWDED 4 + +#define GOL_X 8 +#define GOL_Y 8 +#define GOL_Z 8 + +#define GOL_WRAP 0x01 + + + +void gol_play (int iterations, uint16_t delay) +{ + int i; + + for (i = 0; i < iterations; i++) + { + LED_PORT ^= LED_GREEN; + + gol_nextgen(); + + if (gol_count_changes() == 0) + return; + + tmp2cube(); + + delay_ms(delay); + + //led_red(1); + } +} + +void gol_nextgen (void) +{ + int x,y,z; + unsigned char neigh; + + tmpfill(0x00); + + for (x = 0; x < GOL_X; x++) + { + for (y = 0; y < GOL_Y; y++) + { + for (z = 0; z < GOL_Z; z++) + { + neigh = gol_count_neighbors(x, y, z); + + // Current voxel is alive. + if (getvoxel(x,y,z) == 0x01) + { + if (neigh <= GOL_TERMINATE_LONELY) + { + tmpclrvoxel(x,y,z); + } else if(neigh >= GOL_TERMINATE_CROWDED) + { + tmpclrvoxel(x,y,z); + } else + { + tmpsetvoxel(x,y,z); + } + // Current voxel is dead. + } else + { + if (neigh >= GOL_CREATE_MIN && neigh <= GOL_CREATE_MAX) + tmpsetvoxel(x,y,z); + } + } + } + } +} + +unsigned char gol_count_neighbors (int x, int y, int z) +{ + int ix, iy, iz; // offset 1 in each direction in each dimension + int nx, ny, nz; // neighbours address. + + unsigned char neigh = 0; // number of alive neighbours. + + for (ix = -1; ix < 2; ix++) + { + for (iy = -1; iy < 2; iy++) + { + for (iz = -1; iz < 2; iz++) + { + // Your not your own neighbour, exclude 0,0,0, offset. + if ( !(ix == 0 && iy == 0 && iz == 0) ) + { + if (GOL_WRAP == 0x01) + { + nx = (x+ix)%GOL_X; + ny = (y+iy)%GOL_Y; + nz = (z+iz)%GOL_Z; + } else + { + nx = x+ix; + ny = y+iy; + nz = z+iz; + } + + if ( getvoxel(nx, ny, nz) ) + neigh++; + } + } + } + } + return neigh; +} + +int gol_count_changes (void) +{ + int x,y; + int i = 0; + + for (x = 0; x < GOL_X; x++) + { + for (y = 0; y < GOL_Y; y++) + { + if (fb[x][y] != cube[x][y]) + i++; + } + } + + return i; +} + diff --git a/avr-test2/src/gameoflife.h b/avr-test2/src/gameoflife.h new file mode 100644 index 0000000..e53b900 --- /dev/null +++ b/avr-test2/src/gameoflife.h @@ -0,0 +1,9 @@ +#ifndef GOL_H +#define GOL_H + +void gol_play (int iterations, uint16_t delay); +unsigned char gol_count_neighbors (int x, int y, int z); +void gol_nextgen (void); +int gol_count_changes (void); + +#endif diff --git a/avr-test2/src/launch_effect.cpp b/avr-test2/src/launch_effect.cpp new file mode 100644 index 0000000..19b8d86 --- /dev/null +++ b/avr-test2/src/launch_effect.cpp @@ -0,0 +1,182 @@ +#include "launch_effect.h" +#include "effect.h" +#include "draw.h" +#include "gameoflife.h" + +void launch_effect (int effect) +{ + int i; + unsigned char ii; + + fill(0x00); + + switch (effect) + { + case 0x00: + //effect_rain(100); + break; + + + case 1: + //sendvoxels_rand_z(20,220,2000); + break; + + case 2: + //effect_random_filler(5,1); + //effect_random_filler(5,0); + //effect_random_filler(5,1); + //effect_random_filler(5,0); + break; + + case 3: + //effect_z_updown(20,1000); + break; + + case 4: + effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000); + break; + + case 5: + //effect_blinky2(); + break; + + case 6: + for (ii=0;ii<8;ii++) + { + effect_box_shrink_grow (1, ii%4, ii & 0x04, 450); + } + + effect_box_woopwoop(800,0); + effect_box_woopwoop(800,1); + effect_box_woopwoop(800,0); + effect_box_woopwoop(800,1); + break; + + case 7: + //effect_planboing (AXIS_Z, 400); + //effect_planboing (AXIS_X, 400); + //effect_planboing (AXIS_Y, 400); + //effect_planboing (AXIS_Z, 400); + //effect_planboing (AXIS_X, 400); + //effect_planboing (AXIS_Y, 400); + //fill(0x00); + break; + + case 8: + fill(0x00); + effect_telcstairs(0,800,0xff); + effect_telcstairs(0,800,0x00); + effect_telcstairs(1,800,0xff); + effect_telcstairs(1,800,0xff); + break; + + case 9: + //effect_axis_updown_randsuspend(AXIS_Z, 550,5000,0); + //effect_axis_updown_randsuspend(AXIS_Z, 550,5000,1); + //effect_axis_updown_randsuspend(AXIS_Z, 550,5000,0); + //effect_axis_updown_randsuspend(AXIS_Z, 550,5000,1); + //effect_axis_updown_randsuspend(AXIS_X, 550,5000,0); + //effect_axis_updown_randsuspend(AXIS_X, 550,5000,1); + //effect_axis_updown_randsuspend(AXIS_Y, 550,5000,0); + //effect_axis_updown_randsuspend(AXIS_Y, 550,5000,1); + break; + + case 10: + //effect_loadbar(700); + break; + + case 11: + //effect_wormsqueeze (1, AXIS_Z, 1, 100, 1000); + break; + + + case 12: + effect_stringfly2("INSTRUCTABLES"); + break; + + case 13: + //fill(0x00); + //// Create a random starting point for the Game of Life effect. + //for (i = 0; i < 20;i++) + //{ + // setvoxel(rand()%4,rand()%4,rand()%4); + //} + + //gol_play(20, 400); + break; + + case 14: + //effect_boxside_randsend_parallel (AXIS_Z, 0 , 200,1); + //delay_ms(1500); + //effect_boxside_randsend_parallel (AXIS_Z, 1 , 200,1); + //delay_ms(1500); + + //effect_boxside_randsend_parallel (AXIS_Z, 0 , 200,2); + //delay_ms(1500); + //effect_boxside_randsend_parallel (AXIS_Z, 1 , 200,2); + //delay_ms(1500); + + //effect_boxside_randsend_parallel (AXIS_Y, 0 , 200,1); + //delay_ms(1500); + //effect_boxside_randsend_parallel (AXIS_Y, 1 , 200,1); + //delay_ms(1500); + break; + + case 15: + boingboing(250, 600, 0x01, 0x02); + break; + + case 16: + //effect_smileyspin(2,1000,0); + break; + + case 17: + //effect_pathspiral(100,500); + break; + + case 18: + //effect_path_bitmap(700,2,3); + break; + + case 19: + //effect_smileyspin(2,1000,1); + break; + + case 20: + effect_path_text(1000,"TG"); + break; + + case 21: + effect_rand_patharound(200,500); + break; + + case 22: + effect_wormsqueeze (1, AXIS_Z, -1, 100, 1000); + break; + + case 23: + effect_smileyspin(2,1000,2); + break; + + case 24: + effect_random_sparkle(); + break; + + case 25: + effect_wormsqueeze (1, AXIS_Z, -1, 100, 1000); + break; + + case 26: + boingboing(250, 600, 0x01, 0x03); + break; + + // In case the effect number is out of range: + default: + effect_stringfly2("FAIL"); + break; + + + + } +} + diff --git a/avr-test2/src/launch_effect.h b/avr-test2/src/launch_effect.h new file mode 100644 index 0000000..072822a --- /dev/null +++ b/avr-test2/src/launch_effect.h @@ -0,0 +1,15 @@ +#ifndef LAUNCH_H +#define LAUNCH_H + +#include "cube.h" + +// Total number of effects +// Used in the main loop to loop through all the effects one by bone. +// Set this number one higher than the highest number inside switch() +// in launch_effect() in launch_effect.c +#define EFFECTS_TOTAL 27 + +void launch_effect (int effect); + +#endif + diff --git a/avr-test2/src/lisence.txt b/avr-test2/src/lisence.txt new file mode 100644 index 0000000..812dab5 --- /dev/null +++ b/avr-test2/src/lisence.txt @@ -0,0 +1,5 @@ +Created by Christian Moen (christian@lynet.no) and Ståle Kristoffersen (staalekb@ifi.uio.no) 2011. + +Lisence: http://creativecommons.org/licenses/by-nc-sa/3.0/ + +Happy hacking!! :D diff --git a/avr-test2/src/main.cpp b/avr-test2/src/main.cpp new file mode 100644 index 0000000..dfebb37 --- /dev/null +++ b/avr-test2/src/main.cpp @@ -0,0 +1,450 @@ +/* (c) copyright N.C. 2011 + * vim: ts=2 sw=2 et ai + */ + +// ATMEL ATMEGA8 +// +// +-\/-+ +// (RESET) PC6 1| |28 PC5 (ADC5/SCL) +// (RXD) PD0 2| |27 PC4 (ADC4/SDA) +// (TXD) PD1 3| |26 PC3 (ADC3) +// (INT0) PD2 4| |25 PC2 (ADC2) +// (INT1) PD3 5| |24 PC1 (ADC1) +// (XCK/T0) PD4 6| |23 PC0 (ADC0) +// VCC 7| |22 GND +// GND 8| |21 AREF +// (XTAL1/TOSC1) PB6 9| |20 AVCC +// (XTAL2/TOSC2) PB7 10| |19 PB5 (SCK) +// (T1) PD5 11| |18 PB4 (MISO) +// (AIN0) PD6 12| |17 PB3 (MOSI/OC2) +// (AIN1) PD7 13| |16 PB2 (SS/OC1B) +// (ICP1) PB0 14| |15 PB1 (OC1A) +// +----+ + +extern "C" { +#include <avr/io.h> +#include <avr/interrupt.h> + +#include <stdlib.h> // rand + + +#include "main.h" +#include "effect.h" +#include "launch_effect.h" +//#include "draw.h" + +} + +//int myrand() { return rand(); } + +#define CUBE_SIZE 8 + +//#define AXIS_X 1 +//#define AXIS_Y 2 +//#define AXIS_Z 3 + +volatile unsigned char cube[8][8]; +//volatile unsigned char current_layer = 0; +extern volatile unsigned char current_layer; +volatile bool in_wait = false; + +volatile unsigned char fb[CUBE_SIZE][CUBE_SIZE]; +/***************************************************************************** + * TIME MANAGEMENT + *****************************************************************************/ + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) +#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) + +// the prescaler is set so that timer0 ticks every 64 clock cycles, and the +// the overflow handler is called every 256 ticks. +#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) + +// the whole number of milliseconds per timer0 overflow +#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) + +// the fractional number of milliseconds per timer0 overflow. we shift right +// by three to fit these numbers into a byte. (for the clock speeds we care +// about - 8 and 16 MHz - this doesn't lose precision.) +#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) +#define FRACT_MAX (1000 >> 3) + +//volatile uint32_t timer0_overflow_count = 0; +volatile uint32_t timer0_millis = 0; +//static uint8_t timer0_fract = 0; + + +ISR(TIMER0_OVF_vect) +{ + // copy these to local variables so they can be stored in registers + // (volatile variables must be read from memory on every access) + uint32_t m = timer0_millis; + //uint8_t f = timer0_fract; + static uint8_t timer0_fract = 0; + + m += MILLIS_INC; + //f += FRACT_INC; + timer0_fract += FRACT_INC; + //if (f >= FRACT_MAX) { + if (timer0_fract >= FRACT_MAX) { + //f -= FRACT_MAX; + timer0_fract -= FRACT_MAX; + ++m; + } + + //timer0_fract = f; + timer0_millis = m; + //timer0_overflow_count++; + +//static uint32_t last_time = 0; + //if (timer0_overflow_count & 0x1) + //if (m - last_time >= 5) { + //debounce_keys(); // called nearly each 2ms (0,002048s) + //last_time = m; + //} +} + +/* +inline uint32_t millis() +{ + uint32_t m; + uint8_t oldSREG = SREG; + + // disable interrupts while we read timer0_millis or we might get an + // inconsistent value (e.g. in the middle of a write to timer0_millis) + cli(); + m = timer0_millis; + SREG = oldSREG; + + return m; +} +*/ + +inline uint32_t millis() +{ + return timer0_millis; +} + +void delay(uint32_t ms) +{ + in_wait = true; + uint32_t time1 = millis(); + while ((millis()) - time1 < ms); + in_wait = false; +} +//void delay_ms(uint16_t x) +//{ +// in_wait = true; +// uint8_t y, z; +// for ( ; x > 0 ; x--){ +// for ( y = 0 ; y < 90 ; y++){ +// for ( z = 0 ; z < 6 ; z++){ +// asm volatile ("nop"); +// } +// } +// } +// in_wait = false; +//} + + +/***************************************************************************** + * ACCESSORS + *****************************************************************************/ + +unsigned char inrange(int x, int y, int z); +void set_led(unsigned char x, unsigned char y, unsigned char z, bool on) +{ + + if (!inrange(x, y, z)) { + return; + } + + /* + assert(x >= 0 && x <= 7); + assert(y >= 0 && y <= 7); + assert(z >= 0 && z <= 7); + */ + + if (on) { + cube[y][z] |= ((unsigned char)1) << x; + } + else { + cube[y][z] &= ~(((unsigned char)1) << x); + } +} + +void clear_led() +{ + for (unsigned char z = 0; z < 8; ++z) { + for (unsigned char y = 0; y < 8; ++y) { + cube[y][z] = 0; + } + } +} + +/***************************************************************************** + * RENDER + *****************************************************************************/ + +ISR(TIMER2_COMP_vect) +{ + PORTD &= ~0x08; // layer down, should be done before latch + PORTD &= ~0x20; // latch low + unsigned char current_layer_ = current_layer; + for (unsigned char j = 0; j < 8; ++j) { + unsigned char val = cube[j][current_layer_]; + PORTD &= ~0x10; + PORTC = val; + PORTD = (PORTD & ~0xC0) | (val & 0xC0); + PORTD |= 0x10; + } + PORTB = (PORTB & ~0x07) | current_layer_; + PORTD |= 0x20; + ++current_layer_; + current_layer = current_layer_ & 0x07; + PORTD |= 0x08; // layer, should be done in the end and must be after latch +} + +void tmp2cube (void); +// Take input from a computer and load it onto the cube buffer +void rs232(void) +{ + int tempval; + int x = 0; + int y = 0; + int escape = 0; + + while (1) + { + // Switch state on red LED for debugging + // Should switch state every time the code + // is waiting for a byte to be received. + //LED_PORT ^= LED_RED; + + // Wait until a byte has been received + while ( !(UCSRA & (1<<RXC)) ); + + // Load the received byte from rs232 into a buffer. + tempval = UDR; + + // Uncommet this to echo data back to the computer + // for debugging purposes. + //UDR = tempval; + + // Every time the cube receives a 0xff byte, + // it goes into sync escape mode. + // if a 0x00 byte is then received, the x and y counters + // are reset to 0. This way the x and y counters are + // always the same on the computer and in the cube. + // To send an 0xff byte, you have to send it twice! + + // Go into sync escape mode + if (tempval == 0xff) + { + // Wait for the next byte + while ( !(UCSRA & (1<<RXC)) ); + // Get the next byte + tempval = UDR; + + // Sync signal is received. + // Reset x and y counters to 0. + if (tempval == 0x00) + { + x = 0; + y = 0; + escape = 1; + } + // if no 0x00 byte is received, proceed with + // the byte we just received. + } + + if (escape == 0) + { + // Load data into the current position in the buffer + fb[x][y] = tempval; + + // Check if we have reached the limits of the buffer array. + if (y == 7) + { + if (x == 7) + { + // All data is loaded. Reset both counters + y = 0; + x = 0; + // Copy the data onto the cube. + tmp2cube(); + } else + { + // A layer is loaded, reset y and increment x. + x++; + y = 0; + } + } else + { + // We are in the middle of loading a layer. increment y. + y++; + } + + } else + { + escape = 0; + } + } +} + + + + +/***************************************************************************** + * MAIN + *****************************************************************************/ + +int main() +{ + /* + * ======================================================================= + * Initialisation + * ======================================================================= + */ + + //*** init time management + TCNT0 = 0; // init timer count to 0 + TCCR0 |= 0x03; // prescaler: 64 + TIMSK |= 0x01; // enable timer 0 overflow interrupt + + // Timer 2 + // Frame buffer interrupt + // 14745600/128/11 = 10472.72 interrupts per second + // 10472.72/8 = 1309 frames per second + OCR2 = 11; // interrupt at counter = 10 + TCCR2 |= (1 << CS20) | (0 << CS21) | (1 << CS22); // Prescaler = 128. + TCCR2 |= (1 << WGM21); // CTC mode. Reset counter when OCR2 is reached. + TCNT2 = 0x00; // initial counter value = 0; + TIMSK |= (1 << OCIE2); // Enable CTC interrupt + + PORTD = 0; + PORTB = 0; + PORTC = 0; + DDRD = 0xff; + DDRB = 0xff; + DDRC = 0xff; + + /* + * ======================================================================= + * Serial port init + * ======================================================================= + */ + + // Initiate uart + // USART Baud rate is defined in MYUBRR + //UBRRH = BAUD_PRESCALE >> 8; + //UBRRL = BAUD_PRESCALE; + //// UCSRC - USART control register + //// bit 7-6 sync/ascyn 00 = async, 01 = sync + //// bit 5-4 parity 00 = disabled + //// bit 3 stop bits 0 = 1 bit 1 = 2 bits + //// bit 2-1 frame length 11 = 8 + //// bit 0 clock polarity = 0 + ////UCSRC = 0b10000110; + //// Enable RS232, tx and rx + //UCSRB = (1<<RXEN)|(1<<TXEN); + //UCSRC=(1<<URSEL)|(3<<UCSZ0); + ////UDR = 0x00; // send an empty byte to indicate powerup. + +#if 1 +#define BAUDRATE 38400 +#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1) + UBRRH = (uint8_t)(BAUD_PRESCALLER>>8); + UBRRL = (uint8_t)(BAUD_PRESCALLER); + //UBRRH = (uint8_t)(0); + //UBRRL = (uint8_t)(0); + UCSRC = (1<<URSEL)|(3<<UCSZ0); + UCSRB = (1<<RXEN)|(1<<TXEN); +#undef BAUDRATE +#undef BAUD_PRESCALLER +#endif + + //*** set interupts + sei(); + + /* + * ======================================================================= + * MAIN LOOP + * ======================================================================= + */ + + //while (1) { delay(1000); UDR = 'a'; } + //while (1) { UDR = 'a'; } + //DDRD |= 0x02; while (1) { delay(1000); PORTD ^= 0x02; } + + rs232(); + //while (1) + //{ + // // Show the effects in a predefined order + // for (char i=0; i<EFFECTS_TOTAL; i++) + // launch_effect(i); + + // // Show the effects in a random order. + // // Comment the two lines above and uncomment this + // // if you want the effects in a random order. + // //launch_effect(rand()%EFFECTS_TOTAL); + //} + + + for (;;) { + + //clear_led(); + //delay_ms(1000); + for (unsigned char z = 0; z < 8; ++z) { + for (unsigned char y = 0; y < 8; ++y) { + cube[y][z] = 0xFF; + } + } + //continue; + delay(5000); + + clear_led(); + for (char z = 0; z < 8; ++z) { + for (char y = 0; y < 8; ++y) { + for (char x = 0; x < 8; ++x) { + set_led(x, y, z, true); + //delay(5); + delay(100); + //delay(500); + //delay(1000); + //delay_ms(1000); + } + } + } + + // Show the effects in a predefined order + //for (char i=0; i<EFFECTS_TOTAL; i++) + //launch_effect(i); + //sendvoxels_rand_z(20,220,2000); + //effect_rain(100); + //effect_random_filler(5,1); + //effect_z_updown(20,1000); + //effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000); + //effect_blinky2(); + + + // Show the effects in a random order. + // Comment the two lines above and uncomment this + // if you want the effects in a random order. + //launch_effect(rand()%EFFECTS_TOTAL); + + //effect_boxside_randsend_parallel (AXIS_X, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_X, 1, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Y, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Y, 1, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Z, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Z, 1, 150, 1); + + + //delay(1000); + //PORTB ^= 0x01; + } + + return 0; // normally never return, just to be complient with c99 standard +} diff --git a/avr-test2/src/main.cpp.bakup b/avr-test2/src/main.cpp.bakup new file mode 100644 index 0000000..825c74d --- /dev/null +++ b/avr-test2/src/main.cpp.bakup @@ -0,0 +1,447 @@ +/* (c) copyright N.C. 2011 */ + +// ATMEL ATMEGA8 +// +// +-\/-+ +// (RESET) PC6 1| |28 PC5 (ADC5/SCL) +// (RXD) PD0 2| |27 PC4 (ADC4/SDA) +// (TXD) PD1 3| |26 PC3 (ADC3) +// (INT0) PD2 4| |25 PC2 (ADC2) +// (INT1) PD3 5| |24 PC1 (ADC1) +// (XCK/T0) PD4 6| |23 PC0 (ADC0) +// VCC 7| |22 GND +// GND 8| |21 AREF +// (XTAL1/TOSC1) PB6 9| |20 AVCC +// (XTAL2/TOSC2) PB7 10| |19 PB5 (SCK) +// (T1) PD5 11| |18 PB4 (MISO) +// (AIN0) PD6 12| |17 PB3 (MOSI/OC2) +// (AIN1) PD7 13| |16 PB2 (SS/OC1B) +// (ICP1) PB0 14| |15 PB1 (OC1A) +// +----+ + +extern "C" { +#include <avr/io.h> +#include <avr/interrupt.h> + +#include <stdlib.h> // rand + + +#include "main.h" +#include "effect.h" +#include "launch_effect.h" +//#include "draw.h" + +} + +//int myrand() { return rand(); } + +#define CUBE_SIZE 8 + +//#define AXIS_X 1 +//#define AXIS_Y 2 +//#define AXIS_Z 3 + +volatile unsigned char cube[8][8]; +//volatile unsigned char current_layer = 0; +extern volatile unsigned char current_layer; +volatile bool in_wait = false; + +volatile unsigned char fb[CUBE_SIZE][CUBE_SIZE]; +/***************************************************************************** + * TIME MANAGEMENT + *****************************************************************************/ + +#define clockCyclesPerMicrosecond() ( F_CPU / 1000000L ) +#define clockCyclesToMicroseconds(a) ( (a) / clockCyclesPerMicrosecond() ) +#define microsecondsToClockCycles(a) ( (a) * clockCyclesPerMicrosecond() ) + +// the prescaler is set so that timer0 ticks every 64 clock cycles, and the +// the overflow handler is called every 256 ticks. +#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256)) + +// the whole number of milliseconds per timer0 overflow +#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000) + +// the fractional number of milliseconds per timer0 overflow. we shift right +// by three to fit these numbers into a byte. (for the clock speeds we care +// about - 8 and 16 MHz - this doesn't lose precision.) +#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3) +#define FRACT_MAX (1000 >> 3) + +//volatile uint32_t timer0_overflow_count = 0; +volatile uint32_t timer0_millis = 0; +//static uint8_t timer0_fract = 0; + + +ISR(TIMER0_OVF_vect) +{ + // copy these to local variables so they can be stored in registers + // (volatile variables must be read from memory on every access) + uint32_t m = timer0_millis; + //uint8_t f = timer0_fract; + static uint8_t timer0_fract = 0; + + m += MILLIS_INC; + //f += FRACT_INC; + timer0_fract += FRACT_INC; + //if (f >= FRACT_MAX) { + if (timer0_fract >= FRACT_MAX) { + //f -= FRACT_MAX; + timer0_fract -= FRACT_MAX; + ++m; + } + + //timer0_fract = f; + timer0_millis = m; + //timer0_overflow_count++; + +//static uint32_t last_time = 0; + //if (timer0_overflow_count & 0x1) + //if (m - last_time >= 5) { + //debounce_keys(); // called nearly each 2ms (0,002048s) + //last_time = m; + //} +} + +/* +inline uint32_t millis() +{ + uint32_t m; + uint8_t oldSREG = SREG; + + // disable interrupts while we read timer0_millis or we might get an + // inconsistent value (e.g. in the middle of a write to timer0_millis) + cli(); + m = timer0_millis; + SREG = oldSREG; + + return m; +} +*/ + +inline uint32_t millis() +{ + return timer0_millis; +} + +void delay(uint32_t ms) +{ + in_wait = true; + uint32_t time1 = millis(); + while ((millis()) - time1 < ms); + in_wait = false; +} +//void delay_ms(uint16_t x) +//{ +// in_wait = true; +// uint8_t y, z; +// for ( ; x > 0 ; x--){ +// for ( y = 0 ; y < 90 ; y++){ +// for ( z = 0 ; z < 6 ; z++){ +// asm volatile ("nop"); +// } +// } +// } +// in_wait = false; +//} + + +/***************************************************************************** + * ACCESSORS + *****************************************************************************/ + +unsigned char inrange(int x, int y, int z); +void set_led(unsigned char x, unsigned char y, unsigned char z, bool on) +{ + + if (!inrange(x, y, z)) { + return; + } + + /* + assert(x >= 0 && x <= 7); + assert(y >= 0 && y <= 7); + assert(z >= 0 && z <= 7); + */ + + if (on) { + cube[y][z] |= ((unsigned char)1) << x; + } + else { + cube[y][z] &= ~(((unsigned char)1) << x); + } +} + +void clear_led() +{ + for (unsigned char z = 0; z < 8; ++z) { + for (unsigned char y = 0; y < 8; ++y) { + cube[y][z] = 0; + } + } +} + +/***************************************************************************** + * RENDER + *****************************************************************************/ + +ISR(TIMER2_COMP_vect) +{ + //if (!in_wait) return; + PORTD &= ~0x20; // layer and latch low + unsigned char current_layer_ = current_layer; + for (unsigned char j = 0; j < 8; ++j) { + //for (char j = 0; j < 4; ++j) { + unsigned char val = cube[j][current_layer_]; + PORTD &= ~0x10; + PORTC = val; + PORTD = (PORTD & ~0xC0) | (val & 0xC0); + PORTD |= 0x10; + } + PORTB = (PORTB & ~0x07) | current_layer_; + PORTD |= 0x20; + ++current_layer_; + current_layer = current_layer_ & 0x07; + //if (current_layer_ > 7) current_layer_ = 0; + //current_layer = current_layer_; + //PORTC |= 0x28; // layer and latch high +} + +void tmp2cube (void); +// Take input from a computer and load it onto the cube buffer +void rs232(void) +{ + int tempval; + int x = 0; + int y = 0; + int escape = 0; + + while (1) + { + // Switch state on red LED for debugging + // Should switch state every time the code + // is waiting for a byte to be received. + //LED_PORT ^= LED_RED; + + // Wait until a byte has been received + while ( !(UCSRA & (1<<RXC)) ); + + // Load the received byte from rs232 into a buffer. + tempval = UDR; + + // Uncommet this to echo data back to the computer + // for debugging purposes. + UDR = tempval; + + // Every time the cube receives a 0xff byte, + // it goes into sync escape mode. + // if a 0x00 byte is then received, the x and y counters + // are reset to 0. This way the x and y counters are + // always the same on the computer and in the cube. + // To send an 0xff byte, you have to send it twice! + + // Go into sync escape mode + if (tempval == 0xff) + { + // Wait for the next byte + while ( !(UCSRA & (1<<RXC)) ); + // Get the next byte + tempval = UDR; + + // Sync signal is received. + // Reset x and y counters to 0. + if (tempval == 0x00) + { + x = 0; + y = 0; + escape = 1; + } + // if no 0x00 byte is received, proceed with + // the byte we just received. + } + + if (escape == 0) + { + // Load data into the current position in the buffer + fb[x][y] = tempval; + + // Check if we have reached the limits of the buffer array. + if (y == 7) + { + if (x == 7) + { + // All data is loaded. Reset both counters + y = 0; + x = 0; + // Copy the data onto the cube. + tmp2cube(); + } else + { + // A layer is loaded, reset y and increment x. + x++; + y = 0; + } + } else + { + // We are in the middle of loading a layer. increment y. + y++; + } + + } else + { + escape = 0; + } + } +} + + + + +/***************************************************************************** + * MAIN + *****************************************************************************/ +#define USART_BAUDRATE 115200 +#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1) +//#define BAUD_PRESCALE 51 +int main() +{ + /* + * ======================================================================= + * Initialisation + * ======================================================================= + */ + + //*** init time management + TCNT0 = 0; // init timer count to 0 + TCCR0 |= 0x03; // prescaler: 64 + TIMSK |= 0x01; // enable timer 0 overflow interrupt + + // Timer 2 + // Frame buffer interrupt + // 14745600/128/11 = 10472.72 interrupts per second + // 10472.72/8 = 1309 frames per second + OCR2 = 11; // interrupt at counter = 10 + TCCR2 |= (1 << CS20) | (0 << CS21) | (1 << CS22); // Prescaler = 128. + TCCR2 |= (1 << WGM21); // CTC mode. Reset counter when OCR2 is reached. + TCNT2 = 0x00; // initial counter value = 0; + TIMSK |= (1 << OCIE2); // Enable CTC interrupt + + PORTD = 0; + PORTB = 0; + PORTC = 0; + DDRD = 0xff; + DDRB = 0xff; + DDRC = 0xff; + + /* + * ======================================================================= + * Serial port init + * ======================================================================= + */ + + // Initiate uart + // USART Baud rate is defined in MYUBRR + //UBRRH = BAUD_PRESCALE >> 8; + //UBRRL = BAUD_PRESCALE; + //// UCSRC - USART control register + //// bit 7-6 sync/ascyn 00 = async, 01 = sync + //// bit 5-4 parity 00 = disabled + //// bit 3 stop bits 0 = 1 bit 1 = 2 bits + //// bit 2-1 frame length 11 = 8 + //// bit 0 clock polarity = 0 + ////UCSRC = 0b10000110; + //// Enable RS232, tx and rx + //UCSRB = (1<<RXEN)|(1<<TXEN); + //UCSRC=(1<<URSEL)|(3<<UCSZ0); + ////UDR = 0x00; // send an empty byte to indicate powerup. + +#define BAUDRATE 9600 +#define BAUD_PRESCALLER (((F_CPU / (BAUDRATE * 16UL))) - 1) + // try again... + UBRRH = (uint8_t)(BAUD_PRESCALLER>>8); + UBRRL = (uint8_t)(BAUD_PRESCALLER); + UCSRC = (1<<URSEL)|(3<<UCSZ0); + + UCSRB = (1<<RXEN)|(1<<TXEN); +#undef BAUDRATE +#undef BAUD_PRESCALLER + + //*** set interupts + //sei(); + + /* + * ======================================================================= + * MAIN LOOP + * ======================================================================= + */ + + rs232(); + //while (1) + //{ + // // Show the effects in a predefined order + // for (char i=0; i<EFFECTS_TOTAL; i++) + // launch_effect(i); + + // // Show the effects in a random order. + // // Comment the two lines above and uncomment this + // // if you want the effects in a random order. + // //launch_effect(rand()%EFFECTS_TOTAL); + //} + + + for (;;) { + + //clear_led(); + //delay_ms(1000); + for (unsigned char z = 0; z < 8; ++z) { + for (unsigned char y = 0; y < 8; ++y) { + cube[y][z] = 0xFF; + } + } + //continue; + delay(5000); + + clear_led(); + for (char z = 0; z < 8; ++z) { + for (char y = 0; y < 8; ++y) { + for (char x = 0; x < 8; ++x) { + set_led(x, y, z, true); + //delay(5); + delay(100); + //delay(500); + //delay(1000); + //delay_ms(1000); + } + } + } + + // Show the effects in a predefined order + //for (char i=0; i<EFFECTS_TOTAL; i++) + //launch_effect(i); + //sendvoxels_rand_z(20,220,2000); + //effect_rain(100); + //effect_random_filler(5,1); + //effect_z_updown(20,1000); + //effect_wormsqueeze (2, AXIS_Z, -1, 100, 1000); + //effect_blinky2(); + + + // Show the effects in a random order. + // Comment the two lines above and uncomment this + // if you want the effects in a random order. + //launch_effect(rand()%EFFECTS_TOTAL); + + //effect_boxside_randsend_parallel (AXIS_X, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_X, 1, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Y, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Y, 1, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Z, 0, 150, 1); + //effect_boxside_randsend_parallel (AXIS_Z, 1, 150, 1); + + + //delay(1000); + //PORTB ^= 0x01; + } + + return 0; // normally never return, just to be complient with c99 standard +} diff --git a/avr-test2/src/main.h b/avr-test2/src/main.h new file mode 100644 index 0000000..94d3564 --- /dev/null +++ b/avr-test2/src/main.h @@ -0,0 +1,50 @@ +/* (c) copyright N.C. 2011 + * vim: ts=2 sw=2 et ai + */ + +#ifndef MAIN_H +#define MAIN_H + +#include <avr/io.h> +#include <avr/pgmspace.h> +#include <avr/interrupt.h> +#include <stdlib.h> + +#include "cube.h" + +// Define USART stuff +//#define FOSC 14745600 +#define FOSC 16000000 +#define BAUD 38400 +#define MYUBRR (((((FOSC * 10) / (16L * BAUD)) + 5) / 10) - 1) + +#define DATA_BUS PORTA +#define LAYER_SELECT PORTC +#define LATCH_ADDR PORTB +#define LATCH_MASK 0x07 +#define LATCH_MASK_INV 0xf8 +#define OE_PORT PORTB +#define OE_MASK 0x08 + +// Red led on D2 +#define LED_RED 0x04 +// Green led D3 +#define LED_GREEN 0x08 +// Program led on D4 +#define LED_PGM 0x10; +// Leds connected to port D +#define LED_PORT PORTD +// Rs232 button on D5 +#define RS232_BTN 0x20 +// Main button on B4 +#define MAIN_BTN 0x10 + +void ioinit (void); +void bootmsg (void); + +volatile unsigned char current_layer; +volatile unsigned char pgm_mode; +void rs232(void); +unsigned int bootwait (void); +#endif + |