bert.c
上传用户:lilishw
上传日期:2021-05-28
资源大小:1542k
文件大小:17k
源码类别:

Modem编程

开发平台:

Visual C++

  1. //---------------------------------------------------------------------------------------------------
  2. //  Project:-   DE8681
  3. //  Filename:-  BERT.C
  4. //  Description:-   BERT routines for CMX868.
  5. //  Programmer:-    D.T.F   
  6. //  Version:-   2.0
  7. //  Created:-   28th February 2002
  8. //  Last modified:- 
  9. //---------------------------------------------------------------------------------------------------
  10. //  (C) Consumer Microcircuits Ltd 2002
  11. //
  12. //  This firmware was designed by:-
  13. //          Consumer Microcircuits Ltd,
  14. //          Langford, Maldon,
  15. //          ESSEX
  16. //          CM9 6WG.
  17. //  in the UK for use with CML evaluation kits only and is based on UK originated technology.
  18. //  Please contact
  19. //          sales@cmlmicro.co.uk
  20. //          +44 (0)1621 875500
  21. //  for licensing details.
  22. //---------------------------------------------------------------------------------------------------
  23. #define BERT_C
  24. #include    "ef8681.h"
  25. void bert()
  26. {
  27.     init_bertporta();                       // Configure and initialise Port A ready BERT
  28.     if (DATAXFER)
  29.     {
  30.         CMXTXMODE &= 0xFFE0;                    // Unmask Tx data format bit settings
  31.         CMXTXMODE ^= 0x001F;                    // Sync operation and data bytes from Tx Data Buffer 
  32.         wr16_cbus(CMXTXMODE_ADDR, CMXTXMODE);   // Update CBUS register
  33.         CMXRXMODE &= 0xFFC7;                    // Unmask Rx USART bit settings
  34.         CMXRXMODE ^= 0x0038;                    // Sync operation
  35.         wr16_cbus(CMXRXMODE_ADDR, CMXRXMODE);   // Update CBUS register
  36.     }
  37.     else
  38.     {
  39.         bert868_init();                         // Initialise CMX868 ready for BERT Tx
  40.     }
  41.     CMXGENCTRL &= 0xFF00;
  42.     if (BERTEND)
  43.     {
  44.         CMXGENCTRL ^= 0x0048;                   // Set bits for IRQN enable and Tx irq
  45.     }
  46.     else
  47.     {
  48.         CMXGENCTRL ^= 0x0041;                   // Set bits for IRQN enable and Rx irq
  49.     }
  50.     wr16_cbus(CMXGENCTRL_ADDR, CMXGENCTRL); // Update CBUS register
  51.     bertimer_init();                        // Initialise BER timer
  52.     if (BERTEND)                            // If BERT Tx end (only Tx irq will have been enabled)
  53.     {
  54.         BERTXBYTE = 0;                      // Clear temporary BER Tx byte under construction
  55.         wr_cbus(CMXTXDATA_ADDR, 0xFF);          
  56.         do
  57.         {
  58.             if (!PICIRQN)                   // If IRQN line goes low we can assume Tx Rdy flag is set
  59.             {
  60.                 CMXSTAT = rd16_cbus(CMXSTAT_ADDR);      // Update Status shadow register and clear irq
  61.                 while (!BERTXRDY)
  62.                 {
  63.                     bert_txd();
  64.                 }
  65.                 wr_cbus(CMXTXDATA_ADDR, CMXTXDATA); // Write Tx Data to CMX868 reg                                      
  66.                 BERTXRDY = 0;               // Clear BER Tx Ready flag
  67.             }
  68.         } while (!KEYABORT);                    // Loop until key pushed
  69.     }
  70.     else                                // Otherwise assume BERT Rx end (Tx and Rx irq will have been enabled)
  71.     {
  72.         BER_RXDCLK = 1;                     // Initially set BER Rx data clock hi
  73.         CMXSTAT = rd16_cbus(CMXSTAT_ADDR);  // Update Status shadow register and clear irq
  74.         CMXRXDATA = rd_cbus(CMXRXDATA_ADDR);    // Read CMX868 Rx Data reg and update shadow reg
  75.         BERCNT = 8;                         // Reload BER rx bit counter
  76.         BERRXDATACLR = 0;                   // Clear flag to indicate bit extraction required
  77.         do
  78.         {
  79.             if (!PICIRQN)                   // If IRQN line goes low we can assume Rx Rdy flag is set
  80.             {
  81.                 while (!BERRXDATACLR)
  82.                 {
  83.                     bert_rxd();
  84.                 }
  85.                 CMXSTAT = rd16_cbus(CMXSTAT_ADDR);      // Update Status shadow register and clear irq
  86.                 CMXRXDATA = rd_cbus(CMXRXDATA_ADDR);    // Read CMX868 Rx Data reg and update shadow reg
  87.                 BERCNT = 8;                 // Reload BER rx bit counter
  88.                 BERRXDATACLR = 0;           // Clear flag to indicate bit extraction required
  89.                 bert_rxd();
  90.             }
  91.         } while (!KEYABORT);                // Loop until key pushed
  92.     }   
  93.     BERTFLAG = 0;                           // Clear BERT flag
  94.     KEYABORT = 0;                           // Reset key abort flag
  95. }
  96. void bert868_init()                         // Setup CMX868 for BERT
  97. {
  98.     reset_cbus();                           // Reset the CBUS before we start, will clear all shadow write registers
  99.     pwrup();                                // Power Up CMX868 with correct Xtal and fixed equalisers initially enabled.
  100.     
  101.     FIX_EQU = USER_FIX_EQU;                     // Extract required Tx and Rx Fixed Equaliser settings from S24.
  102.     wr16_cbus(CMXGENCTRL_ADDR, CMXGENCTRL);             // Update CBUS register
  103.     CMXTXDATA = 0xFF;                       // Initially load 1's into Tx Data
  104.     wr_cbus(CMXTXDATA_ADDR,CMXTXDATA);              // Update CBUS register
  105.     // Set up Tx/Rx operating modes
  106.     switch(S27 & 0b11110000)                    // Determine selected protocol
  107.     {
  108.         case PROTB2:
  109.             if (BERTEND)
  110.             {
  111.                 CMXTXMODE ^= 0x4000;            // Configure Tx for V.23 75bps
  112.                 CMXRXMODE ^= 0x5000;            // Configure Rx for V.23 1200bps
  113.             }
  114.             else
  115.             {
  116.                 CMXRXMODE ^= 0x4000;            // Configure Rx for V.23 75bps
  117.                 CMXTXMODE ^= 0x5000;            // Configure Tx for V.23 1200bps
  118.             }
  119.             break;
  120.         case PROTB3:
  121.             if (BERTEND)
  122.             {
  123.                 CMXTXMODE ^= 0x5000;            // Configure Tx for V.23 1200bps
  124.                 CMXRXMODE ^= 0x4000;            // Configure Rx for V.23 75bps
  125.             }
  126.             else
  127.             {
  128.                 CMXRXMODE ^= 0x5000;            // Configure Rx for V.23 1200bps
  129.                 CMXTXMODE ^= 0x4000;            // Configure Tx for V.23 75bps
  130.             }
  131.             break;
  132.         case PROTB4:
  133.             if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
  134.             {
  135.                 CMXTXMODE ^= 0xB000;            // Configure Tx for V.22 600bps high band
  136.                 CMXRXMODE ^= 0xA000;            // Configure Rx for V.22 600bps low band
  137.             }
  138.             else
  139.             {
  140.                 CMXTXMODE ^= 0xA000;            // Configure Tx for V.22 600bps low band
  141.                 CMXRXMODE ^= 0xB000;            // Configure Rx for V.22 600bps high band
  142.             }
  143.             break;
  144.         case PROTB5:
  145.             if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
  146.             {
  147.                 CMXTXMODE ^= 0x9000;            // Configure Tx for V.21 300bps high band
  148.                 CMXRXMODE ^= 0x8000;            // Configure Rx for V.21 300bps low band
  149.             }
  150.             else
  151.             {
  152.                 CMXTXMODE ^= 0x8000;            // Configure Tx for V.21 300bps low band
  153.                 CMXRXMODE ^= 0x9000;            // Configure Rx for V.21 300bps high band
  154.             }
  155.             break;
  156.         case PROTB7:
  157.             if (BERTEND)
  158.             {
  159.                 CMXTXMODE ^= 0x2000;            // Configure Tx for Bell 202 150bps
  160.                 CMXRXMODE ^= 0x3000;            // Configure Rx for Bell 202 1200bps
  161.             }
  162.             else
  163.             {
  164.                 CMXRXMODE ^= 0x2000;            // Configure Rx for Bell 202 150bps
  165.                 CMXTXMODE ^= 0x3000;            // Configure Tx for Bell 202 1200bps
  166.             }
  167.             break;
  168.         case PROTB8:
  169.             if (BERTEND)
  170.             {
  171.                 CMXTXMODE ^= 0x3000;            // Configure Tx for Bell 202 1200bps
  172.                 CMXRXMODE ^= 0x2000;            // Configure Rx for Bell 202 150bps
  173.             }
  174.             else
  175.             {
  176.                 CMXRXMODE ^= 0x3000;            // Configure Rx for Bell 202 1200bps
  177.                 CMXTXMODE ^= 0x2000;            // Configure Tx for Bell 202 150bps
  178.             }
  179.             break;
  180.         case PROTB9:
  181.             if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
  182.             {
  183.                 CMXTXMODE ^= 0x7000;            // Configure Tx for Bell 103 high band
  184.                 CMXRXMODE ^= 0x6000;            // Configure Rx for Bell 103 low band
  185.             }
  186.             else
  187.             {
  188.                 CMXTXMODE ^= 0x6000;            // Configure Tx for Bell 103 low band
  189.                 CMXRXMODE ^= 0x7000;            // Configure Rx for Bell 103 high band
  190.             }
  191.             break;
  192.         default:
  193.             if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
  194.             {
  195.                 CMXTXMODE ^= 0xD000;            // Configure Tx for V.22/Bell 212A 1200bps high band
  196.                 CMXRXMODE ^= 0xC000;            // Configure Rx for V.22/Bell 212A 1200bps low Band
  197.             }
  198.             else
  199.             {
  200.                 CMXTXMODE ^= 0xC000;            // Configure Tx for V.22/Bell 212A 1200bps low band
  201.                 CMXRXMODE ^= 0xD000;            // Configure Rx for V.22/Bell 212A 1200bps high Band
  202.             }
  203.             break;
  204.     }
  205.     // Set up Tx/Rx Gains
  206.     CMXTXMODE ^= (((int) S25) << 9) & 0x0E00;           // Extract required Tx level from S25.
  207.     CMXRXMODE ^= (((int) S26) << 9) & 0x0E00;           // Extract required Rx level from S26.
  208.     // Set up Tx Guard Tones, Scrambler/Descrambler if required and initially disable Auto Equaliser
  209.     switch(S27 & 0b11110000)                    // Determine selected protocol
  210.     {
  211.         case PROTB0: case PROTB1: case PROTB4: case PROTB6: // Auto Equaliser will initially be disabled
  212.             if (BERTBAND)                   // High band operation
  213.             {
  214.                 CMXTXMODE ^= (((int) S23) << 1) & 0x0180;   // Extract Guard Tone setting from S23.
  215.             }
  216.             CMXTXMODE ^= (((int) S21) >> 1) & 0x0060;   // Extract Scrambler setting from S21.
  217.             CMXRXMODE ^= ((int) S21) & 0x00C0;      // Extract Descrambler setting from S21.
  218.             break;
  219.     }
  220.     // Set up Tx and Rx for sync mode
  221.     CMXTXMODE ^= 0x001F;                        // Sync operation using data from Tx Data Buffer
  222.     CMXRXMODE ^= 0x0038;                        // Sync operation
  223.     wr16_cbus(CMXTXMODE_ADDR, CMXTXMODE);               // Update CBUS register
  224.     wr16_cbus(CMXRXMODE_ADDR, CMXRXMODE);               // Update CBUS register
  225.     switch(S27 & 0b11110000)                    // Determine selected protocol
  226.     {
  227.         case PROTB0: case PROTB1: case PROTB4: case PROTB6:
  228.             if (BERTEND)
  229.             {
  230.                 Delay1s(2);             // 2s Delay
  231.             }
  232.             else
  233.             {
  234.                 do
  235.                 {
  236.                     CMXSTAT = rd16_cbus(CMXSTAT_ADDR);  // Read CMX868 Status reg and update shadow reg
  237.                     if (KEYABORT)
  238.                     {
  239.                         return;
  240.                     }
  241.                     DelayMs(50);            // Insert 50ms polling delay
  242.                 } while(!RXENERGYDET || !CONTA);    // Wait until Rx energy and 1's (Bit 7) has been detected
  243.             }
  244.             if ((S27 & 0b11110000) == PROTB0) // If 2400bps QAM is selected need to train at lower speed first
  245.             {
  246.                 // Note backchannel will not sync
  247.                 CMXTXMODE &= 0x0FFF;            // Unmask Tx Mode bit settings
  248.                 CMXRXMODE &= 0x0FFF;            // Unmask Rx Mode bit settings
  249.                 if ((BERTEND && BERTBAND) || (!BERTEND && !BERTBAND))
  250.                 {
  251.                     CMXTXMODE ^= 0xF000;        // Now configure Tx for high band 2400bps V.22 bis
  252.                     CMXRXMODE ^= 0xE000;        // Configure Rx for V.22 bis 2400bps low Band
  253.                 }
  254.                 else
  255.                 {
  256.                     CMXTXMODE ^= 0xE000;        // Now configure Tx for low band 2400bps V.22 bis
  257.                     CMXRXMODE ^= 0xF000;        // Configure Rx for V.22 bis 2400bps high band
  258.                 }
  259.                 wr16_cbus(CMXTXMODE_ADDR,CMXTXMODE);        // Update CBUS register
  260.                 AUTO_EQU = 1;                   // Enable Auto Equaliser
  261.             }
  262.             else
  263.             {
  264.                 AUTO_EQU = USER_AUTO_EQU;       // Extract Auto Equaliser setting from S24.
  265.             }
  266.             wr16_cbus(CMXRXMODE_ADDR,CMXRXMODE);        // Update CBUS register
  267.             break;
  268.     }
  269. }
  270. void init_bertporta()
  271. {
  272.     TRISA = CONFIGBERTPA;                       // Configure Port A for BERT
  273. }
  274. void undo_bertporta()
  275. {
  276.     TRISA = CONFIGPA;                       // Configure Port A
  277. }
  278. void bert_txd()
  279. {
  280.     bertimer_reload();
  281.     if (!BER_TXDCLK)                        // If Tx Data clock is low
  282.     {
  283.         BER_TXDCLK = 1;                     // Set Tx Data clock hi
  284.         return;
  285.     }
  286.     if (BERCNT != 1)
  287.     {
  288.         read_bertxdata();   
  289.         return;
  290.     }
  291.     if (!BERTXRDY)
  292.     {
  293.         read_bertxdata();
  294.     }
  295. }
  296. void read_bertxdata()
  297. {
  298.     BER_TXDCLK = 0;                         // !!!!!!!!!!!!!!!!!!!!! Becareful may be close to successive I/O port problem
  299.                                     // I don't think you can read BER_TXD straight away 
  300.     BERTXBYTE >>= 1;                        // Shift carry bit into MSB of byte under construction.
  301.     BERTXBYTE &= 0b01111111;
  302.     if (BER_TXD)
  303.     {
  304.         BERTXBYTE ^= 0b10000000;
  305.     }
  306.     BERCNT--;                           // Decrement BERT Tx bit counter
  307.     if (BERCNT == 0)                    // If BERT Tx bit counter is zero 
  308.     {
  309.         CMXTXDATA = BERTXBYTE;          // Copy temporary BER Tx byte to new BER Tx Byte
  310.         BERCNT = 8;                     // Reload BERT Tx bit counter
  311.         BERTXRDY = 1;                   // Set flag to indicate a new BER Tx byte has been constructed
  312.     }
  313. }
  314. void modify_rxd()
  315. {
  316.     CMXRXDATA >>= 1;                        // Shift Rx Data byte right 1 bit so LSB falls off into the carry bit.
  317.     BER_RXD = CARRY;                        // Set BER RXD line to mirror carry bit
  318.     BERCNT--;                               // Decrement BERT Rx bit counter
  319.     if (BERCNT == 0)                        // If BERT Rx bit counter is zero 
  320.     {
  321.         BERRXDATACLR = 1;                   // Set flag to indicate a BER Rx byte has been emptied
  322.     }
  323. }
  324. void bert_rxd()
  325. {
  326.     bertimer_reload();
  327.     if (BER_RXDCLK)                         // If Rx Data clock is hi
  328.     {
  329.         BER_RXDCLK = 0;                     // Set Rx Data clock lo
  330.         return;
  331.     }
  332.     if (!BERRXDATACLR)
  333.     {
  334.         modify_rxd();                       // Modify the BER RXD line appropriately
  335.         BER_RXDCLK = 1;                     // Set Rx Data clock hi
  336.     }   
  337. }
  338. void bertimer_reload()
  339. {
  340.     TMR0 = 151 + BERTMR0ADJ;                // TMR0 start count (will cause interrupt on overflow)
  341.     T0IF = 0;                               // Clear the interrupt flag
  342. }
  343. void bertimer_init()
  344. {
  345.     T0CS = 0;                           // Timer increments on instruction clock
  346.     PSA=0;                              // Assign Prescaler to TMR0
  347.     BERTMR0ADJ = 18;                    // Initially set TMR0 adjustment variable for accurate 1200bps timing
  348.     switch(S27 & 0b11110000)
  349.     {
  350.         case PROTB0:
  351.             PS2=0;                      // 2400bps - Prescaler 1:2 TMR0
  352.             PS1=0;
  353.             PS0=0;
  354.             BERTMR0ADJ = 36;            // Adjust TMR0 to give accurate timing at 2400bps
  355.             break;
  356.         case PROTB2:
  357.             PS2=1;                      // 75bps - Prescaler 1:64 TMR0
  358.             PS1=0;
  359.             PS0=1;
  360.             BERTMR0ADJ = 1;             // Adjust TMR0 to give accurate timing at 75bps
  361.             break;
  362.         case PROTB4:
  363.             PS2=0;                      // 600bps - Prescaler 1:8 TMR0
  364.             PS1=1;
  365.             PS0=0;
  366.             BERTMR0ADJ = 9;             // Adjust TMR0 to give accurate timing at 600bps
  367.             break;
  368.         case PROTB5: case PROTB9:
  369.             PS2=0;                      // 300bps - Prescaler 1:16 TMR0
  370.             PS1=1;
  371.             PS0=1;
  372.             BERTMR0ADJ = 5;             // Adjust TMR0 to give accurate timing at 300bps
  373.             break;
  374.         case PROTB7:
  375.             PS2=1;                      // 150bps - Prescaler 1:32 TMR0
  376.             PS1=0;
  377.             PS0=0;
  378.             BERTMR0ADJ = 3;             // Adjust TMR0 to give accurate timing at 150bps
  379.             break;
  380.         default:
  381.             PS2=0;                      // Default 1200bps - Prescaler 1:4 TMR0
  382.             PS1=0;
  383.             PS0=1;
  384.             break;
  385.     }
  386.     TMR0 = 151 + BERTMR0ADJ;            // TMR0 start count (will cause interrupt on overflow)
  387.     T0IF = 0;                           // Clear the interrupt flag
  388.     T0IE = 1;                           // Enable interrupt on TMR0 overflow
  389. }