2016-02-22 23:03:50 +00:00
|
|
|
//
|
2017-05-29 17:43:24 +00:00
|
|
|
// Copyright (C) 2015-2017 Markus Hiienkari <mhiienka@niksula.hut.fi>
|
2016-02-22 23:03:50 +00:00
|
|
|
//
|
|
|
|
// This file is part of Open Source Scan Converter project.
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
//
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "system.h"
|
|
|
|
#include "string.h"
|
|
|
|
#include "altera_avalon_pio_regs.h"
|
|
|
|
#include "i2c_opencores.h"
|
2016-06-12 20:43:24 +00:00
|
|
|
#include "av_controller.h"
|
2016-02-22 23:03:50 +00:00
|
|
|
#include "tvp7002.h"
|
|
|
|
#include "ths7353.h"
|
2017-06-04 21:02:01 +00:00
|
|
|
#include "pcm1862.h"
|
2016-02-22 23:03:50 +00:00
|
|
|
#include "video_modes.h"
|
|
|
|
#include "lcd.h"
|
2016-05-24 21:04:46 +00:00
|
|
|
#include "flash.h"
|
|
|
|
#include "sdcard.h"
|
2016-05-30 10:02:15 +00:00
|
|
|
#include "menu.h"
|
2016-06-12 20:43:24 +00:00
|
|
|
#include "avconfig.h"
|
2016-11-06 13:24:26 +00:00
|
|
|
#include "sysconfig.h"
|
2016-06-12 20:43:24 +00:00
|
|
|
#include "firmware.h"
|
|
|
|
#include "userdata.h"
|
2016-02-22 23:03:50 +00:00
|
|
|
#include "it6613.h"
|
2016-04-15 19:05:53 +00:00
|
|
|
#include "it6613_sys.h"
|
2016-02-22 23:03:50 +00:00
|
|
|
#include "HDMI_TX.h"
|
|
|
|
#include "hdmitx.h"
|
2016-10-20 22:19:53 +00:00
|
|
|
#include "sd_io.h"
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-04-15 19:05:53 +00:00
|
|
|
#define STABLE_THOLD 1
|
|
|
|
#define MIN_LINES_PROGRESSIVE 200
|
|
|
|
#define MIN_LINES_INTERLACED 400
|
2016-08-14 15:57:50 +00:00
|
|
|
#define SYNC_LOCK_THOLD 3
|
|
|
|
#define SYNC_LOSS_THOLD -5
|
2016-04-15 19:05:53 +00:00
|
|
|
#define STATUS_TIMEOUT 10000
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-10-20 22:19:53 +00:00
|
|
|
alt_u8 sys_ctrl;
|
|
|
|
|
2016-02-22 23:03:50 +00:00
|
|
|
// Current mode
|
|
|
|
avmode_t cm;
|
|
|
|
|
|
|
|
extern mode_data_t video_modes[];
|
|
|
|
extern ypbpr_to_rgb_csc_t csc_coeffs[];
|
2016-06-12 20:43:24 +00:00
|
|
|
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
|
2016-12-29 22:14:12 +00:00
|
|
|
extern alt_u16 rc_keymap_default[REMOTE_MAX_KEYS];
|
2016-06-12 20:43:24 +00:00
|
|
|
extern alt_u32 remote_code;
|
|
|
|
extern alt_u32 btn_code, btn_code_prev;
|
|
|
|
extern alt_u8 remote_rpt, remote_rpt_prev;
|
|
|
|
extern avconfig_t tc;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
|
|
|
alt_u8 target_typemask;
|
|
|
|
alt_u8 target_type;
|
|
|
|
alt_u8 stable_frames;
|
2016-09-05 17:49:41 +00:00
|
|
|
alt_u8 update_cur_vm;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-12-29 22:14:12 +00:00
|
|
|
alt_u8 vm_sel, vm_edit, profile_sel;
|
2017-05-18 20:35:43 +00:00
|
|
|
alt_u16 tc_h_samplerate, tc_h_synclen, tc_h_bporch, tc_h_active, tc_v_synclen, tc_v_bporch, tc_v_active;
|
2016-08-16 19:45:23 +00:00
|
|
|
|
2016-02-22 23:03:50 +00:00
|
|
|
char row1[LCD_ROW_LEN+1], row2[LCD_ROW_LEN+1], menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
|
|
|
|
|
2016-06-12 20:43:24 +00:00
|
|
|
extern alt_u8 menu_active;
|
2016-05-23 21:27:50 +00:00
|
|
|
avinput_t target_mode;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-06-04 21:02:01 +00:00
|
|
|
alt_u8 pcm1862_active;
|
|
|
|
|
|
|
|
|
2016-06-12 20:43:24 +00:00
|
|
|
inline void lcd_write_menu()
|
2016-05-30 10:02:15 +00:00
|
|
|
{
|
2016-06-12 20:43:24 +00:00
|
|
|
lcd_write((char*)&menu_row1, (char*)&menu_row2);
|
2016-05-30 10:02:15 +00:00
|
|
|
}
|
2016-03-27 19:40:44 +00:00
|
|
|
|
2016-06-12 20:43:24 +00:00
|
|
|
inline void lcd_write_status() {
|
|
|
|
lcd_write((char*)&row1, (char*)&row2);
|
2016-03-27 19:40:44 +00:00
|
|
|
}
|
|
|
|
|
2017-06-04 21:02:01 +00:00
|
|
|
#ifdef ENABLE_AUDIO
|
2016-11-06 13:24:26 +00:00
|
|
|
inline void SetupAudio(tx_mode_t mode)
|
|
|
|
{
|
|
|
|
// shut down audio-tx before setting new config (recommended for changing audio-tx config)
|
|
|
|
DisableAudioOutput();
|
|
|
|
EnableAudioInfoFrame(FALSE, NULL);
|
|
|
|
|
2017-05-29 17:43:24 +00:00
|
|
|
if (mode == TX_HDMI) {
|
2017-02-07 21:04:30 +00:00
|
|
|
alt_u32 pclk_out = (TVP_EXTCLK_HZ/cm.clkcnt)*video_modes[cm.id].h_total*cm.sample_mult*(cm.fpga_vmultmode+1);
|
|
|
|
|
2017-05-29 17:43:24 +00:00
|
|
|
pclk_out *= 1+cm.tx_pixelrep;
|
2016-11-06 13:24:26 +00:00
|
|
|
|
|
|
|
printf("PCLK_out: %luHz\n", pclk_out);
|
2016-12-29 22:14:12 +00:00
|
|
|
EnableAudioOutput4OSSC(pclk_out, tc.audio_dw_sampl, tc.audio_swap_lr);
|
2016-11-06 13:24:26 +00:00
|
|
|
HDMITX_SetAudioInfoFrame((BYTE)tc.audio_dw_sampl);
|
|
|
|
#ifdef DEBUG
|
|
|
|
Switch_HDMITX_Bank(1);
|
|
|
|
usleep(1000);
|
|
|
|
alt_u32 cts = 0;
|
|
|
|
cts |= read_it2(0x35) >> 4;
|
|
|
|
cts |= read_it2(0x36) << 4;
|
|
|
|
cts |= read_it2(0x37) << 12;
|
|
|
|
printf("CTS: %lu\n", cts);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
inline void TX_enable(tx_mode_t mode)
|
|
|
|
{
|
2016-04-14 10:42:40 +00:00
|
|
|
// shut down TX before setting new config
|
|
|
|
SetAVMute(TRUE);
|
|
|
|
DisableVideoOutput();
|
|
|
|
EnableAVIInfoFrame(FALSE, NULL);
|
|
|
|
|
2017-05-29 17:43:24 +00:00
|
|
|
//Setup TX configuration
|
|
|
|
//TODO: set pclk target and VIC dynamically
|
2016-04-14 10:42:40 +00:00
|
|
|
EnableVideoOutput(PCLK_MEDIUM, COLOR_RGB444, COLOR_RGB444, !mode);
|
2017-05-29 17:43:24 +00:00
|
|
|
|
2016-11-06 13:24:26 +00:00
|
|
|
if (mode == TX_HDMI) {
|
2017-08-09 21:06:35 +00:00
|
|
|
HDMITX_SetAVIInfoFrame(HDMI_Unkown, 0, 0, tc.hdmi_itc, cm.hdmitx_pixr_ifr);
|
2017-05-18 20:35:43 +00:00
|
|
|
cm.cc.hdmi_itc = tc.hdmi_itc;
|
2017-05-29 17:43:24 +00:00
|
|
|
}
|
|
|
|
|
2017-06-04 21:02:01 +00:00
|
|
|
#ifdef ENABLE_AUDIO
|
2017-05-29 17:43:24 +00:00
|
|
|
SetupAudio(mode);
|
2016-11-06 13:24:26 +00:00
|
|
|
#endif
|
2016-04-14 10:42:40 +00:00
|
|
|
|
|
|
|
// start TX
|
2016-03-27 19:40:44 +00:00
|
|
|
SetAVMute(FALSE);
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
void set_lpf(alt_u8 lpf)
|
|
|
|
{
|
2016-02-22 23:03:50 +00:00
|
|
|
alt_u32 pclk;
|
2016-10-20 22:19:53 +00:00
|
|
|
pclk = (TVP_EXTCLK_HZ/cm.clkcnt)*video_modes[cm.id].h_total;
|
2016-08-22 21:52:46 +00:00
|
|
|
printf("PCLK_in: %luHz\n", pclk);
|
2016-03-27 19:40:44 +00:00
|
|
|
|
2016-02-22 23:03:50 +00:00
|
|
|
//Auto
|
|
|
|
if (lpf == 0) {
|
|
|
|
switch (target_type) {
|
|
|
|
case VIDEO_PC:
|
|
|
|
tvp_set_lpf((pclk < 30000000) ? 0x0F : 0);
|
|
|
|
ths_set_lpf(THS_LPF_BYPASS);
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
2016-02-22 23:03:50 +00:00
|
|
|
case VIDEO_HDTV:
|
|
|
|
tvp_set_lpf(0);
|
|
|
|
ths_set_lpf(THS_LPF_BYPASS);
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
2016-02-22 23:03:50 +00:00
|
|
|
case VIDEO_EDTV:
|
|
|
|
tvp_set_lpf(0);
|
|
|
|
ths_set_lpf(1);
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
2016-02-22 23:03:50 +00:00
|
|
|
case VIDEO_SDTV:
|
|
|
|
case VIDEO_LDTV:
|
2016-08-20 12:54:28 +00:00
|
|
|
default:
|
2016-02-22 23:03:50 +00:00
|
|
|
tvp_set_lpf(0);
|
|
|
|
ths_set_lpf(0);
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tvp_set_lpf((tc.video_lpf == 2) ? 0x0F : 0);
|
2016-03-27 19:40:44 +00:00
|
|
|
ths_set_lpf((tc.video_lpf > 2) ? (VIDEO_LPF_MAX-tc.video_lpf) : THS_LPF_BYPASS);
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
inline int check_linecnt(alt_u8 progressive, alt_u32 totlines) {
|
|
|
|
if (progressive)
|
2016-06-22 20:22:59 +00:00
|
|
|
return (totlines >= MIN_LINES_PROGRESSIVE);
|
2016-05-23 21:27:50 +00:00
|
|
|
else
|
2016-06-22 20:22:59 +00:00
|
|
|
return (totlines >= MIN_LINES_INTERLACED);
|
2016-05-23 21:27:50 +00:00
|
|
|
}
|
|
|
|
|
2016-02-22 23:03:50 +00:00
|
|
|
// Check if input video status / target configuration has changed
|
2016-05-23 21:27:50 +00:00
|
|
|
status_t get_status(tvp_input_t input, video_format format)
|
2016-03-27 19:40:44 +00:00
|
|
|
{
|
|
|
|
alt_u32 data1, data2;
|
|
|
|
alt_u32 totlines, clkcnt;
|
|
|
|
alt_u8 progressive;
|
|
|
|
//alt_u8 refclk;
|
|
|
|
alt_u8 sync_active;
|
2016-02-22 23:03:50 +00:00
|
|
|
alt_u8 vsyncmode;
|
2017-05-18 20:35:43 +00:00
|
|
|
alt_u16 totlines_tvp;
|
2016-09-05 17:49:41 +00:00
|
|
|
alt_u16 h_samplerate;
|
2016-03-27 19:40:44 +00:00
|
|
|
status_t status;
|
2016-08-14 15:57:50 +00:00
|
|
|
static alt_8 act_ctr;
|
2016-03-27 19:40:44 +00:00
|
|
|
alt_u32 ctr;
|
2016-05-23 21:27:50 +00:00
|
|
|
int valid_linecnt;
|
2017-01-22 22:56:17 +00:00
|
|
|
alt_u8 h_mult;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
status = NO_CHANGE;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
// Wait until vsync active (avoid noise coupled to I2C bus on earlier prototypes)
|
2016-04-15 19:05:53 +00:00
|
|
|
for (ctr=0; ctr<STATUS_TIMEOUT; ctr++) {
|
2017-05-18 20:35:43 +00:00
|
|
|
if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_2_BASE) & (1<<31))) {
|
2016-03-27 19:40:44 +00:00
|
|
|
//printf("ctrval %u\n", ctr);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
sync_active = tvp_check_sync(input, format);
|
2017-05-18 20:35:43 +00:00
|
|
|
vsyncmode = cm.sync_active ? ((IORD_ALTERA_AVALON_PIO_DATA(PIO_2_BASE) >> 16) & 0x3) : 0;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-05-09 15:55:24 +00:00
|
|
|
// Read sync information from TVP7002 status registers
|
2016-05-23 21:27:50 +00:00
|
|
|
data1 = tvp_readreg(TVP_LINECNT1);
|
|
|
|
data2 = tvp_readreg(TVP_LINECNT2);
|
|
|
|
totlines = ((data2 & 0x0f) << 8) | data1;
|
|
|
|
progressive = !!(data2 & (1<<5));
|
|
|
|
cm.macrovis = !!(data2 & (1<<6));
|
2017-05-09 15:55:24 +00:00
|
|
|
data1 = tvp_readreg(TVP_CLKCNT1);
|
|
|
|
data2 = tvp_readreg(TVP_CLKCNT2);
|
|
|
|
clkcnt = ((data2 & 0x0f) << 8) | data1;
|
2016-05-23 21:27:50 +00:00
|
|
|
|
2017-05-29 17:43:24 +00:00
|
|
|
// Read how many lines TVP7002 outputs in reality (valid only if output enabled)
|
2017-05-18 20:35:43 +00:00
|
|
|
totlines_tvp = ((IORD_ALTERA_AVALON_PIO_DATA(PIO_2_BASE) >> 18) & 0x7ff)+1;
|
2016-05-23 21:27:50 +00:00
|
|
|
|
2016-06-22 20:22:59 +00:00
|
|
|
// NOTE: "progressive" may not have correct value if H-PLL is not locked (!cm.sync_active)
|
|
|
|
if ((vsyncmode == 0x2) || (!cm.sync_active && (totlines < MIN_LINES_INTERLACED))) {
|
2016-05-23 21:27:50 +00:00
|
|
|
progressive = 1;
|
2017-05-09 15:55:24 +00:00
|
|
|
} else if (vsyncmode == 0x1) {
|
2016-05-23 21:27:50 +00:00
|
|
|
progressive = 0;
|
2017-05-18 20:35:43 +00:00
|
|
|
totlines = totlines_tvp; //compensate skipped vsync
|
2016-05-23 21:27:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
valid_linecnt = check_linecnt(progressive, totlines);
|
|
|
|
|
2016-02-22 23:03:50 +00:00
|
|
|
// TVP7002 may randomly report "no sync" (especially with arcade boards),
|
|
|
|
// thus disable output only after N consecutive "no sync"-events
|
2016-05-23 21:27:50 +00:00
|
|
|
if (!cm.sync_active && sync_active && valid_linecnt) {
|
2016-08-14 15:57:50 +00:00
|
|
|
printf("Sync up in %d...\n", SYNC_LOCK_THOLD-act_ctr);
|
|
|
|
if (act_ctr >= SYNC_LOCK_THOLD) {
|
2016-02-22 23:03:50 +00:00
|
|
|
act_ctr = 0;
|
2016-08-14 15:57:50 +00:00
|
|
|
cm.sync_active = 1;
|
2016-03-27 19:40:44 +00:00
|
|
|
status = ACTIVITY_CHANGE;
|
2016-02-22 23:03:50 +00:00
|
|
|
} else {
|
|
|
|
act_ctr++;
|
|
|
|
}
|
2016-08-14 15:57:50 +00:00
|
|
|
} else if (cm.sync_active && (!sync_active || !valid_linecnt)) {
|
|
|
|
printf("Sync down in %d...\n", act_ctr-SYNC_LOSS_THOLD);
|
|
|
|
if (act_ctr <= SYNC_LOSS_THOLD) {
|
|
|
|
act_ctr = 0;
|
|
|
|
cm.sync_active = 0;
|
|
|
|
status = ACTIVITY_CHANGE;
|
|
|
|
} else {
|
|
|
|
act_ctr--;
|
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
} else {
|
|
|
|
act_ctr = 0;
|
|
|
|
}
|
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
if (valid_linecnt) {
|
2017-05-29 17:43:24 +00:00
|
|
|
// Line count reported in TVP7002 status registers is sometimes +-1 line off and may alternate with correct value. Ignore these events
|
|
|
|
if ((totlines > cm.totlines+1) || (totlines+1 < cm.totlines) || (clkcnt != cm.clkcnt) || (progressive != cm.progressive)) {
|
2017-05-18 20:35:43 +00:00
|
|
|
printf("totlines: %lu (cur) / %lu (prev), clkcnt: %lu (cur) / %lu (prev). totlines_tvp: %u, VSM: %u\n", totlines, cm.totlines, clkcnt, cm.clkcnt, totlines_tvp, vsyncmode);
|
2016-08-14 15:57:50 +00:00
|
|
|
/*if (!cm.sync_active)
|
|
|
|
act_ctr = 0;*/
|
2016-04-15 19:05:53 +00:00
|
|
|
stable_frames = 0;
|
|
|
|
} else if (stable_frames != STABLE_THOLD) {
|
|
|
|
stable_frames++;
|
|
|
|
if (stable_frames == STABLE_THOLD)
|
|
|
|
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
|
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-01-22 22:56:17 +00:00
|
|
|
if ((tc.pm_240p != cm.cc.pm_240p) ||
|
|
|
|
(tc.pm_384p != cm.cc.pm_384p) ||
|
|
|
|
(tc.pm_480i != cm.cc.pm_480i) ||
|
|
|
|
(tc.pm_480p != cm.cc.pm_480p) ||
|
2017-02-07 21:04:30 +00:00
|
|
|
(tc.pm_1080i != cm.cc.pm_1080i) ||
|
2017-05-09 15:55:24 +00:00
|
|
|
(tc.l2_mode != cm.cc.l2_mode) ||
|
2017-01-22 22:56:17 +00:00
|
|
|
(tc.l3_mode != cm.cc.l3_mode) ||
|
|
|
|
(tc.l4_mode != cm.cc.l4_mode) ||
|
2017-02-07 21:04:30 +00:00
|
|
|
(tc.l5_mode != cm.cc.l5_mode) ||
|
|
|
|
(tc.l5_fmt != cm.cc.l5_fmt) ||
|
2017-05-29 17:43:24 +00:00
|
|
|
(tc.tvp_hpll2x != cm.cc.tvp_hpll2x) ||
|
2017-08-09 21:06:35 +00:00
|
|
|
(tc.upsample2x != cm.cc.upsample2x) ||
|
2017-05-29 17:43:24 +00:00
|
|
|
(tc.vga_ilace_fix != cm.cc.vga_ilace_fix))
|
2016-03-27 19:40:44 +00:00
|
|
|
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
|
|
|
|
|
2017-08-09 21:06:35 +00:00
|
|
|
if ((tc.s480p_mode != cm.cc.s480p_mode) && (video_modes[cm.id].v_total == 525))
|
2016-04-15 19:05:53 +00:00
|
|
|
status = (status < MODE_CHANGE) ? MODE_CHANGE : status;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-09-05 17:49:41 +00:00
|
|
|
if (update_cur_vm) {
|
2017-02-07 21:04:30 +00:00
|
|
|
tvp_setup_hpll(cm.sample_mult*video_modes[cm.id].h_total, clkcnt, cm.cc.tvp_hpll2x && (video_modes[cm.id].flags & MODE_PLLDIVBY2));
|
2016-09-05 17:49:41 +00:00
|
|
|
status = (status < INFO_CHANGE) ? INFO_CHANGE : status;
|
|
|
|
}
|
|
|
|
|
2016-04-15 19:05:53 +00:00
|
|
|
cm.totlines = totlines;
|
|
|
|
cm.clkcnt = clkcnt;
|
|
|
|
cm.progressive = progressive;
|
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if ((tc.sl_mode != cm.cc.sl_mode) ||
|
2016-06-12 20:43:24 +00:00
|
|
|
(tc.sl_type != cm.cc.sl_type) ||
|
2016-03-27 19:40:44 +00:00
|
|
|
(tc.sl_str != cm.cc.sl_str) ||
|
|
|
|
(tc.sl_id != cm.cc.sl_id) ||
|
|
|
|
(tc.h_mask != cm.cc.h_mask) ||
|
2016-07-09 20:12:35 +00:00
|
|
|
(tc.v_mask != cm.cc.v_mask) ||
|
2017-01-23 22:18:15 +00:00
|
|
|
(tc.mask_br != cm.cc.mask_br) ||
|
2017-09-27 20:43:26 +00:00
|
|
|
(tc.ar_256col != cm.cc.ar_256col) ||
|
|
|
|
(tc.reverse_lpf != cm.cc.reverse_lpf))
|
2016-03-27 19:40:44 +00:00
|
|
|
status = (status < INFO_CHANGE) ? INFO_CHANGE : status;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-01-22 22:56:17 +00:00
|
|
|
if (tc.sampler_phase != cm.cc.sampler_phase) {
|
|
|
|
cm.sample_sel = tvp_set_hpll_phase(tc.sampler_phase, cm.sample_mult);
|
|
|
|
status = (status < INFO_CHANGE) ? INFO_CHANGE : status;
|
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
if (tc.sync_vth != cm.cc.sync_vth)
|
2016-05-30 10:02:15 +00:00
|
|
|
tvp_set_sog_thold(tc.sync_vth);
|
2016-05-23 21:27:50 +00:00
|
|
|
|
2016-09-05 17:49:41 +00:00
|
|
|
if (tc.linelen_tol != cm.cc.linelen_tol)
|
|
|
|
tvp_set_linelen_tol(tc.linelen_tol);
|
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
if (tc.vsync_thold != cm.cc.vsync_thold)
|
|
|
|
tvp_set_ssthold(tc.vsync_thold);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-04-15 19:05:53 +00:00
|
|
|
if ((tc.pre_coast != cm.cc.pre_coast) || (tc.post_coast != cm.cc.post_coast))
|
|
|
|
tvp_set_hpllcoast(tc.pre_coast, tc.post_coast);
|
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if (tc.ypbpr_cs != cm.cc.ypbpr_cs)
|
|
|
|
tvp_sel_csc(&csc_coeffs[tc.ypbpr_cs]);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if (tc.video_lpf != cm.cc.video_lpf)
|
|
|
|
set_lpf(tc.video_lpf);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if (tc.sync_lpf != cm.cc.sync_lpf)
|
|
|
|
tvp_set_sync_lpf(tc.sync_lpf);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-08-20 12:54:28 +00:00
|
|
|
if (!memcmp(&tc.col, &cm.cc.col, sizeof(color_setup_t)))
|
|
|
|
tvp_set_fine_gain_offset(&cm.cc.col);
|
2016-04-14 10:39:49 +00:00
|
|
|
|
2017-06-04 21:02:01 +00:00
|
|
|
#ifdef ENABLE_AUDIO
|
2016-11-06 13:24:26 +00:00
|
|
|
if ((tc.audio_dw_sampl != cm.cc.audio_dw_sampl) ||
|
|
|
|
#ifdef MANUAL_CTS
|
|
|
|
(tc.edtv_l2x != cm.cc.edtv_l2x) ||
|
|
|
|
(tc.interlace_pt != cm.cc.interlace_pt) ||
|
|
|
|
update_cur_vm ||
|
|
|
|
#endif
|
2016-12-29 22:14:12 +00:00
|
|
|
(tc.audio_swap_lr != cm.cc.audio_swap_lr))
|
2016-11-06 13:24:26 +00:00
|
|
|
SetupAudio(tc.tx_mode);
|
|
|
|
#endif
|
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
cm.cc = tc;
|
2016-09-05 17:49:41 +00:00
|
|
|
update_cur_vm = 0;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
return status;
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
|
2017-05-18 20:35:43 +00:00
|
|
|
// h_info: [31:30] [29] [28] [27:20] [19:11] [10:0]
|
|
|
|
// | H_MULTMODE[1:0] | H_L5FMT | | H_SYNCLEN[7:0] | H_BACKPORCH[8:0] | H_ACTIVE[10:0] |
|
|
|
|
//
|
|
|
|
// h_info2: [31:29] [28:19] [18:16] [15:13] [12:10] [9:0]
|
|
|
|
// | | H_MASK[9:0] | H_OPT_SCALE[2:0] | H_OPT_SAMPLE_SEL[2:0] | H_OPT_SAMPLE_MULT[2:0] | H_OPT_STARTOFF[9:0] |
|
2017-01-23 22:18:15 +00:00
|
|
|
//
|
2017-05-18 20:35:43 +00:00
|
|
|
// v_info: [31:29] [28:27] [26] [25:20] [19:17] [16:11] [10:0]
|
|
|
|
// | V_MULTMODE[2:0] | V_SCANLINEMODE[1:0] | V_SCANLINEID | V_MASK[5:0] | V_SYNCLEN[2:0] | V_BACKPORCH[5:0] | V_ACTIVE[10:0] |
|
2017-01-22 22:56:17 +00:00
|
|
|
//
|
2017-09-27 20:43:26 +00:00
|
|
|
// extra: [31:13] [12:8] [7:4] [3:0]
|
|
|
|
// | | X_REV_LPF_STR | H_MASK_BR[3:0] | H_SCANLINESTR[3:0] |
|
2017-01-22 22:56:17 +00:00
|
|
|
//
|
2016-03-27 19:40:44 +00:00
|
|
|
void set_videoinfo()
|
|
|
|
{
|
2016-07-09 20:12:35 +00:00
|
|
|
alt_u8 sl_mode_fpga;
|
2017-08-09 21:06:35 +00:00
|
|
|
alt_u8 h_opt_scale = cm.sample_mult;
|
2017-01-22 22:56:17 +00:00
|
|
|
alt_u16 h_opt_startoffs = 0;
|
2017-05-30 18:16:03 +00:00
|
|
|
alt_u16 h_synclen = video_modes[cm.id].h_synclen;
|
2017-01-23 22:18:15 +00:00
|
|
|
alt_u16 h_border, h_mask;
|
2017-02-07 21:04:30 +00:00
|
|
|
alt_u16 v_active = video_modes[cm.id].v_active;
|
|
|
|
alt_u16 v_backporch = video_modes[cm.id].v_backporch;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-07-09 20:12:35 +00:00
|
|
|
if (cm.cc.sl_mode == 2) { //manual
|
|
|
|
sl_mode_fpga = 1+cm.cc.sl_type;
|
|
|
|
} else if (cm.cc.sl_mode == 1) { //auto
|
|
|
|
if (video_modes[cm.id].flags & MODE_INTERLACED)
|
2017-01-22 22:56:17 +00:00
|
|
|
sl_mode_fpga = cm.fpga_vmultmode ? FPGA_SCANLINEMODE_ALT : FPGA_SCANLINEMODE_OFF;
|
2017-08-09 21:06:35 +00:00
|
|
|
else if ((cm.fpga_vmultmode) && (video_modes[cm.id].group != GROUP_480P))
|
2017-01-22 22:56:17 +00:00
|
|
|
sl_mode_fpga = FPGA_SCANLINEMODE_H;
|
2016-07-09 20:12:35 +00:00
|
|
|
else
|
2017-01-22 22:56:17 +00:00
|
|
|
sl_mode_fpga = FPGA_SCANLINEMODE_OFF;
|
2016-06-12 20:43:24 +00:00
|
|
|
} else {
|
2017-01-22 22:56:17 +00:00
|
|
|
sl_mode_fpga = FPGA_SCANLINEMODE_OFF;
|
2016-07-09 20:12:35 +00:00
|
|
|
}
|
|
|
|
|
2017-01-22 22:56:17 +00:00
|
|
|
switch (cm.target_lm) {
|
2017-05-09 15:55:24 +00:00
|
|
|
case MODE_L2_320_COL:
|
|
|
|
h_opt_scale = 4;
|
|
|
|
break;
|
|
|
|
case MODE_L2_256_COL:
|
|
|
|
h_opt_scale = 6-2*cm.cc.ar_256col;
|
|
|
|
break;
|
2017-01-22 22:56:17 +00:00
|
|
|
case MODE_L3_320_COL:
|
|
|
|
h_opt_scale = 3;
|
|
|
|
break;
|
|
|
|
case MODE_L3_256_COL:
|
2017-02-07 21:04:30 +00:00
|
|
|
h_opt_scale = 4-cm.cc.ar_256col;
|
2017-01-22 22:56:17 +00:00
|
|
|
break;
|
2017-01-23 22:18:15 +00:00
|
|
|
case MODE_L4_320_COL:
|
|
|
|
h_opt_scale = 4;
|
|
|
|
break;
|
|
|
|
case MODE_L4_256_COL:
|
2017-02-07 21:04:30 +00:00
|
|
|
h_opt_scale = 5-cm.cc.ar_256col;
|
|
|
|
break;
|
|
|
|
case MODE_L5_GEN_4_3:
|
|
|
|
if (cm.cc.l5_fmt == L5FMT_1920x1080) {
|
|
|
|
v_active -= 24;
|
|
|
|
v_backporch += 12;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_L5_320_COL:
|
2017-01-23 22:18:15 +00:00
|
|
|
h_opt_scale = 5;
|
2017-02-07 21:04:30 +00:00
|
|
|
if (cm.cc.l5_fmt == L5FMT_1920x1080) {
|
|
|
|
v_active -= 24;
|
|
|
|
v_backporch += 12;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_L5_256_COL:
|
|
|
|
h_opt_scale = 6-cm.cc.ar_256col;
|
|
|
|
if (cm.cc.l5_fmt == L5FMT_1920x1080) {
|
|
|
|
v_active -= 24;
|
|
|
|
v_backporch += 12;
|
|
|
|
}
|
2017-01-23 22:18:15 +00:00
|
|
|
break;
|
2017-01-22 22:56:17 +00:00
|
|
|
default:
|
|
|
|
break;
|
2016-06-12 20:43:24 +00:00
|
|
|
}
|
|
|
|
|
2017-05-30 18:16:03 +00:00
|
|
|
// CEA-770.3 HDTV modes use tri-level syncs which have twice the width of bi-level syncs of corresponding CEA-861 modes
|
|
|
|
if (target_type == VIDEO_HDTV)
|
|
|
|
h_synclen *= 2;
|
|
|
|
|
2017-01-23 22:18:15 +00:00
|
|
|
h_border = (((cm.sample_mult-h_opt_scale)*video_modes[cm.id].h_active)/2);
|
|
|
|
h_mask = h_border + h_opt_scale*cm.cc.h_mask;
|
2017-05-30 18:16:03 +00:00
|
|
|
h_opt_startoffs = h_border + (cm.sample_mult-h_opt_scale)*(h_synclen+(alt_u16)video_modes[cm.id].h_backporch);
|
2017-01-22 22:56:17 +00:00
|
|
|
h_opt_startoffs = (h_opt_startoffs/cm.sample_mult)*cm.sample_mult;
|
2017-05-18 20:35:43 +00:00
|
|
|
printf("h_border: %u, h_opt_startoffs: %u\n", h_border, h_opt_startoffs);
|
|
|
|
|
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, (cm.fpga_hmultmode<<30) |
|
|
|
|
((cm.cc.l5_fmt!=L5FMT_1600x1200)<<29) |
|
2017-05-30 18:16:03 +00:00
|
|
|
((((cm.sample_mult*h_synclen)-cm.hsync_cut)&0xff)<<20) |
|
2017-05-18 20:35:43 +00:00
|
|
|
(((cm.sample_mult*(alt_u16)video_modes[cm.id].h_backporch)&0x1ff)<<11) |
|
|
|
|
((cm.sample_mult*video_modes[cm.id].h_active)&0x7ff));
|
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_4_BASE, (h_mask<<19) |
|
|
|
|
(h_opt_scale<<16) |
|
|
|
|
(cm.sample_sel<<13) |
|
|
|
|
(cm.sample_mult<<10) |
|
|
|
|
h_opt_startoffs);
|
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, (cm.fpga_vmultmode<<29) |
|
|
|
|
(sl_mode_fpga<<27) |
|
|
|
|
(cm.cc.sl_id<<26) |
|
|
|
|
(cm.cc.v_mask<<20) |
|
|
|
|
(video_modes[cm.id].v_synclen<<17) |
|
|
|
|
(v_backporch<<11) |
|
|
|
|
v_active);
|
2017-09-27 20:43:26 +00:00
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_6_BASE, (cm.cc.reverse_lpf<<8) |
|
|
|
|
(cm.cc.mask_br<<4) |
|
2017-05-18 20:35:43 +00:00
|
|
|
cm.cc.sl_str);
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Configure TVP7002 and scan converter logic based on the video mode
|
2016-03-27 19:40:44 +00:00
|
|
|
void program_mode()
|
|
|
|
{
|
2016-08-22 21:52:46 +00:00
|
|
|
alt_u8 h_syncinlen, v_syncinlen;
|
|
|
|
alt_u32 h_hz, v_hz_x100, h_synclen_px;
|
2016-03-27 19:40:44 +00:00
|
|
|
|
|
|
|
// Mark as stable (needed after sync up to avoid unnecessary mode switch)
|
|
|
|
stable_frames = STABLE_THOLD;
|
|
|
|
|
|
|
|
if ((cm.clkcnt != 0) && (cm.totlines != 0)) { //prevent div by 0
|
2016-10-20 22:19:53 +00:00
|
|
|
h_hz = TVP_EXTCLK_HZ/cm.clkcnt;
|
|
|
|
v_hz_x100 = cm.progressive ? ((100*TVP_EXTCLK_HZ)/cm.totlines)/cm.clkcnt : (2*((100*TVP_EXTCLK_HZ)/cm.totlines))/cm.clkcnt;
|
2016-03-27 19:40:44 +00:00
|
|
|
} else {
|
|
|
|
h_hz = 15700;
|
|
|
|
v_hz_x100 = 6000;
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("\nLines: %u %c\n", (unsigned)cm.totlines, cm.progressive ? 'p' : 'i');
|
|
|
|
printf("Clocks per line: %u : HS %u.%.3u kHz VS %u.%.2u Hz\n", (unsigned)cm.clkcnt, (unsigned)(h_hz/1000), (unsigned)(h_hz%1000), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100));
|
|
|
|
|
2016-08-22 21:52:46 +00:00
|
|
|
h_syncinlen = tvp_readreg(TVP_HSINWIDTH);
|
|
|
|
v_syncinlen = tvp_readreg(TVP_VSINWIDTH);
|
|
|
|
printf("Hswidth: %u Vswidth: %u Macrovision: %u\n", (unsigned)h_syncinlen, (unsigned)(v_syncinlen & 0x1F), (unsigned)cm.macrovis);
|
2016-03-27 19:40:44 +00:00
|
|
|
|
|
|
|
sniprintf(row1, LCD_ROW_LEN+1, "%s %u%c", avinput_str[cm.avinput], (unsigned)cm.totlines, cm.progressive ? 'p' : 'i');
|
|
|
|
sniprintf(row2, LCD_ROW_LEN+1, "%u.%.2ukHz %u.%.2uHz", (unsigned)(h_hz/1000), (unsigned)((h_hz%1000)/10), (unsigned)(v_hz_x100/100), (unsigned)(v_hz_x100%100));
|
|
|
|
if (!menu_active)
|
|
|
|
lcd_write_status();
|
|
|
|
|
|
|
|
//printf ("Get mode id with %u %u %f\n", totlines, progressive, hz);
|
2017-01-22 22:56:17 +00:00
|
|
|
cm.id = get_mode_id(cm.totlines, cm.progressive, v_hz_x100/100, target_typemask);
|
2016-03-27 19:40:44 +00:00
|
|
|
|
2016-08-14 15:57:50 +00:00
|
|
|
if (cm.id == -1) {
|
2016-03-27 19:40:44 +00:00
|
|
|
printf ("Error: no suitable mode found, defaulting to 240p\n");
|
|
|
|
cm.id = 4;
|
|
|
|
}
|
2016-08-16 19:45:23 +00:00
|
|
|
vm_sel = cm.id;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
|
|
|
target_type = target_typemask & video_modes[cm.id].type;
|
2017-02-07 21:04:30 +00:00
|
|
|
h_synclen_px = ((alt_u32)h_syncinlen * (alt_u32)video_modes[cm.id].h_total*cm.sample_mult) / cm.clkcnt;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-08-22 21:52:46 +00:00
|
|
|
printf("Mode %s selected - hsync width: %upx\n", video_modes[cm.id].name, (unsigned)h_synclen_px);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-02-07 21:04:30 +00:00
|
|
|
tvp_source_setup(target_type,
|
|
|
|
cm.sample_mult*video_modes[cm.id].h_total,
|
|
|
|
cm.clkcnt,
|
|
|
|
cm.cc.tvp_hpll2x && (video_modes[cm.id].flags & MODE_PLLDIVBY2),
|
|
|
|
(alt_u8)h_synclen_px,
|
|
|
|
cm.cc.pre_coast,
|
|
|
|
cm.cc.post_coast,
|
|
|
|
cm.cc.vsync_thold);
|
2016-02-22 23:03:50 +00:00
|
|
|
set_lpf(cm.cc.video_lpf);
|
2017-01-22 22:56:17 +00:00
|
|
|
cm.sample_sel = tvp_set_hpll_phase(cm.cc.sampler_phase, cm.sample_mult);
|
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
set_videoinfo();
|
2016-11-06 13:24:26 +00:00
|
|
|
|
2017-08-09 21:06:35 +00:00
|
|
|
TX_SetPixelRepetition(cm.tx_pixelrep, ((cm.cc.tx_mode==TX_HDMI) && (cm.tx_pixelrep == cm.hdmitx_pixr_ifr)) ? 1 : 0);
|
2017-02-07 21:04:30 +00:00
|
|
|
|
2017-05-29 17:43:24 +00:00
|
|
|
// Full TX initialization increases mode switch delay, use only for compatibility
|
|
|
|
if (cm.cc.full_tx_setup) {
|
|
|
|
TX_enable(cm.cc.tx_mode);
|
|
|
|
} else if (cm.cc.tx_mode==TX_HDMI) {
|
2017-08-09 21:06:35 +00:00
|
|
|
HDMITX_SetAVIInfoFrame(HDMI_Unkown, 0, 0, cm.cc.hdmi_itc, cm.hdmitx_pixr_ifr);
|
2017-06-04 21:02:01 +00:00
|
|
|
#ifdef ENABLE_AUDIO
|
2016-11-06 13:24:26 +00:00
|
|
|
#ifdef MANUAL_CTS
|
2017-05-29 17:43:24 +00:00
|
|
|
SetupAudio(cm.cc.tx_mode);
|
2016-11-06 13:24:26 +00:00
|
|
|
#endif
|
|
|
|
#endif
|
2017-05-29 17:43:24 +00:00
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
|
2016-12-29 22:14:12 +00:00
|
|
|
void load_profile_disp(alt_u8 code) {
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
switch ((menucode_id)code) {
|
|
|
|
case VAL_MINUS:
|
|
|
|
profile_sel = (profile_sel > 0) ? profile_sel-1 : profile_sel;
|
|
|
|
break;
|
|
|
|
case VAL_PLUS:
|
|
|
|
profile_sel = (profile_sel < MAX_PROFILE) ? profile_sel+1 : profile_sel;
|
|
|
|
break;
|
|
|
|
case OPT_SELECT:
|
|
|
|
retval = read_userdata(profile_sel);
|
|
|
|
sniprintf(menu_row2, LCD_ROW_LEN+1, "%s", (retval==0) ? "Loaded" : "Load failed");
|
|
|
|
lcd_write_menu();
|
2017-01-08 10:02:32 +00:00
|
|
|
if (retval == 0)
|
|
|
|
write_userdata(INIT_CONFIG_SLOT);
|
2016-12-29 22:14:12 +00:00
|
|
|
usleep(500000);
|
|
|
|
break;
|
|
|
|
case NO_ACTION:
|
|
|
|
default:
|
|
|
|
sniprintf(menu_row2, LCD_ROW_LEN+1, "Slot %u", profile_sel);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void save_profile_disp(alt_u8 code) {
|
|
|
|
int retval;
|
|
|
|
|
|
|
|
switch ((menucode_id)code) {
|
|
|
|
case VAL_MINUS:
|
|
|
|
profile_sel = (profile_sel > 0) ? profile_sel-1 : profile_sel;
|
|
|
|
break;
|
|
|
|
case VAL_PLUS:
|
|
|
|
profile_sel = (profile_sel < MAX_PROFILE) ? profile_sel+1 : profile_sel;
|
|
|
|
break;
|
|
|
|
case OPT_SELECT:
|
|
|
|
retval = write_userdata(profile_sel);
|
|
|
|
sniprintf(menu_row2, LCD_ROW_LEN+1, "%s", (retval==0) ? "Saved" : "Save failed");
|
|
|
|
lcd_write_menu();
|
2017-01-08 10:02:32 +00:00
|
|
|
if (retval == 0)
|
|
|
|
write_userdata(INIT_CONFIG_SLOT);
|
2016-12-29 22:14:12 +00:00
|
|
|
usleep(500000);
|
|
|
|
break;
|
|
|
|
case NO_ACTION:
|
|
|
|
default:
|
|
|
|
sniprintf(menu_row2, LCD_ROW_LEN+1, "Slot %u", profile_sel);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-16 19:45:23 +00:00
|
|
|
void vm_display(alt_u8 code) {
|
|
|
|
switch ((menucode_id)code) {
|
|
|
|
case VAL_MINUS:
|
|
|
|
vm_sel = (vm_sel > 0) ? vm_sel-1 : vm_sel;
|
|
|
|
break;
|
|
|
|
case VAL_PLUS:
|
2016-12-29 22:14:12 +00:00
|
|
|
vm_sel = (vm_sel < VIDEO_MODES_CNT-1) ? vm_sel+1 : vm_sel;
|
2016-08-16 19:45:23 +00:00
|
|
|
break;
|
|
|
|
case OPT_SELECT:
|
|
|
|
vm_edit = vm_sel;
|
|
|
|
tc_h_samplerate = video_modes[vm_edit].h_total;
|
|
|
|
tc_h_synclen = (alt_u16)video_modes[vm_edit].h_synclen;
|
|
|
|
tc_h_bporch = (alt_u16)video_modes[vm_edit].h_backporch;
|
2017-05-18 20:35:43 +00:00
|
|
|
tc_h_active = video_modes[vm_edit].h_active;
|
|
|
|
tc_v_synclen = (alt_u16)video_modes[vm_edit].v_synclen;
|
2016-08-16 19:45:23 +00:00
|
|
|
tc_v_bporch = (alt_u16)video_modes[vm_edit].v_backporch;
|
2017-05-18 20:35:43 +00:00
|
|
|
tc_v_active = video_modes[vm_edit].v_active;
|
2016-08-16 19:45:23 +00:00
|
|
|
break;
|
|
|
|
case NO_ACTION:
|
|
|
|
default:
|
|
|
|
strncpy(menu_row2, video_modes[vm_sel].name, LCD_ROW_LEN+1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void vm_tweak(alt_u16 v) {
|
2016-09-05 17:49:41 +00:00
|
|
|
if (cm.sync_active && (cm.id == vm_edit)) {
|
|
|
|
if ((video_modes[cm.id].h_total != tc_h_samplerate) ||
|
|
|
|
(video_modes[cm.id].h_synclen != tc_h_synclen) ||
|
2016-08-16 19:45:23 +00:00
|
|
|
(video_modes[cm.id].h_backporch != (alt_u8)tc_h_bporch) ||
|
2017-05-18 20:35:43 +00:00
|
|
|
(video_modes[cm.id].h_active != tc_h_active) ||
|
|
|
|
(video_modes[cm.id].v_synclen != tc_v_synclen) ||
|
|
|
|
(video_modes[cm.id].v_backporch != (alt_u8)tc_v_bporch) ||
|
|
|
|
(video_modes[cm.id].v_active != tc_v_active))
|
2016-09-05 17:49:41 +00:00
|
|
|
update_cur_vm = 1;
|
2016-08-16 19:45:23 +00:00
|
|
|
}
|
|
|
|
video_modes[vm_edit].h_total = tc_h_samplerate;
|
|
|
|
video_modes[vm_edit].h_synclen = (alt_u8)tc_h_synclen;
|
|
|
|
video_modes[vm_edit].h_backporch = (alt_u8)tc_h_bporch;
|
2017-05-18 20:35:43 +00:00
|
|
|
video_modes[vm_edit].h_active = tc_h_active;
|
|
|
|
video_modes[vm_edit].v_synclen = (alt_u8)tc_v_synclen;
|
2016-08-16 19:45:23 +00:00
|
|
|
video_modes[vm_edit].v_backporch = (alt_u8)tc_v_bporch;
|
2017-05-18 20:35:43 +00:00
|
|
|
video_modes[vm_edit].v_active = tc_v_active;
|
2016-08-16 19:45:23 +00:00
|
|
|
|
|
|
|
sniprintf(menu_row2, LCD_ROW_LEN+1, "%u", v);
|
|
|
|
}
|
|
|
|
|
2016-02-22 23:03:50 +00:00
|
|
|
// Initialize hardware
|
2016-03-27 19:40:44 +00:00
|
|
|
int init_hw()
|
|
|
|
{
|
|
|
|
alt_u32 chiprev;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-10-20 22:19:53 +00:00
|
|
|
// Reset hardware
|
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, AV_RESET_N|LCD_BL);
|
2016-03-27 19:40:44 +00:00
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, 0x00);
|
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, 0x00000000);
|
2017-05-18 20:35:43 +00:00
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_5_BASE, 0x00000000);
|
2016-03-27 19:40:44 +00:00
|
|
|
usleep(10000);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
// unreset hw
|
2016-10-20 22:19:53 +00:00
|
|
|
sys_ctrl = AV_RESET_N|LCD_BL|SD_SPI_SS_N|LCD_CS_N;
|
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
//wait >500ms for SD card interface to be stable
|
|
|
|
//over 200ms and LCD may be buggy?
|
|
|
|
usleep(200000);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
// IT6613 officially supports only 100kHz, but 400kHz seems to work
|
|
|
|
I2C_init(I2CA_BASE,ALT_CPU_FREQ,400000);
|
2016-10-20 22:19:53 +00:00
|
|
|
//I2C_init(I2C_OPENCORES_1_BASE,ALT_CPU_FREQ,400000);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
/* Initialize the character display */
|
|
|
|
lcd_init();
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if (!ths_init()) {
|
2016-02-22 23:03:50 +00:00
|
|
|
printf("Error: could not read from THS7353\n");
|
|
|
|
return -2;
|
2016-03-27 19:40:44 +00:00
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
/* check if TVP is found */
|
|
|
|
chiprev = tvp_readreg(TVP_CHIPREV);
|
|
|
|
//printf("chiprev %d\n", chiprev);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
if (chiprev == 0xff) {
|
2016-03-27 19:40:44 +00:00
|
|
|
printf("Error: could not read from TVP7002\n");
|
|
|
|
return -3;
|
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
tvp_init();
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
chiprev = HDMITX_ReadI2C_Byte(IT_DEVICEID);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
if (chiprev != 0x13) {
|
2016-03-27 19:40:44 +00:00
|
|
|
printf("Error: could not read from IT6613\n");
|
|
|
|
return -4;
|
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
InitIT6613();
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-06-04 21:02:01 +00:00
|
|
|
#ifdef ENABLE_AUDIO
|
|
|
|
if (pcm1862_init()) {
|
|
|
|
printf("PCM1862 found\n");
|
|
|
|
pcm1862_active = 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if (check_flash() != 0) {
|
2016-02-22 23:03:50 +00:00
|
|
|
printf("Error: incorrect flash type detected\n");
|
|
|
|
return -1;
|
2016-03-27 19:40:44 +00:00
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-01-08 10:02:32 +00:00
|
|
|
// Set defaults
|
2016-04-15 19:05:53 +00:00
|
|
|
set_default_avconfig();
|
2017-01-08 10:02:32 +00:00
|
|
|
memcpy(rc_keymap, rc_keymap_default, sizeof(rc_keymap));
|
2016-04-15 19:05:53 +00:00
|
|
|
|
2017-01-08 10:02:32 +00:00
|
|
|
// Load initconfig and profile
|
|
|
|
read_userdata(INIT_CONFIG_SLOT);
|
|
|
|
read_userdata(profile_sel);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2017-01-08 10:02:32 +00:00
|
|
|
// Setup remote keymap
|
2016-04-15 19:05:53 +00:00
|
|
|
if (!(IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & PB1_BIT))
|
2016-02-22 23:03:50 +00:00
|
|
|
setup_rc();
|
|
|
|
|
2016-04-16 19:29:32 +00:00
|
|
|
// init always in HDMI mode (fixes yellow screen bug)
|
2016-04-15 19:05:53 +00:00
|
|
|
TX_enable(TX_HDMI);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
return 0;
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Enable chip outputs
|
2016-03-27 19:40:44 +00:00
|
|
|
void enable_outputs()
|
|
|
|
{
|
|
|
|
// program video mode
|
|
|
|
program_mode();
|
|
|
|
// enable TVP output
|
|
|
|
tvp_enable_output();
|
|
|
|
|
2017-05-29 17:43:24 +00:00
|
|
|
// enable and unmute TX
|
2016-05-23 21:27:50 +00:00
|
|
|
TX_enable(tc.tx_mode);
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
2016-03-27 19:40:44 +00:00
|
|
|
tvp_input_t target_input = 0;
|
|
|
|
ths_input_t target_ths = 0;
|
2017-06-11 22:00:34 +00:00
|
|
|
pcm_input_t target_pcm = 0;
|
2016-03-27 19:40:44 +00:00
|
|
|
video_format target_format = 0;
|
|
|
|
|
|
|
|
alt_u8 av_init = 0;
|
|
|
|
status_t status;
|
|
|
|
|
2016-04-15 19:05:53 +00:00
|
|
|
alt_u32 input_vec;
|
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
int init_stat;
|
|
|
|
|
|
|
|
init_stat = init_hw();
|
|
|
|
|
|
|
|
if (init_stat >= 0) {
|
|
|
|
printf("### DIY VIDEO DIGITIZER / SCANCONVERTER INIT OK ###\n\n");
|
2016-11-06 13:24:26 +00:00
|
|
|
sniprintf(row1, LCD_ROW_LEN+1, "OSSC fw. %u.%.2u" FW_SUFFIX1 FW_SUFFIX2, FW_VER_MAJOR, FW_VER_MINOR);
|
2016-04-15 19:05:53 +00:00
|
|
|
#ifndef DEBUG
|
2017-01-08 10:02:32 +00:00
|
|
|
strncpy(row2, "2014-2017 marqs", LCD_ROW_LEN+1);
|
2016-04-15 19:05:53 +00:00
|
|
|
#else
|
|
|
|
strncpy(row2, "** DEBUG BUILD *", LCD_ROW_LEN+1);
|
|
|
|
#endif
|
2016-03-27 19:40:44 +00:00
|
|
|
lcd_write_status();
|
2017-01-08 10:02:32 +00:00
|
|
|
usleep(500000);
|
2016-03-27 19:40:44 +00:00
|
|
|
} else {
|
|
|
|
sniprintf(row1, LCD_ROW_LEN+1, "Init error %d", init_stat);
|
|
|
|
strncpy(row2, "", LCD_ROW_LEN+1);
|
|
|
|
lcd_write_status();
|
|
|
|
while (1) {}
|
|
|
|
}
|
|
|
|
|
2017-01-08 10:02:32 +00:00
|
|
|
if (tc.def_input < AV_LAST)
|
|
|
|
target_mode = tc.def_input;
|
2016-08-14 15:57:50 +00:00
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
// Mainloop
|
2016-03-27 19:40:44 +00:00
|
|
|
while(1) {
|
2016-05-23 21:27:50 +00:00
|
|
|
// Read remote control and PCB button status
|
2016-04-15 19:05:53 +00:00
|
|
|
input_vec = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE);
|
|
|
|
remote_code = input_vec & RC_MASK;
|
|
|
|
btn_code = ~input_vec & PB_MASK;
|
|
|
|
remote_rpt = input_vec >> 24;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-04-15 19:05:53 +00:00
|
|
|
if ((remote_rpt == 0) || ((remote_rpt > 1) && (remote_rpt < 6)) || (remote_rpt == remote_rpt_prev))
|
|
|
|
remote_code = 0;
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
parse_control();
|
2016-04-15 19:05:53 +00:00
|
|
|
|
2016-05-23 21:27:50 +00:00
|
|
|
if (menu_active)
|
|
|
|
display_menu(0);
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if (target_mode == cm.avinput)
|
|
|
|
target_mode = AV_KEEP;
|
|
|
|
|
|
|
|
switch (target_mode) {
|
|
|
|
case AV1_RGBs:
|
|
|
|
target_input = TVP_INPUT1;
|
|
|
|
target_format = FORMAT_RGBS;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_INPUT_B;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT4;
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
|
|
|
case AV1_RGsB:
|
|
|
|
target_input = TVP_INPUT1;
|
|
|
|
target_format = FORMAT_RGsB;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_INPUT_B;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT4;
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
2016-05-23 21:27:50 +00:00
|
|
|
case AV1_YPBPR:
|
|
|
|
target_input = TVP_INPUT1;
|
|
|
|
target_format = FORMAT_YPbPr;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_INPUT_B;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT4;
|
2016-05-23 21:27:50 +00:00
|
|
|
break;
|
2016-03-27 19:40:44 +00:00
|
|
|
case AV2_YPBPR:
|
|
|
|
target_input = TVP_INPUT1;
|
|
|
|
target_format = FORMAT_YPbPr;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_INPUT_A;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT3;
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
|
|
|
case AV2_RGsB:
|
|
|
|
target_input = TVP_INPUT1;
|
|
|
|
target_format = FORMAT_RGsB;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_INPUT_A;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT3;
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
|
|
|
case AV3_RGBHV:
|
|
|
|
target_input = TVP_INPUT3;
|
|
|
|
target_format = FORMAT_RGBHV;
|
|
|
|
target_typemask = VIDEO_PC;
|
|
|
|
target_ths = THS_STANDBY;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT2;
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
|
|
|
case AV3_RGBs:
|
|
|
|
target_input = TVP_INPUT3;
|
|
|
|
target_format = FORMAT_RGBS;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_STANDBY;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT2;
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
|
|
|
case AV3_RGsB:
|
|
|
|
target_input = TVP_INPUT3;
|
|
|
|
target_format = FORMAT_RGsB;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_STANDBY;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT2;
|
2016-03-27 19:40:44 +00:00
|
|
|
break;
|
2016-05-23 21:27:50 +00:00
|
|
|
case AV3_YPBPR:
|
|
|
|
target_input = TVP_INPUT3;
|
|
|
|
target_format = FORMAT_YPbPr;
|
|
|
|
target_typemask = VIDEO_LDTV|VIDEO_SDTV|VIDEO_EDTV|VIDEO_HDTV;
|
|
|
|
target_ths = THS_STANDBY;
|
2017-06-11 22:00:34 +00:00
|
|
|
target_pcm = PCM_INPUT2;
|
2016-05-23 21:27:50 +00:00
|
|
|
break;
|
2016-03-27 19:40:44 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target_mode != AV_KEEP) {
|
2016-05-23 21:27:50 +00:00
|
|
|
printf("### SWITCH MODE TO %s ###\n", avinput_str[target_mode]);
|
2016-03-27 19:40:44 +00:00
|
|
|
cm.avinput = target_mode;
|
|
|
|
cm.sync_active = 0;
|
|
|
|
ths_source_sel(target_ths, (cm.cc.video_lpf > 1) ? (VIDEO_LPF_MAX-cm.cc.video_lpf) : THS_LPF_BYPASS);
|
|
|
|
tvp_disable_output();
|
2017-06-04 21:02:01 +00:00
|
|
|
#ifdef ENABLE_AUDIO
|
2016-11-06 13:24:26 +00:00
|
|
|
DisableAudioOutput();
|
2017-06-04 21:02:01 +00:00
|
|
|
if (pcm1862_active)
|
2017-06-11 22:00:34 +00:00
|
|
|
pcm_source_sel(target_pcm);
|
2016-11-06 13:24:26 +00:00
|
|
|
#endif
|
2016-05-23 21:27:50 +00:00
|
|
|
tvp_source_sel(target_input, target_format);
|
2016-03-27 19:40:44 +00:00
|
|
|
cm.clkcnt = 0; //TODO: proper invalidate
|
|
|
|
strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1);
|
|
|
|
strncpy(row2, " NO SYNC", LCD_ROW_LEN+1);
|
|
|
|
if (!menu_active)
|
|
|
|
lcd_write_status();
|
2017-01-08 10:02:32 +00:00
|
|
|
if (av_init && (tc.def_input == AV_LAST))
|
|
|
|
write_userdata(INIT_CONFIG_SLOT);
|
|
|
|
av_init = 1;
|
2016-03-27 19:40:44 +00:00
|
|
|
}
|
|
|
|
|
2016-05-30 10:02:15 +00:00
|
|
|
// Check here to enable regardless of av_init
|
|
|
|
if (tc.tx_mode != cm.cc.tx_mode) {
|
2017-08-09 21:06:35 +00:00
|
|
|
HDMITX_SetAVIInfoFrame(HDMI_Unkown, 0, 0, 0, 0);
|
2016-05-30 10:02:15 +00:00
|
|
|
TX_enable(tc.tx_mode);
|
|
|
|
cm.cc.tx_mode = tc.tx_mode;
|
2016-07-09 20:12:35 +00:00
|
|
|
cm.clkcnt = 0; //TODO: proper invalidate
|
2016-05-30 10:02:15 +00:00
|
|
|
}
|
2017-05-18 20:35:43 +00:00
|
|
|
if ((tc.tx_mode == TX_HDMI) && (tc.hdmi_itc != cm.cc.hdmi_itc)) {
|
|
|
|
//EnableAVIInfoFrame(FALSE, NULL);
|
|
|
|
printf("setting ITC to %d\n", tc.hdmi_itc);
|
2017-08-09 21:06:35 +00:00
|
|
|
HDMITX_SetAVIInfoFrame(HDMI_Unkown, 0, 0, tc.hdmi_itc, cm.hdmitx_pixr_ifr);
|
2017-05-18 20:35:43 +00:00
|
|
|
cm.cc.hdmi_itc = tc.hdmi_itc;
|
|
|
|
}
|
2016-05-30 10:02:15 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
if (av_init) {
|
2016-05-23 21:27:50 +00:00
|
|
|
status = get_status(target_input, target_format);
|
2016-03-27 19:40:44 +00:00
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case ACTIVITY_CHANGE:
|
|
|
|
if (cm.sync_active) {
|
|
|
|
printf("Sync up\n");
|
2016-10-20 22:19:53 +00:00
|
|
|
sys_ctrl |= VIDGEN_OFF;
|
|
|
|
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, sys_ctrl);
|
2016-03-27 19:40:44 +00:00
|
|
|
enable_outputs();
|
|
|
|
} else {
|
|
|
|
printf("Sync lost\n");
|
|
|
|
cm.clkcnt = 0; //TODO: proper invalidate
|
|
|
|
tvp_disable_output();
|
|
|
|
//ths_source_sel(THS_STANDBY, 0);
|
|
|
|
strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1);
|
|
|
|
strncpy(row2, " NO SYNC", LCD_ROW_LEN+1);
|
|
|
|
if (!menu_active)
|
|
|
|
lcd_write_status();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MODE_CHANGE:
|
2016-04-15 19:05:53 +00:00
|
|
|
if (cm.sync_active) {
|
2016-03-27 19:40:44 +00:00
|
|
|
printf("Mode change\n");
|
|
|
|
program_mode();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case INFO_CHANGE:
|
|
|
|
if (cm.sync_active) {
|
|
|
|
printf("Info change\n");
|
|
|
|
set_videoinfo();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-22 23:03:50 +00:00
|
|
|
btn_code_prev = btn_code;
|
2016-04-15 19:05:53 +00:00
|
|
|
remote_rpt_prev = remote_rpt;
|
2016-08-14 15:57:50 +00:00
|
|
|
target_mode = AV_KEEP;
|
2016-05-23 21:27:50 +00:00
|
|
|
usleep(300); // Avoid executing mainloop multiple times per vsync
|
2016-03-27 19:40:44 +00:00
|
|
|
}
|
2016-02-22 23:03:50 +00:00
|
|
|
|
2016-03-27 19:40:44 +00:00
|
|
|
return 0;
|
2016-02-22 23:03:50 +00:00
|
|
|
}
|