Code:
; CF-Register addresses
.equ Data_Reg = &H00
.equ Error_Reg = &H01
.equ Feature_Reg = &H01
.equ Sec_Cnt_Reg = &H02
.equ Sec_Num_Reg = &H03
.equ Cyl_Lo_Reg = &H04
.equ Cyl_Hi_Reg = &H05
.equ Head_Reg = &H06
.equ Status_Reg = &H07
.equ Command_Reg = &H07
; Commands for Compact Flash Card
.equ CF_Identify = &HEC
.equ CF_Write_Sec = &H30
.equ CF_Read_Sec = &H20
;------------------------------------------------------------------------------
[_DriveGetIdentity]
$EXTERNAL _CF_Write_Reg
; Read Identity Info from the CF-Card
_DriveGetIdentity:
ldi r21, 1 ; 512 Bytes = 1 Sector to read
ldi r23, CF_Identify ; Command for Card identity
rcall _CF_Write_CommandReg ; send to card
rjmp _CF_Read_Sector_LBASet ; Read Info to SRAM (mit return)
[End]
[_CF_Check_Ready]
; Pin CF_Rdy is Low at Ready
_CF_Check_Ready:
* sbis CF_Control_In , CF_Rdy ; no timeout check
rjmp _CF_Check_Ready
Ret
[END]
[_CF_Write]
$EXTERNAL _CF_Check_Ready
; give a pulse to WE to force Compactflash Card to read Data
; Registeraddress (A0-A2) and Data (D0-D7) must be set
_CF_Write:
rcall _CF_Check_ready
* cbi CF_Control_Out , CF_WE ; WE Line to Low
; Pulse is for Crystal 16 MHz, Approximitly 1 NOP for 2 MHz
; and can be reduced for slower CPU
nop
nop
nop
* #IF _XTAL > 6000000
nop
nop
nop
* #ENDIF
* #IF _XTAL > 12000000
nop
nop
* #ENDIF
* sbi CF_Control_Out , CF_WE ; WE Line to High
ret
[END]
[_CF_Read]
$EXTERNAL _CF_Check_Ready
; Read 1 Byte from the CF
; Register address must be set.
_CF_Read:
rcall _CF_Check_Ready
ldi _temp1, &H00 ; change data-port to Input
* out Cf_Data_DDR , _temp1
* cbi CF_Control_out , CF_OE ; OE Line to Low
nop
nop
nop
* #IF _XTAL > 6000000
nop
nop
nop
* #ENDIF
* #IF _XTAL > 12000000
nop
nop
* #ENDIF
* in r23 , CF_Data_in ; Read Byte
* sbi CF_Control_Out , CF_OE ; OE - Line to High
ldi _temp1, &HFF ; change Data-port back to OUTPUT
* out CF_Data_DDR , _temp1
ret
[END]
[_CF_Set_RegAddr]
; Set register address, and leave pins 3 - 7 unchanged
; two entry-points to routine
; 1: CF_Set_RegAddr: Register address must passed in r22
; 2: CF_Set_RegAddr23: register address is Data
_CF_Set_RegAddr23:
ldi r22, Data_Reg
_CF_Set_RegAddr:
* in _temp1 , CF_Addr_Out ; get current output at Port
andi _temp1, &B11111000 ; CF-Address-bits masked out
or _temp1, r22 ; add CF-Address with OR
* out CF_Addr_Out , _temp1
ret
[End]
[_DriveReadSector]
$EXTERNAL _CF_Set_CntLBA , _CF_Write_Reg , _CF_Read
; Read Sector(s) from CF-Card to SRAM
; Entry with following parameters set:
; Register r21: Count of Sector(s) to transfer
; Register X: Pointer to Sectornumber (LONG)
; Register Z: SRAM-Address, where the data to transfer
_DriveReadSector:
ldi r21, 1 ; fixed to 1 sector to read
rcall _CF_Set_CntLBA ; LBA-Sector to CF
ldi r23, CF_Read_Sec ; read command
rcall _CF_Write_CommandReg ; to Compactflash
_CF_Read_Sector_LBASet:
rcall _CF_Set_RegAddr23 ; turn register-address to data
clr r20 ; Low-Byte of Byte-Count always zero
lsl r21 ; Change Sector-Count to HighByte of Transferlenght
_CF_Read_Sector1:
rcall _CF_Read ; read 1 Byte
st z+, r23
dec r20
brne _CF_READ_SECTOR1
dec r21
brne _CF_READ_SECTOR1 ; all bytes read?
clr r25 ; set default no error
clc
Ret
[END]
[_DriveWriteSector]
$EXTERNAL _CF_Set_CntLBA , _CF_Write_Reg
; write Sector(s) to CF-Card
; Entry with following parameter set:
; Register r21: Count of sector(s) to transfer
; Register X: Pointer to Sectornumber (LONG)
; Register Z: SRAM-Address, at which Data to transfer starts
_DriveWriteSector:
ldi r21, 1 ; fixed to 1 sector to write
rcall _CF_Set_CntLBA ; LBA-Sector to CF
ldi r23, CF_Write_Sec ; write command
rcall _CF_Write_CommandReg ; to compactflash
_CF_Write_Sector_LBASet:
rcall _CF_Set_RegAddr23 ; turn register-address to data
clr r20 ; Low-Byte of Byte-Count alwas zero
lsl r21 ; Change Sector-Count to HighByte of Transferlenght
_CF_Write_Sector1:
ld r23, z+
* out CF_Data_out , r23 ; Byte to data port
rcall _CF_Write ; force CF to read byte
dec r20
brne _CF_Write_SECTOR1
dec r21
brne _CF_Write_SECTOR1 ; last byte written?
clr r25 ; set default no error
clc
Ret
[END]
[_CF_Write_Reg]
$EXTERNAL _CF_Set_RegAddr , _CF_Write
;------------------------------------------------------------------------------
; write a value to a specified register address, value is passed in r23
; two different entry points
; 1: CF_Write_CommandReg: write value to command-register (default)
; 2: CF_Write_Reg: Register passed in r22
_CF_Write_CommandReg:
ldi r22, Command_Reg ; Default register: Command
_CF_Write_Reg:
* out CF_Data_out , r23 ; set data to data port
rcall _CF_Set_RegAddr ; set register address
rjmp _CF_Write ; force CF to accept register and data
[End]
[_CF_Set_CntLBA]
$EXTERNAL _CF_Write_Reg
; Write count of sector(s) (read or write) and Sectornumber (LBA) to CF-Card
; following parameter must be set:
; Register CF_SectorCount: Count of Sector(s) (max &7F)
; Register X: Pointer to sectornumber
;
_CF_Set_CntLBA:
ldi r22, Sec_Cnt_Reg ; Start with Sector-Count Register in CF (2)
mov r23, r21 ; prepare for output
rjmp _CF_Set_LBA2
_CF_Set_LBA1:
ld r23, X+ ; load next byte of sectornumber
_CF_Set_LBA2:
rcall _CF_Write_Reg ; set register-address
inc r22 ; set to next register address
cpi r22, 6
brmi _CF_Set_LBA1 ; Reg. 6 reached? (LBA/Disk/Header)
ld r23, X+ ; need special handling
andi r23, &B00001111 ; mask upper nibble (LBA-Sign and drive)
ori r23, &HE0 ; set to LBA
rjmp _CF_Write_Reg ; write to CF; incl Ret
[END]
[_DriveInit]
$EXTERNAL _DriveReset
; Setup the pins needed for the CF-Card
_DriveInit:
; Data port to OUTPUT
ldi _temp1, &H00 ; all Data pins to low
* out CF_Data_Out , _temp1
ldi _temp1, &HFF
* Out CF_Data_DDR , _temp1 ; Data pins to output
; Controlport: prepare 6 pins, leave other two unchanged
* in _temp1 , CF_Control_Out ;
* andi _temp1 , CF_Control_Dir_Mask ;
* ori _temp1 , CF_Control_Init
* Out CF_Control_Out , _temp1
* in _temp1 , CF_Control_DDR ; read direction of pins at control port
* andi _temp1 , CF_Control_Dir_Mask ; mask out used pins
* ori _temp1 , CF_Control_Direction ; set direction in and Out
* Out CF_Control_DDR , _temp1 ; set new direction configuration
; Address port: attention: adjust if not on Port C at ATMega103
; ATMega103 Port C have only output, so here no configuration is necessary
* in _temp1 , CF_ADDR_DDR
ori _temp1, &B00000111
* Out CF_Addr_DDR , _temp1
; waitms 1
*BASIC:WAITMS 1
; ldi r24, 1
; clr r25
; call _Waitms ; 1 ms delay
rjmp _DriveReset
[End]
[_DriveReset]
;------------------------------------------------------------------------------
; force CF-Card to a Hardware-reset
_DriveReset:
* sbi CF_Control_Out , CF_Reset
; waitms 1
ldi r24, 1
clr r25
call _waitms ; 1 ms delay
* cbi CF_Control_Out , CF_Reset
; waitms 500
clr r24
ldi r25, 2
call _waitms ; 512 ms delay
clr r25 ; set default no error
clc
ret
[End]
[_DriveCheck]
;------------------------------------------------------------------------------
; Checks, whether Card is plugged in: Pin CD1 is LOW
; if OK r24 = 1; otherwise 0
_DriveCheck:
clr r25
clc
* sbis CF_Control_In , CF_CD1 ; flashcard plugged in
ret
* ldi r25 , cpErrDriveNotPresent
sec
ret
[END]
Lesezeichen