Shop OBEX P1 Docs P2 Docs Learn Events
DDS Controller with BS2 — Parallax Forums

DDS Controller with BS2

ArchiverArchiver Posts: 46,084
edited 2003-09-26 23:30 in General Discussion
HI all,

I have again run into a snag with my developing of a program to
control the Analog Devices AD9850. Have everything working but now I
find I need to figure how to update the decimal "freq" variable using
thumbwheels, whose output is binary coded. I have 5 wheels to give a
resolution of 1 KHz. However two things are killing me (a novice).
The previous algorithm I received (thanks Tracy) works with only a 10
KHz resolution and four decimal digits.

The program is below (I hope it is not too long).

Sam.

'{$STAMP BS2}
'{$PBASIC 2.5}
' Variable declarations
clock VAR Word ' input value
freq VAR Word ' input value
dds1 VAR Word ' high 16 bits of tuning
dds0 VAR Word ' low 16 bits of tuning
J VAR Nib ' loop index
top1 VAR dds1.HIGHBYTE ' shorter names -

top0 VAR dds1.LOWBYTE ' delete
bot1 VAR dds0.HIGHBYTE
bot0 VAR dds0.LOWBYTE
control VAR Byte ' input value
control = %00000000 ' Phase/power on-of and

onoff VAR control.BIT2 ' Output control bit
RFwrk VAR Byte ' Workspace for FR
Freqwrk VAR Byte ' Workspace for freq
clock = 10000 ' for 100.00 mhz clock
freq = 0704 ' Startup OUTPUT freq
wheel0 VAR Nib ' MHz x 10
wheel1 VAR Nib ' MHZ x 1
wheel2 VAR Nib ' KHz x 100
wheel3 VAR Nib ' KHz x 10
wheel4 VAR Nib ' KHz x 1


' Setup Initial RF Off status on power up
main:
onoff = 1 ' InitiallY SET OUTPUT
GOTO genword ' Upload new state


' Main Program Loop
main1:
STOP ' temporary with no buttons present
RFonoff: ' check for RF output
BUTTON 9,0,255,250,RFwrk,1,changeRF '


freqbutton: ' check for frequency
BUTTON 10,0,255,250,Freqwrk,1,dials '
GOTO main1


changeRF:
DEBUG "state was ", IBIN8 control, CR ' REMOVE THIS LINE
onoff = ~ onoff ' Toggle third bit
DEBUG "state is ", IBIN8 control, CR ' REMOVE THIS LINE
GOTO genword ' then change the DDS


' quick and dirty routine to read thumbwheels
dials:
GOTO main1
HIGH 4
wheel0 = INA
LOW 4
HIGH 5
wheel1 = INA
LOW 5
HIGH 6
wheel2 = INA
LOW 6
HIGH 7
wheel3 = INA
LOW 7
HIGH 8
wheel4 = INA
LOW 8


' Routine to update the "freq" decimal variable
upd:

' ??????


' Routine to generate output word for DDS card
genword:
'
binary division loop
FOR J=15 TO 0 ' 16 bits of high word
freq=freq//clock<<1 ' remainder*2
dds1.BIT0(J)=freq/clock ' next bit
NEXT
FOR J=15 TO 0 ' 16 bits of low word
freq=freq//clock<<1 ' remainder*2
dds0.BIT0(J)=freq/clock ' next bit
NEXT
'
' This is to verify the correct word is being generated. Delete
' after program is done.
DEBUG "Control word verification", CR
DEBUG "Direct Digital Synthesis (DDS) Control Code", CR
DEBUG "BIN = ", BIN8 top1, 32, BIN8 top0, 32
DEBUG BIN8 bot1, 32, BIN8 bot0, CR
DEBUG "HEX = ", HEX2 top1, 32, HEX2 top0, 32
DEBUG HEX2 bot1, 32, HEX2 bot0, CR

'
send to port
update:
SHIFTOUT 13,14,0,[noparse][[/noparse]dds0\16,dds1\16,control] ' P8 data, P9 clock,
HIGH 15 ' P15 is FQ_UD (freq
LOW 15
DEBUG "Entire word", TAB, BIN8 control, BIN16 dds1, BIN16 dds0,
CR ' Temporary
GOTO main1

Comments

  • ArchiverArchiver Posts: 46,084
    edited 2003-09-26 23:30
    Hi again,

    That particular simple algorithm I showed you is suited to a
    numerator and denominator <32768, that is, your 100 megahertz clock
    was represented by the number 10000, and the frequency was a number
    from 0000 to 9999.

    The plot thickens when you want a range of 00000 to 99999 with a
    clock represented as 100000. The simple algorithm poops out. Not to
    say it is impossible (of course not!). It is just takes a more
    "basic" algorithm, where the stamp must manage the double precision
    shifts and double precision subtract and compare. The following URL
    has PBASIC routines for 32x32 and 40x32 binary divide routines, to
    show you what kind of code is needed:
    http://www.emesys.com/division.htm

    Clock and Freq both have to be represented as double precision
    values, at least as 17 bits.

    There is a similar challenge with the BCD thumbwheels. It is easy to
    get the number up to 9999:
    freq = wheel1*10+wheel2*10+wheel3*10+wheel4

    (note the Stamp evaluates this progressive from left to right, so
    wheel1 ends up being multiplied times 10^3.) But that would run into
    a problem if try to put in wheel0*10 at the left, because the total
    could 65536. Say you enter 77777. The following formula would end
    up with freq=12241 instead of 77777. (12241+65536=77777)

    freq = wheel0*10+wheel1*10+wheel2*10+wheel3*10+wheel4 ' can fail

    There can be a 1 bit carry into the 17th bit in either the last * 10
    or the last +wheel4. Here is one way to get a double precision
    result, where freq0 is the least significant word and freq1 is the
    most significant:
    freq0 = wheel0*10+wheel1*10+wheel2*10+wheel3
    freq0 = freq0 * 10
    freq1 = freq0 ** 10 ' possible carry from multiply
    freq0 = freq0 + wheel4
    IF freq0 < wheel4 then freq1 = 1 ' possible carry from add

    If Clock is represented as the constant 100000, that is double precision:
    clock0 = 34464
    clock1 = 1 ' 100000 = 65536 + 34464

    Once you have that, you have to call the double precision binary long
    division as described in the above URL, to calculate the 32 bit
    binary fraction that approximates freq1:freq0 / clock1:clock0.

    Sound like something to do for a fun weekend?!!??

    -- Tracy
    http://www.emesystems.com





    >HI all,
    >
    >I have again run into a snag with my developing of a program to
    >control the Analog Devices AD9850. Have everything working but now I
    >find I need to figure how to update the decimal "freq" variable using
    >thumbwheels, whose output is binary coded. I have 5 wheels to give a
    >resolution of 1 KHz. However two things are killing me (a novice).
    >The previous algorithm I received (thanks Tracy) works with only a 10
    >KHz resolution and four decimal digits.
    >
    >The program is below (I hope it is not too long).
    >
    >Sam.
    >
    >'{$STAMP BS2}
    >'{$PBASIC 2.5}
    > ' Variable declarations
    >clock VAR Word ' input value
    >freq VAR Word ' input value
    >dds1 VAR Word ' high 16 bits of tuning
    >dds0 VAR Word ' low 16 bits of tuning
    >J VAR Nib ' loop index
    >top1 VAR dds1.HIGHBYTE ' shorter names -
    >
    >top0 VAR dds1.LOWBYTE ' delete
    >bot1 VAR dds0.HIGHBYTE
    >bot0 VAR dds0.LOWBYTE
    >control VAR Byte ' input value
    >control = %00000000 ' Phase/power on-of and
    >
    >onoff VAR control.BIT2 ' Output control bit
    >RFwrk VAR Byte ' Workspace for FR
    >Freqwrk VAR Byte ' Workspace for freq
    >clock = 10000 ' for 100.00 mhz clock
    >freq = 0704 ' Startup OUTPUT freq
    >wheel0 VAR Nib ' MHz x 10
    >wheel1 VAR Nib ' MHZ x 1
    >wheel2 VAR Nib ' KHz x 100
    >wheel3 VAR Nib ' KHz x 10
    >wheel4 VAR Nib ' KHz x 1
    >
    >
    >' Setup Initial RF Off status on power up
    >main:
    >onoff = 1 ' InitiallY SET OUTPUT
    >GOTO genword ' Upload new state
    >
    >
    >' Main Program Loop
    >main1:
    >STOP ' temporary with no buttons present
    >RFonoff: ' check for RF output
    >BUTTON 9,0,255,250,RFwrk,1,changeRF '
    >
    >
    >freqbutton: ' check for frequency
    >BUTTON 10,0,255,250,Freqwrk,1,dials '
    >GOTO main1
    >
    >
    >changeRF:
    >DEBUG "state was ", IBIN8 control, CR ' REMOVE THIS LINE
    >onoff = ~ onoff ' Toggle third bit
    >DEBUG "state is ", IBIN8 control, CR ' REMOVE THIS LINE
    >GOTO genword ' then change the DDS
    >
    >
    >' quick and dirty routine to read thumbwheels
    >dials:
    >GOTO main1
    >HIGH 4
    >wheel0 = INA
    >LOW 4
    >HIGH 5
    >wheel1 = INA
    >LOW 5
    >HIGH 6
    >wheel2 = INA
    >LOW 6
    >HIGH 7
    >wheel3 = INA
    >LOW 7
    >HIGH 8
    >wheel4 = INA
    >LOW 8
    >
    >
    >' Routine to update the "freq" decimal variable
    >upd:
    >
    >' ??????
    >
    >
    >' Routine to generate output word for DDS card
    >genword:
    > '
    binary division loop
    > FOR J=15 TO 0 ' 16 bits of high word
    > freq=freq//clock<<1 ' remainder*2
    > dds1.BIT0(J)=freq/clock ' next bit
    > NEXT
    > FOR J=15 TO 0 ' 16 bits of low word
    > freq=freq//clock<<1 ' remainder*2
    > dds0.BIT0(J)=freq/clock ' next bit
    > NEXT
    > '
    > ' This is to verify the correct word is being generated. Delete
    > ' after program is done.
    > DEBUG "Control word verification", CR
    > DEBUG "Direct Digital Synthesis (DDS) Control Code", CR
    > DEBUG "BIN = ", BIN8 top1, 32, BIN8 top0, 32
    > DEBUG BIN8 bot1, 32, BIN8 bot0, CR
    > DEBUG "HEX = ", HEX2 top1, 32, HEX2 top0, 32
    > DEBUG HEX2 bot1, 32, HEX2 bot0, CR
    >
    >'
    send to port
    >update:
    > SHIFTOUT 13,14,0,[noparse][[/noparse]dds0\16,dds1\16,control] ' P8 data, P9 clock,
    > HIGH 15 ' P15 is FQ_UD (freq
    > LOW 15
    > DEBUG "Entire word", TAB, BIN8 control, BIN16 dds1, BIN16 dds0,
    >CR ' Temporary
    >GOTO main1
    >
    >
    >To UNSUBSCRIBE, just send mail to:
    > basicstamps-unsubscribe@yahoogroups.com
    >from the same email address that you subscribed. Text in the
    >Subject and Body of the message will be ignored.
    >
    >
    >Your use of Yahoo! Groups is subject to http://docs.yahoo.com/info/terms/
Sign In or Register to comment.