Jump to content
IGNORED

TMS 9901 to IDE Interface


Stuart

Recommended Posts

This is a little project to implement an IDE interface through a TMS 9901 programmable systems interface IC, with the software to read and write to the IDE drive written in Cortex BASIC. At the moment there is no file system as such, it only reads and writes directly to sectors on the drive, so it is perhaps a solution looking for a problem - a pseudo-vintage data logger perhaps!

 

The design is based around my TMS 9900 PCB System (www.stuartconner.me.uk/tms9900_breadboard/tms9900_breadboard.htm) where the programmable pins on the 9901 can be easily accessed through two header connectors. The circuit diagram is shown below.

 

post-31406-0-76770800-1508022790_thumb.png

 

On the PCB, some of the 9901 pins are connected to pull-up resistors and some to pull-down resistors. When the 9901 is reset, all the pins are programmed as inputs, so their default logic state is determined by the pull-up/down resistors. When deciding how to connect the IDE interface, it is important that the active low control signals /RESET, /CS0, /READ and /WRITE are connected to pins on the 9901 that default to a high logic level such that the IDE drive defaults to an 'inactive' state. The eight data lines are connected to pins accessed through sequential CRU bits in the 9901 such that they can be set and read using multi-bit CRU instructions.

 

The project is primarily focussed on Compact Flash IDE drives which can be set to operate in an 8-bit mode - two 8-bit read/write operations take place for each 16-bit data transfer. Although the hardware is also compatible with hard drives, they do not support the 8-bit mode, which wastes half the data in each 512-byte sector. The 8-bit mode feature is selected on a Compact Flash drive by writing >01 to the Feature register (register 1) then the >EF 'Set Feature' command to the Command register (register 7).

 

As stated previously, when the 9901 is reset, all the pins are programmed as inputs. Writing to a pin programs it as an output, and it remains as an output until the 9901 is reset - either a hardware reset, or a software reset triggered by writing to a specific CRU bit. Therefore when reading a sector from the drive, the various registers on the drive are first programmed (by selecting a register on the 3-bit address bus then writing a value on the data bus), then the 9901 has to undergo a software reset such that the data bus pins can then be used as inputs to read the data from the sector selected on the drive.

 

The software does not do any 'drive busy' checks on the drive before performing operations. The couple of CF cards I have tried seem to have no problems keeping up with an elderly 3 MHz processor running a BASIC interpreter! Likewise there is no error detection - if it works it works, it if doesn't it doesn't!

 

The Cortex BASIC software listing is shown below, along with an example 'session' writing data from memory to a sector and reading the data back again. The program provides feedback on how the IDE drive registers are being programmed for each operation.

 100  REM TMS 9901 TO IDE INTERFACE
 110  REM BY STUART CONNER, OCTOBER 2017
 120  REM CORTEX BASIC
 130  REM
 140  REM **********************
 150  REM *** INITIALISE CRU ***
 160  REM **********************
 170  BASE 040H+(2*18)  !SET BASE ADDRESS TO CRU BIT 18 OF 9901
 180  REM
 190  REM ********************
 200  REM *** DISPLAY MENU ***
 210  REM ********************
 220  PRINT "SELECT FROM THE FOLLOWING OPTIONS:"
 230  PRINT "(1) WRITE A SECTOR WITH A SPECIFIED BYTE"
 240  PRINT "(2) WRITE A SECTOR WITH DATA FROM MEMORY"
 250  PRINT "(3) READ AND DISPLAY A SECTOR"
 260  PRINT "(9) QUIT"
 270  INPUT "OPTION",CH
 280  IF CH=1 OR CH=2 THEN GOTO 360
 290  IF CH=3 THEN GOTO 670
 300  IF CH=9 THEN END
 310  GOTO 270
 320  REM
 330  REM ********************
 340  REM *** WRITE SECTOR ***
 350  REM ********************
 360  INPUT "SECTOR ADDRESS",SA
 370  IF CH=1 THEN INPUT "BYTE TO WRITE",BYT
 380  IF CH=2 THEN INPUT "MEMORY ADDRESS TO START WRITING FROM",ADS
 390  GOSUB 1080  !RESET 9901
 400  GOSUB 1000  !RESET IDE DRIVE
 410  GOSUB 1470  !SET /CS0 LOW
 420  GOSUB 1660  !SELECT MASTER DRIVE
 430  GOSUB 1750  !SET 8-BIT MODE
 440  NS=1: GOSUB 1870  !SET NUM OF SECTORS TO TRANSFER
 450  GOSUB 1960  !SET SECTOR ADDRESS
 460  REG=7: GOSUB 1160  !SELECT REGISTER 7 TO WRITE COMMAND
 470  DAT=030H: GOSUB 1590  !SET DATA BUS FOR WRITE SECTOR COMMAND
 480  GOSUB 1280  !PULSE /WRITE LOW
 490  REG=0: GOSUB 1160  !SELECT REGISTER 0 TO WRITE DATA
 500  PRINT "WRITING SECTOR:"
 510  FOR I=1 TO 512/16
 520   FOR J=1 TO 16
 530    IF CH=1 THEN CRF[8]=BYT
 540    IF CH=2 THEN CRF[8]=MEM[ADS]: ADS=ADS+1
 550    GOSUB 1280  !PULSE /WRITE LOW
 560   NEXT J
 570   PRINT ".";
 580  NEXT I
 590  PRINT
 600  GOSUB 1530  !SET /CS0 HIGH
 610  PRINT
 620  GOTO 220
 630  REM
 640  REM *******************
 650  REM *** READ SECTOR ***
 660  REM *******************
 670  INPUT "SECTOR ADDRESS",SA
 680  GOSUB 1080  !RESET 9901
 690  GOSUB 1000  !RESET IDE DRIVE
 700  GOSUB 1470  !SET /CS0 LOW
 710  GOSUB 1660  !SELECT MASTER DRIVE
 720  GOSUB 1750  !SET 8-BIT MODE
 730  NS=1: GOSUB 1870  !SET NUM OF SECTORS TO TRANSFER
 740  GOSUB 1960  !SET SECTOR ADDRESS
 750  REG=7: GOSUB 1160  !SELECT REGISTER 7 TO WRITE COMMAND
 760  DAT=020H: GOSUB 1590  !SET DATA BUS FOR READ SECTOR COMMAND
 770  GOSUB 1280  !PULSE /WRITE LOW
 780  GOSUB 1530  !SET /CS0 HIGH
 790  GOSUB 1080  !RESET 9901 TO CHANGE DATA BUS TO INPUT
 800  GOSUB 1470  !SET /CS0 LOW AGAIN
 810  REG=0: GOSUB 1160  !SELECT REGISTER 0 TO READ DATA
 820  PRINT "READING SECTOR (ALL VALUES IN HEX):"
 830  FOR I=1 TO 512/16
 840   FOR J=1 TO 16
 850    GOSUB 1350  !SET /READ LOW
 860    BYT=CRF[8]
 870    GOSUB 1410  !SET /READ HIGH
 880    PRINT #;BYT;" ";
 890   NEXT J
 900   PRINT
 910  NEXT I
 920  PRINT
 930  GOSUB 1530  !SET /CS0 HIGH
 940  PRINT
 950  GOTO 220
 960  REM
 970  REM ***********************
 980  REM *** RESET IDE DRIVE ***
 990  REM ***********************
 1000  PRINT "RESETTING IDE DRIVE"
 1010  CRB[8]=0  !CRU BIT 26 (P0)
 1020  CRB[8]=1
 1030  RETURN
 1040  REM
 1050  REM ******************
 1060  REM *** RESET 9901 ***
 1070  REM ******************
 1080  PRINT "RESETTING TMS 9901"
 1090  CRB[-18]=1  !CRU BIT 0 (SET CLOCK MODE)
 1100  CRB[-3]=0  !CRU BIT 15 (/RST2)
 1110  RETURN
 1120  REM
 1130  REM ***********************************
 1140  REM *** WRITE REGISTER NUMBER (0-7) ***
 1150  REM ***********************************
 1160  PRINT "ADDRESSING REGISTER";REG
 1170  IF REG>=4 THEN CRB[10]=1: REG=REG-4  !CRU BIT 28 (P12)
 1180    ELSE CRB[10]=0
 1190  IF REG>=2 THEN CRB[9]=1: REG=REG-2  !CRU BIT 27 (P11)
 1200    ELSE CRB[9]=0
 1210  IF REG=1 THEN CRB[-2]=1  !CRU BIT 16 (P0)
 1220    ELSE CRB[-2]=0
 1230  RETURN
 1240  REM
 1250  REM ************************
 1260  REM *** PULSE /WRITE LOW ***
 1270  REM ************************
 1280  CRB[12]=0  !CRU BIT 30 (P14)
 1290  CRB[12]=1
 1300  RETURN
 1310  REM
 1320  REM *********************
 1330  REM *** SET /READ LOW ***
 1340  REM *********************
 1350  CRB[13]=0  !CRU BIT 31 (P15)
 1360  RETURN
 1370  REM
 1380  REM **********************
 1390  REM *** SET /READ HIGH ***
 1400  REM **********************
 1410  CRB[13]=1  !CRU BIT 31 (P15)
 1420  RETURN
 1430  REM
 1440  REM ********************
 1450  REM *** SET /CS0 LOW ***
 1460  REM ********************
 1470  CRB[11]=0  !CRU BIT 29 (P13)
 1480  RETURN
 1490  REM
 1500  REM *********************
 1510  REM *** SET /CS0 HIGH ***
 1520  REM *********************
 1530  CRB[11]=1  !CRU BIT 29 (P13)
 1540  RETURN
 1550  REM
 1560  REM ********************
 1570  REM *** SET DATA BUS ***
 1580  REM ********************
 1590  PRINT "SETTING DATA BUS TO";DAT;" (";#;DAT;"H)"
 1600  CRF[8]=DAT
 1610  RETURN
 1620  REM
 1630  REM ***************************
 1640  REM *** SELECT MASTER DRIVE ***
 1650  REM ***************************
 1660  PRINT "SELECTING MASTER DRIVE (REG 6 AND DATA)"
 1670  REG=6: GOSUB 1160  !SELECT REGISTER 6
 1680  DAT=0E0H: GOSUB 1590  !SET DATA BUS
 1690  GOSUB 1280  !PULSE /WRITE LOW
 1700  RETURN
 1710  REM
 1720  REM **********************
 1730  REM *** SET 8-BIT MODE ***
 1740  REM **********************
 1750  PRINT "SELECTING 8-BIT MODE (REG 1 AND DATA, REG 7 AND DATA)"
 1760  REG=1: GOSUB 1160  !SELECT REGISTER 1 TO SET FEATURE
 1770  DAT=01H: GOSUB 1590  !SET DATA BUS
 1780  GOSUB 1280  !PULSE /WRITE LOW
 1790  REG=7: GOSUB 1160  !SELECT REGISTER 7 TO WRITE COMMAND
 1800  DAT=0EFH: GOSUB 1590  !SET DATA BUS
 1810  GOSUB 1280  !PULSE /WRITE LOW
 1820  RETURN
 1830  REM
 1840  REM *****************************************
 1850  REM *** SET NUMBER OF SECTORS TO TRANSFER ***
 1860  REM *****************************************
 1870  PRINT "SETTING NUMBER OF SECTORS TO TRANSFER TO";NS;" (REG 2 AND DATA)"
 1880  REG=2: GOSUB 1160  !WRITE NUM OF SECTORS TO TRANSFER TO REGISTER 2
 1890  DAT=NS: GOSUB 1590  !SET DATA BUS
 1900  GOSUB 1280  !PULSE /WRITE LOW
 1910  RETURN
 1920  REM
 1930  REM *********************************************
 1940  REM *** SET SECTOR (LBA) ADDRESS (0 TO 32767) ***
 1950  REM *********************************************
 1960  PRINT "SETTING SECTOR ADDRESS TO";SA;" (REG 3 AND DATA, REG 4 AND DATA, REG 5 AND DATA)"
 1970  REG=3: GOSUB 1160  !WRITE SECTOR ADDRESS LBA 0 TO REGISTER 3
 1980  DAT=SA LAND 0FFH: GOSUB 1590  !SET DATA BUS
 1990  GOSUB 1280  !PULSE /WRITE LOW
 2000  REG=4: GOSUB 1160  !WRITE SECTOR ADDRESS LBA 1 TO REGISTER 4
 2010  DAT=SA/256 LAND 0FFH: GOSUB 1590  !SET DATA BUS
 2020  GOSUB 1280  !PULSE /WRITE LOW
 2030  REG=5: GOSUB 1160  !WRITE SECTOR ADDRESS LBA 2 TO REGISTER 5
 2040  DAT=0H: GOSUB 1590  !SET DATA BUS
 2050  GOSUB 1280  !PULSE /WRITE LOW
 2060  RETURN

Example:

SELECT FROM THE FOLLOWING OPTIONS:
(1) WRITE A SECTOR WITH A SPECIFIED BYTE
(2) WRITE A SECTOR WITH DATA FROM MEMORY
(3) READ AND DISPLAY A SECTOR
(9) QUIT
OPTION? 2
SECTOR ADDRESS? 10
MEMORY ADDRESS TO START WRITING FROM? 0
RESETTING TMS 9901
RESETTING IDE DRIVE
SELECTING MASTER DRIVE (REG 6 AND DATA)
ADDRESSING REGISTER 6
SETTING DATA BUS TO 224 (E0H)
SELECTING 8-BIT MODE (REG 1 AND DATA, REG 7 AND DATA)
ADDRESSING REGISTER 1
SETTING DATA BUS TO 1 (01H)
ADDRESSING REGISTER 7
SETTING DATA BUS TO 239 (EFH)
SETTING NUMBER OF SECTORS TO TRANSFER TO 1 (REG 2 AND DATA)
ADDRESSING REGISTER 2
SETTING DATA BUS TO 1 (01H)
SETTING SECTOR ADDRESS TO 10 (REG 3 AND DATA, REG 4 AND DATA, REG 5 AND DATA)
ADDRESSING REGISTER 3
SETTING DATA BUS TO 10 (0AH)
ADDRESSING REGISTER 4
SETTING DATA BUS TO 0 (00H)
ADDRESSING REGISTER 5
SETTING DATA BUS TO 0 (00H)
ADDRESSING REGISTER 7
SETTING DATA BUS TO 48 (30H)
ADDRESSING REGISTER 0
WRITING SECTOR:
................................

SELECT FROM THE FOLLOWING OPTIONS:
(1) WRITE A SECTOR WITH A SPECIFIED BYTE
(2) WRITE A SECTOR WITH DATA FROM MEMORY
(3) READ AND DISPLAY A SECTOR
(9) QUIT
OPTION? 3
SECTOR ADDRESS? 10
RESETTING TMS 9901
RESETTING IDE DRIVE
SELECTING MASTER DRIVE (REG 6 AND DATA)
ADDRESSING REGISTER 6
SETTING DATA BUS TO 224 (E0H)
SELECTING 8-BIT MODE (REG 1 AND DATA, REG 7 AND DATA)
ADDRESSING REGISTER 1
SETTING DATA BUS TO 1 (01H)
ADDRESSING REGISTER 7
SETTING DATA BUS TO 239 (EFH)
SETTING NUMBER OF SECTORS TO TRANSFER TO 1 (REG 2 AND DATA)
ADDRESSING REGISTER 2
SETTING DATA BUS TO 1 (01H)
SETTING SECTOR ADDRESS TO 10 (REG 3 AND DATA, REG 4 AND DATA, REG 5 AND DATA)
ADDRESSING REGISTER 3
SETTING DATA BUS TO 10 (0AH)
ADDRESSING REGISTER 4
SETTING DATA BUS TO 0 (00H)
ADDRESSING REGISTER 5
SETTING DATA BUS TO 0 (00H)
ADDRESSING REGISTER 7
SETTING DATA BUS TO 32 (20H)
RESETTING TMS 9901
ADDRESSING REGISTER 0
READING SECTOR (ALL VALUES IN HEX):
FF B0 01 38 80 40 80 00 80 40 80 04 80 40 80 08
80 40 80 0C 80 60 80 10 80 60 80 14 80 60 80 18
80 60 80 1C 80 80 80 20 80 80 80 24 80 80 80 28
80 80 80 2C 80 A0 80 30 80 A0 80 34 80 A0 80 38
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
FF D4 05 C4 FF D4 05 62 FF D4 05 CE FF BA 04 F6
FF C6 01 BC FF C6 01 A0 FF D4 04 FC FF B0 06 10
02 E0 FF B0 04 C1 02 02 FF FC CC B1 02 01 05 FA
CC 81 02 09 00 80 02 0C 00 00 C8 0C FF DE 2F A0
01 E1 04 C0 04 C3 02 08 00 01 2E C5 2F A0 01 DA
06 A0 00 EA 42 01 06 04 43 03 06 2E 45 00 05 F8
46 07 08 9E 48 03 08 CE 4C 00 07 20 4D 03 05 04
4E 03 08 E8 4F 00 09 96 52 00 06 E8 57 01 06 7A
3F 00 08 E2 00 00 02 2B 00 03 C2 9B 13 1F 91 7B
16 FA D1 BB C2 DB 09 86 02 07 FF B0 09 16 17 0D
2E 44 01 12 01 26 CD C4 05 83 02 85 0D 00 13 05
10 F5 05 C7 02 85 0D 00 16 F7 04 5B 04 C0 10 08
02 00 00 01 10 05 02 00 00 02 10 02 02 00 00 04
2F A0 01 CE 2E 00 10 A4 02 0C FF F4 04 FC 07 3C
04 FC 04 DC 02 0C 00 00 C8 0C FF DE 1D 1F 32 20
02 5F 1E 0D 04 C3 02 07 01 7C 10 0B 1F 0F 13 FE
05 83 1F 0F 16 FD 02 07 01 7A 8D C3 12 02 05 C7
10 FC 33 17 04 60 0A 50 10 83 00 07 00 1A 00 0E
00 34 00 1D 00 68 00 3B 00 D0 00 75 01 A0 00 EA
03 40 02 46 04 D0 7F FF 06 38 61 00 7A 00 E0 00
1F 15 16 FE 04 DB 36 1B 1E 12 88 1B 01 9A 1A 05
88 1B 01 9C 1B 02 A6 E0 01 9E 03 80 1D 10 1F 16
16 FE 32 1B 1F 16 16 FE 1F 17 16 FC 03 80 0D 0A
45 52 52 4F 52 20 00 20 20 20 20 00 0D 0A 42 50
00 0D 0A 3F 3E 00 0D 0A 54 49 42 55 47 20 52 45
56 2E 42 20 28 63 6F 6D 6D 73 20 31 39 32 30 30


SELECT FROM THE FOLLOWING OPTIONS:
(1) WRITE A SECTOR WITH A SPECIFIED BYTE
(2) WRITE A SECTOR WITH DATA FROM MEMORY
(3) READ AND DISPLAY A SECTOR
(9) QUIT
OPTION?
  • Like 11
Link to comment
Share on other sites

Sounds perfect for implementing a Forth BLOCK system.

Once you have that it is possible to create a simple file system relatively easily.

Something like TI-99 file system functionality would not be too difficult. (?) (never did it so normal warnings apply)

 

Or you could take some ideas from here: http://www.forthos.org/fs.html

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...