softTone.c
3.3 KB
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
* softTone.c:
* For that authentic retro sound...
* Er... A little experiment to produce tones out of a Pi using
* one (or 2) GPIO pins and a piezeo "speaker" element.
* (Or a high impedance speaker, but don'y blame me if you blow-up
* the GPIO pins!)
* Copyright (c) 2012 Gordon Henderson
***********************************************************************
* This file is part of wiringPi:
* https://projects.drogon.net/raspberry-pi/wiringpi/
*
* wiringPi is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* wiringPi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with wiringPi.
* If not, see <http://www.gnu.org/licenses/>.
***********************************************************************
*/
#include <stdio.h>
#include <pthread.h>
#include "wiringPi.h"
#include "softTone.h"
#define MAX_PINS 64
#define PULSE_TIME 100
static int freqs [MAX_PINS] ;
static pthread_t threads [MAX_PINS] ;
static int newPin = -1 ;
/*
* softToneThread:
* Thread to do the actual PWM output
*********************************************************************************
*/
static PI_THREAD (softToneThread)
{
int pin, freq, halfPeriod ;
struct sched_param param ;
param.sched_priority = sched_get_priority_max (SCHED_RR) ;
pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ;
pin = newPin ;
newPin = -1 ;
piHiPri (50) ;
for (;;)
{
freq = freqs [pin] ;
if (freq == 0)
delay (1) ;
else
{
halfPeriod = 500000 / freq ;
digitalWrite (pin, HIGH) ;
delayMicroseconds (halfPeriod) ;
digitalWrite (pin, LOW) ;
delayMicroseconds (halfPeriod) ;
}
}
return NULL ;
}
/*
* softToneWrite:
* Write a frequency value to the given pin
*********************************************************************************
*/
void softToneWrite (int pin, int freq)
{
pin &= 63 ;
/**/ if (freq < 0)
freq = 0 ;
else if (freq > 5000) // Max 5KHz
freq = 5000 ;
freqs [pin] = freq ;
}
/*
* softToneCreate:
* Create a new tone thread.
*********************************************************************************
*/
int softToneCreate (int pin)
{
int res ;
pthread_t myThread ;
pinMode (pin, OUTPUT) ;
digitalWrite (pin, LOW) ;
if (threads [pin] != 0)
return -1 ;
freqs [pin] = 0 ;
newPin = pin ;
res = pthread_create (&myThread, NULL, softToneThread, NULL) ;
while (newPin != -1)
delay (1) ;
threads [pin] = myThread ;
return res ;
}
/*
* softToneStop:
* Stop an existing softTone thread
*********************************************************************************
*/
void softToneStop (int pin)
{
if (threads [pin] != 0)
{
pthread_cancel (threads [pin]) ;
pthread_join (threads [pin], NULL) ;
threads [pin] = 0 ;
digitalWrite (pin, LOW) ;
}
}