TIME$ - Todo cronometrado... todo sincronizado... midiendo el tiempo en el ZX Spectrum. Este texto reune todas mis notas sobre TIME$ asi como otras instrucciones relacionadas con la misma, funciones existentes en el Basic Microsoft principalmente, así como la forma de definir dichas funciones que no existen en el ZX SPECTRUM. I - El Basic Microsoft I.a - El BASICA y GW-Basic posee tres funciones: dos para el tiempo u hora y uno para la fecha. TIME$ sirve para asignar o leer la hora en curso con la sigte sintaxis: {v$=}TIME$ - devuelve la hora como cadena en formato "hh:mm:ss" TIME$= - asigna hora que puede ser "hh", "hh:mm" o "hh:mm:ss" donde: hh= hora (0 - 23) mm= min. (0 - 59) ss= seg. (0 - 59) DATE$ sirve para asignar o leer la fecha en curso con la sigte sintaxis: {v$=}DATE$ - devuelve la fecha como cadena en formato "mm-dd-aaaa" DATE$= - asigna fecha que puede ser "mm/dd/aa", "mm-dd-aa" o "mm/dd/aaaa" y "mm-dd-aaaa" donde: mm= mes (1 - 12) dd= dia (1 - 31) aa= a~o (1980 - 2099) TIMER Retorna un numero en coma flotante de simple precision el cual representa la cantidad de segundos transcurridos desde la media noche o el reinicio del sistema. Sintaxis: v=TIMER Las fracciones de segundos son calculadas para ser lo cercano en grado posible. Timer es solo lectura a diferencia de TIME$. ON TIMER(n) donde n es una expresión numérica en el rango de 1 a 86,400. Un valor fuera de este rango causa error "Illegal function call". Un acontecimiento ON TIMER(n) es usado con aplicaciones que necesitan un temporizador interno. La trampa ocurre cuando los n segundos han pasado desde TIMER ON en adelante. El ejemplo sigte. muestra la hora en la pantalla cada minuto: 10 ON TIMER(60) GOSUB 10000 20 TIMER ON .. .. .. 10000 OLDROW=CSRLIN REM Salva la fila en curso 10010 OLDCOL=POS(0) REM Salva la columna en curso 10020 LOCATE 1, 1: PRINT TIME$ 10030 LOCATE OLDROW, OLDCOL REM Restaura fila y columna 10040 RETURN En el caso del MSX - tenemos una variable del sistema de nombre TIME que se incrementa en 1 cada 1/50avo de segundo, cada vez que el procesador de video genera una interrupcion, lo cual no sucede cada vez que se lee o escribe un fichero de casete. En vez de ON TIMER, MSX usa ON INTERVAL=xx GOSUB nn y requiere de ser activada mediante INTERVAL ON. I.b - Otros BASICs TIMER Existente en los BASICs de Tandy Color Comp. y Dragon 32, actua de modo similar a su contraparte GW-Basic, pero con la diferencia de que no es solo lectura ya que permite poner a cero tambien el reloj. Devuelve un valor entre 0 y 65535 unidades de tiempo igual a 1/50 de segundo. Ejemplo de su uso - calculo del tiempo del reloj en segundos: 100 TIMER=0 110 T=TIMER/50 130 FOR I=1 TO 5000 140 NEXT I 200 PRINT T TI/TI$ Existentes en el Basic de las maquinas Commodore, no son funciones como tales, sino variables reservadas del sistema. Todas las CBM tienen reloj de tiempo real, con un ciclo de 24 horas dividido en horas, minutos y segundos. TI$= - asigna hora donde v$="hhmmss" en cuanto al uso de TI, podemos calcular el tiempo en la forma: H=TI - para el calculo de horas M=INT(TI/60) - calculo de minutos S=INT(TI/3600) - calculo de segundos TIME Función de tiempo transcurrido existente en el Basic de las CPC. Uso: el sistema mantiene la cuenta del tiempo transcurrido o 'elapsado', desde que se puso en marcha la máquina. La función TIME entrega como resultado dicho 'tiempo'. El tiempo se controla en unidades de 1/300-avos de segundo. No se mantiene actualizado el tiempo mientras se están efectuando operaciones de lectura y escritura con el cassette. TIME$ Esta version es usada por el TRS-80 y devuelve una cadena que contiene la fecha y la hora en curso en la forma: mm/dd/aa hh:mm:ss. ? LEN(TIME$) devuelve 17. El reloj es puesto a cero cada vez que se enciende o resetea la maquina. TIME En el Basic BBC puede ser usado para poner o leer el reloj interno. TIME cuenta en una centesima de intervalo de segundo. No da una hora real. Pero, una vez fijado, puede darnos una buena medida del tiempo. La tecla BREAK no resetea el reloj. Para convertir TIME en un reloj de 24 horas se usa la sigte. rutina: 1000 SEC=(TIME DIV 100) MOD 60 1010 MIN=(TIME DIV 6000)MOD 60 1020 HR =(TIME DIV 360000)MOD 24 Ejemplos: 205 TIME=(Ho*60+Mi)*60+Se)*100 400 nowtime=TIME 1070 finishtime=TIME+1000 1080 REPEAT 1090 REM wait for 10 seconds 1100 UNTIL TIME>=finishtime En el caso de APPLE II - buscando en el manual del Apple IIc lo unico que he encontrado al respecto, es CALL 64680, el cual ejecuta un bucle d retardo que tiene 0.5 (5x^2+27x+26) microsegundos de long., siendo el registro a cargar antes de su llamada el A, que debe contener el valor de retardo x. II - EN EL BASIC SINCLAIR II.a _ QL - SuperBasic El QL posee un reloj interno de tiempo real y varias funciones e instrucciones para su acceso y modificacion. ADATE <{-}s> - comando ajusta el reloj adelantandolo o retrasandolo +/- s segundos. DATE$ {(f)} - funcion donde f=fecha opcional - convierte el valor de f a cadena sin parametros = fecha y hora en la forma "aaaa mm dd hh:mm:ss" DATE - funcion sin parametros, devuelve fecha y hora como un numero real. DAY$ {(f)} - funcion donde f= fecha opcional - da el dia de la semana de f como cadena sin parametros, devuelve el dia de la semana de la fecha actual SDATE - comando fija la fecha y hora del reloj interno del QL mediante el formato: SDATE aaaa,mm,dd,hh,mm,ss. II.b _ Spectrum con BetaBasic CLOCK y TIME$() CLOCK permite usar un reloj de 24 hotras basado en interrupciones, permite ver la hora en pantalla en un formato de "hh:mm:ss" asi como una alarma manejada por una subrutina o serie de comandos. Sintaxis: CLOCK n - donde n= 0 - 7 (activa desactiva alarma o display) " n$ - donde n$= "hh:mm:ss" inicializa el reloj " "Ahh:mm" - donde "a" o "A" son para fijar la alarma en hh:mm " ln - donde ln= nro. de linea de la subrutina de la alarma " :sent:sent2:...:RETURN - actua solo si se activa la alarma Nota: debido a que trabaja con interrupciones, CLOCK se detiene si se usa BEEP u otra operacion de cinta, Microdrive o el ZX IF1. Tanto ON TIMER como ON INTERVAL podrian ser sustituidos en BB con CLOCK "A...": CLOCK ln. TIME$() es el equivalente BB exacto al TIME$ y TI$ de los otros Basics. Estos ultimos son faciles de sustituir en la conversion de listados por la version BB debido a que usa el mismo formato de tiempo. Pero que hacer si no tenemos BetaBasic? II.c _ Sin extension alguna A diferencia del QL o PCs con GW-Basic, el Spectrum carece de funciones como TIME$ que le permitan saber el tiempo transcurrido. Aun asi el manual en su capitulo 18 sobre el movimiento nos ofrece una alternativa a dicha funcion. Extraido del manual original del ZX Spectrum: " Hay una forma mucho mas segura de medir el tiempo. Y es usando los contenidos de ciertas posiciones de memoria. Los datos almacenados son recuperados mediante PEEK. El Capitulo 25 explica con detalles lo que estamos usando: la variable FRAMES. La expresion a usar es: FRAMES = (65536*PEEK 23674+256*PEEK 23673+PEEK 23672)/50 Esto nos da el numero de segundos desde que el computador fue encendido (hasta unos 3 dias con 21 horas, cuando vuelve a 0). He aqui un truco que aplica la regla. Funciones definidas: 10 DEF FN m(x,y)=(x+y+ABS(x-y))/2: REM el mayor de x e y 20 DEF FN u()=(65536*PEEK 23674+256*PEEK 23673+PEEK 23672)/50: REM tiempo, puede resultar erroneo 30 DEF FN t()=FN m(FN u(),FN u()): REM tiempo, correcto " Muy bien, esa es toda la parte que nos interesa para poder definir nuestro equivalente a TIME$. La linea 10 define una funcion que replica MOD que tampoco existe en el Spectrum. La 20 define una funcion con la expresion antes dicha con los tres PEEKs de la variable del sistema FRAMES. La 30 nos da finalmente el equivalente a TIME, TIMER o TI en la definicion de FN T(). Ahora ya solo nos falta una cuarta DEF FN para crear TIME$: 10 DEF FN M(x,y)=(x+y+ABS (x-y))/2 12 DEF FN V(x,y)=x-y*INT (x/y) 14 DEF FN Z()=FN M(65536*PEEK 23674+256*PEEK 23673+PEEK 23672, 65536*PEEK 23674+256*PEEK 23673+PEEK 23672) 16 DEF FN Z$(n)=STR$ INT (n/1800000)+STR$ INT (FN V(n,1800000) /180000)+":"+STR$ INT (FN V(FN V(n,1800000),180000)/30000)+STR$ INT (FN V(FN V(FN V(n,1800000),180000),30000)/3000)+":"+STR$ INT (FN V(FN V(FN V(FN V(n,1800000),180000),30000),3000)/500)+STR$ INT (FN V(FN V(FN V(FN V(FN V(n,1800000),180000),30000),3000), 500)/50) 18 DEF FN T$()=FN z$(FN z()) o tal vez debi decir una quinta DEF FN T$() para obtener TIME$. Ahora esto de usar varios DEF FNs para llegar adonde queriamos, es debido a que en el Spectrum no existe un DEF FN multilineas, creo yo. III - SAM Coupe III.a - con SAM Dos Curiosamente, a pesar de que el BB posee CLOCK y TIME$(), el SAM no, por lo que no me queda otra que definir TIME y TIME$ del mismo modo que hicieramos con el Spectrum. 10 DEF FN m(x,y)=(x MOD y) 20 DEF FN u()=(65536*PEEK (SVAR 634)+256*PEEK (SVAR 633)+ PEEK (SVAR 632))/50 30 DEF FN TIME()=FN m(FN u(),FN u()) Y en el caso de la segunda definicion hariamos los mismos cambios de antes, hasta llegar a: 18 DEF FN TIME$()=FN z$(FN z()) III.b - con Master Basic y Master Dos Como ya se vio, el SAM sin expansiones, carece de funciones como TI y TI$, ahora con MASTER Dos se le a~aden 4 funciones nuevas: DATE y DATE$ DATE es un comando que permite fijar la fecha con el formato de "ddmmaa" o "dd/mm/aa". DATE$ es una funcion que devuelve la fecha bajo el formato de "dd/mm/aa". TIME y TIME$ TIME es un comando con dos propositos dependiendo de su sintaxis: TIME {h$} - donde h$= tiempo en las formas "hhmmss" o "hh:mm:ss" y sin parametros= imprime en pantalla la hoa en curso. TIME$ es una funcion que devuelve la hora como cadena de 8 car. MASTER Basic a~ade una nueva funcion TICS y un nuevo parametro a TIME. TIME + activa el reloj para correr 5416.3 veces mas rapido TIME - desactiva y vuelve al modo normal TICS devuelve el numero de segundos elapsado en el mes transcurrido. Esta funcion aparentemente es el equivalente SAM a TIMER y TI. Nota: TIME en SAM es al parecer un equivalente del CLOCK del BB, pero sin la opcion de alarma y salto a subrutina si se activa o no. Para cerrar Usos de TIME o TIME$ a.- Con RANDOMIZE En algunos listados BASIC podemos encontrar: RANDOMIZE TIMER mientras en otros listados vemos: RANDOMIZE VAL(MID$(TIME$,7,2)) De estos modos el reloj interno puede usar sus intervalos como semilla del numero aleatorio. En el Spectrum el equivalente de estos ejemplos seria simplemente un RANDOMIZE sin parametros. b.- Bucles de retardo En la mayoria de listdos Basic, el bucle de retardo por excelencia es obtenido mediante bucles FOR-NEXT. VEamos como esto puede ser reemplazado por TIMER: Sea la linea: 3680 FOR J=1 TO 1000:NEXT J:RETURN En su lugar podemos usar: 3680 ST=TIMER+1.0 3681 IF TIMER