Changeset 3598


Ignore:
Timestamp:
Mar 8, 2013, 2:22:11 AM (2 years ago)
Author:
wmb
Message:

Neonode touchscreen - added nonlinearity test.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpu/arm/olpc/nn-touchscreen.fth

    r3576 r3598  
    917917;
    918918
     919\ Nonlinearity test
     920
     921d# 2000 constant #pts-max
     922
     923#pts-max /w* value /buf
     9240 value xbuf
     9250 value ybuf
     9260 value #pts
     927
     928: alloc-bufs ( -- )
     929   /buf alloc-mem to xbuf
     930   /buf alloc-mem to ybuf
     931   0 to #pts
     932;
     933
     934: free-bufs ( -- )
     935   xbuf /buf free-mem
     936   ybuf /buf free-mem
     937   0 to #pts
     938;
     939
     940: +w@  ( adr index -- w )  wa+ w@  ;
     941: +w!  ( w adr index -- )  wa+ w!  ;
     942
     943: add-pt  ( w.x w.y -- ) 
     944   #pts #pts-max u<  if
     945      ybuf #pts +w!
     946      xbuf #pts +w!
     947      #pts 1+ to #pts
     948   else
     949      2drop
     950   then
     951;
     952
     953: list-pts ( -- )
     954   #pts 0  ?do
     955      i .  ." : "   xbuf i +w@ .  ybuf i +w@ .  cr
     956   loop
     957;
     958
     959: sum-over ( buf size -- sum )
     960   0 -rot  /w* bounds  ?do   ( sum )
     961      i w@ +                 ( sum' )
     962   /w +loop                  ( sum )
     963;
     964
     965\ Maximum values, assuming max-x = 1200, max-y = 900, #pts = 2000
     966\ max-x2  = 1200   * 1200 =     1,440,000
     967\ max-xy  = 1200   *  900 =     1,080,000
     968\ max-Sx  = 1200   * 2000 =     2,400,000
     969\ max-Sy  =  900   * 2000 =     1,800,000
     970\ max-Sx2 = max-x2 * 2000 = 2,880,000,000
     971\ max-Sxy = max-xy * 2000 = 2,160,000,000
     972
     973\ The max value for the denominator  Sx2 - (Sx)2/n  occurs when
     974\ half the samples are 0 and the other half are max-x
     975\ max-denom = max-Sx2 / 4 =   720,000,000
     976
     977\ A similar argument applies to the numerator, except that it
     978\ can be either negative or positive.  But its maximum absolute
     979\ value is of the same order of magnitude as max-denom
     980
     981\ calculate the sum over x^2 (a double int)
     982\ The maximum value is max-x * max-x * #pts
     983\ For max-x = 1200 and #pts = 2000, max-Sx2 is 2,880,000,000
     984: sum-x2  ( -- Sx2 )
     985   0  #pts 0  ?do  ( Sx2 )
     986      xbuf i +w@   ( Sx2 x )
     987      dup u* +     ( Sx2' )
     988   loop            ( Sx2 )
     989;
     990
     991\ calculate the sum over xy (a double int)
     992: sum-xy  ( -- Sxy )
     993   0  #pts 0  ?do   ( S )
     994      xbuf i +w@    ( S x )
     995      ybuf i +w@    ( S x y )
     996      u* +          ( S' )
     997   loop             ( S )
     998;
     999
     10000 value sum-x
     10010 value sum-y
     1002: linear-least-squares  ( -- intercept num den )
     1003   xbuf #pts sum-over to sum-x
     1004   ybuf #pts sum-over to sum-y
     1005
     1006   \ Slope numerator: SUM(xy) - (SUM(x)*SUM(y) / #pts)
     1007
     1008   \ Sx max is #pts * xmax
     1009   \ Sy max is #pts * ymax
     1010   \ (Sx * Sy)/#pts max is xmax * ymax * #pts
     1011   sum-x sum-y #pts */               ( Sx*Sy/#pts )
     1012   sum-xy swap  -                    ( num )
     1013
     1014   \ Slope denominator:  SUM(x^2) - (SUM(x)^2 / #pts)
     1015   sum-x sum-x #pts */               ( num Sx*Sx/#pts )
     1016   sum-x2 swap  -                    ( num den )
     1017   \ Avoid division by 0
     1018   dup 0=  if  1+  then              ( num den )
     1019
     1020   \ Calculate the intercept
     1021   2dup  sum-x #pts /  -rot */       ( num den  slope*Sx )
     1022
     1023   sum-y #pts /                      ( num den  slope*Sx mean-y )
     1024   swap -   -rot                     ( intercept  num den )
     1025;
     1026
     1027: do-point  ( x y -- )   2dup add-pt  dot  ;
     1028
     1029\ draw line across screen from left to right
     1030: line-in-x  ( intercept num den -- )
     1031   screen-w 0  do                 ( intercept num den )
     1032      3dup  i -rot  */  +         ( intercept num den point-y )
     1033      dup 1 screen-h within  if   ( intercept num den point-y )
     1034         i swap  dot              ( intercept num den )
     1035      else                        ( intercept num den point-y )
     1036         drop                     ( intercept num den )
     1037      then                        ( intercept num den )
     1038   loop                           ( intercept num den )
     1039   3drop                          ( )
     1040;
     1041\ draw line from top to bottom of screen
     1042: line-in-y  ( intercept num den -- )
     1043   swap rot                       ( den num intercept )
     1044   screen-h 0  do                 ( den num intercept )
     1045      3dup  i swap -              ( den num intercept den num y-b )
     1046      -rot */                     ( den num intercept point-x )
     1047      dup 1 screen-w within  if   ( den num intercept point-y )
     1048         i  dot                   ( den num intercept )
     1049      else                        ( den num intercept point-y )
     1050         drop                     ( den num intercept )
     1051      then                        ( den num intercept )
     1052   loop                           ( den num intercept )
     1053   3drop                          ( )
     1054;
     1055: draw-line  ( intercept num den color -- )
     1056   pixcolor !                     ( intercept num den )
     1057   2 pick abs  2 pick abs  >  if  line-in-y  else  line-in-x  then
     1058;
     1059
     10600 value err2
     1061: nonlinearity  ( intercept num den -- mean-sq-nonlinearity )
     1062   0 to err2             ( intercept num den )
     1063   #pts  0  ?do          ( intercept num den )
     1064      3dup               ( intercept num den  intercept num den )
     1065      xbuf i +w@         ( intercept num den  intercept num den  x )
     1066      -rot */  +         ( intercept num den  predicted-y )
     1067      ybuf i +w@ -       ( intercept num den  error )
     1068      dup *              ( intercept num den  error^2 )
     1069      err2 +  to err2    ( intercept num den  )
     1070   loop                  ( intercept num den )
     1071   3drop                 ( )
     1072   err2 #pts /           ( Serror2/#pts )
     1073;
     1074
     1075\ TODO:
     1076\ 1) Message and retry if slope and intercept not approximately correct
     1077\    slope can be checked with
     1078\       ( num den ) h# 10000 -rot */ LOW HIGH within
     1079\       ( expected slope is negative , so LOW and HIGH are negative )
     1080\ 2) Establish threshold for nonlinearity and fail if exceeded
     1081\ 3) Perhaps integrate the nonlinearity test with the targets test?
    9191082
    9201083: scribble
    921    ev(  ['] dot  ev  )ev
    922 ;
     1084   alloc-bufs
     1085   ev(
     1086      0 d# 27 at-xy  ." Follow the line.  Type a key to exit" cr
     1087      screen-h 6 -   screen-h negate  screen-w  blue  draw-line
     1088      ['] do-point ev 
     1089      linear-least-squares  ( intercept num den )
     1090      3dup red draw-line    ( intercept num den )
     1091      ." Nonlinearity: "  nonlinearity .d  cr
     1092      d# 5000 ms
     1093   )ev
     1094   free-bufs
     1095;
     1096
     1097\ : scribble
     1098\    ev(  ['] dot  ev  )ev
     1099\ ;
    9231100
    9241101
Note: See TracChangeset for help on using the changeset viewer.