Audio bridge to Ethernet, is it possible?

Status
Not open for further replies.

tschrama

Well-known member
Hi all,

Your options are welcome on this idea:
Would it be possible to make a Audio to ethernet bridge on a teensy 4.1?

Audio will be send from an external ADC using TDM, 100kHz, 24 bits, 4 or 8 channels. This audio needs to be processed on a Rasb Pi. I figured a Ethernet connection might be good for that task.

Is it possible, or should I look for different route?


Thanks for any comments you might have.
Thijs Schrama
 
Just Bumping.... I am about to start working on this task. Any warning, remarks, opinions are welcome.
 
Today I started experimenting.

This code compiles fine, but halts the ethernet configuration. Do any of you know why?


Code:
/ MATLABUDPBroadcastExample.ino
// Copyright 2016 The MathWorks, Inc.
// some edits T Schrama july 2020 for teensy 4.1 nativeEthernet

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>

int ledPin = LED_BUILTIN;                                    // Connect an LED->330Ohm to pin 5 or LED_BUILTIN

int packetSize;

//byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xAD, 0xDE};

uint8_t mac[6];

unsigned int broadcastPort = 31416;      
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  
char  ArduinoAckMessage[] = "Arduino:ACK\r";       // "\r" is the carriage return, i.e., char(13)
char MATLABBlinkItCommand[] = "MATLAB:BlinkIt\r";  
EthernetUDP Udp;
IPAddress broadcastAddress;

void setup()
{
  teensyMAC(mac);  // function to auire Teensy 4.1 NativeEthernet MAC,  function is define below
  Serial.begin(9600);
  if (Ethernet.begin(mac)==0){
    Serial.println("Failed to configure Ethernet. Halt.");
    delay(1000);                                  // Allow some time for message to be printed
    abort();
  }
  Serial.print("Arduino's IP Address is: ");
  Serial.println(Ethernet.localIP());
  Udp.begin(broadcastPort);  
  pinMode(ledPin, OUTPUT);      
  digitalWrite(ledPin, LOW);    
}

void loop()
{
  // if there's data available, read a packet
  packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Message: ");
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    packetBuffer[packetSize] = '\0';
    Serial.println(packetBuffer);
    if (strcmp(packetBuffer, MATLABBlinkItCommand) == 0)
    {
      broadcastAddress = Udp.remoteIP();
      broadcastAddress[3] = 255;
      Udp.beginPacket(broadcastAddress, broadcastPort);
      Udp.write(ArduinoAckMessage);
      Udp.endPacket();
      digitalWrite(ledPin, HIGH);                   // sets the LED on
      delay(1000);                                  // waits for a second
      digitalWrite(ledPin, LOW);                    // sets the LED off
    }
  }
  delay(10);  
}

// code to aquire MAC adres of teensy 4.1 nativeEthernet
void teensyMAC(uint8_t *mac) {

  static char teensyMac[23];
  
  #if defined(HW_OCOTP_MAC1) && defined(HW_OCOTP_MAC0)
    Serial.println("using HW_OCOTP_MAC* - see https://forum.pjrc.com/threads/57595-Serial-amp-MAC-Address-Teensy-4-0");
    for(uint8_t by=0; by<2; by++) mac[by]=(HW_OCOTP_MAC1 >> ((1-by)*8)) & 0xFF;
    for(uint8_t by=0; by<4; by++) mac[by+2]=(HW_OCOTP_MAC0 >> ((3-by)*8)) & 0xFF;

    #define MAC_OK

  #else
    
    mac[0] = 0x04;
    mac[1] = 0xE9;
    mac[2] = 0xE5;

    uint32_t SN=0;
    __disable_irq();
    
    #if defined(HAS_KINETIS_FLASH_FTFA) || defined(HAS_KINETIS_FLASH_FTFL)
      Serial.println("using FTFL_FSTAT_FTFA - vis teensyID.h - see https://github.com/sstaub/TeensyID/blob/master/TeensyID.h");
      
      FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
      FTFL_FCCOB0 = 0x41;
      FTFL_FCCOB1 = 15;
      FTFL_FSTAT = FTFL_FSTAT_CCIF;
      while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
      SN = *(uint32_t *)&FTFL_FCCOB7;

      #define MAC_OK
      
    #elif defined(HAS_KINETIS_FLASH_FTFE)
      Serial.println("using FTFL_FSTAT_FTFE - vis teensyID.h - see https://github.com/sstaub/TeensyID/blob/master/TeensyID.h");
      
      kinetis_hsrun_disable();
      FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
      *(uint32_t *)&FTFL_FCCOB3 = 0x41070000;
      FTFL_FSTAT = FTFL_FSTAT_CCIF;
      while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
      SN = *(uint32_t *)&FTFL_FCCOBB;
      kinetis_hsrun_enable();

      #define MAC_OK
      
    #endif
    
    __enable_irq();

    for(uint8_t by=0; by<3; by++) mac[by+3]=(SN >> ((2-by)*8)) & 0xFF;

  #endif

  #ifdef MAC_OK
    sprintf(teensyMac, "MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    Serial.println(teensyMac);
  #else
    Serial.println("ERROR: could not get MAC");
  #endif
}
 
OK, got it working.

First, I had to bridge my ethernet in my computer, so the teensy sees my DHCP from my home-internet-provider-modem(?)
Second, I had to change the ethernet library to the nativeEthrnet library.

Code:
#include <fnet.h>
#include <fnet_config.h>
#include <fnet_user_config.h>

#include <NativeEthernet.h>

// MATLABUDPBroadcastExample.ino
// Copyright 2016 The MathWorks, Inc.
// some edits T Schrama july 2020 for teensy 4.1 nativeEthernet

#include <SPI.h>
//#include <Ethernet.h>
//#include <EthernetUdp.h>

int ledPin = LED_BUILTIN;                                    // Connect an LED->330Ohm to pin 5 or LED_BUILTIN

int packetSize;

//byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xAD, 0xDE};

uint8_t mac[6];

unsigned int broadcastPort = 31416;      
char packetBuffer[UDP_TX_PACKET_MAX_SIZE];  
char  ArduinoAckMessage[] = "Arduino:ACK\r";       // "\r" is the carriage return, i.e., char(13)
char MATLABBlinkItCommand[] = "MATLAB:BlinkIt\r";  
EthernetUDP Udp;
IPAddress broadcastAddress;

void setup()
{
  teensyMAC(mac);                                // function to auqire Teensy 4.1 NativeEthernet MAC,  function is defined below
  Serial.begin(9600);
  if (Ethernet.begin(mac)==0){
    Serial.println("Failed to configure Ethernet. Halt.");
    delay(1000);                                  // Allow some time for message to be printed
    abort();
  }
  Serial.print("Arduino's IP Address is: ");
  Serial.println(Ethernet.localIP());
  Udp.begin(broadcastPort);  
  pinMode(ledPin, OUTPUT);      
  digitalWrite(ledPin, LOW);    
}

void loop()
{
  // if there's data available, read a packet
  packetSize = Udp.parsePacket();
  if (packetSize) {
    Serial.print("Message: ");
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    packetBuffer[packetSize] = '\0';
    Serial.println(packetBuffer);
    if (strcmp(packetBuffer, MATLABBlinkItCommand) == 0)
    {
      broadcastAddress = Udp.remoteIP();
      broadcastAddress[3] = 255;
      Udp.beginPacket(broadcastAddress, broadcastPort);
      Udp.write(ArduinoAckMessage);
      Udp.endPacket();
      digitalWrite(ledPin, HIGH);                   // sets the LED on
      delay(1000);                                  // waits for a second
      digitalWrite(ledPin, LOW);                    // sets the LED off
    }
  }
  delay(10);  
}

// code to aquire MAC adres of teensy 4.1 nativeEthernet
void teensyMAC(uint8_t *mac) {

  static char teensyMac[23];
  
  #if defined(HW_OCOTP_MAC1) && defined(HW_OCOTP_MAC0)
    Serial.println("using HW_OCOTP_MAC* - see https://forum.pjrc.com/threads/57595-Serial-amp-MAC-Address-Teensy-4-0");
    for(uint8_t by=0; by<2; by++) mac[by]=(HW_OCOTP_MAC1 >> ((1-by)*8)) & 0xFF;
    for(uint8_t by=0; by<4; by++) mac[by+2]=(HW_OCOTP_MAC0 >> ((3-by)*8)) & 0xFF;

    #define MAC_OK

  #else
    
    mac[0] = 0x04;
    mac[1] = 0xE9;
    mac[2] = 0xE5;

    uint32_t SN=0;
    __disable_irq();
    
    #if defined(HAS_KINETIS_FLASH_FTFA) || defined(HAS_KINETIS_FLASH_FTFL)
      Serial.println("using FTFL_FSTAT_FTFA - vis teensyID.h - see https://github.com/sstaub/TeensyID/blob/master/TeensyID.h");
      
      FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
      FTFL_FCCOB0 = 0x41;
      FTFL_FCCOB1 = 15;
      FTFL_FSTAT = FTFL_FSTAT_CCIF;
      while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
      SN = *(uint32_t *)&FTFL_FCCOB7;

      #define MAC_OK
      
    #elif defined(HAS_KINETIS_FLASH_FTFE)
      Serial.println("using FTFL_FSTAT_FTFE - vis teensyID.h - see https://github.com/sstaub/TeensyID/blob/master/TeensyID.h");
      
      kinetis_hsrun_disable();
      FTFL_FSTAT = FTFL_FSTAT_RDCOLERR | FTFL_FSTAT_ACCERR | FTFL_FSTAT_FPVIOL;
      *(uint32_t *)&FTFL_FCCOB3 = 0x41070000;
      FTFL_FSTAT = FTFL_FSTAT_CCIF;
      while (!(FTFL_FSTAT & FTFL_FSTAT_CCIF)) ; // wait
      SN = *(uint32_t *)&FTFL_FCCOBB;
      kinetis_hsrun_enable();

      #define MAC_OK
      
    #endif
    
    __enable_irq();

    for(uint8_t by=0; by<3; by++) mac[by+3]=(SN >> ((2-by)*8)) & 0xFF;

  #endif

  #ifdef MAC_OK
    sprintf(teensyMac, "MAC: %02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    Serial.println(teensyMac);
  #else
    Serial.println("ERROR: could not get MAC");
  #endif
}
 
Looks as though nobody ever chimed in to assist. :-(
In any case, I must ask: were you able to stream 24/48 multichannel tdm audio to Ethernet using the teensy?
My project requires the same, so I'm more than just curious about your project at large.

Best,

Chris
 
Hi,

Project run low for a while, but I think I got 8 channels working. Will post some code when I get home this weekend.

Meanwhile, what is you project about?
 
I think this is were I left the project last time I worked on it. IIRC i got the sending of the data working, but was never able to verify it on a receiving PC.
see attached code (it uses the Teensy audio toolbox with the queue object and uses UDP to send data)

Code:
#include <Arduino.h>
#include <Audio.h>
#include <TeensyID.h>
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 137, 2);                     // local IP adress
IPAddress ipremote(192, 168, 137, 1);               // remote IP adress
unsigned int localPort = 8888;                      // local port to listen on,to do  AUTOMATE this
unsigned int remotePort = 8888;                     // remote port to listen on,to do  AUTOMATE this

char packetBuffer[UDP_TX_PACKET_MAX_SIZE];          // = 24, buffer to hold incoming packet,
char ReplyBuffer[] = "acknowledged";                // a string to send back, not used yet
EthernetUDP Udp;                                    // An EthernetUDP instance to let us send and receive packets over UDP

uint8_t serial[4];                                  // used for Teensy serial number
bool returnbool = 0;                                // used for return value of codec settings, 1 = succes, 0 = error
uint8_t queue1L = 0;                                // used for size of queue available
uint8_t queue2L = 0;                                // used for size of queue available
uint8_t queue3L = 0;  
uint8_t queue4L = 0;  

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioControlCS42448      cs42448_1;      //xy=403,424
AudioInputTDM            tdm1;           //xy=195,205
AudioRecordQueue         queue1;         //xy=449,120
AudioRecordQueue         queue2;         //xy=450,157
AudioRecordQueue         queue3;         //xy=450,198
AudioRecordQueue         queue4;         //xy=451,237
AudioConnection          patchCord1(tdm1, 0, queue1, 0);
AudioConnection          patchCord2(tdm1, 1, queue2, 0);
AudioConnection          patchCord3(tdm1, 2, queue3, 0);
AudioConnection          patchCord4(tdm1, 3, queue4, 0);
// GUItool: end automatically generated code

void setup() {
  Serial.begin(9600);                                       // Open serial communications and wait for port to open:
  while (!Serial) {  }                                      // wait for serial port to connect. Needed for native USB port only
  Serial.println("Serial port connected");

  Ethernet.begin(mac, ip);                                  // start the Ethernet
  Serial.println("Ethernet started");
  
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {    // Check for Ethernet hardware present
    Serial.println("Ethernet shield was not found");
    while (true) {
      delay(10);                                            // do nothing, no point running without Ethernet hardware
    }
  }
  Serial.println("Ethernet hardware was found");

  if (Ethernet.linkStatus() == LinkOFF) {                   // Check for cable connection
    Serial.println("Ethernet cable is not connected.");
  }
  Serial.println("Ethernet cable is connected");

  Udp.begin(localPort);
  Serial.println("Ethernet started UDP");
  
  teensySN(serial);
  Serial.printf("Teensy USB Serial: %u \n", teensyUsbSN()); // print teensy serial, just to keep track on which teensy i am working on

  AudioMemory(128);                                                        // setup DMA buffer for background DMA CODEC sample fetching

  returnbool = cs42448_1.enable();                                         // Enable the codec
  Serial.print("CS42448_1_enable: return value = ");
  Serial.println(returnbool, BIN);
  delay(100);

  Serial.print("Settings of register 0x05: ");
  Serial.println(cs42448_1.read(0x05), BIN);
  delay(100);
  
  Serial.println("Set the ADC to differential mode...");
  cs42448_1.adcDifferentialMode();
  delay(100);
  
  Serial.println("Freeze the high pass filter...");
  cs42448_1.adcHighPassFilterFreeze();
  delay(100);
  
  Serial.print("Settings of register 0x05: ");
  Serial.println(cs42448_1.read(0x05), BIN);
  delay(100);

  Serial.println("set volume 1...");
  cs42448_1.volume(1);

  Serial.println("set inputLevel(15)...");
  cs42448_1.inputLevel(15);

  queue1.begin();
  queue2.begin();
  queue3.begin();
  queue4.begin();
  Serial.println("...q1,2,3 en 4 started, start fetching audio blocks");
}

char buffer[2048];                          

void loop() {
    queue1L = queue1.available();
    queue2L = queue2.available();
    queue3L = queue3.available();
    queue4L = queue4.available();
    
    if ((queue1L >= 3)||(queue2L >= 3)||(queue3L >= 3)||(queue4L >= 3)) {
      Serial.print("q1=");
      Serial.print(queue1L);
      Serial.print(", q2=");
      Serial.print(queue2L);
      Serial.print(", q3=");
      Serial.print(queue3L);
      Serial.print(", q4=");
      Serial.println(queue4L);
      }
  
    if (queue1L >= 2) { 
           
      memcpy(buffer     , queue1.readBuffer(), 256);
      queue1.freeBuffer();
      memcpy(buffer+ 256, queue1.readBuffer(), 256);
      queue1.freeBuffer();

      memcpy(buffer+ 512, queue2.readBuffer(), 256);
      queue2.freeBuffer();
      memcpy(buffer+ 768, queue2.readBuffer(), 256);
      queue2.freeBuffer();

      memcpy(buffer+ 1024, queue3.readBuffer(), 256);
      queue3.freeBuffer();
      memcpy(buffer+ 1280, queue3.readBuffer(), 256);
      queue3.freeBuffer();

      memcpy(buffer+ 1536, queue4.readBuffer(), 256);
      queue4.freeBuffer();
      memcpy(buffer+ 1792, queue4.readBuffer(), 256);
      queue4.freeBuffer();
      
      // write audio samples as CHAR to UDP
      Udp.beginPacket(ipremote, remotePort);
      Udp.write(buffer);
      Udp.endPacket();
    } 
}
 
Status
Not open for further replies.
Back
Top