Browse Source

samd/machine_pin: Change the pin handling and naming/numbering.

Pin numbers are now the MCU port numbers in the range:

    PA0..PA31:  0..31
    PB0..PB31: 32..63
    PC0..PC31: 64..95
    PD0..PD31: 96..127

Pins can be denoted by the GPIO port number, the name as defined in
pins.csv or a string in the form Pxnn, like "PA16" or "PD03".

The pins.c and pins.h files are now obsolete.  The pin objects are part of
the AF table.

As result of a simplification, the code now supports using pin names or
numbers instead of pin objects for modules like UART, SPI, PWM, I2C, ADC,
pininfo.
pull/9753/head
robert-hh 2 years ago
committed by Damien George
parent
commit
e5cf3fab95
  1. 26
      ports/samd/Makefile
  2. 54
      ports/samd/boards/make-pin-table.py
  3. 128
      ports/samd/boards/make-pins.py
  4. 4
      ports/samd/machine_adc.c
  5. 27
      ports/samd/machine_led.c
  6. 119
      ports/samd/machine_pin.c
  7. 4
      ports/samd/machine_pwm.c
  8. 10
      ports/samd/modsamd.c
  9. 69
      ports/samd/pin_af.c
  10. 18
      ports/samd/pin_af.h

26
ports/samd/Makefile

@ -47,14 +47,10 @@ INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include
INC += -I$(TOP)/lib/asf4/$(MCU_SERIES_LOWER)/include/pio
INC += -I$(TOP)/lib/tinyusb/src
MAKE_PIN_AF = boards/make-pin-af.py
MAKE_PIN_AF = boards/make-pin-table.py
PIN_AF_TABLE_CSV = mcu/$(MCU_SERIES_LOWER)/pin-af-table.csv
GEN_PIN_AF = pin_af_table.c
MAKE_PINS = boards/make-pins.py
BOARD_PINS = $(BOARD_DIR)/pins.csv
GEN_PINS_SRC = $(BUILD)/pins.c
GEN_PINS_HDR = $(BUILD)/pins.h
GEN_PIN_AF = pin_af_table.c
CFLAGS_MCU_SAMD21 = -mtune=cortex-m0plus -mcpu=cortex-m0plus -msoft-float
CFLAGS_MCU_SAMD51 = -mtune=cortex-m4 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
@ -150,7 +146,7 @@ DRIVERS_SRC_C += \
drivers/bus/softspi.c \
# List of sources for qstr extraction
SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(SRC_CXX) $(GEN_PINS_SRC)
SRC_QSTR += $(SRC_C) $(SHARED_SRC_C) $(SRC_CXX)
OBJ += $(PY_O)
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
@ -161,7 +157,6 @@ OBJ += $(addprefix $(BUILD)/, $(ASF4_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(LIBM_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o))
OBJ += $(GEN_PINS_SRC:.c=.o)
ifneq ($(FROZEN_MANIFEST),)
CFLAGS += -DMICROPY_MODULE_FROZEN_MPY
@ -182,19 +177,10 @@ $(BUILD)/firmware.bin: $(BUILD)/firmware.elf
$(BUILD)/firmware.uf2: $(BUILD)/firmware.bin
$(Q)$(PYTHON) $(UF2CONV) -b $(TEXT0) -c -o $@ $<
pin_af.c: $(BUILD)/$(GEN_PIN_AF)
pin_af.c: $(BUILD)/$(GEN_PIN_AF) | $(HEADER_BUILD)
$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) | $(HEADER_BUILD)
$(BUILD)/$(GEN_PIN_AF): $(PIN_AF_TABLE_CSV) $(BOARD_PINS) | $(HEADER_BUILD)
$(ECHO) "Create $@"
$(Q)$(PYTHON) $(MAKE_PIN_AF) --csv $(PIN_AF_TABLE_CSV) --table $(BUILD)/$(GEN_PIN_AF) --mcu $(MCU_SERIES)
machine_led.c machine_pin.c modsamd.c: $(GEN_PINS_HDR)
$(GEN_PINS_SRC) $(GEN_PINS_HDR): $(BOARD_PINS) | $(HEADER_BUILD)
$(ECHO) "Create $@"
$(Q)$(PYTHON) $(MAKE_PINS) --board $(BOARD_PINS) --pins $(GEN_PINS_SRC) --inc $(GEN_PINS_HDR)
$(GEN_PINS_SRC:.c=.o): $(GEN_PINS_SRC)
$(call compile_c)
$(Q)$(PYTHON) $(MAKE_PIN_AF) --csv $(PIN_AF_TABLE_CSV) --board $(BOARD_PINS) --table $(BUILD)/$(GEN_PIN_AF) --mcu $(MCU_SERIES)
include $(TOP)/py/mkrules.mk

54
ports/samd/boards/make-pin-af.py → ports/samd/boards/make-pin-table.py

@ -16,6 +16,7 @@ table_header = """// This file was automatically generated by make-pin-cap.py
class Pins:
def __init__(self):
self.board_pins = [] # list of pin objects
self.pin_names = {}
def parse_csv_file(self, filename):
with open(filename, "r") as csvfile:
@ -25,17 +26,43 @@ class Pins:
if len(row) > 0 and row[0].strip().upper()[:2] in ("PA", "PB", "PC", "PD"):
self.board_pins.append(row)
def parse_pin_file(self, filename):
with open(filename, "r") as csvfile:
rows = csv.reader(csvfile, skipinitialspace=True)
for row in rows:
# Pin numbers must start with "PIN_"
# LED numbers must start with "LED_"
if len(row) > 0:
# for compatibility, map LED_ to PIN_
if row[0].startswith("LED_"):
row[0] = "PIN_" + row[0][4:]
if len(row) == 1:
self.pin_names[row[0]] = (row[0][4:], "{&machine_led_type}")
else:
self.pin_names[row[0]] = (row[1], "{&machine_led_type}")
elif row[0].startswith("PIN_"):
if len(row) == 1:
self.pin_names[row[0]] = (row[0][4:], "{&machine_pin_type}")
else:
self.pin_names[row[0]] = (row[1], "{&machine_pin_type}")
def print_table(self, table_filename, mcu_name):
with open(table_filename, "wt") as table_file:
table_file.write(table_header)
table_file.write("const pin_af_t pin_af_table[] = {\n")
table_file.write("const machine_pin_obj_t pin_af_table[] = {\n")
if mcu_name == "SAMD21":
for row in self.board_pins:
pin = "PIN_" + row[0].upper()
table_file.write(" #ifdef " + pin + "\n")
eic = row[1] if row[1] else "0xff"
adc = row[2] if row[2] else "0xff"
table_file.write(" {%s, %s, %s" % (pin, eic, adc))
if pin in self.pin_names:
name = '"%s"' % self.pin_names[pin][0]
type = self.pin_names[pin][1]
else:
name = '"-"'
type = "{&machine_pin_type}"
table_file.write(" {%s, %s, %s, %s, %s" % (type, pin, name, eic, adc))
for cell in row[3:]:
if cell:
table_file.write(
@ -52,7 +79,15 @@ class Pins:
eic = row[1] if row[1] else "0xff"
adc0 = row[2] if row[2] else "0xff"
adc1 = row[3] if row[3] else "0xff"
table_file.write(" {%s, %s, %s, %s" % (pin, eic, adc0, adc1))
if pin in self.pin_names:
name = '"%s"' % self.pin_names[pin][0]
type = self.pin_names[pin][1]
else:
name = '"-"'
type = "{&machine_pin_type}"
table_file.write(
" {%s, %s, %s, %s, %s, %s" % (type, pin, name, eic, adc0, adc1)
)
for cell in row[4:]:
if cell:
table_file.write(
@ -67,7 +102,7 @@ class Pins:
def main():
parser = argparse.ArgumentParser(
prog="make-pin-cap.py",
prog="make-pin-af.py",
usage="%(prog)s [options] [command]",
description="Generate MCU-specific pin cap table file",
)
@ -75,7 +110,13 @@ def main():
"-c",
"--csv",
dest="csv_filename",
help="Specifies the pin-mux-xxxx.csv filename",
help="Specifies the pin-af-table.csv filename",
)
parser.add_argument(
"-b",
"--board",
dest="pin_filename",
help="Specifies the pins.csv filename",
)
parser.add_argument(
"-t",
@ -96,6 +137,9 @@ def main():
if args.csv_filename:
pins.parse_csv_file(args.csv_filename)
if args.pin_filename:
pins.parse_pin_file(args.pin_filename)
if args.table_filename:
pins.print_table(args.table_filename, args.mcu_name)

128
ports/samd/boards/make-pins.py

@ -1,128 +0,0 @@
#!/usr/bin/env python
"""Generates the pins file for the SAMD port."""
from __future__ import print_function
import argparse
import sys
import csv
pins_header_prefix = """// This file was automatically generated by make-pins.py
//
typedef struct _machine_pin_obj_t {
mp_obj_base_t base;
uint32_t id;
char *name;
} machine_pin_obj_t;
int pin_find(mp_obj_t pin, const machine_pin_obj_t machine_pin_obj[], int table_size);
"""
led_header_prefix = """typedef struct _machine_led_obj_t {
mp_obj_base_t base;
uint32_t id;
char *name;
} machine_led_obj_t;
"""
class Pins:
def __init__(self):
self.board_pins = [] # list of pin objects
self.board_leds = [] # list of led objects
def parse_csv_file(self, filename):
with open(filename, "r") as csvfile:
rows = csv.reader(csvfile, skipinitialspace=True)
for row in rows:
# Pin numbers must start with "PIN_"
# LED numbers must start with "LED_"
if len(row) > 0:
if row[0].startswith("PIN_"):
if len(row) == 1:
self.board_pins.append([row[0], row[0][4:]])
else:
self.board_pins.append([row[0], row[1]])
elif row[0].startswith("LED_"):
self.board_leds.append(["PIN_" + row[0][4:], row[1]])
elif row[0].startswith("-"):
self.board_pins.append(["-1", ""])
def print_pins(self, pins_filename):
with open(pins_filename, "wt") as pins_file:
pins_file.write("// This file was automatically generated by make-pins.py\n")
pins_file.write("//\n")
pins_file.write('#include "modmachine.h"\n')
pins_file.write('#include "sam.h"\n')
pins_file.write('#include "pins.h"\n\n')
pins_file.write("const machine_pin_obj_t machine_pin_obj[] = {\n")
for pin in self.board_pins:
pins_file.write(" {{&machine_pin_type}, ")
pins_file.write(pin[0] + ', "' + pin[1])
pins_file.write('"},\n')
pins_file.write("};\n")
if self.board_leds:
pins_file.write("\nconst machine_led_obj_t machine_led_obj[] = {\n")
for pin in self.board_leds:
pins_file.write(" {{&machine_led_type}, ")
pins_file.write(pin[0] + ', "' + pin[1])
pins_file.write('"},\n')
pins_file.write("};\n")
def print_header(self, hdr_filename):
with open(hdr_filename, "wt") as hdr_file:
hdr_file.write(pins_header_prefix)
if self.board_leds:
hdr_file.write(led_header_prefix)
hdr_file.write(
"extern const machine_pin_obj_t machine_pin_obj[%d];\n" % len(self.board_pins)
)
if self.board_leds:
hdr_file.write(
"extern const machine_led_obj_t machine_led_obj[%d];\n" % len(self.board_leds)
)
def main():
parser = argparse.ArgumentParser(
prog="make-pins.py",
usage="%(prog)s [options] [command]",
description="Generate board specific pin file",
)
parser.add_argument(
"-b",
"--board",
dest="csv_filename",
help="Specifies the pins.csv filename",
)
parser.add_argument(
"-p",
"--pins",
dest="pins_filename",
help="Specifies the name of the generated pins.c file",
)
parser.add_argument(
"-i",
"--inc",
dest="hdr_filename",
help="Specifies name of generated pin header file",
)
args = parser.parse_args(sys.argv[1:])
pins = Pins()
if args.csv_filename:
pins.parse_csv_file(args.csv_filename)
if args.pins_filename:
pins.print_pins(args.pins_filename)
pins.print_header(args.hdr_filename)
if __name__ == "__main__":
main()

4
ports/samd/machine_adc.c

@ -66,8 +66,8 @@ STATIC void adc_obj_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t k
(void)kind;
machine_adc_obj_t *self = MP_OBJ_TO_PTR(o);
mp_printf(print, "ADC(P%c%02u, ADC%u, channel=%u, bits=%u, average=%u)",
"ABCD"[self->id / 32], self->id % 32, self->adc_config.device,
mp_printf(print, "ADC(%s, ADC%u, channel=%u, bits=%u, average=%u)",
pin_name(self->id), self->adc_config.device,
self->adc_config.channel, self->bits, 1 << self->avg);
}

27
ports/samd/machine_led.c

@ -30,7 +30,7 @@
#include "py/mphal.h"
#include "extmod/virtpin.h"
#include "modmachine.h"
#include "pins.h"
#include "pin_af.h"
extern mp_obj_t machine_pin_low_obj;
extern mp_obj_t machine_pin_high_obj;
@ -38,8 +38,10 @@ extern mp_obj_t machine_pin_toggle_obj;
extern mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args);
STATIC void machine_led_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_led_obj_t *self = self_in;
mp_printf(print, "LED(\"%s\")", self->name);
machine_pin_obj_t *self = self_in;
mp_printf(print, "LED(\"%s\", GPIO=P%c%02u)",
pin_name(self->pin_id),
"ABCD"[self->pin_id / 32], self->pin_id % 32);
}
// constructor(id, ...)
@ -47,23 +49,16 @@ mp_obj_t mp_led_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw,
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted LED object
int wanted_led = pin_find(args[0], (const machine_pin_obj_t *)machine_led_obj, MP_ARRAY_SIZE(machine_led_obj));
const machine_led_obj_t *self = NULL;
if (0 <= wanted_led && wanted_led < MP_ARRAY_SIZE(machine_led_obj)) {
self = (machine_led_obj_t *)&machine_led_obj[wanted_led];
}
// the array could be padded with 'nulls' (see other Ports).
// Will also error if the asked for LED (index) is greater than the array row size.
if (self == NULL || self->base.type == NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid LED"));
}
mp_hal_pin_output(self->id);
mp_hal_pin_low(self->id);
const machine_pin_obj_t *self;
self = pin_find(args[0], &machine_led_type);
mp_hal_pin_output(self->pin_id);
mp_hal_pin_low(self->pin_id);
return MP_OBJ_FROM_PTR(self);
}
STATIC const mp_rom_map_elem_t machine_led_locals_dict_table[] = {
// instance methods
{ MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&machine_pin_low_obj) },

119
ports/samd/machine_pin.c

@ -34,7 +34,6 @@
#include "extmod/virtpin.h"
#include "modmachine.h"
#include "samd_soc.h"
#include "pins.h"
#include "pin_af.h"
#include "hal_gpio.h"
@ -68,17 +67,17 @@ STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_prin
machine_pin_obj_t *self = self_in;
char *mode_str;
char *pull_str[] = {"PULL_OFF", "PULL_UP", "PULL_DOWN"};
if (GPIO_IS_OPEN_DRAIN(self->id)) {
if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
mode_str = "OPEN_DRAIN";
} else {
mode_str = (mp_hal_get_pin_direction(self->id) == GPIO_DIRECTION_OUT) ? "OUT" : "IN";
mode_str = (mp_hal_get_pin_direction(self->pin_id) == GPIO_DIRECTION_OUT) ? "OUT" : "IN";
}
mp_printf(print, "Pin(\"%s\", mode=%s, pull=%s, GPIO=P%c%02u)",
self->name,
pin_name(self->pin_id),
mode_str,
pull_str[mp_hal_get_pull_mode(self->id)],
"ABCD"[self->id / 32], self->id % 32);
pull_str[mp_hal_get_pull_mode(self->pin_id)],
"ABCD"[self->pin_id / 32], self->pin_id % 32);
}
STATIC void pin_validate_drive(bool strength) {
@ -87,25 +86,6 @@ STATIC void pin_validate_drive(bool strength) {
}
}
int pin_find(mp_obj_t pin, const machine_pin_obj_t machine_pin_obj[], int table_size) {
int wanted_pin = -1;
if (mp_obj_is_small_int(pin)) {
// Pin defined by the index of pin table
wanted_pin = mp_obj_get_int(pin);
} else if (mp_obj_is_str(pin)) {
// Search by name
size_t slen;
const char *s = mp_obj_str_get_data(pin, &slen);
for (wanted_pin = 0; wanted_pin < table_size; wanted_pin++) {
if (slen == strlen(machine_pin_obj[wanted_pin].name) &&
strncmp(s, machine_pin_obj[wanted_pin].name, slen) == 0) {
break;
}
}
}
return wanted_pin;
}
// Pin.init(mode, pull=None, *, value=None, drive=0). No 'alt' yet.
STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_mode, ARG_pull, ARG_value, ARG_drive, ARG_alt };
@ -120,32 +100,34 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
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);
// clear any existing mux setting
mp_hal_clr_pin_mux(self->pin_id);
// set initial value (do this before configuring mode/pull)
if (args[ARG_value].u_obj != mp_const_none) {
mp_hal_pin_write(self->id, mp_obj_is_true(args[ARG_value].u_obj));
mp_hal_pin_write(self->pin_id, mp_obj_is_true(args[ARG_value].u_obj));
}
// configure mode
if (args[ARG_mode].u_obj != mp_const_none) {
mp_int_t mode = mp_obj_get_int(args[ARG_mode].u_obj);
if (mode == GPIO_MODE_IN) {
mp_hal_pin_input(self->id);
mp_hal_pin_input(self->pin_id);
} else if (mode == GPIO_MODE_OUT) {
mp_hal_pin_output(self->id);
mp_hal_pin_output(self->pin_id);
} else if (mode == GPIO_MODE_OPEN_DRAIN) {
mp_hal_pin_open_drain(self->id);
mp_hal_pin_open_drain(self->pin_id);
} else {
mp_hal_pin_input(self->id); // If no args are given, the Pin is 'input'.
mp_hal_pin_input(self->pin_id); // If no args are given, the Pin is 'input'.
}
}
// configure pull. Only to be used with IN mode. The function sets the pin to INPUT.
uint32_t pull = 0;
mp_int_t dir = mp_hal_get_pin_direction(self->id);
mp_int_t dir = mp_hal_get_pin_direction(self->pin_id);
if (dir == GPIO_DIRECTION_OUT && args[ARG_pull].u_obj != mp_const_none) {
mp_raise_ValueError(MP_ERROR_TEXT("OUT incompatible with pull"));
} else if (args[ARG_pull].u_obj != mp_const_none) {
pull = mp_obj_get_int(args[ARG_pull].u_obj);
gpio_set_pin_pull_mode(self->id, pull); // hal_gpio.h
gpio_set_pin_pull_mode(self->pin_id, pull); // hal_gpio.h
}
// get the strength
@ -158,18 +140,10 @@ STATIC mp_obj_t machine_pin_obj_init_helper(const machine_pin_obj_t *self, size_
// constructor(id, ...)
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
const machine_pin_obj_t *self;
// get the wanted pin object
int wanted_pin = pin_find(args[0], machine_pin_obj, MP_ARRAY_SIZE(machine_pin_obj));
const machine_pin_obj_t *self = NULL;
if (0 <= wanted_pin && wanted_pin < MP_ARRAY_SIZE(machine_pin_obj)) {
self = (machine_pin_obj_t *)&machine_pin_obj[wanted_pin];
}
if (self == NULL || self->base.type == NULL) {
mp_raise_ValueError(MP_ERROR_TEXT("invalid pin"));
}
self = pin_find(args[0], &machine_pin_type);
if (n_args > 1 || n_kw > 0) {
// pin mode given, so configure this GPIO
@ -187,18 +161,18 @@ mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp
machine_pin_obj_t *self = self_in;
if (n_args == 0) {
// get pin
return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self->id));
return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self->pin_id));
} else {
// set pin
bool value = mp_obj_is_true(args[0]);
if (GPIO_IS_OPEN_DRAIN(self->id)) {
if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
if (value == 0) {
mp_hal_pin_od_low(self->id);
mp_hal_pin_od_low(self->pin_id);
} else {
mp_hal_pin_od_high(self->id);
mp_hal_pin_od_high(self->pin_id);
}
} else {
mp_hal_pin_write(self->id, value);
mp_hal_pin_write(self->pin_id, value);
}
return mp_const_none;
}
@ -219,7 +193,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_
// Pin.disable(pin)
STATIC mp_obj_t machine_pin_disable(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
gpio_set_pin_direction(self->id, GPIO_DIRECTION_OFF); // Disables the pin (low power state)
gpio_set_pin_direction(self->pin_id, GPIO_DIRECTION_OFF); // Disables the pin (low power state)
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_disable_obj, machine_pin_disable);
@ -227,10 +201,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_disable_obj, machine_pin_disable);
// Pin.low() Totem-pole (push-pull)
STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (GPIO_IS_OPEN_DRAIN(self->id)) {
mp_hal_pin_od_low(self->id);
if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
mp_hal_pin_od_low(self->pin_id);
} else {
mp_hal_pin_low(self->id);
mp_hal_pin_low(self->pin_id);
}
return mp_const_none;
}
@ -239,10 +213,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low);
// Pin.high() Totem-pole (push-pull)
STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
if (GPIO_IS_OPEN_DRAIN(self->id)) {
mp_hal_pin_od_high(self->id);
if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
mp_hal_pin_od_high(self->pin_id);
} else {
mp_hal_pin_high(self->id);
mp_hal_pin_high(self->pin_id);
}
return mp_const_none;
}
@ -255,16 +229,16 @@ STATIC mp_obj_t machine_pin_toggle(mp_obj_t self_in) {
// Determine DIRECTION of PIN.
bool pin_dir;
if (GPIO_IS_OPEN_DRAIN(self->id)) {
pin_dir = mp_hal_get_pin_direction(self->id);
if (GPIO_IS_OPEN_DRAIN(self->pin_id)) {
pin_dir = mp_hal_get_pin_direction(self->pin_id);
if (pin_dir) {
// Pin is output, thus low, switch to high
mp_hal_pin_od_high(self->id);
mp_hal_pin_od_high(self->pin_id);
} else {
mp_hal_pin_od_low(self->id);
mp_hal_pin_od_low(self->pin_id);
}
} else {
gpio_toggle_pin_level(self->id);
gpio_toggle_pin_level(self->pin_id);
}
return mp_const_none;
}
@ -280,8 +254,8 @@ STATIC mp_obj_t machine_pin_drive(size_t n_args, const mp_obj_t *args) {
pin_validate_drive(strength);
// Set the DRVSTR bit (ASF hri/hri_port_dxx.h
hri_port_write_PINCFG_DRVSTR_bit(PORT,
(enum gpio_port)GPIO_PORT(self->id),
GPIO_PIN(self->id),
(enum gpio_port)GPIO_PORT(self->pin_id),
GPIO_PIN(self->pin_id),
strength);
return mp_const_none;
}
@ -301,9 +275,9 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// Get the IRQ object.
uint8_t eic_id = get_pin_af_info(self->id)->eic;
uint8_t eic_id = get_pin_obj_ptr(self->pin_id)->eic;
machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
if (irq != NULL && irq->pin_id != self->id) {
if (irq != NULL && irq->pin_id != self->pin_id) {
mp_raise_ValueError(MP_ERROR_TEXT("IRQ already used"));
}
@ -322,7 +296,7 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
if (n_args > 1 || kw_args->used != 0) {
// set the mux config of the pin.
mp_hal_set_pin_mux(self->id, ALT_FCT_EIC);
mp_hal_set_pin_mux(self->pin_id, ALT_FCT_EIC);
// Configure IRQ.
#if defined(MCU_SAMD21)
@ -362,7 +336,7 @@ STATIC mp_obj_t machine_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_
irq->base.ishard = args[ARG_hard].u_bool;
irq->flags = 0;
irq->trigger = args[ARG_trigger].u_int;
irq->pin_id = self->id;
irq->pin_id = self->pin_id;
// Enable IRQ if a handler is given.
if (args[ARG_handler].u_obj != mp_const_none) {
@ -457,10 +431,10 @@ STATIC mp_uint_t pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, i
switch (request) {
case MP_PIN_READ: {
return mp_hal_pin_read(self->id);
return mp_hal_pin_read(self->pin_id);
}
case MP_PIN_WRITE: {
mp_hal_pin_write(self->id, arg);
mp_hal_pin_write(self->pin_id, arg);
return 0;
}
}
@ -494,7 +468,7 @@ static uint8_t find_eic_id(int pin) {
STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint8_t eic_id = find_eic_id(self->id);
uint8_t eic_id = find_eic_id(self->pin_id);
if (eic_id != 0xff) {
machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
EIC->INTENCLR.reg |= (1 << eic_id);
@ -507,7 +481,7 @@ STATIC mp_uint_t machine_pin_irq_trigger(mp_obj_t self_in, mp_uint_t new_trigger
STATIC mp_uint_t machine_pin_irq_info(mp_obj_t self_in, mp_uint_t info_type) {
machine_pin_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint8_t eic_id = find_eic_id(self->id);
uint8_t eic_id = find_eic_id(self->pin_id);
if (eic_id != 0xff) {
machine_pin_irq_obj_t *irq = MP_STATE_PORT(machine_pin_irq_objects[eic_id]);
if (info_type == MP_IRQ_INFO_FLAGS) {
@ -525,11 +499,8 @@ STATIC const mp_irq_methods_t machine_pin_irq_methods = {
};
mp_hal_pin_obj_t mp_hal_get_pin_obj(mp_obj_t obj) {
if (!mp_obj_is_type(obj, &machine_pin_type)) {
mp_raise_ValueError(MP_ERROR_TEXT("expecting a Pin"));
}
machine_pin_obj_t *pin = MP_OBJ_TO_PTR(obj);
return pin->id;
const machine_pin_obj_t *pin = pin_find(obj, &machine_pin_type);
return pin->pin_id;
}
MP_REGISTER_ROOT_POINTER(void *machine_pin_irq_objects[16]);

4
ports/samd/machine_pwm.c

@ -107,8 +107,8 @@ STATIC void mp_machine_pwm_duty_set_ns(machine_pwm_obj_t *self, mp_int_t duty_ns
STATIC void mp_machine_pwm_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_pwm_obj_t *self = MP_OBJ_TO_PTR(self_in);
mp_printf(print, "PWM P%c%02u device=%u channel=%u output=%u",
"ABCD"[self->pin_id / 32], self->pin_id % 32, self->device, self->channel, self->output);
mp_printf(print, "PWM %s device=%u channel=%u output=%u",
pin_name(self->pin_id), self->device, self->channel, self->output);
}
// PWM(pin)

10
ports/samd/modsamd.c

@ -30,16 +30,15 @@
#include "sam.h"
#include "pin_af.h"
#include "pins.h"
#include "samd_soc.h"
extern const mp_obj_type_t samd_flash_type;
STATIC mp_obj_t samd_pininfo(mp_obj_t pin_obj) {
mp_hal_pin_obj_t pin = mp_hal_get_pin_obj(pin_obj);
const pin_af_t *pin_af = get_pin_af_info(pin);
const char *name = ((machine_pin_obj_t *)MP_OBJ_TO_PTR(pin_obj))->name;
if (pin_af) {
const machine_pin_obj_t *pin_af = pin_find(pin_obj, NULL);
// Get the name, now that it is not in the pin object
const char *name = pin_af->name;
#if defined(MCU_SAMD21)
mp_obj_t tuple[7] = {
tuple[0] = mp_obj_new_str(name, strlen(name)),
@ -65,7 +64,6 @@ STATIC mp_obj_t samd_pininfo(mp_obj_t pin_obj) {
};
return mp_obj_new_tuple(9, tuple);
#endif
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(samd_pininfo_obj, samd_pininfo);

69
ports/samd/pin_af.c

@ -29,7 +29,9 @@
*/
#include <stdint.h>
#include "string.h"
#include "modmachine.h"
#include "py/runtime.h"
#include "py/misc.h"
#include "pin_af.h"
@ -43,13 +45,65 @@ extern const uint8_t tcc_channel_count[];
// Just look for an table entry for a given pin and raise an error
// in case of no match (which should not happen).
const pin_af_t *get_pin_af_info(int pin_id) {
const machine_pin_obj_t *get_pin_obj_ptr(int pin_id) {
for (int i = 0; i < MP_ARRAY_SIZE(pin_af_table); i++) {
if (pin_af_table[i].pin_id == pin_id) { // Pin match
return &pin_af_table[i];
}
}
mp_raise_ValueError(MP_ERROR_TEXT("wrong pin"));
mp_raise_ValueError(MP_ERROR_TEXT("not a Pin"));
}
const machine_pin_obj_t *pin_find(mp_obj_t pin, const mp_obj_type_t *type) {
const machine_pin_obj_t *self = NULL;
// Is already a object of the proper type
if (mp_obj_is_type(pin, type)) {
return pin;
}
if (mp_obj_is_small_int(pin)) {
// Pin defined by pin number for PAnn, PBnn, etc.
self = get_pin_obj_ptr(mp_obj_get_int(pin));
} else if (mp_obj_is_str(pin)) {
// Search by name
size_t slen;
const char *s = mp_obj_str_get_data(pin, &slen);
// Check for a string like PA02 or PD12
if (slen == 4 && s[0] == 'P' && strchr("ABCD", s[1]) != NULL &&
strchr("0123456789", s[2]) != NULL && strchr("0123456789", s[2]) != NULL) {
int num = (s[1] - 'A') * 32 + (s[2] - '0') * 10 + (s[3] - '0');
self = get_pin_obj_ptr(num);
} else {
for (int i = 0; i < MP_ARRAY_SIZE(pin_af_table); i++) {
if (slen == strlen(pin_af_table[i].name) &&
strncmp(s, pin_af_table[i].name, slen) == 0) {
self = &pin_af_table[i];
}
}
}
}
if (self != NULL && (type == NULL || mp_obj_is_type(self, type))) {
return self;
} else {
mp_raise_ValueError(MP_ERROR_TEXT("not a Pin"));
}
}
const char *pin_name(int id) {
static char board_name[5] = "Pxnn";
for (int i = 0; i < sizeof(pin_af_table); i++) {
if (pin_af_table[i].pin_id == id) {
if (pin_af_table[i].name[0] != '-') {
return pin_af_table[i].name;
} else {
board_name[1] = "ABCD"[id / 32];
id %= 32;
board_name[2] = '0' + id / 10;
board_name[3] = '0' + id % 10;
return board_name;
}
}
}
return "-";
}
// Test, wether the given pin is defined and has signals for sercom.
@ -57,7 +111,7 @@ const pin_af_t *get_pin_af_info(int pin_id) {
// If not, an error will be raised.
sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) {
const pin_af_t *pct_ptr = get_pin_af_info(pin_id);
const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id);
if ((pct_ptr->sercom1 >> 4) == sercom_nr) {
return (sercom_pad_config_t) {ALT_FCT_SERCOM1, pct_ptr->sercom1 & 0x0f};
} else if ((pct_ptr->sercom2 >> 4) == sercom_nr) {
@ -72,7 +126,12 @@ sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom_nr) {
// If not, an error will be raised.
adc_config_t get_adc_config(int pin_id, int32_t flag) {
const pin_af_t *pct_ptr = get_pin_af_info(pin_id);
const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id);
#if defined(MCU_SAMD51)
if (pct_ptr->adc1 != 0xff && (flag & (1 << (pct_ptr->adc1 + 16))) == 0) {
return (adc_config_t) {1, pct_ptr->adc1};
} else
#endif
if (pct_ptr->adc0 != 0xff && (flag & (1 << pct_ptr->adc0)) == 0) {
return (adc_config_t) {0, pct_ptr->adc0};
#if defined(MUC_SAMD51)
@ -91,7 +150,7 @@ adc_config_t get_adc_config(int pin_id, int32_t flag) {
// tries to provide an unused device, if available.
pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t device_status[]) {
const pin_af_t *pct_ptr = get_pin_af_info(pin_id);
const machine_pin_obj_t *pct_ptr = get_pin_obj_ptr(pin_id);
uint8_t tcc1 = pct_ptr->tcc1;
uint8_t tcc2 = pct_ptr->tcc2;

18
ports/samd/pin_af.h

@ -30,15 +30,17 @@
#if defined(MCU_SAMD21)
typedef struct {
typedef struct _machine_pin_obj_t {
mp_obj_base_t base;
uint8_t pin_id;
char *name;
uint8_t eic;
uint8_t adc0;
uint8_t sercom1;
uint8_t sercom2;
uint8_t tcc1;
uint8_t tcc2;
} pin_af_t;
} machine_pin_obj_t;
#define ALT_FCT_TC 4
#define ALT_FCT_TCC1 4
@ -46,8 +48,10 @@ typedef struct {
#elif defined(MCU_SAMD51)
typedef struct {
typedef struct _machine_pin_obj_t {
mp_obj_base_t base;
uint8_t pin_id;
char *name;
uint8_t eic;
uint8_t adc0;
uint8_t adc1;
@ -56,7 +60,7 @@ typedef struct {
uint8_t tc;
uint8_t tcc1;
uint8_t tcc2;
} pin_af_t;
} machine_pin_obj_t;
#define ALT_FCT_TC 4
#define ALT_FCT_TCC1 5
@ -85,7 +89,11 @@ typedef struct _pwm_config_t {
#define ALT_FCT_SERCOM1 2
#define ALT_FCT_SERCOM2 3
extern const machine_pin_obj_t pin_af_table[];
sercom_pad_config_t get_sercom_config(int pin_id, uint8_t sercom);
adc_config_t get_adc_config(int pin_id, int32_t flag);
pwm_config_t get_pwm_config(int pin_id, int wanted_dev, uint8_t used_dev[]);
const pin_af_t *get_pin_af_info(int pin_id);
const machine_pin_obj_t *get_pin_obj_ptr(int pin_id);
const char *pin_name(int id);
const machine_pin_obj_t *pin_find(mp_obj_t pin, const mp_obj_type_t *type);

Loading…
Cancel
Save