X-Authentication-Warning: delorie.com: mail set sender to geda-user-bounces using -f X-Recipient: geda-user AT delorie DOT com Message-ID: <52C5D542.6040001@buffalo.edu> Date: Thu, 02 Jan 2014 16:08:18 -0500 From: "Stephen R. Besch" User-Agent: Mozilla/5.0 (X11; Linux i686; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 MIME-Version: 1.0 To: geda-user AT delorie DOT com Subject: Re: [geda-user] Help sending a sine wave to a speaker References: In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-PM-EL-Spam-Prob: X: 10% Reply-To: geda-user AT delorie DOT com Rob, I know that this a few days late, but I do have some ideas - not so much as to where the error was, since someone already answered this, but in terms of sine wave generation in general. Basically, I would probably never use the SIN(x) function directly at all but I would generate the sine function from a pre-calculated table. This is not as costly as you might think. In your case, 1KHz at 8KHz sample rate, the table only requires (worst case) 8 samples, most of which are redundant. These are Sin(0)=0, Sin(45)=(sqrt2/2), Sin(90)=1, Sin(135)=Sin(45), Sin(180)=0, Sin(225)=-Sin(45), Sin(270)=-1, Sin(315)=-Sin(45). In point of fact, there are only 3 unique values(0.0, 1.0, and ~0.707). The rest are obtained from these by logic and sign inversion. The truth is that the same is true for higher sampling rates too. Your table only needs to contain a quarter wave of a 1Hz sine wave. Higher or lower frequencies can be obtained by changing the rate at which samples are played back (i.e., play at 8kHz and you get 1KHz, Play at 4kHz and you get 500Hz, Play at 16KHz and you get 2KHz. Now, a sine wave sampled at 8f (such as in your case) may look a bit choppy. But played back through an analog output with a 3db roll off pole set to some suitable frequency will pull almost the high frequency edges out of the output and give you an almost perfect sine wave. Stephen R. Besch On 12/31/2013 02:26 PM, Rob Butts wrote: > It has been a while since I've written major C code so I'm having a hard > time coming up with the code. > I have a simple design where I use a microchip pic16f1825 to read a byte > from an eeprom via spi and send it to a dac and ultimately to a speaker. > As a dac and speaker test I want to send a simple 1000Hz sine wave to the > dac at an 8KHz rate. > > Can anyone check my thoughts below? Here's my thinking... > If I set my timer to interrupt at an 8KHz rate and if I want to play the > tone for 10 seconds the for loop might look something like this: > > for(j=0; j < 80000; j++){ > // j is the sample index > // straight sine function means one cycle per 2*pi samples > // sample(j) = sin(j) > // multiply by 2*pi now it is one cycle per sample > // sample(j) = sin((2 * pi) * j) > // multiply by 1,000 samples per second now it is cycles per second > // sample(j) = sin(1000 * 2 * pi * j > // divide by 8000 samples per second now it is cycles per 8000 samples > // sample(j) = sin(1000 * 2 * pi * j / 8000) > // the 1000 cycles is the frequency so in those terms > // sample(j) = sin(freq * 2 * pi * j / 8000) > // now if I want to normalize the amplitude to 0xff the final value is > // sample(j) = 0xff * sin(freq * 2 * pi * j / 8000) > // so... declaring sample as a float > sample = 0xff * sin(freq * 2 * pi * j / 8000); > while(!update_dac){ // where update_dac is set to 1 in the timer > interrupt handler > } > update_ dac = 0; > send_dac((UINT8) sample); > } > > When I execute the code and step through it the value for sample when j = 1 > is 180.238where I expect 3.146 > > Can someone see my error or what is going on? > > Thanks > -- fictio cedit veritati