diff --git a/module_usb_audio/endpoint0/audiorequests.xc b/module_usb_audio/endpoint0/audiorequests.xc index b98a4c6f..a262790d 100644 --- a/module_usb_audio/endpoint0/audiorequests.xc +++ b/module_usb_audio/endpoint0/audiorequests.xc @@ -45,8 +45,12 @@ extern unsigned char mixSel[MAX_MIX_COUNT][MIX_INPUTS]; /* Global var for current frequency, set to default freq */ unsigned int g_curSamFreq = DEFAULT_FREQ; -unsigned int g_curSamFreq48000Family = DEFAULT_FREQ % 48000 == 0; -unsigned int g_curSamFreqMultiplier = (DEFAULT_FREQ * 512 * 4) / (DEFAULT_MCLK_FREQ); +//unsigned int g_curSamFreq48000Family = DEFAULT_FREQ % 48000 == 0; + +#if 0 +/* Original feedback implementation */ +long long g_curSamFreqMultiplier = (DEFAULT_FREQ * 512 * 4) / (DEFAULT_MCLK_FREQ); +#endif /* Store an int into a char array: Note this allows non-word aligned access unlike reinerpret cast */ static void storeInt(unsigned char buffer[], int index, int val) @@ -113,9 +117,19 @@ static unsigned longMul(unsigned a, unsigned b, int prec) return ret; } -static void setG_curSamFreqMultiplier(int x) { - asm(" stw %0, dp[g_curSamFreqMultiplier]" :: "r"(x)); +#if 0 +/* Original feedback implementation */ +unsafe +{ + unsigned * unsafe curSamFreqMultiplier = &g_curSamFreqMultiplier; + +static void setG_curSamFreqMultiplier(unsigned x) +{ + // asm(" stw %0, dp[g_curSamFreqMultiplier]" :: "r"(x)); + *curSamFreqMultiplier = x; } +} +#endif /* Update master volume i.e. i.e update weights for all channels */ static void updateMasterVol( int unitID, chanend ?c_mix_ctl) @@ -261,8 +275,7 @@ static void updateVol(int unitID, int channel, chanend ?c_mix_ctl) int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, chanend c_audioControl, chanend ?c_mix_ctl, chanend ?c_clk_ctl ) { - unsigned char buffer[128]; - int i_tmp; + unsigned char buffer[512]; int unitID; XUD_Result_t result; unsigned datalength; @@ -302,27 +315,29 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c if(datalength == 4) { /* Re-construct Sample Freq */ - i_tmp = buffer[0] | (buffer[1] << 8) | buffer[2] << 16 | buffer[3] << 24; + int newSampleRate = buffer[0] | (buffer[1] << 8) | buffer[2] << 16 | buffer[3] << 24; /* Instruct audio thread to change sample freq (if change required) */ - if(i_tmp != g_curSamFreq) + if(newSampleRate != g_curSamFreq) { - g_curSamFreq = i_tmp; - g_curSamFreq48000Family = g_curSamFreq % 48000 == 0; + int newMasterClock; + + g_curSamFreq = newSampleRate; +#if 0 + /* Original feedback implementation */ + g_curSamFreq48000Family = ((MCLK_48 % g_curSamFreq) == 0); if(g_curSamFreq48000Family) { - i_tmp = MCLK_48; + newMasterClock = MCLK_48; } else { - i_tmp = MCLK_441; + newMasterClock = MCLK_441; } - unsigned mult = (g_curSamFreq*512*4)/i_tmp; - setG_curSamFreqMultiplier(mult); - - asm("ecallf %0"::"r"(mult)); + setG_curSamFreqMultiplier(g_curSamFreq/(newMasterClock/512)); +#endif #ifdef ADAT_RX /* Configure ADAT SMUX based on sample rate */ outuint(c_clk_ctl, SET_SMUX); @@ -845,8 +860,8 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c int i = 2; #ifndef SAMPLE_RATE_LIST - int currentFreq44 = MIN_FREQ_44; - int currentFreq48 = MIN_FREQ_48; + int currentFreq44 = 11025; //MIN_FREQ_44; + int currentFreq48 = 8000; //MIN_FREQ_48; unsigned maxFreq = MAX_FREQ; #if defined (FULL_SPEED_AUDIO_2) @@ -858,6 +873,21 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp, c maxFreq = MAX_FREQ_FS; } #endif + /* Special case for some low sample rates */ + unsigned lowSampleRateList[] = {8000, 11025, 12000, 16000, 22050, 32000}; + + for (int k = 0; k < sizeof(lowSampleRateList)/sizeof(unsigned); k++) + { + if((lowSampleRateList[k] >= MIN_FREQ) && (lowSampleRateList[k] <= MAX_FREQ)) + { + storeFreq(buffer, i, lowSampleRateList[k]); + num_freqs++; + } + } + + /* Just keep doubling for standard freqs >= 44.1/48kHz */ + currentFreq44 = 44100; + currentFreq48 = 48000; while(1) { if((currentFreq44 <= maxFreq) && (currentFreq44 >= MIN_FREQ)) @@ -1071,31 +1101,37 @@ int AudioEndpointRequests_1(XUD_ep ep0_out, XUD_ep ep0_in, USB_SetupPacket_t &sp if((sp.wLength == 3) && (length == 3)) { /* Recontruct sample-freq */ - int i_tmp = buffer[0] | (buffer [1] << 8) | (buffer[2] << 16); + int newSampleRate = buffer[0] | (buffer [1] << 8) | (buffer[2] << 16); - if(i_tmp != g_curSamFreq) + if(newSampleRate != g_curSamFreq) { int curSamFreq44100Family; + int curSamFreq48000Family; /* Windows Audio Class driver has a nice habbit of sending invalid SF's (e.g. 48001Hz) * when under stress. Lets double check it here and ignore if not valid. */ - g_curSamFreq48000Family = i_tmp % 48000 == 0; - curSamFreq44100Family = i_tmp % 44100 == 0; + curSamFreq48000Family = newSampleRate % 48000 == 0; + curSamFreq44100Family = newSampleRate % 44100 == 0; - if(g_curSamFreq48000Family || curSamFreq44100Family) + (curSamFreq48000Family || curSamFreq44100Family) { - g_curSamFreq = i_tmp; +#if 0 + /* Original feedback implementation */ + + int newMasterClock; + g_curSamFreq = newSamplerate; if(g_curSamFreq48000Family) { - i_tmp = MCLK_48; + newMasterClock = MCLK_48; } else { - i_tmp = MCLK_441; + newMasterClock = MCLK_441; } - setG_curSamFreqMultiplier((g_curSamFreq*512*4)/i_tmp); + setG_curSamFreqMultiplier((g_curSamFreq*512*4)/newMasterClock); +#endif /* Instruct audio thread to change sample freq */ outuint(c_audioControl, SET_SAMPLE_FREQ); diff --git a/module_usb_audio/usb_buffer/usb_buffer.xc b/module_usb_audio/usb_buffer/usb_buffer.xc index 4827f616..01c4ddde 100644 --- a/module_usb_audio/usb_buffer/usb_buffer.xc +++ b/module_usb_audio/usb_buffer/usb_buffer.xc @@ -160,10 +160,13 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, XUD_ep ep_hid = XUD_InitEp(c_hid); #endif unsigned u_tmp; - unsigned sampleFreq = 0; + unsigned sampleFreq = DEFAULT_FREQ; + unsigned masterClockFreq = DEFAULT_MCLK_FREQ; unsigned lastClock = 0; unsigned clocks = 0; + long long clockcounter = 0; + #if (NUM_USB_CHAN_IN > 0) unsigned bufferIn = 1; @@ -172,6 +175,7 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, unsigned sofCount = 0; unsigned freqChange = 0; + unsigned mod_from_last_time = 0; #ifdef FB_TOLERANCE_TEST unsigned expected_fb = 0; #endif @@ -317,13 +321,21 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, sofCount = 0; clocks = 0; remnant = 0; + clockcounter = 0; /* Set g_speed to something sensible. We expect it to get over-written before stream time */ int min, mid, max; GetADCCounts(sampleFreq, min, mid, max); g_speed = mid<<16; - + if((MCLK_48 % sampleFreq) == 0) + { + masterClockFreq = MCLK_48; + } + else + { + masterClockFreq = MCLK_441; + } } /* Ideally we want to wait for handshake (and pass back up) here. But we cannot keep this * core locked, it must stay responsive to packets (MIDI etc) and SOFs. So, set a flag and check for @@ -400,17 +412,18 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, } else { - unsigned mask = MASK_16_13, usb_speed; - + unsigned usb_speed; GET_SHARED_GLOBAL(usb_speed, g_curUsbSpeed); +#if 0 + unsigned mask = MASK_16_13; + /* Original feedback implementation */ if(usb_speed != XUD_SPEED_HS) mask = MASK_16_10; /* Number of MCLKS this SOF, approx 125 * 24 (3000), sample by sample rate */ GET_SHARED_GLOBAL(cycles, g_curSamFreqMultiplier); cycles = ((int)((short)(u_tmp - lastClock))) * cycles; - cycles = (int) cycles >> 2; /* /4 */ /* Any odd bits (lower than 16.23) have to be kept seperate */ remnant += cycles & mask; @@ -436,9 +449,11 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, { int usb_speed; asm volatile("stw %0, dp[g_speed]"::"r"(clocks)); // g_speed = clocks - GET_SHARED_GLOBAL(usb_speed, g_curUsbSpeed); + + printhexln(clocks); + if (usb_speed == XUD_SPEED_HS) { (fb_clocks, unsigned[])[0] = clocks; @@ -455,6 +470,63 @@ void buffer(register chanend c_aud_out, register chanend c_aud_in, #endif clocks = 0; } +#else + /* Assuming 48kHz from a 24.576 master clock (0.0407uS period) + * MCLK ticks per SOF = 125uS / 0.0407 = 3072 MCLK ticks per SOF. + * expected Feedback is 48000/8000 = 6 samples. so 0x60000 in 16:16 format. + * Average over 128 SOFs - 128 x 3072 = 0x60000. + */ + + /* Number of MCLK ticks in this SOF period (E.g = 125 * 24.576 = 3072) */ + int count = (int) ((short)(u_tmp - lastClock)); + + unsigned long long full_result = count *64ULL * sampleFreq; + + clockcounter += full_result; + + /* Store MCLK for next time around... */ + lastClock = u_tmp; + + /* Reset counts based on SOF counting. Expect 16ms (128 HS SOFs/16 FS SOFS) per feedback poll + * We always count 128 SOFs, so 16ms @ HS, 128ms @ FS */ + if(sofCount == 128) + { + sofCount = 0; + + clockcounter += mod_from_last_time; + clocks = clockcounter / masterClockFreq; + mod_from_last_time = clockcounter % masterClockFreq; + + clocks <<=3; + +#ifdef FB_TOLERANCE_TEST + if (clocks > (expected_fb - FB_TOLERANCE) && + clocks < (expected_fb + FB_TOLERANCE)) +#endif + { + int usb_speed; + asm volatile("stw %0, dp[g_speed]"::"r"(clocks)); // g_speed = clocks + + GET_SHARED_GLOBAL(usb_speed, g_curUsbSpeed); + + //printhexln(clocks); + if (usb_speed == XUD_SPEED_HS) + { + (fb_clocks, unsigned[])[0] = clocks; + } + else + { + (fb_clocks, unsigned[])[0] = clocks>>2; + } + } +#ifdef FB_TOLERANCE_TEST + else + { + } +#endif + clockcounter = 0; + } +#endif sofCount++; }