📄 drive.c
字号:
/**************************
name:Drive.h
author:RPJ
version:V0.1
description:
单独的外部扫描和驱动模块
***************************/
#include "reg52.h"
#include "absacc.h"
#include "clock.h"
#include "define.h"
#include "drive.h"
#define GLOBALS
#include "variable.h"
/*******************************
name:Micro_Switch_8816(unchar Ext_No,unchar Channel_X,unchar Open)
input:Ext_No,Channel_X,Open
output:none
description:
通过合并用户号,绳路号和开关状态,向8816写入控制数据
绳路号是3456位
用户号是012位
控制状态是7位
开关选通有时间,注意停留
******************************/
void Micro_Switch_8816(unchar Ext_No,unchar Channel_X,unchar Open)
{
unchar data Group,Param;
Group = Ext_No/8;
Param = Ext_No%8;
Param &= 0x0f;
Channel_X &= 0x0f;
Channel_X <<= 3;
Param |=Channel_X;
if(Open)
{
Param |=0x80;
}
XBYTE[(Addr_8816_Data)] = Param;
switch(Group)
{
case 0:
Control_8816A = 0;
Control_8816B = 0;
SelecEN_8816 = 0;
break;
case 1:
Control_8816A = 1;
Control_8816B = 0;
SelecEN_8816 = 0;
break;
case 2:
Control_8816A = 0;
Control_8816B = 1;
SelecEN_8816 = 0;
break;
case 3:
Control_8816A = 1;
Control_8816B = 1;
SelecEN_8816 = 0;
break;
default:
break;
}
SelecEN_8816 = 1;
}
/*************************************
name: init_8816_ext
*************************************/
void Init_8816(void)
{
unchar data i,j;
SelecEN_8816 = 1;
for(i=0;i<32;i++)
{
for(j=0;j<16;j++)
{
Micro_Switch_8816(i,j,0);
}
}
}
/*************************************
name: init_ext_port
*************************************/
void Init_RC_Port(void)
{
unchar data i;
for(i=0;i<4;i++)
{
Ext_Group[i].SCN = 0xff; //默认初始化都是挂机
Ext_Group[i].LL = 0xff; //默认初始化都是挂机
Ext_Group[i].AP = 0;
Ext_Group[i].LAP = 0;
Ext_Group[i].DTMF_ST = 0;
Ext_Group[i].DTMF_Data[0] = 0;
Ext_Group[i].DTMF_Data[1] = 0;
Ext_Group[i].DTMF_Data[2] = 0;
Ext_Group[i].DTMF_Data[3] = 0;
Ext_Group[i].Ext_Ring_ST = 0;
XBYTE[(Addr_EXT_Drive+i*Addr_Offset)] = Ext_Group[i].Ext_Ring_ST;
}
}
/***************************************
subroutine name: Micro_Scan_8870(void)
input variable: group
output variable: /
description: scan 8870 decoder.
查询8870的解码状态,如果持续是1就等待,继续查询
如果8870前次是1,本次是0,表示有一个解码完成
就读取数据再分析(数据已经定时读出了)
注意:由于是模拟交换,存在拨号的号码串号的情况,
特别是在用户听拨号音等待拨号时候,所以听拨号音的
用户同时褡裢在一起的,每个收号器都能受到其中一个
拨号,为了有效防止串号的出现,使用了一定的处理方式。
***************************************/
void Micro_Scan_8870(void)
{
unchar data Ext_No,temp,INT_ST;
unchar data i,point;
/****************DECODER ST***************/
point = SLEC_Point;
INT_ST = Ext_Group[point].DTMF_ST;
/*****************************************/
//if(INT_ST)
//INT_ST = 0;
for(i=0;i<4;i++)
{
Ext_Group[point].DTMF_Data[i] = XBYTE[(Addr_DTMF_Data+i*Addr_Offset)];
}
for(i=0;i<8;i++)
{
Read_8870ST();
Ext_No = i*4+point;
if( Ext_No >= TAL_EXT_PORT )
{
break;
}
if( (Ext_Param[Ext_No].RecDTMF_En & 0xf0) == 0 )
{
Ext_Param[Ext_No].RecDTMF_En = 0;
INT_ST>>=1;
continue;
}
if( INT_ST&0x01 )
{
if(Ext_Param[Ext_No].Ext_State == state1_DailNo )
{//如果当前用户是听拨号音,需要立即关闭
Micro_Switch_8816(Ext_No,BUSY_Channel, 0);
Ext_Timer[Ext_No].Counter_Pause++;
if( Ext_Timer[Ext_No].Counter_Pause <= 1 )
{
INT_ST>>=1;
continue;
}
}
Ext_Param[Ext_No].RecDTMF_En &= 0xf0;
Ext_Param[Ext_No].RecDTMF_En |= MT8870_EnOut;//have tone input when decorder finish
if( i%2 )
{
temp = Ext_Group[point].DTMF_Data[i/2] & 0xf0;
temp >>= 4;
Ext_Param[Ext_No].RecDTMF_Data = Exchang_CIDData(temp);
}
else
{
temp = Ext_Group[point].DTMF_Data[i/2] & 0x0f;
Ext_Param[Ext_No].RecDTMF_Data = Exchang_CIDData(temp);
}
}
else
{
if( Ext_Timer[Ext_No].Counter_Pause <= 1 )
{
if(Ext_Param[Ext_No].Ext_State == state1_DailNo )
{//如果当前用户是听拨号音,但是只收到一个号码,需要重新开启拨号音
Micro_Switch_8816(Ext_No,BUSY_Channel, 1);
Ext_Timer[Ext_No].Counter_Pause = 0;
INT_ST>>=1;
continue;
}
}
Ext_Timer[Ext_No].Counter_Pause = 0;
if( (Ext_Param[Ext_No].RecDTMF_En & 0x0f) == MT8870_EnOut)
{
Ext_Param[Ext_No].RecDTMF_En &= 0xf0;
Ext_Param[Ext_No].RecDTMF_En |= MT8870_NoOut;//no tone input when decorder finish
Ext_Param[Ext_No].Ext_EVENT = event3_ExtRecDtmf;
Ext_Param[Ext_No].Ext_RecDtmf_List[Ext_Timer[Ext_No].Counter_Rec_DTMF++] = Ext_Param[Ext_No].RecDTMF_Data;
MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No,
WP_EVENT, TAL_EVENT, BufSize);
//用户进入收到DTMF信号事件
}
}
INT_ST>>=1;
}
Ext_Group[point].DTMF_ST= 0;
Ext_Group[point].SCN= XBYTE[(Addr_EXT_State+point*Addr_Offset)];
}
/***************************************
subroutine name: Exchang_CIDData
input variable: Num
output variable: num(new)
description: calculte the data value for dtmf.
***************************************/
unchar Exchang_CIDData(unchar Num)
{
if( Num == 0 )
{
Num = 0x0f;
return Num;
}
if( Num == 0x0a )
{
Num = 0;
return Num;
}
else
{
return Num;
}
}
/***************************************
subroutine name: EXT_StateScan
input variable: ext_group/0 or 1
output variable: /
description: scan ext hook off / on,when hook on the decorder shut off,or trun on.
***************************************/
void EXT_StateScan(unchar group)
{
unchar data Ext_No,i,flashtemp;
unchar data GROUP_ST_ANAL,GROUP_ST_NEW;
GROUP_ST_NEW = Ext_Group[group].SCN;
GROUP_ST_NEW |= Ext_Group[group].Ext_Ring_ST;
GROUP_ST_ANAL=GROUP_ST_NEW^Ext_Group[group].LL;
for(i=0;i<8;i++)
{
Ext_No = group * 8+i;
if( Ext_No > TAL_EXT_PORT )
{
break;
}
if( Ext_Param[Ext_No].Flag_Signal == 0x61 )
{
Ext_Group[group].SCN |= (1<<i);//保证初始态为1
Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_ON;
continue;
}//由于在用户振铃期间OFFHOOK信号有低出现,必须屏蔽该段时间
if( GROUP_ST_ANAL & 0x01 )
{
if((GROUP_ST_NEW & 0x01)==0)//如果用户是摘机
{
if( Ext_Param[Ext_No].Ext_State == state7_TalkFrom )
{
if(Ext_Timer[Ext_No].Counter_HK>=EXT_SCAN_ON+Flash_Scan_Start)//大于60ms
{
if(Ext_Timer[Ext_No].Counter_HK<=EXT_SCAN_ON+Flash_Scan_End)//小于180ms
{
Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
Ext_Param[Ext_No].Ext_EVENT = event17_ExtFlash;
MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No,
WP_EVENT, TAL_EVENT, BufSize);
goto Next_Ext;
//用户进入闪断事件;//400~800ms,flash 在60~180ms
}
}
}
}
Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_ON;
if( EXT_SCAN_PRI )
Ext_Timer[Ext_No].Counter_HK++;
else
goto NO_PRI;
}
else
{
if( Ext_Timer[Ext_No].Counter_HK >EXT_SCAN_ON)
{
flashtemp = 0;
if( Ext_Param[Ext_No].Ext_State == state7_TalkFrom )
{
if( GROUP_ST_NEW & 0x01 )
{
flashtemp = Flash_Scan_End;
}
}//只分析挂机的时候的情况,摘机不管了
if( Ext_Timer[Ext_No].Counter_HK >(EXT_SCAN_LEN+flashtemp) )
{
NO_PRI: if( GROUP_ST_NEW & 0x01 )
{
Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
Ext_Param[Ext_No].Ext_EVENT = event2_ExtHookOff;
MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No,
WP_EVENT, TAL_EVENT, BufSize);
//用户进入挂机事件;
}
else
{
Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
Ext_Param[Ext_No].Ext_EVENT = event1_ExtHookOn;
MICRO_SendToBuf(EXT_EVENT_QUEUE[WP_EVENT], Ext_No,
WP_EVENT, TAL_EVENT, BufSize);
//用户进入摘机事件;
}
}
else
{
Ext_Timer[Ext_No].Counter_HK++;
}
}
else
{//由于出现一段时间后发现用户不能使用,所以要查询摘机然后直接挂
Ext_Timer[Ext_No].Counter_HK = EXT_SCAN_OFF;
}
}
Next_Ext:
GROUP_ST_NEW >>= 1;
GROUP_ST_ANAL >>= 1;
}
Ext_Group[group].LL = Ext_Group[group].SCN;
}
/***************************************
subroutine name: Control_4052
input variable: /
output variable: /
description: selec the point to control the anolog switch.
实际的使用中出现了解码信号滞后,所以控制点
要停留处理
同时注意,由于PLD的控制后4052控制信号是反的,
1表示低电平,0表示高电平,所以:
A=1,B=1,实际选通Y0
A=0,B=1,实际选通Y1
A=1,B=0,实际选通Y2
A=0,B=0,实际选通Y3
***************************************/
void Control_4052(void)
{
SLEC_Point++;
SLEC_Point &= 0x03;
switch(SLEC_Point)
{
case 0:
Control_4052A= 0;
Control_4052B= 1;
break;
case 1:
Control_4052A = 1;
Control_4052B = 0;
break;
case 2:
Control_4052A = 0;
Control_4052B = 0;
break;
case 3:
Control_4052A = 1;
Control_4052B = 1;
break;
default:
break;
}
}
/*************************
name:Ext_Timer_Reset(unchar Ext_No)
input:Ext_No
output:/
description:
将用户所有计数参数复位
*************************/
void Ext_Timer_Reset(unchar Ext_No)
{
Ext_Timer[Ext_No].Counter_HK = 0; //所有计数器归0
Ext_Timer[Ext_No].Counter_Signal = 0;
Ext_Timer[Ext_No].Counter_Pause = 0;
Ext_Timer[Ext_No].Counter_Rec_DTMF = 0;
}
/*************************
name:Ext_Param_Reset(unchar Ext_No)
input:Ext_No
output:/
description:
将用户所有参数复位
*************************/
void Ext_Param_Reset(unchar Ext_No)
{
unchar data i;
Ext_Param[Ext_No].Num_Call_Other = 0xff; //主叫浮空
Ext_Param[Ext_No].Num_Call_Me = 0xff; //被叫浮空
i = Ext_Param[Ext_No].Num_Switch_Cable&0x0f;
if(i<TAL_CABLE)
Micro_Switch_8816(Ext_No, i, 0);
Ext_Param[Ext_No].Num_Switch_Cable = 0xff; //绳路浮空
Ext_Param[Ext_No].RecDTMF_Data = 0xff; //接收的数据浮空
Ext_Param[Ext_No].RecDTMF_En = MT8870_NoRec; //收号器不可用
Ext_Param[Ext_No].Ext_EVENT = 0xff; //用户事件浮空
Ext_Param[Ext_No].Ext_State = state0_Free; //改变用户状态
Ext_Param[Ext_No].Flag_Signal = 0; //改变用户状态
for(i=0;i<12;i++)
{
Ext_Param[Ext_No].Ext_RecDtmf_List[i] = 0;
}
Ext_Param[Ext_No].Num_MeetGroup = 0xff;
Ext_Param[Ext_No].Temp_Troop_Call = 0; //改变用户群呼状态
}
/******************************
Name:OPEN_EXT_Signal(unchar Ext_No,unchar Listen)
input:Ext_No,Signal_Type
output:none
description:
Signal_Type说明
听信号音 1
听忙音 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -