2727#include <stdbool.h>
2828
2929#include "py/mpstate.h"
30+ #include "py/runtime.h"
3031#include "__init__.h"
3132#include "PewPew.h"
3233
3334#include "shared-bindings/digitalio/Pull.h"
3435#include "shared-bindings/digitalio/DigitalInOut.h"
3536#include "shared-bindings/util.h"
37+ #include "samd/timers.h"
3638
3739
40+ static uint8_t pewpew_tc_index = 0xff ;
41+
42+
43+ void pewpew_interrupt_handler (uint8_t index ) {
44+ if (index != pewpew_tc_index ) return ;
45+ Tc * tc = tc_insts [index ];
46+ if (!tc -> COUNT16 .INTFLAG .bit .MC0 ) return ;
47+
48+ pew_tick ();
49+
50+ // Clear the interrupt bit.
51+ tc -> COUNT16 .INTFLAG .reg = TC_INTFLAG_MC0 ;
52+ }
53+
3854void pew_init () {
3955 pew_obj_t * pew_singleton = MP_STATE_VM (pew_singleton );
4056 for (size_t i = 0 ; i < pew_singleton -> rows_size ; ++ i ) {
@@ -49,4 +65,57 @@ void pew_init() {
4965 common_hal_digitalio_digitalinout_switch_to_output (pin , true,
5066 DRIVE_MODE_OPEN_DRAIN );
5167 }
68+ if (pewpew_tc_index == 0xff ) {
69+ // Find a spare timer.
70+ Tc * tc = NULL ;
71+ int8_t index = TC_INST_NUM - 1 ;
72+ for (; index >= 0 ; index -- ) {
73+ if (tc_insts [index ]-> COUNT16 .CTRLA .bit .ENABLE == 0 ) {
74+ tc = tc_insts [index ];
75+ break ;
76+ }
77+ }
78+ if (tc == NULL ) {
79+ mp_raise_RuntimeError ("All timers in use" );
80+ }
81+
82+ pewpew_tc_index = index ;
83+
84+ // We use GCLK0 for SAMD21 and GCLK1 for SAMD51 because they both run
85+ // at 48mhz making our math the same across the boards.
86+ #ifdef SAMD21
87+ turn_on_clocks (true, index , 0 );
88+ #endif
89+ #ifdef SAMD51
90+ turn_on_clocks (true, index , 1 );
91+ #endif
92+
93+
94+ #ifdef SAMD21
95+ tc -> COUNT16 .CTRLA .reg = TC_CTRLA_MODE_COUNT16 |
96+ TC_CTRLA_PRESCALER_DIV64 |
97+ TC_CTRLA_WAVEGEN_MFRQ ;
98+ #endif
99+ #ifdef SAMD51
100+ tc_reset (tc );
101+ tc_set_enable (tc , false);
102+ tc -> COUNT16 .CTRLA .reg = TC_CTRLA_MODE_COUNT16
103+ | TC_CTRLA_PRESCALER_DIV64 ;
104+ tc -> COUNT16 .WAVE .reg = TC_WAVE_WAVEGEN_MFRQ ;
105+ #endif
106+
107+ tc_set_enable (tc , true);
108+ //tc->COUNT16.CTRLBSET.reg = TC_CTRLBSET_CMD_STOP;
109+ tc -> COUNT16 .CC [0 ].reg = 160 ;
110+
111+ // Clear our interrupt in case it was set earlier
112+ tc -> COUNT16 .INTFLAG .reg = TC_INTFLAG_MC0 ;
113+ tc -> COUNT16 .INTENSET .reg = TC_INTENSET_MC0 ;
114+ tc_enable_interrupts (pewpew_tc_index );
115+ }
116+ }
117+
118+ void pew_reset (void ) {
119+ MP_STATE_VM (pew_singleton ) = NULL ;
120+ pewpew_tc_index = 0xff ;
52121}
0 commit comments