microvfd.c
来自「ESS3890+SL原代码(1*16内存)」· C语言 代码 · 共 1,859 行 · 第 1/3 页
C
1,859 行
/* Copyright 1997, ESS Technology, Inc. *//* SCCSID @(#)microvfd.c 4.11.1.2 04/12/05 *//* * $Log$ */#include "vcxi.h"#include "const.h"#include "timedef.h"#include "util.h"#include "micro.h"#include "panel.h"#include "ir.h"#include "vfdshare.h"#include "keydef.h"#include "play.h"#ifdef SCR_SAVER#include "scrsaver.h"#endif/************************************************************************ * Shadows are for VFD icons. * * * * Size is determined by the number of grids (G) and segments (P). * * Our internal representation may be different from actual hardware * * especially when we have more than 16 segments (P). In any case, * * the number of "shadows" is the same as number of elements in * * VFD_refresh_table. * ************************************************************************/#ifdef HOST_SLAVE#define SHADOW_LENGTH 1#else#define SHADOW_LENGTH T_VFD_refresh_tbl_SZ#endif/* * Macro to define number of usec (Don't be fractional! Don't be more * than half second!) */#define RETURN_BEFORE_SCHEDULED_TIME if (!VFD_is_scheduled_time()) return;#define SCH_DELAY_BETWEEN_DATA VFD_schedule_state_change(DELAY_BETWEEN_DATA)#define SCH_DELAY_AFTER_DATA VFD_schedule_state_change(DELAY_AFTER_DATA)/************************************************************************ * Macros specific to different VFD drivers. * ************************************************************************/#if (D16311 || D16312)#define KEY_LENGTH 3#define VFD_DUTY_CYCLE 0x8c#define VFD_ADDRESS_INC 0x40#define VFD_ADDRESS_FIX 0x44#define VFD_ADDRESS_MASK 0xc0#define VFD_READ_KEY 0x42#define VFD_READ_SW 0x43#endif /* D16311 || D16312 */#ifdef DSTC6311#define KEY_LENGTH 6#define VFD_DUTY_CYCLE 0x8c#define VFD_ADDRESS_INC 0x40#define VFD_ADDRESS_FIX 0x44#define VFD_ADDRESS_MASK 0xc0#define VFD_READ_KEY 0x42#define VFD_READ_SW 0x43#endif /* DSTC6311 */#ifdef MN12510/* By Liang Weihua */#define KEY_LENGTH 6#define VFD_ADDRESS_MASK 0x40#define VFD_READ_KEY 0x80#if 0 /* philips (Andy may need)*/#define KEY_LENGTH 8#define VFD_ADDRESS_MASK 0x40#define VFD_READ_KEY 0x80#endif#endif /* MN12510 */#ifdef BU2872#define KEY_LENGTH 3#define VFD_ADDRESS_MASK 0x80#define VFD_READ_KEY 0xa0#endif /* BU2872 */#ifdef HT1621#define KEY_LENGTH 3#define CLR_LCD_CS CLEAR_VFD_STROBE /* CLEAR_AUX6 */#define SET_LCD_CS SET_VFD_STROBE /* SET_AUX6 */#define CLR_LCD_WR CLEAR_VFD_CLK /* CLEAR_AUX7 */#define SET_LCD_WR SET_VFD_CLK /* SET_AUX7 */#define CLR_LCD_DATA CLEAR_VFD_DATA /* CLEAR_AUX5 */#define SET_LCD_DATA SET_VFD_DATA /* SET_AUX5 */#define LCD_SYS_EN 0x01 /*turn on system oscillator*/#define LCD_LCD_ON 0x03 /*trun on LCD bias generator*/#define LCD_RC_256 0x18 /*on-chip RC oscillator*/#define LCD_IRQ_DIS 0x80 /*disable IRQ output*/#define LCD_BIAS 0x29 /*4COM & LCD 1/3 bias option */#define LCD_TIMER_DIS 0x008 /*disable time base output*/#define LCD_WDT_DIS 0x00a /*disable WDT time_out flag output*/#define LCD_TONE_OFF 0x010 /*turn off tone output*/#define LCD_TONE_ON 0x012 /*turn on tone output*/#define LCD_NORMAL 0x1c6 /*normal mode*/#define LCD_COMMAND 0x04 /*write command id to 1621*/#define LCD_WRITE 0x05 /*write date/addr id to 1621*/#endif HT1621/************************************************************************ * Macros relate to remote control ASSIGN_SYSCODE moved to ir.c ************************************************************************/#define CLEAR_REMOTE (codeIR &= ~0x100)#ifdef IR_PHILIPS/* Philips IR only has 6 bits */#define REMOTE_KEY (char)(codeIR & 0x3f)#endif /* IR_PHILIPS */#if (IR_NEC || IR_SANYO)/* NEC/SANYO IR have 8 bits */#define REMOTE_KEY (char)(codeIR & 0xff)#endif /* IR_NEC || IR_SANYO */#ifdef PLUS5_KEY int sign_plus5 = 0;#endif PLUS5_KEY/************************************************************************ * Global functions. * ************************************************************************/void initMicroObject(void);int get_keycode(int mode);void microEngine(void);void VFD_clear_lite_anode(unsigned short, int);#ifndef HOST_SLAVE /************************************************************************ * Private functions. * ************************************************************************/PRIVATE void flashCalendar(void);PRIVATE int micro_convert_irkey(int);PRIVATE void VFD_clearSegment(int, unsigned short *);PRIVATE void VFD_flashCalendar(void);PRIVATE void VFD_objectReadByte(void);PRIVATE void VFD_objectSendByte(int);PRIVATE void VFD_parseKey(void);PRIVATE void VFD_searchKey(void);PRIVATE void VFD_set_char(unsigned short *, unsigned int);PRIVATE void VFD_strobeSendByte(int, int);PRIVATE void VFD_schedule_state_change(unsigned int);PRIVATE int VFD_is_scheduled_time(void);PRIVATE void VFD_state_init(void);PRIVATE void VFD_state_scan_key_0(void);PRIVATE void VFD_state_scan_key_1(void);PRIVATE void VFD_state_scan_key_2(void);PRIVATE void VFD_state_scan_key_3(void);PRIVATE void VFD_state_scan_key_4(void);PRIVATE void VFD_state_scan_key_5(void);PRIVATE void VFD_state_refresh_0(void);PRIVATE void VFD_state_refresh_1(void);PRIVATE void VFD_state_refresh_2(void);PRIVATE void VFD_state_refresh_3(void);PRIVATE void VFD_state_refresh_4(void);PRIVATE void VFD_state_refresh_5(void);#ifdef HT1621PRIVATE void LCD_objectSendcommand(int command);PRIVATE void LCD_objectSenddata(int address,int data);PRIVATE void VFD_schedule_state_change(unsigned int);PRIVATE int VFD_is_scheduled_time(void);/*void Fill_Seg(int seg);*/void lcd_delay();#endif HT1621/************************************************************************ * Local variables * ************************************************************************/PRIVATE struct { unsigned int FlashTime;} ObjectTime;/* * There is a stack to keep track which "G/P" byte needs to be updated. * G/P combinations are defined as ANODE_G1L, ANODE_G1H etc in vfdshare.h. */PRIVATE int VFDptr;PRIVATE char VFD_refresh_stack[SHADOW_LENGTH]; #define POPVFD VFD_refresh_stack[--VFDptr]/* * ShadowRam keeps track of the value that needs to be set for the * corresponding G/P combination. */PRIVATE unsigned char ShadowRam[SHADOW_LENGTH];PRIVATE int RefreshCounter;PRIVATE char DataLength;/* * Keep track of scheduled delay. */PRIVATE int VFD_scheduled_timer2;PRIVATE unsigned int VFD_scheduled_realtime;PRIVATE PFV VFD_next_state = VFD_state_init;#endif /* HOST_SLAVE *//************************************************************************ * Global variables * ************************************************************************/int EnableFlashing=0;int FlashingCalendar=0;int key0 = NO_KEY;#define put_keycode(key) (key0 = key) int last_voice_clock;#ifdef HOST_SLAVEextern Slave_Message_Dispatch();#define CUSTOM#else#define CUSTOM static#endifCUSTOM struct { char KeyBuffer[KEY_LENGTH]; char FireKey; unsigned short Digit10Key;#ifdef PLUS5_KEY int Digit5Key;#endif} ObjectKey;/* * Schedule an event in the future. Some VFD controller can't take command * too fast, so we need to give it some breathing room. This routine will * not sit there and hog CPU time! * * Input: * delay: In timer ticks (CPUCLK equals to 10us) assuming it is powered * up. */#ifndef HOST_SLAVEPRIVATE void VFD_schedule_state_change(delay)unsigned int delay;{ if (IS_POWER_DOWN) delay /= IDLEFACTOR; VFD_scheduled_timer2 = UTIL_set_timer2_end(delay, &VFD_scheduled_realtime);}/* * Wait for a scheduled time to arrive. * * Return: 1: time is up. * 0: not yet. */PRIVATE int VFD_is_scheduled_time(){ return(UTIL_reached_timer2_end(VFD_scheduled_timer2, VFD_scheduled_realtime));}#endif /*HOST_SLAVE*/int microKeyPending(){ if ((REMOTE_VALID) || (key0 != NO_KEY)) return (1); return (0);}void initMicroObject(void){#ifndef HOST_SLAVE int i; ObjectTime.FlashTime = glbTimer + HALF_SECOND; VFD_STROBE_INACTIVE; SET_VFD_CLK; SET_VFD_DATA; VFD_blank_all();#endif }int get_keycode(int mode){ int return_key; return_key = key0; if(!mode)key0 = NO_KEY; return return_key;}int Time0;/*===========================================================================*/PRIVATE void VFD_parseKey(void){ int ignore_key, key; if (ObjectKey.FireKey != NO_KEY) { if ((glbTimer - Time0) < 30) return; Time0 = glbTimer;#ifdef SCR_SAVER if (scr_saver_state == SAVER_SHOW || scr_saver_state == SAVER_WAIT) { key_in = 1; process_scr_saver(); }#endif #ifdef PLUS5_KEY if (ObjectKey.FireKey == _KEY_PLUS_5) { sign_plus5 = 1; ObjectKey.Digit5Key += 5; ObjectKey.Digit5Key = preprocess_digit_key(ObjectKey.Digit5Key, &ignore_key,1); ObjectKey.FireKey = NO_KEY;#ifdef JD5PLUS5 ltsign=1; pre_timer=glbTimer+180;#endif } else#endif PLUS5_KEY if (ObjectKey.FireKey == 10) {#ifdef PLUS5_KEY sign_plus5 = 0;#endif PLUS5_KEY ObjectKey.Digit10Key += 10; ObjectKey.Digit10Key = preprocess_digit_key(ObjectKey.Digit10Key, &ignore_key,1); } else if (ObjectKey.FireKey <= 10) {#ifdef PLUS5_KEY if(sign_plus5 == 1) { ObjectKey.Digit5Key += ObjectKey.FireKey; ObjectKey.Digit5Key = preprocess_digit_key(ObjectKey.Digit5Key, &ignore_key,0);#ifdef JD5PLUS5 if(ltsign==1) ltsign = 0;#endif if (!ignore_key) put_keycode(ObjectKey.Digit5Key); ObjectKey.Digit5Key = 0; ObjectKey.Digit10Key = 0; sign_plus5 = 0; } else#endif PLUS5_KEY { ObjectKey.Digit10Key += ObjectKey.FireKey; ObjectKey.Digit10Key = preprocess_digit_key(ObjectKey.Digit10Key, &ignore_key,0); if (!ignore_key) put_keycode(ObjectKey.Digit10Key); ObjectKey.Digit10Key = 0; } } else { key = ObjectKey.FireKey | 0xff00; put_keycode(key); /* function key */ preprocess_function_key(key);#ifdef IR_PHILIPS key = NO_KEY; /* starts at 0xffxx.*/#endif /* IR_PHILIPS */ ObjectKey.Digit10Key = 0;#ifdef PLUS5_KEY sign_plus5 = 0; ObjectKey.Digit5Key = 0;#endif } /* according to Weihua, we should always clear the "Firekey" to * prevent duplicate key entries. */ ObjectKey.FireKey = NO_KEY; }}#ifndef HOST_SLAVE/* * Complement the calendar icon associated with FlashingCalendar. */PRIVATE void flashCalendar(){#if MAX_CALENDAR /* Calendar exists */ unsigned short anode; /* Data read from T_VFD_calendar_tbl */ /* * calendar_tbl is in xxxxyzzzzzzzz format where z is 1 hot while * xxxxy give the "ShadowRam" index. */ anode = T_VFD_calendar_tbl[FlashingCalendar]; VFD_clear_lite_anode(anode, 2);#endif /* Calendar exists */}#endif /*HOST_SLAVE*//* * This routine takes a G/P position and lite/clear the corresponding anode. * This routine will also carry out the old VFD_push function to save * another function call. * * Inputs: * anode: G/P position of the icon * lite: 0 - clear * 1 - lite * 2 - complement */void VFD_clear_lite_anode(anode, lite)unsigned short anode;int lite;{ unsigned int index, tmp; int i;#ifndef HOST_SLAVE index = anode >> 8;#ifdef HT1621#if defined(LCD_2DANCE)||defined(LCD_6DANCE) index = index;#else if(index == 0x0f) index = 16; else if(index == 0x1d) index = 17; else index = index/2;#endif#endif HT1621 tmp = anode; if (lite == 2) ShadowRam[index] ^= tmp; else { ShadowRam[index] &= ~tmp; if (lite) ShadowRam[index] |= tmp; } /* Search in reverse order because of locality */ for (i = VFDptr; i > 0; ) if (VFD_refresh_stack[--i] == index) return; VFD_refresh_stack[VFDptr++] = index;#endif /*HOST_SLAVE */}/* * If there is a wheel in VFD, this routine spins it. * * Input: * set: VFD_WHEEL_CLEAR_FAN clear all fans * VFD_WHEEL_SET_FAN set all fans * VFD_WHEEL_SPIN spin *//*#define INVERT_LITED_WHEEL*/void VFD_spin_wheel(set)int set;{ static int wheelpos = -1; unsigned short * ptr; int items; int i; if (T_VFD_wheel_SZ == 0) return; ptr = T_VFD_wheel; items = T_VFD_wheel_SZ / sizeof(unsigned short); if (set == VFD_WHEEL_SPIN) { wheelpos++; if (wheelpos >= items) wheelpos = 0; for (i = 0; i < items; i++) #ifdef INVERT_LITED_WHEEL VFD_clear_lite_anode(T_VFD_wheel[i], i == wheelpos);#else VFD_clear_lite_anode(T_VFD_wheel[i], i != wheelpos);#endif } else if (set == VFD_WHEEL_SET_FAN) { wheelpos = -1; for (i = 0; i < items; i++) VFD_clear_lite_anode(T_VFD_wheel[i], 1); } else if (set == VFD_WHEEL_CLEAR_FAN) { wheelpos = -1; for (i = 0; i < items; i++) VFD_clear_lite_anode(T_VFD_wheel[i], 0); }}/* * Set a 7-segment character (really 8 segments) to a given character. * * Inputs: * seg: G/P positions for the given character * target: Target character (not in ASCII but in segments) */PRIVATE void VFD_set_char(seg, target)unsigned short * seg;unsigned int target;{ int i; for (i = 0; i < T_VFD_char_segment_size[0]; i++) { /* * By convention, T_VFDICON_tbl[1] is ICON_empty. Don't * update ICON_empty, it is just wasting time! */ if (seg[i] != T_VFDICON_tbl[1]) VFD_clear_lite_anode(seg[i], target & 1); target >>= 1; }}/* * Output 2 7-segment digits. * * Inputs: * pos: VFD_TRACK, VFD_MINUTE, VFD_SECOND, VFD_MIN100, * VFD_TITLE * data: BCD data to write in case of Minute and Second * >>> Hex in case of Track number (TRACK_LOW/TRACK_HIGH) * maskFlag: 1 - Show blank when the high digit is 0 * 0 - Show '0' when the high digit is 0 */void VFD_segment(pos, data, maskFlag)int pos;unsigned int data;int maskFlag;{ unsigned short * digit_tbl = T_VFD_digit_tbl; VFD_CHAR_SEGMENTS * ptr; ptr = &(((VFD_CHAR_SEGMENTS *) T_VFD_char_segments)[pos]); /* * Assume everything is limited to 2 digits (may not be true for * DVD's minute field. */ data &= 0xff; if ((pos == VFD_TRACK) || (pos == VFD_CHAPTER)) { /* hex2bcd table only valid up to 99 */ while (data > 99) data -= 100; data = hex2bcd[data]; /* track/chapter nums are in hex */ } if (pos == VFD_MIN100 ) { /* position VFD_MIN100 only has one digit. */ VFD_set_char(ptr->seg, digit_tbl[data]); } else { /* update the lower digit. */ VFD_set_char((ptr+1)->seg, digit_tbl[data & 0xf]); /* Data is BCD*/ data >>= 4; /* If we don't want to mask off 0, or the digit is not 0, then output the digit. */ VFD_set_char(ptr->seg, (!maskFlag || data) ? digit_tbl[data] : CHAR_); }}/* * Lite those calendar icons associated with track_list. Only * track_list items between [start_index, track_list_max) are included. * * If start_index > track_list_max, then we'll clean all calendar numbers. */void VFD_calendar(int start_index){#ifndef HOST_SLAVE#if MAX_CALENDAR /* Calendar exists */ unsigned short i, lite, index; unsigned short anode; EnableFlashing = 0; /* * calendar_tbl is in xxxxyzzzzzzzz format where z is 1 hot while * xxxxy give the "ShadowRam" index. */ /* Clear up all the calendar icons */ for (i = 0; i <= MAX_CALENDAR; i++) { anode = T_VFD_calendar_tbl[i]; VFD_clear_lite_anode(anode, 0); } /* Lite up ones that we are interested in */ for (i = start_index; i < track_list_max; i++) { lite = track_list[i]; if (lite <= MAX_CALENDAR) { anode = T_VFD_calendar_tbl[lite]; VFD_clear_lite_anode(anode, 1); } }#endif /* Calendar exists */#endif /*HOST_SLAVE*/}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?