Site Provided by VE5KC & Kteck Webs

Using the MMVARI Engine with your programs

(Information for programmers - this file is included in the Engine download file)
MMVARI Soundcard Engine

 

ActiveX control MMVARI.ocx

    JE3HHT Makoto Mori
    Translated into English by JA7UDE Nobuyuki Oba

This document describes MMVARI ActiveX control, MMVARI.ocx.

~~~~~~
Attention
~~~~~~
The enumeration of the property and method has been modified. Applications referring to the MMVARI
enumeration must be recompiled.

~~~~~~
Contents
~~~~~~
o Version up history
o About MMVARI.ocx
o RX and TX channels
o Character transmission mechanism
o Sampling frequency
o MMVARI control property
o MMVARI control method
o MMVARI control event
o Multiple instances of MMVARI control
o About XMMVView control
o XMMVView control property
o XMMVView control method
o XMMVView control event
o About XMMVLvl control
o XMMVLvl control property
o XMMVLvl control method
o XMMVLvl control event
o Closing remarks


=============
Version up history
=============
- September 24, 2010 (Version 1.08)
    MMVARI control
        - Added bRTTYFFT property
        - Supported RTTY FSK
        - Added bCOMFSK property
        - Added bCOMFSKINV property
        - Added qpsk mode
        - Added bSendSingleTone property
        - Changed the number of subchannels to 24
    XMMVView control
        - Added bShowSubChannelMarkers property
        - Added bShowNotchMarkers property
        - Added strSubChannels property

- March 1, 2005 (version 1.06)
    XMMVView control
        - Changed the lower limit of wWidthFreq to 200Hz (previously 500Hz)

- January 20, 2005 (version 1.05)
    XMMVLvl control
        - Added DrawCustom method

- January 11, 2005 (version 1.04)
    MMVARI control
        - Fixed a bug (could not send Japanese half width kana)

- January 8, 2005 (version 1.03)
    MMVARI control
        - Added wRxCenter property
        - Added bCustomFilter and dblCustomSampleFreq properties
        - Added wNumNotches and wNotches properties
        - Added AddNotchFreq, FindNotchFreq, and DeleteNotch methods
        - Added CreateCustomFilter, DeleteCustomFilter, CreateCustomFilterByKW, CreateCustomFilterByIDFT, and
CalcCustomCharacteristic methods
    XMMVView control
    - Added wMouseChannel and wMouseNotch properties

- December 29, 2004 (version 1.02)
    Added EXMMVARI.txt (TNX to JA7UDE)
    MMVARI control
        - Added bOverLevel property
        - Added bPTTLines property
    XMMVView, XMMVLvl control
        - Disabled getting the focus on mouse click
- December 28, 2004 (version 1.01)
    Fixed a bug in the XMMView (small waterfall)
- December 25, 2004 (version 1.00)
    First release

===============
About MMVARI.ocx
===============
MMVARI.ocx is an OLE custom control for VisualBasic6 programming.  It is equipped with a soundcard
engine that supports four modes, GMSK, FSK, FSK-W, and BPSK, which can deal with the Varicode
optimized for MBCS. In addition to these four modes, it is capable of four other standard modes, bpsk,
qpsk,  rtty, and mfsk.

    MMVARI        Soundcard engine
    XMMVView    Paint control for spectrum, waterfall, and waveform
    XMMVLvl    Level meter control
    XMMVBtn    Toggle button control

This document does not explain XMMVBtn control. Refer to the sample container (Test) in this package
for more information on XMMVBtn control.

Files in this package
~~~~~~~~~~~~~~
    MMVARI.ocx    Core file of the MMVARI ActiveX
    XMMVARI.txt    Japanese instruction manual
    EXMMVARI.txt    English instruction manual

The application using any control in MMVARI.ocx must include MMVARI.ocx in its distribution package.
Generally, it is a good idea to have MMVARI.ocx in the same folder where the application resides.

To open the test container source code in the VisualBasic 6.0, you should have MMVARI.ocx in the folder
that has your source code files.

MMVARI.ocx creates VariCode.tbl in the same folder when it is called for the first time. The object of the file
is to boost the speed of the program startup next time and then. If MMVARI.ocx does not find the file at the
start up, it automatically creates the file. Therefore,the application package does not have to include the file for
distribution.

MMVARI.ocx supports the following Windows platforms:
    Windows?95, 98, 98SE, ME
    Windows?NT, 2000, XP

==============
RX and TX channels
==============
MMVARI control is equipped with nine RX channels (one for main, eight for sub), and one TX channel. The
RX channels are indexed from 0 to 8. RX channel 0 is called the main channel. The mode and baud rate of the
TX channel are always the same as those of RXchannel 0.

Most properties of RX channel are implemented in an array form indexed by the channel number. Since array
property cannot be seen in the VisualBasic6 form designer, you could use the object browser instead.

Examples
    strMode(nIndex As Integer) As String        Mode name
    dblSpeed(nIndex As Integer) As Double        Transfer speed

If you set True to bActive property, Channel 0 is made active, and bRxEnabled(0) becomes True. To make
Channel 1 active, for example, do bRxEnabled(1)=True.

* As the number of RX channels increases, MMVARI uses more CPU resources.

=======================
Character transmission mechanism
=======================

MMVARI.ocx has two methods for sending characters. You can use either of them, or both at the same time.

Asynchronous method
~~~~~~~~~~~~~~~
This method transmits characters through the circulate TX buffer equipped in MMVARI.ocx. The buffer can
hold up to 2048 characters. For this purpose, the following properties and methods are provided:

    wBufferCount As Integer
    Function SendText(strText As String) As Integer
    Function SendCWID(strText As String) As Integer
    Function SendChar(wChar As Integer) As Integer
    Function GetSendText() As String

For more information, see the property and method sections.

Synchronous method
~~~~~~~~~~~~~~
MMVARI.ocx requests one character on OnGetTxChar event. This method is suited for the scheme in which
the user application peeks TX characters one bye one from its TX window and sends them to MMVARI.ocx.

* The sample container uses this method for reference.
* You could use the asynchronous and synchronous methods at the same time. MMVARI control checks if the
TX buffer is empty; if so, it generates OnGetTxChar event to inquire the next character to transmit.

==============
Sampling frequency
==============
MMVARI control supports various sampling frequencies. The RX sampling frequency is defined by
dblSampleFreq property. The offset for the TX sampling frequency can be defined by dblTxOffset property
in Hz. Sampling frequencies that MMVARI supports are shownbelow. The default sampling frequency is
11025Hz.

11025Hz    One of the standard frequencies supported by all the soundcards
12000Hz    Frequency that is likely to have zero offset (TxOffset=0), but not supported by all soundcards
6000Hz    Low CPU load, but not supported by all soundcards
8000Hz
16000Hz
18000Hz
22050Hz    One of the standard frequencies, having no specific merit.
24000Hz
44100Hz    One of the standard frequencies, having no specific merit.
48000Hz    For an optical digital interface

* Use 6000Hz for old PCs.
* 8000Hz has some time lag in the spectrum and waterfall display from RX signals because of the number of
FFT points misaligned.
* You can change the sampling frequency anytime on the fly.

The discrimination of the sampling frequency will not cause severe problems in MMVARI though it will in
SSTV. However, the discrimination will result in the frequency mismatch in the practical QSO. It does not
cause a trouble in normal QSOs when the AFC isengaged, but it does for receiving weak signals. For this
reason, it is a good idea your application allows the user to adjust TxOffset.

===================
MMVARI control property
===================

bActive As Boolean
~~~~~~~~~~~~~~
This property is used to start and stop the MMVARI control. Upon putting True to bActive, MMVARI opens
the soundcard and starts receiving the main channel in the default mode. Upon putting False to bActive,
MMVARI closes the soundcard and releases all the resources, such as a COM port.

* When bActive is False, MMVARI does not generate any event.

* When the MMVARI control is discarded, all the resources that MMVARI uses are automatically released.
The application does not have to set False to bActive on exit.

bAddStartCR As Boolean
~~~~~~~~~~~~~~~~~~
If True, MMVARI sends CR/LF at the beginning of the transmission.

bAddStopCR As Boolean
~~~~~~~~~~~~~~~~~~
If True, MMVARI sends CR/LF at the end of the transmission.

bATC As Boolean
~~~~~~~~~~~~
If True, Automatic Timing Control (ATC) is turned on. In the rtty mode, ATC is always off irrespective of this
property. In the mfsk mode, on the other hand, ATC is always on irrespective of this property.

*It is recommended to keep ATC on all the time for better signal decoding.

bLoopExternal As Boolean
~~~~~~~~~~~~~~~~~~~
If True, the sound loop back mode is set to External. This is used for adjusting the TX timing or for satellite
communication.

bNET As Boolean
~~~~~~~~~~~~~
If True, the NET is on, that is, the TX frequency follows the RX frequency.

bPlayBack As Boolean
~~~~~~~~~~~~~~~~
If True, the sound playback function is enabled. To start the playback function, call PlayBack method.

* The sound playback function stores the PCM sound data for the latest 60 seconds in the MMVARI control.
In case of the 11025Hz sampling frequency, it uses about 1.3MB memory space for the sound playback.

bReqRX As Boolean
~~~~~~~~~~~~~~~
If True, MMVARI automatically returns to RX when the encoder enters an idle phase (i.e., no characters
remain in the TX buffer).

bRxEnabled(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

If True, RX channel(nIndex) becomes active. BRxEnabled(0) is equivalent with bActive property. Activating
any of RX channels changes bActive property to True.

bSQ(nIndex As Integer) As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX chennel #

This property gives the squelch status of RX channel(nIndex).

bSync(nIndex As Integer) As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

This property shows the synchronization status of RX channel(nIndex).

bTX As Boolean
~~~~~~~~~~~~
This property is used to switch TX and RX. Putting False to bTX instantaneously makes MMVARI return to
RX even during the transmission. Use bReqRX property for normal TX termination, which performs the proper
amplitude control.

bHPF As Boolean
~~~~~~~~~~~~~
If True, the high-pass filter is engaged for RX. Although this is unnecessary for most soundcards, it sometimes is
effective for eliminating hum in the input audio.

bNotch As Boolean
~~~~~~~~~~~~~~
If True, the notch filter is engaged. Use wNotchFreq to specify the notch filter frequency.

* MMVARI.ocx still has this property for the backward compatibility for version 1.02 or older versions.
MMVARI.ocx version 1.03 and later can have multiple notch frequencies. Use wNotches property, and
AddNotchFreq, FindNotchFreq and DeleteNotch methods.

bMetricSqMFSK As Boolean
~~~~~~~~~~~~~~~~~~~~~
If True, mfsk metric level is used for the squelch. If False, the S/N level is used for the squelch. This property
is effective only for mfsk.

bTreatCenterMFSK As Boolean
~~~~~~~~~~~~~~~~~~~~~~~
If True, the center frequency is used for the carrier frequency. If False, the base tone frequency is used for
the carrier frequency.

bUOS(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

If True, RTTY UOS is active for RX channel(nIndex). This property is effective only for RTTY.

bPTTLock As Boolean
~~~~~~~~~~~~~~~~
If True, MMVARI exclusively uses the PTT port specified by strPTTPort. If False, MMVARI opens the
PTT port only during TX. In case strPTTPort is NONE, this property has no effect.

bCodeMM(nIndex As Integer) As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

bCodeMM specifies the MMVARI code. The code is VariJA, VariHL, VariBV, or VariBY. This property
is affected by wCharset property and the RX mode.

bPTTLines(nLine As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property defines the state of the PTT control lines. If strPPTPort is NONE, this property is not effective.

    0 = pttlineRTS    RTS
    1 = pttlineDTR    DTR
    2 = pttlineTXD    TXD

Example:
    bPTTLines(pttlineRTS) = True
    bPTTLines(pttlineDTR) = False

bOverLevel(nIndex As Integer) As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : RX chennel #

This property shows the overflow status of RX channel(nIndex).

bCustomFilter As Boolean (RaadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property shows if the RX custom filter is engaged.

bRTTYFFT(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : RX channel #

This property specifies the demodulator for RTTY. It is effective only for the RTTY mode.
    0 - IIR
    1 - FFT

bCOMFSK As Boolean
~~~~~~~~~~~~~~~~~
When this property is set to True, the MMVARI.OCX does the FSK keying at the COM port selected by
strPTTPort (only in the RTTY mode). When strPTTPort is COMx, MMVARI.OCX generates the FSK
timing and keys TxD. When strPTTPort is EXTFSK,MMVARI.OCX sends the character data to EXTFSK
(EXTFSK generates the FSK timing). MMVARI.OCX and EXTFSK use Windows' multimedia timer so that
about 1msec jitter is expected. The baud rate is fixed to 45 irrespective of the dblSpeed value.

bCOMFSKINV As Boolean
~~~~~~~~~~~~~~~~~~~~
When this property is set to True, MMVARI.OCX reverses the polarity of the FSK signal at the port specified
by strPTTPort. However, if strPTTPort is EXTFSK, this property is ignored.

bSendSingleTone As Boolean
~~~~~~~~~~~~~~~~~~~~~
When this property is set to True, MMVARI.OCX generates a single tone at the end of transmission.

dblCustomSampleFreq As Double (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property is the sampling frequency (Hz) of the RX custom filter. See CreateCustomFilter method section.

dblFFTSampleFreq As Double (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property is the FFT sampling frequency in Hz.

dblSampleFreq As Double
~~~~~~~~~~~~~~~~~~~
This property specifies the RX sampling frequency.

dblTxOffset As Double
~~~~~~~~~~~~~~~~
This property specifies the TX sampling frequency offset with respect to the RX sampling frequency.

dblSpeed(nIndex As Integer) As Double
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

This property specifies the baud rate of RX channel(nIndex).

dblFreqError(nIndex As Integer) As Double (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

This property shows the RX frequency discrimination (-0.5 to 0.5). When AFC is on, this value will converge
to 0.

dblBandWidth(nIndex As Integer) As Double (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

This property shows the bandwidth of RX channel(nIndex). In the standard RTTY, it is 170Hz. It should be
noted, however, that this property value is different from the bandwidth for actual signal transmission, which
actually requires wider bandwidth.

dblTxShift As Double
~~~~~~~~~~~~~~~
This property specifies the TX shift width in Hz for RTTY and FSK-W. If the shift widths for TX and RX are
far different, the loopback will not function during TX.

dblRxShift(nIndex As Integer) As Double
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

This property specifies the RX shift width in Hz for RTTY and FSK-W.

dwATC As Long
~~~~~~~~~~~~~
This property specifies the adjustment offset in ppm for the RX sampling frequency. When bATC is True,
MMVARI automatically manages the dwATC value.

dwHandle As Long (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~
This property shows the object handle of the MMVARI control. This handle is used for XMMVLvl and
XMMVView controls.

Once the MMVARI object has been established, dwHandle never changes. Therefore, you could use a static
variable as shown below.

    Dim g_dwHandle As Long

    Private Sub Form_Load()
        g_dwHandle = MMVARI.dwHandle
        |
    End Sub

    Private Sub MMVARI_OnDrawFFT(ByVal wCount As Integer, pArray As Long)
        Call XMMVView.Draw(g_dwHandle)
        Call XMMVLvl.Draw(g_dwHandle, 0)
    End Sub

dwSampleBase As Long (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~
This property gives the base sampling frequency. It, for example, is 11025 or 12000.

nBPF As Integer
~~~~~~~~~~~~
This property specifies the bandwidth of the RX BPF. MMVARI automatically adjusts the width in accordance
with the mode and speed. It affects all the RX channels.

    0 - Wide
    1 - Middle
    2 - Narrow
    3 - Ultra narrow

statIsPlaying As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~
This property indicates if the sound playback function is running.

statLostRX As Integer
~~~~~~~~~~~~~~~
This property indicates if a part of the RX sound is lost. When the sound lost is detected, this property
becomes non-zero for approximately three seconds.

statLostTX As Integer
~~~~~~~~~~~~~~~
This property indicates if a part of the TX sound is lost. When the sound lost is detected, this property
becomes non-zero for approximately three seconds.

statSoundOpen As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property shows the status of the soundcard.
    1 - Opened as input
    2 - Opened as output
    3 - Opened as input/output

statComOpen As Integer
~~~~~~~~~~~~~~~~~
This property shows the COM port status.
    0 - Not in use
    1 - Opened
    -1 - Failed to open

strVersion As String (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~
This property has the version number of the MMVARI control.

strPTTPort As String
~~~~~~~~~~~~~~~
This property specifies the COM port name for PTT. Put "NONE" to this property if you do not use the
PTT control function build in MMVARI. The COM port for PTT will not be opened until True is set to
bActive property.

Example:    strPTTPort = "COM1"

Use OnPTT event for PTT make/break control.

strSoundID As String
~~~~~~~~~~~~~~~
This property specifies the soundcard ID(s).

    -1    Windows default
    0    First soundcard
    1    Second soundcard

To specify different soundcards for RX and TX, specify two numbers with a comma in between like:
    0,1    (RX uses the first soundcard and TX uses the second soundcard)

To specify a custom sound, put the name (e.g., WLClient) to this property.

Examples:
    strSoundID = "-1"    'Use Windows default (sound mapper)
    strSoundID = "0,1"
    strSoundID = "WLClient"

strModeList(nIndex As Integer) As String (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property returns the modes supported by the MMVARI control. nIndex is the mode number, and must
be between 0 and wModeMax-1.

Example code:    CBMode.Clear
    For i = 0 To MMVARI.wModeMax - 1 Step 1
        CBMode.AddItem (MMVARI.strModeList(i))
    Next i

The current version supports the following modes:
    GMSK        MBCS experiment (HF)
    FSK        MBCS experiment (V/UHF)
    FSK-W        MBCS experiment (V/UHF, satellite)
    BPSK        MBCS experiment (HF)
    bpsk        Standard bpsk
    rtty-L        BAUDOT (LSB)
    rtty-U        BAUDOT (USB)
    mfsk-L        MFSK (LSB)
    mfsk-U        MFSK (USB)
    qpsk-L        Standard qpsk (LSB)
    qpsk-U        Standard qpsk (USB)

* In the non-MBCS code set, BPSK and bpsk work in the same manner.

* In future MMVARI versions, more modes will be implemented. It is a good idea for the application to have
a mode combo-box by referring to wModeMax and strModeList.

strMode(nIndex As Integer) As String
~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the mode in the Channel(nIndex). If nIndex is 0, the TX mode is also set.
Example:    strMode(0) = "bpsk"

* The mode change will induce the speed change. For example, the mode is changed from bpsk to rtty-L,
MMVARI changes the baud rate to 45.45bps. In such a case, MMVARI generates OnSpeed event.

wChannels As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~
This property returns the maximum number of RX channels supported in the current version. Version 1.08
returns 25.

wModeMax As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~
This property returns the number of modes supported in the current version. Version 1.08 returns 11.
To get each mode name, use strModeList property.

wCharset(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #

This property specifies the font character set for RX channel(nIndex). MMVARI defines the MBCS
VARICODE based on the character set specified here. The application supporting two or more code sets,
put the character set to this property.
Example:    MMVARI.wCharset(0) = RxWindow.Font.Charset

To get the VARICODE of the specified MBCS language, call GetVariType.

* RTTY uses BAUDOT code only.

wFFTType As Integer
~~~~~~~~~~~~~~~~
This property specifies the amplitude of the FFT display.
    0 - dB
    1 - Squared amplitude

wFFTWidth As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~
This property has the number of points used in the FFT calculation. It is less than or equal to 2048.


wWaveMax As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~
This property shows the maximum number of points in the waveform data. The value depends on the mode,
speed, and sampling frequency.

wModGain As Integer
~~~~~~~~~~~~~~~~
This property specifies the digital output level in the rage of 0 to 32767. The default is 16384.

wRxCarrier(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the RX carrier frequency of RX channel(nIndex).

wRxCenter(nIndex As Integer) As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property shows the center frequency (Hz) of the RX carrier of RX chennle(nIndex). In case bTreatCenterMFSK is False and
the mode is mfsk, this property has a value different from wRxCarrier.

wSN(nIndex As Integer) As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property shows the S/N ratio (dB * 100) of RX channel(nIndex).

wSoundCH As Integer
~~~~~~~~~~~~~~~~
This property specifies the sound input channel. The default is 0 (=Monaural).
    0 - Monaural
    1 - Left
    2 - Right

wSoundRxFIFO As Integer
~~~~~~~~~~~~~~~~~~~
This property specifies the depth of the RX FIFO. The valid value is 4 to 32.

wSoundTxFIFO As Integer
~~~~~~~~~~~~~~~~~~~
This property specifies the depth of the TX FIFO. The valid value is 4 to 32.

wSQLevel(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the squelch level (db * 100) of RX channel(nIndex). The default is 300 (=3db).

wTxCarrier As Integer
~~~~~~~~~~~~~~~
This property specifies the TX carrier frequency.

wMode(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the mode of RX channel(nIndex). If nIndex is 0, the TX mode is also set. This
property uses the index number of modes. Use strMode for setting the mode by name.

Example:    wMode(0) = 4    ' bpsk

wAFCLevel As Integer
~~~~~~~~~~~~~~~~
This property specifies the S/N level (dB) for the wide AFC. In case wAFCWidth is less than or equal to
50Hz, the wide AFC does not function and wAFCLevel is ignored. This property is applied to all the RX
channels.

wAFCWidth As Integer
~~~~~~~~~~~~~~~~~
This property specifies the frequency sweeping width (+/-Hz) for the AFC. This property is applied to all
the RX channels.

wBufferMax As Integer
~~~~~~~~~~~~~~~~
This property returns the maximum number of characters buffered in the TX circulate FIFO. The value of
MMVARI.ocx version 1.00 is 2048.

wBufferCount As Integer
~~~~~~~~~~~~~~~~~~
This property shows the number of characters remaining in the circulate TX buffer. The value cannot be
increased. Every MBCS character, such as Japanese Kanji, is treated one character.

Examples:
    ' Clear the buffer
    MMVARI.wBufferCount = 0

    ' Delete one character
    MMVARI.wBufferCount = MMVARI.wBufferCount - 1


wCollectType As Integer
~~~~~~~~~~~~~~~~~
This property selects the collecting scheme of the waveform data. When the property value has 1 or 2,
MMVARI generates OnDrawWave event at the end of wave draw.

    0 - collectNONE    No wave collection
    1 - collectSYNC    Decode signal collection
    2 - collectWAVE    Wave signal collection

wNotchFreq As Integer
~~~~~~~~~~~~~~~~~
This property specifies the notch filter frequency.

* MMVARI.ocx still has this property for the backward compatibility for version 1.02 or older versions.
MMVARI.ocx version 1.03 and later can have multiple notch frequencies. Use wNotches property, and
AddNotchFreq, FindNotchFreq and DeleteNotch methods.

wCWSpeed As Integer
~~~~~~~~~~~~~~~~
This property specifies the CWID speed. The valid value is 10 to 60.

wDiddleRTTY As Integer
~~~~~~~~~~~~~~~~~~
This property specifies the diddle code in the RTTY idle state.
    0 - LTR
    1 - BRK

wTxState As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~
This property shows the TX/RX status.

    0 - txstateRX        RX
    1 - txstateTX        TX
    2 - txstateREQRX        TX and waiting for idle
    3 - txstateWAIT        Switching to RX (flushing PCM data in the sound buffer)
    4 - txstateTONE        Transmitting a single tone

wMetricMFSK(nIndex As Integer, nPhase As Integer) As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : RX channel #
nPhase : 0 = RX metric level, 1 = Even phase metric level, 2 = Odd phase metric level

This property indicates the metric level (0 to 2047) of RX channel(nIndex). MFSK16 at 15.625 baud has
no odd phase.

wLang As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~
This property returns the default language ID.

wDefaultCharset As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property returns the default character set. Non-MBCS language returns ANSI_CHARSET.

wNumNotches As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~
This property has the number of eliminating frequencies the notch filter has.

wNotches(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
nIndex : index of eliminating frequencies

This property specifies the eliminating frequencies in Hz (nIndex) of the notch filters. The number of active
eliminating frequencies can be retrieved by referring to wNumNotches property, If nIndex is larger than
wNumNothes, a new eliminating frequency is added. Put0 to the property to deactivate the eliminating
frequency.

The following example sets three eliminating frequencies, that is, 1000, 1500, and 2000Hz, to the notch filter.
    MMVARI.wNotches(0) = 1000
    MMVARI.wNotches(1) = 1500
    MMVARI.wNotches(2) = 2000

The next example deactivates the first eliminating frequency.
    MMVARI.wNotches(0) = 0

* The value of this property is 0 if the specified nIndex frequency has no eliminating frequency.
* If an eliminating frequency is deleted, the frequency indexes will be changed. Use FindNotchFreq method
to retrieve the index of the particular frequency,.

wNotchTaps As Integer
~~~~~~~~~~~~~~~~~
This property is used to specify the number of taps of the notch filter. The default value is 128.
MMVARI.ocx automatically calibrates the filter shape by changing the number of taps with respect
to the sampling frequency. For example, wNotchTaps 128 with samplingfrequency 6000Hz actually
has 70 taps.

* The notch filter with larger number of taps gives a steeper shape factor, but it requires more CPU power.

==================
MMVARI control method
===================

Sub SetTX(wCmd As Integer)
~~~~~~~~~~~~~~~~~~~~~
This method is used to switch TX/RX. wCmd can be one of the following values:

    0=cmdtxRX    Switch to RX (same as bTX = False)
    1=cmdtxTX    Switch to TX (same as bTX = True)
    2=cmdtxREQRX    Switch to RX if idle (same as bReqRX = True)
    3=cmdtxCW    Switch to TX in the CW mode (MMVARI does not send an idle tone at the beginning and
end of the transmission)
    4=cmdtxTONE    Send an unmodulated tone

The following sample sequence sends a CW ID and returns to RX immediately.
    MMVARI.wBufferCount = 0    ' Clear buffer
    Call MMVARI.SendCWID("de JE3HHT")
    Call MMVARI.SetTX(cmdtxREQRX)
    Call MMVARI.SetTX(cmdtxCW)

Function GetSendText() As String
~~~~~~~~~~~~~~~~~~~~~~~~
This method returns all the characters in the TX buffer. The characters remain in the TX buffer.

    [Example]
    Dim strText As String
    strText = MMVARI.GetSendText()
    MMVARI.wBufferCount = 0    MMVARI.SendText ("<Insert>" & strText)

Function SendText(strText As String) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method appends String strText into the TX buffer and returns the number of characters in the TX buffer.
It can be called in OnGetTxChar event. See OnGetTxChar section for details.

Function SendChar(wChar As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method appends a character wChar into the TX buffer and returns the number of characters in the TX
buffer. It can be called in OnGetTxChar event. See OnGetTxChar section for details. wChar must be ANSI
or MBCS character code.

 Function SendCWID(strText As String) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method appends CW string strText into the TX buffer and returns the number of characters in the TX
buffer. It can be called in OnGetTxChar event. See OnGetTxChar section for details.

The following characters are used for special CW codes:

    @    AS
    :    SK (VA)
    ;    AR
    =    BT
    ]    KN

Function GetVariType(nIndex As Integer) As String
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method returns the VARICODE format of RX channel(nIndex).

Function PlayBack(wSec As Integer) As Boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method executes the sound playback for wSec seconds. The valid value of wSec is 0 to 60. If wSec is 0,
MMVARI stops the playback. If bPlayBack property is False, this method fails.

Sub SetClockAdjust(wTone As Integer, dblSampleFreq As Double)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wTone : Tone frequency of one second signal (Hz)
  dblSampleFreq : Sampling frequency of one second signal (Hz)

This method specifies the tuning parameters of the RX clock adjustment function.

Sub AdjustClock(wWidth As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~
  wWidth : Width of the scan window for clock adjustment

This method starts the clock adjustment. You have to provide a graphic window with wWidth width.
For more information, refer to the OnClockAdjust event section. To stop the clock adjustment, put 0 to
wWidth and call this method.

Sub AttachLongArray(pDist As Long, pSrc As Long, wSize As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pDist : Pointer to the destination array for copy
  pSrc : Pointer to the source array for copy
  wSize : Number of characters to copy
This method copies the array data. It works as the following VisualBasic6 code:

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source
As Any, ByVal Length As Long) Call CopyMemory(pDist, pSrc, wSize * 4)    'Windows API
CopyMemory()

Function CreateVaricodeList(strName As String) As Boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method creates the VARICODE list of file name strName.

Function ReadFFT(pArray As Long, wCount As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  pArray : Pointer to the array of FFT data
  wCount : Number of data

This method reads the FFT data asynchronously. The data is the same as the data given by OnDrawFFT
event. You can call this method in OnDrawFFT event. The method returns the number of data being read
if succeeded.

    Dim dwAmp(1023) As Long
    Call MMVARI.ReadFFT(dwAmp(0), 1024)

Sub AddNotchFreq(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : New eliminating frequency (Hz)

This method adds a new eliminating frequency to the notch filter. If the notch filter already has the same
frequency, the method does nothing.

    Call MMVARI.AddNotchFreq(1000)

Function FindNotchFreq(wFreq As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : Eliminating frequency to search (Hz)

This method searches for the specified frequency and returns the index if the frequency is found. If the
frequency is not found, it returns -1.

    Dim nIndex As Integer
    nIndex = MMVARI.FindNotchFreq(1000)
    If nIndex >= 0 Then
        Call MMVARI.DeleteNotch(nIndex)
    End If

Sub DeleteNotch(nIndex As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : Index of the eliminating frequency

This method deletes the specified eliminating frequency. If nIndex is -1, all the frequencies are deleted and
the notch filter is disengaged.

Function CreateCustomFilter(nTaps As Integer, pCoeff As Double) As Boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nTaps : Number of taps of the filter
  pCoeff : Coefficient data array (nTaps+1)

The method creates a custom RX filter. Using this method, the user can create a filter with arbitrary
parameters. The filter is of nTaps+1 FIR type. MMVARI.ocx uses this filter as a notch filter (the built-in
notch filter is automatically disengaged). The sampling frequency canbe referred to by
dblCustomSampleFreq property.

The number of coefficient data is nTaps+1. 64 tap filter, for example, requires 65 coefficient data. You
can make a steep filter by using a large number of taps, but you need more CPU power.

    Dim dblCoeff[64] As Double
    ' To do : Put coefficient data to dblCoeff(0 to 64)
    Call MMVARI.CreateCustomFilter(64, dblCoeff(0))

See DSP documents to calculate the coefficients for the filter. For creating a simple filter, MMVARI.ocx
provides CreateCustomFilterByKW and CreateCustomFilterbyIDFT methods.

* The filter is inserted just after the subsamping stage (sound front end), just before the FFT processing.
* Activating the built-in notch filter automatically disables the custom filter.

Sub DeleteCustomFilter()
~~~~~~~~~~~~~~~~~~
This method deletes the custom RX filter.

Function CreateCustomFilterByKW(nType As Integer, nTaps As Integer, dblFC1 As Double, dblFC2
As Double, wDB As Integer) As Boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nType : Filter type (0-LPF, 1-HPF, 2-BPF, 3-BEF)
  nTaps : Filter order (must be an even number)
  dblFC1 : First cut-off frequency in Hz
  dblFC2 : Second cut-off frequency in Hz
  wDB : Attenuation value (dB) for the eliminating frequency range

This method creates a custom RX filter. MMVARI calculates the impulse response using the given
parameters and calls CreateCustomFilter method. If wDB is 0, the filter coefficients are compliant to
the impulse response. LPF and HPF do not usedblFC2. If an odd number is assigned in nTaps, this
method fails.

    Dim dblF1 As Double
    Dim dblF2 As Double
    dblF1 = MMVARI.wRxCenter(0) - MMVARI.dblBandWidth(0)
    dblF2 = MMVARI.wRxCenter(0) + MMVARI.dblBandWidth(0)
    Call MMVARI.CreateCustomFilterByKW(2, 128, dblF1, dblF2, 60)

Function CreateCustomFilterByIDFT(nTaps As Integer, pFreqSamp As Double, wDB As Integer)
As Boolean
~~~~~~~~~
  nTaps : Filter order (must be an even number)
  pFreqSamp : Array of frequency-gain data (nTaps/2)
  wDB : Attenuation value (dB) for the eliminating frequency range

This method creates a custom RX filter using the frequency-gain data. MMVARI control calculates the
filter coefficients using the given frequency-gain data, and calls CreateCustomFilter method. If wDB is zero,
the filter coefficients are compliant to the impulseresponse. If an odd number is assigned in nTaps, the
method fails.

The frequency-gain data must be in the range of 0 to 1. The resolution must be dblCustomSampleFreq/nTaps.
MMVARI uses nTaps/2 data. The example below has array X and tone frequency Freq.

    X = Freq * nTaps / dblCustomSampleFreq
    Freq = X * dblCustomSampleFreq / nTaps

     [Example]
    Const NumTAPS = 132
    Dim dblFreqSamp(NumTAPS / 2) As Double
    Dim i As Integer
    For i = 0 To (NumTAPS / 2) Step 1
        dblFreqSamp(i) = 0#
    Next i
    dblFreqSamp(1000# * NumTAPS / MMVARI.dblCustomSampleFreq) = 1#
    Call MMVARI.CreateCustomFilterByIDFT(NumTAPS, dblFreqSamp(0), 60)

Function CalcCustomCharacteristic(pAmp As Double, pPhase As Double, wWidth As Integer, wMaxFreq
As Integer) As Boolean
~~~~~~~~~~~~~~~~~
  pAmp : Array for gain characteristics
  pPhase : Array for phase characteristics
  wWidth : Array size
  wMaxFreq : Maximum frequency (Hz)

This method calculates the frequency gain phase characteristics of the custom RX filter. If no custom filter is
created, the method fails. In the range of 0 to wMaxFreq (Hz), wMaxFreq/wWidth data are calculated.
Supposing X be an array and Freq be frequency, thefollowing equations are given.

    Freq = X * wMaxFreq / wWidth
    X = Freq * wWidth / wMaxFreq

The gain values are in the range of 0 to 1.0 for a standard filters with gain 1. The phase values are in the range
of -pi to +pi.

    Dim dblAmp(800-1) As Double
    Dim dblPhase(800-1) As Double
    Call MMVARI.CalcCustomCharacteristic(dblAmp(0), dblPhase(0), 800, 3000)
    ' To do : Draw a graph using dblAmp and dblPhase values.

================
MMVARI control event
================

OnGetTxChar(wChar As Integer)
~~~~~~~~~~~~~~~~~~~~~~~
  wChar : Character to send (ANSI or MBCS)

This event is generated just before the idle. Put a character (ANSI or MBCS) in wChar to send. If wChar is 0,
MMVARI sends an idle character.

    Private Sub MMVARI_OnGetTxChar(wChar As Integer)
        wChar = &H41    'Send A
    End Sub

You can call SendText method in the OnGetTxChar event handler. In that case, you cannot put any character
in wChar.

    Private Sub MMVARI_OnGetTxChar(wChar As Integer)
        Call MMVARI.SendText ("Hello")
    End Sub

* The sample container in this package has an example code of this event.

* The sound processor has a buffer, and therefore you will receive several OnGetTxChar events before the
sound buffer is fulfilled.

* To send a CW code, add 256 to the ASCII code and put it in wChar. For example, the CW code for 'A'
is 321. Alternatively, you can call SendCWID method.

OnRxChar(ByVal nIndex As Integer, ByVal strChar As String, ByVal wChar As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : RX channel #
  strChar : Received character (BSTR)
  wChar : Received character (ANSI or MBCS)

This event occurs when a character is received in RX channel(nIndex). You do not have to care about odd
delimiters even in MBCS. strChar and wChar are the same data expressed in different formats, so you could
use either of them as you like.

OnRxCarrier(nIndex As Integer, wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : RX channel #
  wFreq : RX frequency

This event occurs when the RX frequency is changed in RX channel(nIndex). This event also occurs
immediately after the RX channel is activated.

OnTxCarrier(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~
  wFreq : TX frequency

This event occurs when the TX frequency is changed. This event also occurs immediately after the MMVARI
control is activated.

OnDrawFFT(wCount As Integer, pArray As Long)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wCount : Number of effective FFT data points
  pArray : Array of FFT data

This event occurs at the update timing of the spectrum drawing. The number of effective FFT data points is
less than half of the number of FFT points (sFFTWidth). You can draw the spectrum or waterfall view
triggered by this event.

The relation between the FFT data position (X) and the tone frequency (Freq) is defined as follows.
    Freq = X * dblFFTSampleFreq / wFFTWidth
    X = Freq * wFFTWidth / dblFFTSampleFreq

MMVARI will perform sub-sampling in some sampling frequencies. Since the FFT sampling frequency during
TX can be affected by dblTxOffset, it is recommended you refer to dblFFTSampleFreq and wFFTWidth for
drawing the spectrum.

The value held in each cell of the array is 0 to 10900. When the FFT data is in the dB format, 10900
corresponds to 100dB.

Private Sub MMVARI_OnDrawFFT(ByVal wCount As Integer, pArray As Long)
    If wCount Then
        Dim fft(2047) As Long
        Call MMVARI.AttachLongArray(fft(0), pArray, wCount)
        ' To do : See array fft here and draw the spectrum or waterfall
    End If
End Sub

* From statistical perspective, this event occurs every wFFTWidth/dblFFTSampleFreq seconds. For
example, it occurs every 186msec for dblSampleFreq=11025Hz. During the sound playback, the events
occur more frequently.

* While MMVARI is trying to open a soundcard, it generates this event every one second (wCount=0).

* You can print the S/N ratio level using this event timing.

To use XMMVView and XMMVLvl controls, just call them with the object handle like the sample shown
below.

Private Sub MMVARI_OnDrawFFT(ByVal wCount As Integer, pArray As Long)
    Call XMMVView.Draw( MMVARI.dwHnalde )
    Call XMMVLvl.Draw( MMVARI.dwHandle, 0 )
End Sub

OnDrawWave(wCount As Integer, pArray1 As Long, pArray2 As Long)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wCount : Number of effective data
  pArray1 : Pointer to the array of replay clock signals and decoded data
  pArray2 : Pointer to the array of decoded data or wave data (PCM data)

This event occurs at the timing of waveform redraw. The number of effective data varies depending on
the mode and speed, but it never exceeds wWaveMax. You redraw the scope in your application using
this event timing.

Each data in pArray1 and pArray2 has value between -16384 and 16384. Replay clock signals and decoded
data always fit in this range. Wave data, on the other hand, are affected by the RX signal level. Therefore, you
might want to engage a simple AGC function.

    wCollectType = collectSYNC        pArray1 = replay clock signals, pArray2 = decoded signals
    wCollectType = collectWAVE        pArray1 = decoded signals, pArray2 = wave signals

To use XMMVView control, you just call it with the MMVARI object handle like the sample below.

Private Sub MMVARI_OnDrawWave(wCount As Integer, pArray1 As Long, pArray2 As Long)
    Call XMMVView.DrawWave( MMVARI.dwHnalde )
End Sub

OnPTT(wTX As Integer)
~~~~~~~~~~~~~~~~~
  wTX : 0 - PTT OFF, 1 - PTT ON

This event occurs when the PTT make/break is required. If you do not use the PTT controller in MMVARI,
you should make/break PTT using this event.

OnNET(bNET As Integer)
~~~~~~~~~~~~~~~~~~~
  bNET : NET state

This event occurs when the NET state is changed.

OnTxState(wState As Integer)
~~~~~~~~~~~~~~~~~~~~~
This event occurs when the TX/RX state is changed. wState is defined as follows:
    0=txstateRX    Switched to RX
    1=txstateTX    Switched to TX
    2=txstateREQRX    Switched to idle
    3=txstateWAIT    Switching to RX (flushing the PCM data in the TX sound buffer)
    4=txstateTONE    Switched to single TX tone

OnMode(nIndex As Integer, mIndex As Integer, strMode As String)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : RX channel #
  mIndex : Mode number (0-)
  strMode : Mode name

This event occurs when the mode of RX channel(nIndex) is changed. It also occurs just after the RX channel
is activated.

OnSpeed(nIndex As Integer, dblSpeed As Double)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : RX channel #
  dblSpeed : Speed (Baud)

This event occurs when the speed of RX channel(nIndex) is changed. It also occurs just after the RX channel
is activated.

OnTiming(nIndex As Integer, dwTiming As Long, wUnit As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  nIndex : RX channel #
  dwTiming : Timing value
  wUnit : Unit of timing value (0=PPM, 1=ms multiplied by 100)
This event occurs when the RX clock timing is changed in RX chennel(nIndex). In the RTTY mode, the unit
of the timing value is ms multiplied by 100. 0 means MMVARI is calculating the timing. In all the modes other
than RTTY, the unit of the timing value isppm.

OnPlayBack(wStat As Integer)
~~~~~~~~~~~~~~~~~~~~~
  wStat : Playback status: 0=end, 1=start

This event occurs when the sound playback is started or ended.

OnClockAdjust(pArray As Long)
~~~~~~~~~~~~~~~~~~~~~~~
pArray : Pointer to the array of level values (the number of values is defined by wWidth of AdjustClock
method)

This event occurs when MMVARI is ready for offering one scan like data every one second. You read the
data in pArray and converts to the brightness or color to draw the graphic, just like FAX and SSTV. The
level value in each cell is in the range of 0 to16384, but it varies depending on RX signal level, condx, and
tuning. You should do fine tuning of the graphic drawing by receivingWWV tick sound. You may want to
implement a simple AGC in your code.

The next sample is a code that draws a picture with width 800 pixels.

Call SetClockAdjust(1000, 11025.0)
Call AdjustClock(800)
    |

Private Sub MMVARI_OnClockAdjust(pArray As Long)
    Dim level(800-1) As Long
    Call MMVARI.AttachLongArray(level(0), pArray, 800)
    'To do: Draw one line in the graphic window
End Sub

OnError(nErrorCode As Integer)
~~~~~~~~~~~~~~~~~~~~~~
This event occurs when MMVARI detects an error. nErrorCode is:

    1=errorLostRX    Lost RX sound
    2=errorLostTX    Lost TX sound
    3=errorSoundOpen    Failed to open the soundcard
    4=errorComOpen    Failed to open the COM port

===========================
Multiple instances of MMVARI control
===========================

You can make two or more MMVARI instances at the same time. For example, if you place two or more
MMVARI control using the form designer, each MMVARI control works independently. This situation is
just like two or more programs that use thesoundcard running simultaneously, and therefore please pay
attention to the following points:

1) Some conventional sound drivers will not allow two or more programs to access the sound card
simultaneously. In this case, you will see only one MMVARI control successfully opens the sound card and
the others return an error. You might want to specifydifferent sound IDs for different MMVARI instances.

2) The same COM port cannot be shared. You will have to assign a different COM port to each instance.
If you do not use the MMVARI PTT control, you have no problem.

===================
About XMMVView control
===================

XMMVView control is a supplemental control for displaying the spectrum and waterfall. It has a fixed skin,
and therefore I would not recommend it for serious use. I trust, however, that it is useful for experimental use.

XMMVView control is supposed to use with VisualBasic6 form designer. There is no limit in the number of
controls to allocate. For example, if you want to place the spectrum and waterfall on the window, you could
place two XMMVView control. The small waterfall for subchannels can be allocated in each subwindow.

* In response to mouse left button click, XMMVView control automatically sends a message to MMVARI
control. If you want to disable this function, set False to bAttachMouse property.

=====================
XMMVView control property
=====================

wType As Integer
~~~~~~~~~~~~~
This property defines the display content.
    0=viewtypeFFT        Specturm
    1=viewtypeWATER        Waterfall
    2=viewtypeWAVE        Waveform
    3=viewtypeFREQERR    AFC level meter
    4=viewtypeSMALLWATER    Waterfall without scale

bFollowRxFreq As Boolean
~~~~~~~~~~~~~~~~~~~
If True, XMMVView automatically adjust wBaseFreq so that the main channel frequency is always visible in
the scope.

bAttachMouse As Boolean
~~~~~~~~~~~~~~~~~~
If True, XMMVView automatically sends a message to MMVARI in response to left mouse click. If False,
the application is in charge of all the mouse related events.

bLSB As Boolean
~~~~~~~~~~~~
Set True to this property if the receiver is in the LSB mode. It is not effective if dwFreqHz is 0.

bWaterAGC As Boolean
~~~~~~~~~~~~~~~~~
If True, the AGC is engaged in the waterfall display.


bShowSync As Boolean
~~~~~~~~~~~~~~~~~
If True, XMMVView shows SYNC status at the top left corner of the window.

bHighQuality As Boolean
~~~~~~~~~~~~~~~~~
If True, the spectrum is displayed in the fine mode. It is useful for small wWidthFreq.

bShowErrorMsg As Boolean
~~~~~~~~~~~~~~~~~~~~
If True, XMMVView displays the error information (strErroMsg) at the bottom right corner of the window.

bWindowsMouseEvent As Boolean
~~~~~~~~~~~~~~~~~~~~~~~~~
If True, XMMVView sends a message to the application in response to a Windows mouse event. The mouse
event is defined by the name of OnWindowsXXXX. The cursor position included in the message is the pixel
position in the control client region. UsewPixelXW and wPixelYW for the conversion.

bShowSubChannelMarkers As Boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~
If True, XMMVView displays the subchannel marker. The default value is True.

bShowNotchMarkers As Boolean
~~~~~~~~~~~~~~~~~~~~~~~~
If True XMMVView displays the notch marker. The default value is True.

ColorFFT(nIndex As Integer) As OLE_COLOR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property defines the colors of the items in the spectrum.

    nIndex    Item
    0    Background color
    1    Signal color
    2    Character color
    3    Scale line color
    4    RX cursor color
    5    TX cursor color

ColorWater(nIndex As Integer) As OLE_COLOR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property defines the colors of the items in the waterfall.

    nIndex    Item
    0    Background color
    1    Signal strength 0 color
    2    Character color
    3    Marker frame color
    4    RX marker color
    5    TX marker color
    6    Signal strength 1 color
    7    Signal strength 2 color
    8    Signal strength 3 color
    9    Signal strength 4 color
    10    Signal strength 5 color
    11    Signal strength 6 color

XMMVView automatically generates 256-level colors in WaterPallete property by referring to Signal strength
0 to 6 colors and wWaterLevel property.

ColorWave(nIndex As Integer) As OLE_COLOR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property defines the waveform colors.
    nIndex    Item
    0    Background color
    1    Signal color
    2    Character color
    3    Horizontal scale line color

ColorFreqErr(nIndex As Integer) As OLE_COLOR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property defines the colors of the items in the AFC level meter.
    nIndex    Item
    0    Background color
    1    Level color (AFC off)
    2    Level color (AFC on)
    3    Level color (Overflow)
    4    Center line color

WaterPalette(nIndex As Integer) As OLE_COLOR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property defines the waterfall pallet specified by nIndex, which is in the range of 0 to 255. XMMVView
control converts the FFT signals to 256 levels and defines the colors by referring to this palette.

When you set a value to ColorWater or wWaterLevel property, XMMVView automatically updates
WaterPalette property. In case you explicitly use the palette, therefore, you should not set a value directly
to ColorWater or wWaterLevel property.

dwFreqHz As Long
~~~~~~~~~~~~~~
This property specifies the transceiver frequency. To put 14.073MHz in the transceiver, write 14073000 to
this property. If dwFreqHz is 0, XMMVView displays the tone frequency on the scale. To display the
transceiver frequency on the scale, you should setappropriate values to dwFreqHz and bLSB properties.

wBaseFreq As Integer
~~~~~~~~~~~~~~~
This property specifies the left end frequency (Hz) of the spectrum or waterfall.

wWidthFreq As Integer
~~~~~~~~~~~~~~~~
This property specifies the width of the frequency (Hz) displayed on the spectrum or waterfall.

wWaterLevel(nIndex As Integer) As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the signal level (0 - 255) of nIndex. XMMVView generates 256-level WaterPalette
property by referring to wWaterLevel and WaterColor properties. The default values are:

    0 = 10
    1 = 60
    2 = 134
    3 = 192
    4 = 220
    5 = 240

wWaterNoise As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~
This property shows the noise floor (dB) during the waterfall drawing. During RX, XMMVView automatically
calculates the noise floor, wWaterNoiseH As Integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the upper limit (dB) of the noise floor. The default value is 65.

wWaterNoiseL As Integer
~~~~~~~~~~~~~~~~~~
This property specifies the lower limit (dB) of the nose floor. The default value is 35.

wCursorFreq As Integer
~~~~~~~~~~~~~~~~~
This property specifies the frequency of the tone cursor displayed on the waterfall. If 0, no cursor is displayed.


wPixelXW As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the control width in pixel.

wPixelYW As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the control height in pixel.

wMouseChannel As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property holds the subchannel number (1~) when the mouse cursor is on the subchannel indicator.

wMouseNotch As Integer (ReadOnly)
~~~~~~~~~~~~~~~~~~~~~~~~~~
This property holds the notch number (index+1) when the mouse cursor is on the notch indicator.

strMsg(nIndex As Integer) As String
~~~~~~~~~~~~~~~~~~~~~~~~~
This property draws a message in the view. The position is defined by nIndex.

    0    Center
    1    Upper left
    2    Upper right
    3    Lower right
    4    Lower left

* If you want to draw a message in the localized language, you must set the font property of the control.

strErrorMsg(nIndex As Integer) As String
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the error message displayed in the view. nIndex specifies the error reason as follows:

    1=errorLostRX    RX sound was lost
    2=errorLostTX    TX sound was lost
    3=errorSoundOpen    Soundcard could not be opened
    4=errorComOpen    COM port could not be opened

* If you want to use the localized language, you must set the font property to the language.

strSubChannels(nIndex As Integer) As String
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This property specifies the subchannel marker string.
  nIndex : subchannel number starting with 1
The default string is the subchannel number in String.

====================
XMMVView control method
====================

Sub Draw(dwHandle As Long)
~~~~~~~~~~~~~~~~~~~~~~
This method draws the spectrum or waterfall. dwHandle is the object handle of theMMVARI control.
dwHandle must be retrieved through MMVARI.dwHandle.

XMMVView control draws the spectrum or waterfall by referring to the FFT data (sampling frequency,
number of data points, and metrics), TX/RX frequencies, and the notch frequency.

If this method is called at least once, XMMVView sends requests, such as frequency change, to MMVARI
in response to mouse left click.

Sub DrawWave(dwHandle As Long)
~~~~~~~~~~~~~~~~~~~~~~~~~
This method draws the waveform. dwHandle is the object handle of the MMVARI control. dwHandle must
be retrieved through MMVARI.dwHandle. XMMVView draw the waveform by referring to the waveform
data (number of points and metrics).

Sub DrawSmallWater(dwHandle As Long, nIndex As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method draws the small waterfall of RX channel(nIndex). dwHandle is the object handle of the MMVARI
control. XMMVView draws the waterfall by referring to the FFT data (sampling frequency, number of data
points, and metrics) and the RX frequency.

If this method is called at least once, XMMVView sends requests, such as frequency change, to MMVARI
in response to the mouse left click.

* This drawing is supposed to be used in the status bar of the subchannel.
* This drawing automatically adjusts the wBaseFreq so that the RX frequency is always visible.

Sub DrawFreqErr(dwHandle As Long, nIndex As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This method draws the AFC level meter of RX channel(nIndex). dwHandle is the object handle of the
MMVARI control. XMMVView draws the meter by referring to MMVARI's dblFreqError.

Sub ClearWater()
~~~~~~~~~~~~
This method clears the waterfall.

==================
XMMVView control event
==================

OnLMouseDown(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : Tone frequency (Hz)
This event occurs when the mouse left button is depressed on the spectrum or waterfall.

OnLMouseUp(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : Tone frequency (Hz)

This event occurs when the mouse left button is released on the spectrum or waterfall.

OnLMouseMove(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : Tone frequency (Hz)

This event occurs when the mouse is moved over the spectrum or waterfall with the left button depressed.

OnRMouseDown(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : Tone frequency (Hz)

This event occurs when the mouse right button is depressed on the spectrum or waterfall.

OnRMouseUp(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : Tone frequency (Hz)

This event occurs when the mouse right button is released on the spectrum or waterfall.

OnRMouseMove(wFreq As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~
  wFreq : Tone frequency (Hz)

This event occurs when the mouse is moved over the spectrum or waterfall with the right button depressed.

OnWindowsLMouseDown(wX As Integer, wY As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wX : Pixel position (X)
  wY : Pixel position (Y)

This event occurs when the Windows mouse event, WM_LBUTTONDOWN, is detected.

OnWindowsLMouseUp(wX As Integer, wY As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wX : Pixel position (X)
  wY : Pixel position (Y)

This event occurs when the windows mouse event, WM_LBUTTONUP, is detected.

OnWindowsRMouseDown(wX As Integer, wY As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wX : Pixel position (X)
  wY : Pixel position (Y)

This event occurs when the windows mouse event, WM_RBUTTONDOWN, is detected.

OnWindowsRMouseUp(wX As Integer, wY As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wX : Pixel position (X)
  wY : Pixel position (Y)

This event occurs when the windows mouse event, WM_RBUTTONUP, is detected.

OnWindowsMouseMove(dwFlag As Long, wX As Integer, wY As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dwFlag : Button status (see a Windows API document)
  wX : Pixel position (X)
  wY : Pixel position (Y)

This event occurs when the Windows mouse event, WM_MOUSEMOVE, is detected.

==================
About XMMVLvl control
==================
XMMVLvl is a supplemental control that draws a signal level meter. It is supposed to be located on the
form using the VisualBasic6 form designer. There is no limit in the number of XMMVLvl control objects
to allocate on the form. To support two or more RXchannels, allocate the same number of XMMVLvl
controls.

===================
XMMVLvl control property
===================

BackColor As OLE_COLOR
~~~~~~~~~~~~~~~~~~~~~
This property defines the background color.

MaxLevel As Integer
~~~~~~~~~~~~~~
This property specifies the maximum S/N ratio multiplied by 100 (or MFSK metrics). The default value is
2048 (=20.48dB).

OffColor As OLE_COLOR
~~~~~~~~~~~~~~~~~~~
This property defines the signal color when the squelch is closed.

OnColor As OLE_COLOR
~~~~~~~~~~~~~~~~~~~
This property defines the signal color when the squelch is opened.

TxColor As OLE_COLOR
~~~~~~~~~~~~~~~~~~~
This property defines the signal color for TX.

===================
XMMVLvl control method
===================

Sub Draw(dwHandle As Long, nIndex As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  dwHandle : Object handle of the MMVARI control
  nIndex : RX channel number to draw

This method draws the level meter. dwHandle is the object handle of MMVARI control. dwHandle is the
object handle of MMVARI control. Use the value of MMVARI.dwHandle. XMMVLvl control draws the
meter by referring to the signal and squelch levels of theRX channel.

After this method is called at least once, XMMVLvl sends the squelch level change request to MMVARI in
response to the mouse left click.

Sub DrawCustom(wSig As Integer, wSq As Integer, fOver As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  wSig: Signal level
  wSq: Squelch level
  fOver: Overflow

This method draws a level meter. You can use this function even if you do not instantiate an MMVARI control.

=================
XMMVLvl control event
=================

OnLMouseDown(level As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~
  level : Signal level (dB * 100)

This event occurs when the mouse left button is pressed.

OnLMouseUp(level As Integer)
~~~~~~~~~~~~~~~~~~~~~~
  level : Signal level (dB * 100)

This event occurs when the mouse left button is released.

OnLMouseMove(level As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~
  level : Signal level (dB * 100)

This event occurs when the mouse is moved with the left button pressed.

OnRMouseDown(level As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~
  level : Signal level (dB * 100)

This event occurs when the mouse right button is depressed.

OnRMouseUp(level As Integer)
~~~~~~~~~~~~~~~~~~~~~~
  level : Signal level (dB * 100)

This event occurs when the mouse right button is released.

OnRMouseMove(level As Integer)
~~~~~~~~~~~~~~~~~~~~~~~~
  level : Signal level (dB * 100)

This event occurs when the mouse is moved with the right button pressed.

===========
Closing remarks
===========

As I am not familiar with VisualBasic6, it took much more time for me to read tons of the manuals and make
a sample container than to make this ActiveX. It is my great pleasure if this sample code is helpful for your
programming.

MMVARI.ocx is freeware for amateur ham radio. You can freely use, modify, and distribute this package
for commercial and non-commercial usage. You do not have to inform me anything about the license.

* If you implement the mfsk mode in a commercial program, you will have to get the permission from M. Greenman ZL1BPU andNino Porcino IZ8BLY.

Good luck and 73,
Mako

 


Please take the time to read the terms of use!

See the Programmer Downloads page to obtain the necessary files.