Generador RTTY Baudot con PIC


Aquí les traigo un sencillo generador de caracteres en código Baudot con modulación en doble tono para conformar el protocolo RTTY, el mismo posee el generador de tonos integrado y la generación de Baudot en el mismo.

El circuito no está en el post porque en si es solo el micro controlador y un pin de salida que en este caso se elige un 16F84A y se usa el pin RA2 como salida. Pero claramente por la sencillez del programa puede usarse cualquier micro controlador.

El programa es muy sencillo de comprender.

Básicamente tenemos dos funciones, freq1 y freq0, esto es para generar dos frecuencias (de ahí viene el doble tono) donde la freq1 "del 1 lógico" la calcule yo a 800Hz y la freq0 "del 0 lógico" a 970Hz, nótese que la distancia es de 170Hz por ende si quieren usar otros valores de frecuencia (que es totalmente valido) deben tener una distancia de 170Hz entre una frecuencia y la otra.

La norma RTTY aparte de exigir estos 170Hz también exige que cada dato se envié a 22ms por ende aquí vienen las cuentas.

tomamos como ejemplo la función freq1, observamos que ponemos el pin de salida a 0 y después a 1, la velocidad que usamos son 625us de Ton y 625us de Toff, quedando así una periodo T de 1250us lo cual si lo pasamos a frecuencia nos da 800Hz, ahora hasta ahí todo bien logramos los 800Hz que queríamos, pero cada dato debe enviarse a 22ms entonces debemos hacer que se demore durante 22ms, para ello usamos un loop del tipo while donde cuenta 17 veces y luego sale del loop, si multiplicamos 17 * 1250us nos dará 21,2ms (es casi el valor de 22ms, gracias a que existe una tolerancia no tendremos problemas). 

La función freq0 es lo mismo que esto pero calculado para 970Hz.

Estas dos funciones forman parte de la generación de doble tono, lo que sería nuestro "modem".

Ahora viene la generación de baudot, para esto se crea un vector de 18 posiciones (lo cual son 18 porque use 18 caracteres para formar "  ELECTGPL  RTTY  ").

El protocolo dice que debe ser 1 bit de start a 0 lógico, seguido de esto 5 bit del dato o el carácter y por ultimo 2 bit de Stop a 1 lógico. Notaran que en el programa está al revés, es decir primero el stop y por último el start, eso es por la forma en la que el micro entrega los bit de forma serie (pero pueden cambiarlo, yo lo he dejado así porque ya lo había codificado así).

Tenemos otro vector que es para la máscara, es decir tiene los valores ponderados de un valor binario de 8 bit, esto es simple, la forma de enviar el dato de forma serial, debe ser bit a bit, entonces esto lo hacemos comparando el dato a enviar con la máscara. Por ejemplo en el loop que tiene un for que itera 8 veces lo que se hace es comprar el byte a enviar (start, dato, stop, stop) con el byte de la máscara. Entonces si aplicamos la operación lógica AND, donde exista un 1 lógico dará verdadero y donde exista un 0 lógico dará falso, entonces si tenemos por ejemplo el primer byte a enviar "11001000" y lo comparamos contra la máscara 8 veces (mediante el incremento del índice del vector) nos dirá como resultado lo siguiente:


11001000 & 00000001 = False

11001000 & 00000010 = False

11001000 & 00000100 = False

11001000 & 00001000 = True

11001000 & 00010000 = False

11001000 & 00100000 = False

11001000 & 01000000 = True

11001000 & 10000000 = True


Esto es lo que hace el for que itera 8 veces, de esta forma recorre bit a bit todo el byte del dato y lo compara contra la máscara. Ahora, seguido de este tenemos la condición, si es verdadero llama a la función freq0 y si es falso a la función freq1, entonces como quedaría esto modulado?, de la siguiente forma.

800Hz 22ms 800Hz 22ms 800Hz 22ms 970Hz 22ms 800Hz 22ms 800Hz 22ms 970Hz 22ms 970Hz 22ms. Esta sería la salida del micro, que luego se repetirá como dice el while unas 18 veces que coincide con los 18 valores vector de datos.

La salida puede ser acoplada como en mi práctica a un transmisor de AM de 80m pero es posible acoplarla a cualquier entrada de AF.

#include <16F84A.h>
#fuses XT
#use delay(clock=4000000)
#define AUDIO PIN_A2
freq1(){        //625us + 625us = 1250us = 800Hz
   int q=0;
   while(q<17){ //22ms / 1250us = 17 veces.
      output_low(AUDIO);
      delay_us(625);
      output_high(AUDIO);
      delay_us(625);
      q++;
   }  
}
freq0(){        //515us + 515us = 1030us = 970Hz
   int p=0;
   while(p<21){ //22ms / 1030us = 21 veces.
      output_low(AUDIO);
      delay_us(515);
      output_high(AUDIO); 
      delay_us(515); 
      p++;
   }  
}
void main(){
   int i,j;     
   byte valor;
   byte const bitMask[8]={1,2,4,8,16,32,64,128};
   byte const ByteDatosSalida[18]={
      0b11001000, //11 00100 0, STOP STOP ESPACIO START
      0b11001000, //11 00100 0, STOP STOP ESPACIO START
      0b11000010, //11 00001 0, STOP STOP "E" START
      0b11100100, //11 10010 0, STOP STOP "L" START
      0b11000010, //11 00001 0, STOP STOP "E" START
      0b11011100, //11 01110 0, STOP STOP "C" START
      0b11100000, //11 10000 0, STOP STOP "T" START
      0b11110100, //11 11010 0, STOP STOP "G" START
      0b11101100, //11 10110 0, STOP STOP "P" START
      0b11100100, //11 10010 0, STOP STOP "L" START
      0b11001000, //11 00100 0, STOP STOP ESPACIO START
      0b11001000, //11 00100 0, STOP STOP ESPACIO START
      0b11010100, //11 01010 0, STOP STOP "R" START
      0b11100000, //11 10000 0, STOP STOP "T" START
      0b11100000, //11 10000 0, STOP STOP "T" START
      0b11101010, //11 10101 0, STOP STOP "Y" START
      0b11001000, //11 00100 0, STOP STOP ESPACIO START
      0b11001000};//11 00100 0, STOP STOP ESPACIO START
   while(true){
      delay_ms(3000);              //delay de repeticion 3s
      i=0;
      while(i<18){                 //cantidad de caracteres 18
         valor=ByteDatosSalida[i]; //carga valor con dato de salida
         for(j=0;j<8;j++){         //recorre los 8 bit del baudot
            if(valor&bitMask[j])   //aplica la mascara
               freq0();            //si es verdadero envia 970Hz
            else
               freq1();            //si es falso envia 800Hz
         }i++; 
      }
   }
}
 



1 comentario: