Last modified on 2 July 2024, at 21:08

Difference between revisions of "765 FDC"

(Ready / Disc Changed signal)
(FDC Command Table (15 commands))
 
(34 intermediate revisions by the same user not shown)
Line 8: Line 8:
  
 
The [[Vortex Disc Drives|Vortex disc interface]] uses other ports. See its dedicated wiki page.
 
The [[Vortex Disc Drives|Vortex disc interface]] uses other ports. See its dedicated wiki page.
 +
 +
<br>
  
 
== IC Models used in CPC ==
 
== IC Models used in CPC ==
Line 25: Line 27:
 
* SED9420C
 
* SED9420C
  
Note: The CPC464, CPC472, 464 Plus and GX4000 are not equipped with a FDC chip.
+
The CPC464, CPC472, 464 Plus and GX4000 are not equipped with a FDC chip.
 +
 
 +
<br>
  
 
== Accessing the FDC 765 ==
 
== Accessing the FDC 765 ==
The Data Register (Port FB7Fh) is used to write Commands and Parameters, to read/write data bytes, and to receive result bytes. These three operations are called Command-, Execution-, and Result-Phase. The Main Status Register signalizes when the FDC is ready to send/receive the next byte through the Data Register.
 
  
a. Command Phase
+
The Data Register (Port FB7Fh) is used to write Commands and Parameters, to read/write data bytes, and to receive result bytes. These three operations are called Command-, Execution-, and Result-Phase :
 +
* Command Phase :A command consists of a command byte (eventually including the MF, MK, SK bits), and up to 8 parameter bytes.
  
A command consists of a command byte (eventually including the MF, MK, SK bits), and up to eight parameter bytes.
+
* Execution Phase : During this phase, the actual data is transferred (if any). Usually that are the data bytes for the read/written sector(s), except for the Format Track Command, in that case 4 bytes for each sector are transferred.
  
b. Execution Phase
+
* Result Phase : Returns up to 7 result bytes (depending on the command) that are containing status information. The Recalibrate and Seek Track commands do not return result bytes directly, instead the program must wait until the Main Status Register signalizes that the command has been completed, and then it must (!) send a Sense Interrupt State command to 'terminate' the Seek/Recalibrate command.
  
During this phase, the actual data is transferred (if any). Usually that are the data bytes for the read/written sector(s), except for the Format Track Command, in that case four bytes for each sector are transferred.
+
The Main Status Register signalizes when the FDC is ready to send/receive the next byte through the Data Register.
  
c. Result Phase
+
<br>
  
Returns up to seven result bytes (depending on the command) that are containing status information. The Recalibrate and Seek Track commands do not return result bytes directly, instead the program must wait until the Main Status Register signalizes that the command has been completed, and then it must (!) send a Sense Interrupt State command to 'terminate' the Seek/Recalibrate command.
+
== FDC Command Table (15 commands) ==
  
== FDC Command Table ==
+
{| class="wikitable"
 +
|+ Read Data (06h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || MT || MF || SK || 0 || 0 || 1 || 1 || 0
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | C: cylinder number
 +
|-
 +
| command byte 3 || colspan="8" | H: head number
 +
|-
 +
| command byte 4 || colspan="8" | R: sector number
 +
|-
 +
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | DTL: data length (if command byte 5==0)
 +
|-
 +
| Execution      || colspan="8" | Data-transfer from the FDD
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
  
Command    Parameters              Exm Result              Description
+
{| class="wikitable"
02+MF+SK    HU TR HD ?? SZ NM GP SL <R> S0 S1 S2 TR HD NM SZ read track
+
|+ Read Deleted Data (0Ch)
03          XX YY                    -                       specify spd/dma
+
|-
04          HU                      - S3                  sense drive state
+
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
05+MT+MF   HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ write sector(s)
+
|-
06+MT+MF+SK HU TR HD SC SZ LS GP SL <R> S0 S1 S2 TR HD LS SZ read sector(s)
+
| command byte 0 || MT || MF || SK || 0 || 1 || 1 || 0 || 0
07          HU                      -                       recalib.seek TP=0
+
|-
08          -                       S0 TP                sense int.state
+
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
  09+MT+MF    HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ wr deleted sec(s)
+
|-
0A+MF      HU                      S0 S1 S2 TR HD LS SZ read ID
+
| command byte 2 || colspan="8" | C: cylinder number
  0C+MT+MF+SK HU TR HD SC SZ LS GP SL <R> S0 S1 S2 TR HD LS SZ rd deleted sec(s)
+
|-
  0D+MF      HU SZ NM GP FB          <W> S0 S1 S2 TR HD LS SZ format track
+
| command byte 3 || colspan="8" | H: head number
0F          HU TP                    -                       seek track n
+
|-
  11+MT+MF+SK HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ scan equal
+
| command byte 4 || colspan="8" | R: sector number
  19+MT+MF+SK HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ scan low or equal
+
|-
1D+MT+MF+SK HU TR HD SC SZ LS GP SL <W> S0 S1 S2 TR HD LS SZ scan high or eq.
+
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | DTL: data length (if command byte 5==0)
 +
|-
 +
| Execution      || colspan="8" | Data-transfer from the FDD
 +
|-
 +
| result byte 0 || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1 || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2 || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3 || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4 || colspan="8" | H: head number
 +
|-
 +
| result byte 5 || colspan="8" | R: sector number
 +
|-
 +
| result byte 6 || colspan="8" | N: bytes per sector
 +
|}
  
Parameter bits that can be specified in some Command Bytes are:
+
{| class="wikitable"
 +
|+ Write Data (05h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || MT || MF || x || 0 || 0 || 1 || 0 || 1
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | C: cylinder number
 +
|-
 +
| command byte 3 || colspan="8" | H: head number
 +
|-
 +
| command byte 4 || colspan="8" | R: sector number
 +
|-
 +
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | DTL: data length (if command byte 5==0)
 +
|-
 +
| Execution      || colspan="8" | Data-transfer to the FDD
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
  
  MT  Bit7  Multi Track (continue multi-sector-function on other head)
+
{| class="wikitable"
  MF  Bit6  MFM-Mode-Bit (Default 1=Double Density)
+
|+ Write Deleted Data (09h)
  SK Bit5 Skip-Bit (set if secs with deleted DAM shall be skipped)
+
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || MT || MF || x || 0 || 1 || 0 || 0 || 1
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | C: cylinder number
 +
|-
 +
| command byte 3 || colspan="8" | H: head number
 +
|-
 +
| command byte 4 || colspan="8" | R: sector number
 +
|-
 +
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | DTL: data length (if command byte 5==0)
 +
|-
 +
| Execution      || colspan="8" | Data-transfer to the FDD
 +
|-
 +
| result byte 0 || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1 || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
  
Parameter/Result bytes are:
+
{| class="wikitable"
 +
|+ Read Track (02h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || x || MF || SK || 0 || 0 || 0 || 1 || 0
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | C: cylinder number
 +
|-
 +
| command byte 3 || colspan="8" | H: head number
 +
|-
 +
| command byte 4 || colspan="8" | R: sector number
 +
|-
 +
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | DTL: data length (if command byte 5==0)
 +
|-
 +
| Execution      || colspan="8" | FDC reads all data fields from index hole to EOT
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
  
  HU  b0,1=Unit/Drive Number, b2=Physical Head Number, other bits zero
+
{| class="wikitable"
  TP  Physical Track Number
+
|+ Read ID (0Ah)
  TR  Track-ID (usually same value as TP)
+
|-
  HD Head-ID
+
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
  SC  First Sector-ID (sector you want to read)
+
|-
  SZ Sector Size (80h shl n) (default=02h for 200h bytes)
+
| command byte 0 || x || MF || x || 0 || 1 || 0 || 1 || 0
  LS  Last Sector-ID (should be same as SC when reading a single sector)
+
|-
  GP Gap (default=2Ah except command 0D: default=52h)
+
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
  SL Sectorlen if SZ=0 (default=FFh)
+
|-
  Sn  Status Register 0..3
+
| Execution      || colspan="8" | The first correct ID information on the cylinder is stored in data register
  FB Fillbyte (for the sector data areas) (default=E5h)
+
|-
  NM Number of Sectors (default=09h)
+
| result byte 0 || colspan="8" | ST0: status register 0
  XX b0..3=headunload n*32ms (8" only), b4..7=steprate (16-n)*2ms
+
|-
  YY b0=DMA_disable, b1-7=headload n*4ms (8" only)
+
| result byte 1 || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2 || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3 || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4 || colspan="8" | H: head number
 +
|-
 +
| result byte 5 || colspan="8" | R: sector number
 +
|-
 +
| result byte 6 || colspan="8" | N: bytes per sector
 +
|}
  
Format Track: output TR,HD,SC,SZ for each sector during execution phase
+
{| class="wikitable"
Read Track: reads NM sectors (starting with first sec past index hole)
+
|+ Format Track (0Dh)
Read ID: read ID bytes for current sec, repeated/undelayed read lists all IDs
+
|-
Recalib: walks up to 77 tracks, 80tr-drives may need second recalib if failed
+
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
Seek/Recalib: All read/write commands will be disabled until succesful senseint
+
|-
Senseint: Set's IC if unsuccesful (no int has occured) (until IC=0)
+
| command byte 0 || x || MF || x || 0 || 1 || 1 || 0 || 1
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 3 || colspan="8" | SC: sectors per track
 +
|-
 +
| command byte 4 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 5 || colspan="8" | D: filler pattern to write in each byte
 +
|-
 +
| Execution      || colspan="8" | FDC formats an entire track
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Scan Equal (11h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || MT || MF || SK || 1 || 0 || 0 || 0 || 1
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | C: cylinder number
 +
|-
 +
| command byte 3 || colspan="8" | H: head number
 +
|-
 +
| command byte 4 || colspan="8" | R: sector number
 +
|-
 +
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | STP: scan test (1=scan contiguous, 2=scan alternate)
 +
|-
 +
| Execution      || colspan="8" | Data compared between the FDD and main-system
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Scan Low or Equal (19h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || MT || MF || SK || 1 || 1 || 0 || 0 || 1
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | C: cylinder number
 +
|-
 +
| command byte 3 || colspan="8" | H: head number
 +
|-
 +
| command byte 4 || colspan="8" | R: sector number
 +
|-
 +
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | STP: scan test (1=scan contiguous, 2=scan alternate)
 +
|-
 +
| Execution      || colspan="8" | Data compared between the FDD and main-system
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Scan High or Equal (1Dh)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || MT || MF || SK || 1 || 1 || 1 || 0 || 1
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | C: cylinder number
 +
|-
 +
| command byte 3 || colspan="8" | H: head number
 +
|-
 +
| command byte 4 || colspan="8" | R: sector number
 +
|-
 +
| command byte 5 || colspan="8" | N: bytes per sector
 +
|-
 +
| command byte 6 || colspan="8" | EOT: end of track (ie. last sector in track)
 +
|-
 +
| command byte 7 || colspan="8" | GPL: gap 3 length
 +
|-
 +
| command byte 8 || colspan="8" | STP: scan test (1=scan contiguous, 2=scan alternate)
 +
|-
 +
| Execution      || colspan="8" | Data compared between the FDD and main-system
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | ST1: status register 1
 +
|-
 +
| result byte 2  || colspan="8" | ST2: status register 2
 +
|-
 +
| result byte 3  || colspan="8" | C: cylinder number
 +
|-
 +
| result byte 4  || colspan="8" | H: head number
 +
|-
 +
| result byte 5  || colspan="8" | R: sector number
 +
|-
 +
| result byte 6  || colspan="8" | N: bytes per sector
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Recalibrate (07h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || colspan="3" style="text-align: center;" | x  || 0 || 0 || 1 || 1 || 1
 +
|-
 +
| command byte 1 || colspan="6" style="text-align: center;" | x || colspan="2" style="text-align: center;" | US
 +
|-
 +
| Execution      || colspan="8" | Head retracted to track 0
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Seek (0Fh)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || colspan="3" style="text-align: center;" | x  || 0 || 1 || 1 || 1 || 1
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD|| colspan="2" style="text-align: center;" | US
 +
|-
 +
| command byte 2 || colspan="8" | NCN: new cylinder number
 +
|-
 +
| Execution      || colspan="8" | Head is positioned over proper cylinder
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Sense Interrupt Status (08h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || colspan="3" style="text-align: center;" | x || 0 || 1 || 0 || 0 || 0
 +
|-
 +
| result byte 0  || colspan="8" | ST0: status register 0
 +
|-
 +
| result byte 1  || colspan="8" | PCN: present cylinder number
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Sense Drive Status (04h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || colspan="3" style="text-align: center;" | x || 0 || 0 || 1 || 0 || 0
 +
|-
 +
| command byte 1 || colspan="5" style="text-align: center;" | x || HD || colspan="2" style="text-align: center;" | US
 +
|-
 +
| result byte 0  || colspan="8" | ST3: status register 3
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Specify (03h)
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || colspan="3" style="text-align: center;" | x || 0 || 0 || 0 || 1 || 1
 +
|-
 +
| command byte 1 || colspan="4" style="text-align: center;" | SRT || colspan="4" style="text-align: center;" | HUT
 +
|-
 +
| command byte 2 || colspan="7" style="text-align: center;" | HLT || ND
 +
|}
 +
 
 +
{| class="wikitable"
 +
|+ Invalid
 +
|-
 +
!                !! D7 !! D6 !! D5 !! D4 !! D3 !! D2 !! D1 !! D0
 +
|-
 +
| command byte 0 || colspan="3" style="text-align: center;" | x || colspan="5" style="text-align: center;" | Invalid Codes
 +
|-
 +
| result byte  0 || colspan="8" | ST0: status register 0
 +
|}
 +
 
 +
Abbreviations used:
 +
 
 +
*MT = Multi-track (continue multi-sector function on other head)
 +
*MF = MFM mode (1 = Double Density)
 +
*SK = Skip deleted-data address mark (set if sectors with deleted DAM shall be skipped)
 +
*HD = Head number select
 +
*US = Unit select (drive select)
 +
 
 +
*HLT = Head Load Time: 2 to 254ms in 2ms increments
 +
*HUT = Head Unload Time: 16 to 240ms in 16ms increments
 +
*SRT = Step Rate Time: 1 to 16ms in 1ms increments (F = 1ms, E = 2ms, etc.)
 +
*ND = Non-DMA mode
 +
 
 +
Notes:
 +
* Format Track: The processor must supply C, H, R, N to the FDC for each sector during execution phase
 +
* Recalibrate: Walks up to 77 tracks, 80tr-drives may need second recalib if failed
 +
* Seek / Recalibrate: All read/write commands will be disabled until succesful sense interrupt
 +
* Specify: All timings will be doubled on CPC because the FDC runs at 4MHz instead of 8MHz for the datasheet
 +
 
 +
<br>
  
 
== FDC Status Registers ==
 
== FDC Status Registers ==
Line 97: Line 525:
 
Main Status Register (Port FB7E)
 
Main Status Register (Port FB7E)
  
   b0..3  DB FDD0..3 Busy (seek/recalib active, until succesful sense intstat)
+
   b0..3  DB   FDD0..3 Busy (seek/recalib active, until succesful sense intstat)
   b4    CB FDC Busy (still in command-, execution- or result-phase)
+
   b4    CB   FDC Busy (still in command-, execution- or result-phase)
   b5    EXM Execution Mode (still in execution-phase, non_DMA_only)
+
   b5    EXM Execution Mode (still in execution-phase, non_DMA_only)
   b6    DIO Data Input/Output (0=CPU->FDC, 1=FDC->CPU) (see b7)
+
   b6    DIO Data Input/Output (0=CPU->FDC, 1=FDC->CPU) (see b7)
   b7    RQM Request For Master (1=ready for next byte) (see b6 for direction)
+
   b7    RQM Request For Master (1=ready for next byte) (see b6 for direction)
  
 
Status Register 0
 
Status Register 0
  
   b0,1  US Unit Select (driveno during interrupt)
+
   b0,1  US   Unit Select (driveno during interrupt)
   b2    HD Head Address (head during interrupt)
+
   b2    HD   Head Address (head during interrupt)
   b3    NR Not Ready (drive not ready or non-existing 2nd head selected)
+
   b3    NR   Not Ready (drive not ready or non-existing 2nd head selected)
   b4    EC Equipment Check (drive failure or recalibrate failed (retry))
+
   b4    EC   Equipment Check (drive failure or recalibrate failed (retry))
   b5    SE Seek End (Set if seek-command completed)
+
   b5    SE   Seek End (Set if seek-command completed)
   b6,7  IC Interrupt Code (0=OK, 1=aborted:readfail/OK if EN, 2=unknown cmd
+
   b6,7  IC   Interrupt Code (0=OK, 1=aborted:readfail/OK if EN, 2=unknown cmd
            or senseint with no int occured, 3=aborted:disc removed etc.)
+
              or senseint with no int occured, 3=aborted:disc removed etc.)
  
 
Status Register 1
 
Status Register 1
  
   b0    MA Missing Address Mark (Sector_ID or DAM not found)
+
   b0    MA   Missing Address Mark (Sector_ID or DAM not found)
   b1    NW Not Writeable (tried to write/format disc with wprot_tab=on)
+
   b1    NW   Not Writeable (tried to write/format disc with wprot_tab=on)
   b2    ND No Data (Sector_ID not found, CRC fail in ID_field)
+
   b2    ND   No Data (Sector_ID not found, CRC fail in ID_field)
   b3,6  0   Not used
+
   b3,6  0   Not used
   b4    OR Over Run (CPU too slow in execution-phase (ca. 26us/Byte))
+
   b4    OR   Over Run (CPU too slow in execution-phase (ca. 26us/Byte))
   b5    DE Data Error (CRC-fail in ID- or Data-Field)
+
   b5    DE   Data Error (CRC-fail in ID- or Data-Field)
   b7    EN End of Track (set past most read/write commands) (see IC)
+
   b7    EN   End of Track (set past most read/write commands) (see IC)
  
 
Status Register 2
 
Status Register 2
  
   b0    MD Missing Address Mark in Data Field (DAM not found)
+
   b0    MD   Missing Address Mark in Data Field (DAM not found)
   b1    BC Bad Cylinder (read/programmed track-ID different and read-ID = FF)
+
   b1    BC   Bad Cylinder (read/programmed track-ID different and read-ID = FF)
   b2    SN Scan Not Satisfied (no fitting sector found)
+
   b2    SN   Scan Not Satisfied (no fitting sector found)
   b3    SH Scan Equal Hit (equal)
+
   b3    SH   Scan Equal Hit (equal)
   b4    WC Wrong Cylinder (read/programmed track-ID different) (see b1)
+
   b4    WC   Wrong Cylinder (read/programmed track-ID different) (see b1)
   b5    DD Data Error in Data Field (CRC-fail in data-field)
+
   b5    DD   Data Error in Data Field (CRC-fail in data-field)
   b6    CM Control Mark (read/scan command found sector with deleted DAM)
+
   b6    CM   Control Mark (read/scan command found sector with deleted DAM)
   b7    0   Not Used
+
   b7    0   Not Used
  
 
Status Register 3
 
Status Register 3
  
   b0,1  US Unit Select (pin 28,29 of FDC)
+
   b0,1  US   Unit Select (pin 28,29 of FDC)
   b2    HD Head Address (pin 27 of FDC)
+
   b2    HD   Head Address (pin 27 of FDC)
   b3    TS Two Side (0=yes, 1=no (!))
+
   b3    TS   Two Side (0=yes, 1=no (!))
   b4    T0 Track 0 (on track 0 we are)
+
   b4    T0   Track 0 (on track 0 we are)
   b5    RY Ready (drive ready signal)
+
   b5    RY   Ready (drive ready signal)
   b6    WP Write Protected (write protected)
+
   b6    WP   Write Protected (write protected)
   b7    FT Fault (if supported: 1=Drive failure)
+
   b7    FT   Fault (if supported: 1=Drive failure)
 +
 
 +
<br>
  
 
== Motor On/Off Flipflop ==
 
== Motor On/Off Flipflop ==
Line 148: Line 578:
  
 
An exception are the Vortex F1-S, F1-D, M1-S and M1-D drives. (How are they different?)
 
An exception are the Vortex F1-S, F1-D, M1-S and M1-D drives. (How are they different?)
 +
 +
<br>
  
 
== Unconnected Pins ==
 
== Unconnected Pins ==
Line 155: Line 587:
 
The CPC doesn't support floppy DMA transfers, and the FDC's Interrupt signal isn't used in the CPC.
 
The CPC doesn't support floppy DMA transfers, and the FDC's Interrupt signal isn't used in the CPC.
  
In the CPC the DS1 signal of the FDC is not connected, making it impossible to select floppy drives 2 and 3. The floppy drives 0 and 1 are selected instead.
+
In the CPC the US1 signal of the FDC is not connected, making it impossible to select floppy drives 2 and 3. The floppy drives 0 and 1 are selected instead.
  
== Ready / Disc Changed signal ==
+
<br>
 +
 
 +
== Ready / Disk Changed signal ==
  
 
This signal differs between floppy drives model:
 
This signal differs between floppy drives model:
  
*For 3inch floppy drives (pin26), it is a "Ready" signal. The /RDY signal is sent whenever a disk is installed and rotating at correct speed in the drive.
+
*For 3inch floppy drives (pin26), it is a "Ready" signal. The /RDY signal is sent whenever a disk is installed and rotating in the drive.
 +
 
 +
*For 3.5inch floppy drives (pin34), it is a "Disk Changed" signal. The /DSKCHG signal determines whether the same disk loaded during the previous disk access is still in the drive.
 +
 
 +
The simplest solution to this issue is to just force the Ready signal on the cable itself. Note that the CPC will then hang if you type the CAT command when no disk is present (inserting a disk will unblock it).
 +
 
 +
Other solutions exist to [[Modify PC floppy drives]] to recreate a Ready signal. Also, Gotek drives (with a FlashFloppy or HxC firmware) can be configured to simulate the Ready signal.
  
*For 3.5inch floppy drives or Gotek (pin34), it is a "Disc Changed" signal. The /DSKCHG signal determines whether the same disk loaded during the previous disk access is still in the drive.
+
<br>
  
 
== Notes ==
 
== Notes ==
Line 178: Line 618:
  
 
Usually single sided 40-track 3" disk drives are used in CPCs. For practical purposes, 42 tracks could be used — the limit is specific to the drive and some support more tracks but 42 is a good maximum. The FDC controller can be used to control 80-tracks and/or double sided drives, though AMSDOS doesn't support such formats. AMSDOS supports a maximum of two disk drives only.
 
Usually single sided 40-track 3" disk drives are used in CPCs. For practical purposes, 42 tracks could be used — the limit is specific to the drive and some support more tracks but 42 is a good maximum. The FDC controller can be used to control 80-tracks and/or double sided drives, though AMSDOS doesn't support such formats. AMSDOS supports a maximum of two disk drives only.
 +
 +
<br>
  
 
== FDC Track Format ==
 
== FDC Track Format ==
 
[[File:FDC765 Track Format.png]]
 
[[File:FDC765 Track Format.png]]
 +
 +
<br>
  
 
== Internal details of the chip ==
 
== Internal details of the chip ==
Line 187: Line 631:
  
 
* From [https://hackaday.com/2012/08/13/taking-a-look-at-decapped-ics/#comment-734991 a comment in the hackaday website]: "Internally this is a microcoded part with a primative controller of NEC’s own design. Testing microcode embedded in a part can be troublesome. The uPD765 had a few extra gates associated with the DMA Request and DMA Ack pins. Presenting a certain illegal combination here places the part into a “test” mode and allows the sequencer microcode to be output on the normal Data pins. The sequencer microcode is responsible for high level commands such as Read Track, Recalibrate, Format Track, or Write Data. There is a similar test mode for the nano-code array which serializes data at the floppy disk head."
 
* From [https://hackaday.com/2012/08/13/taking-a-look-at-decapped-ics/#comment-734991 a comment in the hackaday website]: "Internally this is a microcoded part with a primative controller of NEC’s own design. Testing microcode embedded in a part can be troublesome. The uPD765 had a few extra gates associated with the DMA Request and DMA Ack pins. Presenting a certain illegal combination here places the part into a “test” mode and allows the sequencer microcode to be output on the normal Data pins. The sequencer microcode is responsible for high level commands such as Read Track, Recalibrate, Format Track, or Write Data. There is a similar test mode for the nano-code array which serializes data at the floppy disk head."
 +
 +
<br>
  
 
== FDC Block Diagram ==
 
== FDC Block Diagram ==
 
[[File:FDC Intel 8272A block diagram.gif]]
 
[[File:FDC Intel 8272A block diagram.gif]]
 +
 +
<br>
  
 
== Generic System Diagram ==
 
== Generic System Diagram ==
Line 196: Line 644:
 
[[File:UPD765A System Diagram.png]]
 
[[File:UPD765A System Diagram.png]]
  
== 3-inch Floppy Drive Interface ==
+
<br>
[[File:Interface FDC - Floppy drive.png]]
+
 
 +
== PC to CPC floppy connector ==
 +
[[File:Cpc6128floppytopcfloppy.gif]]
 +
 
 +
<br>
  
 
== FDD Block Diagram ==
 
== FDD Block Diagram ==
 
[[File:Floppy Disk Drive - Block Diagram.png]]
 
[[File:Floppy Disk Drive - Block Diagram.png]]
  
== PC to CPC floppy connector ==
+
<br>
 
+
[[File:Cpc6128floppytopcfloppy.gif]]
+
  
 
== Datasheets ==
 
== Datasheets ==
Line 215: Line 665:
 
* [[Media:Panasonic-3 inch Floppy Drive EME-150.pdf]] Panasonic EME-150M 3inch Floppy Disk Drive Datasheet
 
* [[Media:Panasonic-3 inch Floppy Drive EME-150.pdf]] Panasonic EME-150M 3inch Floppy Disk Drive Datasheet
 
* [[Media:NEC_FD1035_Floppy.pdf]] - NEC FD1035 3.5inch Floppy Disk Drive Datasheet (1984)
 
* [[Media:NEC_FD1035_Floppy.pdf]] - NEC FD1035 3.5inch Floppy Disk Drive Datasheet (1984)
 +
 +
<br>
  
 
== External links ==
 
== External links ==
 
*[http://quasar.cpcscene.net/doku.php?id=assem:fdc Quasar FDC documentation (in french)]
 
*[http://quasar.cpcscene.net/doku.php?id=assem:fdc Quasar FDC documentation (in french)]
 
*[https://64nops.wordpress.com/2021/07/04/a-la-decouverte-du-fdc/ FDC blog articles (in french)]
 
*[https://64nops.wordpress.com/2021/07/04/a-la-decouverte-du-fdc/ FDC blog articles (in french)]
*[https://info-coach.fr/atari/hardware/FD-Hard.php Atari ST Floppy Disk hardware analysis]
+
*[https://info-coach.fr/atari/hardware/FD-Hard.php Atari ST Floppy Drive hardware analysis]
  
 
[[Category:CPC Internal Components]][[Category:Programming]][[Category:DATA Storage]][[Category:Electronic Component]]
 
[[Category:CPC Internal Components]][[Category:Programming]][[Category:DATA Storage]][[Category:Electronic Component]]

Latest revision as of 21:08, 2 July 2024

µPD765 - Floppy Disc Controller (used in DDI-1 and CPC 664/6128).

The ports used by Amstrad and compatible interfaces use:

  • Port FA7Eh - Floppy Motor On/Off Flipflop
  • Port FB7Eh - FDC 765 Main Status Register (read only)
  • Port FB7Fh - FDC 765 Data Register (read/write)

The Vortex disc interface uses other ports. See its dedicated wiki page.


IC Models used in CPC

More than one manufacturer made 765 compatible ICs. These are the ones known to be used in the CPC by looking at pictures of CPC mainboards.

All should operate almost identically.

The following data seperators are used:

  • FDC9216
  • SED9420C

The CPC464, CPC472, 464 Plus and GX4000 are not equipped with a FDC chip.


Accessing the FDC 765

The Data Register (Port FB7Fh) is used to write Commands and Parameters, to read/write data bytes, and to receive result bytes. These three operations are called Command-, Execution-, and Result-Phase :

  • Command Phase :A command consists of a command byte (eventually including the MF, MK, SK bits), and up to 8 parameter bytes.
  • Execution Phase : During this phase, the actual data is transferred (if any). Usually that are the data bytes for the read/written sector(s), except for the Format Track Command, in that case 4 bytes for each sector are transferred.
  • Result Phase : Returns up to 7 result bytes (depending on the command) that are containing status information. The Recalibrate and Seek Track commands do not return result bytes directly, instead the program must wait until the Main Status Register signalizes that the command has been completed, and then it must (!) send a Sense Interrupt State command to 'terminate' the Seek/Recalibrate command.

The Main Status Register signalizes when the FDC is ready to send/receive the next byte through the Data Register.


FDC Command Table (15 commands)

Read Data (06h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 MT MF SK 0 0 1 1 0
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 DTL: data length (if command byte 5==0)
Execution Data-transfer from the FDD
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Read Deleted Data (0Ch)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 MT MF SK 0 1 1 0 0
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 DTL: data length (if command byte 5==0)
Execution Data-transfer from the FDD
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Write Data (05h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 MT MF x 0 0 1 0 1
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 DTL: data length (if command byte 5==0)
Execution Data-transfer to the FDD
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Write Deleted Data (09h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 MT MF x 0 1 0 0 1
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 DTL: data length (if command byte 5==0)
Execution Data-transfer to the FDD
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Read Track (02h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x MF SK 0 0 0 1 0
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 DTL: data length (if command byte 5==0)
Execution FDC reads all data fields from index hole to EOT
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Read ID (0Ah)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x MF x 0 1 0 1 0
command byte 1 x HD US
Execution The first correct ID information on the cylinder is stored in data register
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Format Track (0Dh)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x MF x 0 1 1 0 1
command byte 1 x HD US
command byte 2 N: bytes per sector
command byte 3 SC: sectors per track
command byte 4 GPL: gap 3 length
command byte 5 D: filler pattern to write in each byte
Execution FDC formats an entire track
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Scan Equal (11h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 MT MF SK 1 0 0 0 1
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 STP: scan test (1=scan contiguous, 2=scan alternate)
Execution Data compared between the FDD and main-system
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Scan Low or Equal (19h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 MT MF SK 1 1 0 0 1
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 STP: scan test (1=scan contiguous, 2=scan alternate)
Execution Data compared between the FDD and main-system
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Scan High or Equal (1Dh)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 MT MF SK 1 1 1 0 1
command byte 1 x HD US
command byte 2 C: cylinder number
command byte 3 H: head number
command byte 4 R: sector number
command byte 5 N: bytes per sector
command byte 6 EOT: end of track (ie. last sector in track)
command byte 7 GPL: gap 3 length
command byte 8 STP: scan test (1=scan contiguous, 2=scan alternate)
Execution Data compared between the FDD and main-system
result byte 0 ST0: status register 0
result byte 1 ST1: status register 1
result byte 2 ST2: status register 2
result byte 3 C: cylinder number
result byte 4 H: head number
result byte 5 R: sector number
result byte 6 N: bytes per sector
Recalibrate (07h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x 0 0 1 1 1
command byte 1 x US
Execution Head retracted to track 0
Seek (0Fh)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x 0 1 1 1 1
command byte 1 x HD US
command byte 2 NCN: new cylinder number
Execution Head is positioned over proper cylinder
Sense Interrupt Status (08h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x 0 1 0 0 0
result byte 0 ST0: status register 0
result byte 1 PCN: present cylinder number
Sense Drive Status (04h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x 0 0 1 0 0
command byte 1 x HD US
result byte 0 ST3: status register 3
Specify (03h)
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x 0 0 0 1 1
command byte 1 SRT HUT
command byte 2 HLT ND
Invalid
D7 D6 D5 D4 D3 D2 D1 D0
command byte 0 x Invalid Codes
result byte 0 ST0: status register 0

Abbreviations used:

  • MT = Multi-track (continue multi-sector function on other head)
  • MF = MFM mode (1 = Double Density)
  • SK = Skip deleted-data address mark (set if sectors with deleted DAM shall be skipped)
  • HD = Head number select
  • US = Unit select (drive select)
  • HLT = Head Load Time: 2 to 254ms in 2ms increments
  • HUT = Head Unload Time: 16 to 240ms in 16ms increments
  • SRT = Step Rate Time: 1 to 16ms in 1ms increments (F = 1ms, E = 2ms, etc.)
  • ND = Non-DMA mode

Notes:

  • Format Track: The processor must supply C, H, R, N to the FDC for each sector during execution phase
  • Recalibrate: Walks up to 77 tracks, 80tr-drives may need second recalib if failed
  • Seek / Recalibrate: All read/write commands will be disabled until succesful sense interrupt
  • Specify: All timings will be doubled on CPC because the FDC runs at 4MHz instead of 8MHz for the datasheet


FDC Status Registers

The Main Status register can be always read through Port FB7E. The other four Status Registers cannot be read directly, instead they are returned through the data register as result bytes in response to specific commands.

Main Status Register (Port FB7E)

 b0..3  DB   FDD0..3 Busy (seek/recalib active, until succesful sense intstat)
 b4     CB   FDC Busy (still in command-, execution- or result-phase)
 b5     EXM  Execution Mode (still in execution-phase, non_DMA_only)
 b6     DIO  Data Input/Output (0=CPU->FDC, 1=FDC->CPU) (see b7)
 b7     RQM  Request For Master (1=ready for next byte) (see b6 for direction)

Status Register 0

 b0,1   US   Unit Select (driveno during interrupt)
 b2     HD   Head Address (head during interrupt)
 b3     NR   Not Ready (drive not ready or non-existing 2nd head selected)
 b4     EC   Equipment Check (drive failure or recalibrate failed (retry))
 b5     SE   Seek End (Set if seek-command completed)
 b6,7   IC   Interrupt Code (0=OK, 1=aborted:readfail/OK if EN, 2=unknown cmd
             or senseint with no int occured, 3=aborted:disc removed etc.)

Status Register 1

 b0     MA   Missing Address Mark (Sector_ID or DAM not found)
 b1     NW   Not Writeable (tried to write/format disc with wprot_tab=on)
 b2     ND   No Data (Sector_ID not found, CRC fail in ID_field)
 b3,6   0    Not used
 b4     OR   Over Run (CPU too slow in execution-phase (ca. 26us/Byte))
 b5     DE   Data Error (CRC-fail in ID- or Data-Field)
 b7     EN   End of Track (set past most read/write commands) (see IC)

Status Register 2

 b0     MD   Missing Address Mark in Data Field (DAM not found)
 b1     BC   Bad Cylinder (read/programmed track-ID different and read-ID = FF)
 b2     SN   Scan Not Satisfied (no fitting sector found)
 b3     SH   Scan Equal Hit (equal)
 b4     WC   Wrong Cylinder (read/programmed track-ID different) (see b1)
 b5     DD   Data Error in Data Field (CRC-fail in data-field)
 b6     CM   Control Mark (read/scan command found sector with deleted DAM)
 b7     0    Not Used

Status Register 3

 b0,1   US   Unit Select (pin 28,29 of FDC)
 b2     HD   Head Address (pin 27 of FDC)
 b3     TS   Two Side (0=yes, 1=no (!))
 b4     T0   Track 0 (on track 0 we are)
 b5     RY   Ready (drive ready signal)
 b6     WP   Write Protected (write protected)
 b7     FT   Fault (if supported: 1=Drive failure)


Motor On/Off Flipflop

Writing 00h to Port FA7Eh turns all disk drive motors off, writing 01h turns all motors on. It is not possible to turn on/off the motor of a specific drive separately.

An exception are the Vortex F1-S, F1-D, M1-S and M1-D drives. (How are they different?)


Unconnected Pins

At the end of a successful read or write command, the program should send a Terminal Count (TC) signal to the FDC. However, in the CPC the TC pin isn't connected to the I/O bus, making it impossible for the program to confirm a correct operation. For that reason, the FDC will assume that the command has failed, and it'll return both Bit 6 in Status Register 0 and Bit 7 in Status Register 1 set. The program should ignore this error message.

The CPC doesn't support floppy DMA transfers, and the FDC's Interrupt signal isn't used in the CPC.

In the CPC the US1 signal of the FDC is not connected, making it impossible to select floppy drives 2 and 3. The floppy drives 0 and 1 are selected instead.


Ready / Disk Changed signal

This signal differs between floppy drives model:

  • For 3inch floppy drives (pin26), it is a "Ready" signal. The /RDY signal is sent whenever a disk is installed and rotating in the drive.
  • For 3.5inch floppy drives (pin34), it is a "Disk Changed" signal. The /DSKCHG signal determines whether the same disk loaded during the previous disk access is still in the drive.

The simplest solution to this issue is to just force the Ready signal on the cable itself. Note that the CPC will then hang if you type the CAT command when no disk is present (inserting a disk will unblock it).

Other solutions exist to Modify PC floppy drives to recreate a Ready signal. Also, Gotek drives (with a FlashFloppy or HxC firmware) can be configured to simulate the Ready signal.


Notes

Before accessing a disk you should issue a recalibrate command to the drive to move the head backwards until the track zero signal from the drive is sensed by the FDC. The FDC will also set its track counter for that drive to zero.

On an 80-track drive you may need to repeat that twice because some models of the FDC stop after 77 steps so if recalibrating from track 78 or above the controller might not reach track zero.

In order to format, read or write a sector on a specific track you must first seek that track using command 0Fh. That'll move the read/write head to the physical track number. If you don't do that then the FDC will attempt to read/write data from/to the current physical track, irrespective of the specified logical track ID.

The track, sector, and head IDs are logical IDs only. These logical IDs are defined when formatting the disk and aren't required to reflect the physical track, sector, or head numbers. However, when reading or writing a sector you must specify the same IDs that have been used during formatting.

Despite the name, a sector with a Deleted data Address Mark (DAM) is not deleted; the DAM-flag is just another ID bit. 'Deleted' sectors can be read/written just like normal data sectors and if that ID bit is specified correctly in the command.

Usually single sided 40-track 3" disk drives are used in CPCs. For practical purposes, 42 tracks could be used — the limit is specific to the drive and some support more tracks but 42 is a good maximum. The FDC controller can be used to control 80-tracks and/or double sided drives, though AMSDOS doesn't support such formats. AMSDOS supports a maximum of two disk drives only.


FDC Track Format

FDC765 Track Format.png


Internal details of the chip

  • From a comment in the hackaday website: "Internally this is a microcoded part with a primative controller of NEC’s own design. Testing microcode embedded in a part can be troublesome. The uPD765 had a few extra gates associated with the DMA Request and DMA Ack pins. Presenting a certain illegal combination here places the part into a “test” mode and allows the sequencer microcode to be output on the normal Data pins. The sequencer microcode is responsible for high level commands such as Read Track, Recalibrate, Format Track, or Write Data. There is a similar test mode for the nano-code array which serializes data at the floppy disk head."


FDC Block Diagram

FDC Intel 8272A block diagram.gif


Generic System Diagram

The Amstrad CPC and Amstrad Plus do not have a DMA controller associated with the FDC. The INT pin of the FDC is not connected either.

UPD765A System Diagram.png


PC to CPC floppy connector

Cpc6128floppytopcfloppy.gif


FDD Block Diagram

Floppy Disk Drive - Block Diagram.png


Datasheets


External links