aboutsummaryrefslogtreecommitdiff
path: root/cc3200/mods/pybtimer.c
diff options
context:
space:
mode:
authorDamien George2017-09-06 13:40:51 +1000
committerDamien George2017-09-06 13:40:51 +1000
commit01dd7804b87d60b2deab16712eccb3b97351a9b7 (patch)
tree1aa21f38a872b8e62a3d4e4f74f68033c6f827e4 /cc3200/mods/pybtimer.c
parenta9862b30068fc9df1022f08019fb35aaa5085f64 (diff)
ports: Make new ports/ sub-directory and move all ports there.
This is to keep the top-level directory clean, to make it clear what is core and what is a port, and to allow the repository to grow with new ports in a sustainable way.
Diffstat (limited to 'cc3200/mods/pybtimer.c')
-rw-r--r--cc3200/mods/pybtimer.c735
1 files changed, 0 insertions, 735 deletions
diff --git a/cc3200/mods/pybtimer.c b/cc3200/mods/pybtimer.c
deleted file mode 100644
index f3a12c5e7..000000000
--- a/cc3200/mods/pybtimer.c
+++ /dev/null
@@ -1,735 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013, 2014 Damien P. George
- * Copyright (c) 2015 Daniel Campora
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "py/mpconfig.h"
-#include "py/obj.h"
-#include "py/nlr.h"
-#include "py/runtime.h"
-#include "py/gc.h"
-#include "py/mperrno.h"
-#include "py/mphal.h"
-#include "inc/hw_types.h"
-#include "inc/hw_ints.h"
-#include "inc/hw_memmap.h"
-#include "inc/hw_timer.h"
-#include "rom_map.h"
-#include "interrupt.h"
-#include "prcm.h"
-#include "timer.h"
-#include "pin.h"
-#include "pybtimer.h"
-#include "pybpin.h"
-#include "pins.h"
-#include "mpirq.h"
-#include "pybsleep.h"
-#include "mpexception.h"
-
-
-/// \moduleref pyb
-/// \class Timer - generate periodic events, count events, and create PWM signals.
-///
-/// Each timer consists of a counter that counts up at a certain rate. The rate
-/// at which it counts is the peripheral clock frequency (in Hz) divided by the
-/// timer prescaler. When the counter reaches the timer period it triggers an
-/// event, and the counter resets back to zero. By using the irq method,
-/// the timer event can call a Python function.
-
-/******************************************************************************
- DECLARE PRIVATE CONSTANTS
- ******************************************************************************/
-#define PYBTIMER_NUM_TIMERS (4)
-#define PYBTIMER_POLARITY_POS (0x01)
-#define PYBTIMER_POLARITY_NEG (0x02)
-
-#define PYBTIMER_TIMEOUT_TRIGGER (0x01)
-#define PYBTIMER_MATCH_TRIGGER (0x02)
-
-#define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
-
-/******************************************************************************
- DEFINE PRIVATE TYPES
- ******************************************************************************/
-typedef struct _pyb_timer_obj_t {
- mp_obj_base_t base;
- uint32_t timer;
- uint32_t config;
- uint16_t irq_trigger;
- uint16_t irq_flags;
- uint8_t peripheral;
- uint8_t id;
-} pyb_timer_obj_t;
-
-typedef struct _pyb_timer_channel_obj_t {
- mp_obj_base_t base;
- struct _pyb_timer_obj_t *timer;
- uint32_t frequency;
- uint32_t period;
- uint16_t channel;
- uint16_t duty_cycle;
- uint8_t polarity;
-} pyb_timer_channel_obj_t;
-
-/******************************************************************************
- DEFINE PRIVATE DATA
- ******************************************************************************/
-STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods;
-STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_BASE, .peripheral = PRCM_TIMERA0},
- {.timer = TIMERA1_BASE, .peripheral = PRCM_TIMERA1},
- {.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
- {.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}};
-STATIC const mp_obj_type_t pyb_timer_channel_type;
-STATIC const mp_obj_t pyb_timer_pwm_pin[8] = {&pin_GP24, MP_OBJ_NULL, &pin_GP25, MP_OBJ_NULL, MP_OBJ_NULL, &pin_GP9, &pin_GP10, &pin_GP11};
-
-/******************************************************************************
- DECLARE PRIVATE FUNCTIONS
- ******************************************************************************/
-STATIC mp_obj_t pyb_timer_channel_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
-STATIC void timer_disable (pyb_timer_obj_t *tim);
-STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch);
-STATIC void TIMER0AIntHandler(void);
-STATIC void TIMER0BIntHandler(void);
-STATIC void TIMER1AIntHandler(void);
-STATIC void TIMER1BIntHandler(void);
-STATIC void TIMER2AIntHandler(void);
-STATIC void TIMER2BIntHandler(void);
-STATIC void TIMER3AIntHandler(void);
-STATIC void TIMER3BIntHandler(void);
-
-/******************************************************************************
- DEFINE PUBLIC FUNCTIONS
- ******************************************************************************/
-void timer_init0 (void) {
- mp_obj_list_init(&MP_STATE_PORT(pyb_timer_channel_obj_list), 0);
-}
-
-/******************************************************************************
- DEFINE PRIVATE FUNCTIONS
- ******************************************************************************/
-STATIC void pyb_timer_channel_irq_enable (mp_obj_t self_in) {
- pyb_timer_channel_obj_t *self = self_in;
- MAP_TimerIntClear(self->timer->timer, self->timer->irq_trigger & self->channel);
- MAP_TimerIntEnable(self->timer->timer, self->timer->irq_trigger & self->channel);
-}
-
-STATIC void pyb_timer_channel_irq_disable (mp_obj_t self_in) {
- pyb_timer_channel_obj_t *self = self_in;
- MAP_TimerIntDisable(self->timer->timer, self->timer->irq_trigger & self->channel);
-}
-
-STATIC int pyb_timer_channel_irq_flags (mp_obj_t self_in) {
- pyb_timer_channel_obj_t *self = self_in;
- return self->timer->irq_flags;
-}
-
-STATIC pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
- for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_timer_channel_obj_list).len; i++) {
- pyb_timer_channel_obj_t *ch = ((pyb_timer_channel_obj_t *)(MP_STATE_PORT(pyb_timer_channel_obj_list).items[i]));
- // any 32-bit timer must be matched by any of its 16-bit versions
- if (ch->timer->timer == timer && ((ch->channel & TIMER_A) == channel_n || (ch->channel & TIMER_B) == channel_n)) {
- return ch;
- }
- }
- return MP_OBJ_NULL;
-}
-
-STATIC void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
- pyb_timer_channel_obj_t *channel;
- if ((channel = pyb_timer_channel_find(ch->timer->timer, ch->channel))) {
- mp_obj_list_remove(&MP_STATE_PORT(pyb_timer_channel_obj_list), channel);
- // unregister it with the sleep module
- pyb_sleep_remove((const mp_obj_t)channel);
- }
-}
-
-STATIC void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
- // remove it in case it already exists
- pyb_timer_channel_remove(ch);
- mp_obj_list_append(&MP_STATE_PORT(pyb_timer_channel_obj_list), ch);
- // register it with the sleep module
- pyb_sleep_add((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
-}
-
-STATIC void timer_disable (pyb_timer_obj_t *tim) {
- // disable all timers and it's interrupts
- MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B);
- MAP_TimerIntDisable(tim->timer, tim->irq_trigger);
- MAP_TimerIntClear(tim->timer, tim->irq_trigger);
- pyb_timer_channel_obj_t *ch;
- // disable its channels
- if ((ch = pyb_timer_channel_find (tim->timer, TIMER_A))) {
- pyb_sleep_remove(ch);
- }
- if ((ch = pyb_timer_channel_find (tim->timer, TIMER_B))) {
- pyb_sleep_remove(ch);
- }
- MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
-}
-
-// computes prescaler period and match value so timer triggers at freq-Hz
-STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t *ch, uint32_t *period_out, uint32_t *match_out) {
- uint32_t maxcount = (ch->channel == (TIMER_A | TIMER_B)) ? 0xFFFFFFFF : 0xFFFF;
- uint32_t prescaler;
- uint32_t period_c = (ch->frequency > 0) ? PYBTIMER_SRC_FREQ_HZ / ch->frequency : ((PYBTIMER_SRC_FREQ_HZ / 1000000) * ch->period);
-
- period_c = MAX(1, period_c) - 1;
- if (period_c == 0) {
- goto error;
- }
-
- prescaler = period_c >> 16; // The prescaler is an extension of the timer counter
- *period_out = period_c;
-
- if (prescaler > 0xFF && maxcount == 0xFFFF) {
- goto error;
- }
- // check limit values for the duty cycle
- if (ch->duty_cycle == 0) {
- *match_out = period_c - 1;
- } else {
- if (period_c > 0xFFFF) {
- uint32_t match = (period_c * 100) / 10000;
- *match_out = period_c - ((match * ch->duty_cycle) / 100);
- } else {
- *match_out = period_c - ((period_c * ch->duty_cycle) / 10000);
- }
- }
- return prescaler;
-
-error:
- mp_raise_ValueError(mpexception_value_invalid_arguments);
-}
-
-STATIC void timer_init (pyb_timer_obj_t *tim) {
- MAP_PRCMPeripheralClkEnable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
- MAP_PRCMPeripheralReset(tim->peripheral);
- MAP_TimerConfigure(tim->timer, tim->config);
-}
-
-STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch) {
- // calculate the period, the prescaler and the match value
- uint32_t period_c;
- uint32_t match;
- uint32_t prescaler = compute_prescaler_period_and_match_value(ch, &period_c, &match);
-
- // set the prescaler
- MAP_TimerPrescaleSet(ch->timer->timer, ch->channel, (prescaler < 0xFF) ? prescaler : 0);
-
- // set the load value
- MAP_TimerLoadSet(ch->timer->timer, ch->channel, period_c);
-
- // configure the pwm if we are in such mode
- if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) {
- // invert the timer output if required
- MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
- // set the match value (which is simply the duty cycle translated to ticks)
- MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
- MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
- }
-
-#ifdef DEBUG
- // stall the timer when the processor is halted while debugging
- MAP_TimerControlStall(ch->timer->timer, ch->channel, true);
-#endif
-
- // now enable the timer channel
- MAP_TimerEnable(ch->timer->timer, ch->channel);
-}
-
-/******************************************************************************/
-/* MicroPython bindings */
-
-STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- pyb_timer_obj_t *tim = self_in;
- uint32_t mode = tim->config & 0xFF;
-
- // timer mode
- qstr mode_qst = MP_QSTR_PWM;
- switch(mode) {
- case TIMER_CFG_A_ONE_SHOT_UP:
- mode_qst = MP_QSTR_ONE_SHOT;
- break;
- case TIMER_CFG_A_PERIODIC_UP:
- mode_qst = MP_QSTR_PERIODIC;
- break;
- default:
- break;
- }
- mp_printf(print, "Timer(%u, mode=Timer.%q)", tim->id, mode_qst);
-}
-
-STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
- { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} },
- };
-
- // 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);
-
- // check the mode
- uint32_t _mode = args[0].u_int;
- if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_PWM) {
- goto error;
- }
-
- // check the width
- if (args[1].u_int != 16 && args[1].u_int != 32) {
- goto error;
- }
- bool is16bit = (args[1].u_int == 16);
-
- if (!is16bit && _mode == TIMER_CFG_A_PWM) {
- // 32-bit mode is only available when in free running modes
- goto error;
- }
- tim->config = is16bit ? ((_mode | (_mode << 8)) | TIMER_CFG_SPLIT_PAIR) : _mode;
-
- timer_init(tim);
- // register it with the sleep module
- pyb_sleep_add ((const mp_obj_t)tim, (WakeUpCB_t)timer_init);
-
- return mp_const_none;
-
-error:
- mp_raise_ValueError(mpexception_value_invalid_arguments);
-}
-
-STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- // check arguments
- mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
-
- // create a new Timer object
- int32_t timer_idx = mp_obj_get_int(args[0]);
- if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
- mp_raise_OSError(MP_ENODEV);
- }
-
- pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx];
- tim->base.type = &pyb_timer_type;
- tim->id = timer_idx;
-
- if (n_args > 1 || n_kw > 0) {
- // start the peripheral
- mp_map_t kw_args;
- mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
- pyb_timer_init_helper(tim, n_args - 1, args + 1, &kw_args);
- }
- return (mp_obj_t)tim;
-}
-
-STATIC mp_obj_t pyb_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
- return pyb_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init);
-
-STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
- pyb_timer_obj_t *self = self_in;
- timer_disable(self);
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
-
-STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBTIMER_POLARITY_POS} },
- { MP_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
- };
-
- pyb_timer_obj_t *tim = pos_args[0];
- mp_int_t channel_n = mp_obj_get_int(pos_args[1]);
-
- // verify that the timer has been already initialized
- if (!tim->config) {
- mp_raise_OSError(MP_EPERM);
- }
- if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) {
- // invalid channel
- goto error;
- }
- if (channel_n == (TIMER_A | TIMER_B) && (tim->config & TIMER_CFG_SPLIT_PAIR)) {
- // 32-bit channel selected when the timer is in 16-bit mode
- goto error;
- }
-
- // if only the channel number is given return the previously
- // allocated channel (or None if no previous channel)
- if (n_args == 2 && kw_args->used == 0) {
- pyb_timer_channel_obj_t *ch;
- if ((ch = pyb_timer_channel_find(tim->timer, channel_n))) {
- return ch;
- }
- return mp_const_none;
- }
-
- // parse the arguments
- mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
- mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
-
- // throw an exception if both frequency and period are given
- if (args[0].u_int != 0 && args[1].u_int != 0) {
- goto error;
- }
- // check that at least one of them has a valid value
- if (args[0].u_int <= 0 && args[1].u_int <= 0) {
- goto error;
- }
- // check that the polarity is not 'both' in pwm mode
- if ((tim->config & TIMER_A) == TIMER_CFG_A_PWM && args[2].u_int == (PYBTIMER_POLARITY_POS | PYBTIMER_POLARITY_NEG)) {
- goto error;
- }
-
- // allocate a new timer channel
- pyb_timer_channel_obj_t *ch = m_new_obj(pyb_timer_channel_obj_t);
- ch->base.type = &pyb_timer_channel_type;
- ch->timer = tim;
- ch->channel = channel_n;
-
- // get the frequency the polarity and the duty cycle
- ch->frequency = args[0].u_int;
- ch->period = args[1].u_int;
- ch->polarity = args[2].u_int;
- ch->duty_cycle = MIN(10000, MAX(0, args[3].u_int));
-
- timer_channel_init(ch);
-
- // assign the pin
- if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) {
- uint32_t ch_idx = (ch->channel == TIMER_A) ? 0 : 1;
- // use the default pin if available
- mp_obj_t pin_o = (mp_obj_t)pyb_timer_pwm_pin[(ch->timer->id * 2) + ch_idx];
- if (pin_o != MP_OBJ_NULL) {
- pin_obj_t *pin = pin_find(pin_o);
- pin_config (pin, pin_find_af_index(pin, PIN_FN_TIM, ch->timer->id, PIN_TYPE_TIM_PWM),
- 0, PIN_TYPE_STD, -1, PIN_STRENGTH_4MA);
- }
- }
-
- // add the timer to the list
- pyb_timer_channel_add(ch);
-
- return ch;
-
-error:
- mp_raise_ValueError(mpexception_value_invalid_arguments);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel);
-
-STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
- // instance methods
- { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_timer_init_obj) },
- { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_timer_deinit_obj) },
- { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&pyb_timer_channel_obj) },
-
- // class constants
- { MP_ROM_QSTR(MP_QSTR_A), MP_ROM_INT(TIMER_A) },
- { MP_ROM_QSTR(MP_QSTR_B), MP_ROM_INT(TIMER_B) },
- { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_CFG_A_ONE_SHOT_UP) },
- { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_CFG_A_PERIODIC_UP) },
- { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_INT(TIMER_CFG_A_PWM) },
- { MP_ROM_QSTR(MP_QSTR_POSITIVE), MP_ROM_INT(PYBTIMER_POLARITY_POS) },
- { MP_ROM_QSTR(MP_QSTR_NEGATIVE), MP_ROM_INT(PYBTIMER_POLARITY_NEG) },
- { MP_ROM_QSTR(MP_QSTR_TIMEOUT), MP_ROM_INT(PYBTIMER_TIMEOUT_TRIGGER) },
- { MP_ROM_QSTR(MP_QSTR_MATCH), MP_ROM_INT(PYBTIMER_MATCH_TRIGGER) },
-};
-STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
-
-const mp_obj_type_t pyb_timer_type = {
- { &mp_type_type },
- .name = MP_QSTR_Timer,
- .print = pyb_timer_print,
- .make_new = pyb_timer_make_new,
- .locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
-};
-
-STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
- .init = pyb_timer_channel_irq,
- .enable = pyb_timer_channel_irq_enable,
- .disable = pyb_timer_channel_irq_disable,
- .flags = pyb_timer_channel_irq_flags,
-};
-
-STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
- pyb_timer_channel_obj_t *self;
- uint32_t status;
- if ((self = pyb_timer_channel_find(timer, channel))) {
- status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel;
- MAP_TimerIntClear(self->timer->timer, status);
- mp_irq_handler(mp_irq_find(self));
- }
-}
-
-STATIC void TIMER0AIntHandler(void) {
- TIMERGenericIntHandler(TIMERA0_BASE, TIMER_A);
-}
-
-STATIC void TIMER0BIntHandler(void) {
- TIMERGenericIntHandler(TIMERA0_BASE, TIMER_B);
-}
-
-STATIC void TIMER1AIntHandler(void) {
- TIMERGenericIntHandler(TIMERA1_BASE, TIMER_A);
-}
-
-STATIC void TIMER1BIntHandler(void) {
- TIMERGenericIntHandler(TIMERA1_BASE, TIMER_B);
-}
-
-STATIC void TIMER2AIntHandler(void) {
- TIMERGenericIntHandler(TIMERA2_BASE, TIMER_A);
-}
-
-STATIC void TIMER2BIntHandler(void) {
- TIMERGenericIntHandler(TIMERA2_BASE, TIMER_B);
-}
-
-STATIC void TIMER3AIntHandler(void) {
- TIMERGenericIntHandler(TIMERA3_BASE, TIMER_A);
-}
-
-STATIC void TIMER3BIntHandler(void) {
- TIMERGenericIntHandler(TIMERA3_BASE, TIMER_B);
-}
-
-STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
- pyb_timer_channel_obj_t *ch = self_in;
- char *ch_id = "AB";
- // timer channel
- if (ch->channel == TIMER_A) {
- ch_id = "A";
- } else if (ch->channel == TIMER_B) {
- ch_id = "B";
- }
-
- mp_printf(print, "timer.channel(Timer.%s, %q=%u", ch_id, MP_QSTR_freq, ch->frequency);
-
- uint32_t mode = ch->timer->config & 0xFF;
- if (mode == TIMER_CFG_A_PWM) {
- mp_printf(print, ", %q=Timer.", MP_QSTR_polarity);
- switch (ch->polarity) {
- case PYBTIMER_POLARITY_POS:
- mp_printf(print, "POSITIVE");
- break;
- case PYBTIMER_POLARITY_NEG:
- mp_printf(print, "NEGATIVE");
- break;
- default:
- mp_printf(print, "BOTH");
- break;
- }
- mp_printf(print, ", %q=%u.%02u", MP_QSTR_duty_cycle, ch->duty_cycle / 100, ch->duty_cycle % 100);
- }
- mp_printf(print, ")");
-}
-
-STATIC mp_obj_t pyb_timer_channel_freq(size_t n_args, const mp_obj_t *args) {
- pyb_timer_channel_obj_t *ch = args[0];
- if (n_args == 1) {
- // get
- return mp_obj_new_int(ch->frequency);
- } else {
- // set
- int32_t _frequency = mp_obj_get_int(args[1]);
- if (_frequency <= 0) {
- mp_raise_ValueError(mpexception_value_invalid_arguments);
- }
- ch->frequency = _frequency;
- ch->period = 1000000 / _frequency;
- timer_channel_init(ch);
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_freq_obj, 1, 2, pyb_timer_channel_freq);
-
-STATIC mp_obj_t pyb_timer_channel_period(size_t n_args, const mp_obj_t *args) {
- pyb_timer_channel_obj_t *ch = args[0];
- if (n_args == 1) {
- // get
- return mp_obj_new_int(ch->period);
- } else {
- // set
- int32_t _period = mp_obj_get_int(args[1]);
- if (_period <= 0) {
- mp_raise_ValueError(mpexception_value_invalid_arguments);
- }
- ch->period = _period;
- ch->frequency = 1000000 / _period;
- timer_channel_init(ch);
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_period_obj, 1, 2, pyb_timer_channel_period);
-
-STATIC mp_obj_t pyb_timer_channel_duty_cycle(size_t n_args, const mp_obj_t *args) {
- pyb_timer_channel_obj_t *ch = args[0];
- if (n_args == 1) {
- // get
- return mp_obj_new_int(ch->duty_cycle);
- } else {
- // duty cycle must be converted from percentage to ticks
- // calculate the period, the prescaler and the match value
- uint32_t period_c;
- uint32_t match;
- ch->duty_cycle = MIN(10000, MAX(0, mp_obj_get_int(args[1])));
- compute_prescaler_period_and_match_value(ch, &period_c, &match);
- if (n_args == 3) {
- // set the new polarity if requested
- ch->polarity = mp_obj_get_int(args[2]);
- MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
- }
- MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
- MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
- return mp_const_none;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle);
-
-STATIC mp_obj_t pyb_timer_channel_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
- pyb_timer_channel_obj_t *ch = pos_args[0];
-
- // convert the priority to the correct value
- uint priority = mp_irq_translate_priority (args[1].u_int);
-
- // validate the power mode
- uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
- if (pwrmode != PYB_PWR_MODE_ACTIVE) {
- goto invalid_args;
- }
-
- // get the trigger
- uint trigger = mp_obj_get_int(args[0].u_obj);
-
- // disable the callback first
- pyb_timer_channel_irq_disable(ch);
-
- uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
- uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
- switch (_config) {
- case TIMER_CFG_A_ONE_SHOT_UP:
- case TIMER_CFG_A_PERIODIC_UP:
- ch->timer->irq_trigger |= TIMER_TIMA_TIMEOUT << shift;
- if (trigger != PYBTIMER_TIMEOUT_TRIGGER) {
- goto invalid_args;
- }
- break;
- case TIMER_CFG_A_PWM:
- // special case for the PWM match interrupt
- ch->timer->irq_trigger |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
- if (trigger != PYBTIMER_MATCH_TRIGGER) {
- goto invalid_args;
- }
- break;
- default:
- break;
- }
- // special case for a 32-bit timer
- if (ch->channel == (TIMER_A | TIMER_B)) {
- ch->timer->irq_trigger |= (ch->timer->irq_trigger << 8);
- }
-
- void (*pfnHandler)(void);
- uint32_t intregister;
- switch (ch->timer->timer) {
- case TIMERA0_BASE:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER0BIntHandler;
- intregister = INT_TIMERA0B;
- } else {
- pfnHandler = &TIMER0AIntHandler;
- intregister = INT_TIMERA0A;
- }
- break;
- case TIMERA1_BASE:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER1BIntHandler;
- intregister = INT_TIMERA1B;
- } else {
- pfnHandler = &TIMER1AIntHandler;
- intregister = INT_TIMERA1A;
- }
- break;
- case TIMERA2_BASE:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER2BIntHandler;
- intregister = INT_TIMERA2B;
- } else {
- pfnHandler = &TIMER2AIntHandler;
- intregister = INT_TIMERA2A;
- }
- break;
- default:
- if (ch->channel == TIMER_B) {
- pfnHandler = &TIMER3BIntHandler;
- intregister = INT_TIMERA3B;
- } else {
- pfnHandler = &TIMER3AIntHandler;
- intregister = INT_TIMERA3A;
- }
- break;
- }
-
- // register the interrupt and configure the priority
- MAP_IntPrioritySet(intregister, priority);
- MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
-
- // create the callback
- mp_obj_t _irq = mp_irq_new (ch, args[2].u_obj, &pyb_timer_channel_irq_methods);
-
- // enable the callback before returning
- pyb_timer_channel_irq_enable(ch);
-
- return _irq;
-
-invalid_args:
- mp_raise_ValueError(mpexception_value_invalid_arguments);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_irq_obj, 1, pyb_timer_channel_irq);
-
-STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
- // instance methods
- { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_timer_channel_freq_obj) },
- { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&pyb_timer_channel_period_obj) },
- { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&pyb_timer_channel_duty_cycle_obj) },
- { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_timer_channel_irq_obj) },
-};
-STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
-
-STATIC const mp_obj_type_t pyb_timer_channel_type = {
- { &mp_type_type },
- .name = MP_QSTR_TimerChannel,
- .print = pyb_timer_channel_print,
- .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict,
-};
-