RingTone Player



Copyright (c) 2005 Javier Martinez. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

Here is a funny project, a RingTone player. The main purpose is to read the songs stored in a serial eeprom and play them with the help of a piezo-speaker. Useful to to put it inside a Christmas box to delight us with hundreds of short songs.



What hell is a RingTone?

A RingTone it's a musical score developed by Nokia, it's called NokRing tones or RTTTL (RingTone Text Transfer Language) tones. A song it's written in this way:





The RTTTL format specifications can be found in the web, a plain text of this specs can be found here (local copy). In order to clarify concepts I'll try to explain quickly the RTTTL format. The song name it's anything before the first “:” character. The next section after first “:” and before the second “:” it's the control field; in this field it's defined the song defaults:





Scientific Pitch Notation, ISO 16:1975 standard

Natural

C


D


E

F


G


A


B

Sharp


C#


D#



F#


G#


A#


Italian

Do


Re


Mi

Fa


Sol


La


Si

Octave 4

261,6

277,2

293,7

311,1

329,6

349,2

370,0

392,0

415,3

440,0

466,2

493.9

Octave 5

523.3

554.4

587.3

622.3

659.3

698.5

740

784

830.6

880

932.3

987.8

Octave 6

1047

1109

1175

1245

1319

1397

1480

1568

1661

1760

1865

1976

Octave 7

2093

2217

2349

2489

2637

2794

2960

3136

3322

3520

3729

3951





Anything after the second “:” utill the end of the song are the song notes. In our Simpsons song (d=4,o=5,b=160) a single note “... , g , ...” will be played with some defaults values, as is was written like “... , 4g5 , ...”. The letter “p” is a special note with no sound, and the special character “.” increase the note duration x1.5.





Implementation description

Here I'll try to write some words about how the note's sounds are generated by the PIC16F628. Basically, the frequency note it's generated by PWM module over pin_b3, the note duration it's controlled by TMR1 interrupts, and waveform envelope it's controlled by a couple of resistors.





Frequency note

On each note the PIC will configure the PWM module to make the note with the desired frequency. Based on some constants (fosc, TMR2 prescaler, etc.) the wave period it's managed by PR2 register and the Duty Cycle by the CCPR1 register.

PR2 = Int ( fosc / ( 4 * TMR2presc * fnote ) )



Note

Frequency (Hz)

PR2 (O4)

TMR2 (ms)

C

261,6

238

3,824

C#

277,2

225

3,616

D

293,7

212

3,408

D#

311,1

200

3,216

E

329,6

189

3,040

F

349,2

178

2,864

F#

370,0

168

2,704

G

392,0

159

2,560

G#

415,3

150

2,416

A

440,0

142

2,288

A#

466,2

134

2,160

B

493,9

126

2,032



As you can see, only notes of Octave 4 are in this table. Octaves 5, 6 and 7 double the frequency from previous octave, so PR2 value will be the half value in each step. As a first aproach, CCPR1 value will be half the PR2 value in order to have a duty cycle of 50%.



Note duration

This is done by TMR1 module, using interrupts to get the desired note duration control as close to real time. To get a fine management of note duration, I've splitted each “beat” into 32 “tics”, this will help us to manage notes with short duration (like 1/32 ones). TMR1 interrupt is programmed to loop each “tic”, here's a couple of tables with the neccesary init values:



Note duration

Beats

Tics

1 / 1

4 / 1

128

1 / 2

4 / 2

64

1 / 4

4 / 4

32

1 / 8

4 / 8

16

1 / 16

4 / 16

8

1 / 32

4 / 32

4



Init_TMR1 = int ( 65536 - ( 60 * fosc / ( bpm * tics * 4 * TMR1presc ) ) )



bpm

Init_TMR1

Init_TMR1_H

Init_TMR1_L

TMR1 (ms)

25

28036

109

132

75,000

28

32053

125

53

66,966

31

35294

137

222

60,484

35

38750

151

94

53,572

40

42098

164

114

46,876

45

44702

174

158

41,668

50

46786

182

194

37,500

56

48794

190

154

33,484

63

50655

197

223

29,762

70

52143

203

175

26,786

80

53817

210

57

23,438

90

55119

215

79

20,834

100

56161

219

97

18,750

112

57165

223

77

16,742

125

58036

226

180

15,000

140

58839

229

215

13,394

160

59676

233

28

11,720

180

60327

235

167

10,418

200

60848

237

176

9,376

225

61369

239

185

8,334

250

61786

241

90

7,500

280

62187

242

235

6,698

310

62511

244

47

6,050

355

62895

245

175

5,282





Waveform envelope

Aplying all I've expained above we can play songs, perhaps not the best but it works. Certainly it songs like whistles. In a first aproach a couple of resistors will give “some” amplitude control. The basic idea is to implement de amplitude decay of a piano note; that is, once a piano key is pressed the sound goes down in a few seconds.

The decay of the note it's fixed by the “fail & success” method, currently values are: 150 msecs for 66% amplitude and 300 msecs for 33% amplitude. The values (in tics) to be computed in TMR1 interrupt are:



bpm

66%

33%

25

2

4

28

2

4

31

2

4

35

2

5

40

3

6

45

3

7

50

4

8

56

4

8

63

5

10

70

5

11

80

6

12

90

7

14

100

8

16

112

8

17

125

10

20

140

11

22

160

12

25

180

14

28

200

15

31

225

17

35

250

20

40

280

22

44

310

24

49

355

28

56







A final modification will set the Duty Cycle at 12.5%, this will add more armonics to wave and will sound better. Here're some audio examples in MP3 format:



Score:

Bach_Badinerie:d=16,o=6,b=125:8b,d7,b,8f#,b,f#,8d,f#,d,4b5,f#5,b5,d,b5,c#,b5,c#,
a#5,c#,e,c#,8d,8b5,8b,d7,b,8f#,b,f#,8d,f#,d,4b5,8d,8d,8d,8d,8b,8d,32d,32c#,b5,32d,32c#,
8c#,8f#,8f#,8f#,8f#,8d7,8f#,32f#,32f,32f#,32f,8f,c#,f#,a,f#,g#,f#,g#,f#,f,g#,b,g#,a,
g#,a,g#,f#,a,f#,f,f#,b,f#,f,f#,c#7,f#,f,f#,d7,f#,f,f#,d7,c#7,b,c#7,a,g#,f#,8a,8g#,4f#,1p




Note: These sound files were recorded through a microphone close to the piezo-speaker, my apologies about the sorround noise.



Building the music score file

Once you've collected some songs to store them in the EEPROM, you must build a text file with all of them. You can use the already supplied file to see how to do it. Anyway here's some tips to build it succesfully:



Storing songs into EEPROM

In order to store songs in EEPROM you'll need an external serial adapter circuit (like a MAX232). The circuit have a 5 pin header to do this. Close the jumper before anything else, configure your serial teminal as “300,8,n,1” (yes, 300 bauds) and power up the circuit. You'll see a short message “RTP” in the terminal window. Now send a text file with all your songs, the size of the file must be limited to the size of the EEPROM.

When the text file is already transfered, power off the circuit and open the jumper. That's all!

Note: other way to program the EEPROM is using an external programmer. Use a socket to take off the EEPROM from the circuit.





Aditional pictures

A Christmas “box” for the RTTTL player:



Circuit ready to put it in:



Links

Where to find RingTones:

Online RTTTL player (you'll need a MIDI player in your system):





Eagle files (PCB & circuit)

... to build your own PCB circuit are here.




The source code and HEX file

Source code written in JAL to program the PIC are here.

HEX files.

A sample sound text file to program the EEPROM, take it here.



Legal notes

The source code of this project is GNU GPL

This file, graphics and photographs are GNU FDL

The Eagle circuit was done using the freeware version.





(c)2005 Javier Martínez.