Merge pull request #1614 from sommersoft/new_freq_in

Add frequencyio.FrequencyIn
This commit is contained in:
Dan Halbert 2019-03-04 15:56:48 -05:00 committed by GitHub
commit e6339656fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 1175 additions and 11 deletions

View File

@ -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"

View File

@ -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 ""

View File

@ -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"

View File

@ -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 ""

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -11,6 +11,7 @@ LONGINT_IMPL = MPZ
# Make room for frozen libs.
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21

View File

@ -12,6 +12,7 @@ LONGINT_IMPL = NONE
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_PIXELBUF = 0
CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -14,3 +14,5 @@ CHIP_FAMILY = samd21
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_FREQUENCYIO = 0

View File

@ -11,6 +11,7 @@ LONGINT_IMPL = MPZ
# Make space for frozen libs
CIRCUITPY_DISPLAYIO = 0
CIRCUITPY_FREQUENCYIO = 0
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -19,3 +19,4 @@ FROZEN_MPY_DIRS += $(TOP)/frozen/Adafruit_CircuitPython_NeoPixel
# To keep the build small
CIRCUITPY_I2CSLAVE = 0
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -15,3 +15,5 @@ CHIP_FAMILY = samd21
CIRCUITPY_NETWORK = 1
MICROPY_PY_WIZNET5K = 5500
CIRCUITPY_FREQUENCYIO = 0

View File

@ -20,3 +20,4 @@ CIRCUITPY_RTC = 0
CIRCUITPY_SAMD = 0
CIRCUITPY_USB_MIDI = 0
CIRCUITPY_SMALL_BUILD = 1
CIRCUITPY_FREQUENCYIO = 0

View File

@ -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

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -10,3 +10,5 @@ CIRCUITPY_SMALL_BUILD = 1
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -11,3 +11,5 @@ LONGINT_IMPL = MPZ
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
CIRCUITPY_FREQUENCYIO = 0

View File

@ -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);
}

View File

@ -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

View File

@ -0,0 +1 @@
// No ferquencyio module functions.

View File

@ -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;

View File

@ -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);

View File

@ -24,3 +24,6 @@ CIRCUITPY_NVM = 0
# rtc not yet implemented
CIRCUITPY_RTC = 0
# frequencyio not yet implemented
CIRCUITPY_FREQUENCYIO = 0

View File

@ -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 \

View File

@ -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 \

View File

@ -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

View File

@ -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,
};

View File

@ -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

View File

@ -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,
};

View File

@ -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

View File

@ -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**