;------------------------------------------------------------------------------- ; shadow registers lastbank0 = $02 dataread = $fb datawrite0 = $fc datawrite1 = $fd ptr1 = $fe ;------------------------------------------------------------------------------- ; SPI lowlevel funtions spi_select: pha ; remember current bank lda GMOD3_BANK0 sta lastbank0 ; set bank to $ff so CS=1 lda #$ff sta GMOD3_BANK0 ; enable the SPI interface, disable cartridge rom lda #GMOD3_CTRL_BITBANG_ENABLED sta GMOD3_CTRL ; select the flash lda #GMOD3_SPI_W_CS_ACTIVE | GMOD3_SPI_W_CLK_LO | GMOD3_SPI_W_DATA_HI sta GMOD3_SPI_W pla rts spi_deselect: pha ; deselect the flash lda #GMOD3_SPI_W_CS_INACTIVE | GMOD3_SPI_W_CLK_LO | GMOD3_SPI_W_DATA_HI sta GMOD3_SPI_W ; disable the SPI interface lda #GMOD3_CTRL_BITBANG_DISABLED sta GMOD3_CTRL ; restore current bank lda lastbank0 sta GMOD3_BANK0 pla rts spi_read_byte: ; the flash shifts out a bit on the falling edge of CLK ldx #8 - ; clock 1->0 lda #GMOD3_SPI_W_CS_ACTIVE | GMOD3_SPI_W_CLK_LO sta GMOD3_SPI_W ; read one bit lda GMOD3_SPI_R and #GMOD3_SPI_R_DATA ; mask bit7 ; rotate into byte, LSB first rol ; bit7 into the carry rol dataread ; rotate into outbyte ; clock 0->1 lda #GMOD3_SPI_W_CS_ACTIVE | GMOD3_SPI_W_CLK_HI sta GMOD3_SPI_W dex bne - ; return the byte in A lda dataread rts spi_write_byte: pha sta datawrite0 lda #0 sta datawrite1 ; shift 5 times so the msb is at the right position in datawrite1 ldx #5 - rol datawrite0 rol datawrite1 dex bne - ldx #8 - ; clock 1->0 lda datawrite1 and #GMOD3_SPI_W_DATA ora #GMOD3_SPI_W_CS_ACTIVE | GMOD3_SPI_W_CLK_LO sta GMOD3_SPI_W ; clock 0->1 lda datawrite1 and #GMOD3_SPI_W_DATA ora #GMOD3_SPI_W_CS_ACTIVE | GMOD3_SPI_W_CLK_HI sta GMOD3_SPI_W rol datawrite0 rol datawrite1 dex bne - pla rts ;------------------------------------------------------------------------------- flash_wait_busy: jsr spi_select lda #FLASH_CMD_READ_STATUS jsr spi_write_byte ; lda #0 ; sta TIMER3 - ; lda TIMER3 ; cmp #100 ; 100*10ms = 1s ; bcs @timeout jsr spi_read_byte and #FLASH_STATUS_BUSY bne - ;timeout: jmp spi_deselect ; read manufacturer id/device id/capacity ; returns: ; A: manufacturer ID ($1c) ; X: device ID ($70) ; Y: capacity ($18/24 - 2^24, 16MB) flash_readid: jsr flash_wait_busy ; bcs timeout jsr spi_select lda #FLASH_CMD_REMS jsr spi_write_byte jsr spi_read_byte ; manufacturer id pha jsr spi_read_byte ; device id pha jsr spi_read_byte ; capacity pha jsr spi_deselect pla tay pla tax pla clc rts ;timeout: ; lda #OSERROR_TIMEOUT ; ldx #0 ; rts ;------------------------------------------------------------------------------- ; erase one 64k page ; A - page number flash_erase: pha jsr flash_wait_busy ; bcs timeout jsr spi_select lda #FLASH_CMD_WRITE_ENABLE jsr spi_write_byte jsr spi_deselect jsr spi_select lda #FLASH_CMD_BLOCK_ERASE jsr spi_write_byte pla jsr spi_write_byte lda #0 jsr spi_write_byte lda #0 jsr spi_write_byte jsr spi_deselect jsr flash_wait_busy ; bcs timeout ; ldx #0 ; txa rts ;timeout: ; lda #OSERROR_TIMEOUT ; ldx #0 ; rts addr0: !byte 0 addr1: !byte 0 addr2: !byte 0 ; erase the entire chip ; FIXME: actually use flash-erase command flash_chiperase: ldx #0 - txa pha jsr flash_erase pla tax inx bne - rts ;------------------------------------------------------------------------------- ; read one 256 byte page from flash ; addr0,addr1,addr2 - offset in the flash ; returns OSERROR_... error code in A, carry set on error flash_readpage: sta ptr1 stx ptr1+1 ; jsr popax ; sta addr1 ; stx addr2 ; lda #0 ; sta addr0 jsr flash_wait_busy ; bcs timeout jsr spi_select lda #FLASH_CMD_READ_DATA jsr spi_write_byte lda addr2 jsr spi_write_byte lda addr1 jsr spi_write_byte ;lda addr0 lda #0 jsr spi_write_byte ; read one 256 byte page ldy #0 - jsr spi_read_byte sta (ptr1),y iny bne - jsr spi_deselect ; lda #0 ; tax clc rts ;timeout: ; lda #OSERROR_TIMEOUT ; ldx #0 ; rts ;------------------------------------------------------------------------------- ; write one 256 byte page to flash ; A/X - pointer to data to be written ; addr0,addr1,addr2 - offset in the flash, addr0 should be 0 ; returns OSERROR_... error code in A, carry set on error flash_writepage: sta ptr1 stx ptr1+1 ; lda #0 ; sta addr0 jsr flash_wait_busy ; bcs timeout jsr spi_select lda #FLASH_CMD_WRITE_ENABLE jsr spi_write_byte jsr spi_deselect jsr spi_select lda #FLASH_CMD_PAGE_PROGRAM jsr spi_write_byte lda addr2 jsr spi_write_byte lda addr1 jsr spi_write_byte ; lda addr0 lda #0 jsr spi_write_byte ldy #0 - lda (ptr1),y jsr spi_write_byte iny bne - jsr spi_deselect jsr flash_wait_busy ; bcs timeout ; lda #0 ; tax rts ;timeout: ; lda #OSERROR_TIMEOUT ; ldx #0 ; rts