aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorAndrew Lehmer <alehmer@google.com>2017-04-26 14:58:59 -0700
committerAndrew Lehmer <alehmer@google.com>2017-04-26 14:58:59 -0700
commite76dcf96b0c451e46cddfa695de8feeb92533937 (patch)
treeed9a45d409f988f517e6c3f3a685cbf81ac45a5a /docs
parentbcf013dda8ffac9fd76937be6441b44bb9f3586f (diff)
downloadwalt-e76dcf96b0c451e46cddfa695de8feeb92533937.tar.gz
Import google/walt
Cloned from https://github.com/google/walt.git without modification. Bug: 36896528 Test: N/A
Diffstat (limited to 'docs')
-rw-r--r--docs/AudioLatency.md67
-rw-r--r--docs/ChromeOS.md44
-rw-r--r--docs/Development.md44
-rw-r--r--docs/DragLatency.md41
-rw-r--r--docs/Drag_screen_N5X.pngbin0 -> 121454 bytes
-rw-r--r--docs/Nexus5X_screen_transition.pngbin0 -> 48433 bytes
-rw-r--r--docs/PrivacyPolicy.md13
-rw-r--r--docs/ScreenLatency.md39
-rw-r--r--docs/TapLatency.md33
-rw-r--r--docs/Tap_screen_N7.pngbin0 -> 73625 bytes
-rw-r--r--docs/WALT_bottom_view.pngbin0 -> 923323 bytes
-rw-r--r--docs/WALT_drag_latency.jpgbin0 -> 67707 bytes
-rw-r--r--docs/WALT_icon.svg90
-rw-r--r--docs/WALT_photo.jpgbin0 -> 116400 bytes
-rw-r--r--docs/WALT_photo_audio.jpgbin0 -> 126490 bytes
-rw-r--r--docs/WALT_photo_audio_r07.jpgbin0 -> 120506 bytes
-rw-r--r--docs/WALT_r07_photo.jpgbin0 -> 67201 bytes
-rw-r--r--docs/WALT_stylus.jpgbin0 -> 48165 bytes
-rw-r--r--docs/usage/WALT_usage.md261
-rw-r--r--docs/usage/images/WALT_setup.pngbin0 -> 1172900 bytes
-rw-r--r--docs/usage/images/drag.pngbin0 -> 1938141 bytes
-rw-r--r--docs/usage/images/reprogram.jpgbin0 -> 82568 bytes
-rw-r--r--docs/usage/images/screenshot.pngbin0 -> 13913 bytes
-rw-r--r--docs/usage/images/tap.pngbin0 -> 226069 bytes
24 files changed, 632 insertions, 0 deletions
diff --git a/docs/AudioLatency.md b/docs/AudioLatency.md
new file mode 100644
index 0000000..feac41e
--- /dev/null
+++ b/docs/AudioLatency.md
@@ -0,0 +1,67 @@
+## Audio Latency Measurement
+
+Audio output latency as measured by WALT is the time that passes from the moment an application
+decides to output a tone until it can be detected via the headphone jack. Microphone latency is
+defined similarly.
+
+Low latency audio IO on Android can be achieved via JNI C/C++ code.
+Documentation and sample code can be found on the
+ [High Performance Audio website](http://googlesamples.github.io/android-audio-high-performance/).
+
+
+### Reported values
+
+We are trying to stick to the following (overlapping) principles
+1. Timestamp events as close to hardware as possible. Most events up the stack can be easily timed with software alone.
+1. Measure time intervals that are likely to have low variability.
+
+##### Playback
+
+In order to avoid warm up latency during audio playback it is
+[recommended to constantly enqueue buffers containing silence](http://googlesamples.github.io/android-audio-high-performance/guides/audio-output-latency.html#avoid-warm-up-latency).
+WALT app follows this pattern.
+
+The audio data buffers are enqueued in the
+[player callback](https://github.com/google/walt/blob/v0.1.6/android/WALT/app/src/main/jni/player.c#L107)
+and the latency reported by WALT app is the time from the
+[Enqueue() call](https://github.com/google/walt/blob/v0.1.6/android/WALT/app/src/main/jni/player.c#L123)
+until there is a detectable signal on the wire. Note that this does not include the time between the moment the app decided to output a tone until the Enqueue() call. This is somewhat counterintuitive but this time is deliberately omitted. In case of the WALT app code this time is likely be uniformly distributed between 0 and the length of the buffer (5 ms in case of Nexus 5) and therefore would contribute considerable variance but little interesting information if included in the reported latency.
+
+##### Recording
+The reported latency is the time from the moment the last frame in a buffer was recorded until the
+[recorder callback](https://github.com/google/walt/blob/v0.1.6/android/WALT/app/src/main/jni/player.c#L345)
+receiving that buffer is executed.
+
+TODO: Is the round trip latency expected to be Recording latency + Playback latency + one buffer length?
+
+### Sample measurements
+
+| Device | OS version | Buffer | Playback [ms] | Recording* [ms] |
+| :--- | :--- | :--- | ---: | ---: |
+| Nexus 5 | M4B30Z (6.0.1) | 240 frames @ 48 kHz = 5 ms | 27.6 | 2.5 |
+| Nexus 5X | NRD91P (7.0) | 192 frames @ 48 kHz = 4 ms | 14.9 | 3.5 |
+| Nexus 7 | LMY47Q (5.1) | 240 frames @ 48 kHz = 5 ms | 32.1 | 16.3 |
+| Nexus 9 | MMB29K (6.0.1) | 128 frames @ 48 kHz = 2.6 ms | 9.8 | 1.0 |
+| Nexus 6P | MHC19I (6.0.1) | 192 frames @ 48 kHz = 4 ms | 15.3 | 1.6 |
+| Pixel | NDE63P (7.1) | 192 frames @ 48 kHz = 4 ms | 8.9 | 1.7 |
+| Pixel XL | NDE63H (7.1) | 192 frames @ 48 kHz = 4 ms | 9.1 | 1.6 |
+
+\* WALT clock synchronization accuracy is about 1 ms hence the relative error for recording latency can be fairly high.
+
+#### Published round trip measurements
+Superpowered Inc. maintains an open source app for measuring round trip audio latency -
+[Superpowered Latency App](https://github.com/superpoweredSDK/SuperpoweredLatency).
+
+* [Audio round trip measurements published by Android group](https://source.android.com/devices/audio/latency_measurements.html#measurements)
+* [Audio round trip measurements published by Superpowered Inc.](http://superpowered.com/latency)
+
+
+### Hardware
+
+Audio signal for measuring microphone latency is generated as a square wave using the Teensy tone()
+function ([currently at 5 kHz](https://github.com/google/walt/blob/v0.1.6/arduino/walt/walt.ino#L310)).
+The signal is attenuated by a simple circuit similar to the
+[ChromeOS/Android audio loopback dongle](https://source.android.com/devices/audio/loopback.html).
+
+Audio output signal from the phone is detected when audio line voltage crosses a predefined
+threshold (currently about 65 mV).
diff --git a/docs/ChromeOS.md b/docs/ChromeOS.md
new file mode 100644
index 0000000..6dbf680
--- /dev/null
+++ b/docs/ChromeOS.md
@@ -0,0 +1,44 @@
+## Using WALT on ChromeOS
+
+WALT can be used on ChromeOS in two different modes:
+ 1. Via the [pywalt/walt.py](/pywalt/walt.py) command line script - for this mode refer to [pywalt/README.md](/pywalt/README.md)
+ 1. Using the [WALT Android app](https://play.google.com/store/apps/details?id=org.kamrik.latency.walt) and walt.py script as a bridge
+
+
+For either mode you will need to use a ChromeOS test image -
+[some pointers on how to get it installed](https://www.chromium.org/chromium-os/testing/autotest-developer-faq/ssh-test-keys-setup)
+
+Copy the [pywalt/](/pywalt) directory from WALT repo to the Chromebook. One option is to download a repo tarball directly from GitHub:
+
+```
+wget https://github.com/google/walt/archive/master.tar.gz
+tar -xzf master.tar.gz
+cd walt-master/pywalt
+./walt.py --help
+```
+
+
+
+Connect WALT to Chromebook's USB port and test the setup by running: `$ ./walt.py -t sanity` on the Chromebook.
+This continuously displays readings from WALT's sensors (press Ctrl-C to stop):
+```
+Starting sanity test
+q G:480 PD_screen:3 PD_laser:910 min-max: 480-480 3-3 910-910
+q G:514 PD_screen:3 PD_laser:896 min-max: 480-514 3-3 896-910
+q G:486 PD_screen:4 PD_laser:894 min-max: 480-514 3-4 894-910
+q G:509 PD_screen:4 PD_laser:891 min-max: 480-514 3-4 891-910
+...
+```
+The first reading `G` is the accelerometer, it should change when WALT is rotated.
+`PD_screen` and `PD_laser` are the light sensors (photodiodes), shading them or exposing to light should change their readings.
+
+
+### Using WALT Android app
+
+If you intend to run the android app, run walt.py in TCP bridge mode. This is needed because Android container on ChromeOS has no access to USB.
+ - `iptables -A INPUT -p tcp --dport 50007 -j ACCEPT`
+ - `./walt.py -t bridge`
+
+The script will respond with `Listening on port 50007`. It can be stopped by pressing Ctrl-C. At this point you should be able to use the WALT Android app as if it's running on a regular Android device. If you reset or reconnect the WALT device, you'll need to re-run the script (no need to re-run the iptables command).
+
+If you need to deploy your own version of WALT Android app, follow instruction in [Development.md](Development.md)
diff --git a/docs/Development.md b/docs/Development.md
new file mode 100644
index 0000000..369bce3
--- /dev/null
+++ b/docs/Development.md
@@ -0,0 +1,44 @@
+## Setting up for WALT Android app development
+
+In general WALT Android app has no special requirements but since WALT usually takes up the only available USB connector on the phone, the typical development using ADB via USB becomes difficult. Below are some options to overcome this problem.
+
+
+#### Using a USB hub and a USB Ethernet adapter
+
+ADB can work over TCP connections. The [official documentation](https://developer.android.com/studio/command-line/adb.html#wireless) assumes that the TCP connection is established over WiFi, but a wired Ethernet connection can be used in the same way and is reported to work much better with ADB. Android will recognize and use most USB-Ethernet adapters out of the box.
+
+1. With the phone connected you computer via USB, run `adb tcpip 5555` (you can replace 5555 with any port)
+1. Disconnect the phone from USB
+1. Connect a USB hub (preferably powered) to the phone using a [USB-C to USB-A-female adapter](https://store.google.com/product/usb_type_c_to_usb_standard_a_adapter)
+ or a USB-OTG adapter.
+1. Use the hub to connect WALT, Ethernet adapter and whatever other USB peripherals you might want to test using WALT
+
+Note, this setup is sensitive to the order in which you connect the different components and adapters, experiments with it.
+
+
+#### Using a ChromeOS device with Android
+
+A ChromeOS device with Android (e.g. Asus Flip) is another convenient option.
+
+Since Android on ChromeOS has no access to USB, it requires a TCP bridge script implemented in [walt.py](/pywalt/walt.py). Detailed instructions in [Chromeos.md](Chromeos.md).
+
+In order to set up your for Android development, use either the
+[official guide for Android development on ChromeOS](https://developer.android.com/topic/arc/index.html#setup).
+Or the following short list:
+
+1. Log in to Chromebook via a non-guest account, also avoid restricted corporate/managed accounts
+1. Go to settings, scroll down to Google Play Store and click enable
+1. Click Manage your Android preferences and enable ADB debugging like on a regular Android device:
+ 1. Click About device
+ 1. Keep tapping the build number until it says “You are now a developer” (7 taps)
+ 1. Go back and click on Developer options
+ 1. Enable ADB debugging
+1. Get your Chromebook connected to a network so it would be accessible from you workstation
+1. Switch Chromebook to terminal via ctrl+alt+f2 and log in as root
+1. Run `ifconfig` to get the ip address of eth0 (or wlan0 if using wireless)
+1. On your workstation, run `ssh root@ip_addr` to verify that Chromebook is accessible
+1. Run `adb connect ip_addr:22`. From this point on Android studio and adb on your workstation should treat the Chromebook just like a regular Android device
+1. Run the WALT TCP bridge (more details [here](ChromeOS.md))
+ 1. scp the pywalt folder from your workstation and run the following on the Chromebook:
+ 1. `iptables -A INPUT -p tcp --dport 50007 -j ACCEPT`
+ 1. `python walt.py -t bridge`
diff --git a/docs/DragLatency.md b/docs/DragLatency.md
new file mode 100644
index 0000000..3797e4e
--- /dev/null
+++ b/docs/DragLatency.md
@@ -0,0 +1,41 @@
+## Drag / scroll latency
+
+For detailed instructions on how to perform the measurement refer to the [usage doc](usage/WALT_usage.md#dragscroll-latency).
+
+For drag (or scroll) latency WALT uses a laser that shines across the touch device and hits a detector on the
+other side. The microcontroller monitors the state of the laser detector and reports (over usb) when
+the laser beam is broken. A finger dragged back and forth on a touchpad or touch screen
+and interrupts a laser beam. Touch events from the pad and laser events are then processed together
+to deduce the delay.
+
+A [video](https://plus.google.com/+FrancoisBeaufort/posts/XctAif2nv4U) showing the measurement
+performed using a robotic stylus.
+
+
+![Drag/scroll latency measurement](usage/images/drag.png)
+
+Sample measurements
+
+| Device | OS version | Drag latency [ms]|
+| :--- | :--- | ---: |
+| Nexus 5 | M4B30Z (6.0.1) | 18.4 |
+| Nexus 5X | NRD91P (7.0) | 18.9 |
+| Nexus 7 | LMY47Q (5.1) | 35.8 |
+| Nexus 9 | MMB29K (6.0.1) | 10.2 |
+
+
+## Drag latency calculation
+
+The app collects all the motion events reported by Android with their coordinates and timestamps. The plot on the screenshot below show the vertical coordinate as a function of time as seen by the app _y_(_t_).
+
+The red 'x' marks are points where the finger was at times _t<sub>i</sub>_ when the finger went into or out of the laser beam. The y distance between the two lines of x marks is roughly the thickness of the finger. For now consider only one of the lines, e.g. the upper one.
+
+Now imagine that the clocks timestamping the touch and the laser events diverge a little (this divergence is the latency we want to measure). The red 'x' marks would move along the graph. But half of them would move up and half down (corresponding to direction of the finger movement in that point) and therefore they would diverge in opposite directions from the relatively straight horizontal line you see on the screenshot.
+
+The WALT app finds a shift _S_ such that the standard deviation of _y_( _t<sub>i</sub>_ + _S_) is minimal - that is the 'x' marks are as close as possible to a horizontal straight line on the graph below. The reported number is the average of the two time shifts calculated separately for the upper and the lower lines (corresponding to two sides of the finger).
+
+This calculation that only looks at the _y_ coordinate assumes the laser beam is parallel to the _x_ axis and prefers no motion of the finger in the _x_ direction.
+
+The Python script used for ChromeOS employs a 2D extension of this method (implemented in [minimization.py](/pywalt/minimization.py)). This has the opposite requirement of some considerable spread of the collected _x_ coordinates.
+
+![Drag/scroll latency measurement results](Drag_screen_N5X.png)
diff --git a/docs/Drag_screen_N5X.png b/docs/Drag_screen_N5X.png
new file mode 100644
index 0000000..d82c5a7
--- /dev/null
+++ b/docs/Drag_screen_N5X.png
Binary files differ
diff --git a/docs/Nexus5X_screen_transition.png b/docs/Nexus5X_screen_transition.png
new file mode 100644
index 0000000..2d61083
--- /dev/null
+++ b/docs/Nexus5X_screen_transition.png
Binary files differ
diff --git a/docs/PrivacyPolicy.md b/docs/PrivacyPolicy.md
new file mode 100644
index 0000000..3e96e0c
--- /dev/null
+++ b/docs/PrivacyPolicy.md
@@ -0,0 +1,13 @@
+## WALT Android App Privacy Policy
+
+This file is required in order to comply with Google Play requirements for apps using sensitive permissions:
+https://play.google.com/about/privacy-security/additional-requirements/
+
+WALT app processes all data locally on the Android device and does not transmit any information via the Internet,
+unless you explicitly opt-in to upload test logs and results to our server in the app settings
+(when such functionality becomes available).
+
+If you choose to opt-in to uploading the logs, please note that the logs can (and likely will) become publicly available to all.
+
+WALT app needs the Internet permission on ChromeOS devices where USB is not available to Android apps
+and a TCP bridge is used instead.
diff --git a/docs/ScreenLatency.md b/docs/ScreenLatency.md
new file mode 100644
index 0000000..8a7f1a5
--- /dev/null
+++ b/docs/ScreenLatency.md
@@ -0,0 +1,39 @@
+## Screen latency
+
+WALT can detect when screen changes color between white and black using a photodiode.
+
+![Photo of bottom side of WALT](WALT_bottom_view.png)
+
+Because the screen refreshes at predefined intervals (typically 60 Hz), most drawing commands do not take effect immediately but are processes during the next frame render event. See [Choreographer.FrameCallback](https://developer.android.com/reference/android/view/Choreographer.FrameCallback.html). An in-depth explanation about Android graphics can be found in [this video](https://www.youtube.com/watch?v=Q8m9sHdyXnE).
+
+WALT Android app uses View.setBackgroundColor to change the color and reports the time from the beginning of the next frame rendering until the screen changes physically.
+
+The physical transition between colors is not instantaneous and may look very different depending on the direction - from black to white or white to black. Moreover some sections of the screen may update several milliseconds later than others. These details vary considerably between screen technologies and device models.
+
+Example of screen brightness as a function of time during transition from black to white (blue line) and from white to black (green line) on Nexus 5X. The horizontal lines show the thresholds used by WALT for timing the transition (see #80).
+![Example plot of brightness as a function of time](Nexus5X_screen_transition.png)
+
+### Sample measurements
+
+Example of log output on Nexus 7:
+```
+-------------------------------
+Median screen response latencies (N=100):
+Black to white: 47.3 ms (N=50)
+White to black: 50.2 ms (N=50)
+Average: 48.8 ms
+-------------------------------
+```
+
+
+All measurements below were taken with the device set to max brightness and WALT positioned in the middle of the screen.
+
+| Device | OS version | Blk->white [ms]| White->blk [ms]| Average [ms] |
+| :--- | :--- | ---: | ---: | ---: |
+| Nexus 5 | M4B30Z (6.0.1) | 53.5 | 62.6 | 58.1 |
+| Nexus 5X | NRD91P (7.0) | 60.7 | 75.4 | 68.1 |
+| Nexus 7 | LMY47Q (5.1) | 47.3 | 50.2 | 48.8 |
+| Nexus 9 | MMB29K (6.0.1) | 49.0 | 53.8 | 51.4 |
+
+
+
diff --git a/docs/TapLatency.md b/docs/TapLatency.md
new file mode 100644
index 0000000..a3f84ae
--- /dev/null
+++ b/docs/TapLatency.md
@@ -0,0 +1,33 @@
+## Tap latency
+
+ * [Video demonstration of tap latency measurement](https://www.youtube.com/watch?v=1xAReF75Cts&list=PLd6Fi7WgXfcCEJg1FDqNCoQfpWo7W3J5a&index=2)
+ * [Detailed instructions on how to perform the measurement in usage doc](usage/WALT_usage.md#tap-latency).
+
+WALT uses a “stylus” equipped with an accelerometer. The finger is imitated by a flat metal
+tip that is grounded, pretty much any rigid tip can be used as long as it triggers the touch sensor.
+When the stylus “collides” with touch screen the accelerometer senses a shock (above 3g) which is
+timestamped by the Teensy. In order to generate a similar shock when picking the stylus up from the
+screen, the conductive surface and the accelerometer are mounted on a button of a retractable pen.
+On the way up, the spring keeps the button in contact with the touch screen for the first few mm of
+motion. This allows the hand holding the main part of the pen to gain some speed to which the button is
+then abruptly accelerated generating an easily detectable shock.
+
+Linux [Multi Touch (MT)](https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt)
+implementation timestamps touch events in the kernel as they arrive from the hardware. On Android
+the MT events are then exposed in Java as
+[MotionEvent](http://developer.android.com/reference/android/view/MotionEvent.html)
+and include the kernel timestamp. For tap, the relevant MotionEvent types are
+ACTION_DOWN and ACTION_UP.
+
+Sample measurements
+
+| Device | OS version | ACTION_DOWN [ms]| ACTION_UP [ms]| Kernel to Java [ms] |
+| :--- | :--- | ---: | ---: | ---: |
+| Nexus 5 | M4B30Z (6.0.1) | 26.9 | 15.9 | 3.3 |
+| Nexus 5X | NRD91P (7.0) | 25.0 | 22.5 | 2.4 |
+| Nexus 7 | LMY47Q (5.1) | 29.6 | 31.0 | 1.4 |
+| Nexus 9 | MMB29K (6.0.1) | 18.7 | 19.9 | 1.3 |
+
+
+![Tap measurement](usage/images/tap.png)
+![Tap screenshot](Tap_screen_N7.png)
diff --git a/docs/Tap_screen_N7.png b/docs/Tap_screen_N7.png
new file mode 100644
index 0000000..d78fbae
--- /dev/null
+++ b/docs/Tap_screen_N7.png
Binary files differ
diff --git a/docs/WALT_bottom_view.png b/docs/WALT_bottom_view.png
new file mode 100644
index 0000000..c062047
--- /dev/null
+++ b/docs/WALT_bottom_view.png
Binary files differ
diff --git a/docs/WALT_drag_latency.jpg b/docs/WALT_drag_latency.jpg
new file mode 100644
index 0000000..00c0e46
--- /dev/null
+++ b/docs/WALT_drag_latency.jpg
Binary files differ
diff --git a/docs/WALT_icon.svg b/docs/WALT_icon.svg
new file mode 100644
index 0000000..533afad
--- /dev/null
+++ b/docs/WALT_icon.svg
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="512"
+ height="512"
+ viewBox="0 0 512.00001 512.00001"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.91 r"
+ sodipodi:docname="WALT_icon.svg"
+ inkscape:export-filename="/usr/local/google/home/kamrik/WALT_icon_512.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.7"
+ inkscape:cx="373.97175"
+ inkscape:cy="112.99496"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ units="px"
+ inkscape:window-width="1920"
+ inkscape:window-height="1147"
+ inkscape:window-x="0"
+ inkscape:window-y="720"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-540.36217)">
+ <g
+ id="g4206"
+ transform="matrix(1.1152147,0,0,1.1152147,-28.288187,-98.698129)">
+ <text
+ sodipodi:linespacing="125%"
+ id="text4136"
+ y="1000.7413"
+ x="28.311005"
+ style="font-style:normal;font-weight:normal;font-size:557.60229492px;line-height:125%;font-family:Sans;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:557.60229492px;line-height:125%;font-family:MathJax_Math;-inkscape-font-specification:'MathJax_Math, Italic';text-align:start;writing-mode:lr-tb;text-anchor:start"
+ y="1000.7413"
+ x="28.311005"
+ id="tspan4138"
+ sodipodi:role="line">δ</tspan></text>
+ <text
+ sodipodi:linespacing="125%"
+ id="text4169"
+ y="997.63953"
+ x="253.93924"
+ style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:631.93328857px;line-height:125%;font-family:MathJax_Math;-inkscape-font-specification:'MathJax_Math, Italic';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ y="997.63953"
+ x="253.93924"
+ id="tspan4171"
+ sodipodi:role="line">t</tspan></text>
+ </g>
+ </g>
+</svg>
diff --git a/docs/WALT_photo.jpg b/docs/WALT_photo.jpg
new file mode 100644
index 0000000..c5c5687
--- /dev/null
+++ b/docs/WALT_photo.jpg
Binary files differ
diff --git a/docs/WALT_photo_audio.jpg b/docs/WALT_photo_audio.jpg
new file mode 100644
index 0000000..90420fe
--- /dev/null
+++ b/docs/WALT_photo_audio.jpg
Binary files differ
diff --git a/docs/WALT_photo_audio_r07.jpg b/docs/WALT_photo_audio_r07.jpg
new file mode 100644
index 0000000..98b4268
--- /dev/null
+++ b/docs/WALT_photo_audio_r07.jpg
Binary files differ
diff --git a/docs/WALT_r07_photo.jpg b/docs/WALT_r07_photo.jpg
new file mode 100644
index 0000000..c3177fc
--- /dev/null
+++ b/docs/WALT_r07_photo.jpg
Binary files differ
diff --git a/docs/WALT_stylus.jpg b/docs/WALT_stylus.jpg
new file mode 100644
index 0000000..dec90cc
--- /dev/null
+++ b/docs/WALT_stylus.jpg
Binary files differ
diff --git a/docs/usage/WALT_usage.md b/docs/usage/WALT_usage.md
new file mode 100644
index 0000000..24fd990
--- /dev/null
+++ b/docs/usage/WALT_usage.md
@@ -0,0 +1,261 @@
+# WALT Setup
+
+WALT (**W**hat an **A**wesome **L**atency **T**ester) is a tool for testing latency on Android devices.
+This document will show you how to set up and use your WALT.
+
+About WALT:
+
+ * Source code: https://github.com/google/walt
+ * [Youtube playlist](https://www.youtube.com/playlist?list=PLd6Fi7WgXfcCEJg1FDqNCoQfpWo7W3J5a)
+ * [Android Developers blog post](http://android-developers.blogspot.com/2016/04/a-new-method-to-measure-touch-and-audio.html)
+
+## Prerequisites
+
+WALT kit:
+ * Assembled WALT PCB and base, with DIP socket for Teensy LC
+ * [Teensy LC](http://www.pjrc.com/teensy/teensyLC.html) inserted into DIP socket
+ * 3.5mm male-to-male TRRS cable
+ ([like this](http://www.infinitecables.com/audio-and-pro-audio-cables/3.5mm-cables/3.5mm-male-to-3.5mm-male-4c/3.5mm-male-to-3.5mm-male-4c-black/2ft-3.5mm-4c-male-to-male-28awg-ft4-black/))
+ * Pen modified to replace the top button by a male TS
+ * Optional: laser pointer for measuring touch drag latency
+
+If anything is missing from the list above, please contact the person from whom you received your WALT.
+
+A test device and cables:
+ * Android device with USB micro-B female or type C female and a 3.5mm headset jack
+ * USB OTG (On-The-Go) adapter for your Android device (Examples: [A female to C male](https://store.google.com/product/usb_type_c_to_usb_standard_a_adapter), [A female to micro-B male](https://www.amazon.com/Cable-Matters-Micro-USB-Adapter-6-Inch/dp/B00GM0OZ4O))
+ * USB [Micro-B male to A male](http://www.staples.com/Staples-6-USB-to-Micro-B-Cable-18809-/product_837384) (the usual one we used for everything before type-C)
+ * Laser pointer, if not supplied in the kit
+
+![WALT setup](images/WALT_setup.png)
+
+
+## Setup
+
+ * Install and run the [WALT Android App](https://play.google.com/store/apps/details?id=org.kamrik.latency.walt&hl=en)
+ * Connect WALT to the Android headset using the 3.5mm male to male TRRS cable
+ * Connect WALT to the Android USB port using the cables above. (see photo at top of doc)
+ * You may be prompted to grant the WALT app permission to use the USB, tap "OK"
+ * All 3 LEDs will light up when WALT receives power (see photo below), they will be turned off once the app synchronizes clocks with WALT.
+
+
+## Programming the WALT firmware
+
+1. Launch the app, the main screen is pictured below.
+1. Verify you have the [latest version](https://github.com/google/walt/blob/master/android/WALT/app/build.gradle#L13) installed by tapping on "View log"
+1. Tap "Clock sync" on main menu.
+1. Press the Teensy reset button (see photo below)
+1. Tap "Reprogram WALT"
+1. At this stage you will see several USB permission dialogs. Confirm them all by pressing OK. This is due to WALT presenting itself as different USB devices during reprogramming and normal operation
+1. All 3 LEDs will light briefly (see photo below)
+1. Tap "Reconnect"
+1. Verify that the WALT device has been programmed correctly by running one of the tests below
+
+![WALT app screenshot](images/screenshot.png "WALT app main screen")
+![Teensy reset and reprogram](images/reprogram.jpg "Click Teensy reset button then reprogram WALT from the app")
+
+
+Below is an example of WALT app log when it starts and successfully connects
+to a WALT device. Note the first line and make sure that you use the latest
+version. The last line means that the WALT device clock is behind the Android
+clock but by no more than 161 microseconds. Values about about 1000 us are a
+sign of clock synchronization problems.
+
+
+```
+WALT v0.1.5 (versionCode=6)
+WALT protocol version 4
+DEVICE INFO:
+ google/volantis/flounder:6.0.1/MMB29K/2419427:user/release-keys
+ Build.SDK_INT=23
+ os.version=3.10.40-ga54a4f4
+Requesting permission for USB device.
+Interface claimed successfully
+
+Synced clocks, maxE=161us
+```
+
+# Running the latency tests
+
+This section describes how to run each test and interpret the results.
+
+
+## Audio input latency (microphone)
+
+The Teensy will generate a pulse of audio data which will be received at the 3.5mm headset jack. The time delta between the audio pulse being generated and being received by the WALT application is measured.
+
+ * Tap "Audio latency"
+ * Tap the microphone icon in the top left
+ * Wait for results
+
+
+Below is the output of a test on Nexus 9. The last two lines show the 6 individual measurements and their median. The time measured here is the time that passed from the recording of the _last_ frame in the buffer and until the software callback fired. The length of the optimal buffer in time units can be calculated using the first two lines: 128 frames divided by 48kHz frame rate is about 2.67 ms.
+
+
+```
+Optimal frame rate is: 48000
+Optimal frames per buffer is: 128
+Audio engine created
+Audio recorder created; starting test
+Synced clocks, maxE=154us
+Beeped, reply: 1039241
+Processed: L_cb = 1.167 ms, L_eq = 171.558 ms, noisy frame = 16799
+...
+Beeped, reply: 13621259
+Processed: L_cb = 0.907 ms, L_eq = 203.991 ms, noisy frame = 14465
+Remote clock delayed between -30 and 892 us
+deltas: [1.1671666666666278, 1.1871666666666278, 0.984, 0.9981666666666279, 1.7278333333333722, 0.9071666666666278]
+Median audio recording latency 1.1 ms
+```
+
+## Audio output latency
+
+The WALT app will generate a pulse of audio data which will be transmitted over the 3.5mm headset jack and received by the Teensy. The time delta between audio being transmitted by the app and received by the Teensy is measured
+
+ * Set volume to maximum in Settings -> Sound
+ * Tap "Audio latency"
+ * Tap the play button ▶ in the top right
+ * Results are displayed in the log window, example below.
+
+```
+Beeping...
+Beeped, dtJ2N = 0.059 ms
+beep detected, total latency = 10.44, normal latency = 10.09, mInitiatedBeeps = 1, mDetectedBeeps = 1
+...
+Remote clock delayed between -53 and 349 us
+deltas: [10.439, 12.272, 11.708, 12.194, 12.919, 11.458, 12.985, 10.914, 10.935, 10.631]
+Median Java to native latency 0.006 ms
+Median total audio latency 11.6 ms
+Median callback to output time 9.9 ms
+```
+
+The callback to output time on the last line, 9.9 ms is the time from the execution of the
+[OpenSLES BufferQueue callback that enqueued the buffer](https://github.com/google/walt/blob/master/android/WALT/app/src/main/jni/player.c#L107)
+until the first frames of that buffer were detected by WALT device via the headphone jack.
+
+
+## Screen response latency
+
+ * Tap screen response
+ * Set screen brightness to maximum. On phones using PWM for screen backlight brightness control, yo man need to turn adaptive brightness off (settings -> Display -> Adaptive Brightness)
+ * Position WALT with the screen sensor looking at the screen (the light sensor recessed into the large plastic surface).
+ * Click start ▶
+ * The screen will blink some 20 times. The orange LED on the Teensy will also blink every time the bottom light sensor detects a change.
+ * Results are displayed in the log window
+
+```
+Starting screen response measurement
+Synced clocks, maxE=162us
+Blink count was: 0
+Synced clocks, maxE=857us
+Starting Listener
+======
+doBlink.run(), mInitiatedBlinks = 0 mDetectedBlinks = 0
+blink counts 1 1
+======
+...
+======
+doBlink.run(), mInitiatedBlinks = 20 mDetectedBlinks = 20
+Stopping Listener
+Listener stopped
+Remote clock delayed between -16 and 628 us
+deltas: [69.908, 53.902, 54.715, 50.867, 70.73, 50.188, 71.344, 85.259, 40.691, 68.554, 72.016, 51.666, 71.826, 51.234, 71.896, 52.131, 68.943, 51.768, 71.919, 48.812]
+Median latency 61.6 ms
+```
+
+At the time of this writing (WALT v0.1.5) the number reported on the last line
+of the log above is the time from a call to View.setBackgroundColor() until
+the measured screen brightness crosses a threshold
+[hard coded in WALT firmware](https://github.com/google/walt/blob/master/arduino/walt/walt.ino#L70).
+This has significant drawbacks and will change in future versions.
+
+
+
+## Tap latency
+
+[Video demonstration](https://www.youtube.com/watch?v=1xAReF75Cts&list=PLd6Fi7WgXfcCEJg1FDqNCoQfpWo7W3J5a&index=2)
+
+ * Disconnect the audio cable
+ * Insert the supplied stylus (pen with audio jack) into the WALT's audio connector
+ * Click "Tap Latency"
+ * Tap the black part of the screen with WALT's copper tape tip while holding by the pen (photo below). Repeat some 20-30 times. Try to keep WALT pressed against the screen for a bit longer than you would usually keep the finger on the glass during a momentary tap.
+ * Click the checkmark button (top left of the screen), results will be calculated and displayed
+
+WALT has an accelerometer that is used to detect when the copper tip collides with the glass. The copper tip is grounded and triggers the touch sensor. The stylus springy action helps generate a collision shock detectable by accelerometer on the way back, away from the glass.
+
+![Tap latency measurement](images/tap.png)
+
+In the log below the following abbreviations are used:
+ - p2k - physical to kernel - in most cases this is the interesting time.
+ - k2c - kernel to (java) callback
+
+
+```
+## Restarting tap latency measurement. Re-sync clocks ...
+Synced clocks, maxE=158us
+
+...
+
+ACTION_DOWN event received: Event: t=10269422 x=871.7 y=1026.1 slot=-1 num=0 ACTION_DOWN
+Received S reply: 10247405
+
+ACTION_DOWN: dt_p2k = 22.0 ms
+Ignoring ACTION_MOVE 11
+Ignoring ACTION_MOVE 12
+Ignoring ACTION_MOVE 13
+Ignoring ACTION_MOVE 14
+Ignoring ACTION_MOVE 15
+
+ACTION_UP event received: Event: t=10365071 x=871.7 y=1026.1 slot=-1 num=0 ACTION_UP
+Received S reply: 10348526
+
+ACTION_UP: dt_p2k = 16.5 ms
+
+...
+
+## Processing tap latency data
+Remote clock delayed between -60 and 93 us
+Counts: ACTION_DOWN 20 (bad 1), ACTION_UP 21 (bad 0), ACTION_MOVE 162
+
+ACTION_DOWN:
+[26.515, 22.017, 26.952, 29.363, 29.63, 26.624, 31.581, 26.565, 31.335, 26.83, 31.786, 14.702, 19.796, 20.626, 16.688, 18.001, 19.044, 20.261, 17.66, 26.044]
+[1.774, 0.872, 0.888, 0.948, 1.749, 1.781, 1.698, 1.375, 1.709, 1.985, 2.522, 0.994, 1.008, 0.813, 0.746, 1.289, 1.158, 1.093, 0.891, 3.755]
+Medians, p2k & k2c [ms]: 26.3 1.2
+
+ACTION_UP:
+[16.572, 19.515, 16.545, 18.724, 15.188, 14.682, 18.156, 11.69, 20.367, 15.135, 20.601, 44.948, 17.517, 129.513, 24.681, 21.21, 21.979, 22.805, 133.306, 23.876, 17.579]
+[2.161, 2.02, 1.761, 2.222, 1.228, 1.24, 1.48, 1.42, 1.315, 4.034, 1.279, 1.957, 1.041, 2.058, 2.903, 1.725, 0.99, 2.124, 1.398, 3.018, 0.945]
+Medians, p2k & k2c [ms]: 19.5 1.7
+
+```
+
+## Drag/scroll latency
+
+Drag latency is measured by dragging a finger up and down along the screen. The finger interrupts a laser beam positioned across the screen. By comparing the timings of those beam interruptions with Android touch events the WALT app calculates the delay.
+
+
+ * Position a laser pointer so that the beam crosses the screen roughly in the middle. A convenient method for positioning the laser pointer is by using modeling clay (plasticine)
+ * Place WALT on the other side so that the beam hits the WALT optical sensor looking sideways. A green LED (marked D3) will light up whenever the beam hits the sensor
+ * Click the start button ▶, a green animated line will start going up and down the screen
+ * Drag your finger on the screen, following the animated line
+ * The green counter in the top right corner counts how many times the laser sensor changed state. Each crossing of the beam add 2 to that counter. Continue until the counter shows at least 60
+ * Click the finish **✓**(check mark) button, results will be displayed in the black window
+
+![Drag/scroll latency measurement](images/drag.png)
+
+# Collecting Systrace logs
+
+WALT is able to log physical events as well as system events into systrace. This allows us to look at the system-level calls that occur between the application triggering a change and the WALT device receiving a physical response.
+
+ * In the WALT app go to Settings->General and check `Enable systrace logging`.
+ * On your workstation, follow the [instructions for systrace](https://developer.android.com/studio/profile/systrace-commandline.html) on the command line
+ * From the `android-sdk/platform-tools/systrace` directory, run `python systrace.py --walt`. If `--walt` is not recognized as an option, clone the latest version of [systrace repo](https://github.com/catapult-project/catapult) and from the `catapult/systrace/systrace` directory run `python run_systrace.py --walt`.
+ * Conduct a test through the WALT app. When the test is complete, you should see that TraceLogger wrote some events to a file.
+ * Press enter on your workstation to end the trace and pull the logs from the phone, and the traceview will be generated as HTML.
+
+
+# Troubleshooting
+
+ * Make sure your micro-USB cable is not power-only (can carry data). If it has a button to switch between data and no-data modes (e.g. the KAA cable), click the button.
+ * Make sure volume control on Android DUT is at maximum (update in settings -> sound while TRRS cable is inserted).
+ * Some devices use pulse width modulation (PWM) to control screen brightness. Disable adaptive screen brightness and set brightness manually to maximum.
diff --git a/docs/usage/images/WALT_setup.png b/docs/usage/images/WALT_setup.png
new file mode 100644
index 0000000..b253bf4
--- /dev/null
+++ b/docs/usage/images/WALT_setup.png
Binary files differ
diff --git a/docs/usage/images/drag.png b/docs/usage/images/drag.png
new file mode 100644
index 0000000..e7c81e4
--- /dev/null
+++ b/docs/usage/images/drag.png
Binary files differ
diff --git a/docs/usage/images/reprogram.jpg b/docs/usage/images/reprogram.jpg
new file mode 100644
index 0000000..97dcbbd
--- /dev/null
+++ b/docs/usage/images/reprogram.jpg
Binary files differ
diff --git a/docs/usage/images/screenshot.png b/docs/usage/images/screenshot.png
new file mode 100644
index 0000000..e53d9cd
--- /dev/null
+++ b/docs/usage/images/screenshot.png
Binary files differ
diff --git a/docs/usage/images/tap.png b/docs/usage/images/tap.png
new file mode 100644
index 0000000..0a988c8
--- /dev/null
+++ b/docs/usage/images/tap.png
Binary files differ