
              BFXSPI - VS1005 SPI v0.01
              -------------------------
                for VSOS 3.67 or higher
               2023-07-14  VLSI Solution



The BFXSPI drivers offer buffered SPI operataions for VS1005.

To test this driver pair you need current as of 2023-07-14 versions of:
audiodec.dl3
BfISpiS.dl3
BfOSpiM.dl3

For this demonstration two VS1005 Developer Boards are needed.
They will be called Board 1 and Board 2. Our intent is to send
encoded audio data from Board 1 to Board 2.

1) Copy all .dl3 files in this package to the SYS folder of both
Board 1 and Board 2.

2) Connect two VS1005 Developer Boards B1 and B2 to each other.
Alternatively you may use VS1005 Break-out Boards but then pin names
are slightly different. Connect the following pins together:

Board 1    GND <-> Board 2    GND
Board 1 X2 SC1 <-> Board 2 X2 SC1 (SPI 1 Clock)
Board 1 X2 MO1 <-> Board 2 X2 MO1 (SPI 1 MOSI)
Board 1 X2 MI1 <-> Board 2 X2 MI1 (SPI 1 MISO)
Board 1 X2 XC1 <-> Board 2 X2 XC1 (SPI 1 xChip Select)



3) Prepare receiver Board 2
---------------------------

Connect headphones to Board 2 Headphones connector or an amplifier to
the Line Out connector.

Boot up Board 2. After boot-up, run the following commands:

S:>driver +bfispis p
CALL RESTART FOR 0x23f1
S:>::
Currently installed system devices are:
- D:  476G SD/SD Card, handled by FAT.
- P:        BfISpiS.
- S: 1920K SPI Flash c814, handled by FAT.
S:>playfile p:
Playing 'BfISpiS'


4) Prepare transmitter Board 1
------------------------------

We are going to use the microphones provided on VS1005 Developer Board.
If you are using the VS1005 Break-Out Board, you will need some other
way to feed audio to its analog inputs.

Boot up Board 1. After boot-up, run the following commands. Note that
if you didn't have an audio input driver loaded, the first command
will give an error message. This is not a problem.

S:>driver -auiadc
S:>driver +auiadc s mic1 mic2 dec6 8000
  Input 0xa200  Rate 8000S:>driver +bfospim p
S:>rec +f -b32 -cm -fm -r8000 p:
Recording MP3: 8000 Hz mono at 32 kbit/s
~050a'p:
Open(c92, , wb)
~030a=1

You should now see a time counter running on both boards, and you
should hear the sound of the microphones on Board 1 coming from the
headphones on Board 2. Note that the sound may be faint in volume,
so to test that the system works, you may gnetly touch the microphones
on Board 1.


5) Testing other MP3 encoding parameters

To test other parameters, you may push 'q' or Ctrl-C on Board 1 to
stop encoding MP3. Then, enter for instance the following command
for MP3 encoding with different parameters:
S:>rec +f -b64 -cm -fm -r32000 p:
Recording MP3: 32000 Hz mono at 64 kbit/s

For this demonstration, sample rates 8 kHz, 16 kHz, and 32 kHz are
suppported. Bit-rates up to 64 kbit/s are supported.

MP3 is a format intended for streaming. As such it is resilient to
errors. You may disconnect and reconnect any of the SPI wires and
playback will resume.


6) Testing Opus.

To test Opus, first reset both Board 1 and Board 2. Then enter the
same commands for Board 2 as shown earlier in (3). Then do the same
for Board 1 as shown in (4) except the recording command is as
follows:

S:>rec +f -b8 -cm -fo -r8000 p:
IMEM: only 2708w free!
IMEM: only 742w free!
Recording Opus: 8000 Hz mono at 8 kbit/s

At this early demonstration stage, playing back Opus format will
cause a short burst of noise, then audio starts playing.

Opus encoding is supported at 8 and 16 kHz.




FROM THIS ON THIS DOCUMENTATION IS NOT UPDATED YET! TEXT BELOW
IS IRRELEVANT FOR THIS DRIVER.



There following drivers are available:

Name          Features   Notes and Description

AUOSPDA.DL3        AOut  See note  1
  Driver automatically converts the output of the analog audio output driver
  AUODAC.DL3 to exactly 48 or 96 kHz, then sends that out to S/PDIF.

AUISPD.DL3    In         See notes 2, 3, 5
  S/PDIF input driver, capable of receiving approximately 44.1, 48, 88.2,
  and 96 kHz.

AUXSPD.DL3    In +  Out  See notes 2, 3, 5, 8
  S/PDIF input/output driver, capable of approximately 44.1, 48, 88.2, and
  96 kHz sample rates. Output is automatically synchronized with input.

AUXSPD48.DL3  In +  Out  See notes 2, 4, 6, 8
  S/PDIF input/output driver, capable of approximately 48, and 96 kHz sample
  rates. Output is automatically synchronized with input.
  Uses slightly less memory than AUXSPD.DL3.

AUOSP48S.DL3        Out  See notes 2, 4, 7, 9
  S/PDIF output driver that synchronizes S/PDIF output sample rate with the
  input sample rate, which must be approximately 48 kHz.
  Example use case: In conjunction with I2S input slave driver AUII2SS.DL3
  when it is known that the I2S driver's nominal input sample rate is always
  approximately 48 kHz.

AUOSPD48.DL3        Out  See notes 7
  S/PDIF output driver that supports exactly 48 kHz.

Note 1: This driver supports 48 and 96 kHz output sample rates. An
  automatic hardware sample rate conversion is done from the current
  playback sample rate. For best audio quality, the output sample rate
  should at least as high as the highest playback sample rate.

Note 2: This driver is incompatible with any USB drivers and
  FM Radio receiver software.

Note 3: This driver automatically sets the VSDSP core clock to approximately
  61.440 or 56.446 MHz.

Note 4: This driver automatically sets the VSDSP core clock to approximately
  61.440 MHz.

Note 5: This driver supports 44.1, 48, 88.2, and 96 kHz sample rates.

Note 6: This driver supports 48 and 96 kHz sample rates.

Note 7: This driver supports 48 kHz sample rate.

Note 8: The input and output always operate at the same sample rate.
This driver automatically synchronizes its input and output.
The synchronization driver AUXSYNCS.DL3 is not needed.

Note 9: Output is automatically synchronized with stdaudioinput, which
must be approximately 48 kHz. The synchronization driver AUXSYNCS.DL3 is not
needed.


Features Legend:
In     - Digital DSP Input
Out    - Digital DSP Output
AOut   - Automatic DAC SRC Duplication Output

The Automatic DAC SRC Duplication Output feature duplicates the data
that is sent through the DAC_SRC sample rate upconverter for analog
sound output. For details, see the audio path going through the SRC_CF
component block in Figure "VS1005g playback (DA) audio paths" in the
VS1005g datasheet. Note that for acceptable audio quality, the S/PDIF
sample rate must be at least as high as the highest sample rate that is
played back.


Example config.txt files:

-------- example config.txt #1 ----------
# Start DAC driver and make it stdaudioout
AUODAC s
# Start S/PDIF auto driver:
# - auto DAC copy mode
# - default samplerate (96000)
# - no auto volume control
AUOSPDA
-------- example config.txt #2 ----------
# Start DAC driver and make it stdaudioout
AUODAC s
# Start S/PDIF auto driver:
# - auto DAC copy mode
# - 48000 Hz (alternative: 96000)
# - auto volume control (copies volume control of stdaudioout)
AUOSPDA 48000 v
-------- example config.txt #3 ----------
# Start DAC driver and make it stdaudioout
AUODAC s
# Start S/PDIF input driver and make it staudioin
AUISPD s
# Start Input/output synchronization driver:
# it will keep DAC in sync with S/PDIF input
AUXSYNCS
# Start stdaudioin to stdaudioout audio copy driver
AUXPLAY
-------- example config.txt #4 ----------
# Start S/PDIF In/Out driver and make it staudioin/stdaudioout
AUXSPD s
# Start stdaudioin to stdaudioout audio copy driver, so now S/PDIF input
# is copied to S/PDIF output
AUXPLAY
-------- examples end -------------------

Example #2 from the VSOS Shell command line:
S:>driver +auodac s
S:>driver auospda 48000 v

Example #3 from the VSOS Shell command line:
S:>driver +auodac s
S:>driver +auispd s
S:>driver +auxsyncs
S:>driver +auxplay




For applications that want to specifically access the S/PDIF driver,
the following functions are available.

Opening the Driver:
  // Change name as necessary
  #define LIB_NAME "auospda"

  u_int16 *lib = NULL;
  FILE *fp = NULL;

  lib = LoadLibrary(LIB_NAME);
  if (!lib) {
    printf("Cannot load " LIB_NAME ".DL3 library\n");
    goto finally;
  }
  /* Open */
  fp = (FILE *)RunLoadedFunction(lib, ENTRY_3, 0);
  if (!fp) {
    printf("Cannot open " LIB_NAME ".DL3 audio file\n");
    goto finally;
  }




Closing the driver:
  finally:
  if (fp) {
    /* Close file */
    RunLoadedFunction(lib, ENTRY_4, (s_int16)fp);
    fp = NULL;
  }
  if (lib) {
    DropLibrary(lib);
    lib = NULL;
  }




Fractional sample rate:
  Sample rate is presented as a 32-bit integer. However, particularly
  when streaming, there sometimes is a need to present sample rates
  at greater accuracy. To do this, when setting a sample rate, bits 30:24
  may used presented to present a fractional sample rate in 1/128 Hz
  increments. This is compatible with all VSOS audio drivers: those who
  can't handle fractional sample rates will ignore these bits.

  This driver ignores fractional sample rate information.

  Examples:
  - 44100       Hz is 0x0000ac44.
  - 44100 1/128 Hz is 0x0100ac44.
  - 44100.5     Hz is 0x4000ac44.




IOCTL Controls:
  Restart driver. Normally this needs never be done.
  Example:
    ioctl(fp, IOCTL_RESTART, NULL);

  Set sample rate and number of bits (bits are ignored).
  - labs(rateBits) = sampleRate
  Example:
    /* Set 48 kHz with 24 bits */
    s_int32 rateBits = -48000; /* Or, rateBits = 48000; */
    if (ioctl(fp, IOCTL_AUDIO_SET_RATE_AND_BITS, (char *)(&rateBits))) {
      printf("Couldn't set sample rate and bits\n");
    }

  Get sample rate.
  Example:
    s_int32 sampleRate;
    if (ioctl(fp, IOCTL_AUDIO_GET_ORATE, (char *)(&sampleRate))) {
      printf("Couldn't get sample rate\n");
    }

  Set sample rate.
  Example:
    s_int32 sampleRate = 96000;
    if (ioctl(fp, IOCTL_AUDIO_SET_ORATE, (char *)(&sampleRate))) {
      printf("Couldn't set sample rate\n");
    }

  Get volume.
  Volume is a number between 0 - 511 where 256 is full-scale, and each
  successive number represents a volume gain step of -0.5 dB.
  See table below:
  -   0 = +128.0 dB: Insane amplification (driver saturates to +24.0 dB)
  - 208 =  +24.0 dB: Highest amplification supported by this driver
  - 255 =   +0.5 dB: Slight gain
  - 256 =    0.0 dB: Full scale, neutral volume
  - 257 =   -0.5 dB: 
  - 510 = -127.0 dB: Total silence (with this driver, since about -74 dB)
  - 511 = -127.5 dB: Total silence, may shut down output (not implemented)
  Example:
    volume = ioctl(fp, IOCTL_AUDIO_GET_VOLUME, NULL);

  Set volume.
    Scale for volume is the same as for IOCTL_AUDIO_GET_VOLUME.
  Example:
    /* Set full scale volume */
    if (ioctl(fp, IOCTL_AUDIO_SET_VOLUME, (char *)(256))) {
      printf("Couldn't set volume\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.




Version History:
2023-07-14 HH v0.01 - First prerelease.
