#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <SDL/SDL.h>
#include <SDL/SDL_image.h>
#define BASE_PUERTOS 0x56000000
#define BASE_ADC 0x58000000
#define PUERTO_F_CONFIGURACION 0x50
#define PUERTO_G_CONFIGURACION 0x60
#define PUERTO_F_DATOS PUERTO_F_CONFIGURACION + 4
#define PUERTO_G_DATOS PUERTO_G_CONFIGURACION + 4
#define ADC_0 0x0C
#define BOTON_I 3
#define BOTON_C 4
#define BOTON_D 2
#define INCLINOMETRO_1 9
#define INCLINOMETRO_2 10
#define CONFIGURA_F 0xFC0F
#define CONFIGURA_G 0xFFC3FFFF
#define CONFIGURA_ADC 0x7FC2
typedef struct
{
char boton_izquierdo;
char boton_central;
char boton_derecho;
char inclinacion;
unsigned char luminosidad;
}
ENTRADAS;
volatile char salir = 0;
static volatile void *memoria_puertos;
static volatile void *memoria_adc;
void salida(int sig)
{
salir = 1;
}
void inicializa_entradas()
{
int fd = open("/dev/mem", O_RDWR);
if (fd < 0)
{
perror("/dev/mem");
exit(1);
}
memoria_puertos = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_PUERTOS);
if (memoria_puertos == MAP_FAILED)
{
perror("mmap puertos");
exit(1);
}
memoria_adc = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, BASE_ADC);
if (memoria_adc == MAP_FAILED)
{
perror("mmap adc");
exit(1);
}
uint32_t configuracion = *(uint32_t *) (memoria_puertos + PUERTO_F_CONFIGURACION);
configuracion &= CONFIGURA_F;
*(uint32_t *) (memoria_puertos + PUERTO_F_CONFIGURACION) = configuracion;
configuracion = *(uint32_t *) (memoria_puertos + PUERTO_G_CONFIGURACION);
configuracion &= CONFIGURA_G;
*(uint32_t *) (memoria_puertos + PUERTO_G_CONFIGURACION) = configuracion;
*(uint32_t *) (memoria_adc) = CONFIGURA_ADC;
configuracion = *(uint32_t *) (memoria_adc + ADC_0);
}
void lee_entradas(ENTRADAS *entradas)
{
uint32_t datos = *(uint32_t *) (memoria_puertos + PUERTO_F_DATOS);
entradas->boton_derecho = (datos & (int)pow(2, BOTON_D)) >> BOTON_D;
entradas->boton_izquierdo = (datos & (int)pow(2, BOTON_I)) >> BOTON_I;
entradas->boton_central = (datos & (int)pow(2, BOTON_C)) >> BOTON_C;
datos = *(uint32_t *) (memoria_puertos + PUERTO_G_DATOS);
entradas->inclinacion = ((datos & (int)pow(2, INCLINOMETRO_2)) + (datos & (int)pow(2, INCLINOMETRO_1))) >> INCLINOMETRO_1;
datos = *(uint32_t *) memoria_adc;
if(datos & 0x8000)
{
datos = *(uint32_t *) (memoria_adc + ADC_0);
entradas->luminosidad = (datos & 0x3FF) * 255 / 1023;
}
}
int main(void)
{
SDL_Surface *izquierda;
SDL_Surface *derecha;
SDL_Surface *ok;
SDL_Surface *diamante;
SDL_Surface *sol;
SDL_Surface *pantalla;
SDL_Rect destino;
float radianes = 0;
float destino_radianes;
float suma_radianes;
ENTRADAS entradas;
inicializa_entradas();
if(SDL_Init(SDL_INIT_VIDEO) != 0)
{
printf("No se pudo iniciar SDL: %s\n",SDL_GetError());
exit(1);
}
atexit(SDL_Quit);
pantalla = SDL_SetVideoMode(320, 240, 16,
SDL_HWSURFACE | SDL_DOUBLEBUF);
if(pantalla == NULL)
{
printf("No se puede inicializar el modo gráfico: %s\n",
SDL_GetError());
exit(1);
}
SDL_ShowCursor(SDL_DISABLE);
izquierda = IMG_Load("izquierda.png");
if(izquierda == NULL)
{
printf("No pude cargar gráfico: %s\n", SDL_GetError());
exit(1);
}
derecha = IMG_Load("derecha.png");
if(derecha == NULL)
{
printf("No pude cargar gráfico: %s\n", SDL_GetError());
exit(1);
}
ok = IMG_Load("ok.png");
if(ok == NULL)
{
printf("No pude cargar gráfico: %s\n", SDL_GetError());
exit(1);
}
diamante = IMG_Load("diamante.png");
if (diamante == NULL)
{
printf("No pude cargar gráfico: %s\n", SDL_GetError());
exit(1);
}
sol = IMG_Load("sol.gif");
if(sol == NULL)
{
printf("No pude cargar gráfico: %s\n", SDL_GetError());
exit(1);
}
signal(SIGINT, salida);
while(!salir)
{
lee_entradas(&entradas);
// dibujamos el boton izquierdo
destino.x = 0;
destino.y = pantalla->h / 2 - izquierda->h / 2;
destino.w = izquierda->w;
destino.h = izquierda->h;
if(!entradas.boton_izquierdo)
{
SDL_BlitSurface(izquierda, NULL, pantalla, &destino);
}
else
{
SDL_FillRect(pantalla, &destino, SDL_MapRGB(pantalla->format, 0, 0, 0));
}
// dibujamos el boton central
destino.x = pantalla->w / 2 - ok->w / 2;
if(!entradas.boton_central)
{
SDL_BlitSurface(ok, NULL, pantalla, &destino);
}
else
{
SDL_FillRect(pantalla, &destino, SDL_MapRGB(pantalla->format, 0, 0, 0));
}
// dibujamos el boton derecho
destino.x = pantalla->w - derecha->w;
if(!entradas.boton_derecho)
{
SDL_BlitSurface(derecha, NULL, pantalla, &destino);
}
else
{
SDL_FillRect(pantalla, &destino, SDL_MapRGB(pantalla->format, 0, 0, 0));
}
// dibujamos el sol de luminosidad
destino.x = 0;
destino.y = pantalla->h - sol->h;
SDL_SetAlpha(sol, SDL_SRCALPHA | SDL_RLEACCEL, entradas.luminosidad);
SDL_BlitSurface(sol, NULL, pantalla, &destino);
// dibujamos el diamante de inclinación
switch(entradas.inclinacion)
{
case 1: // izquierda
destino_radianes = 3 * M_PI / 2;
suma_radianes = -0.10;
break;
case 2: // derecha
destino_radianes = M_PI_2;
suma_radianes = 0.10;
break;
case 3: // abajo
if(radianes > M_PI)
{
destino_radianes = 2 * M_PI;
suma_radianes = 0.10;
}
else
{
destino_radianes = 0;
suma_radianes = -0.10;
}
break;
}
if((radianes > (destino_radianes + 0.10)) || (radianes < (destino_radianes - 0.10)))
{
radianes += suma_radianes;
if(radianes < 0)
{
radianes = 2 * M_PI;
}
else if(radianes > (2 * M_PI))
{
radianes = 0;
}
}
destino.x = pantalla->w / 2 + sin(radianes) * diamante->w - diamante->w / 2;
destino.y = pantalla->h / 2 + cos(radianes) * diamante->h - diamante->h / 2;
SDL_BlitSurface(diamante, NULL, pantalla, &destino);
SDL_Flip(pantalla);
SDL_Delay(1);
SDL_FillRect(pantalla, &destino,
SDL_MapRGB(pantalla->format, 0, 0, 0));
destino.x = 0;
destino.y = pantalla->h - sol->h;
SDL_FillRect(pantalla, &destino,
SDL_MapRGB(pantalla->format, 0, 0, 0));
}
SDL_FreeSurface(izquierda);
SDL_FreeSurface(derecha);
SDL_FreeSurface(ok);
SDL_FreeSurface(diamante);
SDL_FreeSurface(sol);
SDL_FreeSurface(pantalla);
printf("\nFin del programa\n");
return 0;
}