Stuart Posted October 14, 2017 Share Posted October 14, 2017 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. 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? 11 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted October 18, 2017 Share Posted October 18, 2017 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.