Part 1: Music Format

CSE466 00AU Music Format

While there were several good ideas, at least two or three of you agreed with something like this:

<MUSIC> = <tempo><events>
<tempo> = one byte indicating the duration, in milliseconds, of a single timeslice
<events> = <event>*
<event> = <s><tne><chan><note><amp>  (this is a two byte packet)
<p> = always set.  Indicates start of packet (see below, be careful!)
<tne> = 5-bits of time to next event, in number of timeslices (max of 32)
<chan> = 2 bits identifying the channel 0-3
<note> = 6-bits to identify note. This equivalent to 64/12 octaves, a pretty good range. Everyone seemed to agree on that.
<amp> = 2 bits of amplitude with zero = off.

Using this format:

Another way to look at an event

I will publish the midi to cse converter this weekend so that you can put some real music into your ROM. But, it should be fairly straighforward for you to write some short test sequences.

Here one additional rule to the music format...a special continuation packet. A continuation packet has a valid TNE, but contains no other information. A continuation packet looks like this:
<p> = 1
<tne> = valid number between 0 and 31
<chan> = x (don't care, but no necessarily zero)
<note> = 1  (indicates that this is a continuation packet when amp = 0)
<amp> = 0   (the idea is that if amp=0 then we can use note for other purposes or special commands)
 
Don't get the above confused with an off event which looks like this
<p> = 1
<tne> = valid number between 0 and 31
<chan> = valid number between 0 and 3
<note> = 0  (indicates that this is an off event for the specified channel)
<amp> = x  (amplitude is don't care if note = 0)
 
If you receive a continuation packet then use <tne> but continue playing the current tones are they are. This is how we handle event separations that are longer than the maximum.

Part 2 and 3: Psuedo Code and Timing Analysis
I was looking only for the code that you need to run in your tone generation ISR. In my opinion, this includes that math for computing the output value, and the time-slice count down. When the time slice count down is expired, the ISR should change the output function parameters based on a set of "pending" values, and it should set a flag. The pending values would then have to be updated by the Event task if the tne countdown has expired. I'm guessing that the ISR is about 50, in which case we need to leave 5 instructions for other things (in the worst case), for a total of 55 instruction between interrupts.  This maximum frequency that you can run the interrupt routine is 2.7M/55 = ~50KHz. This tells me that 10KHz to 20KHz if probably quite feasible while leaving some processor for other tasks. Due to sampling effects, the highest frequency that we should try to create with our system is 1/4 of the sample frequency (max stride = 64). At 10KHz we can do 2.5KHz at 20KHz we can do 5KHz.

Part 4: Data Rate
Using this format, the worst case data occurs when every channel changes on every timeslice. This case requires 2bytes/event * 4events/timeslice = 8bytes/timeslice.  If we set the timeslice according to the homework: 200 slices/second * 8 = 1600 bytes * 8 = 12,800 baud. Too Fast!  It looks like we will have to run at a longer timeslice. Maybe 20ms typical. Now the worst case is one fourth of that, or 3200 baud. Which should be sustainable for short bursts if necessary.