We start by putting first byte in to the out buffer, then subsequent bytes in to registers defined by a start address, FSR resumes thereafter.
We then enter number of reads, number of writes and the pattern for CSN
We call CALCFCNT to re-adjust above figures (this was a whim and not like I am struggling for space!)
Then call SPIGO to actually send the data.
It's slow, it's clunky, but it is mostly automated and works. I will probably take a more shopping list approach if I need speed, or choose a pic with build in SPI which would be a lot less hassle!
Oh and the FSR routine does a bit of everything really, whatever I was so is quite durable I think.
All code (C) Olly_k 2018
;=================================SPI ROUTINE=================================
CLKH:
btfss INTCON,T0IF ;Check if time for a change
goto $-1
bcf INTCON,T0IF ;Reset flag
bsf PORTC,CLK ;Clock High
return
CLKL:
btfss INTCON,T0IF ;Check if time for a change
goto $-1
bcf INTCON,T0IF ;Reset flag
bcf PORTC,CLK ;Clock High
return
;--------------------------------------------------------------------
CALCFCNT: ;We calculate the value to put in to fsrCNTin
;Which decides how many rotates for the buffer shuffle
;We assuming tempS1 still in working at this point too!
subwf tempS0,w ;Here is stored # of MOSI
btfss STATUS,C
goto $+8
btfss STATUS,Z ;If both data the same we must set flags
goto CALC
goto $+5
CALC:
movf tempS0,w
movwf fsrCNTin
bsf SPIflgs,7 ;TEST
return
movf tempS1,w
bcf SPIflgs,7 ;required?
movwf fsrCNTin
return
SPIGO:
; registers to temp registers
movf FsRrADin,w ;
movwf FsRrADDY
movf fsrCNTin
movwf fsrCNT
; Pre-initialisation - MISO starts off clear, so we can put 0x01 in to file
; and wait for it to come round.
; MOSI requires a seperate counting reg (SPIbit)
SPICNT0:
movlw 0x01
movwf SPIbufI ;Preload input with 0x01 for 'byte full' test
movlw 0x08 ;This is for READ
movwf SPIbit
bcf PORTC,CSN ;CSN LOW any data from now on is valid
bcf INTCON,T0IF ;Let's start the timing over
bsf SPIflgs,4 ;First time we want to reset TMR count.
;-----------------------SPI LOOP------------------------
SPILP: ;This is the SPI Loop, lets roll the data in to STATUS
;But first, Check for data to roll out.
btfss SPIflgs,1 ;Is there still anything to send?
goto CTL ;Yes
;CONT...
movlw 0x01
movwf fsrCNT
btfss SPIflgs,2 ;Is that it now nothing for MISO?
goto SPIOUT
;CONT...
movf fsrCNTin,w
movwf fsrCNT
btfsc SPIflgs,7
goto $+2
goto SPIret ;TEMP TEMP
bsf FSRflgs,3
call FSRrtn ;ONE LAST SHUFFLE
goto SPIret ;exit routine
;Here we now start to rotate and read the output buffer (SPIbufO)
CTL:
rlf SPIbufO,f ;Lets get the first value to output from MOSI
btfss STATUS,C ;1 or 0?
goto SPIoutL ;Go to SPIoutLOW
;CONT...
SPIoutH:
bsf PORTC,MOSI
goto SPIOUT
SPIoutL:
bcf PORTC,MOSI
SPIOUT:
bcf PORTC,CSN
btfss SPIflgs,4 ;Is this the first clock pulse?
;If so, we want a nicely timed first pulse
;So we reset TMR0
goto $+5 ;Not our first time
;CONT...
movlw 0x00 ;Set TMR0 for a full count
movwf TMR0
bcf INTCON,T0IF
bcf SPIflgs,4
;*************************
call CLKH ;Action the Output to the bus!
;*************************
;Now we have sent data we need to collect
;But first, lets see where we are up to!
MOSi:
btfsc SPIflgs,1 ;Test if still to check for data output
goto MISo
decfsz SPIbit,f ;SPI bit cnt, when out 8 bits check more bytes?
goto MISo ;Nothing to worry about, continue
;***********TEST1
bcf STATUS,C
rlf tmp3,f ;Do we want a delay and if so is it time?
rlf tmp,f ;rotate previous carry if there is one
btfss STATUS,C
goto MOSCNT
bsf SPIflgs,3 ;Set delay flag
;CNT...
MOSCNT:
;***********TEST1
movlw 0x08
movwf SPIbit
decfsz tempS0,f ;Check and dec number bytes
goto MOcnt ;Continue
bsf SPIflgs,1 ;We set flgs,1 to inhibit further reads
goto MISo
;We now need to shuffle all registers
MOcnt:
bsf SPIflgs,0 ;We need to shuffle everything but not yet
;Set up addys again for next shuffle
MISo:
btfsc SPIflgs,2 ;Have we finished MISO?
goto SPILPC ;Yes? Back to MOSI, but hang on, CLK RST!
btfss PORTC,MISO ;
goto MISOl ;Low, go to MISO Low
MISOh:
bsf STATUS,C
goto $+2
MISOl:
bcf STATUS,C
rlf SPIbufI,f ;Rotate above carry in
btfss STATUS,C ;Check if we have come round?
goto SPILPC ;ok so we need to wait to cont clock
bsf SPIflgs,0 ;shuffle!
movf SPIbufI,w ;We need to save the file now!
movwf FsRiDATA ;Ready to feed in to chain
movlw 0x01
movwf SPIbufI ;Number of addresses to put in
decfsz tempS1,f ;ok, byte complete, dec count
goto SPILPC
bsf SPIflgs,2 ;No more data to read in
; CONT...
SPILPC:
;*************************
call CLKL ;Action the Output to the bus!
;*************************
btfss SPIflgs,1 ;ensure very LAST bit sent is cleared!
goto $+2
bcf PORTC,MOSI ;Do it1 ****************ADDED THIS BELOW TEST3
CLKCNT:
;***********TEST1
btfss SPIflgs,0 ;End of byte? *+*+*+*+*+*+*+*+ Check here for byte
goto SPILP
bcf PORTC,MOSI
;---------------READY TO SHUFFLE FOR NEXT DATA---------------
;THere is an option to allow the FSR shuffle to shrink as data lessens..
;This may be required for faster code but generally remains inactive.
;Might remove or make it a feature. It looks a but messy
btfss FSRflgs,4 ;Check for reduced shuffle
goto $+3
movlw 0x18 ;This will set FSRflgs,4; shuffle shrink
goto $+2
movlw 0x08 ;Lets set up FSR flags
movwf FSRflgs
; Ok prep - copy current files in to temp before continue
movf FsRrADin,w ;
movwf FsRrADDY
movf fsrCNTin,w
movwf fsrCNT
call FSRrtn ;Get next data
bcf SPIflgs,0 ;reset
;-------------------PLANNED BREAK BETWEEN CLOCKS------------------
btfss SPIflgs,3
goto $+2
bsf PORTC,CSN ;*************TEST3
call DLY500uS
bcf INTCON,T0IF ;Reset flag
bcf SPIflgs,3
goto SPILP
;----------------------End routine
SPIret:
call DLY50uS
bsf PORTC,CSN ;render any data invalid
clrf SPIflgs
return
;********************************************************************
;********************************************************************
;-----------------------------FSR Routine----------------------------
;Please see file FSRRoutine.asm for instructions
FSRrtn:
rFSR:
btfss FSRflgs,1 ;one-shot Read
goto fsrWR
fsrRD:
movf FsRrADDY,w ;initial/current read addy
movwf FSR
movf INDF,w
movwf FsRoDATA ;This is Data to be read out
incf FSR,f
movf FSR,w
movwf FsRrADDY ;save new value for next increment
bcf FSRflgs,1 ;Cancel read
return
fsrWR:
btfss FSRflgs,2 ;WRITE
goto fsrSHUF ;No change, set flag and exit
movf FsRwADDY,w ;initial/current read addy
movwf FSR
movf FsRiDATA,w ;This is Data to be read in
movwf INDF
incf FSR,f
movf FSR,w
movwf FsRwADDY
btfss FSRflgs,3 ;Shuffle? return.
; btfsc FSRflgs,3 ;Shuffle? return.
return
fsrCNt: ;if a multi byte wipe is requested we will continue
;here
decfsz fsrCNT,f ;Count requested number to clear
goto fsrWR ;no clear next
return ;do we want to write multiple times?
;------------SHUFFLE CODE!
;Start address, FSRflag 3 set, number of shuffles set. ALL GOOD
fsrSHUF: ;READ
;***Current working registers are moved to temp registers
movf FsRiDATA,w
movwf tempF2
movf FsRrADDY,w
movwf tempF0
movf FsRwADDY,w
movwf tempF1
;First we need to read the current read ADDY and write the same
movf FsRrADDY,w ;Copy the address!
movwf FsRwADDY ;WRITE AND READ THE SAME
;Now copy that first buffer in to the output register
bsf FSRflgs,1 ;We need a read!
call fsrRD ;Back on ourselves again, for a read
movf FsRoDATA,w ;We copy the first shift to buffer
movwf SPIbufO ;Done; we do not come back here now
ShufLP: ;This is loop x times
; First we read the file to shuffle from stored address
;sequence - as we had a read for the output buffer we
;area already 1 increment up.
; FIRST READ
btfss FSRflgs,4 ;Check for reduced shuffle
goto $+3
movlw 0x1A
goto $+2
movlw 0x0A ;Lets set up FSR flags (00001010)
movwf FSRflgs
call rFSR ;Read next file
movf FsRoDATA,w ;we need to copy to the next buffer
movwf FsRiDATA
;The previously read file is now written to the incremented register
; WRITE FIRST READ
btfss FSRflgs,4 ;Check for reduced shuffle
goto $+3
movlw 0x14 ;00001000 Select one shot write
goto $+2
movlw 0x04 ;Lets set up FSR flags
movwf FSRflgs
call fsrWR ;do it!
decfsz fsrCNT,f ;Have we finished yet?
goto ShufLP ;Repeat again
;Now we reduce the shuffle count and determine if any more
;shuffles are required.
movlw 0x01
subwf FsRwADDY,f ;We reduce the count for next shuffle n-1
movf tempF2,w
movwf FsRiDATA ;This needs to be put in shuffle train
;Also we need to reduce the write address by 1
;TEST
btfss FSRflgs,4 ;Check for reduced shuffle
goto $+3
movlw 0x14
goto $+2
movlw 0x04 ;Lets set up FSR flags
movwf FSRflgs
call fsrWR ;
movlw 0x01
addwf FsRwADDY,f ;Bump address back up
clrf FsRiDATA
;TEST
btfss FSRflgs,4 ;Check for reduced shuffle
goto $+3
movlw 0x10
goto $+2
movlw 0x00 ;Lets set up FSR flags
movwf FSRflgs
CT:
;TEST
btfss FSRflgs,4 ;Check for reduced shuffle
goto $+3
movlw 0x10
goto $+2
movlw 0x00 ;Lets set up FSR flags
movwf FSRflgs
;restore addresses
movf tempF0,w
movwf FsRrADDY
movf tempF1,w
movwf FsRwADDY
return
;===========================
CheckADDY: ;So let's check to see this is
;Addressed to us.
clrf FSRflgs ;we're on, no need for delay
movlw 0x61 ;This is first ADDY
movwf FsRrADin ;Put initial address in to FSRw
clrf SPIflgs ;We clear the flags first
movlw 0x01 ;ok first we are expect 16-byte MOSI writes
movwf tempS0
movlw 0x04 ;We are expecting x MISO read
movwf tempS1
call CALCFCNT ;Lets configue number of shuffles
;fsrCNTin IS LOADED AUTOMATICALLY
call SPIGO
return