lørdag 13. mai 2017

RC2014 Bruk av Compact Flash

Dette er et innlegg relatert til RC2014, se introduksjon, og vil mer eller mindre være mine egne notater relatert til denne egenutviklede modulen. Har laget en egen Compact Flash modul basert på ATA-standarden, det vil si bruk av kortet som en IDE-enhet - les innlegget RC2014 IDE Compact Flash for detaljer om maskinvaren. Dette innlegget håndterer programvaresiden.

Compact Flash (CF)

Modulen benytter seg av en 74HCT138N-brikke for håndtering av adresseringen, dette gjøres på samme måte som på Grant Searle sitt design samt slik det gjøres på den tilsvarende offisielle RC2014-modulen - holder disse detaljene identisk for å på sikt kunne bruke den samme programvaren uten endringer. Modulen som jeg laget vil dermed ikke skille seg fra de offisielle, informasjonen nevnt her vil med andre ord være generell og ikke spesifikk for min modul.

Binær adresse (x = don't care)
x001 0???

Som ved tidligere IO-moduler så betyr don't care at man ikke tar stilling til verdiene, men det betyr ikke at man unngår kollisjoner dersom andre enheter benytter adresser som overlapper - typisk vil dette si at modulene vil gjentas flere ganger i adresserommet for hver av kombinasjonene, i dette tilfellet på adressen $10 (16) og $90 (144).

Helt spesifikt så må A6 være lav for å aktivere 74HCT138N, selve adapteren er koblet til Y2 på denne og avgjør dermed at A5, A4 og A3 må være L H L. De resterende bit-ene benyttes for å angi registrene benyttet for å snakke med den ATA-baserte enheten.

Registre

Med adressen $10 som utgangspunkt har man følgende relevante registre tilgjengelig på enheten:

AdresseBeskrivelse
HEXDECRegisterMerknad
$1016DataData ut (les) / Data ut (skriv)
$1117Error / FeatureFeilmelding (les) / Funksjon (skriv)
$1218Sector countAntall sektorer
$1319LBA 0LBA Adresse (A0 - A7)
$1420LBA 1LBA Adresse (A8 - A15)
$1521LBA 2LBA Adresse (A16 - A23)
$1622LBA 3LBA Adresse (A24 - A27), angi enhet
$1723Status / CommandStatus (les) / Utfør kommando (skriv)

Antallet sektorer angir hvor mange sektorer man skal håndtere innenfor en enkelt lese/skrive- operasjon, minste antallet er 1 og hver sektor er 512 byte (man må håndtere hele blokken). Sektorer angis sekvensielt ved bruk av en 28-bit adresse, disse angis gjennom LBA 0 - 3. LBA 0 - 2 de første 24 bit-ene av adressen, LBA 3 inkluderer de siste 4 bit-ene i den 28-bit sektor-adressen samt at man også her angir hvilken enhet som skal adresseres (Master / Slave) - for å holde ting enkelt bruker vi her bare E0 for å lese/skrive til Master.

For å arbeide med enheten vil man kort sagt skrive til et eller flere registre, deretter sende en kommando via kommando-registeret for å få den til å utføre den. Underveis må man sjekke status-registeret for å vite hvorvidt enheten fungerer som forventet, eventuelt er klar til å motta videre kommandoer - svaret vil være en enkel byte der hver bit har følgende betydning:
765x 3xx0 - Bit (x = don't care)
1         - Busy, enheten er opptatt
 1        - Ready, enheten er klar til å motta kommando
  1       - Write Fault, skrivefeil oppstått
     1    - Data request ready, data tilgjengelig for utlesing
        1 - Command error, forrige kommando feilet

Lese data

For å benytte seg av CF-kortet må man i praksis først initialisere kortet, det vil si å sette opp de innstillingene vi trenger for å arbeide med kortet i 8-bit modus (legg merke til CF er den eneste gjenlevende maskinvaren som støtter dette, moderne harddisker gjør ikke det). Deretter skriver man en 28-bit adresse til LBA adresse-registrene, sender kommando for å gjøre data tilgjengelig for lesning og til sist må vi lese ut hele sektoren.

Det meste av programvaren jeg har sett for Z80-baserte maskiner har vært implementert i Assembly, men har for tiden ikke noen løsning for å overføre kompilert programvare til maskinen så valgte å implementere rutinene i Basic isteden.

10 print "Set CF 8-bit mode"
15 OUT 17, 1
16 OUT 23, 239

20 PRINT "Disable write cache"
25 OUT 17, 130  
26 OUT 23, 239

30 PRINT "Set sector count = 0"
35 OUT 18, 1

40 PRINT "Set address = 0"
41 OUT 19, 0
42 OUT 20, 0
43 OUT 21, 0
44 OUT 22, 224
45 OUT 23, 32

50 PRINT "Read first sector:"
55 FOR I=0 TO 511 STEP 8
60 PRINT I;":";
65 FOR B=0 TO 7
70 PRINT INP(16);
75 NEXT B
80 PRINT
85 NEXT I

Dersom man får feilmeldinger, eller at ting ikke fungerer som forventet så kan man lese ut statusen fra registeret på $17. Strengt tatt bør man sjekke statusen mellom hver av kommandoene som utføres, dette for å være sikker på at CF-kortet er klart før man fortsetter - dette har jeg hoppet over her ettersom Basic i seg selv er såpass tregt at man ikke trenger dette, men skriver man tilsvarende Assembly-kode så må man gjøre dette.

For å verifisere at det man får lest ut er korrekt, så kan man åpne kortet i en Hex editor med støtte for dette (eksempelvis WinHex) - på mitt kort gir denne visningen under (til venstre). Gitt at ingenting ryker eller lukter brent elektronikk så vil man ved bruk av skriptet ovenfor få en utskrift slik den vist under til høyre.

  

Legg merke til at en Hex-editor viser, som navnet antyder alt av data i Hex mens skriptet jeg har lagt inn viser utskrift i desimal - for å sammenligne data må man oversette mellom tallsystemene, den vanlige kalkulatoren i Windows vil kunne gjøre dette. Får man det samme resultatet på begge sider, så vet man at kortet fungerer som forventet - i det minste under optimale forhold!

Ingen kommentarer:

Legg inn en kommentar