PIC data logger to CF Card file; CF Card filesystem updated; Data readable via Windows PC software.
PIC 18F452 to CF Card to Windows PC Instrumentation Data Collection
Required Environment:
The program is setup to write an instrumentation file of maximum size based on code logic documented in routine 'cf_file_write'. Maximum file size, as the code is implemented, is 32MB. This is because I have only used 16-bit variables to count CF card file segments. 2**16 * 512 = 32MB. Larger file sizes can be generated by modifying the code to use 24-bit variables. A 24-bit variable would accommodate the sector count for the max file size of 4GB.
Instrumentation data is assigned to file: 'PIC_DATA.DAT'. This can be easily changed as it is specified in ROM via a DB string.
Only the file size and first cluster are updated in the directory entry for the file at completion of data collection.
To setup the CF card for use; I format the CF card (FAT16) and then using an edit program save an empty file to "pic_data.dat". The format ensures no data clusters have been allocated and that my file entry will be in the first segment of the root directory. Then its ready to go.
Miscellaneous notes regarding the program:
;******************************************************************************
;* CF_DB_Inst.ASM
;*
;* Revision: 2 Comments somewhat cleaned-up and working code.
;* Tested file size to 16MB.
;*
;* 03/09/2008
;******************************************************************************
;*
;* This program interfaces with a pre-formatted (FAT16) compact flash memory
;* card in PC Card Memory Mode. The disk partition table is read to get the
;* first partition segment offset. Next the BIOS Parameter Block in the
;* boot sector is read to verify the CF card filesystem format is FAT16.
;* The 1st segment of the root directory of the FAT (File Allocation Table)
;* file system is scanned for a specific file (PIC_DATA.DAT). If that file
;* is found, the file is then verified to be empty, zero length, and no cluster
;* number. Instrumentation data is collected in the CF card user data area
;* and linked to the file by mapping the data segments of the file written
;* to the CF card via the cluster chain mapping; which is written to both
;* copies of the CF Card FAT (FAT1 & FAT2). The directory entry of the file
;* is then updated with the starting cluster chain entry and the filesize
;* in bytes. The instrumentation file written to the CF Card is readable
;* on a Windows PC for further data reduction.
;*
;* Program performs 8-bit I/O with CF card.
;*
;* The PIC is clocked via a 4.9152MHz oscillator in my test setup.
;*
;******************************************************************************
list P=PIC18F452
include "p18f452.inc"
errorlevel -302 ; suppress message 302 from list file
;******************************************************************************
;Configuration bits
CONFIG OSC = XT
CONFIG OSCS = OFF
CONFIG PWRT = ON
CONFIG BOR = OFF
CONFIG WDT = OFF
CONFIG CCP2MUX = OFF
CONFIG STVR = OFF
CONFIG LVP = OFF
CONFIG DEBUG = ON
CONFIG CP0 = OFF
CONFIG CP1 = OFF
CONFIG CP2 = OFF
CONFIG CP3 = OFF
CONFIG CPB = OFF
CONFIG WRT0 = OFF
CONFIG WRT1 = OFF
CONFIG WRT2 = OFF
CONFIG WRT3 = OFF
CONFIG WRTB = OFF
CONFIG WRTC = OFF
CONFIG WRTD = OFF
CONFIG EBTR0 = OFF
CONFIG EBTR1 = OFF
CONFIG EBTR2 = OFF
CONFIG EBTR3 = OFF
CONFIG EBTRB = OFF
;******************************************************************************
;***** Define substitution text
; #define W 0 ; already in "p18f452.inc"
#define F 1
;******************************************************************************
;***** Define symbol constants
constant EOT=0xFF ; End Of Table
;******************************************************************************
;***** Define Assembler constants
;
; Banking values for Bank Select Register (BSR)
;
constant GPR0=0x00 ; These constants correspond to the
constant GPR1=0x01 ; DATABANK names in the linker script
constant GPR2=0x02 ; for the BANKED RAM locations. Use
constant GPR3=0x03 ; these constants to load the BSR
constant GPR4=0x04 ; (Bank Select Register) for variable
constant GPR5=0x05 ; access to those assigned to each bank.
; **WARNING** - match these constants to linker script assignments.
constant PROG_GPR=GPR0 ; udata prog_vars assigned to gpr0
constant CFOPS_GPR=GPR3 ; udata cfops_vars assigned to gpr3
constant MATH_GPR=GPR3 ; udata math_vars assigned to gpr3
;
; CF Card command values, 8 bits
;
WR_SEC_CMD EQU 0x30
RD_SEC_CMD EQU 0x20
;
; CF Card port equates
;
CF_DATA_IN EQU PORTD
CF_DATA_OUT EQU LATD
CF_ADDR EQU LATE
CF_CONTROL EQU LATC ; output MSB:LSB [LED,-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
CF_STATUS EQU PORTC ; input MSB:LSB [LED,-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
; ; input/output out in in out in out out out
;
; CF Card control port (PortC) pin equates
;
CE1 EQU 0
OE EQU 1
WE EQU 2
RDY EQU 3
RSET EQU 4 ; reserved here but not implemented in code
CD1 EQU 5
WAIT EQU 6
LED EQU 7
;
; CF Card register addresses - Memory Mapped Addressing
; low 3 bits as follows: (X,X,X,X,X,A2,A1,A0)
;
DATA_REG EQU 0x00 ; address of data register
ERROR_REG EQU 0x01 ; address of error register
FEATUR_REG EQU 0x01 ; address of features register
SEC_CNT_REG EQU 0x02 ; address of sector count register
SEC_NUM_REG EQU 0x03 ; address of sector number register
CYL_LO_REG EQU 0x04 ; address of low cylinder register
CYL_HI_REG EQU 0x05 ; address of high cylinder register
HEAD_REG EQU 0x06 ; address of head/drive register
STATUS_REG EQU 0x07 ; address of status register
COMMAND_REG EQU 0x07 ; address of command register
;
; CF program operation error codes
;
NO_CARD EQU 0x01 ; CF card not present
BAD_FORMAT EQU 0x02 ; CF card file system not FAT16
FIL_NOT_FND EQU 0x03 ; file not found in root dir
FILE_IN_USE EQU 0x04 ; file already in use
FILE_FULL EQU 0x05 ; maximum file size reached
USER_STOP EQU 0x06 ; user requested stop
;******************************************************************************
;***** Variable definitions
;******************************************************************************
; Key to naming of multiple byte variables:
; 4-byte variable; ll = low word,low byte
; lh = low word, high byte
; hl = high word, low byte
; hh = high word,high byte
; 2-byte variable; lb = low byte
; hb = high byte
acs_vars udata_acs ; interrupt and BSR independent variables
; variables used for context saving
w_temp res 1 ; variables used for context saving
status_temp res 1
pclath_temp res 1
; variables used for instrumentation process
inst_data_b res 1 ; data byte to write to CF Card data file
inst_flag res 1 ; instrumentation interrupt flag
end_inst_fl res 1 ; user signal to terminate instrumentation
timeout_cnt res 1 ; timeout counter, inst not done in time
bank_4_full res 1 ; GPR bank 4 full/empty flag; 0=E, 1=F
bank_5_full res 1 ; GPR bank 5 full/empty flag; 0=E, 1=F
bnk_4_5_prt res 1 ; active GPR bank pointer; 0x04 or 0x05
inst_bytcnt res 1 ; counter for inst bytes written to GPR banks
prog_vars udata ; program variable data
;
; None so far
cfops_vars udata ; CF Card routine's variable data
;
portC_sh res 1 ; PORTA shadow register for RMW proofing
portE_sh res 1 ; PORTE shadow register for RMW proofing
cf_io_data res 1 ; CF I/O data byte
cf_io_reg res 1 ; CF I/O register address
read_ptr_hi res 1 ; 16-bit pointer (cnt) of bytes read
read_ptr_lo res 1
read_tgt_hi res 1 ; 16-bit target
read_tgt_lo res 1
bytecnt res 1 ; working variable
loop_cntr res 1 ; working variable
error_code res 1 ; error code for CF routines, reason for stop
t_16bit_num: ; temp 16-bit variable for 8-bit numbers
t_16bit_lb res 1 ; needed in 16-bit math routines
t_16bit_hb res 1
rdf_off_lb res 1 ; offset of 'filename' entry in root dir
rdf_off_hb res 1 ; includes 0x400 for bank 4 start address
rtdirsiz_lb res 1 ; root directory size in sectors(lb:hb)
rtdirsiz_hb res 1
frdirsec_lb res 1 ; first sector of root directory in FAT1
frdirsec_hb res 1
ffat1sec_lb res 1 ; first sector of FAT1
ffat1sec_hb res 1
ffat2sec_lb res 1 ; first sector of FAT2
ffat2sec_hb res 1
fdatasec_lb res 1 ; first data sector in CF Card partition
fdatasec_hb res 1
fcluscnt_lb res 1 ; count of clusters needed for file
fcluscnt_hb res 1
fatcloff_lb res 1 ; cluster chain link offset into FAT sector
fatcloff_hb res 1
filclus_lb res 1 ; cluster number for file data
filclus_hb res 1
clus_swc_lb res 1 ; cluster entries written in sector
clus_swc_hb res 1
fil_size_ll res 1 ; 4-byte; filesize
fil_size_lh res 1
fil_size_hl res 1
fil_size_hh res 1
fil_swrt_lb res 1 ; 2-byte; file sector swritten cnt
fil_swrt_hb res 1
fil_dsec_lb res 1 ; 2-byte; writing this data sector
fil_dsec_hb res 1
fil_sbwc_lb res 1 ; 2-byte; bytes written in current sector
fil_sbwc_hb res 1
;cf_rw_structure ; Note: keep the following six variables in order
cf_rw_scnt res 1 ; sector cnt to read/write; always = 1
cf_rw_snum res 1 ; sector number; LBA 7-0
cf_rw_cyllo res 1 ; sector number: LBA 15-8
cf_rw_cylhi res 1 ; sector number: LBA 23-16; always 0
cf_rw_head res 1 ; always 0xE0
cf_rw_cmd res 1 ; read/write command value
;end_rw_structure
cf_rw_reg res 1 ; register offset for read/write sector cmd
; This directory structure left for documentation purposes only
;dir_entry_struct: ; defines a FAT directory entry
;dir_name res 11 ; short name
;dir_attr res 1 ; file attributes
;dir_NTres res 1 ; reserved for Windows NT
;dir_time_10 res 1 ; creation time, millisecond stamp
;dir_time_cr res 2 ; time file created
;dir_date_cr res 2 ; date file created
;dir_lstacc res 2 ; date last accessed
;dir_clus_hi res 2 ; high word of first cluster, 0 for FAT16
;dir_time_wr res 2 ; time of last write
;dir_date_wr res 2 ; date of last write
;dir_clus res 2 ; 16-bit: 1st cluster of file
;dir_fsize res 4 ; 32-bit: filesize
; **************************************
; start: CF Partition Table data
; **************************************
pt_vars udata ; variable data corresponding to pt_parm_tbl
; ; MUST CORRESPOND with pt_parm_tbl below
pt_parms:
pt_active res 1 ; 0x80 if active (bootable), otherwise 0x00
pt_strt_chs res 3 ; start of partition in CHS addressing
pt_type res 1 ; partition type: 4, 6, 14 (all FAT16 types)
pt_end_chs res 3 ; end of partition in CHS addressing
pt_ofset_ll res 1 ; 4-byte number: partition offset (physical)
pt_ofset_lh res 1
pt_ofset_hl res 1
pt_ofset_hh res 1
pt_size_ll res 1 ; 4-byte number: partition size in sectors
pt_size_lh res 1
pt_size_hl res 1
pt_size_hh res 1
pt_prm_tbl code
; ; MUST CORRESPOND with pt_vars above
; ; Note: byte offset must be in ascending order
; byte number
; offset bytes description
; ---------- ------ -----------
pt_parm_tbl db 0x01, 0xBE, 0x00,0x01 ; PT; Partition active
db 0x01, 0xBF, 0x00,0x03 ; PT; Start sector in CHS addressing
db 0x01, 0xC2, 0x00,0x01 ; PT; Type
db 0x01, 0xC3, 0x00,0x03 ; PT; End sector in CHS addressing
db 0x01, 0xC6, 0x00,0x04 ; PT; Relative offset in sectors (LBA)
db 0x01, 0xCA, 0x00,0x04 ; PT; Size in sectors
db EOT ; end of table marker
; ************************************
; end: CF Partition Table data
; ************************************
; *****************************************************
; start: Boot Sector & BIOS Parameter Block data
; *****************************************************
bs_bio_vars udata ; variable data corresponding to bs_parm_tbl
; ; MUST CORRESPOND with bs_parm_tbl below
bs_bio_parms:
bpb_bps_lb res 1 ; 2-byte number: bytes per sector
bpb_bps_hb res 1
bpb_spc res 1 ; sectors per cluster
bpb_res_lb res 1 ; 2-byte number: reserved sector count
bpb_res_hb res 1
bpb_num_fat res 1 ; number of FATs
bpb_rent_lb res 1 ; 2-byte number: root directory entries
bpb_rent_hb res 1
bpb_fsiz_lb res 1 ; 2-byte number: sectors per FAT
bpb_fsiz_hb res 1
bpb_hids_ll res 1 ; 4-byte number: hidden sector count
bpb_hids_lh res 1
bpb_hids_hl res 1
bpb_hids_hh res 1
bpb_tsec_ll res 1 ; 4-byte number: total sectors in volume
bpb_tsec_lh res 1
bpb_tsec_hl res 1
bpb_tsec_hh res 1
bpb_ext_sig res 1 ; signature: should be 0x29
bpb_fil_typ res 8 ; file system type: should be FAT16
bpb_sig_510 res 1 ; signature: should be 0x55
bpb_sig_511 res 1 ; signature: should be 0xAA
bs_prm_tbl code
; ; MUST CORRESPOND with bs_bio_parms above
; ; Note: byte offset must be in ascending order
; byte number
; offset bytes description
; ---------- ------ -----------
bs_parm_tbl db 0x00, 0x0B, 0x00,0x02 ; BPB; Count of bytes per sector
db 0x00, 0x0D, 0x00,0x01 ; BPB; Sectors per cluster
db 0x00, 0x0E, 0x00,0x02 ; BPB; Number of reserved sectors
db 0x00, 0x10, 0x00,0x01 ; BPB; Number of FATs
db 0x00, 0x11, 0x00,0x02 ; BPB; Cnt of 32-byte entries in root dir
db 0x00, 0x16, 0x00,0x02 ; BPB; FAT size in sectors
db 0x00, 0x1C, 0x00,0x04 ; BPB; Hidden sectors
db 0x00, 0x20, 0x00,0x04 ; BPB; Total sector count
db 0x00, 0x26, 0x00,0x01 ; BPB; Extended Boot Signature
db 0x00, 0x36, 0x00,0x08 ; BPB; File system type (FAT16)
db 0x01, 0xFE, 0x00,0x01 ; BPB; Boot Signature = 0x55
db 0x01, 0xFF, 0x00,0x01 ; BPB; Boot Signature = 0xAA
db EOT ; end of table marker
; ***************************************************
; end: Boot Sector & BIOS Parameter Block data
; ***************************************************
math_vars udata ; math routine variables
;
math_temp res 1 ; working variable
bsr_temp res 1 ; save/restore BSR register
; mult16x16U variables
a1 res 1 ; 16-bit Multiplicand L:H
a2 res 1
b1 res 1 ; 16-bit Multiplier L:H
b2 res 1
prod_lwlb res 1 ; 32-bit Product - low word:low byte
prod_lwhb res 1
prod_hwlb res 1
prod_hwhb res 1 ; 32-bit Product - high word:high byte
; div16x16U variables
accAlo res 1 ; 16-bit Denominator L:H
accAhi res 1
quotient_lb:
accBlo res 1 ; 16-bit Numerator (also Quotient) L:H
quotient_hb:
accBhi res 1
remain_lb:
accClo res 1 ; 16-bit Remainder L:H
remain_hb:
accChi res 1
accDlo res 1 ; 16-bit working registers L:H
accDhi res 1
; sub16U variables
diff_lb:
sub_dst_lb res 1
diff_hb:
sub_dst_hb res 1
sub_src_lb res 1
sub_src_hb res 1
; add16U variables
sum_lb:
add_dst_lb res 1
sum_hb:
add_dst_hb res 1
add_src_lb res 1
add_src_hb res 1
pgm_strings code ; constant strings used in program
;
fat16_str db "FAT16" ; const str for required FAT type
end_fatstr:
file_name db "PIC_DATADAT" ; const str for filename, BPB does not store '.'
end_filename: ; between filename 'PIC_DATA' and extension 'DAT'
constant FATSTRLEN = end_fatstr - fat16_str - 1 ; -1 for pad byte
constant FILSTRLEN = end_filename - file_name - 1 ; -1 for pad byte
; the strings above are odd num of char, so
; assembler adds a pad byte to make a full word
;******************************************************************************
;***** Interrupt Routines
;******************************************************************************
code 0x0000
; Start at the reset vector.
org 0x000 ; Reset interrupt vector
clrf INTCON,ACCESS ; Disable all interrupts
goto sys_init
;******************************************************************************
; High priority interrupt vector.
org 0x008
nop ; not currently using high priority ints
high_isr_end:
retfie FAST ; return from interrupt, enable high ints
; shadow registers used
;******************************************************************************
; Low priority interrupt vector.
org 0x018
movwf w_temp,ACCESS ; save current W register contents
movf STATUS,W,ACCESS ; move STATUS to w
clrf STATUS,ACCESS
movwf status_temp,ACCESS ; save contents of STATUS register
movff PCLATH,pclath_temp ; save current copy of PCLATH
clrf PCLATH,ACCESS ; reset PCLATH to page 0
; Check if Timer1 interrupt - used to initiate instrumentation activity.
btfss PIR1,TMR1IF,ACCESS
goto check_int1 ; No, so check next source
bcf PIR1,TMR1IF,ACCESS ; clear interrupt flag
; Reset Timer1 count preset.
clrf TMR1L,ACCESS ; prevents inc of high byte during init
movlw 0xFC ; FFFF-FCFF=0300=768 cnts
movwf TMR1H,ACCESS ; so, int every 768 instructions
movlw 0xFF
movwf TMR1L,ACCESS
; Set instrumentation data available flag.
bsf inst_flag,0,ACCESS ; set instrument available flag
goto low_isr_end
check_int1:
; Check if Int1 interrupt - used to terminate instrumentation activity.
; Make same priority as interrupt used to write instrumentation so that
; activity completes for the pending inst value before stopping activity.
btfss INTCON3,INT1IF,ACCESS
goto low_isr_end ; No, so exit
bcf INTCON3,INT1IF,ACCESS ; clear the interrupt flag
bcf INTCON3,INT1IE,ACCESS ; disable further INT1 interrupts
; Disable source of instrumentation interrupts.
bcf PIE1,TMR1IE,ACCESS ; disable Timer1 interrupts
bsf end_inst_fl,0,ACCESS ; set end inst flag
goto low_isr_end
low_isr_end:
clrf STATUS,ACCESS ; ensure file register bank set to 0
movff pclath_temp,PCLATH ; restore pre-isr PCLATH register
movff status_temp,STATUS ; restore pre-isr STATUS register
swapf w_temp,F,ACCESS ; swap w_temp nibbles and return to w_temp
swapf w_temp,W,ACCESS ; swap w_temp into W
retfie 0 ; return from interrupt, enable low ints
; shadow registers not used
;******************************************************************************
;***** Initialization Routine
;******************************************************************************
sys_init:
; Interrupt initialization.
bcf INTCON,GIEH,ACCESS ; disable all interrupts
; PORTC/TRISC initialization - CF Card control lines.
clrf PORTC,ACCESS
clrf LATC,ACCESS ; clear PortC output
movlw B'01101000' ; MSB:LSB [LED,-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
movwf TRISC,ACCESS ; PortC [0,1,2,4,7] output; [3,5,6] input
; PORTD/TRISD initialization - CF Card data bus.
clrf LATD,ACCESS ; clear PortD output
movlw B'00000000' ; set RC7-RC0 to outputs
movwf TRISD,ACCESS
; PORTE/TRISE initialization - CF Card address bus.
clrf LATE,ACCESS ; clear PortE output
movlw B'00000000' ; set RE2-RE0 to outputs
movwf TRISE,ACCESS
; Enable priority on interrupts.
bsf RCON,IPEN,ACCESS ; enable interrupt priority levels
; Timer1 setup.
bcf IPR1,TMR1IP,ACCESS ; set Timer1 interrupt to low priority
movlw B'00000000'
movwf T1CON,ACCESS ; pre & post scaler 1:1, timer off
bcf PIR1,TMR1IF,ACCESS ; clear interrupt flag
bsf PIE1,TMR1IE,ACCESS ; enable Timer1 interrupts
movlw 0xFC ; FFFF-FCFF=0300h=d'768' cnts
movwf TMR1H,ACCESS ; timer rollover every 768 instructions
movlw 0xFF ; so, collect inst data every 625 usec
movwf TMR1L,ACCESS ; (=1600 bytes/sec)
clrf inst_flag,ACCESS ; clear instrumentation flag
clrf timeout_cnt,ACCESS ; clear inst int timeout cntr
movlw 0x45 ; initialize inst data to 45h ('E')
movwf inst_data_b,ACCESS ; this is just a dat pattern value
; External interrupt INT1 setup, used end instrumentation activity.
bcf INTCON2,INTEDG1,ACCESS ; interrupt on falling edge
bcf INTCON3,INT1IP,ACCESS ; set INT1 to low priority, should be
; same priority as instrumentation event
bcf INTCON3,INT1IF,ACCESS ; clear interrrupt flag
bsf INTCON3,INT1IE,ACCESS ; enable interrupt
clrf end_inst_fl,ACCESS ; clear flag. Bit 0: 1=end inst
cf_init:
; Set BSR to CF-Ops variable bank.
movlb CFOPS_GPR ; set BSR to CF-ops variables bank
; Initialize CF Card present logic.
movlw NO_CARD ; start out assuming no CF card
movwf error_code,BANKED
movff CF_STATUS,portC_sh ; get value of portC
bsf portC_sh,LED,BANKED ; turn error LED on
movff portC_sh,CF_CONTROL ; using PortA shadow register
; Init fixed portion of CF read/write structure.
movlw 0x01
movwf cf_rw_scnt,BANKED ; always read/write 1 sector at a time
clrf cf_rw_cylhi,BANKED ; sector address limited to 16-bits
movlw 0xE0
movwf cf_rw_head,BANKED ; set LBA addressing, high sec addr = 0
; Start'em up!
goto main
;******************************************************************************
;***** Main Routine *****
;******************************************************************************
;
main:
;
; verify CF Card present
check_card:
btfsc CF_STATUS,CD1,ACCESS ; check for CF Card present, LATC[5]
goto check_card ; loop till card inserted
; clear no card error condition
clrf error_code,BANKED ; clear error code
movff CF_STATUS,portC_sh ; get value of portC
bcf portC_sh,LED,BANKED ; turn error LED off
movff portC_sh,CF_CONTROL ; using PortA shadow register
;***NOTE*** without the stanby mode below, the first read cmd does not work right.
; Probably issueing a RESET to the CF card first thing would work also.
; set CF to STANDBY mode
movlw B'00000111' ; MSB:LSB [-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
movwf CF_CONTROL,ACCESS ; set control lines on PortA, STANDBY
nop ; breakpoint opportunity
; Read CF Card info and setup for file write.
call cf_setup_init
; Just before ready to begin instrumenting data make this call.
call cf_file_write_init
; Enable interrupts and start Timer1.
bsf INTCON,GIE,ACCESS
bsf INTCON,PEIE,ACCESS ; enable low priority peripheral ints
bsf T1CON,TMR1ON,ACCESS ; start Timer1, used to generate inst data
; Begin collecting instrumentation data.
inst_loop:
; Always call 'cf_file_write' first thing in loop as it is the 'background'
; task that is emptying the GPR instrumentation data buffers to the CF card.
call cf_file_write
; If inst data avail, write it to the GPR inst buffer.
btfss inst_flag,0,ACCESS ; see if inst flag set
goto check_quit ; No, check for user requested stop
; Following instruction alternates inst data between 45h ('E') and 54h ('T').
; This gives a test pattern to data for examining the results.
swapf inst_data_b,F,ACCESS
; Write instrumentation data byte to the GPR buffer.
; Copy inst data to active GPR bank.
movff bnk_4_5_prt,FSR2H ; setup indirect address in active GPR bank
movff inst_bytcnt,FSR2L
movff inst_data_b,INDF2 ; move inst data to GPR bank
; Increment count of bytes written to active bank.
incf inst_bytcnt,F,ACCESS
; Test if counter has rolled over, if so active bank is full.
btfss STATUS,Z,ACCESS
goto write_inst_done ; no rollover, nothing else to do
; Counter has rolled over meaning we have written 256 bytes, the active bank
; is full. So switch to the other bank.
movlw 0x04
xorwf bnk_4_5_prt,W,ACCESS ; was 'bnk_4_5_prt' set to bank 4
btfss STATUS,Z,ACCESS ; Yes, so set active GPR bank to 5
goto set_active_4 ; No, so set active GPR bank to 4
; Set active bank to GPR bank 5.
movlw 0x05
movwf bnk_4_5_prt,ACCESS
; Test for timeout on emptying bank. If we are trying to write data
; to the CF card too fast this variable will still be set meaning we
; are missing some data.
btfsc bank_4_full,0,ACCESS
incf timeout_cnt,F,ACCESS ; Increment counter if timeout
; Set bank 4 full flag.
bsf bank_4_full,0,ACCESS
goto write_inst_done
set_active_4:
; Set active bank to GPR bank 4.
movlw 0x04
movwf bnk_4_5_prt,ACCESS
; Test for timeout on emptying bank.
btfsc bank_5_full,0,ACCESS
incf timeout_cnt,F,ACCESS ; Increment counter if timeout
; Set bank 5 full flag.
bsf bank_5_full,0,ACCESS
write_inst_done:
; Clear flag after writing inst data to buffer.
bcf inst_flag,0,ACCESS ; reset inst data available flag
check_quit:
; Check if user requested end to instrumentation.
btfss end_inst_fl,0,ACCESS ; flag set? Bit 0: 1=end inst
goto inst_loop ; No, so stay in loop
; User requested stop.
; To close instrumentation file and perform update of CF Card root directory
; and FAT structures make this call.
call cf_file_close
movlw USER_STOP
call error_stop ; Does not return!!!
;******************************************************************************
;******************************************************************************
; ***** Subroutines *****
;******************************************************************************
;******************************************************************************
;
error_stop:
; Loads error code passed in WREG to error variable, turns on error LED,
; puts the CF Card in STANDBY mode, and performs a tight loop on last
; instruction, effectively stopping.
;
; Record error code.
movwf error_code,BANKED
; Set CF to STANDBY mode and turn on LED.
movlw B'10000111' ; MSB:LSB [LED,-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
movwf CF_CONTROL,ACCESS ; set control lines on PortA, STANDBY
; effectively stops here in a tight loop
goto $ ; stop
;
cf_check_ready:
;
; Loops until the CF Card is ready for next command.
; CF_CONTROL (PortC) layout; [MSB:LSB]; [LED,-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
;
btfss CF_STATUS,RDY,ACCESS ; check that CF card is ready, PORTC[3]
goto cf_check_ready ; loop till CF card ready
return
;
cf_write:
;
; Writes one byte of data to the CF card I/O buffer.
; CF_CONTROL (PortC) layout; [MSB:LSB]; [X,-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
; CF Card register address passed in cf_io_reg.
; Write data passed in cf_io_data.
;
clrf TRISD,ACCESS ; make data bus an output
call cf_check_ready
movff cf_io_reg,LATE ; put register address on LATE
movff cf_io_data,LATD ; put data on data bus, LATD
movff CF_STATUS,portC_sh ; get value of portC
bcf portC_sh,CE1,BANKED ; strobe -CE1 line low
bcf portC_sh,WE,BANKED ; strobe -WE line low
movff portC_sh,CF_CONTROL ; using PortC shadow register
ck_wr_done:
btfss CF_STATUS,WAIT,ACCESS ; wait for CF done, PORTC[6]
goto ck_wr_done
movff CF_STATUS,portC_sh ; get value of portC
bsf portC_sh,CE1,BANKED ; hold -CE1 line high
bsf portC_sh,WE,BANKED ; hold -WE line high
movff portC_sh,CF_CONTROL ; using PortA shadow register
return
;
cf_sec_rw_cmd:
;
; Reads/Writes a sector of CF card data.
; Command parameters should have already been loaded in cf_rw_structure.
;
movlw d'6'
movwf loop_cntr,BANKED ; will be writing 6 registers
movlw d'2'
movwf cf_rw_reg,BANKED ; starting with reg offset 2
lfsr FSR0,cf_rw_scnt ; point to cf_rw_structure
cf_rw_loop:
movff POSTINC0,cf_io_data ; load register data
movff cf_rw_reg,cf_io_reg ; load register to load
call cf_write
incf cf_rw_reg,F,BANKED ; advance to next register
decfsz loop_cntr,F,BANKED ; loop till all 6 written
goto cf_rw_loop
return
;
cf_read:
;
; Reads one byte from the CF Card I/O buffer.
; Data is read from the 'data' register, CF register addr = 0.
; CF_CONTROL (PortC) layout; [MSB:LSB]; [X,-WAIT,-CD1,RESET,RDY,-WE,-OE,-CE1]
;
movlw B'11111111'
movwf TRISD,ACCESS ; make data bus an input
clrf CF_ADDR,ACCESS ; clear A0 address line, LATE
; read one byte
call cf_check_ready
movff CF_STATUS,portC_sh ; get value of portC
bcf portC_sh,CE1,BANKED ; strobe -CE1 line low
bcf portC_sh,OE,BANKED ; strobe -OE line low
movff portC_sh,CF_CONTROL ; using PortA shadow register
ck_rd_done:
btfss CF_STATUS,WAIT,ACCESS ; wait for CF done, PORTC[6]
goto ck_rd_done
movff CF_DATA_IN,cf_io_data ; save data byte
movff CF_STATUS,portC_sh ; get value of portC
bsf portC_sh,CE1,BANKED ; hold -CE1 line high
bsf portC_sh,OE,BANKED ; hold -OE line high
movff portC_sh,CF_CONTROL ; using PortA shadow register
return
;
load_table_params:
;
; Collects the CF Card data defined in ROM table. The table pointer registers
; have already been setup by the calling routine. Locates variables defined in
; the ROM table by offset into the CF card I/O buffer and copies the value to GPR.
;
bsf EECON1,EEPGD,ACCESS ; access flash program memory
movlw 0xFF
movwf read_ptr_hi,BANKED ; init byte pointer to -1, will rollover to 0
movwf read_ptr_lo,BANKED ; on the first increment
tbl_loop:
tblrd *+ ; read table:byte_offset into TABLAT and inc ptr
movff TABLAT,WREG ; WREG=table:byte_offset
xorlw EOT ; compare table:byte_offset to EOT char
btfsc STATUS,Z,ACCESS ; was last table:byte_offset the EOT
goto end_tbl ; yes, so quit
movff TABLAT,read_tgt_hi ; copy 16-bit offset to target
tblrd *+
movff TABLAT,read_tgt_lo
find_offset_byte:
call cf_read ; read byte of CF ID data
incf read_ptr_lo,F,BANKED ; increment 16-bit pointer
btfsc STATUS,C,ACCESS ; low byte inc cause carry?
incf read_ptr_hi,F,BANKED ; yes, so inc high byte
call compr_ptr_to_tgt ; we there yet?
btfss STATUS,Z,ACCESS ; if cmpr X=Y then Z=1
goto find_offset_byte ; No, read next CF id byte
movlw 0x01
movwf bytecnt,BANKED ; 1 byte per read, 1 byte read
; Store CF ID value in GPR variables.
movff cf_io_data,POSTINC0
; Read number of CF ID data bytes for table entry.
tblrd *+ ; throw away pad byte
tblrd *+ ; read table:bytes into TABLAT and inc ptr
movff TABLAT,WREG ; WREG=table:bytes
subwf bytecnt,W,BANKED ; bytecnt = table:bytes ?
btfsc STATUS,Z,ACCESS
goto tbl_loop ; YES, get next table:word
byte_loop:
; Get byte of CF Card data.
call cf_read ; read byte of CF ID data
incf read_ptr_lo,F,BANKED ; increment 16-bit pointer
btfsc STATUS,C,ACCESS ; low byte inc cause carry?
incf read_ptr_hi,F,BANKED ; yes, so inc high byte
; Store CF card value in GPR variables.
movff cf_io_data,POSTINC0
; Adjust count of bytes read.
incf bytecnt,F,BANKED ; inc cnt of bytes read
; Test to see if we've read all the bytes required.
movff TABLAT,WREG ; WREG=table:bytes
subwf bytecnt,W,BANKED ; bytecnt = table:bytes ?
btfss STATUS,Z,ACCESS
goto byte_loop ; NO, get next CF ID data
goto tbl_loop ; YES, so get next table entry
end_tbl:
return
;
compr_ptr_to_tgt:
;
; Signed and unsigned 16 bit comparison routine:
; by David Cary 2001-03-30
; Returns the correct flags (Z and C) to indicate the X=Y, X>Y, or X<=Y.
; Does not modify X or Y (X=read pointer; Y=read target).
; Results: if X=Y then Z=1.
; if X>Y then C=0.
; if X<=Y then C=1.
movff read_ptr_hi,WREG
subwf read_tgt_hi,W,BANKED ; subtract Y-X
btfss STATUS,Z,ACCESS ; Are they equal?
goto compr_ptr_end ; No
movff read_ptr_lo,WREG ; yes, they are equal -- compare lo
subwf read_tgt_lo,W,BANKED ; subtract Y-X
compr_ptr_end:
return
;
comp_strings:
;
; Compares string in ROM with one in RAM:
; Length of string passed in WREG.
; Results: if X=Y then STATUS:Z=1, otherwise STATUS:Z=0.
; Result is set by XOR instruction.
movwf bytecnt,BANKED ; initialize counter
compr_str_loop:
movff POSTINC0,WREG ; get char of RAM string
tblrd *+ ; read table: get char of ROM string
xorwf TABLAT,W,ACCESS ; compare RAM to ROM char
btfss STATUS,Z,ACCESS ; if equal, compare till done
goto compr_str_end ; no, so quit
decfsz bytecnt,F,BANKED ; dec string length counter
goto compr_str_loop ; compare next characters
compr_str_end:
return
;
cf_load_bootsec_parms:
;
; Sends command to read the CF Card boot sector; sector number: 0.
; Sector zero contains the partition table at offset 0x1BE.
;
; setup sector number (LBA 7:0) register
clrf cf_rw_snum,BANKED ; reading sector zero
; setup cylinder low (LBA 15:8) register
clrf cf_rw_cyllo,BANKED ; reading sector zero
; setup comand register
movlw RD_SEC_CMD ; get read sector command value
movwf cf_rw_cmd,BANKED
call cf_sec_rw_cmd
; Load Boot Sector/BIOS Param Block parameters defined in table structure 'bs_parm_tbl'.
; Setup indirect addr for bs_bio_parms variables.
lfsr FSR0,pt_parms
; Setup TBLPTR for ROM reads.
movlw upper pt_parm_tbl
movwf TBLPTRU,ACCESS
movlw high pt_parm_tbl
movwf TBLPTRH,ACCESS
movlw low pt_parm_tbl
movwf TBLPTRL,ACCESS
; Load RAM variables defined in ROM table.
call load_table_params ; load CF Card ID data defined in table pt_parm_tbl
return
;
cf_load_BIOS_parms:
;
; Send command to read the 1st partition Boot Sector/BIOS Parameter Block.
;
; setup sector number (LBA 7:0) register
movff pt_ofset_ll,cf_rw_snum ; partition table offset (lwlb)
; setup cylinder low (LBA 15:8) register
movff pt_ofset_lh,cf_rw_cyllo ; partition table offset (lwhb)
; setup comand register
movlw RD_SEC_CMD ; get read sector command value
movwf cf_rw_cmd,BANKED
call cf_sec_rw_cmd
; Load Boot Sector/BIOS Param Block parameters defined in table structure 'bs_parm_tbl'.
; Setup indirect addr for bs_bio_parms variables.
lfsr FSR0,bs_bio_parms
; Setup TBLPTR for ROM reads.
movlw upper bs_parm_tbl
movwf TBLPTRU,ACCESS
movlw high bs_parm_tbl
movwf TBLPTRH,ACCESS
movlw low bs_parm_tbl
movwf TBLPTRL,ACCESS
; Load RAM variables defined in ROM table.
call load_table_params ; load CF Card ID data defined in table cf_parm_tbl
return
;
cf_verify_FAT16:
;
; Verifies the BPB file type = FAT16.
;
; Setup indirect addr for BPB file type variable.
lfsr FSR0,bpb_fil_typ
; Setup TBLPTR for ROM reads.
movlw upper fat16_str
movwf TBLPTRU,ACCESS
movlw high fat16_str
movwf TBLPTRH,ACCESS
movlw low fat16_str
movwf TBLPTRL,ACCESS
movlw FATSTRLEN ; get string length
; Load RAM variables defined in ROM table.
call comp_strings ; see if strings match
btfsc STATUS,Z,ACCESS ; successful (Z=0)?
goto end_verify
wrong_format:
movlw BAD_FORMAT ; CF Card format not FAT16
call error_stop
end_verify:
return
;
cf_read_sector:
;
; Read CF Flash sector, put in GPR banks: 4 & 5.
;
; setup comand register
movlw RD_SEC_CMD ; get read sector command value
movwf cf_rw_cmd,BANKED
call cf_sec_rw_cmd
; copy sector of data to GPR banks 4 & 5, 256 bytes per bank
movlw 0x02 ; twice through 256 byte loop
movwf loop_cntr,BANKED
; Setup indirect addr for read data
lfsr FSR0,0x400 ; point to GPR bank 4
; Setup CF read register
movlw DATA_REG
movwf cf_io_reg,BANKED
rd_bank_loop:
; Setup read counter.
clrf bytecnt,BANKED ; 0 -> 0xFF inclusive = d'256'
read_data_loop:
call cf_read
; Store CF data value in GPR.
movff cf_io_data,POSTINC0
decfsz bytecnt,F,BANKED
goto read_data_loop
; finished bank 4 (256 bytes) now do GPR bank 5
decfsz loop_cntr,F,BANKED
goto rd_bank_loop
return
;
cf_write_sector:
;
; Write sector of data in GPR banks: 4 & 5 to CF Card.
;
; setup comand register
movlw WR_SEC_CMD ; get write sector command value
movwf cf_rw_cmd,BANKED
call cf_sec_rw_cmd
; write data in GPR banks 4 & 5, 256 bytes per bank
movlw 0x02 ; twice through 256 byte loop
movwf loop_cntr,BANKED
; Setup indirect addr for write data
lfsr FSR0,0x400 ; point to GPR bank 4
; Setup CF write register
movlw DATA_REG
movwf cf_io_reg,BANKED
wr_bank_loop:
; Setup write counter
clrf bytecnt,BANKED ; 0 -> 0xFF inclusive = d'256'
write_data_loop:
; write data to CF Card
movff POSTINC0,cf_io_data
call cf_write
decfsz bytecnt,F,BANKED
goto write_data_loop
; finished bank 4 (256 bytes) now do GPR bank 5
decfsz loop_cntr,F,BANKED
goto wr_bank_loop
return
;
cf_find_file:
;
; Loads the first sector of the root directory and searches for filename.
; If filename not found an error condition is raised.
;
; Compute first segment of FAT Root Directory, offset by 1st partion offset.
; FirstRootDirSecNum = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16) +
; partition offset
movff bpb_num_fat,t_16bit_lb ; make 16-bit from 8-bit
clrf t_16bit_hb,BANKED
lfsr FSR0,t_16bit_lb
lfsr FSR1,bpb_fsiz_lb
call mult16x16U ; product = (BPB_NumFATs * BPB_FATSz16)
lfsr FSR0,prod_lwlb ; low word of product
lfsr FSR1,bpb_res_lb
call add16U ; sum(1) = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16)
movff sum_lb,t_16bit_lb ; move product to temp variable
movff sum_hb,t_16bit_hb
lfsr FSR0,t_16bit_lb
lfsr FSR1,pt_ofset_ll
call add16U ; sum(2) = pt_ofset_ll:lh + sum(1)
movff sum_lb,frdirsec_lb ; save: FirstRootDirSecNum
movff sum_hb,frdirsec_hb
; Get the root directory. Send command to read the 1st sector of root dir.
; setup sector number (LBA 7:0) register
movff frdirsec_lb,cf_rw_snum ; root dir sector (lb)
; setup cylinder low (LBA 15:8) register
movff frdirsec_hb,cf_rw_cyllo ; root dir sector (hb)
call cf_read_sector
; Search 1st sector of root dir for 'file_name'.
; Each directory entry is 32 bytes, so 512/32=16 entries per sector
movlw d'16'
movwf loop_cntr ; setup loop counter
movlw 0x04
movwf t_16bit_hb,BANKED ; set 16-bit variable to Bank4
clrf t_16bit_lb,BANKED
root_dir_loop:
; Setup indirect addr for root directory sector entries
; lfsr FSR0,bpb_fil_typ
movff t_16bit_hb,FSR0H
movff t_16bit_lb,FSR0L
; Setup TBLPTR for ROM reads
movlw upper file_name
movwf TBLPTRU,ACCESS
movlw high file_name
movwf TBLPTRH,ACCESS
movlw low file_name
movwf TBLPTRL,ACCESS
movlw FILSTRLEN ; get string length
; Load RAM variables defined in ROM table.
call comp_strings ; see if strings match
btfsc STATUS,Z,ACCESS ; successful (Z=0)?
goto end_find_file
; increment variable to access next 32-byte entry
movlw d'32'
addwf t_16bit_lb,F,BANKED
btfsc STATUS,C,ACCESS ; did add cause carry
incf t_16bit_hb,F,BANKED ; yes, so inc high byte of variable
; test for end of sector
decfsz loop_cntr,F,BANKED
goto root_dir_loop
; filename not found in first sector
movlw FIL_NOT_FND ; filename not found
call error_stop
end_find_file:
; At this point t_16bit_lb:hb holds offset of 'filename' entry in root
; directory sector 0, including the 0x400 offset for bank 4.
movff t_16bit_lb,rdf_off_lb ; save offset for later
movff t_16bit_hb,rdf_off_hb
return
;
cf_verify_file_empty:
;
; The last six bytes (cluster & filesize) of the directory entry should
; be zero. These are at offset 0x1A from the beginning of the entry.
; At this point t_16bit_lb:hb holds offset of 'filename' entry in root
; directory sector 0, including the 0x400 offset for bank 4.
movlw 0x1A ; add offset to dir entry offset value
addwf t_16bit_lb,F,BANKED
btfsc STATUS,C,ACCESS ; did add cause carry
incf t_16bit_hb,F,BANKED ; yes, so inc high byte of variable
movff t_16bit_hb,FSR0H ; setup indirect addr pointer
movff t_16bit_lb,FSR0L
movlw d'6'
movwf loop_cntr ; setup loop counter
verfy_empty_loop:
movff POSTINC0,WREG ; get dir entry byte
xorlw 0x00
btfss STATUS,Z,ACCESS ; test if zero
goto not_empty_err
decfsz loop_cntr,F,BANKED
goto verfy_empty_loop
goto end_verify_empty
not_empty_err:
; filename not empty
movlw FILE_IN_USE ; filename already has data
call error_stop
end_verify_empty:
return
;
cf_comp_rootdir_size:
;
; Compute the root directory size (in sectors) and the first data sector.
; RootDirSectors = ((BPB_RootEntCnt * 32) + ( BPB_BytesPerSec - 1))/BPB_BytesPerSec
lfsr FSR0,bpb_bps_lb ; init ptr to minuend
clrf t_16bit_hb,BANKED
movlw d'1'
movwf t_16bit_lb,BANKED ; put 1 in 16-bit temp variable
lfsr FSR1,t_16bit_lb ; init ptr to subtrahend
call sub16U ; diff = (BPB_BytesPerSec - 1)
clrf t_16bit_hb,BANKED
movlw d'32'
movwf t_16bit_lb,BANKED ; put 32 in 16-bit temp variable
lfsr FSR0,t_16bit_lb
lfsr FSR1,bpb_rent_lb
call mult16x16U ; product = (BPB_RootEntCnt * 32)
lfsr FSR0,prod_lwlb ; low word of product
lfsr FSR1,diff_lb
call add16U ; sum = ((BPB_RootEntCnt * 32) +
; ( BPB_BytesPerSec - 1))
lfsr FSR0,bpb_bps_lb ; init ptr to denominator
lfsr FSR1,sum_lb ; init ptr to numerator
call div16by16U ; quotient = RootDirSectors
movff quotient_lb,rtdirsiz_lb ; save result in GPR
movff quotient_hb,rtdirsiz_hb ; save result in GPR
return
;
cf_comp_1st_data_sect:
;
; The start of the CF card data region, the first sector of cluster 2.
; FirstDataSector = BPBResvdSecCnt + (BPB_NumFATs * BPB_FATSz16) +
; RootDirSectors + partition offset
movff bpb_num_fat,t_16bit_lb ; make 16-bit from 8-bit
clrf t_16bit_hb,BANKED
lfsr FSR0,t_16bit_lb
lfsr FSR1,bpb_fsiz_lb
call mult16x16U ; product = (BPB_NumFATs * BPB_FATSz16)
lfsr FSR0,prod_lwlb ; low word of product
lfsr FSR1,bpb_res_lb
call add16U ; sum(1) = BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16)
movff sum_lb,t_16bit_lb ; move product to temp variable
movff sum_hb,t_16bit_hb
lfsr FSR0,t_16bit_lb
lfsr FSR1,rtdirsiz_lb
call add16U ; sum(2) = sum(1) + BPBResvdSecCnt
movff sum_lb,t_16bit_lb ; move product to temp variable
movff sum_hb,t_16bit_hb
lfsr FSR0,t_16bit_lb
lfsr FSR1,pt_ofset_ll
call add16U ; sum(3) = pt_ofset_ll:lh + sum(2)
movff sum_lb,fdatasec_lb ; save: FirstDataSector
movff sum_hb,fdatasec_hb
movff fdatasec_lb,fil_dsec_lb ; set 1st file sector to 1st data sector
movff fdatasec_hb,fil_dsec_hb
return
;
cf_close_dirupdt:
;
; Update root directory file entry.
;
; Get the root directory, put in GPR banks 4&5.
; setup sector number (LBA 7:0) register
movff frdirsec_lb,cf_rw_snum ; root dir sector (lb)
; setup cylinder low (LBA 15:8) register
movff frdirsec_hb,cf_rw_cyllo ; root dir sector (hb)
call cf_read_sector
; DIR_FstClusLo:low byte is at offset 0x1A into the directory entry.
clrf t_16bit_hb,BANKED
movlw 0x1A
movwf t_16bit_lb,BANKED ; put 0x1A in 16-bit temp variable
lfsr FSR0,t_16bit_lb
lfsr FSR1,rdf_off_lb ; addr of file entry in GPR
call add16U ; sum = addr(file in root dir +
; offset to first cluster num)
movff sum_lb,FSR0L ; setup indirect address cluster
movff sum_hb,FSR0H
movlw d'2' ; we are starting file at cluster 2
movff WREG,INDF0 ; put cluster number 4 in directory entry
; DIR_FileSize:low byte is at offset 0x1C into the directory entry.
clrf t_16bit_hb,BANKED
movlw 0x1C
movwf t_16bit_lb,BANKED ; put 0x1C in 16-bit temp variable
lfsr FSR0,t_16bit_lb
lfsr FSR1,rdf_off_lb ; addr of file entry in GPR
call add16U ; sum = addr(file in root dir +
; offset to file size)
movff sum_lb,FSR0L ; setup indirect address to file size
movff sum_hb,FSR0H
; move 4 bytes of filesize to directory entry
movff fil_size_ll,POSTINC0
movff fil_size_lh,POSTINC0
movff fil_size_hl,POSTINC0
movff fil_size_hh,POSTINC0
; Write root directory update back to CF Card.
; setup sector number (LBA 7:0) register
movff frdirsec_lb,cf_rw_snum ; root dir sector (lb)
; setup cylinder low (LBA 15:8) register
movff frdirsec_hb,cf_rw_cyllo ; root dir sector (hb)
call cf_write_sector
return
;
cf_close_clusupdt:
;
; Update the FAT cluster chains for the file, FAT2 is duplicate of FAT1.
;
; Compute FAT1 starting sector number = reserved sectors + 1st partion offset
lfsr FSR0,bpb_res_lb
lfsr FSR1,pt_ofset_ll
call add16U ; sum = pt_ofset + reserved sectors
movff sum_lb,ffat1sec_lb
movff sum_hb,ffat1sec_hb
; Compute FAT2 starting sector number
lfsr FSR0,ffat1sec_lb
lfsr FSR1,bpb_fsiz_lb
call add16U ; sum = FAT1 start sector + FAT sector size
movff sum_lb,ffat2sec_lb
movff sum_hb,ffat2sec_hb
; Compute cluster count for file cluster chain.
; cluster count = file data sectors / sectors per cluster
movff bpb_spc,t_16bit_lb ; convert 8-bit to 16-bit number
clrf t_16bit_hb,BANKED
lfsr FSR0,t_16bit_lb ; init ptr to denominator
lfsr FSR1,fil_swrt_lb ; init ptr to numerator
call div16by16U ; quotient = RootDirSectors
movff quotient_lb,fcluscnt_lb ; save result in RAM
movff quotient_hb,fcluscnt_hb ; save result in RAM
; round cluster count up if any remainder
clrf WREG,ACCESS
xorwf remain_lb,W,BANKED
btfss STATUS,Z,ACCESS ; test if remain_lb = 0
goto clus_round_up ; no, so round up
clrf WREG,ACCESS
xorwf remain_hb,W,BANKED
btfss STATUS,Z,ACCESS ; test if remain_hb = 0
goto clus_round_up ; no, so round up
goto build_chain
clus_round_up:
incf fcluscnt_lb,F,BANKED
btfsc STATUS,C,ACCESS ; carry out?
incf fcluscnt_hb,F,BANKED ; yes, so inc high byte
build_chain:
; Get first sector of FAT1, put in GPR banks 4&5.
; setup sector number (LBA 7:0) register
movff ffat1sec_lb,cf_rw_snum
; setup cylinder low (LBA 15:8) register
movff ffat1sec_hb,cf_rw_cyllo
call cf_read_sector
; Set first cluster for file = 2, cluster 0 & 1 are reserved.
movlw d'2'
movwf filclus_lb,BANKED
clrf filclus_hb,BANKED
; Set clusters written to sector count = 2 (cluster 0 & 1 are reserved).
movlw d'2'
movwf clus_swc_lb,BANKED
clrf clus_swc_hb,BANKED
begin_fat_segment:
; Initialize FAT cluster offset to beginning of GPR bank 4.
movlw d'4'
movwf fatcloff_hb,BANKED
clrf fatcloff_lb,BANKED ; offset = 0x0400
; Compute FAT cluster offset (2-bytes per cluster).
movlw d'2'
movwf t_16bit_lb,BANKED
clrf t_16bit_hb,BANKED
lfsr FSR0,t_16bit_lb
lfsr FSR1,clus_swc_lb
call mult16x16U ; product = 2 * clusters written
lfsr FSR0,prod_lwlb
lfsr FSR1,fatcloff_lb
call add16U ; sum = GRP4 offset + (2 * clusters written)
movff sum_lb,fatcloff_lb
movff sum_hb,fatcloff_hb
movff fatcloff_lb,FSR0L ; setup indirect address for chain link
movff fatcloff_hb,FSR0H
write_chain_loop:
; Test case of only 1 cluster for file, or, one cluster left to write.
decf fcluscnt_lb,W,BANKED ; subtract 1 from low byte
btfss STATUS,Z,ACCESS ; result zero?
goto more_than_one ; no, so create link
clrf WREG,ACCESS ; yes, see if high byte = 0
xorwf fcluscnt_hb,W,BANKED
btfsc STATUS,Z,ACCESS ; file cluster count high byte = 0?
goto write_eoc ; yes, so write end-of-chain mark
more_than_one:
; Each link of cluster chain points to next link, so, increment file cluster number.
incf filclus_lb,F,BANKED
btfsc STATUS,C,ACCESS
incf filclus_hb,F,BANKED
; Write next file cluster number to current FAT cluster entry.
movff filclus_lb,POSTINC0 ; write pointer to next link
movff filclus_hb,POSTINC0
; Decrement count of file clusters.
decf fcluscnt_lb,F,BANKED
btfss STATUS,C,ACCESS ; borrow\ set?
decf fcluscnt_hb,F,BANKED ; yes, so adjust high byte
; Increment count of cluster chain entries written to FAT segment.
incf clus_swc_lb,F,BANKED ; max value is 256
; See if 256 chain entries written (counter rollover), if so, sector is full.
btfss STATUS,Z,ACCESS ; test if = 256
goto write_chain_loop ; no, so continue writing to this sector of FAT
; Write sector of FAT data to CF Card FAT1 from GPR banks 4&5.
; setup sector number (LBA 7:0) register
movff ffat1sec_lb,cf_rw_snum
; setup cylinder low (LBA 15:8) register
movff ffat1sec_hb,cf_rw_cyllo
call cf_write_sector
; Write sector of FAT data to CF Card FAT2 from GPR banks 4&5.
; setup sector number (LBA 7:0) register
movff ffat2sec_lb,cf_rw_snum
; setup cylinder low (LBA 15:8) register
movff ffat2sec_hb,cf_rw_cyllo
call cf_write_sector
; Increment to next sector of FAT1 & FAT2.
incf ffat1sec_lb,F,BANKED ; inc FAT1 sector count
btfsc STATUS,Z,ACCESS
incf ffat1sec_hb,F,BANKED
incf ffat2sec_lb,F,BANKED ; inc FAT2 sector count
btfsc STATUS,Z,ACCESS
incf ffat2sec_hb,F,BANKED
; Get next sector of FAT1, put in GPR banks 4&5.
; setup sector number (LBA 7:0) register
movff ffat1sec_lb,cf_rw_snum
; setup cylinder low (LBA 15:8) register
movff ffat1sec_hb,cf_rw_cyllo
call cf_read_sector
; Clear count of FAT entries written to segment.
clrf clus_swc_lb,BANKED
goto begin_fat_segment
write_eoc:
; We're at the last cluster of the chain, so write end-of-chain to cluster.
movlw 0xFF
movff WREG,POSTINC0 ; write eoc mark: 0xFFFF
movff WREG,POSTINC0
; Write sector of FAT data to CF Card FAT1 from GPR banks 4&5.
; setup sector number (LBA 7:0) register
movff ffat1sec_lb,cf_rw_snum
; setup cylinder low (LBA 15:8) register
movff ffat1sec_hb,cf_rw_cyllo
call cf_write_sector
; Write sector of FAT data to CF Card FAT2 from GPR banks 4&5.
; setup sector number (LBA 7:0) register
movff ffat2sec_lb,cf_rw_snum
; setup cylinder low (LBA 15:8) register
movff ffat2sec_hb,cf_rw_cyllo
call cf_write_sector
return
;
cf_file_write_init:
;
; Initializes instrumentation process variables and sends a command to
; the CF card to write the first data sector.
; Zero instrumentation file variables.
clrf fil_size_ll,BANKED ; filesize
clrf fil_size_lh,BANKED
clrf fil_size_hl,BANKED
clrf fil_size_hh,BANKED
clrf fil_swrt_lb,BANKED ; file sectors written
clrf fil_swrt_hb,BANKED
clrf fil_sbwc_lb,BANKED ; sector bytes written count
clrf fil_sbwc_hb,BANKED
; Initialize instrumentation interrupt variables.
clrf bank_4_full,ACCESS ; init inst data banks to empty
clrf bank_5_full,ACCESS ; init inst data banks to empty
clrf inst_bytcnt,ACCESS ; inst data bytes written to bank
movlw 0x04
movwf bnk_4_5_prt,ACCESS ; start writing to bank 4
; Send command to write the first data sector.
; setup sector number (LBA 7:0) register
movff fil_dsec_lb,cf_rw_snum ; 1st data sector for file(lwlb)
; setup cylinder low (LBA 15:8) register
movff fil_dsec_hb,cf_rw_cyllo ; 1st data sector for file (lwhb)
; setup comand register
movlw WR_SEC_CMD ; get write sector command value
movwf cf_rw_cmd,BANKED
call cf_sec_rw_cmd
return
;
cf_file_write:
;
; Writes one byte of instrumentation data to file. When the max file size
; is reached the file close and CF card file system updates are performed.
; The file size is a 4 byte number; the bytes being hh:hl:lh:ll. The max
; file size test below looks at a single bit of byte 'hl'.
; hh:hl:lh:ll
; Possibilities are: bit 0 set = 00:01:00:00h (65,536) bytes,
; bit 1 set = 00:02:00:00h (131,072) bytes,
; bit 2 set = 00:04:00:00h (262,144) bytes,
; bit 3 set = 00:08:00:00h (524,288) bytes, etc.
; This code mas file size = 02:00:00:00h (33,554,432) bytes.
; Windows max file size = FF:FF:FF:FFh (4,294,967,295) bytes.
;
; Limitation of file size for the code is that I have only implemented 16-bit
; counters for counting sectors. 4GB file requires 8,388,607 sectors!
;
; In code below, the max file size is 0x10000 (65,536) bytes; 128 sectors.
;
; Test for max file size.
btfsc fil_size_hl,0,BANKED ; Test if max filesize reached
goto close_file
; Current sector byte count = 512?
btfss fil_sbwc_hb,1,BANKED ; 511=1FFh, 512=200h so check bit 1
; of counter high byte (bit cnt zero based)
goto cf_file_wbyte ; No, write next byte to file
; Current sector full, so start new sector.
; Increment count of file sectors.
incf fil_swrt_lb,F,BANKED ; inc count of sectors written
btfsc STATUS,C,ACCESS ; carry on increment
incf fil_swrt_hb,F,BANKED ; yes, fixup high byte for carry
; Add 1 to fil_dsec_lb:hb as address of next file sector.
incf fil_dsec_lb,F,BANKED ; setup for next data sector
btfsc STATUS,C,ACCESS ; carry on increment?
incf fil_dsec_hb,F,BANKED ; yes, fixup high byte for carry
; Zero the sector byte count.
clrf fil_sbwc_lb,BANKED
clrf fil_sbwc_hb,BANKED
; Send command to write the next data sector.
; setup sector number (LBA 7:0) register
movff fil_dsec_lb,cf_rw_snum ; data sector (lwlb)
; setup cylinder low (LBA 15:8) register
movff fil_dsec_hb,cf_rw_cyllo ; data sector (lwhb)
; setup comand register
movlw WR_SEC_CMD ; get write sector command value
movwf cf_rw_cmd,BANKED
call cf_sec_rw_cmd
cf_file_wbyte:
; We started writing to file when bank 4 was full. After we empty bank 4 we
; start on bank 5, etc. Continue emptying the current bank until it is empty
; before switching to the other bank.
; Determine which GPR bank we are currently emptying.
; bank4: 'fil_sbwc_hb' = 00; 'fil_sbwc_lb' = 00-FF
; bank5: 'fil_sbwc_hb' = 01; 'fil_sbwc_lb' = 00-FF
; rollover to 'fil_sbwc_hb' = 02; 'fil_sbwc_lb' = 00 (at completion of
; bank 5 is handled above)
;
movf fil_sbwc_hb,W,BANKED ; movf causes Z status update
btfss STATUS,Z,ACCESS ; 'fil_sbwc_hb' = 0?
goto current_bank5 ; No - so we are working bank 5
current_bank4:
btfss bank_4_full,0,ACCESS ; bank 4 full?
goto file_write_done ; No, so wait for data
; Bank 4 full, so work on emptying it.
movlw 0x04 ; setup indirect address to get data
movwf FSR0H,ACCESS ; byte from GPR bank
goto get_data
current_bank5:
btfss bank_5_full,0,ACCESS ; bank 5 full?
goto file_write_done ; No, so wait for data
; Bank 5 full, so work on emptying it.
movlw 0x05 ; setup indirect address to get data
movwf FSR0H,ACCESS ; byte from GPR bank
get_data:
movff fil_sbwc_lb,FSR0L ; counter 'fil_sbwc_lb' will run from 0-FFh
; twice, once for each bank
; Write byte of data to CF card instrumentation file.
movff INDF0,cf_io_data ; get the data byte from the GPR bank
clrf cf_io_reg,BANKED
call cf_write
; Increment count of bytes written to sector.
incf fil_sbwc_lb,F,BANKED
btfsc STATUS,C,ACCESS ; carry on increment?
incf fil_sbwc_hb,F,BANKED ; yes, fixup high byte for carry
; Increment count of bytes written to file.
incf fil_size_ll,F,BANKED
btfsc STATUS,C,ACCESS ; carry on increment?
incf fil_size_lh,F,BANKED ; yes, fixup high byte for carry
btfsc STATUS,C,ACCESS ; carry on increment?
incf fil_size_hl,F,BANKED ; yes, fixup high byte for carry
btfsc STATUS,C,ACCESS ; carry on increment?
incf fil_size_hh,F,BANKED ; yes, fixup high byte for carry
; Test to see if done emptying data bank.
movf fil_sbwc_lb,W,BANKED ; rollover from FFh to 00h?
btfss STATUS,Z,ACCESS ; low byte of counter = 00h?
goto file_write_done ; No, so we're done
; Done emptying GPR bank, clear 'buffer_x_full' flag for bank.
; If 'fil_sbwc_hb' = 01h we just finished bank 4
; If 'fil_sbwc_hb' = 02h we just finished bank 5
movlw 0x01
xorwf fil_sbwc_hb,W,BANKED
btfss STATUS,Z,ACCESS ; is 'fil_sbwc_hb' = 01h
goto clear_5 ; No, clear bank 5 flag
bcf bank_4_full,0,ACCESS ; Yes, clear bank 4 flag
goto file_write_done
clear_5:
bcf bank_5_full,0,ACCESS
file_write_done:
return
close_file:
; Perform CF Card instrumentation data file close and stop.
call cf_file_close
movlw FILE_FULL
call error_stop
;
cf_file_close:
;
; Update root directory and FATs with instrumentation file information.
; If user terminated instrumentation prior to first data byte being
; written to the file, do nothing, CF card file system remains with
; zero length for filename.
;
; Check if user requested instrumentation termination prior to any
; instrumentation data being collected. Test for filesize = 0.
clrf WREG,ACCESS
xorwf fil_size_ll,W,BANKED ; low:low byte=0?
btfss STATUS,Z,ACCESS
goto close_continue ; No, so something in file
xorwf fil_size_lh,W,BANKED ; low:high byte=0?
btfss STATUS,Z,ACCESS
goto close_continue ; No, so something in file
xorwf fil_size_hl,W,BANKED ; high:low byte=0?
btfss STATUS,Z,ACCESS
goto close_continue ; No, so something in file
xorwf fil_size_hh,W,BANKED ; high:high byte=0?
btfss STATUS,Z,ACCESS
goto close_continue ; No, so something in file
goto close_end ; Yes, filesize = 0
close_continue:
; Be sure last sector is full and therefore written.
btfsc fil_sbwc_hb,1,BANKED ; 511=1FFh, 512=200h so check bit 2
; of counter high byte
goto updt_directory ; Yes, continue to dir update
; Finish writing to last sector.
clrf inst_data_b,ACCESS ; finish by writing 0x00's
cf_close_finish:
; Write byte of data to instrumentation file.
movff inst_data_b,cf_io_data
clrf cf_io_reg,BANKED
call cf_write
; Increment count of bytes written to sector.
incf fil_sbwc_lb,F,BANKED
btfsc STATUS,C,ACCESS ; carry on increment?
incf fil_sbwc_hb,F,BANKED ; yes, fixup high byte for carry
; Full yet?
btfss fil_sbwc_hb,1,BANKED ; 511=1FFh, 512=200h so check bit 2
; of counter high byte
goto cf_close_finish ; No, continue to fill segment
; Increment count of file sectors.
incf fil_swrt_lb,F,BANKED ; inc count of sectors written
btfsc STATUS,C,ACCESS ; carry on increment
incf fil_swrt_hb,F,BANKED ; yes, fixup high byte for carry
updt_directory:
; Update root directory entry for instrumentation file.
call cf_close_dirupdt
; Update FAT1 & FAT2 with instrumentation file cluster chains.
call cf_close_clusupdt
close_end:
return
;
cf_setup_init:
;
; Load the CF card partition table info.
call cf_load_bootsec_parms
; Load the BIOS Parameter Block for card partition.
call cf_load_BIOS_parms
; Verify the card format is FAT16.
call cf_verify_FAT16
; Find the inst data file 'PIC_DATA.DAT' in the root directory.
call cf_find_file
; Verify the data file is empty.
call cf_verify_file_empty
; Compute the root directory size in sectors (needed for next computation).
call cf_comp_rootdir_size
; Compute sector number for first data sector of partition.
call cf_comp_1st_data_sect
return
;
;******************************************************************************
; 16-bit x 16-bit unsigned integer multiplication routine
;******************************************************************************
mult16x16U:
;
; Routine length 32 line; time 129 to 228 cycles
; This program looks at the lsb of a1 to decide whether to add b1 to prod_lwhb
; and b2 to prod_hwlb, with appropriate carrys.
; It then looks at the lsb of a2 to decide whether to add b1 to prod_hwlb and
; b2 to prod_hwhb, again with appropriate carrys.
; The rotates then only have to be done 8 times
;
; This is uses slightly more program but takes a little less time than
; a routine that performs one 16 bit addition per rotate and 16 rotates
;
; Code from malin@onspec.co.uk
; Multiple byte addition routine from Microchip AN617
; Result registers used as loop counter from Bob Fehrenbach & Scott Dattalo
;
movff BSR,bsr_temp ; save source BSR
; Set BSR to math variable bank
movlb MATH_GPR ; set BSR to math variable bank
; load multiplication operands
movff POSTINC0,a1 ; load multiplicand variable L:H
movff POSTINC0,a2
movff POSTINC1,b1 ; load multiplier variable L:H
movff POSTINC1,b2
clrf prod_hwhb,BANKED
clrf prod_hwlb,BANKED
clrf prod_lwhb,BANKED
movlw 0x80
movwf prod_lwlb,BANKED
nextbit:
rrcf a2,F,BANKED
rrcf a1,F,BANKED
btfss STATUS,C,ACCESS
goto nobit_l
movf b1,W,BANKED
addwf prod_lwhb,F,BANKED
movf b2,W,BANKED
btfsc STATUS,C,ACCESS
incfsz b2,W,BANKED
addwf prod_hwlb,F,BANKED
btfsc STATUS,C,ACCESS
incf prod_hwhb,F,BANKED
bcf STATUS,C,ACCESS
nobit_l:
btfss a1,7,BANKED
goto nobit_h
movf b1,W,BANKED
addwf prod_hwlb,F,BANKED
movf b2,W,BANKED
btfsc STATUS,C,ACCESS
incfsz b2,W,BANKED
addwf prod_hwhb,F,BANKED
nobit_h:
rrcf prod_hwhb,F,BANKED
rrcf prod_hwlb,F,BANKED
rrcf prod_lwhb,F,BANKED
rrcf prod_lwlb,F,BANKED
btfss STATUS,C,ACCESS
goto nextbit
; restore BSR
movff bsr_temp,BSR ; restore source BSR
return
;******************************************************************************
; 16-bit by 16-bit unsigned integer division routine
;******************************************************************************
div16by16U:
;
; Division : accB(16 bits) / accA(16 bits) -> accB(16 bits) with
; Remainder in accC (16 bits)
; (a) Load the Denominator in location accAhi & accAlo ( 16 bits )
; (b) Load the Numerator in location accBhi & accBlo ( 16 bits )
; (c) CALL D_div
; (d) The 16 bit result is in location accBhi & accBlo
; (e) The 16 bit Remainder is in locations accChi & accClo
;
; Performance :
; Program Memory : 037
; Clock Cycles : 310
;
movff BSR,bsr_temp ; save source BSR
; Set BSR to math variable bank
movlb MATH_GPR ; set BSR to math variable bank
; load division operands
movff POSTINC0,accAlo ; load denominator variable L:H
movff POSTINC0,accAhi
movff POSTINC1,accBlo ; load numerator variable L:H
movff POSTINC1,accBhi
movlw .16 ; for 16 shifts
movwf math_temp,BANKED
movff accBhi,accDhi ; move ACCb to ACCd
movff accBlo,accDlo
clrf accBhi,BANKED
clrf accBlo,BANKED
clrf accChi,BANKED
clrf accClo,BANKED
dloop:
bcf STATUS,C,ACCESS
rlcf accDlo,F,BANKED
rlcf accDhi,F,BANKED
rlcf accClo,F,BANKED
rlcf accChi,F,BANKED
movff accAhi,WREG
subwf accChi,W,BANKED ; check if a>c
btfss STATUS,Z,ACCESS
goto nochk
movff accAlo,WREG
subwf accClo,W,BANKED ; if msb equal then check lsb
nochk:
btfss STATUS,C,ACCESS ; carry set if c>a
goto nogo
movff accAlo,WREG ; c-a into c
subwf accClo,F,BANKED
btfss STATUS,C,ACCESS
decf accChi,F,BANKED
movff accAhi,WREG
subwf accChi,F,BANKED
bsf STATUS,C,ACCESS ; shift a 1 into b (result)
nogo:
rlcf accBlo,F,BANKED
rlcf accBhi,F,BANKED
decfsz math_temp,F,BANKED ; loop untill all bits checked
goto dloop
; restore BSR
movff bsr_temp,BSR ; restore source BSR
return
;******************************************************************************
; 16-bit - 16-bit unsigned integer subtraction routine
;******************************************************************************
sub16U:
;
; Subtraction: DST(16-bit) = DST(16-bit) - SRC(16-bit)
;
; DTS is replaced, SRC is preserved
; Carry is set correctly, Zero flag is not valid
;
movff BSR,bsr_temp ; save source BSR
; Set BSR to math variable bank
movlb MATH_GPR ; set BSR to math variable bank
; load division operands
movff POSTINC0,sub_dst_lb ; load minuend variable L:H
movff POSTINC0,sub_dst_hb
movff POSTINC1,sub_src_lb ; load subtrahend variable L:H
movff POSTINC1,sub_src_hb
; perform subtraction
movff sub_src_lb,WREG ; get low byte of subtrahend
subwf sub_dst_lb,F,BANKED ; subtract DST(low) - SRC(low)
movff sub_src_hb,WREG ; get high byte of subtrahend
btfss STATUS,C,ACCESS ; if there was a borrow, rather than
incf sub_src_hb,W,BANKED ; dec high byte of DST we inc SRC
subwf sub_dst_hb,F,BANKED ; sub high byte and we're done
; restore BSR
movff bsr_temp,BSR ; restore source BSR
return
;******************************************************************************
; 16-bit + 16-bit unsigned integer addition routine
;******************************************************************************
add16U:
;
; Addition: DST(16-bit) = DST(16-bit) + SRC(16-bit)
;
; DTS is replaced, SRC is preserved
; Carry is set correctly
;
movff BSR,bsr_temp ; save source BSR
; Set BSR to math variable bank
movlb MATH_GPR ; set BSR to math variable bank
; load division operands
movff POSTINC0,add_dst_lb ; load minuend variable L:H
movff POSTINC0,add_dst_hb
movff POSTINC1,add_src_lb ; load subtrahend variable L:H
movff POSTINC1,add_src_hb
; perform addition
movff add_src_lb,WREG ; get low byte of source
addwf add_dst_lb,F,BANKED ; add DST(low) + SRC(low)
movff add_src_hb,WREG ; get high byte of source
btfsc STATUS,C,ACCESS ; check for carry on low byte add
incf add_src_hb,W,BANKED ; inc high byte for carry
addwf add_dst_hb,F,BANKED ; add DST(high) + SRC(high)
; restore BSR
movff bsr_temp,BSR ; restore source BSR
return
end
**** Linker Script file ****// File: CF_DB_Inst.lkr
// Linker script for program CF_DB_Inst.ASM
LIBPATH .
CODEPAGE NAME=page START=0x0 END=0x7FFF
CODEPAGE NAME=idlocs START=0x200000 END=0x200007 PROTECTED
CODEPAGE NAME=config START=0x300000 END=0x30000D PROTECTED
CODEPAGE NAME=devid START=0x3FFFFE END=0x3FFFFF PROTECTED
CODEPAGE NAME=eedata START=0xF00000 END=0xF000FF PROTECTED
ACCESSBANK NAME=accessram START=0x0 END=0x7F
DATABANK NAME=gpr0 START=0x80 END=0xFF
DATABANK NAME=gpr1 START=0x100 END=0x1FF
DATABANK NAME=gpr2 START=0x200 END=0x2FF
DATABANK NAME=gpr3 START=0x300 END=0x3FF
DATABANK NAME=gpr4 START=0x400 END=0x4FF
DATABANK NAME=gpr5 START=0x500 END=0x5FF
ACCESSBANK NAME=accesssfr START=0xF80 END=0xFFF PROTECTED
SECTION NAME=acs_vars RAM=accessram
SECTION NAME=prog_vars RAM=gpr3
SECTION NAME=cfops_vars RAM=gpr3
SECTION NAME=pt_vars RAM=gpr3
SECTION NAME=bs_bio_vars RAM=gpr3
SECTION NAME=math_vars RAM=gpr3
SECTION NAME=pt_prm_tbl ROM=page
SECTION NAME=bs_prm_tbl ROM=page
SECTION NAME=pgm_strings ROM=page
**** PIC to CF Card Interface ****
CF-PIC Interface – Using PC Card Common Memory Mode
Pin Name Action
1 GND tie to ground
2-6 D03-D07 I/O, connect to PIC, PORTD[03:07]
7 -CE1 byte/word mode, connect to PIC, PORTC[0]
8 A10 tie to ground
9 -OE Output Enable strobe, connect to PIC, PORTC[1]
10-12 A09-A07 tie to ground
13 VCC tie to +5V
14-17 A06-A03 tie to ground
18-20 A02-A00 register address lines, connect to PIC, PORTE[0:2]
21-23 D00-D02 I/O, connect to PIC, PORTD[00:02]
24 WP leave unconnected
25 -CD2 leave unconnected
26 -CD1 CF Present, connect to PIC, PORTC[5], also to 10K resistor to +5V
27-31 D11-D16 leave unconnected
32 -CE2 byte/word mode, connect to +5V
33 -VS1 leave unconnected
34 -IORD leave unconnected
35 -IOWR leave unconnected
36 -WE I/O write strobe, connect to PIC, PORTC[2]
37 READY CF card ready for new cmd, connect to PIC, PORTC[3]
38 VCC connect to +5V
39 -CSEL tie to ground
40 -VS2 leave unconnected
41 RESET leave unconnected
42 -WAIT CF busy, connect to PIC, PORTC[6]
43 -INPACK leave unconnected
44 -REG tie to +5V
45 BVD2 leave unconnected
46 BVD1 leave unconnected
47-49 D08-D10 leave unconnected
50 GND tie to ground
+
| file: /Techref/member/RR-usa-P64/CF_INST.htm, 90KB, , updated: 2008/9/10 15:22, local time: 2025/10/25 04:41,
owner: RR-usa-P64,
216.73.216.180,10-8-63-169:LOG IN
|
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.org/techref/member/RR-usa-P64/CF_INST.htm"> Data logger, Microchip PIC, FLASH file system, FAT 16, CF Card Reader, CF Card</A> |
| Did you find what you needed? |