{"id":748,"date":"2013-09-26T15:05:55","date_gmt":"2013-09-26T19:05:55","guid":{"rendered":"http:\/\/www.logicalzero.com\/blog\/?p=748"},"modified":"2014-05-23T01:14:48","modified_gmt":"2014-05-23T05:14:48","slug":"hanging-on-the-telephone-part-2-the-code","status":"publish","type":"post","link":"http:\/\/www.logicalzero.com\/blog\/?p=748","title":{"rendered":"Hanging on the Telephone, Part 2: the Code"},"content":{"rendered":"<p><a href=\"http:\/\/www.logicalzero.com\/blog\/wp-content\/uploads\/2013\/09\/dial+digispark.jpg\"><img loading=\"lazy\" class=\"alignleft size-thumbnail wp-image-746\" style=\"padding-right: 1em;\" alt=\"Rotary Dial w\/ Digispark\" src=\"http:\/\/www.logicalzero.com\/blog\/wp-content\/uploads\/2013\/09\/dial+digispark-150x150.jpg\" width=\"150\" height=\"150\" srcset=\"http:\/\/www.logicalzero.com\/blog\/wp-content\/uploads\/2013\/09\/dial+digispark-150x150.jpg 150w, http:\/\/www.logicalzero.com\/blog\/wp-content\/uploads\/2013\/09\/dial+digispark-300x300.jpg 300w, http:\/\/www.logicalzero.com\/blog\/wp-content\/uploads\/2013\/09\/dial+digispark.jpg 512w\" sizes=\"(max-width: 150px) 100vw, 150px\" \/><\/a>Turning a rotary telephone dial into a USB device was easy. As I (re-)discovered, the dial is basically just a pair of switches: a normally-open &#8216;dialing&#8217; switch, which closes while the dial is in motion, and a normally-closed &#8216;pulse&#8217; switch, which opens and closes the same number of times as the number dialed. All I needed to do was count the number of pulses that occur while the &#8216;dialing&#8217; switch is closed, then send a USB keypress event based on that number when the &#8216;dialing&#8217; switch opens again.<\/p>\n<p>I used a Digispark for this project, so the code reflects a few of its oddities. In order to cram software USB emulation onto a tiny microcontroller and still leave room for user code, they had to make some compromises. There are no interrupts available, and their own version of the <code>delay()<\/code> function needed to be used to keep everything in sync. The hardware side is also a little odd: because the Digispark&#8217;s main header doesn&#8217;t provide a ground connection, I just set one of the digital I\/O pins <code>LOW<\/code> and used that. This seemed like a hack at the time, but I later saw this technique on one of Digistump&#8217;s own lists of power user tips, so I don&#8217;t feel so bad.<br \/>\n<!--more--><br clear=\"both\">Here&#8217;s the code:<\/p>\n<pre class=\"lang:arduino decode:true \" title=\"RotaryKeypad_Digispark.ino\" >\/* \r\n Rotary \"Keypad\" (for Digispark)\r\n David Stokes, 2013\r\n*\/\r\n#include \"DigiKeyboard.h\"\r\n\r\n\/\/ 'Pulse' pin: normally closed, opens on pulse\r\n\/\/ This is one of the dial's blue wires.\r\nconst byte PULSE_PIN = 0;\r\n\r\n\/\/ 'Dialing' pin: closes while dial is in motion (either direction)\r\n\/\/ This is one of the dial's white wires.\r\nconst byte DIALING_PIN = 2;\r\n\r\n\/\/ A data pin used as a GND connection (for convenience)\r\n\/\/ This is the remaining blue and white wires from the dial.\r\nconst byte GND_PIN = 1; \r\n\r\n\/\/ Debounce time.\r\nconst unsigned long delayTime = 50;\r\n\r\n\/\/ Previous states of the inputs, to detect changes\r\nboolean lastPulse, lastDialing;\r\n\r\n\/\/ The number being dialed (i.e. pulse count)\r\nbyte number;\r\n\r\nvoid setup() {\r\n  \/\/ Set the pins as inputs, write HIGH to\r\n  \/\/ activate the internal pull-up.\r\n  pinMode(PULSE_PIN, INPUT);\r\n  digitalWrite(PULSE_PIN, HIGH);\r\n  pinMode(DIALING_PIN, INPUT);\r\n  digitalWrite(DIALING_PIN, HIGH);\r\n  \r\n  \/\/ Use one of the data pins as a ground\r\n  pinMode(GND_PIN, OUTPUT);\r\n  digitalWrite(GND_PIN, LOW);\r\n  \r\n  \/\/ Get the initial states of the switches\r\n  lastPulse = digitalRead(PULSE_PIN);\r\n  lastDialing = digitalRead(DIALING_PIN);\r\n}\r\n\r\n\r\nvoid loop() {\r\n  \/\/ This is supposed to help on some systems,\r\n  \/\/ so I'm just going to cargo-cult it in.\r\n  DigiKeyboard.sendKeyStroke(0);\r\n\r\n  boolean pulse = digitalRead(PULSE_PIN);\r\n  boolean dialing = digitalRead(DIALING_PIN);\r\n  \r\n  if (lastPulse &amp;&amp; !pulse) {\r\n    \/\/ PULSE_PIN changed HIGH to LOW\r\n    number++;\r\n    DigiKeyboard.delay(delayTime);\r\n  }\r\n  \r\n  if (!lastDialing &amp;&amp; dialing &amp;&amp; number) {\r\n    \/\/ DIALING_PIN changed from LOW to HIGH\r\n    \/\/ and number is greater than 0\r\n    number = number == 10 ? 0 : number;\r\n    DigiKeyboard.print(char(number + 48));\r\n    DigiKeyboard.delay(delayTime);\r\n    number = 0;\r\n  }\r\n  \r\n  lastPulse = pulse;\r\n  lastDialing = dialing;\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Turning a rotary telephone dial into a USB device was easy. As I (re-)discovered, the dial is basically just a pair of switches: a normally-open &#8216;dialing&#8217; switch, which closes while the dial is in motion, and a normally-closed &#8216;pulse&#8217; switch, which opens and closes the same number of times as the number dialed. All I [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[8],"tags":[41,16,45,30],"_links":{"self":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/748"}],"collection":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=748"}],"version-history":[{"count":9,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/748\/revisions"}],"predecessor-version":[{"id":763,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/748\/revisions\/763"}],"wp:attachment":[{"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=748"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=748"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.logicalzero.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=748"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}