⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ef8681.c

📁 CML CMX868 modem
💻 C
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------------------------------
//	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 + -