atcmd.c
上传用户:sdttscl
上传日期:2010-01-04
资源大小:683k
文件大小:19k
源码类别:

Modem编程

开发平台:

C/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:- 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 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 swicth
  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. if (sreg_offset >= numsregs) // Return ERROR if offset exceeds max value
  308. { // specified in header file
  309. return(ERROR);
  310. }
  311. sregptr = &S0;
  312. sregptr += sreg_offset;
  313. if (ATBUF[ATBUFPTR] == '=')
  314. {
  315. ATBUFPTR++; // Increment AT Command Buffer pointer.
  316. i = ascregtolong();
  317. if (i > 255) // If 8-bit register exceeds 255 return error.
  318. {
  319. return (ERROR);
  320. }
  321. *sregptr = i;
  322. }
  323. else if (ATBUF[ATBUFPTR] == '?')
  324. {
  325. if (HEXOP)
  326. {
  327. hexnum2scrn(*sregptr,2,WORDRES); // Send LF char if word results enabled
  328. }
  329. else
  330. {
  331. decnum2scrn(*sregptr,3,WORDRES); // Send LF char if word results enabled
  332. }
  333. }
  334. else
  335. {
  336. return (ERROR); // Return ERROR to indicate invalid character
  337. }
  338. return (OK); // Return OK to indicate success
  339. }
  340. unsigned char atvcmd(void) // Modify Word Response bit located in S14 reg
  341. {
  342. ATBUFPTR++; // Increment AT Command Buffer pointer.
  343. switch(ATBUF[ATBUFPTR])
  344. {
  345. case '0':
  346. WORDRES = OFF; // Enable number responses
  347. break;
  348. case '1':
  349. WORDRES = ON; // Enable Word responses
  350. break;
  351. default:
  352. return (ERROR); // Return ERROR to indicate invalid character
  353. }
  354. return (OK); // Return OK to indicate success
  355. }
  356. unsigned char atxcmd(void) // Modify Call Characteristic bits located in S22 reg
  357. {
  358. unsigned char tempreg;
  359. ATBUFPTR++; // Increment AT Command Buffer pointer.
  360. switch(ATBUF[ATBUFPTR])
  361. {
  362. case '0':
  363. tempreg = X0CALLING;
  364. break;
  365. case '1':
  366. tempreg = X1CALLING;
  367. break;
  368. case '2':
  369. tempreg = X2CALLING;
  370. break;
  371. case '3':
  372. tempreg = X3CALLING;
  373. break;
  374. case '4':
  375. tempreg = X4CALLING;
  376. break;
  377. default:
  378. return (ERROR); // Return ERROR to indicate invalid character
  379. }
  380. S22 &= 0b00011111; // Clear existing calling characteristics 
  381. S22 ^= tempreg; // Modify S22 to reflect new settings
  382. return (OK); // Return OK to indicate success
  383. }
  384. unsigned char atzcmd(void) // Reset Modem and recall factory profile
  385. {
  386. ATBUFPTR++; // Increment AT Command Buffer pointer.
  387. switch(ATBUF[ATBUFPTR])
  388. {
  389. case '0':
  390. init_sregs(0); // Recall factory profile 0.
  391. break;
  392. case '1':
  393. init_sregs(1); // Recall factory profile 1.
  394. break;
  395. default:
  396. return (ERROR); // Return ERROR to indicate invalid character
  397. }
  398. reset_cbus(); // Perform CMX868 General reset and clear device write shadow registers
  399. return (OK); // Return OK to indicate success
  400. }
  401. unsigned char xatcmd(void)
  402. {
  403. ATBUFPTR++; // Increment AT Command Buffer pointer.
  404. switch(ATBUF[ATBUFPTR])
  405. {
  406. case 'F': case 'f':
  407. return (xatfcmd());
  408. case 'G': case 'g':
  409. return (xatgcmd());
  410. default:
  411. return (ERROR);
  412. }
  413. }
  414. unsigned char xatfcmd(void) // Recall factory profile
  415. {
  416. ATBUFPTR++; // Increment AT Command Buffer pointer.
  417. switch(ATBUF[ATBUFPTR])
  418. {
  419. case '0':
  420. init_sregs(0); // Recall factory profile 0.
  421. break;
  422. case '1':
  423. init_sregs(1); // Recall factory profile 1.
  424. break;
  425. default:
  426. return (ERROR); // Return ERROR to indicate invalid character
  427. }
  428. return (OK); // Return OK to indicate success
  429. }
  430. unsigned char xatgcmd(void) // Modify Guard Tone bits located in S23 reg
  431. {
  432. unsigned char tempreg;
  433. ATBUFPTR++; // Increment AT Command Buffer pointer.
  434. switch(ATBUF[ATBUFPTR])
  435. {
  436. case '0':
  437. tempreg = NOGUARD;
  438. break;
  439. case '1':
  440. tempreg = GUARD550;
  441. break;
  442. case '2':
  443. tempreg = GUARD1800;
  444. break;
  445. default:
  446. return (ERROR); // Return ERROR to indicate invalid character
  447. }
  448. S23 &= 0b00111111; // Clear existing Guard tone settings 
  449. S23 ^= tempreg; // Modify S23 to reflect new settings
  450. return (OK); // Return OK to indicate success
  451. }
  452. unsigned char cmlatcmd(void)
  453. {
  454. ATBUFPTR++; // Increment AT Command Buffer pointer.
  455. switch(ATBUF[ATBUFPTR])
  456. {
  457. case 'F': case 'f': // CML Test Functions
  458. return (cmlatfcmd());
  459. case 'R': case 'r':
  460. return (cmlatrcmd());
  461. default:
  462. return (ERROR);
  463. }
  464. }
  465. unsigned char cmlatfcmd(void) // CML Test Functions
  466. {
  467. ATBUFPTR++; // Increment AT Command Buffer pointer.
  468. switch(ATBUF[ATBUFPTR])
  469. {
  470. case '0':
  471. PORTA = 0b00010000; // Turn off DCDIND LED
  472. PORTB |= 0b00000110; // Ensure RIN and DCDN o/p's are set
  473. hook(0); // On-Hook (Hook LED off)
  474. LED_OVERRIDE = 0;
  475. break;
  476. case '1':
  477. PORTA = 0b00001111; // Turn on DCDIND, RXDIND, TXDIND, DTRIND and HOOK LEDs
  478. PORTB &= 0b11111001; // Clear RIN and DCDN o/p's
  479. hook(1); // Off-Hook (Hook LED on)
  480. LED_OVERRIDE = 1;
  481. break;
  482. case '2':
  483. DelayMs(100); // Wait 100ms
  484. break;
  485. case '3':
  486. Delay1s(1); // Wait 1s
  487. break;
  488. case '4':
  489. T0IE = 0; // Initially disable Timer interrupt
  490. BERTEND = 0; // BERT Rx End
  491. BERTFLAG = 1; // Set BERT Flag
  492. break;
  493. case '5':
  494. T0IE = 0; // Initially disable Timer interrupt
  495. BERTEND = 1; // BERT Tx End
  496. BERTFLAG = 1; // Set BERT Flag
  497. break;
  498. case '6':
  499. TESTFUNC1 = 1; // Set Test Function One flag
  500. break;
  501. case '7':
  502. GPT6 = 30; // Load GPT6 for 30 second
  503. while (PICIRQN != 0)
  504. {
  505. if (GPT6 == 0)
  506. {
  507. return (ERROR); // Return ERROR to indicate invalid character
  508. }
  509. }
  510. CMXSTAT = rd16_cbus(CMXSTAT_ADDR); // Update CMX868 Status Shadow register
  511. if (HEXOP)
  512. {
  513. hexnum2scrn(CMXSTAT,4,WORDRES); // Send LF char if word results enabled
  514. }
  515. else
  516. {
  517. decnum2scrn(CMXSTAT,5,WORDRES); // Send LF char if word results enabled
  518. }
  519. break;
  520. case '8':
  521. return (NYI); // Return NYI to indicate function not implemented yet
  522. case '9':
  523. return (NYI); // Return NYI to indicate function not implemented yet
  524. default:
  525. return (ERROR); // Return ERROR to indicate invalid character
  526. }
  527. return (OK); // Return OK to indicate success
  528. }
  529. unsigned char cmlatrcmd(void)
  530. {
  531. unsigned int j;
  532. unsigned long i;
  533. volatile unsigned char bank3 * byteregptr;
  534. volatile unsigned int bank3 * wordregptr;
  535. unsigned char cbus_addr, reg16bit, writereg;
  536. ATBUFPTR++; // Increment AT Command Buffer pointer.
  537. switch(ATBUF[ATBUFPTR])
  538. {
  539. case 'E': case 'e':
  540. ATBUFPTR++; // Increment AT Command Buffer pointer.
  541. reg16bit = 1; // Assume 16 bit word unless modified
  542. writereg = 1; // Assume write register unless modified
  543. switch(ATBUF[ATBUFPTR])
  544. {
  545. case '0':
  546. cbus_addr = CMXGENCTRL_ADDR;
  547. wordregptr = &CMXGENCTRL;
  548. break;
  549. case '1':
  550. cbus_addr = CMXTXMODE_ADDR;
  551. wordregptr = &CMXTXMODE;
  552. break;
  553. case '2':
  554. cbus_addr = CMXRXMODE_ADDR;
  555. wordregptr = &CMXRXMODE;
  556. break;
  557. case '3':
  558. reg16bit = 0;
  559. cbus_addr = CMXTXDATA_ADDR;
  560. byteregptr = &CMXTXDATA;
  561. break;
  562. case '4':
  563. reg16bit = 0;
  564. cbus_addr = CMXTXDATAV14_ADDR;
  565. byteregptr = &CMXTXDATAV14;
  566. break;
  567. case '5':
  568. writereg = 0;
  569. reg16bit = 0;
  570. cbus_addr = CMXRXDATA_ADDR;
  571. byteregptr = &CMXRXDATA;
  572. break;
  573. case '6':
  574. writereg = 0;
  575. cbus_addr = CMXSTAT_ADDR;
  576. wordregptr = &CMXSTAT;
  577. break;
  578. case '8':
  579. cbus_addr = CMXPROG_ADDR;
  580. wordregptr = &CMXPROG;
  581. break;
  582. case '9':
  583. cbus_addr = CMXTESTADDR_ADDR;
  584. wordregptr = &CMXTESTADDR;
  585. break;
  586. case 'A': case 'a':
  587. cbus_addr = CMXTESTWR_ADDR;
  588. wordregptr = &CMXTESTWR;
  589. break;
  590. case 'B': case 'b':
  591. writereg = 0;
  592. cbus_addr = CMXTESTRD_ADDR;
  593. wordregptr = &CMXTESTRD;
  594. break;
  595. default:
  596. return (ERROR);
  597. }
  598. ATBUFPTR++; // Increment AT Command Buffer pointer.
  599. if ((ATBUF[ATBUFPTR] == '=') && writereg)
  600. {
  601. ATBUFPTR++; // Increment AT Command Buffer pointer.
  602. i = ascregtolong();
  603. if ((i > 65535) || (!reg16bit && (i > 255))) // If 8-bit register and value exceeds 255 return error.
  604. {
  605. return (ERROR);
  606. }
  607. if (reg16bit)
  608. {
  609. *wordregptr = i & 0xFFFF;
  610. wr16_cbus(cbus_addr,*wordregptr);
  611. }
  612. else
  613. {
  614. *byteregptr = i & 0xFF;
  615. wr_cbus(cbus_addr,*byteregptr);
  616. }
  617. break;
  618. }
  619. else if ((ATBUF[ATBUFPTR] == '?'))
  620. {
  621. if (reg16bit)
  622. {
  623. if (!writereg) // Read CBUS if 16 bit read register 
  624. {
  625. *wordregptr = rd16_cbus(cbus_addr); // Place CBUS reply data into shadow register
  626. }
  627. j = *wordregptr & 0xFFFF; // Copy 16 bit shadow register
  628. }
  629. else
  630. {
  631. if (!writereg) // Read CBUS if 8 bit read register 
  632. {
  633. *byteregptr = rd_cbus(cbus_addr); // Place CBUS reply data into shadow register
  634. }
  635. j = *byteregptr & 0xFF; // Copy 8 bit shadow register
  636. }
  637. if (HEXOP)
  638. {
  639. hexnum2scrn(j,4,WORDRES); // Send LF char if word results enabled
  640. }
  641. else
  642. {
  643. decnum2scrn(j,5,WORDRES); // Send LF char if word results enabled
  644. }
  645. break;
  646. }
  647. else
  648. {
  649. return (ERROR);
  650. }
  651. case 'R': case 'r':
  652. reset_cbus(); // Perform CMX868 General Reset and clear device write shadow registers
  653. break;
  654. default:
  655. return (ERROR);
  656. }
  657. return (OK); // Return OK to indicate success
  658. }
  659. unsigned long ascregtolong(void)
  660. {
  661. unsigned char tempbuf[6];
  662. unsigned long tempnum=0;
  663. unsigned long j=1;
  664. signed char i,k;
  665. i=0;
  666. // Loop while characters are decimal digits  
  667. // and are no more than 5 digits long i.e. 65535
  668. while ((ATBUF[ATBUFPTR] <= '9') && (ATBUF[ATBUFPTR] >= '0') && (i < 6))
  669. {
  670. tempbuf[i++] = ATBUF[ATBUFPTR++];
  671. }
  672. ATBUFPTR--;
  673. i--;
  674. for (k=i;k>=0;k--)
  675. {
  676. tempnum += (tempbuf[k] - 0x30) * j;
  677. j *= 10;
  678. }
  679. return (tempnum);
  680. }