bert.c
资源名称:de8681_w.zip [点击查看]
上传用户:sdttscl
上传日期:2010-01-04
资源大小:683k
文件大小:13k
源码类别:
Modem编程
开发平台:
C/C++
- //---------------------------------------------------------------------------------------------------
- // Project:- DE8681
- // Filename:- BERT.C
- // Description:- BERT routines for CMX868.
- // Programmer:- D.T.F
- // Version:- 2.0
- // Created:- 28th February 2002
- // 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 BERT_C
- #include "ef8681.h"
- void bert()
- {
- init_bertporta(); // Configure and initialise Port A ready BERT
- if (DATAXFER)
- {
- CMXTXMODE &= 0xFFE0; // Unmask Tx data format bit settings
- CMXTXMODE ^= 0x001F; // Sync operation and data bytes from Tx Data Buffer
- wr16_cbus(CMXTXMODE_ADDR, CMXTXMODE); // Update CBUS register
- CMXRXMODE &= 0xFFC7; // Unmask Rx USART bit settings
- CMXRXMODE ^= 0x0038; // Sync operation
- wr16_cbus(CMXRXMODE_ADDR, CMXRXMODE); // Update CBUS register
- }
- else
- {
- bert868_init(); // Initialise CMX868 ready for BERT Tx
- }
- CMXGENCTRL &= 0xFF00;
- if (BERTEND)
- {
- CMXGENCTRL ^= 0x0048; // Set bits for IRQN enable and Tx irq
- }
- else
- {
- CMXGENCTRL ^= 0x0041; // Set bits for IRQN enable and Rx irq
- }
- wr16_cbus(CMXGENCTRL_ADDR, CMXGENCTRL); // Update CBUS register
- bertimer_init(); // Initialise BER timer
- if (BERTEND) // If BERT Tx end (only Tx irq will have been enabled)
- {
- BERTXBYTE = 0; // Clear temporary BER Tx byte under construction
- wr_cbus(CMXTXDATA_ADDR, 0xFF);
- do
- {
- if (!PICIRQN) // If IRQN line goes low we can assume Tx Rdy flag is set
- {
- CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Update Status shadow register and clear irq
- while (!BERTXRDY)
- {
- bert_txd();
- }
- wr_cbus(CMXTXDATA_ADDR, CMXTXDATA); // Write Tx Data to CMX868 reg
- BERTXRDY = 0; // Clear BER Tx Ready flag
- }
- } while (!KEYABORT); // Loop until key pushed
- }
- else // Otherwise assume BERT Rx end (Tx and Rx irq will have been enabled)
- {
- BER_RXDCLK = 1; // Initially set BER Rx data clock hi
- CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Update Status shadow register and clear irq
- CMXRXDATA = rd_cbus(CMXRXDATA_ADDR); // Read CMX868 Rx Data reg and update shadow reg
- BERCNT = 8; // Reload BER rx bit counter
- BERRXDATACLR = 0; // Clear flag to indicate bit extraction required
- do
- {
- if (!PICIRQN) // If IRQN line goes low we can assume Rx Rdy flag is set
- {
- while (!BERRXDATACLR)
- {
- bert_rxd();
- }
- CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Update Status shadow register and clear irq
- CMXRXDATA = rd_cbus(CMXRXDATA_ADDR); // Read CMX868 Rx Data reg and update shadow reg
- BERCNT = 8; // Reload BER rx bit counter
- BERRXDATACLR = 0; // Clear flag to indicate bit extraction required
- bert_rxd();
- }
- } while (!KEYABORT); // Loop until key pushed
- }
- BERTFLAG = 0; // Clear BERT flag
- KEYABORT = 0; // Reset key abort flag
- }
- void bert868_init() // Setup CMX868 for BERT
- {
- reset_cbus(); // Reset the CBUS before we start, will clear all shadow write registers
- pwrup(); // Power Up CMX868 with correct Xtal and fixed equalisers initially enabled.
- FIX_EQU = USER_FIX_EQU; // Extract required Tx and Rx Fixed Equaliser settings from S24.
- wr16_cbus(CMXGENCTRL_ADDR, CMXGENCTRL); // Update CBUS register
- CMXTXDATA = 0xFF; // Initially load 1's into Tx Data
- wr_cbus(CMXTXDATA_ADDR,CMXTXDATA); // Update CBUS register
- // Set up Tx/Rx operating modes
- switch(S27 & 0b11110000) // Determine selected protocol
- {
- case PROTB2:
- if (BERTEND)
- {
- CMXTXMODE ^= 0x4000; // Configure Tx for V.23 75bps
- CMXRXMODE ^= 0x5000; // Configure Rx for V.23 1200bps
- }
- else
- {
- CMXRXMODE ^= 0x4000; // Configure Rx for V.23 75bps
- CMXTXMODE ^= 0x5000; // Configure Tx for V.23 1200bps
- }
- break;
- case PROTB3:
- if (BERTEND)
- {
- CMXTXMODE ^= 0x5000; // Configure Tx for V.23 1200bps
- CMXRXMODE ^= 0x4000; // Configure Rx for V.23 75bps
- }
- else
- {
- CMXRXMODE ^= 0x5000; // Configure Rx for V.23 1200bps
- CMXTXMODE ^= 0x4000; // Configure Tx for V.23 75bps
- }
- break;
- case PROTB4:
- if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
- {
- CMXTXMODE ^= 0xB000; // Configure Tx for V.22 600bps high band
- CMXRXMODE ^= 0xA000; // Configure Rx for V.22 600bps low band
- }
- else
- {
- CMXTXMODE ^= 0xA000; // Configure Tx for V.22 600bps low band
- CMXRXMODE ^= 0xB000; // Configure Rx for V.22 600bps high band
- }
- break;
- case PROTB5:
- if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
- {
- CMXTXMODE ^= 0x9000; // Configure Tx for V.21 300bps high band
- CMXRXMODE ^= 0x8000; // Configure Rx for V.21 300bps low band
- }
- else
- {
- CMXTXMODE ^= 0x8000; // Configure Tx for V.21 300bps low band
- CMXRXMODE ^= 0x9000; // Configure Rx for V.21 300bps high band
- }
- break;
- case PROTB7:
- if (BERTEND)
- {
- CMXTXMODE ^= 0x2000; // Configure Tx for Bell 202 150bps
- CMXRXMODE ^= 0x3000; // Configure Rx for Bell 202 1200bps
- }
- else
- {
- CMXRXMODE ^= 0x2000; // Configure Rx for Bell 202 150bps
- CMXTXMODE ^= 0x3000; // Configure Tx for Bell 202 1200bps
- }
- break;
- case PROTB8:
- if (BERTEND)
- {
- CMXTXMODE ^= 0x3000; // Configure Tx for Bell 202 1200bps
- CMXRXMODE ^= 0x2000; // Configure Rx for Bell 202 150bps
- }
- else
- {
- CMXRXMODE ^= 0x3000; // Configure Rx for Bell 202 1200bps
- CMXTXMODE ^= 0x2000; // Configure Tx for Bell 202 150bps
- }
- break;
- case PROTB9:
- if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
- {
- CMXTXMODE ^= 0x7000; // Configure Tx for Bell 103 high band
- CMXRXMODE ^= 0x6000; // Configure Rx for Bell 103 low band
- }
- else
- {
- CMXTXMODE ^= 0x6000; // Configure Tx for Bell 103 low band
- CMXRXMODE ^= 0x7000; // Configure Rx for Bell 103 high band
- }
- break;
- default:
- if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
- {
- CMXTXMODE ^= 0xD000; // Configure Tx for V.22/Bell 212A 1200bps high band
- CMXRXMODE ^= 0xC000; // Configure Rx for V.22/Bell 212A 1200bps low Band
- }
- else
- {
- CMXTXMODE ^= 0xC000; // Configure Tx for V.22/Bell 212A 1200bps low band
- CMXRXMODE ^= 0xD000; // Configure Rx for V.22/Bell 212A 1200bps high Band
- }
- break;
- }
- // Set up Tx/Rx Gains
- CMXTXMODE ^= (((int) S25) << 9) & 0x0E00; // Extract required Tx level from S25.
- CMXRXMODE ^= (((int) S26) << 9) & 0x0E00; // Extract required Rx level from S26.
- // Set up Tx Guard Tones, Scrambler/Descrambler if required and initially disable Auto Equaliser
- switch(S27 & 0b11110000) // Determine selected protocol
- {
- case PROTB0: case PROTB1: case PROTB4: case PROTB6: // Auto Equaliser will initially be disabled
- if (BERTBAND) // High band operation
- {
- CMXTXMODE ^= (((int) S23) << 1) & 0x0180; // Extract Guard Tone setting from S23.
- }
- CMXTXMODE ^= (((int) S21) >> 1) & 0x0060; // Extract Scrambler setting from S21.
- CMXRXMODE ^= ((int) S21) & 0x00C0; // Extract Descrambler setting from S21.
- break;
- }
- // Set up Tx and Rx for sync mode
- CMXTXMODE ^= 0x001F; // Sync operation using data from Tx Data Buffer
- CMXRXMODE ^= 0x0038; // Sync operation
- wr16_cbus(CMXTXMODE_ADDR, CMXTXMODE); // Update CBUS register
- wr16_cbus(CMXRXMODE_ADDR, CMXRXMODE); // Update CBUS register
- switch(S27 & 0b11110000) // Determine selected protocol
- {
- case PROTB0: case PROTB1: case PROTB4: case PROTB6:
- if (BERTEND)
- {
- Delay1s(2); // 2s Delay
- }
- else
- {
- do
- {
- CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Read CMX868 Status reg and update shadow reg
- if (KEYABORT)
- {
- return;
- }
- DelayMs(50); // Insert 50ms polling delay
- } while(!RXENERGYDET || !CONTA); // Wait until Rx energy and 1's (Bit 7) has been detected
- }
- if ((S27 & 0b11110000) == PROTB0) // If 2400bps QAM is selected need to train at lower speed first
- {
- // Note backchannel will not sync
- CMXTXMODE &= 0x0FFF; // Unmask Tx Mode bit settings
- CMXRXMODE &= 0x0FFF; // Unmask Rx Mode bit settings
- if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
- {
- CMXTXMODE ^= 0xF000; // Now configure Tx for high band 2400bps V.22 bis
- CMXRXMODE ^= 0xE000; // Configure Rx for V.22 bis 2400bps low Band
- }
- else
- {
- CMXTXMODE ^= 0xE000; // Now configure Tx for low band 2400bps V.22 bis
- CMXRXMODE ^= 0xF000; // Configure Rx for V.22 bis 2400bps high band
- }
- wr16_cbus(CMXTXMODE_ADDR,CMXTXMODE); // Update CBUS register
- AUTO_EQU = 1; // Enable Auto Equaliser
- }
- else
- {
- AUTO_EQU = USER_AUTO_EQU; // Extract Auto Equaliser setting from S24.
- }
- wr16_cbus(CMXRXMODE_ADDR,CMXRXMODE); // Update CBUS register
- break;
- }
- }
- void init_bertporta()
- {
- TRISA = CONFIGBERTPA; // Configure Port A for BERT
- }
- void undo_bertporta()
- {
- TRISA = CONFIGPA; // Configure Port A
- }
- void bert_txd()
- {
- bertimer_reload();
- if (!BER_TXDCLK) // If Tx Data clock is low
- {
- BER_TXDCLK = 1; // Set Tx Data clock hi
- return;
- }
- if (BERCNT != 1)
- {
- read_bertxdata();
- return;
- }
- if (!BERTXRDY)
- {
- read_bertxdata();
- }
- }
- void read_bertxdata()
- {
- BER_TXDCLK = 0; // !!!!!!!!!!!!!!!!!!!!! Becareful may be close to successive I/O port problem
- // I don't think you can read BER_TXD straight away
- BERTXBYTE >>= 1; // Shift carry bit into MSB of byte under construction.
- BERTXBYTE &= 0b01111111;
- if (BER_TXD)
- {
- BERTXBYTE ^= 0b10000000;
- }
- BERCNT--; // Decrement BERT Tx bit counter
- if (BERCNT == 0) // If BERT Tx bit counter is zero
- {
- CMXTXDATA = BERTXBYTE; // Copy temporary BER Tx byte to new BER Tx Byte
- BERCNT = 8; // Reload BERT Tx bit counter
- BERTXRDY = 1; // Set flag to indicate a new BER Tx byte has been constructed
- }
- }
- void modify_rxd()
- {
- CMXRXDATA >>= 1; // Shift Rx Data byte right 1 bit so LSB falls off into the carry bit.
- BER_RXD = CARRY; // Set BER RXD line to mirror carry bit
- BERCNT--; // Decrement BERT Rx bit counter
- if (BERCNT == 0) // If BERT Rx bit counter is zero
- {
- BERRXDATACLR = 1; // Set flag to indicate a BER Rx byte has been emptied
- }
- }
- void bert_rxd()
- {
- bertimer_reload();
- if (BER_RXDCLK) // If Rx Data clock is hi
- {
- BER_RXDCLK = 0; // Set Rx Data clock lo
- return;
- }
- if (!BERRXDATACLR)
- {
- modify_rxd(); // Modify the BER RXD line appropriately
- BER_RXDCLK = 1; // Set Rx Data clock hi
- }
- }
- void bertimer_reload()
- {
- TMR0 = 151 + BERTMR0ADJ; // TMR0 start count (will cause interrupt on overflow)
- T0IF = 0; // Clear the interrupt flag
- }
- void bertimer_init()
- {
- T0CS = 0; // Timer increments on instruction clock
- PSA=0; // Assign Prescaler to TMR0
- BERTMR0ADJ = 18; // Initially set TMR0 adjustment variable for accurate 1200bps timing
- switch(S27 & 0b11110000)
- {
- case PROTB0:
- PS2=0; // 2400bps - Prescaler 1:2 TMR0
- PS1=0;
- PS0=0;
- BERTMR0ADJ = 36; // Adjust TMR0 to give accurate timing at 2400bps
- break;
- case PROTB2:
- PS2=1; // 75bps - Prescaler 1:64 TMR0
- PS1=0;
- PS0=1;
- BERTMR0ADJ = 1; // Adjust TMR0 to give accurate timing at 75bps
- break;
- case PROTB4:
- PS2=0; // 600bps - Prescaler 1:8 TMR0
- PS1=1;
- PS0=0;
- BERTMR0ADJ = 9; // Adjust TMR0 to give accurate timing at 600bps
- break;
- case PROTB5: case PROTB9:
- PS2=0; // 300bps - Prescaler 1:16 TMR0
- PS1=1;
- PS0=1;
- BERTMR0ADJ = 5; // Adjust TMR0 to give accurate timing at 300bps
- break;
- case PROTB7:
- PS2=1; // 150bps - Prescaler 1:32 TMR0
- PS1=0;
- PS0=0;
- BERTMR0ADJ = 3; // Adjust TMR0 to give accurate timing at 150bps
- break;
- default:
- PS2=0; // Default 1200bps - Prescaler 1:4 TMR0
- PS1=0;
- PS0=1;
- break;
- }
- TMR0 = 151 + BERTMR0ADJ; // TMR0 start count (will cause interrupt on overflow)
- T0IF = 0; // Clear the interrupt flag
- T0IE = 1; // Enable interrupt on TMR0 overflow
- }