Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d89751f
psoc-edge/adc: Implementation basic.
AkshayChandra-IFX Jul 6, 2026
f80ef58
psoc-edge/machine_adc: Add CSV ADC mapping and init cleanup.
AkshayChandra-IFX Jul 7, 2026
b6842ba
psoc-edge/machine_adc: Add comment on BSP structure requirement.
AkshayChandra-IFX Jul 8, 2026
bc843ad
psoc-edge/machine_adc: Clarify AutAnalog BSP comment.
AkshayChandra-IFX Jul 9, 2026
5523a28
psoc-edge: Suppress ADCBlock int-conversion warning.
AkshayChandra-IFX Jul 9, 2026
3389338
extmod/machine_adc_block: Implemented no esp32 specific pin init value.
jaenrig-ifx Jul 9, 2026
cb8e09d
psoc-edge/Makefile: Removed warning suppression.
jaenrig-ifx Jul 9, 2026
2ccb7c9
psoc-edge/mphalport: Added pin obj null macro.
jaenrig-ifx Jul 9, 2026
abeba9c
psoc-edge: Fix ADC review updates and formatting.
AkshayChandra-IFX Jul 15, 2026
5549cf2
psoc-edge: Add ADCBlock and deinit.
AkshayChandra-IFX Jul 17, 2026
6150e2d
psoc-edge: Improve ADC deinit and naming.
AkshayChandra-IFX Jul 20, 2026
b4b140a
psoc-edge/machine_adc: Use generated ADC block/channel lookup tables.
AkshayChandra-IFX Jul 20, 2026
a0a82e2
psoc-edge: Tighten ADC channel state and read_u16 scaling.
AkshayChandra-IFX Jul 21, 2026
d347707
psoc-edge: ADC review fixes.
AkshayChandra-IFX Jul 24, 2026
1202206
psoc-edge/machine_adc: Apply ADC review fixes.
AkshayChandra-IFX Jul 27, 2026
39fbdd2
psoc-edge: Add ADC HW test and quickref updates.
AkshayChandra-IFX Jul 22, 2026
984cf07
psoc-edge: ADC quickref review fixes.
AkshayChandra-IFX Jul 27, 2026
846e22d
tests/psoc-edge: ADC Test review fixes.
AkshayChandra-IFX Jul 27, 2026
15f9a8a
psoc-edge/machine_adc: Use pin obj mp_hal type.
jaenrig-ifx Jul 28, 2026
3b2985b
psoc-edge/machine_adc: Object lifecycle does not require active track.
jaenrig-ifx Jul 28, 2026
e4fcdcc
psoc-edge/machine_acd: Simplify obj attribute names.
jaenrig-ifx Jul 28, 2026
8319cfe
psoc-edge/machine_adc: Restore active state tracking.
AkshayChandra-IFX Jul 29, 2026
5f21e11
docs/machine.ADC: Document deinit() method availability.
AkshayChandra-IFX Jul 29, 2026
ad24aca
tests/psoc-edge: Add ADC test to test plan and runner.
AkshayChandra-IFX Jul 29, 2026
c7df553
psoc-edge/machine_adc: Remove redundant validation checks.
AkshayChandra-IFX Jul 30, 2026
9153a10
tests/psoc-edge: Update ADC resistor value to 15k.
AkshayChandra-IFX Jul 30, 2026
4ecdf82
psoc-edge/adc: Restore PASS clock init and safe deinit reload.
AkshayChandra-IFX Jul 31, 2026
21fd732
psoc-edge/machine_adc: Enable PASS clock group before ADC init.
AkshayChandra-IFX Aug 3, 2026
7cd2e20
psoc-edge/machine_adc: Disable hardware on last channel deinit.
AkshayChandra-IFX Aug 3, 2026
9b5ada8
psoc-edge/machine_adc: Move SAR GPIO channel config ownership.
AkshayChandra-IFX Aug 4, 2026
86ce2ff
psoc-edge/adc: Fix ADC.block handling, update docs.
AkshayChandra-IFX Aug 4, 2026
5f5e210
psoc-edge/adc: Guard ADC deinit.
AkshayChandra-IFX Aug 4, 2026
cf5d6c5
psoc-edge/machine_adc: Move SAR runtime config into driver.
AkshayChandra-IFX Aug 4, 2026
91a60a2
psoc-edge/adc: Drop unused HAL config.
AkshayChandra-IFX Aug 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions docs/library/machine.ADC.rst
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,10 @@ Methods
Take an analog reading and return an integer value with units of
microvolts. It is up to the particular port whether or not this value
is calibrated, and how calibration is done.

.. method:: ADC.deinit()

Turn off the ADC.

.. note::
A new instance needs to be created after calling ``deinit()``.
34 changes: 34 additions & 0 deletions docs/psoc-edge/quickref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,40 @@ subscript notation::

value = mem32[addr] & 0xFFFFFFFF

ADC (analog to digital conversion)
----------------------------------

See :ref:`machine.ADC <machine.ADC>` and :ref:`machine.ADCBlock <machine.ADCBlock>`.

On the PSOC™ Edge, a single ADC block with id - ``0`` is available.

Use :class:`ADC` to read analog values from an ADC-capable pin::

from machine import ADC

adc = ADC('P15_1')
print(adc.read_u16()) # raw analog value in the range 0..65535
print(adc.read_uv()) # analog value in microvolts
adc.deinit()

This port also supports :class:`ADCBlock` to provide control over ADC configuration.

``ADCBlock.connect()`` accepts a channel, a pin, or both when they resolve to the same ADC source.

Use :class:`ADCBlock` to connect a channel to a pin::

from machine import ADCBlock

blk = ADCBlock(0, bits=12)
adc = blk.connect(1, 'P15_1')
print(adc.read_u16())
adc.deinit()

.. note::

``ADCBlock(0, bits=12)`` is supported on this port.
Other ``bits`` values are rejected.

Real time clock (RTC)
---------------------

Expand Down
2 changes: 1 addition & 1 deletion extmod/machine_adc_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ static MP_DEFINE_CONST_FUN_OBJ_KW(machine_adc_block_init_obj, 1, machine_adc_blo
static mp_obj_t machine_adc_block_connect(size_t n_pos_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
machine_adc_block_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_int_t channel_id = -1;
mp_hal_pin_obj_t pin = -1;
mp_hal_pin_obj_t pin = MP_HAL_PIN_OBJ_NULL;
if (n_pos_args == 2) {
if (mp_obj_is_int(pos_args[1])) {
channel_id = mp_obj_get_int(pos_args[1]);
Expand Down
1 change: 1 addition & 0 deletions ports/esp32/mphalport.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ void mp_hal_wake_main_task_from_isr(void);
#include "py/obj.h"
#include "driver/gpio.h"
#define MP_HAL_PIN_FMT "%u"
#define MP_HAL_PIN_OBJ_NULL ((mp_hal_pin_obj_t)-1)
#define mp_hal_pin_obj_t gpio_num_t
mp_hal_pin_obj_t machine_pin_get_id(mp_obj_t pin_in);
#define mp_hal_get_pin_obj(o) machine_pin_get_id(o)
Expand Down
11 changes: 10 additions & 1 deletion ports/psoc-edge/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ GEN_PINS_AF_HDR= $(HEADER_BUILD)/pins_af.h
# any of the objects. The normal dependency generation will deal with the
# case when pins.h is modified. But when it doesn't exist, we don't know
# which source files might need it.
$(OBJ): | $(GEN_PINS_HDR)
$(OBJ): | $(GEN_PINS_HDR) $(GEN_PINS_AF_HDR)

# With conditional pins, we may need to regenerate qstrdefs.h when config
# options change.
Expand Down Expand Up @@ -302,6 +302,7 @@ PSE_LIB_SRC_C += $(addprefix $(PSE_LIB_TOP_DIR)/, \
\
mtb-dsl-pse8xxgp/device-utils/syspm/source/mtb_syspm_callbacks_scb_uart.c \
\
mtb-dsl-pse8xxgp/hal/source/mtb_hal_adc_sar.c \
mtb-dsl-pse8xxgp/hal/source/mtb_hal_clock.c \
mtb-dsl-pse8xxgp/hal/source/mtb_hal_gpio.c \
mtb-dsl-pse8xxgp/hal/source/mtb_hal_lptimer.c \
Expand Down Expand Up @@ -333,6 +334,14 @@ PSE_LIB_SRC_C += $(addprefix $(PSE_LIB_TOP_DIR)/, \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_smif_memnum.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_smif_memslot.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_smif_sfdp.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_autanalog.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_autanalog_ac.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_autanalog_sar.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_autanalog_ctb.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_autanalog_dac.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_autanalog_ptc.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_systrimm.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_rram.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_sysclk_v2.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_sysint_v2.c \
mtb-dsl-pse8xxgp/pdl/drivers/source/cy_syslib.c \
Expand Down
137 changes: 0 additions & 137 deletions ports/psoc-edge/boards/KIT_PSE84_AI/bsp-cfg/cycfg_peripherals.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,143 +201,6 @@ cy_stc_autanalog_stt_ac_t CYBSP_AUTONOMOUS_CONTROLLER_stt[] =
.gpioOut = CY_AUTANALOG_STT_AC_GPIO_OUT_DISABLED,
},
};
cy_stc_autanalog_sar_hs_chan_t CYBSP_SAR_ADC_gpio_ch_cfg[] =
{
{
.posPin = CY_AUTANALOG_SAR_PIN_GPIO1,
.hsDiffEn = false,
.sign = false,
.posCoeff = CY_AUTANALOG_SAR_CH_COEFF_DISABLED,
.negPin = CY_AUTANALOG_SAR_PIN_GPIO0,
.accShift = false,
.negCoeff = CY_AUTANALOG_SAR_CH_COEFF_DISABLED,
.hsLimit = CY_AUTANALOG_SAR_LIMIT_STATUS_DISABLED,
.fifoSel = CY_AUTANALOG_FIFO_DISABLED,
},
};
cy_stc_autanalog_sar_sta_hs_t CYBSP_SAR_ADC_sta_hs_cfg =
{
.hsVref = CY_AUTANALOG_SAR_VREF_VDDA,
.hsSampleTime =
{
31U,
31U,
31U,
31U,
},
.hsGpioChan =
{
&CYBSP_SAR_ADC_gpio_ch_cfg[0U],
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
},
.hsGpioResultMask =
CY_AUTANALOG_SAR_CHAN_MASK_GPIO0,
};
cy_stc_autanalog_sar_sta_t CYBSP_SAR_ADC_sta_cfg =
{
.lpStaCfg = NULL,
.hsStaCfg = &CYBSP_SAR_ADC_sta_hs_cfg,
.posBufPwr = CY_AUTANALOG_SAR_BUF_PWR_OFF,
.negBufPwr = CY_AUTANALOG_SAR_BUF_PWR_OFF,
.accMode = CY_AUTANALOG_SAR_ACC_DISABLED,
.startupCal = CY_AUTANALOG_SAR_CAL_DISABLED,
.chanID = false,
.shiftMode = false,
.intMuxChan =
{
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
},
.limitCond =
{
NULL,
NULL,
NULL,
NULL,
},
.muxResultMask =
CY_AUTANALOG_SAR_CHAN_MASK_MUX_DISABLED,
.firResultMask =
CY_AUTANALOG_SAR_MASK_FIR_DISABLED,
};
cy_stc_autanalog_sar_seq_tab_hs_t CYBSP_SAR_ADC_seq_hs_cfg[] =
{
{
.chanEn = CY_AUTANALOG_SAR_CHAN_MASK_GPIO0,
.muxMode = CY_AUTANALOG_SAR_CHAN_CFG_MUX_DISABLED,
.mux0Sel = CY_AUTANALOG_SAR_CHAN_CFG_MUX0,
.mux1Sel = CY_AUTANALOG_SAR_CHAN_CFG_MUX0,
.sampleTimeEn = true,
.sampleTime = CY_AUTANALOG_SAR_SAMPLE_TIME0,
.accEn = false,
.accCount = CY_AUTANALOG_SAR_ACC_CNT2,
.calReq = CY_AUTANALOG_SAR_CAL_DISABLED,
.nextAction = CY_AUTANALOG_SAR_NEXT_ACTION_GO_TO_ENTRY_ADDR,
},
};
cy_stc_autanalog_sar_t CYBSP_SAR_ADC_cfg =
{
.sarStaCfg = &CYBSP_SAR_ADC_sta_cfg,
.hsSeqTabNum = sizeof(CYBSP_SAR_ADC_seq_hs_cfg) / sizeof(CYBSP_SAR_ADC_seq_hs_cfg[0U]),
.hsSeqTabArr = &CYBSP_SAR_ADC_seq_hs_cfg[0U],
.lpSeqTabNum = 0U,
.lpSeqTabArr = NULL,
.firNum = 0U,
.firCfg = NULL,
.fifoCfg = NULL,
};
cy_stc_autanalog_stt_sar_t CYBSP_SAR_ADC_stt[] =
{
{
.unlock = true,
.enable = true,
.trigger = false,
.entryState = 0U,
},
{
.unlock = true,
.enable = true,
.trigger = true,
.entryState = 0U,
},
{
.unlock = true,
.enable = true,
.trigger = false,
.entryState = 0U,
},
};

#if defined(COMPONENT_MTB_HAL) && (MTB_HAL_DRIVER_AVAILABLE_ADC)
mtb_hal_adc_configurator_t CYBSP_SAR_ADC_hal_config =
{
.config = &CYBSP_SAR_ADC_cfg,
.num_channels = sizeof(CYBSP_SAR_ADC_seq_hs_cfg) / sizeof(CYBSP_SAR_ADC_seq_hs_cfg[0U]),
.clock = NULL,
.adc_index = 0U,
};
#endif /* defined (COMPONENT_MTB_HAL) && (MTB_HAL_DRIVER_AVAILABLE_ADC) */

const cy_stc_i3c_config_t CYBSP_I3C_CONTROLLER_config =
{
.i3cMode = CY_I3C_CONTROLLER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,10 +181,6 @@ extern cy_stc_autanalog_sar_seq_tab_hs_t CYBSP_SAR_ADC_seq_hs_cfg[];
extern cy_stc_autanalog_sar_t CYBSP_SAR_ADC_cfg;
extern cy_stc_autanalog_stt_sar_t CYBSP_SAR_ADC_stt[];

#if defined(COMPONENT_MTB_HAL) && (MTB_HAL_DRIVER_AVAILABLE_ADC)
extern mtb_hal_adc_configurator_t CYBSP_SAR_ADC_hal_config;
#endif /* defined (COMPONENT_MTB_HAL) && (MTB_HAL_DRIVER_AVAILABLE_ADC) */

extern const cy_stc_i3c_config_t CYBSP_I3C_CONTROLLER_config;
extern const cy_stc_pdm_pcm_config_v2_t CYBSP_PDM_config;
extern const cy_stc_pdm_pcm_channel_config_t channel_2_config;
Expand Down
100 changes: 100 additions & 0 deletions ports/psoc-edge/boards/make-pins.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,23 @@ def __init__(self, cpu_pin_name):
self._afs = []
# Optional Counter source routing metadata parsed from PERI0_TR_IO_INPUTx AFs.
self._counter_src = None
# ADC mapping: (block_id, channel_id) or None
self._adc_map = None

def definition(self):
return f"PIN({self._port}, {self._pin}, pin_{self.name()}_af)"

@staticmethod
def parse_adc_label(label):
"""Parse ADC label like 'ADCBLOCK0_CH3' -> (0, 3) or None if invalid."""
label = label.strip()
if not label:
return None
match = re.match(r"^ADCBLOCK(\d+)_CH(\d+)$", label)
if match:
return (int(match.group(1)), int(match.group(2)))
return None

def add_af_scb(self, af_idx, af_name, af):
# The SCB alternate function follow the
# convention:
Expand Down Expand Up @@ -149,6 +162,11 @@ def add_af_peri_tr_io(self, af_idx, af_name, af):
self._afs.append(pin_af)

def add_af(self, af_idx, af_name, af):
# Handle ADC entries (usually from a special "ADC" column)
if af_name == "ADC":
self._adc_map = self.parse_adc_label(af)
return

# The AF index matches the column index for the ACTx functions 0-15
# while for DSx functions the columns 16-19 are mapped to DS2-DS5 respectively.
af_act_max_idx = 15
Expand Down Expand Up @@ -255,6 +273,71 @@ def __init__(self):
self._peri1_tr_io_input_max_index = 0
self._peri1_tr_io_output_max_index = 0

# ADC tracking: dict of (block, channel) -> pin object
self._adc_pin_map = {}

def add_adc(self):
"""Collect ADC mappings from all available pins."""
for pin in self.available_pins():
if pin._adc_map is None:
continue
block_id, channel_id = pin._adc_map
key = (block_id, channel_id)
pin_loc = (pin._port, pin._pin)

# Check for conflicts
if key in self._adc_pin_map:
old_pin = self._adc_pin_map[key]
old_loc = (old_pin._port, old_pin._pin)
if old_loc != pin_loc:
raise boardgen.PinGeneratorError(
f"ADC conflict: block {block_id} ch {channel_id} assigned to "
f"multiple pins ({old_loc} and {pin_loc})"
)

self._adc_pin_map[key] = pin

def _adc_dims(self):
if not self._adc_pin_map:
return (1, 1)

max_block = max(block_id for block_id, _ in self._adc_pin_map.keys())
max_channel = max(channel_id for _, channel_id in self._adc_pin_map.keys())
return (max_block + 1, max_channel + 1)

def print_adc_tables_source(self, out_source):
max_blocks, max_channels = self._adc_dims()

print(file=out_source)
print("// ADC block/channel lookup table generated from board pin map.", file=out_source)
print(
"const machine_pin_obj_t *const "
f"machine_adc_block_pins[{max_blocks}][{max_channels}] = {{",
file=out_source,
)

if self._adc_pin_map:
by_block = defaultdict(dict)
for (block_id, channel_id), pin in self._adc_pin_map.items():
by_block[block_id][channel_id] = pin

for block_id in sorted(by_block.keys()):
print(f" [{block_id}] = {{", file=out_source)
for channel_id in sorted(by_block[block_id].keys()):
pin = by_block[block_id][channel_id]
print(f" [{channel_id}] = &pin_{pin.name()}_obj,", file=out_source)
print(" },", file=out_source)
else:
print(" [0] = {", file=out_source)
print(" [0] = NULL,", file=out_source)
print(" },", file=out_source)

print("};", file=out_source)

def print_source(self, out_source):
super().print_source(out_source)
self.print_adc_tables_source(out_source)

# Collect all unhidden ports from the available
# pins.
# This function can be only used after parse_board_csv()
Expand Down Expand Up @@ -353,6 +436,7 @@ def parse_board_csv(self, filename):
self.add_scbs()
self.add_tcpwm()
self.add_peri_tr_ios()
self.add_adc()

# Override the default implementation just to change the default arguments
# (extra header row, skip first column).
Expand Down Expand Up @@ -553,11 +637,27 @@ def print_peri_tr_io_defines(self, out_header):

print(file=out_header)

def print_adc_defines(self, out_header):
"""Generate ADC lookup table declarations and dimensions."""
max_blocks, max_channels = self._adc_dims()

print("// ADC block/channel lookup dimensions and extern table.", file=out_header)
print("typedef struct _machine_pin_obj_t machine_pin_obj_t;", file=out_header)
print(f"#define MICROPY_HW_ADC_MAX_BLOCKS ({max_blocks})", file=out_header)
print(f"#define MICROPY_HW_ADC_MAX_CHANNELS ({max_channels})", file=out_header)
print(
"extern const machine_pin_obj_t *const "
"machine_adc_block_pins[MICROPY_HW_ADC_MAX_BLOCKS][MICROPY_HW_ADC_MAX_CHANNELS];",
file=out_header,
)
print(file=out_header)

def print_af_header(self, out_af_header):
self.print_scb_defines(out_af_header)
self.print_tcpwm_defines(out_af_header)
self.print_tcpwm_hw_map(out_af_header)
self.print_peri_tr_io_defines(out_af_header)
self.print_adc_defines(out_af_header)

# Add additional header file for AF defines and constants
def extra_args(self, parser):
Expand Down
Loading
Loading