summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-03-04 15:56:48 -0500
committerGitHub <noreply@github.com>2019-03-04 15:56:48 -0500
commite6339656fcc08c2649ae68fa9b40bc804487aa78 (patch)
tree03e0a430c456865bced87652506a3ce2111820e4
parent146271fa580c92646776a2dad8800522256f7c73 (diff)
parent8de4cf6b10b48c982ec67dcc60e4eb96f394409f (diff)
Merge pull request #1614 from sommersoft/new_freq_in
Add frequencyio.FrequencyIn
-rw-r--r--locale/ID.po11
-rw-r--r--locale/circuitpython.pot11
-rw-r--r--locale/de_DE.po11
-rw-r--r--locale/en_US.po11
-rw-r--r--locale/es.po11
-rw-r--r--locale/fil.po11
-rw-r--r--locale/fr.po11
-rw-r--r--locale/it_IT.po11
-rw-r--r--locale/pt_BR.po11
-rw-r--r--ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/meowmeow/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/pewpew10/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk1
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk2
-rw-r--r--ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c547
-rw-r--r--ports/atmel-samd/common-hal/frequencyio/FrequencyIn.h60
-rw-r--r--ports/atmel-samd/common-hal/frequencyio/__init__.c1
-rw-r--r--ports/atmel-samd/timer_handler.c10
-rw-r--r--ports/atmel-samd/timer_handler.h1
-rw-r--r--ports/nrf/mpconfigport.mk3
-rw-r--r--py/circuitpy_defns.mk5
-rw-r--r--py/circuitpy_mpconfig.h8
-rw-r--r--py/circuitpy_mpconfig.mk5
-rw-r--r--shared-bindings/frequencyio/FrequencyIn.c241
-rw-r--r--shared-bindings/frequencyio/FrequencyIn.h46
-rw-r--r--shared-bindings/frequencyio/__init__.c89
-rw-r--r--shared-bindings/frequencyio/__init__.h34
-rw-r--r--shared-bindings/index.rst1
44 files changed, 1175 insertions, 11 deletions
diff --git a/locale/ID.po b/locale/ID.po
index f5fadce49..2d86f7e99 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\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"
@@ -557,6 +557,9 @@ msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX"
msgid "File exists"
msgstr ""
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr ""
@@ -598,6 +601,9 @@ msgstr "Bit clock pada pin tidak valid"
msgid "Invalid buffer size"
msgstr "Ukuran buffer tidak valid"
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
msgid "Invalid channel count"
msgstr ""
@@ -712,6 +718,9 @@ msgstr "Tidak pin RX"
msgid "No TX pin"
msgstr "Tidak ada pin TX"
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr "Tidak ada standar bus I2C"
diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot
index 0808ae43e..2426b37fa 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\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"
@@ -532,6 +532,9 @@ msgstr ""
msgid "File exists"
msgstr ""
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr ""
@@ -573,6 +576,9 @@ msgstr ""
msgid "Invalid buffer size"
msgstr ""
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
msgid "Invalid channel count"
msgstr ""
@@ -687,6 +693,9 @@ msgstr ""
msgid "No TX pin"
msgstr ""
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr ""
diff --git a/locale/de_DE.po b/locale/de_DE.po
index 941a5d5d1..e681c2630 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: Pascal Deneaux\n"
"Language-Team: Sebastian Plamauer, Pascal Deneaux\n"
@@ -537,6 +537,9 @@ msgstr "gatts value konnte nicht geschrieben werden. Status: 0x%04x"
msgid "File exists"
msgstr "Datei existiert"
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr "Die Funktion erwartet, dass der 'lock'-Befehl zuvor ausgeführt wurde"
@@ -580,6 +583,9 @@ msgstr "Ungültiges bit clock pin"
msgid "Invalid buffer size"
msgstr "Ungültige Puffergröße"
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
msgid "Invalid channel count"
msgstr "Ungültige Anzahl von Kanälen"
@@ -703,6 +709,9 @@ msgstr "Kein RX Pin"
msgid "No TX pin"
msgstr "Kein TX Pin"
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr "Kein Standard I2C Bus"
diff --git a/locale/en_US.po b/locale/en_US.po
index 01cbaeb51..e1f80398b 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\n"
"PO-Revision-Date: 2018-07-27 11:55-0700\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -532,6 +532,9 @@ msgstr ""
msgid "File exists"
msgstr ""
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr ""
@@ -573,6 +576,9 @@ msgstr ""
msgid "Invalid buffer size"
msgstr ""
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
msgid "Invalid channel count"
msgstr ""
@@ -687,6 +693,9 @@ msgstr ""
msgid "No TX pin"
msgstr ""
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr ""
diff --git a/locale/es.po b/locale/es.po
index a4eceb1fb..c230ee4ef 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\n"
"PO-Revision-Date: 2018-08-24 22:56-0500\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -562,6 +562,9 @@ msgstr "No se puede escribir el valor del atributo. status: 0x%02x"
msgid "File exists"
msgstr "El archivo ya existe"
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr "La función requiere lock"
@@ -605,6 +608,9 @@ msgstr "Pin bit clock inválido"
msgid "Invalid buffer size"
msgstr "Tamaño de buffer inválido"
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
msgid "Invalid channel count"
msgstr "Cuenta de canales inválida"
@@ -724,6 +730,9 @@ msgstr "Sin pin RX"
msgid "No TX pin"
msgstr "Sin pin TX"
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr "Sin bus I2C por defecto"
diff --git a/locale/fil.po b/locale/fil.po
index fb6002a57..974488f32 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\n"
"PO-Revision-Date: 2018-12-20 22:15-0800\n"
"Last-Translator: Timothy <me@timothygarcia.ca>\n"
"Language-Team: fil\n"
@@ -560,6 +560,9 @@ msgstr "Hindi maisulat ang gatts value, status: 0x%08lX"
msgid "File exists"
msgstr "Mayroong file"
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr "Function nangangailangan ng lock"
@@ -603,6 +606,9 @@ msgstr "Mali ang bit clock pin"
msgid "Invalid buffer size"
msgstr "Mali ang buffer size"
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
msgid "Invalid channel count"
msgstr "Maling bilang ng channel"
@@ -722,6 +728,9 @@ msgstr "Walang RX pin"
msgid "No TX pin"
msgstr "Walang TX pin"
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr "Walang default na I2C bus"
diff --git a/locale/fr.po b/locale/fr.po
index c937a4b5b..21c21f033 100644
--- a/locale/fr.po
+++ b/locale/fr.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2019-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\n"
"PO-Revision-Date: 2018-12-23 20:05+0100\n"
"Last-Translator: Pierrick Couturier <arofarn@arofarn.info>\n"
"Language-Team: fr\n"
@@ -559,6 +559,9 @@ msgstr "Impossible d'écrire la valeur de gatts. status: 0x%08lX"
msgid "File exists"
msgstr "Le fichier existe"
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr "La fonction nécessite un verrou"
@@ -604,6 +607,9 @@ msgstr "Broche invalide pour 'bit clock'"
msgid "Invalid buffer size"
msgstr "longueur de tampon invalide"
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
#, fuzzy
msgid "Invalid channel count"
msgstr "Argument invalide"
@@ -725,6 +731,9 @@ msgstr "Pas de broche RX"
msgid "No TX pin"
msgstr "Pas de broche TX"
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr "Pas de bus I2C par défaut"
diff --git a/locale/it_IT.po b/locale/it_IT.po
index 64fb22128..a3032db9d 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\n"
"PO-Revision-Date: 2018-10-02 16:27+0200\n"
"Last-Translator: Enrico Paganin <enrico.paganin@mail.com>\n"
"Language-Team: \n"
@@ -559,6 +559,9 @@ msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x"
msgid "File exists"
msgstr "File esistente"
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr ""
@@ -603,6 +606,9 @@ msgstr "Pin del clock di bit non valido"
msgid "Invalid buffer size"
msgstr "lunghezza del buffer non valida"
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
#, fuzzy
msgid "Invalid channel count"
msgstr "Argomento non valido"
@@ -720,6 +726,9 @@ msgstr "Nessun pin RX"
msgid "No TX pin"
msgstr "Nessun pin TX"
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr "Nessun bus I2C predefinito"
diff --git a/locale/pt_BR.po b/locale/pt_BR.po
index cf46dfbc5..a55de1994 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-03-01 07:16-0800\n"
+"POT-Creation-Date: 2019-03-03 00:16+0000\n"
"PO-Revision-Date: 2018-10-02 21:14-0000\n"
"Last-Translator: \n"
"Language-Team: \n"
@@ -552,6 +552,9 @@ msgstr "Não é possível gravar o valor do atributo. status: 0x%02x"
msgid "File exists"
msgstr "Arquivo já existe"
+msgid "Frequency captured is above capability. Capture Paused."
+msgstr ""
+
msgid "Function requires lock"
msgstr ""
@@ -594,6 +597,9 @@ msgstr "Pino de bit clock inválido"
msgid "Invalid buffer size"
msgstr "Arquivo inválido"
+msgid "Invalid capture period. Valid range: 1 - 500"
+msgstr ""
+
#, fuzzy
msgid "Invalid channel count"
msgstr "certificado inválido"
@@ -710,6 +716,9 @@ msgstr "Nenhum pino RX"
msgid "No TX pin"
msgstr "Nenhum pino TX"
+msgid "No available clocks"
+msgstr ""
+
msgid "No default I2C bus"
msgstr "Nenhum barramento I2C padrão"
diff --git a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
index bafb8a96c..b1b127ced 100644
--- a/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_mkr1300/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
index b6df8d6e2..0e6fb612e 100644
--- a/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_mkrzero/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
index af953e8c2..26f771b50 100644
--- a/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/arduino_zero/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
index aacffffe0..e1fba0d00 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
@@ -11,6 +11,7 @@ LONGINT_IMPL = MPZ
# Make room for frozen libs.
CIRCUITPY_DISPLAYIO = 0
+CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
index eed40f902..b450f1d55 100644
--- a/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express_crickit/mpconfigboard.mk
@@ -12,6 +12,7 @@ LONGINT_IMPL = NONE
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_PIXELBUF = 0
+CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
index 26e3b7d4d..0b9995583 100644
--- a/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_adalogger/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
index 102cb656f..a469dcf1d 100644
--- a/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_basic/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
index 989a676a5..efd45d049 100644
--- a/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express/mpconfigboard.mk
@@ -14,3 +14,5 @@ CHIP_FAMILY = samd21
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
index c6dc73d39..7d349193b 100644
--- a/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_express_crickit/mpconfigboard.mk
@@ -11,6 +11,7 @@ LONGINT_IMPL = MPZ
# Make space for frozen libs
CIRCUITPY_DISPLAYIO = 0
+CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
index ce3f8668c..16696297d 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_rfm69/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
index 282977338..39fdc591d 100644
--- a/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/feather_m0_rfm9x/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
index 9f4a9fe83..d44f2feb9 100644
--- a/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/gemma_m0/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
index 222a217b3..36cb67ea5 100644
--- a/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/hallowing_m0_express/mpconfigboard.mk
@@ -19,3 +19,4 @@ FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
# To keep the build small
CIRCUITPY_I2CSLAVE = 0
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk
index a620f2919..3547235dd 100644
--- a/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/meowmeow/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
index 1c5f4ff7d..ce46d7000 100644
--- a/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/metro_m0_express/mpconfigboard.mk
@@ -15,3 +15,5 @@ CHIP_FAMILY = samd21
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
index 983e48e21..92f8cff52 100644
--- a/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pewpew10/mpconfigboard.mk
@@ -20,3 +20,4 @@ CIRCUITPY_RTC = 0
CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_SMALL_BUILD = 1
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
index 8bac35604..418f70d92 100644
--- a/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/pirkey_m0/mpconfigboard.mk
@@ -17,6 +17,7 @@ CIRCUITPY_RTC = 0
CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_SMALL_BUILD = 1
+CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
index c0238ce80..ec627b523 100644
--- a/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd21_dev/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
index 462e3e2ca..8d2f35a69 100644
--- a/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/sparkfun_samd21_mini/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index 1c6f6db05..b3448cf49 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
index c9c196da7..5975ad1ba 100644
--- a/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0_haxpress/mpconfigboard.mk
@@ -11,3 +11,5 @@ LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
+
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
new file mode 100644
index 000000000..fa5d08a3f
--- /dev/null
+++ b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.c
@@ -0,0 +1,547 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Michael Schroeder
+ *
+ * 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 "hal/include/hal_gpio.h"
+#include "atmel_start_pins.h"
+#include "supervisor/shared/translate.h"
+
+#include "mpconfigport.h"
+#include "py/runtime.h"
+#include "timer_handler.h"
+#include "background.h"
+
+#include "samd/clocks.h"
+#include "samd/timers.h"
+#include "samd/events.h"
+#include "samd/pins.h"
+#include "samd/external_interrupts.h"
+
+#include "shared-bindings/frequencyio/FrequencyIn.h"
+#include "peripheral_clk_config.h"
+#include "hpl_gclk_config.h"
+
+#include "tick.h"
+
+#ifdef SAMD21
+#include "hpl/gclk/hpl_gclk_base.h"
+#endif
+
+static frequencyio_frequencyin_obj_t *active_frequencyins[TC_INST_NUM];
+volatile uint8_t reference_tc = 0xff;
+#ifdef SAMD51
+static uint8_t dpll_gclk;
+#endif
+
+void frequencyin_emergency_cancel_capture(uint8_t index) {
+ frequencyio_frequencyin_obj_t* self = active_frequencyins[index];
+
+ NVIC_DisableIRQ(self->TC_IRQ);
+ NVIC_ClearPendingIRQ(self->TC_IRQ);
+ #ifdef SAMD21
+ NVIC_DisableIRQ(EIC_IRQn);
+ NVIC_ClearPendingIRQ(EIC_IRQn);
+ #endif
+ #ifdef SAMD51
+ NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
+ NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
+ #endif
+
+ common_hal_frequencyio_frequencyin_pause(self); // pause any further captures
+
+ NVIC_EnableIRQ(self->TC_IRQ);
+ #ifdef SAMD21
+ NVIC_EnableIRQ(EIC_IRQn);
+ #endif
+ #ifdef SAMD51
+ NVIC_EnableIRQ(EIC_0_IRQn + self->channel);
+ #endif
+ mp_raise_RuntimeError(translate("Frequency captured is above capability. Capture Paused."));
+}
+
+void frequencyin_interrupt_handler(uint8_t index) {
+ Tc* ref_tc = tc_insts[reference_tc];
+
+ if (!ref_tc->COUNT16.INTFLAG.bit.OVF) return; // false trigger
+
+ uint32_t current_us;
+ uint64_t current_ms;
+ current_tick(&current_ms, &current_us);
+
+ for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
+ if (active_frequencyins[i] != NULL) {
+ frequencyio_frequencyin_obj_t* self = active_frequencyins[i];
+ Tc* tc = tc_insts[self->tc_index];
+
+ uint32_t mask = 1 << self->channel;
+ if ((EIC->INTFLAG.reg & mask) == mask) {
+ // Make sure capture_period has elapsed before we
+ // record a new event count.
+ if (current_ms - self->last_ms >= self->capture_period) {
+ float new_factor = self->last_us + (1000 - current_us);
+ self->factor = (current_ms - self->last_ms) + (new_factor / 1000);
+ self->last_ms = current_ms;
+ self->last_us = current_us;
+
+ #ifdef SAMD51
+ tc->COUNT16.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_READSYNC_Val;
+ while ((tc->COUNT16.SYNCBUSY.bit.COUNT == 1) ||
+ (tc->COUNT16.CTRLBSET.bit.CMD == TC_CTRLBSET_CMD_READSYNC_Val)) {
+ }
+ #endif
+
+ uint16_t new_freq = tc->COUNT16.COUNT.reg;
+ if ((tc->COUNT16.INTFLAG.reg & TC_INTFLAG_OVF) == 1) {
+ new_freq += 65535;
+ tc->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;
+ }
+ self->frequency = new_freq;
+
+ #ifdef SAMD51
+ tc->COUNT16.CTRLBSET.bit.CMD = TC_CTRLBSET_CMD_RETRIGGER_Val;
+ while ((tc->COUNT16.SYNCBUSY.bit.COUNT == 1) ||
+ (tc->COUNT16.CTRLBSET.bit.CMD == TC_CTRLBSET_CMD_RETRIGGER_Val)) {
+ }
+ #endif
+ }
+ EIC->INTFLAG.reg |= mask;
+ }
+
+ // Check if we've reached the upper limit of detection
+ if (!background_tasks_ok() || self->errored_too_fast) {
+ self->errored_too_fast = true;
+ frequencyin_emergency_cancel_capture(i);
+ }
+ }
+ }
+ ref_tc->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF;
+}
+
+void frequencyin_reference_tc_init() {
+ if (reference_tc == 0xff) {
+ return;
+ }
+ #ifdef SAMD21
+ set_timer_handler(true, reference_tc, TC_HANDLER_FREQUENCYIN);
+ turn_on_clocks(true, reference_tc, 0);
+ #endif
+ // use the DPLL we setup so that the reference_tc and freqin_tc(s)
+ // are using the same clock frequency.
+ #ifdef SAMD51
+ if (dpll_gclk == 0xff) {
+ frequencyin_samd51_start_dpll();
+ }
+ set_timer_handler(true, reference_tc, TC_HANDLER_FREQUENCYIN);
+ turn_on_clocks(true, reference_tc, dpll_gclk);
+ #endif
+
+ Tc *tc = tc_insts[reference_tc];
+ tc_set_enable(tc, false);
+ tc_reset(tc);
+
+ #ifdef SAMD21
+ tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 | TC_CTRLA_PRESCALER_DIV1;
+ tc->COUNT16.INTENSET.bit.OVF = 1;
+ NVIC_EnableIRQ(TC3_IRQn + reference_tc);
+ #endif
+ #ifdef SAMD51
+ tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
+ TC_CTRLA_PRESCALER_DIV1;
+ tc->COUNT16.INTENSET.bit.OVF = 1;
+ NVIC_EnableIRQ(TC0_IRQn + reference_tc);
+ #endif
+}
+
+bool frequencyin_reference_tc_enabled() {
+ if (reference_tc == 0xff) {
+ return false;
+ }
+ Tc *tc = tc_insts[reference_tc];
+ return tc->COUNT16.CTRLA.bit.ENABLE;
+}
+
+void frequencyin_reference_tc_enable(bool enable) {
+ if (reference_tc == 0xff) {
+ return;
+ }
+ Tc *tc = tc_insts[reference_tc];
+ tc_set_enable(tc, enable);
+}
+
+#ifdef SAMD51
+void frequencyin_samd51_start_dpll() {
+ if (clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
+ return;
+ }
+
+ uint8_t free_gclk = find_free_gclk(1);
+ if (free_gclk == 0xff) {
+ dpll_gclk = 0xff;
+ return;
+ }
+
+ GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(free_gclk);
+ // TC4-7 can only have a max of 100MHz source
+ // DPLL1 frequency equation with [X]OSC32K as source: 98.304MHz = 32768(2999 + 1 + 0/32)
+ // Will also enable the Lock Bypass due to low-frequency sources causing DPLL unlocks
+ // as outlined in the Errata (1.12.1)
+ OSCCTRL->Dpll[1].DPLLRATIO.reg = OSCCTRL_DPLLRATIO_LDRFRAC(0) | OSCCTRL_DPLLRATIO_LDR(2999);
+ if (board_has_crystal()) { // we can use XOSC32K directly as the source
+ OSC32KCTRL->XOSC32K.bit.EN32K = 1;
+ OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(1) |
+ OSCCTRL_DPLLCTRLB_LBYPASS;
+ } else {
+ // can't use OSCULP32K directly; need to setup a GCLK as a reference,
+ // which must be done in samd/clocks.c to avoid waiting for sync
+ return;
+ //OSC32KCTRL->OSCULP32K.bit.EN32K = 1;
+ //OSCCTRL->Dpll[1].DPLLCTRLB.reg = OSCCTRL_DPLLCTRLB_REFCLK(0);
+ }
+ OSCCTRL->Dpll[1].DPLLCTRLA.reg = OSCCTRL_DPLLCTRLA_ENABLE;
+
+ while (!(OSCCTRL->Dpll[1].DPLLSTATUS.bit.LOCK || OSCCTRL->Dpll[1].DPLLSTATUS.bit.CLKRDY)) {}
+ enable_clock_generator(free_gclk, GCLK_GENCTRL_SRC_DPLL1_Val, 1);
+ dpll_gclk = free_gclk;
+}
+
+void frequencyin_samd51_stop_dpll() {
+ if (!clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
+ return;
+ }
+
+ disable_clock_generator(dpll_gclk);
+
+ GCLK->PCHCTRL[OSCCTRL_GCLK_ID_FDPLL1].reg = 0;
+ OSCCTRL->Dpll[1].DPLLCTRLA.reg = 0;
+ OSCCTRL->Dpll[1].DPLLRATIO.reg = 0;
+ OSCCTRL->Dpll[1].DPLLCTRLB.reg = 0;
+
+ while (OSCCTRL->Dpll[1].DPLLSYNCBUSY.bit.ENABLE) {
+ }
+ dpll_gclk = 0xff;
+}
+#endif
+
+void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t* self, const mcu_pin_obj_t* pin, const uint16_t capture_period) {
+
+ if (!pin->has_extint) {
+ mp_raise_RuntimeError(translate("No hardware support on pin"));
+ }
+ if ((capture_period == 0) || (capture_period > 500)) {
+ mp_raise_ValueError(translate("Invalid capture period. Valid range: 1 - 500"));
+ }
+ uint32_t mask = 1 << pin->extint_channel;
+ if (eic_get_enable() == 1 &&
+ #ifdef SAMD21
+ ((EIC->INTENSET.vec.EXTINT & mask) != 0 || (EIC->EVCTRL.vec.EXTINTEO & mask) != 0)) {
+ #endif
+ #ifdef SAMD51
+ ((EIC->INTENSET.bit.EXTINT & mask) != 0 || (EIC->EVCTRL.bit.EXTINTEO & mask) != 0)) {
+ #endif
+ mp_raise_RuntimeError(translate("EXTINT channel already in use"));
+ }
+
+ uint8_t timer_index = find_free_timer();
+ if (timer_index == 0xff) {
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+ Tc *tc = tc_insts[timer_index];
+
+ self->tc_index = timer_index;
+ self->pin = pin->number;
+ self->channel = pin->extint_channel;
+ self->errored_too_fast = false;
+ self->last_ms = 0;
+ self->last_us = 1000;
+ self->capture_period = capture_period;
+ #ifdef SAMD21
+ self->TC_IRQ = TC3_IRQn + timer_index;
+ #endif
+ #ifdef SAMD51
+ self->TC_IRQ = TC0_IRQn + timer_index;
+ #endif
+
+ active_frequencyins[timer_index] = self;
+
+ // SAMD21: We use GCLK0 generated from DFLL running at 48mhz
+ // SAMD51: We use a GCLK generated from DPLL1 running at <100mhz
+ #ifdef SAMD21
+ set_timer_handler(timer_index, 0, TC_HANDLER_NO_INTERRUPT);
+ turn_on_clocks(true, timer_index, 0);
+ #endif
+ #ifdef SAMD51
+ frequencyin_samd51_start_dpll();
+ if (dpll_gclk == 0xff && !clock_get_enabled(0, GCLK_SOURCE_DPLL1)) {
+ common_hal_frequencyio_frequencyin_deinit(self);
+ mp_raise_RuntimeError(translate("No available clocks"));
+ }
+ set_timer_handler(timer_index, dpll_gclk, TC_HANDLER_NO_INTERRUPT);
+ turn_on_clocks(true, timer_index, dpll_gclk);
+ #endif
+
+ // Ensure EIC is on
+ if (eic_get_enable() == 0) {
+ turn_on_external_interrupt_controller(); // enables EIC, so disable it after
+ }
+ eic_set_enable(false);
+
+ uint8_t sense_setting = EIC_CONFIG_SENSE0_HIGH_Val;
+ uint8_t config_index = self->channel / 8;
+ uint8_t position = (self->channel % 8) * 4;
+ uint32_t masked_value = EIC->CONFIG[config_index].reg & ~(0xf << position);
+ EIC->CONFIG[config_index].reg = masked_value | (sense_setting << position);
+
+ #ifdef SAMD21
+ masked_value = EIC->EVCTRL.vec.EXTINTEO;
+ EIC->EVCTRL.vec.EXTINTEO = masked_value | (1 << self->channel);
+ #endif
+ #ifdef SAMD51
+ masked_value = EIC->EVCTRL.bit.EXTINTEO;
+ EIC->EVCTRL.bit.EXTINTEO = masked_value | (1 << self->channel);
+ EIC->ASYNCH.bit.ASYNCH = 1;
+ #endif
+
+ turn_on_cpu_interrupt(self->channel);
+
+ eic_set_enable(true);
+
+ // Turn on EVSYS
+ turn_on_event_system();
+ uint8_t evsys_channel = find_async_event_channel();
+ #ifdef SAMD21
+ connect_event_user_to_channel((EVSYS_ID_USER_TC3_EVU + timer_index), evsys_channel);
+ #endif
+ #ifdef SAMD51
+ connect_event_user_to_channel((EVSYS_ID_USER_TC0_EVU + timer_index), evsys_channel);
+ #endif
+ init_async_event_channel(evsys_channel, (EVSYS_ID_GEN_EIC_EXTINT_0 + self->channel));
+ self->event_channel = evsys_channel;
+
+ tc_set_enable(tc, false);
+ tc_reset(tc);
+ #ifdef SAMD21
+ tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
+ TC_CTRLA_PRESCALER_DIV1;
+ tc->COUNT16.EVCTRL.bit.TCEI = 1;
+ tc->COUNT16.EVCTRL.bit.EVACT = TC_EVCTRL_EVACT_COUNT_Val;
+ #endif
+
+ #ifdef SAMD51
+ tc->COUNT16.EVCTRL.reg = TC_EVCTRL_EVACT(TC_EVCTRL_EVACT_COUNT_Val) | TC_EVCTRL_TCEI;
+ tc->COUNT16.CTRLA.reg = TC_CTRLA_MODE_COUNT16 |
+ TC_CTRLA_PRESCALER_DIV1;
+ #endif
+
+ NVIC_EnableIRQ(self->TC_IRQ);
+
+ gpio_set_pin_function(pin->number, GPIO_PIN_FUNCTION_A);
+
+ tc_set_enable(tc, true);
+
+ // setup reference TC if not already
+ if (reference_tc == 0xff) {
+ reference_tc = find_free_timer();
+ if (reference_tc == 0xff) {
+ common_hal_frequencyio_frequencyin_deinit(self);
+ mp_raise_RuntimeError(translate("All timers in use"));
+ }
+ frequencyin_reference_tc_init();
+ }
+ if (!frequencyin_reference_tc_enabled()) {
+ frequencyin_reference_tc_enable(true);
+ }
+}
+
+bool common_hal_frequencyio_frequencyin_deinited(frequencyio_frequencyin_obj_t* self) {
+ return self->pin == NO_PIN;
+}
+
+void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t* self) {
+ if (common_hal_frequencyio_frequencyin_deinited(self)) {
+ return;
+ }
+ reset_pin_number(self->pin);
+
+ // turn off EIC & EVSYS utilized by this TC
+ disable_event_channel(self->event_channel);
+ eic_set_enable(false);
+ #ifdef SAMD21
+ disable_event_user(EVSYS_ID_USER_TC3_EVU + self->tc_index);
+ uint32_t masked_value = EIC->EVCTRL.vec.EXTINTEO;
+ EIC->EVCTRL.vec.EXTINTEO = masked_value ^ (1 << self->channel);
+ #endif
+ #ifdef SAMD51
+ disable_event_user(EVSYS_ID_USER_TC0_EVU + self->tc_index);
+ uint32_t masked_value = EIC->EVCTRL.bit.EXTINTEO;
+ EIC->EVCTRL.bit.EXTINTEO = masked_value ^ (1 << self->channel);
+ NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
+ NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
+ #endif
+ eic_set_enable(true);
+ // check if any other objects are using the EIC; if not, turn it off
+ if (EIC->EVCTRL.reg == 0 && EIC->INTENSET.reg == 0) {
+ eic_reset();
+ turn_off_external_interrupt_controller();
+ }
+
+ // turn off the TC we were using
+ Tc *tc = tc_insts[self->tc_index];
+ tc_set_enable(tc, false);
+ tc_reset(tc);
+ NVIC_DisableIRQ(self->TC_IRQ);
+ NVIC_ClearPendingIRQ(self->TC_IRQ);
+
+ active_frequencyins[self->tc_index] = NULL;
+ self->tc_index = 0xff;
+ self->pin = NO_PIN;
+
+ bool check_active = false;
+ for (uint8_t i = 0; i <= (TC_INST_NUM - 1); i++) {
+ if (active_frequencyins[i] != NULL) {
+ check_active = true;
+ }
+ }
+ if (!check_active) {
+ frequencyin_reference_tc_enable(false);
+ reference_tc = 0xff;
+ #ifdef SAMD51
+ frequencyin_samd51_stop_dpll();
+ #endif
+ }
+}
+
+uint32_t common_hal_frequencyio_frequencyin_get_item(frequencyio_frequencyin_obj_t* self) {
+ NVIC_DisableIRQ(self->TC_IRQ);
+ #ifdef SAMD21
+ NVIC_DisableIRQ(EIC_IRQn);
+ #endif
+ #ifdef SAMD51
+ NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
+ #endif
+
+ // adjust for actual capture period vs base `capture_period`
+ float frequency_adjustment = 0.0;
+ if (self->factor > self->capture_period) {
+ float time_each_event = self->factor / self->frequency; // get the time for each event during actual period
+ float capture_diff = self->factor - self->capture_period; // get the difference of actual and base periods
+ // we only need to adjust if the capture_diff can contain 1 or more events
+ // if so, we add how many events could have occured during the diff time
+ if (time_each_event > capture_diff) {
+ frequency_adjustment = capture_diff / time_each_event;
+ }
+ }
+
+ float value = 1000 / (self->capture_period / (self->frequency + frequency_adjustment));
+
+ NVIC_ClearPendingIRQ(self->TC_IRQ);
+ NVIC_EnableIRQ(self->TC_IRQ);
+ #ifdef SAMD21
+ NVIC_ClearPendingIRQ(EIC_IRQn);
+ NVIC_EnableIRQ(EIC_IRQn);
+ #endif
+ #ifdef SAMD51
+ NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
+ NVIC_EnableIRQ(EIC_0_IRQn + self->channel);
+ #endif
+
+ return value;
+}
+
+void common_hal_frequencyio_frequencyin_pause(frequencyio_frequencyin_obj_t* self) {
+ Tc *tc = tc_insts[self->tc_index];
+ if (!tc->COUNT16.EVCTRL.bit.TCEI) {
+ return;
+ }
+ tc->COUNT16.EVCTRL.bit.TCEI = 0;
+
+ #ifdef SAMD21
+ uint32_t masked_value = EIC->EVCTRL.vec.EXTINTEO;
+ EIC->EVCTRL.vec.EXTINTEO = masked_value ^ (1 << self->channel);
+ #endif
+ #ifdef SAMD51
+ uint32_t masked_value = EIC->EVCTRL.bit.EXTINTEO;
+ EIC->EVCTRL.bit.EXTINTEO = masked_value ^ (1 << self->channel);
+ #endif
+ return;
+}
+
+void common_hal_frequencyio_frequencyin_resume(frequencyio_frequencyin_obj_t* self) {
+ Tc *tc = tc_insts[self->tc_index];
+ if (tc->COUNT16.EVCTRL.bit.TCEI) {
+ return;
+ }
+ tc->COUNT16.EVCTRL.bit.TCEI = 1;
+
+ #ifdef SAMD21
+ uint32_t masked_value = EIC->EVCTRL.vec.EXTINTEO;
+ EIC->EVCTRL.vec.EXTINTEO = masked_value | (1 << self->channel);
+ #endif
+ #ifdef SAMD51
+ uint32_t masked_value = EIC->EVCTRL.bit.EXTINTEO;
+ EIC->EVCTRL.bit.EXTINTEO = masked_value | (1 << self->channel);
+ #endif
+ self->errored_too_fast = false;
+ return;
+}
+
+void common_hal_frequencyio_frequencyin_clear(frequencyio_frequencyin_obj_t* self) {
+ NVIC_DisableIRQ(self->TC_IRQ);
+ #ifdef SAMD21
+ NVIC_DisableIRQ(EIC_IRQn);
+ #endif
+ #ifdef SAMD51
+ NVIC_DisableIRQ(EIC_0_IRQn + self->channel);
+ #endif
+
+ self->frequency = 0;
+
+ NVIC_ClearPendingIRQ(self->TC_IRQ);
+ NVIC_EnableIRQ(self->TC_IRQ);
+ #ifdef SAMD21
+ NVIC_ClearPendingIRQ(EIC_IRQn);
+ NVIC_EnableIRQ(EIC_IRQn);
+ #endif
+ #ifdef SAMD51
+ NVIC_ClearPendingIRQ(EIC_0_IRQn + self->channel);
+ NVIC_EnableIRQ(EIC_0_IRQn + self->channel);
+ #endif
+ return;
+}
+
+uint16_t common_hal_frequencyio_frequencyin_get_capture_period(frequencyio_frequencyin_obj_t *self) {
+ return self->capture_period;
+}
+
+void common_hal_frequencyio_frequencyin_set_capture_period(frequencyio_frequencyin_obj_t *self, uint16_t capture_period) {
+ if ((capture_period == 0) || (capture_period > 500)) {
+ mp_raise_ValueError(translate("Invalid capture period. Valid range: 1 - 500"));
+ }
+
+ self->capture_period = capture_period;
+
+ common_hal_frequencyio_frequencyin_clear(self);
+}
diff --git a/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.h b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.h
new file mode 100644
index 000000000..abd63cc86
--- /dev/null
+++ b/ports/atmel-samd/common-hal/frequencyio/FrequencyIn.h
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Michael Schroeder
+ *
+ * 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_FREQUENCYIO_FREQUENCYIN_H
+#define MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H
+
+#include "common-hal/microcontroller/Pin.h"
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ uint8_t tc_index;
+ uint8_t pin;
+ uint8_t channel;
+ uint8_t event_channel;
+ uint32_t frequency;
+ volatile uint64_t last_ms;
+ volatile uint32_t last_us;
+ float factor;
+ uint32_t capture_period;
+ uint8_t TC_IRQ;
+ volatile bool errored_too_fast;
+} frequencyio_frequencyin_obj_t;
+
+void frequencyin_interrupt_handler(uint8_t index);
+void frequencyin_emergency_cancel_capture(uint8_t index);
+void frequencyin_reference_tc_init(void);
+void frequencyin_reference_tc_enable(bool enable);
+bool frequencyin_reference_tc_enabled(void);
+#ifdef SAMD51
+void frequencyin_samd51_start_dpll(void);
+void frequencyin_samd51_stop_dpll(void);
+#endif
+
+
+#endif // MICROPY_INCLUDED_ATMEL_SAMD_COMMON_HAL_FREQUENCYIO_FREQUENCYIN_H
diff --git a/ports/atmel-samd/common-hal/frequencyio/__init__.c b/ports/atmel-samd/common-hal/frequencyio/__init__.c
new file mode 100644
index 000000000..487814bd0
--- /dev/null
+++ b/ports/atmel-samd/common-hal/frequencyio/__init__.c
@@ -0,0 +1 @@
+// No ferquencyio module functions.
diff --git a/ports/atmel-samd/timer_handler.c b/ports/atmel-samd/timer_handler.c
index 059d4330e..61ab3e6d7 100644
--- a/ports/atmel-samd/timer_handler.c
+++ b/ports/atmel-samd/timer_handler.c
@@ -31,6 +31,7 @@
#include "common-hal/pulseio/PulseOut.h"
#include "shared-module/_pew/PewPew.h"
+#include "common-hal/frequencyio/FrequencyIn.h"
static uint8_t tc_handler[TC_INST_NUM];
@@ -50,9 +51,14 @@ void shared_timer_handler(bool is_tc, uint8_t index) {
pulseout_interrupt_handler(index);
break;
case TC_HANDLER_PEW:
-#if CIRCUITPY_PEW
+ #if CIRCUITPY_PEW
pewpew_interrupt_handler(index);
-#endif
+ #endif
+ break;
+ case TC_HANDLER_FREQUENCYIN:
+ #if CIRCUITPY_FREQUENCYIO
+ frequencyin_interrupt_handler(index);
+ #endif
break;
default:
break;
diff --git a/ports/atmel-samd/timer_handler.h b/ports/atmel-samd/timer_handler.h
index e249fca36..4a7adb58c 100644
--- a/ports/atmel-samd/timer_handler.h
+++ b/ports/atmel-samd/timer_handler.h
@@ -29,6 +29,7 @@
#define TC_HANDLER_NO_INTERRUPT 0x0
#define TC_HANDLER_PULSEOUT 0x1
#define TC_HANDLER_PEW 0x2
+#define TC_HANDLER_FREQUENCYIN 0x3
void set_timer_handler(bool is_tc, uint8_t index, uint8_t timer_handler);
void shared_timer_handler(bool is_tc, uint8_t index);
diff --git a/ports/nrf/mpconfigport.mk b/ports/nrf/mpconfigport.mk
index c90734c63..55c1734b9 100644
--- a/ports/nrf/mpconfigport.mk
+++ b/ports/nrf/mpconfigport.mk
@@ -24,3 +24,6 @@ CIRCUITPY_NVM = 0
# rtc not yet implemented
CIRCUITPY_RTC = 0
+
+# frequencyio not yet implemented
+CIRCUITPY_FREQUENCYIO = 0
diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk
index c10edfe4e..09d0a93e2 100644
--- a/py/circuitpy_defns.mk
+++ b/py/circuitpy_defns.mk
@@ -126,6 +126,9 @@ endif
ifeq ($(CIRCUITPY_DISPLAYIO),1)
SRC_PATTERNS += displayio/% terminalio/%
endif
+ifeq ($(CIRCUITPY_FREQUENCYIO),1)
+SRC_PATTERNS += frequencyio/%
+endif
ifeq ($(CIRCUITPY_GAMEPAD),1)
SRC_PATTERNS += gamepad/%
endif
@@ -231,6 +234,8 @@ $(filter $(SRC_PATTERNS), \
digitalio/DigitalInOut.c \
digitalio/__init__.c \
displayio/ParallelBus.c \
+ frequencyio/__init__.c \
+ frequencyio/FrequencyIn.c \
i2cslave/I2CSlave.c \
i2cslave/__init__.c \
microcontroller/Pin.c \
diff --git a/py/circuitpy_mpconfig.h b/py/circuitpy_mpconfig.h
index 520f7c612..00f3c7b3f 100644
--- a/py/circuitpy_mpconfig.h
+++ b/py/circuitpy_mpconfig.h
@@ -281,6 +281,13 @@ extern const struct _mp_obj_module_t terminalio_module;
#define CIRCUITPY_DISPLAY_LIMIT (0)
#endif
+#if CIRCUITPY_FREQUENCYIO
+extern const struct _mp_obj_module_t frequencyio_module;
+#define FREQUENCYIO_MODULE { MP_OBJ_NEW_QSTR(MP_QSTR_frequencyio), (mp_obj_t)&frequencyio_module },
+#else
+#define FREQUENCYIO_MODULE
+#endif
+
#if CIRCUITPY_GAMEPAD
extern const struct _mp_obj_module_t gamepad_module;
// Scan gamepad every 32ms
@@ -519,6 +526,7 @@ extern const struct _mp_obj_module_t pew_module;
TERMINALIO_MODULE \
DISPLAYIO_MODULE \
ERRNO_MODULE \
+ FREQUENCYIO_MODULE \
GAMEPAD_MODULE \
I2CSLAVE_MODULE \
JSON_MODULE \
diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk
index 54a38dfee..0df6fff06 100644
--- a/py/circuitpy_mpconfig.mk
+++ b/py/circuitpy_mpconfig.mk
@@ -92,6 +92,11 @@ CIRCUITPY_DISPLAYIO = $(CIRCUITPY_FULL_BUILD)
endif
CFLAGS += -DCIRCUITPY_DISPLAYIO=$(CIRCUITPY_DISPLAYIO)
+ifndef CIRCUITPY_FREQUENCYIO
+CIRCUITPY_FREQUENCYIO = 1
+endif
+CFLAGS += -DCIRCUITPY_FREQUENCYIO=$(CIRCUITPY_FREQUENCYIO)
+
ifndef CIRCUITPY_GAMEPAD
CIRCUITPY_GAMEPAD = $(CIRCUITPY_FULL_BUILD)
endif
diff --git a/shared-bindings/frequencyio/FrequencyIn.c b/shared-bindings/frequencyio/FrequencyIn.c
new file mode 100644
index 000000000..908cb307d
--- /dev/null
+++ b/shared-bindings/frequencyio/FrequencyIn.c
@@ -0,0 +1,241 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Michael Schroeder
+ *
+ * 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/frequencyio/FrequencyIn.h"
+#include "shared-bindings/util.h"
+#include "supervisor/shared/translate.h"
+
+//| .. currentmodule:: frequencyio
+//|
+//| :class:`FrequencyIn` -- Read a frequency signal
+//| ========================================================
+//|
+//| FrequencyIn is used to measure the frequency, in hertz, of a digital signal
+//| on an incoming pin. Accuracy has shown to be within 10%, if not better. It
+//| is recommended to utilize an average of multiple samples to smooth out readings.
+//|
+//| Frequencies below 1KHz are not currently detectable.
+//|
+//| FrequencyIn will not determine pulse width (use ``PulseIn``).
+//|
+//| .. class:: FrequencyIn(pin, capture_period=10)
+//|
+//| Create a FrequencyIn object associated with the given pin.
+//|
+//| :param ~microcontroller.Pin pin: Pin to read frequency from.
+//| :param int capture_period: Keyword argument to set the measurement period, in
+//| milliseconds. Default is 10ms; range is 1ms - 500ms.
+//|
+//| Read the incoming frequency from a pin::
+//|
+//| import frequencyio
+//| import board
+//|
+//| frequency = frequencyio.FrequencyIn(board.D11)
+//|
+//| # Loop while printing the detected frequency
+//| while True:
+//| print(frequency.value)
+//|
+//| # Optional clear() will reset the value
+//| # to zero. Without this, if the incoming
+//| # signal stops, the last reading will remain
+//| # as the value.
+//| frequency.clear()
+//|
+STATIC mp_obj_t frequencyio_frequencyin_make_new(const mp_obj_type_t *type, size_t n_args,
+ const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_check_num(n_args, kw_args, 1, 1, true);
+
+ frequencyio_frequencyin_obj_t *self = m_new_obj(frequencyio_frequencyin_obj_t);
+ self->base.type = &frequencyio_frequencyin_type;
+ enum { ARG_pin, ARG_capture_period };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ },
+ { MP_QSTR_capture_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 10} },
+ };
+ 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_pin].u_obj, false);
+ mcu_pin_obj_t* pin = MP_OBJ_TO_PTR(args[ARG_pin].u_obj);
+ assert_pin_free(pin);
+
+ const uint16_t capture_period = args[ARG_capture_period].u_int;
+
+ common_hal_frequencyio_frequencyin_construct(self, pin, capture_period);
+
+ return MP_OBJ_FROM_PTR(self);
+}
+
+//| .. method:: deinit()
+//|
+//| Deinitialises the FrequencyIn and releases any hardware resources for reuse.
+//|
+STATIC mp_obj_t frequencyio_frequencyin_deinit(mp_obj_t self_in) {
+ frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ common_hal_frequencyio_frequencyin_deinit(self);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_deinit_obj, frequencyio_frequencyin_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 frequencyio_frequencyin_obj___exit__(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ common_hal_frequencyio_frequencyin_deinit(args[0]);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(frequencyio_frequencyin___exit___obj, 4, 4, frequencyio_frequencyin_obj___exit__);
+
+//| .. method:: pause()
+//|
+//| Pause frequency capture.
+//|
+STATIC mp_obj_t frequencyio_frequencyin_obj_pause(mp_obj_t self_in) {
+ frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+
+ common_hal_frequencyio_frequencyin_pause(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_pause_obj, frequencyio_frequencyin_obj_pause);
+
+//| .. method:: resume()
+//|
+//| Resumes frequency capture.
+//|
+STATIC mp_obj_t frequencyio_frequencyin_obj_resume(mp_obj_t self_in) {
+ frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+
+ common_hal_frequencyio_frequencyin_resume(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_resume_obj, frequencyio_frequencyin_obj_resume);
+
+//| .. method:: clear()
+//|
+//| Clears the last detected frequency capture value.
+//|
+
+STATIC mp_obj_t frequencyio_frequencyin_obj_clear(mp_obj_t self_in) {
+ frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+
+ common_hal_frequencyio_frequencyin_clear(self);
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_clear_obj, frequencyio_frequencyin_obj_clear);
+
+//| .. attribute:: capture_period
+//|
+//| The capture measurement period. Lower incoming frequencies will be measured
+//| more accurately with longer capture periods. Higher frequencies are more
+//| accurate with shorter capture periods.
+//|
+//| .. note:: When setting a new ``capture_period``, all previous capture information is
+//| cleared with a call to ``clear()``.
+//|
+STATIC mp_obj_t frequencyio_frequencyin_obj_get_capture_period(mp_obj_t self_in) {
+ frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+
+ return MP_OBJ_NEW_SMALL_INT(common_hal_frequencyio_frequencyin_get_capture_period(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequency_get_capture_period_obj, frequencyio_frequencyin_obj_get_capture_period);
+
+STATIC mp_obj_t frequencyio_frequencyin_obj_set_capture_period(mp_obj_t self_in, mp_obj_t capture_period) {
+ frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+
+ common_hal_frequencyio_frequencyin_set_capture_period(self, mp_obj_get_int(capture_period));
+ return mp_const_none;
+}
+MP_DEFINE_CONST_FUN_OBJ_2(frequencyio_frequency_set_capture_period_obj, frequencyio_frequencyin_obj_set_capture_period);
+
+const mp_obj_property_t frequencyio_frequencyin_capture_period_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&frequencyio_frequency_get_capture_period_obj,
+ (mp_obj_t)&frequencyio_frequency_set_capture_period_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+//| .. method:: __get__(index)
+//|
+//| Returns the value of the last frequency captured.
+//|
+STATIC mp_obj_t frequencyio_frequencyin_obj_get_value(mp_obj_t self_in) {
+ frequencyio_frequencyin_obj_t *self = MP_OBJ_TO_PTR(self_in);
+ raise_error_if_deinited(common_hal_frequencyio_frequencyin_deinited(self));
+
+ //return MP_OBJ_NEW_SMALL_INT(common_hal_frequencyio_frequencyin_get_item(self));
+ return mp_obj_new_int_from_float(common_hal_frequencyio_frequencyin_get_item(self));
+}
+MP_DEFINE_CONST_FUN_OBJ_1(frequencyio_frequencyin_get_value_obj, frequencyio_frequencyin_obj_get_value);
+
+const mp_obj_property_t frequencyio_frequencyin_value_obj = {
+ .base.type = &mp_type_property,
+ .proxy = {(mp_obj_t)&frequencyio_frequencyin_get_value_obj,
+ (mp_obj_t)&mp_const_none_obj,
+ (mp_obj_t)&mp_const_none_obj},
+};
+
+STATIC const mp_rom_map_elem_t frequencyio_frequencyin_locals_dict_table[] = {
+ // Methods
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&frequencyio_frequencyin_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&default___enter___obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&frequencyio_frequencyin___exit___obj) },
+ { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&frequencyio_frequencyin_value_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pause), MP_ROM_PTR(&frequencyio_frequencyin_pause_obj) },
+ { MP_ROM_QSTR(MP_QSTR_resume), MP_ROM_PTR(&frequencyio_frequencyin_resume_obj) },
+ { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&frequencyio_frequencyin_clear_obj) },
+ { MP_ROM_QSTR(MP_QSTR_capture_period), MP_ROM_PTR(&frequencyio_frequencyin_capture_period_obj) },
+};
+STATIC MP_DEFINE_CONST_DICT(frequencyio_frequencyin_locals_dict, frequencyio_frequencyin_locals_dict_table);
+
+const mp_obj_type_t frequencyio_frequencyin_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_frequencyin,
+ .make_new = frequencyio_frequencyin_make_new,
+ .locals_dict = (mp_obj_dict_t*)&frequencyio_frequencyin_locals_dict,
+};
diff --git a/shared-bindings/frequencyio/FrequencyIn.h b/shared-bindings/frequencyio/FrequencyIn.h
new file mode 100644
index 000000000..dba6c3a66
--- /dev/null
+++ b/shared-bindings/frequencyio/FrequencyIn.h
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Michael Schroeder
+ *
+ * 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_FREQUENCYIO_FREQUENCYIN_H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO_FREQUENCYIN_H
+
+#include "common-hal/microcontroller/Pin.h"
+#include "common-hal/frequencyio/FrequencyIn.h"
+
+extern const mp_obj_type_t frequencyio_frequencyin_type;
+
+extern void common_hal_frequencyio_frequencyin_construct(frequencyio_frequencyin_obj_t *self,
+ const mcu_pin_obj_t *pin, uint16_t capture_period);
+extern void common_hal_frequencyio_frequencyin_deinit(frequencyio_frequencyin_obj_t *self);
+extern bool common_hal_frequencyio_frequencyin_deinited(frequencyio_frequencyin_obj_t *self);
+extern void common_hal_frequencyio_frequencyin_pause(frequencyio_frequencyin_obj_t *self);
+extern void common_hal_frequencyio_frequencyin_resume(frequencyio_frequencyin_obj_t *self);
+extern void common_hal_frequencyio_frequencyin_clear(frequencyio_frequencyin_obj_t *self);
+extern uint32_t common_hal_frequencyio_frequencyin_get_item(frequencyio_frequencyin_obj_t *self);
+extern uint16_t common_hal_frequencyio_frequencyin_get_capture_period(frequencyio_frequencyin_obj_t *self);
+extern void common_hal_frequencyio_frequencyin_set_capture_period(frequencyio_frequencyin_obj_t *self, uint16_t capture_period);
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO_FREQUENCYIN_H
diff --git a/shared-bindings/frequencyio/__init__.c b/shared-bindings/frequencyio/__init__.c
new file mode 100644
index 000000000..48a026824
--- /dev/null
+++ b/shared-bindings/frequencyio/__init__.c
@@ -0,0 +1,89 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Michael Schroeder
+ *
+ * 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/frequencyio/__init__.h"
+#include "shared-bindings/frequencyio/FrequencyIn.h"
+
+//| :mod:`frequencyio` --- Support for frequency based protocols
+//| =============================================================
+//|
+//| .. module:: frequencyio
+//| :synopsis: Support for frequency based protocols
+//| :platform: SAMD51
+//|
+//| The `frequencyio` module contains classes to provide access to basic frequency IO.
+//|
+//| Libraries
+//|
+//| .. toctree::
+//| :maxdepth: 3
+//|
+//| FrequencyIn
+//|
+
+//| .. warning:: This module is not available in 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.
+//|
+//| For example::
+//|
+//| import frequencyio
+//| import time
+//| from board import *
+//|
+//| frequency = frequencyio.FrequencyIn(D13)
+//| frequency.capture_period = 15
+//| time.sleep(0.1)
+//|
+//| This example will initialize the the device, set
+//| :py:data:`~frequencyio.FrequencyIn.capture_period`, and then sleep 0.1 seconds.
+//| CircuitPython will automatically turn off FrequencyIn capture when it resets all
+//| hardware after program completion. Use ``deinit()`` or a ``with`` statement
+//| to do it yourself.
+//|
+
+STATIC const mp_rom_map_elem_t frequencyio_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_frequencyio) },
+ { MP_ROM_QSTR(MP_QSTR_FrequencyIn), MP_ROM_PTR(&frequencyio_frequencyin_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(frequencyio_module_globals, frequencyio_module_globals_table);
+
+const mp_obj_module_t frequencyio_module = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&frequencyio_module_globals,
+};
diff --git a/shared-bindings/frequencyio/__init__.h b/shared-bindings/frequencyio/__init__.h
new file mode 100644
index 000000000..391576594
--- /dev/null
+++ b/shared-bindings/frequencyio/__init__.h
@@ -0,0 +1,34 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Michael Schroeder
+ *
+ * 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_FREQUENCYIO___INIT___H
+#define MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO___INIT___H
+
+#include "py/obj.h"
+
+// Nothing now.
+
+#endif // MICROPY_INCLUDED_SHARED_BINDINGS_FREQUENCYIO___INIT___H
diff --git a/shared-bindings/index.rst b/shared-bindings/index.rst
index 9641d73d1..4f2e28702 100644
--- a/shared-bindings/index.rst
+++ b/shared-bindings/index.rst
@@ -42,6 +42,7 @@ Module Supported Ports
`bleio` **nRF**
`busio` **All Supported**
`digitalio` **All Supported**
+`frequencyio` **SAMD51**
`gamepad` **SAMD Express, nRF**
`hashlib` **ESP8266**
`i2cslave` **SAMD Express**