Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/edgar-bonet/avr-dac

Turn an AVR into a 1-bit D/A converter
https://github.com/edgar-bonet/avr-dac

Last synced: 21 days ago
JSON representation

Turn an AVR into a 1-bit D/A converter

Awesome Lists containing this project

README

        

# avr-dac: Turn an AVR into a 1-bit D/A converter

This program turns an AVR microcontroller into a 1-bit DAC. The desired
analog level is loaded serially, like on a shift register, as an 8-bit
unsigned integer. Then, once the LATCH input pin is asserted, the level
is output as a pulse density modulated (PDM) waveform. Average waveform
voltage for level n is (n/256)VCC. The
PDM waveform is generated by a software delta-sigma modulator clocked at
fCPU/13 (615 kHz for
fCPU = 8 MHz).

The program is meant to work on any AVR microcontroller. It doesn’t use
any peripheral other than basic GPIO ports, and doesn’t use any RAM. It
has been tested on an ATtiny13A running at 8 MHz off its internal
RC oscillator.

## Configuring

Edit the configuration section at the top of the program to set the
pinout, the clock prescaler and the polarity of the LATCH pin.

Inputs:

* CLK: serial clock
* DAT: serial data, clocked on rising CLK, most significant bit first
* LATCH: latch the data, active-high unless configured otherwise

Output:

* OUT: PDM output

The defaults are:

* pinout: CLK = PB0, DAT = PB1, LATCH = PB2, OUT = PB3
* clock prescaler = 1 (full clock speed)
* LATCH is active-high

## Building

Type

```bash
avr-gcc -mmcu=... -nostdlib avr-dac.S -o avr-dac.elf
```

with the appropriate MCU model, or edit and use the included Makefile.

## Timings

The inputs should conform to the following requirements:

* every input level should be held for at least 26 clock cycles
* DAT setup = 0
* DAT hold = 26 cycles
* last CLK to LATCH = 26 cycles

The delta-sigma modulator is clocked every 13 cycles

Note that the Arduino’s `shiftOut()` and `digitalWrite()` are slow
enough to meet all these requirements.

## Internals

This program does not use interrupts. Instead, it runs a carefully
timed infinite loop, alternatively handling its inputs and outputs.
Within each 26-cycle loop iteration, the inputs are sampled once and
the output is updated twice. It should be noted that this loop uses
100% of the CPU cycles: attempting to perform any additional job would
disrupt the timing.

The CPU cycle count can be broken down as:

* 2 × 5 cycles for the delta-sigma algorithm
* 14 cycles for handling inputs
* 2 cycles for closing the loop

## Test program

The companion sketch test-avr-dac.ino has been run on an Arduino Uno to
test avr-dac.S running on an ATtiny13A. The PDM output from the ATtiny
was filtered through an RC low-pass filter (R = 1 kΩ,
C = 100 nF) in order to get a true analog signal. Here is
the signal as seen on an oscilloscope:

![Output waveform](waveform.png)