// Traductor Morse RS232 -> Lights & Sound
#include <18f4550.h>
#fuses HS,MCLR,NOWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOPBADEN,NOLVP,NOCPD,NODEBUG,NOWRT,NOVREGEN // Fuses
#use delay(clock=20000000) // Clock a 20 Mhz
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Canal serie con el PC
const int maxlendefinition=12; // Maxima longitud de la definicion Morse en las tablas
const long lapsus=1000; // Tiempo en milisegundos para Leds al reset
const long periodo=75; // Tiempo en milisegundos para unidad Morse = . (un punto)
const int lenrecbuffer=64; // Tamaño en bytes del buffer de recepcion
const int COMMAND_NULL=0; // COMANDO NULO -> No hay comando
const int COMMAND_PROCESS=1; // COMANDO PROCESA TEXTO -> Convertir buffer a Morse
char Version[]="1.5.0\0"; // Version del programa
char CharRcv=0; // Caracter recibido por la USART
char Command=0; // Caractar a enviar al main para su procesado
char recbuffer[lenrecbuffer]; // Buffer de recepción
int nextc=0; // Indice de siguiente caracter en recbuffer
char Numeros[10][maxlendefinition]={ // Tabla de definicion de los Numeros
"\x010\x02-----\0 ",
"\x011\x02.----\0 ",
"\x012\x02..---\0 ",
"\x013\x02...--\0 ",
"\x014\x02....-\0 ",
"\x015\x02.....\0 ",
"\x016\x02-....\0 ",
"\x017\x02--...\0 ",
"\x018\x02---..\0 ",
"\x019\x02----.\0 "};
char Letras[27][maxlendefinition]={ // Tabla de definicion de las Letras
"\x01A\x02.-\0 ",
"\x01B\x02-...\0 ",
"\x01C\x02-.-.\0 ",
"\x01D\x02-..\0 ",
"\x01E\x02.\0 ",
"\x01F\x02..-.\0 ",
"\x01G\x02--.\0 ",
"\x01H\x02....\0 ",
"\x01I\x02..\0 ",
"\x01J\x02.---\0 ",
"\x01K\x02-.-\0 ",
"\x01L\x02.-..\0 ",
"\x01M\x02--\0 ",
"\x01N\x02-.\0 ",
"\x01O\x02---\0 ",
"\x01P\x02-..-\0 ",
"\x01Q\x02--.-\0 ",
"\x01R\x02-.-\0 ",
"\x01S\x02...\0 ",
"\x01T\x02-\0 ",
"\x01U\x02..-\0 ",
"\x01V\x02...-\0 ",
"\x01W\x02.--\0 ",
"\x01X\x02-..-\0 ",
"\x01Y\x02-.--\0 ",
"\x01Z\x02--..\0 ",
"\x01Ñ\x02--.--\0 "};
char Signos[7][maxlendefinition]={ // Tabla de definicion de las Letras
"\x01 \x02 \0 ", // Espacio
"\x01,\x02.-.-.-\0 ", // Coma
"\x01?\x02--..--\0 ", // Interrogación
"\x01=\x02-...-\0 ", // Igual
"\x01-\x02-....-\0 ", // Guión
"\x01/\x02-..-.\0 ", // Barra
"\x01@\x02.--.-.\0 "}; // Arroba
#int_rda // Declaración de Interrupción ...
void rda_handler() { // Manejador de la interrupción recepcion USART
CharRcv=0; // Inicializo caracter a recibir
Command=COMMAND_NULL; // Inicializo comando para main
if(kbhit()){ // Si hay algo pendiente de recibir ...
CharRcv
=getc(); // lo recibo sobre RecRcv. if(CharRcv!=0){ // Si no es un \0 ...
recbuffer[nextc]=CharRcv; // lo copio en el buffer, ...
if(CharRcv==0x0D){ // Si he recibido un [Intro] 0x0D 13 ...
recbuffer[nextc]='\0'; // Sustituyo el 0x0D en recbuffer por el terminador \0
Command=COMMAND_PROCESS; // lo copio sobre command para procesarlo en main
} else
{
putc(CharRcv
); // lo envío de vuelta como eco y continuo ... }
if(++nextc==lenrecbuffer){ // Y si despues de incrementar nextc es igual a lenrecbuffer ...
nextc=0; // lo vuelvo a poner a cero
}
}
}
}
void limpia_recbuffer(void){
int i; // Declaro variable de índice
for(i=0;i!=lenrecbuffer;i++){ // Bucle de 0 a lenrecbuffer
recbuffer[i]='\0'; // Pongo a \0
}
nextc=0;
}
void wait_nperiodos(int n){ // Rutina que espera n peridos
int x; // Declaro variable de índice
for(x=0;x<n;++x){ // Bucle de n periodos
delay_ms(periodo); // Espero un periodo en milisegundos
}
}
char morse_parse_char(char* mistring){ // Rutina que extrae el Caracter de la tabla de definiciones
// Entrada : Puntero a la definicion Devuelve: Caracter pulsado
return mistring[1]; // Devuelvo el segundo caracter de la tabla
}
char* morse_parse_code(char* mistring){ // Rutina que extrae el código Morse de la tabla
// Entrada: Puntero a la definicion, Devuelte: Puntero al codigo
int i,j=0; // Declaro variables de indices para copiar ...
char c=' '; // Caracter a procesar uno a uno
char result[maxlendefinition]; // Buffer para el resultado
for(i=3;i<maxlendefinition,c!='\0';i++,j++){ // Bucle que comienza en el caracter 3º y termina al \0 ó en Mñáxima longitud
c=mistring[i]; // Tomo los caracteres uno a uno ...
result[j]=c; // y lo copio en el resultado
}
result[j]='\0'; // Finalizo el string del resultado con el estandar \0
return result; // Devuelvo el resultado
}
void morse_rs232(char* mistring){ // Rutina que monitoriza el código Morse extraído
// Entrada : Puntero a la definicion
char crtr; // Variable para el Carácter pulsado
char* code; // Puntero a la Variable con el Código correspondiente
crtr = morse_parse_char(mistring); // Extraigo el caracter pulsado de la definicion
code = morse_parse_code(mistring); // Extraigo el codigo morse correspondiente a ese caracter
printf("%c -> %s\r\n",crtr
,code
); // Lo envio a la RS232 }
void morse_light_punto(void){
output_High(PIN_E1); // Enciendo Led1 -> Puntos y Led0 -> Completo
output_High(PIN_E0);
wait_nperiodos(1); // Espero 1 x "periodo" de puntos
output_Low(PIN_E1);
output_Low(PIN_E0); // Apago Led1 -> Puntos y Led0 -> Completo
wait_nperiodos(1); // Espero 1 "periodo" de separacion entre puntos y rayas
}
void morse_light_raya(void){
output_High(PIN_E2); // Enciendo Led2 -> Rayas y Led0 -> Completo
output_High(PIN_E0);
wait_nperiodos(3); // Espero 3 x "periodo" de rayas
output_Low(PIN_E2);
output_Low(PIN_E0); // Apago Led2 -> Rayas y Led0 -> Completo
wait_nperiodos(1); // Espero 1 "periodo" de separacion entre puntos y rayas
}
void morse_lights(char* mistring){ // Rutina que enciende los Led's de la RRBOARD2
char* code; // Puntero a la Variable con el Código correspondiente
int i; // Declaro variable de indice para procesar ...
char c=' '; // Caracter a procesar uno a uno e inicializo en blanco
code = morse_parse_code(mistring); // Extraigo el codigo morse correspondiente a ese caracter
for(i=0;i<maxlendefinition-3,c!='\0';i++){ // Bucle que recorre el contenido de code hasta \0
c=code[i]; // Tomo los caracteres a representar uno a uno ...
switch(c){
case ' ': wait_nperiodos(5); // Espero 5 x "periodo" ( espacio entre palabras)
break;
case '.': morse_light_punto();
break;
case '-': morse_light_raya();
break;
}
}
}
void morse_process(char* mitext){
int i,x,y,z; // Variables indice de ratreo de mitext, índice relativas
// a las tablas y al caracter recibido
char xdefinition[maxlendefinition]; // Buffer para seleccionar la definicion correspondiente
char c=' '; // Caracter a procesar uno a uno e inicializo en blanco
for(i=0;i<lenrecbuffer,c!='\0';i++){
// Cargo siguiente caracter a procesar
c=mitext[i];
if(c!='\0'){
// Inicializo índices de tablas a un valor imposible
x=0xff;
y=0xff;
z=0xff;
// Letras Minúsculas, las convierto a mayúsculas
if( (c>'a'- 1) && (c<'z'+ 1)){
c = c - 'a' + 'A';
}
// Letras Mayúsculas, calculo el índice en la tabla según su código ASCII
if( (c>'A'- 1) && (c<'Z'+ 1)){
x = c-'A';
}
// Letras Especiales, puestas a güebo
if( (c=='Ñ') || (c=='ñ')){ // Ñ
x =26;
}
// Números, calculo el índice en la tabla según su código ASCII
if( (c>'0'- 1) && (c<'9'+ 1)){
y = c-'0';
}
//Signos y puntuación, puestos a güebo
if(c==' ') z = 0; // Espacio
if(c==',') z = 1; // Coma
if(c=='?') z = 2; // Interrogación
if(c=='=') z = 3; // Igual
if(c=='-') z = 4; // Guión
if(c=='/') z = 5; // Barra
if(c=='@') z = 6; // Arroba
// Guardo en el buffer de main la definicion correspondiente a lo pulsado
if(x
< 255){sprintf(xdefinition
,"%s",Letras
[x
]);} if(y
< 255){sprintf(xdefinition
,"%s",Numeros
[y
]);} if(z
< 255){sprintf(xdefinition
,"%s",Signos
[z
]);} // Presenta y/o suena (Ahora solo presenta)
morse_rs232(xdefinition);
morse_lights(xdefinition);
}
}
}
void on_reset(){
disable_interrupts(global); // Deshabilito todas las interrupciones
disable_interrupts(int_timer1); // Deshabilito ...
disable_interrupts(int_rda);
disable_interrupts(int_ext);
disable_interrupts(int_ext1);
disable_interrupts(int_ext2);
setup_adc_ports(NO_ANALOGS); // Configuro todo lo que voy
setup_adc(ADC_OFF); // a usar y lo que no ...
setup_spi(FALSE);
setup_psp(PSP_DISABLED);
setup_counters(RTCC_INTERNAL,RTCC_DIV_2);
setup_timer_0(RTCC_OFF);
setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);
setup_timer_2(T2_DISABLED,0,1);
setup_timer_3(T3_DISABLED);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
port_b_pullups(FALSE);
set_tris_e(0b00010000);
set_tris_c(0b10000000);
enable_interrupts(global); // Habilito todas las interrupciones (que esten habilitadas)
enable_interrupts(int_rda); // Habilito la interrupcion por recepcion USART
delay_ms(333); // Espero 333 milisegundos a que todo se estabilice
printf("\r\n"); // Me presento como deben hacer todos los PIC's de printf("Morse with 18F4550 in RRBOARAD2"); // buena familia printf(" v.%s by Redpic\r\n\n\n",Version
);
output_High(PIN_E0); // Enciendo los tres Led's de la RRBOARD2
output_High(PIN_E1);
output_High(PIN_E2);
wait_nperiodos(lapsus/periodo); // Espero lo que indica "lapsus" expresado en unidades de "periodo"
output_Low(PIN_E0);
output_Low(PIN_E1);
output_Low(PIN_E2); // Apago los tres Led's de la RRBOARD2
wait_nperiodos(lapsus/periodo);
limpia_recbuffer(); // Limpio el buffer de recepción
}
void main(){
On_reset();
do{ // Bucle Infinito
if(Command!=COMMAND_NULL){
if(Command==COMMAND_PROCESS){ // COMMAND_PROCESS : Convierte a Morse el contenido de recbuffer
printf("\r\n\n"); // Paso una linea en el monitor rs232 morse_process(recbuffer); // Mando procesar el contenido de recbuffer
printf("\r\n"); // Paso otra linea en el monitor rs232 limpia_recbuffer(); // Limpio el buffer de recepción
Command=COMMAND_NULL; // Limpio el ultimo comando procesado
}
}
}while(TRUE);
}