Go Down

### Topic: How much can 328p handle? (Read 10831 times)previous topic - next topic

#### pito

#30
##### May 07, 2013, 01:51 amLast Edit: May 07, 2013, 01:57 am by pito Reason: 1
The only correct calculation of the DDSword is with 64bit multiplication and LL integers (as above). Some sites show calculation with floating point - bad idea - as the float is not precise enough for the DDSword calculation! (there are even AD DDS chips with 48bit DDSword!).
I would use the libraries, but applying the above LL calc for DDSword.
Also mind when doing sweep with "adding the frequency step" (instead of a freq calculation of each sweep point) the error of the frequency accumulates, when the step is not a precise number.. The same occur when using an encoder as the input dial (and doing adding/subtracting a fixed step).

#### C2

#31
##### May 28, 2013, 10:29 pm
Hi All,

I finally got the DDS freq update to happen via an spi transfer (The spi divider is set to 4, mode0, and LSB first).

I call the SetFrequency function via a while loop, which happens quickly for each frequency setting. I print a time before and after the loop completes and calculate the point-to-point sweep time. Without the below function, the loop takes about 4 us to complete (might be faster, but that is all I'm able to count). When I add the SetFrequency function, I get a freq set time of ~280 us.

I would like to get the function to process faster if I can.

Code: [Select]

void SetFrequency(unsigned long frequency)
{
int32_t tuning_word = (frequency * 0x100000000LL)/124999100L; //calc tuning word
PORTB = PORTB & B11111011; // clear pin 10
SPI.transfer(tuning_word);
SPI.transfer(tuning_word >> 8);
SPI.transfer(tuning_word >> 16);
SPI.transfer(tuning_word >> 24);
SPI.transfer(0x0);
PORTB = PORTB | B00000100; // set pin 10

I think crossroads mentioned something about a control word and I'm also not sure the last byte is correct. I also wonder if it's better to put the spi transfer in a for loop rather than coding each byte manually as I have? It seems it would take longer for the for loop since that is just one more thing to do...?

Also, the datasheet seems to say that each bit is transferred on rising edge of W_CLK. If W_CLK is 4 MHz (the spi clock with 4 x divider), then 40 bits would take 10 us, plus some settling time for the device to process (18 clocks of DDS system clock, 125 MHz?, plus a few more ns...). So it seems that if I'm able to get on the order of 10 us frequency switching time, then I'm done!

#32
##### May 28, 2013, 10:51 pm
Code: [Select]
int32_t tuning_word = (frequency * 0x100000000LL)/124999100L; //calc tuning word

On my Arduino Uno, this formula takes almost 250 us.  I expect the divide is the time suck.

#### pito

#33
##### May 28, 2013, 10:57 pmLast Edit: May 28, 2013, 11:12 pm by pito Reason: 1
Try to go with 8Mhz SPI - 9850 is fast enough..
Why do you try to calculate ddsfreqword at each sweep step??
Do calculate the ddsword for fstart and fstop, do calculate the ddsword for fstep and simply add it to dds_freq within a loop - that must be faster (when you do a linear sweep).

Code: [Select]
unsigned long ddsword_fstart = calculate...
unsigned long ddsword_fstop = calculate...
unsigned long ddsword_fstep = (ddsword_fstop - ddsword_fstart)/number of sweep points

unsigned long ddsword_freq = ddsword_fstart

while (ddsword_freq <= ddsword_fstop)
{
send ddsword_freq to 9850 via SPI @8MHz
ddsword_freq = ddsword_freq + ddsword_fstep
}

That will take 11usec a loop, I bet

#### C2

#34
##### May 29, 2013, 01:32 am

Code: [Select]
int32_t tuning_word = (frequency * 0x100000000LL)/124999100L; //calc tuning word

On my Arduino Uno, this formula takes almost 250 us.  I expect the divide is the time suck.

Thanks, pito. I might even get those calcs out of the function and move them to the config function. Nothing should happen until the parameters are configured and then exit setup mode.

Go Up