mirror of
git://projects.qi-hardware.com/ben-blinkenlights.git
synced 2024-11-27 17:05:20 +02:00
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
This commit is contained in:
parent
a3cea3573c
commit
6d8c8dd951
@ -50,8 +50,12 @@
|
||||
#define TSCR _TCU(0x3c) /* Timer STOP clear */
|
||||
#define TESR _TCU(0x14) /* Timer counter enable set */
|
||||
#define TECR _TCU(0x18) /* Timer counter enable clear */
|
||||
#define TFR _TCU(0x20) /* Timer flag */
|
||||
#define TFSR _TCU(0x24) /* Timer flag set */
|
||||
#define TFCR _TCU(0x28) /* Timer flag clear */
|
||||
#define TCSR(n) _TCU(0x4c+0x10*(n)) /* Timer control */
|
||||
#define TDFR(n) _TCU(0x40+0x10*(n)) /* Timer data full */
|
||||
#define TDHR(n) _TCU(0x44+0x10*(n)) /* Timer data half */
|
||||
#define TCNT(n) _TCU(0x48+0x10*(n)) /* Timer counter */
|
||||
|
||||
#define MSC_STRPCL _MSC(0x00) /* Start/stop MMC/SD clock */
|
||||
|
@ -233,9 +233,14 @@ static void cleanup(void)
|
||||
/* ----- Delay logic ------------------------------------------------------- */
|
||||
|
||||
|
||||
static void until(uint16_t cycles)
|
||||
static void delay(uint16_t cycles)
|
||||
{
|
||||
while ((TCNT(TIMER) & 0xffff) < cycles);
|
||||
static uint16_t next = 0;
|
||||
|
||||
next += cycles;
|
||||
TDHR(TIMER) = next;
|
||||
TFCR = 1 << (TIMER+16);
|
||||
while (!(TFR & (1 << (TIMER+16))));
|
||||
}
|
||||
|
||||
|
||||
@ -292,7 +297,7 @@ static void line(unsigned long line)
|
||||
DTA(DMA) = REG_PADDR(MSC_TXFIFO); /* MUST set this each time */
|
||||
DTC(DMA) = (mode->xres+63) >> 6;
|
||||
|
||||
until(mode->hback_cycles);
|
||||
delay(mode->hback_cycles);
|
||||
|
||||
/* HSYNC */
|
||||
|
||||
@ -313,7 +318,7 @@ static void line(unsigned long line)
|
||||
(1 << 31) | /* no descriptor */
|
||||
1;
|
||||
|
||||
until(mode->hback_cycles+mode->hsync_cycles);
|
||||
delay(mode->hsync_cycles);
|
||||
|
||||
// MSC_TXFIFO = 0xffffffff;
|
||||
|
||||
@ -323,7 +328,7 @@ static void line(unsigned long line)
|
||||
PDDATS = HSYNC;
|
||||
PDFUNC = CMD;
|
||||
|
||||
until(mode->line_cycles);
|
||||
delay(mode->line_cycles-mode->hback_cycles-mode->hsync_cycles);
|
||||
MSC_TXFIFO = 0;
|
||||
if (MSC_STAT & 3)
|
||||
bad++;
|
||||
@ -333,11 +338,10 @@ static void line(unsigned long line)
|
||||
static void hdelay(int cycles)
|
||||
{
|
||||
while (cycles--) {
|
||||
TCNT(TIMER) = 0;
|
||||
PDDATC = HSYNC;
|
||||
until(mode->hsync_cycles);
|
||||
delay(mode->hsync_cycles);
|
||||
PDDATS = HSYNC;
|
||||
until(mode->line_cycles);
|
||||
delay(mode->line_cycles-mode->hsync_cycles);
|
||||
}
|
||||
}
|
||||
|
||||
@ -359,22 +363,15 @@ static void frame(const unsigned long *f)
|
||||
* The horizontal back porch of the previous line is handled inside
|
||||
* "line", so we have to wait for less than a full line here.
|
||||
*/
|
||||
TCNT(TIMER) = 0;
|
||||
PDDATC = HSYNC;
|
||||
until(mode->hsync_cycles);
|
||||
delay(mode->hsync_cycles);
|
||||
PDDATS = HSYNC;
|
||||
until(mode->line_cycles-mode->hback_cycles);
|
||||
delay(mode->line_cycles-mode->hback_cycles-mode->hsync_cycles);
|
||||
|
||||
/*
|
||||
* Note: resetting the timer just before calling "line" isn't enough.
|
||||
* We have t reset it before the loop and right after returning from
|
||||
* "line".
|
||||
*/
|
||||
TCNT(TIMER) = 0;
|
||||
for (p = f; p != f+mode->yres; p++) {
|
||||
for (p = f; p != f+mode->yres; p++)
|
||||
line(*p);
|
||||
TCNT(TIMER) = 0;
|
||||
}
|
||||
|
||||
delay(mode->hback_cycles);
|
||||
|
||||
/* Back porch */
|
||||
hdelay(mode->vback_lines);
|
||||
@ -401,6 +398,7 @@ static void session(void (*gen)(void **fb, int xres, int yres), int frames)
|
||||
|
||||
setup_noirq();
|
||||
|
||||
TCNT(TIMER) = 0;
|
||||
for (i = 0; !frames || i != frames; i++) {
|
||||
frame(f_phys);
|
||||
if (DTC(DMA)) {
|
||||
|
Loading…
Reference in New Issue
Block a user