pybtimer.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /*
  2. * This file is part of the MicroPython project, http://micropython.org/
  3. *
  4. * The MIT License (MIT)
  5. *
  6. * Copyright (c) 2013, 2014 Damien P. George
  7. * Copyright (c) 2015 Daniel Campora
  8. *
  9. * Permission is hereby granted, free of charge, to any person obtaining a copy
  10. * of this software and associated documentation files (the "Software"), to deal
  11. * in the Software without restriction, including without limitation the rights
  12. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  13. * copies of the Software, and to permit persons to whom the Software is
  14. * furnished to do so, subject to the following conditions:
  15. *
  16. * The above copyright notice and this permission notice shall be included in
  17. * all copies or substantial portions of the Software.
  18. *
  19. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  24. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  25. * THE SOFTWARE.
  26. */
  27. #include <stdint.h>
  28. #include <stdio.h>
  29. #include <string.h>
  30. #include "py/runtime.h"
  31. #include "py/gc.h"
  32. #include "py/mperrno.h"
  33. #include "py/mphal.h"
  34. #include "inc/hw_types.h"
  35. #include "inc/hw_ints.h"
  36. #include "inc/hw_memmap.h"
  37. #include "inc/hw_timer.h"
  38. #include "rom_map.h"
  39. #include "interrupt.h"
  40. #include "prcm.h"
  41. #include "timer.h"
  42. #include "pin.h"
  43. #include "pybtimer.h"
  44. #include "pybpin.h"
  45. #include "pins.h"
  46. #include "mpirq.h"
  47. #include "pybsleep.h"
  48. #include "mpexception.h"
  49. /// \moduleref pyb
  50. /// \class Timer - generate periodic events, count events, and create PWM signals.
  51. ///
  52. /// Each timer consists of a counter that counts up at a certain rate. The rate
  53. /// at which it counts is the peripheral clock frequency (in Hz) divided by the
  54. /// timer prescaler. When the counter reaches the timer period it triggers an
  55. /// event, and the counter resets back to zero. By using the irq method,
  56. /// the timer event can call a Python function.
  57. /******************************************************************************
  58. DECLARE PRIVATE CONSTANTS
  59. ******************************************************************************/
  60. #define PYBTIMER_NUM_TIMERS (4)
  61. #define PYBTIMER_POLARITY_POS (0x01)
  62. #define PYBTIMER_POLARITY_NEG (0x02)
  63. #define PYBTIMER_TIMEOUT_TRIGGER (0x01)
  64. #define PYBTIMER_MATCH_TRIGGER (0x02)
  65. #define PYBTIMER_SRC_FREQ_HZ HAL_FCPU_HZ
  66. /******************************************************************************
  67. DEFINE PRIVATE TYPES
  68. ******************************************************************************/
  69. typedef struct _pyb_timer_obj_t {
  70. mp_obj_base_t base;
  71. uint32_t timer;
  72. uint32_t config;
  73. uint16_t irq_trigger;
  74. uint16_t irq_flags;
  75. uint8_t peripheral;
  76. uint8_t id;
  77. } pyb_timer_obj_t;
  78. typedef struct _pyb_timer_channel_obj_t {
  79. mp_obj_base_t base;
  80. struct _pyb_timer_obj_t *timer;
  81. uint32_t frequency;
  82. uint32_t period;
  83. uint16_t channel;
  84. uint16_t duty_cycle;
  85. uint8_t polarity;
  86. } pyb_timer_channel_obj_t;
  87. /******************************************************************************
  88. DEFINE PRIVATE DATA
  89. ******************************************************************************/
  90. STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods;
  91. STATIC pyb_timer_obj_t pyb_timer_obj[PYBTIMER_NUM_TIMERS] = {{.timer = TIMERA0_BASE, .peripheral = PRCM_TIMERA0},
  92. {.timer = TIMERA1_BASE, .peripheral = PRCM_TIMERA1},
  93. {.timer = TIMERA2_BASE, .peripheral = PRCM_TIMERA2},
  94. {.timer = TIMERA3_BASE, .peripheral = PRCM_TIMERA3}};
  95. STATIC const mp_obj_type_t pyb_timer_channel_type;
  96. 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};
  97. /******************************************************************************
  98. DECLARE PRIVATE FUNCTIONS
  99. ******************************************************************************/
  100. STATIC mp_obj_t pyb_timer_channel_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
  101. STATIC void timer_disable (pyb_timer_obj_t *tim);
  102. STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch);
  103. STATIC void TIMER0AIntHandler(void);
  104. STATIC void TIMER0BIntHandler(void);
  105. STATIC void TIMER1AIntHandler(void);
  106. STATIC void TIMER1BIntHandler(void);
  107. STATIC void TIMER2AIntHandler(void);
  108. STATIC void TIMER2BIntHandler(void);
  109. STATIC void TIMER3AIntHandler(void);
  110. STATIC void TIMER3BIntHandler(void);
  111. /******************************************************************************
  112. DEFINE PUBLIC FUNCTIONS
  113. ******************************************************************************/
  114. void timer_init0 (void) {
  115. mp_obj_list_init(&MP_STATE_PORT(pyb_timer_channel_obj_list), 0);
  116. }
  117. /******************************************************************************
  118. DEFINE PRIVATE FUNCTIONS
  119. ******************************************************************************/
  120. STATIC void pyb_timer_channel_irq_enable (mp_obj_t self_in) {
  121. pyb_timer_channel_obj_t *self = self_in;
  122. MAP_TimerIntClear(self->timer->timer, self->timer->irq_trigger & self->channel);
  123. MAP_TimerIntEnable(self->timer->timer, self->timer->irq_trigger & self->channel);
  124. }
  125. STATIC void pyb_timer_channel_irq_disable (mp_obj_t self_in) {
  126. pyb_timer_channel_obj_t *self = self_in;
  127. MAP_TimerIntDisable(self->timer->timer, self->timer->irq_trigger & self->channel);
  128. }
  129. STATIC int pyb_timer_channel_irq_flags (mp_obj_t self_in) {
  130. pyb_timer_channel_obj_t *self = self_in;
  131. return self->timer->irq_flags;
  132. }
  133. STATIC pyb_timer_channel_obj_t *pyb_timer_channel_find (uint32_t timer, uint16_t channel_n) {
  134. for (mp_uint_t i = 0; i < MP_STATE_PORT(pyb_timer_channel_obj_list).len; i++) {
  135. pyb_timer_channel_obj_t *ch = ((pyb_timer_channel_obj_t *)(MP_STATE_PORT(pyb_timer_channel_obj_list).items[i]));
  136. // any 32-bit timer must be matched by any of its 16-bit versions
  137. if (ch->timer->timer == timer && ((ch->channel & TIMER_A) == channel_n || (ch->channel & TIMER_B) == channel_n)) {
  138. return ch;
  139. }
  140. }
  141. return MP_OBJ_NULL;
  142. }
  143. STATIC void pyb_timer_channel_remove (pyb_timer_channel_obj_t *ch) {
  144. pyb_timer_channel_obj_t *channel;
  145. if ((channel = pyb_timer_channel_find(ch->timer->timer, ch->channel))) {
  146. mp_obj_list_remove(&MP_STATE_PORT(pyb_timer_channel_obj_list), channel);
  147. // unregister it with the sleep module
  148. pyb_sleep_remove((const mp_obj_t)channel);
  149. }
  150. }
  151. STATIC void pyb_timer_channel_add (pyb_timer_channel_obj_t *ch) {
  152. // remove it in case it already exists
  153. pyb_timer_channel_remove(ch);
  154. mp_obj_list_append(&MP_STATE_PORT(pyb_timer_channel_obj_list), ch);
  155. // register it with the sleep module
  156. pyb_sleep_add((const mp_obj_t)ch, (WakeUpCB_t)timer_channel_init);
  157. }
  158. STATIC void timer_disable (pyb_timer_obj_t *tim) {
  159. // disable all timers and it's interrupts
  160. MAP_TimerDisable(tim->timer, TIMER_A | TIMER_B);
  161. MAP_TimerIntDisable(tim->timer, tim->irq_trigger);
  162. MAP_TimerIntClear(tim->timer, tim->irq_trigger);
  163. pyb_timer_channel_obj_t *ch;
  164. // disable its channels
  165. if ((ch = pyb_timer_channel_find (tim->timer, TIMER_A))) {
  166. pyb_sleep_remove(ch);
  167. }
  168. if ((ch = pyb_timer_channel_find (tim->timer, TIMER_B))) {
  169. pyb_sleep_remove(ch);
  170. }
  171. MAP_PRCMPeripheralClkDisable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
  172. }
  173. // computes prescaler period and match value so timer triggers at freq-Hz
  174. STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t *ch, uint32_t *period_out, uint32_t *match_out) {
  175. uint32_t maxcount = (ch->channel == (TIMER_A | TIMER_B)) ? 0xFFFFFFFF : 0xFFFF;
  176. uint32_t prescaler;
  177. uint32_t period_c = (ch->frequency > 0) ? PYBTIMER_SRC_FREQ_HZ / ch->frequency : ((PYBTIMER_SRC_FREQ_HZ / 1000000) * ch->period);
  178. period_c = MAX(1, period_c) - 1;
  179. if (period_c == 0) {
  180. goto error;
  181. }
  182. prescaler = period_c >> 16; // The prescaler is an extension of the timer counter
  183. *period_out = period_c;
  184. if (prescaler > 0xFF && maxcount == 0xFFFF) {
  185. goto error;
  186. }
  187. // check limit values for the duty cycle
  188. if (ch->duty_cycle == 0) {
  189. *match_out = period_c - 1;
  190. } else {
  191. if (period_c > 0xFFFF) {
  192. uint32_t match = (period_c * 100) / 10000;
  193. *match_out = period_c - ((match * ch->duty_cycle) / 100);
  194. } else {
  195. *match_out = period_c - ((period_c * ch->duty_cycle) / 10000);
  196. }
  197. }
  198. return prescaler;
  199. error:
  200. mp_raise_ValueError(mpexception_value_invalid_arguments);
  201. }
  202. STATIC void timer_init (pyb_timer_obj_t *tim) {
  203. MAP_PRCMPeripheralClkEnable(tim->peripheral, PRCM_RUN_MODE_CLK | PRCM_SLP_MODE_CLK);
  204. MAP_PRCMPeripheralReset(tim->peripheral);
  205. MAP_TimerConfigure(tim->timer, tim->config);
  206. }
  207. STATIC void timer_channel_init (pyb_timer_channel_obj_t *ch) {
  208. // calculate the period, the prescaler and the match value
  209. uint32_t period_c;
  210. uint32_t match;
  211. uint32_t prescaler = compute_prescaler_period_and_match_value(ch, &period_c, &match);
  212. // set the prescaler
  213. MAP_TimerPrescaleSet(ch->timer->timer, ch->channel, (prescaler < 0xFF) ? prescaler : 0);
  214. // set the load value
  215. MAP_TimerLoadSet(ch->timer->timer, ch->channel, period_c);
  216. // configure the pwm if we are in such mode
  217. if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) {
  218. // invert the timer output if required
  219. MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
  220. // set the match value (which is simply the duty cycle translated to ticks)
  221. MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
  222. MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
  223. }
  224. #ifdef DEBUG
  225. // stall the timer when the processor is halted while debugging
  226. MAP_TimerControlStall(ch->timer->timer, ch->channel, true);
  227. #endif
  228. // now enable the timer channel
  229. MAP_TimerEnable(ch->timer->timer, ch->channel);
  230. }
  231. /******************************************************************************/
  232. /* MicroPython bindings */
  233. STATIC void pyb_timer_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
  234. pyb_timer_obj_t *tim = self_in;
  235. uint32_t mode = tim->config & 0xFF;
  236. // timer mode
  237. qstr mode_qst = MP_QSTR_PWM;
  238. switch(mode) {
  239. case TIMER_CFG_A_ONE_SHOT_UP:
  240. mode_qst = MP_QSTR_ONE_SHOT;
  241. break;
  242. case TIMER_CFG_A_PERIODIC_UP:
  243. mode_qst = MP_QSTR_PERIODIC;
  244. break;
  245. default:
  246. break;
  247. }
  248. mp_printf(print, "Timer(%u, mode=Timer.%q)", tim->id, mode_qst);
  249. }
  250. STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
  251. static const mp_arg_t allowed_args[] = {
  252. { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT, },
  253. { MP_QSTR_width, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 16} },
  254. };
  255. // parse args
  256. mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
  257. mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
  258. // check the mode
  259. uint32_t _mode = args[0].u_int;
  260. if (_mode != TIMER_CFG_A_ONE_SHOT_UP && _mode != TIMER_CFG_A_PERIODIC_UP && _mode != TIMER_CFG_A_PWM) {
  261. goto error;
  262. }
  263. // check the width
  264. if (args[1].u_int != 16 && args[1].u_int != 32) {
  265. goto error;
  266. }
  267. bool is16bit = (args[1].u_int == 16);
  268. if (!is16bit && _mode == TIMER_CFG_A_PWM) {
  269. // 32-bit mode is only available when in free running modes
  270. goto error;
  271. }
  272. tim->config = is16bit ? ((_mode | (_mode << 8)) | TIMER_CFG_SPLIT_PAIR) : _mode;
  273. timer_init(tim);
  274. // register it with the sleep module
  275. pyb_sleep_add ((const mp_obj_t)tim, (WakeUpCB_t)timer_init);
  276. return mp_const_none;
  277. error:
  278. mp_raise_ValueError(mpexception_value_invalid_arguments);
  279. }
  280. STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
  281. // check arguments
  282. mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
  283. // create a new Timer object
  284. int32_t timer_idx = mp_obj_get_int(args[0]);
  285. if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
  286. mp_raise_OSError(MP_ENODEV);
  287. }
  288. pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx];
  289. tim->base.type = &pyb_timer_type;
  290. tim->id = timer_idx;
  291. if (n_args > 1 || n_kw > 0) {
  292. // start the peripheral
  293. mp_map_t kw_args;
  294. mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
  295. pyb_timer_init_helper(tim, n_args - 1, args + 1, &kw_args);
  296. }
  297. return (mp_obj_t)tim;
  298. }
  299. STATIC mp_obj_t pyb_timer_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
  300. return pyb_timer_init_helper(args[0], n_args - 1, args + 1, kw_args);
  301. }
  302. STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_init_obj, 1, pyb_timer_init);
  303. STATIC mp_obj_t pyb_timer_deinit(mp_obj_t self_in) {
  304. pyb_timer_obj_t *self = self_in;
  305. timer_disable(self);
  306. return mp_const_none;
  307. }
  308. STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_timer_deinit_obj, pyb_timer_deinit);
  309. STATIC mp_obj_t pyb_timer_channel(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
  310. static const mp_arg_t allowed_args[] = {
  311. { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
  312. { MP_QSTR_period, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
  313. { MP_QSTR_polarity, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = PYBTIMER_POLARITY_POS} },
  314. { MP_QSTR_duty_cycle, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
  315. };
  316. pyb_timer_obj_t *tim = pos_args[0];
  317. mp_int_t channel_n = mp_obj_get_int(pos_args[1]);
  318. // verify that the timer has been already initialized
  319. if (!tim->config) {
  320. mp_raise_OSError(MP_EPERM);
  321. }
  322. if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) {
  323. // invalid channel
  324. goto error;
  325. }
  326. if (channel_n == (TIMER_A | TIMER_B) && (tim->config & TIMER_CFG_SPLIT_PAIR)) {
  327. // 32-bit channel selected when the timer is in 16-bit mode
  328. goto error;
  329. }
  330. // if only the channel number is given return the previously
  331. // allocated channel (or None if no previous channel)
  332. if (n_args == 2 && kw_args->used == 0) {
  333. pyb_timer_channel_obj_t *ch;
  334. if ((ch = pyb_timer_channel_find(tim->timer, channel_n))) {
  335. return ch;
  336. }
  337. return mp_const_none;
  338. }
  339. // parse the arguments
  340. mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
  341. mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
  342. // throw an exception if both frequency and period are given
  343. if (args[0].u_int != 0 && args[1].u_int != 0) {
  344. goto error;
  345. }
  346. // check that at least one of them has a valid value
  347. if (args[0].u_int <= 0 && args[1].u_int <= 0) {
  348. goto error;
  349. }
  350. // check that the polarity is not 'both' in pwm mode
  351. if ((tim->config & TIMER_A) == TIMER_CFG_A_PWM && args[2].u_int == (PYBTIMER_POLARITY_POS | PYBTIMER_POLARITY_NEG)) {
  352. goto error;
  353. }
  354. // allocate a new timer channel
  355. pyb_timer_channel_obj_t *ch = m_new_obj(pyb_timer_channel_obj_t);
  356. ch->base.type = &pyb_timer_channel_type;
  357. ch->timer = tim;
  358. ch->channel = channel_n;
  359. // get the frequency the polarity and the duty cycle
  360. ch->frequency = args[0].u_int;
  361. ch->period = args[1].u_int;
  362. ch->polarity = args[2].u_int;
  363. ch->duty_cycle = MIN(10000, MAX(0, args[3].u_int));
  364. timer_channel_init(ch);
  365. // assign the pin
  366. if ((ch->timer->config & 0x0F) == TIMER_CFG_A_PWM) {
  367. uint32_t ch_idx = (ch->channel == TIMER_A) ? 0 : 1;
  368. // use the default pin if available
  369. mp_obj_t pin_o = (mp_obj_t)pyb_timer_pwm_pin[(ch->timer->id * 2) + ch_idx];
  370. if (pin_o != MP_OBJ_NULL) {
  371. pin_obj_t *pin = pin_find(pin_o);
  372. pin_config (pin, pin_find_af_index(pin, PIN_FN_TIM, ch->timer->id, PIN_TYPE_TIM_PWM),
  373. 0, PIN_TYPE_STD, -1, PIN_STRENGTH_4MA);
  374. }
  375. }
  376. // add the timer to the list
  377. pyb_timer_channel_add(ch);
  378. return ch;
  379. error:
  380. mp_raise_ValueError(mpexception_value_invalid_arguments);
  381. }
  382. STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel);
  383. STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
  384. // instance methods
  385. { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_timer_init_obj) },
  386. { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_timer_deinit_obj) },
  387. { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&pyb_timer_channel_obj) },
  388. // class constants
  389. { MP_ROM_QSTR(MP_QSTR_A), MP_ROM_INT(TIMER_A) },
  390. { MP_ROM_QSTR(MP_QSTR_B), MP_ROM_INT(TIMER_B) },
  391. { MP_ROM_QSTR(MP_QSTR_ONE_SHOT), MP_ROM_INT(TIMER_CFG_A_ONE_SHOT_UP) },
  392. { MP_ROM_QSTR(MP_QSTR_PERIODIC), MP_ROM_INT(TIMER_CFG_A_PERIODIC_UP) },
  393. { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_INT(TIMER_CFG_A_PWM) },
  394. { MP_ROM_QSTR(MP_QSTR_POSITIVE), MP_ROM_INT(PYBTIMER_POLARITY_POS) },
  395. { MP_ROM_QSTR(MP_QSTR_NEGATIVE), MP_ROM_INT(PYBTIMER_POLARITY_NEG) },
  396. { MP_ROM_QSTR(MP_QSTR_TIMEOUT), MP_ROM_INT(PYBTIMER_TIMEOUT_TRIGGER) },
  397. { MP_ROM_QSTR(MP_QSTR_MATCH), MP_ROM_INT(PYBTIMER_MATCH_TRIGGER) },
  398. };
  399. STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
  400. const mp_obj_type_t pyb_timer_type = {
  401. { &mp_type_type },
  402. .name = MP_QSTR_Timer,
  403. .print = pyb_timer_print,
  404. .make_new = pyb_timer_make_new,
  405. .locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
  406. };
  407. STATIC const mp_irq_methods_t pyb_timer_channel_irq_methods = {
  408. .init = pyb_timer_channel_irq,
  409. .enable = pyb_timer_channel_irq_enable,
  410. .disable = pyb_timer_channel_irq_disable,
  411. .flags = pyb_timer_channel_irq_flags,
  412. };
  413. STATIC void TIMERGenericIntHandler(uint32_t timer, uint16_t channel) {
  414. pyb_timer_channel_obj_t *self;
  415. uint32_t status;
  416. if ((self = pyb_timer_channel_find(timer, channel))) {
  417. status = MAP_TimerIntStatus(self->timer->timer, true) & self->channel;
  418. MAP_TimerIntClear(self->timer->timer, status);
  419. mp_irq_handler(mp_irq_find(self));
  420. }
  421. }
  422. STATIC void TIMER0AIntHandler(void) {
  423. TIMERGenericIntHandler(TIMERA0_BASE, TIMER_A);
  424. }
  425. STATIC void TIMER0BIntHandler(void) {
  426. TIMERGenericIntHandler(TIMERA0_BASE, TIMER_B);
  427. }
  428. STATIC void TIMER1AIntHandler(void) {
  429. TIMERGenericIntHandler(TIMERA1_BASE, TIMER_A);
  430. }
  431. STATIC void TIMER1BIntHandler(void) {
  432. TIMERGenericIntHandler(TIMERA1_BASE, TIMER_B);
  433. }
  434. STATIC void TIMER2AIntHandler(void) {
  435. TIMERGenericIntHandler(TIMERA2_BASE, TIMER_A);
  436. }
  437. STATIC void TIMER2BIntHandler(void) {
  438. TIMERGenericIntHandler(TIMERA2_BASE, TIMER_B);
  439. }
  440. STATIC void TIMER3AIntHandler(void) {
  441. TIMERGenericIntHandler(TIMERA3_BASE, TIMER_A);
  442. }
  443. STATIC void TIMER3BIntHandler(void) {
  444. TIMERGenericIntHandler(TIMERA3_BASE, TIMER_B);
  445. }
  446. STATIC void pyb_timer_channel_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
  447. pyb_timer_channel_obj_t *ch = self_in;
  448. char *ch_id = "AB";
  449. // timer channel
  450. if (ch->channel == TIMER_A) {
  451. ch_id = "A";
  452. } else if (ch->channel == TIMER_B) {
  453. ch_id = "B";
  454. }
  455. mp_printf(print, "timer.channel(Timer.%s, %q=%u", ch_id, MP_QSTR_freq, ch->frequency);
  456. uint32_t mode = ch->timer->config & 0xFF;
  457. if (mode == TIMER_CFG_A_PWM) {
  458. mp_printf(print, ", %q=Timer.", MP_QSTR_polarity);
  459. switch (ch->polarity) {
  460. case PYBTIMER_POLARITY_POS:
  461. mp_printf(print, "POSITIVE");
  462. break;
  463. case PYBTIMER_POLARITY_NEG:
  464. mp_printf(print, "NEGATIVE");
  465. break;
  466. default:
  467. mp_printf(print, "BOTH");
  468. break;
  469. }
  470. mp_printf(print, ", %q=%u.%02u", MP_QSTR_duty_cycle, ch->duty_cycle / 100, ch->duty_cycle % 100);
  471. }
  472. mp_printf(print, ")");
  473. }
  474. STATIC mp_obj_t pyb_timer_channel_freq(size_t n_args, const mp_obj_t *args) {
  475. pyb_timer_channel_obj_t *ch = args[0];
  476. if (n_args == 1) {
  477. // get
  478. return mp_obj_new_int(ch->frequency);
  479. } else {
  480. // set
  481. int32_t _frequency = mp_obj_get_int(args[1]);
  482. if (_frequency <= 0) {
  483. mp_raise_ValueError(mpexception_value_invalid_arguments);
  484. }
  485. ch->frequency = _frequency;
  486. ch->period = 1000000 / _frequency;
  487. timer_channel_init(ch);
  488. return mp_const_none;
  489. }
  490. }
  491. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_freq_obj, 1, 2, pyb_timer_channel_freq);
  492. STATIC mp_obj_t pyb_timer_channel_period(size_t n_args, const mp_obj_t *args) {
  493. pyb_timer_channel_obj_t *ch = args[0];
  494. if (n_args == 1) {
  495. // get
  496. return mp_obj_new_int(ch->period);
  497. } else {
  498. // set
  499. int32_t _period = mp_obj_get_int(args[1]);
  500. if (_period <= 0) {
  501. mp_raise_ValueError(mpexception_value_invalid_arguments);
  502. }
  503. ch->period = _period;
  504. ch->frequency = 1000000 / _period;
  505. timer_channel_init(ch);
  506. return mp_const_none;
  507. }
  508. }
  509. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_period_obj, 1, 2, pyb_timer_channel_period);
  510. STATIC mp_obj_t pyb_timer_channel_duty_cycle(size_t n_args, const mp_obj_t *args) {
  511. pyb_timer_channel_obj_t *ch = args[0];
  512. if (n_args == 1) {
  513. // get
  514. return mp_obj_new_int(ch->duty_cycle);
  515. } else {
  516. // duty cycle must be converted from percentage to ticks
  517. // calculate the period, the prescaler and the match value
  518. uint32_t period_c;
  519. uint32_t match;
  520. ch->duty_cycle = MIN(10000, MAX(0, mp_obj_get_int(args[1])));
  521. compute_prescaler_period_and_match_value(ch, &period_c, &match);
  522. if (n_args == 3) {
  523. // set the new polarity if requested
  524. ch->polarity = mp_obj_get_int(args[2]);
  525. MAP_TimerControlLevel(ch->timer->timer, ch->channel, (ch->polarity == PYBTIMER_POLARITY_NEG) ? true : false);
  526. }
  527. MAP_TimerMatchSet(ch->timer->timer, ch->channel, match);
  528. MAP_TimerPrescaleMatchSet(ch->timer->timer, ch->channel, match >> 16);
  529. return mp_const_none;
  530. }
  531. }
  532. STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_timer_channel_duty_cycle_obj, 1, 3, pyb_timer_channel_duty_cycle);
  533. STATIC mp_obj_t pyb_timer_channel_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
  534. mp_arg_val_t args[mp_irq_INIT_NUM_ARGS];
  535. mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, mp_irq_INIT_NUM_ARGS, mp_irq_init_args, args);
  536. pyb_timer_channel_obj_t *ch = pos_args[0];
  537. // convert the priority to the correct value
  538. uint priority = mp_irq_translate_priority (args[1].u_int);
  539. // validate the power mode
  540. uint8_t pwrmode = (args[3].u_obj == mp_const_none) ? PYB_PWR_MODE_ACTIVE : mp_obj_get_int(args[3].u_obj);
  541. if (pwrmode != PYB_PWR_MODE_ACTIVE) {
  542. goto invalid_args;
  543. }
  544. // get the trigger
  545. uint trigger = mp_obj_get_int(args[0].u_obj);
  546. // disable the callback first
  547. pyb_timer_channel_irq_disable(ch);
  548. uint8_t shift = (ch->channel == TIMER_B) ? 8 : 0;
  549. uint32_t _config = (ch->channel == TIMER_B) ? ((ch->timer->config & TIMER_B) >> 8) : (ch->timer->config & TIMER_A);
  550. switch (_config) {
  551. case TIMER_CFG_A_ONE_SHOT_UP:
  552. case TIMER_CFG_A_PERIODIC_UP:
  553. ch->timer->irq_trigger |= TIMER_TIMA_TIMEOUT << shift;
  554. if (trigger != PYBTIMER_TIMEOUT_TRIGGER) {
  555. goto invalid_args;
  556. }
  557. break;
  558. case TIMER_CFG_A_PWM:
  559. // special case for the PWM match interrupt
  560. ch->timer->irq_trigger |= ((ch->channel & TIMER_A) == TIMER_A) ? TIMER_TIMA_MATCH : TIMER_TIMB_MATCH;
  561. if (trigger != PYBTIMER_MATCH_TRIGGER) {
  562. goto invalid_args;
  563. }
  564. break;
  565. default:
  566. break;
  567. }
  568. // special case for a 32-bit timer
  569. if (ch->channel == (TIMER_A | TIMER_B)) {
  570. ch->timer->irq_trigger |= (ch->timer->irq_trigger << 8);
  571. }
  572. void (*pfnHandler)(void);
  573. uint32_t intregister;
  574. switch (ch->timer->timer) {
  575. case TIMERA0_BASE:
  576. if (ch->channel == TIMER_B) {
  577. pfnHandler = &TIMER0BIntHandler;
  578. intregister = INT_TIMERA0B;
  579. } else {
  580. pfnHandler = &TIMER0AIntHandler;
  581. intregister = INT_TIMERA0A;
  582. }
  583. break;
  584. case TIMERA1_BASE:
  585. if (ch->channel == TIMER_B) {
  586. pfnHandler = &TIMER1BIntHandler;
  587. intregister = INT_TIMERA1B;
  588. } else {
  589. pfnHandler = &TIMER1AIntHandler;
  590. intregister = INT_TIMERA1A;
  591. }
  592. break;
  593. case TIMERA2_BASE:
  594. if (ch->channel == TIMER_B) {
  595. pfnHandler = &TIMER2BIntHandler;
  596. intregister = INT_TIMERA2B;
  597. } else {
  598. pfnHandler = &TIMER2AIntHandler;
  599. intregister = INT_TIMERA2A;
  600. }
  601. break;
  602. default:
  603. if (ch->channel == TIMER_B) {
  604. pfnHandler = &TIMER3BIntHandler;
  605. intregister = INT_TIMERA3B;
  606. } else {
  607. pfnHandler = &TIMER3AIntHandler;
  608. intregister = INT_TIMERA3A;
  609. }
  610. break;
  611. }
  612. // register the interrupt and configure the priority
  613. MAP_IntPrioritySet(intregister, priority);
  614. MAP_TimerIntRegister(ch->timer->timer, ch->channel, pfnHandler);
  615. // create the callback
  616. mp_obj_t _irq = mp_irq_new (ch, args[2].u_obj, &pyb_timer_channel_irq_methods);
  617. // enable the callback before returning
  618. pyb_timer_channel_irq_enable(ch);
  619. return _irq;
  620. invalid_args:
  621. mp_raise_ValueError(mpexception_value_invalid_arguments);
  622. }
  623. STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_irq_obj, 1, pyb_timer_channel_irq);
  624. STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
  625. // instance methods
  626. { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_timer_channel_freq_obj) },
  627. { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&pyb_timer_channel_period_obj) },
  628. { MP_ROM_QSTR(MP_QSTR_duty_cycle), MP_ROM_PTR(&pyb_timer_channel_duty_cycle_obj) },
  629. { MP_ROM_QSTR(MP_QSTR_irq), MP_ROM_PTR(&pyb_timer_channel_irq_obj) },
  630. };
  631. STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
  632. STATIC const mp_obj_type_t pyb_timer_channel_type = {
  633. { &mp_type_type },
  634. .name = MP_QSTR_TimerChannel,
  635. .print = pyb_timer_channel_print,
  636. .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict,
  637. };