Introduction
In our company, we find ourselves in need of using the internal PC speaker (buzzer) on Windows7 64bit.
Googling around searching for the problem, we found that this problem is fully explained here.
There is no trace of an easy solution, at least searching for something like "Windows 7 64bit buzzer" or something like this.
So we started from searching on how the buzzer is implemented and we found this very useful article:
I report here the most interesting part:
-
Send the value 182 to port 43h. This sets up the speaker.
-
Send the frequency number to port 42h. Since this is an 8-bit port, you must use two <tt class="LITERAL">OUT</tt>
instructions to do this. Send the least significant byte first, then the most significant byte.
-
To start the beep, bits 1 and 0 of port 61h must be set to 1. Since the other bits of port 61h have other uses, they must not be modified. Therefore, you must use an <tt class="LITERAL">IN</tt>
instruction first to get the value from the port, then do an OR
to set the two bits, then use an <tt class="LITERAL">OUT</tt>
instruction to send the new value to the port.
-
Pause for the duration of the beep.
-
Turn off the beep by resetting bits 1 and 0 of port 61h to 0. Remember that since the other bits of this port must not be modified, you must read the value, set just bits 1 and 0 to 0, then output the new value.
So with this idea in mind, and as we didn't want to write an assembler piece of code, we looked for a library that let us access the hardware ports and we find this very useful library:
As said from the authors, "InpOut32
" is an open source windows DLL and Driver to give direct access to hardware ports".
Using the Code
Once we have downloaded the driver, we have to:
- Install the driver from highrez, there is a 32bit or 64bit different installer depending on your PC configuration.
- In CLI environment, we can include the .h file, we link the .lib library and use the given DLL (there are two directories binaries\Win32 and binaries\x64 depending on your application configuration).
First, we test if the Input-Output Driver is open, then:
#include "inpout32.h"
...
void MyClass::Beep(unsigned int freq, int ms)
{
Out32(0x43, 0xB6);
int div = 0x1234dc / frequency;
Out32(0x42, (System::Byte)(div & 0xFF));
Out32(0x42, (System::Byte)(div >> 8));
System::Threading::Thread::Sleep(10);
Out32(0x61, (System::Byte)(System::Convert::ToByte(Inp32(0x61)) | 0x03));
System::Threading::Thread::Sleep(ms);
StopBeep();
}
void MyClass::StopBeep()
{
Out32(0x61, (System::Byte)(System::Convert::ToByte(Inp32(0x61)) & 0xFC));
}
...
On the other hand, we can DLLImport
(https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute%28v=vs.90%29.aspx) the DLL without having to link the library and use the .h file.
...
[DllImport("inpout32.dll")]
extern void Out32(short PortAddress, short Data);
[DllImport("inpout32.dll")]
extern char Inp32(short PortAddress);
...
In case of C#, use...
....
[DllImport("inpout32.dll")]
extern static void Out32(short PortAddress, short Data);
[DllImport("inpout32.dll")]
extern static char Inp32(short PortAddress);
...
public void Beep(uint freq, int ms)
{
Out32(0x43, 0xB6);
int div = 0x1234dc / frequency;
Out32(0x42, (Byte)(div & 0xFF));
Out32(0x42, (Byte)(div >> 8));
System.Threading.Thread.Sleep(10);
Out32(0x61, (Byte)(System.Convert.ToByte(Inp32(0x61)) | 0x03));
System.Threading.Thread.Sleep(ms);
StopBeep();
}
public void StopBeep()
{
Out32(0x61, (Byte)(System.Convert.ToByte(Inp32(0x61)) & 0xFC));
}
...
Points of Interest
Remember to always stop the buzzer!
I started programming at Teinos, in a 5 person software working team in march 2004. I got some experience interfacing our main program to various external applications. All of these experiences allowed me to get in touch with many people: end-user, technician and commercial one; learning how to interface myself with these people. After some period I was moved to 'single' software application development. This led me to learn the whole process of software development. From the definition of the specifications to the software release and many times also the installation of the product to the end-user.
In 2009, I moved to ATS. I was charged as Lead Software Developer in a team for a long term new project: Primo (released for the first time in 2010-Q3). The software part for this project was completely written from scratch. These experience led me to understand how to organize the work of a team and take critical decision.
In 2014, in collaboration with a multinational corporation, we started the development of a completely new machine: ARCO FP (released for the first time in 2015-Q3). The software part for this project was completely written from scratch. This experience teaches me how to integrate our company with the needs and rules of other company and how to mitigate different approaches to the production phases.