Gordons Projects

--> Projects Top-Level GIT

Initial GIT submission
[pibrella] / pwmTones.c
1 /*
2  * pwmTones.c:
3  *      Demonstration of using the PWM generator on the Raspberry Pi
4  *      to play simple tunes.
5  *
6  * Copyright (c) 2012-2013 Gordon Henderson. <projects@drogon.net>
7  ***********************************************************************
8  * This file is part of wiringPi:
9  *      https://projects.drogon.net/raspberry-pi/wiringpi/
10  *
11  *    wiringPi is free software: you can redistribute it and/or modify
12  *    it under the terms of the GNU Lesser General Public License as published by
13  *    the Free Software Foundation, either version 3 of the License, or
14  *    (at your option) any later version.
15  *
16  *    wiringPi is distributed in the hope that it will be useful,
17  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *    GNU Lesser General Public License for more details.
20  *
21  *    You should have received a copy of the GNU Lesser General Public License
22  *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
23  ***********************************************************************
24  */
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <math.h>
31
32 #include <wiringPi.h>
33
34 // Beats per minute
35
36 #define TEMPO   120
37 #define MS_PER_BEAT     ((1000*60/TEMPO)/4)
38
39 // Simple scale frequencies
40
41 static const int scale [8] = { 262, 294, 330, 349, 392, 440, 494, 525 } ;
42
43 // Calculated PWM Range values
44
45 static int pwmR [8] ;
46
47 // Our tune: Note followed by duration in quarter crotchets
48
49 const int tune [] = 
50 {
51   0,6, 1,2, 2,6, 0,2,           // Doe, a deer, a
52    2,4, 0,4, 2,8,               //   fe - male deer,
53   1,6, 2,2, 3,2, 3,2, 2,2, 1,2, // ray, a drop of gold-en
54    3,14, -1,2,                  //   sun.
55   2,6, 3,2, 4,6, 2,2,           // Me, a name I
56    4,4, 2,4, 4,8,               //   call my - self
57   3,6, 4,2, 5,2, 5,2, 4,2, 3,2, // Far, a long, long way to
58     5, 16,                      //  run.
59   4,6, 0,2, 1,2, 2,2, 3,2, 4,2, // Sew, a nee - dle pull - ing
60     5,14, -1,2,                 // thread
61   5,6, 1,2, 2,2, 3,2, 4,2, 5,2, // La, a note to fol - low
62    6,14, -1,2,                  //  so.
63   6,6, 2,2, 3,2, 4,2, 5,2, 6,2, // Tea, a drink with jam and
64    7,12, -1,4,                  //  bread
65   6,2, 6,2, 5,4, 4,4, 6,4, 4,4, // that will bring us back to
66   7,4, 4,4, 2,4, 1,4,           // do, oh, oh, oh!
67   
68   
69   -1, 16, -1, -1
70 } ;
71
72 static void revokeRoot (void)
73 {
74   if (getuid () + geteuid () == 0)      // Really running as root
75     return ;
76
77   if (geteuid () == 0)                  // Running setuid root
78     seteuid (getuid ()) ;               // Change effective uid to the uid of the caller
79 }
80
81
82 // The works
83
84 int main (void)
85 {
86   int note, dur ;
87   int i ;
88
89   wiringPiSetup () ;
90   revokeRoot    () ;
91
92 // PWM Setup
93
94   pinMode    (1, PWM_OUTPUT) ;
95   pwmSetMode (PWM_MODE_MS) ;
96   pwmWrite   (1, 0) ;           // Off
97
98 // Calculate the pwmRange values based on the frequency table:
99
100   for (i = 0 ; i < 8 ; ++i)
101     pwmR [i] = (int)rint ( 600000 / (double)scale [i]) ;
102
103 // Print out for reference:
104
105   printf ("Note/PWMR values:\n") ;
106   for (i = 0 ; i < 8 ; ++i)
107     printf ("%2d: %4d -> %4d\n", i, scale [i], pwmR [i]) ;
108
109
110 // Play the tune
111
112   for (;;)
113   {
114     for (i = 0 ;; i += 2)
115     {
116       note = tune [i] ;
117       dur  = tune [i + 1] ;
118       if ((note == -1) && (dur == -1))
119         break ;
120
121       if (note == -1)   // Pause
122         printf ("Rest  ") ;
123       else
124       {
125         printf ("Note: %d  ", note) ;
126         pwmSetRange (pwmR [note]) ;
127         pwmWrite    (1, pwmR [note] / 2) ;
128       }
129
130 // Delay for the note duration
131
132       printf ("Time: %4d\n", MS_PER_BEAT * dur) ;
133       delay (MS_PER_BEAT * dur - 5) ;
134
135 // Stop sound for a few mS between notes
136
137       pwmWrite (1, 0) ;
138       delay (5) ;
139  
140     }
141   }
142
143   return 0 ;
144 }