MiRF (nRF2401A) Question - Clocking in transmission data

Bonjour,

I’m working with Sparkfun’s MiRF boards and I’ve got them working with relatively low frequencies when clocking in data for transmission (approximately 40ms clock frequency). It was a bit of a learning curve to get that far, considering this is my first time attempting this, but I digress.

I’ve noticed that the datasheets claim I can work with up to 1Mbps, and I really have to question the accuracy of that. I’ve tried it at approximately 400kbps and the chips don’t seem to like that. So before I go playing around with what the optimal frequency is, does anyone have suggestions or resources to point me in the right direction?

I have to say I’m disappointed that it’s not working at this frequency since I need to simultaneously handle other code in my micro while transmitting, and I’m handling everything manually (I’m trying to keep strict tabs on the number of instructions and clock cycles for execution). The less time I spend in tranmission the better.

Also, one of the units I received doesn’t work. I popped it into direct mode to monitor the DATA channel and it doesn’t even pick up noise. What are Sparkfun’s return policies on this kind of stufF?

Cheers,

Diego

Hi, I guess you’re using Shockburst: In this case, Clocking Data can be done at 1MHz (500nS rise/fall CLK time) and on-the-air time should be around 400-500 uS for 16 bytes @ 250KBps (what I’m using now). BTW, you don’t have to actively wait for transmission to end, but the micro can do other things.

What are your timings? I have not used 1MBps, but things ought to work the same (even if someone else claimed that there were some timing issues here and there). I had problems at the beginning, but not due to BPS.

Yes, I’m in Shockburst. Here’s my clock in process:

Assert appropriate data on the DATA line, wait 2.5us.

Set the clock high, wait 2.5us.

Set the clock low, repeat.

So yes, I’ve slowed it down some and it still doesn’t want to work. That corresponds to a 200kbps clock period. My setup and hold times should be well within range. I know it’s a timing issue, as when I slow it down to 10kbps it works fine.

Strange, that thing about 10KHz was written somewhere, and I got mislead by that for a while. Now, as I told you, I’m sending data @1MHz and all is fine, @250KBps.

Could it depend on rise/fall timings? Which pins are you using, and how long are they connected? Do you wait enough time after that TX has started, to allow for the whole packet to get through?

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

Hi Diego, well, for first, if you’re clocking @4MHz, then each instruction will take 1uS and not 0.25 … if I’m not wrong.

Your bit-banging routines look fine. But, you’ve not showed how much you’re waiting everytime you switch from TX to RX, and from CS to CE (for example) conditions. Some 50-100uS has to be put into.

And, that thing about “how long you’ll wait AFTER the TX has started”.

About the breadboard issue… I’d not care too much: no RF is going on those wires, maximum will be some 1MHz. I have 3-5cm of wire in my prototypes and everything is fine.

I agree with DarioG, you have not included some needed delay.

BSF PORTD,0 ;let nRF2401A we have data to transmit 

I guess this is where you set CE high. You need 5 µs delay after this, it is the Tce2data time in the datasheet (there is also Tcs2data, 5 µs delay needed after setting CS).

For the actual data clocking, 1MHz should be no problem and works for me (2Mhz works also but this is experimental and not what I use normally). This is with 60mm flat cabel and connector so I don’t think the breadboard should be a problem.

/Lars

Lajon:
“You need 5 µs delay after this…”

Holy hell. You, Lajon, are awesome. I will buy you a beer if you’re ever out this way. It’s working flawlessly now.

Thanks for catching that mistake, that made all the difference.

Cheers,

Diego

Ok, Diego, I take your invitation for me too :lol:

(glad you succeded)