Commit 4a284311 authored by Xavier de Blas's avatar Xavier de Blas

Added chronopic-tests (C and C#)

svn path=/trunk/; revision=351
parent 233343bd
2004-10-10 Juan Gonzalez <juan@iearobotics.com>
-Comenzado test-gsalta-hw. Se lee de la entrada estandar,
detectando las tramas que viene del hw de gsalta.
-Probado con gsalta2.asm. Funciona correctamente.
-Para probar hay que hacer:
$ cat /dev/ttyS0 | ./test-gsalta-hw
Al apretar el pulsador, aparecera su estado y el tiempo
transcurrido desde el ultimo cambio.
2004-10-11 Juan Gonzalez <juan@iearobotics.com>
-Se tiene en cuenta el tiempo maximo. Se imprime "> 65.280 ms"
cuando ha llegado al maximo.
-Anadidos colores en la impresion (usando el modulo termansi.c)
2004-10-12 Juan Gonzalez <juan@iearobotics.com>
-Cambiada la precision. La version gsalta5 envia el tiempo
en decimas de ms (0.1ms).
-Ahora se imprime "> 6.538 ms" cuando llega al maximo
2004-10-16 Juan Gonzalez <juan@iearobotics.com>
-(Cambios hechos con Xavi)
2005-02-04 Juan Gonzalez <juan@iearobotics.com>
-Programa chronopic-serial-conf.c, para configurar el pueto
serie para trabajar con ChronoPic
-Metido en el CVS de Software-libre.org
-Programa test-tramas, para visualizar las tramas enviadas
por ChronoPic
2005-02-05 Juan Gonzalez <juan@iearobotics.com>
-Chronopic-serial-conf:
-Anadido parametro -h para obtener ayuda
-test-tramas:
-La fuente de datos puede ser la entrada estandar o el
puerto serie.
-Anadido parametro -h para la ayuda
-chronopic.c: Funciones de procesado de las tramas
para chronopic. Para ser usado por cualquier programa que
quiera acceder a chronopic.
-test-precision:
-Validacion de Chronopic
-Anadido parametro -h para la ayuda
-test-saltos: Medir el tiempo de vuelo de los saltos
-Creada libchronopic.so
2005-02-06 Juan Gonzalez <juan@iearobotics.com>
-Creado modulo chronopic.cs, para Mono (c#)
-test-saltos.mono, medir el tiempo de vuelo en Mono
# **************************************************************************
# Fichero makefile.
# --------------------------------------------------------------------------
# Licencia GPL. Juan Gonzalez Gomez
# --------------------------------------------------------------------------
#
#***************************************************************************
# Edited for Debian GNU/Linux.
DESTDIR =
# ¿Dónde poner los binarios en el 'make install'?
BIN = $(DESTDIR)/usr/local/bin
#---- Compilador
CC = gcc
CFLAGS = -Wall
#-- Compilador de C#
MCS = mcs
#-------- Nombres y dependencias de los programas a construir
NAME1= chronopic-serial-conf
DEP1= $(NAME1).o chronopic.o
NAME2= test-tramas
DEP2= $(NAME2).o chronopic.o termansi.o
NAME3= test-precision
DEP3= $(NAME3).o chronopic.o
NAME4= test-saltos
DEP4= $(NAME4).o chronopic.o
NAME5= test-saltos.mono
DEP5 = $(NAME5).cs $(DLL_CHRONOPIC).dll
NAME6= test
DEP6 = $(NAME6).cs $(DLL_CHRONOPIC).dll
LIBCHRONOPIC = libchronopic.so
LIBCHRONOPIC_DEP = chronopic.o
DLL_CHRONOPIC = chronopic
all: test test-mono
#-- Construccion de los ejemplos de prueba en c
test: $(NAME1) $(NAME2) $(NAME3) $(NAME4)
#-- Construccion de los ejemplos de prueba en Mono
test-mono: $(NAME5).exe $(NAME6).exe
#--------------------------
# Reglas
#--------------------------
$(NAME1): $(DEP1)
$(CC) -o $(NAME1) $(DEP1)
clean::
rm -f $(NAME1) $(DEP1)
#---------------------------------------
$(NAME2): $(DEP2)
$(CC) -o $(NAME2) $(DEP2)
clean::
rm -f $(NAME2) $(DEP2)
#---------------------------------------
$(NAME3): $(DEP3)
$(CC) -o $(NAME3) $(DEP3)
clean::
rm -f $(NAME3) $(DEP3)
#---------------------------------------
$(NAME4): $(DEP4)
$(CC) -o $(NAME4) $(DEP4)
clean::
rm -f $(NAME4) $(DEP4)
# ---- Generacion de la libreria libchronopic
$(LIBCHRONOPIC): $(LIBCHRONOPIC_DEP)
$(CC) -shared -W1,-soname,$(LIBCHRONOPIC) -o $(LIBCHRONOPIC) \
$(LIBCHRONOPIC_DEP)
clean::
rm -f $(LIBCHRONOPIC) $(LIBCHRONOPIC_DEP)
#----- Crear la DLL
$(DLL_CHRONOPIC).dll: $(LIBCHRONOPIC) $(DLL_CHRONOPIC).cs
$(MCS) -unsafe -target:library $(DLL_CHRONOPIC).cs \
-o $(DLL_CHRONOPIC).dll
clean::
rm -f $(DLL_CHRONOPIC).dll
#-------------------------------
# EJEMPLOS DE PRUEBA EN C#
#-------------------------------
$(NAME5).exe: $(DEP5)
$(MCS) $(NAME5).cs -unsafe -r $(DLL_CHRONOPIC).dll -o $(NAME5).exe
clean::
rm -f $(NAME5).exe
$(NAME6).exe: $(DEP6)
$(MCS) $(NAME6).cs -o $(NAME6).exe -r $(DLL_CHRONOPIC).dll -unsafe \
-pkg:gtk-sharp
clean::
rm -f $(NAME6).exe
#--------------------------
# REGLAS GENERICAS
#--------------------------
.c.o:
$(CC) $(CFLAGS) -c $<
Pequenas utilidades para realizar pruebas con el cronometro de chronojump
--------------------------------------------------------------------------
PROGRAMAS EJEMPLO EN C:
* chronopic-serial-conf: Configuracion del puerto serie para trabajar
con ChronoPIC
* test-tramas: Visualizar las tramas que envia ChronoPIC
* test-precision: Mostrar periodo y frecuencia de senales cuadradas. Se
utiliza para calibracion y validacion de Chronopic
* test-saltos: Medir el tiempo de vuelo de los saltos
--------------------------------------------------------------------------
PROGRAMAS EJEMPLO EN MONO:
* test-saltos.mono: Medir el tiempo de vuelo de los saltos
/***************************************************************************/
/* chronopic-serial-conf.c */
/* (c) Juan Gonzalez. 2004 */
/*-------------------------------------------------------------------------*/
/* Configurar el puerto serie para trabajar con chronopic */
/* Este programa tiene las siguientes funciones: */
/* */
/* 1) Configurar el puerto serie para poder acceder desde el PC al */
/* cronometro (chronopic). La velocidad se establece a 9600 baudios y */
/* se usa la configuracion N81. Al dejarlo asi configurado, es posible */
/* leer las tramas de cronojump directamente abriendo el dispositivo */
/* /dev/ttyS0. Resulta muy util para acceder a chronopic desde otro */
/* lenguaje de programacion distinto de C, como por ejemplo C#, Python */
/* Java, etc... */
/* */
/* 2) Tener disponibles las funciones en C, para poderlas utilizar */
/* desde otros programas en C, o crear una libreria especifica */
/*-------------------------------------------------------------------------*/
/* Licencia GPL */
/***************************************************************************/
/*-------------------------------------------------------------------------
$Id: chronopic-serial-conf.c,v 1.1 2005/02/07 11:14:54 obijuan Exp $
$Revision: 1.1 $
$Source: /cvsroot/chronojump/chronopic/test/chronopic-serial-conf.c,v $
---------------------------------------------------------------------------*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
//-- Las funciones de manejo del puerto serie se encuentran en el
//-- ficher sg-serial.c
#include "chronopic.h"
//-- Dispositivo serie
char disp_serie[80];
/**********************/
/* Imprimir la ayuda */
/**********************/
void help(void)
{
printf ("\n");
printf (
"Forma de uso: chronopic-serial-conf dispositivo_serie [opciones]\n");
printf ("Opciones:\n");
printf (" -h : Mostrar esta ayuda\n\n");
printf ("Ejemplo: chronopic-serial-conf /dev/ttyS0\n");
printf ("\n");
}
/*****************************************************************/
/* Analizar los parametros pasados desde la linea de comandos */
/*---------------------------------------------------------------*/
/* ENTRADAS: Argumentos de la funcion main() */
/* DEVUELVE: */
/* 0 : Error */
/* 1 : OK */
/*****************************************************************/
int analizar_parametros(int argc, char* argv[])
{
int c;
if (argc<2) {
printf ("\nERROR: No se ha especificado dispositivo serie\n");
printf ("Utilice el parametro -h para obtener ayuda\n\n");
return 0;
}
//-- Obtener el dispositivo serie
strcpy(disp_serie,argv[1]);
//-- Obtener el resto de parametros
while ((c = getopt(argc, argv, ":h"))!=EOF) {
switch (c) {
case 'h':
default: help();
return 0;
}
}
return 1;
}
/*****************************/
/* Informacion del programa */
/*****************************/
void presenta()
{
printf ("\n");
printf (
"Chronopic-serial-conf. (c) Juan Gonzalez. Febrero 2005. Licencia GPL\n");
printf (
"Configuracion del puerto serie para trabajar con ChronoPIC\n");
printf ("Proyecto ChronoJump\n");
printf ("\n");
}
/*----------------*/
/* MAIN */
/*----------------*/
int main (int argc, char **argv)
{
int serial_fd=0;
int ok;
presenta();
ok=analizar_parametros(argc,argv);
if (!ok) return 0;
//-- Abrir el puerto serie. Por defecto se abre con los parametros
//-- necesario en Chronopic
serial_fd=chronopic_open(disp_serie);
if (serial_fd==-1) {
printf ("\n");
printf ("Error al abrir puerto serie %s\n",argv[1]);
perror("ERROR: ");
return 1;
}
printf ("\n");
printf ("-------------------------------------------\n");
printf (" Puerto serie configurado para Chronopic \n");
printf ("-------------------------------------------\n");
//-- Cerrar puerto serie
chronopic_close(serial_fd);
return 0;
}
/***********************************************************/
/* chronopic.c Juan Gonzalez Gomez. Febrero 2005 */
/*---------------------------------------------------------*/
/* Funciones de acceso a chronopic */
/* Licencia GPL */
/***********************************************************/
/*------------------------------------------------------------------------
$Id: chronopic.c,v 1.1 2005/02/07 11:14:54 obijuan Exp $
$Revision: 1.1 $
$Source: /cvsroot/chronojump/chronopic/test/chronopic.c,v $
--------------------------------------------------------------------------*/
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include "chronopic.h"
/*********************************/
/* PROTOTIPOS FUNCIONES PRIVADAS */
/*********************************/
int sg_trama_cambio_read(int serial_fd, unsigned char *trama);
/*-----------------------------------------------------------------------*/
/* F U N C I O N E S D E I N T E R F A Z */
/*-----------------------------------------------------------------------*/
/********************************************************************/
/* Abrir el puerto serie y configurarlo para trabajar con chronopic */
/*------------------------------------------------------------------*/
/* ENTRADA: */
/* disp: cadena con el dispositivo serie */
/* */
/* DEVUELVE: */
/* -El descriptor del puerto serie ó -1 si ha ocurrido un error */
/********************************************************************/
int chronopic_open(char *disp)
{
struct termios newtermios;
int fd;
fd = open(disp,O_RDWR | O_NOCTTY); /* Abrir puerto serie */
/* Modificar los atributos */
newtermios.c_cflag= CBAUD | CS8 | CLOCAL | CREAD;
newtermios.c_iflag=IGNPAR;
newtermios.c_oflag=0;
newtermios.c_lflag=0;
newtermios.c_cc[VMIN]=1;
newtermios.c_cc[VTIME]=0;
/* Establecer velocidad por defecto */
cfsetospeed(&newtermios,B9600);
cfsetispeed(&newtermios,B9600);
/* Vaciar los buffers de entrada y salida */
if (tcflush(fd,TCIFLUSH)==-1) {
return -1;
}
/* Vaciar buffer de salida */
if (tcflush(fd,TCOFLUSH)==-1) {
return -1;
}
/* Escribir los nuevos atributos */
if (tcsetattr(fd,TCSANOW,&newtermios)==-1) {
return -1;
}
return fd;
}
/********************************************************************/
/* Cerrar el puerto serie y finalizar sesion con Chronopic */
/*------------------------------------------------------------------*/
/* ENTRADA: */
/* fd: Descriptor del fichero */
/********************************************************************/
void chronopic_close(int fd)
{
close(fd);
}
/***********************************************************************/
/* Leer una trama y devolver el estado de la plataforma y el tiempo */
/* transcurrido desde la ultima transicion */
/* */
/* ENTRADAS: */
/* -fd: Descriptor del puerto serie, donde esta conectado ChronoPic */
/* */
/* SALIDAS: */
/* -t : Tiempo transcurrido */
/* -estado: Estado de la plataforma: */
/* * 0 --> OFF. No hay nadie sobre la plataforma */
/* * 1 --> ON. Hay alguien apoyado */
/* */
/* DEVUELVE: */
/* -1 : Error en la lectura de la trama */
/* 0 : Timeout */
/* 1 : Trama leida correctamente */
/***********************************************************************/
int chronopic_get_trama_cambio(int fd, double *t, int *estado)
{
int n;
unsigned char trama[10];
//-- Esperar a que llegue una trama
n=sg_trama_cambio_read(fd,trama);
//-- Timeout o algun error en recepcion
if (n!=1) return n;
//-- Analizar si es una trama de cambio
if (trama[0]!='X') {
printf ("Error. Trama desconocida\n");
return -1;
}
//-- Obtener el estado
if (trama[1]!=0 && trama[1]!=1) {
printf ("Error. Estado no valido\n");
return -1;
}
*estado = (int)(trama[1]&0xff);
//-- Obtener el tiempo en milisegundos
//-- El Chronopic devuelve 3 bytes, que se obtienen en las posiciones
//-- 2, 3 y 4 de la trama, siendo trama[2] el de mayor peso
//-- Esta en unidades de 8 micro-segundos, por lo que hay que multiplicar
//-- por 8 para obtenerlo en microseungos. Finalmente hay que dividirlo
//-- entre 1000 para obtenerlo en milisegundos.
*t = (double)((trama[2]*65536 + trama[3]*256 + trama[4])*8)/1000;
return 1;
}
/***********************************************************************/
/* Devolver el estado de la plataforma */
/* ENTRADAS: */
/* -fd: Descriptor del puerto serie, donde esta conectado ChronoPic */
/* */
/* SALIDAS: */
/* -estado: Estado de la plataforma: */
/* * 0 --> OFF. No hay nadie sobre la plataforma */
/* * 1 --> ON. Hay alguien apoyado */
/* */
/* DEVUELVE: */
/* -1 : Error en la lectura de la trama */
/* 0 : Timeout */
/* 1 : Trama leida correctamente */
/***********************************************************************/
int chronopic_estado(int serial_fd, int *estado)
{
unsigned char trama[10];
char respuesta[10];
fd_set fds;
struct timeval timeout;
int status;
int ret;
int n;
// Construir la trama del servicio de estado
trama[0]='E';
//-- Enviarla al StarGate
write(serial_fd, trama,1);
//-- Esperar la respuesta
FD_ZERO(&fds);
FD_SET (serial_fd, &fds);
timeout.tv_sec = 0; //-- Establecer el TIMEOUT
timeout.tv_usec = 100000;
ret=select (FD_SETSIZE,&fds, NULL, NULL,&timeout);
switch(ret) {
case 1 : //--Datos listos
n=read (serial_fd, respuesta, 10);
if (respuesta[0]=='E') {
status=1;
*estado=(int)respuesta[1];
}
else { //-- Recibido algo distinto de lo esperado
status=-1;
*estado=0;
}
break;
case 0: //-- Timeout
tcflush(serial_fd,TCIOFLUSH);
status=0;
*estado=0;
break;
default: //-- Otro Error
status=-1;
*estado=0;
break;
}
return status;
}
/*************************************/
/* Solicitar el estado de chronopic */
/* Solo se envia la trama */
/*************************************/
void chronopic_solicitar_estado(int serial_fd)
{
unsigned char trama[10];
// Construir la trama del servicio de estado
trama[0]='E';
//-- Enviarla al StarGate
write(serial_fd, trama,1);
}
/*******************************************/
/* Vaciar el buffer */
/*******************************************/
void chronopic_flush(int serial_fd)
{
/* Vaciar los buffers de entrada y salida */
tcflush(serial_fd,TCIOFLUSH);
}
/**************************************/
/* Leer un numero de bytes */
/**************************************/
int chronopic_read(int serial_fd, unsigned char *trama,
int bytes, int tout)
{
fd_set fds;
ssize_t n;
struct timeval timeout;
int ret;
//-- Comprobar si hay datos esperando en el puerto serie
FD_ZERO(&fds);
FD_SET (serial_fd, &fds);
timeout.tv_sec = 0; //-- Establecer el TIMEOUT
timeout.tv_usec = tout;
ret=select (FD_SETSIZE,&fds, NULL, NULL,&timeout);
switch(ret) {
case 1 : //--Datos listos. Leer una trama
n=read (serial_fd, trama, bytes);
return n;
break;
case 0: //-- Timeout
trama[0]=0;
return 0;
break;
default: //--Cualquier otro error
trama[0]=0;
return -1;
break;
}
//-- Aqui nunca llega...
return 1;
}
/************************************************/
/* Leer una trama de cambio completa */
/************************************************/
int sg_trama_cambio_read(int serial_fd, unsigned char *trama)
{
fd_set fds;
ssize_t n;
struct timeval timeout;
int ret;
//-- Comprobar si hay datos esperando en el puerto serie
FD_ZERO(&fds);
FD_SET (serial_fd, &fds);
timeout.tv_sec = 0; //-- Establecer el TIMEOUT
timeout.tv_usec = 100000; //-- 100ms
ret=select (FD_SETSIZE,&fds, NULL, NULL,&timeout);
switch(ret) {
case 1 : //--Datos listos. Leer una trama
n=read (serial_fd, trama, 5);
if (n!=5) return -1;
return 1;
break;
case 0: //-- Timeout
trama[0]=0;
return 0;
break;
default: //--Cualquier otro error
trama[0]=0;
return -1;
break;
}
//-- Aqui nunca llega...
return 1;
}
/**********************************************/
/* chronopic.cs Juan Gonzalez Gomez. */
/*--------------------------------------------*/
/* Licencia GPL */
/**********************************************/
/*------------------------------------------------------------------------
$Id: chronopic.cs,v 1.1 2005/02/07 11:14:54 obijuan Exp $
$Revision: 1.1 $
$Source: /cvsroot/chronojump/chronopic/test/chronopic.cs,v $
--------------------------------------------------------------------------*/
using System;
using System.Runtime.InteropServices;
public class Chronopic {
//-- Acceso a la libreria chronopic
const string library = "chronopic";
//****************************
// TIPOS
//****************************
//-- Respuestas en el acceso a Chronopic
public enum Respuesta : int
{
Ok = 1,
Error = -1,
Timeout = 0,
}
//-- Estado de la plataforma
public enum Plataforma : int
{
ON = 1,
OFF = 0,
UNKNOW = -1,
}
//******************************
// CONSTRUCTORES Y DESTRUCTORES
//******************************
//-- Constructor
public Chronopic(string disp)
{
this.serial_fd=this.Open(disp);
}
//-- Destructor
~Chronopic()
{
if (this.serial_fd!=-1)
this.Close();
}
//***************************************
// METODOS PUBLICOS
//***************************************
//----------------------------
//-- Cerrar el puerto serie
//----------------------------
public void Close()
{
Chronopic.close(this.serial_fd);
this.serial_fd=-1;
}
//----------------------------------
//-- Leer un evento en Chronopic
//----------------------------------
public Respuesta Read_event(out double timestamp,
out Plataforma plataforma)
{
double t;
int estado;
int error;
Respuesta resp;
//-- Leer trama
error=read(this.serial_fd,out t, out estado);
//-- Convertir el error al tipo Respuesta
switch(error) {
case 0:
resp = Respuesta.Timeout;
plataforma = Plataforma.UNKNOW;
timestamp = 0.0;
break;
case 1:
resp = Respuesta.Ok;
timestamp = t;
if (estado==0)
plataforma = Plataforma.OFF;
else
plataforma = Plataforma.ON;
break;
default:
resp = Respuesta.Error;
timestamp = 0.0;
plataforma = Plataforma.UNKNOW;
break;
}
return resp;
}
//----------------------------------------
//-- Obtener el estado de la plataforma
//----------------------------------------
public Respuesta Read_platform(out Plataforma plataforma)
{
int error;
int estado;
Respuesta resp;
//-- Enviar trama de estado
error=Chronopic.estado(this.serial_fd, out estado);
//-- Convertir el error al tipo Respueta