<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Is it possible to read a data pin with PPI? (PS/2 bit banging using PPI)</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/103840/is-it-possible-to-read-a-data-pin-with-ppi-ps-2-bit-banging-using-ppi</link><description>Hi, 
 I am trying to implement a PS/2 bit banging driver. My initial attempt used the GPIO library and interrupts, but unfortunately the interrupts are not fast enough and oftentimes there are transmission errors due to missed bits. 
 Now I am exploring</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 21 Sep 2023 04:39:54 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/103840/is-it-possible-to-read-a-data-pin-with-ppi-ps-2-bit-banging-using-ppi" /><item><title>RE: Is it possible to read a data pin with PPI? (PS/2 bit banging using PPI)</title><link>https://devzone.nordicsemi.com/thread/446974?ContentTypeID=1</link><pubDate>Thu, 21 Sep 2023 04:39:54 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e3d2ec3e-c87f-4a54-8633-60b6190edb25</guid><dc:creator>hmolesworth</dc:creator><description>&lt;p&gt;Since the PS2 keyboard (internal) data transitions occur on the clock +ve edge and are subsequently sampled by an external device on the clock -ve edge the data line can be used as a single edge-per-bit signal to capture a counter/timer value via PPI as the data transition is known to be clean.&lt;/p&gt;
&lt;p&gt;One counter counts the Clock transitions from 0-10 (11 bits) and at the last bit captures a time giving the 11-bit clock period, which although varies between keyboards is very consistent over the 11-bits making up a single transmission for a given keyboard. Since the data is cleanly changed on the +ve edge of the clock only a single data transition occurs for each bit and this edge can be used to capture a timer value using the 5 x CC registers on (say) timer 4. There are a maximum of 5 negative transitions worst case, odd parity and 0xAA data value so 10 CC registers are required which means reusing registers and storing the captured values within the interrupt.&lt;/p&gt;
&lt;p&gt;Once each edge time has been captured for a complete single character, the 11-bit time can be used to accurately decode the actual character. Edit: Updated for both edge detection and time detection&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// 11-bit Data bit changes on clock +ve edge, sample value on clock -ve edge
//
// Standard character 0x21 - Single sample, single timer (T4), requires reload
//
// Idle &amp;#39;Start&amp;#39;Bit 0&amp;#39;Bit 1&amp;#39;Bit 2&amp;#39;Bit 3&amp;#39;Bit 4&amp;#39;Bit 5&amp;#39;Bit 6&amp;#39;Bit 7&amp;#39;Par  &amp;#39;Stop | Idle
//      |     |     |     |     |     |     |     |     |     |     |     | 11-Bit Framing
//      |     |     |     |     |     |     |     |     |     |     |     |
//         0     1     2     3     4     5     6     7     8     9     10   Counter 3
//      |     |     |     |     |     |     |     |     |     |     |     |
// --------+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--------
//         |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  | Clock
//         |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
//         +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+  +--+
//      |     |     |     |     |     |     |     |     |     |     |     |
// Idle &amp;#39;Start&amp;#39;Bit 0&amp;#39;Bit 1&amp;#39;Bit 2&amp;#39;Bit 3&amp;#39;Bit 4&amp;#39;Bit 5&amp;#39;Bit 6&amp;#39;Bit 7&amp;#39;Par  &amp;#39;Stop | Idle
// -----+     +-----+                       +-----+           +-----+-----+--------
//      |     |     |                       |     |           |
//      |     |     |                       |     |           |             Data Normal
//      +-----+     +-----+-----+-----+-----+     +-----+-----+
//
//      +-----+     +-----+-----+-----+-----+     +-----+-----+
//      |     |     |                       |     |           |             Data Invert
//      |     |     |                       |     |           |
// -----+     +-----+                       +-----+           +-----+-----+--------
//      |     |     |     |     |     |     |     |     |     |     |     |
//      |     |     |     |     |     |     |     |     |     |     |     | 11-Bit Framing
// Idle &amp;#39;Start&amp;#39;Bit 0&amp;#39;Bit 1&amp;#39;Bit 2&amp;#39;Bit 3&amp;#39;Bit 4&amp;#39;Bit 5&amp;#39;Bit 6&amp;#39;Bit 7&amp;#39;Par  &amp;#39;Stop | Idle
//      |     |     |     |     |     |     |     |     |     |     |     |
//      |     |     |                       |     |           |                                                Clear Reload
//      |     |     |                       |     |           |       -- Edge 10   pTimer4-&amp;gt;CC[4] = BT/2+(10*BT) *      3,0
//      |     |     |                       |     |           |       -- Edge  9   pTimer4-&amp;gt;CC[3] = BT/2+( 9*BT) -      2
//      |     |     |                       |     |           |       -- Edge  8   pTimer4-&amp;gt;CC[2] = BT/2+( 8*BT) -      1
//      |     |     |                       |     |           |       -- Edge  7   pTimer4-&amp;gt;CC[1] = BT/2+( 7*BT) -      0
//      |     |     |                       |     |           |       -- Edge  6   pTimer4-&amp;gt;CC[0] = BT/2+( 6*BT) -      -
//      |     |     |                       |     |           +--------- Edge  5   pTimer4-&amp;gt;CC[5] = BT/2+( 5*BT) *      -
//      |     |     |                       |     +--------------------- Edge  4   pTimer4-&amp;gt;CC[4] = BT/2+( 4*BT) -      -
//      |     |     |                       +--------------------------- Edge  3   pTimer4-&amp;gt;CC[3] = BT/2+( 3*BT) -      2
//      |     |     +--------------------------------------------------- Edge  2   pTimer4-&amp;gt;CC[2] = BT/2+( 2*BT) -      1
//      |     +--------------------------------------------------------- Edge  1   pTimer4-&amp;gt;CC[1] = BT/2+( 1*BT) -      0
//      +--------------------------------------------------------------- Edge  0   pTimer4-&amp;gt;CC[0] = BT/2         -      -
//      |     |     |     |     |     |     |     |     |     |     |                                          Clear Reload
//      |     |     |     |     |     |     |     |     |     |     +--- Stop bit  pTimer4-&amp;gt;CC[4] = BT/2+(10*BT) *      3,0
//      |     |     |     |     |     |     |     |     |     +--------- Parity    pTimer4-&amp;gt;CC[3] = BT/2+( 9*BT) -      2
//      |     |     |     |     |     |     |     |     +--------------- Bit 7     pTimer4-&amp;gt;CC[2] = BT/2+( 8*BT) -      1
//      |     |     |     |     |     |     |     +--------------------- Bit 6     pTimer4-&amp;gt;CC[1] = BT/2+( 7*BT) -      0
//      |     |     |     |     |     |     +--------------------------- Bit 5     pTimer4-&amp;gt;CC[0] = BT/2+( 6*BT) -      -
//      |     |     |     |     |     +--------------------------------- Bit 4     pTimer4-&amp;gt;CC[5] = BT/2+( 5*BT) *      -
//      |     |     |     |     +--------------------------------------- Bit 3     pTimer4-&amp;gt;CC[4] = BT/2+( 4*BT) -      -
//      |     |     |     +--------------------------------------------- Bit 2     pTimer4-&amp;gt;CC[3] = BT/2+( 3*BT) -      2
//      |     |     +--------------------------------------------------- Bit 1     pTimer4-&amp;gt;CC[2] = BT/2+( 2*BT) -      1
//      |     +--------------------------------------------------------- Bit 0     pTimer4-&amp;gt;CC[1] = BT/2+( 1*BT) -      0
//      +--------------------------------------------------------------- Start Bit pTimer4-&amp;gt;CC[0] = BT/2         -      -&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Is it possible to read a data pin with PPI? (PS/2 bit banging using PPI)</title><link>https://devzone.nordicsemi.com/thread/446961?ContentTypeID=1</link><pubDate>Thu, 21 Sep 2023 00:21:30 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e19e7f57-0bdc-4bca-a4ce-99711da51710</guid><dc:creator>Kimcha</dc:creator><description>&lt;p&gt;Thank you. I am using Zephyr 3.2 and whatever is bundled with it.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Unfortunately, my hardware design already uses digital-only pins for this design.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Is it possible to &amp;ldquo;copy&amp;rdquo; pin values from a digital pin to the analogue pins using PPI?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Is it possible to read a data pin with PPI? (PS/2 bit banging using PPI)</title><link>https://devzone.nordicsemi.com/thread/446950?ContentTypeID=1</link><pubDate>Wed, 20 Sep 2023 17:59:12 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c08dae0a-d558-49fa-a1fe-dfb83d70f42d</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>[quote user="Kimcha"]Does the SAADC library only work on analogue pins or does it also work on digital ones?[/quote]
&lt;p&gt;The SAADC only works with the analog inputs (AIN0-AIN7), but these are shared with digital GPIOs and can be dynamically switched between analog and digital functionality from the firmware.&lt;/p&gt;
[quote user="Kimcha"]And do you have any sample code for using it in this way?[/quote]
&lt;p&gt;Unfortunately, I do not have any sample code showing how to do this.&amp;nbsp;Are you using nRF Connect SDK or nRF5 SDK?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Is it possible to read a data pin with PPI? (PS/2 bit banging using PPI)</title><link>https://devzone.nordicsemi.com/thread/446713?ContentTypeID=1</link><pubDate>Tue, 19 Sep 2023 15:30:21 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d8416b1e-24fe-4521-ad91-3743d3f976aa</guid><dc:creator>Kimcha</dc:creator><description>&lt;p&gt;Thank you, Jorgen. Does the SAADC library only work on analogue pins or does it also work on digital ones?&lt;/p&gt;
&lt;p&gt;And do you have any sample code for using it in this way?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Is it possible to read a data pin with PPI? (PS/2 bit banging using PPI)</title><link>https://devzone.nordicsemi.com/thread/446442?ContentTypeID=1</link><pubDate>Mon, 18 Sep 2023 11:32:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:0b66f404-49e4-436c-aa80-e891cca7d5d9</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Unfortunately, it is not possible to capture digital levels on GPIOs using PPI.&lt;/p&gt;
&lt;p&gt;The other alternative is to use the SAADC peripheral to capture the analog level of the GPIO and determine the logical level of the signal from the captured SAADC samples in your buffer. The SAADC sample task can be triggered through PPI. If the frames have a static length, you do not need a timer to capture the number of clock pulses, you can set the SAADC buffer length of the packet size and connect the GPIOTE input event from the clock pin directly to the sample task of the SAADC through PPI. When the SAADC buffer have been filled with the requested number of samples (corresponding to the number of bits in your package), the END event will be generated and you can handle the frame assembly in the SAADC event handler.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Jørgen&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>