Ajuste de AZIMUT by Z80user

Todo sobre la creación, diseño y programación de nuevo software para
nuestro Spectrum

Moderador: Sir Cilve Sinclair

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Mié Feb 29, 2012 5:12 pm

Código: Seleccionar todo

start   DI
        LD      HL,#7F40
        LD      D,#58
loop    LD      B,#00
bucle1  LD      A,H
        IN      A,[#FE]
        XOR     A,C
        AND     A,L
        JR      NZ,findA
        DJNZ    bucle1
findA   LD      E,B
        LD      A,[DE]
        INC     A
        AND     A,H
        LD      [DE],A
        LD      C,#FF
bucle2  LD      A,H
        IN      A,[#FE]
        XOR     A,C
        AND     A,L
        JR      NZ,findB
        DJNZ    bucle2
findB   LD      E,B
        LD      A,[DE]
        INC     A
        AND     A,H
        LD      [DE],A
        LD      C,#00
        LD      A,H
        IN      A,[#FE]
        RRA
        JR      C,loop
        EI
        RET
Rutina optimizada en tamaño y velocidad, de "EL AJUSTE DEL AZIMUT " aunque mas espartana.

Basicamente lee cuando hay un cambio en el nivel de entrada de audio y muestra un cuadradito cambiante de color, en basic, funciona perfectamente, sin hacer push/pop.

Para finalizar la rutina, se pulsa la tecla Espacio.
El programa funciona de la siguiente forma:
Cuando detecta un cambio de nivel, mide la duracion, marcando un cuadradito en la posicion #58xx, cuanto mayor es el valor de xx, mas rapida fue la frecuencia que capturo. Despues vuelve a hacer otra deteccion de cambio de nivel, cambiando con el offset xx otro bloque de color.
Apartir de estos 2 cambios de color, que se pueden observar tranquilamente, se puede detectar la frecuencia a la que ha detectado una forma de onda.
Cuando no hay señal, se cambia el color del cuadradito en 0:0
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Ajuste de AZIMUT by Z80user

Mensaje por antoniovillena » Mié Feb 29, 2012 8:04 pm

Hola Z80user

Hace poco publiqué una rutina parecida, la misma que se usa en el calibrador de CargandoLeches. La anuncié en los foros de WOS:
http://www.worldofspectrum.org/forums/showthread.php?t=38080

El algoritmo es distinto, en lugar de temporizar un pulso se hacen muchas lecturas al puerto y se cuentan las veces que sale 0 y las veces que sale 1. En una primera versión usé atributos, por lo que había 32 posibles valores. Luego añadí el caracter que está dividido por la mitad, por lo que ahora tiene 64 posibles valores y lo más importante, un valor central con el que calibrar.

Si te interesa duplicar la resolución, aquí tienes el código.

Código: Seleccionar todo

        output  "loadverify.bin"
        org     $5ccb*2-$2d25+fin-ini
ini     nop
        di
        ldir
        db      $de, $c0, $37, $0e, $8f, $39, $96
        jp      jump
jump    ld      b, 32
aki     ld      a, 133
        rst     10H
        djnz    aki
loopi   ld      h, b
        ld      l, c
        ld      bc, $7ffe
        ld      de, $1820
loop1   in      a, (c)
        jp      po, zero
        jp      balan
zero    ld      a, d
        inc     hl
balan   xor     $10
        out     (c), a
        djnz    loop1
        dec     e
        jr      nz, loop1
        rl      l
        ld      a, h
        ld      de, $591e
        ld      hl, $591f
        ld      c, l
        ld      (hl), b
        lddr
        ld      l, a
        ld      (hl), $5b
        jr      nc, loopi
        ld      (hl), $43
        inc     l
        ld      (hl), d
        jr      loopi
fin
/*<?php require 'zx.inc.php';
  generate_basic('loadverify', "\357\326\26\7\14\20\4\21\4\335")?>*/
Imagen

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Re: Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Mié Feb 29, 2012 11:43 pm

La tuya "sincroniza", y es menos sensible, el cuadradito en un emulador no baila apenas, salvo al iniciar, o finalizar un bloque, en la mia, no se esta quieta salvo que no haya señal. Ni activando la memoria contenida, con interupciones, y cinta defectuosa (con lloro) en el ZXSPIN ya baila un poco
La mia asi bailan bastante, con un "Pilot Pulse" basico baila entre 2 bloques, con todo, baila entre muchas posiciones.

Asi que basicamente hacen cosas distintas
Lo que yo no hago es borrar lo que pinto, se queda muy feo, despues de un tiempo, y es aconsejable tener un texto detras para ver mas detalles.
Esta ingeniosa la forma de doblar la resolucion :-) pero ya tiene resolucion de sobra 255 posiciones, la 256 no sirve, es cuando no detecta señal. Aunque para cosas normales no utiliza mas de unas 52 pocisiones utilies y alguna mas alta, cuando detecta algun ruido (con una cinta emulada, la verdad, no se como aparece tanto ruido)

Podria servir como detector del tipo de carga, viendo que pinta
10 FOR n =1to16 : PRINT "FEDCBA9876543210":NEXT n : RANDOMIZE USR ...
con eso se ve mejor donde esta variando

La mia sirve para detectar frecuencias, por ejemplo, permite conocer la frecuencia aproximada de un modo de carga turbo, e indicar aproximadamente el metodo de carga, apartir de que cuadraditos se encienden.
Indica lo buena que es la grabacion, de acuerdo a cuanto se muevan los cuadraditos, que se pinten 2 o 3 cuadraditos cercano es lo ideal.
Tomar el numero de bits a 0 o a 1, con los metodos normales de carga, por deteccion de la frecuencia, como tienen un ciclo a 50%, puer lo raro, es que se desvie del centro, que parece que es en lo que se basa la tuya.

Spectrum, y la mayoria de los sistemas de carga del Spectrum, usan el "clock" si es un 0 y "doble clock" si es un uno (Densidad de codigo, proxima al 66%)
Para la rutina que desarollo, estoy usando un Non-return-to-zero (de densidad de codigo 100%), aunque ni tu rutina ni la mia, sirven para poder observar algo, aunque fuese infinitamente mas lenta
para transmitir 1 byte #00 usa esta secuencia

Código: Seleccionar todo

_.-._.-._.-._.-.----._.-._.-._.-._.-.______
D P D P D P D P SSSS D P D P D P D P SSSSSS

D = Dato
P = paridad
S = Sincronizacion, correccion de errores y escribir el dato en memoria, y si hay un error en la correccion de errores, marca el bloque como defectuoso y continua la carga, para no dessincronizarse.

Asi que aun se pueden hacer mas detectores de carga Azimut y demas :-)

Esta la he hecho, para poder detectar con ella, frecuencisa, y mas esactamente lo bueno que sera el clon, para leer desde una funte externa, Usando un PC de generador de ondas cuadradas, unicamente modulando la frecuencia, deberia bastar.

No cumple la componente continua, que es lo que detecta tu rutina perfectamente, pero se le aproxima bastante. Basicamente, es que la señal este el mismo tiempo a 0 que a 1. Aqui la tengo algo mas de tiempo a 0 que a 1.

La O tildada impide que se direccione la pagina correctamente.
componente continua = http://es.wikipedia.org/wiki/Códigos_en_línea
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Ajuste de AZIMUT by Z80user

Mensaje por antoniovillena » Jue Mar 01, 2012 1:19 am

Hola Z80user

Ya he estudiado el código de tu rutina, la he ensamblado y probado en un emulador. Por cierto al ensamblar con sjasmplus he tenido problemas con "XOR A,C" y "AND A,L" que las reconoce como macro (XOR A seguido de XOR C y lo mismo con AND).

No tienen nada que ver. Lo que haces es medir la duración de los pulsos, y el dial (pensé equivocadamente que era una barra de 32 caracteres) muestra la frecuencia. En mi caso da igual la frecuencia, lo que mido es el duty cycle de una onda cuadrada, que supuestamente tiene que ser el 50%, pero varía si está mal ajustado el azimut.

Yo me he basado en el código de la ROM del Tape Tester del spectrum 128K. Sin mirar mucho tu código pensé que lo que hacías era medir el duty cycle dividiendo la duración del primer pulso entre la suma del primero y el segundo. Lo que no entiendo es cómo saber cuando el azimut está bien calibrado con tu sistema.

No sabía que había más gente investigando en nuevas rutinas de carga. Hace varios años probé también NRZ pero con malos resultados. Los grandes avances en esta materia los consiguió decicoder con su throwing shavings. Se trata de codificar símbolos de 2 bits y se pueden conseguir hasta el 80% de la velocidad de muestreo en media onda, y hasta el 57% en onda completa (CargandoLeches usa onda completa). Lo máximo que he visto cargar por audio en spectrum real son 27428 bps, aunque supongo que con frecuencias de muestreo mayores (96000, 192000) y con otras modulaciones se podrían llegar a los 50000 bps.
Imagen

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Re: Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Vie Mar 02, 2012 10:01 am

La rutina tiene 16 velocidades distintas
Tiempo por byte = 92*Y*Z + 236*Z +176
Y puede ser 1,2,3,4,5,6,7, u 8 ... Z puede ser 7 u 8

Las velocidades son entre 1415 bytes/s y 440 bytes/s
Permite un nivel de ruido (detectar algo incorrectamente) en todas las velocidades

Velocidad de la rutina mas rapida 1415 Bytes/s = 22640 muestras/s
Velocidad de la rutina mas lenta 440 Bytes/s = 28160 muestras/s

Si el numero de muestras/s es inversamente proporcional a los bytes/s, pero es mas inmune al ruido. como maximo puede existir 1 error por nibble (cada 4 bits), y puede detectar errores de longitud 2, segun version.

NOTA: el numero de baudios/s en esta rutina no se como tomarlo.
De cada 7 u 8 "muestras confirmadas", solo se genera 1 nibble.

Si lo maximo que has visto son 27428 baudio, esta no batira ese record, se quedaria en unos 11320 baudios (1415bytes/s *8bits/byte), y la genera varias frecuencias sonoras, no una o dos frecuencias base. es mas melodica :mrgreen:
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Ajuste de AZIMUT by Z80user

Mensaje por antoniovillena » Vie Mar 02, 2012 10:57 am

Bueno, 11320bps es una muy buena velocidad, casi 8 veces más rápido que la carga estándar. Lo que no me concuerda es que uses frecuencias de muestreo de 22640 y 28160. Tendrías que normalizar estas frecuencias para que funcionen con fuentes de audio normales. La de 22640 se puede convertir a 22050, pero la de 28160 queda un poco lejos de alguna conocida.
Imagen

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Re: Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Sab Mar 03, 2012 12:49 am

Velocidad de la rutina mas rapida 1415 Bytes/s = 19810 muestras/s (perdon son 19810, 22640, es para otra velocidad)

27428 bps, es la velocidad mas alta de carga, con un PC como generador de sonido, si no recuerdo mal. (3428.5 Bytes/s)
48000/27428 = 1.75 muestras/bit
44100/27428 = 1.61 muestras/bit
El problema, es que la tarjeta de sonido no puede hacer 1/4 ni 1/2 ni 3/4, solo puede hacer una frecuencia de 48KHz, o 44.1KHz

... mas bien cada 12 muestras de la tarjeta de sonido del PC, El spectrum es capaz de capturar unicamente 8 muestras (383.33 T-States), despues durante 291.66 T-States esta esperando a sincronizarse.

Asi que optimizando un poco la rutina, se podrian sacar facilmente otros cuantos baudios.
El truco esta en que cada 875 T-States, hay un margen de 73 T-States, para leer cada uno de los baudios, pero despues de un tiempo, la sincronizacion se pierde, si se leen todos. es lo que tiene de especial esa rutina ultrarapida, que la longitud de la rutina, sea 875 T-States, en ese tiempo puedes hacer la mejor rutina que creas conveniente. Asi que la rutina con una tarjeta de sonido de PC, esta limitada a 48.000 baudios

Código: Seleccionar todo

.__.__.__.__.__.__.__.__.__.__.__._
_._._.____._._.____._._.____._._.__
Ambas lineas tienen el mismo numero de muestras (los puntos), en el mismo periodo de tiempo, pero se necesitan frecuencias distintas para ser capturadas.

La autosincronizacion la puedo hacer con algunas variantes -5/0/+5 o -10/0/+12 o con variaciones mayores

Lo que trato de evitar es el mensaje "R Tape loading error, 0:1", no una rutina optimizada en velocidad, sino, con algo de inmunidad frente al ruido y que se pueda grabar en una cinta de audio convencional en la medida de lo posible.

La velocidad de 1415 B/s a mi no me gusta, pierde muchas propiedades conparadola con otras versiones, la version mas basica que crearia, seria de 930 B/s (Y=3 y Z=7), porque tiene autosincronizacion, las versiones con Y=1o2 no lo tienen autosincronizacion. las mejores versiones, desde el punto de vista tecnico son las Y=5 y Y=7 con Z=8.
485 B/s, 552 B/s, 609 B/s, y 693 B/s.
La rom, tiene una velocidad media de 191.875 B/s asi que es entre 2.5 y 3.6 veces mas rapida.
Para un 128KB pasamos de 11:23 minutos, a 3:09 minutos con correccion de errores, o 3:35 con correccion y deteccion de errores.
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Ajuste de AZIMUT by Z80user

Mensaje por antoniovillena » Sab Mar 03, 2012 10:58 am

Hola Z80User

Los 27428bps son a 48000Hz, a 1.75 muestras por bit. A 44100Hz la velocidad es de 25200bps. La razón de por qué 1.75 y no 2 por ejemplo es esta:

-Los bits se transfieren en grupos de dos, es forma de símbolos. Existen 4 símbolos distintos, cada uno de distinta duración. Esta es la forma más eficiente de modular, tanto a 1 bit por símbolo como a 3 bits por símbolo se consiguen peores velocidades.
-Como es una versión de onda completa (las de media onda nunca funcionaron bien) el símbolo de menor longitud necesita dos muestras, una para el pulso alto y otra para el pulso bajo. El resto de símbolos tienen una duración de 3, 4 y 5 muestras.
-La media de duración de cada símbolo es de (2+3+4+5)/4= 3.5 muestras. Como se transmiten 2 bits, esto nos da 1.75 muestras por bit.

Este método se llama "throwing shavings", lo descubrió decicoder y lo usó por primera vez en la herramenta k7zx. A dia de hoy es el método más rápido y fiable que existe para cargar en spectrum con una fuente de audio.

Con respecto a tu método, he leído varias veces tu último post y no me entero de nada. Lo veo interesante y me gustaría saber en qué fase de desarrollo está, si lo has probado en spectrum reales y si vas a publicar los fuentes.
Imagen

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Re: Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Sab Mar 03, 2012 2:02 pm

Código: Seleccionar todo

NOTA: Los puntos es cuando se toma una muestra.
NOTA: Ejemplo de longitud del sample de 1 nibble, con ambos sincronismos laterales.
Patron 1
Señal    = _________---------_________---------_________---------_________---------_________---------
Muestras =           .......  .......  .......  .......  .......  .......  .......  ....... 

Patron 2
Señal    = _________---------_________---------_________---------_________---------_________---------
Muestras =          ....... .......+ .......+ .......+ .......+ .......+ .......+ .......+

Patron 3
Señal    = _________---------_________---------_________---------_________---------_________---------
Muestras =           .......   .......   .......- .......- .......- .......- .......- .......-

Patron 4
Señal    = _________---------_________---------_________---------_________---------_________---------
Muestras =       .......+  .......+  .......+  .......  .......  .......  .......  ....... 

Patron 5
Señal    = _________----_----____-____-_-----_-__--_____---__----___-_____---_-----____-____---------
Muestras =           .......  .......  .......  .......  .......  .......  .......  ....... 

Patron 6
Señal    = _________---------___________________________---------_________---------_________---------
Muestras =           .......  .......  .......  .......  .......  .......  .......  ....... 

Patron 7
Señal    = _________---------___________________________---------------------------_________---------
Muestras =           .......  .......  .......  .......  .......  .......  .......  ....... 

Patron 8
Señal    = _________---------_-_-_-_-_---------_________---------_________---------_________---------
Muestras =           .......  .......  .......  .......  .......  .......  .......  ....... 

Patron 9
Señal    = _________---------_-_-_-_-_---------_________-_-_-_-_-_________---------_________---------
Muestras =           .......  .......  .......  .......  .......  .......  .......  ....... 
Patron 1: Lo ideal, cada muestra se lee cuando debe
Patron 2: Leemos mas rapido de lo que la señal llega, insertamos una pausa
Patron 3: Leemos mas lento de lo que la señal llega, reducimos el tiempo hasta la siguiente lectura
Patron 4: Maxima resincronizacion entre 2 bits, al cabo de un tiempo se resincroniza (son necesarios cambios de nivel)
Patron 5: Algunas muestras toman un valor erroneo. Se corrige perfectamente, con el nivel 1 de correccion de errores
Patron 6: Algunos bit no se grabaron correctamente. Se corrige perfectamente, con el nivel 2 de correccion de errores
Patron 7: 2 bits se leyeron de forma incorrecta, ERROR detectado durante la carga, detectadon con el 2º nivel de correccion
Patron 8: 1 bits fueron leidos de forma incorrecta. La carga continua, es un error admitible, ya que podemos corregir 1 bit
Patron 9: 2 bits fueron leidos de forma incorrecta. La carga continua, es un error admitible, ya que podemos corregir 1 bit y si son 2 errores es detectable, aqui tenemos un 25% de posibilidade de interpretar ambos bits, de forma erronea, el 50% de corregir el error, y un 25% de haberlos interpretado de forma correcta. Si son 2 detecciones erroneas, y hemos corregido 1 bit, estamos seguros que el nibble escrito es correcto

Cualquier otro caso, salvo olvido, creo que no esta contemplado.

Para un numero inpar de muestras, es facil cual es el valor que mas se repite. y dar un valor.
Para un numero par de muestras, leer el 50% con valores distintos, se considera un error.
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Ajuste de AZIMUT by Z80user

Mensaje por antoniovillena » Sab Mar 03, 2012 2:48 pm

Gracias Z80User. Con este último mensaje he comprendido mejor el formato que usas. Pero sigo sin saber en qué estado de desarrollo está, si hay código escrito, si este código funciona en un spectrum real, y si estarías dispuesto a compartirlo con la comunidad.
Imagen

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Re: Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Sab Mar 03, 2012 11:41 pm

Hay codigo escrito, lo publique hace tiempo, aunque con un bug, introducido al transcribirlo, porque en el emulador corria cuando lo puse, que es en donde conte los T-States para sincronizar las rutinas.
viewtopic.php?f=6&t=2047&p=21830
Viene con una explicacion de como funciona, algo mas somera. Aqui he explicado como funciona la onda (por no desviarme del hilo demasiado).
Lo unico de la rutina, mas que la rutina en si, son las 2 tablas de 128 o 256 bytes y la de 16 bytes, ambas son las responsables del funcionamiento de la rutina.
Como la rutina SAVE, esta la mayoria del tiempo en un bucle, se puede hacer que en donde la rutina LOAD no tenga lectura, pueda hacer que suene una melodia, insertando algun error, y modificando los niveles base, cuando la rutina LOAD esta en la fase de correccion.

Como he dicho, hay 16 posibles versiones, cada rutina SAVE y LOAD, tienen que estar sincronizadas en nivel de T-States. En la rutina LOAD es basicamente cambiar 2 bytes, para indicar que metodo de carga se utiliza.
En la rutina SAVE, es hacer que la duracion de los retardos sea la adecuada, sobra bastante tiempo.
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Ajuste de AZIMUT by Z80user

Mensaje por antoniovillena » Dom Mar 04, 2012 12:32 am

Por lo que veo pone que está sin probar. Me gustaría ayudarte, pero no puedo perder tiempo en ensamblar algo que no sé si funcionará, y en caso de que no funcione no saber qué hacer. A ver el algoritmo es interesante, es mucho más rápido que la carga estándar y podría funcionar en cinta. Pero al menos tendrías que hacer una demo en un archivo TZX o WAV que funcione en algún emulador.
Imagen

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Re: Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Dom Mar 04, 2012 2:37 pm

Ya he dicho que el inconveniente, es crear las tablas, la rutina no lee los datos mucho mas rapido que algunas cargas que ya existen
Para la rutina SAVE, independientemente del tiempo que tarde, para sincronizarse con la rutina LOAD
Existen 725760 tablas en total: 80640, para el metodo de hamming (de 7 bits) y 645120, para el metodo de hamming ampliado ( de 8 bits).

Opciones:
1º Modo de ordenar
D3-D2-D1-D0-P3-P2-P1-PP
D3-D2-D1-D0-P3-P2-PP-P1 son 2 tablas distintas.

2º Inversion de bits
Para evitar un silecion demasiado largo, para codificar el bible #0 y #F, se invierten algunos bits.

Datos para la rutina SAVE, configuracion D3-P1-D2-P2-D1-P3-D0-PP, Hamming extendido,
DB #55,#03,#48,#1E,#30,#66,#2D,#7B,#84,#D2,#99,#CF,#E1,#B7,#FC,#AA

Para la rutina LOAD, 3 bits se generan de la siguiente manera
3º Segun el numero de muestras por bit, se puede detectar un flanco (no valido para 1 y 2 muestras), metodo explicado en los "patrones" de un mensaje anterior

Código: Seleccionar todo

Ejemplo para 3 muestras por bit
000 = bit=0, perfecto
001 = bit=0, relentizar
010 = bit=0, normal / error (Se puede considerar ruido de linea)
011 = bit=1, acelerar
100 = bit=0, acelerar
101 = bit=1, normal / error (Se puede considerar ruido de linea)
110 = bit=1, relentizar
111 = bit=1, perfecto
para 4 muestras o mas, es similar

Codificacion:
B7-B6 = 01 para normal y perfecto, 00, para acelerar, 11, para relentizar, 10, para error.
B5 = bit mas probable, si B7-B6 = 10, se puede usar para otra tarea.
B4-B1 = el nibble, una vez corregido, con hamming.
B0 = Para indicar si ha habido un error de paridad por el metodo de Hamming extendido.

Si se omite el metodo de hamming extendido, se puede variar, para ganar algo mas de velocidad a:
B5 = indiferente
B4-B1 = el nibble, una vez corregido, con hamming.

Basicamente con esta informacion, se crear el metodo. (quien quiera los ficheros que me deje un privado con su e-mail especificando lo que quiere "Rutina de carga")
NOTA: La rutina no tiene pre-rutina de sincronizacion, es solo la parte de lectura y escritura propiamente dicha. y no tienen los timmings ajustados. En su momento fue una prueba de concepto.

Lo de crear un un WAV o TZX, no se de ningun emulador que permita capturar un OUT [#FE],A a un fichero
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Avatar de Usuario
antoniovillena
Nonamed
Mensajes: 1164
Registrado: Dom Ene 09, 2011 8:55 am

Re: Ajuste de AZIMUT by Z80user

Mensaje por antoniovillena » Dom Mar 04, 2012 3:11 pm

Z80user escribió:Lo de crear un un WAV o TZX, no se de ningun emulador que permita capturar un OUT [#FE],A a un fichero


Es que normalmente las ultracargas se generan con PC y se reproducen con un spectrum, por lo que los WAV o TZX los generarías con un programa en el lenguaje que suelas usar sobre PC. El WAV o TZX tendría una primera parte en carga estándar que carga el código Z80, y una segunda parte que es la ultracarga en sí. Si te resulta complicado juntar estas dos partes puedes tener un TAP o SNA para el código Z80 y generar el WAV o TZX sólo con la ultracarga.

Te recomiendo que uses una pantalla de carga de algún juego (el que más te guste) como ejemplo. Y una vez hayas comprobado que funcione tienes que indicar en qué emulador lo has probado, qué versión, y qué opciones has usado (por ejemplo fast loading desactivado) para que podamos reproducir tus resultados.

Si tienes problemas para generar el WAV o no sabes el formato que poner en la primera parte (carga estándar), quizás este código fuente te ayude. Es el generador de WAVs que usa CargandoLeches para crear ficheros en carga estándar partiendo de un fichero TAP, un SNA de 48K ó uno de 128K.

http://emuscriptoria.svn.sourceforge.net/viewvc/emuscriptoria/leches/

Archivo leches_std.php

Código: Seleccionar todo

<?
function outbits($val){
  global $inibit, $bytes;
  for($i= 0; $i<$val; $i++)
    $bytes.= $inibit ? '@' : 'Ч;
  $inibit^= 1;
  for($i= 0; $i<$val; $i++)
    $bytes.= $inibit ? '@' : 'Ч;
  $inibit^= 1;
}
function pilot($val){
  global $mhigh;
  while( $val-- )
    outbits( 14 << $mhigh );
}
function block($str, $type){
  $chk= $type;
  for($i= 0; $i<strlen($str); $i++)
    $chk^= ord($str[$i]);
  return chr($type) . $str . chr($chk);
}
$argc==1 && die(
  "\nCargandoLeches Standard WAV generator v0.1 14-02-2012 Antonio Villena, GPLv3 license\n\n".
  "  leches_std file.tap [Sample Rate] [Polarity]\n".
  "  leches_std file.sna [Sample Rate] [Polarity] [Address Patch]\n\n".
  "-Sample Rate: In Khz and rounded (22, 24, 44 or 48). For 22050, 24000, 44100 and 48000Hz\n".
  "-Polarity:    0 or 1. If 1 the WAV signal is inverted. Same results if the signal is balanced\n".
  "-Address Patch: Address used in SNA for storing the register. Must be unused in the game\n\n".
  "Only file is mandatory. Default values are 44 (Sample Rate), 0 (Polarity) and 5780 (Address Patch)\n");
$mlow= $argv[2]==24 || $argv[2]==48 ? 1 : 0;
$mhigh= $argv[2]==22 || $argv[2]==24 ? 0 : 1;
$srate= array(array(22050,24000),array(44100,48000));
$inibit= $argv[3]==1 ? 1 : 0;
$st= array();
for($i= 0; $i<256; $i++){
  for( $j= 0; $j<8; $j++ )
     outbits( ($i<<$j & 0x80 ? 10 : 5 ) << $mhigh );
  $st[$i]= $bytes;
  $bytes= '';
}
file_exists($argv[1]) || die ("\n  Error: File not exists\n");
$nombre= substr($argv[1],0,-4);
$sna= file_get_contents($argv[1]);
$noprint || print("\nGenerating WAV...");
if( strtolower(substr($argv[1],-3))=='tap' ){
  while( $pos<strlen($sna) ){
    $len= ord($sna[$pos++])|ord($sna[$pos++])<<8;
    pilot( 2000 );
    outbits( 4 << $mhigh );
    while( $len-- )
      $bytes.= $st[ord($sna[$pos++])];
  }
}
else{
  strtolower(substr($argv[1],-3))=='sna' || die ("\n  Invalid file: Must be TAP or SNA\n");
  $r= ord($sna[20]);
  $parche= isset($argv[4]) ? hexdec($argv[4]) : 0x5780;
  if( strlen($sna)==49179 ){
    $r= (($r&127)-13)&127 | $r&128;
    $sp= ord($sna[23]) | ord($sna[24])<<8;
    $regs=  chr(0x21).substr($sna, 7, 2).chr(0xe5).pack('v', 0x8f1). // AF'
            chr(0x3e).ord($sna[26]).chr(0xd3).chr(0xfe).  // Border
            chr(0x01).substr($sna, 13, 2).                // BC
            chr(0x11).substr($sna, 11, 2).                // DE
            pack('v', 0x21dd).substr($sna, 17, 2).        // IX
            chr(0x3e).chr($r).pack('v', 0x4fed).          // R
            chr(0x21).substr($sna, 21, 2).pack('v', 0xf1e5). // AF
            chr(0x21).substr($sna, 0x8004-0x3fe5, 2).chr(0xe5). // restore stack in HL
            chr(0x21).substr($sna, 0x8002-0x3fe5, 2).chr(0xe5). // restore stack in HL
            chr(0x21).substr($sna, 0x8000-0x3fe5, 2).chr(0xe5). // restore stack in HL
            chr(0x21).substr($sna, 9, 2).                 // HL
            chr(0x31).pack('v', $sp+2).                   // SP
            chr(0xf3|ord($sna[19])<<3).                   // IFF1
            chr(0xc3).substr($sna, $sp-0x3fe5, 2);        // PC
    $bl2= block(chr(0x3e).$sna[0].pack('v', 0x47ed).      // I
                chr(0xde).chr(0xc0).chr(0x37).chr(0x0e).chr(0x8f).chr(0x39).chr(0x96).
                chr(0x01).substr($sna, 5, 2).             // BC'
                chr(0x11).substr($sna, 3, 2).             // DE'
                chr(0x21).substr($sna, 1, 2).chr(0xd9).   // HL'
                chr(0xed).chr(ord($sna[25])==1?0x56:
                              (ord($sna[25])?0x5e:0x46)). // IM
                pack('v', 0x21fd).substr($sna, 15, 2).    // IY
                chr(0x11).pack('v', 0xc000).              // LD DE, $C000
                chr(0x21).pack('v', 0x4000).              // LD HL, $4000
                chr(0x31).pack('v', 0x8008).              // LD SP, $8008
                chr(0xc3).pack('v', 0x07f4), 255);        // JP $07F4
    $sna=   substr($sna, 27, 0x4002).
            pack('vv', 0x05cd, $parche).
            substr($sna, 0x8006-0x3fe5);
    $sna=   block(substr($sna, 0, $parche-0x4000).
                  $regs.
                  substr($sna, $parche+strlen($regs)-0x4000), 255);
    $bl1= block("\0".substr(str_pad($nombre,10),0,10).pack('vvv', 39, 0,  39), 0);
    pilot( 2000 );
    outbits( 4 << $mhigh );
    for( $i= 0; $i<19; $i++ )
      $bytes.= $st[ord($bl1[$i])];
    pilot( 2000 );
    outbits( 4 << $mhigh );
    for( $i= 0; $i<41; $i++ )
      $bytes.= $st[ord($bl2[$i])];
    pilot( 2000 );
    outbits( 4 << $mhigh );
    for( $i= 0; $i<0xc002; $i++ )
      $bytes.= $st[ord($sna[$i])];
  }
  else{
    $r= (($r&127)-7)&127 | $r&128;
    strlen($sna)==131103 || die ("\n  Invalid length for SNA file: Must be 49179 or 131103\n");
    $page[5]= substr($sna, 27, 0x4000);
    $rutina=  chr(0xd9).                         // BFE6    EXX
              chr(0x1c).                         // BFF7    INC   E
              chr(0xcb).chr(0x5b).               // BFE8    BIT   3, E
              chr(0xc2).pack('v', $parche).      // BFEA    JP    NZ, PARCHE
              chr(0xed).chr(0x59).               // BFED    OUT   (C), E
              chr(0xd9).                         // BFEF    EXX
              chr(0x3b).                         // BFF0    DEC   SP
              chr(0x3b).                         // BFF1    DEC   SP
              chr(0x16).chr(0x40).               // BFF2    LD    D, $40
              chr(0xdd).chr(0x26).chr(0xc0).     // BFF4    LD    IXH, $C0
              chr(0xc3).pack('v', 0x05c8).       // BFF7    JP    $05c8
              pack('vv', 0, 0);                  // BFFA
    $rutina.= pack('v', 0xbffe-strlen($rutina));
    $antp2= substr($sna, 0x801b-strlen($rutina), strlen($rutina));
    $page[2]= substr($sna, 0x401b, 0x4000-strlen($rutina)).$rutina;
    $last= ord($sna[0xc01d])&7;
    $page[$last]= substr($sna, 21, 2).
                  substr($sna, 0x801d, 0x3ffe);
    for($i= 0; $i<8; $i++)
      if(($last!=$i)&&($i!=2)&&($i!=5))
        $page[$i]= substr($sna, 0xc01f+$next++*0x4000, 0x4000);
    $regs=  chr(0x3e).$sna[0xc01d].chr(0xed).chr(0x79).  // last 7FFD
            chr(0x01).substr($sna, 5, 2).                // BC'
            chr(0x1e).$sna[3].chr(0xd9).                 // E'
            chr(0x21).substr($sna, 7, 2).chr(0xe5).pack('v', 0x8f1). // AF'
            chr(0x01).pack('v', strlen($antp2)).         // LD   BC, len(antp2)
            chr(0x11).pack('v', 0xc000-strlen($antp2)).  // LD   DE, $c000-len(antp2)
            chr(0x21).pack('v', $parche+62).             // LD   HL, point
            chr(0xed).chr(0xb0).                         // LDIR
            chr(0x3e).ord($sna[26]).chr(0xd3).chr(0xfe). // Border
            chr(0x01).substr($sna, 13, 2).               // BC
            chr(0x11).substr($sna, 11, 2).               // DE
            pack('v', 0x21dd).substr($sna, 17, 2).       // IX
            chr(0x3e).chr($r).pack('v', 0x4fed).         // R
            chr(0xf1).                                   // AF
            chr(0x21).substr($sna, 0x801b, 2).chr(0x22).pack('v', 0xc000).// last stack value
            chr(0x21).substr($sna, 9, 2).                // HL
            chr(0x31).substr($sna, 23, 2).               // SP
            chr(0xf3|ord($sna[19])<<3).                  // IFF1
            chr(0xc3).substr($sna, 0xc01b, 2).           // PC
            $antp2;
    $bl2= block(chr(0x11).chr(0x10).$sna[4].             // D' E=$10
                chr(0x0e).chr(0xfd).                     // LD    C, $FD
                chr(0xc0).chr(0x38).chr(0x0e).chr(0x8f).chr(0x39).chr(0x96).
                chr(0x06).chr(0x7f).                     // LD    B, $7F
                chr(0x21).substr($sna, 1, 2).            // HL'
                chr(0xd9).                               // EXX
                chr(0x3e).$sna[0].pack('v', 0x47ed).     // I
                chr(0xed).chr(ord($sna[25])==1?0x56:
                             (ord($sna[25])?0x5e:0x46)). // IM
                pack('v', 0x21fd).substr($sna, 15, 2).   // IY
                chr(0x11).pack('v', 0x4000+strlen($rutina)).//LD  DE, $401b
                chr(0x21).pack('v', 0xc000-strlen($rutina)).//LD  HL, $BFE5
                chr(0x31).pack('v', 0xc002).             // LD    SP, $C002
                chr(0xc3).pack('v', 0x07f4), 255);       // JP    $07F4
    if($parche<0x8000)
      $page[5]= substr($page[5], 0, $parche-0x4000).
                $regs.
                substr($page[5], $parche+strlen($regs)-0x4000);
    else
      $page[2]= substr($page[2], 0, $parche-0x8000).
                $regs.
                substr($page[2], $parche+strlen($regs)-0x8000);
    $bl1= block("\0".substr(str_pad($nombre,10),0,10).pack('vvv', 39, 0,  39), 0);
    pilot( 2000 );
    outbits( 4 << $mhigh );
    for( $i= 0; $i<19; $i++ )
      $bytes.= $st[ord($bl1[$i])];
    pilot( 2000 );
    outbits( 4 << $mhigh );
    for( $i= 0; $i<41; $i++ )
      $bytes.= $st[ord($bl2[$i])];
    pilot( 2000 );
    outbits( 4 << $mhigh );
    $bl3= block($rutina.$page[0], 255);
    for( $i= 0; $i<0x4002+strlen($rutina); $i++ )
      $bytes.= $st[ord($bl3[$i])];
    for($i= 1; $i<8; $i++){
      $page[$i]= block($page[$i], 0);
      for($j= 1; $j<0x4002; $j++)
        $bytes.= $st[ord($page[$i][$j])];
    }
  }
}
pilot( 300 );
$longi= strlen($bytes);
$noprint || print("Done\n");
$chan= 1;
$output=  'RIFF'.pack('L', $longi+36).'WAVEfmt '.pack('L', 16).pack('v', 1).pack('v', $chan).
          pack('L', $srate[$mhigh][$mlow]).pack('L', $srate[$mhigh][$mlow]*$chan).
          pack('v', $chan).pack('v', 8).'data'.pack('L', $longi).$bytes;
$noprint || file_put_contents($nombre.'.wav', $output);
Imagen

Z80user
Manic Miner
Mensajes: 215
Registrado: Vie Jun 08, 2007 9:42 am
Ubicación: En un lugar de la mancha
Contactar:

Re: Ajuste de AZIMUT by Z80user

Mensaje por Z80user » Mar Mar 06, 2012 12:44 am

Con un emulador que grabase un TZX, o un fichero de audio, se haria en un plis plas
En un WAV he estado haciendo los calculos en una hoja de calcuo y para una tarjeta que emitiese audio a 48KHz, en un 128K, hay menos de un 24% de posibilidades de NO generar errores. :shock:

Generaria por cada 256 bytes (20480 muestras) hasta 1500 muestras erroneas, por lo que seria una rutina que ya de por si genera errores- :mrgreen: Apartir de 88.2 KHz ya no genera errores en 64 Khz aun puede generar errores :roll: .
La rutina interpretaria estos errores, como errores de sincronismo en 1 muestra, soporta 2 muestras erroneas, a la 3º muestra dessincronizada, adios ... error de carga. Afortunadamente no genera ninguno de 2 muestras, pero a 32KHz parece que si generaria alguno.

En cuanto al PHP, lo puedo leer, pero no puedo hacer mucho mas alla. No se mucho acerca del php, supongo que como compilar con la linea de comandos: "c:\php fichero.php *parametros"

antoniovillena escribió:Es que normalmente las ultracargas se generan con PC y se reproducen con un spectrum
Yo la pense en su dia para usarse en un Spectrum, para cargar y salvar partidas (aunque como has podido ver, son rutinas bien grandes se llevan unos 400 bytes entre ambas practicamente, y sin rutina de sincronizacion)

Para esta semana mirare los metodos de sincronizacion de las rutinas de carga. y asi miro como sincronizarla.
EL ruido que genera, creo que es como la rutina que te pase. RUIDO basicamente :? nada que se le parezca a una carga de un spectrum normal y corriente.
Si vas a tirar Hardware, primero pregunta si alguien lo puede recuperar.
No abandones un ordenador en un vertedero, donalo a alguien.

Responder

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 22 invitados