' 0C5BD99AD1F61FFAC338EC4E52E759BD0CE29A82B8FF5CC4C13660ED546621A1ED6152AB7E085784AFF60FD003ABBF0493E3D9FA0E02070E0A84C0C19767360A ' sRipeTech ' 8D2ADA514 2024-09-16 17:02:28 ' using an Adafruit FT232H breakout board to drive a HC-SR08 AD9850 DDS board ' uses the parallel mode of loading the frequency information ' ----------------------------------------------- ' A fairly minimalistic program. ' Once run, you set the frequency of the AD9850 using the command ' ' AD9850setFrequency (freq) ' where freq represents the required frequency ' e.g. ' AD9850setFrequency (1.5) ' to 1.5 Hz ' AD9850setFrequency (1000) ' to 1 kHz ' AD9850setFrequency (1000000) ' to 1 MHz ' Note: fractional values are allowed ' lowest frequency is about 0.03 Hz ' ----------------------------------------------- ' Adafruit FT232H breakout board ' ----------------------------------------------- ' Helpful documents from: ' Future Technology Devices International Limited (FTDI) ' http://ftdichip.com ' Specifically: ' D2XX Programmer's Guide ' AN_255_USB-to-I2C-Example-using-the-FT232H-and-FT201X-devices ' AN_113_FTDI_Hi_Speed_USB_To_I2C_Example ' This demo accesses the Adfruit FT232H board via the FTD2XX (USB) device driver ' obtained from https://ftdichip.com/drivers/d2xx-drivers/ ' Is in the downloadfile: CDM212364_Setup.zip ' Install the driver as "administrator" ' ----------------------------------------------- ' HC-SR08 AD9850 DDS board ' ----------------------------------------------- ' Helpful documents from: ' Analog Devices, Inc ' Specifically: ' https://www.analog.com/media/en/technical-documentation/data-sheets/ad9850.pdf ' ' There appears to be limited information on the HC-SR08 DDS_A9850, try a WEB search ! ' ----------------------------------------------- ' program logic is basically ' set the FT232H into GPIO mode ' all commands to the FT232H are then simple FT_WRITE commands ' one command to initialise the AD9850 ' one command to load a frequency to the AD9850 ' ----------------------------------------------- ' Inter-board wiring ' ----------------------------------------------- ' pins used on the Adafruit FT232H breakout board and the AD9850 board ' FT232H AD bus D0 to the W_CLK pin on the AD9850 ' FT232H AD bus D2 to the FU_UD pin on the AD9850 ' FT232H AD bus D4 to the RESET pin on the AD9850 ' ' FT232H AC bus D0 through to FT232H AC bus D7 are wired to the AD9850 D0 - D7 ' output signal was taken from the AD9850 Sine Wave out 1 pin ' ----------------------------------------------- ' Program: ' ----------------------------------------------- newscript ' ----------------------------------------------- ' pins used on the Adafruit FT232H breakout board and the AD9850 board dim WCLKPin = 0x01 lshift 0 ' FT232H AD bus D0 to the W_CLK pin on the AD9850 dim FQUDPin = 0x01 lshift 2 ' FT232H AD bus D2 to the FU_UD pin on the AD9850 dim RESETPin = 0x01 lshift 4 ' FT232H AD bus D4 to the RESET pin on the AD9850 ' ----------------------------------------------- ' global variables dim myDLL , FT_ListDevices , FT_GetVIDPID , FT_Reload , FT_SetUSBParameters , FT_Close , FT_Open , FT_OpenEx dim FT_ResetDevice , FT_GetQueueStatus , FT_SetChars , FT_SetTimeouts , FT_SetLatencyTimer , FT_SetFlowControl dim FT_SetBaudRate , FT_SetBitMode , FT_Write , FT_Read , FT_GetDeviceInfo dim gcmdIndex = 0 dim gCmdBuffer = bytearray ( 256 ) dim ftHandle = -1 const selectDeviceId = 0 ' I have assumed that there is only ONE FT232H device connected const wrLoByteCmd = 0x80 const wrHiByteCmd = 0x82 ' ----------------------------------------------- ' BOR = bitwise OR ' BAND = bitwise AND const RESETOff = ( 0*WCLKPin) BOR ( 0*FQUDPin) BOR ( 0*RESETPin ) BAND 0xff const RESETOn = ( 0*WCLKPin) BOR ( 0*FQUDPin) BOR ( 1*RESETPin ) BAND 0xff const WCLKOff = ( 0*WCLKPin) BOR ( 0*FQUDPin) BOR ( 0*RESETPin ) BAND 0xff const WCLKOn = ( 1*WCLKPin) BOR ( 0*FQUDPin) BOR ( 0*RESETPin ) BAND 0xff const FQUDOff = ( 0*WCLKPin) BOR ( 0*FQUDPin) BOR ( 0*RESETPin ) BAND 0xff const FQUDOn = ( 0*WCLKPin) BOR ( 1*FQUDPin) BOR ( 0*RESETPin ) BAND 0xff ' ----------------------------------------------- FUNCTION defineFTD2XXlinks () myDLL = dll.open ("FTD2XX") IF ( myDLL == 0 ) THEN Message ="Could not open the DLL file" STOP END IF ' not all of these are stictly necessary for this program! ' FT_STATUS FT_ListDevices (PVOID pvArg1, PVOID pvArg2, DWORD dwFlags) FT_ListDevices = dll.link( myDLL, "FT_ListDevices", 3 , "unsigned" ) ' FT_STATUS FT_GetVIDPID (DWORD * pdwVID, DWORD * pdwPID) FT_GetVIDPID = dll.link( myDLL, "FT_GetVIDPID", 2 , "unsigned" ) ' FT_STATUS FT_Reload (WORD wVID, WORD wPID) FT_Reload = dll.link( myDLL, "FT_Reload", 2 , "unsigned" ) ' FT_STATUS FT_SetUSBParameters (FT_HANDLE ftHandle, DWORD dwInTransferSize, DWORD dwOutTransferSize) FT_SetUSBParameters = dll.link( myDLL, "FT_SetUSBParameters" , 3 , "unsigned" ) ' FT_STATUS FT_Close (FT_HANDLE ftHandle) FT_Close = dll.link( myDLL, "FT_Close" , 1 , "unsigned" ) ' FT_STATUS FT_Open (int iDevice, FT_HANDLE *ftHandle) FT_Open = dll.link( myDLL, "FT_Open" , 2 , "unsigned" ) ' FT_STATUS FT_OpenEx (PVOID pvArg1, DWORD dwFlags, FT_HANDLE *ftHandle) FT_OpenEx = dll.link( myDLL, "FT_OpenEx" , 3 , "unsigned" ) ' FT_STATUS FT_ResetDevice (FT_HANDLE ftHandle) FT_ResetDevice = dll.link( myDLL, "FT_ResetDevice" , 1 , "unsigned" ) ' FT_STATUS FT_GetQueueStatus (FT_HANDLE ftHandle, LPDWORD lpdwAmountInRxQueue) FT_GetQueueStatus = dll.link( myDLL, "FT_GetQueueStatus" , 2 , "unsigned" ) ' FT_STATUS FT_SetChars (FT_HANDLE ftHandle, UCHAR uEventCh, UCHAR uEventChEn, UCHAR uErrorCh, UCHAR uErrorChEn) FT_SetChars = dll.link( myDLL, "FT_SetChars" , 5 , "unsigned" ) ' FT_STATUS FT_SetTimeouts (FT_HANDLE ftHandle, DWORD dwReadTimeout, DWORD dwWriteTimeout) FT_SetTimeouts = dll.link( myDLL, "FT_SetTimeouts" , 3 , "unsigned" ) ' FT_STATUS FT_SetLatencyTimer (FT_HANDLE ftHandle, UCHAR ucTimer) FT_SetLatencyTimer = dll.link( myDLL, "FT_SetLatencyTimer" , 2 , "unsigned" ) ' FT_STATUS FT_SetFlowControl (FT_HANDLE ftHandle, USHORT usFlowControl, UCHAR uXon, UCHAR uXoff) FT_SetFlowControl = dll.link( myDLL, "FT_SetFlowControl" , 4 , "unsigned" ) ' FT_STATUS FT_SetBaudRate (FT_HANDLE ftHandle, DWORD dwBaudRate) FT_SetBaudRate = dll.link( myDLL, "FT_SetBaudRate" , 2 , "unsigned" ) ' FT_STATUS FT_SetBitMode (FT_HANDLE ftHandle, UCHAR ucMask, UCHAR ucMode) FT_SetBitMode = dll.link( myDLL, "FT_SetBitMode" , 3 , "unsigned" ) ' FT_STATUS FT_Write (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpdwBytesWritten) ' seems to be limited to a buffer of 256 bytes FT_Write = dll.link( myDLL, "FT_Write" , 4 , "unsigned" ) ' FT_STATUS FT_Read (FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToRead, LPDWORD lpdwBytesReturned) FT_Read = dll.link( myDLL, "FT_Read" , 4 , "unsigned" ) ' FT_STATUS FT_GetDeviceInfo (FT_HANDLE ftHandle, FT_DEVICE *pftType, LPDWORD lpdwID, PCHAR pcSerialNumber, PCHAR pcDescription, PVOID pvDummy) FT_GetDeviceInfo = dll.link( myDLL, "FT_GetDeviceInfo" , 6 , "unsigned" ) END function ' ----------------------------------------------- FUNCTION ErrorReport ( ftStatus , txt ) report ' display the report panel report = "ftStatus = " & ftstatus & chr(0x0a) & txt STOP END function ' ----------------------------------------------- FUNCTION OnNewScript () IF ( ftHandle) then Report ( " OnNewScript for FT232H called " & hex( fthandle) ) FT_Close(ftHandle) ftHandle = 0 END IF inherit OnNewScript () END function ' ----------------------------------------------- FUNCTION FT232hclose () dim ftStatus = 0 IF ( ftHandle == -1 ) then ELSE ftStatus = ftStatus BOR FT_Close ( ftHandle ) IF ftStatus THEN ErrorReport ( ftStatus , "Can not close the previous device " ) END IF END IF ftHandle = -1 END Function ' ----------------------------------------------- FUNCTION FT232HWaitForResponses ( nbrBytesExpected ) ' return nbr read bytes dim TimeOutCounter = 100 dim BytesInRxQueue=0 , nbrBytesRead = 0 , i dim ftStatus = 0 returnValue = 0 DO Sleep(60) ' ms ftStatus = FT_GetQueueStatus ( ftHandle , @ BytesInRxQueue ) TimeOutCounter-- LOOP while ( ( ftStatus == 0 ) AND ( BytesInRxQueue < nbrBytesExpected ) AND ( TimeOutCounter ) ) IF ( ( ftStatus == 0 ) AND ( TimeOutCounter ) ) THEN ftStatus = ftStatus BOR FT_Read(ftHandle, @ gCmdBuffer, BytesInRxQueue , @ nbrBytesRead) IF ftStatus THEN ErrorReport ( ftStatus , "bad Wait for response A") ELSE freestring = "' Read from Master Queue: Wanted " & nbrBytesExpected & " inQueue: " & BytesInRxQueue & " Read Nbr " & nbrBytesRead & ": " FOR i = 0 to (nbrBytesRead-1) freestring = freestring & " " & hex ( gCmdBuffer (i ) ) NEXT i returnValue = nbrBytesRead END IF ELSE ErrorReport ( ftStatus , "bad Wait for response B") END IF END FUNCTION ' ----------------------------------------------- FUNCTION FT232HbadCmdTest ( value) dim nbrBytesWritten =0 dim ftStatus = 0 gCmdBuffer (0) = value BAND 0x0ff ftStatus = FT_Write(ftHandle, @ gCmdBuffer, 1 , @ nbrBytesWritten) IF ftStatus THEN ErrorReport ( ftStatus , "bad FT_Write in FT232HbadCmdTest") STOP END if returnValue = false IF ( FT232HWaitForResponses (2) == 2 ) then IF ( ( gcmdBuffer(0) == 0xfa) AND ( gcmdBuffer(1) == value) ) then ELSE ErrorReport ( ftStatus , "bad cmd test " & hex(value)) STOP END If END If END function ' ----------------------------------------------- FUNCTION FT232HConfigureForGPIO ( ) dim ftStatus = 0 , BytesInRxQueue = 0 , nbrBytesRead = 0 report() ' clear the REPORT panel, ready for any error reports FT232hclose () ' just in case this function is called more than once. ' select the FT232H IF ( ftHandle == -1 ) then ftStatus = ftStatus BOR FT_Open ( selectDeviceId , @ ftHandle ) IF ftStatus THEN ErrorReport ( ftStatus , "bad FT_Open on device id: " & selectDeviceId & " Assigned to another program, or not connected") STOP END IF ELSE ErrorReport ( ftStatus , "bad FT_Open B") END IF ftStatus = ftStatus BOR FT_GetQueueStatus ( ftHandle , @ BytesInRxQueue ) IF ( ftStatus == 0 ) then FT_Read(ftHandle, @ gCmdBuffer, BytesInRxQueue , @ nbrBytesRead) ELSE ErrorReport ( ftStatus , "bad purge queue A") STOP END if ftStatus = ftStatus BOR FT_ResetDevice ( ftHandle ) ftStatus = ftStatus BOR FT_SetUSBParameters(ftHandle, 65535 , 65535 ) ftStatus = ftStatus BOR FT_SetChars(ftHandle, 0,0,0,0) ftStatus = ftStatus BOR FT_SetTimeouts(ftHandle, 5000, 5000) ftStatus = ftStatus BOR FT_SetLatencyTimer(ftHandle, 16) ftStatus = ftStatus BOR FT_SetBitMode(ftHandle, 0 , 0) ' FT_BITMODE_RESET ftStatus = ftStatus BOR FT_SetBitMode(ftHandle, 0 , 2) ' FT_BITMODE_MPSSE IF ( ftStatus ) then ErrorReport ( ftStatus , "bad init") STOP END if ftStatus = ftStatus BOR FT_GetQueueStatus ( ftHandle , @ BytesInRxQueue ) IF ( ftStatus == 0 ) then FT_Read(ftHandle, @ gCmdBuffer, BytesInRxQueue , @ nbrBytesRead) ELSE ErrorReport ( ftStatus , "bad purge queue B") STOP END if FT232HbadCmdTest (0x0aa) FT232HbadCmdTest (0x0ab) END function ' ----------------------------------------------- FUNCTION AD9850init () gcmdIndex = 0 ' ----------------------------------------------------------- ' RESET gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = RESETOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = RESETOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' enter PARALLEL mode gcmdBuffer(gcmdIndex++) = wrHiByteCmd gcmdBuffer(gcmdIndex++) = 0 gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' WCLK pulse gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' FQUD pulse gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = FQUDOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = FQUDOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- dim nbrBytesWritten = 0 dim ftStatus = 0 ftStatus = FT_Write(ftHandle, @ gCmdBuffer, gcmdIndex , @ nbrBytesWritten) IF ftStatus THEN ErrorReport ( ftStatus , "bad FT_Write in AD9850init") END if ' ----------------------------------------------------------- ' now initialise gcmdBuffer for setting the AD9850 frequency ' to say 4 kHz, actual frequency is not important. ' We simply want to populate the basic data structure dim controlDword = cint ( 4000 * 0x0ffffffff / 125000000 ) gcmdIndex = 0 ' ----------------------------------------------------------- ' WORD 0 gcmdBuffer(gcmdIndex++) = wrHiByteCmd gcmdBuffer(gcmdIndex++) = 0 gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' WORD 1 gcmdBuffer(gcmdIndex++) = wrHiByteCmd gcmdBuffer(gcmdIndex++) = (controlDword rshift 24) Band 0x0ff gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' WORD 2 gcmdBuffer(gcmdIndex++) = wrHiByteCmd gcmdBuffer(gcmdIndex++) = (controlDword rshift 16) Band 0x0ff gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' WORD 3 gcmdBuffer(gcmdIndex++) = wrHiByteCmd gcmdBuffer(gcmdIndex++) = (controlDword rshift 8) Band 0x0ff gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' WORD 4 gcmdBuffer(gcmdIndex++) = wrHiByteCmd gcmdBuffer(gcmdIndex++) = (controlDword rshift 0) Band 0x0ff gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = WCLKOff gcmdBuffer(gcmdIndex++) = 0xff ' ----------------------------------------------------------- ' FQ UP gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = FQUDOn gcmdBuffer(gcmdIndex++) = 0xff gcmdBuffer(gcmdIndex++) = wrLoByteCmd gcmdBuffer(gcmdIndex++) = FQUDOff gcmdBuffer(gcmdIndex++) = 0xff END function ' ----------------------------------------------- dim controlDword dim nbrBytesWritten = 0 dim ftStatus = 0 ' following function was written to minimise processing overhead FUNCTION AD9850setFrequency (frequency) controlDword = cint ( frequency * 0x0ffffffff / 125000000 ) gcmdBuffer(10) = (controlDword rshift 24) Band 0x0ff gcmdBuffer(19) = (controlDword rshift 16) Band 0x0ff gcmdBuffer(28) = (controlDword rshift 08) Band 0x0ff gcmdBuffer(37) = (controlDword rshift 00) Band 0x0ff IF ftStatus := FT_Write(ftHandle, @ gCmdBuffer, gcmdIndex , @ nbrBytesWritten) THEN ErrorReport ( ftStatus , "bad FT_Write in AD9850setFrequency") END if END Function ' ----------------------------------------------- ' ----------------------------------------------- ' NOW RUN THE PROGRAM ' ----------------------------------------------- defineFTD2XXlinks () FT232HConfigureForGPIO () AD9850init () AD9850setFrequency ( 2 ) STOP ' everything seems to be okay, check the OUTPUT for 2 pulses per second ' ----------------------------------------------- ' now lets generate a few sine waves. ' Will select AUDIO frequencies so that we can hear them AD9850setFrequency (0) sleep(500) AD9850setFrequency (1 * 261.625565) ' middle C sleep(500) AD9850setFrequency (0) sleep(500) AD9850setFrequency (2 * 261.625565) ' sleep(500) AD9850setFrequency (0) sleep(500) AD9850setFrequency (3 * 261.625565) ' sleep(500) AD9850setFrequency (0) sleep(500) AD9850setFrequency (4 * 261.625565) ' sleep(500) AD9850setFrequency (0) STOP ' ' ----------------------------------------------- ' now lets make a sweep generator FUNCTION sweep ( startAt , stepSize , steps ) ' following function was written to maximise the number of frequence updates per second, ' so there is NO error checking! dim frequency = startAt dim i hiresTime FOR i = 0 to steps controlDword = cint ( frequency * 0x0ffffffff / 125000000 ) gcmdBuffer(10) = (controlDword rshift 24) Band 0x0ff gcmdBuffer(19) = (controlDword rshift 16) Band 0x0ff gcmdBuffer(28) = (controlDword rshift 08) Band 0x0ff gcmdBuffer(37) = (controlDword rshift 00) Band 0x0ff FT_Write(ftHandle, @ gCmdBuffer, gcmdIndex , @ nbrBytesWritten) frequency=frequency+stepSize NEXT i report ("Frequence updates per second = " & cint (hiresTick * steps / hiresdelta )) AD9850setFrequency (0) END function STOP ' and get it to step from 0 Hz to 4000 Hz in steps of 0.5 Hz ' ----------------------------------------------- sweep ( 0 , 0.5 , 8000 ) STOP ' ' ----------------------------------------------- ' now lets make a audio-frequency sweep generator ' But rather than uniform steps between frequencies ' we shall play the 88 notes on a standard piano dim TwelthRootOf2 = 1.0594630943592952646 dim SixthRootOf2 = TwelthRootOf2 * TwelthRootOf2 FUNCTION PianoNotes () dim sleepTime = 250 dim frq = 27.5 ' Bottom A on an 88 key piano dim i FOR i = 1 to 88 AD9850setFrequency (frq) frq = frq * TwelthRootOf2 sleep ( sleepTime ) NEXT i AD9850setFrequency (0) END function pianoNotes() STOP ' ' ----------------------------------------------- ' now we will play do-rah-me-fa-so-la-ti-do ' i.e. a major key progression, based on some root frequency FUNCTION majorKey ( frq ) dim sleepTime = 250 AD9850setFrequency (0) sleep ( sleepTime ) AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * TwelthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * TwelthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime * 3 ) AD9850setFrequency (0) END function majorKey(261.625565 ) STOP ' ' ----------------------------------------------- ' now a minor key progression, based on some root frequency FUNCTION minorKey ( frq ) dim sleepTime = 250 AD9850setFrequency (0) sleep ( sleepTime ) AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * TwelthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * SixthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime ) frq = frq * TwelthRootOf2 AD9850setFrequency (frq) sleep ( sleepTime * 3 ) AD9850setFrequency (0) END function minorKey(261.625565 ) STOP ' ' ----------------------------------------------- ' now a radio-frequency sweep generator ' say from 3800000Hz to 3804000Hz ( 3.8 MHz-3.804 MHz) ' in 1 Hz steps Sweep ( 3800000, 1 , 4000 ) STOP ' ' ----------------------------------------------- ' now in 2 Hz steps Sweep ( 3800000, 2 , 2000 ) STOP '