Good ideas. Thanks for everyone.
What's the purpose of it so we can gauge any other specs such as jitter.
Vibration exciter driver in an old scientific instrument. Currently it has free running oscillator phase locked to an external reference. The instability of the oscillator is causing problems especially when starting the system.
My first thought is to use a cheap low pin count micro controller and use its PWM/NCO/REFCLK/Timer output.
Interesting, that came in to my mind too. My plan B was to use the existing PLL circuitry and simply fine adjust the n of the counter according to the PIC ADC input voltage. Not elegant but probably works.
Or it could be possible to use the PIC for the whole phase locking.
I made one yesterday with a PIC10F322 using its NCO, plus a canned 10MHz oscillator for the reference. Note the sidebands, due to the way the NCO works, there's a bit of FMing on there shown as spikes at about 24kHz intervals. It's very slightly off due to the resolution of the NCO, at 152,001Hz.
Canned oscillator alone takes 10mA, PIC only about 2mA, and much less if slowed down, it's running at full speed.
BOM cost about £1.20 / $1.80.
An SI5351 would give far better performance, but it's a bit of a bugger to program.
#include <xc.h>
#include <stdint.h>
#pragma config FOSC=INTOSC
#pragma config WDTE=OFF
#pragma config PWRTE=OFF
#pragma config MCLRE=ON
#define NCO1CLK_FREQ (10000000UL)
#define NCO_FREQ (152000UL)
#define NCO_INC (65536.0-(512.0*NCO1CLK_FREQ/NCO_FREQ)) // Needs to be double to maintain precision
int main(void)
{
OSCCONbits.IRCF=0b111; // 16MHz
ANSELA=0; // Digital I/O
TRISAbits.TRISA2=0;
NCO1CON = 0xC0; // Enable module and output, fixed duty cycle mode
NCO1CLK = 0x00; // NCO1CLK pin/RA1
NCO1INCH = (int8_t)(NCO_INC/256);
NCO1INCL = (int8_t)(NCO_INC);
while (1)
{
NOP();
}
return 0;
}