diff options
| author | vg <vgm+dev@devys.org> | 2020-07-07 16:24:01 +0200 | 
|---|---|---|
| committer | vg <vgm+dev@devys.org> | 2020-07-07 16:24:01 +0200 | 
| commit | 66dcf910bd4744d8ced56cb9586aa937a1a2d4c5 (patch) | |
| tree | df4dca1ae4af1e5df0be0d1f4f2cd0d54751f8e8 /test/arduinocube | |
| download | hic-66dcf910bd4744d8ced56cb9586aa937a1a2d4c5.tar.gz hic-66dcf910bd4744d8ced56cb9586aa937a1a2d4c5.tar.bz2 hic-66dcf910bd4744d8ced56cb9586aa937a1a2d4c5.zip  | |
Diffstat (limited to 'test/arduinocube')
| -rw-r--r-- | test/arduinocube/arduinocube.pde | 812 | 
1 files changed, 812 insertions, 0 deletions
diff --git a/test/arduinocube/arduinocube.pde b/test/arduinocube/arduinocube.pde new file mode 100644 index 0000000..40e926f --- /dev/null +++ b/test/arduinocube/arduinocube.pde @@ -0,0 +1,812 @@ +#include <avr/interrupt.h> +#include <string.h> +#define AXIS_X 1 +#define AXIS_Y 2 +#define AXIS_Z 3 + +#define delay_ms(x) delayMicroseconds((x)/1000) + +volatile unsigned char cube[8][8]; +volatile int current_layer = 0; + +void setup() +{ +    int i; + +    for(i=0; i<14; i++) +        pinMode(i, OUTPUT); + +    // Reset any PWM configuration that the arduino may have set up automagically! +    TCCR2A = 0x00; +    TCCR2B = 0x00; + +    TCCR2A |= (0x01 << WGM21); // CTC mode. clear counter on TCNT2 == OCR2A +    OCR2A = 10; // Interrupt every 25600th cpu cycle (256*100) +    TCNT2 = 0x00; // start counting at 0 +    TCCR2B |= (0x01 << CS22) | (0x01 << CS21); // Start the clock with a 256 prescaler + +    TIMSK2 |= (0x01 << OCIE2A); + + +    digitalWrite(13, HIGH); +} + +ISR (TIMER2_COMPA_vect) +{ +    char i; + +    // all layer selects off +    //PORTC = 0x00; +    //PORTB &= 0x0f; + +    //PORTB |= 0x08; // output enable off. + +    //digitalWrite(13, LOW); +    digitalWrite(8, LOW); + +    for (i=0; i<8; i++) +    { +        char line = cube[current_layer][i]; +        //PORTD = cube[current_layer][i]; +        //PORTB = (PORTB & 0xF8) | (0x07 & (i+1)); +        for (char j  = 0; j < 8; ++j, line >>= 1) { +            digitalWrite(9, LOW); +            digitalWrite(7, line & 1); +            //digitalWrite(7, HIGH); +            digitalWrite(9, HIGH); +        } +    } + +    //PORTB &= 0b00110111; // Output enable on. +    digitalWrite(8, HIGH); +    //digitalWrite(13, HIGH); + +    /* +    if (current_layer < 6) +    { +        PORTC = (0x01 << current_layer); +    } else if (current_layer == 6) +    { +        digitalWrite(12, HIGH); +    } else +    { +        digitalWrite(13, HIGH); +    } +    */ +    digitalWrite(12, current_layer & 0x1 ? HIGH : LOW); +    digitalWrite(11, current_layer & 0x2 ? HIGH : LOW); +    digitalWrite(10, current_layer & 0x4 ? HIGH : LOW); + + +    current_layer++; + +    if (current_layer == 8) +        current_layer = 0; +} + +void loop() +{ +    int i,x,y,z; + +    while (true) +    { + +        effect_planboing(AXIS_Z, 400); +        effect_planboing(AXIS_Y, 400); +        effect_planboing(AXIS_X, 400); + +        effect_blinky2(); + +        effect_random_filler(75,1); +        effect_random_filler(75,0); + +        effect_rain(100); + +        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); + +    } +} + + +// ========================================================================================== +//   Effect functions +// ========================================================================================== + +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); + +    } + +} + + +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); +    } +} + +// 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_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))); +        } +    } + +} + +// 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); +    } +} + +// ========================================================================================== +//   Draw functions +// ========================================================================================== + + +// 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 to ON +void clrvoxel(int x, int y, int z) +{ +    if (inrange(x,y,z)) +        cube[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 < 8 && y >= 0 && y < 8 && z >= 0 && z < 8) +    { +        return 0x01; +    } else +    { +        // One of the coordinates was outside the cube. +        return 0x00; +    } +} + +// 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 0x01; +        } else +        { +            return 0x00; +        } +    } else +    { +        return 0x00; +    } +} + +// 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<8) +    { +        for (i=0;i<8;i++) +            cube[z][i] = 0xff; +    } +} + +// Clears voxels in the same manner as above +void clrplane_z (int z) +{ +    int i; +    if (z>=0 && z<8) +    { +        for (i=0;i<8;i++) +            cube[z][i] = 0x00; +    } +} + +void setplane_x (int x) +{ +    int z; +    int y; +    if (x>=0 && x<8) +    { +        for (z=0;z<8;z++) +        { +            for (y=0;y<8;y++) +            { +                cube[z][y] |= (1 << x); +            } +        } +    } +} + +void clrplane_x (int x) +{ +    int z; +    int y; +    if (x>=0 && x<8) +    { +        for (z=0;z<8;z++) +        { +            for (y=0;y<8;y++) +            { +                cube[z][y] &= ~(1 << x); +            } +        } +    } +} + +void setplane_y (int y) +{ +    int z; +    if (y>=0 && y<8) +    { +        for (z=0;z<8;z++) +            cube[z][y] = 0xff; +    } +} + +void clrplane_y (int y) +{ +    int z; +    if (y>=0 && y<8) +    { +        for (z=0;z<8;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<8;z++) +    { +        for (y=0;y<8;y++) +        { +            cube[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"); +            } +        } +    } +} +*/ + + + +// 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 < 8; i++) +    { +        if (direction == -1) +        { +            ii = i; +        } else +        { +            ii = (7-i); +        } + + +        for (x = 0; x < 8; x++) +        { +            for (y = 0; y < 8; 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 < 8; x++) +    { +        for (y = 0; y < 8; 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); +        } +    } +} +  | 
