@@ -49,11 +49,9 @@ extern uint8_t timer_refcount[TC_INST_NUM + TCC_INST_NUM];
4949extern const uint16_t prescaler [8 ];
5050
5151// This timer is shared amongst all AudioOut objects under the assumption that
52- // the code is single threaded.
53- static struct tc_module * tc_instance ;
54- static struct dac_module * dac_instance ;
55- static struct events_resource * tc_event ;
56- static struct events_resource * dac_event ;
52+ // the code is single threaded. The audioout_tc_instance, audioout_dac_instance,
53+ // audioout_tc_event, and audioout_dac_event pointers live in
54+ // MICROPY_PORT_ROOT_POINTERS so they don't get garbage collected.
5755
5856// The AudioOut object is being currently played. Only it can pause the timer
5957// and change its frequency.
@@ -62,25 +60,22 @@ static audioio_audioout_obj_t* active_audioout;
6260static uint8_t refcount = 0 ;
6361
6462void audioout_reset (void ) {
65- // Only reset DMA. PWMOut will reset the timer.
63+ // Only reset DMA. PWMOut will reset the timer. Other code will reset the DAC.
6664 refcount = 0 ;
67- tc_instance = NULL ;
68- if (dac_instance != NULL ) {
69- dac_reset (dac_instance );
70- }
71- dac_instance = NULL ;
65+ MP_STATE_VM (audioout_tc_instance ) = NULL ;
66+ MP_STATE_VM (audioout_dac_instance ) = NULL ;
7267
73- if (tc_event != NULL ) {
74- events_detach_user (tc_event , EVSYS_ID_USER_DAC_START );
75- events_release (tc_event );
68+ if (MP_STATE_VM ( audioout_tc_event ) != NULL ) {
69+ events_detach_user (MP_STATE_VM ( audioout_tc_event ) , EVSYS_ID_USER_DAC_START );
70+ events_release (MP_STATE_VM ( audioout_tc_event ) );
7671 }
77- tc_event = NULL ;
72+ MP_STATE_VM ( audioout_tc_event ) = NULL ;
7873
79- if (dac_event != NULL ) {
80- events_detach_user (dac_event , EVSYS_ID_USER_DMAC_CH_0 );
81- events_release (dac_event );
74+ if (MP_STATE_VM ( audioout_dac_event ) != NULL ) {
75+ events_detach_user (MP_STATE_VM ( audioout_dac_event ) , EVSYS_ID_USER_DMAC_CH_0 );
76+ events_release (MP_STATE_VM ( audioout_dac_event ) );
8277 }
83- dac_event = NULL ;
78+ MP_STATE_VM ( audioout_dac_event ) = NULL ;
8479
8580 dma_abort_job (& audio_dma );
8681}
@@ -90,16 +85,16 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
9085
9186 // Configure the DAC to output on input event and to output an empty event
9287 // that triggers the DMA to load the next sample.
93- dac_instance = gc_alloc (sizeof (struct dac_module ), false);
94- if (dac_instance == NULL ) {
88+ MP_STATE_VM ( audioout_dac_instance ) = gc_alloc (sizeof (struct dac_module ), false);
89+ if (MP_STATE_VM ( audioout_dac_instance ) == NULL ) {
9590 mp_raise_msg (& mp_type_MemoryError , "" );
9691 }
9792 struct dac_config config_dac ;
9893 dac_get_config_defaults (& config_dac );
9994 config_dac .left_adjust = true;
10095 config_dac .reference = DAC_REFERENCE_AVCC ;
10196 config_dac .clock_source = GCLK_GENERATOR_0 ;
102- enum status_code status = dac_init (dac_instance , DAC , & config_dac );
97+ enum status_code status = dac_init (MP_STATE_VM ( audioout_dac_instance ) , DAC , & config_dac );
10398 if (status != STATUS_OK ) {
10499 common_hal_audioio_audioout_deinit (self );
105100 mp_raise_OSError (MP_EIO );
@@ -108,14 +103,12 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
108103
109104 struct dac_chan_config channel_config ;
110105 dac_chan_get_config_defaults (& channel_config );
111- dac_chan_set_config (dac_instance , DAC_CHANNEL_0 , & channel_config );
112- dac_chan_enable (dac_instance , DAC_CHANNEL_0 );
106+ dac_chan_set_config (MP_STATE_VM ( audioout_dac_instance ) , DAC_CHANNEL_0 , & channel_config );
107+ dac_chan_enable (MP_STATE_VM ( audioout_dac_instance ) , DAC_CHANNEL_0 );
113108
114109 struct dac_events events_dac = { .generate_event_on_buffer_empty = true,
115110 .on_event_start_conversion = true };
116- dac_enable_events (dac_instance , & events_dac );
117-
118- dac_enable (dac_instance );
111+ dac_enable_events (MP_STATE_VM (audioout_dac_instance ), & events_dac );
119112
120113 // Figure out which timer we are using.
121114 Tc * t = NULL ;
@@ -131,37 +124,37 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
131124 mp_raise_RuntimeError ("All timers in use" );
132125 return ;
133126 }
134- tc_instance = gc_alloc (sizeof (struct tc_module ), false);
135- if (tc_instance == NULL ) {
127+ MP_STATE_VM ( audioout_tc_instance ) = gc_alloc (sizeof (struct tc_module ), false);
128+ if (MP_STATE_VM ( audioout_tc_instance ) == NULL ) {
136129 common_hal_audioio_audioout_deinit (self );
137130 mp_raise_msg (& mp_type_MemoryError , "" );
138131 }
139132
140133 // Don't bother setting the period. We set it before you playback anything.
141134 struct tc_config config_tc ;
142135 tc_get_config_defaults (& config_tc );
143-
144136 config_tc .counter_size = TC_COUNTER_SIZE_16BIT ;
145137 config_tc .clock_prescaler = TC_CLOCK_PRESCALER_DIV1 ;
146138 config_tc .wave_generation = TC_WAVE_GENERATION_MATCH_FREQ ;
147- if (tc_init (tc_instance , t , & config_tc ) != STATUS_OK ) {
139+ if (tc_init (MP_STATE_VM ( audioout_tc_instance ) , t , & config_tc ) != STATUS_OK ) {
148140 common_hal_audioio_audioout_deinit (self );
149- mp_printf (& mp_plat_print , "tc \n" );
150141 mp_raise_OSError (MP_EIO );
151142 return ;
152143 };
153144
154145 struct tc_events events_tc ;
155146 events_tc .generate_event_on_overflow = true;
156- tc_enable_events (tc_instance , & events_tc );
147+ events_tc .on_event_perform_action = false;
148+ events_tc .event_action = TC_EVENT_ACTION_OFF ;
149+ tc_enable_events (MP_STATE_VM (audioout_tc_instance ), & events_tc );
157150
158- tc_enable (tc_instance );
159- tc_stop_counter (tc_instance );
151+ tc_enable (MP_STATE_VM ( audioout_tc_instance ) );
152+ tc_stop_counter (MP_STATE_VM ( audioout_tc_instance ) );
160153
161154 // Connect the timer overflow event, which happens at the target frequency,
162155 // to the DAC conversion trigger.
163- tc_event = gc_alloc (sizeof (struct events_resource ), false);
164- if (tc_event == NULL ) {
156+ MP_STATE_VM ( audioout_tc_event ) = gc_alloc (sizeof (struct events_resource ), false);
157+ if (MP_STATE_VM ( audioout_tc_event ) == NULL ) {
165158 common_hal_audioio_audioout_deinit (self );
166159 mp_raise_msg (& mp_type_MemoryError , "" );
167160 }
@@ -185,24 +178,24 @@ static void shared_construct(audioio_audioout_obj_t* self, const mcu_pin_obj_t*
185178
186179 config .generator = generator ;
187180 config .path = EVENTS_PATH_ASYNCHRONOUS ;
188- if (events_allocate (tc_event , & config ) != STATUS_OK ||
189- events_attach_user (tc_event , EVSYS_ID_USER_DAC_START ) != STATUS_OK ) {
181+ if (events_allocate (MP_STATE_VM ( audioout_tc_event ) , & config ) != STATUS_OK ||
182+ events_attach_user (MP_STATE_VM ( audioout_tc_event ) , EVSYS_ID_USER_DAC_START ) != STATUS_OK ) {
190183 common_hal_audioio_audioout_deinit (self );
191184 mp_raise_OSError (MP_EIO );
192185 return ;
193186 }
194187
195188 // Connect the DAC to DMA
196- dac_event = gc_alloc (sizeof (struct events_resource ), false);
197- if (dac_event == NULL ) {
189+ MP_STATE_VM ( audioout_dac_event ) = gc_alloc (sizeof (struct events_resource ), false);
190+ if (MP_STATE_VM ( audioout_dac_event ) == NULL ) {
198191 common_hal_audioio_audioout_deinit (self );
199192 mp_raise_msg (& mp_type_MemoryError , "" );
200193 }
201194 events_get_config_defaults (& config );
202195 config .generator = EVSYS_ID_GEN_DAC_EMPTY ;
203196 config .path = EVENTS_PATH_ASYNCHRONOUS ;
204- if (events_allocate (dac_event , & config ) != STATUS_OK ||
205- events_attach_user (dac_event , EVSYS_ID_USER_DMAC_CH_0 ) != STATUS_OK ) {
197+ if (events_allocate (MP_STATE_VM ( audioout_dac_event ) , & config ) != STATUS_OK ||
198+ events_attach_user (MP_STATE_VM ( audioout_dac_event ) , EVSYS_ID_USER_DMAC_CH_0 ) != STATUS_OK ) {
206199 common_hal_audioio_audioout_deinit (self );
207200 mp_raise_OSError (MP_EIO );
208201 return ;
@@ -239,26 +232,26 @@ void common_hal_audioio_audioout_construct_from_file(audioio_audioout_obj_t* sel
239232void common_hal_audioio_audioout_deinit (audioio_audioout_obj_t * self ) {
240233 refcount -- ;
241234 if (refcount == 0 ) {
242- if (tc_instance != NULL ) {
243- tc_reset (tc_instance );
244- gc_free (tc_instance );
245- tc_instance = NULL ;
235+ if (MP_STATE_VM ( audioout_tc_instance ) != NULL ) {
236+ tc_reset (MP_STATE_VM ( audioout_tc_instance ) );
237+ gc_free (MP_STATE_VM ( audioout_tc_instance ) );
238+ MP_STATE_VM ( audioout_tc_instance ) = NULL ;
246239 }
247- if (dac_instance != NULL ) {
248- dac_reset (dac_instance );
249- gc_free (dac_instance );
250- dac_instance = NULL ;
240+ if (MP_STATE_VM ( audioout_dac_instance ) != NULL ) {
241+ dac_reset (MP_STATE_VM ( audioout_dac_instance ) );
242+ gc_free (MP_STATE_VM ( audioout_dac_instance ) );
243+ MP_STATE_VM ( audioout_dac_instance ) = NULL ;
251244 }
252- if (tc_event != NULL ) {
253- events_detach_user (tc_event , EVSYS_ID_USER_DAC_START );
254- events_release (tc_event );
255- gc_free (tc_event );
256- tc_event = NULL ;
245+ if (MP_STATE_VM ( audioout_tc_event ) != NULL ) {
246+ events_detach_user (MP_STATE_VM ( audioout_tc_event ) , EVSYS_ID_USER_DAC_START );
247+ events_release (MP_STATE_VM ( audioout_tc_event ) );
248+ gc_free (MP_STATE_VM ( audioout_tc_event ) );
249+ MP_STATE_VM ( audioout_tc_event ) = NULL ;
257250 }
258- if (dac_event != NULL ) {
259- events_release (dac_event );
260- gc_free (dac_event );
261- dac_event = NULL ;
251+ if (MP_STATE_VM ( audioout_dac_event ) != NULL ) {
252+ events_release (MP_STATE_VM ( audioout_dac_event ) );
253+ gc_free (MP_STATE_VM ( audioout_dac_event ) );
254+ MP_STATE_VM ( audioout_dac_event ) = NULL ;
262255 }
263256 reset_pin (self -> pin -> pin );
264257 }
@@ -274,17 +267,17 @@ static void set_timer_frequency(uint32_t frequency) {
274267 break ;
275268 }
276269 }
277- uint8_t old_divisor = tc_instance -> hw -> COUNT16 .CTRLA .bit .PRESCALER ;
270+ uint8_t old_divisor = MP_STATE_VM ( audioout_tc_instance ) -> hw -> COUNT16 .CTRLA .bit .PRESCALER ;
278271 if (new_divisor != old_divisor ) {
279- tc_disable (tc_instance );
280- tc_instance -> hw -> COUNT16 .CTRLA .bit .PRESCALER = new_divisor ;
281- tc_enable (tc_instance );
272+ tc_disable (MP_STATE_VM ( audioout_tc_instance ) );
273+ MP_STATE_VM ( audioout_tc_instance ) -> hw -> COUNT16 .CTRLA .bit .PRESCALER = new_divisor ;
274+ tc_enable (MP_STATE_VM ( audioout_tc_instance ) );
282275 }
283- while (tc_is_syncing (tc_instance )) {
276+ while (tc_is_syncing (MP_STATE_VM ( audioout_tc_instance ) )) {
284277 /* Wait for sync */
285278 }
286- tc_instance -> hw -> COUNT16 .CC [0 ].reg = new_top ;
287- while (tc_is_syncing (tc_instance )) {
279+ MP_STATE_VM ( audioout_tc_instance ) -> hw -> COUNT16 .CC [0 ].reg = new_top ;
280+ while (tc_is_syncing (MP_STATE_VM ( audioout_tc_instance ) )) {
288281 /* Wait for sync */
289282 }
290283}
@@ -293,8 +286,10 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self, bool loop) {
293286 common_hal_audioio_audioout_get_playing (self );
294287 // Shut down any active playback.
295288 if (active_audioout != NULL ) {
296- tc_stop_counter (tc_instance );
289+ tc_stop_counter (MP_STATE_VM ( audioout_tc_instance ) );
297290 dma_abort_job (& audio_dma );
291+ } else {
292+ dac_enable (MP_STATE_VM (audioout_dac_instance ));
298293 }
299294 struct dma_descriptor_config descriptor_config ;
300295 dma_descriptor_get_config_defaults (& descriptor_config );
@@ -314,15 +309,15 @@ void common_hal_audioio_audioout_play(audioio_audioout_obj_t* self, bool loop) {
314309 dma_start_transfer_job (& audio_dma );
315310
316311 set_timer_frequency (self -> frequency );
317- tc_start_counter (tc_instance );
312+ tc_start_counter (MP_STATE_VM ( audioout_tc_instance ) );
318313}
319314
320315void common_hal_audioio_audioout_stop (audioio_audioout_obj_t * self ) {
321316 if (common_hal_audioio_audioout_get_playing (self )) {
322- tc_stop_counter (tc_instance );
317+ tc_stop_counter (MP_STATE_VM ( audioout_tc_instance ) );
323318 dma_abort_job (& audio_dma );
324319 active_audioout = NULL ;
325- // TODO(tannewt): Disable the DAC to save power.
320+ dac_disable ( MP_STATE_VM ( audioout_dac_instance ));
326321 }
327322}
328323
0 commit comments