📄 smc_dtc_upload.fsm
字号:
;===================================================================
;
; SMART MEDIA CARD
;
;===================================================================
;------------
; smc_dtc_up
;------------
;------------------------------------------------------------------
; START ADDRESS FOR read data to USB
; ST7: Give a 3 or 4 bytes address, number of pages
; 0x1632 - 0x1635 = The address, big endien (0x00E2-0x00E5)
; 0x163F = Number of pages (counter), it should be 0 on exit
; On return: Counter = 0 means no error
; Counter !=0 means ECC error on that page
;------------------------------------------------------------------
:init_command_address
LD MSB 1 ; data_flash port = output
LD LSB 9 ; DATA_FLASH Port driven by FCI
LD CTRL_FCI ; PARALLEL Port driven by FCI
LD MSB 0
LD LSB 15
LD DDR_PARALLEL ; PA3-0 as output, PA4 as input
LD OR_PARALLEL ; PA3=/RD, PA2=ALE, PA1=/WE, PA0=CLE
; PA4=R/B
LD MSB 15
LD MASK ; MASK = 0xFF
XOR ; A = 0
LD ADR_BUFFER01 ; clear the high byte of ADR0
LD DATA_FLASH ; command Read(1), sequential read
LD LSB 1
LD X ; X = 1
LD ADR_BUFFER11
;;; Output the sequential read command (0x00)
LD LSB 10
LD DR_PARALLEL ; WE = 1, CLE = 0
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 9
LD DR_PARALLEL ; WE = 0, CLE = 1
LD LSB 11
LD DR_PARALLEL ; WE = 1, CLE = 1
LD LSB 10
LD DR_PARALLEL ; WE = 1, CLE = 0
;--------------------------------------------------
; START ADDRESS FOR address_latch_cycle
;--------------------------------------------------
LD MSB 14
LD LSB 06
LD ADR_BUFFER00 ; buffer pointer 0 = 0x00E6
LD A DATA_BUFFER0
LD Y ; Y = number of address bytes
DECY
LD LSB 12
LD CMP01 ; CMP01 = 12, for send address toggling lines
LD LSB 14
LD DR_PARALLEL ; ALE = 1, WE = 1
LD A ADR_BUFFER01 ; clear A as the first byte, it is always 0
LD ADR_BUFFER10 ; clear low byte of ADR1
LD CMP10 ; clear low byte of CMP1
LD BUFFER_MNGT ; clear SEGment offset for using Y on ECC check
:loop_send_address
;-----------------
SUB16 ADR_BUFFER0 ; send address from high byte to low byte
LD DATA_FLASH ; Output the address bytes
LD A CMP01
LD DR_PARALLEL ; ALE = 1, WE = 0
LD LSB 14
LD DR_PARALLEL ; ALE = 1, WE = 1
LD A DATA_BUFFER0
DECY
JP :loop_send_address
LD MSB 0
LD LSB 10
LD DR_PARALLEL ; ALE = 0, WE = 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Start to read one page
;; 1. Test the READY/BUSY line is ready
;; 2. Wait one of the buffer is free
;; 3. Read the page data
;; 4. Check the ECC
;; 5. Submit the buffer to send the page data
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
:Wait_SMC_Ready
;--------------
LD A ADR_BUFFER01
LD CMP01
LD LSB 2
LD CMP00 ; CMP0 = 0x0002, will use for RD toggling
LD ADR_BUFFER00 ; buffer pointer 0 = 0x0002
;;; Reset the ECC calculation machine
; LD MSB 0 ; data_flash port = intput
LD LSB 9 ; DATA_FLASH Port driven by FCI
LD CTRL_FCI ; PARALLEL Port driven by FCI
LD MSB 2 ; ECC Mode & Reset TMP Reg
LD CTRL_FCI ; PARALLEL Port driven by FCI
:wait_ready_line
;---------------
ADDER16 ADR_BUFFER0
CP ADR_BUFFER0=>CMP0
JP :test_busy_line
; the waiting loop is timeout
STATUS STOP ERROR ; return with error
:test_busy_line
;--------------
LD A DR_PARALLEL
EXCHANGE
BCLR1
JP :wait_ready_line
:Init_Page_Reading
;----------------- ; Initialize ADR0 for read ECC
LD A ADR_BUFFER10
LD ADR_BUFFER01 ; clear high byte of pointer 0
LD MSB 15
LD LSB 8
LD ADR_BUFFER00 ; ADR0 = 0x00F8, points the ECC memory
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Test and wait one of the buffer is full
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LD A ADR_BUFFER11
BSET2
JP :wait_buffer1_full
LD LSB 1
LD ADR_BUFFER11 ; buffer pointer 1 = 0x0100
:wait_buffer0_full
;-----------------
LD A BUFFER_MNGT
BSET3
JP :wait_buffer0_full
JP :read_one_page
:wait_buffer1_full
;-----------------
LD A, BUFFER_MNGT
BSET4
JP :wait_buffer1_full
:read_one_page
;-------------
LD A ADR_BUFFER10
LD Y ; Clear Y
:read_256_bytes
;--------------
LD LSB 2
LD DR_PARALLEL ; RD = 0; WE = 1; ALE=CLE=0
LD LSB 10
LD DR_PARALLEL ; RD = 1; WE = 1; ALE=CLE=0
LD A DATA_FLASH ; Get the reading data byte
LD DATA_BUFFER1 ; Save it in the buffer
LD ECC_CRC ; Load to ECC_CRC REG
LD A ECC_CRC ; AUTO UPDATE OF Line PARITY 1
LD A ECC_CRC ; AUTO UPDATE OF Line PARITY 2
LD A ECC_CRC ; AUTO UPDATE OF column PARITY
ADDER16 ADR_BUFFER1
INCY
JP :read_256_bytes
;-------------------
; Save the calculated ECC to 0xF8, 0xF9, 0xFA -- 0xFB, 0xFC, 0xFD
;-------------------
:read_ecc_calcul
LD A TMP_ECC ; first read (Line parity 1)
LD DATA_BUFFER0
LD A ECC_CRC ; -- INCR CRC_ECC_STATE --
ADDER16 ADR_BUFFER0
LD A TMP_ECC ; second read (Line parity 2)
LD DATA_BUFFER0
LD A ECC_CRC ; -- INCR CRC_ECC_STATE --
ADDER16 ADR_BUFFER0
LD A TMP_ECC ; third read ( column parity)
LD DATA_BUFFER0
ADDER16 ADR_BUFFER0
LD A ADR_BUFFER11 ; The value can be 0010, 0011, 0100, 0101
BCLR1
JP :read_256_bytes
;---------------------------------------------
; Read 16 bytes of redundant area from the SMC
; They will be saved in 0xE7-0xF6
;---------------------------------------------
:init_read_spare
LD LSB 15
LD Y ; Y = 15
LD MSB 14
LD LSB 06
LD ADR_BUFFER00 ; ADR0 = 0x00E6,
; points to one byte before spare area
:read_spare
;----------
ADDER16 ADR_BUFFER0
LD LSB 2
LD DR_PARALLEL ; RD = 0; WE = 1; ALE=CLE=0
LD LSB 10
LD DR_PARALLEL ; RD = 1; WE = 1; ALE=CLE=0
LD A DATA_FLASH ; Save one byte of redundant area
LD DATA_BUFFER0
DECY
JP :read_spare
;------------------------------------------------------
; Check the calculated ECC againest with redundant area
;------------------------------------------------------
:init_ecc2_check
;---------------
LD MSB 15
LD LSB 10
LD Y ; Y = 0xFA, points to ECC2[2]
LD LSB 4
LD CMP00 ; CMP0 = 0x00F4
:ecc2_check
;----------
LD A DATA_BUFFER0 ; ADR0 = spare area = 0x00F6, 0x00F5, 0x00F4
LD MASK
LD A <Y> ; Y = 0xFA, 0xF9, 0xF8
XOR
CP A=>X
JP :ecc_error
SUB16 ADR_BUFFER0
DECY
CP ADR_BUFFER0=>CMP0
JP :ecc2_check
:init_ecc1_check
;---------------
LD MSB 15
LD LSB 13
LD Y ; Y = 0xFD, points to ECC1[2]
LD LSB 0
LD CMP00 ; CMP0 = 0x00F0
SUB16 ADR_BUFFER0 ; buffer pointer 0 = 0x00F2
:ecc1_check
;----------
SUB16 ADR_BUFFER0
LD A DATA_BUFFER0 ; buffer pointer 0 = 0x00F1, 0x00F0, 0x00EF
LD MASK
LD A <Y> ; Y = 0xFD, 0xFC, 0xFB
XOR
CP A<X
JP :no_ecc_error
:ecc_error
;---------
STATUS STATUS STOP
:no_ecc_error
;------------
DECY
CP ADR_BUFFER0=>CMP0
JP :ecc1_check
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; After the ECC check is verified. Submit the buffer read
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
LD A ADR_BUFFER11 ; The value is either 0011 or 0101
BSET3
JP :Set_buffer1_full
:Set_buffer0_full
;----------------
LD LSB 1
JP :Set_Buffer_Full
:Set_buffer1_full
;----------------
LD LSB 2
:Set_Buffer_Full
;---------------
LD BUFFER_MNGT
LD LSB 0
LD BUFFER_MNGT
:next_page
;---------
LD MSB 15
LD LSB 15
LD MASK
LD ADR_BUFFER00 ; buffer pointer 0 = 0x00FF, points the counter
LD A DATA_BUFFER0
CLC
SUB8 X
LD DATA_BUFFER0 ; update the page counter
CP A=>X
LD MSB 3
LD LSB 3
BRANCH :Wait_SMC_Ready
:all_pages_read
;--------------
; ** LD A BUFFER_MNGT ; wait for 2 buffers are free
; ** BSET3
; ** JP :all_pages_read
; ** BSET4
; ** JP :all_pages_read
STATUS STOP ; FINISH SUCCESSFULLY!
;------------------------------------------------------------------
; START ADDRESS FOR read data FF to USB
; ST7: Give number of pages
; 0x163F = Number of pages (counter), it should be 0 on exit
; On return: Counter = 0 means no error
; Counter !=0 means ECC error on that page
;------------------------------------------------------------------
LD MSB 0
LD LSB 0
LD ADR_BUFFER10 ; low byte of pointer 1
LD ADR_BUFFER01 ; high byte of pointer 0
LD CMP10
LD LSB 1
LD ADR_BUFFER11 ; ADR1 = 0x0100
LD X ; X = 1
LD LSB 5
LD CMP11 ; CMP1 = 0x0500
LD MSB 15
LD LSB 15
LD ADR_BUFFER00 ; ADR00 = 0x00FF
:fill_buffer_with_FF
LD DATA_BUFFER1
ADDER16 ADR_BUFFER1
CP ADR_BUFFER1<CMP1
JP :fill_buffer_with_FF
LD A DATA_BUFFER0
LD Y ; load the page counter
:FFsend_2_pages
;--------------
DECY
JP :FFwait_for_buffer_0
JP :FF_finish
:FFwait_for_buffer_0
;-----------------
LD A BUFFER_MNGT
BSET3
JP :FFwait_for_buffer_0
LD LSB 1
LD BUFFER_MNGT ; mark buffer0 full
LD LSB 0
LD BUFFER_MNGT ; mark buffer0 full
DECY
JP :FFwait_for_buffer_1
:FF_finish
INCY
LD A Y
LD DATA_BUFFER0 ; clear the page counter
STATUS STOP
:FFwait_for_buffer_1
;-----------------
LD A BUFFER_MNGT
BSET4
JP :FFwait_for_buffer_1
LD LSB 2
LD BUFFER_MNGT ; mark buffer1 full
LD LSB 0
LD BUFFER_MNGT ; mark buffer1 full
JP :FFsend_2_pages
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -