CON {{ SDSPI driver for P2-ES ASM RC4 - SMARTPINS! SDSPI ASM for P2 v_0_1_0 by Cheezus Slice - Joe Heinz - 2019 Cheezus Slice (Joe Heinz) - July - 2019 cheezusslicedj@gmail.com Thanks to all those out there in fourm land! Original spin version by Radical Eye Software Copyright 2008 }} sectorsize = 512 spi_clk_max = 25_000_00 ' 20mhz safe spi_clk_inv = 1 ' 1 inverted, 0 non-inverted VAR byte cog PUB HOOK ' test compile 'start_explicit( 3, 2, 1, 0 ) PUB Stop if cog cogstop(cog-1) cog := 0 PUB start_explicit( _DO, _CLK, _DI, _CS ) : card_type | domask, dimask stop cmd := "i" 'set flag to know if the started cog has read its parameters arg1 := _DO | (_CLK << 8) + (_DI << 16) + ( _CS << 24)' pins arg2 := getmask(_CLK, _DO) + (getmask(_CLK, _DI) << 4) ' clock masks arg2 += spi_clk_inv << 8 ' clock invert arg3 := GetBitTime(spi_clk_max) ' spi bit time err := GetBitTime(400_000 ) '400k cog := cognew(@_asm_start,@cmd) + 1 'coginit(16,@_asm_start,@cmd)+1' if cog repeat until cmd <> "i" ' wait until cog is done reading parameter card_type := err ' arg5 returns card type or returns with error from low level driver PUB ReadBlock(n, b) return DoCommand("r", n, b, 0) PUB WriteBlock(n, b) return DoCommand("w", n, b, 0) PUB release ' return DoCommand("z",0,0,0) ' need to think about this! PUB GetCog return cog PRI GetBitTime(max_clkfreq) : bt bt :=((clkfreq / max_clkfreq) /2 )+1 ' SPI bit time if bt < 2 ' make sure at least sysclock /2 bt := 2 PRI DoCommand(_cmd, _arg1, _arg2, _arg3) repeat while cmd <> 0 arg1 := _arg1 arg2 := _arg2 arg3 := _arg3 cmd := _cmd repeat until cmd <> _cmd return err PRI getmask(clk, data) : t t := (clk - data) & %0111 't := clk - data 'if ( || t ) <> t ' t := ( || t ) + %0100 DAT org _asm_start mov ptr_to_mbox, ptra ' save mbox address for later '' get parameters from spin get_cmd rdlong cmd_in, ptra wz ' '' timeout and release card after 10s if_z jmp #get_cmd ' no cmd so handle time rdlong arg1_in, ++ptra rdlong arg2_in, ++ptra rdlong arg3_in, ++ptra rdlong err_out, ++ptra ' dummy read to align err pointer '' decode command cmp cmd_in, #"i" wz if_z jmp #do_init cmp cmd_in, #"c" wz if_z call #card_init cmp cmd_in, #"r" wz if_z jmp #read_a cmp cmd_in, #"w" wz if_z jmp #write_b ' cmp cmd_in, #"z" wz ' if_z jmp #release mov err_out, #5 ' err = no command ' '' do commands end_cmd drvh pinCS ' set cs high wrlong err_out, ptra mov cmd_in, #0 ' signal done to spin driver mov ptra, ptr_to_mbox ' return ptra back to mbox wrlong cmd_in, ptr_to_mbox jmp #get_cmd do_init getbyte pinDO, arg1_in, #0 getbyte pinCLK, arg1_in, #1 getbyte pinDI, arg1_in, #2 getbyte pinCS, arg1_in, #3 getnib sp_doclk, arg2_in, #0 getnib sp_diclk, arg2_in, #1 getnib sp_inv_pin, arg2_in, #2 shl sp_doclk, #24 shl sp_diclk, #24 shl sp_inv_pin, #14 mov sp_bt, arg3_in ' get max clock mov sp_init_bt, err_out ' get 400k clock mov err_out, #0 ' err = no error rdlong delay1s, #$14 ' clkfreq from hub dirl pinCLK '' setup Clock pin mov spare, ##sp_clk ' transition add spare, sp_inv_pin ' invert clock wrpin spare, pinCLK ' set clock mode wxpin sp_init_bt, pinCLK ' set base period (*2) dirh pinCLK ' enable clk dirl pinDI '' setup DI pin mov spare, ##sp_stx ' sync tx add spare, sp_diclk ' setup bpin wrpin spare, pinDI ' set di mode wxpin #sp_stx_c, pinDI ' set di config dirh pinDI ' enable smartpin wypin #$FF, pinDI ' prime shifter dirl pinDO '' setup DO pin mov spare, ##sp_srx ' sync rx add spare, sp_doclk ' setup bpin wrpin spare, pinDO ' set do mode wxpin #sp_srx_c, pinDO ' set do config dirh pinDO ' enable pin call #card_init jmp #end_cmd read_a '' arg1 is sd ptr, arg2 is hub mov cmdout, #17 ' command = block read shr arg1_in, blocksh ' non-hc compatibility mov cmdpar, arg1_in ' sd block address getct timeout ' setup 1s timeout addct1 timeout, delay1s ' in case card does not respond call #do_sdcmd call #read_resp mov ptrb, arg2_in mov spare, ##sectorsize .loop call #read_byte wrbyte reply, ptrb++ djnz spare, #.loop call #read_byte call #read_byte jmp #end_cmd write_b '' arg1 is sd ptr, arg2 is hub mov cmdout, #24 ' command = block write shr arg1_in, blocksh ' non-hc compatibility mov cmdpar, arg1_in ' sd block address getct timeout ' setup 1s timeout addct1 timeout, delay1s ' in case card does not respond call #do_sdcmd mov dataout, #$fe call #send_byte mov ptrb, arg2_in mov spare, ##sectorsize .loop rdbyte dataout, ptrb++ call #send_byte djnz spare, #.loop call #read_byte call #read_byte call #read_resp and reply, #$1f cmp reply, #5 wz if_nz mov err_out, ##-42 ' err = bwrite timeout call #sd_busy jmp #end_cmd card_init drvh pinCS ' set cs high wypin ##sectorsize, pinCLK ' set init clocks call #wait_clock ' wait for smartpins to finish dirl pinCLK '' setup Clock pin wxpin sp_bt, pinCLK ' set base period (*2) dirh pinCLK ' enable clk mov cmdout, #0 ' cmd 0,0 mov cmdpar, #0 getct timeout ' setup 1s timeout addct1 timeout, delay1s ' in case card does not respond call #do_sdcmd drvh pinCS ' set cs high mov cmdout, #8 ' cmd 8, $1aa mov cmdpar, #$1AA call #do_sdcmd call #read_byte ' read 32 bit call #read_byte call #read_byte call #read_byte drvh pinCS ' set cs high .cmd55 mov err_out, ##-40 ' err = card won't init mov cmdout, #55 ' cmd 55,0 mov cmdpar, #0 call #do_sdcmd mov cmdout, #41 ' cmd 41, $4000_0000 mov cmdpar, ##$4000_0000 ' call #do_sdcmd drvh pinCS ' set cs high cmp reply, #$01 wz ' 01 = idle if_z jmp #.cmd55 mov cmdout, #58 ' cmd 58, 0 mov cmdpar, #0 call #do_sdcmd call #read_byte testb reply, #6 wz if_nz mov blocksh, #9 ' sd support if_nz mov err_out, #1 ' sd support, return card type 1 ' if_nz jmp #end_cmd ' don't support SD, SDHC only if_z mov blocksh, #0 ' sdhc if_z mov err_out, #2 ' return card type 2 call #read_byte call #read_byte call #read_byte drvh pinCS ' set cs high mov cmdout, #16 ' cmd 16, $200 mov cmdpar, ##$200 call #do_sdcmd card_init_ret ret do_sdcmd '' OP is cmdout, parm = cmdpar drvl pinCS call #read_byte mov dataout, cmdout add dataout, #$40 call #send_byte getbyte dataout, cmdpar, #3 call #send_byte getbyte dataout, cmdpar, #2 call #send_byte getbyte dataout, cmdpar, #1 call #send_byte getbyte dataout, cmdpar, #0 call #send_byte cmp cmdout, #0 wz if_z mov dataout, #$95 if_nz mov dataout, #$87 call #send_byte call #read_resp do_sdcmd_ret ret send_byte SHL dataout, #32-8 ' Set MSB First REV dataout ' Set MSB First wypin dataout, pinDI ' data !! rdpin pa, pinCLK wypin #byteclks, pinCLK ' start clock, tx data call #wait_clock wypin #$FF, pinDI send_byte_ret ret read_byte rdpin pa, pinCLK wypin #byteclks, pinCLK ' start clock call #wait_clock rdpin reply, pinDO ' get data rev reply and reply, #$ff read_byte_ret ret sd_busy call #read_byte cmp reply, #0 wz if_z call #check_time if_z jmp #sd_busy sd_busy_ret ret read_resp call #read_byte cmp reply, #$ff wz if_z call #check_time if_z jmp #read_resp read_resp_ret ret check_time pollct1 wc if_c mov err_out, ##-41 ' err = timeout if_c jmp #end_cmd check_time_ret ret wait_clock testp pinCLK wc if_nc jmp #wait_clock wait_clock_ret ret buff res 128 ' save 512 longs for block buffer (LUTS) ' loaded on init ''15 longs CHZ code {=== Pin Variables ===} pinDO res 1 ' do pinCLK res 1 ' clk pinDI res 1 ' di pinCS res 1 ' chip select {===== Smartpin Clock Variables =====}'' smartpins stuffs sp_doclk res 1 ' smartpin mask for clock to do sp_diclk res 1 ' smartpin mask for clock to di sp_bt res 1 ' bit time sp_init_bt res 1 ' bit time @400k sp_inv_pin res 1 ' invert clock pin {===== Command Mailbox =====} ptr_to_mbox res 1 ' pointer to spin mailbo cmd_in res 1 ' mailbox in arg1_in res 1 arg2_in res 1 arg3_in res 1 err_out res 1 {=== Timing Variables ===} delay1s res 1 ' clkfreq = 1 s FIT $1C0 ''============[ COG VARIABLES - SD BOOT ROM A]======================================== org $1C0 ' place the variables in cog $1C0-$1DF cmdout res 1 ' The 8b CMDxx | $40 cmdpar res 1 ' The 32b parameters cmdcrc res 1 ' The 8b CRC (must be valid for CMD0 & CMD8) cmdpar2 res 1 ' SDV1=$0, SDV2=$40000000 cmdtype res 1 ' reply is R1=1, R3=3, R7=7, else 0 reply res 1 ' R1 reply (moved to replyR1 when R3/R7 32b reply here) replyR1 res 1 ' R1 reply (8b saved when R3/R7 32b reply follows) dataout res 1 ' 8/32 bit data being shifted out bytescnt res 1 ' #bytes to send/recv bitscnt res 1 ' #bits to be shifted in/out ctr1 res 1 timeout res 1 ' = starttime + delay spare res 1 skiprun res 1 ' 1= skip load/run mbr/vol & load/no-run fname '\ 1=SDV1, 2=SDV2(byte address), 3=SDHC/SDV2(block address) blocksh res 1 '/ block shift 0/9 bits clustersh res 1 ' sectors/cluster SHL 'n' bits vol_begin res 1 '$0000_2000 ' Ptn0: first sector of PTN fsi_begin res 1 '$0000_2001 ' Ptn0: sector of file system info fat_begin res 1 '$0000_3122 ' Ptn0: first sector of FAT table dir_begin res 1' $0000_4000 ' Ptn0: first sector of DATA is DIR table dat_begin res 1 '$0000_4580 $0000_54C0' Ptn0: first sector of file's DATA ptn_size res 1 '$0008_0000 ' file-size 32KB = 64<<9 sectors _bufad res 1 _blocknr res 1 _sectors res 1 _entries res 1 bufad res 1 ' ptr sector buffer blocknr res 1 ' sector# fname res 3 ' 8+3+1 _hubdata res 1 FIT 496 dat '' singleton spin mailbox alignl cmd long 0 arg1 long 0 arg2 long 0 arg3 long 0 err long 0 { var '' multi spin mailbox long cmd, arg1, arg2, arg3, arg4, err } con smartpin_constants '%AAAA_BBBB_FFF_PPPPPPPPPPPPP_TT_MMMMM_0 ''PPPP_PPP_PPP_PPP 'ppp =''xxxx_CIO_HHH_LLL 'sp_inv_pin = %0000_001_000_000 << 8 'smartpin modes TT_MMMMM_0 sp_stx = %01_11100_0 ' +2 sp_srx = %00_11101_0 ' +3 sp_srx_c = %1_00111 sp_stx_c = %1_00111 sp_clk = %01_00101_0 '+ sp_inv_pin ' inv clock right way byteclks = (2*8)