Configures the fixed-frequency DAC for use
Not available on the imp005
|An imp pin or other object
The DAC output
|Float or Integer
The sample rate in Hertz
An array of up to eight non-zero blobs to be used as buffers of output data to output
The function that will be called when a buffer has been consumed
Optional processing flags A_LAW_DECOMPRESS and/or AUDIO
The fixed-frequency DAC can perform repeated digital-to-analog conversions at a regular rate. It is useful as an analog audio output, for instance, or as a general-purpose waveform generator.
The buffers, passed to the DAC as an array of blobs, contain the data to be converted. By default, the fixed-frequency DAC expects 16-bit, little-endian, unsigned linear data. However, current hardware only has 12 bits of precision; the four least significant bits of each sample are dropped. In this case, and with a sample rate of 1kHz, 2000 bytes of data are converted every second. If the buffers are 2000 bytes each, callback, a function called automatically to manage a given depleted buffer, will be called once a second.
On imps with true DACs, simply pass a pin object into the output parameter. The pin must be capable of supporting DAC operation, or an exception will be thrown.
The imp004m does not contain a DAC, but it is able to emulate one, and this functionality is supported by fixedfrequencydac. For the imp004m, pass the object hardware.pwmpairKD into output in place of a pin object. This configures pins K and D as digital outputs in PWM mode. Each pin outputs eight bits of a 16-bit sample at 96MHz: the most significant bits through pin K, the least through pin D. In this mode, all other fixedfrequencydac methods work as you would expect.
You should note that the range of possible sample rates available is narrower using this imp004m mechanism than it is on imps with a real DAC. As such, fixedfrequencydac.configure() will only accept values between 1500Hz and 16000Hz when called on the imp004m, and if any argument other than hardware.pwmpairKD is passed into output, an exception will be thrown.
In addition, the output signal will require feeding through an external filter circuit to remove the DC bias.
Following the configuration of fixedfrequencydac this way, pin D may be reconfigured to another role if you wish. This is useful if audio quality is not a priority for you application, but pin availability is. If pin D has been reconfigured, pin K will continue to output the most significant eight bits of the 16-bit DAC output; the least significant bits are lost and the appropriate pin of your filter circuit should be grounded.
This function is called automatically by the DAC when is has processed the data in a buffer. It is also called to warn you of under-run conditions. It has the following parameter of its own:
|The buffer most recently consumed by the DAC
When the callback is executed, the buffer’s contents can be refreshed immediately or at a later time. Alternatively, the buffer can be discarded and replaced with a new one. Whatever the buffer’s fate, the method fixedfrequencydac.addbuffer() is used to add the new or replenished buffer to the DAC’s queue.
An under-run can occur when the DAC has no buffers left to process. This can occur, for example, when the code has taken too long to add a fresh buffer after the Data-Consumed Callback function has been called to notify your code that the DAC has one less buffer to process. When the DAC has no further buffers to process, it calls the Data-Consumed Callback and passes it
null. Your implementation of the Data-Consumed Callback should check for this condition and take appropriate action.
If the A_LAW_DECOMPRESS option is supplied, then the buffers should contain 8-bit A-law compressed data. The imp will decompress the data prior to sending it to the DAC. In this case, the data rate is halved: at 1kHz, 1000 bytes of data are consumed every second.
The minimum sample rate is 1/60Hz (0.0166Hz) or one sample per minute. The maximum sample rate of the hardware is a theoretical 2MHz, but Squirrel would be unable to generate data at that rate except in short bursts. The maximum achievable rate (whether burst or continuous) thus depends on how much processing must be done to generate the data, and should be determined empirically for any given application. As a rough guideline, the imp should be able to stream 8kHz 8-bit audio over a network (with network latency being the biggest bottleneck).
The optional AUDIO flag should be supplied when the fixedfrequencydac is being used for audio playback. This tells the imp to improve the output for audio: for example, ‘de-clicking’ is applied when starting or stopping playback.
fixedfrequencydac.configure() will accept an empty array into its buffers parameter. No exception will be raised at this point but an exception will be raised if you subsequently call fixedfrequencydac.start() without having added any buffers by the time the call is made. Buffers can be added by calling fixedfrequencydac.addbuffer().
This code streams a 1kHz sinusoidal wave from agent to an imp. The original 16-bit signal is A-law compressed, and the resulting 8-bit data are sent to the imp. The code supports any imp, using impOS’ imp.info() to determine the type, and configuring the fixed-frequency DAC accordingly (or throwing an error in the case of the imp005, which has no DAC support). If you run this code under impOS 34 or under, it will default to imp001 usage, whatever your device.