source: rtos_arduino/trunk/arduino_lib/hardware/arduino/samd/cores/arduino/Tone.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 7.9 KB
RevLine 
[136]1/* Tone.cpp
2
3 A Tone Generator Library
4
5 Written by Brett Hagman
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with this library; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20
21Version Modified By Date Comments
22------- ----------- -------- --------
230001 B Hagman 09/08/02 Initial coding
240002 B Hagman 09/08/18 Multiple pins
250003 B Hagman 09/08/18 Moved initialization from constructor to begin()
260004 B Hagman 09/09/26 Fixed problems with ATmega8
270005 B Hagman 09/11/23 Scanned prescalars for best fit on 8 bit timers
28 09/11/25 Changed pin toggle method to XOR
29 09/11/25 Fixed timer0 from being excluded
300006 D Mellis 09/12/29 Replaced objects with functions
310007 M Sproul 10/08/29 Changed #ifdefs from cpu to register
320008 S Kanemoto 12/06/22 Fixed for Leonardo by @maris_HY
330009 Arduino.org 15/06/30 Add M0/M0 Pro support
34*************************************************/
35
36
37#include "Tone.h"
38
39
40unsigned long int count_duration=0;
41uint8_t pin_sound=0;
42
43
44void tone(uint8_t pin, unsigned int frequency, unsigned long duration)
45{
46
47 unsigned int tim_per=0, duty=0,presc_tc=0, presc_tcc=0;
48 double freq=0.0,div=0.0;
49 uint8_t isTC = 0 ;
50 uint8_t Channelx ;
51 Tc* TCx ;
52 Tcc* TCCx ;
53
54
55 if((frequency < 20) | (frequency > 25000)) return;
56 freq=frequency * 1.0;
57
58 if(duration !=0)
59 {
60 count_duration= 188 * duration;
61 set_timer5();
62 pin_sound=pin;
63 }
64
65 switch ( g_APinDescription[pin].ulPWMChannel ) //TC or TCC selection
66 {
67 case PWM3_CH0 :
68 TCx = TC3 ; // not work
69 Channelx = 0 ;
70 isTC = 1 ;
71 break;
72
73 case PWM3_CH1: // not work
74 TCx = TC3 ;
75 Channelx = 1;
76 isTC = 1;
77 break;
78
79 case PWM0_CH0 :
80 TCCx = TCC0;
81 Channelx = 0;
82 break;
83
84 case PWM0_CH1 :
85 TCCx = TCC0;
86 Channelx = 1;
87 break;
88
89 case PWM0_CH4 :
90 TCCx = TCC0;
91 Channelx = 0;
92 break;
93
94 case PWM0_CH5 :
95 TCCx = TCC0;
96 Channelx = 1;
97 break;
98
99 case PWM0_CH6 :
100 TCCx = TCC0;
101 Channelx = 2;
102 break;
103
104 case PWM0_CH7 :
105 TCCx = TCC0;
106 Channelx = 3;
107 break;
108
109 case PWM1_CH0 :
110 TCCx = TCC1;
111 Channelx = 0;
112 break;
113
114 case PWM1_CH1 :
115 TCCx = TCC1;
116 Channelx = 1;
117 break;
118
119 case PWM2_CH0 :
120 TCCx = TCC2;
121 Channelx = 0;
122 break;
123
124 case PWM2_CH1 :
125 TCCx = TCC2;
126 Channelx = 1;
127 break;
128 }
129
130
131 switch ( GetTCNumber( g_APinDescription[pin].ulPWMChannel ) ) //clock selection using GCLK3
132 {
133 case 0: // TCC0
134 //Enable GCLK for TCC0 (timer counter input clock)
135 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
136 break ;
137
138 case 1: // TCC1
139 //Enable GCLK for TCC1 (timer counter input clock)
140 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ;
141 break ;
142
143 case 2: // TCC2
144 //Enable GCLK for TCC2 (timer counter input clock)
145 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 )) ;
146 break ;
147
148 case 3: // TC3
149 //Enable GCLK for TC3 (timer counter input clock)
150 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID( GCM_TCC2_TC3 ));
151 break ;
152
153 case 4: // TC4
154 //Enable GCLK for TC4 (timer counter input clock)
155 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
156 break ;
157
158 case 5: // TC5
159 //Enable GCLK for TC5 (timer counter input clock)
160 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 )) ;
161 break ;
162 }
163
164
165
166
167 if((frequency >=20) & (frequency <= 100))
168 {
169 div=1024.0;
170 presc_tcc=TCC_CTRLA_PRESCALER_DIV1024;
171 presc_tc=TC_CTRLA_PRESCALER_DIV1024;
172 }
173 else if((frequency > 100) & (frequency <= 350))
174 {
175 div=256.0;
176 presc_tcc=TCC_CTRLA_PRESCALER_DIV256;
177 presc_tc=TC_CTRLA_PRESCALER_DIV1024;
178 }
179 else if((frequency > 350) & (frequency <= 1900))
180 {
181 div=64.0;
182 presc_tcc=TCC_CTRLA_PRESCALER_DIV64;
183 presc_tc=TC_CTRLA_PRESCALER_DIV1024;
184 }
185 else if((frequency > 1900) & (frequency <= 5500))
186 {
187 div=16.0;
188 presc_tcc=TCC_CTRLA_PRESCALER_DIV16;
189 presc_tc=TC_CTRLA_PRESCALER_DIV1024;
190 }
191 else if((frequency > 5500) & (frequency <= 30000))
192 {
193 div=8.0;
194 presc_tcc=TCC_CTRLA_PRESCALER_DIV8;
195 presc_tc=TC_CTRLA_PRESCALER_DIV1024;
196 }
197 else;
198
199 tim_per=(uint8_t)(floor((8.0e6/(2.0 * div * freq)) - 1.0));
200 duty= (uint8_t)(tim_per / 2);
201 pinPeripheral( pin, g_APinDescription[pin].ulPinType ) ;
202
203 if ( isTC )
204 {
205 // -- Configure TC
206 //DISABLE TCx
207 TCx->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE);
208 //Set Timer counter Mode to 8 bits
209 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8;
210 TCx->COUNT8.CTRLA.reg |= presc_tc;
211 //Set TCx as normal FRQ
212 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_WAVEGEN_NFRQ;
213 //Set TCx in waveform mode Normal PWM
214 TCx->COUNT8.CC[Channelx].reg = duty;
215 //Set PER to maximum counter value (resolution : 0xFF)
216 TCx->COUNT8.PER.reg = tim_per;
217 // Enable TCx
218 TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
219 }
220 else
221 {
222 // -- Configure TCC
223
224 //DISABLE TCCx
225 TCCx->CTRLA.reg &=~(TCC_CTRLA_ENABLE);
226 TCCx->CTRLA.reg |=presc_tcc;
227 //Set TCx as normal FRQ
228 TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ;
229 //Set TCx in waveform mode Normal PWM
230 TCCx->CC[Channelx].reg = duty;
231 //Set PER to maximum counter value (resolution : 0xFF)
232 TCCx->PER.reg = tim_per;
233 //ENABLE TCCx
234 TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ;
235
236 }
237
238 return;
239}
240
241
242void noTone(uint8_t pin)
243{
244 if((pin >= 2) & (pin <= 7)) TCC0->CTRLA.reg &=~(TCC_CTRLA_ENABLE); // disable TCC0
245 else if((pin == 8) | (pin == 9)) TCC1->CTRLA.reg &=~(TCC_CTRLA_ENABLE); // disable TCC1
246 else if ((pin == 10) | (pin ==12)) TC3->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE); // disable TC3
247 else if ((pin == 11) | (pin == 13)) TCC2->CTRLA.reg &=~(TCC_CTRLA_ENABLE); // disable TCC2
248 else;
249
250return;
251}
252
253void set_timer5(void)
254{
255 NVIC_DisableIRQ( TC5_IRQn ) ;
256 NVIC_ClearPendingIRQ( TC5_IRQn ) ;
257 NVIC_SetPriority( TC5_IRQn, 0 ) ;
258
259 //GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
260 GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TC4_TC5 ));
261
262 TC5->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE);
263 TC5->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8 | TC_CTRLA_PRESCALER_DIV1;
264 TC5->COUNT8.INTENSET.reg |= TC_INTENSET_OVF;
265 TC5->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE;
266 NVIC_EnableIRQ( TC5_IRQn ) ;
267}
268
269void TC5_Handler( void )
270{
271 if((TC5->COUNT16.INTFLAG.reg & TC_INTFLAG_OVF))
272 {
273
274 count_duration--;
275 if(count_duration == 0)
276 {
277 noTone(pin_sound);
278 TC5->COUNT8.CTRLA.reg &=~(TC_CTRLA_ENABLE); // disable TC5
279
280 }
281 }
282 TC5->COUNT8.INTFLAG.reg |= ~(TC_INTFLAG_OVF); // reset flag
283
284}
285
286
Note: See TracBrowser for help on using the repository browser.