FAT16 IDE Interface
SPI-IDE Interface prototype
This project was created to provide a simple command-driven interface to an IDE device that supports the FAT16 file structure. I specifically had Compact Flash (CF) media in mind as it can be powered from 5v and accessed as an IDE device. By using the FAT16 file structure, I can move the CF media between this adapter and a PC using a readily available USB flash memory reader. In this way, I can easily move program and data files between the HOST system and a PC for easy processing and storage.
A User Manual and support files are available here ->FAT16 IDE
Communication with the host is through a standard SPI interface. The design could be easily reconfigured to provide RS-232 or parallel interfaces as well.
The FAT16 driver supports 16 open files at a time. Files can be opened for READ, WRITE, or APPEND. Data can be read sequentially or you can set the file pointer to absolute or relative locations within the file. You pass the amount of bytes to read or write with each instruction.
File names are limited to the DOS 8.3 naming conventions. When moving through a directory tree, you can only move one level at a time. The exception is you can move to the ROOT directory at any time by using the "/" parameter. To move back one level, you use the ".." parameter. You can rename files, directories, and the volume label.
The HIDDEN and SYSTEM attributes are ignored in this implimetation. They will be maintained if already set by another source. The READ ONLY attribute is implimented and will prevent a file or directory from being erased or modified. Use the PROTECT and UNPROTECT commands to change this attribute. The ERASE ALL command will erase all files and empty directories in the current directory INCLUDING those marked READ ONLY. Therefore, this command must be used carefully.
The onboard DS1302 provides a real-time clock for date stamping of files. You can set and retrieve the current date and time from the HOST. If you do not install the DS1302, the firmware will return a default value, or the value you enter using the Set date/time function.
The FORMAT command will format the device with 1 partition using one FAT table. A maximum size of 2GB is supported. The interface cannot read secondary partions if they exist on the device. You may put two devices in the IDE connector and use the MASTER/SLAVE jumpers to have two drives available. However, only one drive can be accessed at a time. You need to re-initialize the interface to switch drives. Lastly, there is also support for RAW sector access for those not interested in using the FAT16 support. You may read and write 512-byte blocks to any sector on the drive. Care must be taken with FAT16-formatted drives if RAW commands are used or the file structure may become corrupt and unaccessible.
Here are the commands used to access the media from the Host:
HEX Command 00 reserved (null character) 01-1F reserved for returned error codes C0 Close all files C1 list directory C2 make directory C3 change directory C4 erase file/directory C5 erase all files and empty directories in current directory C6 protect file (read only attribute) C7 unprotect file (read only attribute) C8 rename file/directory/vol label C9 open File CA Read File CB Write File CC Set pointer CD Get pointer CE Close File CF Test if File Exists D0 File Size D1 Read Sector (Direct access mode) D2 Write Sector (Direct access mode) E0 list date/time E1 set date/time E2 get rtc reg F0 list volume label F1 list free space F2 format drive F3 list drive info F4 Mount drive (and Initialize FAT file System)The SPI communications channel is configures as a slave device. The Slave requires a minimum of 1.75uS to complete each SPI transaction. Read the status to ensure the slave is ready for your request. The host accesses the slave using these routines:
IDEStat - Returns the current status of the SPI Slave device SendIDECmd - Sends a 1-byte command to the slave SendIDE - sends 1 data byte to the slave RxIDE - gets 1 byte of data from the slaveThe IDEStat routine returns the status back to the Host using 1 byte:
Bit 7 - Ready for Command if 1 Bit 6 - Data Ready to send to the Host when 1 Bit 5 - Ready to receive data from the host when 0 bit 4-0 contain a binary error code. These are the error codes: 00000 - 00 - No Error 00001 - 01 - ATA init error 00010 - 02 - missing file name 00011 - 03 - Format error 00100 - 04 - File not found 00101 - 05 - Read Only File 00110 - 06 - invalid file type/open error 00111 - 07 - unable to erase all files 01000 - 08 - file not open 01001 - 09 - file already open in another handle 01010 - 0A - write protected 01011 - 0B - disk full 01100 - 0C - root directory full 01101 - 0D - invalid command 01110 - 0E - Handle in use 01111 - 0F - read past EOF 10000 - 10 - File too large > 2^32 10001 - 11 - Cluster size too big
Here are the 65C02/65816 routines:
SPIPort = $01 ; bit address of Slave on SPI slave select register ; ; Send Command to IDE ; SendIDECmd pha SendIDECmd1 jsr IdeStat and #$A0 cmp #$80 bne SendIDeCmd1 bra SendIde1 ; ; Send data (in A) to IDE Slave ; SendIDE pha SendIDE0 jsr IdeStat ; get status and #$20 ; IDE ready for command and ready to receive data bne SendIDE0 ; not ready, check status again SendIDE1 lda #SPIPort ; trb SPISSR ; select device lda #$01 ; send data sta spidr ; SendIDE4 lda SPISR bpl SendIDE4 ; wait for tx to end nop nop nop nop ; wait for SPI to be ready lda spidr ; clr flags pla ; send data byte sta spidr ; start shift SendIDE5 lda SPISR bpl SendIDE5 ; wait for tx to end lda spidr ; clr SPI flag lda #SPIPort ; tsb SPISSR ; Deselect device rts ; ; Get Char from IDE ; RxIde jsr IdeStat and #$40 ; IDE data ready to send beq RxIDE ; not ready, check status again lda #SPIPort ; trb SPISSR ; select device lda #$03 ; send data sta spidr ; RxIDE4 lda SPISR bpl RxIDE4 ; wait for tx to end nop nop nop nop ; wait for SPI to be ready lda spidr ; clr flags lda #$00 ; send null sta spidr ; start shift RXIDE5 lda SPISR bpl RxIDE5 ; wait for tx to end lda spidr ; get received data pha ; save it lda #SPIPort ; tsb SPISSR ; Deselect device pla ; restore data rts ; ; Read IDE status ; IdeStat lda #SPIPort ; trb SPISSR ; select device lda spidr ; clr flags lda #$02 ; get status sta spidr ; IdeStat1 lda SPISR bpl IdeStat1 ; wait for tx to end nop nop nop nop ; wait for SPI to be ready lda spidr ; clr flags lda #$00 ; null sta spidr ; start shift IdeStat2 lda SPISR bpl IdeStat2 ; wait for tx to end lda spidr ; get STATUS pha lda #SPIPort ; tsb SPISSR ; Deselect device pla ; restore data rtsHere is a conceptual picture of the production board. It is very simple.
Here is the schematic:
Here is the PCB trace layout:
Here is the parts list:
Part Description Digikey Part # ------------------------------------------------- C1 .1uF ceramic cap BC1160CT-ND IC1 Atmel ATMega324P-20PU ATMEGA324P-20PU-ND J1 SPI Port 2x5 header * Note 1 J2 IDE port 2x20 header * Note 1 J4 Host +5v 1x2 header * Note 2 OSC-1 20.0 MHz TTL Osc X964-ND Jumper jumper block S9000-ND for J4,J5,J7 if needed (Optional components - see text) B1 3V CR2032 P189-ND C2 220uF Electrolytic Cap 493-1492-ND C3 220uF Electrolytic Cap 493-1492-ND IC2 DS1302 Real Time Clock DS1302+-ND IC3 LM7805 5v Regualtor 497-1443-5-ND J3 Ext +5v * Note 3 J5 Socket +5v 1x2 header * Note 2 J6 Ext 9-12v * Note 3 J7 Host 9-12v 1x2 header * Note 2 LED1 Red T1-3/4 Led with 516-1339-ND internal current-limiting resistor X1 32.768 khz crystal 300-8301-ND Battery holder BH32T-C-ND Note 1 - order one 1SAM1028-36-ND for J1 and J2 break off appropriate number if pins for each Note 2 - order one TSW-106-07-L-S-ND for J4,J5, and J6 break into three 1x2 headers. Note 3 - solder wire to the pads from external connectors All parts are available from Digikey.com A printed circuit board and programmed ATmega324P are available from the author for $32 plus shipping. Inexpensive IDE-CF adapters are available from places like Amazon, Ebay, and geeks.com.