Data AcQuisition And Real-Time AnalysisScope - Spectrum - Spectrogram - Signal Generator
Software for Windows
Science with your Sound Card!
The following is from the Daqarta Help system:
Speech and music
Musical instrument tuning
Contact us about
The DaquinOscope macro mini-app is included with Daqarta. It uses an Arduino Uno running DaqPort to collect and display 1, 2, or 4 simultaneous 0-5 VDC analog channels or 1, 2, 4, or 8 simultaneous 0-5 V digital channels.
AC input signals can be used via a simple AC-to-DC Input Level Shifter and Limiter circuit for each line. This converts signals up to +/-2.5 volts AC to 0-5 V DC, such that the original analog zero becomes +2.5 V, while -2.5 becomes 0 and +2.5 becomes +5.
Data collection takes place in 1024-sample bursts, allowing the Arduino to run at maximum speeds, and is then sent via its USB virtual serial port for display by Daqarta.
For 1-channel analog inputs, the Daqarta display will show all 1024 samples from that channel. For 2-channel analog inputs, each channel will show only 512 samples, and the Daqarta X-Axis eXpand will be used to automatically spread them out to just fill the screen width. With 4-channel analog inputs, each will have only 256 samples, again automatically filling the screen width.
Digital inputs are always acquired as 1024 samples of 8 bits (8 digital input pins) each, so no matter whether you select 1, 2, 4, or 8 channels for display, they are always shown with 1024 samples per channel.
Full triggering controls are provided, including Auto/Normal mode with adjustable level, hysteresis, delay, holdoff, and rising/falling slope controls. Whether viewing analog or digital signals, you can always trigger on any analog input (pins A0-A5) or digital input (pins 2-13). Trigger delay may be set to negative values to view waveforms that happen before the trigger event.
In addition, you may use up to 4 simultaneous digital oscillators to generate 1-bit square-wave test signals, which use phase accumulator techniques to achieve extremely fine frequency resolution. Or you may use up to 3 square waves, plus one arbitrary 8-bit waveform that uses 8 digital outputs driving a simple R-2R ladder DAC that you can build from a handful of resistors.
Please note that although DaquinOscope works normally with most main Daqarta features such as waveform and spectrum displays, cursor readouts, and Voltmeter (with some considerations in RMS mode), it does not work with the Frequency Counter. See that topic for details. Also, DaquinOscope's burst-mode operation means it can't supply the continuous data stream needed for DDisk recording.
When DaquinOscope starts up the first thing it does is invoke the _ComDev_Scan macro subroutine to locate the COM port used by the Arduino. If _ComDev_Scan hasn't run previously, either by prior use of DaquinOscope or DC_Chart_Recorder or some other macro, or it hasn't run with the same Arduino in the same USB socket, there may be a brief delay while the ports are scanned. On subsequent runs with the same device in the same socket, _ComDev_Scan will immediately return the proper port from its stored list.
On some versions of Arduino boards, there may be a 2-second initialization delay the first time the board is used in the current Daqarta session. A "Waiting for Arduino init..." message will appear during this delay. Other than the (undocumented) need for this delay, these boards run fine.
Next, a Windows file Open dialog will appear with DscopeSetup as the default filename. You can hit the ESCape key or click the Cancel button to omit loading this setup, or you can choose another setup if you have saved one when exiting a prior DaquinOscope run. (See the Saving DaquinOscope Setups subtopic for more information.)
Then DaquinOscope appears as a Custom Controls dialog that allows adjustment of various parameters. You can open this Help topic by right-clicking anywhere in the dialog. (You can also open it by clicking on the Help button when DaquinOscope is selected in the Macro List, or in the Macro Edit dialog.)
There are actually 3 different dialog pages. The default Main Controls page is discussed first, followed by Trigger Timing and Oscillators and Misc. The general layout of each dialog is shown here, with generic names Ctrl0 through Btn7 indicating positions that will be referred to in the discussion. The actual dialogs use descriptive names that may change from one dialog page to the next as their function changes.
You can switch pages by clicking the button (Btn7) at the lower right of each page; on the main page it is labeled More Controls >>>.
Note that certain important controls appear on all pages, while others are on the first two pages, and some are only on one page.
The Sample Delay control appears in the same place (Ctrl0) on all dialog pages. It adds an adjustable delay after each sample to reduce the effective sample rate. The actual measured sample rate in Hz is shown via a separate floating resizeable Sample Rate display. The displayed rate is also used to automatically update the Daqarta time (X) axis. In general, you can blindly adjust Sample Delay until you get a desired sample rate or waveform display.
The Sample Delay is applied after all requested channels per sample, and the measured sample rate is likewise the overall sample rate. For analog inputs with Sample Delay set to 0, this means that each 2-channel sample time point takes approximately twice as long to acquire as a single channel, resulting in about half the number of 2-channel samples per second. For 4 channels the overall rate is about 1/4 the single-channel rate.
As Sample Delay increases, it begins to dominate the overall sample time, so there is less difference between 1, 2, and 4 analog channels.
Note that the number of Digital channels has no effect on sample rate, since 8 channels are always sampled internally and then only the selected channels are displayed.
Using default settings for other controls, the following sample rates were obtained for various sample delays:
Sample -------- Analog -------- -- Digital 1-8 Ch -- Delay 1 ch 2 ch 4 ch Mode 0,3 Mode 1,2 0 104618 47302 24270 428094 386707 1 93601 45862 23801 317618 293578 2 85906 43866 23214 240828 226749 5 68303 38589 21724 139434 134737 10 50723 32315 19554 81920 80301 20 33516 24409 16385 44920 44421 50 16678 14054 10950 19066 18976 100 9067 8229 7059 9732 9709 200 4743 4501 4128 4917 4911
The above default Analog sampling is set to 8 bits, and uses a 2 MHz ADC Clock. These are set via controls at the lower left of the "Oscillators and Misc" controls page. Setting 10-bit sampling will reduce sample rates, as will slower ADC Clock settings. (See ADC Clock for details.)
It is also possible to use interrupt-driven sampling, but only at much lower overall sample rates (below 30 kHz or so). See the "Oscillator Interrupt Rate" and "Interrupt Lock" control topics on the same "Oscillators and Misc" controls page.
The Trigger Pin control (Ctrl1) only appears on the Main Controls dialog page, where it allows selection of the source for triggered operation. You should always set the desired source before toggling the Trigger button on (Btn1), especially if the Auto / Normal Trigger button Btn3) is in Normal Trigger mode. The reason is that if there is no triggerable signal on the selected line, Normal Trigger will wait until one arrives... which may never happen. Auto Trigger mode will wait for the Auto-Trigger Wait interval (Ctrl2 on the Trigger Timing page), which defaults to 1 second per trace update.
The Trigger Pin control looks like an edit type, but you can't actually enter anything into it. Instead, use the slider or the small up/down buttons to move through the options, which will be shown in the control window.
The selections are Analog Pin 0 through Analog Pin 5, then Digital Pin 2 through Digital Pin 13, then Wave Osc 0 if it is in use.
As indicated in the Introduction, you can use digital signals to trigger analog acquisition, or analog signals to trigger digital acquisition.
The Trigger Level control (Ctrl2) only appears on the Main Controls dialog page. It only applies to triggering from an analog source. If Trigger Hysteresis (Ctrl3) is set to 0 and Rising Trigger (Btn3) is selected, then when the raw ADC value (0-1023) of the incoming analog source rises above Trigger Level, a trigger event is detected. If Falling Trigger is selected, then the source must fall below Trigger Level.
Note that trigger level is always specified over a 10-bit range, even if the main data acquisition is only 8-bit. If you want to trigger on a specified 8-bit level you need to multiply the value by 4 before entering here.
The Trigger Hysteresis control (Ctrl3) only appears on the Main Controls dialog page. As with Trigger Level, it only applies to analog trigger sources, and is likewise in raw ADC steps but is limited to 0-255.
When set to any value above zero, Trigger Hysteresis works with Trigger Level to provide a two-threshold trigger system that is noise-resistant.
Trigger Hysteresis is added to Trigger Level to form an upper limit, and subtracted from it to form a lower limit. With Rising Trigger, the trigger source must start below the lower threshold and rise through the upper threshold before a trigger event is detected. With Falling Trigger the order is reversed.
See the main Daqarta Trigger Hysteresis topic for an extended discussion of the general principles.
Analog / Digital Inputs:
The Analog / Digital Inputs button (Btn0) appears on the Main Controls and Trigger Timing dialog pages. It toggles between analog-only and digital-only input modes. This only applies to signal display, not to trigger sources... you can have digital triggering for Analog signals, or analog triggering for Digital signals.
When in Analog mode, the Channels button (Btn2) below it can be toggled between 1, 2, and 4 channels. Btn4 below that will be labeled Analog Pins and will allow selection from among the 6 avaiable analog channels of the Arduino.
When Btn0 is in Digital mode, the Channels button can be toggled between 1, 2, 4, and 8 channels, and the button below it will be Digital Pins.
The Trigger button appears in the same place (Btn1) on all control pages. When toggled on the trigger system is activated, such that data collection waits until a trigger event is detected on the selected Trigger Pin before collecting and displaying 1024 samples. If the trigger mode is set to Auto Trigger (default) and no trigger event is detected before the Auto-Trigger Wait elapses (1 second default), then data collection begins regardless. If the trigger mode is set to Normal Trigger then it will wait indefinitely.
The above assumes that Trigger Delay (Ctrl1 on the Trigger Timing dialog page) is set to 0 (default). Positive delay values mean that data collection waits that many microseconds before collection begins. (Negative values are allowed, with certain limitations, allowing you to view events before the trigger. See the Trigger Delay topic for a full explanation.)
Trigger action is also affected by Trigger Holdoff (Ctrl3 on the Trigger Timing dialog page), which is the minimum time between trigger events. This is useful for signals like repeating tone bursts. See the topic for more information.
The Channels button (Btn2) appears on the Main Controls and Trigger Timing dialog pages, and sets the number of input channels to be sampled. Clicking this button advances from 1 Channel to 2 Channels to 4 Channels and back to 1 Channel, if the button above it (Btn0) is set to Analog Inputs.
If Btn0 is set to Digital Inputs, then the repeated clicks of the Channel button advance through 1, 2, 4, 8 and back to 1.
In either case, holding down the SHIFT key while clicking the button will decrease the number of channels, until eventually wrapping back to the maximum.
Note that increasing the number of channels causes the Y axis display to increase as well. For example, with a single channel the default display runs from 0 to 5V. With 2 channels it runs from 0 to 10V, with the second channel running from 0 to 5 and the original single channel shifted up to run from 5 to 10. With 4 channels the range is 0 to 20, with the 4th channel from 0 to 5, the 3rd from 5 to 10, the second from 10 to 15, and the 1st from 15 to 20.
These channel positions are set by DaquinOscope via the main Daqarta Individual Adjust controls in the Zero dialog, as well as overall Display Magnification. Changing the Zero settings will give erroneous axis readings, but the cursor readouts will be correct. Changing the magnification (via PgUp or PgDn keys) may drive the intended channel off the screen, but again will not affect the readouts.
In addition, with Analog Inputs the X axis changes when Channels changes. There are two factors at work here: First, the Arduino has only a single ADC to acquire analog data, so for multiple channels it must "multiplex" them by switching to each in turn and reading it separately. At the fastest speeds (no Sample Delay) it thus takes about twice as long to read two channels as one, and four times as long to read four.
Note that this multiplexing causes "channel skew", where the channels are not actually sampled simultaneously, but are displayed as if they were because the different sample times are lost. This can cause mistaken conclusions about whether events are simultaneous, or which one came first.
The second factor is due to the limited 2048-byte working memory of the Arduino Uno, which after allowing for other working variables only has room for 1024 total ADC data values. If Channels is set to 2, there is room for only 512 samples of 2-channel data; at 4 channels, only 256 samples. So DaquinOscope reduces the displayed samples (via the main Daqarta X-Axis eXpand control) so they just fill the display in each Channels mode.
The X-axis display is thus adjusted to account for both of the above factors. (There is no such Digital Inputs change, nor channel skew, since all 8 channels are always sampled simultaneously and fit into a single byte.)
IMPORTANT: If you use Daqarta's Spectrum mode to view 2 or 4 analog channels, please note that the spectrum of each channel is always computed with a full 1024 samples. When using 2-channel mode, with only 512 actual data samples per channel, 512 null samples appended to each before computing the spectrum. Likewise, with 4 channels having only 256 actual data samples each, 768 null samples are appended.
This gives less overall energy reported at every frequency due to the last half or 3/4 of the data being nulls. For a more accurate spectrum make sure Spectrum Window is active, then set Spectrum Width to 512 for 2 channels or 256 for 4, and finally make sure that the small offset button to the right of Width is toggled to '<' to align the window with the start of the data. (The default is 'o' for a centered window.)
Please read the Window Width and Peak Operation subtopic under Spectrum Window Width if you want to use Peak or Track modes.
Rising/Falling Trigger Slope:
The trigger slope button (Btn3 on the Main Controls and Trigger Timing dialog pages) toggles between Rising Trigger (default) and Falling Trigger. In Rising mode, an analog source (selected by the Trigger Pin control) must rise through the Trigger Level from below. In Falling mode it must fall through from above.
With digital sources Trigger Level is ignored. In Rising mode a trigger event happens on a rising edge, where the digital input pin rises from 0 to 1. (There is actually a threshold that is typically about halfway between 0 and 5 volts, but it is not a precise value.) In Falling mode, a change from digital 1 to 0 causes a trigger event.
The Analog/Digital Pins button (Btn4) appears on the Main Controls and Trigger Timing dialog pages. Although the 1,2,4,8 Channels button (Btn2) controls the number of channels, this Analog/Digital Pins button allows you to specify which channels to use.
Clicking this button opens a Wait Buttons Button Select dialog that allows selection of any 4 channels. If Btn0 is set to Analog Inputs then this button will be Analog Pins; you can select from ADC Pin 0 to ADC Pin 5, with 0-3 default:
The buttons you select do not need to be sequential; you can (for example) select 1, 3, 4, and 5.
Selections do not take effect until you click the OK button at the bottom of the Wait Buttons dialog.
If 1 Channel is set on Btn2, then the uppermost selected button will be displayed. For 2 channels, the upper 2 selected buttons will be used.
Things are slightly more complicated if Digital Inputs is set on Btn0. Only 8 digital pins can be used at one time, but the Arduino Uno has 13 pins, including pins 0 and 1 which are dedicated to the serial port. Pins 14 and 15 are not physically connected, but are present internally.
To allow access to all pins, DaquinOscope allows selection of Digital Mode on Btn6 of the second page of controls, labeled DaquinOscope - Trigger Timing and found by clicking the More Controls >>> button (Btn7) at the lower right of the main dialog.
With the default Digital Mode 0 = Pins 0-7, the Digital Pins button will show only those pins. Here are the Digital Pins buttons for each of the modes:
As with Analog Pins, you only select 4 pins in the Digital Pins dialog, and they don't need to be sequential. The uppermost selected pin is used for 1 Channel, the upper 2 for 2 Channels, and the upper 4 for 4 Channels. All 8 pins are used in 8 Channels mode, regardless of whether they are selected.
Auto / Normal Trigger:
The Auto / Normal Trigger button (Btn5 on the Main Controls and Trigger Timing dialog pages) defaults to Auto Trigger but can be toggled to Normal Trigger. If the main Trigger button is active, Normal Trigger waits for a valid trigger event before updating the display, such that the Trigger Pin signal meets the specified Trigger Level, Trigger Hysteresis, Rising / Falling Trigger, Trigger Delay, and Trigger Holdoff specifications. If a valid trigger event never arrives, the display is never updated.
Auto Trigger likewise waits for a valid trigger event with the same specifications, but if one doesn't arrive within Auto-Trigger Wait seconds (Ctrl2 on the Trigger Timing dialog page) the display is updated with current input channel data regardless. It will not be synchronized with anything, but you will at least be able to see what's there.
Even if you plan to ultimately use Normal Trigger, you should consider starting out with Auto Trigger until you see that you are getting the desired triggering action. If you start out with Normal, and you don't see any display updates, it can be hard to determine the problem: The input signal may have become disconnected, or it may have dropped below the Trigger Level threshold, or you may have set Trigger Pins to the wrong channel, etc. With Auto, you can easily troubleshoot the problem.
Save Data File:
Clicking Save Data File (Btn6 on the Main Controls dialog page) saves the data used to create the current display to a .DQA file, which is Daqarta's extended .WAV format. It preserves X and Y calibration data that Daqarta will use to show the original voltages and times on subsequent viewing of the file, along with any Notes that were made before clicking Save Data File.
You could use the "Save trace as DQA data file" in the main Daqarta File Menu, but that only works for 1, 2, or 4 channels... not the 8 channels available in Digital mode. Save Data File will save these properly, and Daqarta will later be able to open the file with the normal DD/Open button in the toolbar, or the Open Existing option in the File Menu.
One possible advantage of using "Save trace as DQA data file" in the File Menu for 1 or 2 channels is that it will also save main Daqarta Generator or Input channels from your sound card, along with the DaquinOscope channels, as long as they don't conflict with the Display Channels buttons at the lower left of the main Daqarta display area.
For example, with a single DaquinOscope channel active it will replace the former L.In button with Ch0, and be displayed in yellow (default color). That means that R.In, L.Out, and R.Out are still free to show the right Input and both Left and Right Generator channels normally, which will be saved along with the DaquinOscope Ch0.
On the other hand, if you display 2 DaquinOscope channels they replace both L.In and R.In channels with Ch0 and Ch1, leaving only L.Out and R.Out free for Generator signals. With 4 DaquinOscope channels there are no main Daqarta channels available for display or saving.
You will also need to use "Save trace as DQA data file" for Averager data, whether for DaquinOscope or mixed main Daqarta channels.
(Another feature of using "Save trace as DQA data file" for 1, 2, or 4 channels is that the file will subsequently appear in Recent Files; that doesn't happen when using the Save Data File button.)
Please note: The Direct-to-Disk DDisk option will not allow continuous data collection of DaquinOscope data, only sound card data. That's because the Arduino must send data over the slow USB serial port; continuous data would be limited to sample rates in the 10 Hz range. DaquinOscope gets around this by collecting 1024-sample data bursts at high speed, then sending the data back to Daqarta in a separate burst during which no incoming data can be collected. This mimics the way a hardware oscilloscope behaves with real-time data, since you couldn't view a continuous stream anyway... it has to be "frozen" in screen-sized bursts or you'd only see a blur. (You might still see only a blur, with DaquinOscope or a hardware scope, unless you have the trigger set correctly.)
After opening a saved file, Daqarta can only display 4 file channels at a time, but for 8-channel files the Display Channels buttons at the lower left of the display are labeled Ch0-Ch3 (default) and Up/Down arrows will appear to their right, allowing display (and cursor readout) of any 4 adjacent channels, from Ch0-Ch3 to Ch4-Ch7.
If you use software other than Daqarta to view DaquinOscope files, you will need to manually change the extension from .DQA to .WAV after the recording. You will lose the X and Y calibration that is included in the .DQA format, but the waveforms will be intact.
Alternatively, if you don't need 8-channel Digital files and you don't need X and Y calibration, you can use the other main File Menu options to save as .WAV, .DAT, or .TXT.
The default Save Data File name is "Dscope.DQA", which you can change by replacing the "Dscope" quoted string in the Str1="Dscope" line near the start of the DaquinOscope macro code. Note that the .DQA extension will be added automatically during the save.
You can also change the filename via the normal Windows Save As dialog that appears when you click the Save Data File button.
If you want the file names to form an ever-increasing series, such as Rat000, Rat001, etc., you can go to the main Daqarta File menu and toggle "Auto-Increment Filenames" on (a check mark will appear at the left). You can toggle this on or off any time while DaquinOscope is running.
Alternatively, you can modify the DaquinOscope macro code to always auto-increment, regardless of the main File menu Auto-Increment state, or to never auto-increment. Locate this line near the start of the code:
UF=2 ;Auto-increment DATA file name
Change the value of UF as needed:
UF=0 ;Never auto-increment UF=1 ;Always auto-increment UF=2 ;Use main Auto-Increment state
More Controls Button:
Clicking Btn7 advances the dialog to the next page. On the default page this button is labeled More Controls >>> and the page title is DaquinOscope - Main Controls. One click advances to the DaquinOscope - Trigger Timing page title, while the button itself changes to Osc and Misc Controls to indcate that if you click it again the dialog will advance to DaquinOscope - Oscillators and Misc. On that page, the button will show Main Controls to indicate that a third click will return to the default page.
Note that if you hold down the SHIFT key while clicking this button, the dialog will go back to the prior page in the cycle. If you are on the default page, it will go to DaquinOscope - Oscillators and Misc.
Trigger Timing Controls:
To reach the Trigger Timing dialog page starting from the default Main Controls page, click the More Controls >>> button (Btn7) at the lower right corner of the page.
The Trigger Delay control (Ctr1, only on the Trigger Timing dialog page) sets the delay, in microseconds, that elapses between arrival of a trigger event and the start of data collection for the next display update.
Positive Trigger Delay allows you to move the 1024-sample display "window" later in time, up to 32767 microseconds. This lets you examine events that arrive more than 1024 samples after a trigger event, which at high sample rates can be a rather short time. For example, at a typical single-channel Analog sample rate of 104618 Hz with Sample Delay at zero, the display shows less than 10 milliseconds of data. (1024 / sample rate.) With Digital inputs it could be less than 2.5 msec.
If your region of interest is later than that, you could widen the window by increasing Sample Delay to reduce the sample rate, but at the expense of resolution. That would be like using lower-power binoculars to view a scene... more things may be in view, but smaller and harder to resolve. With Trigger Delay, on the other hand, you can pan across the scene at full high-power resolution.
Sometimes you may want to see what happened before the trigger event. To accomplish this, DaquinOscope acquires data continuously into a 1024-sample circular buffer while waiting for a trigger event. When the event is detected, the Trigger Delay setting (in samples now, instead of microseconds) specifies how far back in the buffer to start when sending data to Daqarta for display.
For example, if you set Trigger Delay to -100, the Ctrl1 label will be NEG Trigger Delay, samples instead of Trigger Delay, usec. The desired display region will be from -100 to +923 samples instead of the usual 0-1023. The circular buffer starts filling while awaiting the trigger event. Suppose it is at buffer position 500 when the trigger event is detected. This means that the position 400 will correspond to the -100 Trigger Delay setting, and 400 + 1023 = 1423 will be the last sample acquired. The buffer actually holds only 1023 samples, after which it fills starting from position 0 up to 399 (400 samples) and then stops just before overwriting sample 400 (the desired -100 equivalent). Then the collected data is sent to Daqarta starting with samples 400-1023 followed by 0 to 399. The X axis is automatically adjusted to show the location of the trigger event at 0 time, with prior data shown at negative times.
The above example is for Analog Inputs with Channels set to 1, or for Digital Inputs. For 2-channel analog inputs, the maximum negative delay is -511 samples, and for 4-channel analog inputs it is -255 samples.
Please note: To allow negative Trigger Delay, you must be either in Digital Inputs mode, or Analog Inputs with ADC Bits (Btn6 of the Oscillators and Misc dialog page) set to 8 (default). You can not use 10-bit ADC Bits for this.
Also, you can not use Interrupt Lock with negative Trigger Delay. The delay will automatically be forced to 0 if it is negative when interrupts are toggled on, and the control will only accept positive values.
Important: With Analog Inputs, negative Trigger Delay requires that the Trigger Pin be set to one of the analog channels being displayed. If not, the first (lowest-numbered or top-screen) channel will be used by default.
With Digital Inputs and negative Trigger Delay the Trigger Pin requirements are more relaxed, in that you can use any digital pin as a trigger, even if it is not being displayed.
In no case can you use analog Trigger Pins with Digital Inputs, nor digital Trigger Pins with Analog Inputs when using negative Trigger Delay.
Note that for Analog Inputs there is a slight sample rate decrease with negative Trigger Delay, compared to 0 or positive delay. The reason is that for negative delay the trigger conditions must be tested on every sample, which adds a small delay to each sample interval. For 0 or positive delay all trigger testing happens before the start of sample collection, which then runs with no added sample delay.
The Auto-Trigger Wait control (Ctr2, only on the Trigger Timing dialog page) sets the maximum time, in seconds, that Auto-Trigger mode will wait for a trigger event. If no event is found, data collection proceeds anyway and the display is updated without being synchronized with anything. See the Auto Trigger subtopic for more info.
Auto-Trigger Wait may be set between 10 msec and 32767 seconds. The default is 1 second. In general, you should make this value somewhat longer than the longest expected time between triggers, but not by much. Note that when DaquinOscope is waiting for a trigger the system is unresponsive. If you set the wait time too large, you may get tired of waiting... just as you would in Normal Trigger mode instead of Auto Trigger.
The Trigger Holdoff control (Ctr3, only on the Trigger Timing dialog page) sets the minimum interval between triggers, in seconds, and defaults to 0.
Non-zero Trigger Holdoff is useful for signals like repeating tone bursts, where you want to trigger on the start of each burst, not on some arbitrary cycle of the waveform within the burst. Without Holdoff, any one of the cycles in a burst might be an acceptable trigger.
Trigger Holdoff is usually used with Normal Trigger mode, unless you are sure that the burst repeat period is less than the Auto-Trigger Wait time. Then you can use Auto Trigger mode.
The display will not be stable until Holdoff is properly set, but you should be able to see signal bursts rolling past. For Analog Inputs set Trigger Level to a value about half that of the visible peaks. The display still won't be stable, but at least it should always start at the same vertical extent of the waveform. (This is not an issue with Digital Inputs.)
The Holdoff value must be shorter than the overall burst repeat cycle by at least one cycle of the carrier frequency (the waveform that appears during a burst). It must also be at least as long as one burst (less one carrier cycle).
If you know the burst duration, set Holdoff to that value. (Note that for Holdoff purposes, the relevant duration is actually the time the burst exceeds the Trigger Level, not the overall burst duration. This is usually only an issue for bursts with slow rise and/or fall times.)
If the burst duration is variable, set Holdoff to the maximum value. If the repeat cycle is variable, set Holdoff less than the lowest repeat cycle.
For example, suppose you have a 500 Hz tone burst that varies between 10 and 15 msec, and the overall repeat cycle varies between 40 and 60 msec. One cycle of the 500 Hz carrier is 1/500 = 2 msec. Holdoff must be greater than (15 - 2) and less than (40 - 2) msec.
If you are not sure of the durations involved (which may be the case if you are not controlling them yourself, and you can't get a stable trigger to view them until Holdoff is properly set), then take a guess. You should deliberately make your guess a little too high or too low. If you start with a low value, slowly increase it until you get a stable display. If you start with a high value, slowly decrease it.
If the burst durations or repeat cycle times are variable, the display may seem to be stable for a while, then roll when the duration becomes too long or the repeat cycle too short. If so, keep changing Holdoff in the same direction until the display remains stable. If you go too far and it becomes unstable again, back off to a medium value.
The Digital Mode button (Btn6, only on the Trigger Timing dialog page) sets the range of pins used for Digital Inputs. There are 4 modes, reachable by repeated clicks as needed:
Digital Mode 0 = Pins 0-7 (default) Digital Mode 1 = Pins 2-9 Digital Mode 2 = Pins 6-13 Digital Mode 3 = Pins 8-15
Modes 0 and 3 are slightly faster than modes 1 and 2 because each uses a single port on the Arduino processor. (PORTD for Mode 0 and PORTB for Mode 3.) Unfortunately, each of these modes only accesses 6 useful pins instead of 8. That's because Pins 0 and 1 in Mode 0 are committed to the serial port, and Pins 14 and 15 in Mode 3 have no external connections.
Modes 1 and 2 are slower because they must access both PORTD and PORTB and combine the results to get the indicated 8 active pins.
Oscillators and Misc. Controls:
To reach the Oscillators and Misc. Controls dialog page starting from the default Main Controls page, click the More Controls >>> button (Btn7) at the lower right corner of the page to get to the Trigger Timing page (at which point the button becomes Osc and Misc Controls >>> to indicate what comes next), then click it one more time. The button will then be labeled Main Controls >>>, and the dialog title will be DaquinOscope - Oscillators and Misc. as shown:
DaquinOscope supports up to 4 independent oscillators, whose outputs may be used to drive external systems that are monitored by DaquinOscope's conventional oscilloscope functions.
Please note, however, that the oscillators use Arduino interrupts to control their sample rate, unlike the default Sample Delay timing used for input acquisition. The oscillator interrupt is generated by a hardware timer at a programmable rate set via the Osc. Interrupt Rate, Hz control, and all active oscillators are updated on each interrupt. This only takes a small amount of time, but it will interfere with the independent (hence unsynchronized) Sample Delay timing to cause jitter in the acquired input data.
To avoid this, DaquinOscope provides an Interrupt Lock button that forces input acquisition to also use the oscillator interrupt, instead of the Sample Delay, keeping everything synchronized. This will require much lower sample rates than the default Sample Delay system allows. See the Interrupt Lock - Rate Limits subtopic and especially Freeze-Up Recovery for more information.
All 4 of the oscillators (Osc0 - Osc3) may be square wave types, each having its output on its own selected digital Pin 2-13. (Note that Pin 13 is also connected to the Arduino's onboard LED.)
Alternatively, the 0th oscillator (Osc0) may use Pins 2-9 wired to a simple 8-bit R-2R ladder DAC to produce an arbitrary analog waveform, such as a sine wave, using a 256-step or 1024-step wavetable. (Note that the 1024-step table uses the same memory otherwise used by the oscilloscope data acquisition functions, so DaquinOscope is then no longer a "scope" but a dedicated oscillator... DaquinOsc?)
There are individual Phase and Frequency controls for each of the oscillators, accessible by toggling the Set Oscillator0 button (Btn0 on this page only) as needed. The button below that defaults to Osc0 = Pin 0 (OFF), and opens a dialog that allows you to set the digital output pin for that oscillator.
All oscillators employ phase accumulator methods to allow extremely fine frequency resolution using a constant output sample rate, set by the Osc. Interrupt Rate, Hz control (Ctrl2, on this page only). The square oscillators have a resolution of one part in 2^25, so at the default 10000 Hz sample rate the resolution is 10000 / 2^25 or 0.000298 Hz (298 microhertz). The wavetable oscillator (either 256- or 1024-step table) has a resolution of one part in 2^32, or 0.00000233 Hz (2.33 microhertz).
The frequency of each oscillator is set via the Oscillator N Freq, Hz control, where N is 0-3 as selected by the Set OscillatorN button. The lowest frequency that can be created is the same as its resolution at the given sample rate (0.000298 Hz for square, and 0.00000233 Hz for wavetable) as discussed above. (Compare to the Arduino's native tone() function, which can go no lower than 31 Hz.)
The maximum oscillator frequency is half the sample rate. This will be fine for square waves, which only need two samples per cycle. For wavetable oscillators you will need many more samples per cycle, depending on how closely you want the output to approximate the target wave shape.
Please note that the frequency control computes internal values based upon the current Osc. Interrupt Rate, Hz at the time the frequency is set. If you later change the interrupt rate, the actual output frequency will change proportionally, but the displayed Oscillator N Freq control will not change. So, you should always set the interrupt rate first, before setting any oscillator frequencies.
Free-Standing Arduino Oscillators:
When you close DaquinOscope (using the OK button or the [X] in the dialog title bar), it normally turns off the oscillators and their associated interrupts. Otherwise, they would keep running as long as the Arduino had power, and might interfere with the next application such as the DC_Chart_Recorder.
If you want to keep the oscillators running, comment out this line near the end:
Port=$(hF0) + "F" + $(hC0) ;Set Oscs (and ints) off
Then run DaquinOscope and set the oscillators as desired. Close DaquinOscope, and they will continue as before. If you have an external power supply for the Arduino, you can disconnect the USB cable from the computer to get a free-standing oscillator or set of oscillators.
This may be especially useful with a wavetable oscillator that is set to produce a continuous test schedule or a flashing LED sequence, for example.
Square Wave Jitter:
The phase accumulator method, when used for square waves, can result in a certain amount of cycle-to-cycle jitter, even though the average frequency is very accurate. (See the "Edges - Snap vs. Interpolate" subtopic under the Square Wave topic for the main Daqarta Generator for a discussion. DaquinOscope square wave oscillators use the "Snap" method.)
The jitter arises at any square wave frequency that is not an exact power of 2 divided into the sample rate. For the 10000 Hz default rate, dividing by 2, 4, 8, 16 and 32 gives 5000, 2500, 1250, 625, and 312.5 Hz respectively. The lowest possible jitter-free frequency would be with a divisor of 2^25, for a frequency of 0.000298023 Hz (equal to the frequency resolution), or a period of 3355.443 seconds or 55.92 minutes.
However, frequencies which are any even integer divided into the sample rate are much better than odd or non-integer values. For example, 1000 Hz (sample rate / 10) gives a very slow jitter, with a frequency of 0.0003 Hz or a period of 3355 seconds (55.9 minutes). On the other hand, 440 Hz has a jitter frequency of 165 Hz, or a period of only 6 msec!
Below is a table of even divisors up to 32, with the associated frequencies and jitter periods. (The perfect jitter-free values show periods of ******* to represent an infinite period.)
Note that the frequencies listed are those actually generated, which don't exactly match the results of the division because of the above-mentioned 298 microhertz frequency resolution of the phase table method. So instead of 10000 / 10 = 1000, the table shows 999.999940395 Hz... an error of 60 parts per billion. (Note that this presumes the Arduino clock generator is exactly its nominal value of 16 MHz; in reality it is probably much worse than 60 ppb.)
Div Frequency Jitter period, sec 2 5000.000000000 ******* 4 2500.000000000 ******* 6 1666.666567326 3355.443 8 1250.000000000 ******* 10 999.999940395 3355.443 12 833.333432674 1677.722 14 714.285671711 3355.443 16 625.000000000 ******* 18 555.555522442 3355.443 20 500.000119209 838.861 22 454.545319080 671.089 24 416.666567326 838.861 26 384.615361690 3355.443 28 357.142984867 559.241 30 333.333313465 3355.443 32 312.500000000 *******
You can use the Jitter_Tbl macro included with Daqarta to generate longer tables, with other sample rates than 10000 Hz. This may allow you to optimize for certain oscillator frequencies.
The actual jitter frequency and period will be displayed on a pop-up message window when you enter or change the value of any square wave oscillator.
See the Oscillator Interrupt Rate and Oscillator N Frequency control subtopics below for more information.
DaquinOscope wavetable oscillators use a circular phase accumulator that consists of an ordinary 32-bit value. At each output sample, a frequency-specific constant value is added to the accumulator and the result is used as an address into a 256- or 1024-step wavetable. The 256-step oscillator uses the uppermost 8 bits as the address into the wavetable, while the 1024-step oscillator uses the upper 10 bits.
The 8-bit value that is read from that address is then sent to the 8 output pins (Digital Pins 2-9) to produce 8-bit waveforms, typically using a simple R-2R ladder DAC. (See Wavetable DAC Construction, below.)
The 256- or 1024-step wavetable oscillator thus requires a table file with 256 or 1024 8-bit values. DaquinOscope makes it easy to provide this table by allowing you to select any Daqarta Arb file of any length, and automatically scales it to fit. Daqarta includes a library of many common and not-so-common waveforms, and you can create your own custom files using the Arb_From_Equation or Arb_From_List macro mini-apps, or from a text file of values.
To load the wavetable file, or to replace one already loaded, make sure that the Set OscillatorN button is toggled to Set Oscillator0. Then click on the Osc0 = Pin N and enter 14 for a 256-value file or 15 for a 1024-value file. (Note that only the 256-value file will allow simultaneous data acquisistion.)
A Windows file Open dialog will appear, showing all the files of .DAT type in the Daqarta - User_Data folder. Those that start with Arb_ are the included library files, described in the Arb_From_Equation topic.
After choosing a file, but before you can toggle to Oscillators ON, you'll need to enter a value for Oscillator 0 Frequency, Hz. This control assumes that the file holds exactly one cycle of the desired waveform, such that the output frequency will be the number of complete passes through the file per second. (Make sure you have set the desired interrupt rate first.)
Here's an example of the 256-step output waveform when using the Arb_Sine file with a DAC made of 10K and 20K standard 5% tolerance 1/4 watt metal film resistors. (1% tolerance was also tested and gave no measureable improvement in distortion.)
The Interrupt Rate was 40 kHz, and the Oscillator 0 Freq was set to give exactly one cycle in the 1024 samples of Daqarta display width: 40000 / 1024 = 39.0625 Hz. Note that this waveform was acquired with the ADC in 8-bit mode (at the default 2 MHz ADC Clock setting), so this is an 8-bit output viewed on an 8-bit input:
The slight flat spots at the high and low points are due to the auto-scaling of Arb_Sine from 16-bit to 8-bit resolution for DaquinOscope. These can be reduced or eliminated by using Arb_From_Equation to create a sine wave with slightly reduced amplitude factor K. Reducing it from 32767 to 32000 will eliminate the flats but give a wave with slightly less than full-scale output, while 32250 will just barely reach full scale at the peaks. But these are basically cosmetic changes that have no effect on measured distortion.
Increasing the frequency to 1000 Hz and switching Daqarta to Spectrum mode we see that there is indeed a fair amount of distortion. (But note that a "perfect" 8-bit DAC would have a similar amount, simply due to the low number of bits.)
The big DC component seen in the spectrum is due to the fact that this sine wave runs between 0 and 5 volts, not symmetrically about 0. The spectrum shows this as the equivalent of a +/-2.5 V sine riding on a +2.5 VDC baseline. (Note that 2.5 V is 20 * log10(2.5 / 1.0) = +7.96 dB above 1 volt, as indicated by the dB V Pk label. Toggling to Spectrum RMS mode would reduce everything by 3 dB, but the ratios would be the same.)
By using the Sigma mode of the cursor readouts we can measure the energy above 1500 Hz at about -30.5 dB, which relative to the +7.96 dB fundamental gives a THD+N distortion of 38.46 dB or about 1.2%. That's similar to the sine output of typical benchtop function generators. (Note that this is a "loopback" distortion measurement, so includes any distortion from the 8-bit Arduino ADC. But a separate measurement of the oscillator output using a 16-bit sound card with the THD_Meter macro mini-app found virtually the same result: 1.15% for THD+N and 0.82% for THD 25.)
It's possible to view the individual output bits by switching DaquinOscope from Analog to Digital. (You can do this even if you don't have a DAC.) By default this uses Digital Mode 0 to view pins 0-7, so toggle the More Controls >>> button at the lower right once so you see Trigger Timing in the title bar, then toggle the button at the lower left to Digital Mode 1 = Pins 2-9. Now toggle to 8 Channels:
This hints at another application for a wavetable oscillator: It isn't limited to analog output via a DAC, but can be used to drive up to 8 digital lines with arbitrary test patterns. These lines could be used to drive stepper motor phases, LEDs, relays, or any other devices that use on/off signals.
You can set Oscillator 0 Freq to super-low values to get slow stepping through the sequence, if desired.
You don't need to use any standard waveform; you can enter a list of 1024 values to create your own custom Arb, using the method in Creating Arb .DAT Files From Text.
However, note that DaquinOscope is set to use standard Daqarta Arb files, which are 16 bits and 1024, 2048, 4096, 8192, or 16384 samples; it then converts them down to 256 or 1024 samples as needed. So if you only need 256 values for a custom Arb wavetable, you'll need to enter each one 4 times to get 1024 total. One trick to do this is to use a text editor that can handle columns; enter your 256 values in a single column, then copy it to make 4 columns.
If you need to use even less states in your test sequence, you can use the same trick to make 8, 16, 32, etc columns. For example, if you need only 128 values you'd make 8 columns for 1024 total values. When loaded for use as a 256-step wavetable, every 4th value would be used; you'd thus get two identical adjacent values instead of 8.
Note also that DaquinOscope is expecting 16-bit data, which it will convert to 8 bits by shifting right. You should thus left-shift your desired 8-bit values by 8 bits, padding with 8 zeros on the right.
You can enter values in hexadecimal format by preceding each with 'h', or in binary format by preceding with 'b'. So if you want to end up with a bit pattern of 11001010 you could enter it as b1100101000000000. In hexadecimal the same value would be CA so you'd enter hCA00.
Of course, you can use the DAC to create a single-channel analog test sequence using the same approach. Here you may find the Arb_From_List approach the easiest way to create simple test schedules, especially those that ramp linearly between values.
See the Free-Standing Arduino Oscillators topic above if you want the sequence to continue to run without DaquinOscope, or indeed without any computer attached.
Wavetable DAC Construction:
The Digital-to-Analog Converter (DAC) for DaquinOscope uses an "R-2R ladder" approach:
Note that the 9 lower (vertical) resistors are 20K each, twice the value of the 7 upper (horizontal) 10K resistors in the schematic. The exact values are not critical, but the 2:1 ratio is. You could just as well use 24K and 12K or 30K and 15K if you are using standard 5% tolerance values. (Use 1/4 watt metal or carbon film types, never carbon composition.) These 5% values will give decent results for many purposes, like a benchtop "function generator"; see the 1000 Hz spectrum image in the subtopic above. You might think that using 1% tolerance values would give better results, but tests showed no improvement in actual measurements, undoubtedly because this is only an 8-bit system.
The board layout is shown below with the 20K resistors in pink. This is a view from the top (component side) of the board, with the copper traces on the bottom shown as if in an X-ray:
Note that the pin numbers on the layout have the LSB (pin 2) at the top and the MSB (pin 9) at the bottom, while the schematic has the MSB on the left and the LSB on the right.
Pay special attention to the sole 20K resistor on the top of the right side, which goes to ground. Other than this, all the 20K resistors are on the left (digital pin) side and all the 10K resistors are on the right.
The board layout assumes you will install it like a typical Arduino "shield", parallel to the Arduino board itself. Thus the ground connection is shown on the opposite header strip from the digital output pins. The resistor leads connected to the digital pins can be cut to plug directly into the header. Together with the ground lead this will support the shield above the Arduino. You can wire the OUT connection from the DAC to a separate connector or circuit as needed.
As an alternative, you can cut off the right side of the board (at the green line in the above image) and wire the ground to the 20K resistor it connects to, via the pad provided. Bend all the resistor leads that connect to output pins, making them parallel to the board, and trim so that you can stand the board on its edge and plug it into the digital header. Use hookup wire to connect the ground to an Arduino ground on either header.
The above image is not suitable for printing at the exact scale. Instead, the schematic and printable 600 DPI layouts are inclued in the Daquino_DAC_All600.PNG file that is installed with Daqarta in the Documents - Daqarta - Circuits folder.
Be sure to read the Notes section of Daqarta Printed Circuits before you begin.
You can use the printed layouts directly to create your own circuit boards, with either the laser printer toner transfer method, or with the direct-draw method discussed under Printed Circuit Construction.
Alternatively, you can edit the Daquino_DAC.PCB file in the same folder to make custom modifications first. See the PCB Files discussion in Daqarta Printed Circuits for the required software to use this file, and for information on how to submit it to have boards made by a 3rd-party supplier.
However, you don't really need any printed circuit board for this. The staggered placement of the the resistors was used to make it easy to wire this up on a 1.1 by 1.3-inch scrap of tenth-inch grid perfboard, using the resistor leads themselves to make all connections on the board. In this case the vertical (not shield) board orientation is recommended. The resistors whose ends will plug into the digital header can be secured with hot glue after construction to make a rigid assembly.
The image below shows the top and bottom views of the perfboard version. This used 1% tolerance resistors whose color bands don't show up very well in the photo, so the top band of each resistor was enhanced in this image. Bright red indicates 20K resistors, brown (all others) are 10K. Arduino pin numbers are shown, as are ground and output connections:
Oscillator N Phase:
The Oscillator N Phase control (Ctrl1 on the Oscillators and Misc dialog page only) defaults to Oscillator 0 Phase until the Set Oscillator0 button is toggled to another oscillator number.
The phase is set in percent of a full cycle, not in degrees. This forces the indicated oscillator phase accumulator counter to start at that specified point whenever the oscillators are started. (They are all re-started whenever you change any Phase setting, as well as when they are toggled on with the Oscillators ON / OFF button.)
Please note that Oscillator Phase is only relevant between two or more oscillators set to the same frequency.
Thus, if you have two oscillators running at 1000 Hz and one has its phase set to 25% while the other is at 0, the first one will always be 90 degrees (25% of a 360-degree cycle) ahead of the other. The other two oscillators may be set to 1000 Hz but with different phases, such as 50% and 75%.
Alternatively, you can set the other two to a different frequency, and they will track each other at whatever phases you set, independently of the first two oscillators.
Note that you must set oscillator frequencies before setting phases. Changing the frequency resets the phase accumulator of that oscillator to 0; it does not match the specified Oscillator Phase until a phase adjustment or an Oscillators ON / OFF restart.
Oscillator Interrupt Rate:
The Oscillator Interrupt Rate control (Ctrl2 on the Oscillators and Misc dialog page only) defaults to 10000 Hz. This is the sample rate for all oscillators, and is also used as the sample rate for analog and digital inputs when the Interrupt Lock button (Btn5) is active.
The Interrupt Rate is based on an internal timer running at 2 MHz, divided by a value N from 40 to 256. The lowest rate is 7812.5 Hz when N is 256, and the upper rate is 50000 Hz when N is 40. You don't have to know anything about this divisor when using the control, except to be aware that the frequency you enter will be converted to the nearest valid frequency. Most of these will not be convenient values. The table below shows typical "nice" rates, and the N divisors used internally to get them:
Hz N 50000 40 40000 50 25000 80 20000 100 12500 160 10000 200 8000 250
If you enter other values, the actual frequency will be shown. DaquinOscope computes it essentially by dividing it into 2 MHz, rounding the result to the nearest integer, and dividing that into 2 MHz. So if you enter (say) 15000 Hz, then 2000000 / 15000 = 133.3333, which is rounded to 133, and 2000000 / 133 gives an actual frequency of 15037.594 Hz.
There is normally no reason to avoid these other values, since DaquinOscope will use the actual sample rate to set the Oscillator frequency. Likewise, when Interrupt Lock is active to set the input sample rate, the display X axis will be automatically adjusted to reflect the true time base.
Normally, you should always set the sample rate before you set frequency and/or phase. However, once they are set for a given sample rate, changing the rate will change all output frequencies by exactly the ratio of the change, while keeping the same phase relationship. For example, if you set everything initially at a 10 kHz rate, changing it to 20 kHz will exactly double all the frequencies. Note, though, that the Oscillator N Frequency display will not change when you change the rate.
As noted earlier, the sample rates can only change to specific values; you can't (for example) set 30 kHz to triple the 10 kHz frequencies. But you can get a triple if you pick the right starting rate. Consider that the sample rate is 2 MHz divided by a value N. If you want to triple the rate, then the initial N should be 3 times the final N. For example, if the final sample rate is to be 40 kHz the N would be 50 as shown in the above table. So you need to set an initial rate with a value of 3 * 50 = 150. The rate to set would thus be 2 MHz / 150 = 13333.333 Hz.
Oscillator N Frequency:
The Oscillator N Frequency control (Ctrl3 on the Oscillators and Misc dialog page only) defaults to Oscillator 0 Frequency until the Set Oscillator0 button is toggled to another oscillator number.
The frequency is set in Hz. As noted in the Oscillator Overview section, the oscillators use a phase accumulator technique to achieve high resolution. The resolution is the reciprocal of the accumulator counter size C, which is 2^25 for square oscillators, or 2^32 for the wavetable oscillators.
When you enter a value, the closest achievable value is actually used and displayed. If the entered value is Z Hz and the Interrupt Rate is S, then the phase step size US is
US=C * Z / S
The actual frequency F is then
F=US * S / C
This is displayed with 5 decimal places. (The macro code can be easily changed to show anywhere from 0 to 9 places.)
The values you enter are limited to 25000 Hz, regardless of the Interrupt Rate. However, the displayed "actual" rate does not consider aliasing, which takes place for frequencies above half the Interrupt Rate. So, for example, if the Interrupt Rate is 10000 Hz and you enter 6000 Hz, you'll see 5999.99994 Hz but the actual output will be "folded" about 5000 Hz (the Nyquist frequency) and you'll actually get 4000.00006 Hz.
Set Oscillator N:
The Set Oscillator N button (Btn0 on the Oscillators and Misc dialog page only) defaults to Set Oscillator 0. Each click of the button advances from 0 to 3 and then wraps back to 0.
This changes the current Oscillator N Phase and Oscillator 0 Freq controls, as well as the OscN Pin button, to show and allow adjustment of properties of the selected oscillator.
The OscN Pin button (Btn2 on the Oscillators and Misc dialog page only) defaults to Osc0 = Pin 0 (OFF). It shows the digital output pin assigned to oscillator N, which may be 0-3 as selected by the Set Oscillator N button just above it.
If you click on this button, it pops up a window showing "Pin Number: " that allows you to enter a number from the keyboard. Hit the Enter key to conclude, and the window will vanish and the new number will appear on the button.
Each oscillator must have a different pin number.
Valid "normal" square wave output pins are 2-12. Pins 0 and 1 are reserved for serial port access. They are never used for oscillator outputs, but can be used to turn off the selected oscillator. They are shown with (OFF) after them, as in the Pin 0 default noted above.
Pin 13 can be used for square wave output, but is also connected to an on-board LED and the button label shows Pin 13 (LED).
If you are not using a wavetable oscillator (see below), please note that using only pins in the 10-13 range enables a more efficient square wave scheme that allows higher interrupt rates, which allows higher sample rates. See the Interrupt Lock - Rate Limits subtopic below.
Pin 14 doesn't select a real output pin, but instead specifies the 256-value wavetable oscillator. The button shows Pin 14 (Wave256) to indicate this. This option is available only for Osc0.
Likewise, pin 15 selects the 1024-value wavetable oscillator and is shown as Pin 15 (Wave1k), and is likewise only available only for Osc0.
Note that the 256- or 1024-value wavetable oscillator uses a simple 8-bit R-2R ladder DAC driven by pins 2-9. You can thus select either pin 14 (Wave256) or pin 15 (Wave1k) for Osc0, and in either case you can not select any pins 2-9 as square oscillators for Osc1-3. However, you can still use pins 10-13 for these.
When you set Osc0 to use either wavetable oscillator, you will be prompted to select an Arb Wave file to provide the wavetable. Daqarta includes a large assortment of files to choose from, created with the Arb_From_Equation macro mini-app and having names starting with Arb_, such as Arb_Sine.DAT, Arb_Triangle.DAT, etc. If you want something else, you can create it with Arb_From_Equation or with the Arb_From_List mini-app.
Please note that the wavetable oscillators must share the same limited Arduino memory that is also used for data acquisition. 10-bit Analog acquisition uses 1280 bytes of memory, while Digital or 8-bit Analog uses 1024 bytes. So if you select Wave1k then there will be no data acquisition, and you will see "No display with 1024-sample Wave".
If you select Wave256, you will see "Forcing 8-bit ADC mode for 256-sample Wave". Since 8-bit ADC mode (or Digital mode) uses only 1024 bytes of memory for acquisition, the remaining 256 bytes are free to hold the Wave256 waveform for simultaneous operation.
Oscillators On/Off Button:
The Oscillators On/Off button (Btn3 on the Oscillators and Misc dialog page only) defaults to Oscillators OFF.
Clicking it to Oscillators ON will activate any oscillators that have previously had their OscN Pin and Oscillator N Freq set. If none have been set, the button will remain at Oscillators OFF and a message will pop up saying "Set Pin and Freq for at least one Osc".
The ADC Clock button (Btn4, on the Oscillators and Misc dialog page only) defaults to ADC Clock = 2 MHz.
Clicking this button opens a Wait Buttons Button Select dialog that allows selection of other ADC clock speeds. The fastest is 8 MHz, which is disabled by default since it causes problems on some Arduino devices.
The 2 MHz clock is probably best for general-purpose use. Slower clocks may be needed for 10-bit ADC operation in high-precision applications. Faster clocks can be used where speed is more important than accuracy.
The table below shows typical sample rates for a single ADC channel at each clock speed, for 8-bit and 10-bit operation:
----- Sample Rates ----- ADC speed 8-bit 10-bit 4 MHz 156 kHz 127 kHz 2 MHz 104 kHz 89.4 kHz 1 MHz 58.6 kHz 55.2 kHz 500 kHz 33.2 kHz 31.2 kHz 250 kHz 17.8 kHz 16.6 kHz 125 kHz 8927 Hz 8927 Hz
If you want to try the 8 MHz clock you can comment out the following line in the Btn4 handler (IF.Ctrls=8) in the Dscope_Ctrls subroutine. Just add a semicolon in front of it:
WaitBtns#0x=0 ;Disable 8 MHz Btn 0
However, even if this works on your device, the accuracy will be quite poor. You might consider going to the ultimate in the speed vs resolution tradeoff, and simply switch from Analog to Digital inputs; you'll get up to 8 channels with a sample rate over 400 kHz.
The Interrupt Lock button (Btn5, on the Oscillators and Misc dialog page only) is normally off. When toggled on, it forces input acquisition to be locked to the Oscillator Interrupt Rate, instead of using the Sample Delay control on the main dialog page.
You will most likely want to use Interrupt Lock whenever you are using oscillators, since the oscillator interrupts will otherwise cause jitter in the sample delay. However, using interrupts will greatly reduce the maximum input sample rate. See the Interrupt Lock - Rate Limits topic below, and Freeze-Up Recovery after that.
Please note that with Interrupt Lock active you can't use negative Trigger Delay.
Interrupt Lock - Rate Limits:
In Interrupt Lock mode with Analog or Digital inputs active (the normal case unless you are using the Wave1k wavetable oscillator), there are limits to how many oscillators and input channels you can have active at any given Interrupt Rate. If you try to do too much, too fast, the DaquinOscope will freeze up and you will need to use the Freeze-Up Recovery method in the next subtopic.
The following are tables of approximate rate limits for various configurations. No Osc is when only the inputs are active. 1 Osc to 4 Osc refers to the number of square-wave oscillators active along with the inputs. Wave256 is when Osc0 is set to "pin 14" to get a 256-sample wavetable oscillator for use with an R-2R DAC on pins 2-9, with inputs but no square wave oscillators active. (You can use up to 3 square wave oscillators along with Wave256. The limits aren't shown here, but should be similar to the 2 Osc to 4 Osc cases.)
Note that with Digital inputs active, the number of channels doesn't matter since all 8 are always acquired, and the Channels control just determines whether 1, 2, 4, or 8 are shown.
There are two tables; the first is for general use including the use of inputs only (no oscillators), or inputs plus the 256-sample wavetable, or square wave oscillators that use arbitrary pins 2-13.
Interrupt Rate limits in kHz:
Arbitrary Osc pins 2-13: Channels No Osc 1 Osc 2 Osc 3 Osc 4 Osc Wave256 1 Analog 50 38 29 23 21 40 2 Analog 30 25 20 17 15 25 4 Analog 18 16 14 12 11 16 1-8 Digital 50 38 29 18 16 48
The second table is for inputs plus oscillators on pins 10-13 only, using a more efficient square wave scheme:
Fast Osc pins 10-13 only: Channels 1 Osc 2 Osc 3 Osc 4 Osc 1 Analog 50 43 35 32 2 Analog 32 25 23 21 4 Analog 18 15 14 13 1-8 Digital 50 43 40 35
When Interrupt Lock is active and the Interrupt Rate is too high for the number of oscillators and input channels, DaquinOscope will freeze up. To recover, first unplug the Arduino USB connector. DaquinOscope will un-freeze, at which point you should close it normally. When prompted to save a DscopeSetup file, hit Escape or Cancel to simply exit.
Now plug the USB connector back in and re-start DaquinOscope as desired.
8/10 ADC Bits:
The 8/10 ADC Bits button (Btn6, on the Oscillators and Misc dialog page only) defaults to 8 ADC Bits.
The default 8-bit mode will resolve only 256 levels over the full-scale range, whereas 10-bit mode will resolve 1024.
The maximum sample rate (Sample Delay = 0) will be higher in 8-bit mode than in 10-bit. Typical values:
1 ch 2 ch 4 ch 8-bit 104618 47302 24270 10-bit 89448 43302 22679
Note, however, that 10-bit mode does not support negative Trigger Delay. If you set negative delay while in 8-bit mode, the ADC Bits button will be forced to 8 bits and disabled.
In addition, 10-bit mode does not allow use of either wavetable oscillator, since it uses both the 1024 bytes of Arduino memory needed for the Wave1k oscillator, and the 256 bytes needed for the Wave256 oscillator.
8-bit mode uses only 1024 bytes of memory, so the Wave256 oscillator is allowed. The ADC Bits button will be forced to 8 bits and disabled when Wave256 has been selected.
Saving DaquinOscope Setups:
When you hit the OK button to exit DaquinOscope you will see a Windows file Save As dialog prompting you to save the current setup as DscopeSetup. That's the name of the default setup that you will be prompted to use when DaquinOscope next starts up. You can save under a different name, such as one that describes the intended use.
Then on start-up you can select that name from the list of files presented, or accept the DscopeSetup default, or hit Cancel or the Escape key to use the built-in defaults.
Note that not all control settings will be restored from the file. In particular, the Trigger state will be forced off. This is a protection against the common case where there is no trigger signal at start-up because some external source is not active yet, or the signal level is below the Trigger Level. If Trigger was selected, there would be no visible screen activity; the Arduino would be spending all its time waiting for an event that never comes, and the DaquinOscope controls would be unresponsive unless Auto Trigger was selected. Even then, at the default Auto-Trigger Delay of 1 second, control response would be very sluggish. By always starting with Trigger off, you can make sure you have the proper signal and/or trigger levels before toggling it on.
Also, at start-up the Oscillators OFF state is forced to prevent accidents, such as where the equipment to be driven by the oscillator signals is not ready to receive them. Or, worse yet, it is ready, and your 10 ton stamping press starts up before you are ready!
However, all other oscillator control settings are restored, including pin numbers, frequencies, and phases, and if a wavetable oscillator was in use its waveform file will be loaded and ready when Oscillators ON is toggled.
Variable, Control, and Array Usage:
The following summary of variable, control, and array usage is intended to aid in understanding the macro script operation. It can also help in modifying the script, including avoiding accidental re-use of critical variables.
Variables: C Oscillator phase cycle counter size (2^25 or 2^32) D Full-Scale Digital range, Volts E Square Osc jitter error G Square Osc jitter (Glitch) period H Trigger Holdoff, secs J Square Osc Jitter freq K Full-scale Analog range, Volts N Square Osc samples per phase P Osc Phase Start, percent R Sample rate display update limit S Interrupt rate for Osc or Int Lock T Timer var for Holdoff X Work var Z Osc freq (Ctrl3 working value) Q0 Osc number to be adjusted Q1 Work var (_Acq_Mode, Ctrl2, Btn1 pin) QA 0 = Analog, 1 = Digital Inputs QC Display chans (1,2,4, or 8 for Digital) QD Trigger Delay, (-1023 to +32767) QH Trigger Hyst (0-255) QI _Write general loop index QL Trigger Level (0-1023) QM Trigger mode command QN _Write digital upload trace index QP Osc Phase Start, internal value QR Displayed sample rate QS Trigger Slope (0 = Rising, 1 = Falling) QT Trigger state QW Auto-trigger wait (neg=integer sec, else sec/64u) QX _Write digital bit index, also effective chans for sample rate Qa Task state Qb 0 = 8-bit, 1 = 10-bit Qc Trigger pin (A0 default) Qd 0 = Analog trig (1 = Digital) Qi Interrupt Lock Qm Digital Mode 0-3 Qn 0 = Auto, 1 = Normal Trigger Qo Oscillator state (0=off, 1=on) Qr 0=5V FS range, 2=1.1V Qv Digital trace view map Qw Auto-trigger Wait control variable (10m-32767 sec) UA ADC clock 1-7 UC Ctrl1 trigger pin selection number UD Sample Delay UF Auto-Increment File names (0, 1, 2) UI Misc loop counter UM ADC channel map or digital input options UN Work var (Btn4) UR _Write work var and sample rate US Osc step working variable UT Elapsed acquisition time, usec UV Save Ch during _Task UX Work var (Btn4) UZ File name continuation (0,1,2) Ub Master ADC pins bitmap Uc Bitmap of display chans Ud Scale factor for Digital In display Um Work var (Btn4) Ut Interrupt timer load value (1-255). Ut=2e6/S - 1 Custom Controls: Ctrl0 Sample Delay Ctrl1 Trigger Pin, Trigger Delay, Oscillator Phase Ctrl2 Trigger Level, Auto-Trigger Delay, Osc. Interrupt Rate Ctrl3 Trigger Hysteresis, Trigger Holdoff, Oscillator Frequency Btn0 Analog/Digital Inputs, Set Oscillator N Btn1 Trigger toggle Btn2 N Channels, Oscillator Pin N Btn3 Rising/Falling Trigger, Oscillators ON/OFF Btn4 Analog/Digital Pins, ADC Clock Btn5 Auto/Normal Trigger, Interrupt Lock Btn6 Save Data File, Digital Mode N, 8/10 ADC Bits Btn7 Dialog page change: Main Controls, Trigger Timing, Osc and Misc Arrays: Buf0-Buf7 Setup load/save, Chan 0-7 display data buffers Str1 Data file name and path Str6 _Get_String text prompt and entry Str7 Misc labels Str7 Digital view bitmaps Str7 Oscillator settings Str7 Wave oscillator file name
DaquinOscope Macro Listing:
;<Help=H4922 Posn#0="Ardu" Posn#1=0 @_ComDev_Scan Str1="Dscope" ;Default data file D=5.00 ;Full-Scale Digital range Qr=0 ;0 = 5V analog range, 2 = 1.1V Qr=Qr&2 ;Allow only 0 or 2 IF.Qr=0 K=5.00 ;5V Full-scale Analog range ELSE. K=1.10 ;1.1V range ENDIF. H=0 ;No trigger Holdoff T=0 ;Null holdoff timer R=0.01 ;1% sample rate display change limit QR=0 ;Current displayed sample rate Qi=0 ;1 = Interrupt Lock Qm=0 ;Digital Mode (0 = pins 0-7) Q0=0 ;Set Osc 0 default S=10k ;Default int rate for Osc Ut=199 ;Timer load for 10 kHz int rate UD=0 ;Sample Delay QL=512 ;Default Trig Level QH=5 ;Default Trig Hyst QA=0 ;Default to Analog input display QC=1 ;Default single-chan display UF=2 ;Auto-increment file name if main AutoInc on UZ=0 ;Do not continue prior name series Posn#0=UF ;0=no AutoInc, 1=AutoInc, 2=main AutoInc state Posn#1=UZ ;0=no continue, 1=continue prior, 2=prior DaquinOscope GetFilePath=2 ;Prior DATA file path Str1=FileName?P +z ;Prior path and name without extension IF.((UZ&1) && Str1)=0 ;If no name or no continue flag: Str1="Dscope" ;Use default Data file AutoInc#Bu=-1 ;Reset name series ENDIF. Ud=1000 ;Scale factor for Digital In (1024 = FS) UA=3 ;Default ADC clock 3 = 2 MHz QT=0 ;Default Trig off Qn=0 ;Auto-Trig default Qw=1 ;Auto-Trig wait = 1 sec QW=-1 ;Default 1 sec Auto-Trigger wait QD=0 ;Default = no trigger delay Qd=0 ;Default Analog trig (1=Digital) Qc=0 ;Default A0 trigger pin QS=0 ;Default Trig Slope = Rising Qb=0 ;0=8-bit, 1=10-bit ADC Ub=b1111 ;Master ADC bitmap default UI=2 WHILE.UI=<14 ;Set pins 2 - 13 as INPUTs Port#D2=h40D0 + UI UI=UI+1 WEND. Port=$(hF0) + "b" + $(h80) ;Clear acquisition flags Msg= Close= Spect=0 Sgram=0 Trig=0 TrigDelay=0 ZeroScrnInd=1 ;Individual screen zero posns Zero=1 ;Main Zero on Mtr1= ;Remove Mtr1 Mtr0="<F(50)" ;Set default Mtr sizes Mtr1="<F(50)" Btn7=0 Str7= Str7="Trigger Level" Str7="Auto-Trigger Wait, sec" Str7="Osc. Interrupt Rate, Hz" Str7="Trigger Hysteresis" Str7="Trigger Holdoff, sec" Str7="Oscillator " Str7=" Freq, Hz" Str7="Analog Inputs" Str7="Digital Inputs" Str7="OFF" Str7="ON" Str7="Rising Trigger" Str7="Falling Trigger" Str7="Analog Pins" Str7="Digital " Str7="ADC Clock" Str7="Auto Trigger" Str7="Normal Trigger" Str7="Pins 0-7" Str7="Pins 2-9" Str7="Pins 6-13" Str7="Pins 8-15" Str7="Digital Mode" Str7="8 ADC Bits" Str7="10 ADC Bits" Str7="Analog Pin " Str7="Digital Pin " Str7="Wave Osc 0" Str7#d=h08060200 ;4-byte array = 0, 2, 6, 8 (UNUSED) Str7="Clock1 = 8 MHz" Str7="Clock2 = 4 MHz" Str7="Clock3 = 2 MHz" Str7="Clock4 = 1 MHz" Str7="Clock5 = 500 kHz" Str7="Clock6 = 250 kHz" Str7="Clock7 = 125 kHz" ;Digital View defaults: Str7#b=b00111100 ;Mode 0 = view pins 2,3,4,5 Str7#b=b00001111 ;Mode 1 = view pins 2,3,4,5 Str7#b=b00111100 ;Mode 2 = view pins 8,9,10,11 Str7#b=b00001111 ;Mode 3 = view pins 8,9,10,11 ;Str7 to Str7 = Osc0-3 frequencies (8 bytes each) Z ;Str7 to Str7 = Osc0-3 step sizes (4 bytes each) US ;Str7 to Str7 = Osc0-3 phases (8 bytes each) P ;Str7 to Str7 = Osc0-3 accum start (4 bytes each) QP ;Str7 to Str7 are pins for Osc0 to Osc3 (Q1) Str7#b=0 ;Osc0 output pin Str7#b=0 ;Osc1 output pin Str7#b=0 ;Osc2 output pin Str7#b=0 ;Osc3 output pin Str7="0011111111111234" ;Pin num index (0-15) to  Str7=" (OFF)" ;Pin = 0, 1 Str7="" ;Pins 2-12 Str7=" (LED)" ;Pin 13 Str7=" (Wave256)" ;Pin 14 Str7=" (Wave1k)" ;Pin 15 ;Str7 is flag byte, non-null if Wave Osc file uploaded ;Str7 to  is Wave Osc file name loaded to Arb7 Buf7="<Load:DscopeSetup" IF.Posn?f=1 ;Load OK? Str7#A=Buf7(aE) ;Restore strings from Buf7- Buf7#Br=3 ;Restore vars from Buf7- UF=Posn?0 ;Replace saved UF, UZ UZ=Posn?1 IF.UZ=2 ;Use prior-session name, if any? Str1#A=Buf7(aC) ;Restore string from Buf7- ENDIF. Q1=Str7?b ;Osc 0 Pin number IF.Q1=>13 ;Wave Osc? IF.Str7?b="U" A.ArbX7= ;Remove current Arb7 wave A.Arb7=Str7 ;Open file for Arb7 US=2^32 * Z / S IF.Q1=14 ;256-sample Wave? Port#a7=$(hF0) + "o" ;Upload 256-byte data to Arduino ELSE. ;Else 1024-sample Wave T=2^31 ;Block display updates Mtr1="No display with 1024-sample Wave" Port#A7=$(hF0) + "O" ;Upload 1 Kbyte data to Arduino ENDIF. ENDIF. ENDIF. ENDIF. IF.QD=<0 ;Set trigger delay display TrigDelay#N=QD ELSE. TrigDelay#N=QD * QR / 1e6 ENDIF. Port=$(hF0) + "D" + $w(QD) ;Set trigger delay QT=0 ;Trigger OFF Qo=0 ;Oscillators OFF Port=$(hF0) + "F" + $(hC0) ;Set Oscs off Port=$(hF0) + "I" + $(Ut) ;Set default int rate Port=$(hF0) + "A" + $(UA) ;Set ADC clock Port=$(hF0) + "b" + $(Qb+Qr) ;Set 8-bit or 10-bit mode Ctrls="<<DaquinOscope - Main Controls" Ctrl0="<S(0,10000)" ;Sample Delay range 0-10000 usec Ctrl0="<p(0)" ;No decimal places Ctrl0="<<Sample Delay, usec" ;Control label Ctrl0=UD ;Initial setting Ctrls=0 ;Control number for @_Dscope_Ctrls IF.Qi=1 ;Interrupt Lock on? Ctrl0="<D" ;Disable Sample Delay if so QR=0 ;Force Sample Rate display update ENDIF. @_Dscope_Ctrls ;Run IF.Ctrls=0 code to set delay Ctrl1="<<Trigger Pin" ;Control label Ctrl1="<r(0,18)" ;Read-only slider range Ctrls=1 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Set trigger pin Ctrl2="<S(0,1023)" ;Trigger Level range 0-1023 samples Ctrl2="<p(0)" ;No decimal places Ctrl2="<<" + Str7 ;Control label = "Trigger Level" Ctrl2=QL ;Initial setting Ctrls=2 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Set trigger level Ctrl3="<S(0,255)" ;Trigger Hysteresis range 0-255 Ctrl3="<p(0)" ;No decimal places Ctrl3="<<" + Str7 ;Label = "Trigger Hysteresis" Ctrl3=QH ;Initial setting Ctrls=3 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Set trigger hysteresis Btn0="<T" ;Analog/Digital Inputs button Btn0=QA ;Initial state Ctrls=4 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Set Analog/Digital mode and label Btn1="<T" ;Trigger toggle Btn1=QT ;Initial state Btn1="Trigger" ;Button label Ctrls=5 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Set trigger state Btn2="<M(QA + 2)" ;Chan modes 0-2 for Analog, 0-3 Digital Btn2=log2(QC) ;Channel count 1,2,4 or 1,2,4,8 Ctrls=6 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Set channel count and button label Btn3="<T" ;Rising/Falling Trigger (slope) button Btn3=QS ;Initial state Ctrls=7 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Set button label and trigger slope Btn4="<M" ;Momentary pushbutton IF.QA=0 Btn4="" + Str7 ;"Analog Pins" ELSE. Btn4="" + Str7 + Str7[940 + 10 * Qm] ;"Digital Pins 0-7", etc ENDIF. Btn5="<T" ;Auto/Normal Trigger toggle Btn5=Qn ;Initial state Ctrls=9 ;Control number for @_Dscope_Ctrls @_Dscope_Ctrls ;Also sets Auto-Trigger Wait Btn6="<M" ;Momentary button Btn6="Save Data File" Btn7="<M(2)" ;3-state pushbutton Btn7=0 Btn7="More Controls >>>" Qv=Str7?b[1400 + Qm] ;Set View for Digital Mode @_Dscope_Acq_Mode ;Sets UM ADC bitmap from Ub Qa=0 ;Initial task state Task="_Dscope_Task" UI=0 ;Clear channel data Buf0-3 WHILE.UI=<4 Ch=UI ;Set BufN number BufV="<=(0)" ;Fill BufN with nulls UI=UI+1 ;Next BufN WEND. Buf0#Ch=0 ;Display buttons show Ch0, etc Buf0#Vx=1 ;Allow Vert units w/o User Units tog Mtr0="<<Sample Rate" ;Mtr0 title @_Dscope_Ctrls=Ctrls ;Open Custom Ctrls dialog Task="-_Dscope_Task" ;Uninstall task when Ctrls closed UI=0 ;Disable all BufN channel displays WHILE.UI=<8 Ch=UI ;Set BufN number BufV="<d-" ;Disable BufN display UI=UI+1 ;Next BufN WEND. Mtr0= ;Close Sample Rate Mtr0 Mtr1= ;Close info display if active Port=$(hF0) + "F" + $(hC0) ;Set Oscs (and ints) off Buf0#d=0 ;No upload auto-display Buf0#Vx=0 ;Restore normal Vert axis Buf0#VU=0 ;Normal vertical units Buf0#Ch=-1 ;Restore normal Display buttons TrigDelay=0 ;No Trigger Delay Spect=0 ;Force off to enable Zero Sgram=0 Zero=0 ;Toggle Zero off Port#O=0 ;Close COM port Buf7#aE=Str7[0,2047] ;Save string data to Buf7- Buf7#Bs=3 ;Save variables to Buf7- Buf7#aC=Str1[0,511] ;Save filename string to Buf7- Buf7="<Save:DscopeSetup" ;Save DaquinOscope setup
_Dscope_Acq_Mode Macro Subroutine Listing:
;<Help=H4922 ;On entry, Ub holds master ADC bitmap ;QC holds current chans (1, 2, 4, 8) ;Returns with new UM = ADC or Digital mode bitmap TrigDelay=0 ;Reset for Xpand change, adj later IF.Qi=1 ;Ints on? IF.QD=<0 ;Neg Trig Delay? QD=0 ;Force 0 if so Port=$(hF0) + "D" + $w(QD) ;Set new Trig Delay ENDIF. ENDIF. IF.Spect=1 ;Spectrum on? Spect=0 ;Force waveform display ENDIF. IF.Sgram=1 ;Spectrogram on? Sgram=0 ;Force waveform display ENDIF. IF.QC=1 ;1-channel display? Xpand=0 ;No X expand if so Uc=b0001 ;Display single chan on L.IN LI.ZeroScrnAdj=100 ;Show w. 0 at bottom TraceMag=1 ;2x vert. magnification ENDIF. IF.QC=2 ;2-channel display, 512 samples each? IF.QA=0 ;Analog display? Xpand=1 ;X expand ON XpandMax#N=511 ;Samples 0-511 fill screen width XpandMin#N=0 IF.QD=<-511 ;Trig Delay too neg? QD=-511 ;Limit Trig Delay Port=$(hF0) + "D" + $w(QD) ;Set new Trig Delay IF.Btn7=1 ;Trig Delay ctrl visible? Ctrl1=QD ;Show new Trig Delay ENDIF. ENDIF. ENDIF. Uc=b0011 ;Display 2 chans, LI and RI LI.ZeroScrnAdj=0 ;LI (Ch0) at screen top RI.ZeroScrnAdj=100 ;RI (Ch1) at screen bottom TraceMag=0 ;1x vert. magnification ENDIF. IF.QC=4 ;4-chan display, 256 samples each? IF.QA=0 ;Analog display? Xpand=1 ;X expand ON XpandMax#N=255 ;Samples 0-255 fill screen width XpandMin#N=0 IF.QD=<-255 ;Trig Delay too neg? QD=-255 ;Limit Trig Delay Port=$(hF0) + "D" + $w(QD) ;Set new Trig Delay IF.Btn7=1 ;Trig Delay ctrl visible? Ctrl1=QD ;Show new Trig Delay ENDIF. ENDIF. ENDIF. Uc=b1111 ;Display 4 chans LI.ZeroScrnAdj=-50 ;Ch0 at screen top RI.ZeroScrnAdj=0 LO.ZeroScrnAdj=50 RO.ZeroScrnAdj=100 ;Ch3 at screen bottom TraceMag=-1 ;0.5x vert. magnification ENDIF. IF.QC=8 ;8-chan only available for Digital Uc=b1111 ;Display 4 chans via upload, 4 direct TraceMag=-2 ;0.25 x vert. magnification UI=0 ;Channel counter UX=1 ;Upload channel bit posn UN=0 ;Upload channel count WHILE.UI=<8 Ch=UI ;BufN chan IF.((UX & Qv) && !(UN & 4)) ;Bit set, and UN<4? BufV="<d-" ;Upload, disable direct Ch=UN ;Set upload chan Ch.ZeroScrnAdj=25 * UI - 75 ;Vertical zero posn UN=UN+1 ;Count upload chan ELSE. ;Else direct display BufV="<dWU2" ;Show unipolar waveform, dotted BufV#Z=(7 - UI) * 256 / 8 ;Vertical zero posn ENDIF. UX=UX << 1 ;Next upload chan bit posn UI=UI+1 ;Next chan 0-7 WEND. ELSE. ;Else 1, 2, 4 chans via upload UI=0 ;Chan counter 0-7 WHILE.UI=<8 ;Disable direct chan displays for all Ch=UI ;Set BufN for chan BufV="<d-" ;Disable direct display UI=UI+1 ;Next chan WEND. ENDIF. Buf0#d=Uc ;Arduino chan priority ;Buf0#d=Uc & (~Posn?A) ;Optional main chan priority IF.QA=0 ;Analog acq mode? Q1=1 ;Moving bit Um=0 ;Resulting bitmap UN=QC ;Num ADC chans (1, 2, 4) UI=0 WHILE.UI=<6 UX=Ub & Q1 ;Isolate target bit IF.UX=>0 ;Was it set? Um=Um | UX ;Set in result if so UN=UN-1 ;Count the bit IF.UN=0 ;Done with all QC bits? LoopBreak=2 ;Exit WHILE loop ENDIF. ENDIF. Q1=Q1 << 1 ;Next higher bit to test UI=UI+1 ;Next ADC pin WEND. UM=Um + (Qi << 6) ;New ADC bitmap ELSE. ;Else Digital mode UM=h80 + Qm + (Qi << 6) ;Else new digital mode command ENDIF. IF.QD=<0 ;Negative trigger delay? TrigDelay#N=QD ;Restore if so ELSE. TrigDelay#N=QD * QR / 1e6 ;Else restore pos delay, if any ENDIF.
_Dscope_Ctrls Macro Subroutine Listing:
;<Help=H4922 IF.Ctrls=0 ;Ctrl0 = Sample Delay UD=Ctrl0 ;Get control value Port=$(hF0) + "s" + $w(UD) ;Set new sample delay ENDIF. IF.Ctrls=1 ;Ctrl1 IF.Btn7=0 ;Main dialog, Trigger Pin? Btn5=0 ;Force Auto-Trig UC=UC + Ctrl1?u ;Get new control up/down value IF.UC=>18 ;Out of range? UC=18 ;Limit range if so ENDIF. IF.UC=<0 ;Under range? UC=0 ;Limit to 0 if so ENDIF. Ctrl1#s=UC ;Update slider with new value IF.UC=<6 ;Analog pins 0-5? Ctrl1="< " + Str7 + UC ;"Analog Pin nn" Qd=0 ;0 = Analog trigger Qc=UC ;Trigger pin ELSE. ;Else Digital control range 6-18 UI=UC - 6 + 2 ;6 => Digital pin 2 IF.UC=18 ;Max control value? Ctrl1="< " + Str7 ;"Wave Osc 0" ELSE. Ctrl1="< " + Str7 + UI ;"Digital Pin nn" ENDIF. Qd=1 ;1 = Digital trigger Qc=UI ;Trigger pin ENDIF. QM=QT<<7 + Qd<<6 + QS<<5 + Qc ;Trig mode cmd value Port=$(hF0) + "T" + $(QM) + $w(QL) ;Set Trigger mode ENDIF. IF.Btn7=1 ;Trigger Timing, Trigger Delay? QD=Ctrl1 ;Get new control value IF.QD=<0 ;Negative? Ctrl1="<<NEG Trigger Delay, samples" ;Neg is in samples ELSE. ;Else pos is in usec Ctrl1="<<Trigger Delay, usec" ENDIF. Port=$(hF0) + "D" + $w(QD) ;Set Trigger Delay IF.QD=<0 ;Was it negative (samples)? TrigDelay#N=QD ;Set Daqarta to match ELSE. ;Else pos (usec) TrigDelay#N=QD * QR / 1e6 ;Convert to samples ENDIF. ENDIF. IF.Btn7=2 ;Osc dialog, Osc Phase? P=Ctrl1 ;Get 0-100% value Str7[1560 + 8 * Q0]#q=P ;Save qword in array IF.Str7?b[1620 + Q0]=>13 ;Wave Osc ("pin" 14 or 15)? QP=P/100 * 2^32 ;Wave accum start value ELSE. ;Else square wave osc QP=P/100 * 2^25 ;Square accum start value ENDIF. Str7[1600 + 4 * Q0]#d=QP ;Save dword in array IF.Qo=1 ;Oscs ON now? Port=$(hF0) + "F" + $(hC0) ;Set oscs OFF temp UI=0 ;Osc number counter WHILE.UI=<4 ;Set all oscs Q1=Str7?b[1620 + UI] ;Pin number US=Str7?d[1540 + 4 * UI] ;Freq step QP=Str7?d[1600 + 4 * UI] ;Phase accum value Port=$(hF0) + "F" + $(h80 + UI<<4 + Q1) + $d(US) + $d(QP) UI=UI+1 WEND. Port=$(hF0) + "F" + $(hC1) ;Set oscs back ON ENDIF. ENDIF. ENDIF. IF.Ctrls=h81 ;Ctrl1 slider IF.Btn7=0 ;Main dialog = Trig Pin Btn5=0 ;Force Auto-Trig UC=Ctrl1?s ;Get slider posn 0-18 IF.UC=<6 ;0-5 = Analog pins Ctrl1="< " + Str7 + UC ;"Analog Pin nn" Qd=0 ;Analog trig mode Qc=UC ;Trig pin ELSE. ;Else Digital pins UI=UC - 6 + 2 ;Convert 6-18 to 2-14 IF.UC=18 ;Max control value 18? Ctrl1="< " + Str7 ;"Wave Osc 0" ELSE. ;Else normal Digital pin Ctrl1="< " + Str7 + UI ;"Digital Pin nn" ENDIF. Qd=1 ;Digital trig mode Qc=UI ;Trig pin ENDIF. QM=QT<<7 + Qd<<6 + QS<<5 + Qc ;Trig mode cmd Port=$(hF0) + "T" + $(QM) + $w(QL) ;Send to USB serial port ENDIF. ENDIF. IF.Ctrls=2 ;Ctrl2 IF.Btn7=0 ;Main dialog - Trigger Level? QL=Ctrl2 ;Get control value IF.QT=1 ;Trigger active? QM=QT<<7 + Qd<<6 + QS<<5 + Qc ;Trig mode cmd Port=$(hF0) + "T" + $(QM) + $w(QL) ;Send to port ENDIF. ENDIF. IF.Btn7=1 ;Trig Timing - Auto-Trig Wait? Qw=Ctrl2 ;Get control value IF.Qw=>2 ;More than 2 secs requested? QW=-Qw ;Set neg = integer secs ELSE. ;Else set in 64 usec steps QW=Qw / 64u ENDIF. Port=$(hF0) + "W" + $w(QW) ;Set Auto-Trigger Wait ENDIF. IF.Btn7=2 ;Osc/Misc - Interrupt Rate? Q1=Ctrl2?u ;Scroll button step IF.Q1=0 ;Direct edit (no scroll)? S=Ctrl2 ;Get requested rate, Hz Ut=cint(2M / S - 1) ;Int timer load value ELSE. ;Else slider Ut=Ut-Q1 ;Slide load value +/-1 IF.Ut=>255 ;Too large (freq too low)? Ut=255 ;Limit = 2M/256 = 7812.5 Hz ENDIF. IF.Ut=<39 ;Too small (freq too high)? Ut=39 ;Limit = 50 kHz ENDIF. ENDIF. S=2M/(Ut + 1) ;Sample rate from load value Ctrl2=S ;Set control to show it Port=$(hF0) + "I" + $(Ut) ;Set interrupt timer ENDIF. ENDIF. IF.Ctrls=3 ;Ctrl3 IF.Btn7=0 ;Main dialog - Trigger Hyst? QH=Ctrl3 ;Get Hyst value 0-255 Port=$(hF0) + "h" + $(QH) ;Set Hyst (single byte) ENDIF. IF.Btn7=1 ;Trigger Timing - Holdoff? H=Ctrl3 ;Get Holdoff value T=0 ;Reset Holdoff timer ENDIF. IF.Btn7=2 ;Osc/Misc - Osc Freq? Z=Ctrl3 ;Get new freq Str7[1500 + 8 * Q0]#q=Z ;Save in array IF.Str7?b[1620 + Q0]=>13 ;Wave osc (Wave256 or Wave1k)? C=2^32 ;Wave osc accum size US=C * Z / S ;Wave osc phase step ELSE. ;Else square osc C=2^25 ;Square osc accum size US=C * Z / S ;Square Osc phase step N=C / (2 * US) ;Steps per square phase E=abs(N - cint(N)) ;Error fraction per phase E=E / cint(N) ;Error fraction per sample J=E * S / 2 ;Jitter frequency G=1/J ;Jitter (Glitch) period Msg=J(0.6) + " Jitter Hz" _ +n +G + " Period sec" ENDIF. Ctrl3=US * S / C ;Actual freq to control Str7[1540 + 4 * Q0]#d=US ;Save phase step in array IF.Qo=1 ;Oscs ON now? Q1=Str7?b[1620 + Q0] ;Pin number Port=$(hF0) + "F" + $(h80 + Q0<<4 + Q1) + $d(US) + $d(0) ENDIF. ENDIF. ENDIF. IF.Ctrls=4 ;Btn0 = Analog/Digital or Osc number IF.Btn7=<2 ;Analog/Digital toggle? QA=Btn0 ;New state 0=Analog, 1=Digital Btn0="" + Str7[400 + 20 * QA] ;Analog/Digital Inputs label Btn2="<M(QA + 2)" ;0-2 if Analog, 0-3 if Digital IF.QA=0 ;Analog now? Btn4="" + Str7 ;Analog Pins IF.Btn2=3 ;Was Digital in 8-chan mode? Btn2=2 ;Cut back to 4 for Analog QC=2^Btn2 ;2^2 = 4 Btn2=""+QC + " Channel" ENDIF. X=K ;Vert range for analog ELSE. ;Else Digital now Btn4="" + Str7 + Str7[940 + 10 * Qm] ;Digital Pins label X=D * 2 ;Vert range for digital ENDIF. Buf0#Vs=X ;Spect magnitude scaling UI=0 ;Chan counter WHILE.UI=<4 ;4 chans shown on later file Open Ch=UI ;Chan to set BufV#Vf=X ;Vert range for file BufV#Uf="Volt" ;Vert units for file UI=UI+1 ;Next chan WEND. @_Dscope_Acq_Mode ;Set new UM mode bitmap IF.QA=0 ;Analog? Buf0#VU=K * 2 ;Set vert range ELSE. ;Else Digital Buf0#VU=D * 4 ENDIF. ELSE. ;Else Osc number Msg= ;Clear prior Ctrl3 Freq jitter msg Q0=Btn0 ;Osc number to adjust Btn0="Set Oscillator " + Q0 ;Label button Q1=Str7?b[1620 + Q0] ;Current output pin from array UX=Str7?b[1624 + Q1] - h30 ;Index 0-4 for pin text Btn2="Osc" + Q0 + " = Pin " + Q1 + Str7[1640 + 12 * UX] Ctrl1="<<" + Str7 + Q0 + " Phase, %" ;"Oscillator N Phase" Ctrl3="<<" + Str7 + Q0 + Str7 ;"Oscillator N Freq, Hz" Ctrl3="<S(0,25k)" ;Limit to 25 kHz Ctrl1=Str7?q[1560 + 8 * Q0] ;Osc Phase % from array Ctrl3=Str7?q[1500 + 8 * Q0] ;Osc Freq from array ENDIF. ENDIF. IF.Ctrls=5 ;Btn1 = Trigger toggle QT=Btn1 ;Get new trigger state Trig=QT ;Set main Daqarta trig to match QM=QT<<7 + Qd<<6 + QS<<5 + Qc ;Trig mode cmd Port=$(hF0) + "T" + $(QM) + $w(QL) ;Send to device ENDIF. IF.Ctrls=6 ;Btn 2 = # channels / Osc Pin IF.Btn7=<2 ;Num chans? QC=2^Btn2 ;1, 2, or 4 chans (or 8 if Digital) Btn2="" + QC + " Channel" ;Label button @_Dscope_Acq_Mode ;Set new UM mode bitmap ELSE. ;Else Osc Pin Mtr1= ;Clear status msg, if any Ch=6 ;Str6 used for _Get_String StrV="Pin Number: " ;Prompt text @_Get_String ;Get user entry Q1=StrV?E[Posn?3-1,Posn?5-2] ;Evaluate to extract user entry IF.Q1=<2 ;Invalid pin? Q1=0 ;Set 0 = OFF ENDIF. IF.Q1=>15 ;Invalid pin? Q1=0 ;Set 0 = OFF ENDIF. IF.Q0=0 ;Setting Osc 0? T=0 ;Clear Holdoff timer ENDIF. IF.(Q0 && sgn(Q1-13)=1 ;Q0=>0 AND Q1=>13? Msg="Only Osc0 allows Wave mode." ELSE. UI=4 ;In case Q1 = pin 0 IF.Q1=!0 ;Non-zero pin number? UI=0 ;Osc test counter WHILE.UI=<4 ;Scan all OscN IF.UI=!Q0 ;Different than current? IF.Str7?b[1620 + UI]=Q1 ;Matching pin? Msg="Output pin already in use." LoopBreak=2 ;Exit WHILE if so ENDIF. ENDIF. UI=UI+1 ;Next OscN to scan WEND. ENDIF. IF.UI=4 ;No matching pins? IF.(QD * QT)=>=0 ;If no neg Trig Delay, Btn6="<N" ;Enable ADC bits ENDIF. Z=Str7?q[1500 + 8 * Q0] ;Osc freq Ctrl3="<S(0,25k)" ;25 kHz range IF.Q0=0 ;Setting Osc0? T=0 ;Clear Holdoff timer ENDIF. IF.Q1=>13 ;Wave Osc? A.ArbX7= ;Remove current Arb7 wave Arb7= ;File Open dialog for Arb7 IF.Posn?f=1 ;Load OK? GetFilePath=1 ;Get full path+name+ext UX=FileName?N ;Dummy read of name IF.Posn?z=<99 ;Will it fit in storage? Str7=FileName?N + z ;Store name Str7="U" ;Flag = Named wave uploaded ENDIF. US=2^32 * Z / S ;Wave osc freq step IF.Q1=14 ;256-sample Wave? Port#a7=$(hF0) + "o" ;Upload data Mtr1="Forcing 8-bit ADC mode for 256-sample Wave" Qb=0 ;0=8 bits, 1=10 Btn6=Qb ;Force btn to 8 Btn6="<D" ;Disable changes Btn6="" + Str7 ;Show 8-bit label Port=$(hF0) + "b" + $(Qb+Qr) ;Set 8-bit mode ELSE. ;Else 1024-sample Wave T=2^31 ;Block display updates Mtr1="No display with 1024-sample Wave" Port#A7=$(hF0) + "O" ;Upload data ENDIF. ENDIF. ELSE. US=2^25 * Z / S ;Square osc freq step ENDIF. Str7[1540 + 4 * Q0]#d=US ;Save freq step in array Str7[1620 + Q0]#b=Q1 ;Save new pin number UX=Str7?b[1624 + Q1] - h30 ;Pin number label index Btn2="Osc" + Q0 + " = Pin " + Q1 + Str7[1640 + 12 * UX] IF.Qo=1 ;Osc button ON? Port=$(hF0) + "F" + $(Q0<<4 + Q1) + $d(US) ;Set freq ENDIF. ENDIF. ENDIF. ENDIF. ENDIF. IF.Ctrls=7 ;Btn3 = Trigger Slope / Osc ON/OFF IF.Btn7=<2 ;Rising/Falling Trigger button? QS=Btn3 ;New slope state Btn3="" + Str7[700 + 20 * QS] ;Rising/Falling Trigger label IF.QT=1 ;Trigger active? QM=QT<<7 + Qd<<6 + QS<<5 + Qc ;Trig mode cmd Port=$(hF0) + "T" + $(QM) + $w(QL) ;Send to port ENDIF. ELSE. ;Else Osc ON/OFF button Msg= ;Clear old message, if any IF.Btn3=1 ;Oscs going ON? UI=0 ;Osc counter Q1=0 ;Freq / pin flags WHILE.UI=<4 ;Check all 4 oscs Q1=Q1 + (Str7?b[1620 + UI] && Str7?d[1540 + 4 * UI]) UI=UI+1 ;Next osc WEND. IF.Q1=0 ;No oscs set up? Btn3=0 ;Force to OFF Msg="Set Pin and Freq for at least one Osc" ELSE. ;Else at least one set Port=$(hF0) + "F" + $(hC0) ;Oscs OFF while setting UI=0 ;Osc counter WHILE.UI=<4 ;Set all oscs Q1=Str7?b[1620 + UI] ;Pin number IF.Q1=>13 ;Wave Osc? IF.Str7?b=0 ;Not uploaded yet? IF.Q1=14 ;Wave256? Port#a7=$(hF0) + "o" ;Upload 256 bytes ELSE. ;Else Wave1k Port#A7=$(hF0) + "O" ;Upload 1024 bytes ENDIF. Str7="U" ;Flag=uploaded ENDIF. ENDIF. QP=Str7?d[1600 + 4 * UI] ;Phase accum value US=Str7?d[1540 + 4 * UI] ;Freq step Port=$(hF0) + "F" + $(h80 + UI<<4 + Q1) + $d(US) + $d(QP) UI=UI+1 ;Next osc to set WEND. Port=$(hF0) + "F" + $(hC1) ;All set, Oscs ON ENDIF. ELSE. ;Else oscs going OFF Port=$(hF0) + "F" + $(hC0) ;Oscs OFF ENDIF. Qo=Btn3 ;New Osc ON/OFF state Btn3="Oscillators " + Str7[500 + 10 * Qo] ;Label ON/OFF ENDIF. ENDIF. IF.Ctrls=8 ;Btn4 = ADC/Digital Pins or ADC Clock select Btn4="<D" ;Disable during WaitBtns select IF.Btn7=2 ;Osc/Misc page? UI=0 ;ADC Clock index if so WHILE.UI=<7 ;7 clock rates to WaitBtns Ch=UI ;WaitBtns button index WaitBtns#V="" + Str7[1220 + 20 * UI] ;Set label from array UI=UI+1 ;Next index WEND. WaitBtns#R=1 ;Radio-button mode WaitBtns#0x=0 ;Disable 8 MHz Btn 0 Ch=UA-1 ;Mode 1-7 -> Btn 0-6 WaitBtns#V=1 ;Current mode on WaitBtns#N=7 ;7 ADC clock rates ELSE. ;Else Analog / Digital Pins IF.QA=0 ;Analog Inputs? UI=0 ;Button index WHILE.UI=<6 ;ADC pins 0-5 to WaitBtns Ch=UI ;WaitBtns button index WaitBtns#V="ADC Pin " + UI ;Set label from array UI=UI+1 ;Next button index WEND. WaitBtns#R=0 ;Independent buttons WaitBtns#b=Ub ;Master ADC bitmap WaitBtns#N=6 ;Only ADC pins 0-5 ELSE. ;Else Digital Inputs IF.Btn7=1 ;Trigger Timing dialog? Btn6="<D" ;No Digital Mode changes ENDIF. UX=Str7?b[1200 + Qm] ;0,2,6,8 start pin from Qm=0-3 UI=0 ;Button index WHILE.UI=<8 ;Set 8 digital pins buttons Ch=UI ;WaitBtns button index WaitBtns#V="Digital Pin " + UX ;Set label from array UX=UX+1 ;Next label index UI=UI+1 ;Next button index WEND. WaitBtns#R=0 ;Independent buttons WaitBtns#b=Qv ;Master Digital In view bitmap WaitBtns#N=8 ;Use all 8 buttons ENDIF. ENDIF. ENDIF. IF.Ctrls=h88 ;Return from WaitBtns IF.Btn7=2 ;Osc/Misc page? UA=WaitBtns?R + 1 ;Number of set button, 1-based Port=$(hF0) + "A" + $(UA) ;Set ADC clock rate Btn4="" + Str7 + Str7[1220 + 20 * (UA-1) + 6] ;ADC Clock label Btn4="<N" ;Re-enable button disabled above ELSE. ;Else Analog/Digital Pins IF.QA=0 ;Analog Inputs? UI=WaitBtns?b ;Get bitmap from WaitBtns UN=bcnt(UI) ;Count of pins set IF.UN=<QC ;Not enough for num chans? Msg="Must have at least" + QC + "pins selected" WaitBtns#N=6 ;Try again ELSE. ;Else at least 1 pin / chan Ub=UI ;New master ADC bitmap Btn2="<M(int(log2(UN)))" ;Limit Btn2 chans to match @_Dscope_Acq_Mode ;Set new UM mode bitmap Btn4="<N" ;Re-enable button Msg= ;Clear any error msg ENDIF. ELSE. ;Else Digital Inputs UI=WaitBtns?b ;Bitmap from WaitBtns UN=bcnt(UI) ;Number of pins set IF.QC=>4 ;8 chan mode? UX=4 ;Limit test to 4 chans ELSE. ;Else 1,2,4 chans UX=QC ;Actual chan count ENDIF. IF.UN=<UX ;Not enough for num chans? Msg="Must have at least" + UX + "pins selected" WaitBtns#N=8 ;Try again ELSE. ;Else at least 1 pin / chan Qv=UI ;New Digital In view map Str7[1400 + Qm]#b=Qv ;Store in byte array @_Dscope_Acq_Mode ;Set new UM mode bitmap Btn4="<N" ;Re-enable button IF.Btn7=1 ;Trigger Timing dialog? Btn6="<N" ;Allow Digital Mode changes ENDIF. Msg= ;Clear any error msg ENDIF. ENDIF. ENDIF. ENDIF. IF.Ctrls=9 ;Btn5 = Trigger Auto/Norm / Interrupt Lock IF.Btn7=2 ;Interrupt Lock? Qi=Btn5 ;Get new state, 1 = Int Lock IF.Qi=1 ;Int Lock now? Btn6="<D" ;Disable ADC Bits Ctrl0="<D" ;Disable Sample Delay IF.Qb=1 ;ADC Bits = 10? Mtr1="Forcing 8-bit ADC mode for Interrupt Lock" Qb=0 ;0 = 8 bits, 1 = 10 bits Btn6=Qb ;Set button for 8 bits Btn6="" + Str7 ;Show 8-bit label Port=$(hF0) + "b" + $(Qb+Qr) ;Set 8-bit mode ENDIF. ELSE. ;Else Int Lock going off Btn6="<N" ;Enable ADC bits Ctrl0="<N" ;Enable Sample Delay ENDIF. @_Dscope_Acq_Mode ;Set new UM mode bitmap ELSE. ;Else Trig Auto/Norm Qn=Btn5 ;New Auto/Norm state Btn5="" + Str7[900 + 20 * Qn] ;Set button label IF.Btn5=0 ;Going to Auto? Port=$(hF0) + "W" + $w(QW) ;Set Auto-Trigger Wait ELSE. ;Else Normal Port=$(hF0) + "W" + $w(0) ;No Auto-Trigger Wait ENDIF. ENDIF. ENDIF. IF.Ctrls=10 ;Btn6 = File Save, Digital Mode, 8/10 ADC Bits IF.Btn7=2 ;Osc/Misc dialog = 8/10 ADC Bits? Qb=Btn6 ;0 = 8 ADC bits, 1 = 10 bits Btn6="" + Str7[1025 + 25 * Qb] ;Show label Port=$(hF0) + "b" + $(Qb+Qr) ;Set 8-bit or 10-bit mode ENDIF. IF.Btn7=1 ;Trigger Timing dialog = Digital Mode? Qm=Btn6 ;0-3 Digital Mode Qv=Str7?b[1400 + Qm] ;Set View for this mode Btn4="" + Str7 + Str7[940 + 10 * Qm] ;Digital Pins Btn6="" + Str7 + Qm(0) + " = " + Str7[940 + 10 * Qm] @_Dscope_Acq_Mode ;Set new UM mode bitmap ENDIF. IF.Btn7=0 ;Main dialog = File Save? IF.QA=0 ;Analog inputs? Buf0#M=Ub ;ADC chan file save bitmap ELSE. ;Else Digital Buf0#M=Qv ;Digital chan file save bitmap ENDIF. Buf0#Rf=QR ;File sample rate Buf0#N=QC ;1, 2, 4, or 8 chans AutoInc#Bu=UF ;Filename AutoInc state (0,1,2) Buf0="<SaveDQA:" + Str1 ;Save As prompt IF.Posn?f=1 ;Name entered? GetFilePath=2 ;Get save path and name Str1=FileName?P +z ;Save it without extension ENDIF. ENDIF. ENDIF. IF.Ctrls=11 ;Btn7 = Setup options IF.Btn7=0 ;Main dialog default? Ctrls="<<DaquinOscope - Main Controls" ;Dialog title Ctrl1="<<Trigger Pin" ;Control label Ctrl1="<r(0,18)" ;Pin range (ADC + dig + Wave Osc) Ctrl1#s=UC ;Set current pin select number IF.UC=<6 ;0-5 = ADC? Ctrl1="< " + Str7 + UC ;"Analog Pin nn" ELSE. ;Else digital or Wave Osc UI=UC - 6 + 2 ;Slider number to digital pin 2-14 IF.UC=18 ;Slider at max? Ctrl1="< " + Str7 ;"Wave Osc 0" ELSE. ;Else normal digital Ctrl1="< " + Str7 + UI ;"Digital Pin nn" ENDIF. ENDIF. Ctrl2="<<" + Str7 ;"Trigger Level" Ctrl2="<S(0,1023)" ;Slider range Ctrl2="<p(0)" ;No decimal places Ctrl2=QL ;Control = current Level Ctrl3="<<" + Str7 ;"Trigger Hysteresis" Ctrl3="<S(0,255)" ;Slider range Ctrl3="<p(0)" ;No decimal places Ctrl3=QH ;Control = current Hysteresis Btn0="<T" ;Toggle button, Analog/Digital Btn0=QA ;Btn0 = current state Btn0="" + Str7[400 + 20 * QA] ;Analog/Digital Inputs label Btn2="<M(QA + 2)" ;Chans = Multi-state 0-2 or 0-3 Btn2=log2(QC) ;Current chans 1,2,4 or 1,2,4,8 Btn2="" + QC + " Channel" ;"N channel" label Btn3=QS ;Rising/Falling slope state Btn3="" + Str7[700 + 20 * QS] ;"Rising/Falling Trigger" IF.QA=0 ;Analog input mode? Btn4="" + Str7 ;"Analog Pins" ELSE. ;Else Digital inputs Btn4="" + Str7 + Str7[940 + 10 * Qm] ;"Digital Pins 0-7", etc ENDIF. Btn5="<T" ;Auto/Normal Trigger toggle Btn5=Qn ;Set current state Btn5="" + Str7[900 + 20 * Qn] ;Label button Btn6="<M" ;Momentary File Save button Btn6="<N" ;Enable Btn6="Save Data File" ;Label Btn7="More Controls >>>" ;This dialog change button label ENDIF. IF.Btn7=1 ;Trigger Timing dialog? Ctrls="<<DaquinOscope - Trigger Timing" IF.(Qb + Qi)=0 ;8-bit ADC, no Int Lock? Ctrl1="<S(-1023, 32767)" ;Allow negative Trigger Delay IF.QD=<0 ;Current delay negative? Ctrl1="<<NEG Trigger Delay, samples" ELSE. Ctrl1="<<Trigger Delay, usec" ENDIF. ELSE. ;Else 10-bit ADC Ctrl1="<S(0, 32767)" ;No neg delay Ctrl1="<<Trigger Delay, usec" ;Always usec IF.QD=<0 ;Current delay negative? QD=0 ;Force to 0 if so ENDIF. ENDIF. Ctrl1="<p(0)" ;No decimal places Ctrl1=QD ;Ctrl1 shows Trigger Delay value Ctrl2="<<" + Str7 ;"Auto-Trigger Wait, sec" Ctrl2="<S(10m, 32767)" ;10 ms to 32767 sec range Ctrl2="<p(3)" ;3 decimal places Ctrl2=Qw ;Show current Wait value Ctrl3="<<" + Str7 ;"Trigger Holdoff, sec" Ctrl3="<S(0,32767" ;0-32767 sec range Ctrl3="<p(3)" ;3 decimal places Ctrl3=H ;Show current Holdoff value Btn0="<T" ;Toggle button, Analog/Digital Btn0=QA ;Btn0 = current state Btn0="" + Str7[400 + 20 * QA] ;Analog/Digital Inputs label Btn2="<M(QA + 2)" ;Chans = Multi-state 0-2 or 0-3 Btn2=log2(QC) ;Current chans 1,2,4 or 1,2,4,8 Btn2="" + QC + " Channel" ;"N channel" label Btn3=QS ;Rising/Falling slope state Btn3="" + Str7[700 + 20 * QS] ;"Rising/Falling Trigger" IF.QA=0 ;Analog input mode? Btn4="" + Str7 ;"Analog Pins" ELSE. ;Else Digital inputs Btn4="" + Str7 + Str7[940 + 10 * Qm] ;"Digital Pins 0-7", etc ENDIF. Btn5="<T" ;Auto/Normal Trigger toggle Btn5=Qn ;Set current state Btn5="" + Str7[900 + 20 * Qn] ;Label button Btn6="<M(3)" ;0-3 Digital Modes Btn6="<N" ;Enable button Btn6=Qm ;Set current mode Btn6="" + Str7 + Qm(0) + " = " + Str7[940 + 10 * Qm] ;Show it Btn7="Osc and Misc Controls >>>" ;Dialog change button label ENDIF. IF.Btn7=2 ;Osc/Misc dialog? Ctrls="<<DaquinOscope - Oscillators and Misc." Ctrl1="<S(0,99.9999)" ;Osc N Phase range Ctrl1="<p(4)" ;4 decimal places Ctrl1="<<" + Str7 + Q0 + " Phase, %" ;"Oscillator Q0 Phase" Ctrl1=Str7?q[1560 + 8 * Q0] ;Set Osc Q0 Phase from array Ctrl2="<S(7812.5,50k)" ;Interrupt rate rane Ctrl2="<<" + Str7 ;"Interrupt Rate" Ctrl2=S ;Set current rate S Ctrl3="<<" + Str7 + Q0 + Str7 ;"Oscillator N Freq, Hz" Ctrl3="<S(0,25k)" ;0-25000 Hz Freq range Ctrl3="<p(5)" ;5 decimal places Ctrl3=Str7?q[1500 + 8 * Q0] ;Set Osc Q0 Freq from array Btn0="<M(3)" ;0-3 OscN Btn0=Q0 ;Set Osc Q0 Btn0="Set Oscillator " + Q0 Btn2="<M" ;Momentary button for Osc Pin Q1=Str7?b[1620 + Q0] ;Get current pin number for Osc Q0 UX=Str7?b[1624 + Q1] - h30 ;Pin number text index Btn2="Osc" + Q0 + " = Pin " + Q1 + Str7[1640 + 12 * UX] ;"Osc0 = Pin 0 (OFF)" Btn3=Qo ;Oscillators ON/OFF state Btn3="Oscillators " + Str7[500 + 10 * Qo] ;Show ON or OFF Btn4="" + Str7 + Str7[1220 + 20 * (UA-1) + 6] ;ADC Clock label Btn5="Interrupt Lock" Btn5=Qi ;1 = Int Lock Btn6="<T" ;ADC Bits = Toggle-type button Btn6=Qb ;Set current state Btn6="" + Str7[1025 + 25 * Qb] ;"8 ADC Bits" or "10 ADC Bits" IF.Str7?b=14 ;Wave256 Osc loaded? OR.(QD * QT)=<0 ;OR Trigger, w. neg delay? Btn6="<D" ;Disable ADC Bits button ELSE. Btn6="<N" ;Else enable ENDIF. Btn7="Main Controls >>>" ;Dialog change button label ENDIF. ENDIF.
_Dscope_Task Macro Subroutine Listing:
;<Help=H4922 IF.Pause=1 ;Paused? LoopBreak=0 ;No update if so ENDIF. IF.Timer=<T ;Trigger Holdoff time elapsed? LoopBreak=0 ;No update if not ENDIF. UV=Ch ;Save _Ctrls Ch IF.Qa=0 ;Task state = ready to request next burst? Port=$(hF1) + $(UM) ;UM = bitmap (+ 40h if ints) Qa=1 ;Task state = burst requested ENDIF. IF.Qa=1 ;Waiting for 0xF1 return of acq time? UT=Port?4 ;Request elapsed acquisition time, usec IF.Port?n=!0 ;Any bytes read? T=Timer ;Time of 0xF1 return ;Earliest time for next trigger: T=T - UT / 1e6 + H ;(Current less acq time = trig time) + Holdoff IF.(UM & h80)=0 ;Analog (ADC) input mode? IF.Qb=1 ;10-bit ADC? Port#D1=hF2 ;Request 1280 bytes if so ELSE. Port#D1=hF3 ;Else request 1024 bytes for 8-bit ENDIF. ELSE. ;Else Digital input mode Port#D1=hF3 ;Request 1024 bytes for 8 digital pins ENDIF. Qa=2 ;Task state = Data requested ENDIF. ENDIF. IF.Qa=2 ;Waiting for 1K samples? IF.(UM & h80)=0 ;Analog (ADC) mode? IF.QC=1 ;Single chan? IF.Qb=1 ;10-bit ADC? Buf0#A1=Port?A ;Get 1K *samples* to Buf0 ELSE. ;Else 8-bit ADC Buf0#b1=Port?a ;Get 1K bytes to Buf0 ENDIF. ENDIF. IF.QC=2 ;2 channels? IF.Qb=1 ;10-bit ADC? Buf0#A2=Port?A ;Get 512 samples each to Buf0-1 ELSE. ;Else 8-bit ADC Buf0#b2=Port?a ;Get 512 bytes each to Buf0-1 ENDIF. ENDIF. IF.QC=4 ;4 channels? IF.Qb=1 ;10-bit ADC? Buf0#A4=Port?A ;Get 256 samples each to Buf0-3 ELSE. ;Else 8-bit ADC Buf0#b4=Port?a ;Get 256 bytes each to Buf0-3 ENDIF. ENDIF. ELSE. ;Else Digital input mode Ch#n=(Qm + 1) & 2 ;0,2,2,0 bit offset for Qm modes 0,1,2,3 Buf0#Dn=Port?D ;Upload top viewmap button bit to Buf0 ENDIF. IF.Port?n=!0 ;Any bytes read? @_Dscope_Write ;Display if so Qa=0 ;Reset task state for next update ENDIF. ENDIF. Ch=UV ;Restore _Ctrls Ch
_Dscope_Write Macro Subroutine Listing:
;<Help=H4922 IF.(UM & h80)=0 ;Analog mode? QI=0 ;Channel index Ch=QI ;Index for BufV BufV="<uW0" ;Always upload initial chan IF.Btn2=>0 ;2 or 4 chans? Ch=QI+1 ;Set 2nd chan index BufV="<uW1" ;Upload 2nd chan ENDIF. IF.Btn2=2 ;4 chans? Ch=QI+2 BufV="<uW2" Ch=QI+3 BufV="<uW3" ENDIF. QX=QC ;Effective chans for sample rate ELSE. ;Else Digital mode QX=1 ;Bit posn marker QN=0 ;Upload data chan 0-3 IF.(QX & Qv)=>0 ;Does Buf0 need upload? Buf0="<uW(QN)" QN=QN+1 ENDIF. QI=1 ;Now Buf1-Buf7 UR=(Qm + 1) & 2 ;0,2,2,0 bit offset for Qm modes 0,1,2,3 WHILE.QI=<8 Ch=QI Ch#n=(QI + UR) & 7 BufV#Dn=Port?C QX=QX << 1 IF.QN=<4 IF.(QX & Qv)=>0 ;Bit set for upload? BufV="<uW(QN)" QN=QN+1 ENDIF. ENDIF. QI=QI+1 WEND. QX=1 ;Effective chans for sample rate ENDIF. IF.(QD * QT)=<0 ;Negative trigger delay, w. active trig? Port#D1=h81 ;Delayed samples, low word UR=Port?2 Port#D1=h82 ;Delayed samples, high word UR=(Port?2)<<16 + UR ;Combined delayed N-chan samples UR=UR * 1e6 / UT ;Delayed sample rate Port#D1=h83 ;Actual neg delay samples, abs val UP=Port?2 UP=-UP ;Convert to neg IF.UP=!QD ;Same as control setting? QD=UP ;Update if not IF.Btn7=1 ;Trig delay showing? Ctrl1=QD ;Update if so ENDIF. ENDIF. ELSE. UR=1024e6 / UT / QX ;Normal sample rate ENDIF. X=abs(UR-QR) / QR ;Fractional change from display IF.X=>R ;Past limit? QR=UR ;Update if so Buf0#R=QR ;Update X axis sample rate Buf0#Rf=QR ;Update file sample rate Buf0#Rs=QR ;Update Spectrum X axis Mtr0=QR + " Hz" ;Update display ENDIF.
See also Macro Examples and Mini-Apps, DaqPort Arduino Sketch, USB / Serial Communications Port Access
Questions? Comments? Contact us!We respond to ALL inquiries, typically within 24 hrs.
Over 35 Years of Innovative Instrumentation
© Copyright 2007 - 2022 by Interstellar Research
All rights reserved