I am building a small OS. For that i wanted to play audio. I can use ports,interrupts. I have no restrictions as i am building an OS itself.
So how can i play an audio file using a C program. Please remember that I cannot and don't want to use any ready made library or so.
If you're building your own OS, you also need to care about the physical details of your audio hardware.
Differences in hardware is why operating systems introduced the concept of the device driver.
If your audio hardware is sound blaster compatible, have a look here:
http://www.phatcode.net/res/243/files/sbhwpg.pdf
There's an archive of lots of hardware-near audio code here (various hardware platforms):
http://www.dcee.net/Files/Programm/Sound/
Here's a chapter on programming sound devices:
http://www.oreilly.de/catalog/multilinux/excerpt/ch14-01.htm
Related
How to play sounds at different tones in C without using any external library? I know there are dozens of sound libraries in C that allows you to play sound but what I want to know is how does that work behind? How do you tell the computer to play a certain note at a certain tone/frequency?
I know it's possible on windows using the sound() function but I can't find any documentation talking about Linux, all that I found is the beep() function (or write(1, "\a", 1)) that outputs the default terminal beep but I can't figure out how to play different sounds.
The Linux kernel native audio API is ALSA (Advanced Linux Sound Architecture).
Example of raw audio playback with ALSA:
https://gist.github.com/ghedo/963382/815c98d1ba0eda1b486eb9d80d9a91a81d995283
However, ALSA is a low-level API that is not recommended to be used directly by higher-level applications.
A modern system audio API for GNU/Linux would be either PulseAudio (the current default on Ubuntu), or the newer and arguably better PipeWire (the default on Fedora).
Example of raw audio playback with PipeWire that generates audio "from scratch":
https://docs.pipewire.org/page_tutorial4.html
How do you tell the computer to play a certain note at a certain tone/frequency?
Sound is a mechanical vibration that propagates through the air (or another medium). It can be represented digitally as a sequence of numerical values representing air pressure at a given sampling rate. To play a given tone/frequency, generate a sine wave of that frequency (at the playback sampling rate) and use the sound API of your choice to play it.
See the PipeWire tutorial above for an example generating a 440Hz tone.
About PulseAudio/PipeWire:
These libraries are typically part of the OS and exposed as system APIs (so they are not "external libraries" if that means some library to ship with your program or to ask users to install), and they should be used by applications to play audio.
Behind the scene, these libraries handle audio routing, mixing, echo-canceling, recording, and playback to the kernel through ALSA (or using Bluetooth, etc). Everything that users and developers expect from the system audio layer.
Until recently, PulseAudio was the de-facto universal desktop system audio API, and many apps still use the PulseAudio API to play audio on GNU/Linux.
PipeWire includes compatibility with PulseAudio, so that apps using the PulseAudio API will keep working in the foreseeable future.
Example of raw audio playback with PulseAudio:
https://freedesktop.org/software/pulseaudio/doxygen/pacat-simple_8c-example.html
I was wandering, why there are no implementations of the devices written in CMSIS-Driver?
I mean that I have few peripherals: LCD, temperature and pressure sensor, current meter etc. - all of them very popular used in arduino and learning sets.
Each of these devices uses some protocol to communicate with the uC. some are for i2C, some communicate by SPI, some by UART. I was wondering if there are drivers that handle those devices, and as a backend use CMSIS-Driver API.
I think that it is a decent api, and after all standard develop by ARM, so why I can not find any drivers using it?
For example when I was looking for s18b20 (temperature sensor for 1-wire), I was easily able to find driver for this device written in RUST language, but I was not able to find any implementation for C that would use CMSIS. (in this case compare to rust is quite solid, because Rust has nice embedded API, and you can easily use the driver on multiple targets, just like CMSIS-Driver is spouse to work)
I was able to find some projects using this peripheral, but they all operated on HAL that is different for every uC, so the implementation is not portable ( unlike RUST, and potentially CMSIS-Driver)
So my main questions are:
Why there are so little implementations based on CMSIS-Driver? Maybe there is some hidden implementation repository that I do not know about?
Am I missing something? Is the CMSIS-Driver not designed for the casual developers? Who is it designed for then ?
CMSIS is not concerned with external devices, it deals primarily with interface drivers for interfaces on the microcontroller die. So if you have an SPI device, you might use the CMSIS. SPI driver for that part, but it is then your responsibility as a developer to write the higher-level driver for the external device.
Higher-level software platforms such as ARM's embed, or ST's CubeMX use CMSIS interface drivers, and include drivers for common higher level devices. They tend to be for more complex devices related to networking, filesystems and displays. I would not expect much support for such trivially simple devices such as a temperature sensor.
I am developing my own OS and for days I’ve been wondering how to control video card, audio card to build a delicate GUI. It seems that the procedure is a bit different from that of controlling mouse or keyboard.
By the way,
1.How does an OS recognize hardware drivers?
2.Are all hardware drivers written for specific platforms (such as Windows,Linux,etc.)?
Still freshman in the university and failed to find relevant information
thanks for help =)
how to control video card
Graphics cards typically support a VGA mode and the VESA 2.0 standard. So this could be a good starting point for your first video driver.
How does an OS recognize hardware drivers?
Linux uses a device tree describing the hardware which has a compatible field for every item that needs a driver. All hardware drivers are kept in linker generated lists. If a driver has the same compatible value it can be used to drive the hardware. The linker list item is generated from a macro in the driver code using a specialized linker script.
Are all hardware drivers written for specific platforms (such as Windows, Linux, etc.)?
If you provide the right wrappers you may be able to reuse existing drivers. E.g. U-Boot reuses Linux drivers for USB devices. And the NDISwrapper can be used to run Windows WLAN drivers on Linux.
I am interested in learning how to do embedded system programming in c. However, I will need some hardware.
I am wondering is there any software that can simulate what the control board will do?
The control board is listed in the following tutorial
http://www.learn-c.com/hardware.htm
Many thanks for any advice
The board you linked to is not an embedded system board, it is an I/O interface for a PC. If you want to simulate that, you can simply write PC code stubs for the I/O functions that simulate connected devices' behaviour. However, you will not learn much about embedded systems from this. You may learn a little about PC based control, but since the board does not support interrupts or DMA, I suggest again that you will not learn much of that either.
Moreover the board is designed for an ISA bus slot. Modern PCs no longer have such slots. And modern operating systems prevent access to hardware I/O in user level code.
If you are serious about learning embedded systems development, you might for example download Keil's MDK-ARM evaluation; it includes an ARM simulator with on-chip peripheral simulation for a number of commonly available ARM based micro-controllers, and real hardware is available at reasonable cost.
If PC based control is of more interest, then you would be better off starting with a USB based I/O device, such as this example.
I'm attempting to write a very simple OS in ASM and C. (NASM assembler)
I would like to access the sound card directly, with or without drivers.
If I don't need drivers, how could I access and send a sample audio file
to the sound card? (An example would be nice)
If I do need drivers, is there anyway to interface them and call functions
from the drivers? And how do I access and send a sample audio file to the
sound card? (Another example would be nice)
I hate to discourage you, but modern sound card drivers are extremely complicated, and as you probably know, OS-specific. This is one of the difficult challenges in OS development - driver support. It's not something that can be achieved with a simple code snippet.
In order to load a file, you need a file system. Have you implemented that yet? The fact that you used the "kernel" flag suggests that your OS is still in its infancy. I'm not sure I would want to put sound support into the kernel of an operating system.
That being said, there is a good emulator called Bochs that has Sound Blaster 16 emulation. And some really old documentation for how to program it. This might be your best bet. Accessing sound hardware was much easier back in the day.
Your best bet is probably to look at either the Linux or FreeBSD sound drivers and see what they do. You're not likely to get much better implementation documentation for any but the simplest sound card...
This is a hard problem. Be warned :-p
Of course you need a driver, and of course there's no easy way to interface with existing ones (there was some proposal for a unified OS-agnostic "Uniform Driver Interface" - but I don't think it got anywhere).
So, after you've written the code to read a file from your hard drive, you'll need to roll your own audio driver.
Now, I haven't done this in a while, so this may be outdated, but in the 90's you'd configure your sound card with a few 'out dx, al' (details varied across soundcards), and then setup DMA to send data from a memory buffer to your card. The card (or was it the DMA controller?) would fire off an interrupt when it reached the end of the buffer, which you'd use to fill the buffer with new data.
If your card has a working linux driver I'd start by looking at its code. Otherwise, you'll have to reverse engineer the windows driver, Soft-Ice's bpio (break on io port access) logging used to be good for that iirc.
Good luck.
Here is a free open-sourced operating system written in all assembly. It is great reference for assembly kernel programming if you are new to it.
http://www.menuetos.net/index.htm