ef8681.c
资源名称:de8681_w.rar [点击查看]
上传用户:lilishw
上传日期:2021-05-28
资源大小:1542k
文件大小:29k
源码类别:
Modem编程
开发平台:
Visual C++
- //---------------------------------------------------------------------------------------------------
- // Project:- DE8681
- // Filename:- EF8681.C
- // Description:- Socket Modem Main Routine and Interrupt Service Routine.
- // Programmer:- D.T.F
- // Version:- 3.0
- // Created:- 28th February 2001
- // Last modified:- 1/12/2003 (M.T)
- //---------------------------------------------------------------------------------------------------
- // (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"
- __CONFIG(UNPROTECT|FOSC0|CPD|BKBUG);
- 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
- // 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 (TESTFUNC2)
- {
- testfunc2();
- }
- 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] != ' ')
- {
- 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 V3.2"); // 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,"CML USA");
- break;
- case 5:
- strcpy(tempbuf,"sales@cmlmicro.com");
- break;
- case 6:
- strcpy(tempbuf,"sg.sales@cmlmicro.com");
- break;
- case 7:
- strcpy(tempbuf,"us.sales@cmlmicro.com");
- break;
- case 8:
- strcpy(tempbuf,"Tel:+44(0)1621 875500");
- break;
- case 9:
- strcpy(tempbuf,"www.cmlmicro.com");
- break;
- default:
- return;
- }
- while ( tempbuf[i] != ' ')
- {
- 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)
- {
- 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)
- {
- GPT1--; // Decrement General Purpose Timer 1
- }
- if (GPT2 != 0) // Check status of General Purpose Timer 2 (10ms)
- {
- GPT2--; // Decrement General Purpose Timer 2
- }
- if (PS100ms == 0)
- {
- PS100ms = 10; // Reload 100ms prescaler
- PS1s--; // Decrement 1s Prescaler
- if (CDLOSTTMR != 0) // Check status of Carrier Detect Lost Timer (100ms)
- {
- CDLOSTTMR--; // Decrement Carrier Detect Lost Timer
- }
- if (RDTIMEOUT != 0) // Check status of Ring Detect timeout reg (100ms)
- {
- RDTIMEOUT--; // Decrement Ring Detect timeout reg
- }
- if (GPT3 != 0) // Check status of General Purpose Timer 3 (100ms)
- {
- GPT3--; // Decrement General Purpose Timer 3
- }
- if (GPT4 != 0) // Check status of General Purpose Timer 4 (100ms)
- {
- GPT4--; // Decrement General Purpose Timer 4
- }
- else
- {
- if(LED_OVERRIDE)
- {
- // Ensures that the TXD and RXD LEDs stay illuminated
- TXDIND = 1; // after an at@f1 command
- RXDIND = 1;
- }
- if(!LED_OVERRIDE)
- {
- TXDIND = 0; // Ensures that the TXD and RXD LEDs
- RXDIND = 0;
- }
- }
- if (PS1s == 0)
- {
- PS1s = 10; // Reload 1s prescaler
- if (GPT5 != 0) // Check status of General Purpose Timer 5 (1s)
- {
- GPT5--; // Decrement General Purpose Timer 5
- }
- if (GPT6 != 0) // Check status of General Purpose Timer 6 (1s)
- {
- GPT6--; // Decrement General Purpose Timer 6
- }
- }
- }
- }
- TMR0 = 22; // Reload the timer (250us * 4) per interrupt
- // Delay in interrupt saving adjusted for
- T0IF = 0; // Clear the interrupt flag
- T0IE = 1; // Enable Timer interrupt
- }
- void init_regs()
- {
- unsigned char i;
- for(i=0; i<48; i++)
- {
- ATBUF[i] = 0; // Clear AT Command Buffer
- }
- for(i=0; i<32; i++)
- {
- MSGBUF[i] = 0; // Clear Message Buffer
- }
- TELNUM[0] = NUL; // Will intially appear empty
- MODEMSTAT = 0x00; // Initially set Evaluation Mode Flag and AT Command Mode Flag
- ATCMDSTAT = 0x00; // Clear AT Command Status register
- BERTSTAT = 0x00;
- XFERSTAT = 0x00;
- ATBUFPTR = 0x00; // Initialise AT Command Buffer pointer
- MSGBUFLDPTR = 0x00; // Initialise Message Buffer Load pointer
- MSGBUFRDPTR = 0x00; // Initialise Message Buffer Read pointer
- DATABUFLDPTR = 0x00; // Initialise Data Buffer Load pointer
- DATABUFRDPTR = 0x00; // Initialise Data Buffer Read pointer
- }
- void init_sregs(unsigned char settings)
- {
- static unsigned char bank1 sreginit[2][30] ={ // Factory Profile 0
- { 0,0,43,13,10,8,2,50,2,6, // S0 to S9
- 7,10,20,0,138,0,0,0,30,2, // S10 to S19
- 0,193,64,0,1,176,48,0,0,0}, // S20 to S29
- // Factory Profile 1
- { 5,0,43,13,10,8,2,50,2,6, // S0 to S9
- 7,20,20,0,128,0,0,0,30,2, // S10 to S19
- 0,193,0,0,3,176,176,0,0,0} // S20 to S29
- };
- unsigned char i;
- volatile unsigned char bank2 * sregptr;
- if (settings <= 1)
- {
- sregptr = &S0;
- for(i=0; i < numsregs; i++)
- {
- *sregptr = sreginit[settings][i]; // Load S registers with initial settings
- sregptr++;
- }
- }
- }
- void init_micro()
- {
- OPTION = 0x00;
- STATUS = 0x00;
- PIR1 = 0x00;
- INTCON = 0x00;
- PIE1 = 0x00;
- }
- void init_ports()
- {
- TRISA = CONFIGPA; // Configure Port A
- TRISB = CONFIGPB; // Configure Port B
- TRISC = CONFIGPC; // Configure Port C
- ADCON1 = 0x06; // Port A no analog i/p's, all digital.
- PORTA = INITPA; // Initial Port A settings
- PORTB = INITPB; // Initial Port B settings
- PORTC = INITPC; // Initial Port C settings
- }
- void hook(unsigned char state) // State determines if on or off hook (State != 0 takes modem off-hook)
- {
- if (state == 0)
- {
- RLYDRV_ON = 0; // On-Hook
- }
- else
- {
- RLYDRV_ON = 1; // Off-Hook
- }
- wr16_cbus(CMXGENCTRL_ADDR,CMXGENCTRL); // Write General Control information to C-BUS.
- }
- void ringdetection() // Simple crude BT or Bell Ring Detect Check. A valid ring consists of a burst greater
- // than 300ms then no ring detect when resampled 1 sec after burst ended.
- {
- if (POLLTMR == 0)
- {
- POLLTMR = 20; // Reload 20ms Ring detect sampling interval register
- if (!RDINPROG) // Check if ringing is in progress
- {
- RDCNT = 0; // Clear ring detect sample counter
- CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Read CMX868 Status reg and update shadow reg
- if (RDET) // Ring Detect Check
- {
- S1 = 0; // Clear ring count S-register
- RDCNT++;
- RDTIMEOUT = 0; // Ensure ring detect timeout reg is clear at start
- RDINPROG = 1; // Set flag to indicate ringing in progress
- RIN = 0; // Clear RIN line
- }
- }
- else
- {
- if (RDTIMEOUT <= 70) // Check 8sec ring timeout timer has been running for at least 1sec
- {
- CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Read CMX868 Status reg and update shadow reg
- if (RDET) // Ring Detect Check
- {
- RIN = 0; // Ensure RIN line is clear
- if (RDCNT != 255) // Prevent ring detect sample count reg from wrapping round
- {
- RDCNT++;
- }
- }
- else
- {
- RIN = 1; // Set RIN line
- if (RDCNT >= 15) // Check if ring burst exceeded 300ms
- {
- S1++; // Increment ring count S-register
- resmsgtopc(RING); // Send Ring message to terminal
- if (S1 == S0)
- {
- RDINPROG = 0; // Initialise flag ready for next auto answer
- ATCMDMODE = 0; // Clear flag to indicate ready for handshaking
- ANSORIG = 0; // Clear flag to indicate answering
- }
- else
- {
- RDTIMEOUT = 80; // Reload 8sec ring detect timeout timer (100ms)
- RDCNT = 0; // Clear ring detect sample counter
- }
- }
- else
- {
- if (RDTIMEOUT == 0) // Abort ring detect validation if 8 sec timeout has occurred
- {
- RDINPROG = 0; // Initialise flag ready for next auto answer
- }
- }
- }
- }
- }
- }
- }
- void dial() // Dial routine Tx always enabled, alternates between DTMF and Notone
- {
- unsigned char i=0;
- CMXTXMODE &= 0x0E00;
- CMXTXMODE |= 0x1000; // Select DTMF/Tones
- // Set the DTMF twist from that set in the 3 LSBs of S28
- CMXTXMODE |= (S28 & 0x07) << 5;
- while (TELNUM[i] != NUL)
- {
- if (TELNUM[i] == ',') // Introduce delay dial sequence
- {
- Delay1s(S8);
- }
- else
- {
- CMXTXMODE |= 0x0010; // Tx DTMF
- switch(TELNUM[i])
- {
- case 'A': case 'a':
- CMXTXMODE |= DTMF_A;
- break;
- case 'B': case 'b':
- CMXTXMODE |= DTMF_B;
- break;
- case 'C': case 'c':
- CMXTXMODE |= DTMF_C;
- break;
- case 'D': case 'd':
- CMXTXMODE |= DTMF_D;
- break;
- case '*':
- CMXTXMODE |= DTMF_star;
- break;
- case '#':
- CMXTXMODE |= DTMF_hash;
- break;
- case '0':
- CMXTXMODE |= DTMF_0;
- break;
- default: // Numbers 1-9
- CMXTXMODE |= (TELNUM[i] - 0x30);
- break;
- }
- wr16_cbus(CMXTXMODE_ADDR, CMXTXMODE);
- DelayMs(S11 * 10);
- CMXTXMODE &= 0xFFE0; // Turn Tone Off
- wr16_cbus(CMXTXMODE_ADDR, CMXTXMODE);
- DelayMs(S11 * 10);
- }
- i++;
- }
- }
- void decnum2scrn(unsigned int value, unsigned char digits, unsigned char linefeed) // Number of digits and LF can be controlled
- {
- unsigned int k,quot,rem;
- if ((digits > 0) && (digits < 6))
- {
- rem = value;
- k=1;
- do
- {
- k *= 10; // Multiply k by 10
- digits--; // Decrement digits value
- } while (digits > 1);
- do
- {
- quot = rem / k;
- MSGBUF[MSGBUFLDPTR++] = (quot + 0x30) & 0xFF;// Load Message Buffer
- MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
- rem %= k;
- k /= 10;
- } while (k >= 1);
- }
- MSGBUF[MSGBUFLDPTR++] = S3; // Load Message Buffer with CR Char
- MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
- if (linefeed)
- {
- 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 screen
- }
- void hexnum2scrn(unsigned int wordvalue, unsigned char digits, unsigned char linefeed) // LF can be controlled
- {
- unsigned char shift;
- unsigned char k;
- shift = 4 * digits;
- do
- {
- shift = shift - 4;
- k = (wordvalue >> shift) & 0x0F;
- if (k <= 9)
- {
- MSGBUF[MSGBUFLDPTR++] = (k + 0x30) & 0xFF; // Load Message Buffer
- }
- else
- {
- MSGBUF[MSGBUFLDPTR++] = (k + 0x37) & 0xFF; // Load Message Buffer
- }
- MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
- } while (shift != 0);
- MSGBUF[MSGBUFLDPTR++] = S3; // Load Message Buffer with CR Char
- MSGBUFLDPTR &= msgbufwrap; // Wrap round buffer if necessary
- if (linefeed)
- {
- 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 screen
- }
- void testfunc1()
- {
- CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Update CMX868 Status Shadow register
- if (HEXOP)
- {
- hexnum2scrn(CMXSTAT,4,WORDRES); // Send LF char if word results enabled
- }
- else
- {
- decnum2scrn(CMXSTAT,5,WORDRES); // Send LF char if word results enabled
- }
- GPT1 = S19; // Load GPT1(10ms) with S19 value
- if (GPT1 < 2)
- {
- GPT1 = 2; // Only allow 20ms minimum
- }
- while(GPT1 != 0) // Continue to loop until timer has expired
- continue;
- }
- // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- // + at@d cmd function - set 868 to output DTMF tone
- // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- void testfunc2()
- {
- if (ACHAR)
- {
- // check if typed char is '1'-'9' more code efficient this way
- if (ATBUF[0] < ':' && ATBUF[0] > '0')
- {
- setTone(ATBUF[0] - '0');
- }
- else
- {
- // For rest of valid chars CMXTXMODE can't be calculated easily so need switch
- // convert 'a'-'d' to uppercase
- if (ATBUF[0] > 0x60 && ATBUF[0] < 'e')
- {
- ATBUF[0] -= 0x20;
- }
- switch (ATBUF[0])
- {
- case 'A' :
- setTone(DTMF_A);
- break;
- case 'B' :
- setTone(DTMF_B);
- break;
- case 'C' :
- setTone(DTMF_C);
- break;
- case 'D' :
- setTone(DTMF_D);
- break;
- case '0' :
- setTone(DTMF_0);
- break;
- case '*' :
- setTone(DTMF_star);
- break;
- case '#' :
- setTone(DTMF_hash);
- break;
- default :
- resmsgtopc(OK);
- reset_cbus();
- TESTFUNC2 = 0;
- break;
- }
- }
- wr16_cbus(CMXTXMODE_ADDR, CMXTXMODE);
- ACHAR = 0;
- }
- }
- /* reduces compiled code size - used by testfunc2() */
- void setTone(char tone)
- {
- // keep the tx level, twist level but clear the
- // previous DTMF character
- CMXTXMODE &= 0xFFF0;
- // select the new tone
- CMXTXMODE |= tone;
- }