cc3200: Simplify the Timer API and correct the documents.
Make the PWM duty cycle configurable from 0.00 to 100.00 by accepting values from 0 to 10000. Add automatic Pin assignment when operating in PWM mode.
This commit is contained in:
parent
562bcffd3a
commit
73c9f85b4c
|
@ -1,11 +1,11 @@
|
||||||
Pin,Name,Default,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15,ADC
|
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,,,,
|
1,GP10,GP10,GP10,I2C0_SCL,,TIM3_PWM,,,SD0_CLK,UART1_TX,,,,,TIM0_CC,,,,
|
||||||
2,GP11,GP11,GP11,I2C0_SDA,,TIM3_PWM1,pXCLK(XVCLK),,SD0_CMD,UART1_RX,,,,,TIM1_CC0,I2S0_FS,,,
|
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_CC1,,,,
|
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_CC0,,,,
|
4,GP13,GP13,GP13,,,,pHS(HSYNC),I2C0_SDA,,UART0_RX,,,,,TIM2_CC,,,,
|
||||||
5,GP14,GP14,GP14,,,,pDATA8(CAM_D4),I2C0_SCL,,SPI0_CLK,,,,,TIM2_CC1,,,,
|
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_CC0,,,
|
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_CC1,,,
|
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,,,,,,,,
|
8,GP17,GP17,GP17,,,,pDATA11(CAM_D7),UART1_RX,,SPI0_CS0,SD0_CMD,,,,,,,,
|
||||||
9,VDD_DIG1,VDD_DIG1,VDD_DIG1,,,,,,,,,,,,,,,,
|
9,VDD_DIG1,VDD_DIG1,VDD_DIG1,,,,,,,,,,,,,,,,
|
||||||
10,VIN_IO1,VIN_IO1,VIN_IO1,,,,,,,,,,,,,,,,
|
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,,,,,,,,,,,,,,,,
|
12,FLASH_SPI_DOUT,FLASH_SPI_DOUT,FLASH_SPI_DOUT,,,,,,,,,,,,,,,,
|
||||||
13,FLASH_SPI_DIN,FLASH_SPI_DIN,FLASH_SPI_DIN,,,,,,,,,,,,,,,,
|
13,FLASH_SPI_DIN,FLASH_SPI_DIN,FLASH_SPI_DIN,,,,,,,,,,,,,,,,
|
||||||
14,FLASH_SPI_CS,FLASH_SPI_CS,FLASH_SPI_CS,,,,,,,,,,,,,,,,
|
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,,,,,,,
|
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,,,,,,,,,,,,,,,,
|
18,GP28,GP28,GP28,,,,,,,,,,,,,,,,
|
||||||
19,TCK,TCK,,TCK,,,,,,,TIM1_PWM2,,,,,,,,
|
19,TCK,TCK,,TCK,,,,,,,TIM1_PWM,,,,,,,,
|
||||||
20,GP29,TMS,GP29,TMS,,,,,,,,,,,,,,,
|
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,,,,,,,,,,,,,,,,
|
22,WLAN_XTAL_N,WLAN_XTAL_N,WLAN_XTAL_N,,,,,,,,,,,,,,,,
|
||||||
23,WLAN_XTAL_P,WLAN_XTAL_P,WLAN_XTAL_P,,,,,,,,,,,,,,,,
|
23,WLAN_XTAL_P,WLAN_XTAL_P,WLAN_XTAL_P,,,,,,,,,,,,,,,,
|
||||||
24,VDD_PLL,VDD_PLL,VDD_PLL,,,,,,,,,,,,,,,,
|
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,,,,,,,,,,,,,,,,
|
47,VDD_ANA2,VDD_ANA2,VDD_ANA2,,,,,,,,,,,,,,,,
|
||||||
48,VDD_ANA1,VDD_ANA1,VDD_ANA1,,,,,,,,,,,,,,,,
|
48,VDD_ANA1,VDD_ANA1,VDD_ANA1,,,,,,,,,,,,,,,,
|
||||||
49,VDD_RAM,VDD_RAM,VDD_RAM,,,,,,,,,,,,,,,,
|
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,,,,,,,,,,,,,,,,
|
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,,,,,,,,
|
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,,,,,,,,,,,,,,,,
|
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,,,,,,,,,,,,,,,,
|
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
|
58,GP3,GP3,GP3,,,,pDATA7(CAM_D3),,UART1_TX,,,,,,,,,,ADC0_CH1
|
||||||
59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC0_CH2
|
59,GP4,GP4,GP4,,,,pDATA6(CAM_D2),,UART1_RX,,,,,,,,,,ADC0_CH2
|
||||||
60,GP5,GP5,GP5,,,,pDATA5(CAM_D1),,I2S0_DAT1,TIM2_CC1,,,,,,,,,ADC0_CH3
|
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_CC0,,,,,,,,,
|
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,,,
|
62,GP7,GP7,GP7,,,UART1_RTS,,,,,,,UART0_RTS,UART0_TX,,I2S0_CLK,,,
|
||||||
63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC0,,,,
|
63,GP8,GP8,GP8,,,,,,SD0_IRQ,I2S0_FS,,,,,TIM3_CC,,,,
|
||||||
64,GP9,GP9,GP9,,,TIM2_PWM1,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC0,,,,
|
64,GP9,GP9,GP9,,,TIM2_PWM,,,SD0_DAT0,I2S0_DAT0,,,,,TIM0_CC,,,,
|
||||||
65,GND_TAB,GND_TAB,GND_TAB,,,,,,,,,,,,,,,,
|
65,GND_TAB,GND_TAB,GND_TAB,,,,,,,,,,,,,,,,
|
||||||
|
|
|
|
@ -12,7 +12,7 @@ SUPPORTED_AFS = { 'UART': ('TX', 'RX', 'RTS', 'CTS'),
|
||||||
'SPI': ('CLK', 'MOSI', 'MISO', 'CS0'),
|
'SPI': ('CLK', 'MOSI', 'MISO', 'CS0'),
|
||||||
#'I2S': ('CLK', 'FS', 'DAT0', 'DAT1'),
|
#'I2S': ('CLK', 'FS', 'DAT0', 'DAT1'),
|
||||||
'I2C': ('SDA', 'SCL'),
|
'I2C': ('SDA', 'SCL'),
|
||||||
'TIM': ('PWM0', 'PWM1', 'CC0', 'CC1'),
|
'TIM': ('PWM'),
|
||||||
'SD': ('CLK', 'CMD', 'DAT0'),
|
'SD': ('CLK', 'CMD', 'DAT0'),
|
||||||
'ADC': ('CH0', 'CH1', 'CH2', 'CH3')
|
'ADC': ('CH0', 'CH1', 'CH2', 'CH3')
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ class AF:
|
||||||
def print(self):
|
def print(self):
|
||||||
print (' AF({:16s}, {:4d}, {:8s}, {:4d}, {:8s}), // {}'.format(self.name, self.idx, self.fn, self.unit, self.type, self.name))
|
print (' AF({:16s}, {:4d}, {:8s}, {:4d}, {:8s}), // {}'.format(self.name, self.idx, self.fn, self.unit, self.type, self.name))
|
||||||
|
|
||||||
|
|
||||||
class Pin:
|
class Pin:
|
||||||
"""Holds the information associated with a pin."""
|
"""Holds the information associated with a pin."""
|
||||||
def __init__(self, name, port, gpio_bit, pin_num):
|
def __init__(self, name, port, gpio_bit, pin_num):
|
||||||
|
|
|
@ -196,6 +196,10 @@ void nlr_jump_fail(void *val) {
|
||||||
|
|
||||||
void mperror_enable_heartbeat (bool enable) {
|
void mperror_enable_heartbeat (bool enable) {
|
||||||
if (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.enabled = true;
|
||||||
mperror_heart_beat.do_disable = false;
|
mperror_heart_beat.do_disable = false;
|
||||||
mperror_heartbeat_switch_off();
|
mperror_heartbeat_switch_off();
|
||||||
|
|
|
@ -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_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 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_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_free_af_from_pins (uint8_t fn, uint8_t unit, uint8_t type);
|
||||||
STATIC void pin_deassign (pin_obj_t* pin);
|
STATIC void pin_deassign (pin_obj_t* pin);
|
||||||
STATIC void pin_obj_configure (const pin_obj_t *self);
|
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));
|
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
|
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;
|
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) {
|
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);
|
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++) {
|
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
|
// check if the pin supports the target af
|
||||||
int af = pin_obj_find_af(pin, fn, unit, type);
|
int af = pin_obj_find_af(pin, fn, unit, type);
|
||||||
if (af > 0 && af == pin->af) {
|
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);
|
pin_deassign (pin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,10 +72,7 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
PIN_TYPE_TIM_PWM0 = 0,
|
PIN_TYPE_TIM_PWM = 0,
|
||||||
PIN_TYPE_TIM_PWM1,
|
|
||||||
PIN_TYPE_TIM_CC0,
|
|
||||||
PIN_TYPE_TIM_CC1,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
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);
|
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_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);
|
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_
|
#endif // PYBPIN_H_
|
||||||
|
|
|
@ -43,7 +43,10 @@
|
||||||
#include "interrupt.h"
|
#include "interrupt.h"
|
||||||
#include "prcm.h"
|
#include "prcm.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "pin.h"
|
||||||
#include "pybtimer.h"
|
#include "pybtimer.h"
|
||||||
|
#include "pybpin.h"
|
||||||
|
#include "pins.h"
|
||||||
#include "mpirq.h"
|
#include "mpirq.h"
|
||||||
#include "pybsleep.h"
|
#include "pybsleep.h"
|
||||||
#include "mpexception.h"
|
#include "mpexception.h"
|
||||||
|
@ -55,30 +58,8 @@
|
||||||
/// Each timer consists of a counter that counts up at a certain rate. The rate
|
/// 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
|
/// 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
|
/// 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.
|
/// 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
|
DECLARE PRIVATE CONSTANTS
|
||||||
|
@ -89,7 +70,6 @@
|
||||||
|
|
||||||
#define PYBTIMER_TIMEOUT_TRIGGER (0x01)
|
#define PYBTIMER_TIMEOUT_TRIGGER (0x01)
|
||||||
#define PYBTIMER_MATCH_TRIGGER (0x02)
|
#define PYBTIMER_MATCH_TRIGGER (0x02)
|
||||||
#define PYBTIMER_EVENT_TRIGGER (0x04)
|
|
||||||
|
|
||||||
#define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
|
#define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
|
||||||
|
|
||||||
|
@ -112,8 +92,8 @@ typedef struct _pyb_timer_channel_obj_t {
|
||||||
uint32_t frequency;
|
uint32_t frequency;
|
||||||
uint32_t period;
|
uint32_t period;
|
||||||
uint16_t channel;
|
uint16_t channel;
|
||||||
|
uint16_t duty_cycle;
|
||||||
uint8_t polarity;
|
uint8_t polarity;
|
||||||
uint8_t duty_cycle;
|
|
||||||
} pyb_timer_channel_obj_t;
|
} 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 = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
|
||||||
{.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}};
|
{.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}};
|
||||||
STATIC const mp_obj_type_t pyb_timer_channel_type;
|
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
|
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
|
// check limit values for the duty cycle
|
||||||
if (ch->duty_cycle == 0) {
|
if (ch->duty_cycle == 0) {
|
||||||
*match_out = period_c - 1;
|
*match_out = period_c - 1;
|
||||||
}
|
} else {
|
||||||
else {
|
if (period_c > 0xFFFF) {
|
||||||
*match_out = period_c - ((period_c * ch->duty_cycle) / 100);
|
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;
|
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:
|
case TIMER_CFG_A_PERIODIC_UP:
|
||||||
mode_qst = MP_QSTR_PERIODIC;
|
mode_qst = MP_QSTR_PERIODIC;
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mp_printf(print, "Timer(%u, mode=Timer.%q)", (tim->id + 1), mode_qst);
|
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 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[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
|
{ 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
|
// check the mode
|
||||||
uint32_t _mode = args[0].u_int;
|
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 &&
|
if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_PWM) {
|
||||||
_mode != TIMER_CFG_A_CAP_TIME && _mode != TIMER_CFG_A_PWM) {
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,11 +333,7 @@ error:
|
||||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \classmethod \constructor(id, ...)
|
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) {
|
||||||
/// 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) {
|
|
||||||
// check arguments
|
// check arguments
|
||||||
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
|
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;
|
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) {
|
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);
|
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_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) {
|
STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
|
||||||
pyb_timer_obj_t *self = self_in;
|
pyb_timer_obj_t *self = self_in;
|
||||||
timer_disable(self);
|
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);
|
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 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[] = {
|
static const mp_arg_t allowed_args[] = {
|
||||||
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
{ 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->frequency = args[0].u_int;
|
||||||
ch->period = args[1].u_int;
|
ch->period = args[1].u_int;
|
||||||
ch->polarity = args[2].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);
|
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
|
// add the timer to the list
|
||||||
pyb_timer_channel_add(ch);
|
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_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_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_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_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_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_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_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_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);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (mode == TIMER_CFG_A_PWM) {
|
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, ")");
|
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) {
|
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];
|
pyb_timer_channel_obj_t *ch = args[0];
|
||||||
if (n_args == 1) {
|
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);
|
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) {
|
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];
|
pyb_timer_channel_obj_t *ch = args[0];
|
||||||
if (n_args == 1) {
|
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);
|
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) {
|
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];
|
pyb_timer_channel_obj_t *ch = args[0];
|
||||||
if (n_args == 1) {
|
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
|
// calculate the period, the prescaler and the match value
|
||||||
uint32_t period_c;
|
uint32_t period_c;
|
||||||
uint32_t match;
|
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);
|
compute_prescaler_period_and_match_value(ch, &period_c, &match);
|
||||||
if (n_args == 3) {
|
if (n_args == 3) {
|
||||||
// set the new polarity if requested
|
// 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);
|
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) {
|
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_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);
|
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;
|
goto invalid_args;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case TIMER_CFG_A_PWM:
|
||||||
// special case for the PWM match interrupt
|
// special case for the PWM match interrupt
|
||||||
ch->timer->irq_trigger |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
|
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
|
// instance methods
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_timer_channel_freq_obj },
|
{ 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_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_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 },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_irq), (mp_obj_t)&pyb_timer_channel_irq_obj },
|
||||||
};
|
};
|
||||||
|
|
|
@ -365,21 +365,15 @@ Q(width)
|
||||||
Q(channel)
|
Q(channel)
|
||||||
Q(polarity)
|
Q(polarity)
|
||||||
Q(duty_cycle)
|
Q(duty_cycle)
|
||||||
Q(time)
|
|
||||||
Q(event_count)
|
|
||||||
Q(event_time)
|
|
||||||
Q(A)
|
Q(A)
|
||||||
Q(B)
|
Q(B)
|
||||||
Q(ONE_SHOT)
|
Q(ONE_SHOT)
|
||||||
Q(PERIODIC)
|
Q(PERIODIC)
|
||||||
Q(EDGE_COUNT)
|
|
||||||
Q(EDGE_TIME)
|
|
||||||
Q(PWM)
|
Q(PWM)
|
||||||
Q(POSITIVE)
|
Q(POSITIVE)
|
||||||
Q(NEGATIVE)
|
Q(NEGATIVE)
|
||||||
Q(TIMEOUT)
|
Q(TIMEOUT)
|
||||||
Q(MATCH)
|
Q(MATCH)
|
||||||
Q(EVENT)
|
|
||||||
|
|
||||||
// for uhashlib module
|
// for uhashlib module
|
||||||
//Q(uhashlib)
|
//Q(uhashlib)
|
||||||
|
|
|
@ -5,11 +5,6 @@ class Timer -- control internal timers
|
||||||
|
|
||||||
.. only:: port_wipy
|
.. 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,
|
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.
|
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
|
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::
|
Example usage to toggle an LED at a fixed frequency::
|
||||||
|
|
||||||
from machine import Timer
|
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.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 = tim.channel(Timer.A, freq=5) # configure channel A at a frequency of 5Hz
|
||||||
tim_ch.callback(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
|
tim_ch.irq(handler=lambda t:led.toggle()) # toggle a LED on every cycle of the timer
|
||||||
|
|
||||||
Example using named function for the callback::
|
Example using named function for the callback::
|
||||||
|
|
||||||
from machine import Timer
|
from machine import Timer
|
||||||
tim = Timer(1, mode=Timer.PERIODIC)
|
from machine import Pin
|
||||||
tim_a = tim.channel(Timer.A, freq=1000)
|
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
|
def tick(timer): # we will receive the timer object when being called
|
||||||
print(timer.time()) # show current timer's time value (is microseconds)
|
print(timer.time()) # show current timer's time value (is microseconds)
|
||||||
led.toggle() # toggle the LED
|
led.toggle() # toggle the LED
|
||||||
|
|
||||||
tim_a.callback(handler=tick)
|
tim_a.irq(handler=tick) # create the interrupt
|
||||||
|
|
||||||
Further examples::
|
Further examples::
|
||||||
|
|
||||||
from machine import Timer
|
from machine import Timer
|
||||||
tim1 = Timer(2, mode=Timer.EVENT_COUNT) # initialize it capture mode
|
tim1 = Timer(2, mode=Timer.ONE_SHOT) # initialize it in one shot mode
|
||||||
tim2 = Timer(1, mode=Timer.PWM) # initialize it in PWM 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
|
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
|
||||||
tim_ch = tim2.channel(Timer.B, freq=10000, duty_cycle=50) # start the PWM on channel B with a 50% duty cycle
|
tim2_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)
|
tim2_ch.freq(20) # set the frequency (can also get)
|
||||||
tim_ch.freq(20) # set the frequency (can also get)
|
tim2_ch.duty_cycle(30) # set the duty cycle to 30% (can also get)
|
||||||
tim_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
|
||||||
tim_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
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -69,9 +63,7 @@ Constructors
|
||||||
|
|
||||||
.. only:: port_wipy
|
.. only:: port_wipy
|
||||||
|
|
||||||
Construct a new timer object of the given id. If additional
|
Construct a new timer object of the given id. ``id`` can take values from 0 to 3.
|
||||||
arguments are given, then the timer is initialised by ``init(...)``.
|
|
||||||
``id`` can be 1 to 4.
|
|
||||||
|
|
||||||
|
|
||||||
Methods
|
Methods
|
||||||
|
@ -94,10 +86,9 @@ Methods
|
||||||
period of the channel expires.
|
period of the channel expires.
|
||||||
- ``Timer.PERIODIC`` - The timer runs periodically at the configured
|
- ``Timer.PERIODIC`` - The timer runs periodically at the configured
|
||||||
frequency of the channel.
|
frequency of the channel.
|
||||||
- ``Timer.EDGE_TIME`` - Meaure the time pin level changes.
|
- ``Timer.PWM`` - Output a PWM signal on a pin.
|
||||||
- ``Timer.EDGE_COUNT`` - Count the number of pin level changes.
|
|
||||||
|
|
||||||
- ``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
|
(or large periods), 32-bit timers should be used. 32-bit mode is only available
|
||||||
for ``ONE_SHOT`` AND ``PERIODIC`` modes.
|
for ``ONE_SHOT`` AND ``PERIODIC`` modes.
|
||||||
|
|
||||||
|
@ -130,12 +121,11 @@ Methods
|
||||||
|
|
||||||
Either ``freq`` or ``period`` must be given, never both.
|
Either ``freq`` or ``period`` must be given, never both.
|
||||||
|
|
||||||
- ``polarity`` this is applicable for:
|
- ``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.
|
||||||
|
|
||||||
- ``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)
|
|
||||||
|
|
||||||
class TimerChannel --- setup a channel for a timer
|
class TimerChannel --- setup a channel for a timer
|
||||||
==================================================
|
==================================================
|
||||||
|
@ -166,6 +156,9 @@ Methods
|
||||||
- ``priority`` level of the interrupt. Can take values in the range 1-7.
|
- ``priority`` level of the interrupt. Can take values in the range 1-7.
|
||||||
Higher values represent higher priorities.
|
Higher values represent higher priorities.
|
||||||
- ``handler`` is an optional function to be called when the interrupt is triggered.
|
- ``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.
|
Returns a callback object.
|
||||||
|
|
||||||
|
@ -179,18 +172,31 @@ Methods
|
||||||
|
|
||||||
Get or set the timer channel period (in microseconds).
|
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])
|
.. method:: timerchannel.duty_cycle([value])
|
||||||
|
|
||||||
Get or set the duty cycle of the PWM signal (in the range of 0-100).
|
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.
|
||||||
|
|
|
@ -49,10 +49,10 @@ See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`. :
|
||||||
from machine import Timer
|
from machine import Timer
|
||||||
from machine import Pin
|
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 = tim.channel(Timer.A, freq=1000)
|
||||||
tim_a.time() # get the value in microseconds
|
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)
|
p_out = Pin('GP2', mode=Pin.OUT)
|
||||||
tim_a.irq(handler=lambda t: p_out.toggle())
|
tim_a.irq(handler=lambda t: p_out.toggle())
|
||||||
|
|
Loading…
Reference in New Issue