diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index 4c58cd284852..18b4d2106577 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -912,10 +912,6 @@ msgstr "" msgid "Error in safemode.py." msgstr "" -#: shared-bindings/ssl/SSLSocket.c -msgid "Error: Failure to bind" -msgstr "" - #: shared-bindings/alarm/__init__.c msgid "Expected a kind of %q" msgstr "" @@ -1222,6 +1218,10 @@ msgstr "" msgid "Invalid data_pins[%d]" msgstr "" +#: ports/raspberrypi/common-hal/rp2clock/OutputPin.c +msgid "Invalid divisor: [1, 2-16777215]" +msgstr "" + #: shared-module/msgpack/__init__.c msgid "Invalid format" msgstr "" @@ -1230,6 +1230,16 @@ msgstr "" msgid "Invalid format chunk size" msgstr "" +#: ports/raspberrypi/common-hal/rp2clock/InputPin.c +#, c-format +msgid "Invalid freq: %u" +msgstr "" + +#: ports/raspberrypi/common-hal/rp2clock/InputPin.c +#, c-format +msgid "Invalid freqs: %u > %u" +msgstr "" + #: shared-bindings/wifi/Radio.c msgid "Invalid hex password" msgstr "" @@ -1657,6 +1667,16 @@ msgstr "" msgid "Permission denied" msgstr "" +#: ports/raspberrypi/common-hal/rp2clock/InputPin.c +#, c-format +msgid "Pin %d invalid, valid pins are: 20,22" +msgstr "" + +#: ports/raspberrypi/common-hal/rp2clock/OutputPin.c +#, c-format +msgid "Pin %d invalid, valid pins are: 21,23,24,25" +msgstr "" + #: ports/stm/common-hal/alarm/pin/PinAlarm.c msgid "Pin cannot wake from Deep Sleep" msgstr "" @@ -2730,6 +2750,10 @@ msgstr "" msgid "clip point must be (x,y) tuple" msgstr "" +#: ports/raspberrypi/common-hal/rp2clock/InputPin.c +msgid "clock_configure_gpin failed!" +msgstr "" + #: shared-bindings/msgpack/ExtType.c msgid "code outside range 0~127" msgstr "" diff --git a/ports/raspberrypi/Makefile b/ports/raspberrypi/Makefile index 2eb81017b3ed..56d226ad0e68 100644 --- a/ports/raspberrypi/Makefile +++ b/ports/raspberrypi/Makefile @@ -259,6 +259,17 @@ SRC_C += \ $(SRC_CYW43) \ $(SRC_LWIP) \ +ifeq ($(CIRCUITPY_RP2CLOCK),1) +SRC_C += \ + bindings/rp2clock/__init__.c \ + bindings/rp2clock/OutputPin.c \ + bindings/rp2clock/InputPin.c \ + bindings/rp2clock/AuxSrc.c \ + bindings/rp2clock/Index.c \ + common-hal/rp2clock/OutputPin.c \ + common-hal/rp2clock/InputPin.c \ + +endif ifeq ($(CIRCUITPY_USB_HOST), 1) SRC_C += \ diff --git a/ports/raspberrypi/bindings/rp2clock/AuxSrc.c b/ports/raspberrypi/bindings/rp2clock/AuxSrc.c new file mode 100644 index 000000000000..701435d859aa --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/AuxSrc.c @@ -0,0 +1,99 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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 "py/runtime.h" +#include "py/enum.h" +#include "bindings/rp2clock/AuxSrc.h" + +//| class AuxSrc: +//| """Defines the internal clock for GPOUT on RP2040.""" +//| +//| def __init__(self) -> None: +//| """Enum-like class to define the clock src.""" +//| PLL_SYS: object +//| """PLL used to derive SYS clock.""" +//| +//| GPIN0: object +//| """Input clock on GP20.""" +//| +//| GPIN1: object +//| """Input clock on GP22.""" +//| +//| PLL_USB: object +//| """Generates 48MHz USB reference clock.""" +//| +//| PLL_ROSC: object +//| """Ring oscillator clock. 1.8-12MHz on boot depending on PVT.""" +//| +//| PLL_XOSC: object +//| """External oscillator clock.""" +//| +//| SYS: object +//| """Derived system clock.""" +//| +//| USB: object +//| """Derived USB clock after PLL_USB divider, 48MHz.""" +//| +//| ADC: object +//| """Current ADC selected clock, 48MHz.""" +//| +//| RTC: object +//| """Current RTC selected clock.""" +//| +//| REF: object +//| """Current reference clock for watchdog and timers.""" +//| +const mp_obj_type_t rp2clock_auxsrc_type; + +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, PLL_SYS, AUXSRC_PLL_SYS); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, GPIN0, AUXSRC_GPIN0); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, GPIN1, AUXSRC_GPIN1); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, PLL_USB, AUXSRC_PLL_USB); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, PLL_ROSC, AUXSRC_PLL_ROSC); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, PLL_XOSC, AUXSRC_PLL_XOSC); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, SYS, AUXSRC_SYS); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, USB, AUXSRC_USB); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, ADC, AUXSRC_ADC); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, RTC, AUXSRC_RTC); +MAKE_ENUM_VALUE(rp2clock_auxsrc_type, rp2clock_auxsrc, REF, AUXSRC_REF); + +MAKE_ENUM_MAP(rp2clock_auxsrc) { + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, PLL_SYS), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, GPIN0), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, GPIN1), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, PLL_USB), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, PLL_ROSC), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, PLL_XOSC), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, SYS), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, USB), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, ADC), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, RTC), + MAKE_ENUM_MAP_ENTRY(rp2clock_auxsrc, REF), +}; + +STATIC MP_DEFINE_CONST_DICT(rp2clock_auxsrc_locals_dict, rp2clock_auxsrc_locals_table); +MAKE_PRINTER(rp2clock, rp2clock_auxsrc); +MAKE_ENUM_TYPE(rp2clock, AuxSrc, rp2clock_auxsrc); diff --git a/ports/raspberrypi/bindings/rp2clock/AuxSrc.h b/ports/raspberrypi/bindings/rp2clock/AuxSrc.h new file mode 100644 index 000000000000..1e2a8ab4b02a --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/AuxSrc.h @@ -0,0 +1,47 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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. + */ + +#pragma once + +#include "py/obj.h" +#include "hardware/regs/clocks.h" + +// Output sources +typedef enum { + AUXSRC_PLL_SYS = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, + AUXSRC_GPIN0 = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLKSRC_GPIN0, + AUXSRC_GPIN1 = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLKSRC_GPIN1, + AUXSRC_PLL_USB = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB, + AUXSRC_PLL_ROSC = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_ROSC_CLKSRC, + AUXSRC_PLL_XOSC = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_XOSC_CLKSRC, + AUXSRC_SYS = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLK_SYS, + AUXSRC_USB = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLK_USB, + AUXSRC_ADC = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLK_ADC, + AUXSRC_RTC = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLK_RTC, + AUXSRC_REF = CLOCKS_CLK_GPOUT0_CTRL_AUXSRC_VALUE_CLK_REF, +} rp2clock_auxsrc_t; + +extern const mp_obj_type_t rp2clock_auxsrc_type; diff --git a/ports/raspberrypi/bindings/rp2clock/Index.c b/ports/raspberrypi/bindings/rp2clock/Index.c new file mode 100644 index 000000000000..3e4ad606c376 --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/Index.c @@ -0,0 +1,94 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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 "py/runtime.h" +#include "py/enum.h" +#include "bindings/rp2clock/Index.h" + +//| class Index: +//| """Defines the internal clock to be driven from GPIN external pin.""" +//| +//| def __init__(self) -> None: +//| """Enum-like class to define the internal clock index.""" +//| GPOUT0: object +//| """Clock routed to GPOUT0 (GP21)""" +//| +//| GPOUT1: object +//| """Clock routed to GPOUT1 (GP23)""" +//| +//| GPOUT2: object +//| """Clock routed to GPOUT2 (GP24)""" +//| +//| GPOUT3: object +//| """Clock routed to GPOUT3 (GP25)""" +//| +//| REF: object +//| """Reference clock for watchdog and timers.""" +//| +//| SYS: object +//| """Main system clock for processors.""" +//| +//| PERI: object +//| """Peripheral clock: UART, SPI, etc. 12-125MHz""" +//| +//| USB: object +//| """USB clock: Must be 48MHz.""" +//| +//| ADC: object +//| """ADC clock: Must be 48MHz.""" +//| +//| RTC: object +//| """RTC clock: Nominally 46875 for 1 second ticks.""" +//| +const mp_obj_type_t rp2clock_index_type; + +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, GPOUT0, INDEX_GPOUT0); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, GPOUT1, INDEX_GPOUT1); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, GPOUT2, INDEX_GPOUT2); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, GPOUT3, INDEX_GPOUT3); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, REF, INDEX_REF); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, SYS, INDEX_SYS); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, PERI, INDEX_PERI); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, USB, INDEX_USB); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, ADC, INDEX_ADC); +MAKE_ENUM_VALUE(rp2clock_index_type, rp2clock_index, RTC, INDEX_RTC); + +MAKE_ENUM_MAP(rp2clock_index) { + MAKE_ENUM_MAP_ENTRY(rp2clock_index, GPOUT0), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, GPOUT1), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, GPOUT2), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, GPOUT3), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, REF), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, SYS), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, PERI), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, USB), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, ADC), + MAKE_ENUM_MAP_ENTRY(rp2clock_index, RTC), +}; + +STATIC MP_DEFINE_CONST_DICT(rp2clock_index_locals_dict, rp2clock_index_locals_table); +MAKE_PRINTER(rp2clock, rp2clock_index); +MAKE_ENUM_TYPE(rp2clock, Index, rp2clock_index); diff --git a/ports/raspberrypi/bindings/rp2clock/Index.h b/ports/raspberrypi/bindings/rp2clock/Index.h new file mode 100644 index 000000000000..5a9c25fd4a78 --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/Index.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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. + */ + +#pragma once + +#include "py/obj.h" +#include "hardware/clocks.h" + +// Input sources +typedef enum { + INDEX_GPOUT0 = clk_gpout0, + INDEX_GPOUT1 = clk_gpout1, + INDEX_GPOUT2 = clk_gpout2, + INDEX_GPOUT3 = clk_gpout3, + INDEX_REF = clk_ref, + INDEX_SYS = clk_sys, + INDEX_PERI = clk_peri, + INDEX_USB = clk_usb, + INDEX_ADC = clk_adc, + INDEX_RTC = clk_rtc, +} rp2clock_index_t; + +extern const mp_obj_type_t rp2clock_index_type; diff --git a/ports/raspberrypi/bindings/rp2clock/InputPin.c b/ports/raspberrypi/bindings/rp2clock/InputPin.c new file mode 100644 index 000000000000..5932ca683f19 --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/InputPin.c @@ -0,0 +1,149 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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 "py/obj.h" +#include "py/enum.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/objarray.h" + +#include "shared-bindings/util.h" +#include "bindings/rp2clock/InputPin.h" +#include "common-hal/rp2clock/InputPin.h" + +STATIC void check_for_deinit(rp2clock_inputpin_obj_t *self) { + if (common_hal_rp2clock_inputpin_deinited(self)) { + raise_deinited_error(); + } +} + +//| class InputPin: +//| """Route external clocks to internal clocks via dedicated pins.""" +//| +//| def __init__( +//| self, pin: microcontroller.Pin, index: rp2clock.Index, src_freq: int, target_freq: int +//| ) -> None: +//| """Creates a clock input pin object. +//| +//| .. note:: Valid pins are: GP20, GP22. +//| +//| :param ~microcontroller.Pin pin: Pin to be used as clock input. +//| +//| :param ~rp2clock.Index index: Destination clock to be connected to the input pin. +//| +//| :param int src_freq: Frequency of clock input at the pin. +//| +//| :param int target_freq: Desired frequency for ~rp2clock.Index clock.""" +STATIC mp_obj_t rp2clock_inputpin_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_pin, ARG_index, ARG_src_freq, ARG_target_freq }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_index, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_src_freq, MP_ARG_REQUIRED | MP_ARG_INT }, + { MP_QSTR_target_freq, MP_ARG_REQUIRED | MP_ARG_INT }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + rp2clock_inputpin_obj_t *self = m_new_obj_with_finaliser(rp2clock_inputpin_obj_t); + self->base.type = &rp2clock_inputpin_type; + + // Validate pin number + common_hal_rp2clock_inputpin_validate_index_pin(args[ARG_pin].u_rom_obj); + self->pin = args[ARG_pin].u_rom_obj; + + // Validate clock + self->index = cp_enum_value(&rp2clock_index_type, args[ARG_index].u_obj, MP_QSTR_rp2clock_index); + + // Validate frequencies + common_hal_rp2clock_inputpin_validate_freqs(args[ARG_src_freq].u_int, args[ARG_target_freq].u_int); + self->src_freq = args[ARG_src_freq].u_int; + self->target_freq = args[ARG_target_freq].u_int; + + // Enable and return + common_hal_rp2clock_inputpin_enable(self); + return MP_OBJ_FROM_PTR(self); +}; + +//| def deinit(self) -> None: +//| """Releases the pin and frees any resources.""" +STATIC mp_obj_t rp2clock_inputpin_deinit(mp_obj_t self_in) { + rp2clock_inputpin_obj_t *self = MP_OBJ_TO_PTR(self_in); + // Release pin + common_hal_rp2clock_inputpin_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(rp2clock_inputpin_deinit_obj, rp2clock_inputpin_deinit); + +//| def enable(self) -> None: +//| """Configures the pin and enables the internal clock.""" +STATIC mp_obj_t rp2clock_inputpin_enable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + rp2clock_inputpin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + common_hal_rp2clock_inputpin_enable(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(rp2clock_inputpin_enable_obj, 1, rp2clock_inputpin_enable); + +//| def disable(self) -> None: +//| """Disables the pin and internal clock""" +STATIC mp_obj_t rp2clock_inputpin_disable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + rp2clock_inputpin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + common_hal_rp2clock_inputpin_disable(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(rp2clock_inputpin_disable_obj, 1, rp2clock_inputpin_disable); + +//| def enabled(self) -> bool: +//| """Check if pin is enabled.""" +//| +static mp_obj_t rp2clock_inputpin_get_enabled(mp_obj_t self_in) { + rp2clock_inputpin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(self->enabled); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2clock_inputpin_get_enabled_obj, rp2clock_inputpin_get_enabled); +MP_PROPERTY_GETTER(rp2clock_inputpin_enabled_obj, + (mp_obj_t)&rp2clock_inputpin_get_enabled_obj); + +STATIC const mp_rom_map_elem_t rp2clock_inputpin_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&rp2clock_inputpin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rp2clock_inputpin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&rp2clock_inputpin_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&rp2clock_inputpin_disable_obj) }, + { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&rp2clock_inputpin_enabled_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(rp2clock_inputpin_locals_dict, rp2clock_inputpin_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + rp2clock_inputpin_type, + MP_QSTR_InputPin, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, rp2clock_inputpin_make_new, + locals_dict, &rp2clock_inputpin_locals_dict + ); diff --git a/ports/raspberrypi/bindings/rp2clock/InputPin.h b/ports/raspberrypi/bindings/rp2clock/InputPin.h new file mode 100644 index 000000000000..5d1a5602855c --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/InputPin.h @@ -0,0 +1,31 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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. + */ + +#pragma once + +#include "shared-bindings/microcontroller/Pin.h" + +extern const mp_obj_type_t rp2clock_inputpin_type; diff --git a/ports/raspberrypi/bindings/rp2clock/OutputPin.c b/ports/raspberrypi/bindings/rp2clock/OutputPin.c new file mode 100644 index 000000000000..f9f7af58401e --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/OutputPin.c @@ -0,0 +1,140 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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 "py/obj.h" +#include "py/objproperty.h" +#include "py/runtime.h" +#include "py/objarray.h" +#include "py/enum.h" + +#include "shared-bindings/util.h" +#include "bindings/rp2clock/OutputPin.h" +#include "common-hal/rp2clock/OutputPin.h" + +STATIC void check_for_deinit(rp2clock_outputpin_obj_t *self) { + if (common_hal_rp2clock_outputpin_deinited(self)) { + raise_deinited_error(); + } +} + +//| class OutputPin: +//| def __init__(self, pin: microcontroller.Pin, src: rp2clock.AuxSrc, divisor: float) -> None: +//| """Creates a clock output pin object. +//| +//| .. note:: Valid pins are: GP21, GP23, GP24, GP25. +//| +//| :param ~microcontroller.Pin pin: Pin to be used as clock output. +//| +//| :param ~rp2clock.AuxSrc src: Source clock to be connected to the output pin. +//| +//| :param float divisor: Divisor for clock before it's driven onto pin.""" +STATIC mp_obj_t rp2clock_outputpin_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *all_args) { + enum { ARG_pin, ARG_src, ARG_divisor }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_pin, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_src, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_divisor, MP_ARG_REQUIRED | MP_ARG_OBJ }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + rp2clock_outputpin_obj_t *self = m_new_obj_with_finaliser(rp2clock_outputpin_obj_t); + self->base.type = &rp2clock_outputpin_type; + + // Validate pin number + common_hal_rp2clock_outputpin_validate_src_pin(args[ARG_pin].u_rom_obj); + self->pin = args[ARG_pin].u_rom_obj; + self->divisor = common_hal_rp2clock_outputpin_validate_divisor(mp_obj_get_float(args[ARG_divisor].u_obj)); + + // Validate clock + self->src = cp_enum_value(&rp2clock_auxsrc_type, args[ARG_src].u_obj, MP_QSTR_rp2clock_auxsrc); + + // Enable pin + common_hal_rp2clock_outputpin_enable(self); + return MP_OBJ_FROM_PTR(self); +} + +//| def deinit(self) -> None: +//| """Releases the pin and frees any resources.""" +STATIC mp_obj_t rp2clock_outputpin_deinit(mp_obj_t self_in) { + rp2clock_outputpin_obj_t *self = MP_OBJ_TO_PTR(self_in); + // Release pin + common_hal_rp2clock_outputpin_deinit(self); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(rp2clock_outputpin_deinit_obj, rp2clock_outputpin_deinit); + +//| def enable(self) -> None: +//| """Configures the pin and enables the clock output.""" +STATIC mp_obj_t rp2clock_outputpin_enable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + rp2clock_outputpin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + common_hal_rp2clock_outputpin_enable(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(rp2clock_outputpin_enable_obj, 1, rp2clock_outputpin_enable); + +//| def disable(self) -> None: +//| """Disables the pin and external clock.""" +STATIC mp_obj_t rp2clock_outputpin_disable(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + rp2clock_outputpin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + check_for_deinit(self); + common_hal_rp2clock_outputpin_disable(self); + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(rp2clock_outputpin_disable_obj, 1, rp2clock_outputpin_disable); + +//| enabled: bool +//| """Check if pin is enabled.""" +//| +static mp_obj_t rp2clock_outputpin_get_enabled(mp_obj_t self_in) { + rp2clock_outputpin_obj_t *self = MP_OBJ_TO_PTR(self_in); + check_for_deinit(self); + return mp_obj_new_bool(self->enabled); +} +MP_DEFINE_CONST_FUN_OBJ_1(rp2clock_outputpin_get_enabled_obj, rp2clock_outputpin_get_enabled); +MP_PROPERTY_GETTER(rp2clock_outputpin_enabled_obj, + (mp_obj_t)&rp2clock_outputpin_get_enabled_obj); + +STATIC const mp_rom_map_elem_t rp2clock_outputpin_locals_dict_table[] = { + // Functions + { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&rp2clock_outputpin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&rp2clock_outputpin_deinit_obj) }, + { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&rp2clock_outputpin_enable_obj) }, + { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&rp2clock_outputpin_disable_obj) }, + // Properties + { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&rp2clock_outputpin_enabled_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(rp2clock_outputpin_locals_dict, rp2clock_outputpin_locals_dict_table); + +MP_DEFINE_CONST_OBJ_TYPE( + rp2clock_outputpin_type, + MP_QSTR_OutputPin, + MP_TYPE_FLAG_HAS_SPECIAL_ACCESSORS, + make_new, rp2clock_outputpin_make_new, + locals_dict, &rp2clock_outputpin_locals_dict + ); diff --git a/ports/raspberrypi/bindings/rp2clock/OutputPin.h b/ports/raspberrypi/bindings/rp2clock/OutputPin.h new file mode 100644 index 000000000000..f0d5b1121e8c --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/OutputPin.h @@ -0,0 +1,31 @@ +/* + * This file is part of the Micro Python project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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. + */ + +#pragma once + +#include "shared-bindings/microcontroller/Pin.h" + +extern const mp_obj_type_t rp2clock_outputpin_type; diff --git a/ports/raspberrypi/bindings/rp2clock/__init__.c b/ports/raspberrypi/bindings/rp2clock/__init__.c new file mode 100644 index 000000000000..f65406fb6061 --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/__init__.c @@ -0,0 +1,56 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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 "py/runtime.h" + +#include "shared-bindings/board/__init__.h" +#include "shared-bindings/microcontroller/__init__.h" +#include "shared-bindings/microcontroller/Pin.h" +#include "bindings/rp2clock/__init__.h" +#include "bindings/rp2clock/AuxSrc.h" +#include "bindings/rp2clock/Index.h" +#include "bindings/rp2clock/OutputPin.h" +#include "bindings/rp2clock/InputPin.h" + +//| """Hardware interface for RP2040 clock control""" +STATIC const mp_rom_map_elem_t rp2clock_module_globals_table[] = { + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_rp2clock) }, + { MP_ROM_QSTR(MP_QSTR_OutputPin), MP_ROM_PTR(&rp2clock_outputpin_type) }, + { MP_ROM_QSTR(MP_QSTR_InputPin), MP_ROM_PTR(&rp2clock_inputpin_type) }, + + // Enum like classes + { MP_ROM_QSTR(MP_QSTR_AuxSrc), MP_ROM_PTR(&rp2clock_auxsrc_type) }, + { MP_ROM_QSTR(MP_QSTR_Index), MP_ROM_PTR(&rp2clock_index_type) }, +}; + +STATIC MP_DEFINE_CONST_DICT(rp2clock_module_globals, rp2clock_module_globals_table); + +const mp_obj_module_t rp2clock_module = { + .base = { &mp_type_module }, + .globals = (mp_obj_dict_t *)&rp2clock_module_globals, +}; + +MP_REGISTER_MODULE(MP_QSTR_rp2clock, rp2clock_module); diff --git a/ports/raspberrypi/bindings/rp2clock/__init__.h b/ports/raspberrypi/bindings/rp2clock/__init__.h new file mode 100644 index 000000000000..2c5c13dfda66 --- /dev/null +++ b/ports/raspberrypi/bindings/rp2clock/__init__.h @@ -0,0 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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. + */ + +#pragma once + +#include "py/obj.h" diff --git a/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.mk b/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.mk index 20607d50e41c..608289888e05 100644 --- a/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.mk +++ b/ports/raspberrypi/boards/raspberry_pi_pico/mpconfigboard.mk @@ -10,3 +10,4 @@ EXTERNAL_FLASH_DEVICES = "W25Q16JVxQ" CIRCUITPY__EVE = 1 CIRCUITPY_PICODVI = 1 +CIRCUITPY_RP2CLOCK = 1 diff --git a/ports/raspberrypi/common-hal/rp2clock/InputPin.c b/ports/raspberrypi/common-hal/rp2clock/InputPin.c new file mode 100644 index 000000000000..bc1035509af6 --- /dev/null +++ b/ports/raspberrypi/common-hal/rp2clock/InputPin.c @@ -0,0 +1,88 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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 "shared-bindings/microcontroller/Pin.h" +#include "common-hal/rp2clock/InputPin.h" +#include "bindings/rp2clock/Index.h" +#include "hardware/clocks.h" +#include "hardware/gpio.h" +#include "py/runtime.h" + +// GPIN must be [20,22] +void common_hal_rp2clock_inputpin_validate_index_pin(const mcu_pin_obj_t *pin) { + if ((pin->number != 20) && (pin->number != 22)) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Pin %d invalid, valid pins are: 20,22"), pin->number); + } +} + +void common_hal_rp2clock_inputpin_validate_freqs(uint32_t src, uint32_t target) { + if (src == 0) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid freq: %u"), src); + } + if (target == 0) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid freq: %u"), target); + } + if (target > src) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Invalid freqs: %u > %u"), target, src); + } +} + +bool common_hal_rp2clock_inputpin_deinited(rp2clock_inputpin_obj_t *self) { + return self->pin == NULL; +} + +void common_hal_rp2clock_inputpin_deinit(rp2clock_inputpin_obj_t *self) { + if (common_hal_rp2clock_inputpin_deinited(self)) { + return; + } + if (self->enabled) { + common_hal_rp2clock_inputpin_disable(self); + } + self->pin = NULL; +} + +static void common_hal_rp2clock_inputpin_claim_pin(rp2clock_inputpin_obj_t *self) { + // Check pin is available + assert_pin_free(self->pin); + // Claim pin + common_hal_mcu_pin_claim(self->pin); +} + +void common_hal_rp2clock_inputpin_enable(rp2clock_inputpin_obj_t *self) { + common_hal_rp2clock_inputpin_claim_pin(self); + // Check return value + if (!clock_configure_gpin(self->index, self->pin->number, self->src_freq, self->target_freq)) { + mp_raise_RuntimeError(MP_ERROR_TEXT("clock_configure_gpin failed!")); + } + self->enabled = true; +} + +void common_hal_rp2clock_inputpin_disable(rp2clock_inputpin_obj_t *self) { + if (!self->enabled) { + return; + } + common_hal_reset_pin(self->pin); + self->enabled = false; +} diff --git a/ports/raspberrypi/common-hal/rp2clock/InputPin.h b/ports/raspberrypi/common-hal/rp2clock/InputPin.h new file mode 100644 index 000000000000..7fd05c130da4 --- /dev/null +++ b/ports/raspberrypi/common-hal/rp2clock/InputPin.h @@ -0,0 +1,48 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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. + */ +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "bindings/rp2clock/Index.h" +#include "hardware/clocks.h" + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; + rp2clock_index_t index; + uint32_t src_freq; + uint32_t target_freq; + bool enabled; +} rp2clock_inputpin_obj_t; + +void common_hal_rp2clock_inputpin_validate_index_pin(const mcu_pin_obj_t *pin); +bool common_hal_rp2clock_inputpin_deinited(rp2clock_inputpin_obj_t *self); +void common_hal_rp2clock_inputpin_deinit(rp2clock_inputpin_obj_t *self); +void common_hal_rp2clock_inputpin_validate_freqs(uint32_t src, uint32_t target); + +// Configure clock in/out +void common_hal_rp2clock_inputpin_enable(rp2clock_inputpin_obj_t *self); +void common_hal_rp2clock_inputpin_disable(rp2clock_inputpin_obj_t *self); diff --git a/ports/raspberrypi/common-hal/rp2clock/OutputPin.c b/ports/raspberrypi/common-hal/rp2clock/OutputPin.c new file mode 100644 index 000000000000..b7062122c2c5 --- /dev/null +++ b/ports/raspberrypi/common-hal/rp2clock/OutputPin.c @@ -0,0 +1,83 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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 "shared-bindings/microcontroller/Pin.h" +#include "common-hal/rp2clock/OutputPin.h" +#include "bindings/rp2clock/AuxSrc.h" +#include "hardware/clocks.h" +#include "hardware/gpio.h" +#include "py/runtime.h" + +// GPOUT must be [21,23,24,25] +void common_hal_rp2clock_outputpin_validate_src_pin(const mcu_pin_obj_t *pin) { + if ((pin->number != 21) && (pin->number != 23) && + (pin->number != 24) && (pin->number != 25)) { + mp_raise_ValueError_varg(MP_ERROR_TEXT("Pin %d invalid, valid pins are: 21,23,24,25"), pin->number); + } +} + +mp_float_t common_hal_rp2clock_outputpin_validate_divisor(mp_float_t div) { + if (mp_obj_float_binary_op(MP_BINARY_OP_EQUAL, div, mp_obj_new_float(1.0f)) || + (div >= 2.0f && div <= 16777215.0f)) { + return div; + } + mp_raise_ValueError(MP_ERROR_TEXT("Invalid divisor: [1, 2-16777215]")); + return 1.0f; +} + +bool common_hal_rp2clock_outputpin_deinited(rp2clock_outputpin_obj_t *self) { + return self->pin == NULL; +} + +void common_hal_rp2clock_outputpin_deinit(rp2clock_outputpin_obj_t *self) { + if (common_hal_rp2clock_outputpin_deinited(self)) { + return; + } + if (self->enabled) { + common_hal_rp2clock_outputpin_disable(self); + } + self->pin = NULL; +} + +static void common_hal_rp2clock_outputpin_claim_pin(rp2clock_outputpin_obj_t *self) { + // Check pin is available + assert_pin_free(self->pin); + // Claim pin + common_hal_mcu_pin_claim(self->pin); +} + +void common_hal_rp2clock_outputpin_enable(rp2clock_outputpin_obj_t *self) { + common_hal_rp2clock_outputpin_claim_pin(self); + clock_gpio_init(self->pin->number, self->src, self->divisor); + self->enabled = true; +} + +void common_hal_rp2clock_outputpin_disable(rp2clock_outputpin_obj_t *self) { + if (!self->enabled) { + return; + } + common_hal_reset_pin(self->pin); + self->enabled = 0; +} diff --git a/ports/raspberrypi/common-hal/rp2clock/OutputPin.h b/ports/raspberrypi/common-hal/rp2clock/OutputPin.h new file mode 100644 index 000000000000..d1e7bda6c195 --- /dev/null +++ b/ports/raspberrypi/common-hal/rp2clock/OutputPin.h @@ -0,0 +1,47 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Elliot Buller + * + * 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. + */ +#pragma once + +#include "common-hal/microcontroller/Pin.h" +#include "bindings/rp2clock/AuxSrc.h" +#include "hardware/clocks.h" + +typedef struct { + mp_obj_base_t base; + const mcu_pin_obj_t *pin; + rp2clock_auxsrc_t src; + mp_float_t divisor; + bool enabled; +} rp2clock_outputpin_obj_t; + +void common_hal_rp2clock_outputpin_validate_src_pin(const mcu_pin_obj_t *pin); +bool common_hal_rp2clock_outputpin_deinited(rp2clock_outputpin_obj_t *self); +void common_hal_rp2clock_outputpin_deinit(rp2clock_outputpin_obj_t *self); +mp_float_t common_hal_rp2clock_outputpin_validate_divisor(mp_float_t div); + +// Configure clock out +void common_hal_rp2clock_outputpin_enable(rp2clock_outputpin_obj_t *self); +void common_hal_rp2clock_outputpin_disable(rp2clock_outputpin_obj_t *self); diff --git a/ports/raspberrypi/common-hal/rp2clock/__init__.c b/ports/raspberrypi/common-hal/rp2clock/__init__.c new file mode 100644 index 000000000000..6af57cac3739 --- /dev/null +++ b/ports/raspberrypi/common-hal/rp2clock/__init__.c @@ -0,0 +1 @@ +// No rp2clock module functions diff --git a/py/circuitpy_mpconfig.mk b/py/circuitpy_mpconfig.mk index fc9fdcbd31af..e06fd18372c8 100644 --- a/py/circuitpy_mpconfig.mk +++ b/py/circuitpy_mpconfig.mk @@ -431,6 +431,12 @@ CFLAGS += -DCIRCUITPY_REQUIRE_I2C_PULLUPS=$(CIRCUITPY_REQUIRE_I2C_PULLUPS) CIRCUITPY_RP2PIO ?= 0 CFLAGS += -DCIRCUITPY_RP2PIO=$(CIRCUITPY_RP2PIO) +# CIRCUITPY_RP2CLOCK is handled in the raspberrypi tree. +# Only for rp2 chips. +# Assume not a rp2 build. +CIRCUITPY_RP2CLOCK ?= 0 +CFLAGS += -DCIRCUITPY_RP2CLOCK=$(CIRCUITPY_RP2CLOCK) + CIRCUITPY_RGBMATRIX ?= 0 CFLAGS += -DCIRCUITPY_RGBMATRIX=$(CIRCUITPY_RGBMATRIX)