
        AUIETH AES67/RTP audio input driver
        -----------------------------------
               for VSOS 3.68 or higher
              2025-02-28  VLSI Solution

The audio ethernet audio input driver.

The ethernet input driver lets the user read a stereo signal from a
audio ethernet packets.

Supported parameters while loading are:
s - Make driver as stdaudioin

Example driver +auieth s

In auieth.c there are two compilation features
#define ENABLE_MONITOR_MAIN
#define COPY_AUDIO_INTERRUPT

if ENABLE_MONITOR_MAIN is defined main() has following parameters

auieth [-h][-d][-i][-l][-m][-p][-v][-w]
where
-h - Short help
-d - Dump last received metaheader.
-l - Dump audio data from buffer as it is fed to there
-r - Raw metaheader  dump
-v - Print stats once
-m - Monitor auieth processing printing stats in loop
-w - Write output to pckts.txt file

And if COPY_AUDIO_INTERRUPT isn't defined, additional parameters:

-p - Dump packets\n"
-i - Most idiotic dump which dumps raw data from ethernet receiver

ENABLE_MONITOR_MAIN enables monitopring features, which allow looking more to processing.


COPY_AUDIO_INTERRUPT makes interrupt execution longer as it copies the data. This blocks other interrupts.


After the driver has been loaded it is possible to for example monitor it.
S:>auieth -m
IC: 52220 S:   16261180 Bad:          0 LE: 0000 ROF:          0 OF:        285 IH:          0 CT:       1122 F:  952

Fields are:
IC: interrupt count
S: sample count
Bad: Not good packets
LE: Last error in packet
ROF: Receiver over flow
OF: Input buffer overflow
IH: Interrupt to handler clock cycle delay (interrupt duration in COPY_AUDIO_INTERRUPT configuration)
CT: Receiver to buffer copy time in clock cycles
F: Input buffer fill


To enable VSDSP ethernet reception, some commands has to be executed on risc-v side.

Load linux, and in linux shell, if you aren't running it already
Set defaults
~ # maccfg -d

Enable VSDSP ethernet
~ # maccfg -w 0x0=0x4880

Check values
~ # maccfg -A
VLSI MAC Registers...showing non-zero registers 0x0-0x7F
  ETH_CF         0x00: 4880
  ETH_STATUS     0x01: 0c91
  ETH_DEV_ID     0x02: 0011
  MDIO_CF        0x10: 021c
  MDIO_FRAME     0x11: 0400
  MDIO_WRDATA    0x12: 1300
  MDIO_RDDATA    0x13: 0041
  IFGSET         0x20: 1818
  RX_MIN_LEN     0x21: 0018
  RX_MAN_LEN     0x22: 05ec
  RX_MPKT        0x23: 8109
  COUNTER_LOW    0x28: 047c
  COUNTER_HIGH   0x29: cdf8
  RX_FILTER_RV   0x40: 9808
  HWADDR_HI_RV   0x41: 5653
  HWADDR_MD_RV   0x42: 7276
  HWADDR_LO_RV   0x43: 4553
  RX_FILTER_VS   0x67: 9e14
  RX_MODIFY_VS   0x68: 000f
  RX_UDPPRT_VS   0x6b: 138c
  RX_ADOFMT_VS   0x6d: 0011
  HWADDR_HI_VS   0x6e: 5653
  HWADDR_MD_VS   0x6f: 7276
  HWADDR_LO_VS   0x70: 455

Check IP address
~ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000
    link/ether 56:53:72:76:45:53 brd ff:ff:ff:ff:ff:ff
    inet 172.16.2.54/24 scope global eth0
       valid_lft forever preferred_lft forever

With this configuration 172.16.2.54 in UDP port 5004 can receive RTP
packets and those should be hgandled by auieth.



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

  u_int16 *adcLib = NULL;
  FILE *adcFP = NULL;

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



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



Reading Data:
  Character-based reading is NOT supported.

  The only supported read operation is:
  fread(buffer, sizeof(buffer[0]), BUFFER_ELEMENTS, fp);
  where the amount to read must be aligned with whole stereo samples,
  so 2 16-bit words for 16-bit audio, and 4 16-bit words for 32-bit audio!



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

  Get number of bits.
  Example:
    bits = ioctl(fp, IOCTL_AUDIO_GET_BITS, NULL);

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

  Get input buffer fill state in 16-bit words.
  - Only for drivers with input capability
  Example:
    iBufFill = ioctl(fp, IOCTL_AUDIO_GET_INPUT_BUFFER_FILL, NULL);

  Get input buffer size in 16-bit words.
  - Only for drivers with input capability
  Example:
    iBufSize = ioctl(fp, IOCTL_AUDIO_GET_INPUT_BUFFER_SIZE, NULL);

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

  Get overflow sample counter for the input buffer.
  - Only for drivers with input
  Example:
    s_int32 oFlow;
    if (ioctl(adcFP, IOCTL_AUDIO_GET_OVERFLOWS, (char *)(&oFlow))) {
      printf("Couldn't get overflow counter\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:
2025-05-10 HV v1.00 - First real driver
