1 /******************************************************************************/
5 /******************************************************************************/
7 unsigned char codigo(unsigned char, unsigned char, unsigned char, unsigned char);
9 void inicializar_registros();
11 unsigned char recibir_trama();
12 unsigned char contestar_si_error();
13 void configurar_haz0(unsigned char, unsigned char);
14 void configurar_haz1(unsigned char, unsigned char);
15 void telec_actualizacion();
16 void telec_conformacion(unsigned char);
17 void telec_temperatura();
18 void telec_pet_Estado();
20 /* Fichero de definición de direcciones de memoria
21 asignadas a los diferentes registros */
24 /* Direcciones de los puertos P4 y P5 y del TIMER3*/
31 /* Dirección del bit que indica que hay una conversión A/D preparada */
35 Valores que utilizamos para obtener el código de Hamming de los mensajes.
36 El mensaje es de 29 bits (4 bytes) y la redundancia la tomamos de 11 bits.
37 La matriz de Hamming asociada será por tanto de tamaño (11x29) bits.
38 En las matrices siguiente colocamos la expresión hexadecimal de cada
39 una de las columnas de la matriz de Hamming. La obtención de los bits de
40 redundancia asociados a un mensaje los obtendremos haciendo la operación XOR
41 entre las columnas de la matriz de Hamming correspondientes a los '1' de los 29
42 bits del mensaje. Esto es más eficiente que realizar el producto matricial.
43 Como la memoria está organizada en bytes, utilizamos dos matrices. En una de ellas,
44 "Hamming_H", colocamos las tres primeras filas de la matriz de Hamming y en la otra,
45 "Hamming_L", las 8 filas restantes.
48 #define Hamming_H0 0x0
49 #define Hamming_H1 0x1
50 #define Hamming_H2 0x2
51 #define Hamming_H3 0x1
52 #define Hamming_H4 0x6
53 #define Hamming_H5 0x5
54 #define Hamming_H6 0x2
55 #define Hamming_H7 0x7
56 #define Hamming_H8 0x8
57 #define Hamming_H9 0x3
58 #define Hamming_H10 0x9
59 #define Hamming_H11 0x6
60 #define Hamming_H12 0x2
61 #define Hamming_H13 0x9
62 #define Hamming_H14 0x4
63 #define Hamming_H15 0x4
64 #define Hamming_H16 0x3
65 #define Hamming_H17 0x8
66 #define Hamming_H18 0x7
67 #define Hamming_H19 0x6
68 #define Hamming_H20 0x0
69 #define Hamming_H21 0x8
70 #define Hamming_H22 0x7
71 #define Hamming_H23 0x6
72 #define Hamming_H24 0x9
73 #define Hamming_H25 0x2
74 #define Hamming_H26 0x3
75 #define Hamming_H27 0x7
76 #define Hamming_H28 0x3
77 #define Hamming_H29 0x3
78 #define Hamming_H30 0x3
79 #define Hamming_H31 0x3
82 /* Dirección del bit que inicia la conversión A/D */
86 /* Valores booleanos */
91 /* Máscaras utilizadas para identificar los telecomandos */
92 #define CONFORMACION 0xC0
93 /* Telecomando que procesan todos los Subarrays. Se cambia el apuntamiento de la antena */
95 #define ACTUALIZACION 0x80
96 /* Telecomando en el que se envía a un Subarray el próximo estado de uno de los haces */
98 #define TEMPERATURA 0x00
99 /* Telecomando en el que se solicita a un Subarray la temperatura del módulo T/R */
101 #define PETICION_ESTADO 0x40
102 /* Telecomando en el que se solicita a un Subarray el estado de programación de un haz */
105 /* Valores booleanos utilizados en las rutinas de recepción de tramas */
106 #define TIEMPO_EXCEDIDO 0x01
107 #define TIEMPO_NO_EXCEDIDO 0x00
110 /* Asociamos etiquetas a los identificadores que utiliza el
111 compilador para designar algunos registros del micro */
112 #define ACUMULADOR ACC
113 #define BUFFER_SERIE SBUF
114 #define DATO_RECIBIDO RI
115 #define DATO_ENVIADO TI
116 #define PARIDAD_ACC P
117 #define BIT_PARIDAD_REC RB8
118 #define BIT_PARIDAD_TRA TB8
121 /* Sustituimos por etiquetas algunas operaciones sencillas */
122 #define obtener_direc_mensaje (BYTE[0] & 0x3F)
123 #define direccion_CONFORMACION (BYTE[1] & 0x3F)
124 #define obtener_tipo_mensaje (BYTE[0] & 0xC0)
125 #define direc_subarray ((P5 & 0x7E) >> 1)
128 /* DECLARACION DE VARIABLES */
129 volatile unsigned char int_serie;
130 unsigned char BYTE[5];
131 unsigned char BYTE_MENSAJE[3];
132 volatile unsigned char ERROR_PARIDAD;
136 Matriz que utilizamos para almacenar los estados predefinidos.
137 En las posiciones pares (0,2,4,...) están los códigos de amplitud y en las
138 impares (1,3,5,...) los de fase.
140 unsigned char tabla_estados[20];
144 Matriz en la que almacenamos los índices a la tabla de estados correspondientes a la programación
145 actual de los dos haces. Los índices tienen 11 bits de longitud. El contenido de la matriz es
147 estado_haces[0] --> haz 0, i10...i3
148 estado_haces[1] --> haz 0, i2...i0
149 estado_haces[2] --> haz 1, i10...i3
150 estado_haces[3] --> haz 1, i2...i0
152 unsigned char estado_haces[4];
160 unsigned char direc_mensaje;
161 unsigned char TIMEOUT;
162 unsigned char mensaje;
164 unsigned char DIRECCION_SUBARRAY;
166 inicializar_registros();
168 /* Obtenemos la dirección del subarray */
169 DIRECCION_SUBARRAY = direc_subarray;
171 /* bucle del programa */
174 /* Bandera que utilizamos para determinar si la interrupción
175 que se produce se ha originado en el puerto serie */
178 /* El micro entra en modo de bajo consumo mientras no se
179 produzca actividad en el puerto serie */
180 while(int_serie == 0)
183 /* Se ha detectado actividad en el bus de telecomandos. Capturamos la trama */
184 TIMEOUT = recibir_trama();
186 /* Si no se ha excedido el tiempo límite se procede a identificar el mensaje recibido */
187 if (TIMEOUT == FALSE)
189 mensaje = obtener_tipo_mensaje;
190 direc_mensaje = obtener_direc_mensaje;
192 if (direc_mensaje == DIRECCION_SUBARRAY)
193 ERROR = contestar_si_error();
195 /* Si no ha habido error en la recepción se procesa el telecomando */
200 case CONFORMACION : telec_conformacion(DIRECCION_SUBARRAY);
204 case ACTUALIZACION : if (direc_mensaje == DIRECCION_SUBARRAY)
205 telec_actualizacion();
209 case TEMPERATURA : if (direc_mensaje == DIRECCION_SUBARRAY)
214 case PETICION_ESTADO : if (direc_mensaje == DIRECCION_SUBARRAY)
227 Subrutina que actualiza el TIMER3 con el que se implementa la función WATCHDOG.
228 Esta función se habilita conectando un pin externo a nivel bajo, y funciona de
229 forma independiente al código que se ejecuta en el micro. Cuando el TIMER3 llega
230 al final de la cuenta se produce un RESET del micro, por tanto, hay que habilitar
231 un mecanismo de recarga del CONTADOR de forma que entre dos recargas no medie un
232 tiempo mayor al que emplea la cuenta.
233 Este tiempo oscila (para la frecuencia de reloj que utilizamos, 11.059 MHz) entre
234 2.22 ms para una cuenta mínima y 569 ms para una cuenta máxima.
235 Aquí usaremos el CONTADOR con cuenta máxima, para lo cual, dado que la cuenta
236 es ascendente, el valor de recarga es 0.
237 La recarga la haremos utilizando la interrupción que provoca el TIMER0 al llegar al
248 Subrutina que atiende a la interrupción provocada por la UART del puerto serie
249 cuando se ha recibido o enviado un carácter.
250 En esta subrutina lo único que hacemos es poner el valor 1 en la variable 'int_serie'
251 para indicar que la interrupción ocurrida es debida al puerto serie. Esto es necesario
252 porque el micro sale del estado de bajo consumo mediante cualquier interrupción, y sólo
253 queremos que lo haga cuando haya actividad en el puerto serie, de forma que si se produce
254 alguna otra interrupción el micro chequea esta variable y si está a 0 vuelve a entrar en
255 el estado de bajo consumo.
257 La variable 'int_serie' se pone a cero siempre justo antes de entrar en el modo de bajo
258 consumo, y es únicamente en esta subrutina donde se pone a valor uno.
260 void sint(void) interrupt 4 using 2
267 Subrutina que atiende a la interrupción provocada por el TIMER0.
268 Utilizamos esta interrupción para recargar el TIMER3 que relacionado con la operación del
270 Esta interrupción se produce (para la frecuencia de reloj que utilizamos, 11.059 MHz) cada
271 71.12 ms, lo que supone un margen de seguridad amplio frente a los 569 ms que emplea el
272 TIMER3 en realizar una cuenta.
274 void tint() interrupt 1 using 1
276 /* Llamamos a la subrutina que actualiza el TIMER3 del 'watchdog' */
282 Función que implementa la codificación de Hamming (40,32) del mensaje
283 (tc1, tc2, tc3, tc4).
284 La función devuelve la redundancia del mensaje de entrada en las variables "red"
285 Como ya hemos comentado al declarar la matriz 'Hamming', para no realizar producto de matriz
286 por vector para calcular la redundancia, almacenamos la matriz generadora de Hamming como dos
287 vectores de valores hexadecimales de longitud 29.
288 Para obtener la redundancia lo que hacemos es realizar la operación XOR entre los valores del
289 vectores "Hamming_H" cuyo índice coincide con los índices de los dígitos igual a '1'
290 en la palabra mensaje.
291 Para encontrar estos índices comparamos cada uno de los 4 bytes de que se compone el mensaje
292 con las potencias de dos (2^7, 2^6, ... , 2^1, 2^0).
294 unsigned char codigo(unsigned char tc1,unsigned char tc2,unsigned char tc3,unsigned char tc4)
296 // unsigned char red;
297 unsigned char red = 0;
301 if (tc1 & 128) red ^= Hamming_H0;
302 if (tc1 & 64 ) red ^= Hamming_H1;
303 if (tc1 & 32 ) red ^= Hamming_H2;
304 if (tc1 & 16 ) red ^= Hamming_H3;
305 if (tc1 & 8 ) red ^= Hamming_H4;
306 if (tc1 & 4 ) red ^= Hamming_H5;
307 if (tc1 & 2 ) red ^= Hamming_H6;
308 if (tc1 & 1 ) red ^= Hamming_H7;
313 if (tc2 & 128) red ^= Hamming_H8;
314 if (tc2 & 64 ) red ^= Hamming_H9;
315 if (tc2 & 32 ) red ^= Hamming_H10;
316 if (tc2 & 16 ) red ^= Hamming_H11;
317 if (tc2 & 8 ) red ^= Hamming_H12;
318 if (tc2 & 4 ) red ^= Hamming_H13;
319 if (tc2 & 2 ) red ^= Hamming_H14;
320 if (tc2 & 1 ) red ^= Hamming_H15;
325 if (tc3 & 128) red ^= Hamming_H16;
326 if (tc3 & 64 ) red ^= Hamming_H17;
327 if (tc3 & 32 ) red ^= Hamming_H18;
328 if (tc3 & 16 ) red ^= Hamming_H19;
329 if (tc3 & 8 ) red ^= Hamming_H20;
330 if (tc3 & 4 ) red ^= Hamming_H21;
331 if (tc3 & 2 ) red ^= Hamming_H22;
332 if (tc3 & 1 ) red ^= Hamming_H23;
337 if (tc4 & 128) red ^= Hamming_H24;
338 if (tc4 & 64 ) red ^= Hamming_H25;
339 if (tc4 & 32 ) red ^= Hamming_H26;
340 if (tc4 & 16 ) red ^= Hamming_H27;
341 if (tc4 & 8 ) red ^= Hamming_H28;
342 if (tc4 & 4 ) red ^= Hamming_H29;
343 if (tc4 & 2 ) red ^= Hamming_H30;
344 if (tc4 & 1 ) red ^= Hamming_H31;
352 Subrutina que implementa el envío de mensajes en respuesta a los telecomandos recibidos.
353 Los mensajes enviados son siempre de dos bytes más el byte de redundancia del código de Hamming.
354 Para utilizar el mismo código en transmisión que en recepción, se añade un tercer byte con valor
355 0 cuando se calcula la redundancia del mensaje a enviar. Esto mismo hace el módulo que recibe
356 los mensajes que envían los subarrays para chequear la corrección de dichos mensajes.
358 El proceso de envío es el siguiente.
360 - Activar el 'driver' de transmisión.
362 - Enviar 3 bytes del mensaje:
363 * Calcular la paridad de cada byte y colarla en el registro de la UART etiquetado como
365 * Colocar el byte a transmitir en el registro de salida 'BUFFER_SERIE'.
366 * Esperar que la UART indique en la bandera 'DATO_ENVIADO' que se ha enviado un byte
367 antes de enviar el siguiente.
369 - Desactivar el 'driver' de transmisión.
371 Para evitar que por alguna eventualidad la UART no actualice la bandera 'DATO_ENVIADO' y el
372 programa quede indefinidamente esperando, utilizamos la variable 'CONTADOR' que se incrementa
373 cada vez que hacemos una comprobación de la bandera. Cuando se llega a un valor límite no
374 se hacen mas comprobaciones y se sigue enviando el resto del mensaje.
375 Podríamos haber optado por abortar la transmisión en el caso de se llegue al valor límite de
376 la cuenta, porque esto indicaría que se ha producido un error. Sin embargo continuamos la
377 transmisión dejando que recaiga sobre el módulo que recibe los mensajes la responsabilidad de
378 actuar frente a la detección de un error.
379 Esto no supone ningún riesgo grave porque los mensajes de respuesta a telecomandos no afectan
380 al estado de apuntamiento de la antena.
384 unsigned char CONTADOR;
387 Paridad impar. Metemos el bit de paridad en BIT_PARIDAD_TRA antes de mandar un byte.
388 En el "flag" PARIDAD_ACC tenemos la paridad del dato que hay en el ACUMULADOR.
389 Como la paridad es impar lo negamos
392 /* Activar driver transmisión:
396 for (num_byte = 0; num_byte <3; num_byte ++)
398 ACUMULADOR = BYTE_MENSAJE[num_byte];
399 BIT_PARIDAD_TRA = ~PARIDAD_ACC;
400 BUFFER_SERIE = ACUMULADOR;
402 /* Esperamos que el dato sea enviado */
404 while ((DATO_ENVIADO == 0) && (CONTADOR < 254))
407 /* Desactivamos el flag */
411 /* Desactivar driver */
417 Subrutina que se ejecuta al comenzar a funcionar el microcontrolador
418 y que adecua al cometido que ha de realizar el micro los valores en
421 void inicializar_registros()
423 /* Registro de interrupciones:
424 habilitamos la interrupción del TIMER0 */
428 /* fosc = 11.059 MHz */
429 /* Transmisión a 9600 baudios */
434 /* Registros de los 'timers' */
435 /* Timer 1 en 'auto-reload' para generar velocidad transmisión */
436 /* Usamos el TIMER0 para recargar el TIMER3 mientras se */
437 /* espera un nuevo comando */
438 /* El TIMER1 se usa para generar el 'baud-rate' */
439 /* Los timers son de 16 bits. */
445 /* Activamos los 'timers' */
452 Subrutina que hace que el micro entre en estado de bajo consumo
456 /* Habilitamos la interrupción del puerto serie */
459 /* Activamos el modo 'idle' de bajo consumo. De este modo se sale
460 cuando se produce alguna interrupción */
463 /* Esta instrucción se ejecuta una vez que se ha salido del modo 'idle'
464 Deshabilitamos la interrupción del puerto serie */
469 Subrutina que realiza la recepción de los telecomandos. Todos tienen una longitud de 4 bytes
470 más el byte del código de Hamming.
471 Los bytes recibidos los coloca la UART en el registro 'BUFFER_SERIE', y el programa los coloca en las
472 variables 'BYTE0...4'.
473 La recepción de cada byte supone esperar que la bandera 'DATO_RECIBIDO' sea actualizada por la UART.
474 Para evitar que por alguna eventualidad el programa pudiera quedar indefinidamente esperando que se
475 actualizara dicha bandera se utiliza el mismo método que en la subrutina de enviar mensajes, la variable
476 'CONTADOR' se incrementa a cada comprobación que se hace de la bandera. Si se alcanza un valor límite,
477 en este caso, y a diferencia de la subrutina de transmisión, se aborta la recepción y se devuelve el valor
478 'TIEMPO_EXCEDIDO' indicando que ha habido un error en la recepción.
479 En este caso si que es obligado abortar el proceso puesto que de no hacerlo se podría provocar un
480 funcionamiento incorrecto de la antena al ejecutar comandos erróneos.
482 A cada byte recibido se le comprueba si la paridad es la correcta. Caso de no serlo se actualiza la variable
483 global 'ERROR_PARIDAD' que evitará que se procesen telecomandos erróneos. Un error de paridad detectado no
484 aborta la recepción. Lo que se hace es que una vez acabada se envía un mensaje indicando el error detectado.
486 unsigned char recibir_trama()
489 Variable que utilizaremos para evitar que el programa
490 se quede esperando si se produce una interrupción en
491 el puerto serie, pero no llega ningún dato
493 unsigned char CONTADOR;
495 /* Indice del byte que se está recibiendo */
496 unsigned char num_byte;
498 /* Ponemos a cero el indicador de error en la paridad de los datos recibidos */
501 /* Bucle de recepción */
502 for (num_byte = 0; num_byte < 5; num_byte ++)
506 /* esperamos que haya un dato válido */
507 while((DATO_RECIBIDO == 0) && (CONTADOR < 254))
510 /* Si no ha llegado ningún dato salimos de la función y devolvemos una señal indicándolo */
512 return TIEMPO_EXCEDIDO;
514 /* Desactivamos el "flag" */
517 /* Almacenamos el dato que ha llegado */
518 BYTE[num_byte] = BUFFER_SERIE;
519 ACUMULADOR = BYTE[num_byte];
521 /* Determinamos la paridad del dato recibido. 'PARIDAD_ACC' indica si el dato en el acumulador
522 tiene paridad par. Por tanto, habrá un error de paridad cuando la paridad recibida sea la misma
523 que indica 'PARIDAD_ACC' */
524 if (BIT_PARIDAD_REC == PARIDAD_ACC)
529 /* transmisión terminada */
530 return TIEMPO_NO_EXCEDIDO;
535 Subrutina que envía un mensaje de error si ha ocurrido alguna de las dos situaciones siguientes:
537 - Se ha detectado un error de paridad en al recepción de algún byte del último telecomando.
539 - El código de Hamming recibido no coincide con el que realmente corresponde a los cuatro bytes
540 del mensaje recibido.
542 En cada ocasión únicamente contesta un Subarray puesto que cada telecomando lleve incluido un campo
543 que identifica al Subarray direccionado, incluso cuando el telecomando es global. En este último caso
544 la dirección del Subarray está en el segundo byte del mensaje y en el resto de los casos en el primero.
545 La subrutina devuelve un indicador de si ha habido error.
547 unsigned char contestar_si_error()
549 BYTE_MENSAJE[2] = codigo(BYTE[0], BYTE[1], BYTE[2], BYTE[3]);
551 if ((ERROR_PARIDAD == 1) || (BYTE[4] != BYTE_MENSAJE[2]))
553 BYTE_MENSAJE[0] = BYTE_MENSAJE[1] = BYTE_MENSAJE[1] = 0x00;
563 /**********************************************************************************/
564 /* MAPEADO DE LAS LINEAS DE CONTROL DE LOS DOS HACES CON LOS PUERTOS DEL MICRO */
566 /* Simbolización: Haz 1, bit 2 de Amplitud -> H1A2 */
567 /* Haz 0, bit 0 de Fase -> H0F0 */
569 /* | BIT0 | BIT1 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7 | */
570 /* | | | | | | | | | */
571 /* PUERTO 0 -> P0 | H0A9 | | | | | | | | */
572 /* | | | | | | | | | */
573 /* PUERTO 1 -> P1 | H1F0 | H1F1 | H1F2 | H1F3 | H1F4 | H0F0 | H0F1 | H0F2 | */
574 /* | | | | | | | | | */
575 /* PUERTO 2 -> P2 | H0A0 | H0A1 | H0A2 | H0A3 | H0A4 | H0A5 | H0A6 | H0A7 | */
576 /* | | | | | | | | | */
577 /* PUERTO 3 -> P3 | | | | H1A8 | H1A9 | H0F3 | H0F4 | H0A8 | */
578 /* | | | | | | | | | */
579 /* PUERTO 4 -> P4 | H1A0 | H1A1 | H1A2 | H1A3 | H1A4 | H1A5 | H1A6 | H1A7 | */
581 /**********************************************************************************/
585 Subrutina que configura el HAZ 0.
586 Los valores de las líneas H9..H0 se obtienen según las siguientes expresiones:
589 H8 <-- (~A3 & A2) | (A3 & A1)
590 H7 <-- (~A3 & A1) | (A3 & A2)
591 H6 <-- A3 | (A1 & ~A2)
599 donde, '~', '|' y '&' representan la negación, la operación OR y la operación AND
600 binaria, respectivamente.
602 void configurar_haz0(unsigned char amplitud, unsigned char fase)
604 unsigned char conf_P2 = 0x00;
606 /* ponemos a cero los bits de los puertos que vamos a cambiar mediante una operación 'OR' */
612 conf_P2 |= (~(amplitud & 0x10))* 0x01;
615 conf_P2 |= (amplitud & 0x10) * 0x02;
618 conf_P2 |= (~(amplitud & 0x08))* 0x04;
621 conf_P2 |= (~(amplitud & 0x04))* 0x08;
624 conf_P2 |= (~(amplitud & 0x02))* 0x10;
627 conf_P2 |= ((amplitud & 0x08) | (amplitud & 0x04))* 0x20;
630 conf_P2 |= ((amplitud & 0x08) | ((amplitud & 0x02)&(~(amplitud & 0x04))))* 0x40;
633 conf_P2 |= (((amplitud & 0x08)&(amplitud & 0x04)) | ((amplitud & 0x02)&(~(amplitud & 0x08))))* 0x80;
636 P3 |= (((amplitud & 0x08)&(amplitud & 0x02)) | ((amplitud & 0x04)&(~(amplitud & 0x08))))* 0x80;
638 P0 |= (~(amplitud & 0x01)) * 0x01;
640 /* Actualizamos el puerto P2 */
643 /* Actualizamos el puerto P1 */
644 P1 |= (fase & 0x07) << 5;
646 /* Actualizamos el puerto P3 */
647 P3 |= (fase & 0x18) << 2;
652 Subrutina que configura el HAZ 1.
654 void configurar_haz1(unsigned char amplitud, unsigned char fase)
656 unsigned char conf_P4 = 0x00;
658 /* ponemos a cero los bits de los puertos que vamos a cambiar mediante una operación 'OR' */
663 conf_P4 |= (~(amplitud & 0x10))* 0x01;
666 conf_P4 |= (amplitud & 0x10) * 0x02;
669 conf_P4 |= (~(amplitud & 0x08))* 0x04;
672 conf_P4 |= (~(amplitud & 0x04))* 0x08;
675 conf_P4 |= (~(amplitud & 0x02))* 0x10;
678 conf_P4 |= ((amplitud & 0x08) | (amplitud & 0x04))* 0x20;
681 conf_P4 |= ((amplitud & 0x08) | ((amplitud & 0x02)&(~(amplitud & 0x04))))* 0x40;
684 conf_P4 |= (((amplitud & 0x08)&(amplitud & 0x04)) | ((amplitud & 0x02)&(~(amplitud & 0x08))))* 0x80;
687 P3 |= (((amplitud & 0x08)&(amplitud & 0x02)) | ((amplitud & 0x04)&(~(amplitud & 0x08))))* 0x08;
689 P3 |= (~(amplitud & 0x01)) * 0x10;
691 /* Actualizamos el puerto P4 */
694 /* Actualizamos el puerto P1 */
700 Telecomando en el que se envía a un Subarray concreto para actualizar uno de los estados de programación
702 El índice del estado consta de bits contenidos en BYTE1
703 Los 10 bits de la palabra del nuevo estado están en:
704 5 bits de amplitud en BYTE2[4..0]
705 5 bits de fase en BYTE3[7..3]
707 void telec_actualizacion()
709 unsigned char fase, amplitud, fila, columna, i, p;
711 /* Obtenemos la columna correspondiente al estado que se actualiza */
712 /* dentro de la matriztabla_estados */
713 columna = 1 << (BYTE[1] & 0x07);
715 /* Obtenemos la fila */
716 fila = (BYTE[1] >> 3) * 0x0A;
718 /* Obtenemos el valor de la fase */
721 /* Obtenemos el valor de la amplitud */
724 /* Actualizamos la tabla */
725 for (i = 0x00, p = 0x01; i < 0x05; i++, p <<= 1)
727 /* Colocamos un '0' en todas las posiciones correspondientes */
729 tabla_estados[fila+i ] &= 0xFF ^ columna;
730 tabla_estados[fila+i+5] &= 0xFF ^ columna;
732 /* Según el valor de amplitud y fase colocamos un '1' en las */
733 /* posiciones correspondientes */
734 if (amplitud & p) tabla_estados[fila+i ] |= columna;
735 if (fase & p) tabla_estados[fila+i+5] |= columna;
739 /* Contestamos indicando que no ha habido error.
740 Los bytes del mensaje de respuesta son 0xFC y 0x00,
741 y completa la palabra código Hamming el byte 0x76.
743 BYTE_MENSAJE[0] = 0xFF;
744 BYTE_MENSAJE[1] = 0x00;
745 BYTE_MENSAJE[2] = 0x76;
751 Subrutina que actualiza con la nueva programación las líneas de control de la red desfasadora
753 La variable 'haz_conformado' contiene la información sobre el haz que hay que reprogramar.
755 void telec_conformacion(unsigned char DIRECCION_SUBARRAY)
757 unsigned char haz_conformado, amplitud = 0x00, fase = 0x00, fila, columna, i, p;
759 /* Obtenemos la columna dentro de la matriz tabla_estados */
760 columna = 1 << (BYTE[1] & 0x07);
762 /* Obtenemos la fila */
763 fila = (BYTE[1] >> 3) * 0x0A;
765 /* Obtenemos el haz que se reprograma */
766 haz_conformado = BYTE[3];
768 /* Obtenemos los valores de las palabras de amplitud y fase */
769 for (i = 0x00, p = 0x01; i < 0x05; i++, p <<= 1)
771 if (tabla_estados[fila+i ] & columna) amplitud |= p;
772 if (tabla_estados[fila+i+5] & columna) fase |= p;
775 /* Colocamos los valores correspondientes en
776 las líneas de control */
777 if (haz_conformado == 0x00)
779 estado_haces[0] = amplitud;
780 estado_haces[1] = fase;
781 configurar_haz0(amplitud, fase);
784 if (haz_conformado == 0x01)
786 estado_haces[2] = amplitud;
787 estado_haces[3] = fase;
788 configurar_haz1(amplitud, fase);
791 /* Contestar, si corresponde, que no habido error */
792 if (direccion_CONFORMACION == DIRECCION_SUBARRAY)
794 BYTE_MENSAJE[0] = 0xFF;
795 BYTE_MENSAJE[1] = 0x00;
796 BYTE_MENSAJE[2] = 0x76;
803 Subrutina que realiza la adquisición de la temperatura del módulo T/R.
804 La conversión analógica es de 10 bits.
805 El mensaje se compone de dos bytes más el código de Hamming con la siguiente distribución:
808 BYTE1 : 0 0 0 0 0 0 T9 T8
809 BYTE2 : T7 T6 T5 T4 T3 T2 T1 T0
810 BYTE3 : H7 H6 H5 H4 H3 H2 H1 H0
812 donde T9..T0 son los 10 bits de la lectura de la temperatura y
813 H7..H0 son los 8 bits de la redundancia de Hamming.
815 void telec_temperatura()
817 unsigned char CONTADOR;
819 /* Reseteamos el registro de control del conversor A/D */
822 /* Activar la conversión A/D */
823 ADCON = ADCON | AD_INI;
825 /* Esperamos a que termine el muestreo.
826 Con la variable contador establecemos un tiempo límite de espera */
828 while (((ADCON & AD_FIN) == 0) || (CONTADOR == 250))
831 /* Si se ha superado el tiempo de espera enviamos mensaje de error */
834 BYTE_MENSAJE[0] = BYTE_MENSAJE[1] = BYTE_MENSAJE[2] = 0x00;
839 /* Realizamos la lectura del conversor */
840 BYTE_MENSAJE[0] = (ADCON & 0xC0) >> 6;
841 BYTE_MENSAJE[1] = ADAT;
843 /* Calculamos la palabra código */
844 BYTE_MENSAJE[2] = codigo(BYTE_MENSAJE[0], BYTE_MENSAJE[1], 0x00, 0x00);
846 /* Enviamos respuesta */
852 Subrutina que implementa dos funciones:
854 - Envía un mensaje en respuesta a un telecomando de petición de estado con la
855 programación actual del haz solicitado, información que está contenida en la
856 variable 'tabla_estados' en la forma siguiente:
857 * tabla_haces_prog[2*haz] <- Amplitud (5bits)
858 * tabla_haces_prog[2*haz+1] <- Fase (5bits)
860 El mensaje se compone de dos bytes más el código de Hamming con la siguiente distribución:
863 BYTE1 : 0 0 0 A4 A3 A2 A1 A0
864 BYTE2 : 0 0 0 F4 F3 F2 F1 F0
865 BYTE3 : H7 H6 H5 H4 H3 H2 H1 H0
867 - Provoca un RESET del microcontrolador cuando el telecomando de petición de temperatura
868 tiene el segundo byte igual a 0xFF.
869 Este RESET intencionado se utiliza cuando el módulo que distribuye los mensajes a los distintos
870 subarrays detecta que hay un error en el bus de telemedidas que persiste cuando se dirige a un
871 subarray en particular, o bien hay un subarray que no contesta. Estas anomalías posiblemente son
872 debidas a que un subarray por cualquier motivo desconocido ha sufrido un error en la posición de
873 memoria donde almacena la dirección que lo identifica, de forma que hay dos subarrays con la misma
874 dirección o bien un subarray tiene una dirección no válida (superior a 51, dirección máxima).
876 void telec_pet_Estado()
880 /* Comprobamos si se trata de un comando de reset */
881 /* En caso afirmativo entramos en un bucle vacío */
882 /* para que se provoque un reset */
886 Deshabilitamos las interrupciones de forma que el TIMER0 no
887 pueda activar la rutina 'watchdog()' y se produzca un RESET.
896 /* Si el telecomando es efectivamente de petición */
897 /* de estado obtenemos el haz direccionado */
900 /* Construimos los bytes de respuesta */
901 BYTE_MENSAJE[0] = estado_haces[2*haz];
902 BYTE_MENSAJE[1] = estado_haces[2*haz+1];
904 BYTE_MENSAJE[2] = codigo(BYTE_MENSAJE[0], BYTE_MENSAJE[1], 0x00, 0x00);
906 /* Enviamos mensaje de respuesta */