Playground Sketch Writes to Sound Chip Using Code I Don't Understand

Hi Everyone,

I am new to micro controller programming, but I have some software development experience. I am looking at the following tutorial and trying to figure out what each piece of the code is doing....

http://playground.arduino.cc/Main/AY38910

So far, I have been able to understand most of what is happening by doing web searches and reading the sound chip's manual. However, the following code is giving me trouble because I haven't been able to phrase a search that produces useful results...

void set_chA(int i)
{
  write_data(0x00, tp[i]&0xff);
  write_data(0x01, (tp[i] >> 8)&0x0f);    
}

So this function gets a musical note number from a song array. The first one is a "60" (which is normally middle C) Then, it looks in an array that stores the information on what value the sound chip needs to produce that note. In the case of "60" that value is "478." Then, I don't understand what is happening with the "&0xff" or the (tp >> 8 )&0x0f) The processor is looking for an 8 bit value for fine pitch tuning in the first "write_data" and a 4 bit value for coarse pitch tuning in the second. I have been searching through C syntax references and I have seen that the "&" is usually a pointer, but I can't figure out how it is working here. 0xff would be the maximum number of 8 bit combinations and 0x0f would be the maximum for 4, right? Is that somehow significant or is that a coincidence? Thanks.

MoZI: So far, I have been able to understand most of what is happening by doing web searches and reading the sound chip's manual. However, the following code is giving me trouble because I haven't been able to phrase a search that produces useful results...

void set_chA(int i)
{
  write_data(0x00, tp[i]&0xff);
  write_data(0x01, (tp[i] >> 8)&0x0f);    
}

Does that work? I looked at the code you posted the link to. It doesn't send out the data properly. Normally, code like this is used to send a 16 bit (or larger) number to a device by using multiple 8 bit writes. For example, a value like this:

uint16_t value = 0x1234

Would be send out like this:

write_data (0, value & 0xFF); // send out lower half write_date (1, value >> 8); // send out upper half.

This is what happens:

0x1234 & 0xFF = 0x34 0x1234 >> 8 = 0x0012 (the 34 "falls off the end")

But, the code you posted does not send out the original value. The second line (masking with 0x0F) seems wrong.

I haven't tested the code yet. My chip is coming in the mail, but I found a two year old forum post where people were talking about doing the project. Some people said the code wasn't working, but no one mentioned that part of the code.

I'm still not exactly sure what the numbers assigned to each note mean. The sound chip manual has several equations on how to get them to produce the note you want with the clock you are using, but I haven't deciphered the specifics. The trend, though, is that higher notes have lower numbers. The highest note in this example is 0.

The code is using the same number to derive both the fine and coarse tune which seems wrong to me also, but I don't know enough about all the pieces to say where it's wrong.

I am looking up masking to try to understand it better, also.

MoZI: I am looking up masking to try to understand it better, also.

Good. Look up "bit masks", "high and lo bytes", "bit shifting" and "big-endian/little endian". That should help you some.

Thanks! Those search terms are helping already. I knew I was in trouble when I didn't even know what to Google to find the answer.

Ok check this out…

The chip actually uses a 12-bit value to create the note, but only has 8 bit chunks of memory to store it in. So it has a “Coarse Tune” byte (which only uses 4 bits) and a “FIne Tune” byte, but they are in different registers. So when I said earlier that it was giving it a value of 478. That gives a binary value of “0b111011110,” which is 9 bits.

So tell me if this makes sense…
The first function call passes in 478 as an int which is then converted to binary “111011110.”
Then, the &0xff is used to format the data into an 8 bit piece that knocks off the left most bit. So, “11011110.”
Then, in the second function call the chip needs the rest of the 12 bit value so the same number is passed in again.
The &0x0f >> 8 takes the same binary value “111011110” and shifts it 8 places. So, “000000001.”
Then, the &0x0f formats it into a 4 bit value. So, “0001.”

So that way, it always has instructions for HIGH or LOW for every pin, but with exactly 8 bits in the Fine Tune and exactly 4 bits in the Coarse Tune.