-
Notifications
You must be signed in to change notification settings - Fork 9
/
tone1.ino
131 lines (105 loc) · 3.29 KB
/
tone1.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/*
Melody
Plays a melody
This example code is in the public domain.
http://arduino.cc/en/Tutorial/Tone
*/
#include "pitches.h"
void noTone(unsigned long ulPin);
void tone(unsigned long ulPin, unsigned long frequency, long duration);
// notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4,4,4,4,4 };
void setup() {
}
void loop() {
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 8; thisNote++) {
// to calculate the note duration, take one second
// divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000/noteDurations[thisNote];
tone(8, melody[thisNote],noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(8);
}
delay(3000);
}
void loop1() {
// no need to repeat the melody.
tone(8,100,30);
delay(50);
}
/*
Tone generator
v1 use timer, and toggle any digital pin in ISR
funky duration from arduino version
TODO use FindMckDivisor?
timer selected will preclude using associated pins for PWM etc.
could also do timer/pwm hardware toggle where caller controls duration
*/
// timers TC0 TC1 TC2 channels 0-2 ids 0-2 3-5 6-8 AB 0 1
// use TC1 channel 0
#define TONE_TIMER TC1
#define TONE_CHNL 0
#define TONE_IRQ TC3_IRQn
// TIMER_CLOCK4 84MHz/128 with 16 bit counter give 10 Hz to 656KHz
// piano 27Hz to 4KHz
static uint8_t pinEnabled[PINS_COUNT];
static uint8_t TCChanEnabled = 0;
static boolean pin_state = false ;
static Tc *chTC = TONE_TIMER;
static uint32_t chNo = TONE_CHNL;
volatile static int32_t toggle_count;
static uint32_t tone_pin;
// frequency (in hertz) and duration (in milliseconds).
void tone(uint32_t ulPin, uint32_t frequency, int32_t duration)
{
const uint32_t rc = VARIANT_MCK / 256 / frequency;
tone_pin = ulPin;
toggle_count = 0; // strange wipe out previous duration
if (duration > 0 ) toggle_count = 2 * frequency * duration / 1000;
else toggle_count = -1;
if (!TCChanEnabled) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)TONE_IRQ);
TC_Configure(chTC, chNo,
TC_CMR_TCCLKS_TIMER_CLOCK4 |
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC
chTC->TC_CHANNEL[chNo].TC_IER=TC_IER_CPCS; // RC compare interrupt
chTC->TC_CHANNEL[chNo].TC_IDR=~TC_IER_CPCS;
NVIC_EnableIRQ(TONE_IRQ);
TCChanEnabled = 1;
}
if (!pinEnabled[ulPin]) {
pinMode(ulPin, OUTPUT);
pinEnabled[ulPin] = 1;
}
TC_Stop(chTC, chNo);
TC_SetRC(chTC, chNo, rc); // set frequency
TC_Start(chTC, chNo);
}
void noTone(uint32_t ulPin)
{
TC_Stop(chTC, chNo); // stop timer
digitalWrite(ulPin,LOW); // no signal on pin
}
// timer ISR TC1 ch 0
void TC3_Handler ( void ) {
TC_GetStatus(TC1, 0);
if (toggle_count != 0){
// toggle pin TODO better
digitalWrite(tone_pin,pin_state= !pin_state);
if (toggle_count > 0) toggle_count--;
} else {
noTone(tone_pin);
}
}