Sanity Check - SGTL5000 QFN20 (à la Rev D2) Hardware and Software Design

Hello! Hobbyist here slowly going crazy to figure this out... I'm running out of ideas and wanted to post this in hopes of getting some additional thoughts on this as I'm not sure how else to best move forward. Pardon any mis-wordings below -- EE and software is not my primary background.

Objective 1: Upcycle an old CB, desktop microphone so it is usable on PCs via USB. (I know you can buy desktop mics but where's the fun in that? Despite the frustration this has been a wonderful learning experience, and I am incredibly amazed by the Teensy community!)

- Bought some Teensy 4.0s and RevD Audio Shields.
- Made some edits to the usb_desc.c and usb_desc.h for custom names and to make it such that only the Mic input will show up as a USB device.
- Generated code using the Audio System Design Tool. Pretty much just to set micgain and a highpass filter. Code is at the end.
- Added some code for push-to-talk, debounce, and turn on an LED. It has been commented out during debugging.
- I have been able to get this working perfectly.


Objective 2: Due to space constraints, I could not fit the stock Audio Shield without chopping it up. Cue me designing a custom shield.

- For some reason I thought using the QFN20 version of the SGTL5000 chip was the best option. I based the electrical circuit based on the PJRC documentation. Since many features weren't needed for my application (SD card, line out, line in, headphone) I did not include them.
- Attached to this post is my electrical circuit with some annotations that may help explain what's going on. The SGTL5000 section -- I tried to copy the power and mic circuit exactly from here https://www.pjrc.com/store/teensy3_audio.html
- Used the same code from Objective 1.
- I have not been able to get any response with my custom shield.

Debugging: I've done some common sense debugging and am at a loss for what to do next. Below is a mostly chronological list of steps I've done already. Any further pointers?
- Quintuple checked the soldering of the QFN20 chip, even under microscope. I believe soldering is ok.
- Used a multimeter to check input voltage to the SGTL5000. 3.3V VDDIO and VDDA is ok, 1.8V VDDD is ok. I believe the SGTL5000 is getting power.
- Used a multimeter to check MICBIAS. I am seeing a fluctuating ~0.070V to ~0.200V with a multimeter. I am not seeing any voltage with an oscilloscope. I believe there is an issue with the MICBIAS output.
- Checked for obvious shorts or voltage where it shouldn't be. I do not believe there are any shorts.
- Removed the Mic-related capacitors and rechecked voltages. Still the same MICBIAS observation.
- O'scoped all the clock signals. Compared all signals to the OEM Audio Shield and the frequency is spot on. I believe the SGTL5000 is getting the correct clock signals.
- O'scoped the SDA and SCL lines. I haven't decoded the message, but I do see a blip in the signal upon Teensy bootup. I believe the SGTL5000 is getting bootup commands.
- O'scoped the TX and RX lines with no signal. I believe the SGTL5000 is not outputting any data. For reference, I scoped the stock Audio Shield and was able to clearly see activity on the TX line.
- Removed the SGTL5000 and replaced it with another one. Checked the soldering many times again.
- Using a multimeter, all input voltages are still ok.
- When rechecking MICBIAS, it was reading ~2.8V for a few minutes, and then it went back to ~0.070V to ~0.200V.




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

//**********************************************************************************//
// With highpass filter
AudioInputI2S            i2s1;           //xy=239.09091186523438,217.09091186523438
AudioAmplifier           amp1;           //xy=339.66669845581055,264.6666889190674
AudioFilterBiquad        biquad1;        //xy=508,266
AudioOutputUSB           usb1;           //xy=749.091064453125,273.0910186767578
AudioConnection          patchCord1(i2s1, amp1);
AudioConnection          patchCord2(amp1, biquad1);
AudioConnection          patchCord3(biquad1, 0, usb1, 0);
AudioConnection          patchCord4(biquad1, 0, usb1, 1);
AudioControlSGTL5000     sgtl5000_1;     //xy=382.0909118652344,567.0909214019775
//**********************************************************************************//

float gainValue = 1;    //Max gain = 1
float gainStep = 0.1;   //Gain increment during ramps
bool talk = false;      //Talk yes or no?
int talk1 = LOW;        //Talk switch sample 1
int talk2 = LOW;        //Talk switch sample 2
int talk3 = LOW;        //Talk switch sample 3
const int talkPin = 12; //The number of the Talk switch pin
const int talkLED = 6;  //The number of the LED control pin

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);   //DIAG.  Use internal LED for diagnostics for now
  pinMode(talkPin, INPUT);        //Set talkPin and digital input
  pinMode(talkLED, OUTPUT);       //Set talkOutput and digital output

  Serial.begin(9600);             //DIAG.  For diagnostics 
  AudioMemory(12);                //12 seems to work well.
  sgtl5000_1.enable();           
  sgtl5000_1.volume(1);
  sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
  sgtl5000_1.micGain(24);         //Set 36 as the base
  amp1.gain(1);                   //Initialize mic off

  biquad1.setHighpass(0, 60, 0.7071);  //Highpass filter at 125Hz, first stage
  //biquad1.setHighpass(1, 125, 0.7071);  //Highpass filter at 125Hz, second stage

  Serial.println("On");           //DIAG
  talk = true;                   //Initialize off
  digitalWrite(LED_BUILTIN, HIGH); //Initialize off
  digitalWrite(talkLED, HIGH); //Initialize off 

  delay(1000);
}


void loop() {
//  //Update 3-sample history every loop
//  talk3 = talk2;
//  talk2 = talk1;
//  talk1 = digitalRead(talkPin);   
//
//   //Debounce -- if 3 consecutive samples, then chnage Talk state
//   if (talk3 == HIGH && talk2 == HIGH && talk1 == HIGH){
//     talk = false;
//   }
//   if (talk3 == LOW && talk2 == LOW && talk1 == LOW){
//     talk = true;
//   }
//
//  //TODO Analog input as mic gain adjuster
// 
//  if (talk == true){                      //If talk = on, start ramping gain to 1
//    if (gainValue < 1){
//      gainValue = gainValue + gainStep;   //Ramp gain to avoid pops
//      Serial.println(gainValue);          //DIAG
//      amp1.gain(gainValue);
//    }
//    if (gainValue >= 1){                  //Do the following once ramp is complete and fully on
//      amp1.gain(1);                       //Make sure gain is at max 1 in case of overshoot/rounding error      
//      gainValue = 1;                 
////      delay(5000);                        //Remove!!
////      talk = false;                       //Remove!!
//      digitalWrite(talkLED, LOW);         //Turn external LED off      
//      digitalWrite(LED_BUILTIN, LOW);     //DIAG
//      Serial.println("Off");              //DIAG
//    }
//  }
//
//  if (talk == false){                     //If talk = off, start ramping gain to 0
//    if (gainValue > 0){
//      gainValue = gainValue - gainStep;   //Ramp gain to avoid pops
//      Serial.println(gainValue);          //DIAG
//      amp1.gain(gainValue);
//    }
//    if (gainValue <= 0){                  //Do the following once ramp is complete and fully off
//      amp1.gain(0);                       //Make sure gain is at muted 0 in case of overshoot/rounding error                   
//      gainValue = 0;
////      delay(5000);                        //Remove!!
////      talk = true;                        //Remove!!
//      digitalWrite(talkLED, HIGH);        //Turn external LED on
//      digitalWrite(LED_BUILTIN, HIGH);    //DIAG
//      Serial.println("On");               //DIAG          
//    }     
//  }

  delay(5);                               //5 msec loops
}
 

Attachments

  • myShield.png
    myShield.png
    1.6 MB · Views: 18
Hmm, just saw the note "Wires for MCLK, BCLK, LRCLK, TX & RX should be kept short. The audio shield is meant to connect to Teensy through short pins. Wires can be used, but wires must be short to avoid problems."

Per the attached PCB layout, is it something I should mostly be ok with?
 

Attachments

  • myPCB.png
    myPCB.png
    97.1 KB · Views: 20
The decoupling caps are rather big and far away from the chip - 0603 is a better choice. traces carrying power and ground should be wider to reduce inductance. It will probably work though, just a bit closer to the edge than is generally liked.

Vias in pads are a bad idea for smaller SMT parts BTW, they can tomb-stone.

A ground-plane on the bottom layer would be good. Then signals get a low-inductance return path and won't ring so much.
 
Thanks! Is the recommendation to redo the layout with 0603 decoupling caps and move them closer? Before I go that far, is there an equivalent of a *IDN? to see if the SGTL5000 is able to communicate at all?

Noted about the trace widths and pad vias. I tried to shave every 0.010" off any apparently made some non-optimal choices.

For what it's worth -- both the top and bottom layers are both filled GND planes. I hid them in the prior image as they would have drowned out some of the other information. I tried my best to keep data on the bottom layer and power on the top layer.
 

Attachments

  • myPCBBottom.png
    myPCBBottom.png
    78.6 KB · Views: 12
  • myPCBTop.png
    myPCBTop.png
    137.9 KB · Views: 11
This is so embarassing... The culprit is... Insufficient soldering at the QFN20! Such a rookie mistake and I can't believe I missed it, even under microscope. I have many things to tidy up but it should be downhill from here! Thank you again PJRC contributors for all the amazing documentation that goes behind the hardware and software!
 
Continued follow-up, it works! I foolishly also flipped the collector and emitter on MOSFET Q1 in the schematic, but was able to whitewire a fix. In hopes of contributing back to the community, below are images of the project and some lessons learned along the way!

The final product.
IMG_0059.JPG

I work in an office environment with several loud people around me, and my built-in laptop mic was garnering a lot of complaints during telecon meetings. I had a push-to-talk microphone several years ago and wanted something similar so I didn't have to constantly deal with muting myself through software. I'm huge on art deco and found a vintage Turner microphone that is totally my vibe.

I was originally just going to go full analog, but for some strange reason I just could not get the 3.5mm audio jack working properly. In a search for alternative solution, I stumbled upon this guide. I pretty much followed the same path and cobbled something together over a weekend. It was not pretty, but it kinda worked?!
mic_01.jpg

mic_02.jpg


I used this for a couple weeks but there were a few pretty major issues that were enough to compel a major revision.
  1. When plugged in, the USB soundcard obviously registered as a soundcard -- with speaker output and mic in. It was easy to disable the speaker output in Windows, but it felt like a sloppy thing to do.
  2. The telecon software (Teams) I most often use has software noise reduction, but when turned off it turns out there was a major buzz occurring at 1000Hz, 2000Hz, 3000Hz, etc. The circuit was unusable for anything without software noise reduction.
  3. The push-to-talk mechanism electrically disconnected the electret mic in the circuit. When open there was pretty appreciable ground noise coming in.
  4. Not sure if it _was_ due to the software noise reduction, but the sound from this always sounded kinda nasally.

Software noise reduction made it all usable, but I was not proud of what I made. Through continued research into how to improve this, I somehow stumbled upon the Teensy. I am using a Teensy 3.2 for a different project, but didn't realize they have audio processing capability. I bought an Audio Shield, paired it with a pretty nice PUI AOM-5024 series electret mic (discovered it through this list), did some basic prototyping, and confirmed that it would do exactly what I wanted with much better sound quality!

mic_03.jpg

mic_04.jpg

Due to the limited space, I could not fit the Audio Shield without chopping it or the microphone up. So that brought me to a couple of custom PCBs and the origin of this initial post. After figuring out the hardware, I put everything together and finished up the software, posted as follows.

Code:
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SerialFlash.h>

//**********************************************************************************//
AudioInputI2S            i2s1;         
AudioAmplifier           amp1;         
AudioFilterBiquad        biquad1;     
AudioOutputUSB           usb1;         
AudioConnection          patchCord1(i2s1, amp1);
AudioConnection          patchCord2(amp1, biquad1);
AudioConnection          patchCord3(biquad1, 0, usb1, 0);
AudioConnection          patchCord4(biquad1, 0, usb1, 1);
AudioControlSGTL5000     sgtl5000_1;   

//**********************************************************************************//
float ampGain = 0;            //Max gain = 1
float ampStep = 0.1;          //Gain increment during ramps
bool talk = false;            //Talk yes or no?
int talk1 = LOW;              //Talk switch sample 1
int talk2 = LOW;              //Talk switch sample 2
int talk3 = LOW;              //Talk switch sample 3
const int talkPin = 12;       //The number of the Talk switch pin
const int talkLED = 6;        //The number of the LED control pin
int micGainPin = A1;          //Mic gain pin
float micGainValue = 0;       //Mic gain analog input value in 0-1023.  This is intentionall float
int micGainOffset = 0;        //Mic gain offset in dB.  This is intentionally integer
int micGainOffsetLast = 1;    //Last micGainOffset value.  This is intentionally integer
int micGainBase = 20;         //Mic gain, base value in dB

//**********************************************************************************//
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);   //DIAG.  Use internal LED for diagnostics for now
  pinMode(talkPin, INPUT);        //Set talkPin and digital input
  pinMode(talkLED, OUTPUT);       //Set talkOutput and digital output

  AudioMemory(12);                //12 seems to work well.
  sgtl5000_1.enable();         
  sgtl5000_1.volume(1);
  sgtl5000_1.inputSelect(AUDIO_INPUT_MIC);
  sgtl5000_1.micGain(micGainBase);//Set 36 as the base
  amp1.gain(0);                   //Initialize mic off

  biquad1.setHighpass(0, 60, 0.7071);  //Highpass filter at 125Hz, first stage
  //biquad1.setHighpass(1, 125, 0.7071);  //Highpass filter at 125Hz, second stage

  talk = false;                   //Initialize off
  digitalWrite(LED_BUILTIN, LOW); //Initialize off
  digitalWrite(talkLED, LOW);     //Initialize off

  delay(1000);
}

//**********************************************************************************//
void loop() {
  //Update 3-sample history every loop
  talk3 = talk2;
  talk2 = talk1;
  talk1 = digitalRead(talkPin);
 
  //Debounce -- if 3 consecutive samples, then chnage Talk state
  if (talk3 == HIGH && talk2 == HIGH && talk1 == HIGH){
   talk = true;
  }
  if (talk3 == LOW && talk2 == LOW && talk1 == LOW){
   talk = false;
  }

  //Set micGain based on variable resistor
  micGainValue = analogRead(micGainPin);              //Recall this is float
  micGainOffset = int(-0.0294*micGainValue + 15.06);  //This equation linearly maps 3.3-0V to -15-+15dB.  Convert to int (no decimal dB)
  if (micGainOffset != micGainOffsetLast){            //Only update if a change is detected
    sgtl5000_1.micGain(micGainBase + micGainOffset);  //Set the new micGain with volume controlled value
    micGainOffsetLast = micGainOffset;
  }
 
  if (talk == true){                      //If talk = on, start ramping gain to 1
    if (ampGain < 1){
      ampGain = ampGain + ampStep;        //Ramp gain to avoid pops
      amp1.gain(ampGain);
    }
    if (ampGain >= 1){                    //Do the following once ramp is complete and fully on
      amp1.gain(1);                       //Make sure gain is at max 1 in case of overshoot/rounding error     
      ampGain = 1;                     
    }
  }

  if (talk == false){                     //If talk = off, start ramping gain to 0
    if (ampGain > 0){
    ampGain = ampGain - ampStep;          //Ramp gain to avoid pops
      amp1.gain(ampGain);
    }
    if (ampGain <= 0){                    //Do the following once ramp is complete and fully off
      amp1.gain(0);                       //Make sure gain is at muted 0 in case of overshoot/rounding error                 
      ampGain = 0;
      digitalWrite(talkLED, LOW);         //Turn external LED on
    }   
  }

  //Turn on/off LED.  Put this outside of the "talk" conditions to ensure there is no hot-mic error
  if (ampGain > 0){
    digitalWrite(talkLED, HIGH);          //Turn external LED off     
  }
  if (ampGain == 0){
    digitalWrite(talkLED, LOW);           //Turn external LED off     
  }

  delay(5);                               //5 msec loops.  Use delay instead of millis() as to avoice millis() saturation and rollover algorithms
}

Through inspection, there's really nothing that special about it. The basic features are:
  1. Push to talk with a very crude debounce.
  2. Turn on LED if mic is active.
  3. Provision for mic gain adjustment from a potentiometer voltage signal.
  4. Volume ramping to minimize sound pops.
  5. 125Hz highpass filter.
I don't go into it, but some fairly minor mechanical mods were needed on the Turner mic -- 1) grind down a couple of mounting posts that would otherwise hit the Teensy and 2) drill out the hole going into the head so I could better run wires through.)

To make good even better, I really did want to set it up so it would only show up as a microphone when plugged it. This guide got me very close, but it took many hours to figure out it was a pretty simple edit. If you navigate to usb_desc.h, just edit the descriptor length and comment out a couple select spots. If you search for "PENGUIN" in the below code you'll see exactly what was changed (you may want to do a sanity check against the original file in case I missed tagging something). You'll also have to make the same changes for the "// configuration for 12 Mbit/sec speed" descriptor.

Code:
// **************************************************************
//   USB Descriptor Sizes
// **************************************************************

// pre-compute the size and position of everything in the config descriptor
//
#define AUDIO_INTERFACE_DESC_SIZE    8 + 9+10+12+9+12 + 9+9+7+11+9+7 + 9+9+7+11+9+7+9  //No output  PENGUIN


#ifdef AUDIO_INTERFACE
    // configuration for 480 Mbit/sec speed
        // interface association descriptor, USB ECN, Table 9-Z
        8,                                      // bLength
        11,                                     // bDescriptorType
        AUDIO_INTERFACE,                        // bFirstInterface
        3,                                      // bInterfaceCount
        0x01,                                   // bFunctionClass
        0x01,                                   // bFunctionSubClass
        0x00,                                   // bFunctionProtocol
        0,                                      // iFunction
    // Standard AudioControl (AC) Interface Descriptor
    // USB DCD for Audio Devices 1.0, Table 4-1, page 36
    9,                    // bLength
    4,                    // bDescriptorType, 4 = INTERFACE
    AUDIO_INTERFACE,            // bInterfaceNumber
    0,                    // bAlternateSetting
    0,                    // bNumEndpoints
    1,                    // bInterfaceClass, 1 = AUDIO
    1,                    // bInterfaceSubclass, 1 = AUDIO_CONTROL
    0,                    // bInterfaceProtocol
    0,                    // iInterface
    // Class-specific AC Interface Header Descriptor
    // USB DCD for Audio Devices 1.0, Table 4-2, page 37-38
    10,                    // bLength
    0x24,                    // bDescriptorType, 0x24 = CS_INTERFACE
    0x01,                    // bDescriptorSubtype, 1 = HEADER
    0x00, 0x01,                // bcdADC (version 1.0)
    LSB(53), MSB(53),            // wTotalLength  PENGUIN
    2,                    // bInCollection
    AUDIO_INTERFACE+1,            // baInterfaceNr(1) - Transmit to PC
    AUDIO_INTERFACE+2,            // baInterfaceNr(2) - Receive from PC
    // Input Terminal Descriptor
    // USB DCD for Audio Devices 1.0, Table 4-3, page 39
    12,                    // bLength
    0x24,                    // bDescriptorType, 0x24 = CS_INTERFACE
    0x02,                    // bDescriptorSubType, 2 = INPUT_TERMINAL
    1,                    // bTerminalID
    0x02, 0x02,                // wTerminalType, 0x0202 = DEKTOP MICROPHONE, PENGUIN
    //0x01, 0x02,                // wTerminalType, 0x0201 = MICROPHONE
    //0x03, 0x06,                // wTerminalType, 0x0603 = Line Connector
    //0x02, 0x06,                // wTerminalType, 0x0602 = Digital Audio
    0,                    // bAssocTerminal, 0 = unidirectional
    2,                    // bNrChannels
    0x03, 0x00,                // wChannelConfig, 0x0003 = Left & Right Front
    0,                    // iChannelNames
    0,                     // iTerminal
    // Output Terminal Descriptor
    // USB DCD for Audio Devices 1.0, Table 4-4, page 40
    9,                    // bLength
    0x24,                    // bDescriptorType, 0x24 = CS_INTERFACE
    3,                    // bDescriptorSubtype, 3 = OUTPUT_TERMINAL
    2,                    // bTerminalID
    0x01, 0x01,                // wTerminalType, 0x0101 = USB_STREAMING
    0,                    // bAssocTerminal, 0 = unidirectional
    1,                    // bCSourceID, connected to input terminal, ID=1
    0,                    // iTerminal
    // Input Terminal Descriptor
    // USB DCD for Audio Devices 1.0, Table 4-3, page 39
    12,                    // bLength
    0x24,                    // bDescriptorType, 0x24 = CS_INTERFACE
    2,                    // bDescriptorSubType, 2 = INPUT_TERMINAL
    3,                    // bTerminalID
    0x01, 0x01,                // wTerminalType, 0x0101 = USB_STREAMING
    0,                    // bAssocTerminal, 0 = unidirectional
    2,                    // bNrChannels
    0x03, 0x00,                // wChannelConfig, 0x0003 = Left & Right Front
    0,                    // iChannelNames
    0,                     // iTerminal
/*     // Volume feature descriptor  PENGUIN
    10,                    // bLength
    0x24,                 // bDescriptorType = CS_INTERFACE
    0x06,                 // bDescriptorSubType = FEATURE_UNIT
    0x31,                 // bUnitID
    0x03,                 // bSourceID (Input Terminal)
    0x01,                 // bControlSize (each channel is 1 byte, 3 channels)
    0x01,                 // bmaControls(0) Master: Mute
    0x02,                 // bmaControls(1) Left: Volume
    0x02,                 // bmaControls(2) Right: Volume
    0x00,                // iFeature */
/*     // Output Terminal Descriptor  PENGUIN
    // USB DCD for Audio Devices 1.0, Table 4-4, page 40
    9,                    // bLength
    0x24,                    // bDescriptorType, 0x24 = CS_INTERFACE
    3,                    // bDescriptorSubtype, 3 = OUTPUT_TERMINAL
    4,                    // bTerminalID
    //0x02, 0x03,                // wTerminalType, 0x0302 = Headphones
    0x02, 0x06,                // wTerminalType, 0x0602 = Digital Audio
    0,                    // bAssocTerminal, 0 = unidirectional
    0x31,                // bCSourceID, connected to feature, ID=31
    0,                    // iTerminal */
      
    // Standard AS Interface Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.5.1, Table 4-18, page 59
    // Alternate 0: default setting, disabled zero bandwidth
    9,                    // bLenght
    4,                    // bDescriptorType = INTERFACE
    AUDIO_INTERFACE+1,            // bInterfaceNumber
    0,                    // bAlternateSetting
    0,                    // bNumEndpoints
    1,                    // bInterfaceClass, 1 = AUDIO
    2,                    // bInterfaceSubclass, 2 = AUDIO_STREAMING
    0,                    // bInterfaceProtocol
    0,                    // iInterface
    // Alternate 1: streaming data
    9,                    // bLenght
    4,                    // bDescriptorType = INTERFACE
    AUDIO_INTERFACE+1,            // bInterfaceNumber
    1,                    // bAlternateSetting
    1,                    // bNumEndpoints
    1,                    // bInterfaceClass, 1 = AUDIO
    2,                    // bInterfaceSubclass, 2 = AUDIO_STREAMING
    0,                    // bInterfaceProtocol
    0,                    // iInterface
    // Class-Specific AS Interface Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.5.2, Table 4-19, page 60
    7,                     // bLength
    0x24,                    // bDescriptorType = CS_INTERFACE
    1,                    // bDescriptorSubtype, 1 = AS_GENERAL
    2,                    // bTerminalLink: Terminal ID = 2
    3,                    // bDelay (approx 3ms delay, audio lib updates)
    0x01, 0x00,                // wFormatTag, 0x0001 = PCM
    // Type I Format Descriptor
    // USB DCD for Audio Data Formats 1.0, Section 2.2.5, Table 2-1, page 10
    11,                    // bLength
    0x24,                    // bDescriptorType = CS_INTERFACE
    2,                    // bDescriptorSubtype = FORMAT_TYPE
    1,                    // bFormatType = FORMAT_TYPE_I
    2,                    // bNrChannels = 2
    2,                    // bSubFrameSize = 2 byte
    16,                    // bBitResolution = 16 bits
    1,                    // bSamFreqType = 1 frequency
    LSB(44100), MSB(44100), 0,        // tSamFreq
    // Standard AS Isochronous Audio Data Endpoint Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.6.1.1, Table 4-20, page 61-62
    9,                     // bLength
    5,                     // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR
    AUDIO_TX_ENDPOINT | 0x80,        // bEndpointAddress
    0x09,                     // bmAttributes = isochronous, adaptive
    LSB(AUDIO_TX_SIZE), MSB(AUDIO_TX_SIZE),    // wMaxPacketSize
    4,                     // bInterval, 4 = every 8 micro-frames
    0,                    // bRefresh
    0,                    // bSynchAddress
    // Class-Specific AS Isochronous Audio Data Endpoint Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.6.1.2, Table 4-21, page 62-63
    7,                      // bLength
    0x25,                      // bDescriptorType, 0x25 = CS_ENDPOINT
    1,                      // bDescriptorSubtype, 1 = EP_GENERAL
    0x00,                      // bmAttributes
    0,                      // bLockDelayUnits, 1 = ms
    0x00, 0x00,                  // wLockDelay
  
  
    // Standard AS Interface Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.5.1, Table 4-18, page 59
    // Alternate 0: default setting, disabled zero bandwidth
    9,                    // bLenght
    4,                    // bDescriptorType = INTERFACE
    AUDIO_INTERFACE+2,            // bInterfaceNumber
    0,                    // bAlternateSetting
    0,                    // bNumEndpoints
    1,                    // bInterfaceClass, 1 = AUDIO
    2,                    // bInterfaceSubclass, 2 = AUDIO_STREAMING
    0,                    // bInterfaceProtocol
    0,                    // iInterface
    // Alternate 1: streaming data
    9,                    // bLenght
    4,                    // bDescriptorType = INTERFACE
    AUDIO_INTERFACE+2,            // bInterfaceNumber
    1,                    // bAlternateSetting
    2,                    // bNumEndpoints
    1,                    // bInterfaceClass, 1 = AUDIO
    2,                    // bInterfaceSubclass, 2 = AUDIO_STREAMING
    0,                    // bInterfaceProtocol
    0,                    // iInterface
    // Class-Specific AS Interface Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.5.2, Table 4-19, page 60
    7,                     // bLength
    0x24,                    // bDescriptorType = CS_INTERFACE
    1,                    // bDescriptorSubtype, 1 = AS_GENERAL
    3,                    // bTerminalLink: Terminal ID = 3
    3,                    // bDelay (approx 3ms delay, audio lib updates)
    0x01, 0x00,                // wFormatTag, 0x0001 = PCM
    // Type I Format Descriptor
    // USB DCD for Audio Data Formats 1.0, Section 2.2.5, Table 2-1, page 10
    11,                    // bLength
    0x24,                    // bDescriptorType = CS_INTERFACE
    2,                    // bDescriptorSubtype = FORMAT_TYPE
    1,                    // bFormatType = FORMAT_TYPE_I
    2,                    // bNrChannels = 2
    2,                    // bSubFrameSize = 2 byte
    16,                    // bBitResolution = 16 bits
    1,                    // bSamFreqType = 1 frequency
    LSB(44100), MSB(44100), 0,        // tSamFreq
    // Standard AS Isochronous Audio Data Endpoint Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.6.1.1, Table 4-20, page 61-62
    9,                     // bLength
    5,                     // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR
    AUDIO_RX_ENDPOINT,            // bEndpointAddress
    0x05,                     // bmAttributes = isochronous, asynchronous
    LSB(AUDIO_RX_SIZE), MSB(AUDIO_RX_SIZE),    // wMaxPacketSize
    4,                     // bInterval, 4 = every 8 micro-frames
    0,                    // bRefresh
    AUDIO_SYNC_ENDPOINT | 0x80,        // bSynchAddress
    // Class-Specific AS Isochronous Audio Data Endpoint Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.6.1.2, Table 4-21, page 62-63
    7,                      // bLength
    0x25,                      // bDescriptorType, 0x25 = CS_ENDPOINT
    1,                      // bDescriptorSubtype, 1 = EP_GENERAL
    0x00,                      // bmAttributes
    0,                      // bLockDelayUnits, 1 = ms
    0x00, 0x00,                  // wLockDelay
  
  
    // Standard AS Isochronous Audio Synch Endpoint Descriptor
    // USB DCD for Audio Devices 1.0, Section 4.6.2.1, Table 4-22, page 63-64
    9,                     // bLength
    5,                     // bDescriptorType, 5 = ENDPOINT_DESCRIPTOR
    AUDIO_SYNC_ENDPOINT | 0x80,        // bEndpointAddress
    0x11,                     // bmAttributes = isochronous, feedback
    4, 0,                    // wMaxPacketSize, 4 bytes
    4,                     // bInterval, 4 = 4 = every 8 micro-frames
    7,                    // bRefresh,
    0,                    // bSynchAddress
#endif

};

Overall the mic has been working very well and sounds much better now. Thanks, Teensy!!
 
Last edited:
Back
Top