Spiacente, questo articolo non è disponibile in inglese. United-Kingdom-flag-icon-26
Please ask, if you wish an english translation added

 

 

LX389

 

Interconnettere lo Z80 ed il PC

 

Questo è il tema: scambiare dati tra i due mondi. Nel mio caso l'esigenza è diventata una necessità nel momento in cui, facendo ripartire il mio Z80 dopo anni, mi sono accorto che i floppy da 5" erano ormai irrimediabilmente rovinati.

La comunicazione seriale è la prima risposta che viene in mente per questa esigenza. Peccato che, al momento, interfacce seriali per lo Z80NE non esistevano (ora si!).

Di conseguenza, la soluzione al problema più immediato e con la necessità di utilizzare l'hardware a disposizione, mi ha indirizzato quasi obbligatoriamente verso l'utilizzo di una comunicazione basata da un lato sull'interfaccia parallela/stampante LX389 e la corrispondente porta parallela del PC dall'altro lato.

Non ci sono altre porte disponibili, la porta stampante sulla video grafica sebbene gestita da uno Z80 PIO (quindi perfettamente bidirezionale), purtroppo è abbinata ad un line driver 7407 che ne blocca la funzionalità in input.

 

Hardware

 

La LX389 è una schedina mezza altezza, molto simpatica, progettata da Nuova Elettronica con l'intento di permettere il collegamento di una stampante allo Z80, una parallela Centronics per la precisione.

Ma la buona NE ha comunque predisposto la scheda affinche su di essa, in alternativa alla porta stampante, fossero disponibili due porte parallele entrambe utilizzabili come input e/o come output. Il tutto utilizzando quattro buffer-latch e altri quattro logiche per l'indirizzamento della scheda sul bus.

L'unica "pecca" per così dire di questa progettazione è che le due porte hanno ognuna i pin di input e quelli di output separati, mentre per il collegamento con il PC occorre una porta realmente bidirezionale, una porta cioè dove i pin possano svolgere a comando sia la funzione di input che quella di output.

Prima di procedere con la parte Z80 vediamo cosa ci aspetta dal lato PC. Premesso che qui i requisiti importanti sono due:

  • La disponibilità della porta parallela, requisito non scontato visto che i PC più moderni non la montano più di default. Occorre quindi un PC dove se anche la porta non disponibile nativamente sia possibile aggiungerne una.
  • La porta in questione deve essere bidirezionale. Esistono diverse logiche di funzionamento: SPP, Bidir, EPP, ECP. Tutte sono ok tranne la SPP che NON è bidirezionale. Bisogna anche verificare che da setup del BIOS la porta sia effettivamente impostata come EPP/ECP.

La porta parallela del PC

La porta in questione è sempre abbinata ad un connettore a vaschetta da 25 poli con questa piedinatura

Parallel port pinout

e controllata da tre registri, accessibili sequenzialmente da un indirizzo base

Port access registers

Riassumendo la funzionalità dei pin in una tabella:

Pin
Reg Bit
Description
Direction
1 /C0 Strobe Output
2 D0 Data Bit 0 Output
3 D1 Data Bit 1 Output
4 D2 Data Bit 2 Output
5 D3 Data Bit 3 Output
6 D4 Data Bit 4 Output
7 D5 Data Bit 5 Output
8 D6 Data Bit 6 Output
9 D7 Data Bit 7 Output
10 S6 Acknowledge Input
11 /S7 Busy Input
12 S5 Paper End Input
13 S4 Select In Input
   
Pin
Reg Bit
Description
Direction
14 /C1 Auto Feed Output
15 S3 Error Input
16 C2 Initialise Output
17 /C3 Select Output
18 - Ground -
19 - Ground -
20 - Ground -
21 - Ground -
22 - Ground -
23 - Ground -
24 - Ground -
25 - Ground -

 

Il controllo dei vari pin, in Linux, è possibile in tre diverse modalità, ognuna con dei pro e contro. Per una introduzione al problema ma sotto Windows potete leggere qui.

  1. Raw i/o
    In questo caso si accede direttamente all'hardware dei tre registri coinvolti. E' il metodo più semplice e veloce, ma dovendo accedere a così basso livello è necessario avere in privilegi del superutente "root". E' anche possibile impostare l'eseguibile che utilizza la parallela come setuid(0) per semplificarne l'utilizzo.
    Ora, i puristi della security, obietteranno immediatamente che questo crea dei problemi (di sicurezza appunto) e che quindi è altamente sconsigliabile. Cosa del tutto vera.
    Ma, nel nostro caso, stiamo parlando di una applicazione destinata a girare su un sistema non pubblico, da "laboratorio" e quindi possiamo tranquillamente ignorare la cosa nelle giuste condizioni.
  2. Accesso alla device /dev/lpx
    Forse il più corretto da un punto di vista formale, ma lento e in ultima analisi abbastanza macchinoso.
  3. Via ppdev driver
    Probabilmente il migliore dei tre. Non veloce come l'accesso raw (ma sempre a velocità luce rispetto ad uno Z80) però lavora in user space e quindi non crea problemi di sicurezza. La programmazione avviene tramite una serie di chiamate ioctl(), vedi qui e qui per approfondire.

Come vedremo nella parte software, attualmente ho utilizzato il metodo raw i/o ma, con un pò di calma, le future versioni passeranno all'utilizzo di ppdev.

La parallela dello Z80 - funzionamento

Ok, preparatevi a scaldare il saldatore, ma prima vediamo cosa vogliamo realizzare.

Come anticipato la LX389 mette a disposizione due porte parallele dove però ognuna di esse ha i pin di input e output separati. L'idea è collegare insieme, su una delle due porte, gli 8 pin di input e i relativi 8 di ouput. Quindi dai 16 pin iniziali ne otterremo 8 che possono switchare tra le due modalità ingresso/uscita. Chiameremo questa: data port.

La porta rimanente che chiameremo control port avrà assegnate due importanti funzionalità: un pin in uscita andrà a controllare il chip enable della data port (IC5) quindi funzionando come selettore della modalità i/o della porta stessa.

La seconda funzionalità sarà quella di controllore dei segnali di handshake con il PC collaborando con la porta dati al trasferimento delle informazioni. A questo scopo utilizzeremo due pin in output e due in input.

La scelta di avere due pin di handshake per lato è dovuta al fatto che la differenza di velocità tra i due sistemi è veramente notevole, e, più e moderno il PC utilizzato, più questo gap prestazionale si allarga. Quindi i sistemi per ogni byte trasferito asseriscono prima un segnale di READY, ovvero dato disponibile sulla porta, e poi attendono dal corrispondente una segnale di AKNOWLEDGE prima di intraprendere una nuova operazione. Questo rallenta un pò le performance ma elimina la maggior parte degli errori (e nel protocollo logico è inserito anche un CRC per ulteriore sicurezza).

E passiamo allo schema elettrico, perfettamente riprodotto dall'amico Pino Giaquinto (*)

 Schema Parallela Bidirezionale

In questo modo è facile rilevare le differenze rispetto allo schema originale sulla rivista numero 73 di Nuova Elettronica.

In sostanza IC5 e IC6, che sono la porta 1 della LX389, vengono accoppiati bit a bit per ottenere la data port, il pin 1 di IC5 è scollegato dalla massa e collegato al pin 2 di IC7 a controllare la direzione della data port. IC7 e IC8 sono la porta 2 della LX389.

IC6 come ingresso è sempre attivo sul bus dati della parallela mentre IC5, che è in output si trova normalmente in alta impedenza e forza i dati sul bus parallelo solo quando il pin 1 si trova a zero, pilotato a come detto da IC7, pin 2 (D0).

Ora bisogna accoppiare le due porte PC <> Z80 in modo che possano scambiarsi dati. Il cablaggio relativo è il seguente:

 Cablaggio

 La parallela dello Z80 - realizzazione

La realizzazione dell'interfaccia non è affatto complessa. La maggior parte del lavoro consiste nel cablaggio ovvero nel prelavare i segnali dai connettori CONNETTORE 1 e CONNETTORE 2 della LX389 e questo (a parte realizzare correttamente i collegamenti da punto a punto) lascia molto spazio alla fantasia e alla capacità di ognuno.

L'unica modifica che risulta effettivamente sulla LX389 è tagliare la pista di massa al pin 1 di IC5 e collegarlo al pin 2 di IC7.

Per capire meglio, torna ancora un volta utile l'aiuto dell'amico Pino. La mia realizzazione e la sua sono completamente differenti, benchè funzionalmente identiche e, come al solito, quella di Pino è decisamente più ordinata.

Qualche foto, penso, vale più di mille parole. Cliccate sulla foto per vederla ingrandita.

Le foto a sinistra sono l'implementazione originale, quelle a destra la reinterpretazione di Pino Giaquinto:

IMG 20160403 160846 Lato saldature
 Modifica pin 1 di IC5 Modifica pin 1 di IC5 + trasferimento segnali alla porta stampante

 

Il motivo per cui nella foto di destra i segnali di handshake sono portati al connettore della stampante è perchè in questo caso viene utilizzato proprio quel connettore per collegarsi al PC. Nel mio caso invece la soluzione è diversa (si lo so, è un pò incasinata, ma devo precisare che è anche la realizzazione prototipo), ovvero:

connettore parallela Lato componenti
 Il prototipo L'ottimizzazione

 

Nel primo caso si è utilizzata una piccola basetta millefori con montati 3 connettori, due che vanno ad inserirsi sulla LX389 ed uno al centro (in foto non si vede) da cui parte il cavo parallelo. Le connessioni quindi sono tutte filate sulla basetta stessa.

Nel secondo caso invece, il collegamento al PC parte dalla porta stampante, i segnali di handshake sono filati dal lato saldature e l'accoppiamento dei bit dati tra IC5 e IC6 è ottenuto con un piccolo flat inserito nel CONNETTORE 1 in alto a destra.

L'ultimo accorgimento di cui bisogna tenere conto e l'indirizzamento della LX389. La data port ha indirizzo 03H e la control port 02H.

Di conseguenza i ponticelli P1,P2 e P3 della scheda devono essere tutti chiusi.

Ponticelli
Ponticelli LX389

 

Software

 

 Naturalmente senza una adeguato software di gestione dei trasferimenti quanto sopra sarebbe del tutto inutile.

Ci sono due parti da considerare, ciò che va installato su PC e la naturale controparte sullo Z80. Della parte sullo Z80 ce ne possiamo occupare dopo aver visto il lato PC, perchè, per quanto riguarda lo Z80 è necessaria una piccola digressione sullo stato attuale delle cose.

Il PC, server per lo Z80

Quanto sviluppato fa riferimento al mondo Linux, dovuta premessa, ed è sviluppato in C. Detto questo, il porting sotto Windows è senz'altro possibile ma le routine di gestione della porta parallela sono tutte da rifare, in special modo per ambienti Vista/Windows7/Windows10 dove l'accesso diretto all'hardware non è possibile.

Nel nostro caso invece si è utilizzato la gestione della porta via raw i/o cosa che richiede, come detto precedentemente, i privilegi di root. Questa e altre problematiche sono in corso di risoluzione (vedi Todo più avanti).

Altra premessa è che il software per lo Z80 è scritto per il CP/M e quindi compatibile con il SONE (vedi Todo), niente NEDOS. La gestione del NEDOS è rimandata ad un secondo momento, principalmente perchè non sono ancora a conoscenza del meccanismo dei drivers su questo s.o., peraltro uguale al TRS-DOS (o NEWDOS nello specifico).

Tornando al punto, esistono tre utility per il trasferimento tra Z80<>PC, due dedicate al traferimento diretto send_Z80DS e receive_Z80DS che come i nomi suggeriscono, effettuano rispettivamente invio verso lo Z80 e ricezione dallo Z80 di file e/o regioni di memoria.

Il pezzo "forte" però è un server per dischi virtuali che opera, appunto, attraverso la parallela chiamato vdsk_server.

Il vdsk_server ha diverse caratteristiche di cui le principali:

  • Gestione floppy in formato .IMG/.DSK accessibili come da cpmtools tramite la definizione del formato disco.
  • Gestione floppy in formato .DMK, utilizzato anche da Roberto Bazzano per l'archiviazione del software su www.z80ne.com.
  • Gestione floppy in formato .IMD, che, come sopra, viene utilizzato da Roberto Bazzano per l'archiviazione del software.
  • Accesso trasparente in lettura/scrittura per lo Z80 alle immagini floppy.

Ho usato il termine floppy ma in realtà sarebbe più appropriato "volume" in quanto le immagini possono essere anche relative ad HD.

Utilizzo:

> sudo ./vdsk_server -h
ZDS - Z80NE Virtual Disk Server v1.8

Usage: vdsk_server [-zZ] [-f A:format] [-F B:format] [-b boot] [-L label] [-n base] image [image2]

Options:

-z              No skew for drive A:
-Z              No skew for drive B:
-c              Create image for for drive A: if not exist
-L <label>      Label drive A: if not exist (CP/M only)
-b <fname>      Up to four code files to initialize boot tracks (CP/M only)
-f <type>       Diskdefs type for drive A:
-F <type>       Diskdefs type for drive B:
-n <X>          Drive id remap base X: (CP/M only)
-h              Usage help (this)
-u              Dump sectors during transfer
-D              DMK mode for non CP/M images (NE-DOS/NEWDOS/other)
-I              IMD mode for non CP/M images (NE-DOS/NEWDOS/other)
-p <d:h:t:s:z:k>
                Disk parameters for DMK create density:heads:tracks:sectors:sec. size:skew factor
                where:
                d       0 = FM, 1 = MFM
                h       1 = SS, 2 = DS
                t       # of tracks per side
                s       # of sectors per track
                z       Sector size in bytes 128/256/512
                k       skew factor

 

Il server suporta due immagini disco. nativamente, in formati distinti se richiesto. Gli identificativi dei dischi devono essere successivi ad esempio A:, B: fino a O:, P: Al momento però le opzioni per il doppio disco si applicano solo al formato .IMG/.DSK. Per i formati .DMK e .IMD al momento si può usare un solo disco (immagine).

Inoltre la gestione dei .DSK è limitata a dischi CP/M. I formati dei dischi sono specificati in un file esterno "diskdef" esattamente come per cpmtools (vedi più avanti).

Le opzioni nel dettaglio:

-z

Non applica skew factor. I settori vengono letti sequenzialmente come fisicamente presenti sul disco.

-Z

Come sopra, ma per il second disco (solo .DSK)

-c

Richiede la creazione di una immagine. Per il formsto .DSK l'immagine viene creata nel formato specificato con -f, per le immagini .DMK e .IMD occore utilizzare l'opzione -p.

-L
etichetta <nomedisco> assegnata all'immagine creata con -c. Opzione valida solo per il formato .DSK (cp/m)
-b
Utiizzata con -b <fname1> <fname2> <fname3> <fname4>. Permette di specificare fino a 4 frammenti di codice (eseguibile) per inizializzare il bootstrap del disco che verranno caricati a partire al settore 0, traccia 0. (solo .DSK)
-f
Formato diskdef da utiizzare per l'immagine del primo disco (solo .DSK)
-F
Formato diskdef da utilizzare per l'immagine del secondo disco (solo .DSK)
-n

Base di rinumerazione dei drive. Ad esempio -n C significa che all'immagine disco verranno asseganti i drive C: per il primo e D: per il secondo (max P)

-h
Testo di help
-u
Mostra il dump (esadecimale) del settore in trasferimento
-D
Attiva la modalità per immagini in formato .DMK
-I
Attiva la modalità per immagini .IMD
-p

Parametri del disco utilizzati per la creazione di immagini in formato .DSK/.IMD con l'opzione -c. Esattamente occorre specificare una stringa nel formato d:h:t:s:z:k dove:

d       0 = FM, 1 = MFM
h       1 = SS, 2 = DS
t       # of tracks per side
s       # of sectors per track
z       Sector size in bytes 128/256/512
k       skew factor
 

Formati disponibili per le immagini .DSK/.IMG

diskdef SONE128
  seclen 128
  tracks 40
  sectrk 17
  blocksize 1024
  maxdir 32
  skew 4
  boottrk 3
  os 2.2
end

diskdef ZDSdos
  seclen 256
  tracks 40
  sectrk 10
  blocksize 1024
  maxdir 32
  skew 0
  boottrk 0
  os 2.2
end

diskdef ZDS
  seclen 512
  tracks 160
  sectrk 11
  blocksize 2048
  maxdir 256
  skew 4
  boottrk 2
  os 3
end

diskdef ZDSHD8
  seclen 512
  tracks 64
  sectrk 256
  blocksize 2048
  maxdir 1024
  skew 0
  boottrk 1
  os 3
end

 

I vari formati sono disponibili nel file vdsk_server/diskdefs.

Le routine per lo Z80

Ovviamente anche il nostro bravo Z80NE va "istruito" sull'uso della parallela.

Le routine riportate di seguito non sono necessarie se decidete di utilizzare la multifunzione perchè sono tutte già integrate sul monitor della stessa e quindi anche nel CP/M3.

Il codice è riportato qui per due ragioni: per conoscenza e perchè ancora non avuto tempo di integrarle nel SONE. Se qualche volontario si offrisse...

Non mi vorrei ripetere, ma mi ripeto, ricordando che le routine riportate qui non sono necessariamente all'ultima versione. Fate sempre riferimento a github invece.

Qui il codice di basso livello:

 Per chi volesse cimentarsi nell'implementare il tutto sul SONE ecco qui l'occorrente:

Per compilare il SONE, modificato o no, è sufficiente eseguire:

> ./makecpm.sh xx

dove xx indica il taglio di ram disponibile (48/56/60/62). In github il tutto si trova nella cartella "software/SONE/sone".

Sono necessari i tools indicati qui.

Tutto quanto sopra è per l'utilizzo del vdsk_server per l'accesso trasparente ai dischi virtuali, se invece volessimo trasferire il disco montato sul PC direttamente al nostro floppy occorre un utility per lo Z80 chiamata dsktran

Attualmente questa utility è disponibile solo per CP/M ma è in grado di trasferire qualsiasi immagine purchè supportata dal vdk_server e, fisicamente, dal floppy driver. A questo proposito notare, che tutte le opzioni con settori da 512 bytes non sono disponibili se non effettuando alcune modifiche sull'interfaccia floppy.

All'avvio il programma richiede alcune informazioni riguardo il numero di tracce/settori/formato e quindi inizia il trasferimento del disco sector-by-sector. Notare che selezionando il formato NEDOS viene regolarmente trattata la traccia 17 con gli specifici address mark.

 

Esempi di utilizzo

Avvio da disco virtuale. In questo video la console seriale dello Z80 (disponibile sulla multifunzione) è collegata ad un vecchio ma funzionale terminal server Annex e quindi in rete:

 

 

Todo list - Cose da fare

  • Porting vdsk_server su parport driver
  • dsktran versione NEDOS

 

 * Pino, dove trovi la pazienza per queste cose? Ancora grazie per il tuo insostituibile supporto!

 

 

Spiacente, questo articolo non è disponibile in inglese. United-Kingdom-flag-icon-26
Please ask, if you wish an english translation added

 

 

 
 
Floppy interface

 

Interfaccia Floppy Disk

 Portiamo i floppy a 880Kbytes di capacità

 

 

 

 

Hardware

 

under construction 

 

 

20171030 084642 20171030 084634 20171030 084723
 La daughter board Cablaggio ai connettori Modifiche a IC10

 

Il software

 

 

Spiacente, questo articolo non è disponibile in inglese. United-Kingdom-flag-icon-26
Please ask, if you wish an english translation added

 

 

mf 1
 
mf 2

 

La Multifunction Board

 Scateniamo la Z80!

 

 

 

 

Hardware

 

under construction 

 

 

20171030 084642 20171030 084634 20171030 084723
 La daughter board Cablaggio ai connettori Modifiche a IC10

 

Il software

 

Spiacente, questo articolo non è disponibile in inglese. United-Kingdom-flag-icon-26
Please ask, if you wish an english translation added

 

 

20171030 085820 

 

Lo Z80 NE nasce con due tipi si schede di memoria RAM una scheda statica da 8Kb ed una dinamica da 32 Kb.

Era possibile inserire più schede di memoria, in varie combinazioni, ottenendo diversi tagli di memoria come si vede in questa tabella:

Configurazione memoria

Purtroppo, in qualunque combinazione, non è possibile superare il limite dei 56K, lasciando scoperti gli ultimi 8kbytes di memoria e precisamente E000h fino a FFFFh.

Questa scelta è dovuta al fatto che in questo ultimo range di memoria sono presenti due regioni:

  • La ROM di sistema, o Monitor che è allocata da F000h a FFFFh (solo da F000h a F7FFh se da due Kbytes), e, ovviamente, non può essere eliminata.
  • La scheda video LX388 a bassa risoluzione utilizzava una RAM condivisa allocata da EC00h a EDFFh, bloccando di fatto tutto il range E000h-EFFFh.

Però, successivamente alla presentazione della scheda videografica LX529, che utilizza una memoria privata (non condivisa) la regione E000-EFFFh si è liberata, o almeno è libera, per tutti qulli che non utilizzano la "vecchia" scheda video. Ma nonostante questo ancora non è possibile superare il limite dei 56Kb perchè i banchi delle schede di memoria di Nuova Elettronica si basano su multipli di 8Kbytes, mentre per sfruttare gli ultimi Kbytes liberi da E000h servirebbe un banco di 4Kbytes così da arrivare a 56 + 4 = 60K di ram disponibile.

 

Modifiche hardware

Una possibile soluzione è quella di utilizzare due schede di memoria dinamica da 32Kbytes LX392 forzando la seconda scheda (totalmente popolata) a presentare sul bus solo 28K di memoria, cioè lasciando liberi gli ultimi 4Kbytes per la EPROM di sistema.

Il "trucco" sta nel disattivarla quando sul bus vengono presentati indirizzi a partire da F000h in su, utilizzando un semplice 74LS20.

Per fare questo si può aggiungere alla scheda una piccola "daughter board" su cui montare il 74LS20 e fare una piccola modifica intorno al 74LS139, IC10 della scheda dinamica che ha la funzionalità di selettore dei due banchi di 16K dinamici.

Questo è il circuito da aggiungere:

60kmem 

 

Queste invece sono le patch da eseguire sulla LX392 e riguardano IC10:

  • Separare i pin 2 e 3, il pin 2 deve rimanere scollegato
  • Collegare il pin 2 al pin 8 del 74LS20 (come da schema sopra)
  • Chiudere il ponticello P2 (P3 e P4 aperti)
  • Collegare il pin 9 di IC10  al ponticello P3 in basso cioè non dal lato attualmente collegato al pin 11 sempre di IC10 (vedi foto)

Come anticipato, in questo modo la scheda è attiva a coprire tutto lo spazio di indirizzamento fino a 64Kb, ma il 74LS20 aggiuntivo provvederà a disabilitarla ogni volta che sul bus è presente un indirizzo nel range Fxxxh, lasciando libero lo spazio occupato dalla EPROM, sia che sia da due o da quattro kbytes, per un totale effettivo di 60Kbytes.

Qualche foto indicativa (cliccare sull'immagine per ingrandire):

20171030 084642 20171030 084634 20171030 084723
 La daughter board Cablaggio ai connettori Modifiche a IC10

 

Il software

Il NE-DOS è un sistema operativo allocato nella parte bassa della memoria a partire dalla locazione 0h, questo gli consente di poter eseguire automaticamente il sizing della RAM disponibile.

Quindi utilizzando il NE-DOS non è necessario nulla per usare gli ultimi 4K appena aggiunti.

Un discorso diverso però vale per il CP/M o SONE come lo chiama Nuova Elettronica.

il CP/M usa uno schema di allocazione diverso. Per il CP/M 2.2, quale è il SONE, il tipico schema di utilizzo della RAM è questo:

arch mem

Le posizioni dei componenti del CP/M (CCP+BDOS+BIOS) sono prefissate al caricamento del sistema operativo, pertanto per passare da un sistema a 56K ad uno a 60K sono necessarie delle operazioni di adattamento del CP/M stesso.