diff --git a/cc3200/boards/cc3200_af.csv b/cc3200/boards/cc3200_af.csv index a310020587..a93cb54a5b 100644 --- a/cc3200/boards/cc3200_af.csv +++ b/cc3200/boards/cc3200_af.csv @@ -1,11 +1,11 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,ADC -1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM0,,,SD0_CLK,UART1_TX,,,,,TIM0_CC1,,,, -2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM1,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC0,I2S0_FS,,, -3,GP12,GP12,GP12,,,I2S0_CLK,pVS(VSYNC),I2C0_SCL,,UART0_TX,,,,,TIM1_CC1,,,, -4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC0,,,, -5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC1,,,, -6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C0_SDA,,SPI0_MISO,SD0_DAT0,,,,,TIM3_CC0,,, -7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,SPI0_MOSI,SD0_CLK,,,,,TIM3_CC1,,, +1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM,,,SD0_CLK,UART1_TX,,,,,TIM0_CC,,,, +2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC,I2S0_FS,,, +3,GP12,GP12,GP12,,,I2S0_CLK,pVS(VSYNC),I2C0_SCL,,UART0_TX,,,,,TIM1_CC,,,, +4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC,,,, +5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC,,,, +6,GP15,GP15,GP15,,,,pDATA9(CAM_D5),I2C0_SDA,,SPI0_MISO,SD0_DAT0,,,,,TIM3_CC,,, +7,GP16,GP16,GP16,,,,pDATA10(CAM_D6),UART1_TX,,SPI0_MOSI,SD0_CLK,,,,,TIM3_CC,,, 8,GP17,GP17,GP17,,,,pDATA11(CAM_D7),UART1_RX,,SPI0_CS0,SD0_CMD,,,,,,,, 9,VDD_DIG1,VDD_DIG1,VDD_DIG1,,,,,,,,,,,,,,,, 10,VIN_IO1,VIN_IO1,VIN_IO1,,,,,,,,,,,,,,,, @@ -13,13 +13,13 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1 12,FLASH_SPI_DOUT,FLASH_SPI_DOUT,FLASH_SPI_DOUT,,,,,,,,,,,,,,,, 13,FLASH_SPI_DIN,FLASH_SPI_DIN,FLASH_SPI_DIN,,,,,,,,,,,,,,,, 14,FLASH_SPI_CS,FLASH_SPI_CS,FLASH_SPI_CS,,,,,,,,,,,,,,,, -15,GP22,GP22,GP22,,,,,TIM2_CC0,,I2S0_FS,,,,,,,,, +15,GP22,GP22,GP22,,,,,TIM2_CC,,I2S0_FS,,,,,,,,, 16,GP23,TDI,GP23,TDI,UART1_TX,,,,,,,I2C0_SCL,,,,,,, -17,GP24,TDO,GP24,TDO,UART1_RX,,TIM3_CC0,TIM0_PWM0,I2S0_FS,,,I2C0_SDA,,,,,,, +17,GP24,TDO,GP24,TDO,UART1_RX,,TIM3_CC,TIM0_PWM,I2S0_FS,,,I2C0_SDA,,,,,,, 18,GP28,GP28,GP28,,,,,,,,,,,,,,,, -19,TCK,TCK,,TCK,,,,,,,TIM1_PWM2,,,,,,,, +19,TCK,TCK,,TCK,,,,,,,TIM1_PWM,,,,,,,, 20,GP29,TMS,GP29,TMS,,,,,,,,,,,,,,, -21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM0,,,,,,, +21,GP25,SOP2,GP25,,I2S0_FS,,,,,,,TIM1_PWM,,,,,,, 22,WLAN_XTAL_N,WLAN_XTAL_N,WLAN_XTAL_N,,,,,,,,,,,,,,,, 23,WLAN_XTAL_P,WLAN_XTAL_P,WLAN_XTAL_P,,,,,,,,,,,,,,,, 24,VDD_PLL,VDD_PLL,VDD_PLL,,,,,,,,,,,,,,,, @@ -48,19 +48,19 @@ Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF1 47,VDD_ANA2,VDD_ANA2,VDD_ANA2,,,,,,,,,,,,,,,, 48,VDD_ANA1,VDD_ANA1,VDD_ANA1,,,,,,,,,,,,,,,, 49,VDD_RAM,VDD_RAM,VDD_RAM,,,,,,,,,,,,,,,, -50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC0,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,, +50,GP0,GP0,GP0,,,UART0_RTS,I2S0_DAT0,,I2S0_DAT1,TIM0_CC,,SPI0_CS0,UART1_RTS,,UART0_CTS,,,, 51,RTC_XTAL_P,RTC_XTAL_P,RTC_XTAL_P,,,,,,,,,,,,,,,, 52,RTC_XTAL_N,RTC_XTAL_N,GP32,,I2S0_CLK,,I2S0_DAT0,,UART0_RTS,,SPI0_MOSI,,,,,,,, -53,GP30,GP30,GP30,,I2S0_CLK,I2S0_FS,TIM2_CC1,,,SPI0_MISO,,UART0_TX,,,,,,, +53,GP30,GP30,GP30,,I2S0_CLK,I2S0_FS,TIM2_CC,,,SPI0_MISO,,UART0_TX,,,,,,, 54,VIN_IO2,VIN_IO2,VIN_IO2,,,,,,,,,,,,,,,, -55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC1,,,,,,,,, +55,GP1,GP1,GP1,,,UART0_TX,pCLK (PIXCLK),,UART1_TX,TIM0_CC,,,,,,,,, 56,VDD_DIG2,VDD_DIG2,VDD_DIG2,,,,,,,,,,,,,,,, -57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC0,,,,,,,,,ADC0_CH0 +57,GP2,GP2,GP2,,,UART0_RX,,,UART1_RX,TIM1_CC,,,,,,,,,ADC0_CH0 58,GP3,GP3,GP3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC0_CH1 59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC0_CH2 -60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC1,,,,,,,,,ADC0_CH3 -61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,TIM3_CC0,,,,,,,,, +60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC,,,,,,,,,ADC0_CH3 +61,GP6,GP6,GP6,,,UART1_CTS,pDATA4(CAM_D0),UART0_RTS,UART0_CTS,TIM3_CC,,,,,,,,, 62,GP7,GP7,GP7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,I2S0_CLK,,, -63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC0,,,, -64,GP9,GP9,GP9,,,TIM2_PWM1,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC0,,,, +63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC,,,, +64,GP9,GP9,GP9,,,TIM2_PWM,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC,,,, 65,GND_TAB,GND_TAB,GND_TAB,,,,,,,,,,,,,,,, diff --git a/cc3200/boards/make-pins.py b/cc3200/boards/make-pins.py index 676896803a..26ca5a0b92 100644 --- a/cc3200/boards/make-pins.py +++ b/cc3200/boards/make-pins.py @@ -12,7 +12,7 @@ SUPPORTED_AFS = { 'UART': ('TX', 'RX', 'RTS', 'CTS'), 'SPI': ('CLK', 'MOSI', 'MISO', 'CS0'), #'I2S': ('CLK', 'FS', 'DAT0', 'DAT1'), 'I2C': ('SDA', 'SCL'), - 'TIM': ('PWM0', 'PWM1', 'CC0', 'CC1'), + 'TIM': ('PWM'), 'SD': ('CLK', 'CMD', 'DAT0'), 'ADC': ('CH0', 'CH1', 'CH2', 'CH3') } @@ -44,6 +44,7 @@ class AF: def print(self): print (' AF({:16s}, {:4d}, {:8s}, {:4d}, {:8s}), // {}'.format(self.name, self.idx, self.fn, self.unit, self.type, self.name)) + class Pin: """Holds the information associated with a pin.""" def __init__(self, name, port, gpio_bit, pin_num): diff --git a/cc3200/misc/mperror.c b/cc3200/misc/mperror.c index 73a6b6fc14..5561b03056 100644 --- a/cc3200/misc/mperror.c +++ b/cc3200/misc/mperror.c @@ -196,6 +196,10 @@ void nlr_jump_fail(void *val) { void mperror_enable_heartbeat (bool enable) { if (enable) { + #ifndef BOOTLOADER + // configure the led again + pin_config ((pin_obj_t *)&MICROPY_SYS_LED_GPIO, PIN_MODE_0, GPIO_DIR_MODE_OUT, PIN_TYPE_STD, 0, PIN_STRENGTH_6MA); + #endif mperror_heart_beat.enabled = true; mperror_heart_beat.do_disable = false; mperror_heartbeat_switch_off(); diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c index a8a19a1bd5..ce304404b5 100644 --- a/cc3200/mods/pybpin.c +++ b/cc3200/mods/pybpin.c @@ -60,7 +60,6 @@ DECLARE PRIVATE FUNCTIONS STATIC pin_obj_t *pin_find_named_pin(const mp_obj_dict_t *named_pins, mp_obj_t name); STATIC pin_obj_t *pin_find_pin_by_port_bit (const mp_obj_dict_t *named_pins, uint port, uint bit); STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type); -STATIC int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type); STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type); STATIC void pin_deassign (pin_obj_t* pin); STATIC void pin_obj_configure (const pin_obj_t *self); @@ -199,6 +198,14 @@ uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit) nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); } +int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) { + int8_t af = pin_obj_find_af(pin, fn, unit, type); + if (af < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + } + return af; +} + /****************************************************************************** DEFINE PRIVATE FUNCTIONS ******************************************************************************/ @@ -231,14 +238,6 @@ STATIC int8_t pin_obj_find_af (const pin_obj_t* pin, uint8_t fn, uint8_t unit, u return -1; } -STATIC int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) { - int8_t af = pin_obj_find_af(pin, fn, unit, type); - if (af < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); - } - return af; -} - STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type) { mp_map_t *named_map = mp_obj_dict_get_map((mp_obj_t)&pin_board_pins_locals_dict); for (uint i = 0; i < named_map->used - 1; i++) { @@ -248,7 +247,7 @@ STATIC void pin_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type) { // check if the pin supports the target af int af = pin_obj_find_af(pin, fn, unit, type); if (af > 0 && af == pin->af) { - // the pin is assigned to the target af, de-assign it + // the pin supports the target af, de-assign it pin_deassign (pin); } } diff --git a/cc3200/mods/pybpin.h b/cc3200/mods/pybpin.h index 3e7784926f..ad02cc777a 100644 --- a/cc3200/mods/pybpin.h +++ b/cc3200/mods/pybpin.h @@ -72,10 +72,7 @@ enum { }; enum { - PIN_TYPE_TIM_PWM0 = 0, - PIN_TYPE_TIM_PWM1, - PIN_TYPE_TIM_CC0, - PIN_TYPE_TIM_CC1, + PIN_TYPE_TIM_PWM = 0, }; enum { @@ -139,5 +136,6 @@ pin_obj_t *pin_find(mp_obj_t user_obj); void pin_assign_pins_af (mp_obj_t *pins, uint32_t n_pins, uint32_t pull, uint32_t fn, uint32_t unit); uint8_t pin_find_peripheral_unit (const mp_obj_t pin, uint8_t fn, uint8_t type); uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit); +int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type);; #endif // PYBPIN_H_ diff --git a/cc3200/mods/pybtimer.c b/cc3200/mods/pybtimer.c index 9220487ebe..048b1795fc 100644 --- a/cc3200/mods/pybtimer.c +++ b/cc3200/mods/pybtimer.c @@ -43,7 +43,10 @@ #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" @@ -55,30 +58,8 @@ /// 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, +/// event, and the counter resets back to zero. By using the irq 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 3 -/// 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(1, mode=Timer.PWM) # initialize it in PWM mode -/// tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the event counter with a frequency of 1Hz and triggered by positive edges -/// tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle -/// 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 -/// tim_ch.period(2000000) # change the period to 2 seconds -/// /****************************************************************************** DECLARE PRIVATE CONSTANTS @@ -89,7 +70,6 @@ #define PYBTIMER_TIMEOUT_TRIGGER (0x01) #define PYBTIMER_MATCH_TRIGGER (0x02) -#define PYBTIMER_EVENT_TRIGGER (0x04) #define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ @@ -112,8 +92,8 @@ typedef struct _pyb_timer_channel_obj_t { uint32_t frequency; uint32_t period; uint16_t channel; + uint16_t duty_cycle; uint8_t polarity; - uint8_t duty_cycle; } pyb_timer_channel_obj_t; /****************************************************************************** @@ -125,6 +105,7 @@ STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_B {.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 @@ -231,9 +212,13 @@ STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t // check limit values for the duty cycle if (ch->duty_cycle == 0) { *match_out = period_c - 1; - } - else { - *match_out = period_c - ((period_c * ch->duty_cycle) / 100); + } 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; @@ -304,31 +289,12 @@ STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_ case TIMER_CFG_A_PERIODIC_UP: 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 + 1), mode_qst); } -/// \method init(mode, *, width) -/// Initialise the timer. Initialisation must give the desired mode -/// and an optional timer width -/// -/// tim.init(mode=Timer.ONE_SHOT, width=32) # one shot mode -/// tim.init(mode=Timer.PERIODIC) # configure in free running periodic mode -/// split 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, }, @@ -341,8 +307,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co // 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_CAP_COUNT && - _mode != TIMER_CFG_A_CAP_TIME && _mode != TIMER_CFG_A_PWM) { + if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_PWM) { goto error; } @@ -368,11 +333,7 @@ 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 1 to 4 -STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { +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); @@ -395,15 +356,11 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_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); @@ -411,24 +368,6 @@ STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit); -/// \method channel(channel, *, freq, period, 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. -/// - `period` - specifies the period in microseconds. -/// - `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. -/// - `duty_cycle` - sets the duty cycle value -/// 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} }, @@ -490,10 +429,22 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp ch->frequency = args[0].u_int; ch->period = args[1].u_int; ch->polarity = args[2].u_int; - ch->duty_cycle = MIN(100, MAX(0, args[3].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); @@ -515,14 +466,11 @@ STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_B), MP_OBJ_NEW_SMALL_INT(TIMER_B) }, { MP_OBJ_NEW_QSTR(MP_QSTR_ONE_SHOT), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_ONE_SHOT_UP) }, { MP_OBJ_NEW_QSTR(MP_QSTR_PERIODIC), MP_OBJ_NEW_SMALL_INT(TIMER_CFG_A_PERIODIC_UP) }, - { 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) }, { MP_OBJ_NEW_QSTR(MP_QSTR_TIMEOUT), MP_OBJ_NEW_SMALL_INT(PYBTIMER_TIMEOUT_TRIGGER) }, { MP_OBJ_NEW_QSTR(MP_QSTR_MATCH), MP_OBJ_NEW_SMALL_INT(PYBTIMER_MATCH_TRIGGER) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_EVENT), MP_OBJ_NEW_SMALL_INT(PYBTIMER_EVENT_TRIGGER) }, }; STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table); @@ -610,14 +558,12 @@ STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, m break; } if (mode == TIMER_CFG_A_PWM) { - mp_printf(print, ", %q=%u", MP_QSTR_duty_cycle, ch->duty_cycle); + mp_printf(print, ", %q=%u.%02u", MP_QSTR_duty_cycle, ch->duty_cycle / 100, ch->duty_cycle % 100); } } 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) { @@ -637,8 +583,6 @@ STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_freq_obj, 1, 2, pyb_timer_channel_freq); -/// \method period([value]) -/// get or set the period of the timer channel in microseconds STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args) { pyb_timer_channel_obj_t *ch = args[0]; if (n_args == 1) { @@ -658,59 +602,6 @@ STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args) } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_period_obj, 1, 2, pyb_timer_channel_period); -/// \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_c; - uint32_t match; - (void)compute_prescaler_period_and_match_value(ch, &period_c, &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 - uint32_t time_t = (1000 * value) / period_c; - return mp_obj_new_int((time_t * 1000) / ch->frequency); - } else { - // set - value = (mp_obj_get_int(args[1]) * ((ch->frequency * period_c) / 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_c - 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_c; - uint32_t match; - (void)compute_prescaler_period_and_match_value(ch, &period_c, &match); - uint32_t value = MAP_TimerValueGet(ch->timer->timer, ch->channel == (TIMER_A | TIMER_B) ? TIMER_A : ch->channel); - uint32_t time_t = (1000 * value) / period_c; - 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) { @@ -721,7 +612,7 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a // calculate the period, the prescaler and the match value uint32_t period_c; uint32_t match; - ch->duty_cycle = MIN(100, MAX(0, mp_obj_get_int(args[1]))); + 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 @@ -735,7 +626,6 @@ STATIC mp_obj_t pyb_timer_channel_duty_cycle(mp_uint_t n_args, const mp_obj_t *a } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle); -/// \method irq(trigger, priority, handler, wake) STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_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); @@ -766,18 +656,6 @@ STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_arg goto invalid_args; } break; - case TIMER_CFG_A_CAP_COUNT: - ch->timer->irq_trigger |= TIMER_CAPA_MATCH << shift; - if (trigger != PYBTIMER_MATCH_TRIGGER) { - goto invalid_args; - } - break; - case TIMER_CFG_A_CAP_TIME: - ch->timer->irq_trigger |= TIMER_CAPA_EVENT << shift; - if (trigger != PYBTIMER_EVENT_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; @@ -855,9 +733,6 @@ 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_period), (mp_obj_t)&pyb_timer_channel_period_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_irq), (mp_obj_t)&pyb_timer_channel_irq_obj }, }; diff --git a/cc3200/qstrdefsport.h b/cc3200/qstrdefsport.h index 9a461d812c..2bd7daa118 100644 --- a/cc3200/qstrdefsport.h +++ b/cc3200/qstrdefsport.h @@ -365,21 +365,15 @@ Q(width) Q(channel) Q(polarity) Q(duty_cycle) -Q(time) -Q(event_count) -Q(event_time) Q(A) Q(B) Q(ONE_SHOT) Q(PERIODIC) -Q(EDGE_COUNT) -Q(EDGE_TIME) Q(PWM) Q(POSITIVE) Q(NEGATIVE) Q(TIMEOUT) Q(MATCH) -Q(EVENT) // for uhashlib module //Q(uhashlib) diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst index 8464c7b369..751f6536a7 100644 --- a/docs/library/machine.Timer.rst +++ b/docs/library/machine.Timer.rst @@ -5,11 +5,6 @@ class Timer -- control internal timers .. only:: port_wipy - .. note:: - - Contrary with the rest of the API, timer IDs start at 1, not a t zero. This is because - the ``Timer`` API is still provisional. A new MicroPython wide API will come soon. - Timers can be used for a great variety of tasks, calling a function periodically, counting events, and generating a PWM signal are among the most common use cases. Each timer consists of 2 16-bit channels and this channels can be tied together to @@ -20,40 +15,39 @@ class Timer -- control internal timers Example usage to toggle an LED at a fixed frequency:: from machine import Timer - tim = Timer(4) # create a timer object using timer 4 + from machine import Pin + led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED + tim = Timer(3) # create a timer object using timer 3 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 + tim_ch = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz + tim_ch.irq(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer Example using named function for the callback:: from machine import Timer - tim = Timer(1, mode=Timer.PERIODIC) - tim_a = tim.channel(Timer.A, freq=1000) + from machine import Pin + tim = Timer(1, mode=Timer.PERIODIC, width=32) + tim_a = tim.channel(Timer.A | Timer.B, freq=1) # 1 Hz frequency requires a 32 bit timer - led = Pin('GPIO2', mode=Pin.OUT) + led = Pin('GP16', mode=Pin.OUT) # enable GP16 as output to drive the LED def tick(timer): # we will receive the timer object when being called print(timer.time()) # show current timer's time value (is microseconds) led.toggle() # toggle the LED - tim_a.callback(handler=tick) + tim_a.irq(handler=tick) # create the interrupt Further examples:: from machine import Timer - tim1 = Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode - tim2 = Timer(1, mode=Timer.PWM) # initialize it in PWM mode - tim_ch = tim1.channel(Timer.A, freq=1, polarity=Timer.POSITIVE) # start the event counter with a frequency of 1Hz and triggered by positive edges - tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle - 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 - tim_ch.period(2000000) # change the period to 2 seconds - + tim1 = Timer(2, mode=Timer.ONE_SHOT) # initialize it in one shot mode + tim2 = Timer(1, mode=Timer.PWM) # initialize it in PWM mode + tim1_ch = tim1.channel(Timer.A, freq=10, polarity=Timer.POSITIVE) # start the event counter with a frequency of 10Hz and triggered by positive edges + tim2_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle + tim2_ch.freq(20) # set the frequency (can also get) + tim2_ch.duty_cycle(30) # set the duty cycle to 30% (can also get) + tim2_ch.duty_cycle(30, Timer.NEGATIVE) # set the duty cycle to 30% and change the polarity to negative + tim2_ch.period(2000000) # change the period to 2 seconds .. note:: @@ -69,9 +63,7 @@ Constructors .. only:: port_wipy - Construct a new timer object of the given id. If additional - arguments are given, then the timer is initialised by ``init(...)``. - ``id`` can be 1 to 4. + Construct a new timer object of the given id. ``id`` can take values from 0 to 3. Methods @@ -94,10 +86,9 @@ Methods period of the channel expires. - ``Timer.PERIODIC`` - The timer runs periodically at the configured frequency of the channel. - - ``Timer.EDGE_TIME`` - Meaure the time pin level changes. - - ``Timer.EDGE_COUNT`` - Count the number of pin level changes. + - ``Timer.PWM`` - Output a PWM signal on a pin. - - ``width`` must be either 16 or 32 (bits). For really low frequencies <= ~1Hz + - ``width`` must be either 16 or 32 (bits). For really low frequencies < 5Hz (or large periods), 32-bit timers should be used. 32-bit mode is only available for ``ONE_SHOT`` AND ``PERIODIC`` modes. @@ -112,7 +103,7 @@ Methods If only a channel identifier passed, then a previously initialized channel object is returned (or ``None`` if there is no previous channel). - + Othwerwise, a TimerChannel object is initialized and returned. The operating mode is is the one configured to the Timer object that was used to @@ -130,12 +121,11 @@ Methods Either ``freq`` or ``period`` must be given, never both. - - ``polarity`` this is applicable for: - - - ``PWM``, defines the polarity of the duty cycle - - ``EDGE_TIME`` and ``EDGE_COUNT``, defines the polarity of the pin level change to detect. - To detect both rising and falling edges, make ``polarity=Timer.POSITIVE | Timer.NEGATIVE``. - - ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0-100) + - ``polarity`` this is applicable for ``PWM``, and defines the polarity of the duty cycle + - ``duty_cycle`` only applicable to ``PWM``. It's a percentage (0.00-100.00). Since the WiPy + doesn't support floating point numbers the duty cycle must be specified in the range 0-10000, + where 10000 would represent 100.00, 5050 represents 50.50, and so on. + class TimerChannel --- setup a channel for a timer ================================================== @@ -166,31 +156,47 @@ Methods - ``priority`` level of the interrupt. Can take values in the range 1-7. Higher values represent higher priorities. - ``handler`` is an optional function to be called when the interrupt is triggered. + - ``trigger`` must be ``Timer.TIMEOUT`` when the operating mode is either ``Timer.PERIODIC`` or + ``Timer.ONE_SHOT``. In the case that mode is ``Timer.PWM`` then trigger must be equal to + ``Timer.MATCH``. Returns a callback object. .. only:: port_wipy .. method:: timerchannel.freq([value]) - + Get or set the timer channel frequency (in Hz). .. method:: timerchannel.period([value]) Get or set the timer channel period (in microseconds). - - .. method:: timerchannel.time([value]) - - Get or set the timer channel current **time** value (in microseconds). - - .. method:: timerchannel.event_count() - - Get the number of edge events counted. - - .. method:: timerchannel.event_time() - - Get the time of ocurrance of the last event. .. method:: timerchannel.duty_cycle([value]) - + Get or set the duty cycle of the PWM signal (in the range of 0-100). + +Constants +--------- + +.. data:: Timer.ONE_SHOT +.. data:: Timer.PERIODIC +.. data:: Timer.PWM + + Selects the timer operating mode. + +.. data:: Timer.A +.. data:: Timer.B + + Selects the timer channel. Must be ORed (``Timer.A`` | ``Timer.B``) when + using a 32-bit timer. + +.. data:: Timer.POSITIVE +.. data:: Timer.NEGATIVE + + Timer channel polarity selection (only relevant in PWM mode). + +.. data:: Timer.TIMEOUT +.. data:: Timer.MATCH + + Timer channel IRQ triggers. diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst index a30eec2aae..6c2cf0de7c 100644 --- a/docs/wipy/quickref.rst +++ b/docs/wipy/quickref.rst @@ -49,10 +49,10 @@ See :ref:`machine.Timer ` and :ref:`machine.Pin `. : from machine import Timer from machine import Pin - tim = Timer(1, mode=Timer.PERIODIC) + tim = Timer(0, mode=Timer.PERIODIC) tim_a = tim.channel(Timer.A, freq=1000) tim_a.time() # get the value in microseconds - tim_a.freq(1) # 1 Hz + tim_a.freq(5) # 5 Hz p_out = Pin('GP2', mode=Pin.OUT) tim_a.irq(handler=lambda t: p_out.toggle())