45
45
/*
46
46
#define USE_TIMERB2 // interferes with PWM on pin 11
47
47
#define USE_TIMERB0 // interferes with PWM on pin 6
48
- #define USE_TIMERA0 // interferes with PWM on pins 5,9,10 NOT RECOMMENDED
49
48
*/
50
49
51
50
// Can't use TIMERB3 -- used for application time tracking
52
- // Using TIMERA0 NOT RECOMMENDED -- leave to last -- all other timers use its clock!
53
- const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { TIMERB1 /* , TIMERB2, TIMERB0, TIMERA0 */ };
54
- static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { NOT_A_PIN /* , NOT_A_PIN, NOT_A_PIN, NOT_A_PIN */ };
51
+ // Using TIMERA0 NOT RECOMMENDED -- all other timers use its clock!
52
+ const uint8_t PROGMEM tone_pin_to_timer_PGM[] = { TIMERB1 /* , TIMERB2, TIMERB0 */ };
53
+ static uint8_t tone_pins[AVAILABLE_TONE_PINS] = { NOT_A_PIN /* , NOT_A_PIN, NOT_A_PIN */ };
55
54
56
55
57
56
// timerx_toggle_count:
58
57
// > 0 - duration specified
59
58
// = 0 - stopped
60
59
// < 0 - infinitely (until stop() method called, or new play() called)
61
60
62
- #if defined(USE_TIMERA0)
63
- volatile long timera0_toggle_count;
64
- volatile uint8_t *timera0_outtgl_reg;
65
- volatile uint8_t timera0_bit_mask;
66
- #endif
67
-
68
61
#if defined(USE_TIMERB0)
69
62
volatile long timerb0_toggle_count;
70
63
volatile uint8_t *timerb0_outtgl_reg;
@@ -147,101 +140,50 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
147
140
toggle_count = -1 ;
148
141
}
149
142
150
- // Timer settings
151
- switch (_timer){
143
+ // Timer settings -- will be type B
152
144
153
- case TIMERB0:{
154
- case TIMERB1:{
155
- case TIMERB2:{
156
-
157
- // Get timer struct
158
- TCB_t *timer_B = ((TCB_t *)&TCB0 + (_timer - TIMERB0));
145
+ // Get timer struct
146
+ TCB_t *timer_B = ((TCB_t *)&TCB0 + (_timer - TIMERB0));
159
147
160
- // Disable for now, set clk according to 'prescaler_needed'
161
- // (Prescaled clock will come from TCA --
162
- // by default it should have a prescaler of 64 (250kHz clock)
163
- // TCA default initialization is in wiring.c -- init() )
164
- if (prescaler_needed){
165
- timer_B->CTRLA = TCB_CLKSEL_CLKTCA_gc;
166
- } else {
167
- timer_B->CTRLA = TCB_CLKSEL_CLKDIV1_gc;
168
- }
148
+ // Disable for now, set clk according to 'prescaler_needed'
149
+ // (Prescaled clock will come from TCA --
150
+ // by default it should have a prescaler of 64 (250kHz clock)
151
+ // TCA default initialization is in wiring.c -- init() )
152
+ if (prescaler_needed){
153
+ timer_B->CTRLA = TCB_CLKSEL_CLKTCA_gc;
154
+ } else {
155
+ timer_B->CTRLA = TCB_CLKSEL_CLKDIV1_gc;
156
+ }
169
157
170
- // Timer to Periodic interrupt mode
171
- // This write will also disable any active PWM outputs
172
- timer_B->CTRLB = TCB_CNTMODE_INT_gc;
158
+ // Timer to Periodic interrupt mode
159
+ // This write will also disable any active PWM outputs
160
+ timer_B->CTRLB = TCB_CNTMODE_INT_gc;
173
161
174
- // Write compare register
175
- timer_B->CCMP = compare_val;
162
+ // Write compare register
163
+ timer_B->CCMP = compare_val;
176
164
177
- // Enable interrupt
178
- timer_B->INTCTRL = TCB_CAPTEI_bm;
165
+ // Enable interrupt
166
+ timer_B->INTCTRL = TCB_CAPTEI_bm;
179
167
180
- // Populate variables needed in interrupt
181
- if (_timer == TIMERB1){
182
- timerb1_outtgl_reg = port_outtgl;
183
- timerb1_bit_mask = bit_mask;
184
- timerb1_toggle_count = toggle_count;
168
+ // Populate variables needed in interrupt
169
+ if (_timer == TIMERB1){
170
+ timerb1_outtgl_reg = port_outtgl;
171
+ timerb1_bit_mask = bit_mask;
172
+ timerb1_toggle_count = toggle_count;
185
173
186
- } else if (_timer == TIMERB2){
187
- timerb2_outtgl_reg = port_outtgl;
188
- timerb2_bit_mask = bit_mask;
189
- timerb2_toggle_count = toggle_count;
174
+ } else if (_timer == TIMERB2){
175
+ timerb2_outtgl_reg = port_outtgl;
176
+ timerb2_bit_mask = bit_mask;
177
+ timerb2_toggle_count = toggle_count;
190
178
191
- } else { // _timer == TIMERB0
192
- timerb0_outtgl_reg = port_outtgl;
193
- timerb0_bit_mask = bit_mask;
194
- timerb0_toggle_count = toggle_count;
195
- }
196
-
197
- // Enable timer
198
- timer_B->CTRLA |= TCB_ENABLE_bm;
199
-
200
- break ;
201
- }
202
- }
203
- }
204
-
205
- /* Keep in mind this is NOT RECOMMENDED since other timers
206
- rely on the clock of TCA0 */
207
- #if defined(USE_TIMERA0)
208
- case TIMERA0:{
209
-
210
- // Disable for now, assign clock according to prescaler_needed
211
- if (prescaler_needed){
212
- TCA0.SINGLE .CTRLA = TCA_SINGLE_CLKSEL_DIV64_gc;
213
- } else {
214
- // WARNING: THIS MIGHT AFFECT TCB OPERATION
215
- // -- THEY MAY BE USING TCA CLOCK!!!!
216
- TCA0.SINGLE .CTRLA = TCA_SINGLE_CLKSEL_DIV1_gc;
217
- }
218
-
219
- // Timer to Normal mode
220
- // This write will also disable any active PWM outputs
221
- TCA0.SINGLE .CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc;
222
-
223
- // Write compare register
224
- TCA0.SINGLE .PERBUF = compare_val;
225
-
226
- // Enable interrupt
227
- TCA0.SINGLE .INTCTRL = TCA_SINGLE_OVF_bm;
228
-
229
- // Populate variables needed in interrupt
230
- timera0_outtgl_reg = port_outtgl;
231
- timera0_bit_mask = bit_mask;
232
- timera0_toggle_count = toggle_count;
233
-
234
- // Enable timer
235
- TCA0.SINGLE .CTRLA |= TCA_SINGLE_ENABLE_bm;
236
-
237
- break ;
238
- }
239
- #endif
179
+ } else { // _timer == TIMERB0
180
+ timerb0_outtgl_reg = port_outtgl;
181
+ timerb0_bit_mask = bit_mask;
182
+ timerb0_toggle_count = toggle_count;
183
+ }
240
184
241
- default :{
242
-
243
- break ;
244
- }
185
+ // Enable timer
186
+ timer_B->CTRLA |= TCB_ENABLE_bm;
245
187
246
188
}
247
189
}
@@ -251,80 +193,38 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
251
193
configuration it had to output PWM for analogWrite() */
252
194
void disableTimer (uint8_t _timer)
253
195
{
254
- switch (_timer){
255
- case TIMERB0:{
256
- case TIMERB1:{
257
- case TIMERB2:{
196
+ // Reinit back to producing PWM -- timer will be type B
258
197
259
- // Get timer struct
260
- TCB_t *timer_B = ((TCB_t *)&TCB0 + (_timer - TIMERB0));
261
-
262
- // Disable interrupt
263
- timer_B->INTCTRL = 0 ;
198
+ // Get timer struct
199
+ TCB_t *timer_B = ((TCB_t *)&TCB0 + (_timer - TIMERB0));
264
200
265
- // Disable timer
266
- timer_B->CTRLA = 0 ;
201
+ // Disable interrupt
202
+ timer_B->INTCTRL = 0 ;
267
203
268
- // RESTORE PWM FUNCTIONALITY:
204
+ // Disable timer
205
+ timer_B->CTRLA = 0 ;
269
206
270
- /* 8 bit PWM mode, but do not enable output yet, will do in analogWrite() */
271
- timer_B->CTRLB = (TCB_CNTMODE_PWM8_gc);
272
-
273
- /* Assign 8-bit period */
274
- timer_B->CCMPL = PWM_TIMER_PERIOD;
275
-
276
- /* default duty 50%, set when output enabled */
277
- timer_B->CCMPH = PWM_TIMER_COMPARE;
278
-
279
- /* Use TCA clock (250kHz) and enable */
280
- /* (sync update commented out, might try to synchronize later */
281
- timer_B->CTRLA = (TCB_CLKSEL_CLKTCA_gc) | (TCB_ENABLE_bm);
282
-
283
- break ;
284
- }
285
- }
286
- }
287
-
288
- #if defined(USE_TIMERA0)
289
- case TIMERA0:{
290
-
291
- // Disable interrupt
292
- TCA0.SINGLE .INTCTRL = 0 ;
293
-
294
- // Disable timer
295
- TCA0.SINGLE .CTRLA = 0 ;
207
+ // RESTORE PWM FUNCTIONALITY:
296
208
297
- // RESTORE PWM FUNCTIONALITY:
298
-
299
- /* Setup timers for single slope PWM, but do not enable, will do in analogWrite() */
300
- TCA0.SINGLE .CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc;
209
+ /* 8 bit PWM mode, but do not enable output yet, will do in analogWrite() */
210
+ timer_B->CTRLB = (TCB_CNTMODE_PWM8_gc);
301
211
302
- /* Period setting, 16 bit register but val resolution is 8 bit */
303
- TCA0. SINGLE . PER = PWM_TIMER_PERIOD;
212
+ /* Assign 8- bit period */
213
+ timer_B-> CCMPL = PWM_TIMER_PERIOD;
304
214
305
- /* Default duty 50%, will re-assign in analogWrite() */
306
- TCA0.SINGLE .CMP0BUF = PWM_TIMER_COMPARE;
307
- TCA0.SINGLE .CMP1BUF = PWM_TIMER_COMPARE;
308
- TCA0.SINGLE .CMP2BUF = PWM_TIMER_COMPARE;
215
+ /* default duty 50%, set when output enabled */
216
+ timer_B->CCMPH = PWM_TIMER_COMPARE;
309
217
310
- /* Use DIV64 prescaler (giving 250kHz clock), enable TCA timer */
311
- TCA0.SINGLE .CTRLA = (TCA_SINGLE_CLKSEL_DIV64_gc) | (TCA_SINGLE_ENABLE_bm);
312
-
313
- break ;
314
- }
315
- #endif
218
+ /* Use TCA clock (250kHz) and enable */
219
+ /* (sync update commented out, might try to synchronize later */
220
+ timer_B->CTRLA = (TCB_CLKSEL_CLKTCA_gc) | (TCB_ENABLE_bm);
316
221
317
- default :{
318
-
319
- break ;
320
- }
321
- }
322
222
}
323
223
324
224
325
225
void noTone (uint8_t _pin)
326
226
{
327
- int8_t _timer = - 1 ;
227
+ int8_t _timer = NOT_ON_TIMER ;
328
228
329
229
// Find timer associated with pin
330
230
for (int i = 0 ; i < AVAILABLE_TONE_PINS; i++) {
@@ -342,40 +242,15 @@ void noTone(uint8_t _pin)
342
242
break ;
343
243
}
344
244
}
345
-
346
- disableTimer (_timer);
347
-
348
- // Keep pin low after disabling of timer
349
- digitalWrite (_pin, LOW);
350
- }
351
245
352
- #ifdef USE_TIMERA0
353
- ISR (TCA0_OVF_vect)
354
- {
355
- if (timera0_toggle_count != 0 ){
356
-
357
- // toggle the pin
358
- *timera0_outtgl_reg = timera0_bit_mask;
359
-
360
- // If duration was defined, decrement
361
- if (timera0_toggle_count > 0 ){
362
- timera0_toggle_count--;
363
- }
364
-
365
- // If no duration (toggle count negative), go on until noTone() call
366
-
367
- } else { // If toggle count = 0, stop
368
-
369
- disableTimer (TIMERA0);
246
+ if (_timer > NOT_ON_TIMER){
247
+ disableTimer (_timer);
370
248
371
- // keep pin low after stop (OUTCLR = OUTTGL - 1)
372
- *(timera0_outtgl_reg - 1 ) = timera0_bit_mask;
249
+ // Keep pin low after disabling of timer
250
+ digitalWrite (_pin, LOW);
373
251
}
374
-
375
- /* Clear flag */
376
- TCA0.SINGLE .INTFLAGS = TCA_SINGLE_OVF_bm;
252
+
377
253
}
378
- #endif
379
254
380
255
381
256
#ifdef USE_TIMERB0
0 commit comments