Date:2011-05-02 11:11:29 (12 years 10 months ago)
Author:Werner Almesberger
Commit:6d8c8dd951c4e3f43811b09f17de54e1ee3734f0
Message:ubb-vga: use a free-running counter instead of resetting it for each line

Two benefits:
1) We don't accumulate errors from the delay between the timer reset and
the deadline preceding it
2) In the future, we may use WAIT to wait for timer expiration, which
should cause less bus activity and is should also reduce jitter

- regs4740.h (TFR. TFSR, TFCR, TDHR): added more timer registers
- ubb-vga.c (until): renamed to "delay" and changed to measure relative
to the last deadline
- ubb-vga.c (line, hdelay, frame): replaced "until" with "delay"
- ubb-vga.c (hdelay, frame, session): reset the timer only once, at
the beginning of the session
- ubb-vga.c (frame): we didn't wait for the horizontal back porch of
the last image line
Files: ubb-vga/regs4740.h (1 diff)
ubb-vga/ubb-vga.c (7 diffs)

Change Details

ubb-vga/regs4740.h
5050#define TSCR _TCU(0x3c) /* Timer STOP clear */
5151#define TESR _TCU(0x14) /* Timer counter enable set */
5252#define TECR _TCU(0x18) /* Timer counter enable clear */
53#define TFR _TCU(0x20) /* Timer flag */
54#define TFSR _TCU(0x24) /* Timer flag set */
55#define TFCR _TCU(0x28) /* Timer flag clear */
5356#define TCSR(n) _TCU(0x4c+0x10*(n)) /* Timer control */
5457#define TDFR(n) _TCU(0x40+0x10*(n)) /* Timer data full */
58#define TDHR(n) _TCU(0x44+0x10*(n)) /* Timer data half */
5559#define TCNT(n) _TCU(0x48+0x10*(n)) /* Timer counter */
5660
5761#define MSC_STRPCL _MSC(0x00) /* Start/stop MMC/SD clock */
ubb-vga/ubb-vga.c
233233/* ----- Delay logic ------------------------------------------------------- */
234234
235235
236static void until(uint16_t cycles)
236static void delay(uint16_t cycles)
237237{
238    while ((TCNT(TIMER) & 0xffff) < cycles);
238    static uint16_t next = 0;
239
240    next += cycles;
241    TDHR(TIMER) = next;
242    TFCR = 1 << (TIMER+16);
243    while (!(TFR & (1 << (TIMER+16))));
239244}
240245
241246
...... 
292297    DTA(DMA) = REG_PADDR(MSC_TXFIFO); /* MUST set this each time */
293298    DTC(DMA) = (mode->xres+63) >> 6;
294299
295    until(mode->hback_cycles);
300    delay(mode->hback_cycles);
296301
297302    /* HSYNC */
298303
...... 
313318        (1 << 31) | /* no descriptor */
314319        1;
315320
316    until(mode->hback_cycles+mode->hsync_cycles);
321    delay(mode->hsync_cycles);
317322
318323// MSC_TXFIFO = 0xffffffff;
319324
...... 
323328    PDDATS = HSYNC;
324329    PDFUNC = CMD;
325330
326    until(mode->line_cycles);
331    delay(mode->line_cycles-mode->hback_cycles-mode->hsync_cycles);
327332    MSC_TXFIFO = 0;
328333    if (MSC_STAT & 3)
329334        bad++;
...... 
333338static void hdelay(int cycles)
334339{
335340    while (cycles--) {
336        TCNT(TIMER) = 0;
337341        PDDATC = HSYNC;
338        until(mode->hsync_cycles);
342        delay(mode->hsync_cycles);
339343        PDDATS = HSYNC;
340        until(mode->line_cycles);
344        delay(mode->line_cycles-mode->hsync_cycles);
341345    }
342346}
343347
...... 
359363     * The horizontal back porch of the previous line is handled inside
360364     * "line", so we have to wait for less than a full line here.
361365     */
362    TCNT(TIMER) = 0;
363366    PDDATC = HSYNC;
364    until(mode->hsync_cycles);
367    delay(mode->hsync_cycles);
365368    PDDATS = HSYNC;
366    until(mode->line_cycles-mode->hback_cycles);
369    delay(mode->line_cycles-mode->hback_cycles-mode->hsync_cycles);
367370
368    /*
369     * Note: resetting the timer just before calling "line" isn't enough.
370     * We have t reset it before the loop and right after returning from
371     * "line".
372     */
373    TCNT(TIMER) = 0;
374    for (p = f; p != f+mode->yres; p++) {
371    for (p = f; p != f+mode->yres; p++)
375372        line(*p);
376        TCNT(TIMER) = 0;
377    }
373
374    delay(mode->hback_cycles);
378375
379376    /* Back porch */
380377    hdelay(mode->vback_lines);
...... 
401398
402399    setup_noirq();
403400
401    TCNT(TIMER) = 0;
404402    for (i = 0; !frames || i != frames; i++) {
405403        frame(f_phys);
406404        if (DTC(DMA)) {

Archive Download the corresponding diff file

Branches:
master



interactive