syncMaster for problem 3

Committer:
the729
Date:
Fri Dec 03 20:53:21 2010 +0000
Revision:
0:b9f06a7ae791

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
the729 0:b9f06a7ae791 1 #include "mbed.h"
the729 0:b9f06a7ae791 2 #include "timesync.h"
the729 0:b9f06a7ae791 3 #include "hdtimeval_math.h"
the729 0:b9f06a7ae791 4
the729 0:b9f06a7ae791 5 int32_t clock_sec;
the729 0:b9f06a7ae791 6 DigitalOut led(LED1);
the729 0:b9f06a7ae791 7 Serial uart_sync(p28,p27);
the729 0:b9f06a7ae791 8 Timeout tmr_callback;
the729 0:b9f06a7ae791 9
the729 0:b9f06a7ae791 10 hdtimeval_t timeq[QUEUE_SIZE];
the729 0:b9f06a7ae791 11 void (*funcq[QUEUE_SIZE])(void);
the729 0:b9f06a7ae791 12 uint8_t qfront;
the729 0:b9f06a7ae791 13 uint8_t qtail;
the729 0:b9f06a7ae791 14
the729 0:b9f06a7ae791 15 uint32_t sync_count[3];
the729 0:b9f06a7ae791 16
the729 0:b9f06a7ae791 17 void (*trigf)(struct timeval *);
the729 0:b9f06a7ae791 18 hdtimeval_t trigt;
the729 0:b9f06a7ae791 19
the729 0:b9f06a7ae791 20 void clock_init();
the729 0:b9f06a7ae791 21 void tmr1_irq();
the729 0:b9f06a7ae791 22 void uart_recv();
the729 0:b9f06a7ae791 23 __INLINE void getHDTime(struct hdtimeval * hdtv);
the729 0:b9f06a7ae791 24 void runTriggerFunc();
the729 0:b9f06a7ae791 25
the729 0:b9f06a7ae791 26 void timesync_init()
the729 0:b9f06a7ae791 27 {
the729 0:b9f06a7ae791 28 sync_count[0]=0;
the729 0:b9f06a7ae791 29 sync_count[1]=0;
the729 0:b9f06a7ae791 30 sync_count[2]=0;
the729 0:b9f06a7ae791 31
the729 0:b9f06a7ae791 32 wait_ms(100);
the729 0:b9f06a7ae791 33 clock_init();
the729 0:b9f06a7ae791 34 uart_sync.baud(115200);
the729 0:b9f06a7ae791 35 uart_sync.attach(&uart_recv, Serial::RxIrq);
the729 0:b9f06a7ae791 36
the729 0:b9f06a7ae791 37 qfront = 0;
the729 0:b9f06a7ae791 38 qtail = 0;
the729 0:b9f06a7ae791 39 trigf = NULL;
the729 0:b9f06a7ae791 40 }
the729 0:b9f06a7ae791 41
the729 0:b9f06a7ae791 42 void clock_init()
the729 0:b9f06a7ae791 43 {
the729 0:b9f06a7ae791 44 // select PCLK
the729 0:b9f06a7ae791 45 LPC_SC->PCLKSEL1 = (LPC_SC->PCLKSEL1 & ~(3<<CLK_TIMER)) | (PCLK_DEVIDER<<CLK_TIMER);
the729 0:b9f06a7ae791 46 // power on timer
the729 0:b9f06a7ae791 47 LPC_SC->PCONP |= (1<<PCTIM2);
the729 0:b9f06a7ae791 48
the729 0:b9f06a7ae791 49 // reset timer
the729 0:b9f06a7ae791 50 TMR->TCR = 2;
the729 0:b9f06a7ae791 51 TMR->CTCR = 0;
the729 0:b9f06a7ae791 52 TMR->PR = 0;
the729 0:b9f06a7ae791 53 TMR->TC = 1;
the729 0:b9f06a7ae791 54 TMR->MR0 = SystemCoreClock - 1;
the729 0:b9f06a7ae791 55 TMR->MCR = 3;
the729 0:b9f06a7ae791 56
the729 0:b9f06a7ae791 57 clock_sec = 0;
the729 0:b9f06a7ae791 58
the729 0:b9f06a7ae791 59 // capture on CAP.0
the729 0:b9f06a7ae791 60 TMR->CCR = 0x05;
the729 0:b9f06a7ae791 61 LPC_PINCON->PINSEL0 = LPC_PINCON->PINSEL0 | (3<<8);
the729 0:b9f06a7ae791 62
the729 0:b9f06a7ae791 63 // setup interrupt
the729 0:b9f06a7ae791 64 __enable_irq();
the729 0:b9f06a7ae791 65 NVIC_SetVector(TIMER2_IRQn, (uint32_t)&tmr1_irq);
the729 0:b9f06a7ae791 66 NVIC_EnableIRQ(TIMER2_IRQn);
the729 0:b9f06a7ae791 67
the729 0:b9f06a7ae791 68 NVIC_SetPriority(TIMER2_IRQn, 0);
the729 0:b9f06a7ae791 69 NVIC_SetPriority(UART2_IRQn, 1);
the729 0:b9f06a7ae791 70 NVIC_SetPriority(TIMER3_IRQn, 2);
the729 0:b9f06a7ae791 71 NVIC_SetPriority(UART0_IRQn, 2);
the729 0:b9f06a7ae791 72 NVIC_SetPriority(UART3_IRQn, 1);
the729 0:b9f06a7ae791 73
the729 0:b9f06a7ae791 74 // begin freerun
the729 0:b9f06a7ae791 75 TMR->TCR = 1;
the729 0:b9f06a7ae791 76 }
the729 0:b9f06a7ae791 77
the729 0:b9f06a7ae791 78 void tmr1_irq()
the729 0:b9f06a7ae791 79 {
the729 0:b9f06a7ae791 80 if (TMR->IR & (1<<4)) {
the729 0:b9f06a7ae791 81 if (trigf) {
the729 0:b9f06a7ae791 82 trigt.tv_sec = clock_sec;
the729 0:b9f06a7ae791 83 if ((TMR->IR & 0x01) && TMR->CR0 < 256)
the729 0:b9f06a7ae791 84 trigt.tv_sec = clock_sec+1;
the729 0:b9f06a7ae791 85 trigt.ticks = TMR->CR0;
the729 0:b9f06a7ae791 86 //runTriggerFunc();
the729 0:b9f06a7ae791 87 tmr_callback.attach_us(&runTriggerFunc, 10);
the729 0:b9f06a7ae791 88 }
the729 0:b9f06a7ae791 89 TMR->IR = (1<<4);
the729 0:b9f06a7ae791 90 }
the729 0:b9f06a7ae791 91 if (TMR->IR & 0x1) {
the729 0:b9f06a7ae791 92 // Overflow!
the729 0:b9f06a7ae791 93 clock_sec ++;
the729 0:b9f06a7ae791 94 TMR->IR = 0x1;
the729 0:b9f06a7ae791 95 }
the729 0:b9f06a7ae791 96 if (TMR->IR & 0x2) {
the729 0:b9f06a7ae791 97 if (clock_sec == timeq[qfront].tv_sec) {
the729 0:b9f06a7ae791 98 uint32_t nowtick = timeq[qfront].ticks;
the729 0:b9f06a7ae791 99 funcq[qfront]();
the729 0:b9f06a7ae791 100 qfront = (qfront+1)%QUEUE_SIZE;
the729 0:b9f06a7ae791 101 while(qfront != qtail
the729 0:b9f06a7ae791 102 && clock_sec == timeq[qfront].tv_sec
the729 0:b9f06a7ae791 103 && nowtick == timeq[qfront].ticks) {
the729 0:b9f06a7ae791 104 funcq[qfront]();
the729 0:b9f06a7ae791 105 qfront = (qfront+1)%QUEUE_SIZE;
the729 0:b9f06a7ae791 106 }
the729 0:b9f06a7ae791 107 if (qfront == qtail) {
the729 0:b9f06a7ae791 108 TMR->MCR &= ~(1<<3);
the729 0:b9f06a7ae791 109 } else {
the729 0:b9f06a7ae791 110 TMR->MR1 = timeq[qfront].ticks;
the729 0:b9f06a7ae791 111 }
the729 0:b9f06a7ae791 112 } else if (clock_sec > timeq[qfront].tv_sec) {
the729 0:b9f06a7ae791 113 // we missed it!
the729 0:b9f06a7ae791 114 printf("miss\r\n");
the729 0:b9f06a7ae791 115 qfront = (qfront+1)%QUEUE_SIZE;
the729 0:b9f06a7ae791 116 if (qfront == qtail) {
the729 0:b9f06a7ae791 117 TMR->MCR &= ~(1<<3);
the729 0:b9f06a7ae791 118 } else {
the729 0:b9f06a7ae791 119 TMR->MR1 = timeq[qfront].ticks;
the729 0:b9f06a7ae791 120 }
the729 0:b9f06a7ae791 121 }
the729 0:b9f06a7ae791 122 TMR->IR = 0x2;
the729 0:b9f06a7ae791 123 }
the729 0:b9f06a7ae791 124 }
the729 0:b9f06a7ae791 125
the729 0:b9f06a7ae791 126 void runTriggerFunc()
the729 0:b9f06a7ae791 127 {
the729 0:b9f06a7ae791 128 timeval_t t;
the729 0:b9f06a7ae791 129 hdtv_totv(&t, &trigt);
the729 0:b9f06a7ae791 130 trigf(&t);
the729 0:b9f06a7ae791 131 }
the729 0:b9f06a7ae791 132
the729 0:b9f06a7ae791 133 void uart_recv()
the729 0:b9f06a7ae791 134 {
the729 0:b9f06a7ae791 135 hdtimeval_t tstamp;
the729 0:b9f06a7ae791 136 getHDTime(&tstamp);
the729 0:b9f06a7ae791 137
the729 0:b9f06a7ae791 138 //if (!(LPC_UART2->IIR & 0x01) && (LPC_UART2->LSR & 0x01)) {
the729 0:b9f06a7ae791 139 if (uart_sync.readable()) {
the729 0:b9f06a7ae791 140 sync_pkt64_t pkt64;
the729 0:b9f06a7ae791 141 sync_pkt32_t pkt32;
the729 0:b9f06a7ae791 142 sync_pkt24_t pkt24;
the729 0:b9f06a7ae791 143 char * data = NULL;
the729 0:b9f06a7ae791 144 uint8_t len = 0;
the729 0:b9f06a7ae791 145 char cmd;
the729 0:b9f06a7ae791 146
the729 0:b9f06a7ae791 147 cmd = uart_sync.getc();
the729 0:b9f06a7ae791 148 //cmd = LPC_UART2->RBR;
the729 0:b9f06a7ae791 149 //printf("byte: %x \r\n", cmd);
the729 0:b9f06a7ae791 150 switch (cmd) {
the729 0:b9f06a7ae791 151 case SYNCTYPE_64:
the729 0:b9f06a7ae791 152 pkt64.rx_time = tstamp;
the729 0:b9f06a7ae791 153 pkt64.tx_time = TMR->TC;
the729 0:b9f06a7ae791 154 uart_sync.putc(pkt64.raw[0]);
the729 0:b9f06a7ae791 155 len = 9;
the729 0:b9f06a7ae791 156 data = pkt64.raw + 1;
the729 0:b9f06a7ae791 157 sync_count[0]++;
the729 0:b9f06a7ae791 158 break;
the729 0:b9f06a7ae791 159 case SYNCTYPE_32:
the729 0:b9f06a7ae791 160 pkt32.rx_time = tstamp.ticks;
the729 0:b9f06a7ae791 161 pkt32.tx_time = TMR->TC;
the729 0:b9f06a7ae791 162 uart_sync.putc(pkt32.raw[0]);
the729 0:b9f06a7ae791 163 len = 5;
the729 0:b9f06a7ae791 164 data = pkt32.raw + 1;
the729 0:b9f06a7ae791 165 sync_count[1]++;
the729 0:b9f06a7ae791 166 break;
the729 0:b9f06a7ae791 167 case SYNCTYPE_24:
the729 0:b9f06a7ae791 168 pkt24.rx_time = tstamp.ticks << 8;
the729 0:b9f06a7ae791 169 pkt24.tx_time = TMR->TC;
the729 0:b9f06a7ae791 170 uart_sync.putc(pkt24.raw[0]);
the729 0:b9f06a7ae791 171 len = 4;
the729 0:b9f06a7ae791 172 data = pkt24.raw + 1;
the729 0:b9f06a7ae791 173 sync_count[2]++;
the729 0:b9f06a7ae791 174 break;
the729 0:b9f06a7ae791 175 }
the729 0:b9f06a7ae791 176 while (len-->0) {
the729 0:b9f06a7ae791 177 uart_sync.putc(*(data++));
the729 0:b9f06a7ae791 178 }
the729 0:b9f06a7ae791 179 //printf("rx_tick: %d,%d,%d \r\n", tstamp.tv_sec, tstamp.ticks>>24, tstamp.ticks & 0xFFFFFF);
the729 0:b9f06a7ae791 180 }
the729 0:b9f06a7ae791 181 led = !led;
the729 0:b9f06a7ae791 182 }
the729 0:b9f06a7ae791 183
the729 0:b9f06a7ae791 184 __INLINE void getHDTime(struct hdtimeval * hdtv)
the729 0:b9f06a7ae791 185 {
the729 0:b9f06a7ae791 186 __disable_irq();
the729 0:b9f06a7ae791 187 hdtv->tv_sec = clock_sec;
the729 0:b9f06a7ae791 188 hdtv->ticks = TMR->TC;
the729 0:b9f06a7ae791 189 __enable_irq();
the729 0:b9f06a7ae791 190 return;
the729 0:b9f06a7ae791 191 }
the729 0:b9f06a7ae791 192
the729 0:b9f06a7ae791 193 void getTime(struct timeval * tv)
the729 0:b9f06a7ae791 194 {
the729 0:b9f06a7ae791 195 hdtimeval_t tstamp;
the729 0:b9f06a7ae791 196
the729 0:b9f06a7ae791 197 getHDTime(&tstamp);
the729 0:b9f06a7ae791 198 hdtv_totv(tv, &tstamp);
the729 0:b9f06a7ae791 199 return;
the729 0:b9f06a7ae791 200 }
the729 0:b9f06a7ae791 201
the729 0:b9f06a7ae791 202 int enqueue(void (*schedFunc)(void), hdtimeval_t *tv)
the729 0:b9f06a7ae791 203 {
the729 0:b9f06a7ae791 204 uint8_t p = qtail;
the729 0:b9f06a7ae791 205 if ((qtail+1)%QUEUE_SIZE == qfront) {
the729 0:b9f06a7ae791 206 return 1;
the729 0:b9f06a7ae791 207 }
the729 0:b9f06a7ae791 208 while(p != qfront) {
the729 0:b9f06a7ae791 209 uint8_t prev = (p+QUEUE_SIZE-1)%QUEUE_SIZE;
the729 0:b9f06a7ae791 210 if (tv->tv_sec > timeq[prev].tv_sec
the729 0:b9f06a7ae791 211 || (tv->tv_sec == timeq[prev].tv_sec && tv->ticks >= timeq[prev].ticks)) break;
the729 0:b9f06a7ae791 212 timeq[p] = timeq[prev];
the729 0:b9f06a7ae791 213 funcq[p] = funcq[prev];
the729 0:b9f06a7ae791 214 p = prev;
the729 0:b9f06a7ae791 215 }
the729 0:b9f06a7ae791 216 timeq[p] = *tv;
the729 0:b9f06a7ae791 217 funcq[p] = schedFunc;
the729 0:b9f06a7ae791 218 qtail = (qtail+1)%QUEUE_SIZE;
the729 0:b9f06a7ae791 219 return 0;
the729 0:b9f06a7ae791 220 }
the729 0:b9f06a7ae791 221
the729 0:b9f06a7ae791 222 int runAtTime(void (*schedFunc)(void), struct timeval *tv)
the729 0:b9f06a7ae791 223 {
the729 0:b9f06a7ae791 224 hdtimeval_t hdtv;
the729 0:b9f06a7ae791 225 int ret;
the729 0:b9f06a7ae791 226 hdtv.tv_sec = tv->tv_sec;
the729 0:b9f06a7ae791 227 hdtv.ticks = tv->tv_usec * 96;
the729 0:b9f06a7ae791 228 ret = enqueue(schedFunc, &hdtv);
the729 0:b9f06a7ae791 229 if (!ret && qtail != qfront) {
the729 0:b9f06a7ae791 230 TMR->MR1 = timeq[qfront].ticks;
the729 0:b9f06a7ae791 231 TMR->MCR |= (1<<3);
the729 0:b9f06a7ae791 232 }
the729 0:b9f06a7ae791 233 return ret;
the729 0:b9f06a7ae791 234 }
the729 0:b9f06a7ae791 235
the729 0:b9f06a7ae791 236 void runAtTrigger(void (*trigFunc)(struct timeval *tv))
the729 0:b9f06a7ae791 237 {
the729 0:b9f06a7ae791 238 trigf = trigFunc;
the729 0:b9f06a7ae791 239 }