Port pinout use: ;* SPI: C0=CS, C1=SCLK, C2=SDIn, C3=SDOut (module referenced) * inidur equ.b $20 ;VM sense loop delay btw reads ;* SPI support sCl equ.b 1 ;clock (uC output) sDI equ.b 2 ;data into module (uC output) sDO equ.b 3 ;data out of module (uC input) sCS equ.b 0 ;chip select (uC output) ;* VMusic2 support, all are short commands & end w/ vdir equ.b $01 ;get current directory v3a equ.b $21 ;play all vrr equ.b $8f ;play random vcd equ.b $02 ;chg dir vpf equ.b $1d ;play file vrd equ.b $04 ;read file vst equ.b $20 ;stop vsb equ.b $26 ;skip backward vsf equ.b $25 ;skip forward vp equ.b $8b ;pause vsc equ.b $10 ;shortened command set prmpt equ.b '>' ;cmd complete: ">", cr equ.b $0d ;carriage return lf equ.b $0a ;line feed, separator in index.txt bfrlen equ.b 400 ;ASCII dir/filename buffer 50 max lstend equ.b $aa ;list end flag vmccnt equ.b $60 ;VM cmd wait count vmlcnt equ.b $08 ;VM line wait count timupr equ.w $0006 ;play timer "skip" limit ;************************************************************** ;* Assign all storage ;************************************************************** ;* SPI support vmcdl ds.b 1 ;Command Delay tank vmldl ds.b 1 ;Line Delay tank plaflg ds.b 1 ;playing/stopped(0) pauflg ds.b 1 ;paused/not(0) pa_flg ds.b 1 ;play all/not(0) dirflg ds.b 1 ;directory/file list(0) curidx equ * ;current index in bfr curixH ds.b 1 curixL ds.b 1 spiflg ds.b 1 ;status / data(0) flag chrtnk ds.b 1 ;8 bits to/from VM module vmwtk1 ds.b 1 ;VM LONG wait count tank vmwtk0 ds.b 1 ;VM wait count tank msgbfr ds.b 16 ;play timer msg area & dump tank idxszH ds.b 1 ;index.txt file size idxszL ds.b 1 ; bfrlen is limit (uses end flag) dbIctr ds.b 1 ;debounce Inactive counter dbItnk ds.b 1 ;debounce tank timbnd ds.b 2 ;timer upper boundary timprv ds.b 2 ;most recent timer value curmin ds.b 1 ;current play minute on display timcnt equ * ;16 bit of play timer gptnk ds.b 1 ;gen purp tank genctr ds.b 1 ;general counter/tank ;* port C SPI: b0=CS, b1=clk, b2=sdin, b3=sdout mov #$00,PTCD ;init all idle mov #$f7,PTCDD ;init all outputs, exc b3 mov #%00110010,TPM1SC ;rst+stop tmr, no INTs, presc=busclk/4 clr vmwtk1 ;init long count tank for std wait clr plaflg ;init as Stopped clr pauflg ;init as Not Paused clr pa_flg ;init as not PlayAll mov #dbIcnt,dbItnk ;init debounce tank mov #$aa,dirflg ;init to directory list lda #lstend sta namend ;put list end flag @ bfr end mov #vmccnt,vmcdl ;CMD delay init mov #vmlcnt,vmldl ;LINE delay init ;* Init VMusic: purge all pwr up msgs, sync THEN set short cmds w/Ascii jsr VM_SCS ;set for Short Commands IniVMP: jsr SPIRxD ;get a chr tst spiflg beq IniPCk ;bfr not empty, chk for prompt mov #cr,chrtnk ; else, send a & chk again jsr SPITxD bra IniVMP IniPCk: lda chrtnk cmp #'>' ;get until ">" of "D:\>" bne IniVMP jsr VMPurg ; then dump read bfr jsr VM_SCS ;set for Short Commands jsr BfrBnk ;blankout name buffer jsr VMDir ;load bfr w/root directories ldhx #Blank jsr Lcd_Rt ;blankout right ;************************************************************** ;* VMusic routines: ;* Play file name on upper display line=current index VMPlay: mov #vpf,chrtnk ;send Play File jsr SPITxD mov #' ',chrtnk jsr SPITxD jsr VM_CDl ;Cmd delay ldhx curidx mov #8,genctr ;max 8 chr name VMP_NS: lda ,x ;get file name chr cmp #' ' ;if=' ': go send ".MP3" beq VMPExt ;dump space padding sta chrtnk ;xfr for send jsr SPITxD ; else send aix #1 ; inc name index dbnz genctr,VMP_NS ; and chk/send another VMPExt: mov #'.',chrtnk ;send ".MP3" jsr SPITxD ; =only allowed file type mov #'M',chrtnk jsr SPITxD mov #'P',chrtnk jsr SPITxD mov #'3',chrtnk jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send jsr VM_LDl ;Cmd delay rts VM_RD: mov #vrd,chrtnk ;send Read jsr SPITxD ; read "index.txt" file mov #' ',chrtnk jsr SPITxD jsr VM_CDl ;Cmd delay ldhx #IdxNam ;ROM name mov #9,genctr ;file name length VMR_DS: mov x+,chrtnk ;get file name chr jsr SPITxD ; send dbnz genctr,VMR_DS ; and send another mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts VM_CD: mov #vcd,chrtnk ;send Chg Dir jsr SPITxD mov #' ',chrtnk jsr SPITxD jsr VM_CDl ;Cmd delay ldhx curidx mov #8,genctr ;max 8 chr name VMP_DS: lda ,x ;get file name chr cmp #' ' ;if=' ': go send beq VM_CDx ;dump space padding sta chrtnk ;xfr for send jsr SPITxD ; else send aix #1 ; inc name index dbnz genctr,VMP_DS ; and chk/send another VM_CDx: mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts ;* Get & filter current directory for all subdirectories VMDir: jsr VMPurg jsr VM_Dir ;send Dir cmd jsr VM_LDl ; and go wait jsr VMRead ldhx #nambfr ;set buffer index @ base sthx curidx ;set previous index=1st of current line VMGLDy: jsr VM_CDl VMGDir: jsr VM_BDl jsr SPIRxD ;get a chr lda ,x ;end stop chk cmp #$aa ;bfr end stop? beq VMGXit ;direct exit, only displays top N tst spiflg bne VMGXit lda chrtnk cmp #'>' beq VMGXit cmp #cr beq VMGDCn mov chrtnk,x+ bra VMGDir VMGDCn: aix #-4 ;either "." of ".xxx" OR " " of " DIR" lda ,x cmp #'.' ;if ".xxx": it's a file, ignore it bne VMGNaF ldhx curidx ;reset index to overwrite this line bra VMGLDy ;get another line VMGNaF: txa ;get low byte of current index sub curixL ; suboff previous sta gptnk ;temp save lda #8 ;constant name length sub gptnk ;A=# spaces to pad name, if any mov #' ',gptnk ;load " " VMDPad: sthx curidx ;save as new previous, B4 pad count test tsta beq VMGLDy ;directory name normalized, get another mov gptnk,x+ ;pad a space deca bra VMDPad ;pad out to 8 chrs VMGXit: lda #$aa ; sta ,x ;set new list end flag ;* root directories in name buffer, only directories, all 8 chrs long jsr VMPurg rts ;* Get & filter files in current directory for only ".MP3" type VMGFil: lda #lstend sta namend ;put last end flag @ bfr end ldhx #nambfr ;set buffer index @ base sthx curidx ;set index=1st line VMFGaF: mov #9,gptnk ;get a filename: load name length limit VMFWLp: jsr VM_LDl ;Line delay between names VMFGaB: jsr VM_BDl ;short delay btw byte reads jsr SPIRxD ;get a byte lda chrtnk ;get it cmp #'>' ;prompt? beq VMFXit ;=">": overstuff ">" w/endflag & exit tst spiflg ;bfr Ok: proc name chr beq VMFCon ;empty buffer, wait until # entries=0 tst genctr ;number of files >0: wait & try again bgt VMFWLp bra VMFXit ;=0: direct exit VMFCon: lda ,x ;end stop chk cmp #$aa ;bfr end stop? beq VMFXit ;direct exit, only displays top N lda chrtnk cmp #lf ;if , process name length beq VMFllp ; and pad to 8 if Nec cmp #cr ;if , ignore/get another () beq VMFGaB sta ,x ; else put to bfr aix #1 ; and inc index dbnz gptnk,VMFGaB ; and get another mov #'~',gptnk ;@ 9th name chr: chg 7&8->"~1" aix #-3 mov gptnk,x+ mov #'1',gptnk mov gptnk,x+ VMFLTr: jsr VM_BDl ;Byte delay btw reads jsr SPIRxD ;get a byte tst spiflg ;empty read bfr: direct exit bne VMFXit ; to set new list end flag lda chrtnk cmp #lf ;on long names: eat until bne VMFLTr dec genctr ;1 fewer entries to get sthx curidx ;save new index bra VMFGaF ;now, @ line end, get another VMFllp: txa ;get low byte of current index sub curixL ; suboff previous sta gptnk ;temp save lda #8 ;constant name length sub gptnk ;A=# spaces to pad name, if any mov #' ',gptnk ;load " " VMFPad: dec genctr ;1 fewer entries to get sthx curidx ;save new index tsta ;chk pad counter, 0=exit beq VMFGaF ;file name padded to 8, get another mov gptnk,x+ ;pad a space deca ;decr pad counter bra VMFPad ;pad out to 8 chrs VMFXit: lda #$aa ; sta ,x ;set new list end flag ;* .MP3 file names in buffer, all 8 chrs long rts ;* Wait for VM internals to process a cmd, line, byte VM_CDl: mov vmcdl,vmwtk1 ;Command delay, wait after send VM_LDl: mov vmldl,vmwtk0 ;Line delay bra VMWLp0 VM_BDl: mov #1,vmwtk0 ;Byte delay VMWLp1: clra VMWLp0: feed_watchdog dbnza VMWLp0 dbnz vmwtk0,VMWLp1 tst vmwtk1 ;if=0: stay there=std wait beq VMWXit dbnz vmwtk1,VM_BDl ;else is LONG wait VMWXit: rts VMTmRd: mov #5,genctr ;Timer read is ALWAYS 5 chrs VMTRLp: jsr VM_BDl jsr SPIRxD ; else goes bad @ 12== mov chrtnk,x+ ;put to bfr dbnz genctr,VMTRLp ; gimme 5 rts ; and out VMRead: jsr VM_BDl ;Byte delay jsr SPIRxD ;Read to buffer, until seen lda chrtnk cmp #cr beq VMRBX ;loop until lda ,x ;chk for list end flag cmp #$aa ;hit bfr end flag? beq VMRBX ;immediate exit mov chrtnk,x+ ;put to bfr bra VMRead ; and get another VMRBX: rts VM_V3A: mov #v3a,chrtnk ;Play all jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send rts VM_VRR: mov #vrr,chrtnk ;Play random jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send rts VM_VP: mov #vp,chrtnk ;Pause/Resume jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts VM_VSF: mov #vsf,chrtnk ;Skip Forward 1 Track jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts VM_VSB: mov #vsb,chrtnk ;Skip Backward 1 Track jsr SPITxD ;must be done twice mov #cr,chrtnk ;else restarts same track jsr SPITxD jsr VM_CDl ;Cmd delay mov #vsb,chrtnk jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts VM_Dir: mov #vdir,chrtnk ;Directory jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts VM_VST: mov #vst,chrtnk ;STOP jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts VM_SCS: mov #'S',chrtnk ;Short Command Set jsr SPITxD mov #'C',chrtnk jsr SPITxD mov #'S',chrtnk jsr SPITxD mov #cr,chrtnk jsr SPITxD ;send jsr VM_CDl ;Cmd delay rts VMPurg: jsr SPIRxD ;Purge: get a byte jsr VM_BDl tst spiflg beq VMPurg ;loop until VM reads empty rts BfrBnk: ldhx #nambfr ;blank out entire name buffer mov #' ',gptnk BB_Lp: feed_watchdog mov gptnk,x+ cphx #namend ;end chk blo BB_Lp lda #$aa sta ,x ;set end flag rts ;************************************************************** ;* SPI routines: read/write, data/status, byte to/from chrtnk ;* NOTE: in/out refer to module ;* Read 8 bits from data/status register to chrtnk SPIRxD: bset sDI,PTCD ;set data in high = start bset sCS,PTCD ;set chip select bset sCl,PTCD ;clock set bclr sCl,PTCD ;clock clr = START bset sCl,PTCD ;clock set bclr sCl,PTCD ;clock clr = READ bclr sDI,PTCD ;set data in low bset sCl,PTCD ;clock set = DATA Adr + b7 bra SPIRx8 ;go get 8 bits SPIRxS: bset sDI,PTCD ;set data in high = start bset sCS,PTCD ;set chip select bset sCl,PTCD ;clock set bclr sCl,PTCD ;clock clr = START bset sCl,PTCD ;clock set bclr sCl,PTCD ;clock clr = READ bset sCl,PTCD ;clock set = STAT Adr + b7 SPIRx8: feed_watchdog brset sDO,PTCD,B7In ;BRXXX sets Carry flag B7In: rol chrtnk ;C->b0 bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = bit6 ready brset sDO,PTCD,B6In ;BRXXX sets Carry flag B6In: rol chrtnk ;C->b0, b0->b1...etc bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = bit5 ready brset sDO,PTCD,B5In ;BRXXX sets Carry flag B5In: rol chrtnk ; bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = bit4 ready brset sDO,PTCD,B4In ;BRXXX sets Carry flag B4In: rol chrtnk ; bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = bit3 ready brset sDO,PTCD,B3In ;BRXXX sets Carry flag B3In: rol chrtnk ; bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = bit2 ready brset sDO,PTCD,B2In ;BRXXX sets Carry flag B2In: rol chrtnk ; bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = bit1 ready brset sDO,PTCD,B1In ;BRXXX sets Carry flag B1In: rol chrtnk ; bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = bit0 ready brset sDO,PTCD,B0In ;BRXXX sets Carry flag B0In: rol chrtnk ;All b0-7 in place bclr sCl,PTCD ;clock clr bset sCl,PTCD ;clock set = STATUS bit ready bclr sCl,PTCD ;clock clr mov #$55,spiflg ;old data / status read fail brset sDO,PTCD,RxOld ; clr spiflg ;clr flag: new data / read ok RxOld: bset sCl,PTCD ;clock set bclr sCl,PTCD ;clock clr bclr sCS,PTCD ;clr chip select bclr sDI,PTCD ;set data in low bset sCl,PTCD ;clock set bclr sCl,PTCD ;clock clr = READ DONE feed_watchdog rts ;* Write 8 bits to data/status register from chrtnk SPITxD: feed_watchdog bset sDI,PTCD ;set data in high = start bset sCS,PTCD ;set chip select bset sCl,PTCD ;clock set (1) bclr sCl,PTCD ;clock clr = START bclr sDI,PTCD ;set data in low bset sCl,PTCD ;clock set (2) bclr sCl,PTCD ;clock clr = WRITE bset sCl,PTCD ;clock set (3) bclr sCl,PTCD ;clock clr = DATA Adr bclr sDI,PTCD ;preset bit low clc ; and init carry bit clear rol chrtnk ;b7->C (& C->b0) bcc B7_L bset sDI,PTCD ;set bit high B7_L: bset sCl,PTCD ;clock set = bit sent (4) bclr sCl,PTCD ;clock clr bclr sDI,PTCD ;preset bit low rol chrtnk ;b6->C (& C->b0) bcc B6_L bset sDI,PTCD ;set bit high B6_L: bset sCl,PTCD ;clock set = bit sent (5) bclr sCl,PTCD ;clock clr bclr sDI,PTCD ;preset bit low rol chrtnk ;b5->C (& C->b0) bcc B5_L bset sDI,PTCD ;set bit high B5_L: bset sCl,PTCD ;clock set = bit sent (6) bclr sCl,PTCD ;clock clr bclr sDI,PTCD ;preset bit low rol chrtnk ;b4->C (& C->b0) bcc B4_L bset sDI,PTCD ;set bit high B4_L: bset sCl,PTCD ;clock set = bit sent (7) bclr sCl,PTCD ;clock clr bclr sDI,PTCD ;preset bit low rol chrtnk ;b3->C (& C->b0) bcc B3_L bset sDI,PTCD ;set bit high B3_L: bset sCl,PTCD ;clock set = bit sent (8) bclr sCl,PTCD ;clock clr bclr sDI,PTCD ;preset bit low rol chrtnk ;b2->C (& C->b0) bcc B2_L bset sDI,PTCD ;set bit high B2_L: bset sCl,PTCD ;clock set = bit sent (9) bclr sCl,PTCD ;clock clr bclr sDI,PTCD ;preset bit low rol chrtnk ;b1->C (& C->b0) bcc B1_L bset sDI,PTCD ;set bit high B1_L: bset sCl,PTCD ;clock set = bit sent (10) bclr sCl,PTCD ;clock clr bclr sDI,PTCD ;preset bit low rol chrtnk ;b0->C (& C->b0) bcc B0_L bset sDI,PTCD ;set bit high B0_L: bset sCl,PTCD ;clock set = bit sent (11) bclr sCl,PTCD ;clock clr All 8 bits sent rol chrtnk ;9th roll restores chrtnk value mov #$55,spiflg ;preset as write fail (bfr full) bset sCl,PTCD ;clock set (12) bclr sCl,PTCD ;clock clr: get status bit brset sDO,PTCD,TxERR ; clr spiflg ;write OK TxERR: bclr sCS,PTCD ;clr chip select bclr sDI,PTCD ;set data in low bset sCl,PTCD ;clock set (13) bclr sCl,PTCD ;clock clr = WRITE DONE feed_watchdog rts ;**************************************************************