syncSlave for problem 3

Files at this revision

API Documentation at this revision

Comitter:
the729
Date:
Fri Dec 03 20:53:52 2010 +0000
Commit message:

Changed in this revision

hdtimeval_math.cpp Show annotated file Show diff for this revision Revisions of this file
hdtimeval_math.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
timesync.h Show annotated file Show diff for this revision Revisions of this file
timesync_slave.cpp Show annotated file Show diff for this revision Revisions of this file
timesync_slave.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 362932d519c6 hdtimeval_math.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hdtimeval_math.cpp	Fri Dec 03 20:53:52 2010 +0000
@@ -0,0 +1,67 @@
+#include "hdtimeval_math.h"
+
+void hdtv_add (hdtimeval_t * r, hdtimeval_t * v1, hdtimeval_t * v2)
+{
+    r->tv_sec = v1->tv_sec + v2->tv_sec;
+    r->ticks = v1->ticks + v2->ticks;
+    if (r->ticks >= MAX_TICK) {
+        r->tv_sec++;
+        r->ticks -= MAX_TICK;
+    }
+}
+
+void hdtv_div2 (hdtimeval_t * r, hdtimeval_t * v)
+{
+    if (v->tv_sec & 0x1) {
+        r->ticks = ((v->ticks+MAX_TICK)>>1);
+    } else {
+        r->ticks = (v->ticks>>1);
+    }
+    r->tv_sec = (v->tv_sec>>1);
+}
+
+void hdtv_div8 (hdtimeval_t * r, hdtimeval_t * v)
+{
+    r->ticks = ((v->ticks+MAX_TICK*(v->tv_sec & 0x7))>>3);
+    r->tv_sec = (v->tv_sec>>3);
+}
+
+void hdtv_sub (hdtimeval_t * r, hdtimeval_t * v1, hdtimeval_t * v2)
+{
+    r->tv_sec = v1->tv_sec - v2->tv_sec;
+    if (v1->ticks < v2->ticks) {
+        r->ticks = MAX_TICK + v1->ticks - v2->ticks;
+        r->tv_sec --;
+    } else {
+        r->ticks = v1->ticks - v2->ticks;
+    }
+}
+
+void hdtv_muldiv (hdtimeval_t * r, hdtimeval_t * v, hdtimeval_t * m, hdtimeval_t * d)
+{
+    double dblm, dbld, factor, rsec, rticks;
+    uint32_t irticks, c;
+    int32_t irsec;
+
+    dblm = (double)(m->tv_sec) * (double)MAX_TICK + (double)(m->ticks);
+    dbld = (double)(d->tv_sec) * (double)MAX_TICK + (double)(d->ticks);
+    factor = dblm / dbld;
+    
+    rsec = (double)(v->tv_sec) * factor;
+    rticks = (double)(v->ticks) * factor + (rsec - floor(rsec)) * (double)MAX_TICK;
+    irticks = (uint32_t)rticks;
+    irsec = (int32_t)rsec;
+    c = irticks / MAX_TICK;
+    r->tv_sec = irsec + c;
+    r->ticks = irticks - c * MAX_TICK;
+}
+
+void hdtv_totv(timeval_t * r, hdtimeval_t * v)
+{
+    r->tv_sec = v->tv_sec;
+    r->tv_usec = (v->ticks + 48)/96;
+    if (r->tv_usec >= 1000000) {
+        r->tv_sec ++;
+        r->tv_usec -= 1000000;
+    }
+}
diff -r 000000000000 -r 362932d519c6 hdtimeval_math.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hdtimeval_math.h	Fri Dec 03 20:53:52 2010 +0000
@@ -0,0 +1,13 @@
+#ifndef HDTIMEVAL_MATH_H
+#define HDTIMEVAL_MATH_H
+
+#include "timesync.h"
+
+void hdtv_add (hdtimeval_t * r, hdtimeval_t * v1, hdtimeval_t * v2);
+void hdtv_div2 (hdtimeval_t * r, hdtimeval_t * v);
+void hdtv_div8 (hdtimeval_t * r, hdtimeval_t * v);
+void hdtv_sub (hdtimeval_t * r, hdtimeval_t * v1, hdtimeval_t * v2);
+void hdtv_muldiv (hdtimeval_t * r, hdtimeval_t * v, hdtimeval_t * m, hdtimeval_t * d);
+void hdtv_totv(timeval_t * r, hdtimeval_t * v);
+
+#endif //HDTIMEVAL_MATH_H
diff -r 000000000000 -r 362932d519c6 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Dec 03 20:53:52 2010 +0000
@@ -0,0 +1,27 @@
+#include "mbed.h"
+#include "timesync.h"
+
+DigitalOut myled(LED2);
+DigitalOut mypin(p21);
+
+timeval_t t;
+
+void pinToggle()
+{
+    mypin = 1;
+    myled = 1;
+    mypin = 0;
+    myled = 0;
+    t.tv_sec += 1;
+    runAtTime(&pinToggle, &t);
+}
+
+int main() {
+    timesync_init();
+    
+    t.tv_sec = 5;
+    t.tv_usec = 500000;
+    runAtTime(&pinToggle, &t);
+    while(1) {
+    }
+}
diff -r 000000000000 -r 362932d519c6 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Dec 03 20:53:52 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
diff -r 000000000000 -r 362932d519c6 timesync.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timesync.h	Fri Dec 03 20:53:52 2010 +0000
@@ -0,0 +1,76 @@
+#ifndef TIMESYNC_H
+#define TIMESYNC_H
+
+#include "mbed.h"
+
+typedef unsigned int uint32_t;
+typedef int int32_t;
+typedef unsigned short uint16_t;
+typedef short int16_t;
+typedef unsigned char uint8_t;
+//typedef char int8_t;
+
+typedef struct timeval {
+    int32_t tv_sec;
+    uint32_t tv_usec;
+} timeval_t;
+
+typedef struct hdtimeval {
+    int32_t tv_sec;
+    uint32_t ticks;
+} hdtimeval_t;
+
+typedef union sync_pkt24 {
+    struct {
+        uint32_t rx_time;
+        uint16_t tx_time;
+    };
+    struct {
+        char no_use;
+        char raw[5];
+    };
+} sync_pkt24_t;
+
+typedef union sync_pkt32 {
+    struct {
+        uint32_t rx_time;
+        uint16_t tx_time;
+    };
+    char raw[6];
+} sync_pkt32_t;
+
+typedef union sync_pkt64 {
+    struct {
+        hdtimeval_t rx_time;
+        uint16_t tx_time;
+    };
+    char raw[10];
+} sync_pkt64_t;
+
+typedef enum {
+    SYNCTYPE_NONE = 0,
+    SYNCTYPE_64 = 0xA0,
+    SYNCTYPE_32 = 0xA3,
+    SYNCTYPE_24 = 0xA5
+} synctype_t;
+
+void timesync_init();
+
+void getTime(struct timeval * tv);
+int runAtTime(void (*schedFunc)(void), struct timeval *tv);
+void runAtTrigger(void (*trigFunc)(struct timeval *tv));
+
+#define TMR LPC_TIM2
+#define MAX_TICK (SystemCoreClock)
+
+#define PCLK_DEVIDER 1  // PCLK = CCLK
+#define CLK_TIMER 12     // TIMER2 as the timer
+#define CLK_UART 16     // UART2 as uart
+#define PCTIM0 1        // Power Control Timer0
+#define PCTIM1 2        // Power Control Timer1
+#define PCTIM2 22        // Power Control Timer1
+#define PCUART2 24      // Power Control UART2
+
+#define QUEUE_SIZE 16
+
+#endif //TIMESYNC_H
diff -r 000000000000 -r 362932d519c6 timesync_slave.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timesync_slave.cpp	Fri Dec 03 20:53:52 2010 +0000
@@ -0,0 +1,456 @@
+#include "mbed.h"
+#include "timesync.h"
+#include "timesync_slave.h"
+#include "hdtimeval_math.h"
+
+int32_t clock_sec;
+DigitalOut led(LED1);
+Serial uart_sync(p28,p27);
+Timeout tmr_sync;
+Timeout tmr_callback;
+
+hdtimeval_t front_lt;
+hdtimeval_t timeq[QUEUE_SIZE];
+void (*funcq[QUEUE_SIZE])(void);
+uint8_t qfront;
+uint8_t qtail;
+
+void (*trigf)(struct timeval *);
+hdtimeval_t trigt;
+//bool trigactive;
+
+//state_t state;
+synctype_t syncbusy;
+synctype_t tmp_synctype;
+hdtimeval_t txstamp;
+
+coeff_t coeff;
+
+void clock_init();
+void tmr1_irq();
+void uart_recv();
+__INLINE void getHDTime(struct hdtimeval * hdtv);
+void sync_req();
+void update_data(synctype_t t, void * pkt_p, hdtimeval_t * rxstamp);
+void getLocalTime(hdtimeval * gt, hdtimeval * lt);
+void getGlobalTime(hdtimeval * lt, hdtimeval * gt);
+void runTriggerFunc();
+
+void timesync_init()
+{
+    wait_ms(100);
+    coeff.v1div2.tv_sec = 0;
+    coeff.v1div2.ticks = 0;
+    coeff.w1div2.tv_sec = 0;
+    coeff.w1div2.ticks = 0;
+    coeff.beta1.tv_sec = 0;
+    coeff.beta1.ticks = 1;
+    coeff.beta2.tv_sec = 0;
+    coeff.beta2.ticks = 1;
+    coeff.size = 0;
+    coeff.front = 0;
+    trigf = NULL;
+    
+    clock_init();
+    uart_sync.baud(115200);
+    uart_sync.attach(&uart_recv, Serial::RxIrq);
+
+    syncbusy = SYNCTYPE_NONE;
+    tmp_synctype = SYNCTYPE_64;
+    tmr_sync.attach(&sync_req, 0.1);
+}
+/*
+void timesync_poll()
+{
+    //static last_poll;
+    tmp_synctype = SYNCTYPE_24;
+    sync_req();
+}
+*/
+void clock_init()
+{
+    // select PCLK
+    LPC_SC->PCLKSEL1 = (LPC_SC->PCLKSEL1 & ~(3<<CLK_TIMER)) | (PCLK_DEVIDER<<CLK_TIMER);
+    // power on timer
+    LPC_SC->PCONP |= (1<<PCTIM2);
+    
+    // reset timer
+    TMR->TCR = 2;
+    TMR->CTCR = 0;
+    TMR->PR = 0;
+    TMR->TC = 1;
+    TMR->MR0 = SystemCoreClock - 1;
+    TMR->MCR = 3;
+    
+    clock_sec = 0;
+
+    // capture on CAP.0        
+    TMR->CCR = 0x07;
+    LPC_PINCON->PINSEL0 = LPC_PINCON->PINSEL0  | (3<<8);
+    
+    // setup interrupt
+    __enable_irq();
+    NVIC_SetVector(TIMER2_IRQn, (uint32_t)&tmr1_irq);
+    NVIC_EnableIRQ(TIMER2_IRQn);
+    
+    NVIC_SetPriority(TIMER2_IRQn, 0);
+    NVIC_SetPriority(UART2_IRQn, 1);
+    NVIC_SetPriority(TIMER3_IRQn, 2);
+    NVIC_SetPriority(UART0_IRQn, 2);
+    NVIC_SetPriority(UART3_IRQn, 1);
+
+    // begin freerun
+    TMR->TCR = 1;
+}
+
+void tmr1_irq()
+{
+    if (TMR->IR & (1<<4)) {
+        if (trigf) {
+            trigt.tv_sec = clock_sec;
+            if ((TMR->IR & 0x01) && TMR->CR0 < 256)
+                trigt.tv_sec = clock_sec+1;
+            trigt.ticks = TMR->CR0;
+            //runTriggerFunc();
+            tmr_callback.attach_us(&runTriggerFunc, 10);
+        }
+        TMR->IR = (1<<4);
+    }
+    if (TMR->IR & 0x1) {
+        // Overflow!
+        clock_sec ++;
+        TMR->IR = 0x1;
+    }
+    if (TMR->IR & 0x2) {
+        if (clock_sec == front_lt.tv_sec) {
+            hdtimeval_t * nowtv = timeq+qfront;
+            funcq[qfront]();
+            qfront = (qfront+1)%QUEUE_SIZE;
+            while(qfront != qtail 
+            && nowtv->tv_sec == timeq[qfront].tv_sec
+            && nowtv->ticks == timeq[qfront].ticks) {
+                funcq[qfront]();
+                qfront = (qfront+1)%QUEUE_SIZE;
+            }
+            if (qfront == qtail) {
+                TMR->MCR &= ~(1<<3);
+            } else {
+                getLocalTime(&timeq[qfront], &front_lt);
+                TMR->MR1 = front_lt.ticks;
+            }
+        } else if (clock_sec > front_lt.tv_sec) {
+            // we missed it!
+            qfront = (qfront+1)%QUEUE_SIZE;
+            if (qfront == qtail) {
+                TMR->MCR &= ~(1<<3);
+            } else {
+                getLocalTime(&timeq[qfront], &front_lt);
+                TMR->MR1 = front_lt.ticks;
+            }
+        }
+        TMR->IR = 0x2;
+    }
+}
+
+void runTriggerFunc()
+{
+    timeval_t t;
+    getGlobalTime(&trigt, &trigt);
+    hdtv_totv(&t, &trigt);
+    trigf(&t);
+}
+
+void uart_recv()
+{
+    hdtimeval_t tstamp;
+    getHDTime(&tstamp);
+    
+    //if (!(LPC_UART2->IIR & 0x01) && (LPC_UART2->LSR & 0x01)) {
+    if (uart_sync.readable()) {
+        sync_pkt64_t pkt64;
+        sync_pkt32_t pkt32;
+        sync_pkt24_t pkt24;
+        char * data = NULL;
+        void * pkt_p = NULL;
+        uint8_t len = 0;
+        
+        if (!syncbusy) {
+            len = uart_sync.getc();
+            return;
+        }
+        
+        switch(syncbusy) {
+            case SYNCTYPE_64:
+                data = pkt64.raw;
+                pkt_p = (void *)&pkt64;
+                len = 10;
+                break;
+            case SYNCTYPE_32:
+                data = pkt32.raw;
+                pkt_p = (void *)&pkt32;
+                len = 6;
+                break;
+            case SYNCTYPE_24:
+                pkt24.no_use = 0;
+                pkt_p = (void *)&pkt24;
+                data = pkt24.raw;
+                len = 5;
+                break;
+        }
+        while(len-->0) {
+            //while(!(LPC_UART2->LSR & 0x01));
+            *(data++)= uart_sync.getc(); //LPC_UART2->RBR;
+        }
+        
+        update_data(syncbusy, pkt_p, &tstamp);
+    }
+    syncbusy = SYNCTYPE_NONE;
+}
+
+void sync_req()
+{
+    //if (syncbusy) return;
+    __disable_irq();
+    txstamp.tv_sec = clock_sec;
+    txstamp.ticks = TMR->TC;
+    uart_sync.putc(tmp_synctype);
+    //LPC_UART2->THR = tmp_synctype;
+    __enable_irq();
+    syncbusy = tmp_synctype;
+}
+
+void update_data(synctype_t t, void * pkt_p, hdtimeval_t * rxstamp)
+{
+    hdtimeval_t v, w;
+    hdtimeval_t master_rxt, master_txt;
+    int32_t ticks_diff;
+    hdtv_add(&v, &txstamp, rxstamp);
+    switch (t) {
+        case SYNCTYPE_64: {
+            sync_pkt64_t * p = (sync_pkt64_t *)pkt_p;
+            master_rxt = p->rx_time;
+            master_txt.tv_sec = master_rxt.tv_sec;
+            master_txt.ticks = (master_rxt.ticks & 0xFFFF0000) + p->tx_time;
+        } break;
+        case SYNCTYPE_32: {
+            sync_pkt32_t * p = (sync_pkt32_t *)pkt_p;
+            hdtimeval_t tmp;
+            getGlobalTime(&txstamp, &tmp);
+            if (tmp.ticks > MAX_TICK/2) {
+                if (p->rx_time > tmp.ticks-MAX_TICK/2) {
+                    master_rxt.tv_sec = tmp.tv_sec;
+                } else {
+                    master_rxt.tv_sec = tmp.tv_sec +1;
+                }
+            } else {
+                if (p->rx_time > tmp.ticks+MAX_TICK/2) {
+                    master_rxt.tv_sec = tmp.tv_sec-1;
+                } else {
+                    master_rxt.tv_sec = tmp.tv_sec;
+                }
+            }
+            master_rxt.ticks = p->rx_time;
+            master_txt.tv_sec = master_rxt.tv_sec;
+            master_txt.ticks = (master_rxt.ticks & 0xFFFF0000) + p->tx_time;
+        } break;
+        case SYNCTYPE_24: {
+            sync_pkt24_t * p = (sync_pkt24_t *)pkt_p;
+            hdtimeval_t tmp;
+            getGlobalTime(&txstamp, &tmp);
+            p->rx_time >>= 8;
+            if (tmp.ticks > (1<<23)) {
+                tmp.ticks = tmp.ticks-(1<<23);
+                master_rxt.ticks = (tmp.ticks & 0xFF000000) + p->rx_time;
+                master_rxt.tv_sec = tmp.tv_sec;
+            } else {
+                tmp.ticks = tmp.ticks+MAX_TICK-(1<<23);
+                master_rxt.ticks = (tmp.ticks & 0xFF000000) + p->rx_time;
+                master_rxt.tv_sec = tmp.tv_sec-1;
+            }
+            if (master_rxt.ticks < tmp.ticks) {
+                master_rxt.ticks += 0x1000000;
+                if (master_rxt.ticks > MAX_TICK) {
+                    master_rxt.ticks &= 0xFFFFFF;
+                    master_rxt.tv_sec ++;
+                }
+            }
+            master_txt.tv_sec = master_rxt.tv_sec;
+            master_txt.ticks = (master_rxt.ticks & 0xFFFF0000) + p->tx_time;            
+        } break;
+    }
+    //printf("t1,t2: %d,%d, %d,%d \r\n",master_rxt.tv_sec, master_rxt.ticks>>24, master_rxt.ticks & 0xFFFFFF, master_txt.ticks);
+    if (master_rxt.ticks > master_txt.ticks) {
+        master_txt.ticks += 0x10000;
+        if (master_txt.ticks >= MAX_TICK) {
+            master_txt.ticks &= 0xFFFF;
+            master_txt.tv_sec ++;
+        }
+    }
+    hdtv_add(&w, &master_rxt, &master_txt);
+
+    hdtv_div2(&v, &v);
+    hdtv_div2(&w, &w);
+    // evaluate performance
+    {
+        hdtimeval_t tmp;
+        getGlobalTime(&v, &tmp);
+        hdtv_sub(&tmp, &tmp, &w);
+        if (tmp.tv_sec > 10) 
+            ticks_diff = 0x7FFFFFFF;
+        else {
+            ticks_diff = tmp.tv_sec * MAX_TICK + tmp.ticks;
+        }
+        //printf("perf: %d \r\n", ticks_diff);
+    }
+    if (coeff.size)
+        if (coeff.size<HISTORY_LEN) {
+            hdtv_sub(&coeff.beta1, &w, &(coeff.hisw[0]));
+            hdtv_sub(&coeff.beta2, &v, &(coeff.hisv[0]));
+        } else {
+            hdtv_sub(&coeff.beta1, &w, &(coeff.hisw[coeff.front]));
+            hdtv_sub(&coeff.beta2, &v, &(coeff.hisv[coeff.front]));
+        }
+    /*if(coeff.size>=8) {
+        hdtimeval_t tmp;
+        hdtv_div8(&tmp, &(coeff.hisw[coeff.front]));
+        hdtv_sub(&coeff.w1div2, &coeff.w1div2, &tmp);
+        hdtv_div8(&tmp, &(coeff.hisv[coeff.front]));
+        hdtv_sub(&coeff.v1div2, &coeff.v1div2, &tmp);
+        hdtv_div8(&tmp, &w);
+        hdtv_add(&coeff.w1div2, &coeff.w1div2, &tmp);
+        hdtv_div8(&tmp, &v);
+        hdtv_add(&coeff.v1div2, &coeff.v1div2, &tmp);
+    } else {*/
+        coeff.v1div2 = v;
+        coeff.w1div2 = w;
+    //}
+    coeff.hisw[coeff.front] = w;
+    coeff.hisv[coeff.front] = v;
+    coeff.front = (coeff.front+1) % HISTORY_LEN;
+    if (coeff.size<=HISTORY_LEN) coeff.size++;
+    /*if (coeff.size==8) {
+        hdtimeval_t tmp;
+        coeff.w1div2.tv_sec = 0;
+        coeff.w1div2.ticks = 0;
+        coeff.v1div2.tv_sec = 0;
+        coeff.v1div2.ticks = 0;
+        for (uint8_t i=0; i<8; i++) {
+            hdtv_div8(&tmp, &(coeff.hisw[i]));
+            hdtv_add(&coeff.w1div2, &coeff.w1div2, &tmp);
+            hdtv_div8(&tmp, &(coeff.hisv[i]));
+            hdtv_add(&coeff.v1div2, &coeff.v1div2, &tmp);
+        }
+        printf("updated!\r\n");
+    }*/
+    //printf("w/v: %d, %d \r\n", coeff.w1div2.ticks, coeff.v1div2.ticks);
+    if (qfront != qtail) {
+        getLocalTime(&timeq[qfront], &front_lt);
+        TMR->MR1 = front_lt.ticks;
+        TMR->MCR |= (1<<3);
+    }
+    // schedule next sync
+    ticks_diff = abs(ticks_diff);
+    if (ticks_diff < 200 && coeff.size>8) {
+        tmp_synctype = SYNCTYPE_24;
+        tmr_sync.attach(&sync_req, 60);
+    } else if (ticks_diff < 500 && coeff.size>4) {
+        tmp_synctype = SYNCTYPE_24;
+        tmr_sync.attach(&sync_req, 30);
+    } else if (ticks_diff < 800 && coeff.size>2) {
+        tmp_synctype = SYNCTYPE_24;
+        tmr_sync.attach(&sync_req, 20);
+    } else if (ticks_diff < 5000) {
+        tmp_synctype = SYNCTYPE_32;
+        tmr_sync.attach(&sync_req, 10);
+    } else {
+        tmp_synctype = SYNCTYPE_64;
+        tmr_sync.attach(&sync_req, 5);
+    }
+    led = !led;
+}
+
+__INLINE void getHDTime(struct hdtimeval * hdtv)
+{
+    __disable_irq();
+    hdtv->tv_sec = clock_sec;
+    hdtv->ticks = TMR->TC;
+    __enable_irq();
+    return;
+}
+
+void getTime(struct timeval * tv)
+{
+    hdtimeval_t tstamp, gstamp, tstamp1; 
+    static hdtimeval_t comp_delay = {0,0};
+
+    getHDTime(&tstamp);
+    
+    hdtv_add(&gstamp, &tstamp, &comp_delay);
+    getGlobalTime(&gstamp, &gstamp);
+    
+    getHDTime(&tstamp1);
+    hdtv_sub(&comp_delay, &tstamp1, &tstamp);
+    //printf("delay: %d\r\n", comp_delay.ticks);
+
+    tv->tv_sec = gstamp.tv_sec;
+    tv->tv_usec = ((gstamp.ticks+48) >> 5) / 3;
+    return; 
+}
+
+void getGlobalTime(hdtimeval * lt, hdtimeval * gt)
+{
+    hdtimeval_t tmp;
+    hdtv_sub(&tmp, lt, &coeff.v1div2);
+    hdtv_muldiv(&tmp, &tmp, &coeff.beta1, &coeff.beta2);
+    hdtv_add(gt, &tmp, &coeff.w1div2);
+}
+
+void getLocalTime(hdtimeval * gt, hdtimeval * lt)
+{
+    hdtimeval_t tmp;
+    hdtv_sub(&tmp, gt, &coeff.w1div2);
+    hdtv_muldiv(&tmp, &tmp, &coeff.beta2, &coeff.beta1);
+    hdtv_add(lt, &tmp, &coeff.v1div2);
+}
+
+int enqueue(void (*schedFunc)(void), hdtimeval_t *tv)
+{
+    uint8_t p = qtail;
+    if ((qtail+1)%QUEUE_SIZE == qfront) {
+        return 1;
+    }
+    while(p != qfront) {
+        uint8_t prev = (p+QUEUE_SIZE-1)%QUEUE_SIZE;
+        if (tv->tv_sec > timeq[prev].tv_sec 
+        || (tv->tv_sec == timeq[prev].tv_sec && tv->ticks >= timeq[prev].ticks)) break;
+        timeq[p] = timeq[prev];
+        funcq[p] = funcq[prev];
+        p = prev;
+    } 
+    timeq[p] = *tv;
+    funcq[p] = schedFunc;
+    qtail = (qtail+1)%QUEUE_SIZE;
+    return 0;
+}
+
+int runAtTime(void (*schedFunc)(void), struct timeval *tv)
+{
+    hdtimeval_t hdtv;
+    int ret;
+    hdtv.tv_sec = tv->tv_sec;
+    hdtv.ticks = tv->tv_usec * 96;
+    //getLocalTime(&hdtv, &hdtv);
+    ret = enqueue(schedFunc, &hdtv);
+    if (qfront != qtail) {
+        getLocalTime(&timeq[qfront], &front_lt);
+        TMR->MR1 = front_lt.ticks;
+        TMR->MCR |= (1<<3);
+    }
+    return ret;
+}
+
+
+void runAtTrigger(void (*trigFunc)(struct timeval *tv))
+{
+    trigf = trigFunc;
+}
diff -r 000000000000 -r 362932d519c6 timesync_slave.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/timesync_slave.h	Fri Dec 03 20:53:52 2010 +0000
@@ -0,0 +1,19 @@
+#ifndef TIMESYNC_SLAVE_H
+#define TIMESYNC_SLAVE_H
+
+#include "timesync.h"
+
+#define HISTORY_LEN 8
+
+typedef struct {
+    hdtimeval_t v1div2;
+    hdtimeval_t w1div2;
+    hdtimeval_t beta1;
+    hdtimeval_t beta2;
+    hdtimeval_t hisw[HISTORY_LEN];
+    hdtimeval_t hisv[HISTORY_LEN];
+    uint8_t front;
+    uint8_t size;
+} coeff_t;
+
+#endif //TIMESYNC_SLAVE_H