@@ -34,35 +34,54 @@ Version Modified By Date Comments
34
34
0010 Arduino.org 16/07/27 Added Arduino Primo support
35
35
*************************************************/
36
36
37
-
37
+ # include " Arduino.h "
38
38
#include " Tone.h"
39
39
#include " WVariant.h"
40
40
41
41
unsigned long int count_duration=0 ;
42
42
volatile bool no_stop = false ;
43
43
uint8_t pin_sound=0 ;
44
+ static uintptr_t _toneToken = (uintptr_t )(&_toneToken);
44
45
45
46
46
47
void tone (uint8_t pin, unsigned int frequency, unsigned long duration)
47
48
{
49
+ static_assert (sizeof (unsigned long ) == sizeof (uint32_t ));
50
+
48
51
unsigned int time_per=0 ;
49
-
50
- if ((frequency < 20 ) | (frequency > 25000 )) return ;
51
-
52
+
53
+ // limit frequency to reasonable audible range
54
+ if ((frequency < 20 ) | (frequency > 25000 )) {
55
+ LOG_LV1 (" TON" , " frequency outside range [20..25000] -- ignoring" );
56
+ return ;
57
+ }
58
+
59
+ // Use fixed PWM2 (due to need to connect interrupt)
60
+ if (!HwPWMx[2 ]->isOwner (_toneToken) &&
61
+ !HwPWMx[2 ]->takeOwnership (_toneToken)) {
62
+ LOG_LV1 (" TON" , " unable to allocate PWM2 to Tone" );
63
+ return ;
64
+ }
52
65
53
66
float per=float (1 )/frequency;
54
67
time_per=per/0.000008 ;
55
68
unsigned int duty=time_per/2 ;
56
- if (duration > 0 ){
69
+ if (duration > 0 ) {
57
70
no_stop = false ;
58
71
float mil=float (duration)/1000 ;
59
- if (per>mil)
72
+ if (per>mil) {
60
73
count_duration=1 ;
61
- else
74
+ } else {
62
75
count_duration= mil/per;
63
- }
64
- else
76
+ }
77
+ } else {
65
78
no_stop = true ;
79
+ }
80
+
81
+ // PWM configuration depends on the following:
82
+ // [ ] time_per
83
+ // [ ] duty ( via seq )
84
+ // [ ] pin ( via pins[0] )
66
85
67
86
// Configure PWM
68
87
static uint16_t seq_values[]={0 };
@@ -97,6 +116,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration)
97
116
break;
98
117
}
99
118
#else
119
+
100
120
// Use fixed PWM2, TODO could conflict with other usage
101
121
uint32_t pins[NRF_PWM_CHANNEL_COUNT]={NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED, NRF_PWM_PIN_NOT_CONNECTED};
102
122
pins[0 ] = g_ADigitalPinMap[pin];
@@ -110,7 +130,7 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration)
110
130
nrf_pwm_configure (PWMInstance, NRF_PWM_CLK_125kHz, NRF_PWM_MODE_UP, time_per);
111
131
nrf_pwm_decoder_set (PWMInstance, NRF_PWM_LOAD_COMMON, NRF_PWM_STEP_AUTO);
112
132
nrf_pwm_sequence_set (PWMInstance, 0 , &seq);
113
- nrf_pwm_shorts_enable (PWMInstance, NRF_PWM_SHORT_SEQEND0_STOP_MASK);
133
+ nrf_pwm_shorts_enable (PWMInstance, NRF_PWM_SHORT_SEQEND0_STOP_MASK); // shortcut for when SEQ0 ends, PWM output will automatically stop
114
134
115
135
// enable interrupt
116
136
nrf_pwm_event_clear (PWMInstance, NRF_PWM_EVENT_PWMPERIODEND);
@@ -125,6 +145,11 @@ void tone(uint8_t pin, unsigned int frequency, unsigned long duration)
125
145
126
146
void noTone (uint8_t pin)
127
147
{
148
+ if (!HwPWMx[2 ]->isOwner (_toneToken)) {
149
+ LOG_LV1 (" TON" , " Attempt to set noTone when not the owner of the PWM peripheral. Ignoring call...." );
150
+ return ;
151
+ }
152
+
128
153
#if 0
129
154
uint8_t pwm_type=g_APinDescription[pin].ulPWMChannel;
130
155
NRF_PWM_Type * PWMInstance = NRF_PWM0;
@@ -180,13 +205,15 @@ void PWM2_IRQHandler(void){
180
205
nrf_pwm_event_clear (NRF_PWM2, NRF_PWM_EVENT_PWMPERIODEND);
181
206
if (!no_stop){
182
207
count_duration--;
183
- if (count_duration == 0 )
184
- noTone (pin_sound);
185
- else
186
- nrf_pwm_task_trigger (NRF_PWM2, NRF_PWM_TASK_SEQSTART0);
187
- }
188
- else
208
+ if (count_duration == 0 ) {
209
+ nrf_pwm_task_trigger (NRF_PWM2, NRF_PWM_TASK_STOP);
210
+ nrf_pwm_disable (NRF_PWM2);
211
+ } else {
212
+ nrf_pwm_task_trigger (NRF_PWM2, NRF_PWM_TASK_SEQSTART0);
213
+ }
214
+ } else {
189
215
nrf_pwm_task_trigger (NRF_PWM2, NRF_PWM_TASK_SEQSTART0);
216
+ }
190
217
}
191
218
192
219
#ifdef __cplusplus
0 commit comments