Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ports psoc6 timer #72

Merged
merged 3 commits into from
Jul 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
6 changes: 6 additions & 0 deletions docs/psoc6/feature_list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ Enabled modules
* I2C
* RTC
* SoftI2C
* SPI
* SoftSPI
* PWM
* Timer
* micropython
* ucryptolib
* uctypes
Expand Down Expand Up @@ -117,6 +121,8 @@ Table :ref:`configuration details <table_mpy_configuration>` below lists specifi
+-----------------+----------------------------------------------------------------------------------------------------------------------+
| machine.SoftSPI | Option ``MICROPY_PY_MACHINE_SOFTSPI`` enabled. |
+-----------------+----------------------------------------------------------------------------------------------------------------------+
| machine.Timer | mode = Timer.PERIODIC is not supported |
+-----------------+----------------------------------------------------------------------------------------------------------------------+
| machine.SPI | Option ``MICROPY_PY_MACHINE_SPI``, ``MICROPY_PY_MACHINE_SPI_MSB`` , ``MICROPY_PY_MACHINE_SPI_MSB`` enabled. |
+-----------------+----------------------------------------------------------------------------------------------------------------------+
| psoc6 | Option to enable the external instead of the internal flash: ``MICROPY_ENABLE_EXT_QSPI_FLASH``. |
Expand Down
15 changes: 15 additions & 0 deletions docs/psoc6/quickref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -447,4 +447,19 @@ Methods
^^^^^^^
All the methods(functions) given in :ref:`machine.SPI <machine.SPI>` class have been implemented in this port

Timers
------

Hardware timer is supported.

Use the :mod:`machine.Timer` class::

from machine import Timer
import time
tim = Timer(0) #Default assignment: period=9999, frequency=10000
tim.init(period=2000, mode=Timer.ONE_SHOT, callback=lambda t:print(2))
time.sleep_ms(100)

Here id=0 should be passed mandatorily.

.. note:: Here mode=Timer.PERIODIC is not currently supported
1 change: 1 addition & 0 deletions ports/psoc6/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ MOD_SRC_C += $(addprefix modules/,\
machine/machine_rtc.c \
machine/machine_spi.c \
machine/pins.c \
machine/machine_timer.c \
\
psoc6/modpsoc6.c \
psoc6/psoc6_fatfs.c \
Expand Down
155 changes: 155 additions & 0 deletions ports/psoc6/modules/machine/machine_timer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// mpy includes
#include "py/runtime.h"
#include "py/mphal.h"


// MTB includes
#include "cybsp.h"
#include "cyhal.h"


#define TIMER_MODE_ONE_SHOT (0)
#define TIMER_MODE_PERIODIC (1)

typedef struct _machine_timer_obj_t {
mp_obj_base_t base;
cyhal_timer_t timer_obj;
uint32_t mode;
uint32_t period;
uint32_t freq;
mp_obj_t callback;
} machine_timer_obj_t;

const mp_obj_type_t machine_timer_type;

static void isr_timer(void *callback_arg, cyhal_timer_event_t event) {
machine_timer_obj_t *self = callback_arg;
mp_sched_schedule(self->callback, MP_OBJ_FROM_PTR(self));
}


STATIC void machine_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
qstr mode = self->mode == TIMER_MODE_ONE_SHOT ? MP_QSTR_ONE_SHOT : MP_QSTR_PERIODIC;
mp_printf(print, "Timer(mode=%q, period=%u, tick_hz=%u)", mode, self->period, self->freq);
}

STATIC mp_obj_t machine_timer_init_helper(machine_timer_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_mode, ARG_callback, ARG_period, ARG_freq, };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_mode, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = TIMER_MODE_ONE_SHOT} },
{ MP_QSTR_callback, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_rom_obj = MP_ROM_NONE} },
{ MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 9999u} },
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 10000u} },
};
// Parse args
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);

self->mode = args[ARG_mode].u_int;
self->freq = args[ARG_freq].u_int;
self->period = args[ARG_period].u_int;

if (args[ARG_callback].u_obj != mp_const_none) {
self->callback = args[ARG_callback].u_obj;
}

// Timer initialisation of port
cy_rslt_t rslt;

const cyhal_timer_cfg_t timer_cfg =
{
.compare_value = 0, /* Timer compare value, not used */
.period = self->period, /* Defines the timer period */
.direction = CYHAL_TIMER_DIR_UP, /* Timer counts up */
.is_compare = false, /* Don't use compare mode */
.is_continuous = self->mode, /* Run the timer */
.value = 0 /* Initial value of counter */
};

/* Initialize the timer object. Does not use pin output ('pin' is NC) and
* does not use a pre-configured clock source ('clk' is NULL). */

rslt = cyhal_timer_init(&self->timer_obj, NC, NULL);
CY_ASSERT(CY_RSLT_SUCCESS == rslt);

/* Apply timer configuration such as period, count direction, run mode, etc. */
rslt = cyhal_timer_configure(&self->timer_obj, &timer_cfg);

/* Set the frequency of timer to Defined frequency */
rslt = cyhal_timer_set_frequency(&self->timer_obj, self->freq);

/* Assign the ISR to execute on timer interrupt */
cyhal_timer_register_callback(&self->timer_obj, isr_timer, self);

/* Set the event on which timer interrupt occurs and enable it */
cyhal_timer_enable_event(&self->timer_obj, CYHAL_TIMER_IRQ_TERMINAL_COUNT, 3, true);

/* Start the timer with the configured settings */
rslt = cyhal_timer_start(&self->timer_obj);

CY_ASSERT(CY_RSLT_SUCCESS == rslt);

return mp_const_none;
}

STATIC mp_obj_t machine_timer_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);
machine_timer_obj_t *self = mp_obj_malloc(machine_timer_obj_t, &machine_timer_type);

self->base.type = &machine_timer_type;

mp_int_t id = 0;
if (n_args > 0) {
id = mp_obj_get_int(args[0]);
--n_args;
++args;
}
// Get timer id
if (id != 0) {
mp_raise_ValueError(MP_ERROR_TEXT("Specified Timer doesn't exist. Currently only id 0 is comfigured"));
}

if (n_args > 0 || n_kw > 0) {
// Start the timer
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
machine_timer_init_helper(self, n_args, args, &kw_args);
}

return MP_OBJ_FROM_PTR(self);
}

STATIC mp_obj_t machine_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
machine_timer_obj_t *self = MP_OBJ_TO_PTR(args[0]);
return machine_timer_init_helper(self, n_args - 1, args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_timer_init_obj, 1, machine_timer_init);

STATIC mp_obj_t machine_timer_deinit(mp_obj_t self_in) {
machine_timer_obj_t *self = MP_OBJ_TO_PTR(self_in);
cyhal_timer_free(&self->timer_obj);
return mp_const_none;
}

STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_timer_deinit_obj, machine_timer_deinit);

STATIC const mp_rom_map_elem_t machine_timer_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&machine_timer_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&machine_timer_init_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_timer_deinit_obj) },

{ MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_MODE_ONE_SHOT) },
{ MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_MODE_PERIODIC) },
};

STATIC MP_DEFINE_CONST_DICT(machine_timer_locals_dict, machine_timer_locals_dict_table);

MP_DEFINE_CONST_OBJ_TYPE(
machine_timer_type,
MP_QSTR_Timer,
MP_TYPE_FLAG_NONE,
make_new, machine_timer_make_new,
print, machine_timer_print,
locals_dict, &machine_timer_locals_dict
);
1 change: 1 addition & 0 deletions ports/psoc6/modules/machine/modmachine.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&mp_machine_soft_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&machine_timer_type) },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);

Expand Down
1 change: 1 addition & 0 deletions ports/psoc6/modules/machine/modmachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern const mp_obj_type_t machine_pin_type;
extern const mp_obj_type_t machine_rtc_type;
extern const mp_obj_type_t machine_pwm_type;
extern const mp_obj_type_t machine_spi_type;
extern const mp_obj_type_t machine_timer_type;

/* Note: the static functions' prototypes in the .c file cannot be declared here
since they are static. The static type in those functions come from MPY hence
Expand Down
6 changes: 6 additions & 0 deletions tests/psoc6/timer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import time
from machine import Timer

t = Timer(0)
t.init(period=2000, mode=Timer.ONE_SHOT, callback=lambda t: print("hello"))
time.sleep_ms(3000)
1 change: 1 addition & 0 deletions tests/psoc6/timer.py.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello
Loading