chiark / gitweb /
Makefiles: Honour LDCONFIG from the environment
[wiringPi.git] / wiringPi / softTone.c
1 /*
2  * softTone.c:
3  *      For that authentic retro sound...
4  *      Er... A little experiment to produce tones out of a Pi using
5  *      one (or 2) GPIO pins and a piezeo "speaker" element.
6  *      (Or a high impedance speaker, but don'y blame me if you blow-up
7  *      the GPIO pins!)
8  *      Copyright (c) 2012 Gordon Henderson
9  ***********************************************************************
10  * This file is part of wiringPi:
11  *      https://projects.drogon.net/raspberry-pi/wiringpi/
12  *
13  *    wiringPi is free software: you can redistribute it and/or modify
14  *    it under the terms of the GNU Lesser General Public License as
15  *    published by the Free Software Foundation, either version 3 of the
16  *    License, or (at your option) any later version.
17  *
18  *    wiringPi is distributed in the hope that it will be useful,
19  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *    GNU Lesser General Public License for more details.
22  *
23  *    You should have received a copy of the GNU Lesser General Public
24  *    License along with wiringPi.
25  *    If not, see <http://www.gnu.org/licenses/>.
26  ***********************************************************************
27  */
28
29 #include <stdio.h>
30 #include <pthread.h>
31
32 #include "wiringPi.h"
33 #include "softTone.h"
34
35 #define MAX_PINS        64
36
37 #define PULSE_TIME      100
38
39 static int freqs         [MAX_PINS] ;
40 static pthread_t threads [MAX_PINS] ;
41
42 static int newPin = -1 ;
43
44
45 /*
46  * softToneThread:
47  *      Thread to do the actual PWM output
48  *********************************************************************************
49  */
50
51 static PI_THREAD (softToneThread)
52 {
53   int pin, freq, halfPeriod ;
54   struct sched_param param ;
55
56   param.sched_priority = sched_get_priority_max (SCHED_RR) ;
57   pthread_setschedparam (pthread_self (), SCHED_RR, &param) ;
58
59   pin    = newPin ;
60   newPin = -1 ;
61
62   piHiPri (50) ;
63
64   for (;;)
65   {
66     freq = freqs [pin] ;
67     if (freq == 0)
68       delay (1) ;
69     else
70     {
71       halfPeriod = 500000 / freq ;
72
73       digitalWrite (pin, HIGH) ;
74       delayMicroseconds (halfPeriod) ;
75
76       digitalWrite (pin, LOW) ;
77       delayMicroseconds (halfPeriod) ;
78     }
79   }
80
81   return NULL ;
82 }
83
84
85 /*
86  * softToneWrite:
87  *      Write a frequency value to the given pin
88  *********************************************************************************
89  */
90
91 void softToneWrite (int pin, int freq)
92 {
93   pin &= 63 ;
94
95   /**/ if (freq < 0)
96     freq = 0 ;
97   else if (freq > 5000) // Max 5KHz
98     freq = 5000 ;
99
100   freqs [pin] = freq ;
101 }
102
103
104 /*
105  * softToneCreate:
106  *      Create a new tone thread.
107  *********************************************************************************
108  */
109
110 int softToneCreate (int pin)
111 {
112   int res ;
113   pthread_t myThread ;
114
115   pinMode      (pin, OUTPUT) ;
116   digitalWrite (pin, LOW) ;
117
118   if (threads [pin] != 0)
119     return -1 ;
120
121   freqs [pin] = 0 ;
122
123   newPin = pin ;
124   res    = pthread_create (&myThread, NULL, softToneThread, NULL) ;
125
126   while (newPin != -1)
127     delay (1) ;
128
129   threads [pin] = myThread ;
130
131   return res ;
132 }
133
134
135 /*
136  * softToneStop:
137  *      Stop an existing softTone thread
138  *********************************************************************************
139  */
140
141 void softToneStop (int pin)
142 {
143   if (threads [pin] != 0)
144   {
145     pthread_cancel (threads [pin]) ;
146     pthread_join   (threads [pin], NULL) ;
147     threads [pin] = 0 ;
148     digitalWrite (pin, LOW) ;
149   }
150 }