summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--locale/ID.po17
-rw-r--r--locale/circuitpython.pot17
-rw-r--r--locale/de_DE.po17
-rw-r--r--locale/en_US.po17
-rw-r--r--locale/en_x_pirate.po17
-rw-r--r--locale/es.po17
-rw-r--r--locale/fil.po17
-rw-r--r--locale/fr.po17
-rw-r--r--locale/it_IT.po17
-rw-r--r--locale/pl.po17
-rw-r--r--locale/pt_BR.po17
-rw-r--r--locale/zh_Latn_pinyin.po17
-rw-r--r--ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/common-hal/ps2io/Ps2.c441
-rw-r--r--ports/atmel-samd/common-hal/ps2io/Ps2.h62
-rw-r--r--ports/atmel-samd/common-hal/ps2io/__init__.c1
-rw-r--r--ports/atmel-samd/eic_handler.c7
-rw-r--r--ports/atmel-samd/eic_handler.h1
-rw-r--r--ports/atmel-samd/supervisor/port.c1
-rw-r--r--ports/atmel-samd/tools/gen_pin_name_table.py3
-rw-r--r--py/circuitpy_defns.mk5
-rw-r--r--py/circuitpy_mpconfig.h8
-rw-r--r--py/circuitpy_mpconfig.mk6
-rw-r--r--shared-bindings/index.rst1
-rw-r--r--shared-bindings/ps2io/Ps2.c237
-rw-r--r--shared-bindings/ps2io/Ps2.h45
-rw-r--r--shared-bindings/ps2io/__init__.c73
-rw-r--r--shared-bindings/ps2io/__init__.h35
36 files changed, 1124 insertions, 24 deletions
diff --git a/locale/ID.po b/locale/ID.po
index f5c0c0949..e9d26e2a6 100644
--- a/locale/ID.po
+++ b/locale/ID.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -518,6 +518,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Channel EXTINT sedang digunakan"
@@ -546,6 +547,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -932,6 +937,10 @@ msgstr "Tidak ada GCLK yang kosong"
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1015,6 +1024,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Tambahkan module apapun pada filesystem\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2176,7 +2189,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 34070dc69..ed58d75f0 100644
--- a/locale/circuitpython.pot
+++ b/locale/circuitpython.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:41-0700\n"
+"POT-Creation-Date: 2019-05-22 16:00-0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -506,6 +506,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr ""
@@ -534,6 +535,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr ""
@@ -907,6 +912,10 @@ msgstr ""
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -989,6 +998,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2131,7 +2144,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 2cb97c3d3..936aaffa2 100644
--- a/locale/de_DE.po
+++ b/locale/de_DE.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: Pascal Deneaux\n"
"Language-Team: Sebastian Plamauer, Pascal Deneaux\n"
@@ -510,6 +510,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Drive mode wird nicht verwendet, wenn die Richtung input ist."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "EXTINT Kanal ist schon in Benutzung"
@@ -538,6 +539,10 @@ msgstr "Eine UUID wird erwartet"
msgid "Expected tuple of length %d, got %d"
msgstr "Habe ein Tupel der Länge %d erwartet aber %d erhalten"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr "Akquirieren des Mutex gescheitert"
@@ -920,6 +925,10 @@ msgstr "Keine freien GCLKs"
msgid "No hardware random available"
msgstr "Kein hardware random verfügbar"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1004,6 +1013,10 @@ msgstr "Pixel außerhalb der Puffergrenzen"
msgid "Plus any modules on the filesystem\n"
msgstr "und alle Module im Dateisystem \n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2178,7 +2191,7 @@ msgstr "Objekt ist kein Iterator"
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "Objekt ist nicht in sequence"
diff --git a/locale/en_US.po b/locale/en_US.po
index ebc18cfae..cea074190 100644
--- a/locale/en_US.po
+++ b/locale/en_US.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -506,6 +506,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr ""
@@ -534,6 +535,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr ""
@@ -907,6 +912,10 @@ msgstr ""
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -989,6 +998,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2131,7 +2144,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po
index 04706abdc..6889c29b7 100644
--- a/locale/en_x_pirate.po
+++ b/locale/en_x_pirate.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: @sommersoft, @MrCertainly\n"
@@ -510,6 +510,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Avast! EXTINT channel already in use"
@@ -538,6 +539,10 @@ msgstr ""
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr ""
@@ -911,6 +916,10 @@ msgstr ""
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -993,6 +1002,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2135,7 +2148,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index 77739f49c..f7f1ea0c4 100644
--- a/locale/es.po
+++ b/locale/es.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2018-08-24 22:56-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -524,6 +524,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Modo Drive no se usa cuando la dirección es input."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "El canal EXTINT ya está siendo utilizado"
@@ -554,6 +555,10 @@ msgstr "Se espera un %q"
msgid "Expected tuple of length %d, got %d"
msgstr "Se esperaba un tuple de %d, se obtuvo %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -946,6 +951,10 @@ msgstr "Sin GCLKs libres"
msgid "No hardware random available"
msgstr "No hay hardware random disponible"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1035,6 +1044,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Incapaz de montar de nuevo el sistema de archivos"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2213,7 +2226,7 @@ msgstr "objeto no es un iterator"
msgid "object not callable"
msgstr "objeto no puede ser llamado"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "objeto no en secuencia"
diff --git a/locale/fil.po b/locale/fil.po
index 5954e29b4..73e6e79e7 100644
--- a/locale/fil.po
+++ b/locale/fil.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2018-12-20 22:15-0800\n"
"Last-Translator: Timothy <me@timothygarcia.ca>\n"
"Language-Team: fil\n"
@@ -519,6 +519,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Drive mode ay hindi ginagamit kapag ang direksyon ay input."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Ginagamit na ang EXTINT channel"
@@ -549,6 +550,10 @@ msgstr "Umasa ng %q"
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -941,6 +946,10 @@ msgstr "Walang libreng GCLKs"
msgid "No hardware random available"
msgstr "Walang magagamit na hardware random"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1028,6 +1037,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Kasama ang kung ano pang modules na sa filesystem\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2212,7 +2225,7 @@ msgstr "object ay hindi iterator"
msgid "object not callable"
msgstr "hindi matatawag ang object"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "object wala sa sequence"
diff --git a/locale/fr.po b/locale/fr.po
index 0bd0f8771..0362e1c49 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2019-04-14 20:05+0100\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n"
@@ -522,6 +522,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Le mode Drive n'est pas utilisé quand la direction est 'input'."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Canal EXTINT déjà utilisé"
@@ -552,6 +553,10 @@ msgstr "Un UUID est attendu"
msgid "Expected tuple of length %d, got %d"
msgstr "Tuple de longueur %d attendu, obtenu %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -949,6 +954,10 @@ msgstr "Pas de GCLK libre"
msgid "No hardware random available"
msgstr "Pas de source matérielle d'aléa disponible"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1045,6 +1054,10 @@ msgstr "Pixel au-delà des limites du tampon"
msgid "Plus any modules on the filesystem\n"
msgstr "Ainsi que tout autre module présent sur le système de fichiers\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr "Appuyez sur une touche pour entrer sur REPL ou CTRL-D pour recharger."
@@ -2247,7 +2260,7 @@ msgstr "l'objet n'est pas un itérateur"
msgid "object not callable"
msgstr "objet non appelable"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "l'objet n'est pas dans la séquence"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index 12f21c38e..760f00423 100644
--- a/locale/it_IT.po
+++ b/locale/it_IT.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2018-10-02 16:27+0200\n"
"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n"
"Language-Team: \n"
@@ -519,6 +519,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Canale EXTINT già in uso"
@@ -549,6 +550,10 @@ msgstr "Atteso un %q"
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -940,6 +945,10 @@ msgstr "Nessun GCLK libero"
msgid "No hardware random available"
msgstr "Nessun generatore hardware di numeri casuali disponibile"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1033,6 +1042,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Imposssibile rimontare il filesystem"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2208,7 +2221,7 @@ msgstr "l'oggetto non è un iteratore"
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "oggetto non in sequenza"
diff --git a/locale/pl.po b/locale/pl.po
index 1a7471f72..10752c703 100644
--- a/locale/pl.po
+++ b/locale/pl.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2019-03-19 18:37-0700\n"
"Last-Translator: Radomir Dopieralski <circuitpython@sheep.art.pl>\n"
"Language-Team: pl\n"
@@ -509,6 +509,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Tryb sterowania nieużywany w trybie wejścia."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Kanał EXTINT w użyciu"
@@ -537,6 +538,10 @@ msgstr "Oczekiwano UUID"
msgid "Expected tuple of length %d, got %d"
msgstr "Oczekiwano krotkę długości %d, otrzymano %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr "Nie udało się uzyskać blokady"
@@ -917,6 +922,10 @@ msgstr "Brak wolnych GLCK"
msgid "No hardware random available"
msgstr "Brak generatora liczb losowych"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -999,6 +1008,10 @@ msgstr "Piksel poza granicami bufora"
msgid "Plus any modules on the filesystem\n"
msgstr "Oraz moduły w systemie plików\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr "Dowolny klawisz aby uruchomić konsolę. CTRL-D aby przeładować."
@@ -2156,7 +2169,7 @@ msgstr "obiekt nie jest iteratorem"
msgid "object not callable"
msgstr "obiekt nie jest wywoływalny"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "obiektu nie ma sekwencji"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index 390610041..e2b13cbd3 100644
--- a/locale/pt_BR.po
+++ b/locale/pt_BR.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2018-10-02 21:14-0000\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -514,6 +514,7 @@ msgid "Drive mode not used when direction is input."
msgstr ""
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "Canal EXTINT em uso"
@@ -544,6 +545,10 @@ msgstr "Esperado um"
msgid "Expected tuple of length %d, got %d"
msgstr ""
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr "Falha ao enviar comando."
+
#: ports/nrf/common-hal/bleio/Device.c
#, fuzzy
msgid "Failed to acquire mutex"
@@ -930,6 +935,10 @@ msgstr "Não há GCLKs livre"
msgid "No hardware random available"
msgstr ""
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr "Sem suporte de hardware no pino de clock"
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1016,6 +1025,10 @@ msgstr ""
msgid "Plus any modules on the filesystem\n"
msgstr "Não é possível remontar o sistema de arquivos"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr "Buffer Ps2 vazio"
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr ""
@@ -2165,7 +2178,7 @@ msgstr ""
msgid "object not callable"
msgstr ""
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "objeto não em seqüência"
diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po
index 82264cb52..dbc87115b 100644
--- a/locale/zh_Latn_pinyin.po
+++ b/locale/zh_Latn_pinyin.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: circuitpython-cn\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-05-13 17:34-0700\n"
+"POT-Creation-Date: 2019-05-22 15:56-0300\n"
"PO-Revision-Date: 2019-04-13 10:10-0700\n"
"Last-Translator: hexthat\n"
"Language-Team: Chinese Hanyu Pinyin\n"
@@ -510,6 +510,7 @@ msgid "Drive mode not used when direction is input."
msgstr "Fāngxiàng shūrù shí qūdòng móshì méiyǒu shǐyòng."
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "EXTINT channel already in use"
msgstr "EXTINT píndào yǐjīng shǐyòng"
@@ -538,6 +539,10 @@ msgstr "Yùqí UUID"
msgid "Expected tuple of length %d, got %d"
msgstr "Qīwàng de chángdù wèi %d de yuán zǔ, dédào %d"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Failed sending command."
+msgstr ""
+
#: ports/nrf/common-hal/bleio/Device.c
msgid "Failed to acquire mutex"
msgstr "Wúfǎ huòdé mutex"
@@ -917,6 +922,10 @@ msgstr "Méiyǒu miǎnfèi de GCLKs"
msgid "No hardware random available"
msgstr "Méiyǒu kěyòng de yìngjiàn suíjī"
+#: ports/atmel-samd/common-hal/ps2io/Ps2.c
+msgid "No hardware support on clk pin"
+msgstr ""
+
#: ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
#: ports/atmel-samd/common-hal/pulseio/PulseIn.c
msgid "No hardware support on pin"
@@ -1004,6 +1013,10 @@ msgstr "Xiàngsù chāochū huǎnchōng qū biānjiè"
msgid "Plus any modules on the filesystem\n"
msgstr "Zài wénjiàn xìtǒng shàng tiānjiā rènhé mókuài\n"
+#: shared-bindings/ps2io/Ps2.c
+msgid "Pop from an empty Ps2 buffer"
+msgstr ""
+
#: main.c
msgid "Press any key to enter the REPL. Use CTRL-D to reload."
msgstr "Àn xià rènhé jiàn jìnrù REPL. Shǐyòng CTRL-D chóngxīn jiāzài."
@@ -2168,7 +2181,7 @@ msgstr "duìxiàng bùshì diédài qì"
msgid "object not callable"
msgstr "duìxiàng wúfǎ diàoyòng"
-#: py/sequence.c
+#: py/sequence.c shared-bindings/displayio/Group.c
msgid "object not in sequence"
msgstr "duìxiàng bùshì xùliè"
diff --git a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
index 0444a37b9..c566795c4 100644
--- a/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/cp32-m4/mpconfigboard.mk
@@ -15,3 +15,5 @@ CIRCUITPY_TOUCHIO = 0
CHIP_VARIANT = SAMD51J20A
CHIP_FAMILY = samd51
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
index e6b21e25b..af1037c38 100644
--- a/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/datalore_ip_m4/mpconfigboard.mk
@@ -18,3 +18,5 @@ CIRCUITPY_TOUCHIO = 0
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
index 4fddcffc1..5972b5e46 100644
--- a/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m4_express/mpconfigboard.mk
@@ -18,3 +18,5 @@ CHIP_FAMILY = samd51
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
index 63158681b..0ae23bdef 100644
--- a/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/grandcentral_m4_express/mpconfigboard.mk
@@ -15,3 +15,5 @@ CIRCUITPY_TOUCHIO = 0
CHIP_VARIANT = SAMD51P20A
CHIP_FAMILY = samd51
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
index d4d674d9d..176935c38 100644
--- a/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/itsybitsy_m4_express/mpconfigboard.mk
@@ -16,3 +16,5 @@ CIRCUITPY_TOUCHIO = 0
CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
index 654a84eb8..2a6191b36 100644
--- a/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_airlift_lite/mpconfigboard.mk
@@ -18,3 +18,5 @@ CHIP_FAMILY = samd51
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
index 35162b678..32e623e67 100644
--- a/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m4_express/mpconfigboard.mk
@@ -18,3 +18,5 @@ CHIP_FAMILY = samd51
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
index 27bad2693..5f744dfd2 100644
--- a/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/mini_sam_m4/mpconfigboard.mk
@@ -17,3 +17,5 @@ CIRCUITPY_TOUCHIO = 0
CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
index 93b07bc76..bfcada0d7 100644
--- a/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trellis_m4_express/mpconfigboard.mk
@@ -16,3 +16,5 @@ CIRCUITPY_TOUCHIO = 0
CHIP_VARIANT = SAMD51G19A
CHIP_FAMILY = samd51
+
+CIRCUITPY_PS2IO = 1
diff --git a/ports/atmel-samd/common-hal/ps2io/Ps2.c b/ports/atmel-samd/common-hal/ps2io/Ps2.c
new file mode 100644
index 000000000..6a06864f2
--- /dev/null
+++ b/ports/atmel-samd/common-hal/ps2io/Ps2.c
@@ -0,0 +1,441 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017-2018 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "common-hal/ps2io/Ps2.h"
+
+#include <stdint.h>
+
+#include "atmel_start_pins.h"
+#include "hal/include/hal_gpio.h"
+
+#include "background.h"
+#include "eic_handler.h"
+#include "mpconfigport.h"
+#include "py/gc.h"
+#include "py/runtime.h"
+#include "samd/external_interrupts.h"
+#include "samd/pins.h"
+#include "shared-bindings/microcontroller/__init__.h"
+#include "shared-bindings/ps2io/Ps2.h"
+#include "supervisor/shared/translate.h"
+
+#include "tick.h"
+
+#define STATE_IDLE 0
+#define STATE_RECV 1
+#define STATE_RECV_PARITY 2
+#define STATE_RECV_STOP 3
+#define STATE_RECV_ERR 10
+
+#define ERROR_STARTBIT 0x01
+#define ERROR_TIMEOUT 0x02
+#define ERROR_PARITY 0x04
+#define ERROR_STOPBIT 0x08
+#define ERROR_BUFFER 0x10
+
+#define ERROR_TX_CLKLO 0x100
+#define ERROR_TX_CLKHI 0x200
+#define ERROR_TX_ACKDATA 0x400
+#define ERROR_TX_ACKCLK 0x800
+#define ERROR_TX_RTS 0x1000
+#define ERROR_TX_NORESP 0x2000
+
+static void ps2_set_config(ps2io_ps2_obj_t* self) {
+ uint32_t sense_setting = EIC_CONFIG_SENSE0_FALL_Val;
+ set_eic_handler(self->channel, EIC_HANDLER_PS2);
+ turn_on_eic_channel(self->channel, sense_setting);
+}
+
+static void disable_interrupt(ps2io_ps2_obj_t* self) {
+ uint32_t mask = 1 << self->channel;
+ EIC->INTENCLR.reg = mask << EIC_INTENSET_EXTINT_Pos;
+}
+
+static void resume_interrupt(ps2io_ps2_obj_t* self) {
+ disable_interrupt(self);
+
+ self->state = STATE_IDLE;
+ gpio_set_pin_function(self->clk_pin, GPIO_PIN_FUNCTION_A);
+ uint32_t mask = 1 << self->channel;
+ EIC->INTFLAG.reg = mask << EIC_INTFLAG_EXTINT_Pos;
+ EIC->INTENSET.reg = mask << EIC_INTENSET_EXTINT_Pos;
+
+ ps2_set_config(self);
+}
+
+static void clk_hi(ps2io_ps2_obj_t* self) {
+ // External pull-up
+ // Must set pull after setting direction.
+ gpio_set_pin_direction(self->clk_pin, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(self->clk_pin, GPIO_PULL_OFF);
+}
+
+static bool wait_clk_lo(ps2io_ps2_obj_t* self, uint32_t us) {
+ clk_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (gpio_get_pin_level(self->clk_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static bool wait_clk_hi(ps2io_ps2_obj_t* self, uint32_t us) {
+ clk_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (!gpio_get_pin_level(self->clk_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static void clk_lo(ps2io_ps2_obj_t* self) {
+ gpio_set_pin_pull_mode(self->clk_pin, GPIO_PULL_OFF);
+ gpio_set_pin_direction(self->clk_pin, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(self->clk_pin, 0);
+}
+
+static void data_hi(ps2io_ps2_obj_t* self) {
+ // External pull-up
+ gpio_set_pin_direction(self->data_pin, GPIO_DIRECTION_IN);
+ gpio_set_pin_pull_mode(self->data_pin, GPIO_PULL_OFF);
+}
+
+static bool wait_data_lo(ps2io_ps2_obj_t* self, uint32_t us) {
+ data_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (gpio_get_pin_level(self->data_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static bool wait_data_hi(ps2io_ps2_obj_t* self, uint32_t us) {
+ data_hi(self);
+ common_hal_mcu_delay_us(1);
+ while (!gpio_get_pin_level(self->data_pin) && us) {
+ --us;
+ common_hal_mcu_delay_us(1);
+ }
+ return us;
+}
+
+static void data_lo(ps2io_ps2_obj_t* self) {
+ gpio_set_pin_pull_mode(self->data_pin, GPIO_PULL_OFF);
+ gpio_set_pin_direction(self->data_pin, GPIO_DIRECTION_OUT);
+ gpio_set_pin_level(self->data_pin, 0);
+}
+
+static void idle(ps2io_ps2_obj_t* self) {
+ clk_hi(self);
+ data_hi(self);
+}
+
+static void inhibit(ps2io_ps2_obj_t* self) {
+ clk_lo(self);
+ data_hi(self);
+}
+
+static void delay_us(uint32_t t) {
+ common_hal_mcu_delay_us(t);
+}
+
+void ps2_interrupt_handler(uint8_t channel) {
+ // Grab the current time first.
+ uint32_t current_us;
+ uint64_t current_ms;
+ current_tick(&current_ms, &current_us);
+
+ ps2io_ps2_obj_t* self = get_eic_channel_data(channel);
+ int data_bit = gpio_get_pin_level(self->data_pin) ? 1 : 0;
+
+ // test for timeout
+ if (self->state != STATE_IDLE) {
+ int64_t diff_ms = current_ms - self->last_int_ms;
+ if (diff_ms >= 2) { // a.k.a. > 1.001ms
+ self->last_errors |= ERROR_TIMEOUT;
+ self->state = STATE_IDLE;
+ }
+ }
+
+ self->last_int_us = current_us;
+ self->last_int_ms = current_ms;
+
+ if (self->state == STATE_IDLE) {
+ self->bits = 0;
+ self->parity = false;
+ self->bitcount = 0;
+ self->state = STATE_RECV;
+ if (data_bit) {
+ // start bit should be 0
+ self->last_errors |= ERROR_STARTBIT;
+ self->state = STATE_RECV_ERR;
+ } else {
+ self->state = STATE_RECV;
+ }
+
+ } else if (self->state == STATE_RECV) {
+ if (data_bit) {
+ self->bits |= data_bit << self->bitcount;
+ self->parity = !self->parity;
+ }
+ ++self->bitcount;
+ if (self->bitcount >= 8) {
+ self->state = STATE_RECV_PARITY;
+ }
+
+ } else if (self->state == STATE_RECV_PARITY) {
+ ++self->bitcount;
+ if (data_bit) {
+ self->parity = !self->parity;
+ }
+ if (!self->parity) {
+ self->last_errors |= ERROR_PARITY;
+ self->state = STATE_RECV_ERR;
+ } else {
+ self->state = STATE_RECV_STOP;
+ }
+
+ } else if (self->state == STATE_RECV_STOP) {
+ ++self->bitcount;
+ if (! data_bit) {
+ self->last_errors |= ERROR_STOPBIT;
+ } else if (self->waiting_cmd_response) {
+ self->cmd_response = self->bits;
+ self->waiting_cmd_response = false;
+ } else if (self->bufcount >= sizeof(self->buffer)) {
+ self->last_errors |= ERROR_BUFFER;
+ } else {
+ self->buffer[self->bufposw] = self->bits;
+ self->bufposw = (self->bufposw + 1) % sizeof(self->buffer);
+ self->bufcount++;
+ }
+ self->state = STATE_IDLE;
+
+ } else if (self->state == STATE_RECV_ERR) {
+ // just count the bits until idle
+ if (++self->bitcount >= 10) {
+ self->state = STATE_IDLE;
+ }
+ }
+}
+
+void common_hal_ps2io_ps2_construct(ps2io_ps2_obj_t* self,
+ const mcu_pin_obj_t* data_pin, const mcu_pin_obj_t* clk_pin) {
+ if (!clk_pin->has_extint) {
+ mp_raise_RuntimeError(translate("No hardware support on clk pin"));
+ }
+ if (eic_get_enable() && !eic_channel_free(clk_pin->extint_channel)) {
+ mp_raise_RuntimeError(translate("EXTINT channel already in use"));
+ }
+
+ clk_hi(self);
+ data_hi(self);
+
+ self->channel = clk_pin->extint_channel;
+ self->clk_pin = clk_pin->number;
+ self->data_pin = data_pin->number;
+ self->state = STATE_IDLE;
+ self->bufcount = 0;
+ self->bufposr = 0;
+ self->bufposw = 0;
+ self->waiting_cmd_response = false;
+
+ set_eic_channel_data(clk_pin->extint_channel, (void*) self);
+
+ // Check to see if the EIC is enabled and start it up if its not.'
+ if (eic_get_enable() == 0) {
+ turn_on_external_interrupt_controller();
+ }
+
+ gpio_set_pin_function(clk_pin->number, GPIO_PIN_FUNCTION_A);
+ gpio_set_pin_function(data_pin->number, GPIO_PIN_FUNCTION_A);
+
+ turn_on_cpu_interrupt(self->channel);
+
+ claim_pin(clk_pin);
+ claim_pin(data_pin);
+
+ // Set config will enable the EIC.
+ ps2_set_config(self);
+}
+
+bool common_hal_ps2io_ps2_deinited(ps2io_ps2_obj_t* self) {
+ return self->clk_pin == NO_PIN;
+}
+
+void common_hal_ps2io_ps2_deinit(ps2io_ps2_obj_t* self) {
+ if (common_hal_ps2io_ps2_deinited(self)) {
+ return;
+ }
+ set_eic_handler(self->channel, EIC_HANDLER_NO_INTERRUPT);
+ turn_off_eic_channel(self->channel);
+ reset_pin_number(self->clk_pin);
+ reset_pin_number(self->data_pin);
+ self->clk_pin = NO_PIN;
+ self->data_pin = NO_PIN;
+}
+
+uint16_t common_hal_ps2io_ps2_get_len(ps2io_ps2_obj_t* self) {
+ return self->bufcount;
+}
+
+bool common_hal_ps2io_ps2_get_paused(ps2io_ps2_obj_t* self) {
+ uint32_t mask = 1 << self->channel;
+ return (EIC->INTENSET.reg & (mask << EIC_INTENSET_EXTINT_Pos)) == 0;
+}
+
+int16_t common_hal_ps2io_ps2_popleft(ps2io_ps2_obj_t* self)
+{
+ common_hal_mcu_disable_interrupts();
+ if (self->bufcount <= 0) {
+ common_hal_mcu_enable_interrupts();
+ return -1;
+ }
+ uint8_t b = self->buffer[self->bufposr];
+ self->bufposr = (self->bufposr + 1) % sizeof(self->buffer);
+ self->bufcount -= 1;
+ common_hal_mcu_enable_interrupts();
+ return b;
+}
+
+uint16_t common_hal_ps2io_ps2_clear_errors(ps2io_ps2_obj_t* self)
+{
+ common_hal_mcu_disable_interrupts();
+ uint16_t errors = self->last_errors;
+ self->last_errors = 0;
+ common_hal_mcu_enable_interrupts();
+ return errors;
+}
+
+// Based upon TMK implementation of PS/2 protocol
+// https://github.com/tmk/tmk_keyboard/blob/master/tmk_core/protocol/ps2_interrupt.c
+
+int16_t common_hal_ps2io_ps2_sendcmd(ps2io_ps2_obj_t* self, uint8_t b)
+{
+ disable_interrupt(self);
+ inhibit(self);
+ delay_us(100);
+
+ /* RTS and start bit */
+ data_lo(self);
+ clk_hi(self);
+ if (!wait_clk_lo(self, 10000)) {
+ self->last_errors |= ERROR_TX_RTS;
+ goto ERROR;
+ }
+
+ bool parity = true;
+ for (uint8_t i = 0; i < 8; i++) {
+ delay_us(15);
+ if (b & (1 << i)) {
+ parity = !parity;
+ data_hi(self);
+ } else {
+ data_lo(self);
+ }
+ if (!wait_clk_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKHI;
+ goto ERROR;
+ }
+ if (!wait_clk_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKLO;
+ goto ERROR;
+ }
+ }
+
+ delay_us(15);
+ if (parity) {
+ data_hi(self);
+ } else {
+ data_lo(self);
+ }
+ if (!wait_clk_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKHI;
+ goto ERROR;
+ }
+ if (!wait_clk_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_CLKLO;
+ goto ERROR;
+ }
+
+ /* Stop bit */
+ delay_us(15);
+ data_hi(self);
+
+ /* Ack */
+ if (!wait_data_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKDATA;
+ goto ERROR;
+ }
+ if (!wait_clk_lo(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKCLK;
+ goto ERROR;
+ }
+
+ /* wait for idle state */
+ if (!wait_clk_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKCLK;
+ goto ERROR;
+ }
+ if (!wait_data_hi(self, 50)) {
+ self->last_errors |= ERROR_TX_ACKDATA;
+ goto ERROR;
+ }
+
+ /* Wait for response byte */
+ self->waiting_cmd_response = true;
+ idle(self);
+ resume_interrupt(self);
+
+ for (int i = 0; i < 25; ++i) {
+ delay_us(1000);
+ common_hal_mcu_disable_interrupts();
+ bool has_response = !self->waiting_cmd_response;
+ uint8_t response = self->cmd_response;
+ common_hal_mcu_enable_interrupts();
+
+ if (has_response) {
+ return response;
+ }
+ }
+
+ /* No response */
+ common_hal_mcu_disable_interrupts();
+ self->waiting_cmd_response = false;
+ self->last_errors |= ERROR_TX_NORESP;
+ common_hal_mcu_enable_interrupts();
+ return -1;
+
+ /* Other errors */
+ERROR:
+ idle(self);
+ resume_interrupt(self);
+ return -1;
+}
diff --git a/ports/atmel-samd/common-hal/ps2io/Ps2.h b/ports/atmel-samd/common-hal/ps2io/Ps2.h
new file mode 100644
index 000000000..cce6ae474
--- /dev/null
+++ b/ports/atmel-samd/common-hal/ps2io/Ps2.h
@@ -0,0 +1,62 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PS2IO_PS2_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PS2IO_PS2_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t channel;
+ uint8_t clk_pin;
+ uint8_t data_pin;
+
+ uint8_t state;
+ uint64_t last_int_ms;
+ uint32_t last_int_us;
+
+ uint16_t bits;
+ bool parity;
+ uint8_t bitcount;
+
+ uint8_t buffer[16];
+ uint8_t bufcount;
+ uint8_t bufposr;
+ uint8_t bufposw;
+
+ uint16_t last_errors;
+
+ bool waiting_cmd_response;
+ uint8_t cmd_response;
+} ps2io_ps2_obj_t;
+
+void ps2_interrupt_handler(uint8_t channel);
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_PS2IO_PS2_H
diff --git a/ports/atmel-samd/common-hal/ps2io/__init__.c b/ports/atmel-samd/common-hal/ps2io/__init__.c
new file mode 100644
index 000000000..ba4b4249f
--- /dev/null
+++ b/ports/atmel-samd/common-hal/ps2io/__init__.c
@@ -0,0 +1 @@
+// No ps2io module functions.
diff --git a/ports/atmel-samd/eic_handler.c b/ports/atmel-samd/eic_handler.c
index db5f260e5..30ecaa7ca 100644
--- a/ports/atmel-samd/eic_handler.c
+++ b/ports/atmel-samd/eic_handler.c
@@ -25,6 +25,7 @@
*/
#include "common-hal/pulseio/PulseIn.h"
+#include "common-hal/ps2io/Ps2.h"
#include "common-hal/rotaryio/IncrementalEncoder.h"
#include "shared-bindings/microcontroller/__init__.h"
//#include "samd/external_interrupts.h"
@@ -46,6 +47,12 @@ void shared_eic_handler(uint8_t channel) {
break;
#endif
+#if CIRCUITPY_PS2IO
+ case EIC_HANDLER_PS2:
+ ps2_interrupt_handler(channel);
+ break;
+#endif
+
#if CIRCUITPY_ROTARYIO
case EIC_HANDLER_INCREMENTAL_ENCODER:
incrementalencoder_interrupt_handler(channel);
diff --git a/ports/atmel-samd/eic_handler.h b/ports/atmel-samd/eic_handler.h
index 2f9ccd67f..71b0fce67 100644
--- a/ports/atmel-samd/eic_handler.h
+++ b/ports/atmel-samd/eic_handler.h
@@ -29,6 +29,7 @@
#define EIC_HANDLER_NO_INTERRUPT 0x0
#define EIC_HANDLER_PULSEIN 0x1
#define EIC_HANDLER_INCREMENTAL_ENCODER 0x2
+#define EIC_HANDLER_PS2 0x3
void set_eic_handler(uint8_t channel, uint8_t eic_handler);
void shared_eic_handler(uint8_t channel);
diff --git a/ports/atmel-samd/supervisor/port.c b/ports/atmel-samd/supervisor/port.c
index 4f53d30f9..37360deb0 100644
--- a/ports/atmel-samd/supervisor/port.c
+++ b/ports/atmel-samd/supervisor/port.c
@@ -52,6 +52,7 @@
#include "common-hal/pulseio/PulseIn.h"
#include "common-hal/pulseio/PulseOut.h"
#include "common-hal/pulseio/PWMOut.h"
+#include "common-hal/ps2io/Ps2.h"
#include "common-hal/rtc/RTC.h"
#include "common-hal/touchio/TouchIn.h"
#include "samd/cache.h"
diff --git a/ports/atmel-samd/tools/gen_pin_name_table.py b/ports/atmel-samd/tools/gen_pin_name_table.py
index 76c9cf255..ded64e5f6 100644
--- a/ports/atmel-samd/tools/gen_pin_name_table.py
+++ b/ports/atmel-samd/tools/gen_pin_name_table.py
@@ -156,6 +156,9 @@ capabilities = {
"PA14", "PA15", "PA16", "PA17", "PA18", "PA19", "PA20",
"PA21", "PA22", "PA23", "PA30", "PA31"]
},
+ "ps2io": {
+ "Ps2": ALL_BUT_USB,
+ },
"touchio": {
"TouchIn": ["PA02", "PA03", "PB08", "PB09", "PA04", "PA05", "PA06",
"PA07", "PB02", "PB03"]
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index 1aca33901..722f06e93 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -162,6 +162,9 @@ endif
ifeq ($(CIRCUITPY_PULSEIO),1)
SRC_PATTERNS += pulseio/%
endif
+ifeq ($(CIRCUITPY_PS2IO),1)
+SRC_PATTERNS += ps2io/%
+endif
ifeq ($(CIRCUITPY_RANDOM),1)
SRC_PATTERNS += random/%
endif
@@ -252,6 +255,8 @@ $(filter $(SRC_PATTERNS), \
pulseio/PulseIn.c \
pulseio/PulseOut.c \
pulseio/__init__.c \
+ ps2io/Ps2.c \
+ ps2io/__init__.c \
rotaryio/IncrementalEncoder.c \
rotaryio/__init__.c \
rtc/RTC.c \
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index 0575bcfe0..c794759f8 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -416,6 +416,13 @@ extern const struct _mp_obj_module_t pulseio_module;
#define PULSEIO_MODULE
#endif
+#if CIRCUITPY_PS2IO
+extern const struct _mp_obj_module_t ps2io_module;
+#define PS2IO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_ps2io), (mp_obj_t)&ps2io_module },
+#else
+#define PS2IO_MODULE
+#endif
+
#if CIRCUITPY_RANDOM
extern const struct _mp_obj_module_t random_module;
#define RANDOM_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_random), (mp_obj_t)&random_module },
@@ -580,6 +587,7 @@ extern const struct _mp_obj_module_t ustack_module;
PEW_MODULE \
PIXELBUF_MODULE \
PULSEIO_MODULE \
+ PS2IO_MODULE \
RANDOM_MODULE \
RE_MODULE \
ROTARYIO_MODULE \
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index b436929e0..ed9b9f461 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -153,6 +153,12 @@ CIRCUITPY_PULSEIO = 1
endif
CFLAGS += -DCIRCUITPY_PULSEIO=$(CIRCUITPY_PULSEIO)
+# Only for SAMD boards for the moment
+ifndef CIRCUITPY_PS2IO
+CIRCUITPY_PS2IO = 0
+endif
+CFLAGS += -DCIRCUITPY_PS2IO=$(CIRCUITPY_PS2IO)
+
ifndef CIRCUITPY_RANDOM
CIRCUITPY_RANDOM = 1
endif
diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst
index 4f2e28702..8f9bbbb31 100644
--- a/shared-bindings/index.rst
+++ b/shared-bindings/index.rst
@@ -53,6 +53,7 @@ Module Supported Ports
`nvm` **SAMD Express**
`os` **All Supported**
`pulseio` **SAMD/SAMD Express**
+`ps2io` **SAMD/SAMD Express**
`random` **All Supported**
`rotaryio` **SAMD51, SAMD Express**
`storage` **All Supported**
diff --git a/shared-bindings/ps2io/Ps2.c b/shared-bindings/ps2io/Ps2.c
new file mode 100644
index 000000000..bdbbf795c
--- /dev/null
+++ b/shared-bindings/ps2io/Ps2.c
@@ -0,0 +1,237 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "lib/utils/context_manager_helpers.h"
+#include "py/objproperty.h"
+#include "py/runtime.h"
+#include "py/runtime0.h"
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/ps2io/Ps2.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: ps2io
+//|
+//| :class:`Ps2` -- Communicate with a PS/2 keyboard or mouse
+//| =========================================================
+//|
+//| Ps2 implements the PS/2 keyboard/mouse serial protocol, used in
+//| legacy devices. It is similar to UART but there are only two
+//| lines (Data and Clock). PS/2 devices are 5V, so bidirectional
+//| level converters must be used to connect the I/O lines to pins
+//| of 3.3V boards.
+//|
+//| .. class:: Ps2(data_pin, clock_pin)
+//|
+//| Create a Ps2 object associated with the given pins.
+//|
+//| :param ~microcontroller.Pin data_pin: Pin tied to data wire.
+//| :param ~microcontroller.Pin clock_pin: Pin tied to clock wire.
+//| This pin must support interrupts.
+//|
+//| Read one byte from PS/2 keyboard and turn on Scroll Lock LED::
+//|
+//| import ps2io
+//| import board
+//|
+//| kbd = ps2io.Ps2(board.D10, board.D11)
+//|
+//| while len(kbd) == 0:
+//| pass
+//|
+//| print(kbd.popleft())
+//| print(kbd.sendcmd(0xed))
+//| print(kbd.sendcmd(0x01))
+//|
+STATIC mp_obj_t ps2io_ps2_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_datapin, ARG_clkpin };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_datapin, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_clkpin, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+ assert_pin(args[ARG_clkpin].u_obj, false);
+ assert_pin(args[ARG_datapin].u_obj, false);
+ const mcu_pin_obj_t* clkpin = MP_OBJ_TO_PTR(args[ARG_clkpin].u_obj);
+ assert_pin_free(clkpin);
+ const mcu_pin_obj_t* datapin = MP_OBJ_TO_PTR(args[ARG_datapin].u_obj);
+ assert_pin_free(datapin);
+
+ ps2io_ps2_obj_t *self = m_new_obj(ps2io_ps2_obj_t);
+ self->base.type = &ps2io_ps2_type;
+
+ common_hal_ps2io_ps2_construct(self, datapin, clkpin);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitialises the Ps2 and releases any hardware resources for reuse.
+//|
+STATIC mp_obj_t ps2io_ps2_deinit(mp_obj_t self_in) {
+ ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_ps2io_ps2_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_deinit_obj, ps2io_ps2_deinit);
+
+//| .. method:: __enter__()
+//|
+//| No-op used by Context Managers.
+//|
+// Provided by context manager helper.
+
+//| .. method:: __exit__()
+//|
+//| Automatically deinitializes the hardware when exiting a context. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+STATIC mp_obj_t ps2io_ps2_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_ps2io_ps2_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ps2io_ps2___exit___obj, 4, 4, ps2io_ps2_obj___exit__);
+
+//| .. method:: popleft()
+//|
+//| Removes and returns the oldest received byte. When buffer
+//| is empty, raises an IndexError exception.
+//|
+STATIC mp_obj_t ps2io_ps2_obj_popleft(mp_obj_t self_in) {
+ ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_ps2io_ps2_deinited(self));
+
+ int b = common_hal_ps2io_ps2_popleft(self);
+ if (b < 0) {
+ mp_raise_IndexError(translate("Pop from an empty Ps2 buffer"));
+ }
+ return MP_OBJ_NEW_SMALL_INT(b);
+}
+MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_popleft_obj, ps2io_ps2_obj_popleft);
+
+//| .. method:: sendcmd(byte)
+//|
+//| Sends a command byte to PS/2. Returns the response byte, typically
+//| the general ack value (0xFA). Some commands return additional data
+//| which is available through :py:func:`popleft()`.
+//|
+//| Raises a RuntimeError in case of failure. The root cause can be found
+//| by calling :py:func:`clear_errors()`. It is advisable to call
+//| :py:func:`clear_errors()` before :py:func:`sendcmd()` to flush any
+//| previous errors.
+//|
+//| :param int byte: byte value of the command
+//|
+STATIC mp_obj_t ps2io_ps2_obj_sendcmd(mp_obj_t self_in, mp_obj_t ob) {
+ ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_ps2io_ps2_deinited(self));
+ mp_int_t cmd = mp_obj_get_int(ob) & 0xff;
+ int resp = common_hal_ps2io_ps2_sendcmd(self, cmd);
+ if (resp < 0) {
+ mp_raise_RuntimeError(translate("Failed sending command."));
+ }
+ return MP_OBJ_NEW_SMALL_INT(resp);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(ps2io_ps2_sendcmd_obj, ps2io_ps2_obj_sendcmd);
+
+//| .. method:: clear_errors()
+//|
+//| Returns and clears a bitmap with latest recorded communication errors.
+//|
+//| Reception errors (arise asynchronously, as data is received):
+//|
+//| 0x01: start bit not 0
+//|
+//| 0x02: timeout
+//|
+//| 0x04: parity bit error
+//|
+//| 0x08: stop bit not 1
+//|
+//| 0x10: buffer overflow, newest data discarded
+//|
+//| Transmission errors (can only arise in the course of sendcmd()):
+//|
+//| 0x100: clock pin didn't go to LO in time
+//|
+//| 0x200: clock pin didn't go to HI in time
+//|
+//| 0x400: data pin didn't ACK
+//|
+//| 0x800: clock pin didn't ACK
+//|
+//| 0x1000: device didn't respond to RTS
+//|
+//| 0x2000: device didn't send a response byte in time
+//|
+STATIC mp_obj_t ps2io_ps2_obj_clear_errors(mp_obj_t self_in) {
+ ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_ps2io_ps2_deinited(self));
+
+ return MP_OBJ_NEW_SMALL_INT(common_hal_ps2io_ps2_clear_errors(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(ps2io_ps2_clear_errors_obj, ps2io_ps2_obj_clear_errors);
+
+//| .. method:: __len__()
+//|
+//| Returns the number of received bytes in buffer, available
+//| to :py:func:`popleft()`.
+//|
+STATIC mp_obj_t ps2_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
+ ps2io_ps2_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_ps2io_ps2_deinited(self));
+ uint16_t len = common_hal_ps2io_ps2_get_len(self);
+ switch (op) {
+ case MP_UNARY_OP_BOOL: return mp_obj_new_bool(len != 0);
+ case MP_UNARY_OP_LEN: return MP_OBJ_NEW_SMALL_INT(len);
+ default: return MP_OBJ_NULL; // op not supported
+ }
+}
+
+STATIC const mp_rom_map_elem_t ps2io_ps2_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&ps2io_ps2_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&ps2io_ps2___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_popleft), MP_ROM_PTR(&ps2io_ps2_popleft_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sendcmd), MP_ROM_PTR(&ps2io_ps2_sendcmd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_clear_errors), MP_ROM_PTR(&ps2io_ps2_clear_errors_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(ps2io_ps2_locals_dict, ps2io_ps2_locals_dict_table);
+
+const mp_obj_type_t ps2io_ps2_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Ps2,
+ .make_new = ps2io_ps2_make_new,
+ .unary_op = ps2_unary_op,
+ .locals_dict = (mp_obj_dict_t*)&ps2io_ps2_locals_dict,
+};
diff --git a/shared-bindings/ps2io/Ps2.h b/shared-bindings/ps2io/Ps2.h
new file mode 100644
index 000000000..523869d55
--- /dev/null
+++ b/shared-bindings/ps2io/Ps2.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO_PS2_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO_PS2_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/ps2io/Ps2.h"
+
+extern const mp_obj_type_t ps2io_ps2_type;
+
+extern void common_hal_ps2io_ps2_construct(ps2io_ps2_obj_t* self,
+ const mcu_pin_obj_t* data_pin, const mcu_pin_obj_t* clk_pin);
+extern void common_hal_ps2io_ps2_deinit(ps2io_ps2_obj_t* self);
+extern bool common_hal_ps2io_ps2_deinited(ps2io_ps2_obj_t* self);
+extern uint16_t common_hal_ps2io_ps2_get_len(ps2io_ps2_obj_t* self);
+extern int16_t common_hal_ps2io_ps2_popleft(ps2io_ps2_obj_t* self);
+extern int16_t common_hal_ps2io_ps2_sendcmd(ps2io_ps2_obj_t* self, uint8_t b);
+extern uint16_t common_hal_ps2io_ps2_clear_errors(ps2io_ps2_obj_t* self);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO_PS2_H
diff --git a/shared-bindings/ps2io/__init__.c b/shared-bindings/ps2io/__init__.c
new file mode 100644
index 000000000..ec7c43e51
--- /dev/null
+++ b/shared-bindings/ps2io/__init__.c
@@ -0,0 +1,73 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdint.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+
+#include "shared-bindings/microcontroller/Pin.h"
+#include "shared-bindings/ps2io/Ps2.h"
+
+//| :mod:`ps2io` --- Support for PS/2 protocol
+//| =====================================================
+//|
+//| .. module:: ps2io
+//| :synopsis: Support for PS/2 based devices
+//| :platform: SAMD21
+//|
+//| The `ps2io` module contains classes to provide PS/2 communication.
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| Ps2
+//|
+
+//| .. warning:: This module is not available in some SAMD21 builds. See the
+//| :ref:`module-support-matrix` for more info.
+//|
+
+//| All classes change hardware state and should be deinitialized when they
+//| are no longer needed if the program continues after use. To do so, either
+//| call :py:meth:`!deinit` or use a context manager. See
+//| :ref:`lifetime-and-contextmanagers` for more info.
+//|
+
+STATIC const mp_rom_map_elem_t ps2io_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ps2io) },
+ { MP_ROM_QSTR(MP_QSTR_Ps2), MP_ROM_PTR(&ps2io_ps2_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(ps2io_module_globals, ps2io_module_globals_table);
+
+const mp_obj_module_t ps2io_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&ps2io_module_globals,
+};
diff --git a/shared-bindings/ps2io/__init__.h b/shared-bindings/ps2io/__init__.h
new file mode 100644
index 000000000..1ff3d97b5
--- /dev/null
+++ b/shared-bindings/ps2io/__init__.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Scott Shawcroft
+ * Copyright (c) 2019 Elvis Pfutzenreuter <epxx@epxx.co>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_PS2IO___INIT___H