samd/machine_i2c: Support default instance and SCL/SDA pin values.
If a board configures a default I2C instance and/or SCL/SDA pins, then these no longer need to be given in the constructor. This allows the user to easily construct the default I2C instance via `machine.I2C()` and that will work on the default pins as designated on the board silkscreen. Signed-off-by: robert-hh <robert@hammelrath.com>
This commit is contained in:
@@ -34,6 +34,7 @@
|
|||||||
#include "extmod/modmachine.h"
|
#include "extmod/modmachine.h"
|
||||||
#include "samd_soc.h"
|
#include "samd_soc.h"
|
||||||
#include "pin_af.h"
|
#include "pin_af.h"
|
||||||
|
#include "genhdr/pins.h"
|
||||||
#include "clock_config.h"
|
#include "clock_config.h"
|
||||||
|
|
||||||
#define DEFAULT_I2C_FREQ (400000)
|
#define DEFAULT_I2C_FREQ (400000)
|
||||||
@@ -119,17 +120,26 @@ void common_i2c_irq_handler(int i2c_id) {
|
|||||||
|
|
||||||
static void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
static void machine_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||||
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
machine_i2c_obj_t *self = MP_OBJ_TO_PTR(self_in);
|
||||||
mp_printf(print, "I2C(%u, freq=%u, scl=%u, sda=%u)",
|
mp_printf(print, "I2C(%u, freq=%u, scl=\"%q\", sda=\"%q\")",
|
||||||
self->id, self->freq, self->scl, self->sda);
|
self->id, self->freq, pin_find_by_id(self->scl)->name, pin_find_by_id(self->sda)->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||||
enum { ARG_id, ARG_freq, ARG_scl, ARG_sda };
|
enum { ARG_id, ARG_freq, ARG_scl, ARG_sda };
|
||||||
static const mp_arg_t allowed_args[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_OBJ },
|
#if MICROPY_HW_DEFAULT_I2C_ID < 0
|
||||||
|
{ MP_QSTR_id, MP_ARG_REQUIRED | MP_ARG_INT, {.u_int = -1} },
|
||||||
|
#else
|
||||||
|
{ MP_QSTR_id, MP_ARG_INT, {.u_int = MICROPY_HW_DEFAULT_I2C_ID} },
|
||||||
|
#endif
|
||||||
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = DEFAULT_I2C_FREQ} },
|
{ MP_QSTR_freq, MP_ARG_INT, {.u_int = DEFAULT_I2C_FREQ} },
|
||||||
|
#if defined(pin_SCL) && defined(pin_SDA)
|
||||||
|
{ MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = pin_SCL} },
|
||||||
|
{ MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = pin_SDA} },
|
||||||
|
#else
|
||||||
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
{ MP_QSTR_scl, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
{ MP_QSTR_sda, MP_ARG_REQUIRED | MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// Parse args.
|
// Parse args.
|
||||||
@@ -137,7 +147,7 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
|
|||||||
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||||
|
|
||||||
// Get I2C bus.
|
// Get I2C bus.
|
||||||
int id = mp_obj_get_int(args[ARG_id].u_obj);
|
int id = args[ARG_id].u_int;
|
||||||
if (id < 0 || id >= SERCOM_INST_NUM) {
|
if (id < 0 || id >= SERCOM_INST_NUM) {
|
||||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C(%d) doesn't exist"), id);
|
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("I2C(%d) doesn't exist"), id);
|
||||||
}
|
}
|
||||||
@@ -148,15 +158,13 @@ mp_obj_t machine_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
|
|||||||
self->instance = sercom_instance[self->id];
|
self->instance = sercom_instance[self->id];
|
||||||
|
|
||||||
// Set SCL/SDA pins.
|
// Set SCL/SDA pins.
|
||||||
sercom_pad_config_t scl_pad_config;
|
|
||||||
self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj);
|
self->scl = mp_hal_get_pin_obj(args[ARG_scl].u_obj);
|
||||||
scl_pad_config = get_sercom_config(self->scl, self->id);
|
|
||||||
|
|
||||||
sercom_pad_config_t sda_pad_config;
|
|
||||||
self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj);
|
self->sda = mp_hal_get_pin_obj(args[ARG_sda].u_obj);
|
||||||
sda_pad_config = get_sercom_config(self->sda, self->id);
|
|
||||||
|
sercom_pad_config_t scl_pad_config = get_sercom_config(self->scl, self->id);
|
||||||
|
sercom_pad_config_t sda_pad_config = get_sercom_config(self->sda, self->id);
|
||||||
if (sda_pad_config.pad_nr != 0 || scl_pad_config.pad_nr != 1) {
|
if (sda_pad_config.pad_nr != 0 || scl_pad_config.pad_nr != 1) {
|
||||||
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin for sda or scl"));
|
mp_raise_ValueError(MP_ERROR_TEXT("invalid sda/scl pin"));
|
||||||
}
|
}
|
||||||
MP_STATE_PORT(sercom_table[self->id]) = self;
|
MP_STATE_PORT(sercom_table[self->id]) = self;
|
||||||
self->freq = args[ARG_freq].u_int;
|
self->freq = args[ARG_freq].u_int;
|
||||||
|
|||||||
Reference in New Issue
Block a user