On 03/10/2011 11:41 PM, Robert LaJeunesse wrote:

Poor man's solution: Use an Arduino to read the Thunderbolt 1PPS and lock a 50Hz
(or 60Hz) square wave to the 1PPS. Any resulting jitter can likely be kept in
Here is an even poorer man's solution (and plug):

A DDS using both compare outputs of an 8 pin part to get
a phase-centered PWM with half the usual ripple.
With PPS input as a bonus so the zero crossing occurs where
you want it to.

http://n1.taur.dk/gen60a.jpg

Output 5Vpp@60Hz +1.1mVpp@39kHz. Very pretty sinewave.


//
  TinyAWG.c
//  60Hz generator - 2011 Kasper Pedersen - Beerware license
//
//  This is an arbirtrary waveform generator set up to produce 60Hz sine
//  Compile with GCC -Os
//
//
// 2-5V  -------+-----------------------------+
//              |                             |
//              |        ______________       |
//              |     __|*             |__    |
//             | |   |__|          VCC |__|---+--||--+
//           3k| |      |              |         1u  |
//              |     __|              |_           _|_
// 10MHz ---||--+----|__| CLK      LOCK|__|         GND
//         1n   |       |              |
//             | |    __|              |__    ___      ___
//           3k| |   |__| PPS      PWM1|__|---___--+---___-------+
//              |       |              |      2k2  |   3k3       |
//              |     __|              |__    ___  |             |
// GND   -------+----|__| GND      PWM0|__|---___--+--||--+--||--+---------
//              |       |______________|      2k2    100n |  100n
//              |          ATTINY13V                      |        60Hz out
//              |                                         |
//              +-----------------------------------------+----------------
//
//
//  Rising edge on PPS input (optional) will steer the output
//  so that, after 128 edges, the positive zero crossing
//  of the output will coincide with PPS.
//  When this happens, LOCK will go high.
//
//  PWM frequency is 39kHz
//  first filter stage attenuates 27x
//  second filter stage attenuates 81x and pulls phase 1 deg.

#include<avr/io.h>
#include<avr/interrupt.h>
#include<avr/pgmspace.h>

#define DCBIAS 127
PROGMEM unsigned char table[256]={
 127,130,133,136,139,142,145,149,152,155,158,161,164,167,169,172,
 175,178,181,184,186,189,192,194,197,200,202,205,207,209,212,214,
 216,218,220,222,224,226,228,230,232,233,235,237,238,240,241,242,
 243,245,246,247,248,248,249,250,251,251,252,252,252,253,253,253,
 253,253,253,253,252,252,252,251,251,250,249,248,248,247,246,245,
 243,242,241,240,238,237,235,233,232,230,228,226,224,222,220,218,
 216,214,212,209,207,205,202,200,197,194,192,189,186,184,181,178,
 175,172,169,167,164,161,158,155,152,149,145,142,139,136,133,130,
 127,124,121,118,115,112,109,105,102,99,96,93,90,87,85,82,
 79,76,73,70,68,65,62,60,57,54,52,49,47,45,42,40,
 38,36,34,32,30,28,26,24,22,21,19,17,16,14,13,12,
 11,9,8,7,6,6,5,4,3,3,2,2,2,1,1,1,
 1,1,1,1,2,2,2,3,3,4,5,6,6,7,8,9,
 11,12,13,14,16,17,19,21,22,24,26,28,30,32,34,36,
 38,40,42,45,47,49,52,54,57,60,62,65,68,70,73,76,
 79,82,85,87,90,93,96,99,102,105,109,112,115,118,121,124};

unsigned char phase;
signed acc;
unsigned char lastp=1;

ISR(SIG_OVERFLOW0)
{
        signed s;
        unsigned char v;
        //60Hz*256=15360Hz increment rate.
        //irq rate is 10MHz/256=39062.5Hz.
        //we need to increment at: 60*256*256 / 10M
        //split into primes and eliminate common factors:
        //10MHz       = 2^7 *     5* 5^6
        //60*256 *256 = 2^7 *2 *  5 *2*2*3 * 2^8
        //scaler = 2*2*2*3*256  / 5*5*5*5*5*5
        //       = 6144 / 15625

        v=__LPM(&table[phase]); //generate output
        OCR0A=v;
        OCR0B=(2*DCBIAS)-v;     

        s=acc; //generate phase
        s-=6144;
        if (s<0) {
                acc= s+15625;
                ++phase;                
        } else {
                acc= s;
        }

        if (PINB&16) { //on rising edge: adjust phase so this conincides with 
the positive zero crossing.
                if (!lastp) { //we need 128 pulses to become adjusted
                        lastp=1;
                        if (!phase) {
                                //phase is 0. At 15kHz we are within 65us       
                                PORTB|=4;
                        } else
                        if (phase&0x80) {
                                ++phase; // 65us adjustments
                                PORTB&=~4;
                        } else {
                                --phase;
                                PORTB&=~4;
                        }
                }
        } else {
                lastp=0;
        }
}

void main(void)
{
        TCCR0A=0xB3; //A is clear on match, positive output when bigger
        TCCR0B=0x01;
        TIMSK0=0x02;
        DDRB|=1;  //output
        DDRB|=2;
        DDRB|=4;   //"locked" output
        PORTB|=16; //~50uA pullup on PPS pin.
        sei();
        for (;;);
}


_______________________________________________
time-nuts mailing list -- time-nuts@febo.com
To unsubscribe, go to https://www.febo.com/cgi-bin/mailman/listinfo/time-nuts
and follow the instructions there.

Reply via email to