lunes, 14 de octubre de 2013

Anarchist [7x5 led matrix shooter]

The anarchist must be kept safe from the waves of pigs who want to capture him, by throwing molotov cocktails.
LED 7x5 Matrix controlled by a PIC16F876A + joystick and button, powered by USB or 4 AA cased in a little plastic box.

-*-* Photos













*-*- Code

// -*- ANARCHIST:
//     the A-guy is surrounded by the pigs. help him be free.
//


/*
-*- MAIN
 10 inicio
 20 leer movimiento
    21 filtrar (dentro de paredes)
 30 mover chico
    31 dibujar
 40 leer disparo
    41 ejecutar rutina de disparo
    42 destruir cerdos afectados
 60 victoria?
 70 verificar avance de cerdos
 80 derrota?
 90 return


-*-* SCENE
* y0 - - o o o
*    - - o o o
*    - - o o -
*    + - - o o
*    - - o o o
*    - - - - o
* y6 - - - - o
*   x0      x4  <-scene[0..4]

 \***************************************/


volatile unsigned char scene[5];         // a char for each column
volatile signed char a_p;                // anarchist position
volatile signed char cuenta_ciclos;      // for increasing speed as game goes on;
signed char ctrl, movimiento_x,  movimiento_y, ref_x, ref_y, aux_row, aux_col, i, j, a, b, sh, jp;
unsigned int k;                          // counter
signed char disparo, salto, movimiento, collision, victoria, captura;    // FLGS
unsigned char buffer, period_dif, period_ref;         // period <- can control velocity with this
unsigned int score;
/* *************************************** */
/* *************************************** */

void set_ports()
  // initialize control registers and ports
  {
  ADCON1 = 0x00;   // portA is full analog
  TRISA  = 0xFF;   // portA is input
  TRISB = 0x00;    // portB is ROWS
  PORTB = 0x00;    // initialize portB
  TRISC = 0x00;    // portC is COLUMNS ONE  (verde)
  PORTC = 0xFF;    // initialize portC
  }

void read_controls()
  // read analog_val and compares with prev_analog_val
  // sets ctrl01 and ctrl02 according to difference
  {
  a = Adc_Read(0)>>6; // it needs just 4 msb
  if ((a - ref_x) == 0){movimiento_x = 0;}
  else { movimiento_x = (a - ref_x)>0 ? 1: -1; }
  b = Adc_Read(1)>>6; // it needs just 4 msb
  if ((b - ref_y) == 0){movimiento_y = 0;}
  else { movimiento_y = (b - ref_y)>0 ? 1: -1; }

  sh = Adc_Read(2)>>4;
  disparo = (sh > 0) ? 1 : 0;
  jp = Adc_Read(3)>>4;
  salto = (jp > 0) ? 1 : 0;
  }


void show_scene()                        // HOW TO SHOW
  {
  for (i=0; i<=4; i++)       // each column as an array of x
    {
    aux_col = scene[i];     //   put the row vector in column i
    PORTB = aux_col;        //   set the ports
    if (i==0)               //     initialize
      {aux_row = 1;}
    else                    //     shift previous val
      {aux_row = aux_row << 1;}
    PORTC = ~aux_row;
    Delay_ms(1);
    }
  }


void mover_chico_x()
  // actualiza posición del anarquista en funcion del movimiento
  // 1 : inc y, scene[0] <<
  // -1: dec y, scene[0] >>
  // 0 : keep
  {
  if (movimiento_x == 1)
    {
    if (a_p < 6)
      {
      a_p++;
      scene[0] = scene[0]<<1;
      }
    }
  if (movimiento_x == -1)
    {
    if (a_p > 0)
      {
      a_p--;
      scene[0] = scene[0]>>1;
      }
    }
  if (movimiento_x == 0)
    {
    a_p = a_p;
    }
  }


void disparo_routine()
  {
  collision = 0;                                 // initialize
  victoria = 0;
  buffer = 1;
  for (j=0; j<5; j++)                       // sweep the scene
    {
    if (j==0) { show_scene(); }             // if a-guy col just show scene
    // A. shot_propagation_routine
    else
      {
      if ((scene[j] & scene[0]) == scene[0])// B. collision_routine
        {
        scene[j] = scene[j] ^ scene[0];     // i. scene with destruction
        show_scene;
        break;                              // break the for
        }
      else                                  // -*-*traspaso
        {
        buffer = scene[j];
        scene[j] = scene[j] | scene[0];     // i. combine the scene
        show_scene();
        scene[j] = buffer;
        }
      }
    }
  /*
  for (j=1; j<5 ;j++)
    {
    victoria = (victoria | scene[j]);
    }
  if (victoria == 0) {victoria = 1;}
  else {victoria = 0;}
  */
  }


void avance_tirania()
  {
  captura = 0;                                   // capture flag
  for(j=1; j<5; j++)
    {
    if ((j == 1) & (scene[j]!=0)) {captura = 1;} // you lose
    else;
    scene[j] = scene[j+1];                       // else shift policemen and reinforce
    if (j == 4) { scene[j] = 0x7F; }
    else;
    cuenta_ciclos = 0;
    }
  // if (captura == 1): you lose; else continue;
  }

void init_scene()
  {
  scene[0] = 0b00001000;    // here there is an anarchist
  scene[1] = 0b00000000;    //
  scene[2] = 0b00001000;    //
  scene[3] = 0b00011100;    //
  scene[4] = 0b00111110;    // and here the first line of pigs
  a_p = 3;                  // position of anarchy
  victoria = 0;
  disparo = 0;
  cuenta_ciclos = 0;
  period_dif=50;
  }

void victory_routine()
  {
  unsigned int d;
  // begins victory display
  scene[4] = 0x00;
  scene[3] = ((score<<8)>>9);
  scene[2] = 0x00;
  scene[1] = (score>>9);
  scene[0] = 0x00;
  for (d=0; d<200; d++) { show_scene(); }
  PORTC = 0xFF;
  Delay_ms(500);
  for (d=0; d<200; d++) { show_scene(); }
  // end of victory display
  // maintenance routines
  victoria = 0;
  Delay_ms(500);
  init_scene();
  score = 0;
  }

void capture_routine()
  {
  unsigned int d;
  // begins capture display
  scene[4] = 0x00;
  scene[3] = ((score<<8)>>9);
  scene[2] = 0x00;
  scene[1] = (score>>9);
  scene[0] = 0x00;
  for (d=0; d<200; d++) { show_scene(); }
  PORTC = 0xFF;
  Delay_ms(500);
  for (d=0; d<200; d++) { show_scene(); }
  // end of capture display
  // maintenance routines
  captura = 0;
  Delay_ms(500);
  init_scene();
  score = 0;
  }

/* *************************************** */
/* *************************************** */

void main()
  {
  // SETUP
  set_ports();
  ref_x = Adc_Read(0)>>6;
  ref_y = Adc_Read(1)>>6;
  period_dif=50;
  period_ref=12;
  score=0;
  init_scene();                  // 10 init

  // LOOP
  while (1)
    {
    read_controls();             // 20 read controls
    mover_chico_x();             // 30 mover anarquista

    if (disparo==1)              // 40 rutina arrojar_molotov
      {
      disparo_routine();
      }
    else;

    if (victoria==1)             // 50 rutina de la victoria
      {
      victory_routine();
      }
    else;

    if (cuenta_ciclos > period_dif)   // 60 avance de tirania
      {
      avance_tirania();
      score++;
      if (captura == 1)          // 70 rutina de captura
        {
        capture_routine();
        }
      else;
      }
    else;
    cuenta_ciclos++;
    if (((score << 11) >> 11) == 0x10 )
      {
      period_dif -= 1;
      }
    else;
    for (k=0; k<=period_ref; k++)    // 80 dibuja un rato
      {
      show_scene();
      }
    }
  }


*--**-- Video

martes, 8 de octubre de 2013

steampong

steampong is about two cats playing pong in kind of a steampunk universe.
usb powered, 8x8 led matrix, with extra cats that celebrates.

--*--* imgs











--*--*video


--*--* code:

// -*- STEAM_PONG:
//     two cats playing pong with potentiometers.
//    
/*
 -*- MAIN
 10 inicio
 20 leer movimiento
     21 filtrar (dentro de paredes)
 30 mover paletas
 40 mover bola
 50 dibujar
 60 return
*/

/***************************************\
 * scene(8x8 matrix):
 * 0 - - - - - - - -
 *   - - - - - - - -
 *   - - - - + - - -
 *   + - - - - - - -
 *   + - - - - - - +
 *   - - - - - - - +
 *   - - - - - - - -
 * 7 - - - - - - - -
 *   0             7  <-scene[0..7]
 \***************************************/


volatile unsigned char framebuffer_pos = 0x00;
volatile unsigned char scene[8]; // a char for each column

volatile signed char o_x, o_y;          // ball x & y positions
volatile signed char o_dx, o_dy;        // ball x & y directions
volatile signed char i1_p, i2_p;        // players positions
volatile signed char redraw, speed_counter, current_speed;    // 1 if must redraw; increasing speed as game goes on; actual speed; and score.
const char speed_bumper = 10;    // increase speed after this cycles
//const unsigned char d1[] = {0x00, 0x10, 0x20, 0x7f, 0x00}; /* the number 1 */
//const unsigned char d2[] = {0x47, 0x49, 0x49, 0x49, 0x31}; /* the number 2 */

signed char ctrl01, ctrl02, analog_val01, analog_val02, ant_analog_val01, ant_analog_val02, aux_portB, aux_portC, i,j, aux_a, aux_b;
signed char suelta, rebote_paleta, pos;
unsigned int k;                  // counter
unsigned char period=30;         // period <- can control velocity with this

/* *************************************** */
/* *************************************** */

void set_ports()
  // initialize control registers and ports
  {
  ADCON1 = 0x00;   // portA is full analog
  TRISA  = 0xFF;   // portA is input
  TRISB = 0x00;    // portB is ROWS
  PORTB = 0x00;    // initialize portB
  TRISC = 0x00;    // portC is COLUMNS
  PORTC = 0xFF;    // initialize portC
  }

void read_controls()
  // read analog_val and compares with ant_analog_val
  // sets ctrl01 and ctrl02 according to difference
  {
  analog_val01 = Adc_Read(0)>>6; // it needs just 4 msb
  analog_val02 = Adc_Read(1)>>6;
 
  aux_a = analog_val01 - ant_analog_val01;
  aux_b = analog_val02 - ant_analog_val02;

  if (aux_a == 0) ctrl01 = 0;
  else ctrl01 = (aux_a > 0) ? 1 : -1;
  if (aux_b == 0) ctrl02 = 0;
  else ctrl02 = (aux_b > 0) ? 1 : -1;
 
  ant_analog_val01 = analog_val01;
  ant_analog_val02 = analog_val02;
  }

void mover_paletas()
  // actualiza posición de las paletas en función de ctrl0X
  // 1 : inc y, scene <<
  // -1: dec y, scene >>
  // 0 : keep
  {
  if (ctrl01 == 1)
    {
    if (i1_p < 6)
      {
      i1_p++;
      scene[0] = scene[0]<<1;
      }
    }
  if (ctrl01 == -1)
    {
    if (i1_p > 0)
      {
      i1_p--;
      scene[0] = scene[0]>>1;
      }
    }
  if (ctrl01 == 0)
    {
    i1_p = i1_p;
    }

  if (ctrl02 == 1)
    {
    if (i2_p < 6)
      {
      i2_p++;
      scene[7] = scene[7]<<1;
      }
    }
  if (ctrl02 == -1)
    {
    if (i2_p > 0)
      {
      i2_p--;
      scene[7] = scene[7]>>1;
      }
    }
  if (ctrl02 == 0)
    {
    i2_p = i2_p;
    }
  }


void init_scene()
  {
  scene[0] = 0b00011000;    // player 01
  scene[1] = 0b00000000;    //
  scene[2] = 0b00010000;    //
  scene[3] = 0b00000000;    //
  scene[4] = 0b00000000;    //
  scene[5] = 0b00000000;    //
  scene[6] = 0b00000000;    //
  scene[7] = 0b00011000;    // player 02
  i1_p = 3;                 // positions of p1
  i2_p = 3;                 // positions of p2
  o_x = 2;                  // ball x coo
  o_y = 4;                  // ball y coo
  o_dx = 1;                 // ball x dir
  o_dy = 0;                 // ball y dir
  }

void show_scene()
  {
  for (i=0; i<8; i++)       // columns x
    {
    aux_portB = scene[i];   //   put the row vector in column i
    PORTB = aux_portB;      //   set the ports
    if (i==0)               //     initialize
      {aux_portC = 1;}
    else                    //     shift previous val
      {aux_portC = aux_portC << 1;}
    PORTC = ~aux_portC;
    Delay_ms(1);
    }
  }

void point_for_one()
  {
  volatile unsigned char catscene[28] = {0x00, 0x18, 0x24, 0x00,
                                         0x04, 0x02, 0x14, 0x00,
                                         0x20, 0x20, 0x00, 0x14,
                                         0x02, 0x04, 0x00, 0x24,
                                         0x18, 0x00, 0x20, 0x1C,
                                         0x00, 0x04, 0x0A, 0x00,
                                         0x00, 0x00, 0x00, 0x00};
  unsigned int d;
  for (d=0; d<24;d++)
    {
    j = 0;
    while(j<10)
      {
      for (i=d; i<d+8; i++)       // columns x
        {
        aux_portB = catscene[i];   //   put the row vector in column i
        PORTB = aux_portB;      //   set the ports
        if (i==d)               //     initialize
          {aux_portC = 1;}
        else                    //     shift previous val
          {aux_portC = aux_portC << 1;}
        PORTC = ~aux_portC;
        Delay_ms(1);
        }
      j++;
      }
    }
  init_scene();
  }

void point_for_two()
  {
  volatile unsigned char catscene[28] = {0x00, 0x18, 0x24, 0x00,
                                         0x04, 0x02, 0x14, 0x00,
                                         0x20, 0x20, 0x00, 0x14,
                                         0x02, 0x04, 0x00, 0x24,
                                         0x18, 0x00, 0x20, 0x1C,
                                         0x00, 0x0A, 0x04, 0x00,
                                         0x00, 0x00, 0x00, 0x00};
  unsigned int d;
  for (d=0; d<24; d++)
    {
    j = 0;
   
    while(j<10)
      {
      for (i=d; i<d+8; i++)         // columns x
        {
        aux_portB = catscene[i];   //   put the row vector in column i
        PORTB = aux_portB;         //   set the ports
        if (i==d) aux_portC = 1;   //     initialize
        else aux_portC = aux_portC << 1; //     shift previous val
        PORTC = ~aux_portC;
        Delay_ms(1);
        }
      j++;
      }
    }
  init_scene();
  }


void mover_bola()
  // mover bola en función de dx, dy, i1_p, i2_p
  //   41 si golpea pared: pared()
  //   42 si golpea paleta: casos{esquina_up, esquina_dn, simple}
  //   43 si bola suelta: casos{win01, win02, simple}
  {
  // pared
  if (o_y == 0) o_dy = -o_dy;
  if (o_y == 7) o_dy = -o_dy;
 
  // golpe_paleta
  suelta = 0;
  rebote_paleta = 0;
  pos = (o_x == 1) ? i1_p : i2_p;
  if (o_x == 1 || o_x == 6)            // detecta x
    {
    suelta = 1;
    if (o_y == pos || o_y == pos+1)    // rebote normal
      {
      o_dx = -o_dx;
      suelta = 0;
      rebote_paleta = 1;
      }
    else if (o_y == pos-1 && o_dy == 1)// esquina_up
      {
      o_dx = -o_dx;
      o_dy = -o_dy;
      suelta = 0;
      rebote_paleta = 1;
      }
    else if (o_y == pos+2 && o_dy == -1)//esquina_dn
      {
      o_dx = -o_dx;
      o_dy = -o_dy;
      suelta = 0;
      rebote_paleta = 1;
      }
    }
 
  // suelta
  if (suelta)
    {
    if (o_x == 1)                      // *point for 2!
      {
      o_x += o_dx;
      o_y += o_dy;
      point_for_two();
      }
    else                               // *point for 1!
      {
      o_x += o_dx;
      o_y += o_dy;
      point_for_one();
      }
    }
 
  //si fue rebote en paleta ajusta direcciones
  if (rebote_paleta)
      {
      if (o_x == 1 && (ctrl01 == 1)  && (o_dy <  1)) o_dy++;
      if (o_x == 1 && (ctrl01 == -1) && (o_dy > -1)) o_dy--;
      if (o_x == 6 && (ctrl02 == 1)  && (o_dy <  1)) o_dy++;
      if (o_x == 6 && (ctrl02 == -1) && (o_dy > -1)) o_dy--;
      }
   
  // si hay pared después de rebote
  if (o_y == 0 && o_dy == -1) o_dy = -o_dy;
  if (o_y == 7 && o_dy ==  1) o_dy = -o_dy;

  // y finalmente mueve la bolita
  o_x += o_dx;
  o_y += o_dy;
  scene[1]=0x00; scene[2]=0x00; scene[3]=0x00;
  scene[4]=0x00; scene[5]=0x00; scene[6]=0x00;
  scene[o_x] = 0x01<<o_y;
  }


/* *************************************** */
// MAIN

/* *************************************** */

void main()
  {
  // SETUP
  set_ports();
 
  ant_analog_val01 = Adc_Read(0)>>6;
  ant_analog_val02 = Adc_Read(1)>>6;
  init_scene();                  // 10 init

  // LOOP
  while (1)
    {
    read_controls();             // 20 read controls
    mover_paletas();             // 30 mover paletas
    mover_bola();                // 40 mover bola
   
    for (k=0; k<=period; k++)    // 50 dibujar por un rato
      {
      show_scene();
      }
    }
  }