[openfirmware] [commit] r3598 - cpu/arm/olpc

repository service svn at openfirmware.info
Fri Mar 8 03:22:11 CET 2013


Author: wmb
Date: Fri Mar  8 03:22:11 2013
New Revision: 3598
URL: http://tracker.coreboot.org/trac/openfirmware/changeset/3598

Log:
Neonode touchscreen - added nonlinearity test.

Modified:
   cpu/arm/olpc/nn-touchscreen.fth

Modified: cpu/arm/olpc/nn-touchscreen.fth
==============================================================================
--- cpu/arm/olpc/nn-touchscreen.fth	Thu Mar  7 10:10:51 2013	(r3597)
+++ cpu/arm/olpc/nn-touchscreen.fth	Fri Mar  8 03:22:11 2013	(r3598)
@@ -916,11 +916,188 @@
    ['] (.tsmsg) to .tsmsg
 ;
 
+\ Nonlinearity test
+
+d# 2000 constant #pts-max
+
+#pts-max /w* value /buf
+0 value xbuf
+0 value ybuf
+0 value #pts
+
+: alloc-bufs ( -- )
+   /buf alloc-mem to xbuf
+   /buf alloc-mem to ybuf
+   0 to #pts
+;
+
+: free-bufs ( -- )
+   xbuf /buf free-mem
+   ybuf /buf free-mem
+   0 to #pts
+;
+
+: +w@  ( adr index -- w )  wa+ w@  ;
+: +w!  ( w adr index -- )  wa+ w!  ;
+
+: add-pt  ( w.x w.y -- )  
+   #pts #pts-max u<  if
+      ybuf #pts +w! 
+      xbuf #pts +w! 
+      #pts 1+ to #pts
+   else
+      2drop
+   then
+;
+
+: list-pts ( -- )
+   #pts 0  ?do
+      i .  ." : "   xbuf i +w@ .  ybuf i +w@ .  cr
+   loop
+;
+
+: sum-over ( buf size -- sum )
+   0 -rot  /w* bounds  ?do   ( sum )
+      i w@ +                 ( sum' )
+   /w +loop                  ( sum )
+; 
+
+\ Maximum values, assuming max-x = 1200, max-y = 900, #pts = 2000
+\ max-x2  = 1200   * 1200 =     1,440,000
+\ max-xy  = 1200   *  900 =     1,080,000
+\ max-Sx  = 1200   * 2000 =     2,400,000
+\ max-Sy  =  900   * 2000 =     1,800,000
+\ max-Sx2 = max-x2 * 2000 = 2,880,000,000
+\ max-Sxy = max-xy * 2000 = 2,160,000,000
+
+\ The max value for the denominator  Sx2 - (Sx)2/n  occurs when
+\ half the samples are 0 and the other half are max-x
+\ max-denom = max-Sx2 / 4 =   720,000,000
+
+\ A similar argument applies to the numerator, except that it
+\ can be either negative or positive.  But its maximum absolute
+\ value is of the same order of magnitude as max-denom
+
+\ calculate the sum over x^2 (a double int)
+\ The maximum value is max-x * max-x * #pts
+\ For max-x = 1200 and #pts = 2000, max-Sx2 is 2,880,000,000
+: sum-x2  ( -- Sx2 )
+   0  #pts 0  ?do  ( Sx2 )
+      xbuf i +w@   ( Sx2 x )
+      dup u* +     ( Sx2' )
+   loop            ( Sx2 )
+;
+
+\ calculate the sum over xy (a double int)
+: sum-xy  ( -- Sxy )
+   0  #pts 0  ?do   ( S )
+      xbuf i +w@    ( S x )
+      ybuf i +w@    ( S x y )
+      u* +          ( S' )
+   loop             ( S )
+;
+
+0 value sum-x
+0 value sum-y
+: linear-least-squares  ( -- intercept num den )
+   xbuf #pts sum-over to sum-x
+   ybuf #pts sum-over to sum-y
+
+   \ Slope numerator: SUM(xy) - (SUM(x)*SUM(y) / #pts)
+
+   \ Sx max is #pts * xmax
+   \ Sy max is #pts * ymax
+   \ (Sx * Sy)/#pts max is xmax * ymax * #pts
+   sum-x sum-y #pts */               ( Sx*Sy/#pts )
+   sum-xy swap  -                    ( num )
+
+   \ Slope denominator:  SUM(x^2) - (SUM(x)^2 / #pts)
+   sum-x sum-x #pts */               ( num Sx*Sx/#pts )
+   sum-x2 swap  -                    ( num den )
+   \ Avoid division by 0
+   dup 0=  if  1+  then              ( num den )
+
+   \ Calculate the intercept
+   2dup  sum-x #pts /  -rot */       ( num den  slope*Sx )
+
+   sum-y #pts /                      ( num den  slope*Sx mean-y )
+   swap -   -rot                     ( intercept  num den )
+;
+
+: do-point  ( x y -- )   2dup add-pt  dot  ;
+
+\ draw line across screen from left to right
+: line-in-x  ( intercept num den -- )
+   screen-w 0  do                 ( intercept num den )
+      3dup  i -rot  */  +         ( intercept num den point-y )
+      dup 1 screen-h within  if   ( intercept num den point-y )
+         i swap  dot              ( intercept num den )
+      else                        ( intercept num den point-y )
+         drop                     ( intercept num den )
+      then                        ( intercept num den )
+   loop                           ( intercept num den )
+   3drop                          ( )
+;
+\ draw line from top to bottom of screen
+: line-in-y  ( intercept num den -- )
+   swap rot                       ( den num intercept )
+   screen-h 0  do                 ( den num intercept )
+      3dup  i swap -              ( den num intercept den num y-b )
+      -rot */                     ( den num intercept point-x )
+      dup 1 screen-w within  if   ( den num intercept point-y )
+         i  dot                   ( den num intercept )
+      else                        ( den num intercept point-y )
+         drop                     ( den num intercept )
+      then                        ( den num intercept )
+   loop                           ( den num intercept )
+   3drop                          ( )
+;
+: draw-line  ( intercept num den color -- )
+   pixcolor !                     ( intercept num den )
+   2 pick abs  2 pick abs  >  if  line-in-y  else  line-in-x  then
+;
+
+0 value err2
+: nonlinearity  ( intercept num den -- mean-sq-nonlinearity )
+   0 to err2             ( intercept num den )
+   #pts  0  ?do          ( intercept num den )
+      3dup               ( intercept num den  intercept num den )
+      xbuf i +w@         ( intercept num den  intercept num den  x )
+      -rot */  +         ( intercept num den  predicted-y )
+      ybuf i +w@ -       ( intercept num den  error )
+      dup *              ( intercept num den  error^2 )
+      err2 +  to err2    ( intercept num den  )
+   loop                  ( intercept num den )
+   3drop                 ( )
+   err2 #pts /           ( Serror2/#pts )
+;
+
+\ TODO:
+\ 1) Message and retry if slope and intercept not approximately correct
+\    slope can be checked with
+\       ( num den ) h# 10000 -rot */ LOW HIGH within
+\       ( expected slope is negative , so LOW and HIGH are negative )
+\ 2) Establish threshold for nonlinearity and fail if exceeded
+\ 3) Perhaps integrate the nonlinearity test with the targets test?
 
 : scribble
-   ev(  ['] dot  ev  )ev
+   alloc-bufs
+   ev(
+      0 d# 27 at-xy  ." Follow the line.  Type a key to exit" cr
+      screen-h 6 -   screen-h negate  screen-w  blue  draw-line
+      ['] do-point ev  
+      linear-least-squares  ( intercept num den )
+      3dup red draw-line    ( intercept num den )
+      ." Nonlinearity: "  nonlinearity .d  cr
+      d# 5000 ms
+   )ev
+   free-bufs
 ;
 
+\ : scribble
+\    ev(  ['] dot  ev  )ev
+\ ;
+
 
 0 value dx
 0 value dy



More information about the openfirmware mailing list