-
Programe y analice el anterior codigo, se dara cuenta que la tarea 1 apaga y prende cada 3 segundos la imagen 1 de goku, y la tarea 2 prende y apaga la imagen de goku cada 5 segundos.(Modifiquelo apra que sea cada 10 ms)
- Ahora modifiquemos las tareas para que hagan lo siguiente
void task1(void* pdata)
{
unsigned char animation=0;
// inicializo todas las imagenes en el mismo punto
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,0, 0);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,0, 0);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,0, 0);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,0, 0);
while (1)
{
animation++;
if(animation>3){animation=0;}
switch(animation){
case 0: IOWR(ON_OFF1_BASE,0,1);
IOWR(ON_OFF2_BASE,0,0);
IOWR(ON_OFF3_BASE,0,0);
IOWR(ON_OFF4_BASE,0,0);
break;
case 1: IOWR(ON_OFF1_BASE,0,0);
IOWR(ON_OFF2_BASE,0,1);
IOWR(ON_OFF3_BASE,0,0);
IOWR(ON_OFF4_BASE,0,0);
break;
case 2: IOWR(ON_OFF1_BASE,0,0);
IOWR(ON_OFF2_BASE,0,0);
IOWR(ON_OFF3_BASE,0,1);
IOWR(ON_OFF4_BASE,0,0);
break;
case 3: IOWR(ON_OFF1_BASE,0,0);
IOWR(ON_OFF2_BASE,0,0);
IOWR(ON_OFF3_BASE,0,0);
IOWR(ON_OFF4_BASE,0,1);
break;
}
//tiempo de retrazo
OSTimeDlyHMSM(0, 0, 0, 100);
}
}
void task2(void* pdata)
{
unsigned int pos_x=0,pos_y=0;
while (1)
{
pos_x++;
pos_y++;
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,pos_x, pos_y);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,pos_x, pos_y);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,pos_x, pos_y);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,pos_x, pos_y);
OSTimeDlyHMSM(0, 0, 0, 70);
}
}
- Programe y analice el codigo, si se da cuenta una tarea esta encargada de animar a Goku y la otra tarea esta encargada de mover al goku.
- Ahora modifiquemos el prorgama para que goku se mueva con las direcciones del control 1 usando el task2
void task2(void* pdata)
{
unsigned int pos_x=0,pos_y=0;
unsigned short snes1_control=0;
unsigned char buttons_control1[12];
while (1)
{
snes1_control=IORD(SNES_CONTROL1_BASE,0);
buttons_control1[0]=snes1_control & 1;// B
buttons_control1[1]=(snes1_control & 2)>>1;// Y
buttons_control1[2]=(snes1_control & 4)>>2;// Start
buttons_control1[3]=(snes1_control & 8)>>3;// select
buttons_control1[4]=(snes1_control & 16)>>4;//UP
buttons_control1[5]=(snes1_control & 32)>>5;//down
buttons_control1[6]=(snes1_control & 64)>>6;//left
buttons_control1[7]=(snes1_control & 128)>>7;//right
buttons_control1[8]=(snes1_control & 256)>>8;//A
buttons_control1[9]=(snes1_control & 512)>>9;//X
buttons_control1[10]=(snes1_control & 1024)>>10;//L
buttons_control1[11]=(snes1_control & 2048)>>11;//R
if(buttons_control1[4]==0){
pos_y=pos_y-10;
}
else if(buttons_control1[5]==0){
pos_y=pos_y+10;
}
if(buttons_control1[6]==0){
pos_x=pos_x-10;
}
else if(buttons_control1[7]==0){
pos_x=pos_x+10;
}
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,pos_x, pos_y);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,pos_x, pos_y);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,pos_x, pos_y);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,pos_x, pos_y);
OSTimeDlyHMSM(0, 0, 0, 70);
}
}
-
Si modifica bien la tarea 2 vera a goku moverse usando las flechas del control 1.
- Ahora modifique el codigo para lo siguiente:
#include <stdio.h>
#include "includes.h"
#include <system.h>
#include "io.h"
/* Definition of Task Stacks */
#define TASK_STACKSIZE 2048
OS_STK task1_stk[TASK_STACKSIZE];
OS_STK task2_stk[TASK_STACKSIZE];
OS_STK task3_stk[TASK_STACKSIZE];
/* Definition of Task Priorities */
#define TASK1_PRIORITY 1
#define TASK2_PRIORITY 2
#define TASK3_PRIORITY 3
void set_pos_image(int basex, int basey,int x, int y){// FUNCION PARA POSICIONAR IMAGENES
IOWR(basex,0,x);
IOWR(basey,0,y);
}
void init_game(void){// FUNCION PARA INICIALIZAR JUEGO
// INICIALIZO LA ESCALA DE CADA IMAGEN
IOWR(SCALE1_BASE,0,0);
IOWR(SCALE2_BASE,0,0);
IOWR(SCALE2_BASE,0,0);
IOWR(SCALE2_BASE,0,0);
//APAGAO CADA IMAGEN AL INICIO DEL JUEGO A MENOS DE QUE QUIERA MOSTRARLAS
IOWR(ON_OFF1_BASE,0,0);
IOWR(ON_OFF2_BASE,0,0);
IOWR(ON_OFF3_BASE,0,0);
IOWR(ON_OFF4_BASE,0,0);
//INICIALIZO LA POSICION DE LAS IMAGENES
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,0, 0);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,30, 0);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,60, 0);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,90, 0);
}
// VARIABLES GLOBALES DE BOTONES
unsigned char buttons_control1[12];
unsigned char buttons_control2[12];
void task1(void* pdata)// TASK PARA ANIMAR A goku
{
unsigned char animation=0;
// inicializo todas las imagenes en el mismo punto
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,0, 0);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,0, 0);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,0, 0);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,0, 0);
while (1)
{
animation++;
if(animation>3){animation=0;}
switch(animation){
case 0: IOWR(ON_OFF1_BASE,0,1);
IOWR(ON_OFF2_BASE,0,0);
IOWR(ON_OFF3_BASE,0,0);
IOWR(ON_OFF4_BASE,0,0);
break;
case 1: IOWR(ON_OFF1_BASE,0,0);
IOWR(ON_OFF2_BASE,0,1);
IOWR(ON_OFF3_BASE,0,0);
IOWR(ON_OFF4_BASE,0,0);
break;
case 2: IOWR(ON_OFF1_BASE,0,0);
IOWR(ON_OFF2_BASE,0,0);
IOWR(ON_OFF3_BASE,0,1);
IOWR(ON_OFF4_BASE,0,0);
break;
case 3: IOWR(ON_OFF1_BASE,0,0);
IOWR(ON_OFF2_BASE,0,0);
IOWR(ON_OFF3_BASE,0,0);
IOWR(ON_OFF4_BASE,0,1);
break;
}
//tiempo de retrazo
OSTimeDlyHMSM(0, 0, 0, 100);
}
}
void task2(void* pdata)// TASK PARA ADQUIRIR BOTONES
{
unsigned short snes1_control=0;
while (1)
{
snes1_control=IORD(SNES_CONTROL1_BASE,0);
buttons_control1[0]=snes1_control & 1;// B
buttons_control1[1]=(snes1_control & 2)>>1;// Y
buttons_control1[2]=(snes1_control & 4)>>2;// Start
buttons_control1[3]=(snes1_control & 8)>>3;// select
buttons_control1[4]=(snes1_control & 16)>>4;//UP
buttons_control1[5]=(snes1_control & 32)>>5;//down
buttons_control1[6]=(snes1_control & 64)>>6;//left
buttons_control1[7]=(snes1_control & 128)>>7;//right
buttons_control1[8]=(snes1_control & 256)>>8;//A
buttons_control1[9]=(snes1_control & 512)>>9;//X
buttons_control1[10]=(snes1_control & 1024)>>10;//L
buttons_control1[11]=(snes1_control & 2048)>>11;//R
snes1_control=IORD(SNES_CONTROL2_BASE,0);
buttons_control2[0]=snes1_control & 1;// B
buttons_control2[1]=(snes1_control & 2)>>1;// Y
buttons_control2[2]=(snes1_control & 4)>>2;// Start
buttons_control2[3]=(snes1_control & 8)>>3;// select
buttons_control2[4]=(snes1_control & 16)>>4;//UP
buttons_control2[5]=(snes1_control & 32)>>5;//down
buttons_control2[6]=(snes1_control & 64)>>6;//left
buttons_control2[7]=(snes1_control & 128)>>7;//right
buttons_control2[8]=(snes1_control & 256)>>8;//A
buttons_control2[9]=(snes1_control & 512)>>9;//X
buttons_control2[10]=(snes1_control & 1024)>>10;//L
buttons_control2[11]=(snes1_control & 2048)>>11;//R
OSTimeDlyHMSM(0, 0, 0, 70);
}
}
void task3(void* pdata)// TASK PARA MOVER A GOKU
{
unsigned int pos_x=0,pos_y=0;
while (1)
{
if(buttons_control1[4]==0){
pos_y=pos_y-10;
}
else if(buttons_control1[5]==0){
pos_y=pos_y+10;
}
if(buttons_control1[6]==0){
pos_x=pos_x-10;
}
else if(buttons_control1[7]==0){
pos_x=pos_x+10;
}
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,pos_x, pos_y);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,pos_x, pos_y);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,pos_x, pos_y);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,pos_x, pos_y);
OSTimeDlyHMSM(0, 0, 0, 70);
}
}
/* The main function creates two task and starts multi-tasking */
int main(void)
{
//INICIALIZO JUEGO ANTES DE LANZARLO
init_game();
OSTaskCreateExt(task1,
NULL,
(void *)&task1_stk[TASK_STACKSIZE-1],
TASK1_PRIORITY,
TASK1_PRIORITY,
task1_stk,
TASK_STACKSIZE,
NULL,
0);
OSTaskCreateExt(task2,
NULL,
(void *)&task2_stk[TASK_STACKSIZE-1],
TASK2_PRIORITY,
TASK2_PRIORITY,
task2_stk,
TASK_STACKSIZE,
NULL,
0);
OSTaskCreateExt(task3,
NULL,
(void *)&task3_stk[TASK_STACKSIZE-1],
TASK3_PRIORITY,
TASK3_PRIORITY,
task3_stk,
TASK_STACKSIZE,
NULL,
0);
OSStart();
return 0;
}
- Si analiza y ejecuta el codigo anterior, se dara cuenta que existen ahora tres tasks, uno para animar a goku, el otro para adquirir los botones de los dos controles de SNES, y el otro para mover a goku de acuerdo al control 1 del snes.
//Ahora agreguemos un task mas para el audio del video juego
void task4(void* pdata)// TASK PARA GENERAR AUDIO
{
unsigned int nota_div_freq[32]={56817,56817,47777,56817,42565,56817,37920,42565,47777,47777,37920,47777,31887,47777,37920,47777,63775,63775,50619,63775,47777,63775,42565,47777,71585,71585,56817,71585,50619,71585,47777,50619};
unsigned char count=0;
//init div_freq
IOWR(NOTA_BASE,0,0);
while (1)
{
count++;
if(count>31){
count=0;
}
IOWR(NOTA_BASE,0,nota_div_freq[count]);
if(buttons_control1[0]==0){// si se oprime B
OSTimeDlyHMSM(0, 0, 0, 170/4);
}
else if(buttons_control1[1]==0){// si se oprime Y
OSTimeDlyHMSM(0, 0, 0, 170/2);
}
else{// si no se oprime nada
OSTimeDlyHMSM(0, 0, 0, 170);
}
}
}
- Si agrego bien el task4, debe ahora sonar en paralelo una pequeña cancion repetitivamente, recuerde que el puerto nota[31:0] estaconectado por meido del Nios al divisor de frecuencia, con el cual usted puede variar para genear diferentes frecuencias por lo cual puede generar canciones o tonos diferentes.
Recuerde la formula del divisor de frecuencia IN= (50Mhz/(2*fout))-1
- El codigo completo en C esta en el siguiente link.
- Modifique el task3, para que se vea como el siguiente y analice lo que sucede.
void task3(void* pdata)// TASK PARA MOVER A GOKU
{
unsigned int pos_x=0,pos_y=0;
while (1)
{
if(buttons_control1[4]==0){
pos_y=pos_y-10;
}
else if(buttons_control1[5]==0){
pos_y=pos_y+10;
}
if(buttons_control1[6]==0){
pos_x=pos_x-10;
}
else if(buttons_control1[7]==0){
pos_x=pos_x+10;
}
if (buttons_control1[8]==0)
{
int i;
for(i=0;i<4;i++){
IOWR(SCALE1_BASE,0,i);
IOWR(SCALE2_BASE,0,i);
IOWR(SCALE3_BASE,0,i);
IOWR(SCALE4_BASE,0,i);
OSTimeDlyHMSM(0, 0, 0, 10);
}
IOWR(SCALE1_BASE,0,0);
IOWR(SCALE2_BASE,0,0);
IOWR(SCALE3_BASE,0,0);
IOWR(SCALE4_BASE,0,0);
}
if(buttons_control1[0]==0){
int i;
for(i=0;i<10;i++){
pos_x=pos_x+10;
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,pos_x, pos_y);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,pos_x, pos_y);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,pos_x, pos_y);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,pos_x, pos_y);
}
}
if(buttons_control1[1]==0){
int i;
for(i=0;i<10;i++){
pos_x=pos_x-10;
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,pos_x, pos_y);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,pos_x, pos_y);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,pos_x, pos_y);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,pos_x, pos_y);
}
}
set_pos_image(GOKU_X1_BASE,GOKU_Y1_BASE,pos_x, pos_y);
set_pos_image(GOKU_X2_BASE,GOKU_Y2_BASE,pos_x, pos_y);
set_pos_image(GOKU_X3_BASE,GOKU_Y3_BASE,pos_x, pos_y);
set_pos_image(GOKU_X4_BASE,GOKU_Y4_BASE,pos_x, pos_y);
OSTimeDlyHMSM(0, 0, 0, 70);
}
}