Changeset 3598


Ignore:
Timestamp:
Mar 8, 2013, 3:22:11 AM (14 months 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.