Entire Forum This board This topic Members Entire Site
 Pages: [1]
 Author Topic: Advice needed  (Read 1806 times) 0 Members and 1 Guest are viewing this topic.
LabVIEWguru
Senior Member

Offline

Posts: 285

Thank You
-Given: 239

 « on: August 27, 2013, 09:44:38 21:44 »

I don't want to start a fight, but:

I need compiler advice. I want to use something like the ATMega 16 to drove a DDS device, display and so on. The control word for the DDS is 32 or 48 bits, so each time I rotate the knob the encode sends a pulse and I have to add or subtract a 32 bit value from the 32 bit tuning word, update the display, and so forth. Lots of math....  long long in "C"

So, from those of you that have used a "C" compiler in the Atmel, which is the best one, most efficient, most stable, best math functions and so forth?

LabVIEWguru
 Logged
h0nk
Active Member

Offline

Posts: 150

Thank You
-Given: 117

 « Reply #1 on: August 28, 2013, 02:56:40 02:56 »

Hello,

i wrote some time ago some routines for the AD9850 for the MSP430 in assembler.
I used s simpler logic to obtain the control words.
There is a constant for every digit of the frequency:

Code:
F10M DL 0147ae148h
F1M DL 020c49bah
F100k DL 0346dc5h
F10k DL 053e2dh
F1k DL 08638h
F100 DL 0d6ch
F10 DL 0158h
F1 DL 022h

The simple task is to multiply (or as i did repeated add) these constants with the appropriate digit of the frequency and get sum of it.

For the frequency i used a 16 digit buffer. Only the first 8 digits are used in the calculation, but i can
simply shift the buffer in any direction to change the frequency by 10 and no digits are lost.

So there is no complex math :-)

Best Regards

--
Edit: I dont use AVR's for new designs. I would suggest IAR Workbench for the easy debugging with the AVR Dragon.
 « Last Edit: August 28, 2013, 11:00:49 11:00 by h0nk » Logged
hate
Hero Member

Offline

Posts: 557

Thank You
-Given: 156

 « Reply #2 on: August 28, 2013, 03:54:56 03:54 »

People find Codevision's CodeWizard, easy to configure the peripherals of target AVR. Last time I checked, CodeWizard didn't include every detail for peripheral settings though. On the other hand AVR-Gcc seems to be more professional with a linker, assembler, library (avr-libc), it can compile C++ code (no libraries for C++ exist yet including the standard lib) and maintained by ATMEL. Having used both in the past, my choice was AVR-Gcc between the 2. I can't comment on other compilers though.
 Logged

Regards...
microkid
Active Member

Offline

Posts: 130

Thank You
-Given: 44

 « Reply #3 on: August 28, 2013, 07:00:57 07:00 »

My first option would be AVR GCC which can be trusted. I dont feel your project requires any complicated peripherals to be configured.

You can also try IAR which is professional compiler.

MicroKid
 Logged

Never Never Never giveup
sam_des
Active Member

Offline

Posts: 223

Thank You
-Given: 62

 « Reply #4 on: August 28, 2013, 01:31:15 13:31 »

Hi,

avr-gcc is obviously good choice. Just don't forget to add math lib in your linker options. This library is much better than code natively generated by gcc. Also any math going above 32-bits, will cause huge code-size increase, even greater than 32-bit floating point lib. Obviously 64-bit routines are not optimized, IAR or Crossworks does much better job here. Crossworks even have multiple optimized math routines.

Also you can implement your own assembly level math routines, customizing size/speed, as per your needs and call them from c.

As far as peripheral initialization is concerned, ready-made solutions like code-wizard, they are good for initial testing, but not for final version, in my opinion.

sam_des
 « Last Edit: August 28, 2013, 01:36:11 13:36 by sam_des » Logged

Never be afraid to do something new. Remember Amateurs built the Ark, Professionals built the Titanic !
LabVIEWguru
Senior Member

Offline

Posts: 285

Thank You
-Given: 239

 « Reply #5 on: September 03, 2013, 10:56:24 22:56 »

i wrote some time ago some routines for the AD9850 for the MSP430 in assembler.
I used s simpler logic to obtain the control words.
There is a constant for every digit of the frequency:

The simple task is to multiply (or as i did repeated add) these constants with the appropriate digit of the frequency and get sum of it.

For the frequency i used a 16 digit buffer. Only the first 8 digits are used in the calculation, but i can
simply shift the buffer in any direction to change the frequency by 10 and no digits are lost.

So there is no complex math :-)

--
Edit: I dont use AVR's for new designs. I would suggest IAR Workbench for the easy debugging with the AVR Dragon.

Honk:

1) Why not use Atmel for new designs?

2) Maybe I've made it to complicated. I've done that once or twice before.

I think I am arriving at the same place. I was going to use an encoder of some type to generate a interrupt. If the interrupt then sees another pin HI, we will increment. Pin LO is a decrement. I can start from a pre-loaded state when I turn the VFO on or from the last frequency remembered when I turned it off.

I'll probably increment by your F100 unless I select (push button) otherwise. So each step of the encoder will generate an interrupt that increments or decrements F100 hz.

So, let's say I'm at 10 mhz (F10M) as my starting position. I bump my knob to increment 100 hz (F100).

LAST_FREQ + F100 --> TEMP_DDS_REGISTER-->shift out the SPI to the DDS
DISP_FREQ + 100hz --> convert to ascii --> parallel out to display

If this is correct, that would be a lot simpler than what I had originally done. I originally had programmed in assembler with a Freescale micro just to jump between a number of preselected channels at a predetermined time. Then I wanted to build a really, really fast zero-crossing switch so I would "jump" when the input to the mixer crossed zero. My VFO in assembler was becoming very difficult very quickly.

I purchased two "crystal-plexed" 11 meter radios to use as a development system. I was able to fire them up on 10M with just some "tweaking." I had a couple contacts just to make sure everything worked and all was stable. So my simple project has become about 5 projects all based on the DDS VFO.

So, what do you think? Anyone else have any comments?

LabVIEWguru
 Logged
h0nk
Active Member

Offline

Posts: 150

Thank You
-Given: 117

 « Reply #6 on: September 04, 2013, 01:32:21 01:32 »

Honk:

1) Why not use Atmel for new designs?
I have used Atmels (90S8515,90S2313) in the last millennium. But i dont like the way how they handle their data spaces :-).
If a project make use of them, i have no problems with them.

Most of my projects include some form of signal processing and require features like arithmetic saturation,
extended address capabilities and so on. For this i used in early days the Motorola 56002 and later
Texas Instruments C5000 and C2000 series.
On the lower end i would use the PIC16F15xx which have really neat peripherals like
a NCO (Numerical Controlled Oscillator) or CLC's (Configurable Logic Cell).

For this project i used the MSP430 because of its 16 bit capabilities, the possibility to drive a passive 14 segment LCD,
integrated ADC's, DAC's and OPV's (MSP430FG4618).

Quote
2) Maybe I've made it to complicated. I've done that once or twice before.

I think I am arriving at the same place. I was going to use an encoder of some type to generate a interrupt. If the interrupt then sees another pin HI, we will increment. Pin LO is a decrement. I can start from a pre-loaded state when I turn the VFO on or from the last frequency remembered when I turned it off.

I'll probably increment by your F100 unless I select (push button) otherwise. So each step of the encoder will generate an interrupt that increments or decrements F100 hz.

So, let's say I'm at 10 mhz (F10M) as my starting position. I bump my knob to increment 100 hz (F100).

LAST_FREQ + F100 --> TEMP_DDS_REGISTER-->shift out the SPI to the DDS
DISP_FREQ + 100hz --> convert to ascii --> parallel out to display

If this is correct, that would be a lot simpler than what I had originally done. I originally had programmed in assembler with a Freescale micro just to jump between a number of preselected channels at a predetermined time. Then I wanted to build a really, really fast zero-crossing switch so I would "jump" when the input to the mixer crossed zero. My VFO in assembler was becoming very difficult very quickly.

I purchased two "crystal-plexed" 11 meter radios to use as a development system. I was able to fire them up on 10M with just some "tweaking." I had a couple contacts just to make sure everything worked and all was stable. So my simple project has become about 5 projects all based on the DDS VFO.

So, what do you think? Anyone else have any comments?

LabVIEWguru

Ok,

lets begin.

My design is around two registers.

There is one for the actual frequency and a register for the increment. Both registers can hold 16 digits.
Only the 8 most significant digits are used for the calculation.
The other 8 spaces hold only digits, so they do not get lost if a register is shifted right.
(Which would divide the frequency by ten.)
The register hold their values as a representation of their digit value: '0' becomes 0 and '9' becomes 9.
The frequency 31.415926 MHz would look like:

Code:
R10M R1M R100k R10k R1k R100 R10 R1 O1 O2 O3 O4 O5 O6 O7 O8
3 1 4 1 5 9 2 6 0 0 0 0 0 0 0 0

To calculate the DDS controlword You have to multiply each value with the appropriate constant and take the sum of all products.

Code:
controlword = sum(R10M * F10M + R1M * F1M + R100k * F100k + R10k * F10k + R1k * F1k + R100 * F100 + R10 * F10 + R1 * F1)

Since the coefficients are small, in the range from 0 to 9, there is no really penalty if you do a simple repeated add of the constants.
So the controlword becomes:

Code:
F10M DL 0147ae148h
F1M DL 020c49bah
F100k DL 0346dc5h
F10k DL 053e2dh
F1k DL 08638h
F100 DL 0d6ch
F10 DL 0158h
F1 DL 022h

(0147ae148h+0147ae148h+0147ae148h) + (020c49bah) + (0346dc5h+0346dc5h+0346dc5h+0346dc5h) + (053e2dh) + \
(08638h+08638h+08638h+08638h+08638h) + (0d6ch+0d6ch+0d6ch+0d6ch+0d6ch+0d6ch+0d6ch+0d6ch+0d6ch) + \
(0158h+0158h) + (022h+022h+022h+022h+022h+022h)

gives: 4056fe33h (without warranty :-)

Since i want arbitrary step values, and not only a step by digits there is second register which holds this increment.
To do a step up the increment register has to be added to the frequency register.

For a simple VCO in a receiver this might not be necessary and simpler approach, as You described may be used.

All operation is done on the frequency register and the controlword is always calculated from this register.
To display the frequency, You can simply add 030h (aka '0') to each digit to get its ASCII representation.

Direct manipulation of the control word would be useful for FM-modulation or logarithmic sweeps.

The bad news about all this are rounding errors. You can get rid of them, if You extend the constants by
two hexadecimal digits and do 8 bit right shift on the control word before You write it to the DDS.
Thats up to You... :-)

Best Regards
--
P.S.
For fast switching between arbitrary values You should consider the AD9856 and its family members.
They can hold 4 controlwords for their DDS and switch between them.
No math (but hardware) involved :-)
 « Last Edit: September 04, 2013, 01:41:33 01:41 by h0nk » Logged
LabVIEWguru
Senior Member

Offline

Posts: 285

Thank You
-Given: 239