Author: wmb Date: Wed Nov 14 08:31:04 2012 New Revision: 3424 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/3424
Log: OLPC ARM audio test - workaround channel-swapping problem (trac #12096). Also added some experimental code.
Modified: cpu/arm/olpc/sound.fth cpu/x86/pc/olpc/plot.fth dev/geode/ac97/selftest.fth dev/hdaudio/noiseburst.fth dev/hdaudio/test.fth
Modified: cpu/arm/olpc/sound.fth ============================================================================== --- cpu/arm/olpc/sound.fth Wed Nov 14 08:11:21 2012 (r3423) +++ cpu/arm/olpc/sound.fth Wed Nov 14 08:31:04 2012 (r3424) @@ -219,6 +219,7 @@ ; : master-rx ( -- ) h# 0c sspa@ h# 8004.0001 or h# 0c sspa! ; \ Master, on : slave-rx ( -- ) h# 0c sspa@ h# 8000.0001 or h# 0c sspa! ; \ Slave, on +: flush-rx ( -- ) h# 0c sspa@ h# 8000.0004 or h# 0c sspa! ; \ Hit the flush bit : disable-sspa-rx ( -- ) h# 0c sspa@ h# 8000.0004 or h# 4.0001 invert and h# 0c sspa! ;
: reset-tx ( -- ) h# 8000.0002 h# 8c sspa! ; @@ -260,6 +261,7 @@ ; : master-tx ( -- ) h# 8c sspa@ h# 8004.0001 or h# 8c sspa! ; \ Master, on : slave-tx ( -- ) h# 8c sspa@ h# 8000.0001 or h# 8c sspa! ; \ Slave, on +: flush-tx ( -- ) h# 8c sspa@ h# 8000.0004 or h# 8c sspa! ; \ Hit the flush bit : disable-sspa-tx ( -- ) h# 8c sspa@ h# 8000.0004 or h# 4.0001 invert and h# 8c sspa! ;
h# fc0 constant /audio-buf @@ -289,9 +291,14 @@ out-desc h# 30 adma! \ Link to first descriptor out-desc to my-out-desc ; + +0 value use-packmod? + : start-out-ring ( -- ) 1 h# 80 adma! \ Enable DMA completion interrupts - h# 0081.3020 h# 40 adma! \ 16 bits, pack, fetch next, enable, chain, hold dest, inc src + h# 0080.3020 \ 16 bits, fetch next, enable, chain, hold dest, inc src + use-packmod? if h# 1.0000 or then + h# 40 adma! ; : stop-out-ring ( -- ) h# 100000 h# 40 adma! 0 h# 80 adma! ;
@@ -304,17 +311,43 @@ : start-in-ring ( -- ) 1 h# 84 adma! \ Enable DMA completion interrupts \ h# 0081.3008 h# 44 adma! \ 16 bits, pack, fetch next, enable, chain, inc dest, hold src - h# 00a1.31c8 h# 44 adma! \ 16 bits, pack, fetch next, enable, chain, burst32, inc dest, hold src + + h# 00a0.31c8 \ 16 bits, fetch next, enable, chain, burst32, inc dest, hold src + use-packmod? if h# 1.0000 or then + h# 44 adma! ; : stop-in-ring ( -- ) h# 100000 h# 44 adma! 0 h# 84 adma! ;
+: unpack-move ( src dst packed-len -- ) + 1 rshift 0 ?do ( src dst ) + over i wa+ w@ ( src dst sample ) + over i la+ wa1+ w! ( src dst ) + loop ( src dst ) + 2drop ( ) +; + +: pack-move ( src dst packed-len -- ) + 1 rshift 0 ?do ( src dst ) + over i la+ wa1+ w@ ( src dst sample ) + over i wa+ w! ( src dst ) + loop ( src dst ) + 2drop ( ) +; + : copy-out ( -- ) - my-out-desc >r ( r: desc ) - out-len /audio-buf min ( this-len r: desc ) - dup r@ l! ( this-len r: desc ) - out-adr r@ la1+ l@ third move ( this-len r: desc ) - out-adr over + to out-adr ( this-len r: desc ) - out-len swap - to out-len ( r: desc ) + my-out-desc >r ( r: desc ) + use-packmod? if + out-len /audio-buf min ( this-packed-len r: desc ) + dup r@ l! ( this-packed-len r: desc ) + out-adr r@ la1+ l@ third move ( this-packed-len r: desc ) + else + out-len /audio-buf 2/ min ( this-packed-len r: desc ) + dup 2* r@ l! ( this-packed-len r: desc ) + out-adr r@ la1+ l@ third unpack-move ( this-packed-len r: desc ) + then + + out-adr over + to out-adr ( this-packed-len r: desc ) + out-len swap - to out-len ( r: desc ) out-len if r> 3 la+ l@ to my-out-desc else @@ -323,11 +356,16 @@ ;
: copy-in ( -- ) - in-len /audio-buf min ( this-len ) - my-in-desc 2 la+ l@ in-adr third move ( this-len ) - in-adr over + to in-adr ( this-len ) - in-len over - to in-len ( this-len ) - drop ( ) + use-packmod? if + in-len /audio-buf min ( this-packed-len ) + my-in-desc 2 la+ l@ in-adr third move ( this-packed-len ) + else + in-len /audio-buf 2/ min ( this-packed-len ) + my-in-desc 2 la+ l@ in-adr third pack-move ( this-packed-len ) + then + in-adr over + to in-adr ( this-packed-len ) + in-len over - to in-len ( this-packed-len ) + drop ( ) my-in-desc 3 la+ l@ to my-in-desc ;
@@ -567,7 +605,17 @@ in-adr0 i la+ w@ in-adr0 i wa+ w! loop ; -: out-in ( out-adr out-len in-adr in-len -- ) +code startit ( sspa-adr -- ) + set r0,#0x80f101f1 + set r1,#0x80f501f1 + str r0,[tos,#0x8c] + str r1,[tos,#0x0c] + pop tos,sp +c; +: startoutin ( -- ) disable-interrupts sspa-base startit enable-interrupts ; +: xstartoutin ( -- ) slave-tx master-rx ; + +: out-in0 ( out-adr out-len in-adr in-len -- ) open-out-in
to in-len0 to in-adr0 ( out-adr out-len ) @@ -578,7 +626,7 @@
\ Resetting the clock at this point seems to prevent intermittent channel \ reversal on reception. - audio-clock-on drop ( ) \ This will mess up any frequency settings +\ audio-clock-on drop ( ) \ This will mess up any frequency settings
setup-sspa-tx ( ) setup-sspa-rx ( ) @@ -591,7 +639,53 @@ start-in-ring ( ) start-out-ring ( )
+ xstartoutin +\ slave-tx ( ) +\ master-rx ( ) \ Now the clock is on + + true to playing? + + begin in-len playing? or while ( ) + in-ready? if copy-in then ( ) + playing? if ?end-playing then ( ) + repeat ( ) + disable-sspa-rx ( ) + disable-sspa-tx ( ) + + stop-in-ring + stop-out-ring + + reset-rx + reset-tx + + close-out-in + mono? if collapse-in then ( ) +; + +: out-in1 ( out-adr out-len in-adr in-len -- ) + open-out-in + + to in-len0 to in-adr0 ( out-adr out-len ) + to out-len to out-adr ( ) + + in-adr0 to in-adr ( ) + in-len0 mono? if 2* then to in-len + + \ Resetting the clock at this point seems to prevent intermittent channel + \ reversal on reception. +\ audio-clock-on drop ( ) \ This will mess up any frequency settings + + make-out-ring ( ) + copy-out ( ) \ Prefill the first Tx buffer + out-len if copy-out then ( ) \ Prefill the second Tx buffer + + setup-sspa-rx ( ) + make-in-ring ( ) + start-in-ring ( ) master-rx ( ) \ Now the clock is on + + start-out-ring ( ) + setup-sspa-tx ( ) slave-tx ( )
true to playing? @@ -613,6 +707,87 @@ mono? if collapse-in then ( ) ;
+d# 20 value audio-dly +: out-in2 ( out-adr out-len in-adr in-len -- ) + open-out-in + + to in-len0 to in-adr0 ( out-adr out-len ) + to out-len to out-adr ( ) + + in-adr0 to in-adr ( ) + in-len0 mono? if 2* then to in-len + + \ Resetting the clock at this point seems to prevent intermittent channel + \ reversal on reception. +\ audio-clock-on drop ( ) \ This will mess up any frequency settings + + setup-sspa-tx ( ) + setup-sspa-rx ( ) + + make-in-ring ( ) + make-out-ring ( ) + copy-out ( ) \ Prefill the first Tx buffer + out-len if copy-out then ( ) \ Prefill the second Tx buffer + + xstartoutin + + audio-dly us + flush-rx + flush-tx + start-in-ring ( ) + start-out-ring ( ) + + + true to playing? + + begin in-len playing? or while ( ) + in-ready? if copy-in then ( ) + playing? if ?end-playing then ( ) + repeat ( ) + disable-sspa-rx ( ) + disable-sspa-tx ( ) + + stop-in-ring + stop-out-ring + + reset-rx + reset-tx + + close-out-in + mono? if collapse-in then ( ) +; + +defer out-in ' out-in0 to out-in + +0 [if] +working recipe: only one out-in in test-common +out-in2 +disable-interrupts before audio-clock-on and enable after reset-rx +dly 73 us +read and discard rx fifo depth before flush-rx + +also works with dly 10 us +reliably swaps with dly 1 us +swaps with dly 5 +swap with dly 7 +not swap with dly 8 + +Hmmm, maybe the basic issue is the double out-in in test-common - +Try out-in0 using one out-in +Try out-in2 without read/discard fifo depth using one out-in + +Swap alternates every 10 or so us, flipping at about 8 or 9 mod 10 +An extra 2 samples appear ever 10 or so us, at about 1 or 2 mod 10 + +04 us is stable with swapping +14 us is stable with no swapping + +If you remove flush-rx from fr ( : fr 1c sspa@ foo ! flush-rx ; ) +swapping always happens - 04, 14, 24 us all swap + This is because when you flush-rx with fifo depth 2, 6, a, etc, + that loses an odd number of channel samples +[then] + 0 [if] \ Interactive test words for out-in h# 20000 constant tlen : xb load-base 1meg + ; @@ -730,6 +905,25 @@ fload ${BP}/dev/hdaudio/test.fth warning !
+: wro + wlan-reset-gpio# gpio-dir-in \ So it doesn't fight the cross-wire +; +: input-normal ( -- ) + \ Reconnect pin 36 to WLAN_RESET# + wlan-reset-gpio# af@ 7 invert and wlan-reset-gpio# af! + + \ Reconnect pin 26 back to SSPA1 I2S_DATA_IN + d# 28 af@ 7 invert and 1 or d# 28 af! +; +: input-from-lrclk ( -- ) + \ Move pin 26 from SSPA1 I2S_DATA_IN to SSPA2 I2S_DATA_IN + \ so it doesn't conflict with pin 36. + d# 28 af@ 7 invert and 3 or d# 28 af! + + \ Connect pin 36 to SSPA1 I2S_DATA_IN + wlan-reset-gpio# af@ 7 invert and 2 or wlan-reset-gpio# af! +; + finish-device
device-end
Modified: cpu/x86/pc/olpc/plot.fth ============================================================================== --- cpu/x86/pc/olpc/plot.fth Wed Nov 14 08:11:21 2012 (r3423) +++ cpu/x86/pc/olpc/plot.fth Wed Nov 14 08:31:04 2012 (r3424) @@ -30,7 +30,10 @@ screen-height wave-height 2* - pitch* frame-buffer-adr + ;
-: wave0 ( -- ) screen-height wave-height - ; +0 value wave# +: set-wave# ( n -- ) to wave# ; + +: wave0 ( -- ) screen-height wave# 2* 1+ wave-height * - ;
: clear-waveform ( -- ) bg
Modified: dev/geode/ac97/selftest.fth ============================================================================== --- dev/geode/ac97/selftest.fth Wed Nov 14 08:11:21 2012 (r3423) +++ dev/geode/ac97/selftest.fth Wed Nov 14 08:31:04 2012 (r3424) @@ -126,6 +126,14 @@ : copy-left-to-right ( adr len -- ) bounds ?do i w@ i wa1+ w! /l +loop ; +: copy-pack ( adr len -- ) + 0 ?do ( adr ) + dup i + w@ ( adr w ) + dup wljoin ( adr l ) + over i 2/ + l! ( adr ) + 8 +loop ( adr ) + drop ( ) +;
\ The recording data format is stereo, but usually there is only one mic. \ Depending on the CODEC used, the right channel of the recording is either @@ -140,16 +148,18 @@ d# -3 set-volume play ;
+0 value skip-sweep? : selftest ( -- error? ) open 0= if ." Failed to open /audio" cr true exit then wav-test record-len la1+ " dma-alloc" $call-parent to record-base - sweep-test + skip-sweep? 0= if sweep-test then mic-test record-base record-len la1+ " dma-free" $call-parent close false ; +alias st1 selftest
\ LICENSE_BEGIN \ Copyright (c) 2007 FirmWorks
Modified: dev/hdaudio/noiseburst.fth ============================================================================== --- dev/hdaudio/noiseburst.fth Wed Nov 14 08:11:21 2012 (r3423) +++ dev/hdaudio/noiseburst.fth Wed Nov 14 08:31:04 2012 (r3424) @@ -308,7 +308,7 @@ i <w@ 2 pick - h# 7fff min h# -7fff max i w! i wa1+ <w@ over - h# 7fff min h# -7fff max i wa1+ w! /l +loop ( mean ) - drop ( ) + 2drop ( ) ; : lose-6db ( adr len -- ) bounds ?do ( ) @@ -447,6 +447,9 @@ h# 21000 value /rb \ Mono (stereo for loopback) - 8100 for fixture, 21000 for case, : rb load-base 1meg + ;
+: pb+ pb wa1+ ; +: rb+ rb wa1+ ; + : d.. ( -- ) <# # # # # ascii . hold # # # # ascii . hold #s #> type space ; : find-max-mono ( -- ) pb rb /pb 2 / h# 100 - d# 160 d# 120 mono-covar-max .d max-covar d.. @@ -459,10 +462,28 @@ ;
: #samples ( -- n ) /pb 4 / h# 100 - ; -: left-range ( -- stereo-adr mono-adr #points ) pb rb #samples ; -: right-range ( -- stereo-adr mono-adr #points ) pb wa1+ rb #samples ; -: left-stereo-range ( -- stereo-adr mono-adr #points ) pb rb #samples ; -: right-stereo-range ( -- stereo-adr mono-adr #points ) pb wa1+ rb wa1+ #samples ; + +defer mono-rb ' rb to mono-rb + +defer left-rb ' rb to left-rb +defer right-rb ' rb+ to right-rb + +defer left-pb ' pb to left-pb +defer right-pb ' pb+ to right-pb + +: swap-lr-pb ( -- ) + ['] pb to right-pb + ['] pb+ to left-pb +; +: unswap-lr-pb ( -- ) + ['] pb to left-pb + ['] pb+ to right-pb +; + +: left-range ( -- stereo-adr mono-adr #points ) left-pb mono-rb #samples ; +: right-range ( -- stereo-adr mono-adr #points ) right-pb mono-rb #samples ; +: left-stereo-range ( -- stereo-adr mono-adr #points ) left-pb left-rb #samples ; +: right-stereo-range ( -- stereo-adr mono-adr #points ) right-pb right-rb #samples ;
: fixture-analyze-left ( -- ) left-range d# 146 d# 141 sm-covar-sum dnegate @@ -537,8 +558,8 @@ ; : calc-sm-impulse ( offset -- adr ) \ offset is 0 for left or 2 for right ?alloc-impulse-buf - pb + rb #samples ( adr1 adr2 #samples ) - #impulse-response 0 do + if right-range else left-range then ( adr1 adr2 #samples ) + #impulse-response 0 do ( adr1 adr2 #samples ) 3dup swap i wa+ swap stereo-mono-covar ( adr1 adr2 #samples d.covar ) d# 500,000,000 m/mod nip ( adr1 adr2 #samples n.covar ) impulse-response i wa+ w! ( adr1 adr2 #samples ) @@ -547,9 +568,9 @@ impulse-response ( adr ) ; : calc-stereo-impulse ( offset -- adr ) \ offset is 0 for left or 2 for right - ?alloc-impulse-buf - dup pb + swap rb + #samples ( adr1 adr2 #samples ) - #impulse-response 0 do + ?alloc-impulse-buf ( offset ) + if right-stereo-range else left-stereo-range then ( adr1 adr2 #samples ) + #impulse-response 0 do ( adr1 adr2 #samples ) 3dup swap i la+ swap stereo-covar ( adr1 adr2 #samples d.covar ) d# 50,000,000 m/mod nip ( adr1 adr2 #samples n.covar ) impulse-response i wa+ w! ( adr1 adr2 #samples ) @@ -575,7 +596,12 @@
\ This version puts the tone first into the left channel for \ half the time, then into the right channel for the remainder + +\ This version puts a tone at one frequency in the left channel +\ and a tone at twice that frequency in the right channel + : make-2tones ( adr len freq sample-rate -- ) + 2over erase ( adr len freq sample-rate ) 2dup set-freq ( adr len freq sample-rate )
3 pick make-cycle drop ( adr len freq sample-rate ) @@ -607,19 +633,17 @@ pb wa1+ /pb -stereo-wmean pb /pb lose-6db pb /pb rb /rb - disable-interrupts +\ disable-interrupts ; : analyze-signal ( -- error? ) - enable-interrupts +\ enable-interrupts rb /rb fix-dc false ( error? ) analyze-left if ( error? ) - ." Left channel failure" cr 1+ then
analyze-right if - ." Right channel failure" cr 2+ then ;
Modified: dev/hdaudio/test.fth ============================================================================== --- dev/hdaudio/test.fth Wed Nov 14 08:11:21 2012 (r3423) +++ dev/hdaudio/test.fth Wed Nov 14 08:31:04 2012 (r3424) @@ -95,18 +95,25 @@ $call-analyzer ( ) " prepare-signal" $call-analyzer ( pb /pb rb /rb ) \ First shorter run lets the input channel settle - 2over 4 / 2over 4 / out-in ( pb /pb rb /rb ) +\ 2over 4 / 2over 4 / out-in ( pb /pb rb /rb ) out-in ( ) - " analyze-signal" $call-analyzer ( okay? ) + " analyze-signal" $call-analyzer ( error? ) ; +: .test-error ( error? -- error? ) + dup 1 and if ." Left channel failure" cr then + dup 2 and if ." Right channel failure" cr then +; + false value plot? \ Set to true to plot the impulse response, for debugging : plot-impulse ( adr -- ) d# 600 ( adr #samples ) - " 0 set-fg h# ffffffff set-bg single-drawing clear-drawing wave" evaluate - key ascii d = if debug-me then + " 0 set-fg h# ffffffff set-bg single-drawing ( clear-drawing ) wave" evaluate +\ key ascii d = if debug-me then ; +: plot-impulse0 ( adr -- ) 0 " set-wave#" $call-screen plot-impulse ; +: plot-impulse1 ( adr -- ) 1 " set-wave#" $call-screen plot-impulse ;
-: test-with-case ( -- ) +: test-with-case ( -- error? ) \ " setup-case" $call-analyzer \ xxx - this needs to use the internal speakers and mic even though the loopback cable is attached true to force-speakers? true to force-internal-mic? @@ -114,11 +121,11 @@ input-test-settings mono output-test-settings case-test-volume set-volume ." Testing internal speakers and microphone" cr - " setup-case" test-common + " setup-case" test-common .test-error false to force-speakers? false to force-internal-mic? plot? if - 0 " calc-sm-impulse" $call-analyzer plot-impulse - 2 " calc-sm-impulse" $call-analyzer plot-impulse + 0 " calc-sm-impulse" $call-analyzer plot-impulse0 + 2 " calc-sm-impulse" $call-analyzer plot-impulse1 then ; : test-with-fixture ( -- error? ) @@ -127,22 +134,41 @@ input-test-settings mono output-test-settings fixture-test-volume set-volume \ -23 prevents obvious visible clipping ." Testing internal speakers and microphone with fixture" cr - " setup-fixture" test-common + " setup-fixture" test-common .test-error false to force-speakers? false to force-internal-mic? plot? if - 0 " calc-sm-impulse" $call-analyzer plot-impulse - 2 " calc-sm-impulse" $call-analyzer plot-impulse + 0 " calc-sm-impulse" $call-analyzer plot-impulse0 + 2 " calc-sm-impulse" $call-analyzer plot-impulse1 then ; +true value allow-swapping? +: ?try-swapped ( error? -- error?' ) + allow-swapping? 0= if exit then ( error? ) + dup if ( error? ) + " swap-lr-pb" $call-analyzer ( error? ) + " analyze-signal" $call-analyzer ( error? swapped-error? ) + " unswap-lr-pb" $call-analyzer ( error? swapped-error? ) + 0= if ( error? ) + \ If swapping left and right "fixes" the problem, we + \ don't report an error. This works around a hard-to-fix + \ random channel-swapping problem with Marvell MMP3. + ." Channel swap!" cr ( error? ) + drop false ( 0 ) + then ( error? ) + then ( error? ) +; : test-with-loopback ( -- error? ) mic-bias-off input-test-settings stereo output-test-settings loopback-test-volume set-volume ." Testing headphone and microphone jacks with loopback cable" cr - " setup-loopback" test-common + " setup-loopback" test-common ( error? ) + ?try-swapped + .test-error + plot? if - 0 " calc-stereo-impulse" $call-analyzer plot-impulse - 2 " calc-stereo-impulse" $call-analyzer plot-impulse + 0 " calc-stereo-impulse" $call-analyzer plot-impulse0 + 2 " calc-stereo-impulse" $call-analyzer plot-impulse1 then ;
openfirmware@openfirmware.info