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 KingdomPosts: 8592 |
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 KingdomPosts: 2794 |
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 StatesPosts: 925 |
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 |