... hardware timer output is surely a good idea ...[but] I have to update a DAC ...
I've gotten good results getting an audio-frequency signal from a DAC using a hardware timer. Most DAC's have a "load" input, often called "LDAC," usually active low, that transfers data from internal holding registers to the DAC output register, so that multiple DACs can be loaded in sequence, and update their outputs simultaneously. The hardware timer fires the LDAC pulse; the next data sample is loaded into the DAC by an ISR, or in the main program.
The timer is set up like this:
- Waveform Generation Mode = Fast PWM
- Compare Output Mode A = Normal, OCXA disconnected
- Compare Output Mode B = OCXB set on match/clear at BOTTOM, or opposite, depending on the requirements of the DAC
- Clock Select and OCRXA as required to generate the required DAC update frequency
- OCRXB to provide a pulse of appropriate length to the DAC
- Interrupt on OCRXB compare match enabled; other interrupts disabled
OCXB is connected to LDAC. The first sample is loaded to the DAC's internal registers in setup(), then the timer is started. ISR(TIMERX_COMPB_vect) loads the next sample into the DAC's internal registers, bumps the pointer, and exits. When the timer rolls over, the output goes low, and the data is loaded into the DAC's output registers, without any action from the program. If the timing isn't too fast, the ISR could instead signal the main program, and let the main handle the I/O.
For something like frequency synthesis, where timing accuracy matters, this method is superior to updating the DAC output from inside an ISR. There's no problem with interrupt latency, and no chance that the timer will fire late because some other interrupt was being serviced at the time. It may not be theoretically "jitter-free," but its jitter is so much reduced that, from a practical standpoint, you could call it "jitter-free."