;************* readme for Compact Flash driver for AVR  ********
;
; File Name		:"Readme.txt"
; Date			: 27-01-2001
; Version		: 1.3
; Author		: Loek Gijben
; Contact               : L.H.Gijben@Flatnet.TUDelft.nl
;
; This source code consists of two files: 
; An include file, CFdriver.inc, in which ports, pins and registers 
; are named and defined. And a code file, CFdriver.asm.
; Although the asm-file is extensively commented a lot of the info
; is put into this readme file. 
;***************************************************************


;***************************************************************
; This is a fairly comprehensive explanation of the workings and
; some rationale behind it.
; This is a bare bones driver for communication with Compact-Flash
; memory cards, also applicable to some types of PC-Card type I and 
; type II Flash disks
; It uses the CF-ATA specifications, in particular the memory 
; mapped mode. Do not expect it to work with ordinary harddisks,
; CD-Roms and the like.
; Maybe PC-card devices or microdrives will work with a little 
; tweaking, consult the appropriate device manual for that.
;
; For implementing a filesystem like FAT you are on your own. We *do*
; have our own FAT16 implementation but as it is so basic, reduced to
; our very limited needs, you will almost certainly have no use for it.
;
; This driver works with AVRASM, other assemblers unknown (please
; send feedback). Code may probably be optimized with IAR or so.
;
; Finally: this driver code is given to the public domain. Our 
; interests in this lie in the fact that popularizing CF will benefit
; our application too :^)
; Feel free to improve or alter this in any way you like, as long as 
; you satisfy my vanity by mentioning my name in your source code, 
; like "Based on/parts of blabla..the basic CF driver by Loek Gijben" 
; Feedback is very welcome, but I urge you to read the Sandisk 
; manuals first...
;***************************************************************

;********** revision history  **********************************
; 0.1 02-02-2000	Failed attempt to use STK300 memory expansion
;			(now know 3 reasons why...)
; 0.8 10-05-2000	Reading ATA regs works, Writing to no avail
; 0.9 15-05-2000	Sloooow bidirectional communication
; 1.0 01-06-2000	Optimized to 400KB/s
; 1.1 13-10-2000	Translated into English, divided in .asm and .inc
; 1.2 13-11-2000	Cleaned up code, made public
; 1.3 27-01-2001	Debugged and published
;***************************************************************

;*********Ports and pins lay-out *******************************
;
;          (some pins of) ATMega603/103
; SIGNAL_NAME             _____________      SIGNAL_NAME
;      .                 |             |          .
;   ATA_D0   <->  PA0  --| 51        2 |--   PE0 (RxD)   --> ATA_A0
;   ATA_D1   <->  PA1  --| 36        3 |--   PE1 (TxD)   --> ATA_A1
;   ATA_D2   <->  PA2  --| 37        4 |--   PE2 (AC+)   --> ATA_A2
;   ATA_D3   <->  PA3  --| 38        5 |--   PE3 (AC-)   --> ATA_A3
;   ATA_D4   <->  PA4  --| 39        6 |--   PE4 (Int4)  <-- CF_RDYBSY
;   ATA_D5   <->  PA5  --| 40        7 |--   PE5 (Int5)  --> CF_notRd
;   ATA_D6   <->  PA6  --| 41        8 |--   PE6 (Int6)  --> CF_notWr 
;   ATA_D7   <->  PA7  --| 42        9 |--   PE7 (Int7)  --> CF_notCE
; 
; You might use another port than PortE, like B,D or a combination of C and F.
; So whenever furtheron is referred to "PortE" please replace it for your
; port of choice. 
; With this PortE be careful when you also use alternate functions (like in this
; case the UART, comparator and/or the higher external interrupts).
; Datadirection for PortE is fixed, make sure when you do an OUT on PortC that
; PortE 4 always stays 0 (input pin = high impedance, tristate), else you
; needlessly drain/source the totempole on the RDY/BSY pin of the CF.
;
;
;       Pin connections Compact-Flash connector
;    SIGNAL_NAME        ______        SIGNAL_NAME
;       Gnd ---  GND --| 1  26|-- -CD1    --- nc
;    ATA_D3 <->  D03 --| 2  27|--  D11    --- nc
;    ATA_D4 <->  D04 --| 3  28|--  D12    --- nc
;    ATA_D5 <->  D05 --| 4  29|--  D13    --- nc
;    ATA_D6 <->  D06 --| 5  30|--  D14    --- nc
;    ATA_D7 <->  D07 --| 6  31|--  D15    --- nc
;  CF_notCE --> -CE1 --| 7  32|-- -CE2    --- VCC
;       Gnd ---  A10 --| 8  33|-- -VS1    --- nc
;  CF_notRd --> -OE  --| 9  34|-- -IORD   --- VCC    
;       Gnd ---  A09 --|10  35|-- -IOWR   --- VCC
;       Gnd ---  A08 --|11  36|-- -WE     <-- CF_notWr
;       Gnd ---  A07 --|12  37|--  RDY/BSY--> CF_RDYBSY
;       VCC ---  VCC --|13  38|--  VCC    --- VCC
;       Gnd ---  A06 --|14  39|-- -CSEL   --- Gnd
;       Gnd ---  A05 --|15  40|-- -VS2    --- nc
;       Gnd ---  A04 --|16  41|--  RESET  --- Gnd
;    ATA_A3 -->  A03 --|17  42|-- -WAIT   --- nc
;    ATA_A2 -->  A02 --|18  43|-- -INPACK --- nc
;    ATA_A1 -->  A01 --|19  44|-- -REG    --- VCC
;    ATA_A0 -->  A00 --|20  45|--  BVD2   --- nc
;    ATA_D0 <->  D00 --|21  46|--  BVD1   --- nc
;    ATA_D1 <->  D01 --|22  47|--  D08    --- nc
;    ATA_D2 <->  D02 --|23  48|--  D09    --- nc
;        nc ---  WP  --|24  49|--  D10    --- nc
;        nc --- -CD2 --|25  50|--  GND    --- Gnd
;                      |______|
;                   50 pins header
;
; According to a spokesman of Sandisk the Wait signal will no longer
; be used in future CF implementations. He wrote that all that is 
; needed to put or get a byte to/from a CF is setting up an address 
; and Chip Enable the flash, which may be done concurrently, and strobe 
; out/in with -WE/-OE (on rising flank).
; After a command the CF may be busy for up to 20ms. You must wait for the
; ready signal before you can go on. A software replacement for pin 37 may be 
; implemented by polling the CF status register (or you can always do dead 
; reckoning: build in a 20ms delay after each command...)
; In this particular driver it is handy that CF_RDYBSY is also configurable as
; external interrupt 4. So interrupt driven waiting for RDY/BSY comes in mind...
;***************************************************************

;************* Timing issues ***********************************
; Timing diagrams are available in the CF-ATA specifications. These are free to 
; download from http://www.compactflash.org after registration. Another very
; good source is Sandisk corporation: http://www.sandisk.com/cons/prod_lit.htm
; register free for OEM manuals.
; Two simplified ASCII art versions are given below. 
; Read timings diagram:                                  
;                  ____ _____________________________ ______________
; ATA A0-A4 Setup  ____X|____________________________X______________
;                       |                  ->| th(A) |<- 
;                     ->|tsu(A)|<-         ->| th(CE)|<-
;                  ____ |      |             |       |______________
; -CE              ____\|______|_____________|_______/______________
;                       |    ->| ta(OE) |<-  |          
;                  _____|______|        |    |______________________ 
; -OE                          \________|____/
;                       |      |        |    |<- tdis(OE) ->|
;                       |      |        |___________________|    
; Dout             --------------------<|___________________|>------
;
; Write timings diagram:                                  
:                  ____ _____________________________ ______________
; ATA A0-A4 Setup  ____X|____________________________X______________
;                       |                  ->|       |<- trec(WE)
;                     ->|tsu(A)|<-         ->| th(CE)|<-
;                  ____ |      |             |       |______________
; -CE              ____\|______|_____________|_______/______________
;                       |      |<- tw(WE)  ->|          
;                  _____|______|             |______________________ 
; -WR                          \_____________/
;                       |      |      ->|    |<- tsu(D-WEH)
;                       |      |        |____|______________|    
; Din              --------------------<|____|______________|>------
;                                            |<- th(D) ---->|
; tsu(A)     30ns Address setup time minimum
; ta(OE)    125ns Output Enable Access time maximum
; th(A)      20ns Address Hold Time minimum
; th(CE)     20ns CE Hold following CE
; tdis(OE)  100ns Output Disable Time from OE
; tw(WE)    150ns WE Pulse Width
; trec(WE)   30ns Write Recovery Time
; tsu(D-WEH) 80ns Data Setup before WE
; th(D)      30ns Data Hold following WE 
; tw(WT)    350ns Wait Width Time (not shown on diagrams)
;
; Implications for a read cycle: After setting up ATAaddress + -CE we need
; at least 30ns before -OE. Won't hurt until we use a 33MHz AVR ;^)
; Also the -OE strobe must be at least 125ns, which yield an 8MHz clock.
; Future CF designs are prognosed to be quite a bit faster than that.
; After deasserting -OE data is still valid on the bus for *at least* 100ns
; (in fact, with high impedance on all sides of the bus it is much longer).  
; Finally the -OE cycle to cycle time is at least 350ns, this implicates
; a minimum read cycle algorithm length.
;
; Implications for a Write cycle: Data may be set up on the bus up front.
; Then 30ns after ATAaddress and -CE are set up the Write strobe may be
; engaged, which must be hold for 150ns implicating a maximum clock of 6.6MHz
; Faster than that requires a wait state.
;***************************************************************

;*********ATA registers & Commands *****************************
;
;	#	READ 		WRITE
;     ________________________________________	
;	0 	Read Data 	Write Data
;	1 	Error 		Features
;	2 	Sector Count 	Sector Count
;	3 	LBA  7-0	LBA 7-0
;	4 	LBA 15-8 	LBA 15-8
;	5 	LBA 23-16	LBA 23-16
;	6 	LBA 27-24 	LBA 27-24
;	7 	Status 		Command
;	E	Alt Status	Device Ctl
;
; Alternative descriptions for 3-6 (C/H/S addressing) are available
; but there's no point in using that when LBA is possible, is there?
; Sector reads or -writes need a setup of Sector Count and LBA
; registers first, then issue the read/write command.
; 
; ATA Commands used in this driver are:
; $E5	; Execute drive diagnostics
; $50	; Format Track (relates to format sector(s) in LBA mode)
; $EC	; Identify drive
; $E0	; Sleep (let little machine rest on tiny pillow :^)	
; $20	; Read sector(s)
; $30	; Write sector(s) 
; 
; Other useful commands may be easy to implement at your choice 
;
; After commands that involve reading/writing sectors the CF expects
; the dataregister to be read/written 512 times. And that a number of
; times set in the <Sector Count> register. So if you set the 
; Sector Count on eight the CF expects you to clock in/out 4kB.
; (hint: clustersize in FAT filesystem) 
;***************************************************************

;***************************************************************
; This driver uses two registers for the ATAdata and ATAaddress. 
; Also five general purpuse registers are needed for temporary storage. You 
; may change this to other registers to suit your needs, but if you decide
; to use lower 16 registers then replace "ldi reg, value" with 
; "ldi higherreg, value
;  mov reg, higherreg"
; Furthermore, for the sector transfers indirect addressing via 
; the X-register is being used, and this requires a 
; block of 512 contiguous bytes in (X)SRAM to transfer to/from. 
; You may change the X register to Y or Z for indirect addressing. Please do a
; search and replace then for XL, XH and X+ in CFdriver.asm
;***************************************************************

;***************************************************************
; The actual loop for clocking in/out one sector of 512 bytes is
; rolled out. Each rcall for a subroutine need 7 clockcycles, so
; with a rolled out loop we can decrease overhead. 
; Drawback is that binary code gets bigger, and in this case even 
; to an extend that conditional branches cannot reach their 
; destination (i.e. further than 64 bytes away).
; Like with "brne destination" and destination is too far away. 
; You'll notice a workaround in the code in the form:
; -	brne Jumpto_destination
; -	.
; -	.
; - Jumpto_destination: jmp destination
; If you roll the loop back in you might get rid of this construction.
;***************************************************************

;***************************************************************
; Because I only have a STK300 development kit, with an onboard
; ATMega103L, this is the only controller on which it is tested.
; I make use of ATmega commodities like plenty of Ports, RAM and 
; codespace. 
; Requirements are:
; - 7 general purpose registers.
; - Use of either X, Y or Z register for indirect SRAM addressing.
; - A contiguous block of 512 bytes (external)memory to transfer a 
;   sector to or from.
; - One IO capable port
; - Additional 7 output pins and one (optional) input pin, preferably 
;   combined in one port.
; No EEPROM, or timer/counters are used.
; 
; Also I work with plain vanilla AVRASM32.EXE, I guess this is not 
; the most optimal assembler, but I expect code for it to work 
; everywhere. The code looks good in AVR studio but you may need to 
; tweak the tab settings in your editor.
; Because assembler is not very handy for all kind of bookkeeping
; tasks like maintaining a filesystem or all kinds of error detection
; there are no provisions for it. Better do that in C, Pascal, Basic
; and so Forth...  
; 
; A CF (Compact-Flash) may be addressed in various modes, one of 
; them being memory mapped mode. This mode is the easiest to imple-
; ment, straightforward, at the cost of not being compatible with
; ATA interfaces for other devices like CD-ROM etc.
; Having a STK300 with a "memory expansion" connector my first 
; attempt was to let the CF act as some sort of XSRAM (with a15 for
; Chip Enable the flash). Albeit possible in theory, I ran into 
; difficulties with buscontention on PortA, timing problems with 
; read and write strobes, and a lot of problems trying to use both
; external SRAM and CF on the memory expansion connector.
; Anyone who wants to take a better shot at this one is invited to
; do so.
; My second try was to do all signals and buses "by hand". It gave
; a lot of control over the system, and to my surprise it was not 
; slower; a byte transfer to/from SRAM in five clockcycles = 800kB/s
; on my 4MHz Atmega.
; This driver uses 8bit communication, but if you have a port on 
; your controller to spare you can expand it to 16 bit datatransfer
; with some work, making it up to 30% faster.
; 
; This driver is optimized for speed as it has a twofold advantage:
; 1) It will return to the main program within a ms
; 2) A CF still consumes 100-200 mW while active, the faster the 
;    transfers go the shorter the dutycycle can be. For 128kb/s 
;    average throughput the dutycycle can be as low as 2% -> 2-4mW!
; 
; The ports you use for this driver will generally depend on the 
; peripherals you use. If you have two committed IO ports to spare for
; this driver then you can throw away some of the code that is 
; used to prevent collisions with peripherals. For instance, If you 
; don't use PortA as a CF databus then you don't have to switch on/off 
; SRE in MCUCR all the time when you tranfer to/from XSRAM.
; 
; My effort was to make it as hardware independent as possible. There-
; fore all port- and pin names (except X register) are set in 
; CFdriver.inc, so your first step is to adjust this one to your needs.
; If you have your system working just do a search and replace for
; the actual pin & portnames you use, and you end up with a pretty 
; good readable code for your system. Don't forget that all comments 
; are regarding to PortA as ATAdataPort and PortE as 
; ATAaddressPort/CF_RDYBSYPort, so you will have to change the comments
; too to keep it readable.
; 
; Thank you for reading this all to the bottom. Please do the same
; with all the comments in the code.
; 
; January 2001
; Loek Gijben
; "If you just go on long enough infinity will loose it's meaning"
; 
; PS.  I'm not a programmer. This evolved out of necessity.
; PSS. As the famous Mr. Marc Lalonde I'm not a native English speaker.
;      So you are invited to help me out on misspellings and other
;      unintentional "flowers of speech" ;^))

;**** end of readme.txt ******************************************
