OLPC XO-4 - improved the reliability of the audio test:

a) Instead of the real random number generator, use a LFSR-based PRNG,
   with a polynomial that happens to give a good spectrum for acoustic
   testing with OLPC speakers.  In addition to working around a unit-
   dependent problem with the MMP3's hardware RNG, this also speeds up
   the test because the LFSR is faster than the hardware RNG.
b) Store 16-bit "random" values in the audio buffer instead of using
   32-bit random numbers and hoping that the top and bottom halves
   are uncorrelated.  This seems to give better decorrelation of left
   and right signals.
c) Hard-reset the audio subsystem by powering off/on the audio island
   between the acoustic and loopback tests, thus making the loopback
   test more repeatable.


git-svn-id: svn://coreboot.org/openfirmware@3623 1552c027-8020-0410-b4b5-a757f869b4ce
This commit is contained in:
Mitch Bradley 2013-03-25 22:36:14 +00:00
parent a35ee0afb7
commit 311899d7e2
7 changed files with 176 additions and 123 deletions

View File

@ -741,6 +741,15 @@ h# 10.0000 h# 8000 - h# 4000 - dictionary-size !
fload ${BP}/cpu/arm/saverom.fth \ Save the dictionary for standalone startup
fload ${BP}/forth/lib/lfsr.fth
0 value lfsr-state
: init-audio-noise ( -- )
random-long to lfsr-state
\ Use a polynomial with a 32-bit period
lfsr-polynomials d# 32 na+ @ to lfsr-poly
;
: audio-noise ( -- n ) lfsr-state lfsr-step dup to lfsr-state ;
fload ${BP}/dev/hdaudio/noiseburst.fth \ audio-test support package
\ Because visible doesn't work sometimes when calling back from Linux

View File

@ -182,6 +182,14 @@ true value use-audio-pll?
then
false
;
\ This is a grotesque workaround for a hardware problem. The audio
\ subsystem (SSPA + ADMA) works reasonably reliably right after the
\ audio island is powered on, but subsequent tries tend to get
\ confused about which channel is which, and possibly about the
\ initial SSPA FIFO contents. Resetting between test phases makes
\ the test work more reliably. Attempts to get help from the vendor,
\ over a long period of time, were unsuccessful.
: reset-audio ( -- ) audio-clock-off d# 50 ms audio-clock-on drop ;
: reset-rx ( -- ) h# 8000.0002 h# 0c sspa! ;

View File

@ -479,6 +479,8 @@ fload ${BP}/cpu/x86/pc/saveabs.fth
fload ${BP}/forth/lib/selstr.fth
fload ${BP}/cpu/x86/pc/olpc/via/padlock.fth \ Via security engine
alias init-audio-noise noop
alias audio-noise random-long
fload ${BP}/dev/hdaudio/noiseburst.fth \ audio-test support package
fload ${BP}/ofw/inet/loadtcp.fth

View File

@ -620,14 +620,18 @@ fload ${BP}/forth/lib/tones.fth
[then]
: prepare-signal ( -- out-adr, len in-adr,len )
init-audio-noise
\ Doing the noise 16 bits at a time does a better job
\ of decorrelating the channels compared to storing
\ a 32-bit "random" number
[ifdef] debug-analyzer?
debug-analyzer? if
pb /pb d# 1000 d# 48000 make-2tones
else
pb /pb bounds do random-long i l! /l +loop
pb /pb bounds do audio-noise i w! /w +loop
then
[else]
pb /pb bounds do random-long i l! /l +loop
pb /pb bounds do audio-noise i w! /w +loop
[then]
pb /pb -stereo-wmean
pb wa1+ /pb -stereo-wmean

View File

@ -227,6 +227,7 @@ true value allow-swapping?
: automatic-test ( -- )
analysis-parameters " set-analysis-parameters" $call-analyzer
acoustic-test
[ifdef] reset-audio reset-audio [then]
loopback-test
;
: selftest ( -- error? )

143
forth/lib/lfsr-memtest.fth Normal file
View File

@ -0,0 +1,143 @@
\ See license at end of file
purpose: Linear feedback shift register memory tests
[ifdef] arm-assembler
code lfsr-fill ( adr seed polynomial -- adr' )
\ tos:polynomial
ldmia sp!,{r0,r1} \ r0:seed r1:adr
mov r2,r0 \ r2:lfsr
begin
str r2,[r1],#4
movs r2,r2,lsr #1
eorcs r2,r2,tos
cmp r2,r0
= until
mov tos,r1
c;
code random-fill ( adr len data index polynomial -- )
ldmia sp!,{r1,r2,r3,r4} \ tos:poly r1:index r2:data r3:len r4:adr
movs r3,r3,lsr #2 \ Convert to longword count
nxteq
sub r0,r3,#1 \ r0:remaining count
\ r3:address-lfsr r4:data-lfsr r5:data-poly
set r5,#0x80200003 \ 32-bit polynomial
begin
\ Compute new data value with an LFSR step
movs r2,r2,lsr #1
eorcs r2,r2,r5
\ Compute new address index, discarding values >= len
begin
movs r1,r1,lsr #1
eorcs r1,r1,tos
cmp r1,r3
u< until
\ Write the "random" value to the "random" address (adr[index])
str r2,[r4,r1,lsl #2]
decs r0,#1
0= until
pop tos,sp
c;
code random-check ( adr len data index remain polynomial -- false | adr len data index remain true )
ldmia sp!,{r0,r1,r2,r3,r4} \ tos:poly r0:remain r1:index r2:data r3:len r4:adr
cmp r0,#0
moveq tos,#0 \ Return false
nxteq
mov r7,r3,lsr #2 \ Convert to longword count
set r5,#0x80200003 \ 32-bit polynomial
begin
\ Compute new data value with an LFSR step
movs r2,r2,lsr #1
eorcs r2,r2,r5
\ Compute new address index, discarding values >= len
begin
movs r1,r1,lsr #1
eorcs r1,r1,tos
cmp r1,r7
u< until
\ Read the value at the "random" address (adr[index])
ldr r6,[r4,r1,lsl #2]
\ Compare it to the calculated value
cmp r6,r2
decne r0,#1
stmnedb sp!,{r0,r1,r2,r3,r4} \ Push results
mvnne tos,#0 \ True on top of stack
nxtne
decs r0,#1
0= until
mov tos,#0
c;
[then]
: round-up-log2 ( n -- log2 )
dup log2 ( n log2 )
tuck 1 swap lshift ( log2 n 2^log2 )
> - ( log2' )
;
defer .lfsr-mem-error
: (.lfsr-mem-error) ( adr len data index remain -- adr len data index remain )
push-hex
." Error at address " 4 pick 2 pick la+ dup 8 u.r ( adr len data index remain err-adr )
." - expected " 3 pick 8 u.r ( adr len data index remain err-adr )
." got " l@ 8 u.r cr
pop-base
;
' (.lfsr-mem-error) to .lfsr-mem-error
: random-test ( adr len -- )
dup /l <= if 2drop exit then ( adr len #bits )
dup /l / round-up-log2 ( adr len #bits )
polynomials swap la+ l@ ( adr len polynomial )
3dup 1 1 rot random-fill ( adr len polynomial )
>r ( adr len r: polynomial )
1 1 third /l / 1- ( adr len data index remain r: polynomial )
begin ( adr len data index remain r: polynomial )
r@ random-check ( false | adr len data index remain true r: polynomial )
while ( adr len data index remain r: polynomial )
.lfsr-mem-error ( adr len data index remain r: polynomial )
repeat ( r: polynomial )
r> drop
;
\ LICENSE_BEGIN
\ Copyright (c) 2010 FirmWorks
\
\ Permission is hereby granted, free of charge, to any person obtaining
\ a copy of this software and associated documentation files (the
\ "Software"), to deal in the Software without restriction, including
\ without limitation the rights to use, copy, modify, merge, publish,
\ distribute, sublicense, and/or sell copies of the Software, and to
\ permit persons to whom the Software is furnished to do so, subject to
\ the following conditions:
\
\ The above copyright notice and this permission notice shall be
\ included in all copies or substantial portions of the Software.
\
\ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
\ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
\ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
\ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\
\ LICENSE_END

View File

@ -1,12 +1,7 @@
\ See license at end of file
purpose: Linear feedback shift register code and related memory tests
0 value lfsr-state
0 value lfsr-poly
: lfsr-step ( state -- state' )
dup 2/ swap 1 and if lfsr-poly xor then
;
[ifdef] arm-assembler
code lfsr-step ( state -- state' )
@ -17,89 +12,6 @@ code lfsr-step ( state -- state' )
eor tos,tos,r0
then
c;
code lfsr-fill ( adr seed polynomial -- adr' )
\ tos:polynomial
ldmia sp!,{r0,r1} \ r0:seed r1:adr
mov r2,r0 \ r2:lfsr
begin
str r2,[r1],#4
movs r2,r2,lsr #1
eorcs r2,r2,tos
cmp r2,r0
= until
mov tos,r1
c;
code random-fill ( adr len data index polynomial -- )
ldmia sp!,{r1,r2,r3,r4} \ tos:poly r1:index r2:data r3:len r4:adr
movs r3,r3,lsr #2 \ Convert to longword count
nxteq
sub r0,r3,#1 \ r0:remaining count
\ r3:address-lfsr r4:data-lfsr r5:data-poly
set r5,#0x80200003 \ 32-bit polynomial
begin
\ Compute new data value with an LFSR step
movs r2,r2,lsr #1
eorcs r2,r2,r5
\ Compute new address index, discarding values >= len
begin
movs r1,r1,lsr #1
eorcs r1,r1,tos
cmp r1,r3
u< until
\ Write the "random" value to the "random" address (adr[index])
str r2,[r4,r1,lsl #2]
decs r0,#1
0= until
pop tos,sp
c;
code random-check ( adr len data index remain polynomial -- false | adr len data index remain true )
ldmia sp!,{r0,r1,r2,r3,r4} \ tos:poly r0:remain r1:index r2:data r3:len r4:adr
cmp r0,#0
moveq tos,#0 \ Return false
nxteq
mov r7,r3,lsr #2 \ Convert to longword count
set r5,#0x80200003 \ 32-bit polynomial
begin
\ Compute new data value with an LFSR step
movs r2,r2,lsr #1
eorcs r2,r2,r5
\ Compute new address index, discarding values >= len
begin
movs r1,r1,lsr #1
eorcs r1,r1,tos
cmp r1,r7
u< until
\ Read the value at the "random" address (adr[index])
ldr r6,[r4,r1,lsl #2]
\ Compare it to the calculated value
cmp r6,r2
decne r0,#1
stmnedb sp!,{r0,r1,r2,r3,r4} \ Push results
mvnne tos,#0 \ True on top of stack
nxtne
decs r0,#1
0= until
mov tos,#0
c;
[then]
0 [if] \ This is for testing the period of various polynomials
code lfsr-period ( polynomial -- period )
\ tos:polynomial
@ -127,6 +39,11 @@ code lfsr-step ( state -- state' )
ax push
c;
[then]
[ifndef] lfsr-step
: lfsr-step ( state -- state' )
dup 2/ swap 1 and if lfsr-poly xor then
;
[then]
0 [if]
\ Given a list of bit numbers for the polynomial taps, compute the mask value
@ -146,7 +63,8 @@ c;
\ Polynomials for maximal length LFSRs for different bit lengths
\ The values come from the Wikipedia article for Linear Feedback Shift Register and from
\ http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf
create polynomials \ #bits period
create lfsr-polynomials
\ #bits period
h# 0 , \ 0 0
h# 1 , \ 1 1
h# 3 , \ 2 3
@ -181,38 +99,6 @@ h# 20000029 , \ 30 3fffffff
h# 48000000 , \ 31 7fffffff
h# 80200003 , \ 32 ffffffff
: round-up-log2 ( n -- log2 )
dup log2 ( n log2 )
tuck 1 swap lshift ( log2 n 2^log2 )
> - ( log2' )
;
defer .lfsr-mem-error
: (.lfsr-mem-error) ( adr len data index remain -- adr len data index remain )
push-hex
." Error at address " 4 pick 2 pick la+ dup 8 u.r ( adr len data index remain err-adr )
." - expected " 3 pick 8 u.r ( adr len data index remain err-adr )
." got " l@ 8 u.r cr
pop-base
;
' (.lfsr-mem-error) to .lfsr-mem-error
: random-test ( adr len -- )
dup /l <= if 2drop exit then ( adr len #bits )
dup /l / round-up-log2 ( adr len #bits )
polynomials swap la+ l@ ( adr len polynomial )
3dup 1 1 rot random-fill ( adr len polynomial )
>r ( adr len r: polynomial )
1 1 third /l / 1- ( adr len data index remain r: polynomial )
begin ( adr len data index remain r: polynomial )
r@ random-check ( false | adr len data index remain true r: polynomial )
while ( adr len data index remain r: polynomial )
.lfsr-mem-error ( adr len data index remain r: polynomial )
repeat ( r: polynomial )
r> drop
;
\ LICENSE_BEGIN
\ Copyright (c) 2010 FirmWorks
\