' ----------------------------------------------------------- ' Program for Micromite to communicate with an Arduino Zero or ' Due to control an AD5355 frequency generator. ' This code also initialises an AD4351 as a 100MHz clock to drive the ' 5355 ' ' This is experimental code and will use serial comms between the two ' processor boards ' ' ' --------------------------------------------------------------------------- OPTION AUTORUN ON OPTION EXPLICIT DIM AS STRING KPStr$ = " " ' input character from touch screen keypad DIM AS STRING KPInStr$ = " "' input string from keypad (NNNN.NN) DIM AS STRING RFOFreq$ = " "' output frequency display string DIM AS STRING NuFreq$ = " " ' string version of new frequency DIM AS INTEGER index ' counter DIM AS INTEGER outData, inData ' variables DIM AS INTEGER IntFlag = 0 ' flag to show if screen has been touched DIM AS INTEGER SettChg = 0 ' flag to show when settings have changed DIM AS INTEGER Lock = 0 ' 4351 PLL lock status (1 = locked) DIM AS INTEGER FPFD = 10 ' effective Ref freq input MHz (D & T=0, R=1) DIM AS INTEGER INTA = 0 DIM AS INTEGER FRAC = 0 ' numerator of the fractional division DIM AS INTEGER MODA = 2 ' preset fractional modulus (2 - 4095) DIM AS INTEGER RFODiv = 1 ' RF output divider value (1 - 64) DIM AS FLOAT INTAF = 0.0 ' integer division factor DIM AS FLOAT FRACF = 0.0 ' FP equivalent of FRAC, used in calc's DIM AS FLOAT OutFreq4351 = 100.00 ' value for 4351 output frequency 100mhZ DIM AS FLOAT OutFreq5355 = 1000.00' value for 5355 output frequency 1000MHz DIM AS FLOAT OutRes = 100/1000 ' output frequency resolution 100 KHz Dim AS INTEGER ADFReg(6) ' array for ADF4351 control register commands ADFReg(0) = &H500000 ' initial value for ADFReg(0), for startup at 437 MHz ADFReg(1) = &H8008011 ' initial value for ADFReg(1), with 10MHz clock ADFReg(2) = &H1A004E42 ' initial value for ADFReg(2) ADFReg(3) = &H4004B3 ' initial value for ADFReg(3) ADFReg(4) = &HDA00FC ' initial value for ADFReg(4), both outputs enabled ADFReg(5) = &H580005 ' initial value for ADFReg(5) ' ' --------------------------------------------------------------------------- Const DBlue = RGB(0,0,128) CONST Bone = RGB(255,255,192) CONST White = RGB(WHITE) CONST Black = RGB(BLACK) CONST Red = RGB(RED) CONST Green = RGB(GREEN) SETPIN 22, DIN ' declare pin 22 an input (for MISO) PIN(21) = 0 ' then initialise pin 21 to low and SETPIN 21, DOUT ' declare it a digital output (MOSI) PIN(24) = 0 ' next set pin 24 to low and SETPIN 24, DOUT ' declare it a digital output (SCK) PIN(17) = 0 ' then set pin 17 to low and SETPIN 17, DOUT ' declare it a digital output (LE) SETPIN 18, DIN ' declare pin 18 a digital input (LD) PIN(16) = 0 SETPIN 16, DOUT SETPIN 15, INTL, TchInt ' call TchInt to set flag when screen touched TIMER = 0 ' reset timer so it starts ' first write to the ADF4351 registers, to initialise it PRINT "Initialising ADF4351." SendRegData ' send initialising data to ADF4351 registers Wait4Lock ' wait until PLL locked PRINT "Now generating 100.00MHz -- PLL locked!" ' then advise user PRINT " " ' ' ----------------------------------------------------------------- ' main program loop starts here ShowMainScrn ' first show the main screen DO IF IntFlag = 1 THEN CheckBtn ' if screen was touched, go check it out IF SettChg = 1 THEN ' if settings were changed PIN(16) = 0 Update5355(outFreq5355) ' calculate the new register values RFOFreq$ = STR$(outFreq5355,0,4) + " MHz" ShowMainScrn ' show main screen with new frequency print ("5355 Output Frequency " + RFOFreq$ + ", Lock = " + STR$(Lock)) PRINT " " END IF SettChg = 0 ' finally clear settings changed flag PAUSE 500 ' set to loop about twice per second LOOP END ' end of main part of program; subroutines and functions follow ' ----------------------------------------------------------------- ' subroutine to show the main LCD screen with buttons SUB ShowMainScrn IntFlag = 0 ' clear interrupt flag to begin CLS Black RFOFreq$ = STR$(OutFreq5355,0,2) + " MHz" RBOX 0,0, MM.HRes-2, MM.VRes-2, 5, RGB(Cyan), DBlue TEXT MM.HRes/2, MM.VRes/8, " G0MGX ", CM, 1, 3, Red, DBlue TEXT MM.HRes/2, MM.VRes/4, "ADF5355 Module Driver Program", CM, 1, 1, White, DBlue TEXT MM.HRes/2, MM.VRes*3/8, "Current Frequency:", CM, 1, 2, Green, DBlue RBOX 4, MM.VRes/2, MM.HRes-10, MM.VRes/4-4, 8, Black, Red TEXT MM.HRes/2, MM.VRes*5/8, RFOFreq$, CM, 1, 3, White, Red RBOX 4, MM.VRes*3/4, MM.HRes-10, MM.VRes/4-6, 8, Black, Bone TEXT MM.HRes/2, MM.VRes*7/8, "TOUCH TO CHANGE", CM, 1, 2, Black, Bone END SUB ' ----------------------------------------------------------------- ' subroutine to set IntFlag when touchscreen is touched SUB TchInt IntFlag = 1 END SUB ' ----------------------------------------------------------------- ' subroutine to wait until PLL is in Locked state (pin 18 = 1) SUB Wait4Lock PRINT "Waiting for lock" LChk: IF (PIN(18) <> 1) THEN GOTO LChk ENDIF Lock = 1 PIN(16) = 1 print "Lock Complete" END SUB ' ----------------------------------------------------------------- ' subroutine to send command words to the six ADF4351 registers, ' in descending order as recommended SUB SendRegData For index = 5 To 0 STEP -1 outData = ADFReg(index) ' make outData the next 32-bit word to send Send32 ' then send it Print ("Reg(" + STR$(index) + ") = " + HEX$(outData, 8)) Next END SUB ' ----------------------------------------------------------------- ' subroutine to send a 32-bit word to the ADF4351 SUB Send32 PIN(17) = 0 ' first bring LE low to start transaction inData = SPIPort(22,21,24,outData,0,0,32) ' then send the 32-bit data PIN(17) = 1 ' then bring LE high to load it into register PAUSE 0.1 ' pause for 100us make sure data is latched PIN(17) = 0 ' then bring it low again END SUB ' and return ' ----------------------------------------------------------------- ' subroutine called when screen is touched, to check whether it has ' been touched on the 'TOUCH TO CHANGE' button at the bottom of ' the LCD screen (or not, in which case it just returns) SUB CheckBtn IntFlag = 0 ' first clear interrupt flag IF TOUCH(Y) < MM.VRes*3/4 THEN SettChg = 0 ' no valid button pressed, so just return EXIT SUB ' with SettChg still 0 ELSE ' must have touched button, so ChangeFreq ' go allow input of a new frequency SettChg = 1 ' and set flag to show a change was made END IF END SUB ' before returning ' ----------------------------------------------------------------- ' subroutine to change the ADF5355 output frequency SUB ChangeFreq IntFlag = 0 ' clear interrupt flag to begin CLS Black TEXT 0,MM.VRes/16, "Current Frequency:", LM,1,1, White, Black TEXT MM.HRes/4, MM.VRes*3/16, STR$(OutFreq5355,0,4), CM, 1,2, White, Black TEXT 0, MM.VRes*5/16, "Enter New Freq:", LM, 1,1, White, Black BOX 0, MM.VRes*3/8, MM.HRes/2 -4, MM.VRes/8, 0, White, White TEXT MM.HRes/4, MM.VRes*7/16, SPACE$(7), CM, 1,2, Red, White TEXT 0, MM.VRes*5/8, "TOUCH OK BUTTON",LM,1,1, Green, Black TEXT 0, MM.VRes*11/16, "BELOW TO ENTER:", LM,1,1,Green, Black KPadDraw ' now go draw keypad KPInStr$ = SPACE$(7) ' clear the input string DO InCharFrmKP ' then go get a character/string from the keypad (> KPStr$) SELECT CASE KPStr$ CASE "OK" ' OK button was touched IF KPInStr$ = SPACE$(7) THEN EXIT DO ' if KPInStr$ null string, exit now NuFreq$ = LEFT$(KPInStr$, 7) ' otherwise make KPInStr$ the new Frequency IF Val(NuFreq$) < 52 OR VAL(NuFreq$) > 13600 THEN EXIT DO ' bomb out if outside range TEXT MM.HRes/4, MM.VRes*7/16, NuFreq$, CM, 1,2, Red, White ' show it OutFreq5355 = VAL(NuFreq$) ' then update output frequency EXIT DO ' and leave CASE "0" TO "9", "-", "." KPInStr$ = RIGHT$(KPInStr$, 6) ' a numeral, so shorten KPInStr$ KPInStr$ = KPInStr$ + KPStr$ ' then add the new digit to it TEXT MM.HRes/4, MM.VRes*7/16, KPInStr$, CM, 1,2, Red, White ' & show it CASE CHR$(08) KPInStr$ = Left$(KPInStr$, LEN(KPInStr$) -1) 'if it's a backspace, blank last char TEXT MM.HRes/4, MM.VRes*7/16, KPInStr$ + " ", CM, 1,2, Red, White '& re-show END SELECT PAUSE 250 LOOP END SUB ' ----------------------------------------------------------------- ' subroutine to draw keypad on right, OK & backspace buttons lower left SUB KPadDraw ' keypad boxes RBOX MM.HRes/2, 0, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*4/6, 0, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*5/6, 0, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes/2, MM.VRes/4, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*4/6, MM.VRes/4, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*5/6, MM.VRes/4, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes/2, MM.VRes/2, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*4/6, MM.VRes/2, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*5/6, MM.VRes/2, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes/2, MM.VRes*3/4, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*4/6, MM.VRes*3/4, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone RBOX MM.HRes*5/6, MM.VRes*3/4, MM.HRes/6-4, MM.VRes/4-4, 10, Black, Bone ' boxes at lower left for backspace and OK buttons, plus legends RBOX 0, MM.VRes*3/4, MM.HRes/6-4, MM.VRes/4, 10, Black, Bone RBOX MM.HRes/6, MM.VRes*3/4, MM.HRes/3-4, MM.VRes/4, 10, Black, Bone TEXT MM.HRes/12, MM.VRes*7/8, "<-", CM, 1, 2, Black, Bone TEXT MM.HRes/3, MM.VRes*7/8, "OK", CM, 1, 3, Red, Bone ' legends for the keypad buttons TEXT MM.HRes*7/12, MM.VRes/8, "7", CM, 1, 3, Black, Bone TEXT MM.HRes*9/12, MM.VRes/8, "8", CM, 1, 3, Black, Bone TEXT MM.HRes*11/12, MM.VRes/8, "9", CM, 1, 3, Black, Bone TEXT MM.HRes*7/12, MM.VRes*3/8, "4", CM, 1, 3, Black, Bone TEXT MM.HRes*9/12, MM.VRes*3/8, "5", CM, 1, 3, Black, Bone TEXT MM.HRes*11/12, MM.VRes*3/8, "6", CM, 1, 3, Black, Bone TEXT MM.HRes*7/12, MM.VRes*5/8, "1", CM, 1, 3, Black, Bone TEXT MM.HRes*9/12, MM.VRes*5/8, "2", CM, 1, 3, Black, Bone TEXT MM.HRes*11/12, MM.VRes*5/8, "3", CM, 1, 3, Black, Bone TEXT MM.HRes*7/12, MM.VRes*7/8, "-", CM, 1, 3, Black, Bone TEXT MM.HRes*9/12, MM.VRes*7/8, "0", CM, 1, 3, Black, Bone TEXT MM.HRes*11/12, MM.VRes*7/8, ".", CM, 1, 3, Black, Bone END SUB ' -------------------------------------------------------------------- SUB InCharFrmKP ' sub to get a char from the touch keypad ' (returns char in KPStr$) IntFlag = 0 ' clear interrupt flag to begin ICFK2: IF TOUCH(X) = -1 THEN GOTO ICFK2 'wait until keypad touched ' but also loop back if no valid button was touched IF TOUCH(X) < MM.HRes/2 AND TOUCH(Y) < MM.VRes*3/4 THEN GOTO ICFK2 SELECT CASE TOUCH(X) ' now decide which button was touched CASE 0 TO MM.HRes/6-1 KPStr$ = CHR$(08) ' must have been backspace button CASE MM.HRes/6 TO MM.HRes/2-1 KPStr$ = "OK" ' must have been OK button CASE MM.HRes/2 TO MM.HRes*2/3-1 'first column of keypad itself SELECT CASE TOUCH(Y) ' must be first column CASE 0 TO MM.VRes/4 -1 ' if it's in the first row KPStr$ = "7" ' must be the 7 button CASE MM.VRes/4 TO MM.VRes/2 -1 'try second row KPStr$ = "4" ' must be the 4 button CASE MM.VRes/2 TO MM.Vres*3/4 -1 'try third row KPStr$ = "1" ' must be the 1 button CASE MM.VRes*3/4 TO MM.VRes ' try fourth row KPStr$ = "-" ' must be the hyphen button END SELECT CASE MM.HRes*2/3 TO MM.HRes*5/6-1 'centre column of keypad SELECT CASE TOUCH(Y) CASE 0 TO MM.VRes/4 -1 ' if it's in the first row KPStr$ = "8" ' must be the 8 button CASE MM.VRes/4 TO MM.VRes/2 -1 'try second row KPStr$ = "5" ' must be the 5 button CASE MM.VRes/2 TO MM.Vres*3/4 -1 'try third row KPStr$ = "2" ' must be the 2 button CASE MM.VRes*3/4 TO MM.VRes ' try fourth row KPStr$ = "0" ' must be the 0 button END SELECT CASE MM.HRes*5/6 TO MM.HRes ' last column of keypad SELECT CASE TOUCH(Y) CASE 0 TO MM.VRes/4 -1 ' if it's in the first row KPStr$ = "9" ' must be the 9 button CASE MM.VRes/4 TO MM.VRes/2 -1 'try second row KPStr$ = "6" ' must be the 6 button CASE MM.VRes/2 TO MM.Vres*3/4 -1 'try third row KPStr$ = "3" ' must be the 3 button CASE MM.VRes*3/4 TO MM.VRes ' try fourth row KPStr$ = "." ' must be the DP button END SELECT END SELECT END SUB ' ----------------------------------------------------------------- ' subroutine to calculate ADF5355 register settings for a new ' frequency setting (= OutFreq5355) SUB Update5355 (Freq AS FLOAT) PRINT "WRITING TO COM2 "; PRINT Freq OPEN "COM2:9600" AS #2 PRINT #2, Freq CLOSE #2 END SUB ' ----------------------------------------------------------------- ' SPI Port function (Revised by Geoff Graham, 4/8/2017) CFunction SPIPort(integer, integer, integer, integer) integer 00000008 40024800 00442021 40024800 0044102B 1440FFFD 00000000 03E00008 00000000 27BDFFB0 AFBF004C AFBE0048 AFB70044 AFB60040 AFB5003C AFB40038 AFB30034 AFB20030 AFB1002C AFB00028 00808821 00A09021 00C0A021 00E0A821 10800005 8FB30068 10A00004 3C029D00 14C00008 3C109D00 3C029D00 8C420010 00002021 24050002 0040F809 00003021 3C109D00 8E020010 8E240000 24050002 0040F809 00003021 8E020024 8E240000 0040F809 00002821 AFA20018 8E020028 0040F809 8E240000 AFA2001C 8E020024 8E440000 0040F809 24050006 AFA20020 8E020024 8E440000 0040F809 24050005 AFA20024 8E020028 0040F809 8E440000 24170001 0057B804 8FA20064 10400008 3C109D00 8C420000 50400006 8E020024 24030003 5443000D 8E020024 3C109D00 8E020024 8E840000 0040F809 24050005 0040B021 8E020024 8E840000 0040F809 24050006 1000000A 0040F021 8E840000 0040F809 24050006 0040B021 8E020024 8E840000 0040F809 24050005 0040F021 3C029D00 8C420028 0040F809 8E840000 24140001 0054A004 12600002 24110008 8E710000 2631FFFF 32220020 24030001 02238804 02208021 0002800A 0002880B 2402FFFF 2403FFFF AFA20010 12A00005 AFA30014 8EA20000 8EA30004 AFA20010 AFA30014 8FA30060 10600002 0000A821 8C750000 02301025 00009021 10400039 00009821 8FA40010 02241824 8FA60014 02061024 00621025 10400004 8FA30024 8FA20020 10000002 AC570000 AC770000 AED40000 00000000 00000000 00000000 00000000 00000000 00000000 52A00013 00121FC2 02A02021 0411FF6A 00000000 00121FC2 00131040 00122840 8FA60018 8CC40000 8FA6001C 00C42006 30840001 00A49025 00629825 AFD40000 0411FF5D 02A02021 1000000C 00101FC0 00131040 00122840 8FA60018 8CC40000 8FA6001C 00C42006 30840001 00A49025 00629825 AFD40000 00101FC0 00111042 00621025 00101842 00408821 00431025 1440FFC9 00608021 00000000 00000000 00000000 00000000 8FA20064 10400006 00000000 8C420000 10400003 24030002 14430003 02401021 AED40000 02401021 02601821 8FBF004C 8FBE0048 8FB70044 8FB60040 8FB5003C 8FB40038 8FB30034 8FB20030 8FB1002C 8FB00028 03E00008 27BD0050 End CFunction