📄 ef8681.c
字号:
//---------------------------------------------------------------------------------------------------
// Project:- DE8681
// Filename:- EF8681.C
// Description:- Socket Modem Main Routine and Interrupt Service Routine.
// Programmer:- D.T.F
// Version:- 2.0
// Created:- 28th February 2001
// Last modified:-
//---------------------------------------------------------------------------------------------------
// (C) Consumer Microcircuits Ltd 2002
//
// This firmware was designed by:-
// Consumer Microcircuits Ltd,
// Langford, Maldon,
// ESSEX
// CM9 6WG.
// in the UK for use with CML evaluation kits only and is based on UK originated technology.
// Please contact
// sales@cmlmicro.co.uk
// +44 (0)1621 875500
// for licensing details.
//---------------------------------------------------------------------------------------------------
#define EF8681_C
#include "ef8681.h"
main()
{
unsigned char tmpresult;
init_micro(); // Initialise Micro
init_ports(); // Initialise PIC Ports
init_regs(); // Initialise registers
init_sregs(0); // Initialise S registers with Factory 0 defaults.
init_spi(); // Initialise SPI for control of CMX868 CBUS
reset_cbus(); // Perform CMX868 General Reset and clear device shadow registers
init_GPTs(); // Initialise General Purpose Timers
sci_init(19200, SCI_EIGHT);
PEIE = 1; // Enable Peripheral Interrupts
GIE = 1; // Enable Global Interrupts
RCIE = 1; // Unmask receiver interrupts
while (DTRN) // Wait until DTRN is low, indicating PC COM port is connected
continue;
PORTB &= 0b11110111; // Now clear DSRN to indicate DE8681 connection to PC
genmsgtopc(idmsg); // Send id message to terminal
// CMX868 Rev C Check
pwrup(); // Power Up CMX868 with correct Xtal and fixed equalisers initially enabled.
if (dut_chksum() == ERROR)
{
genmsgtopc(dutrevmsg); // Send device revision error message to terminal
}
reset_cbus(); // Reset the CBUS, will clear all shadow write registers
// Initial settings
EVMODE = 1; // Set Evaluation Mode Flag
ATCMDMODE = 1; // Set AT Command Mode Flag
CTSN = 0; // Clear CTSN to indicate board is ready to receive characters
// Main Loop code
do
{
if(!DTRN)
{
DTRIND = 1; // Ensures that the DTR LED is lit when Hyper Terminal
} // is connected and disconnected
else
{
DTRIND = 0;
}
if (BERTFLAG) // BERT can be performed whilst off-line or in Data transfer mode
{ // Carrier is not monitored during this test
bert();
init_GPTs(); // Initialise General Purpose Timers ready for normal use
undo_bertporta(); // Re-initialise Port A for normal use (outputs to drive LEDs)
}
if (TESTFUNC1) // Test Function One outputs to screen the status register contents at the S19 rate
{
do
{
testfunc1(); // Execute Test Function One
} while (!KEYABORT); // Loop until key pushed
TESTFUNC1 = 0; // Clear Test Function flag
KEYABORT = 0; // Reset key abort flag
}
if (ATCMDMODE && (S0 != 0)) // Check if auto answer is possible during AT command mode
{
ringdetection(); // Check for ring detect or validate ringing
}
if (LOADCHAR)
{
while (TXIE) // Wait until all previous characters are sent to screen
continue;
TXIE = 1; // Enable Tx Interrupt
LOADCHAR = 0; // Clear Load character flag
}
if (INTERPRET)
{
resmsgtopc(atcmd_interpret());
INTERPRET = 0;
ATBUFPTR = 0x00; // Re-initialise AT Command Buffer pointer
CTSN = 0; // Ensure CTSN is low to allow further characters
}
if (!DATAXFER && !ATCMDMODE)
{
hndshake_init();
hook(1); // Go off-hook
if (ANSORIG)
{
Delay1s(S6); // Temporary Blind Dialling always
dial(); // Dial routine if originating
}
tmpresult = hndshake_go();
resmsgtopc(tmpresult);
if ((tmpresult == NOCARRIER) || (tmpresult == NYI))
{
reset_cbus(); // Reset CMX868 into powersave, will cause board to go on-hook
DCDIND = 0; // Turn off CD LED
DCDN = 1; // Set DCDN line
DATAXFER = 0; // Abort data transfer
ATCMDMODE = 1; // Revert back to AT Command Mode
KEYABORT = 0; // Ensure key abort flag is cleared
}
}
if (DATAXFER && !ATCMDMODE)
{
dataxfer(); // Data Transfer loop, will exit if carrier is lost
// or escape sequence is entered
while (TXIE) // Ensure all outstanding rx data has been displayed before continuing
continue;
CTSN = 0; // Ensure CTSN is low to allow further characters
if (!DATAXFER)
{
resmsgtopc(NOCARRIER); // Return No Carrier message to PC
}
else
{
resmsgtopc(OK); // Return OK message to PC
}
}
if (DATAXFER && (POLLTMR == 0))
{
CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Read CMX868 Status reg and update shadow reg
if (hangup()) // If the carrier detect flag has been lost
{
reset_cbus(); // Reset CMX868 into powersave, will cause board to go on-hook
DCDIND = 0; // Turn off CD LED
DCDN = 1; // Set DCDN line
DATAXFER = 0; // Abort data transfer
ATCMDMODE = 1; // Revert back to AT Command Mode
resmsgtopc(NOCARRIER);
}
POLLTMR = 20; // Reload 20ms Rx Energy polling timer
}
} while (EVMODE);
}
// Response message routine using case statements
// rather than array of pointers
void resmsgtopc(unsigned char messnum)
{
char tempbuf[24];
unsigned char i=0;
if (RESOFF) // Check Result Codes are required
{
return;
}
if (!WORDRES) // Check if number response are required
{
if (HEXOP)
{
hexnum2scrn(messnum,2,0); // Do not send LF char
}
else
{
decnum2scrn(messnum,2,0); // Do not send LF char
}
return;
}
switch(messnum)
{
case 0:
strcpy(tempbuf,"OK");
break;
case 1:
strcpy(tempbuf,"CONNECT");
break;
case 2:
strcpy(tempbuf,"RING");
break;
case 3:
strcpy(tempbuf,"NO CARRIER");
break;
case 4:
strcpy(tempbuf,"ERROR");
break;
case 5:
strcpy(tempbuf,"NO DIAL TONE");
break;
case 6:
strcpy(tempbuf,"BUSY");
break;
case 7:
strcpy(tempbuf,"CONNECT 2400");
break;
case 8:
strcpy(tempbuf,"CONNECT 1200");
break;
case 9:
strcpy(tempbuf,"CONNECT 600");
break;
case 10:
strcpy(tempbuf,"CONNECT 300");
break;
case 11:
strcpy(tempbuf,"CONNECT 1200/75");
break;
case 12:
strcpy(tempbuf,"CONNECT 75/1200");
break;
case 13:
strcpy(tempbuf,"CONNECT 1200/150");
break;
case 14:
strcpy(tempbuf,"CONNECT 150/1200");
break;
case 15:
strcpy(tempbuf,"NYI");
break;
default: // i.e. no result code
return;
}
while ( tempbuf[i] != '\0')
{
MSGBUF[MSGBUFLDPTR++] = tempbuf[i]; // Load Character into output buffer
MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
i++; // Point to next character from message
}
MSGBUF[MSGBUFLDPTR++] = S3; // Load Message Buffer with CR char
MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
if (WORDRES)
{
MSGBUF[MSGBUFLDPTR++] = S4; // Load Message Buffer with LF char
MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
}
TXIE = 1; // Enable Tx Interrupt
while (TXIE)
continue; // Wait until all characters have been sent to terminal
}
void genmsgtopc(unsigned char messnum)
{
char tempbuf[24];
unsigned char i=0;
if (RESOFF) // Check Result Codes are required
{
return;
}
switch(messnum)
{
case 0:
strcpy(tempbuf,"EF8681 V2.0"); // Change this string when code is modified
break;
case 1:
strcpy(tempbuf,"DE8681 Demonstration Kit");
break;
case 2:
strcpy(tempbuf,"CML UK");
break;
case 3:
strcpy(tempbuf,"CML Singapore");
break;
case 4:
strcpy(tempbuf,"MX-COM, INC");
break;
case 5:
strcpy(tempbuf,"sales@cmlmicro.co.uk");
break;
case 6:
strcpy(tempbuf,"sales@cmlmicro.com.sg");
break;
case 7:
strcpy(tempbuf,"mxsales@mxcom.com");
break;
case 8:
strcpy(tempbuf,"Tel:+44(0)1621 875500");
break;
case 9:
strcpy(tempbuf,"www.cmlmicro.co.uk");
break;
case 10:
strcpy(tempbuf,"Invalid CMX868 Rev C");
break;
default:
return;
}
while ( tempbuf[i] != '\0')
{
MSGBUF[MSGBUFLDPTR++] = tempbuf[i]; // Load Character into output buffer
MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
i++; // Point to next character from message
}
MSGBUF[MSGBUFLDPTR++] = S3; // Load Message Buffer with CR char
MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
if (WORDRES)
{
MSGBUF[MSGBUFLDPTR++] = S4; // Load Message Buffer with LF char
MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
}
TXIE = 1; // Enable Tx Interrupt
while (TXIE)
continue; // Wait until all characters have been sent to terminal
}
void interrupt isr(void)
{
unsigned char i;
if (T0IE && T0IF) // Check if Timer Interrupt Enabled and interrupt flag set
{
if (!BERTFLAG)
{
update_GPTs();
}
else
{
if (BERTEND)
{
bert_txd();
}
else
{
bert_rxd();
}
}
}
if (RCIE && RCIF) // Check if Rx Character Interrupt Enable and Flag
{
TXDIND = 1; // Turn on TXD LED
GPT4 = 2; // LED will stay illuminated for approx. 200mS
if (DATAXFER && !ATCMDMODE)
{
rx_datachars();
}
else
{
rx_atchars();
}
}
if (TXIE) // Check if Tx Character Interrupt is enabled
{
RXDIND = 1; // Turn on RXD LED
GPT4=2;
tx_chars();
}
}
void init_GPTs()
{
ESCTMR = 0; // 50ms Escape Sequence Timer
POLLTMR = 0; // 1ms General Purpose Polling Timer
RDTIMEOUT = 0; // Ensure ring detect timeout reg is clear at start
GPT1 = 0; // 10ms General Purpose Timers
GPT2 = 0;
GPT3 = 0; // 100ms General Purpose Timers
GPT4 = 0;
GPT5 = 0; // 1 second General Purpose Timers
GPT6 = 0;
PS10ms = 10; // Initialise Prescalers
PS100ms = 10;
PS1s = 10;
ESCPS = 50;
T0CS = 0; // Timer increments on instruction clock
PSA=0; // Assign Prescaler to TMR0
PS2=0; // Prescaler 1:4 TMR0
PS1=0;
PS0=1;
TMR0 = 22; // Ideally TMR0 count should be 250 except
// need to account for interrupt saving code
// which is approximately 70us.
T0IF = 0; // Clear the interrupt flag
T0IE = 1; // Enable interrupt on TMR0 overflow
}
void update_GPTs()
{
T0IE = 0; // Disable Timer interrupt
ESCPS--; // Decrement Escape sequence prescaler
if (POLLTMR != 0) // Check status of General Purpose Polling Timer (1ms)
{
POLLTMR--; // Decrement General Purpose Polling Timer
}
if (ESCPS == 0)
{
ESCPS = 50; // Reload 50ms prescaler
if (ESCTMR != 0) // Check status of Escape Sequence Timer (50ms)
{
ESCTMR--; // Decrement Escape Sequence Timer
}
}
PS10ms--; // Decrement 10ms prescaler
if (PS10ms == 0)
{
PS10ms = 10; // Reload 10ms prescaler
PS100ms--; // Decrement 100ms Prescaler
if (GPT1 != 0) // Check status of General Purpose Timer 1 (10ms)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -