Misc updates

-optimizations from Borti
-more code refactoring
-fix build warnings
-change scanline mode logic
This commit is contained in:
marqs 2016-06-12 23:43:24 +03:00
parent 51c43a7c10
commit 6c5f753245
24 changed files with 952 additions and 642 deletions

View File

@ -58,7 +58,6 @@
<File Name="sys_controller/tvp7002/tvp7002.h"/>
<File Name="sys_controller/tvp7002/tvp7002.c"/>
</VirtualDirectory>
<File Name="sys_controller/av_controller.c"/>
<VirtualDirectory Name="memory">
<File Name="sys_controller/memory/flash.h"/>
<File Name="sys_controller/memory/flash.c"/>
@ -69,6 +68,16 @@
<File Name="sys_controller/ossc/menu.c"/>
<File Name="sys_controller/ossc/menu.h"/>
<File Name="sys_controller/ossc/sysconfig.h"/>
<File Name="sys_controller/ossc/controls.h"/>
<File Name="sys_controller/ossc/controls.c"/>
<File Name="sys_controller/ossc/avconfig.h"/>
<File Name="sys_controller/ossc/avconfig.c"/>
<File Name="sys_controller/ossc/av_controller.c"/>
<File Name="sys_controller/ossc/av_controller.h"/>
<File Name="sys_controller/ossc/firmware.h"/>
<File Name="sys_controller/ossc/firmware.c"/>
<File Name="sys_controller/ossc/userdata.h"/>
<File Name="sys_controller/ossc/userdata.c"/>
</VirtualDirectory>
</VirtualDirectory>
<Description/>

View File

@ -142,7 +142,6 @@ ACDS_VERSION := 14.1
ELF := sys_controller.elf
# Paths to C, C++, and assembly source files.
C_SRCS += av_controller.c
C_SRCS += it6613/EDID.c
C_SRCS += it6613/HDMI_TX.c
C_SRCS += it6613/hdmitx_nios2.c
@ -155,7 +154,12 @@ C_SRCS += ths7353/ths7353.c
C_SRCS += spi_charlcd/lcd.c
C_SRCS += memory/flash.c
C_SRCS += memory/sdcard.c
C_SRCS += ossc/av_controller.c
C_SRCS += ossc/avconfig.c
C_SRCS += ossc/controls.c
C_SRCS += ossc/firmware.c
C_SRCS += ossc/menu.c
C_SRCS += ossc/userdata.c
CXX_SRCS :=
ASM_SRCS :=
@ -177,7 +181,7 @@ APP_CFLAGS_DEFINED_SYMBOLS := -DNO_I2C_DEBUG -DNO_DEBUG
APP_CFLAGS_UNDEFINED_SYMBOLS :=
APP_CFLAGS_OPTIMIZATION := -Os
APP_CFLAGS_DEBUG_LEVEL :=
APP_CFLAGS_WARNINGS := -Wall
APP_CFLAGS_WARNINGS := -Wall -Wno-unused-but-set-variable -Wno-unused-variable -Wno-unused-function
APP_CFLAGS_USER_FLAGS := -fdata-sections -ffunction-sections -fshort-enums
APP_ASFLAGS_USER :=

View File

@ -1,5 +1,6 @@
//#include "terasic_includes.h"
//#include "mcu.h"
#include <unistd.h>
#include "it6613_sys.h"
#include "hdmitx.h"
#include "HDMI_TX.h"

View File

@ -78,6 +78,8 @@ HDCP_ResumeAuthentication()
}
#endif
void DelayMS(unsigned int ms);
//#include "edid.h"
// #include "dss_sha.h"
#include "it6613_drv.h"

View File

@ -1,5 +1,6 @@
#include <stdio.h>
#include <unistd.h>
#include "sysconfig.h"
#include "system.h"
#include "i2c_opencores.h"
#include "it6613.h"

View File

@ -1225,7 +1225,7 @@ SetInputMode(BYTE InputMode,BYTE bInputSignalType)
static void
SetCSCScale(BYTE bInputMode,BYTE bOutputMode)
{
BYTE ucData,csc ;
BYTE ucData,csc=0 ;
BYTE filter = 0 ; // filter is for Video CTRL DN_FREE_GO,EN_DITHER,and ENUDFILT

View File

@ -279,7 +279,7 @@ HDMITX_ChangeDisplayOption(HDMI_Video_Type OutputVideoTiming, HDMI_OutputColorMo
bInputColorMode &= ~F_VIDMODE_ITU709 ;
}
if( Colorimetry != HDMI_640x480p60)
if( OutputVideoTiming != HDMI_640x480p60)
{
bInputColorMode |= F_VIDMODE_16_235 ;
}
@ -377,7 +377,7 @@ ParseEDID()
// collect the EDID ucdata of segment 0
BYTE CheckSum ;
BYTE BlockCount ;
BOOL err ;
BOOL err = FALSE ;
BOOL bValidCEA = FALSE ;
int i ;

View File

@ -18,8 +18,10 @@
//
#include <unistd.h>
#include <string.h>
#include "flash.h"
#include "lcd.h"
#include "ci_crc.h"
extern alt_epcq_controller_dev epcq_controller_0;
extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];

View File

@ -23,6 +23,7 @@
#include "string.h"
#include "altera_avalon_pio_regs.h"
#include "i2c_opencores.h"
#include "av_controller.h"
#include "tvp7002.h"
#include "ths7353.h"
#include "video_modes.h"
@ -30,16 +31,14 @@
#include "flash.h"
#include "sdcard.h"
#include "menu.h"
#include "avconfig.h"
#include "sysconfig.h"
#include "firmware.h"
#include "userdata.h"
#include "it6613.h"
#include "it6613_sys.h"
#include "HDMI_TX.h"
#include "hdmitx.h"
#include "ci_crc.h"
alt_u8 fw_ver_major = 0;
alt_u8 fw_ver_minor = 70;
#define FW_UPDATE_RETRIES 3
#define LINECNT_THOLD 1
#define STABLE_THOLD 1
@ -48,109 +47,18 @@ alt_u8 fw_ver_minor = 70;
#define SYNC_LOSS_THOLD 5
#define STATUS_TIMEOUT 10000
#define MAINLOOP_SLEEP_US 10000
#define DEFAULT_PRE_COAST 1
#define DEFAULT_POST_COAST 0
#define DEFAULT_SAMPLER_PHASE 16
#define DEFAULT_SYNC_VTH 11
#define RC_MASK 0x0000ffff
#define PB_MASK 0x00030000
#define PB0_BIT 0x00010000
#define PB1_BIT 0x00020000
#define HDMITX_MODE_MASK 0x00040000
static const char *rc_keydesc[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "MENU", "OK", "BACK", "UP", "DOWN", "LEFT", "RIGHT", "INFO", "LCD_BACKLIGHT", "SCANLINE_TGL", "SCANLINE_INT+", "SCANLINE_INT-"};
#define REMOTE_MAX_KEYS (sizeof(rc_keydesc)/sizeof(char*))
alt_u16 rc_keymap[REMOTE_MAX_KEYS] = {0x3E29, 0x3EA9, 0x3E69, 0x3EE9, 0x3E19, 0x3E99, 0x3E59, 0x3ED9, 0x3E39, 0x3EC9, 0x3E4D, 0x3E1D, 0x3EED, 0x3E2D, 0x3ECD, 0x3EAD, 0x3E6D, 0x3E65, 0x3E01, 0x1C48, 0x1C50, 0x1CD0};
#define lcd_write_menu() lcd_write((char*)&menu_row1, (char*)&menu_row2)
#define lcd_write_status() lcd_write((char*)&row1, (char*)&row2)
static const char *avinput_str[] = { "-", "AV1: RGBS", "AV1: RGsB", "AV1: YPbPr", "AV2: YPbPr", "AV2: RGsB", "AV3: RGBHV", "AV3: RGBS", "AV3: RGsB", "AV3: YPbPr" };
typedef enum {
AV_KEEP = 0,
AV1_RGBs = 1,
AV1_RGsB = 2,
AV1_YPBPR = 3,
AV2_YPBPR = 4,
AV2_RGsB = 5,
AV3_RGBHV = 6,
AV3_RGBs = 7,
AV3_RGsB = 8,
AV3_YPBPR = 9
} avinput_t;
// In reverse order of importance
typedef enum {
NO_CHANGE = 0,
INFO_CHANGE = 1,
MODE_CHANGE = 2,
TX_MODE_CHANGE = 3,
ACTIVITY_CHANGE = 4
} status_t;
typedef enum {
TX_HDMI = 0,
TX_DVI = 1
} tx_mode_t;
// Target configuration
avconfig_t tc;
//TODO: transform binary values into flags
typedef struct {
alt_u32 totlines;
alt_u32 clkcnt;
alt_u8 progressive;
alt_u8 macrovis;
alt_8 id;
alt_u8 sync_active;
alt_u8 linemult;
avinput_t avinput;
// Current configuration
avconfig_t cc;
} avmode_t;
// Current mode
avmode_t cm;
typedef struct {
char fw_key[4];
alt_u8 version_major;
alt_u8 version_minor;
char version_suffix[8];
alt_u32 hdr_len;
alt_u32 data_len;
alt_u32 data_crc;
alt_u32 hdr_crc;
} fw_hdr;
#define USERDATA_HDR_SIZE 11
typedef struct {
char userdata_key[8];
alt_u8 version_major;
alt_u8 version_minor;
alt_u8 num_entries;
} userdata_hdr;
#define USERDATA_ENTRY_HDR_SIZE 2
typedef struct {
alt_u8 type;
alt_u8 entry_len;
} userdata_entry;
typedef enum {
UDE_REMOTE_MAP = 0,
UDE_AVCONFIG,
} userdata_entry_type;
extern mode_data_t video_modes[];
extern ypbpr_to_rgb_csc_t csc_coeffs[];
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
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;
alt_u8 target_typemask;
alt_u8 target_type;
@ -158,336 +66,16 @@ alt_u8 stable_frames;
char row1[LCD_ROW_LEN+1], row2[LCD_ROW_LEN+1], menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
alt_u8 menu_active;
alt_u32 remote_code;
alt_u8 remote_rpt, remote_rpt_prev;
alt_u32 btn_code, btn_code_prev;
extern alt_u8 menu_active;
avinput_t target_mode;
int check_fw_header(alt_u8 *databuf, fw_hdr *hdr)
inline void lcd_write_menu()
{
alt_u32 crcval, tmp;
strncpy(hdr->fw_key, (char*)databuf, 4);
if (strncmp(hdr->fw_key, "OSSC", 4)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid image");
menu_row2[0] = '\0';
return 1;
}
hdr->version_major = databuf[4];
hdr->version_minor = databuf[5];
strncpy(hdr->version_suffix, (char*)(databuf+6), 8);
hdr->version_suffix[7] = 0;
memcpy(&tmp, databuf+14, 4);
hdr->hdr_len = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
memcpy(&tmp, databuf+18, 4);
hdr->data_len = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
memcpy(&tmp, databuf+22, 4);
hdr->data_crc = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
// Always at bytes [508-511]
memcpy(&tmp, databuf+508, 4);
hdr->hdr_crc = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
if (hdr->hdr_len < 26 || hdr->hdr_len > 508) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid header");
menu_row2[0] = '\0';
return -1;
}
crcval = crcCI(databuf, hdr->hdr_len, 1);
if (crcval != hdr->hdr_crc) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid hdr CRC");
menu_row2[0] = '\0';
return -2;
}
return 0;
lcd_write((char*)&menu_row1, (char*)&menu_row2);
}
int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_u8 *tmpbuf)
{
alt_u32 crcval=0, i, bytes_to_read;
int retval;
for (i=0; i<size; i=i+SD_BUFFER_SIZE) {
bytes_to_read = ((size-i < SD_BUFFER_SIZE) ? (size-i) : SD_BUFFER_SIZE);
retval = read_sd_block(offset+i, bytes_to_read, tmpbuf);
if (retval != 0)
return -2;
crcval = crcCI(tmpbuf, bytes_to_read, (i==0));
}
if (crcval != golden_crc) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid data CRC");
menu_row2[0] = '\0';
return -3;
}
return 0;
}
#ifdef DEBUG
int fw_update()
{
sniprintf(menu_row2, LCD_ROW_LEN+1, "Not implemented");
lcd_write_menu();
usleep(1000000);
return -1;
}
#else
int fw_update()
{
int retval, i;
int retries = FW_UPDATE_RETRIES;
alt_u8 databuf[SD_BUFFER_SIZE];
alt_u32 btn_vec;
alt_u32 bytes_to_rw;
fw_hdr fw_header;
retval = check_sdcard(databuf);
if (retval != 0)
goto failure;
retval = check_fw_header(databuf, &fw_header);
if (retval != 0)
goto failure;
sniprintf(menu_row1, LCD_ROW_LEN+1, "Validating data");
sniprintf(menu_row2, LCD_ROW_LEN+1, "%u bytes", (unsigned)fw_header.data_len);
lcd_write_menu();
retval = check_fw_image(512, fw_header.data_len, fw_header.data_crc, databuf);
if (retval != 0)
goto failure;
sniprintf(menu_row1, LCD_ROW_LEN+1, "%u.%.2u%s%s", fw_header.version_major, fw_header.version_minor, (fw_header.version_suffix[0] == 0) ? "" : "-", fw_header.version_suffix);
strncpy(menu_row2, "Update? 1=Y, 2=N", LCD_ROW_LEN+1);
lcd_write_menu();
while (1) {
btn_vec = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (btn_vec == rc_keymap[RC_BTN1]) {
break;
} else if (btn_vec == rc_keymap[RC_BTN2]) {
retval = 2;
return 1;
}
usleep(MAINLOOP_SLEEP_US);
}
//disable video output
tvp_disable_output();
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) | (1<<2)));
usleep(MAINLOOP_SLEEP_US);
strncpy(menu_row1, "Updating FW", LCD_ROW_LEN+1);
update_init:
strncpy(menu_row2, "please wait...", LCD_ROW_LEN+1);
lcd_write_menu();
for (i=0; i<fw_header.data_len; i=i+SD_BUFFER_SIZE) {
bytes_to_rw = ((fw_header.data_len-i < SD_BUFFER_SIZE) ? (fw_header.data_len-i) : SD_BUFFER_SIZE);
retval = read_sd_block(512+i, bytes_to_rw, databuf);
if (retval != 0)
return -200;
retval = write_flash_page(databuf, ((bytes_to_rw < PAGESIZE) ? bytes_to_rw : PAGESIZE), (i/PAGESIZE));
if (retval != 0)
goto failure;
//TODO: support multiple page sizes
if (bytes_to_rw > PAGESIZE) {
retval = write_flash_page(databuf+PAGESIZE, (bytes_to_rw-PAGESIZE), (i/PAGESIZE)+1);
if (retval != 0)
goto failure;
}
}
strncpy(menu_row1, "Verifying flash", LCD_ROW_LEN+1);
strncpy(menu_row2, "please wait...", LCD_ROW_LEN+1);
lcd_write_menu();
retval = verify_flash(0, fw_header.data_len, fw_header.data_crc, databuf);
if (retval != 0)
goto failure;
return 0;
failure:
lcd_write_menu();
usleep(1000000);
// Probable rw error, retry update
if ((retval <= -200) && (retries > 0)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Retrying update");
retries--;
goto update_init;
}
return -1;
}
#endif
int write_userdata()
{
alt_u8 databuf[PAGESIZE];
int retval;
strncpy((char*)databuf, "USRDATA", 8);
databuf[8] = fw_ver_major;
databuf[9] = fw_ver_minor;
databuf[10] = 2;
retval = write_flash_page(databuf, USERDATA_HDR_SIZE, (USERDATA_OFFSET/PAGESIZE));
if (retval != 0) {
return -1;
}
databuf[0] = UDE_REMOTE_MAP;
databuf[1] = 4+sizeof(rc_keymap);
databuf[2] = databuf[3] = 0; //padding
memcpy(databuf+4, rc_keymap, sizeof(rc_keymap));
retval = write_flash_page(databuf, databuf[1], (USERDATA_OFFSET/PAGESIZE)+1);
if (retval != 0) {
return -1;
}
databuf[0] = UDE_AVCONFIG;
databuf[1] = 4+sizeof(avconfig_t);
databuf[2] = databuf[3] = 0; //padding
memcpy(databuf+4, &tc, sizeof(avconfig_t));
retval = write_flash_page(databuf, databuf[1], (USERDATA_OFFSET/PAGESIZE)+2);
if (retval != 0) {
return -1;
}
return 0;
}
int set_default_avconfig()
{
memset(&tc, 0, sizeof(avconfig_t));
tc.pre_coast = DEFAULT_PRE_COAST;
tc.post_coast = DEFAULT_POST_COAST;
tc.sampler_phase = DEFAULT_SAMPLER_PHASE;
tc.sync_vth = DEFAULT_SYNC_VTH;
tc.vsync_thold = DEFAULT_VSYNC_THOLD;
tc.en_alc = 1;
return 0;
}
int read_userdata()
{
int retval, i;
alt_u8 databuf[PAGESIZE];
userdata_hdr udhdr;
userdata_entry udentry;
retval = read_flash(USERDATA_OFFSET, USERDATA_HDR_SIZE, databuf);
if (retval != 0) {
printf("Flash read error\n");
return -1;
}
strncpy(udhdr.userdata_key, (char*)databuf, 8);
if (strncmp(udhdr.userdata_key, "USRDATA", 8)) {
printf("No userdata found on flash\n");
return 1;
}
udhdr.version_major = databuf[8];
udhdr.version_minor = databuf[9];
udhdr.num_entries = databuf[10];
//TODO: check version compatibility
printf("Userdata: v%u.%.2u, %u entries\n", udhdr.version_major, udhdr.version_minor, udhdr.num_entries);
for (i=0; i<udhdr.num_entries; i++) {
retval = read_flash(USERDATA_OFFSET+((i+1)*PAGESIZE), USERDATA_ENTRY_HDR_SIZE, databuf);
if (retval != 0) {
printf("Flash read error\n");
return -1;
}
udentry.type = databuf[0];
udentry.entry_len = databuf[1];
retval = read_flash(USERDATA_OFFSET+((i+1)*PAGESIZE), udentry.entry_len, databuf);
if (retval != 0) {
printf("Flash read error\n");
return -1;
}
switch (udentry.type) {
case UDE_REMOTE_MAP:
if ((udentry.entry_len-4) == sizeof(rc_keymap)) {
memcpy(rc_keymap, databuf+4, sizeof(rc_keymap));
printf("RC data read (%u bytes)\n", sizeof(rc_keymap));
}
break;
case UDE_AVCONFIG:
if ((udentry.entry_len-4) == sizeof(avconfig_t)) {
memcpy(&tc, databuf+4, sizeof(avconfig_t));
printf("Avconfig data read (%u bytes)\n", sizeof(avconfig_t));
}
break;
default:
printf("Unknown userdata entry\n");
break;
}
}
return 0;
}
void setup_rc()
{
int i, confirm;
alt_u32 remote_code_prev;
for (i=0; i<REMOTE_MAX_KEYS; i++) {
strncpy(menu_row1, "Press", LCD_ROW_LEN+1);
strncpy(menu_row2, rc_keydesc[i], LCD_ROW_LEN+1);
lcd_write_menu();
confirm = 0;
while (1) {
remote_code = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (remote_code && (remote_code != remote_code_prev)) {
if (confirm == 0) {
rc_keymap[i] = remote_code;
strncpy(menu_row1, "Confirm", LCD_ROW_LEN+1);
lcd_write_menu();
confirm = 1;
} else {
if (remote_code == rc_keymap[i]) {
confirm = 2;
} else {
strncpy(menu_row1, "Mismatch, retry", LCD_ROW_LEN+1);
lcd_write_menu();
confirm = 0;
}
}
}
remote_code_prev = remote_code;
if (confirm == 2)
break;
usleep(MAINLOOP_SLEEP_US);
}
}
inline void lcd_write_status() {
lcd_write((char*)&row1, (char*)&row2);
}
inline void TX_enable(tx_mode_t mode)
@ -507,70 +95,6 @@ inline void TX_enable(tx_mode_t mode)
SetAVMute(FALSE);
}
void parse_control()
{
if (remote_code)
printf("RCODE: 0x%.4x, %u\n", remote_code, remote_rpt);
if (btn_code_prev == 0 && btn_code != 0)
printf("BCODE: 0x%.2x\n", btn_code>>16);
if (remote_code == rc_keymap[RC_BTN1]) {
target_mode = AV1_RGBs;
} else if (remote_code == rc_keymap[RC_BTN4]) {
target_mode = AV1_RGsB;
} else if (remote_code == rc_keymap[RC_BTN7]) {
target_mode = AV1_YPBPR;
} else if (remote_code == rc_keymap[RC_BTN2]) {
target_mode = AV2_YPBPR;
} else if (remote_code == rc_keymap[RC_BTN5]) {
target_mode = AV2_RGsB;
} else if (remote_code == rc_keymap[RC_BTN3]) {
target_mode = AV3_RGBHV;
} else if (remote_code == rc_keymap[RC_BTN6]) {
target_mode = AV3_RGBs;
} else if (remote_code == rc_keymap[RC_BTN9]) {
target_mode = AV3_RGsB;
} else if (remote_code == rc_keymap[RC_BTN0]) {
target_mode = AV3_YPBPR;
} else if (remote_code == rc_keymap[RC_MENU]) {
menu_active = !menu_active;
if (menu_active) {
display_menu(1);
} else {
lcd_write_status();
}
/*} else if (remote_code == rc_keymap[RC_BACK]) {
menu_active = 0;
lcd_write_status();*/
} else if (remote_code == rc_keymap[RC_INFO]) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "VMod: %s", video_modes[cm.id].name);
//sniprintf(menu_row1, LCD_ROW_LEN+1, "0x%x 0x%x 0x%x", ths_readreg(THS_CH1), ths_readreg(THS_CH2), ths_readreg(THS_CH3));
sniprintf(menu_row2, LCD_ROW_LEN+1, "LO: %u VSM: %u", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, (IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) >> 16) & 0x3);
lcd_write_menu();
printf("Mod: %s\n", video_modes[cm.id].name);
printf("Lines: %u M: %u\n", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, cm.macrovis);
} else if (remote_code == rc_keymap[RC_LCDBL]) {
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) ^ (1<<1)));
} else if (remote_code == rc_keymap[RC_SL_TGL]) {
tc.sl_mode = (tc.sl_mode > 0) ? 0 : 1;
} else if (remote_code == rc_keymap[RC_SL_MINUS]) {
if (tc.sl_str > 0)
tc.sl_str--;
} else if (remote_code == rc_keymap[RC_SL_PLUS]) {
if (tc.sl_str < SCANLINESTR_MAX)
tc.sl_str++;
}
if (btn_code_prev == 0) {
if (btn_code & PB0_BIT)
target_mode = (cm.avinput == AV3_YPBPR) ? AV1_RGBs : (cm.avinput+1);
if (btn_code & PB1_BIT)
tc.sl_mode = (tc.sl_mode > 0) ? 0 : 1;
}
}
void set_lpf(alt_u8 lpf)
{
alt_u32 pclk;
@ -704,6 +228,7 @@ status_t get_status(tvp_input_t input, video_format format)
}
if ((tc.sl_mode != cm.cc.sl_mode) ||
(tc.sl_type != cm.cc.sl_type) ||
(tc.sl_str != cm.cc.sl_str) ||
(tc.sl_id != cm.cc.sl_id) ||
(tc.h_mask != cm.cc.h_mask) ||
@ -747,6 +272,8 @@ status_t get_status(tvp_input_t input, video_format format)
void set_videoinfo()
{
alt_u8 slid_target;
alt_u8 sl_en_fpga;
alt_u8 sl_mode_fpga = 0;
if (video_modes[cm.id].flags & MODE_L3ENABLE_MASK) {
cm.linemult = 2;
@ -759,8 +286,20 @@ void set_videoinfo()
slid_target = cm.cc.sl_id;
}
if (cm.cc.sl_mode == 0) {
sl_en_fpga = 0;
} else if (cm.cc.sl_mode == 2) { //manual
sl_en_fpga = 1;
sl_mode_fpga = cm.cc.sl_type;
} else if ((video_modes[cm.id].flags & (MODE_L2ENABLE|MODE_L3ENABLE_MASK)) && !(video_modes[cm.id].flags & MODE_INTERLACED)) {
sl_en_fpga = 1;
sl_mode_fpga = 0;
} else {
sl_en_fpga = 0;
}
IOWR_ALTERA_AVALON_PIO_DATA(PIO_2_BASE, (cm.linemult<<30) | (cm.cc.l3_mode<<28) | (cm.cc.h_mask)<<22 | (video_modes[cm.id].h_active<<10) | video_modes[cm.id].h_backporch);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, ((!!cm.cc.sl_mode)<<31) | (cm.cc.sl_mode > 0 ? (cm.cc.sl_mode-1)<<30 : 0) | (slid_target<<29) | (cm.cc.sl_str<<25) | (cm.cc.v_mask<<19) | (video_modes[cm.id].v_active<<7) | video_modes[cm.id].v_backporch);
IOWR_ALTERA_AVALON_PIO_DATA(PIO_3_BASE, (sl_en_fpga<<31) | (sl_mode_fpga<<30) | (slid_target<<29) | (cm.cc.sl_str<<25) | (cm.cc.v_mask<<19) | (video_modes[cm.id].v_active<<7) | video_modes[cm.id].v_backporch);
}
// Configure TVP7002 and scan converter logic based on the video mode
@ -787,7 +326,6 @@ void program_mode()
data2 = tvp_readreg(TVP_VSINWIDTH);
printf("Hswidth: %u Vswidth: %u Macrovision: %u\n", (unsigned)data1, (unsigned)(data2 & 0x1F), (unsigned)cm.macrovis);
//TODO: rewrite with strncpy to reduce code size
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));
//strncpy(row1, avinput_str[cm.avinput], LCD_ROW_LEN+1);
@ -919,7 +457,7 @@ int main()
if (init_stat >= 0) {
printf("### DIY VIDEO DIGITIZER / SCANCONVERTER INIT OK ###\n\n");
sniprintf(row1, LCD_ROW_LEN+1, "OSSC fw. %u.%.2u", fw_ver_major, fw_ver_minor);
sniprintf(row1, LCD_ROW_LEN+1, "OSSC fw. %u.%.2u", FW_VER_MAJOR, FW_VER_MINOR);
#ifndef DEBUG
strncpy(row2, "2014-2016 marqs", LCD_ROW_LEN+1);
#else

View File

@ -0,0 +1,71 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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/>.
//
#ifndef AV_CONTROLLER_H_
#define AV_CONTROLLER_H_
#include "avconfig.h"
static const char *avinput_str[] = { "-", "AV1: RGBS", "AV1: RGsB", "AV1: YPbPr", "AV2: YPbPr", "AV2: RGsB", "AV3: RGBHV", "AV3: RGBS", "AV3: RGsB", "AV3: YPbPr" };
typedef enum {
AV_KEEP = 0,
AV1_RGBs = 1,
AV1_RGsB = 2,
AV1_YPBPR = 3,
AV2_YPBPR = 4,
AV2_RGsB = 5,
AV3_RGBHV = 6,
AV3_RGBs = 7,
AV3_RGsB = 8,
AV3_YPBPR = 9
} avinput_t;
// In reverse order of importance
typedef enum {
NO_CHANGE = 0,
INFO_CHANGE = 1,
MODE_CHANGE = 2,
TX_MODE_CHANGE = 3,
ACTIVITY_CHANGE = 4
} status_t;
typedef enum {
TX_HDMI = 0,
TX_DVI = 1
} tx_mode_t;
//TODO: transform binary values into flags
typedef struct {
alt_u32 totlines;
alt_u32 clkcnt;
alt_u8 progressive;
alt_u8 macrovis;
alt_8 id;
alt_u8 sync_active;
alt_u8 linemult;
avinput_t avinput;
// Current configuration
avconfig_t cc;
} avmode_t;
inline void lcd_write_menu();
inline void lcd_write_status();
#endif

View File

@ -0,0 +1,47 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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 <string.h>
#include "avconfig.h"
#include "tvp7002.h"
#define DEFAULT_PRE_COAST 1
#define DEFAULT_POST_COAST 0
#define DEFAULT_SAMPLER_PHASE 16
#define DEFAULT_SYNC_VTH 11
// Target configuration
avconfig_t tc;
// Default configuration
const avconfig_t tc_default = {
.sampler_phase = DEFAULT_SAMPLER_PHASE,
.sync_vth = DEFAULT_SYNC_VTH,
.vsync_thold = DEFAULT_VSYNC_THOLD,
.en_alc = 1,
.pre_coast = DEFAULT_PRE_COAST,
.post_coast = DEFAULT_POST_COAST,
};
int set_default_avconfig()
{
memcpy(&tc, &tc_default, sizeof(avconfig_t));
return 0;
}

View File

@ -0,0 +1,62 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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/>.
//
#ifndef AVCONFIG_H_
#define AVCONFIG_H_
#include "alt_types.h"
#define SCANLINESTR_MAX 15
#define HV_MASK_MAX 63
#define VIDEO_LPF_MAX 5
#define SAMPLER_PHASE_MAX 31
#define SYNC_VTH_MAX 31
#define VSYNC_THOLD_MIN 10
#define VSYNC_THOLD_MAX 200
#define PLL_COAST_MAX 5
#define SL_MODE_MAX 2
#define SL_TYPE_MAX 1
#define LM_MODE_MAX 1
typedef struct {
alt_u8 sl_mode;
alt_u8 sl_type;
alt_u8 sl_str;
alt_u8 sl_id;
alt_u8 linemult_target;
alt_u8 l3_mode;
alt_u8 h_mask;
alt_u8 v_mask;
alt_u8 tx_mode;
alt_u8 s480p_mode;
alt_u8 sampler_phase;
alt_u8 ypbpr_cs;
alt_u8 sync_vth;
alt_u8 vsync_thold;
alt_u8 sync_lpf;
alt_u8 video_lpf;
alt_u8 en_alc;
alt_u8 pre_coast;
alt_u8 post_coast;
} avconfig_t;
int set_default_avconfig();
#endif

View File

@ -0,0 +1,148 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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 <string.h>
#include <unistd.h>
#include "alt_types.h"
#include "sysconfig.h"
#include "controls.h"
#include "menu.h"
#include "av_controller.h"
#include "video_modes.h"
#include "lcd.h"
#include "altera_avalon_pio_regs.h"
static const char *rc_keydesc[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "MENU", "OK", "BACK", "UP", "DOWN", "LEFT", "RIGHT", "INFO", "LCD_BACKLIGHT", "SCANLINE_MODE", "SCANLINE_TYPE", "SCANLINE_INT+", "SCANLINE_INT-", "LINEMULT_MODE"};
alt_u16 rc_keymap[REMOTE_MAX_KEYS] = {0x3E29, 0x3EA9, 0x3E69, 0x3EE9, 0x3E19, 0x3E99, 0x3E59, 0x3ED9, 0x3E39, 0x3EC9, 0x3E4D, 0x3E1D, 0x3EED, 0x3E2D, 0x3ECD, 0x3EAD, 0x3E6D, 0x3E65, 0x3E01, 0x1C48, 0x1C18, 0x1C50, 0x1CD0, 0x1CC8};
extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
extern const mode_data_t video_modes[];
extern avmode_t cm;
extern avconfig_t tc;
extern avinput_t target_mode;
extern alt_u8 menu_active;
alt_u32 remote_code;
alt_u8 remote_rpt, remote_rpt_prev;
alt_u32 btn_code, btn_code_prev;
void setup_rc()
{
int i, confirm;
alt_u32 remote_code_prev = 0;
for (i=0; i<REMOTE_MAX_KEYS; i++) {
strncpy(menu_row1, "Press", LCD_ROW_LEN+1);
strncpy(menu_row2, rc_keydesc[i], LCD_ROW_LEN+1);
lcd_write_menu();
confirm = 0;
while (1) {
remote_code = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (remote_code && (remote_code != remote_code_prev)) {
if (confirm == 0) {
rc_keymap[i] = remote_code;
strncpy(menu_row1, "Confirm", LCD_ROW_LEN+1);
lcd_write_menu();
confirm = 1;
} else {
if (remote_code == rc_keymap[i]) {
confirm = 2;
} else {
strncpy(menu_row1, "Mismatch, retry", LCD_ROW_LEN+1);
lcd_write_menu();
confirm = 0;
}
}
}
remote_code_prev = remote_code;
if (confirm == 2)
break;
usleep(WAITLOOP_SLEEP_US);
}
}
}
void parse_control()
{
int i;
if (remote_code)
printf("RCODE: 0x%.4x, %u\n", remote_code, remote_rpt);
if (btn_code_prev == 0 && btn_code != 0)
printf("BCODE: 0x%.2x\n", btn_code>>16);
for (i = RC_BTN1; i < REMOTE_MAX_KEYS; i++) {
if (remote_code == rc_keymap[i])
break;
if (i == REMOTE_MAX_KEYS - 1)
goto Button_Check;
}
switch (i) {
case RC_BTN1: target_mode = AV1_RGBs; break;
case RC_BTN4: target_mode = AV1_RGsB; break;
case RC_BTN7: target_mode = AV1_YPBPR; break;
case RC_BTN2: target_mode = AV2_YPBPR; break;
case RC_BTN5: target_mode = AV2_RGsB; break;
case RC_BTN3: target_mode = AV3_RGBHV; break;
case RC_BTN6: target_mode = AV3_RGBs; break;
case RC_BTN9: target_mode = AV3_RGsB; break;
case RC_BTN0: target_mode = AV3_YPBPR; break;
case RC_MENU:
menu_active = !menu_active;
if (menu_active)
display_menu(1);
else
lcd_write_status();
break;
case RC_INFO:
sniprintf(menu_row1, LCD_ROW_LEN+1, "VMod: %s", video_modes[cm.id].name);
sniprintf(menu_row2, LCD_ROW_LEN+1, "LO: %u VSM: %u", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, (IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) >> 16) & 0x3);
lcd_write_menu();
printf("Mod: %s\n", video_modes[cm.id].name);
printf("Lines: %u M: %u\n", IORD_ALTERA_AVALON_PIO_DATA(PIO_4_BASE) & 0xffff, cm.macrovis);
break;
case RC_LCDBL:
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) ^ (1<<1)));
break;
case RC_SL_MODE: tc.sl_mode = (tc.sl_mode < SL_MODE_MAX) ? (tc.sl_mode + 1) : 0; break;
case RC_SL_TYPE: tc.sl_type = (tc.sl_type < SL_TYPE_MAX) ? (tc.sl_type + 1) : 0; break;
case RC_SL_MINUS: tc.sl_str = tc.sl_str ? (tc.sl_str - 1) : 0; break;
case RC_SL_PLUS: tc.sl_str = (tc.sl_str < SCANLINESTR_MAX) ? (tc.sl_str + 1) : SCANLINESTR_MAX; break;
case RC_LM_MODE: tc.linemult_target = (tc.linemult_target < LM_MODE_MAX) ? (tc.linemult_target + 1) : 0; break;
default: break;
}
Button_Check:
if (btn_code_prev == 0) {
if (btn_code & PB0_BIT)
target_mode = (cm.avinput == AV3_YPBPR) ? AV1_RGBs : (cm.avinput+1);
if (btn_code & PB1_BIT)
tc.sl_mode = tc.sl_mode < SL_MODE_MAX ? tc.sl_mode + 1 : 0;
}
}

View File

@ -0,0 +1,60 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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/>.
//
#ifndef CONTROLS_H_
#define CONTROLS_H_
#define RC_MASK 0x0000ffff
#define PB_MASK 0x00030000
#define PB0_BIT 0x00010000
#define PB1_BIT 0x00020000
typedef enum {
RC_BTN1 = 0,
RC_BTN2,
RC_BTN3,
RC_BTN4,
RC_BTN5,
RC_BTN6,
RC_BTN7,
RC_BTN8,
RC_BTN9,
RC_BTN0,
RC_MENU,
RC_OK,
RC_BACK,
RC_UP,
RC_DOWN,
RC_LEFT,
RC_RIGHT,
RC_INFO,
RC_LCDBL,
RC_SL_MODE,
RC_SL_TYPE,
RC_SL_PLUS,
RC_SL_MINUS,
RC_LM_MODE,
} rc_code_t;
#define REMOTE_MAX_KEYS RC_LM_MODE-RC_BTN1+1
void setup_rc();
void parse_control();
#endif

View File

@ -0,0 +1,202 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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 <string.h>
#include <unistd.h>
#include "firmware.h"
#include "sdcard.h"
#include "flash.h"
#include "sysconfig.h"
#include "controls.h"
#include "tvp7002.h"
#include "av_controller.h"
#include "lcd.h"
#include "ci_crc.h"
#include "altera_avalon_pio_regs.h"
extern char menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
static int check_fw_header(alt_u8 *databuf, fw_hdr *hdr)
{
alt_u32 crcval, tmp;
strncpy(hdr->fw_key, (char*)databuf, 4);
if (strncmp(hdr->fw_key, "OSSC", 4)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid image");
menu_row2[0] = '\0';
return 1;
}
hdr->version_major = databuf[4];
hdr->version_minor = databuf[5];
strncpy(hdr->version_suffix, (char*)(databuf+6), 8);
hdr->version_suffix[7] = 0;
memcpy(&tmp, databuf+14, 4);
hdr->hdr_len = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
memcpy(&tmp, databuf+18, 4);
hdr->data_len = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
memcpy(&tmp, databuf+22, 4);
hdr->data_crc = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
// Always at bytes [508-511]
memcpy(&tmp, databuf+508, 4);
hdr->hdr_crc = ALT_CI_NIOS_CUSTOM_INSTR_ENDIANCONVERTER_0(tmp);
if (hdr->hdr_len < 26 || hdr->hdr_len > 508) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid header");
menu_row2[0] = '\0';
return -1;
}
crcval = crcCI(databuf, hdr->hdr_len, 1);
if (crcval != hdr->hdr_crc) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid hdr CRC");
menu_row2[0] = '\0';
return -2;
}
return 0;
}
static int check_fw_image(alt_u32 offset, alt_u32 size, alt_u32 golden_crc, alt_u8 *tmpbuf)
{
alt_u32 crcval=0, i, bytes_to_read;
int retval;
for (i=0; i<size; i=i+SD_BUFFER_SIZE) {
bytes_to_read = ((size-i < SD_BUFFER_SIZE) ? (size-i) : SD_BUFFER_SIZE);
retval = read_sd_block(offset+i, bytes_to_read, tmpbuf);
if (retval != 0)
return -2;
crcval = crcCI(tmpbuf, bytes_to_read, (i==0));
}
if (crcval != golden_crc) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Invalid data CRC");
menu_row2[0] = '\0';
return -3;
}
return 0;
}
#ifdef DEBUG
int fw_update()
{
sniprintf(menu_row2, LCD_ROW_LEN+1, "Not implemented");
lcd_write_menu();
usleep(1000000);
return -1;
}
#else
int fw_update()
{
int retval, i;
int retries = FW_UPDATE_RETRIES;
alt_u8 databuf[SD_BUFFER_SIZE];
alt_u32 btn_vec;
alt_u32 bytes_to_rw;
fw_hdr fw_header;
retval = check_sdcard(databuf);
if (retval != 0)
goto failure;
retval = check_fw_header(databuf, &fw_header);
if (retval != 0)
goto failure;
sniprintf(menu_row1, LCD_ROW_LEN+1, "Validating data");
sniprintf(menu_row2, LCD_ROW_LEN+1, "%u bytes", (unsigned)fw_header.data_len);
lcd_write_menu();
retval = check_fw_image(512, fw_header.data_len, fw_header.data_crc, databuf);
if (retval != 0)
goto failure;
sniprintf(menu_row1, LCD_ROW_LEN+1, "%u.%.2u%s%s", fw_header.version_major, fw_header.version_minor, (fw_header.version_suffix[0] == 0) ? "" : "-", fw_header.version_suffix);
strncpy(menu_row2, "Update? 1=Y, 2=N", LCD_ROW_LEN+1);
lcd_write_menu();
while (1) {
btn_vec = IORD_ALTERA_AVALON_PIO_DATA(PIO_1_BASE) & RC_MASK;
if (btn_vec == rc_keymap[RC_BTN1]) {
break;
} else if (btn_vec == rc_keymap[RC_BTN2]) {
retval = 2;
return 1;
}
usleep(WAITLOOP_SLEEP_US);
}
//disable video output
tvp_disable_output();
IOWR_ALTERA_AVALON_PIO_DATA(PIO_0_BASE, (IORD_ALTERA_AVALON_PIO_DATA(PIO_0_BASE) | (1<<2)));
usleep(10000);
strncpy(menu_row1, "Updating FW", LCD_ROW_LEN+1);
update_init:
strncpy(menu_row2, "please wait...", LCD_ROW_LEN+1);
lcd_write_menu();
for (i=0; i<fw_header.data_len; i=i+SD_BUFFER_SIZE) {
bytes_to_rw = ((fw_header.data_len-i < SD_BUFFER_SIZE) ? (fw_header.data_len-i) : SD_BUFFER_SIZE);
retval = read_sd_block(512+i, bytes_to_rw, databuf);
if (retval != 0)
return -200;
retval = write_flash_page(databuf, ((bytes_to_rw < PAGESIZE) ? bytes_to_rw : PAGESIZE), (i/PAGESIZE));
if (retval != 0)
goto failure;
//TODO: support multiple page sizes
if (bytes_to_rw > PAGESIZE) {
retval = write_flash_page(databuf+PAGESIZE, (bytes_to_rw-PAGESIZE), (i/PAGESIZE)+1);
if (retval != 0)
goto failure;
}
}
strncpy(menu_row1, "Verifying flash", LCD_ROW_LEN+1);
strncpy(menu_row2, "please wait...", LCD_ROW_LEN+1);
lcd_write_menu();
retval = verify_flash(0, fw_header.data_len, fw_header.data_crc, databuf);
if (retval != 0)
goto failure;
return 0;
failure:
lcd_write_menu();
usleep(1000000);
// Probable rw error, retry update
if ((retval <= -200) && (retries > 0)) {
sniprintf(menu_row1, LCD_ROW_LEN+1, "Retrying update");
retries--;
goto update_init;
}
return -1;
}
#endif

View File

@ -0,0 +1,43 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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/>.
//
#ifndef FIRMWARE_H_
#define FIRMWARE_H_
#include "alt_types.h"
#define FW_VER_MAJOR 0
#define FW_VER_MINOR 70
#define FW_UPDATE_RETRIES 3
typedef struct {
char fw_key[4];
alt_u8 version_major;
alt_u8 version_minor;
char version_suffix[8];
alt_u32 hdr_len;
alt_u32 data_len;
alt_u32 data_crc;
alt_u32 hdr_crc;
} fw_hdr;
int fw_update();
#endif

View File

@ -19,18 +19,20 @@
#include <string.h>
#include "menu.h"
#include "av_controller.h"
#include "controls.h"
#include "lcd.h"
#include "tvp7002.h"
#define OPT_NOWRAP 0
#define OPT_WRAP 1
extern char row1[LCD_ROW_LEN+1], row2[LCD_ROW_LEN+1], menu_row1[LCD_ROW_LEN+1], menu_row2[LCD_ROW_LEN+1];
extern avconfig_t tc;
extern alt_u32 remote_code;
extern alt_u8 menu_active;
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
//TODO: move to separate source file(s)
extern alt_u16 rc_keymap[22];
#define lcd_write_menu() lcd_write((char*)&menu_row1, (char*)&menu_row2)
#define lcd_write_status() lcd_write((char*)&row1, (char*)&row2)
alt_u8 menu_active;
static const char *off_on_desc[] = { "Off", "On" };
static const char *video_lpf_desc[] = { "Auto", "Off", "95MHz (HDTV II)", "35MHz (HDTV I)", "16MHz (EDTV)", "9MHz (SDTV)" };
@ -39,7 +41,8 @@ static const char *s480p_mode_desc[] = { "Auto", "DTV 480p", "VGA 640x480" };
static const char *sync_lpf_desc[] = { "Off", "33MHz (min)", "10MHz (med)", "2.5MHz (max)" };
static const char *l3_mode_desc[] = { "Generic 16:9", "Generic 4:3", "320x240 optim.", "256x240 optim." };
static const char *tx_mode_desc[] = { "HDMI", "DVI" };
static const char *sl_mode_desc[] = { "Off", "Horizontal", "Vertical" };
static const char *sl_mode_desc[] = { "Off", "Auto", "Manual" };
static const char *sl_type_desc[] = { "Horizontal", "Vertical" };
static const char *sl_id_desc[] = { "Even", "Odd" };
static void sampler_phase_disp(alt_u8 v) { sniprintf(menu_row2, LCD_ROW_LEN+1, "%d deg", (v*1125)/100); }
@ -50,49 +53,50 @@ static void lines_disp(alt_u8 v) { sniprintf(menu_row2, LCD_ROW_LEN+1, "%u lines
static void pixels_disp(alt_u8 v) { sniprintf(menu_row2, LCD_ROW_LEN+1, "%u pixels", v); }
MENU(menu_vinputproc, P99_PROTECT({ \
{ "Video LPF", OPT_AVCONFIG_SELECTION, { .sel = { &tc.video_lpf, SETTING_ITEM(video_lpf_desc) } } },
{ "YPbPr in ColSpa", OPT_AVCONFIG_SELECTION, { .sel = { &tc.ypbpr_cs, SETTING_ITEM(ypbpr_cs_desc) } } },
{ "Auto lev. ctrl", OPT_AVCONFIG_SELECTION, { .sel = { &tc.en_alc, SETTING_ITEM(off_on_desc) } } },
{ "Video LPF", OPT_AVCONFIG_SELECTION, { .sel = { &tc.video_lpf, OPT_WRAP, SETTING_ITEM(video_lpf_desc) } } },
{ "YPbPr in ColSpa", OPT_AVCONFIG_SELECTION, { .sel = { &tc.ypbpr_cs, OPT_WRAP, SETTING_ITEM(ypbpr_cs_desc) } } },
{ "Auto lev. ctrl", OPT_AVCONFIG_SELECTION, { .sel = { &tc.en_alc, OPT_WRAP, SETTING_ITEM(off_on_desc) } } },
}))
MENU(menu_sampling, P99_PROTECT({ \
{ "Sampling phase", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.sampler_phase, 0, 31, sampler_phase_disp } } },
{ "480p in sampler", OPT_AVCONFIG_SELECTION, { .sel = { &tc.s480p_mode, SETTING_ITEM(s480p_mode_desc) } } },
{ "Sampling phase", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.sampler_phase, OPT_NOWRAP, 0, SAMPLER_PHASE_MAX, sampler_phase_disp } } },
{ "480p in sampler", OPT_AVCONFIG_SELECTION, { .sel = { &tc.s480p_mode, OPT_WRAP, SETTING_ITEM(s480p_mode_desc) } } },
//{ "Modeparam editor", OPT_SUBMENU, { .sub = NULL } },
}))
MENU(menu_sync, P99_PROTECT({ \
{ "Analog sync LPF", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sync_lpf, SETTING_ITEM(sync_lpf_desc) } } },
{ "Analog sync Vth", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.sync_vth, 0, 31, sync_vth_disp } } },
{ "Vsync threshold", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.vsync_thold, 10, 200, vsync_thold_disp } } },
{ "H-PLL Pre-Coast", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.pre_coast, 0, 5, lines_disp } } },
{ "H-PLL Post-Coast", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.post_coast, 0, 5, lines_disp } } },
{ "Analog sync LPF", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sync_lpf, OPT_WRAP, SETTING_ITEM(sync_lpf_desc) } } },
{ "Analog sync Vth", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.sync_vth, OPT_NOWRAP, 0, SYNC_VTH_MAX, sync_vth_disp } } },
{ "Vsync threshold", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.vsync_thold, OPT_NOWRAP, VSYNC_THOLD_MIN, VSYNC_THOLD_MAX, vsync_thold_disp } } },
{ "H-PLL Pre-Coast", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.pre_coast, OPT_NOWRAP, 0, PLL_COAST_MAX, lines_disp } } },
{ "H-PLL Post-Coast", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.post_coast, OPT_NOWRAP, 0, PLL_COAST_MAX, lines_disp } } },
}))
MENU(menu_output, P99_PROTECT({ \
{ "240p/288p lineX3", OPT_AVCONFIG_SELECTION, { .sel = { &tc.linemult_target, SETTING_ITEM(off_on_desc) } } },
{ "Linetriple mode", OPT_AVCONFIG_SELECTION, { .sel = { &tc.l3_mode, SETTING_ITEM(l3_mode_desc) } } },
{ "240p/288p lineX3", OPT_AVCONFIG_SELECTION, { .sel = { &tc.linemult_target, OPT_WRAP, SETTING_ITEM(off_on_desc) } } },
{ "Linetriple mode", OPT_AVCONFIG_SELECTION, { .sel = { &tc.l3_mode, OPT_WRAP, SETTING_ITEM(l3_mode_desc) } } },
//{ "Interlace passt.", OPT_AVCONFIG_SELECTION, { .sel = { &tc.s480p_mode, SETTING_ITEM(s480p_desc) } } },
{ "TX mode", OPT_AVCONFIG_SELECTION, { .sel = { &tc.tx_mode, SETTING_ITEM(tx_mode_desc) } } },
{ "TX mode", OPT_AVCONFIG_SELECTION, { .sel = { &tc.tx_mode, OPT_WRAP, SETTING_ITEM(tx_mode_desc) } } },
}))
MENU(menu_postproc, P99_PROTECT({ \
{ "Scanlines", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_mode, SETTING_ITEM(sl_mode_desc) } } },
{ "Scanline str.", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.sl_str, 0, 15, sl_str_disp } } },
{ "Scanline id.", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_id, SETTING_ITEM(sl_id_desc) } } },
{ "Horizontal mask", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.h_mask, 0, 63, pixels_disp } } },
{ "Vertical mask", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.v_mask, 0, 63, pixels_disp } } },
{ "Scanlines", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_mode, OPT_WRAP, SETTING_ITEM(sl_mode_desc) } } },
{ "Scanline str.", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.sl_str, OPT_NOWRAP, 0, SCANLINESTR_MAX, sl_str_disp } } },
{ "Scanline type", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_type, OPT_WRAP, SETTING_ITEM(sl_type_desc) } } },
{ "Scanline id.", OPT_AVCONFIG_SELECTION, { .sel = { &tc.sl_id, OPT_WRAP, SETTING_ITEM(sl_id_desc) } } },
{ "Horizontal mask", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.h_mask, OPT_NOWRAP, 0, HV_MASK_MAX, pixels_disp } } },
{ "Vertical mask", OPT_AVCONFIG_NUMVALUE, { .num = { &tc.v_mask, OPT_NOWRAP, 0, HV_MASK_MAX, pixels_disp } } },
}))
MENU(menu_main, P99_PROTECT({ \
{ "Video in proc", OPT_SUBMENU, { .sub = &menu_vinputproc } }, \
{ "Sampling opt.", OPT_SUBMENU, { .sub = &menu_sampling } }, \
{ "Sync opt.", OPT_SUBMENU, { .sub = &menu_sync } }, \
{ "Output opt.", OPT_SUBMENU, { .sub = &menu_output } }, \
{ "Post-proc.", OPT_SUBMENU, { .sub = &menu_postproc } }, \
{ "Fw. update", OPT_FUNC_CALL, { .fun = { fw_update, "OK - pls restart" } } }, \
{ "Reset settings", OPT_FUNC_CALL, { .fun = { set_default_avconfig, "Reset done" } } }, \
{ "Save settings", OPT_FUNC_CALL, { .fun = { write_userdata, "Saved" } } }, \
{ "Video in proc >", OPT_SUBMENU, { .sub = &menu_vinputproc } }, \
{ "Sampling opt. >", OPT_SUBMENU, { .sub = &menu_sampling } }, \
{ "Sync opt. >", OPT_SUBMENU, { .sub = &menu_sync } }, \
{ "Output opt. >", OPT_SUBMENU, { .sub = &menu_output } }, \
{ "Post-proc. >", OPT_SUBMENU, { .sub = &menu_postproc } }, \
{ "Fw. update >", OPT_FUNC_CALL, { .fun = { fw_update, "OK - pls restart" } } }, \
{ "<Reset settings>", OPT_FUNC_CALL, { .fun = { set_default_avconfig, "Reset done" } } }, \
{ "<Save settings >", OPT_FUNC_CALL, { .fun = { write_userdata, "Saved" } } }, \
}))
// Max 2 levels currently
@ -102,27 +106,23 @@ alt_u8 navlvl = 0;
void display_menu(alt_u8 forcedisp)
{
menucode_id code;
int retval = 0;
menucode_id code = NO_ACTION;
menuitem_type type;
alt_u8 *val, val_wrap, val_min, val_max;
int i, retval = 0;
if (remote_code == rc_keymap[RC_UP])
code = PREV_PAGE;
else if (remote_code == rc_keymap[RC_DOWN])
code = NEXT_PAGE;
else if (remote_code == rc_keymap[RC_RIGHT])
code = VAL_PLUS;
else if (remote_code == rc_keymap[RC_LEFT])
code = VAL_MINUS;
else if (remote_code == rc_keymap[RC_OK])
code = OPT_SELECT;
else if (remote_code == rc_keymap[RC_BACK])
code = PREV_MENU;
else
code = NO_ACTION;
for (i=RC_OK; i < RC_INFO; i++) {
if (remote_code == rc_keymap[i]) {
code = i;
break;
}
}
if (!forcedisp && (code == NO_ACTION))
return;
type = navi[navlvl].m->items[navi[navlvl].mp].type;
// Parse menu control
switch (code) {
case PREV_PAGE:
@ -156,31 +156,17 @@ void display_menu(alt_u8 forcedisp)
}
break;
case VAL_MINUS:
switch (navi[navlvl].m->items[navi[navlvl].mp].type) {
case OPT_AVCONFIG_SELECTION:
if (*(navi[navlvl].m->items[navi[navlvl].mp].sel.data) > 0)
*(navi[navlvl].m->items[navi[navlvl].mp].sel.data) = *(navi[navlvl].m->items[navi[navlvl].mp].sel.data) - 1;
break;
case OPT_AVCONFIG_NUMVALUE:
if (*(navi[navlvl].m->items[navi[navlvl].mp].num.data) > navi[navlvl].m->items[navi[navlvl].mp].num.min)
*(navi[navlvl].m->items[navi[navlvl].mp].num.data) = *(navi[navlvl].m->items[navi[navlvl].mp].num.data) - 1;
break;
default:
break;
}
break;
case VAL_PLUS:
switch (navi[navlvl].m->items[navi[navlvl].mp].type) {
case OPT_AVCONFIG_SELECTION:
if (*(navi[navlvl].m->items[navi[navlvl].mp].sel.data) < navi[navlvl].m->items[navi[navlvl].mp].sel.num_settings-1)
*(navi[navlvl].m->items[navi[navlvl].mp].sel.data) = *(navi[navlvl].m->items[navi[navlvl].mp].sel.data) + 1;
break;
case OPT_AVCONFIG_NUMVALUE:
if (*(navi[navlvl].m->items[navi[navlvl].mp].num.data) < navi[navlvl].m->items[navi[navlvl].mp].num.max)
*(navi[navlvl].m->items[navi[navlvl].mp].num.data) = *(navi[navlvl].m->items[navi[navlvl].mp].num.data) + 1;
break;
default:
break;
if ((type == OPT_AVCONFIG_SELECTION) || (type == OPT_AVCONFIG_NUMVALUE)) {
val = navi[navlvl].m->items[navi[navlvl].mp].sel.data;
val_wrap = navi[navlvl].m->items[navi[navlvl].mp].sel.wrap_cfg;
val_min = navi[navlvl].m->items[navi[navlvl].mp].sel.min;
val_max = navi[navlvl].m->items[navi[navlvl].mp].sel.max;
if (code == VAL_MINUS)
*val = (*val > val_min) ? (*val-1) : (val_wrap ? val_max : val_min);
else
*val = (*val < val_max) ? (*val+1) : (val_wrap ? val_min : val_max);
}
break;
default:
@ -188,21 +174,19 @@ void display_menu(alt_u8 forcedisp)
}
// Generate menu text
type = navi[navlvl].m->items[navi[navlvl].mp].type;
strncpy(menu_row1, navi[navlvl].m->items[navi[navlvl].mp].name, LCD_ROW_LEN+1);
switch (navi[navlvl].m->items[navi[navlvl].mp].type) {
case OPT_AVCONFIG_SELECTION:
strncpy(menu_row1, navi[navlvl].m->items[navi[navlvl].mp].name, LCD_ROW_LEN+1);
strncpy(menu_row2, navi[navlvl].m->items[navi[navlvl].mp].sel.setting_str[*(navi[navlvl].m->items[navi[navlvl].mp].sel.data)], LCD_ROW_LEN+1);
break;
case OPT_AVCONFIG_NUMVALUE:
strncpy(menu_row1, navi[navlvl].m->items[navi[navlvl].mp].name, LCD_ROW_LEN+1);
navi[navlvl].m->items[navi[navlvl].mp].num.f(*(navi[navlvl].m->items[navi[navlvl].mp].num.data));
break;
case OPT_SUBMENU:
sniprintf(menu_row1, LCD_ROW_LEN+1, "%s >", navi[navlvl].m->items[navi[navlvl].mp].name);
menu_row2[0] = 0;
break;
case OPT_FUNC_CALL:
sniprintf(menu_row1, LCD_ROW_LEN+1, "<%s>", navi[navlvl].m->items[navi[navlvl].mp].name);
if (code == OPT_SELECT)
sniprintf(menu_row2, LCD_ROW_LEN+1, "%s", (retval==0) ? navi[navlvl].m->items[navi[navlvl].mp].fun.text_success : "Error");
else

View File

@ -17,11 +17,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include "alt_types.h"
#ifndef MENU_H_
#define MENU_H_
#include "alt_types.h"
#include "controls.h"
typedef enum {
OPT_AVCONFIG_SELECTION,
OPT_AVCONFIG_NUMVALUE,
@ -35,12 +36,15 @@ typedef void (*disp_func)(alt_u8);
typedef struct {
alt_u8 *data;
alt_u8 num_settings;
alt_u8 wrap_cfg;
alt_u8 min;
alt_u8 max;
const char **setting_str;
} opt_avconfig_selection;
typedef struct {
alt_u8 *data;
alt_u8 wrap_cfg;
alt_u8 min;
alt_u8 max;
disp_func f;
@ -73,81 +77,30 @@ typedef struct {
menu_t *menu;
} opt_submenu;
#define SETTING_ITEM(x) sizeof(x)/sizeof(char*), x
#define SETTING_ITEM(x) 0, sizeof(x)/sizeof(char*)-1, x
#define MENU(X, Y) menuitem_t X##_items[] = Y; const menu_t X = { sizeof(X##_items)/sizeof(menuitem_t), X##_items };
#define P99_PROTECT(...) __VA_ARGS__
#define MAX_MENU_LEVELS 4
typedef enum {
NO_ACTION = 0,
NEXT_PAGE = 1,
PREV_PAGE = 2,
VAL_PLUS = 3,
VAL_MINUS = 4,
OPT_SELECT = 5,
PREV_MENU = 6,
} menucode_id;
NO_ACTION = 0,
OPT_SELECT = RC_OK,
PREV_MENU = RC_BACK,
PREV_PAGE = RC_UP,
NEXT_PAGE = RC_DOWN,
VAL_MINUS = RC_LEFT,
VAL_PLUS = RC_RIGHT,
} menucode_id; // order must be consequential with rc_code_t
typedef struct {
const menu_t *m;
alt_u8 mp;
} menunavi;
void display_menu(alt_u8 forcedisp);
//TODO: move all below to separate header(s)
#define SCANLINESTR_MAX 15
#define VIDEO_LPF_MAX 5
typedef struct {
alt_u8 sl_mode;
alt_u8 sl_str;
alt_u8 sl_id;
alt_u8 linemult_target;
alt_u8 l3_mode;
alt_u8 h_mask;
alt_u8 v_mask;
alt_u8 tx_mode;
alt_u8 s480p_mode;
alt_u8 sampler_phase;
alt_u8 ypbpr_cs;
alt_u8 sync_vth;
alt_u8 vsync_thold;
alt_u8 sync_lpf;
alt_u8 video_lpf;
alt_u8 en_alc;
alt_u8 pre_coast;
alt_u8 post_coast;
} avconfig_t;
typedef enum {
RC_BTN1 = 0,
RC_BTN2,
RC_BTN3,
RC_BTN4,
RC_BTN5,
RC_BTN6,
RC_BTN7,
RC_BTN8,
RC_BTN9,
RC_BTN0,
RC_MENU,
RC_OK,
RC_BACK,
RC_UP,
RC_DOWN,
RC_LEFT,
RC_RIGHT,
RC_INFO,
RC_LCDBL,
RC_SL_TGL,
RC_SL_PLUS,
RC_SL_MINUS,
} rc_code_t;
int write_userdata();
int fw_update();
int set_default_avconfig();
#endif

View File

@ -31,4 +31,6 @@
//#define printf alt_printf
#endif
#define WAITLOOP_SLEEP_US 10000
#endif /* SYSCONFIG_H_ */

View File

@ -0,0 +1,131 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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 <string.h>
#include "userdata.h"
#include "sysconfig.h"
#include "flash.h"
#include "firmware.h"
#include "controls.h"
#include "av_controller.h"
extern alt_u16 rc_keymap[REMOTE_MAX_KEYS];
extern avconfig_t tc;
int write_userdata()
{
alt_u8 databuf[PAGESIZE];
int retval;
strncpy((char*)databuf, "USRDATA", 8);
databuf[8] = FW_VER_MAJOR;
databuf[9] = FW_VER_MINOR;
databuf[10] = 2;
retval = write_flash_page(databuf, USERDATA_HDR_SIZE, (USERDATA_OFFSET/PAGESIZE));
if (retval != 0) {
return -1;
}
databuf[0] = UDE_REMOTE_MAP;
databuf[1] = 4+sizeof(rc_keymap);
databuf[2] = databuf[3] = 0; //padding
memcpy(databuf+4, rc_keymap, sizeof(rc_keymap));
retval = write_flash_page(databuf, databuf[1], (USERDATA_OFFSET/PAGESIZE)+1);
if (retval != 0) {
return -1;
}
databuf[0] = UDE_AVCONFIG;
databuf[1] = 4+sizeof(avconfig_t);
databuf[2] = databuf[3] = 0; //padding
memcpy(databuf+4, &tc, sizeof(avconfig_t));
retval = write_flash_page(databuf, databuf[1], (USERDATA_OFFSET/PAGESIZE)+2);
if (retval != 0) {
return -1;
}
return 0;
}
int read_userdata()
{
int retval, i;
alt_u8 databuf[PAGESIZE];
userdata_hdr udhdr;
userdata_entry udentry;
retval = read_flash(USERDATA_OFFSET, USERDATA_HDR_SIZE, databuf);
if (retval != 0) {
printf("Flash read error\n");
return -1;
}
strncpy(udhdr.userdata_key, (char*)databuf, 8);
if (strncmp(udhdr.userdata_key, "USRDATA", 8)) {
printf("No userdata found on flash\n");
return 1;
}
udhdr.version_major = databuf[8];
udhdr.version_minor = databuf[9];
udhdr.num_entries = databuf[10];
//TODO: check version compatibility
printf("Userdata: v%u.%.2u, %u entries\n", udhdr.version_major, udhdr.version_minor, udhdr.num_entries);
for (i=0; i<udhdr.num_entries; i++) {
retval = read_flash(USERDATA_OFFSET+((i+1)*PAGESIZE), USERDATA_ENTRY_HDR_SIZE, databuf);
if (retval != 0) {
printf("Flash read error\n");
return -1;
}
udentry.type = databuf[0];
udentry.entry_len = databuf[1];
retval = read_flash(USERDATA_OFFSET+((i+1)*PAGESIZE), udentry.entry_len, databuf);
if (retval != 0) {
printf("Flash read error\n");
return -1;
}
switch (udentry.type) {
case UDE_REMOTE_MAP:
if ((udentry.entry_len-4) == sizeof(rc_keymap)) {
memcpy(rc_keymap, databuf+4, sizeof(rc_keymap));
printf("RC data read (%u bytes)\n", sizeof(rc_keymap));
}
break;
case UDE_AVCONFIG:
if ((udentry.entry_len-4) == sizeof(avconfig_t)) {
memcpy(&tc, databuf+4, sizeof(avconfig_t));
printf("Avconfig data read (%u bytes)\n", sizeof(avconfig_t));
}
break;
default:
printf("Unknown userdata entry\n");
break;
}
}
return 0;
}

View File

@ -0,0 +1,47 @@
//
// Copyright (C) 2015-2016 Markus Hiienkari <mhiienka@niksula.hut.fi>
//
// 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/>.
//
#ifndef USERDATA_H_
#define USERDATA_H_
#include "alt_types.h"
#define USERDATA_HDR_SIZE 11
typedef struct {
char userdata_key[8];
alt_u8 version_major;
alt_u8 version_minor;
alt_u8 num_entries;
} userdata_hdr;
#define USERDATA_ENTRY_HDR_SIZE 2
typedef struct {
alt_u8 type;
alt_u8 entry_len;
} userdata_entry;
typedef enum {
UDE_REMOTE_MAP = 0,
UDE_AVCONFIG,
} userdata_entry_type;
#endif
int write_userdata();
int read_userdata();

View File

@ -17,9 +17,12 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
#include <unistd.h>
#include <string.h>
#include "lcd.h"
#include "alt_types.h"
#include "altera_avalon_pio_regs.h"
#include "i2c_opencores.h"
#define LCD_CMD 0x00
#define LCD_DATA 0x40

View File

@ -241,7 +241,7 @@ void tvp_sel_clk(alt_u8 refclk)
}
}
void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc)
void tvp_sel_csc(const ypbpr_to_rgb_csc_t *csc)
{
tvp_writereg(TVP_CSC1HI, (csc->G_Y >> 8));
tvp_writereg(TVP_CSC1LO, (csc->G_Y & 0xff));

View File

@ -79,7 +79,7 @@ void tvp_setup_hpll(alt_u16 h_samplerate, alt_u16 v_lines, alt_u8 hz, alt_u8 pll
void tvp_sel_clk(alt_u8 refclk);
void tvp_sel_csc(ypbpr_to_rgb_csc_t *csc);
void tvp_sel_csc(const ypbpr_to_rgb_csc_t *csc);
void tvp_set_lpf(alt_u8 val);