Perhaps a silly question: analogWriteResolution and Teensy 3.1 DAC/PWM

Status
Not open for further replies.

Theremingenieur

Senior Member+
As I understand the documentation here, analogWriteResolution(nBits) is a rather global setting. Now, if I want to use 12bit resolution on pin A14 (Teensy 3.1 DAC), but 16bit resolution for PWM on a Timer0 pin (i.e. pin5) and 10bit resolution for PWM on a Timer1 pin (i.e. pin 3), how do I proceed?
 
As I understand the documentation here, analogWriteResolution(nBits) is a rather global setting. Now, if I want to use 12bit resolution on pin A14 (Teensy 3.1 DAC), but 16bit resolution for PWM on a Timer0 pin (i.e. pin5) and 10bit resolution for PWM on a Timer1 pin (i.e. pin 3), how do I proceed?

i never use the PWM stuff but looks as if you could simply hardcode it into the analogWrite() function:

ie https://github.com/PaulStoffregen/cores/blob/master/teensy3/pins_teensy.c/#L407
 
I wasn't aware analogWriteResolution applied to PWM. Despite the silly name, PWM is not analog so the fact that the same call is used to write PWM and to write Analog is a historical curiousity.
 
There is a Digital to analog converter (DAC) in the T3.1.
And some apps and libraries for it.
 
If you look at the analogWrite code, or the PWM documentation, you'll see the code is scaling the resolution you choose to the actual timer numerical range. In the "PWM Resolution" section, there's a list of frequencies that give the timer an exact power-of-2 range.

If you want 16 bits of actual resolution, not only do you need to use analogWriteResolution(16), but you should also make sure you're using a PWM frequency that really does give 16 bits. When F_BUS is 48 MHz, that's 732 Hz.

It's easy to scale 10 or 12 bits up to a 16 bit number by left shifting.
 
Thanks for all the replies. I wanted to use different resolutions on different PWM pins in order to have also different speed. The link towards pins_teensy.c is extremely helpful, because it allows to understand what happens behind. It's really a pity (at least for teensy beginners as I am one) that there is not a systematic WIKI with an exhaustive and systematic function and object documentation for developers using teensyduino, similar to the arduino reference page.
 
I think I started to sort it out and thus to solve it. I created a DAC class which is fully independent of any analogWrite settings. This gives me the freedom to work on PWM with different frequencies and resolutions later.

My goal was to do as many of the needed calculations and settings as possible during the class initialization to speed up the write procedure compared to the analogWriteDAC0() function in analog.c

This DAC class is initialized with a pointer to the signal and updates the output value every time the method action() is called from the signal generating object.

In the .h file:
Code:
#define dVoxDacRes 12
#define dVoxSigRes 16

class dVoxDAC {
public:
  dVoxDAC(int32_t *signalBus = NULL);
  void action();
private:
  int32_t *_signalBus;
  const uint16_t _ofs = 1 << (dVoxDacRes - 1);
  const uint16_t _max = (1 << dVoxDacRes) - 1;
  const uint16_t _min = 0;
  const int8_t _shift = dVoxSigRes - dVoxDacRes;
};

In the .cpp file:
Code:
dVoxDAC::dVoxDAC(int32_t *signalBus) {
  /* Hardware configuration 
   ** sets reference to DACREF_2 = 3.3V VDDA */
  SIM_SCGC2 |= SIM_SCGC2_DAC0;
  DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS;
  /* Connect */
  _signalBus = signalBus;
}

void dVoxDAC::action() {
  if (_signalBus != NULL)
    *(int16_t *)&(DAC0_DAT0L) = constrain((*_signalBus  >> _shift) + (_ofs), _min, _max);
}
 
Last edited:
Status
Not open for further replies.
Back
Top