samd/modmachine: Make some machine classes configurable by #defines.

These include ADC, DAC, I2C, SoftI2C, SPI, SoftI2C, PWM, UART, pulse.  This
is useful for devices like the Adafruit Trinket series which have almost no
accessible GPIO pins.

Signed-off-by: robert-hh <robert@hammelrath.com>
This commit is contained in:
robert-hh 2023-03-11 08:03:18 +01:00 committed by Damien George
parent b2df094bf8
commit 47fa723586
12 changed files with 131 additions and 32 deletions

View File

@ -25,9 +25,12 @@
* THE SOFTWARE.
*/
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_ADC
#include <stdint.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "sam.h"
@ -82,14 +85,7 @@ static uint8_t resolution[] = {
ADC_CTRLB_RESSEL_8BIT_Val, ADC_CTRLB_RESSEL_10BIT_Val, ADC_CTRLB_RESSEL_12BIT_Val
};
// Calculate the floor value of log2(n)
mp_int_t log2i(mp_int_t num) {
mp_int_t res = 0;
for (; num > 1; num >>= 1) {
res += 1;
}
return res;
}
extern mp_int_t log2i(mp_int_t num);
STATIC void adc_obj_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) {
(void)kind;
@ -274,3 +270,5 @@ static void adc_init(machine_adc_obj_t *self) {
// Set the port as given in self->id as ADC
mp_hal_set_pin_mux(self->id, ALT_FCT_ADC);
}
#endif

View File

@ -25,9 +25,12 @@
* THE SOFTWARE.
*/
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_DAC
#include <stdint.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mphal.h"
#include "sam.h"
@ -183,3 +186,5 @@ MP_DEFINE_CONST_OBJ_TYPE(
print, dac_print,
locals_dict, &dac_locals_dict
);
#endif

View File

@ -26,6 +26,9 @@
*/
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_I2C
#include "py/mphal.h"
#include "py/mperrno.h"
#include "extmod/machine_i2c.h"
@ -274,3 +277,5 @@ MP_DEFINE_CONST_OBJ_TYPE(
protocol, &machine_i2c_p,
locals_dict, &mp_machine_i2c_locals_dict
);
#endif

View File

@ -25,8 +25,11 @@
* THE SOFTWARE.
*/
#include <string.h>
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_PWM
#include <string.h>
#include "py/mphal.h"
#include "modmachine.h"
#include "clock_config.h"
@ -393,3 +396,5 @@ STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns
duty_type_flags[self->device] &= ~(1 << self->channel);
mp_machine_pwm_start(self);
}
#endif

View File

@ -24,7 +24,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_SPI
#include "py/mphal.h"
#include "extmod/machine_spi.h"
#include "modmachine.h"
@ -57,7 +61,6 @@ typedef struct _machine_spi_obj_t {
} machine_spi_obj_t;
extern Sercom *sercom_instance[];
MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]);
void common_spi_irq_handler(int spi_id) {
// handle Sercom IRQ RXC
@ -270,16 +273,6 @@ STATIC void machine_sercom_deinit(mp_obj_base_t *self_in) {
MP_STATE_PORT(sercom_table[self->id]) = NULL;
}
void sercom_deinit_all(void) {
for (int i = 0; i < SERCOM_INST_NUM; i++) {
Sercom *spi = sercom_instance[i];
spi->SPI.INTENCLR.reg = 0xff;
sercom_register_irq(i, NULL);
sercom_enable(spi, 0);
MP_STATE_PORT(sercom_table[i]) = NULL;
}
}
STATIC void machine_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
machine_spi_obj_t *self = (machine_spi_obj_t *)self_in;
@ -341,3 +334,5 @@ MP_DEFINE_CONST_OBJ_TYPE(
protocol, &machine_spi_p,
locals_dict, &mp_machine_spi_locals_dict
);
#endif

View File

@ -25,6 +25,9 @@
* THE SOFTWARE.
*/
#include "py/runtime.h"
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART
#include "py/mphal.h"
#include "py/stream.h"
#include "py/ringbuf.h"
@ -59,6 +62,28 @@ typedef struct _machine_uart_obj_t {
} machine_uart_obj_t;
Sercom *sercom_instance[] = SERCOM_INSTS;
MP_REGISTER_ROOT_POINTER(void *sercom_table[SERCOM_INST_NUM]);
// Common Sercom functions used by all Serial devices
void sercom_enable(Sercom *uart, int state) {
uart->USART.CTRLA.bit.ENABLE = state; // Set the state on/off
// Wait for the Registers to update.
while (uart->USART.SYNCBUSY.bit.ENABLE) {
}
}
void sercom_deinit_all(void) {
for (int i = 0; i < SERCOM_INST_NUM; i++) {
Sercom *uart = sercom_instance[i];
uart->USART.INTENCLR.reg = 0xff;
sercom_register_irq(i, NULL);
sercom_enable(uart, 0);
MP_STATE_PORT(sercom_table[i]) = NULL;
}
}
#endif
#if MICROPY_PY_MACHINE_UART
STATIC const char *_parity_name[] = {"None", "", "0", "1"}; // Is defined as 0, 2, 3
@ -105,13 +130,6 @@ void common_uart_irq_handler(int uart_id) {
}
}
void sercom_enable(Sercom *uart, int state) {
uart->USART.CTRLA.bit.ENABLE = state; // Set the state on/off
// Wait for the Registers to update.
while (uart->USART.SYNCBUSY.bit.ENABLE) {
}
}
STATIC void machine_uart_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "UART(%u, baudrate=%u, bits=%u, parity=%s, stop=%u, "
@ -544,3 +562,4 @@ MP_DEFINE_CONST_OBJ_TYPE(
protocol, &uart_stream_p,
locals_dict, &machine_uart_locals_dict
);
#endif

View File

@ -36,7 +36,14 @@ typedef struct _machine_wdt_obj_t {
mp_obj_base_t base;
} machine_wdt_obj_t;
extern mp_int_t log2i(mp_int_t num);
// Calculate the floor value of log2(n)
mp_int_t log2i(mp_int_t num) {
mp_int_t res = 0;
for (; num > 1; num >>= 1) {
res += 1;
}
return res;
}
STATIC const machine_wdt_obj_t machine_wdt = {{&machine_wdt_type}};

View File

@ -81,12 +81,18 @@ void samd_main(void) {
soft_reset_exit:
mp_printf(MP_PYTHON_PRINTER, "MPY: soft reboot\n");
#if MICROPY_PY_MACHINE_ADC
adc_deinit_all();
#endif
pin_irq_deinit_all();
#if MICROPY_PY_MACHINE_PWM
pwm_deinit_all();
#endif
soft_timer_deinit();
gc_sweep_all();
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART
sercom_deinit_all();
#endif
mp_deinit();
}
}

View File

@ -234,17 +234,33 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
{ MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
#if MICROPY_PY_MACHINE_ADC
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
#endif
#if MICROPY_PY_MACHINE_DAC
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
#if MICROPY_PY_MACHINE_PWM
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
#endif
#if MICROPY_PY_MACHINE_SOFTI2C
{ MP_ROM_QSTR(MP_QSTR_SoftI2C), MP_ROM_PTR(&mp_machine_soft_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_I2C
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
#endif
#if MICROPY_PY_MACHINE_SOFTSPI
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
#endif
#if MICROPY_PY_MACHINE_SPI
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
#if MICROPY_PY_MACHINE_UART
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },
#endif
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&machine_wdt_type) },
#if MICROPY_PY_MACHINE_RTC
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&machine_rtc_type) },
@ -254,7 +270,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&machine_disable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&machine_enable_irq_obj) },
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
#if MICROPY_PY_MACHINE_PULSE
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_lightsleep), MP_ROM_PTR(&machine_lightsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_lightsleep_obj) },

View File

@ -29,14 +29,26 @@
#include "py/obj.h"
#include "shared/timeutils/timeutils.h"
#if MICROPY_PY_MACHINE_ADC
extern const mp_obj_type_t machine_adc_type;
#endif
#if MICROPY_PY_MACHINE_DAC
extern const mp_obj_type_t machine_dac_type;
#endif
#if MICROPY_PY_MACHINE_I2C
extern const mp_obj_type_t machine_i2c_type;
#endif
extern const mp_obj_type_t machine_pin_type;
#if MICROPY_PY_MACHINE_PWM
extern const mp_obj_type_t machine_pwm_type;
#endif
#if MICROPY_PY_MACHINE_SPI
extern const mp_obj_type_t machine_spi_type;
#endif
extern const mp_obj_type_t machine_timer_type;
#if MICROPY_PY_MACHINE_UART
extern const mp_obj_type_t machine_uart_type;
#endif
extern const mp_obj_type_t machine_wdt_type;
#if MICROPY_PY_MACHINE_RTC
extern const mp_obj_type_t machine_rtc_type;

View File

@ -94,18 +94,39 @@
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_UASYNCIO (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_RTC (1)
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#ifndef MICROPY_PY_MACHINE_ADC
#define MICROPY_PY_MACHINE_ADC (1)
#endif
#ifndef MICROPY_PY_MACHINE_DAC
#define MICROPY_PY_MACHINE_DAC (1)
#endif
#ifndef MICROPY_PY_MACHINE_I2C
#define MICROPY_PY_MACHINE_I2C (1)
#endif
#ifndef MICROPY_PY_MACHINE_SPI
#define MICROPY_PY_MACHINE_SPI (1)
#endif
#ifndef MICROPY_PY_MACHINE_SOFTI2C
#define MICROPY_PY_MACHINE_SOFTI2C (1)
#endif
#ifndef MICROPY_PY_MACHINE_SOFTSPI
#define MICROPY_PY_MACHINE_SOFTSPI (1)
#endif
#ifndef MICROPY_PY_MACHINE_UART
#define MICROPY_PY_MACHINE_UART (1)
#endif
#define MICROPY_PY_MACHINE_TIMER (1)
#define MICROPY_SOFT_TIMER_TICKS_MS systick_ms
#define MICROPY_PY_OS_DUPTERM (3)
#define MICROPY_PY_MACHINE_BITSTREAM (1)
#ifndef MICROPY_PY_MACHINE_PULSE
#define MICROPY_PY_MACHINE_PULSE (1)
#endif
#ifndef MICROPY_PY_MACHINE_PWM
#define MICROPY_PY_MACHINE_PWM (1)
#define MICROPY_PY_MACHINE_PWM_INCLUDEFILE "ports/samd/machine_pwm.c"
#endif
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MP_STATE_PORT MP_STATE_VM

View File

@ -121,6 +121,7 @@ const char *pin_name(int id) {
return "-";
}
#if MICROPY_PY_MACHINE_I2C || MICROPY_PY_MACHINE_SPI || MICROPY_PY_MACHINE_UART
// Test, whether the given pin is defined and has signals for sercom.
// If that applies return the alt_fct and pad_nr.
// If not, an error will be raised.
@ -135,7 +136,9 @@ sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) {
mp_raise_ValueError(MP_ERROR_TEXT("wrong serial device"));
}
}
#endif
#if MICROPY_PY_MACHINE_ADC
// Test, whether the given pin is defined as ADC.
// If that applies return the adc instance and channel.
// If not, an error will be raised.
@ -152,6 +155,9 @@ adc_config_t get_adc_config(int pin_id, int32_t flag) {
mp_raise_ValueError(MP_ERROR_TEXT("ADC pin used"));
}
}
#endif
#if MICROPY_PY_MACHINE_PWM
// Test, whether the given pin is defined and has signals for pwm.
// If that applies return the alt_fct, tcc number and channel number.
@ -188,3 +194,5 @@ pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t device_status[])
}
mp_raise_ValueError(MP_ERROR_TEXT("not a PWM Pin"));
}
#endif