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

Modem编程

开发平台:

Visual C++

  1. //---------------------------------------------------------------------------------------------------
  2. //  Project:-       DE8681
  3. //  Filename:-      ATCMD.C
  4. //  Description:-   Routines for AT Command Functions and Interpretation.
  5. //  Programmer:-    D.T.F   
  6. //  Version:-       3.0
  7. //  Created:-       28th February 2002
  8. //  Last modified:- 1/12/2003 (M.T)
  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 ATCMD_C
  24. #include    "ef8681.h"
  25. unsigned char atcmd_interpret(void)
  26. {
  27.     unsigned char retval;
  28.     ATBUFPTR = 0;
  29.     while (ATBUF[ATBUFPTR] != NUL)              // Check if NULL encountered to indicate end of AT command.
  30.     {   
  31.         switch(ATBUF[ATBUFPTR])
  32.         {
  33.             case 'A': case 'a':
  34.                 retval = atacmd();  // Routine sets Answer flag in S register
  35.                                     // AT Command Mode Flag cleared to indicate Handshaking
  36.                 break;
  37.             case 'B': case 'b':
  38.                 retval = atbcmd();  // Routine to control communication standard
  39.                 break;
  40.             case 'D': case 'd':
  41.                 retval = atdcmd();  // Routine to extract DTMF digits and set Call flag in S register
  42.                                     // AT Command Mode Flag cleared to indicate Handshaking
  43.                 break;
  44.             case 'E': case'e':
  45.                 retval = atecmd();      // Routine to control echo
  46.                 break;
  47.             case 'H': case'h':
  48.                 retval = athcmd();      // Routine to control hook switch
  49.                 break;
  50.             case 'I': case'i':
  51.                 retval = aticmd();      // Routine to provide user product information
  52.                 break;
  53.             case 'N': case'n':
  54.                 retval = atncmd();      // Routine to enable/disable modulation fallback
  55.                 break;
  56.             case 'O': case'o':
  57.                 retval = atocmd();      // Routine to revert back to online mode
  58.                 break;
  59.             case 'Q': case'q':
  60.                 retval = atqcmd();      // Routine to control Modem responses
  61.                 break;
  62.             case 'S': case's':
  63.                 retval = atscmd();      // Routine to write or read S-Registers
  64.                 break;
  65.             case 'V': case'v':
  66.                 retval = atvcmd();      // Routine to control result code format
  67.                 break;
  68.             case 'X': case'x':
  69.                 retval = atxcmd();      // Routine to control calling characteristics
  70.                 break;
  71.             case 'Z': case'z':
  72.                 retval = atzcmd();      // Routine to reset modem and restore factory profiles
  73.                 break;
  74.             case '&':
  75.                 retval = xatcmd();      // Routine to excute extended AT Commands
  76.                 break;
  77.             case '@':
  78.                 retval = cmlatcmd();    // Routine to excute CML specific AT Commands
  79.                 break;
  80.             default:
  81.                 retval = ERROR;
  82.                 break;
  83.         }
  84.         // If an error occurs during interpretation
  85.         // or Manual Answer or Dial has been requested
  86.         // AT Command interpretation will be terminated
  87.         if (retval != OK)
  88.         {
  89.             return (retval);
  90.         }
  91.         ATBUFPTR++;                 // Increment AT Command Buffer pointer.
  92.     }   
  93.     return (OK);                    // Intepretation has completed successfully or no commands had been entered.
  94. }
  95. unsigned char atacmd(void)
  96. {
  97.     ATCMDMODE = 0;
  98.     ANSORIG = 0;                    // Set to indicate answering
  99.     return (NORESULT);
  100. }
  101. unsigned char atbcmd(void)          // Modify Call Characteristic bits located in S27 reg
  102. {
  103.     unsigned char tempreg;
  104.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  105.     switch(ATBUF[ATBUFPTR])
  106.     {
  107.         case '0':
  108.             tempreg = PROTB0;
  109.             break;
  110.         case '1':
  111.             tempreg = PROTB1;
  112.             break;
  113.         case '2':
  114.             tempreg = PROTB2;
  115.             break;
  116.         case '3':
  117.             tempreg = PROTB3;
  118.             break;
  119.         case '4':
  120.             tempreg = PROTB4;
  121.             break;
  122.         case '5':
  123.             tempreg = PROTB5;
  124.             break;
  125.         case '6':
  126.             tempreg = PROTB6;
  127.             break;
  128.         case '7':
  129.             tempreg = PROTB7;
  130.             break;
  131.         case '8':
  132.             tempreg = PROTB8;
  133.             break;
  134.         case '9':
  135.             tempreg = PROTB9;
  136.             break;
  137.         default:
  138.             return (ERROR);             // Return ERROR to indicate invalid character
  139.     }
  140.     S27 &= 0b00001111;                  // Clear existing Protocol settings 
  141.     S27 ^= tempreg;                     // Modify S27 to reflect new settings
  142.     return (OK);                        // Return OK to indicate success
  143. }
  144. unsigned char atdcmd(void)
  145. {
  146.     unsigned char   i, tmp;
  147.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  148.     tmp = ATBUF[ATBUFPTR];                  // Load temporary character register
  149.     if ((tmp == 'L') || (tmp == 'l'))
  150.     {
  151.         if (TELNUM[0] != NUL)
  152.         {
  153.             ATCMDMODE = 0;              // Clear AT Command Mode Flag
  154.             ANSORIG = 1;                // Set to indicate originate
  155.             return (NORESULT);          // Return NORESULT to indicate success without result code.
  156.         }
  157.         else
  158.         {
  159.             return (ERROR);             // Return ERROR to indicate no previous telephone number exists
  160.         }
  161.     }
  162.     i = 0;
  163.     while ((tmp <= '9' && tmp >= '0') || (tmp <= 'D' && tmp >= 'A')
  164.         || (tmp <= 'd' && tmp >= 'a') || tmp == '#' || tmp == '*' || tmp == ',')
  165.     {
  166.         TELNUM[i++] = tmp;              // Load character into telephone digit buffer
  167.         if (i >= maxteldigits)
  168.         {
  169.             TELNUM[0] = NUL;            // Destroy previous loaded digits due to error
  170.             return(ERROR);              // Return ERROR to indicate telephone digit buffer is full
  171.         }
  172.         ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  173.         tmp = ATBUF[ATBUFPTR];          // Load temporary character register
  174.     }
  175.     if (i > 0)
  176.     {
  177.         ATBUFPTR--;                     // Decrement AT Command Buffer pointer (not essential because interpreter will be terminated)
  178.         TELNUM[i] = NUL;                // Null terminate telephone digit string
  179.         ATCMDMODE = 0;                  // Clear AT Command Mode Flag
  180.         ANSORIG = 1;                    // Set to indicate originate
  181.         return(NORESULT);               // Return NORESULT to indicate success without result code.
  182.     }
  183.     else
  184.     {
  185.         return (ERROR);                 // Return ERROR to indicate no previous telephone number exists
  186.     }
  187. }
  188. unsigned char atecmd(void)                  // Modify Echo Character bit located in S14 reg
  189. {
  190.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  191.     switch(ATBUF[ATBUFPTR])
  192.     {
  193.         case '0':
  194.             ECHO = OFF;             // Disable Echoing
  195.             break;
  196.         case '1':
  197.             ECHO = ON;              // Enable Echoing
  198.             break;
  199.         default:
  200.             return (ERROR);             // Return ERROR to indicate invalid character
  201.     }
  202.     return (OK);                        // Return OK to indicate success
  203. }
  204. unsigned char athcmd(void)                  // Hook switch control
  205. {
  206.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  207.     switch(ATBUF[ATBUFPTR])
  208.     {
  209.         case '0':
  210.             hook(0);                // On-Hook
  211.             break;
  212.         case '1':
  213.             hook(1);                // Off-Hook
  214.             break;
  215.         default:
  216.             return (ERROR);             // Return ERROR to indicate invalid character
  217.     }
  218.     return (OK);                        // Return OK to indicate success
  219. }
  220. unsigned char aticmd(void)                  // Send information to terminal
  221. {
  222.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  223.     switch(ATBUF[ATBUFPTR])
  224.     {
  225.         case '0':
  226.             genmsgtopc(idmsg);          // Send id message to terminal
  227.             break;
  228.         case '1':
  229.             genmsgtopc(prodmsg);            // Send product message to terminal
  230.             break;
  231.         case '2':
  232.             genmsgtopc(cmlukmsg);           // Send CML UK message to terminal
  233.             genmsgtopc(cmlukwwwmsg);        // Send CML UK Web address message to terminal
  234.             genmsgtopc(cmlukemmsg);         // Send CML UK Email address message to terminal
  235.             genmsgtopc(cmluktelmsg);        // Send CML UK Telephone message to terminal
  236.             break;
  237.         case '3':
  238.             genmsgtopc(cmlsgmsg);           // Send CML Singapore message to terminal
  239.             genmsgtopc(cmlsgemmsg);         // Send CML Singapore Email address message to terminal
  240.             break;
  241.         case '4':
  242.             genmsgtopc(mxcommsg);           // Send MX-COM message to terminal
  243.             genmsgtopc(mxcomemmsg);         // Send MXCOM Email address message to terminal
  244.             break;
  245.         default:
  246.             return (ERROR);             // Return ERROR to indicate invalid character
  247.     }
  248.     return (OK);                        // Return OK to indicate success
  249. }
  250. unsigned char atncmd(void)
  251. {
  252.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  253.     switch(ATBUF[ATBUFPTR])
  254.     {
  255.         case '0':
  256.             FALLBACK = OFF;             // Disable Modulation Fallback
  257.             break;
  258.         case '1':
  259.             FALLBACK = ON;              // Enable Modulation Fallback
  260.             break;
  261.         default:
  262.             return (ERROR);             // Return ERROR to indicate invalid character
  263.     }
  264.     return (OK);                        // Return OK to indicate success
  265. }
  266. unsigned char atocmd(void)
  267. {
  268.     DATAXFER = 1;                       // Revert back to online data transfer mode
  269.     ATCMDMODE = 0;
  270.     return (NORESULT);
  271. }
  272. unsigned char atqcmd(void)                  // Modify Response bit located in S14 reg
  273. {
  274.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  275.     switch(ATBUF[ATBUFPTR])
  276.     {
  277.         case '0':
  278.             RESOFF = FALSE;             // Enable result code responses
  279.             break;
  280.         case '1':
  281.             RESOFF = TRUE;              // Disable result code responses
  282.             break;
  283.         default:
  284.             return (ERROR);             // Return ERROR to indicate invalid character
  285.     }
  286.     return (OK);                        // Return OK to indicate success
  287. }
  288. unsigned char atscmd(void)
  289. {
  290.     unsigned long i;
  291.     unsigned char k=0;
  292.     char tempbuf[3];
  293.     volatile unsigned char bank2 * sregptr;
  294.     unsigned char sreg_offset;
  295.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  296.     if ((ATBUF[ATBUFPTR] > '9') || (ATBUF[ATBUFPTR] < '0'))
  297.     {
  298.         return(ERROR);
  299.     }
  300.     tempbuf[k++] = ATBUF[ATBUFPTR++];
  301.     if ((ATBUF[ATBUFPTR] <= '9') && (ATBUF[ATBUFPTR] >= '0'))
  302.     {
  303.         tempbuf[k++] = ATBUF[ATBUFPTR++];
  304.     }
  305.     tempbuf[k] = NUL;
  306.     sreg_offset = (atoi(tempbuf)) & 0xFF;           // Convert ASCII decimal to integer
  307.     
  308.     if (sreg_offset >= numsregs)                // Return ERROR if offset exceeds max value
  309.     {                           // specified in header file
  310.         return(ERROR);
  311.     }
  312.     sregptr = &S0;
  313.     sregptr += sreg_offset;
  314.     if (ATBUF[ATBUFPTR] == '=')
  315.     {
  316.         ATBUFPTR++;                 // Increment AT Command Buffer pointer.
  317.         i = ascregtolong();
  318.         if (i > 255)                    // If 8-bit register exceeds 255 return error.
  319.         {
  320.             return (ERROR);
  321.         }
  322.         *sregptr = i;
  323.     }
  324.     else if (ATBUF[ATBUFPTR] == '?')
  325.     {
  326.         if (HEXOP)
  327.         {
  328.             hexnum2scrn(*sregptr,2,WORDRES);    // Send LF char if word results enabled
  329.         }
  330.         else
  331.         {
  332.             decnum2scrn(*sregptr,3,WORDRES);    // Send LF char if word results enabled
  333.         }
  334.     }
  335.     else
  336.     {
  337.         return (ERROR);                 // Return ERROR to indicate invalid character
  338.     }
  339.     return (OK);                        // Return OK to indicate success
  340. }
  341. unsigned char atvcmd(void)                  // Modify Word Response bit located in S14 reg
  342. {
  343.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  344.     switch(ATBUF[ATBUFPTR])
  345.     {
  346.         case '0':
  347.             WORDRES = OFF;              // Enable number responses
  348.             break;
  349.         case '1':
  350.             WORDRES = ON;               // Enable Word responses
  351.             break;
  352.         default:
  353.             return (ERROR);             // Return ERROR to indicate invalid character
  354.     }
  355.     return (OK);                        // Return OK to indicate success
  356. }
  357. unsigned char atxcmd(void)                  // Modify Call Characteristic bits located in S22 reg
  358. {
  359.     unsigned char tempreg;
  360.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  361.     switch(ATBUF[ATBUFPTR])
  362.     {
  363.         case '0':
  364.             tempreg = X0CALLING;
  365.             break;
  366.         case '1':
  367.             tempreg = X1CALLING;
  368.             break;
  369.         case '2':
  370.             tempreg = X2CALLING;
  371.             break;
  372.         case '3':
  373.             tempreg = X3CALLING;
  374.             break;
  375.         case '4':
  376.             tempreg = X4CALLING;
  377.             break;
  378.         default:
  379.             return (ERROR);             // Return ERROR to indicate invalid character
  380.     }
  381.     S22 &= 0b00011111;                  // Clear existing calling characteristics 
  382.     S22 ^= tempreg;                     // Modify S22 to reflect new settings
  383.     return (OK);                        // Return OK to indicate success
  384. }
  385. unsigned char atzcmd(void)                  // Reset Modem and recall factory profile
  386. {
  387.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  388.     switch(ATBUF[ATBUFPTR])
  389.     {
  390.         case '0':
  391.             init_sregs(0);              // Recall factory profile 0.
  392.             break;
  393.         case '1':
  394.             init_sregs(1);              // Recall factory profile 1.
  395.             break;
  396.         default:
  397.             return (ERROR);             // Return ERROR to indicate invalid character
  398.     }
  399.     reset_cbus();                       // Perform CMX868 General reset and clear device write shadow registers
  400.     return (OK);                        // Return OK to indicate success
  401. }
  402. unsigned char xatcmd(void)
  403. {
  404.     ATBUFPTR++;                     // Increment AT Command Buffer pointer.
  405.     switch(ATBUF[ATBUFPTR])
  406.     {
  407.         case 'F': case 'f':
  408.             return (xatfcmd());
  409.         case 'G': case 'g':
  410.             return (xatgcmd());
  411.         default:
  412.             return (ERROR);
  413.     }
  414. }
  415. unsigned char xatfcmd(void)             // Recall factory profile
  416. {
  417.     ATBUFPTR++;                         // Increment AT Command Buffer pointer.
  418.     switch(ATBUF[ATBUFPTR])
  419.     {
  420.         case '0':
  421.             init_sregs(0);              // Recall factory profile 0.
  422.             break;
  423.         case '1':
  424.             init_sregs(1);              // Recall factory profile 1.
  425.             break;
  426.         default:
  427.             return (ERROR);             // Return ERROR to indicate invalid character
  428.     }
  429.     return (OK);                        // Return OK to indicate success
  430. }
  431. unsigned char xatgcmd(void)             // Modify Guard Tone bits located in S23 reg
  432. {
  433.     unsigned char tempreg;
  434.     ATBUFPTR++;                         // Increment AT Command Buffer pointer.
  435.     switch(ATBUF[ATBUFPTR])
  436.     {
  437.         case '0':
  438.             tempreg = NOGUARD;
  439.             break;
  440.         case '1':
  441.             tempreg = GUARD550;
  442.             break;
  443.         case '2':
  444.             tempreg = GUARD1800;
  445.             break;
  446.         default:
  447.             return (ERROR);             // Return ERROR to indicate invalid character
  448.     }
  449.     S23 &= 0b00111111;                  // Clear existing Guard tone settings 
  450.     S23 ^= tempreg;                     // Modify S23 to reflect new settings
  451.     return (OK);                        // Return OK to indicate success
  452. }
  453. unsigned char cmlatcmd(void)
  454. {
  455.     ATBUFPTR++;                         // Increment AT Command Buffer pointer.
  456.     switch(ATBUF[ATBUFPTR])
  457.     {
  458.         case 'F': case 'f':             // CML Test Functions
  459.             return (cmlatfcmd());
  460.         case 'R': case 'r':
  461.             return (cmlatrcmd());       
  462.         case 'D': case 'd':
  463.             TESTFUNC2 = 1;
  464.             pwrup();                    // Leave powersave mode to allow DTMF Tx to operate
  465.             
  466.             // Set DTMF Tx Mode with S25 bits 2-0 selecting Tx Gain,
  467.             // and DTMF twist level set by S28 bits 2-0
  468.             CMXTXMODE = 0x1010 | ((S25 & 0x07) << 9) | ((S28 & 0x07) << 5);                                                      
  469.             return(OK);
  470.         default:
  471.             return (ERROR);
  472.     }
  473. }
  474. unsigned char cmlatfcmd(void)           // CML Test Functions
  475. {
  476.     ATBUFPTR++;                         // Increment AT Command Buffer pointer.
  477.     switch(ATBUF[ATBUFPTR])
  478.     {
  479.         case '0':
  480.             PORTA = 0b00010000;         // Turn off DCDIND LED
  481.             PORTB |= 0b00000110;        // Ensure RIN and DCDN o/p's are set
  482.             hook(0);                    // On-Hook (Hook LED off)
  483.             LED_OVERRIDE = 0;
  484.             break;
  485.         case '1':
  486.             PORTA = 0b00001111;         // Turn on DCDIND, RXDIND, TXDIND, DTRIND and HOOK LEDs
  487.             PORTB &= 0b11111001;        // Clear RIN and DCDN o/p's
  488.             hook(1);                    // Off-Hook (Hook LED on)
  489.             LED_OVERRIDE = 1;
  490.             break;
  491.         case '2':
  492.             DelayMs(100);               // Wait 100ms
  493.             break;
  494.         case '3':
  495.             Delay1s(1);                 // Wait 1s
  496.             break;
  497.         case '4':
  498.             T0IE = 0;                   // Initially disable Timer interrupt
  499.             BERTEND = 0;                // BERT Rx End
  500.             BERTFLAG = 1;               // Set BERT Flag
  501.             break;
  502.         case '5':
  503.             T0IE = 0;                   // Initially disable Timer interrupt
  504.             BERTEND = 1;                // BERT Tx End
  505.             BERTFLAG = 1;               // Set BERT Flag
  506.             break;
  507.         case '6':
  508.             TESTFUNC1 = 1;              // Set Test Function One flag
  509.             break;
  510.         case '7':
  511.             GPT6 = 30;                  // Load GPT6 for 30 second
  512.             while (PICIRQN != 0)
  513.             {
  514.                 if (GPT6 == 0)
  515.                 {
  516.                     return (ERROR);     // Return ERROR to indicate invalid character
  517.                 }
  518.             }
  519.             CMXSTAT = rd16_cbus(CMXSTAT_ADDR);  // Update CMX868 Status Shadow register
  520.             if (HEXOP)
  521.             {
  522.                 hexnum2scrn(CMXSTAT,4,WORDRES); // Send LF char if word results enabled
  523.             }
  524.             else
  525.             {
  526.                 decnum2scrn(CMXSTAT,5,WORDRES); // Send LF char if word results enabled
  527.             }
  528.             break;
  529.         case '8':
  530.             return (NYI);               // Return NYI to indicate function not implemented yet
  531.         case '9':
  532.             return (NYI);               // Return NYI to indicate function not implemented yet
  533.         default:
  534.             return (ERROR);             // Return ERROR to indicate invalid character
  535.     }
  536.     return (OK);                        // Return OK to indicate success
  537. }
  538. unsigned char cmlatrcmd(void)
  539. {
  540.     unsigned int j;
  541.     unsigned long i;
  542.     volatile unsigned char bank3 * byteregptr;
  543.     volatile unsigned int bank3 * wordregptr;
  544.     unsigned char cbus_addr, reg16bit, writereg;
  545.     ATBUFPTR++;                         // Increment AT Command Buffer pointer.
  546.     switch(ATBUF[ATBUFPTR])
  547.     {
  548.         case 'E': case 'e':
  549.             ATBUFPTR++;                 // Increment AT Command Buffer pointer.
  550.             reg16bit = 1;               // Assume 16 bit word unless modified
  551.             writereg = 1;               // Assume write register unless modified
  552.             switch(ATBUF[ATBUFPTR])
  553.             {
  554.                 case '0':
  555.                     cbus_addr = CMXGENCTRL_ADDR;
  556.                     wordregptr = &CMXGENCTRL;
  557.                     break;
  558.                 case '1':
  559.                     cbus_addr = CMXTXMODE_ADDR;
  560.                     wordregptr = &CMXTXMODE;
  561.                     break;
  562.                 case '2':
  563.                     cbus_addr = CMXRXMODE_ADDR;
  564.                     wordregptr = &CMXRXMODE;
  565.                     break;
  566.                 case '3':
  567.                     reg16bit = 0;
  568.                     cbus_addr = CMXTXDATA_ADDR;
  569.                     byteregptr = &CMXTXDATA;
  570.                     break;
  571.                 case '4':
  572.                     reg16bit = 0;
  573.                     cbus_addr = CMXTXDATAV14_ADDR;
  574.                     byteregptr = &CMXTXDATAV14;
  575.                     break;
  576.                 case '5':
  577.                     writereg = 0;
  578.                     reg16bit = 0;
  579.                     cbus_addr = CMXRXDATA_ADDR;
  580.                     byteregptr = &CMXRXDATA;
  581.                     break;
  582.                 case '6':
  583.                     writereg = 0;
  584.                     cbus_addr = CMXSTAT_ADDR;
  585.                     wordregptr = &CMXSTAT;
  586.                     break;
  587.                 case '8':
  588.                     cbus_addr = CMXPROG_ADDR;
  589.                     wordregptr = &CMXPROG;
  590.                     break;
  591.                 case '9':
  592.                     cbus_addr = CMXTESTADDR_ADDR;
  593.                     wordregptr = &CMXTESTADDR;
  594.                     break;
  595.                 case 'A': case 'a':
  596.                     cbus_addr = CMXTESTWR_ADDR;
  597.                     wordregptr = &CMXTESTWR;
  598.                     break;
  599.                 case 'B': case 'b':
  600.                     writereg = 0;
  601.                     cbus_addr = CMXTESTRD_ADDR;
  602.                     wordregptr = &CMXTESTRD;
  603.                     break;
  604.                 default:
  605.                     return (ERROR);
  606.             }                   
  607.             ATBUFPTR++;             // Increment AT Command Buffer pointer.
  608.             if ((ATBUF[ATBUFPTR] == '=') && writereg)
  609.             {
  610.                 ATBUFPTR++;         // Increment AT Command Buffer pointer.
  611.                 i = ascregtolong();
  612.                 if ((i > 65535) || (!reg16bit && (i > 255)))    // If 8-bit register and value exceeds 255 return error.
  613.                 {
  614.                     return (ERROR);
  615.                 }
  616.                 if (reg16bit)
  617.                 {
  618.                     *wordregptr = i & 0xFFFF;
  619.                     wr16_cbus(cbus_addr,*wordregptr);
  620.                 }
  621.                 else
  622.                 {
  623.                     *byteregptr = i & 0xFF;                 
  624.                     wr_cbus(cbus_addr,*byteregptr);
  625.                 }
  626.                 break;
  627.             }
  628.             else if ((ATBUF[ATBUFPTR] == '?'))
  629.             {
  630.                 if (reg16bit)
  631.                 {
  632.                     if (!writereg)      // Read CBUS if 16 bit read register 
  633.                     {
  634.                         *wordregptr = rd16_cbus(cbus_addr); // Place CBUS reply data into shadow register
  635.                     }
  636.                     j = *wordregptr & 0xFFFF;           // Copy 16 bit shadow register
  637.                 }
  638.                 else
  639.                 {
  640.                     if (!writereg)      // Read CBUS if 8 bit read register 
  641.                     {
  642.                         *byteregptr = rd_cbus(cbus_addr);   // Place CBUS reply data into shadow register
  643.                     }
  644.                     j = *byteregptr & 0xFF; // Copy 8 bit shadow register
  645.                 }
  646.                 if (HEXOP)
  647.                 {
  648.                     hexnum2scrn(j,4,WORDRES);           // Send LF char if word results enabled
  649.                 }
  650.                 else
  651.                 {
  652.                     decnum2scrn(j,5,WORDRES);           // Send LF char if word results enabled
  653.                 }
  654.                 break;
  655.             }
  656.             else
  657.             {
  658.                 return (ERROR);
  659.             }
  660.         case 'R': case 'r':
  661.             reset_cbus();               // Perform CMX868 General Reset and clear device write shadow registers
  662.             break;
  663.         default:
  664.             return (ERROR);
  665.     }
  666.     return (OK);                        // Return OK to indicate success
  667. }
  668. unsigned long ascregtolong(void)
  669. {
  670.     unsigned char tempbuf[6];
  671.     unsigned long tempnum=0;
  672.     unsigned long j=1;
  673.     signed char i,k;
  674.     i=0;
  675.     // Loop while characters are decimal digits  
  676.     // and are no more than 5 digits long i.e. 65535
  677.     while ((ATBUF[ATBUFPTR] <= '9') && (ATBUF[ATBUFPTR] >= '0') && (i < 6))
  678.     {
  679.         tempbuf[i++] = ATBUF[ATBUFPTR++];
  680.     }
  681.     ATBUFPTR--;
  682.     i--;
  683.     for (k=i;k>=0;k--)
  684.     {
  685.         tempnum += (tempbuf[k] - 0x30) * j;
  686.         j *= 10;
  687.     }
  688.     return (tempnum);
  689. }