ZEZJ zero error zero jitter period generation

Discussion in 'Embedded Systems and Microcontrollers' started by THE_RB, Nov 21, 2009.

  1. THE_RB

    Thread Starter AAC Fanatic!

    Feb 11, 2008
    5,435
    1,305
    Hi, I've just updated my "zero error 1 second timer routines" page, there is a new section at the bottom that now supports zero-jitter period generation.

    Like the other code on the page it will generate any period (or frequency) from any xtal using just one simple constant to set the period. But this new system generates the period with zero jitter (which many people have requested). It is now useful for xtal-locked signal generation etc like to generate exactly 50Hz output or a 1 second clock signal etc.

    The algortihm and code may not be immediately obvious so I will explain the basics;

    ZEZJ algorithm;
    (first, #define PERIOD in TMR0 ticks)
    1. generate X interrupts of 100 ticks length
    2. generate 1 interrupt of "remainder" length 100-199
    3. done! make the event (toggle PIC pin etc)

    It is "zero-error" as the interrupt always subtracts the 100 tick period (or remainder period) from TMR0, so that any immediate latency will be corrected on the next interrupt.

    It is "zero jitter" because the remainder period syncs to the #defined PERIOD so the event (toggle PIC pin) always happens at exactly PERIOD.

    The clever part is the "X*100 + remainder 100-199" because it means that the end of PERIOD can can never conflict with the TMR0 interrupt! This is because subtracting 100-199 will always result in a legal TMR0 count that will be corrected on the next int. So the result is that you can just #define PERIOD and it will automatically generate an exact jitter free period with no messy timing conflicts.

    # Note! If you wanted to use the code below to generate other xtal-locked frequencies, you just need to change the PERIOD value (and maybe the xtal);
    # toggle PERIOD = (xtal / 4 / freq / 2)
    # 1 second; 4MHz xtal, PERIOD = 500000
    # 50 Hz; 8MHz xtal; PERIOD = 20000
    # 60 Hz; 6MHz xtal, PERIOD = 12500
    # 60 Hz; 12MHz xtal, PERIOD = 25000
    # 1 second; 8.867238MHz cheap TV xtal, PERIOD = (8867238 / 4 / 2)

    Here is the code to generate 50Hz with a PIC 12F675 4MHz xtal.
    Code (Text):
    1.  
    2. /******************************************************************************
    3.   ZeroJitter.c   Generates zero-error and zero jitter interrupt period.
    4.   Open-source  -  21 Nov 2009  -  www.RomanBlack.com/one_sec.htm
    5.  
    6.   PIC 12F675, 4MHz xtal.
    7.   This is like my zero-error 1 second timing system, that uses a convenient
    8.   constant to set ANY period (with 1 timer tick resolution).
    9.   However this system has zero jitter!
    10.   Can be used to generate 1 second period, or 50Hz freq output etc.
    11. ******************************************************************************/
    12.  
    13. // PERIOD sets the pin toggle freq; toggle PERIOD = (xtal / 4 / freq / 2)
    14. #define PERIOD 10000   // (xtal 4Mhz) TMR0 1MHz, 10000 = 100Hz toggle (50Hz output)
    15.  
    16. #define PER_COUNTS ((PERIOD / 100) - 1)  // don't edit this!
    17. #define PER_REMAINDER (PERIOD - (PER_COUNTS * 100))  // don't edit this!
    18.  
    19. unsigned int pcount;    // used in interrupt to count PER_COUNTS
    20. //-----------------------------------------------------------------------------
    21.  
    22.  
    23. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    24. void interrupt()
    25. {
    26.   //-----------------------------------------------------
    27.   // this is the TMR0 overflow interrupt.
    28.   // Note! TMR0 has a 3 tick write latency, writes must be -3
    29.   //-----------------------------------------------------
    30.   // check if time to toggle the output pin
    31.   if(!pcount)
    32.   {
    33.     asm {
    34.       movlw 0x01      ; // mask for pin 0
    35.       xorwf GPIO,f    ; // toggle PIC pin GPIO.0
    36.     }
    37.     pcount = (PER_COUNTS+1);    // how many delays to make total
    38.     TMR0 -= (PER_REMAINDER-3);  // first delay will be ==remainder
    39.   }
    40.   // else make a normal delay
    41.   else
    42.   {
    43.     TMR0 -= (100-3);       // make another 100 tick delay
    44.   }
    45.   pcount--;
    46.   //-----------------------------------------------------
    47.   // clear the TMR0 overflow flag and exit
    48.   INTCON.T0IF = 0;
    49. }
    50. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    51.  
    52.  
    53. //=============================================================================
    54. //   MAIN
    55. //=============================================================================
    56. void main ()
    57. {
    58.   //-----------------------------------------------------
    59.   // PIC 12F675  setup ports
    60.   ANSEL = 0;            // ADC off
    61.   CMCON = 0x07;         // comparators off
    62.   GPIO =   0b00000000;  // clear GPIO
    63.   TRISIO = 0b00000000;  // All outputs
    64.   WPU =    0b00000000;  // pin pullups; 1 = pullup on (for button)
    65.  
    66.   //-----------------------------------------------------
    67.   // timer setup etc
    68.   OPTION_REG = 0b00001000;    // TMR0 on, 1:1 prescale
    69.   pcount = 0;
    70.   INTCON = 0b10100000;  // GIE on, T0IE on (turn interrupt on)
    71.  
    72.   //-----------------------------------------------------
    73.   // main run loop here
    74.   while(1)
    75.   {
    76.     continue;   // loop and do nothing, just let the interrupt happen
    77.   }
    78. }
    79. //-----------------------------------------------------------------------------
    80.  
    This can be used on even the smallest cheapest PICs, I deliberately chose TMR0 for this reason. ROM needed is about 54, RAM needed is 2.

    Code was programmed and tested out perfectly, all values of PERIOD >=100.

    There is more info here;
    http://www.romanblack.com/one_sec.htm
     
Loading...