software/dvimixer: support two channels
This commit is contained in:
parent
06064d33aa
commit
546aa76aef
|
@ -1,7 +1,7 @@
|
|||
M2DIR=../..
|
||||
include $(M2DIR)/software/common.mak
|
||||
|
||||
OBJECTS=crt0.o isr.o main.o
|
||||
OBJECTS=crt0.o isr.o dvisampler0.o dvisampler1.o main.o
|
||||
|
||||
all: videomixer.bin
|
||||
|
||||
|
@ -30,6 +30,30 @@ main.o: main.c
|
|||
%.o: %.S
|
||||
$(assemble)
|
||||
|
||||
define gen0
|
||||
@echo " GEN " $@
|
||||
@sed -e "s/dvisamplerX/dvisampler0/g;s/DVISAMPLERX/DVISAMPLER0/g" $< > $@
|
||||
endef
|
||||
|
||||
define gen1
|
||||
@echo " GEN " $@
|
||||
@sed -e "s/dvisamplerX/dvisampler1/g;s/DVISAMPLERX/DVISAMPLER1/g" $< > $@
|
||||
endef
|
||||
|
||||
dvisampler0.c: dvisamplerX.c
|
||||
$(gen0)
|
||||
dvisampler0.h: dvisamplerX.h
|
||||
$(gen0)
|
||||
dvisampler1.c: dvisamplerX.c
|
||||
$(gen1)
|
||||
dvisampler1.h: dvisamplerX.h
|
||||
$(gen1)
|
||||
|
||||
isr.o: dvisampler0.h dvisampler1.h
|
||||
main.o: dvisampler0.h dvisampler1.h
|
||||
dvisampler0.o: dvisampler0.h
|
||||
dvisampler1.o: dvisampler1.h
|
||||
|
||||
libs:
|
||||
make -C $(M2DIR)/software/libcompiler-rt
|
||||
make -C $(M2DIR)/software/libbase
|
||||
|
@ -40,5 +64,6 @@ load: videomixer.bin
|
|||
|
||||
clean:
|
||||
rm -f $(OBJECTS) $(OBJECTS:.o=.d) videomixer.elf videomixer.bin .*~ *~
|
||||
rm -f dvisampler0.h dvisampler0.c dvisampler1.h dvisampler1.c
|
||||
|
||||
.PHONY: main.o clean libs load
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <irq.h>
|
||||
#include <uart.h>
|
||||
#include <hw/csr.h>
|
||||
#include <hw/flags.h>
|
||||
|
||||
#include "dvisamplerX.h"
|
||||
|
||||
#define FRAMEBUFFER_COUNT 4
|
||||
#define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1)
|
||||
|
||||
static unsigned int dvisamplerX_framebuffers[FRAMEBUFFER_COUNT][640*480] __attribute__((aligned(16)));
|
||||
static int dvisamplerX_fb_slot_indexes[2];
|
||||
static int dvisamplerX_next_fb_index;
|
||||
|
||||
void dvisamplerX_isr(void)
|
||||
{
|
||||
int fb_index = -1;
|
||||
|
||||
if(dvisamplerX_dma_slot0_status_read() == DVISAMPLER_SLOT_PENDING) {
|
||||
fb_index = dvisamplerX_fb_slot_indexes[0];
|
||||
dvisamplerX_fb_slot_indexes[0] = dvisamplerX_next_fb_index;
|
||||
dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_next_fb_index]);
|
||||
dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisamplerX_next_fb_index = (dvisamplerX_next_fb_index + 1) & FRAMEBUFFER_MASK;
|
||||
}
|
||||
if(dvisamplerX_dma_slot1_status_read() == DVISAMPLER_SLOT_PENDING) {
|
||||
fb_index = dvisamplerX_fb_slot_indexes[1];
|
||||
dvisamplerX_fb_slot_indexes[1] = dvisamplerX_next_fb_index;
|
||||
dvisamplerX_dma_slot1_address_write((unsigned int)dvisamplerX_framebuffers[dvisamplerX_next_fb_index]);
|
||||
dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisamplerX_next_fb_index = (dvisamplerX_next_fb_index + 1) & FRAMEBUFFER_MASK;
|
||||
}
|
||||
|
||||
if(fb_index != -1)
|
||||
fb_base_write((unsigned int)dvisamplerX_framebuffers[fb_index]);
|
||||
}
|
||||
|
||||
void dvisamplerX_init_video(void)
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
dvisamplerX_dma_ev_pending_write(dvisamplerX_dma_ev_pending_read());
|
||||
dvisamplerX_dma_ev_enable_write(0x3);
|
||||
mask = irq_getmask();
|
||||
mask |= 1 << DVISAMPLERX_INTERRUPT;
|
||||
irq_setmask(mask);
|
||||
|
||||
dvisamplerX_dma_frame_size_write(sizeof(dvisamplerX_framebuffers[0]));
|
||||
dvisamplerX_fb_slot_indexes[0] = 0;
|
||||
dvisamplerX_dma_slot0_address_write((unsigned int)dvisamplerX_framebuffers[0]);
|
||||
dvisamplerX_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisamplerX_fb_slot_indexes[1] = 1;
|
||||
dvisamplerX_dma_slot1_address_write((unsigned int)dvisamplerX_framebuffers[1]);
|
||||
dvisamplerX_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisamplerX_next_fb_index = 2;
|
||||
|
||||
fb_base_write((unsigned int)dvisamplerX_framebuffers[3]);
|
||||
}
|
||||
|
||||
static int dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2;
|
||||
|
||||
void dvisamplerX_print_status(void)
|
||||
{
|
||||
printf("dvisamplerX ph:%4d %4d %4d // charsync:%d%d%d [%d %d %d] // chansync:%d // res:%dx%d\n",
|
||||
dvisamplerX_d0, dvisamplerX_d1, dvisamplerX_d2,
|
||||
dvisamplerX_data0_charsync_char_synced_read(),
|
||||
dvisamplerX_data1_charsync_char_synced_read(),
|
||||
dvisamplerX_data2_charsync_char_synced_read(),
|
||||
dvisamplerX_data0_charsync_ctl_pos_read(),
|
||||
dvisamplerX_data1_charsync_ctl_pos_read(),
|
||||
dvisamplerX_data2_charsync_ctl_pos_read(),
|
||||
dvisamplerX_chansync_channels_synced_read(),
|
||||
dvisamplerX_resdetection_hres_read(),
|
||||
dvisamplerX_resdetection_vres_read());
|
||||
}
|
||||
|
||||
void dvisamplerX_calibrate_delays(void)
|
||||
{
|
||||
dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
|
||||
dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
|
||||
dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
|
||||
while(dvisamplerX_data0_cap_dly_busy_read()
|
||||
|| dvisamplerX_data1_cap_dly_busy_read()
|
||||
|| dvisamplerX_data2_cap_dly_busy_read());
|
||||
dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
|
||||
dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
|
||||
dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
|
||||
dvisamplerX_data0_cap_phase_reset_write(1);
|
||||
dvisamplerX_data1_cap_phase_reset_write(1);
|
||||
dvisamplerX_data2_cap_phase_reset_write(1);
|
||||
dvisamplerX_d0 = dvisamplerX_d1 = dvisamplerX_d2 = 0;
|
||||
}
|
||||
|
||||
void dvisamplerX_adjust_phase(void)
|
||||
{
|
||||
switch(dvisamplerX_data0_cap_phase_read()) {
|
||||
case DVISAMPLER_TOO_LATE:
|
||||
dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||
dvisamplerX_d0--;
|
||||
dvisamplerX_data0_cap_phase_reset_write(1);
|
||||
break;
|
||||
case DVISAMPLER_TOO_EARLY:
|
||||
dvisamplerX_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||
dvisamplerX_d0++;
|
||||
dvisamplerX_data0_cap_phase_reset_write(1);
|
||||
break;
|
||||
}
|
||||
switch(dvisamplerX_data1_cap_phase_read()) {
|
||||
case DVISAMPLER_TOO_LATE:
|
||||
dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||
dvisamplerX_d1--;
|
||||
dvisamplerX_data1_cap_phase_reset_write(1);
|
||||
break;
|
||||
case DVISAMPLER_TOO_EARLY:
|
||||
dvisamplerX_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||
dvisamplerX_d1++;
|
||||
dvisamplerX_data1_cap_phase_reset_write(1);
|
||||
break;
|
||||
}
|
||||
switch(dvisamplerX_data2_cap_phase_read()) {
|
||||
case DVISAMPLER_TOO_LATE:
|
||||
dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||
dvisamplerX_d2--;
|
||||
dvisamplerX_data2_cap_phase_reset_write(1);
|
||||
break;
|
||||
case DVISAMPLER_TOO_EARLY:
|
||||
dvisamplerX_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||
dvisamplerX_d2++;
|
||||
dvisamplerX_data2_cap_phase_reset_write(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int dvisamplerX_init_phase(void)
|
||||
{
|
||||
int o_d0, o_d1, o_d2;
|
||||
int i, j;
|
||||
|
||||
for(i=0;i<100;i++) {
|
||||
o_d0 = dvisamplerX_d0;
|
||||
o_d1 = dvisamplerX_d1;
|
||||
o_d2 = dvisamplerX_d2;
|
||||
for(j=0;j<1000;j++)
|
||||
dvisamplerX_adjust_phase();
|
||||
if((abs(dvisamplerX_d0 - o_d0) < 4) && (abs(dvisamplerX_d1 - o_d1) < 4) && (abs(dvisamplerX_d2 - o_d2) < 4))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dvisamplerX_locked;
|
||||
|
||||
void dvisamplerX_service(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(dvisamplerX_locked) {
|
||||
if(dvisamplerX_clocking_locked_read()) {
|
||||
dvisamplerX_adjust_phase();
|
||||
dvisamplerX_print_status();
|
||||
} else {
|
||||
printf("dvisamplerX: lost PLL lock\n");
|
||||
dvisamplerX_locked = 0;
|
||||
}
|
||||
} else {
|
||||
if(dvisamplerX_clocking_locked_read()) {
|
||||
printf("dvisamplerX: PLL locked\n");
|
||||
dvisamplerX_calibrate_delays();
|
||||
printf("dvisamplerX: delays calibrated\n");
|
||||
ret = dvisamplerX_init_phase();
|
||||
if(ret)
|
||||
printf("dvisamplerX: phase init OK\n");
|
||||
else
|
||||
printf("dvisamplerX: phase did not settle\n");
|
||||
dvisamplerX_print_status();
|
||||
dvisamplerX_locked = 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef __DVISAMPLERX_H
|
||||
#define __DVISAMPLERX_H
|
||||
|
||||
void dvisamplerX_isr(void);
|
||||
void dvisamplerX_init_video(void);
|
||||
void dvisamplerX_print_status(void);
|
||||
void dvisamplerX_calibrate_delays(void);
|
||||
void dvisamplerX_adjust_phase(void);
|
||||
int dvisamplerX_init_phase(void);
|
||||
void dvisamplerX_service(void);
|
||||
|
||||
#endif
|
|
@ -2,7 +2,8 @@
|
|||
#include <irq.h>
|
||||
#include <uart.h>
|
||||
|
||||
void dvisampler0_isr(void); // FIXME
|
||||
#include "dvisampler0.h"
|
||||
#include "dvisampler1.h"
|
||||
|
||||
void isr(void);
|
||||
void isr(void)
|
||||
|
@ -15,4 +16,6 @@ void isr(void)
|
|||
uart_isr();
|
||||
if(irqs & (1 << DVISAMPLER0_INTERRUPT))
|
||||
dvisampler0_isr();
|
||||
if(irqs & (1 << DVISAMPLER1_INTERRUPT))
|
||||
dvisampler1_isr();
|
||||
}
|
||||
|
|
|
@ -3,179 +3,11 @@
|
|||
|
||||
#include <irq.h>
|
||||
#include <uart.h>
|
||||
#include <console.h>
|
||||
#include <hw/csr.h>
|
||||
#include <hw/flags.h>
|
||||
|
||||
static int dvisampler0_d0, dvisampler0_d1, dvisampler0_d2;
|
||||
|
||||
static void print_status(void)
|
||||
{
|
||||
printf("dvisampler0 ph: %4d %4d %4d // %d%d%d [%d %d %d] // %d // %dx%d\n", dvisampler0_d0, dvisampler0_d1, dvisampler0_d2,
|
||||
dvisampler0_data0_charsync_char_synced_read(),
|
||||
dvisampler0_data1_charsync_char_synced_read(),
|
||||
dvisampler0_data2_charsync_char_synced_read(),
|
||||
dvisampler0_data0_charsync_ctl_pos_read(),
|
||||
dvisampler0_data1_charsync_ctl_pos_read(),
|
||||
dvisampler0_data2_charsync_ctl_pos_read(),
|
||||
dvisampler0_chansync_channels_synced_read(),
|
||||
dvisampler0_resdetection_hres_read(),
|
||||
dvisampler0_resdetection_vres_read());
|
||||
}
|
||||
|
||||
static void calibrate_delays(void)
|
||||
{
|
||||
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
|
||||
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
|
||||
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_CAL);
|
||||
while(dvisampler0_data0_cap_dly_busy_read()
|
||||
|| dvisampler0_data1_cap_dly_busy_read()
|
||||
|| dvisampler0_data2_cap_dly_busy_read());
|
||||
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
|
||||
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
|
||||
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_RST);
|
||||
dvisampler0_data0_cap_phase_reset_write(1);
|
||||
dvisampler0_data1_cap_phase_reset_write(1);
|
||||
dvisampler0_data2_cap_phase_reset_write(1);
|
||||
dvisampler0_d0 = dvisampler0_d1 = dvisampler0_d2 = 0;
|
||||
printf("Delays calibrated\n");
|
||||
}
|
||||
|
||||
static void adjust_phase(void)
|
||||
{
|
||||
switch(dvisampler0_data0_cap_phase_read()) {
|
||||
case DVISAMPLER_TOO_LATE:
|
||||
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||
dvisampler0_d0--;
|
||||
dvisampler0_data0_cap_phase_reset_write(1);
|
||||
break;
|
||||
case DVISAMPLER_TOO_EARLY:
|
||||
dvisampler0_data0_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||
dvisampler0_d0++;
|
||||
dvisampler0_data0_cap_phase_reset_write(1);
|
||||
break;
|
||||
}
|
||||
switch(dvisampler0_data1_cap_phase_read()) {
|
||||
case DVISAMPLER_TOO_LATE:
|
||||
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||
dvisampler0_d1--;
|
||||
dvisampler0_data1_cap_phase_reset_write(1);
|
||||
break;
|
||||
case DVISAMPLER_TOO_EARLY:
|
||||
dvisampler0_data1_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||
dvisampler0_d1++;
|
||||
dvisampler0_data1_cap_phase_reset_write(1);
|
||||
break;
|
||||
}
|
||||
switch(dvisampler0_data2_cap_phase_read()) {
|
||||
case DVISAMPLER_TOO_LATE:
|
||||
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_DEC);
|
||||
dvisampler0_d2--;
|
||||
dvisampler0_data2_cap_phase_reset_write(1);
|
||||
break;
|
||||
case DVISAMPLER_TOO_EARLY:
|
||||
dvisampler0_data2_cap_dly_ctl_write(DVISAMPLER_DELAY_INC);
|
||||
dvisampler0_d2++;
|
||||
dvisampler0_data2_cap_phase_reset_write(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int init_phase(void)
|
||||
{
|
||||
int o_d0, o_d1, o_d2;
|
||||
int i, j;
|
||||
|
||||
for(i=0;i<100;i++) {
|
||||
o_d0 = dvisampler0_d0;
|
||||
o_d1 = dvisampler0_d1;
|
||||
o_d2 = dvisampler0_d2;
|
||||
for(j=0;j<1000;j++)
|
||||
adjust_phase();
|
||||
if((abs(dvisampler0_d0 - o_d0) < 4) && (abs(dvisampler0_d1 - o_d1) < 4) && (abs(dvisampler0_d2 - o_d2) < 4))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define FRAMEBUFFER_COUNT 4
|
||||
#define FRAMEBUFFER_MASK (FRAMEBUFFER_COUNT - 1)
|
||||
|
||||
static unsigned int dvisampler0_framebuffers[FRAMEBUFFER_COUNT][640*480] __attribute__((aligned(16)));
|
||||
static int dvisampler0_fb_slot_indexes[2];
|
||||
static int dvisampler0_next_fb_index;
|
||||
|
||||
static void dvisampler0_init_video(void)
|
||||
{
|
||||
unsigned int mask;
|
||||
|
||||
dvisampler0_dma_ev_pending_write(dvisampler0_dma_ev_pending_read());
|
||||
dvisampler0_dma_ev_enable_write(0x3);
|
||||
mask = irq_getmask();
|
||||
mask |= 1 << DVISAMPLER0_INTERRUPT;
|
||||
irq_setmask(mask);
|
||||
|
||||
dvisampler0_dma_frame_size_write(sizeof(dvisampler0_framebuffers[0]));
|
||||
dvisampler0_fb_slot_indexes[0] = 0;
|
||||
dvisampler0_dma_slot0_address_write((unsigned int)dvisampler0_framebuffers[0]);
|
||||
dvisampler0_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisampler0_fb_slot_indexes[1] = 1;
|
||||
dvisampler0_dma_slot1_address_write((unsigned int)dvisampler0_framebuffers[1]);
|
||||
dvisampler0_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisampler0_next_fb_index = 2;
|
||||
|
||||
fb_base_write((unsigned int)dvisampler0_framebuffers[0]);
|
||||
}
|
||||
|
||||
void dvisampler0_isr(void)
|
||||
{
|
||||
int fb_index = -1;
|
||||
|
||||
if(dvisampler0_dma_slot0_status_read() == DVISAMPLER_SLOT_PENDING) {
|
||||
fb_index = dvisampler0_fb_slot_indexes[0];
|
||||
dvisampler0_fb_slot_indexes[0] = dvisampler0_next_fb_index;
|
||||
dvisampler0_dma_slot0_address_write((unsigned int)dvisampler0_framebuffers[dvisampler0_next_fb_index]);
|
||||
dvisampler0_dma_slot0_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisampler0_next_fb_index = (dvisampler0_next_fb_index + 1) & FRAMEBUFFER_MASK;
|
||||
}
|
||||
if(dvisampler0_dma_slot1_status_read() == DVISAMPLER_SLOT_PENDING) {
|
||||
fb_index = dvisampler0_fb_slot_indexes[1];
|
||||
dvisampler0_fb_slot_indexes[1] = dvisampler0_next_fb_index;
|
||||
dvisampler0_dma_slot1_address_write((unsigned int)dvisampler0_framebuffers[dvisampler0_next_fb_index]);
|
||||
dvisampler0_dma_slot1_status_write(DVISAMPLER_SLOT_LOADED);
|
||||
dvisampler0_next_fb_index = (dvisampler0_next_fb_index + 1) & FRAMEBUFFER_MASK;
|
||||
}
|
||||
|
||||
if(fb_index != -1)
|
||||
fb_base_write((unsigned int)dvisampler0_framebuffers[fb_index]);
|
||||
}
|
||||
|
||||
static void vmix(void)
|
||||
{
|
||||
unsigned int counter;
|
||||
|
||||
while(1) {
|
||||
while(!dvisampler0_clocking_locked_read());
|
||||
printf("PLL locked\n");
|
||||
calibrate_delays();
|
||||
if(init_phase())
|
||||
printf("Phase init OK\n");
|
||||
else
|
||||
printf("Phase did not settle\n");
|
||||
print_status();
|
||||
|
||||
counter = 0;
|
||||
while(dvisampler0_clocking_locked_read()) {
|
||||
counter++;
|
||||
if(counter == 2000000) {
|
||||
print_status();
|
||||
adjust_phase();
|
||||
counter = 0;
|
||||
}
|
||||
}
|
||||
printf("PLL unlocked\n");
|
||||
}
|
||||
}
|
||||
#include "dvisampler0.h"
|
||||
#include "dvisampler1.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
@ -187,7 +19,7 @@ int main(void)
|
|||
|
||||
dvisampler0_init_video();
|
||||
fb_enable_write(1);
|
||||
vmix();
|
||||
while(1) dvisampler0_service();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue