        Mono / Stereo / Differential Manipulation Filter FtMono 1.02
        ------------------------------------------------------------
                        for VSOS 3.66 or higher
                       2023-02-23  VLSI Solution




The FtMono filter drivers offers mono, stereo and channel inversion functions.
Amongst other things, they makes it possible to create systems with a
differential LR output. To use the package, copy the .dl3 files to your
VS1005 system disk SYS/ folder, then follow the instructions in this manual.
The mono filters can be accessed both from C programs using ioctl() calls,
or from the VSOS Shell command line.

The package consists of the following programs:

Name    Description
FtOMono Mono manipulation driver that connects to stdaudioout
FtIMono Mono manipulation driver that connects to stdaudioin
SetMono User program to set and display parameters for the mono manipulator

The filter is very lightweight. The size of the driver is less than 300
instruction words, and the worst case CPU usage is approximately 0.2 MIPS
at 48 kHz, or 0.4 MIPS at 96 kHz, plus call overheads.

Note:
If data is 32 bits, only 16 most significant bits are handled.

Note:
The source code is the same for both FtOMono and FtIMono. For
FtOMono, the project defines the preprocessor symbol USE_STDAUDIOOUT,
and for FtIMono, USE_STDAUDIOIN is defined. Then, code is compiled
conditionally.




Starting FtOMono.DL3 in config.txt and setting it to output a
differential stereo signal:
# Starts mono filter to stdaudioout
FtOMono
# Set LR differential mode inverting right channel
RUN SetMono lr ir

Note: FtOMono is loaded and stays in memory. Because SetMono doesn't need to
stay in memory, it is started with the RUN command.


Starting FtOMono.dl3 from the VSOS Shell command line, setting it to
differential mode inverting the right channel, and checking the status
of the audio output:
S:>driver +FtOMono
S:>SetMono lr ir
S:>SetMono
Mono flags: lr ir
S:>auoutput
stdaudioout:     0x2218, FtOMono::audioFile=0x0843(2115)
  ->Identify():  0x2828, auodac::Identify returns "AUODAC"
  ->op:          0x2213, FtOMono::audioFileOps=0x0000(0)
    ->Ioctl():   0x3077, FtOMono::AudioIoctl
    ->Write():   0x30c2, FtOMono::AudioWrite
Sample rate:     48000
Bits per sample: 16
Buffer size:     4096 16-bit words (2048 16-bit stereo samples)
Buffer fill:     4 16-bit words (2 16-bit stereo samples)
Sample counter:  1828388
Underflows:      1664073
Volume:          +0.0 dB of maximum level

Starting FtIMono.dl3 from the VSOS Shell command line, setting it to
differential mode inverting the right channel, and checking the status
of the audio input:
S:>driver +FtIMono
S:>SetMono -i lr ir
S:>SetMono -i
Mono flags: lr ir
S:>AuInput
stdaudioin:      0x23d4, FtIMono::audioFile=0x0823(2083)
  ->Identify():  0x2a68, auiadc::Identify returns "AUIADC"
  ->op:          0x23cf, FtIMono::audioFileOps=0x0000(0)
    ->Ioctl():   0x30fc, FtIMono::AudioIoctl
    ->Read():    0x3147, FtIMono::AudioRead
Sample rate:     48000
Bits per sample: 16
Buffer size:     512 16-bit words (256 16-bit stereo samples)
Buffer fill:     508 16-bit words (254 16-bit stereo samples)
Sample counter:  2907073
Overflows:       2906769


Unloading the FtOMono.dl3 driver using the VSOS Shell:
S:>driver -FtOMono

Unloading the FtIMono.dl3 driver using the VSOS Shell:
S:>driver -FtIMono


Starting FtOMono.dl3 using C code: // Change name as necessary #define
  LIB_NAME "ftomono"

  u_int16 *monoLib = NULL;
  FILE *monoFP = NULL;

  monoLib = LoadLibrary(LIB_NAME);
  if (!monoLib) {
    printf("Cannot load " LIB_NAME ".dl3 library\n");
    goto finally;
  }
  monoFP = stdaudioout;

Note that if you have started FtOMono/FtIMono from config.txt, you don't
need to open it from your software, but instead you can directly send
ioctl() calls to stdaudioout/stdaudioin.



Closing the driver:
  finally:
  if (monoLib) {
    DropLibrary(monoLib);
    monoLib = NULL;
  }




Running SetMono from the VSOS Shell to set mono mode and invert left channel:
S:>setmono mono il        (for FtOMono)
or
S:>setmono -i mono il     (for FtIMono)

To read the status of the filter:
S:>setmono                (for FtOMono)
Mono flags: mono il
or
S:>setmono -i             (for FtIMono)
Mono flags: mono il

For more options:
S:>setmono -h




Data structures:

If using an earlier version than VSOS 3.65, the following data structures
are not yet in aucommon.h, so you need to add this to your source code:

#ifndef IOCTL_AUDIO_GET_MONO

#define IOCTL_AUDIO_GET_MONO		320
#define IOCTL_AUDIO_SET_MONO		321

#define MONO_MODE_LR	0x0000
#define MONO_MODE_LL	0x0001
#define MONO_MODE_RR	0x0002
#define MONO_MODE_RL	0x0003
#define MONO_MODE_MONO	0x0004
#define MONO_MODE_MASK	0x0007
#define MONO_INV_L	0x0008
#define MONO_INV_R	0x0010

#endif /* !IOCTL_AUDIO_GET_MONO */




IOCTL Controls:
  All ioctl controls except those listed here are forwarded to the underlying
  audio driver.

  Read current mono filter flags:
    s_int16 n = ioctl(monoFP, IOCTL_AUDIO_GET_MONO, NULL);
    if (n<0) {
      printf("Fail\n);
    }

  Set filter to mono mode and inverting left output for differential signal:
    if (ioctl(fp, IOCTL_AUDIO_SET_MONO,
       (void *)(MONO_MODE_MONO|MONO_INV_L)) != S_OK) {
      printf("Fail\n");
    }



License:
This code may be used freely in any product containing one or more ICs
by VLSI Solution.


Disclaimer:
No guarantee is given for the usability of this code.


History:
2023-02-23 HH 1.02  Corrected return value for AudioRead(), fixed returning
                    stdaudioin for input driver FtIMono.dl3
2021-12-14 HH 1.01  Added 32-bit support and input driver FtIMono.dl3
2021-12-13 HH 1.00  First release for stdaudioout
