{"id":2507,"date":"2019-09-02T14:48:46","date_gmt":"2019-09-02T05:48:46","guid":{"rendered":"https:\/\/www.codedojo.com\/?p=2507"},"modified":"2020-06-11T22:41:00","modified_gmt":"2020-06-11T13:41:00","slug":"input-lag-fun-measuring-atari-2600-latency-from-controller-to-display-with-an-arduino","status":"publish","type":"post","link":"https:\/\/www.codedojo.com\/?p=2507","title":{"rendered":"Input lag fun &#8211; measuring Atari 2600 latency from controller to display with an Arduino"},"content":{"rendered":"<p><a href=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/blog_title.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2511\" src=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/blog_title.jpg\" alt=\"\" width=\"506\" height=\"285\" srcset=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/blog_title.jpg 506w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/blog_title-300x169.jpg 300w\" sizes=\"auto, (max-width: 506px) 100vw, 506px\" \/><\/a><\/p>\n<p>Input lag.\u00a0 It&#8217;s a catch-all name people use when talking about the latency that gets added in the various places between when you push a button and finally see results on your screen.<\/p>\n<p>Many (especially console) games these days are designed to hide it because the developers cannot predict the latency of the display device the player is using.<\/p>\n<p>There are often additional considerations such as video drivers, vsync, &#8220;Game mode&#8221; display options, refresh rate, back buffering and dealing with high latency wireless controllers.<\/p>\n<p>If I add 100 milliseconds of additional lag to Red Dead Redemption 2, I&#8217;d doubt you&#8217;d notice with its mushy-ass controls.\u00a0 But if you try that with old school platformers and bullet hells designed for ultra-low lag, well, it ain&#8217;t gonna be pretty.<\/p>\n<h1>If you&#8217;re skeptical of the difference input lag can make, try this:<\/h1>\n<div id=\"attachment_2510\" style=\"width: 810px\" class=\"wp-caption alignnone\"><a href=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/mario2.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-2510\" class=\"wp-image-2510 size-full\" src=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/mario2.jpg\" alt=\"\" width=\"800\" height=\"611\" srcset=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/mario2.jpg 800w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/mario2-300x229.jpg 300w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/mario2-768x587.jpg 768w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/mario2-624x477.jpg 624w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><\/a><p id=\"caption-attachment-2510\" class=\"wp-caption-text\">Super Mario Bros. 2 (Japan) is just mean. See that mushroom? It kills you!<\/p><\/div>\n<p>Play the murderous Super Mario Brothers 2 (Japan) directly from a Famicom on an old school CRT and then try the same thing on your Raspberry Pi, PC, or even the same NES console through an upscaler\/LCD tv.<\/p>\n<p>As you switch back and forth you&#8217;ll probably feel the difference.\u00a0 The game is more difficult and <em>less comfortable<\/em> with the extra lag.<\/p>\n<p><strong>It&#8217;s not just about reaction times<\/strong> &#8211; there is this thing your brain does where it&#8217;s forced to jump and move slightly earlier than the onscreen action.\u00a0 We can all automatically do it, sure, but it&#8217;s&#8230; different.\u00a0 It doesn&#8217;t feel as connected.\u00a0 It&#8217;s too.. I don&#8217;t know, milky.\u00a0 A lot depends on the number of frames missed as well as when the console polls. (for example, the Atari 2600 polls 30 times a second, during the vertical blank interrupt but )<\/p>\n<p>This goes for much of the 8 and 16 bit action content from consoles and computers of yesteryear.<\/p>\n<h1>So real hardware and CRTs are the only way to go for fast response controls?<\/h1>\n<p>Woah, settle down, I didn&#8217;t say that!\u00a0 Retro emulation is astonishing and with the right gear and settings it <em>should<\/em> be possible to match or even beat old-school latency in specific cases such as with <a href=\"https:\/\/docs.libretro.com\/guides\/runahead\/\">Run Ahead<\/a> on the NES.<\/p>\n<p>That said, I have not been able to do it yet with my setups.\u00a0 Additionally, there are sometimes trade-offs like screen tearing and visual artifacts when you&#8217;re aiming at ultra-low latency.\u00a0 I&#8217;m sure things will continue to improve given the recent focus on reducing input lag on both displays and controllers.<\/p>\n<p><em>(Note: I was going to say &#8220;twitch gaming&#8221;\u00a0 instead of &#8220;fast response controls&#8221; but I&#8217;m guessing that term is too ambiguous these days)<\/em><\/p>\n<h1>Measuring input lag accurately<\/h1>\n<p>Instead of getting lost in subjective testing by &#8220;feel&#8221;, let&#8217;s get scientific about it.\u00a0 For my purposes, I wanted to measure the exact latency between a button press on an Atari 2600 console and the display pixels changing.\u00a0 The full trip.<\/p>\n<p><em>&lt;disclaimer &#8211; I&#8217;m an electronics amateur and don&#8217;t know what I&#8217;m doing.\u00a0 Breaking stuff is how you learn, right?&gt;\u00a0<\/em><\/p>\n<p>I used a cheap Arduino Uno with an LCD\/button shield (they call things you stick on them shields, ok?) to do it.\u00a0 It&#8217;s so simple you don&#8217;t even need a breadboard!<\/p>\n<p><a href=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/lagmaster1.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-2508\" src=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/lagmaster1-768x1024.jpg\" alt=\"\" width=\"625\" height=\"833\" srcset=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/lagmaster1-768x1024.jpg 768w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/lagmaster1-225x300.jpg 225w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/lagmaster1-624x832.jpg 624w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/lagmaster1.jpg 1200w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><\/a><\/p>\n<h1>The light sensor<\/h1>\n<p>First I wired up an LDR (Light Dependent Resistor) to the board&#8217;s analog in pin A0, and connected the other end to the ground.\u00a0 We can now detect light with a analogRead(A0) command.\u00a0 Oh right, I also put a 100K resistor in there.<\/p>\n<p><a href=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/light_sensor.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-2509\" src=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/light_sensor.jpg\" alt=\"\" width=\"500\" height=\"726\" srcset=\"https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/light_sensor.jpg 500w, https:\/\/www.codedojo.com\/wp-content\/uploads\/2019\/09\/light_sensor-207x300.jpg 207w\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" \/><\/a><\/p>\n<p>To get the light sensor to physically stick on the screen (so it will hover over the pixels in question) I commandeered the suction cup that came in a iFixit kit and glue-gunned a rubber earbud cover to house it.<\/p>\n<p>Just nod and smile please, without commenting how there is glue everywhere and it looks ridiculous.<\/p>\n<p>My light sensor returns a number between 300 and 1024 or so.\u00a0 When stuck onto a monitor more like 800 to 1000 (black and white&#8230; black pixels still have a lot of light coming through I guess) but good enough.<\/p>\n<h1>Getting the Arduino Uno to push the Atari fire button digitally<\/h1>\n<p>Next I cut the cable off a broken Atari 2600 controller (it was a cheap clone from Ebay that I broken during a particularly exuberant C64 performance) and using <a href=\"https:\/\/atariage.com\/forums\/topic\/269266-trying-to-mod-a-quick-shot-1-for-the-7800\/?do=findComment&amp;comment=3834160\">this diagram<\/a> figured out the wires for the fire button and ground.<\/p>\n<p>I connected the controller ground wire to the Arduino&#8217;s ground pin, then the fire button wire in the D2 pin.\u00a0 I can now control the fire button like this:<\/p>\n<pre> pinMode(C_ATARI_BUTTON_PIN, OUTPUT);\n\n\/\/To turn button off\n digitalWrite(C_ATARI_BUTTON_PIN, HIGH);\n\n\/\/To turn the button on\n digitalWrite(C_ATARI_BUTTON_PIN, LOW);<\/pre>\n<p>I didn&#8217;t know you could directly wire it like that, mixing the 5v high signals from both the Atari and Arduino, but whatever, it works.\u00a0 Read this <a href=\"https:\/\/atariage.com\/forums\/topic\/266868-joystick-pinout-question\/?do=findComment&amp;comment=3788375\">post by BigO<\/a> to understand why setting it to LOW causes it to be &#8220;on&#8221; as far as the Atari is concerned.<\/p>\n<p>I noticed if the Arduino is NOT powered buts its joystick lead is plugged into the Atari, there are weird video glitches.\u00a0 I guess due to the unpowered Arduino draining amperage from the fire button lead, enough to cause fluctuations in the entire system?\u00a0 Ignore any smoke, move along.<\/p>\n<p>Adding support for more buttons would be as easy as plugging the additional wires into more Arduino pins.\u00a0 In the picture of the whole device above, it&#8217;s only the Red and Yellow wires I&#8217;m using, the blue\/white ones aren&#8217;t connected to anything.<\/p>\n<h1>The code<\/h1>\n<p>All that&#8217;s left is to write some code so the device can be controlled with the LCD shield&#8217;s buttons.\u00a0 \u00a0Here&#8217;s what those buttons do:<\/p>\n<ul>\n<li>Select &#8211; Show current light level reading<\/li>\n<li>Left &#8211; Nothing<\/li>\n<li>Up &#8211; Increase light change timing required to trigger<\/li>\n<li>Down &#8211; decrease light change time required to trigger<\/li>\n<li>Right &#8211; Start measuring.\u00a0 (Will cause the Atari&#8217;s fire button to click, then it waits until the light has changed enough.<\/li>\n<\/ul>\n<p><a href=\"http:\/\/www.codedojo.com\/files\/LagMaster.ino\">Here is the code for the Arduino sketch.<\/a> (I did all this in a messy few hours, don&#8217;t judge me)<\/p>\n<p><strong>Tip:<\/strong> I leave the button in the &#8220;pressed&#8221; state for 100 MS (I guess 33.333 MS would technically be enough for an Atari 2600, but whatever, doesn&#8217;t matter), and I look for about a 60 change from the light sensor to count as &#8220;hey, this part of the screen has\u00a0 definitely changed, stop the timer, we&#8217;re there&#8221;.<\/p>\n<blockquote class=\"twitter-tweet\" data-width=\"550\" data-dnt=\"true\">\n<p lang=\"en\" dir=\"ltr\">Blog: Input lag fun &#8211; measuring Atari 2600 latency from controller to display with an Arduino <a href=\"https:\/\/t.co\/XEMarxuzSJ\">https:\/\/t.co\/XEMarxuzSJ<\/a> <a href=\"https:\/\/t.co\/KlpYkLMTow\">pic.twitter.com\/KlpYkLMTow<\/a><\/p>\n<p>&mdash; Seth A. Robinson (@rtsoft) <a href=\"https:\/\/twitter.com\/rtsoft\/status\/1168405569520095232?ref_src=twsrc%5Etfw\">September 2, 2019<\/a><\/p><\/blockquote>\n<p><script async src=\"https:\/\/platform.twitter.com\/widgets.js\" charset=\"utf-8\"><\/script><\/p>\n<p>You can&#8217;t see it, but I&#8217;m pulling the Reset button on the Atari 2600 between tests so it&#8217;s on the right screen for the Arduino to send the &#8220;fire button&#8221; when I start a measurement.\u00a0 The game is Xenophobe.<\/p>\n<h1>Testing results:\u00a0 Atari 2600 console on CRT<\/h1>\n<ul>\n<li>Sensor in the upper left of the CRT return between 0 and 33 MS.<\/li>\n<li>Sensor in the buttom left of the CRT returns between 16 and 33 MS.<\/li>\n<\/ul>\n<p>This seems about what it should be, give or take 1 MS or so?\u00a0 It&#8217;s possible to get near 0 MS from button push to pixel display.\u00a0 I mean, I guess I knew it was, but it&#8217;s still fun to measure it.<\/p>\n<p>So why did I use the Xenophobe cartridge?\u00a0 Because it&#8217;s just the first game I found that clearly changes a dark block of the screen to a lighter color instantly when a button is pressed. (I wouldn&#8217;t want to use light to dark due to possible ghosting issues)<\/p>\n<p>There are probably homebrew roms built to do this for most system but I couldn&#8217;t find one with a cursory googling so here we go.<\/p>\n<h1>Testing results: Atari 2600 console with upscaler, various video switchers &amp; old Dell LCD monitor<\/h1>\n<ul>\n<li>Sensor in upper left of panel returns between 79 and 130 MS<\/li>\n<\/ul>\n<p>Ouch.\u00a0 Well, I knew it wasn&#8217;t going to be good, I can only imagine how bad it would be with a Pi or something instead.\u00a0 Anyway, I won&#8217;t go serious into testing (I&#8217;m no <a href=\"https:\/\/www.youtube.com\/user\/mylifeingaming\/videos\">My life In Gaming<\/a>)\u00a0 or my exact hardware in my retro area (<a href=\"https:\/\/www.codedojo.com\/?p=2426\">it&#8217;s weird&#8230;<\/a>), I just want to be ready for when I need to compare latency on my setups down the road.<\/p>\n<h1>Conclusion &amp; random thoughts<\/h1>\n<p>I&#8217;d like to test the full &#8220;controller to display&#8221; latency on my Raspberry Pi &amp; main computer setups as well but I think that means I&#8217;d have to hack into a 360 controller so the Arduino can control the button as we did with the Atari.\u00a0 \u00a0Maybe later.<\/p>\n<p>Would be wondrous to get to a place where we could once again write games counting on the C2S\u00a0 (controller to screen) lag being low and knowing everybody is getting the best experience.<\/p>\n<p>You always want to know your server ping time when you play online, right?<\/p>\n<p>Well, maybe we could start building in latency test systems so a console (using its camera? or maybe all TV\/monitors&#8217;s should have a tiny light sensor in a corner that could be queried via HDMI) would know its own latency (both visual and auditory) and a game could use that data to automatically sync up stuff for rhythm games, adjust game timing of quick-time events, or even to just display a &#8220;congratulations, you&#8217;ve got horrible latency&#8221; warning if needed.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Input lag.\u00a0 It&#8217;s a catch-all name people use when talking about the latency that gets added in the various places between when you push a button and finally see results on your screen. Many (especially console) games these days are designed to hide it because the developers cannot predict the latency of the display device [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[31,6],"tags":[],"class_list":["post-2507","post","type-post","status-publish","format-standard","hentry","category-arduino","category-tech-tips"],"_links":{"self":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts\/2507","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2507"}],"version-history":[{"count":14,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts\/2507\/revisions"}],"predecessor-version":[{"id":2593,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=\/wp\/v2\/posts\/2507\/revisions\/2593"}],"wp:attachment":[{"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2507"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2507"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.codedojo.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2507"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}