mercoledì 22 gennaio 2014

Sinclair QL Microdrive

Qualche veloce premessa sul funzionamento dei microdrive.

  • Come è stata pensata e costruita la cassetta microdrive si è detto qui (link)
  • Come viene selezionata l'unità MDV1 o MDV2 si è detto qui (link)
  • Come il microdrive scrive e legge i dati lo si può leggere sul QL Service Manual, dal quale riporto qualche stralcio : "...i dati sono salvati su due tracce usando la tipica configurazione di una testina stereo per le audiocassette, e sono scritti in bytes, un byte su una traccia e il byte successivo sulla altra traccia. I dati sono letti nel medesimo modo..." ; Ciò vuol significare che il primo byte è scritto/letto sulla traccia 1, il secondo byte è scritto/letto sulla traccia 2, il terzo byte nuovamente sulla traccia 1 ed il quarto byte nuovamente sulla traccia 2 . E così via. Il segnale che veicola i dati da scrivere/leggere della traccia 1 e quello della traccia 2 sono generatati dalla ULA ZX8302 , e giungono alle unità microdrive , così come il segnale di  che determina la modalità di scrittura o lettura. Il segnale di lettura/scrittura, opera nel seguente modo: se il livello logico è alto allora il microdrive è in modalità di lettura, viceversa se il livello logico è basso il microdrive esegue le operazioni di scrittura. Un altro segnale di controllo comanda la attivazione o meno della testina di cancellazione del nastro , la quale agisce su entrambe le tracce contemporaneamente.
  • Codifica del segnale dati di scrittura/lettura ; è usata la codifica a modulazione di frequenza  secondo lo schema bifase : frequenza pari a n KHz per il valore "0" , e frequenza di 2*n KHz per il valore "1" (per i microdrive del QL siamo a 50 KHz per lo zero , e 100 KHz per l' uno)



Il funzionamento della unità Microdrive nel dettaglio

Per chi voglia cimentarsi nella realizzazione di un dispositivo hardware in grado di sostituire le unità microdrive e simularne il loro utilizzo, è necessario capirne il funzionamento fin nei minimi particolari , incominciando dalla parte più complessa : il processo di formattazione delle cartucce (poichè coinvolge simultaneamente sia le operazioni di scrittura che quelle di lettura, nonché la formattazione dei dati).

A tal fine sarebbe necessario interfacciare una scheda a microcontrollore alla ULA ZX8302 , per raccogliere i segnali dei dati della traccia 1 , traccia 2 ,  il segnale di controllo lettura/scrittura ed il segnale di cancellazione nastro.

Secondo il sistema di codifica dei dati sopra riportato, sia per la traccia 1 che per la traccia 2 , il valore di "zero" utilizza una frequenza di 50 KHz , raddoppiando a 100 KHz per il valore "uno" ; il fatto che non è presente un altro segnale a frequenza costante a cui fare riferimento per "agganciare" il segnale delle due tracce, unitamente al fatto che la lettura deve essere eseguita sia sul fronte di salita che sul fronte di discesa dei segnali di entrambe le tracce, è facile intuire che il sistema interfaccia debba per forza di cose avere una più che discreta potenza e velocità di calcolo, già solo per acquisire i segnali, senza processarli o memorizzarli.

Siccome volevo avventurarmi in questa impresa, avevo a disposizione due soluzioni : utilizzare un sistema di medio-alto livello (una MCU a 160 MHz capace processare di 40 milioni di istruzioni per secondo) , oppure un sistema di basso livello (MCU a 12 MHZ , con una media di 12 milioni di istruzioni per secondo). Manco a dirlo ho optato per la seconda, non fosse altro per pigrizia e perché avevo già tutto pronto. Questa scelta però ha comportato a dover rinunciare ad acquisire la seconda traccia, così leggendo solo la prima si ha a disposizione solo l'informazione dei bytes "dispari": metà dati sufficienti comunque  per ricostruire il funzionamento dei microdrive. Per rendere più veloce ed efficiente l'esecuzione del programma , la MCU è stata programmata in assembler .



Il programma di acquisizione della traccia 1 , non utilizza timer particolari o sistemi di polling del segnale, ma semplicemente "conta" quanti passi di programma sono stati eseguiti ad ogni transizione del segnale di traccia (sia sul fronte di salita che su quello di discesa) per le sole operazioni di scrittura (quindi con il segnale scrittura/lettura allo stato basso). I passi contati sono memorizzati nella RAM interna della MCU da 4KBytes ; a fine lettura (o meglio a memoria esaurita), i dati raccolti sono presi dalla RAM ed inviati tramite una porta seriale ad un computer.

Codice:

$asm
LDI R27 , $01               'fai puntare a X l'indirizzo sram $0100  (MBS)
LDI R26 , $00               'fai puntare a X l'indirizzo sram $0100  (LBS)                                            
LDI R16,$00                 'imposta il contatore passi =0

Main:
SBIC pina,2                   'se il segnale lettura/scrittura...
JMP Main                       '...è settato per la lettura, allora torna a testarlo
INCR R16                      'incrementa di una unità il contatore passi
CPI R27,$10                   'se si è esaurita la memoria RAM...
BREQ Finito                   'allora vai a finito
JMP Main                        'torna all'inizio del programma Main


Gestisci_int:                     'interruzione sul fronte di salita o discesa della traccia
ST X+,R16                       'salva il contatore passi in RAM
LDI R16,$00                    'azzera il contatore passi
RETI                                 'fine interruzione e ritorna al programma main
$end Asm

Con programma di acquisizione così concepito, si ottengono due tipi di dati : un dato ad 1 byte che riporta il numero di passi programma quando la traccia microdrive assume il valore uguale a zero (è 1 byte solo perché nella modulazione di frequenza bifase si ha 1 sola cresta o 1 sola gola) , oppure un dato a 2 bytes che riporta il numero di passi programma per la traccia con valore uguale a uno (sono di 2 byte perché in questo caso si ha 1 cresta seguita da 1 gola, o viceversa, e quindi viene letto il numero di passi programma sia della cresta che della gola).

Dati grezzi dalla traccia 1 (valori in esadecimale):

0000000000000000000000001A07080807121211121112111212111211121112111212111211
1211121211121112111211121211121112111208070808070808070808080708080708080708080807080807080807080808071211080811121108081108
08070808081108071208071208070808070808081112070812111211121108081112121112111207081211120807120708121108081112080712110808
1112111212070811080811064270040708121112111212111211121112111212111211121112121112111211121112
12111211121112111212111207080808070808070808070808070808080712080708080708080708080708121108080708121112111211121211121112
1112111212111211121112121112111207080808070808070808070808080708110808110808110808110808110808110808110808110808110808110807
12080712080712080712080712080712070812070812070812070812070812070812070811080811080811080811080811080811080811080811080811
0807120807120807120807120807120807120807120708120708120708120708120708120708120708110808110808110808110808110808110808110808
11080811080712080712080712080712080712080712070812070812070812070812070812070812070811080811080811080811080811080811080811
0808110808110807120807120807120807120807120807120807120708120708120708120708120708120708120708110808110808110808110808110808
11080811080811080811080712080712080712080712080712080712080712070812070812070812070812070812070811080811080811080811080811
0808110808110808110808110808110807120807120807120807120807120807120708120708120708120708120708120708120708110808110808110808
11080811080811080811080811080811080712080712080712080712080712080712080712070812070812070812070812070812070812070811080811
08081108081108081108081108081108081108081108071208071208071208071208071208071207081207081207
0812070812070812070812070811080811080811080811080811080811080811080811080811080712080712080712080712080712080712080712070812
07081207081207081207081207081108081108081108081108081108081108081108081108081108081108071208071208071208071208071208071207
0812070812070812070812070812070812070811080811080811080811080811080811080811080811080811080712080712080712080712080712080712
08071207081207081207081207081207081207081207081108081108081108081108081108081108081108081108081108071208071208071208071208
0712080712080712070812070812070812070812070812070811080811080811080811080811080811080811080811080811080811080712080712080712
08071208071208071207081207081207081207081207081207081207081108081108081108081108081108081108081108081108081108071208071208
0712080712080712080712080712070812070812070812070812070812070812070811080811080811080811080811080811080811080811080811080712
08071208071208071208071208071208071207081207081207081207081207081207081108081108081108081108081108081108081108081108081108
0712080712080712080712080712080712080712070812070812070812070812070812070812070811080811080811080811080811080811080811080811
08081108071208071208071208071208071208071208071207081207081207081207081207081207081108081108
08110808110808110808110808110808110808110808110807120807120807120807120807120807120708120708120708120708120708120708120708
1108081108081108081108081108081108081108081108081108071208071208071208071208071208071208071207081207081207081207081207081207
08120708110808110808110808110808110808110808110808110808110807120807120807120807120807120807120708120708120708120708120708
1207081207081108081108081108081108081108081108081108081108081108071208071208071208071208071208071208071207081207081207081207
08120708120708120708110808110808110808110808110808110808110808110808110807120807120807120807120807120807120807120708120708
1207081207081207081207081108081108081108081108081108081108081108081108081108081108071208071208071208071208071208071207081207
08120708120708120708120708120708110808110808110808110808110808110808110808110808110807120807120807120807120807120807120807
1207081207081207081207081207081207081108081108081108081108081108081108081108081108081108081108071208071208071208071208071208
07120708120708120708120708120708120708120708110808110808110808110808110808110808110808110808110807120807120807120807120807
1208071208071207081207081207081207081207081207081207081108081108081108081108081108081108081108
08110808110807120807120807120807120807120807120807120708120708120708120708120708120708110808110808110808110808110808110808
1108081108081108081108071208071208071208071208071208071207081207081207081207081207081207081207081108081108081108081108081108
08110808110808110808110807120807120807120807120807120807120807120708120708120708120708120708120708110808110808110808110808
1108081108081108081108081108081108071208071208071208071208071208071207081207081207081207081207081207081207081108081108081108
08110808110808110808110808110808110807120807120807120807120807120807120807120708120708120708120708120708120708120708110808
1108081108081108081108081108081108081108081108071208071208071208071208071208071208071207081207081207081207081207081207081108
08110808110808110808110808110808110808110808110808110807120807120807120807120807120807120708120708120708120708120708120708
1207081108081108081108081108081108081108081108081108081108071208071208071208071208071208071208071207081207081207081207081207
08120708110808110808110808110808110808110808110808110808110808110807120807120807120807120807120807120708120708120708120708
12070812070812070811080811080811080811080811080811080811080811080811080712080712080712080712
0807120807120807120708120708120708120708120708120708120708110808110808110808110808110808110808110808110808110807120807120807
12080712080712080712080712070812070812070812070812070812070811080811080811080811080811080811080811080811080811080811080712
0807120807120807120807120807120708120708120708120708120708120708120708110808110808110808110808110808110808110808110808110807
12080712080712080712080712080712080712070812070812070812070812070812070811080811080811080811080811080811080811080811080811
0808110807120807120807120807120807120807120708120708120708120708120708120708120708110808110808110808110808110808110808110808
11080811080712080712080712080712080712080712080712070812070812070812070812070812070812070811080811080811080811080811080811
0808110808110808110807120807120807120807120807120807120807120708120708120708120708120708120708110808110808110808110808110808
11080811080811080811080712080712080712080712080712080712080712070812070812070812070812070812070812070811080811080811080811
0808110808110808110808110808110807120807120807120807120807120807120807120708120708120708120708120708120708110808110808110808
11080811080811080811080811080811080811080712080712080712080712080712080712070812070812070812070812070812070812070811080811
08081108081108081108081108081108081108081108071208071208071208071208071208071208071207081207
0812070812070812070812070812070811080811080811080811080811080811080811080811080811080712080712080712080712080712080712070812
07081207081207081207081207081207081108081108081108081108081108081108081108081108081108070808080708080708121112111208071208
0712070812070812070812070812070812070811080811080811080811080811080811080811080811080811080811080712080712080712080712080712
08071208071207081207081207081207081207081207081108081108081108081108081108081108081108081108081108081108071208071208071208
0712080712080712070812070812070812070812070812070812070811080811080811080811080811080811080811080811080811080712080712080712
08071208071208071208071207081207081207081207081207081207081108081108081108081108081108081108081108081108081108081108071208
0712080712080712080712080712070812070812070812070812070812070812070811080811080811080811080811080811080811080811080811080811
08071208071208071208071208071208071207081207081207081207081207081207081108081108081108081108081108081108081108081108081108
0811080712080712080712080712080712080712080712070812070812070812070812070812070811080811080811080811080811080811080811080811
08081108081108071208071208071208071208070000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000046494E4520300D0A

Quando viene rilevato il segnale a 100 KHz (valore=1) sono necessari o 7 oppure 8 passi programma, mentre per il segnale a 50 KHz (valore=0) sono necessari 11 oppure 12 passi programma.

Siccome sono disponibili delle immagini (dump) di cartucce microdrive del QL, se questi dump vengono letti da un programma di editor esadecimale, si ottiene qualcosa simile a questo:


Con tanta pazienza e con l'aiuto del disassemblato del codice del sistema operativo del QL (rom Minerva 1.81) , si può intuire quale sia la formattazione dei dati sul nastro microdrive ; ho riportato alcune note a matita e con l'aiuto di colori diversi , per meglio visualizzare il layout.

Ora, con il dissasemblato della rom e con lo schema sopra riportato, è possibile trarre qualche informazione dai dati grezzi della traccia 1 appena acquisita :

0000000000000000000000001A07080807 =GARBAGE DATA

12 11 12 11 12 11 12 12
 0  0  0  0  0  0  0  0   =$00
12 11 12 11 12 11 12 12
 0  0  0  0  0  0  0  0   =$00
12 11 12 11 12 11 12 12  
 0  0  0  0  0  0  0  0   =$00
12 11 12 11 12 11 12 12  
 0  0  0  0  0  0  0  0   =$00
12 11 12 11 12 11 12 12  
 0  0  0  0  0  0  0  0   =$00

0807 0808 0708 0807 0808 0807 0808 0708
  1   1     1    1    1    1    1    1     =$FF
0807 0808 0807 0808 0708 0807 0808 0807 
  1   1     1    1    1    1    1    1     =$FF

12 11 0808 11 12 11 0808 11 
 0  0   1   0  0  0   1  0  =$44 =D

0808 0708 0808 11 0807 12 0807 12
  1    1    1   0  1    0   1   0  =$57 =W

0807 0808 0708 0808 11 12 0708 12
  1    1    1    1   0  0   1  0   =$4F =O

11 12 11 12 11 0808 11 12
 0  0  0  0  0   1   0  0   =$20 =spazio
 
12 11 12 11 12 0708 12 11
 0  0  0  0  0   1   0  0   =$20 =spazio

12 0807 12 0708 12 11 0808 11
 0   1   0   1   0  0   1   0  =$4A (1 casuale)

12 0807 12 11 0808 11 12 11 
 0   1   0  0   1  0   0  0  =$12 (1 CRC)

12120708110808110642700407081211 =GARBAGE DATA

12 11 12 12 11 12 11 12 
 0  0  0  0  0  0  0  0   =$00
11 12 11 12 12 11 12 11 
 0  0  0  0  0  0  0  0   =$00
12 11 12 12 11 12 11 12 
 0  0  0  0  0  0  0  0   =$00
11 12 11 12 12 11 12 11 
 0  0  0  0  0  0  0  0   =$00
12 11 12 11 12 12 11 12
 0  0  0  0  0  0  0  0   =$00

0708 0808 0708 0807 0808 0708 0807 0808
  1    1    1    1    1    1    1    1   =$FF

0807 12 0807 0808 0708 0807 0808 0708
  1   0   1    1    1    1    1   1   =$FD

12 11 0808 0708 12 11 12 11
 0  0   1   1    0  0  0  0   =$0C

12 11 12 12 11 12 11 12
 0  0  0  0  0  0  0  0   =$00
11 12 11 12 12 11 12 11
 0  0  0  0  0  0  0  0   =$00
12 11 12 12 11 12 11 12
 0  0  0  0  0  0  0  0   =$00
0708 0808 0708 0807 0808 0708 0808 0708
  1    1    1    1    1    1    1    1   =$FF

110808110808110808110808
 0  1  0  1  0  1  0  1   =$AA
110808110808110808110808  
 0  1  0  1  0  1  0  1   =$AA
110808110807120807120807  
 0  1  0  1  0  1  0  1   =$AA
120807120807120807120708 
 0  1  0  1  0  1  0  1   =$AA
120708120708120708120708 
 0  1  0  1  0  1  0  1   =$AA
120708120708110808110808 
 0  1  0  1  0  1  0  1   =$AA
110808110808110808110808  
 0  1  0  1  0  1  0  1   =$AA
110808110808110807120807 
 0  1  0  1  0  1  0  1   =$AA

<in totale si hanno 256 bytes di valore $AA>
<ultimi dati di dump memoria MCU>
1208071208071208071208070000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000 46 49 4E 45 20 30 0D 0A
<messaggio di fine dump dalla MCU>       F I  N  E  _  0  CR LF

E' sempre necessario ricordare che si ha acquisito solo la traccia 1 , e quindi abbiamo solo la metà delle informazioni (solo i bytes dispari) , perché è mancante la traccia 2. Tuttavia già così possiamo trovare il "sector header" composto dalla sequenza di $00 e $FF , il nome che è stato dato alla cartuccia in fase di formattazione, in questo caso avendo dato il nome "DRWHO" ed avendo solo i byte della 1 traccia, troviamo le lettere D W O , con le mancanti lettere R e H che sono state scritte dalla traccia 2.

Sperando in una maggiore chiarezza, allego questa figura che riporta le informazioni ottenute dalla traccia 1 , figura eseguita sulla falsa riga della figura del layout di formattazione



Altra cosa che si può vedere, è la presenza di valori uguali a $AA dopo l' header dei blocco dati ; di fatto, tutto il blocco dati (sono 512 bytes) è riempito con i valori $AA e $55 ($55 è mancante perché scritto dalla traccia 2) nella fase iniziale di formattazione del blocco dati , in accordo con il dissasemblato rom

* Preset format block
 wdcs st_free 0 1
        move.l  #[wd]<<16![cs],(a0)+ empty / block 0 / checksum
        addq.l  #bldata-blpre-2,a0 preamble mainly zeroes
        subq.w  #1,(a0)+        finishing with 2 bytes of ones for sync
        move.w  #(blend-bldata)/2-1,d1 fill data and extra bytes
 wdcs $AA $55 bdl/2

La cosa più interessante però è rappresentata dai dati spazzatura (garbage data) , dati che sembrano essere sputati fuori dalla ULA ZX8302 sulla traccia 1 , quando ancora il segnale scrittura/lettura è settato in scrittura.  Mia opinione che questi dati spazzatura presenti all'inizio dell' header di settore e tra la fine dell' header di settore e l'inizio dell' header di blocco dati , siano in realtà dati in qualche modo associati al "GAP" , che è quella porzione di nastro inutilizzata tra un settore ed il successivo; opinione suffragata dal codice della rom:

write_lp
        move.l  a5,a1           08    reset pointer
        moveq   #shend-shbeg-1,d1 08  write sector header
        delay   (2840-85)       gap allows for jsr and final wait
        jsr     md_wblok(pc)
        move.w  #blend-blbeg-1,d1 16 write specially long block
        delay   (2840-80)       gap allows for jsr and final wait
        jsr     md_wblok(pc)
        subq.b  #1,sno-map(a1)  24+16 next sector number
        bcc.s   write_lp        12/18 last sector is 0
        move.b  #pc.read,(a3)   erase off


moveq   #shend-shbeg-1,d1 sposta in memoria l'header di settore , ma non lo scrive ancora fisicamente sul nastro ; poi c'è un intervallo delay   (2840-85)  per il gap , e solo dopo si chiama la subroutine per la scrittura su microdrive jsr     md_wblok(pc) . Idem per le successive istruzioni della scrittura del blocco dati, con la differenza che durante il gap wait il segnale scrittura/lettura si alza per poi abbassarsi nuovamente quando è chiamata la subroutine md_Wblock del blocco dati.

La limitata memoria della MCU di acquisizione , non permette ulteriori analisi sul processo (poi si sa,  l'appetito vien mangiando...) , tuttavia da quel che si vede , sembra fattibile un sistema hardware di emulazione della unità miscrodrive , che interagisca con i segnali di controllo microdrive della ULA ZX8302 , acquisendo solo i segnali anche senza nessuna elaborazione , come quella eseguita manualmente in queste prove , e memorizzando gli stati dei segnali in un buffer di memoria circolare di adeguata grandezza (qualche centinaio di KBytes , valore da calcolarsi con calma) ; dico un buffer di memoria circolare perché è ciò che più si avvicina al tipo di nastro magnetico continuo utilizzato nelle cartucce microdrive. 
Visto in questa ottica (cioè senza elaborazione dei dati, ma operando solo sul grezzo) , l'eventuale emulatore così pensato potrebbe lavorare indipendentemente sia su un QL che su uno ZX Spectum Microdrive. 


2 commenti:

nibbler71 ha detto...
Questo commento è stato eliminato da un amministratore del blog.
Mirko ha detto...

nibbler71 , ti ho contattato alla email che mio hai inviato :-)