Hi,
I'm looking at implementing some simple PC speaker functions.
I would like to use it with the PIT (channel 2 of course).
I'm familiar with setting up channel 0 on the PIT. How do I set up channel 0 and 2? Is it as simple as setting up channel 0 (sending the configuration byte and frequency), and then sending another configuration byte that specifies channel 2?
Thanks for your help
Implementing PIT Channel 2 and PC Speaker
Re: Implementing PIT Channel 2 and PC Speaker
Hi,
For simple beeping; during initialisation I'd clear the "timer 2 gate to speaker enable" flag, set channel 2 to a default (known) frequency, then set a "current frequency" variable to whatever that frequency is. Then, to start a beep (e.g. as part of a beep(frequency, duration)" function) you'd check if requested frequency is different to the current frequency and if it's different you'd calculate a new channel 2 count and set it; then you'd set the "timer 2 gate to speaker enable" flag and use some other timer to measure the duration, and clear the "timer 2 gate to speaker enable" flag when that other timer says the sound should stop. Note: the other timer could be anything and will probably be some sort of generic kernel function for delays.
Also note that (for simple beeping) the speaker can only handle one beep at a time. If someone wants a beep when another beep is already in progress, then you can either wait for the current beep to finish before starting the new beep, or cancel the current beep and start the new beep immediately.
For more advanced speaker control you'd use pulse width modulation. In this case software gives digitized sound to the speaker driver (where 'digitized sound" is a set of samples where each sample says where the speaker should be), and the speaker driver can do mixing (combine multiple digitized sounds) and other things (e.g. volume control). The basic idea is to use a fixed frequency (faster than what the speaker can respond to) and vary the width of each pulse to control the position of the speaker.
For controlling the width of a pulse I'd use channel 2 in "low byte only, one shot" mode.
The problem here is that you don't know much about the speaker itself and don't know how quickly it can respond (e.g. a lot of motherboards use small/cheap piezo tweeters). Because of this you have to make sure the frequency you use is too high to be audible (e.g. 22 KHz or higher). A lot of audio is sampled at 44.1 KHz, so either 44.1 KHz or 22500 Hz might be good choices for your frequency.
For a frequency of 22500 Hz; every 44.4444 us you want to set a pulse width of between 0 us and 44.4444 us. A count of 53 would give you 44.444 us; so this means you've got 53 values you can use for pulse width (or "speaker position").
For a frequency of 44.1 Khz; every 22.2222 us you want to set a pulse width of between 0 us and 22.2222 us. A count of "26.5" would give you 22.2222 us; so this means that you've got 27 values you can use for pulse width (or "speaker position").
Note that for a pulse width of 0 you wouldn't set a new channel 2 count at all, and for a pulse width of "Max" you'd look ahead and combine it with future pulses (to avoid the need to set channel 2 count again for those future pulse/s). For example (for 44.1 KHz) instead of setting a count of 27 for one pulse and then setting a count of 10 for the next pulse, you'd just set a count of 37 and skip the next pulse.
Mostly what I'm saying here is that there would be a compromise between the frequency you use and the number of different "speaker positions" you can have. You'd probably want to try a few different frequencies to determine whether "higher frequency with less speaker positions" sounds better than "lower frequency with more speaker positions". However, I'd be tempted to assume that a lower frequency (e.g. 22500 Hz) with more speaker positions would be better, especially if you do volume control or do individual digitized sounds at 75% of their volume so that when 2 or more digitized sounds are mixed you end up with less clipping.
Cheers,
Brendan
There's a "timer 2 gate to speaker enable" flag in the PS/2 controller (think of it as ANDed with timer 2's output - it needs to be 1 or timer 2 won't cause a sound). Because this is in the PS/2 controller, I have no idea what happens on modern systems (e.g. 80x86 Apple machines) that don't have a PS/2 controller.mark3094 wrote:I'm familiar with setting up channel 0 on the PIT. How do I set up channel 0 and 2? Is it as simple as setting up channel 0 (sending the configuration byte and frequency), and then sending another configuration byte that specifies channel 2?
For simple beeping; during initialisation I'd clear the "timer 2 gate to speaker enable" flag, set channel 2 to a default (known) frequency, then set a "current frequency" variable to whatever that frequency is. Then, to start a beep (e.g. as part of a beep(frequency, duration)" function) you'd check if requested frequency is different to the current frequency and if it's different you'd calculate a new channel 2 count and set it; then you'd set the "timer 2 gate to speaker enable" flag and use some other timer to measure the duration, and clear the "timer 2 gate to speaker enable" flag when that other timer says the sound should stop. Note: the other timer could be anything and will probably be some sort of generic kernel function for delays.
Also note that (for simple beeping) the speaker can only handle one beep at a time. If someone wants a beep when another beep is already in progress, then you can either wait for the current beep to finish before starting the new beep, or cancel the current beep and start the new beep immediately.
For more advanced speaker control you'd use pulse width modulation. In this case software gives digitized sound to the speaker driver (where 'digitized sound" is a set of samples where each sample says where the speaker should be), and the speaker driver can do mixing (combine multiple digitized sounds) and other things (e.g. volume control). The basic idea is to use a fixed frequency (faster than what the speaker can respond to) and vary the width of each pulse to control the position of the speaker.
For controlling the width of a pulse I'd use channel 2 in "low byte only, one shot" mode.
The problem here is that you don't know much about the speaker itself and don't know how quickly it can respond (e.g. a lot of motherboards use small/cheap piezo tweeters). Because of this you have to make sure the frequency you use is too high to be audible (e.g. 22 KHz or higher). A lot of audio is sampled at 44.1 KHz, so either 44.1 KHz or 22500 Hz might be good choices for your frequency.
For a frequency of 22500 Hz; every 44.4444 us you want to set a pulse width of between 0 us and 44.4444 us. A count of 53 would give you 44.444 us; so this means you've got 53 values you can use for pulse width (or "speaker position").
For a frequency of 44.1 Khz; every 22.2222 us you want to set a pulse width of between 0 us and 22.2222 us. A count of "26.5" would give you 22.2222 us; so this means that you've got 27 values you can use for pulse width (or "speaker position").
Note that for a pulse width of 0 you wouldn't set a new channel 2 count at all, and for a pulse width of "Max" you'd look ahead and combine it with future pulses (to avoid the need to set channel 2 count again for those future pulse/s). For example (for 44.1 KHz) instead of setting a count of 27 for one pulse and then setting a count of 10 for the next pulse, you'd just set a count of 37 and skip the next pulse.
Mostly what I'm saying here is that there would be a compromise between the frequency you use and the number of different "speaker positions" you can have. You'd probably want to try a few different frequencies to determine whether "higher frequency with less speaker positions" sounds better than "lower frequency with more speaker positions". However, I'd be tempted to assume that a lower frequency (e.g. 22500 Hz) with more speaker positions would be better, especially if you do volume control or do individual digitized sounds at 75% of their volume so that when 2 or more digitized sounds are mixed you end up with less clipping.
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
Re: Implementing PIT Channel 2 and PC Speaker
Thanks for all the information. There's certainly a lot to absorb there.
For now, I'm just after some simple beeps that I can use when there is an error (especially if it's a video error, and I can't write details to the screen).
For this, I think PWM would be overkill, so I think I'd be better off staying with something similar to the PIT timer 2 sample on the wiki (http://wiki.osdev.org/PC_Speaker)
It looks like the play_sound function sends new configuration information to the PIT to configure timer 2 every time it is called, so as long as it doesn't 'overwrite' my timer 0 config, I should be fine.
For now, I'm just after some simple beeps that I can use when there is an error (especially if it's a video error, and I can't write details to the screen).
For this, I think PWM would be overkill, so I think I'd be better off staying with something similar to the PIT timer 2 sample on the wiki (http://wiki.osdev.org/PC_Speaker)
It looks like the play_sound function sends new configuration information to the PIT to configure timer 2 every time it is called, so as long as it doesn't 'overwrite' my timer 0 config, I should be fine.