summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--cc3200/application.lds1
-rw-r--r--cc3200/application.mk2
-rw-r--r--cc3200/misc/mpcallback.c1
-rw-r--r--cc3200/mods/modnetwork.c6
-rw-r--r--cc3200/mods/modpyb.c2
-rw-r--r--cc3200/mods/modwlan.c1
-rw-r--r--cc3200/mods/pybpin.c1
-rw-r--r--cc3200/mods/pybrtc.c24
-rw-r--r--cc3200/mods/pybrtc.h1
-rw-r--r--cc3200/mods/pybtimer.c834
-rw-r--r--cc3200/mods/pybtimer.h38
-rw-r--r--cc3200/mods/pybuart.c24
-rw-r--r--cc3200/mods/pybuart.h2
-rw-r--r--cc3200/mpconfigport.h1
-rw-r--r--cc3200/mptask.c12
-rw-r--r--cc3200/qstrdefsport.h27
16 files changed, 946 insertions, 31 deletions
diff --git a/cc3200/application.lds b/cc3200/application.lds
index 4ffcd03c35..22ad1968d5 100644
--- a/cc3200/application.lds
+++ b/cc3200/application.lds
@@ -26,7 +26,6 @@
__stack_size__ = 2K; /* interrupts are handled within this stack */
__min_heap_size__ = 8K;
-__rtos_heap_size = 16K;
MEMORY
{
diff --git a/cc3200/application.mk b/cc3200/application.mk
index 29be228bd1..6ae8b51ab1 100644
--- a/cc3200/application.mk
+++ b/cc3200/application.mk
@@ -98,6 +98,7 @@ APP_MODS_SRC_C = $(addprefix mods/,\
pybsd.c \
pybsleep.c \
pybspi.c \
+ pybtimer.c \
pybuart.c \
pybwdt.c \
)
@@ -192,6 +193,7 @@ $(BUILD)/FreeRTOS/Source/%.o: CFLAGS += -Os
$(BUILD)/ftp/%.o: CFLAGS += -Os
$(BUILD)/hal/%.o: CFLAGS += -Os
$(BUILD)/misc/%.o: CFLAGS += -Os
+$(BUILD)/mods/%.o: CFLAGS += -Os
$(BUILD)/py/%.o: CFLAGS += -Os
$(BUILD)/simplelink/%.o: CFLAGS += -Os
$(BUILD)/drivers/cc3100/%.o: CFLAGS += -Os
diff --git a/cc3200/misc/mpcallback.c b/cc3200/misc/mpcallback.c
index 87969f7276..6ca4f49d20 100644
--- a/cc3200/misc/mpcallback.c
+++ b/cc3200/misc/mpcallback.c
@@ -71,7 +71,6 @@ mp_obj_t mpcallback_new (mp_obj_t parent, mp_obj_t handler, const mp_cb_methods_
mpcallback_obj_t *mpcallback_find (mp_obj_t parent) {
for (mp_uint_t i = 0; i < MP_STATE_PORT(mpcallback_obj_list).len; i++) {
- // search for the object and then remove it
mpcallback_obj_t *callback_obj = ((mpcallback_obj_t *)(MP_STATE_PORT(mpcallback_obj_list).items[i]));
if (callback_obj->parent == parent) {
return callback_obj;
diff --git a/cc3200/mods/modnetwork.c b/cc3200/mods/modnetwork.c
index f9536ccb5e..f7dfd139f8 100644
--- a/cc3200/mods/modnetwork.c
+++ b/cc3200/mods/modnetwork.c
@@ -80,10 +80,10 @@ STATIC mp_obj_t network_server_stop(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_server_stop_obj, network_server_stop);
-STATIC mp_obj_t network_server_enabled(void) {
+STATIC mp_obj_t network_server_running(void) {
return MP_BOOL(servers_are_enabled());
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_server_enabled_obj, network_server_enabled);
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_server_running_obj, network_server_running);
STATIC mp_obj_t network_server_login(mp_obj_t user, mp_obj_t pass) {
const char *_user = mp_obj_str_get_str(user);
@@ -102,7 +102,7 @@ STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
#if (MICROPY_PORT_HAS_TELNET || MICROPY_PORT_HAS_FTP)
{ MP_OBJ_NEW_QSTR(MP_QSTR_start_server), (mp_obj_t)&network_server_start_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_stop_server), (mp_obj_t)&network_server_stop_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_server_enabled), (mp_obj_t)&network_server_enabled_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_server_running), (mp_obj_t)&network_server_running_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_server_login), (mp_obj_t)&network_server_login_obj },
#endif
};
diff --git a/cc3200/mods/modpyb.c b/cc3200/mods/modpyb.c
index a261c8b0d8..5dc9a35c23 100644
--- a/cc3200/mods/modpyb.c
+++ b/cc3200/mods/modpyb.c
@@ -62,6 +62,7 @@
#include "pybwdt.h"
#include "pybsleep.h"
#include "pybspi.h"
+#include "pybtimer.h"
#include "utils.h"
#include "gccollect.h"
#include "mperror.h"
@@ -271,6 +272,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_Sleep), (mp_obj_t)&pyb_sleep_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_HeartBeat), (mp_obj_t)&pyb_heartbeat_obj },
diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c
index e2fbdf5031..c00145ec3e 100644
--- a/cc3200/mods/modwlan.c
+++ b/cc3200/mods/modwlan.c
@@ -787,6 +787,7 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
// connect to the requested access point
modwlan_Status_t status;
status = wlan_do_connect (ssid, ssid_len, bssid, sec, key, key_len);
+ // TODO: make the timeout a parameter so that is configurable
if (status == MODWLAN_ERROR_TIMEOUT) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed));
}
diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c
index e1e7e4871b..c9454de337 100644
--- a/cc3200/mods/pybpin.c
+++ b/cc3200/mods/pybpin.c
@@ -755,6 +755,7 @@ STATIC void EXTI_Handler(uint port) {
uint32_t bit = MAP_GPIOIntStatus(port, true);
MAP_GPIOIntClear(port, bit);
+ // TODO: loop through all the active bits before exiting
pin_obj_t *self = (pin_obj_t *)pin_find_pin_by_port_bit(&pin_cpu_pins_locals_dict, port, bit);
mp_obj_t _callback = mpcallback_find(self);
mpcallback_handler(_callback);
diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c
index a9cc995d57..603f9930c8 100644
--- a/cc3200/mods/pybrtc.c
+++ b/cc3200/mods/pybrtc.c
@@ -92,6 +92,18 @@ void pybrtc_init(void) {
}
}
+void pyb_rtc_callback_disable (mp_obj_t self_in) {
+ // check the wake from param
+ if (pybrtc_data.prwmode & PYB_PWR_MODE_ACTIVE) {
+ // disable the slow clock interrupt
+ MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
+ }
+ // disable wake from ldps and hibernate
+ pybsleep_configure_timer_wakeup (PYB_PWR_MODE_ACTIVE);
+ // read the interrupt status to clear any pending interrupt
+ (void)MAP_PRCMIntStatus();
+}
+
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
******************************************************************************/
@@ -108,18 +120,6 @@ STATIC void pyb_rtc_callback_enable (mp_obj_t self_in) {
pybsleep_configure_timer_wakeup (pybrtc_data.prwmode);
}
-STATIC void pyb_rtc_callback_disable (mp_obj_t self_in) {
- // check the wake from param
- if (pybrtc_data.prwmode & PYB_PWR_MODE_ACTIVE) {
- // disable the slow clock interrupt
- MAP_PRCMIntDisable(PRCM_INT_SLOW_CLK_CTR);
- }
- // disable wake from ldps and hibernate
- pybsleep_configure_timer_wakeup (PYB_PWR_MODE_ACTIVE);
- // read the interrupt status to clear any pending interrupt
- (void)MAP_PRCMIntStatus();
-}
-
/******************************************************************************/
// Micro Python bindings
diff --git a/cc3200/mods/pybrtc.h b/cc3200/mods/pybrtc.h
index a41cff772e..0c7a6f859a 100644
--- a/cc3200/mods/pybrtc.h
+++ b/cc3200/mods/pybrtc.h
@@ -34,5 +34,6 @@
extern const mp_obj_base_t pyb_rtc_obj;
void pybrtc_init(void);
+void pyb_rtc_callback_disable (mp_obj_t self_in);
#endif // PYBRTC_H_
diff --git a/cc3200/mods/pybtimer.c b/cc3200/mods/pybtimer.c
new file mode 100644
index 0000000000..c52b506110
--- /dev/null
+++ b/cc3200/mods/pybtimer.c
@@ -0,0 +1,834 @@
+/*
+ * This file is part of the Micro Python 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 MICROPY_HAL_H
+#include "py/obj.h"
+#include "py/nlr.h"
+#include "py/runtime.h"
+#include "py/gc.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 "pybtimer.h"
+#include "pybsleep.h"
+#include "mpcallback.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 callback method,
+/// the timer event can call a Python function.
+///
+/// Example usage to toggle an LED at a fixed frequency:
+///
+/// tim = pyb.Timer(3) # create a timer object using timer 4
+/// tim.init(mode=Timer.PERIODIC) # initialize it in periodic mode
+/// tim_ch = tim.channel(Timer.A, freq=2) # configure channel A at a frequency of 2Hz
+/// tim_ch.callback(handler=lambda t:led.toggle()) # toggle a led on every cycle of the timer
+///
+/// Further examples:
+///
+/// tim1 = pyb.Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
+/// tim2 = pyb.Timer(0, mode=Timer.PWM) # initialize it in PWM mode
+/// tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the PWM on channel B with a 50% duty cycle
+/// tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the event counter with a frequency of 1Hz and triggered by positive edges
+/// tim_ch.time() # get the current time in usec (can also be set)
+/// tim_ch.freq(20) # set the frequency (can also get)
+/// tim_ch.duty_cycle(30) # set the duty cycle to 30% (can also get)
+/// tim_ch.duty_cycle(30, Timer.NEGATIVE) # set the duty cycle to 30% and change the polarity to negative
+/// tim_ch.event_count() # get the number of captured events
+/// tim_ch.event_time() # get the the time of the last captured event
+///
+
+/******************************************************************************
+ DECLARE PRIVATE CONSTANTS
+ ******************************************************************************/
+#define PYBTIMER_NUM_TIMERS (4)
+#define PYBTIMER_POLARITY_POS (0x01)
+#define PYBTIMER_POLARITY_NEG (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 intflags;
+ 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;
+ uint16_t channel;
+ uint8_t polarity;
+ uint8_t duty_cycle;
+} pyb_timer_channel_obj_t;
+
+/******************************************************************************
+ DEFINE PRIVATE DATA
+ ******************************************************************************/
+STATIC const mp_cb_methods_t pyb_timer_channel_cb_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;
+
+/******************************************************************************
+ DECLARE PRIVATE FUNCTIONS
+ ******************************************************************************/
+STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_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 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);
+}
+
+void timer_disable_all (void) {
+ pyb_timer_obj_t timer = {
+ .timer = TIMERA0_BASE,
+ .intflags = TIMER_CAPB_EVENT | TIMER_CAPB_MATCH |
+ TIMER_TIMB_TIMEOUT | TIMER_CAPA_EVENT |
+ TIMER_CAPA_MATCH | TIMER_TIMA_TIMEOUT,
+ .peripheral = PRCM_TIMERA0
+ };
+
+ for (uint32_t i = 0; i < PYBTIMER_NUM_TIMERS; i++) {
+ // in case it's not clocked
+ MAP_PRCMPeripheralClkEnable(timer.peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+ timer_disable(&timer);
+ // timer base offset according to hw_memmap.h
+ timer.timer += 0x1000;
+ // peripheral offset according to prcm.h
+ timer.peripheral++;
+ }
+}
+
+void pyb_timer_channel_callback_enable (mp_obj_t self_in) {
+ pyb_timer_channel_obj_t *self = self_in;
+ MAP_TimerIntClear(self->timer->timer, self->timer->intflags & self->channel);
+ MAP_TimerIntEnable(self->timer->timer, self->timer->intflags & self->channel);
+}
+
+void pyb_timer_channel_callback_disable (mp_obj_t self_in) {
+ pyb_timer_channel_obj_t *self = self_in;
+ MAP_TimerIntDisable(self->timer->timer, self->timer->intflags & self->channel);
+}
+
+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;
+}
+
+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);
+ }
+}
+
+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);
+}
+
+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->intflags);
+ MAP_TimerIntClear(tim->timer, tim->intflags);
+ MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+ memset(&pyb_timer_obj[tim->id], 0, sizeof(pyb_timer_obj_t));
+}
+
+// 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 = PYBTIMER_SRC_FREQ_HZ / ch->frequency;
+
+ period = MAX(1, period) - 1;
+ prescaler = period >> 16;
+ *period_out = period;
+ if (prescaler > 0xFF && maxcount == 0xFFFF) {
+ goto error;
+ }
+ // check limit values for the duty cycle
+ if (ch->duty_cycle == 0) {
+ *match_out = period - 1;
+ }
+ else {
+ *match_out = period - ((period * ch->duty_cycle) / 100);
+ }
+ if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM && (*match_out > 0xFFFF)) {
+ goto error;
+ }
+ return prescaler;
+
+error:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_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;
+ uint32_t match;
+ uint32_t prescaler = compute_prescaler_period_and_match_value(ch, &period, &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);
+
+ // 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);
+ }
+ // configure the event edge type if we are in such mode
+ else if ((ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_COUNT || (ch->timer->config & 0x0F) == TIMER_CFG_A_CAP_TIME) {
+ uint32_t polarity = TIMER_EVENT_BOTH_EDGES;
+ if (ch->polarity == PYBTIMER_POLARITY_POS) {
+ polarity = TIMER_EVENT_POS_EDGE;
+ }
+ else if (ch->polarity == PYBTIMER_POLARITY_NEG) {
+ polarity = TIMER_EVENT_NEG_EDGE;
+ }
+ MAP_TimerControlEvent(ch->timer->timer, ch->channel, polarity);
+ }
+
+#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);
+}
+
+/******************************************************************************/
+/* Micro Python 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:
+ mode_qst = MP_QSTR_ONE_SHOT;
+ break;
+ case TIMER_CFG_A_PERIODIC:
+ mode_qst = MP_QSTR_PERIODIC;
+ break;
+ case TIMER_CFG_A_CAP_COUNT:
+ mode_qst = MP_QSTR_EDGE_COUNT;
+ break;
+ case TIMER_CFG_A_CAP_TIME:
+ mode_qst = MP_QSTR_EDGE_TIME;
+ break;
+ default:
+ break;
+ }
+ mp_printf(print, "<Timer%u, mode=Timer.%q>", tim->id, mode_qst);
+}
+
+/// \method init(mode, *, width)
+/// Initialise the timer. Initialisation must give the desired mode
+/// and an optional timer width
+///
+/// tim.init(mode=Timer.PERIODIC) # configure in free running periodic mode
+/// tim.init(mode=Timer.ONE_SHOT, width=16) # one shot mode splitted into two 16-bit independent timers
+///
+/// Keyword arguments:
+///
+/// - `width` - specifies the width of the timer. Default is 32 bit mode. When in 16 bit mode
+/// the timer is splitted into 2 independent channels.
+///
+STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_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 = 32} },
+ };
+
+ // 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 && _mode != TIMER_CFG_A_PERIODIC && _mode != TIMER_CFG_A_CAP_COUNT &&
+ _mode != TIMER_CFG_A_CAP_TIME && _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_ONE_SHOT && _mode != TIMER_CFG_A_PERIODIC)) {
+ // 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
+ pybsleep_add ((const mp_obj_t)tim, (WakeUpCB_t)timer_channel_init);
+
+ return mp_const_none;
+
+error:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+}
+
+/// \classmethod \constructor(id, ...)
+/// Construct a new timer object of the given id. If additional
+/// arguments are given, then the timer is initialised by `init(...)`.
+/// `id` can be 0 to 3
+STATIC mp_obj_t pyb_timer_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_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
+ uint32_t timer_idx = mp_obj_get_int(args[0]);
+ if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable));
+ }
+
+ 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;
+}
+
+// \method init()
+/// initializes the timer
+STATIC mp_obj_t pyb_timer_init(mp_uint_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);
+
+// \method deinit()
+/// disables the timer
+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);
+
+/// \method channel(channel, *, freq, polarity, duty_cycle)
+/// Initialise the timer channel. Initialization requires at least a frequency param. With no
+/// extra params given besides the channel id, the channel is returned with the previous configuration
+/// os 'None', if it hasn't been initialized before.
+///
+/// tim1.channel(Timer.A, freq=1000) # set channel A frequency to 1KHz
+/// tim2.channel(Timer.AB, freq=10) # both channels (because it's a 32 bit timer) combined to create a 10Hz timer
+///
+/// when initialiazing the channel of a 32-bit timer, channel ID MUST be = Timer.AB
+///
+/// Keyword arguments:
+///
+/// - `freq` - specifies the frequency in Hz
+///
+/// - `polarity` - in PWM specifies the polarity of the pulse. In capture mode specifies the edge to capture.
+/// in order to capture on both negative and positive edges, make it = Timer.POSITIVE | Timer.NEGATIVE.
+///
+STATIC mp_obj_t pyb_timer_channel(mp_uint_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_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) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible));
+ }
+
+ 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);
+
+ // check the frequency
+ if (args[0].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[1].u_int == (PYBTIMER_POLARITY_POS | PYBTIMER_POLARITY_NEG)) {
+ goto error;
+ }
+ // check the range of the duty cycle
+ if (args[2].u_int < 0 || args[2].u_int > 100) {
+ 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->polarity = args[1].u_int;
+ ch->duty_cycle = args[2].u_int;
+
+ timer_channel_init(ch);
+
+ // add the timer to the list
+ pyb_timer_channel_add(ch);
+
+ return ch;
+
+error:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel);
+
+STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = {
+ // instance methods
+ { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_timer_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_timer_deinit_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_channel), (mp_obj_t)&pyb_timer_channel_obj },
+
+ // class constants
+ { MP_OBJ_NEW_QSTR(MP_QSTR_A), MP_OBJ_NEW_SMALL_INT(TIMER_A) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_B), MP_OBJ_NEW_SMALL_INT(TIMER_B) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AB), MP_OBJ_NEW_SMALL_INT(TIMER_A | TIMER_B) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_ONE_SHOT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PERIODIC) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_COUNT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_COUNT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_EDGE_TIME), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_CAP_TIME) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PWM), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PWM) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_POSITIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_POS) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_NEGATIVE), MP_OBJ_NEW_SMALL_INT(PYBTIMER_POLARITY_NEG) },
+};
+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_cb_methods_t pyb_timer_channel_cb_methods = {
+ .init = pyb_timer_channel_callback,
+ .enable = pyb_timer_channel_callback_enable,
+ .disable = pyb_timer_channel_callback_disable,
+};
+
+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_obj_t _callback = mpcallback_find(self);
+ mpcallback_handler(_callback);
+ }
+}
+
+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, "<%q %s, timer=%u, %q=%u", MP_QSTR_TimerChannel,
+ ch_id, ch->timer->id, MP_QSTR_freq, ch->frequency);
+
+ uint32_t mode = ch->timer->config & 0xFF;
+ if (mode == TIMER_CFG_A_CAP_COUNT || mode == TIMER_CFG_A_CAP_TIME || 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;
+ }
+ if (mode == TIMER_CFG_A_PWM) {
+ mp_printf(print, ", %q=%u", MP_QSTR_duty_cycle, ch->duty_cycle);
+ }
+ }
+ mp_printf(print, ">");
+}
+
+/// \method freq([value])
+/// get or set the frequency of the timer channel
+STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_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
+ ch->frequency = mp_obj_get_int(args[1]);
+ 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);
+
+/// \method time([value])
+/// get or set the value of the timer channel in microseconds
+STATIC mp_obj_t pyb_timer_channel_time(mp_uint_t n_args, const mp_obj_t *args) {
+ pyb_timer_channel_obj_t *ch = args[0];
+ uint32_t value;
+ // calculate the period, the prescaler and the match value
+ uint32_t period;
+ uint32_t match;
+ (void)compute_prescaler_period_and_match_value(ch, &period, &match);
+ if (n_args == 1) {
+ // get
+ value = (ch->channel == TIMER_B) ? HWREG(ch->timer->timer + TIMER_O_TBV) : HWREG(ch->timer->timer + TIMER_O_TAV);
+ // return the current timer value in microseconds
+ // substract value to period since we are always operating in count-down mode
+ uint32_t time_t = (1000 * (period - value)) / period;
+ return mp_obj_new_int((time_t * 1000) / ch->frequency);
+ }
+ else {
+ // set
+ value = (mp_obj_get_int(args[1]) * ((ch->frequency * period) / 1000)) / 1000;
+ if ((value > 0xFFFF) && (ch->timer->config & TIMER_CFG_SPLIT_PAIR)) {
+ // this exceeds the maximum value of a 16-bit timer
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+ }
+ // write period minus value since we are always operating in count-down mode
+ TimerValueSet (ch->timer->timer, ch->channel, (period - value));
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_time_obj, 1, 2, pyb_timer_channel_time);
+
+/// \method event_count()
+/// get the number of events triggered by the configured edge
+STATIC mp_obj_t pyb_timer_channel_event_count(mp_obj_t self_in) {
+ pyb_timer_channel_obj_t *ch = self_in;
+ return mp_obj_new_int(MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_count_obj, pyb_timer_channel_event_count);
+
+/// \method event_time()
+/// get the time at which the last event was triggered
+STATIC mp_obj_t pyb_timer_channel_event_time(mp_obj_t self_in) {
+ pyb_timer_channel_obj_t *ch = self_in;
+ // calculate the period, the prescaler and the match value
+ uint32_t period;
+ uint32_t match;
+ (void)compute_prescaler_period_and_match_value(ch, &period, &match);
+ uint32_t value = MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel);
+ // substract value to period since we are always operating in count-down mode
+ uint32_t time_t = (1000 * (period - value)) / period;
+ return mp_obj_new_int((time_t * 1000) / ch->frequency);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_channel_event_time_obj, pyb_timer_channel_event_time);
+
+/// \method duty_cycle()
+/// get or set the duty cycle when in PWM mode
+STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_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;
+ uint32_t match;
+ ch->duty_cycle = mp_obj_get_int(args[1]);
+ compute_prescaler_period_and_match_value(ch, &period, &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);
+ 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);
+
+/// \method callback(handler, value, priority)
+/// create a callback object associated with the timer channel
+STATIC mp_obj_t pyb_timer_channel_callback (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ mp_arg_val_t args[mpcallback_INIT_NUM_ARGS];
+ mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mpcallback_INIT_NUM_ARGS, mpcallback_init_args, args);
+
+ pyb_timer_channel_obj_t *ch = pos_args[0];
+ mp_obj_t _callback = mpcallback_find(ch);
+ if (kw_args->used > 0 || !_callback) {
+ // convert the priority to the correct value
+ uint priority = mpcallback_translate_priority (args[2].u_int);
+
+ // validate the power mode
+ uint pwrmode = args[4].u_int;
+ if (pwrmode != PYB_PWR_MODE_ACTIVE) {
+ goto invalid_args;
+ }
+
+ // disable the callback first
+ pyb_timer_channel_callback_disable(ch);
+
+ uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
+ uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
+ switch (_config) {
+ case TIMER_CFG_A_ONE_SHOT:
+ case TIMER_CFG_A_PERIODIC:
+ ch->timer->intflags |= TIMER_TIMA_TIMEOUT << shift;
+ break;
+ case TIMER_CFG_A_CAP_COUNT:
+ ch->timer->intflags |= TIMER_CAPA_MATCH << shift;
+ break;
+ case TIMER_CFG_A_CAP_TIME:
+ ch->timer->intflags |= TIMER_CAPA_EVENT << shift;
+ break;
+ case TIMER_CFG_A_PWM:
+ // special case for the match interrupt
+ ch->timer->intflags |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
+ break;
+ default:
+ break;
+ }
+ if (ch->channel == (TIMER_A | TIMER_B)) {
+ // again a special case for the match interrupt
+ if (_config == TIMER_CFG_A_PWM) {
+ ch->timer->intflags |= TIMER_TIMB_MATCH;
+ } else {
+ ch->timer->intflags |= (ch->timer->intflags << 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
+ _callback = mpcallback_new (ch, args[1].u_obj, &pyb_timer_channel_cb_methods);
+
+ // reload the timer
+ uint32_t period;
+ uint32_t match;
+ compute_prescaler_period_and_match_value(ch, &period, &match);
+ MAP_TimerLoadSet(ch->timer->timer, ch->channel, period);
+
+ // enable the callback before returning
+ pyb_timer_channel_callback_enable(ch);
+ }
+ return _callback;
+
+invalid_args:
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_callback_obj, 1, pyb_timer_channel_callback);
+
+STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
+ // instance methods
+ { MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_timer_channel_freq_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&pyb_timer_channel_time_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_event_count), (mp_obj_t)&pyb_timer_channel_event_count_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_event_time), (mp_obj_t)&pyb_timer_channel_event_time_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_duty_cycle), (mp_obj_t)&pyb_timer_channel_duty_cycle_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_timer_channel_callback_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,
+};
+
diff --git a/cc3200/mods/pybtimer.h b/cc3200/mods/pybtimer.h
new file mode 100644
index 0000000000..849e41ed74
--- /dev/null
+++ b/cc3200/mods/pybtimer.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the Micro Python 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.
+ */
+
+/******************************************************************************
+ DECLARE EXPORTED DATA
+ ******************************************************************************/
+extern const mp_obj_type_t pyb_timer_type;
+
+/******************************************************************************
+ DECLARE PUBLIC FUNCTIONS
+ ******************************************************************************/
+void timer_init0 (void);
+void timer_disable_all (void);
+
diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c
index 8d1f79b03f..87b8b15e7c 100644
--- a/cc3200/mods/pybuart.c
+++ b/cc3200/mods/pybuart.c
@@ -101,6 +101,7 @@ STATIC void UART0IntHandler(void);
STATIC void UART1IntHandler(void);
STATIC void uart_callback_enable (mp_obj_t self_in);
STATIC void uart_callback_disable (mp_obj_t self_in);
+STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in);
/******************************************************************************
DEFINE PRIVATE TYPES
@@ -124,7 +125,8 @@ struct _pyb_uart_obj_t {
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
-STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS];
+STATIC pyb_uart_obj_t pyb_uart_obj[PYB_NUM_UARTS] = {{.reg = UARTA0_BASE, .peripheral = PRCM_UARTA0},
+ {.reg = UARTA1_BASE, .peripheral = PRCM_UARTA1}};
STATIC const mp_cb_methods_t uart_cb_methods;
/******************************************************************************
@@ -208,20 +210,19 @@ mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, uint rxbuffe
return _callback;
}
+void uart_disable_all (void) {
+ for (int i = 0; i < PYB_NUM_UARTS; i++) {
+ // in case it's not clocked
+ MAP_PRCMPeripheralClkEnable(pyb_uart_obj[i].peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
+ pyb_uart_deinit(&pyb_uart_obj[i]);
+ }
+}
+
/******************************************************************************
DEFINE PRIVATE FUNCTIONS
******************************************************************************/
// assumes init parameters have been set up correctly
STATIC void uart_init (pyb_uart_obj_t *self) {
- if (self->uart_id == PYB_UART_0) {
- self->reg = UARTA0_BASE;
- self->peripheral = PRCM_UARTA0;
- }
- else {
- self->reg = UARTA1_BASE;
- self->peripheral = PRCM_UARTA1;
- }
-
// Enable the peripheral clock
MAP_PRCMPeripheralClkEnable(self->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
@@ -457,6 +458,7 @@ STATIC mp_obj_t pyb_uart_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t
pyb_uart_obj_t *self = &pyb_uart_obj[uart_id];
self->base.type = &pyb_uart_type;
self->uart_id = uart_id;
+
if (n_args > 1 || n_kw > 0) {
// start the peripheral
mp_map_t kw_args;
@@ -474,7 +476,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_init_obj, 1, pyb_uart_init);
/// \method deinit()
/// Turn off the UART bus.
-mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
+STATIC mp_obj_t pyb_uart_deinit(mp_obj_t self_in) {
pyb_uart_obj_t *self = self_in;
// unregister it with the sleep module
diff --git a/cc3200/mods/pybuart.h b/cc3200/mods/pybuart.h
index 2441c1b9dc..66812a8834 100644
--- a/cc3200/mods/pybuart.h
+++ b/cc3200/mods/pybuart.h
@@ -38,12 +38,12 @@ typedef struct _pyb_uart_obj_t pyb_uart_obj_t;
extern const mp_obj_type_t pyb_uart_type;
void uart_init0(void);
-mp_obj_t pyb_uart_deinit(mp_obj_t self_in);
bool uart_rx_any(pyb_uart_obj_t *uart_obj);
int uart_rx_char(pyb_uart_obj_t *uart_obj);
bool uart_tx_char(pyb_uart_obj_t *self, int c);
bool uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len);
void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len);
mp_obj_t uart_callback_new (pyb_uart_obj_t *self, mp_obj_t handler, uint rxbuffer_size, mp_int_t priority);
+void uart_disable_all (void);
#endif // PYBUART_H_
diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h
index dfdce7f8bd..c585b3e382 100644
--- a/cc3200/mpconfigport.h
+++ b/cc3200/mpconfigport.h
@@ -139,6 +139,7 @@ extern const struct _mp_obj_module_t mp_module_network;
mp_obj_list_t mod_network_nic_list; \
mp_obj_list_t pybsleep_obj_list; \
mp_obj_list_t mpcallback_obj_list; \
+ mp_obj_list_t pyb_timer_channel_obj_list; \
// type definitions for the specific machine
diff --git a/cc3200/mptask.c b/cc3200/mptask.c
index 4c077107f7..28dde5185c 100644
--- a/cc3200/mptask.c
+++ b/cc3200/mptask.c
@@ -63,6 +63,7 @@
#include "pybsd.h"
#include "pins.h"
#include "pybsleep.h"
+#include "pybtimer.h"
#include "mpcallback.h"
/******************************************************************************
@@ -124,6 +125,7 @@ soft_reset:
mperror_init0();
uart_init0();
pin_init0();
+ timer_init0();
readline_init0();
mod_network_init0();
#if MICROPY_HW_ENABLE_RNG
@@ -242,15 +244,23 @@ soft_reset_exit:
// soft reset
pybsleep_signal_soft_reset();
-
mp_printf(&mp_plat_print, "PYB: soft reboot\n");
+ // disable all peripherals that could trigger a callback
+ pyb_rtc_callback_disable(NULL);
+ timer_disable_all();
+ uart_disable_all();
+
+ // flush the serial flash buffer
sflash_disk_flush();
#if MICROPY_HW_HAS_SDCARD
pybsd_deinit();
#endif
+ // wait for pending transactions to complete
+ HAL_Delay(20);
+
goto soft_reset;
}
diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h
index b14925d196..3a8fb55dea 100644
--- a/cc3200/qstrdefsport.h
+++ b/cc3200/qstrdefsport.h
@@ -235,7 +235,7 @@ Q(network)
Q(route)
Q(start_server)
Q(stop_server)
-Q(server_enabled)
+Q(server_running)
Q(server_login)
// for WLAN class
@@ -325,3 +325,28 @@ Q(send_recv)
Q(ACTIVE_LOW)
Q(ACTIVE_HIGH)
+// for Timer class
+Q(Timer)
+Q(TimerChannel)
+Q(init)
+Q(deinit)
+Q(freq)
+Q(mode)
+Q(width)
+Q(channel)
+Q(polarity)
+Q(duty_cycle)
+Q(time)
+Q(event_count)
+Q(event_time)
+Q(A)
+Q(B)
+Q(AB)
+Q(ONE_SHOT)
+Q(PERIODIC)
+Q(EDGE_COUNT)
+Q(EDGE_TIME)
+Q(PWM)
+Q(POSITIVE)
+Q(NEGATIVE)
+