I’m using PORTD for sending data to the transceiver. D0 goes to CE, D2 to the CLOCK and D3 to DATA. Here’s my code, which I wrote in assembly:
;*****************************************************************
;** Transmission Time ********************************************
MOVLB 05h ;bank select register
MOVLW 11h ;0001001 (address 17)
MOVWF DATAOUT_T ;high byte of data output
MOVWF DATAOUT_T-01h
MOVLW 55h ;01010101
MOVWF DATAOUT_T-02h
MOVLW 0Fh ;00001111
MOVWF DATAOUT_T-03h
MOVLW 0F0h ;11110000
MOVWF DATAOUT_T-04h
MOVLW 55h ;01010101
MOVWF DATAOUT_T-05h
SND_D MOVLW 06h ;run through this many registers
MOVWF NUMREGS ;keep track of how many we've gone through
MOVLW DATAOUT_L ;load in address of high byte for data packet
MOVWF FSRL ;copy address to the FSRL, this will be our pointer
MOVLW DATAOUT_H ;load in address of low byte for data packet
MOVWF FSRH ;copy high byte to FSRH
BSF PORTD,0 ;let nRF2401A we have data to transmit
SENDC3 MOVLW 08h ;initialize register loop counter
MOVWF LPCNTR ;we have 8 bits per register
TX1 BCF PORTD,2 ;set clock low
BTFSS INDF,7 ;If c=0
BCF PORTD,3 ;set corresponding data output to 0
BTFSC INDF,7 ;If c=1
BSF PORTD,3 ;set corresponding data output to 1
RLNCF INDF,1 ;rotate data at address pointed to by FSR
;**************CLOCK PAUSE*************************
MOVLW 042h
MOVWF CNTR1
WAIT5 DECFSZ CNTR1,1
GOTO WAIT5
;**************************************************
BSF PORTD,2 ;positive clock edges transfer the bit to nRF2401A, set clock high
;**************CLOCK PAUSE*************************
MOVLW 042h
MOVWF CNTR1
WAIT6 DECFSZ CNTR1,1
GOTO WAIT6
;**************************************************
DECFSZ LPCNTR,1 ;until our loop is complete, run through next data bit in register
GOTO TX1
DECF FSRL,1 ;change pointer location to next register byte
DECFSZ NUMREGS,1 ;continue through all registers
GOTO SENDC3 ;run through our byte transmission loop
BCF PORTD,0 ;let nRF2401A know we're finished
BCF PORTD,2 ;clear lingering clock
BCF PORTD,3 ;clear lingering data
;Give some time for the transmission to go through ~0.15s
MOVLW 0FFh
MOVWF CNTR1
MOVWF CNTR2
WAITX7 DECFSZ CNTR1,1
GOTO WAITX7
DECFSZ CNTR2,1
GOTO WAITX7
GOTO SND_D ;repeat
;*****************************************************************
The key area to focus on is the following:
TX1 BCF PORTD,2 ;set clock low
BTFSS INDF,7 ;If c=0
BCF PORTD,3 ;set corresponding data output to 0
BTFSC INDF,7 ;If c=1
BSF PORTD,3 ;set corresponding data output to 1
RLNCF INDF,1 ;rotate the data at address pointed to by FSR, without carry
;**************CLOCK PAUSE*************************
MOVLW 042h
MOVWF CNTR1
WAIT5 DECFSZ CNTR1,1
GOTO WAIT5
;**************************************************
BSF PORTD,2 ;positive clock edges...
;**************CLOCK PAUSE*************************
MOVLW 042h
MOVWF CNTR1
WAIT6 DECFSZ CNTR1,1
GOTO WAIT6
;**************************************************
My PIC is clocked at 4MHz, so each cycle takes 0.25us to execute. The only instructions which take two cycles are the GOTO’s and the DECFSZ’s (decremenet F, skip if zero). The latter of which only takes two if the target register is in fact 0. In the clock pause section, the MOVLW instruction corresponds to the number of times my ‘WAIT’ loop should be executed. It’s set to 66(base 10), but let’s call it X for now. The correct number of cycles required for its execution can be calculated like this:
execution time = ((X-1)*3+1)/frequency (for X>1, otherwise, 2)
Leaving the current value of 42 gives me two 31us pauses, so the entire process translates into a 16kbps transmission time. This works fine. Now assuming I never enter a number below 2 for X, the shortest time this code can execute given a 4MHz clock (with X=2) is 1us. You’ll notice this is double the HOLD and CLOCK_HIGH time required by the transceiver. So why does the transceiver have trouble with it?
I spoke with some IEEE friends over the weekend and they mentioned something I had not taken into consideration. My circuit is currently in the prototyping stage and as such I’m working on a breadboard, which suffer from relatively large stray capacitances. It may be that this is interfering with my transmission, but I have no way to tell until I move this onto an PCB. I can’t assume it’ll work faster when moving it off a breadboard, so I’ve resolved to just work around the issue.
If anyone has any more suggestions, I’d love to hear them.
Thanks,
Diego