Project 9: Alarm Clock



Project 10 (Last): X-mas Carol Using Interrupts

1. Goals

a. To learn programming of interrupts.

b. To learn programming of concurrent tasks using interrupts.

2. Introduction

In this project, you will create a Christmas carol box using the timer interrupts. Two songs are given and you will implement both which can be chosen by pressing the XIRQ button. Timer Interrupts allow much more accurate control of pitch and length of notes resulting in ease of song implementation.

3. Project description

Implement two songs using OC2 and OC3 interrupts. Two songs are “Silent Night” and “Jingle Bells” (see attached), and pressing the XIRQ switch should change the song from one to another. If the XIRQ switch is not pressed until the end of the song, the same song is repeated. The pitch and length of the note must be accurate (should not use any guess work) as well as the rests (pauses). How to compute these values is described in detail in the following section.

4. Implementation Hints

First interrupts are assigned as follow:

OC2 interrupts: controls the pitch of note, since it is connected to the speaker.

OC3 interrupts: controls the length of the note.

Next, we need to create an accurate song table.

(1) Timing of music notes

There are two kinds of timing periods you have to compute for implementation both in number of cycles (500 nano sec): one for pitch and the other for duration.

First, consider the number of required cycles for the pitch of a note. Since we are going to use the toggle mode of OC2, the cycle for a note should represent the width of one pulse (half cycle of a complete square wave period), i.e.

OC2 toggle cycles = (1/(2*Pitch_frequency)) / 500 nsec

The following table shows the result of example computations. Please fill in blank cells for your implementation.

|Note |Frequency (Hz) |68HC11 cycles |

|A3 |440 | |

|A4 |880 | |

|C5 |1,046.5 |$3bb |

|C#5 |1,108.5 |$386 |

|D5 |1,174.5 | |

|D#5 |1,244 |$324 |

|E5 |1,318 |$2f7 |

|F5 |1,397 | |

|F#5 |1,480 |$2a4 |

|G5 |1,568 | |

|G#5 |1,661 |$25a |

|A5 |1,760 |$238 |

|A#5 |1,865 | |

|B5 |1,976 | |

|C6 |2,093 | |

|C#6 |2,217 |$1c3 |

|D6 |2,349 | |

|D#6 |2,489 | |

|E6 |2,637 |$17b |

|F6 |2,794 | |

|F#6 |2,960 | |

|G6 |3,136 | |

|G#6 |3,322 | |

Note: In the above, G6 means note G at octave-6. The frequency difference between the consecutive octaves is twice. For example, G5 is 1,568HZ and G6 is 3,136 Hz (=2*1,568). Using this relationship, you can find frequencies for any notes in any octaves using the basic notes given in the above table.

Next, you need to compute the duration of each note. The duration of each note determines the speed of a song and is represented by beats-per-minute of a quarter note. Let’s assume that we want to play a song with 128 beats per minute speed ( most songs are within the range of 100 – 150 beats per minute) . Then the quarter note is played as 2.1 beats per second which is equivalent to 937,500 (=(1/(2.1))/(500nsec)) 68HC11 cycles per second. Unfortunately, this time length is longer that the maximum time that can be handled by the 16-bit timer of 68HC11. Therefore, we may have to use multiple count of small lengths. For clarification, see following table.

|Note length |68HC11 cycles |Multiple of 1/64 note |

|1/4 note |937,500 |16 |

|1/8 note |468,750 |8 |

|1/16 note |234,373 |4 |

|1/32 note |117,188 |2 |

|1/64 note |58,594 |1 |

| |= $ e4e1 | |

Clearly, the nearest fit to the 16bit timer is the 1/64 note, and the rest of lengths can be represented by multiple of 1/64 notes which is implemented by OC3. Using these information we wish to write the song table as follows. ( I purposely left the definitions of some notes as blank.)

; Note definitions

Coct5 = 3bb

Doct5 =

Eoct5 =

Foct5 =

Fsoct5 =

Goct5 =

Aoct5 =238

Boct5 =

Coct6 =

Doct6 =

Eoct6 = 17b

Pause = 1ff

Jingle: dw Doct5, 10, Boct5, 10, Aoct5, 10, Goct5, 10

dw Doct5, 20, Pause, 20

dw Doct5, 10, Boct5, 10, Aoct5, 10, Goct5, 10

dw Eoct5, 20, Pause, 20

dw Eoct5, 10, Coct6, 10, Boct5, 10, Aoct5, 10

dw Fsoct5, 20, Pause, 20

dw Doct6, 10, Doct6, 10, Coct6, 10, Aoct5, 10

dw Boct5, 20, Pause, 20

EndJingle: dw 0

For “Silent Night”, the data would start like the following:

SilentN: dw Goct5, c, Aoct5, 4, Goct5, 8, Eoct5, 18

dw Goct5, c, Aoct5, 4, Goct5, 8, Eoct5, 18

dw Doct6, 10, Doct6, 8, Boct5, 18

dw Coct6, 10, Coct6, 8, Goct5, 18

EndSilentN: dw 0

* Note, these are only the partial data.

Once these basic tables are established, the next steps are writing the interrupt routines.

(2) Interrupt implementation

Since OC2 implements the pitch of a note, it should be a simple timed interrupt based on the cycles of each note. Assume that the number of cycles for pitch is stored in Pulwidth then the OC2 interrupt service routine should simply be.

; OC2 interrupt service routine

OC2svr: ldx #Regbas

ldd Pulwidth

addd TOC2,x

std TOC2,x

bclr TFLG1,x,bf

rti

Next, OC3 interrupt include few things. It should be responsible to keeping in track of the duration of each note represented by multiple of 1/64 notes. In addition, it has to check if a note is rest or not. If it is rest, the connection to timed I/O logic should be disconnected. In addition, it should change the data at Pulwidth such that OC2 changes its pitch for the next note. Here is the starting part of the OC3 service routine.

Len64th = e4e1 ;Number of cycles for the length one 64th note

OC3svr: ldx #Regbas

ldd #Len64th

addd TOC3,x ;Prepare next timed interrupt

std TOC3,x

; Count of multiple 1/64 len

dec NoteLen

.

.

.

This project should give you a good summary of what is the interrupt and how you can use. Since this is the last project, please try to write a clean and professional look of the code.

Check-off Due: Dec. 16 Thursday

Report Due: Dec. 17, Friday

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download