INTERPRETE DE COMANDOS [HECHO], en progmem, tabla saltos, ++

EDITADO AÑADIDO: SE PERDIO EL 1º MSG, LO PUSE EN EL 4º.

/* GUARDAR COMO comandos.h  */		
#ifndef comandos_h
#define comandos_h

//--------------------- un ejemplo de internet de poke y peek
unsigned int   	addres_ram;
#define 	PEEK(addr)      (*(unsigned char *)(addr))
#define		POKE(addr, b)   (*(unsigned char *)(addr) = (b))
//unsigned char	mem

ademas estos ficheros:

/*GUARDAR COMO interprete.h  */
#ifndef interprete_h
#define interprete_h

#define	coman_top 30		//numero de comandos que usamos, curarse en salud

unsigned char	in_k;		//interprete, variable comodin
unsigned char	in_ptr;		//interprete, puntero al bufer 
unsigned char	in_pgm;		//interprete, letra pillada de progmem para comparar
unsigned char	in_buf;		//interprete, letra pillada de bufer para comparar

char *mem;			//puntero a memoria de programa a un c
//int  *imem;			//puntero a memoria de programa a un i

void		_interprete_patrulla(void);	//NUCLEO DEL INTERPRETE DE COMANDOS
void		_interprete_mal_num(void);
unsigned char	_in_arroba_d(char n);//ENTRA UN ASCII DE DECIMAL Y SALE COMO BYTE, o error
unsigned char	_in_arroba_h(char n);//ENTRA UN ASCII DE HEXADE Y SALE COMO BYTE, o error

#endif
/*GUARDAR COMO main.h  */
#ifndef main_h
#define main_h

//	ma_cntr		//CONTROL
#define sonido 1
#define eco 0
//	ma_stat		//STATUS
#define on 0			//que si esta ejecutando
//	ma_error	//ERROR
#define kk 3
#define rs_over_dato 2
#define rs_RX_sat 1
#define poe 0

unsigned char	ma_cntr;	//main control
unsigned char	ma_stat;	//main status
unsigned char	ma_error;	//main error

unsigned char	k;		//variable comodin
unsigned char	k2;		//variable comodin

unsigned char	var0;		//variable de ejemplo
unsigned char	var1;		//variable de ejemplo

char RX_c;			//letra que llega por rs232
char bufer[16];			//bufer de lo que llega por rs232, y usa el interprete, EL UNICO QUE HAY AQUI
unsigned char	ptr_bufer;	//puntero a ese bufer


void	_main_reset(void);
void	_bufer_reset(void);		//RESET DEL BUFER RS232
void	_main_off(void);	//EJEMPO DE EJECUCION DE COMANDO 
void	_main_on(void);		//EJEMPO DE EJECUCION DE COMANDO 
void	_main_eco_0(void);		//"ECO 0", NO ECO DE RECEPCION	bitClear(ma_cntr,eco);	}
void	_main_eco_1(void);		//"ECO 1",

#endif

en la mainx esta la captura a un bufer propio desde el que compara

/* GUARDAR COMO mainx.ico  */
/**************************************/
/******     M A I N             *******/

#include "main.h"
#include "interprete.h"
#include "comandos.h"

void  setup (){				//SETUP
	Serial.begin(9600);			//
	Serial.print("PASO POR RESET HARD\n");
	_main_reset();
	}
void  loop (){				//LOOP
	if(Serial.available()){			//llego algo por rs232
		RX_c=(char)Serial.read();		//lo lee
		bufer[ptr_bufer]=RX_c;			//lo mete en bufer
		ptr_bufer++;				//puntero bufer++
		if(bitRead(ma_cntr,eco)){		//activo el eco?
			Serial.write(RX_c);			//eco enviar
			}
		}				
	_interprete_patrulla();			//ejemplo, logica estar en if(available,,,tras meter
	}

/**************************************/
/******    R U T I N A S        *******/

void	_main_reset(void){
	_rom_load(0);	//carga de rom 
	_bufer_reset();
	//ma_cntr=0;	//leido en load(0)
	ma_stat=0;
	ma_error=0;
	}
void	_bufer_reset(void){		//RESET DEL BUFER RS232
	ptr_bufer=0;				//ptr a 0
	RX_c=0;					//entra = 0x00
	}
	
void	_main_off(void){	//EJEMPO DE EJECUCION DE COMANDO 
	Serial.print("nuestro invento esta en OFF\n");
	}
void	_main_on(void){		//EJEMPO DE EJECUCION DE COMANDO 
	Serial.print("INVENTO EN ON\n");
	}

void	_main_eco_0(void){		//"ECO 0", NO ECO DE RECEPCION
	bitClear(ma_cntr,eco);	}
void	_main_eco_1(void){		//"ECO 1",
	bitSet(ma_cntr,eco);  	}
/* GUARDAR COMO comandos.h  */		
#ifndef comandos_h
#define comandos_h

//--------------------- un ejemplo de internet de poke y peek
unsigned int   	addres_ram;
#define 	PEEK(addr)      (*(unsigned char *)(addr))
#define		POKE(addr, b)   (*(unsigned char *)(addr) = (b))
//unsigned char	memo_byte;
//----------------- otro ejemplo de internet de poke y peek
//char *ptr;
//char contenido;
//// Leemos de la direccion 0xFFFF
//ptr = (char*)0xFFFF;
//contenido = *ptr;
//// Escribimos en la direccion 0xAAAA el caracter 'a'.
//ptr = (char*)0xAAAA;
//*ptr = 'a';
//------------------------
unsigned int   	addres_rom;


void	_ram_pregun(void);	//RAM?, DICE ADDRES Y EL DATO
void	_ram_igual(void);	// "ram=@@@@"  //CONCRETA LA ADDRES, Y DATO
void	_ram_poke(void);	// "poke=@@"
void	_ram_dump(void);	//DUMP DE 1/4K DE RAM desde el addres_ram
void	_var0(void);  		//"var0=@@",	
void	_var1(void);  		//"var1=@@",	
void	_var_ver(void);	//"var dump",	

void	_rom_dump(void);	//DUMP DE 1�/4K DE ROM
void	_save_0(void);		//GUARDA VARIABLES EN BANCO 0, EL QUE CARGA AL INICIO
void	_save_1(void);
void	_save_2(void);
void	_save_3(void);
void	_load_0(void);		//CARGA VARIABLES DESDE BANCO 0, EL QUE CARGA AL INICIO
void	_load_1(void);
void	_load_2(void);
void	_load_3(void);
void	_rom_save(unsigned char banco);		//GUARDA EN UNO DE 4 BANCOS DE EPROM
void	_rom_load(unsigned char banco);		//LEE UN BANCO DE EPROM
void	_rom_bancos_ver(void);			//DUMP POR RS232 DE LOS 4 BANCOS
void	_rom_bancos_ver_comun_d(void);		//PARTE COMUN DECIMAL
void	_rom_bancos_ver_comun_h(void);		//PARTE COMUN HEXA
	
void	_help0(void);
void	_help1(void);
void	_saca_memo(char *s_mem);	//SACA DESDE MEMORIA, ENTRA CON UN PUNTERO A MEM
void	_saca_memo_l(char *s_mem);	//SACA DESDE MEMORIA LARGO, TERMINA CON $

#endif
/* GUARDAR COMO comandos.ino  */
/**************************************/
/******     C O M A N D O S     *******/
#include <EEPROM.h>
//#include "interprete.h"
#include "main.h"
#include "comandos.h"
	

/**************************************/
/*   C O S I L L A S   D E   R A M    */
void	_ram_pregun(void){			//RAM?, DICE ADDRES Y EL DATO
	Serial.print(addres_ram, HEX);
	Serial.print(" ");
	Serial.println(PEEK(addres_ram), HEX);
	}
void	_ram_igual(void){	// "ram=@@@@"  //CONCRETA LA ADDRES, Y DATO
	bitClear(ma_error,poe);	//error a cero
	
	_in_arroba_h(4);		//traduce a byte 1�@, pa ver si error
	_in_arroba_h(5);	
	_in_arroba_h(6);	
	_in_arroba_h(7);
	
	if(bitRead(ma_error,poe)){	//error?
		_interprete_mal_num();
		return;
		}
	
	addres_ram =_in_arroba_h(4);	addres_ram =addres_ram<<4;	//traduce a byte 1�@, y pone, y rota
	addres_ram+=_in_arroba_h(5);	addres_ram =addres_ram<<4;
	addres_ram+=_in_arroba_h(6);	addres_ram =addres_ram<<4;
	addres_ram+=_in_arroba_h(7);	
	
	_ram_pregun();
	
	}
void	_ram_poke(void){	// "poke=@@"
	bitClear(ma_error,poe);	//error a cero

	_in_arroba_h(5);	
	_in_arroba_h(6);	

	if(bitRead(ma_error,poe)){	//error?
		_interprete_mal_num();
		return;
		}

	k =_in_arroba_h(5);	k =k<<4;
	k+=_in_arroba_h(6);	

	Serial.print("POKE antes  : ");
	_ram_pregun();
	POKE(addres_ram,k);
	Serial.print("POKE despues: ");
	_ram_pregun();

	}

void	_ram_dump(void){	//DUMP DE 1/4K DE RAM desde el addres_ram
	for(k=0;k<0x20;k++){
		Serial.print("0x");
		Serial.print(addres_ram,HEX);
		for(k2=0;k2<8;k2++){	//pone los numeritos
			Serial.print(" ");
			Serial.print(PEEK(addres_ram),HEX);
			addres_ram++;
			}
		addres_ram-=8;		//
		Serial.print(" ");
		for(k2=0;k2<8;k2++){	//pone las letritas
			if(PEEK(addres_ram)<0x20){
				Serial.write('.');
				addres_ram++;
				continue;}
			if(PEEK(addres_ram)>0x7E){
				Serial.write('.');
				addres_ram++;
				continue;}
			Serial.write(PEEK(addres_ram));
			addres_ram++;
			}
		Serial.print("\n");
		}
	}

void	_var0(void){  	//"var0=@@",	
	bitClear(ma_error,poe);	//error a cero
	_in_arroba_h(5);	_in_arroba_h(6);//si @ viene en hexa usar esta linea
//	_in_arroba_d(5);	_in_arroba_d(6);//si @ viene en decimal usar esta linea
	if(bitRead(ma_error,poe)){	//error?
		_interprete_mal_num();
		return;
		}
	var0 =_in_arroba_h(5);	var0 =var0<<4;	//si @ viene en hexa usar esta linea
	var0+=_in_arroba_h(6);			//si @ viene en hexa usar esta linea
//	var0 =_in_arroba_d(5);	var0 *=10	//si @ viene en decimal usar esta linea
//	var0+=_in_arroba_d(6);			//si @ viene en decimal usar esta linea
	}
void	_var1(void){  	//"var1=@@",	
	bitClear(ma_error,poe);	//error a cero
	_in_arroba_h(5);	_in_arroba_h(6);//si @ viene en hexa usar esta linea
//	_in_arroba_d(5);	_in_arroba_d(6);//si @ viene en decimal usar esta linea
	if(bitRead(ma_error,poe)){	//error?
		_interprete_mal_num();
		return;
		}
	var1 =_in_arroba_h(5);	var1 =var1<<4;	//si @ viene en hexa usar esta linea
	var1+=_in_arroba_h(6);			//si @ viene en hexa usar esta linea
//	var1 =_in_arroba_d(5);	var1 *=10	//si @ viene en decimal usar esta linea
//	var1+=_in_arroba_d(6);			//si @ viene en decimal usar esta linea
	}
void	_var_ver(void){	//"var ver",	
	Serial.print("ma_cntr=\t");	Serial.print("0x");	Serial.println(ma_cntr,HEX);
	Serial.print("var0   =\t");	Serial.print("0x");	Serial.println(var0,HEX);
	Serial.print("var1   =\t");	Serial.print("0x");	Serial.println(var1,HEX);
	}
			
/**************************************/
/*   C O S I L L A S   D E   R O M    */
void	_rom_del(void){	//BORRA 1�/4K DE ROM
	for(addres_rom=0;addres_rom<0x100;addres_rom++){
		EEPROM.write(addres_rom,0x00);
		}
	}
void	_rom_dump(void){	//DUMP DE 1�/4K DE ROM
	addres_rom=0;
	for(k=0;k<0x20;k++){
		Serial.print("0x");
		Serial.print(addres_rom,HEX);	//pone addres
		for(k2=0;k2<8;k2++){	//poner los numeritos
			Serial.print(" ");
			Serial.print(EEPROM.read(addres_rom),HEX);
			addres_rom++;
			}
		addres_rom-=8;		//retrocede para letritas
		Serial.print(" ");
		for(k2=0;k2<8;k2++){	//pone las letritas
			if(PEEK(addres_rom)<0x20){
				Serial.write('.');
				addres_rom++;
				continue;}
			if(PEEK(addres_rom)>0x7E){
				Serial.write('.');
				addres_rom++;
				continue;}
			Serial.write(EEPROM.read(addres_rom));
			addres_rom++;
			}
		Serial.print("\n");
		}
	}

void	_save_0(void){_rom_save(0);}//GUARDA VARIABLES EN BANCO 0, EL QUE CARGA AL INICIO
void	_save_1(void){_rom_save(1);}
void	_save_2(void){_rom_save(2);}
void	_save_3(void){_rom_save(3);}

void	_load_0(void){_rom_load(0);}//CARGA VARIABLES DESDE BANCO 0, EL QUE CARGA AL INICIO
void	_load_1(void){_rom_load(1);}
void	_load_2(void){_rom_load(2);}
void	_load_3(void){_rom_load(3);}


void	_rom_save(unsigned char banco){		//GUARDA EN UNO DE 4 BANCOS DE EPROM
	addres_rom=(banco<<4);				//multiplica por 16, = base del banco
	
	EEPROM.write(addres_rom,ma_cntr);		addres_rom++;	//guarda e incremen
	EEPROM.write(addres_rom,ma_cntr);		addres_rom++;	//ma_cntr save 2 veces para ejemplo
	EEPROM.write(addres_rom,var0);  		addres_rom++;	//
	EEPROM.write(addres_rom,var1);  		addres_rom++;	//
//	EEPROM.write(ro,,,
///	EEPROM.wr,,,        AQUI PONER NUESTRAS OTRAS VARIABLES A GUARDAR, MAX. 16
	}
	
void	_rom_load(unsigned char banco){		//LEE UN BANCO DE EPROM
	addres_rom=(banco<<4);				//multiplica por 16, = base del banco
							//LEER SINCRONIZADO CON ESCRITURA ! ! !
	ma_cntr	=EEPROM.read(addres_rom);		addres_rom++;	//
	ma_cntr	=EEPROM.read(addres_rom);		addres_rom++;	//escrita dos veces
	var0	=EEPROM.read(addres_rom);		addres_rom++;	//
	var1	=EEPROM.read(addres_rom);		addres_rom++;	//
//	ma_cntr	=EEPRO,,,
//	ma_cntr	=E,,,        AQUI PONER NUESTRAS OTRAS VARIABLES A RECOGER, MAX. 16
	}


void	_rom_bancos_ver(void){			//DUMP POR RS232 DE LOS 4 BANCOS
	addres_rom=0x0000;
	Serial.print("VARIAB  BANCO \t0\t1\t2\t3\n");	//cabezera

	Serial.print("ma_cntr (hexa \t0x");	//etiquetado , tab y 0x por escribir en hexa
	_rom_bancos_ver_comun_h();
	Serial.print("ma_cntr (deci \t");	//lo mismo en decimal, ejemplo
	_rom_bancos_ver_comun_d();
	Serial.print("var0 (hexa \t");		//PONERLAS SINCRONIZADAS CON SAVE()
	_rom_bancos_ver_comun_h();
	Serial.print("var1 (hexa \t");		//
	_rom_bancos_ver_comun_h();
		//repetir bloques para cada variable 
	}

void	_rom_bancos_ver_comun_h(void){		//PARTE COMUN HEXA
	Serial.print(EEPROM.read(addres_rom+0x00),HEX);	Serial.print("\t");//banco 0
	Serial.print(EEPROM.read(addres_rom+0x10),HEX);	Serial.print("\t");//banco 1,,,
	Serial.print(EEPROM.read(addres_rom+0x20),HEX);	Serial.print("\t");
	Serial.println(EEPROM.read(addres_rom+0x30),HEX);	
	addres_rom++;	//siguiente variable  * * O J O  es aqui donde ++
	}
void	_rom_bancos_ver_comun_d(void){		//PARTE COMUN DECIMAL
	Serial.print(EEPROM.read(addres_rom+0x00),DEC);	Serial.print("\t");//banco 0
	Serial.print(EEPROM.read(addres_rom+0x10),DEC);	Serial.print("\t");//banco 1,,,
	Serial.print(EEPROM.read(addres_rom+0x20),DEC);	Serial.print("\t");
	Serial.println(EEPROM.read(addres_rom+0x30),DEC);
	addres_rom++;	//siguiente variable  * * O J O  es aqui donde ++
	}		//hacer un addres_rom-- para ver la misma variable en hexa y deci
/* GUARDAR COMO help.ino  */
#include <avr/pgmspace.h>
#include "comandos.h"

prog_char str_02[] PROGMEM ="\n L I S T A D O   D E   C O M A N D O S   B A S I C O S , \n\n";

prog_char str_04[] PROGMEM ="PONERLOS LITERAL, RESPETAR ESPACIOS, HEXES EN MAYUS\n\n";

prog_char str_06[] PROGMEM ="'off' apaga \n";
prog_char str_08[] PROGMEM ="'on' enciende\n\n";

prog_char str_10[] PROGMEM ="'eco 0' anula eco de RS232\n";
prog_char str_12[] PROGMEM ="'eco 1' activa eco\n\n";		

prog_char str_14[] PROGMEM ="'ram?' dice donde esta el puntero a RAM, y su PEEK\n";
prog_char str_16[] PROGMEM ="'ram=@@@@' pone alli el puntero a RAM (@=cifra HEXA MAYUSC) \n";
prog_char str_18[] PROGMEM ="'poke=@@' hace POKE en puntero a RAM, PELIGRO\n";
prog_char str_20[] PROGMEM ="'ram dump' vuelca 1k de RAM desde el puntero, puntero termina aumentado\n\n";   

prog_char str_2a[] PROGMEM ="'var0=@@' variables de ejemplo\n";   
prog_char str_2b[] PROGMEM ="'var1=@@' @=cifra HEXA MAYUSC\n";   
prog_char str_2c[] PROGMEM ="'var ver' muestra las variables\n\n";

prog_char str_22[] PROGMEM ="'rom ver' muestra las variables guardadas en los 4 bancos\n";
prog_char str_24[] PROGMEM ="'rom dump' vuelca el 1�/4k de rom\n";

prog_char str_26[] PROGMEM ="'save 0' guarda variables en banco 0 de rom, el que carga al inicio\n";
prog_char str_28[] PROGMEM ="'save 1' \n";
prog_char str_30[] PROGMEM ="'save 2' \n";
prog_char str_32[] PROGMEM ="'save 3' \n";		

prog_char str_34[] PROGMEM ="'load 0' recoge variables del banco 0 de rom, el que carga al inicio\n";
prog_char str_36[] PROGMEM ="'load 1' \n";
prog_char str_38[] PROGMEM ="'load 2' \n";
prog_char str_40[] PROGMEM ="'load 3' \n\n";	

prog_char str_42[] PROGMEM ="'help' esta ayuda\n";
prog_char str_44[] PROGMEM ="'help 2' ejemplo de mala colocacion en tabla \n";		
prog_char str_46[] PROGMEM ="'h' atajo ayuda\n";

prog_char str_99[] PROGMEM ="$";	//marca mia de fin de pagina


void	_help0(void){
	_saca_memo_l(str_02);  //saca todo hasta encontrar $ dolar, una chapuza
	}
		
void	_help1(void){
	_saca_memo(str_42);
	_saca_memo(str_44);
	_saca_memo(str_46);
	}
	
void	_saca_memo(char *s_mem){		//SACA DESDE MEMORIA, ENTRA CON UN PUNTERO A MEM
	while (1) {					//bucle
		k=pgm_read_byte(s_mem);				//lee de memo prog
		s_mem++;					//apunta a siguiente
		if(!k){return;}					//si leyo 0, return
		Serial.write(k);				//ahora saca lo leido
		}	
	}
void	_saca_memo_l(char *s_mem){		//SACA DESDE MEMORIA LARGO, TERMINA CON $
	while (1) {					//bucle
		k=pgm_read_byte(s_mem);				//lee de memo prog
		s_mem++;					//apunta a siguiente
		if(!k){continue;}				//si leyo 0, salta
		if(k=='

){return;} //si leyo $, return
Serial.write(k); //ahora saca lo leido
}
}

QUE PUTADA, SE PERDIO EL 1º MSG, MENOS MAL QUE LO GUARDARA

hola amis:

cuando el ardu es extension del PC, lo bonito es enviarle "on", "off", "t barrido=01:23:45".
este problema te pones y lo sacas. pero es un rollo, ademas de T de programacion come memoria.

normalmente se hace con una cadena de if(comando="tal cosa"){comando();
para pocos comandos gana en sencillez al que propongo.

2º meter "tales cosas" en progmem,
3º hacer una tabla saltos

y la 4º meter [sato, "comando"] en una estructura en progmem.
ejempo: _ram_igual, "ram=@@@@", //@ son comodines, en este caso asciis de hexadeci, envias por consola (o programa en PC) ram=00B2 y te da el PEEK de esa memoria, que es el timer2, y se vera cambiar, los hexa en MAYUSCULAS.

empeze con un ejemplo de on off pero me lie con utilidades de ram, y rom, el comando "help" da esto:

 L I S T A D O   D E   C O M A N D O S   B A S I C O S , 

PONERLOS LITERAL, RESPETAR ESPACIOS, HEXES EN MAYUS

'off' apaga 
'on' enciende

'eco 0' anula eco de RS232
'eco 1' activa eco

'ram?' dice donde esta el puntero a RAM, y su PEEK
'ram=@@@@' pone alli el puntero a RAM (@=cifra HEXA MAYUSC) 
'poke=@@' hace POKE en puntero a RAM, PELIGRO
'ram dump' vuelca 1k de RAM desde el puntero, puntero termina aumentado

'var0=@@' variables de ejemplo
'var1=@@' @=cifra HEXA MAYUSC
'var ver' muestra las variables

'rom ver' muestra las variables guardadas en los 4 bancos
'rom dump' vuelca el 1º/4k de rom
'save 0' guarda variables en banco 0 de rom, el que carga al inicio
'save 1' 
'save 2' 
'save 3' 
'load 0' recoge variables del banco 0 de rom, el que carga al inicio
'load 1' 
'load 2' 
'load 3' 

'help' esta ayuda
'help 2' ejemplo de mala colocacion en tabla 
'h' atajo ayuda

el nucleo esta en e este fichero: GUARDAR COMO interprete.ino

/* GUARDAR COMO interprete.ino  */
/**********************************************/
/*   I N T E R P R E T E   C O M A N D O S    */
#include <avr/pgmspace.h>	//nesario por usar PROGMEM, pgm_read_byte,,

#include "interprete.h"		//decaraciones y definiciones propias de este fichero
#include "main.h"		//_ma_off, _ma_on,,, declaradas alli
#include "comandos.h"		//muchos comando alli def

typedef void (*fptr) (void); 	//define una funcion generica 

/**********************************************/
/*  P O N E R   R U T I N A   Y   S A L T O   */
PROGMEM struct {		//estrucutura contiene_
	void (*pf)(void);		//salto a funcion asociada
	char coman[10];		//letras comando asociado ! ! ! MAX 9, mejor 8, (O CAMBIAR 10)
	}tabsal[coman_top] = {	
	//con la estructura hago una matriz, EN 'coman_top' PONER CUANTAS SON, esta en .h

		_main_off,	"off",
		_main_on,  	"on",		
						//Y POR AQUI PONGO LOS PARES
		_main_eco_0,	"eco 0",	//NOMBRE DE FUNCION Y LETRAS
		_main_eco_1,	"eco 1",	//las mas usadas o urgentes al principio
						//asi ahorramos tiempo
		_ram_pregun,	"ram?",		
		_ram_igual,	"ram=@@@@",	//@ ES COMODIN, NO COMPRUEBA, 
		_ram_poke,	"poke=@@",	//pueden variar por ser cifras
		_ram_dump,	"ram dump",	
		
		_var0,  	"var0=@@",				
		_var1,  	"var1=@@",				
		_var_ver,	"var ver",				

		_rom_dump,	"rom dump",		
		_rom_bancos_ver,"rom ver",
		
		_save_0,	"save 0",
		_save_1,	"save 1",
		_save_2,	"save 2",
		_save_3,	"save 3",
		
		_load_0,	"load 0",
		_load_1,	"load 1",
		_load_2,	"load 2",
		_load_3,	"load 3",
		
		_help0, 	"help",
		_help0, 	"h",
		_help1, 	"help 2",	//PONER 1º LOS NOMBRES LARGOS, PORQUE SI NO
						//LO ASUME EL CORTO Y EL EXCESO LETRAS CANTA ERROR, EJEMPLO
		//_rom_del,	"d0",
		};//PONER EN coman_top (esta en .h) CUANTAS SON, o algun mas



/**************************************/
/******     N U C L E O         *******/
void	_interprete_patrulla(void){	//NUCLEO DEL INTERPRETE DE COMANDOS
	fptr f; //crea una funcion generica del tipo definido como fptr, no idea, sacao internet
	if(RX_c!=0x0A){	return;}	//no llego final de parrafo
	if(ptr_bufer < 3){			//si solo llegaron 0x0d y 0x0a
		_bufer_reset();
		return;}
	for(in_k=0;in_k<coman_top;in_k++){		//en in_k el numero de comando
		in_ptr=0;				//ptr a 0
		mem = tabsal[in_k].coman;			//mem apunta a inicio tabsal[in_k].coman en la progmem
		while (1) {				//bucle
			in_pgm=pgm_read_byte(mem);		//lee de memo prog
		//	in_pgm=pgm_read_byte(&(mem));		// C O M P R O B A R   funciona sin &
			in_buf=bufer[in_ptr];		//in_buf = letra a comparar, matrices lentas
			in_ptr++;				//apunta a siguiente en bufer
			mem++;					//apunta a siguiente en progmem
			if(!in_pgm){	//if(in_pgm==0){	//llego al final?
				if( in_buf == 0x0D){			//termino en el bufer 
					goto _interprete_ok;}			//si, antes coincidio, OK
				if( in_buf == 0x0A){			//termino en el bufer
					goto _interprete_ok;}			//si, antes coincidio, OK
				goto _interprete_mal;			//OTRO GOTO, VIVA RICHIE
				}
			if( in_buf == 0x0A){			//termino el bufer?
				break;} 				//si, a por otro parrafo
			if( in_pgm == '@'){			//llego comodin?
				continue;} 				//si, a por otra letra
			if( in_buf != in_pgm){			//coincide?
				break;} 				//no, a por otro parrafo	
			//fin de bucle, entonces es que coinciden letras, a por otra			
			}	
		}//NO ENCONTRO COINCIDENCIA
		
	_interprete_mal:				//interprete mal
		Serial.print("mal comando, type 'help'\n");
		_bufer_reset();
		return;
		
	_interprete_ok:					//interprete OK
		//Serial.print("_interprete_ok\n"); 	
	      
		f = (fptr)pgm_read_word(&(tabsal[in_k].pf));	//ESTE ES EL MEOLLO DEL ASUNTO
		f();
			//NO LO ENTIENDO BIEN, ES REFRITO DE RECORTES DE INTERNET
			// tabsal[in_k].pf aqui esta la direcion de inicio de la rutina
			// el & �fuerza la direcion?, no entiendo, 2 dias duro me llevo ponerlo
			// pgm_read_word(&(tabsal[in_k].pf)); como todo esta en progmem, lo lee
			// (fptr)pgm_read_word(&(tabsal[in_k].pf)); �fuerza a que el numero devuelto 
			//     sea del tipo funcion generica (fptr)?
			// el tipo 'fptr', es 'normal', no es que este en ram, pero tampoco esta 
			// fosilizada en la progmem, ella copia el fosil
			// f es una del tipo (fptr), por eso puede recibir el vector, carga escopeta
			// f() dispara
			// todo lo dicho son elucubraciones sin garantias 
			
		_bufer_reset();
		//return;	//es ultimo tonteria ponerlo			
	}

/**************************************/
/*       A U X I L I A R E S          */
void	_interprete_mal_num(void){
	Serial.print("mal numero, (�hexas en mayusculas?)\n");
	}	

unsigned char	_in_arroba_d(char n){//ENTRA UN ASCII DE DECIMAL Y SALE COMO BYTE, o error
	in_buf=bufer[n];		//in_buf = letra a traducir a byte/2
					//uso in_buf por estar libre
	in_buf-=0x30;			//ver ascii wikip
	if(in_buf>9){			//
		bitSet(ma_error,poe);
		in_buf=0;
		}
	return(in_buf);
	}	

unsigned char	_in_arroba_h(char n){//ENTRA UN ASCII DE HEXADE Y SALE COMO BYTE, o error
	in_buf=bufer[n];		//in_buf = letra a traducir a byte/2
					//uso in_buf por estar libre
	in_buf-=0x30;			//ver ascii wikip
	if(in_buf>9){			//puede tratarse de >9
		in_buf-=7;			//ver ascii wikip
		if(in_buf>15){			//
			bitSet(ma_error,poe);
			in_buf=0;
			}
		}
	return(in_buf);
	}