Home
JAQForum Ver 20.06
Log In or Join  
Active Topics
Local Time 07:24 05 May 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : MM2: AD9850 Freq Gen with IR control

Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 8592
Posted: 08:01am 03 Dec 2014
Copy link to clipboard 
Print this post

This program is a complete solution for an IR controlled Frequency generator based on one of the AD9850 modules that are widely available.

This will be the last new topic for a bit I promise. The Micromite 2 really does make things very easy. This was going to be a port of the PICAXE program I use for my bench frequency generator but it ended up much easier to start from scratch.

I've put together the code from the NEC IR receiver together with the driver for the MAX7219 display and added a driver for the AD9850 plus a tiny bit of program logic.

The wiring of the AD9850 module is important to set it into serial mode:

VCC pins 1,18,19,20
GND pins 6,11,17

For my program I'm using pins for the AD9850 as follows:
MM2 pin 16 to pin 4 (Data)
MM2 pin 9 to pin 3 (Latch)
MM2 pin 26 to pin 2 (Clock)
output to scope pin 10

I'm bit banging the output to the AD9850 as neither the MAX7219 or AD9850 have a proper chip select. Both just use a short latch pulse to load the data and it seemed wrong to send both all the clock and data pulses and hope they discard the correct ones.

The main program implements a very simple state machine. On startup, having restored the last used frequency (or 1000hz if first time run) it passes through an update mode which updates the AD9850 and then sits in wait-input mode waiting for a character from the IR remote.

On first valid input (0-9) it goes into program-mode and displays the input with leading "." characters.

If a complete frequency is not input within a specified timeout (set to 30secs). The program leaves program-mode and returns to wait-input mode restoring the display to the original frequency.

As characters are input the display is shifted left so the frequency is input most significant digit first.

If 8 digits are input or the "play" key is pressed on the remote the program enters prepare-update mode.
Here the frequency is tested against a maximum allowed (I've set this at 20MHz). If it passes the test the new frequency is copied to the output frequency parameter and the program jumps to update mode as described above.

If the test is not passed the display is restored and the program re-enters wait-input mode.

The frequency calculation has been tested against the Analog Devices online calculator and the frequency output checked on my scope.

By building on the modules posted earlier this post has now taken longer to write than the program.

Wait Input mode

Program mode



'
' IR controlled frequency generator
'
option explicit
option default integer
option autorun on
cpu 48
'
const CS=10 'latch pin for display
const ADLATCH=9 'latch pin for ad9850
const ADCLK=26
const ADDATA=16
const MAXfrequency=20000000
'
' MAX7219 Registers
const decode=&H09
const intens=&H0A
const scanlim=&H0B
const shutdwn =&H0C
const digtest=&H0F
' MAX7219 Data Constants
const Set_Off = 0
const Set_On = 1
const No_Digits = 7 ' Scan limit for digits 0 to 3 = 4
const Dec_Digits = 15 ' decode digits 0 to 3 according to "code B"
const Init_Inten = 12 ' 0 (=1/32 PWM on time) to 15 (=31/32 PWM on time)
const DigBlank = 15 '"Code B" value to black a digit
const DecimPnt = 128 ' Add this value to a digit value/code when we want the decimal point illuminated
const Decimal = 10
const Hexadec = 16
' Array of segment codes for numbers and letter approximations
data &H7E, &H30, &H6D, &H79, &H33, &H5B, &H5F, &H70, &H7F, &H7B, &H77, &H1F, &H4E, &H3D, &H4F, &H47, &H5E, &H37
data &H30, &H3C, &H2F, &H0E, &H55, &H15, &H1D, &H67, &H73, &H05, &H5B, &H0F, &H3E, &H1C, &H5C, &H49, &H3B, &H6D
'
' Global variables
'
dim as integer IRreceived=0,IRread=0,IRbuffer(8);
'
INIT:
pause 1000
dim outfrequency,buildfrequency,digit,displayed$ length 8
dim ch(36),i
for i= 0 to 35
read ch(i)
next i
initmax7219
initAD9850
outfrequency=1000
setpin 2,intl,readpulses,pullup 'enable the IR interrupt
var restore 'get the last frequency if not first time in
updateAD9850(outfrequency)
'
Main:
updateAD9850(outfrequency)
var save outfrequency
waitinput:
display(str$(outfrequency,8))
do
loop while IRread=IRreceived ' start an input process
timer=0 'start the timer to see if we get bored waiting for input
buildfrequency=0
getinput:
' the next test will fall straight through first time in as we know there is a character waiting
do
loop while IRread=IRreceived and timer < 30000' start an input process
if timer >= 30000 then goto waitinput 'if the user is too slow then no cha
digit = IRbuffer(IRread) 'get the character
IRread=(IRread+1) mod 8
if digit=13 and buildfrequency=0 then goto waitinput 'cr but no input
if digit=13 then goto prepareupdate

buildfrequency=buildfrequency*10+digit
display(str$(buildfrequency,8,0,"."))
if buildfrequency>=10000000 then goto prepareupdate 'got 8 character so must be complete
goto getinput
prepareupdate:
if buildfrequency<=Maxfrequency then goto doupdate
goto waitinput 'frequency was to high so go back to current frequency
doupdate:
outfrequency=buildfrequency
goto main
end
'
readpulses:
local i,j
i=NECreceive()
if i<>&HFF then 'We don't want repeats for this application
if ((IRreceived+1) mod 8) <> IRread then 'check for buffer full
select case i
case &H16
j=0
case &H0C
j=1
case &H18
j=2
case &H5E
j=3
case &H08
j=4
case &H1C
j=5
case &H5A
j=6
case &H42
j=7
case &H52
j=8
case &H4A
j=9
case &H43
j=13
case else
j=-1
end select
if j>=0 then
IRbuffer(IRreceived)=j
IRreceived=(IRreceived+1) mod 8
endif
endif
endif
ireturn
'
sub updateAD9850(frequency)
local AD9850pout,i,j,k
ad9850pout=(frequency<<32)\125000000
for i=0 to 32 step 8
j=(AD9850pout>>i) and &HFF
for k=0 to 7
PIN(ADDATA)=(j>>k) and 1
pulse ADCLK,0.005
next k
next i
pulse ADLATCH,0.005
end sub
'
sub initAD9850
pin(ADLATCH)=0
setpin ADLATCH,dout
pin(ADCLK)=0
setpin ADCLK,dout
pin(ADDATA)=0
setpin ADDATA,dout
end sub
'
sub initmax7219
pin(cs)=0
setpin cs, dout
SPI OPEN 1000000,3,16
sendcommand(decode,0) 'we want straight access to the elements of the LEDs
sendcommand(intens,Init_Inten)
sendcommand(scanlim,No_Digits)
sendcommand(Shutdwn, Set_on)
sendcommand(DigTest, Set_Off)
clearMAX7219
end sub
'
sub sendcommand(register, command)
local i = SPI((register<<8)+command)
pulse CS,0.005
end sub
'
sub display(textin$)
local text$
text$=ucase$(textin$)
local i,j,k=0,buff(16)
for i=0 to 7
buff(i)=0
endif
for i=1 to len(text$)
j=asc(mid$(text$,i,1))
if j=32 then
buff(k)=0
else
if j=46 then 'handle the special case of fullstops/decimal points
if k<>0 then
if (buff(k-1) and 128)=0 then
k=k-1
buff(k)=buff(k) or 128 'set the decimal point on the previous character
else
buff(k)=128
endif
else
buff(k)=128
endif
else
j=j-48 'convert ascii
if j>9 then j=j-7
if j>=0 and j<=35 then
buff(k)=ch(j)
else
buff(k)=0
endif
endif
endif
k=k+1
if k>=10 then exit for
next i
for i=1 to 8
sendcommand(i,buff(8-i))
next i
end sub
'
sub clearMAX7219
for i=1 to 8
sendcommand(i,0) 'blank the display
next i
end sub
'
CFunction NECreceive
00000000
27bdfed8 afbe0124 03a0f021 afc00008 3c04bf80 34840600 34058010 ac850000
afc00000 10000004 00000000 3c04bf80 34840610 ac800000 3c04bf88 34846020
8c840000 30840001 1080fff8 00000000 1000004d 00000000 3c04bf80 34840610
8c850000 8fc40000 00042080 03c42021 ac850018 10000002 00000000 00000000
3c04bf88 34846020 8c840000 30840001 308400ff 10800008 00000000 3c04bf80
34840610 8c850000 34049c40 00a4202b 1480ffe9 00000000 3c04bf80 34840610
8c850000 34049c40 00a4202b 10800004 00000000 3c04bf80 34840610 ac800000
8fc40000 24840001 afc40000 10000008 00000000 3c04bf80 34840610 8c850000
8fc40000 00042080 03c42021 ac850018 3c04bf88 34846020 8c840000 30840001
14800008 00000000 3c04bf80 34840610 8c850000 34049c40 00a4202b 1480ffed
00000000 3c04bf80 34840610 8c850000 34049c40 00a4202b 10800004 00000000
3c04bf80 34840610 ac800000 8fc40000 24840001 afc40000 8fc50000 24040042
10a4000a 00000000 3c04bf80 34840610 8c850000 34049c40 00a4202b 1480ffb7
00000000 10000002 00000000 00000000 8fc50000 24040004 14a40005 00000000
240200ff 00001821 10000057 00000000 8fc40000 2c840005 14800009 00000000
8fc40000 2c840042 10800005 00000000 00001021 00001821 1000004b 00000000
8fc40018 00042902 00a02021 00042040 00852021 afc4000c afc00004 10000016
00000000 8fc40004 24840001 00042040 afc40010 8fc40010 00042080 03c42021
8c850018 8fc4000c 0085202b 10800007 00000000 8fc40004 24050001 00852004
8fc50008 00a42025 afc40008 8fc40004 24840001 afc40004 8fc40004 2c840020
1480ffe8 00000000 8fc40008 a3c40014 8fc40008 00042202 308400ff 00042027
a3c40015 8fc40008 00042402 a3c40016 8fc40008 00042602 308400ff 00042027
a3c40017 93c50014 93c40015 00a42026 0004202b 308500ff 93c60016 93c40017
00c42026 0004202b 308400ff 00a42025 308400ff 10800005 00000000 00001021
00001821 10000008 00000000 93c50016 93c40015 00042200 00a42021 00801021
000427c3 00801821 03c0e821 8fbe0124 27bd0128 03e00008 00000000
End CFunction


 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2794
Posted: 10:49am 03 Dec 2014
Copy link to clipboard 
Print this post

OK matherp - do tell all of us how you seem to have more hours in the day than anyone else!!

Yet more code to play with - thanks once again.

If I'm late for my wedding then I'm going to 100% blame you and your code

WW

For everything Micromite visit micromite.org

Direct Email: whitewizzard@micromite.o
 
viscomjim
Guru

Joined: 08/01/2014
Location: United States
Posts: 925
Posted: 05:05pm 03 Dec 2014
Copy link to clipboard 
Print this post

Outstanding, except for this part...

This will be the last new topic for a bit I promise.

You need to break that promise. This is great stuff and greatly appreciated!!
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024