home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / devices / serialdevice / example2.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  23KB  |  561 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Devices                 Amiga C Club       */
  7. /* Chapter: Serial Device               Tulevagen 22       */
  8. /* File:    Example2.c                  181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-04-26                                       */
  11. /* Version: 1.00                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20.  
  21.  
  22. /* This program demonstrates how you can use the Serial Device */
  23. /* to read and write information from and to the Serial Port.  */
  24. /* Since I do not know what you have connected to your serial  */
  25. /* port, this program does not do very much. However, the      */
  26. /* functions are easy to call, so it should not be hard for    */
  27. /* you to change this program into a nice serial communication */
  28. /* package.                                                    */
  29. /*                                                             */
  30. /* This example is rather similar to Example 1, but this time  */
  31. /* we do not wait for the serial port to complete our request. */
  32. /* Instead we do somethings (well not very much) and now and   */
  33. /* then checks if the request has been completed.              */
  34.  
  35.  
  36.  
  37. #include <exec/types.h>        /* STRPTR         */
  38. #include <devices/serial.h>    /* Serial Device  */
  39.  
  40.  
  41.  
  42. /* Size of our data buffer: */
  43. #define MY_BUFFER_SIZE 200
  44.  
  45. /* Size of the Serial Device's own input buffer: (Must be */
  46. /* at least 512 bytes, but more is recommended.)          */
  47. #define INPUT_BUFFER_SIZE 1024
  48.  
  49. /* Read 8 bits/character: */
  50. #define READ_LENGTH   8
  51.  
  52. /* Write 8 bits/character: */
  53. #define WRITE_LENGTH  8
  54.  
  55. /* Sen 1 stop bit between each character: */
  56. #define STOP_LENGTH  1
  57.  
  58. /* Break time in microseconds: (1/2 sec) */
  59. #define BREAK_TIME    500000
  60.  
  61. /* Baud rate: */
  62. #define BAUD_RATE     9600
  63.  
  64. /* Serial flags: (Parity enabled, checking for end of file characters.) */
  65. #define SERIAL_FLAGS SERF_PARTY_ON|SERF_EOFMODE
  66.  
  67. /* Additional flags: (Mark-space parity not used.) */
  68. #define ADDITIONAL_FLAGS 0
  69.  
  70.  
  71.  
  72.  
  73.  
  74. /* Declare a pointer to our reply port: */
  75. struct MsgPort *replymp = NULL;
  76.  
  77. /* Declare a pointer to our serial request block: */
  78. struct IOExtSer *serial_req = NULL;
  79.  
  80. /* Store the serial device error here: */
  81. UWORD serial_dever = TRUE;
  82.  
  83. /* Declare our data buffer: */
  84. BYTE buffer[ MY_BUFFER_SIZE ];
  85.  
  86.  
  87.  
  88.  
  89. /* Declare our functions: */
  90.  
  91. /* Our main function: */
  92. void main();
  93.  
  94. /* Clears and removes everything nice and neatly: */
  95. void clean_up( UBYTE error, STRPTR text );
  96.  
  97. /* Sets serial parameters: */
  98. UBYTE SetSerParams(
  99.   struct IOExtSer *ioreq,
  100.   ULONG buffer_length,
  101.   ULONG baud_rate,
  102.   ULONG break_time,
  103.   UBYTE read_length,
  104.   UBYTE write_length,
  105.   UBYTE stop_length,
  106.   UBYTE serial_flags,
  107.   ULONG extended_flags,
  108.   UBYTE *eof_chars
  109. );
  110.  
  111. /* Prints some information about the error: */
  112. void SerError( UBYTE error );
  113.  
  114. /* Sends data to the Serial Port without going to sleep: */
  115. void SerWriteNoWait(
  116.   struct IOExtSer *ioreq,
  117.   BYTE *data,
  118.   ULONG length
  119. );
  120.  
  121. /* Reads data from the Serial Port without going to sleep: */
  122. void SerReadNoWait(
  123.   struct IOExtSer *ioreq,
  124.   BYTE *data,
  125.   ULONG length
  126. );
  127.  
  128.  
  129.  
  130. void main()
  131. {
  132.   /* Error number: */
  133.   UBYTE error;
  134.   
  135.   /* The eight end-of-file characters: */
  136.   /* They MUST be in descending order! */
  137.   UBYTE eof_char[8]={ 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x00 };
  138.  
  139.   /* Declare a pointer and set it to NULL: */
  140.   struct IOExtSer *ptr = NULL;
  141.   
  142.   
  143.   
  144.   /* Get a reply port: (No name, priority 0) */
  145.   replymp = (struct MsgPort *)
  146.     CreatePort( NULL, 0 );
  147.   if( !replymp )
  148.     clean_up( 0, "Could not create the reply port!" );
  149.  
  150.  
  151.  
  152.   /* Create a serial request block: */
  153.   serial_req = (struct IOExtSer *)
  154.     CreateExtIO( replymp, sizeof( struct IOExtSer ) );
  155.   if( !serial_req )
  156.     clean_up( 0, "Not enough memory for the serial request block!" );
  157.  
  158.  
  159.  
  160.   /* Open the Serial Device: */
  161.   serial_dever = OpenDevice( SERIALNAME, 0, serial_req, 0 );
  162.   if( serial_dever )
  163.     clean_up( 0, "Could not open the Serial Device!" );
  164.  
  165.  
  166.  
  167.   error = (UBYTE) SetSerParams(
  168.     serial_req,        /* Pointer to our serial request block.          */
  169.     INPUT_BUFFER_SIZE, /* Size of the Serial Device's own input buffer. */
  170.     BAUD_RATE,         /* Baud rate (read and write). [112 - 292000]    */
  171.     BREAK_TIME,        /* Break time in microseconds.                   */
  172.     READ_LENGTH,       /* # of bits/char (1-8). Parity not included.    */
  173.     WRITE_LENGTH,      /* # of bits/char (1-8). Parity not included.    */
  174.     STOP_LENGTH,       /* # of stop bits between the characters. (1-2)  */
  175.     SERIAL_FLAGS,      /* Serial flags.                                 */
  176.     ADDITIONAL_FLAGS,  /* Additional flags.                             */
  177.     eof_char           /* Pointer to an array of eight end-of-file chr. */
  178.   );
  179.  
  180.   /* OK? */
  181.   if( error )
  182.     clean_up( error, "Could not set the serial parameters!" );
  183.  
  184.  
  185.  
  186.   /* These two bytes will turn on the lamp on a Sharp JX-100 */
  187.   /* color scanner, if it happens to be connected to your    */
  188.   /* serial port: (To make this example simple we do not     */
  189.   /* turn it off.)                                           */ 
  190.   buffer[ 0 ] = 0x4C;
  191.   buffer[ 1 ] = 0x31;
  192.   
  193.  
  194.   /* Send 2 bytes to the serial port and return immediately: */
  195.   SerWriteNoWait( serial_req, buffer, 2 ); 
  196.  
  197.  
  198.   /* As long as the pointer is not pointing to */
  199.   /* the request we should stay in the loop:   */
  200.   while( ptr == NULL )
  201.   {
  202.     /*   ... do something ...    */
  203.     /* Well, I do not know what. */
  204.   
  205.     /* Check if the request has been completed: (If the  */
  206.     /* request has been compleded CheckIO() will return  */
  207.     /* a pointer to the request, else NULL is returned.) */
  208.     ptr = (struct IOExtSer *) CheckIO( serial_req );
  209.   }
  210.  
  211.   /* At last the request was completed! */
  212.  
  213.  
  214.   /* Remove the requstblock's message. (The ptr and ioreq */
  215.   /* are in this example identical, so it does not matter */
  216.   /* whichever you will use. The paranteces around the    */
  217.   /* expression is actually unnecessary, but this looks   */
  218.   /* better.)                                             */
  219.   Remove( &(ptr->IOSer.io_Message.mn_Node) );
  220.  
  221.  
  222.   /* Check if everything is OK? */
  223.   if( serial_req->IOSer.io_Error )
  224.     SerError( error );       /* ERROR */
  225.   else
  226.     printf( "Lamp OFF!\n" ); /* OK    */
  227.  
  228.  
  229.  
  230.   /* Clean up and quit: */
  231.   clean_up( 0, "The End!" );
  232. }
  233.  
  234.  
  235.  
  236. /* Close and return everything that has been */
  237. /* opened and allocated before we quit:      */
  238.  
  239. void clean_up( UBYTE error, STRPTR text )
  240. {
  241.   /* Print some information about the problem: */
  242.   if( error )
  243.     SerError( error );
  244.  
  245.   /* Close the Serial Device: */ 
  246.   if( !serial_dever )
  247.     CloseDevice( serial_req );
  248.  
  249.   /* Deallocate the serial request block: */
  250.   if( serial_req )
  251.     DeleteExtIO( serial_req, sizeof( struct IOExtSer ) );
  252.  
  253.   /* Remove the replyport: */
  254.   if( replymp )
  255.     DeletePort( replymp);
  256.  
  257.   /* Print the message: */
  258.   printf( "\n%s\n", text );
  259.  
  260.   /* Quit: */
  261.   exit( 0 );
  262. }
  263.  
  264.  
  265.  
  266. /* SetSerParams() sets the serial parameters. It initializes a IOExtSer    */
  267. /* structure, and does a SDCMD_SETPARAMS commad. If everything is OK it    */
  268. /* returns NULL, else an error number is returned.                         */
  269. /*                                                                         */
  270. /* Synopsis: er = SetSerParams( io, bl, br, bt, rl, wl, sl, sf, ef, chr ); */
  271. /*                                                                         */
  272. /* er:       (UBYTE) SetSerParams() returns 0 if everything was OK, else   */
  273. /*           an error value is returned. See function SerError() for more  */
  274. /*           information.                                                  */
  275. /*                                                                         */ 
  276. /* io:       (struct IOExtSer *) Pointer to the serial request block you   */
  277. /*           want to initialize.                                           */
  278. /*                                                                         */
  279. /* bl:       (ULONG) Size of the internal serial buffer which will be used */
  280. /*           when you read data. Must be at least 512 (bytes), but more is */
  281. /*           recommended. The faster and more data you want to read, the   */
  282. /*           bigger should the internal buffer be. Some recommended sizes: */
  283. /*           512, 1024, 2048, 4096, 8192 or 16384.                         */
  284. /*                                                                         */
  285. /* br:       (ULONG) Baud rate. Can be anything between 110 and 292000.    */
  286. /*           (Up to 292000 is all right for the hardware, but the software */
  287. /*           can not cope with this, especially since other tasks may be   */
  288. /*           running at the same time. You should therefore not use baud   */
  289. /*           rates above 31250.) Some recommended values: 110, 300, 1200,  */
  290. /*           2400, 4800, 9600, 19200 or 31250 (the last is a bit though).  */
  291. /*                                                                         */
  292. /* bt:       (ULONG) Break time in micro seconds. All break requests will  */
  293. /*           be set to this time.                                          */
  294. /*                                                                         */
  295. /* rl:       (UBYTE) How many bits chould be read for each character.      */
  296. /*           Usually 7 or 8 bits.                                          */
  297. /*                                                                         */
  298. /* wl:       (UBYTE) How many bits chould be written for each character.   */
  299. /*           Usually 7 or 8 bits.                                          */
  300. /*                                                                         */
  301. /* sl:       (UBYTE) How many stop bits shoud be written or expected.      */
  302. /*           Normally set to 1, but you may set it to 2 if rl/wl = 7.      */
  303. /*                                                                         */
  304. /* sf:       (UBYTE) You may use the following serial flags:               */
  305. /*                                                                         */
  306. /*           SERF_PARTY_ON   Parity checking/writing is turned on. (The    */
  307. /*                           sum of all data bits are divided by two, and  */
  308. /*                           the remainder is the parity bit. If even      */
  309. /*                           parity is used the bit will be set to 1 if    */
  310. /*                           the remainder is even. If odd parity is used  */
  311. /*                           the parity bit will be set to 0 if the        */
  312. /*                           remainder is even.                            */
  313. /*                                                                         */
  314. /*           SERF_PARTY_ODD  Set this flag if you want to use odd parity.  */
  315. /*                           (The default setting is even parity.)         */
  316. /*                                                                         */
  317. /*           SERF_7WIRE      This flag should only be used when you call   */
  318. /*                           the OpenDevice(), and not by this function.   */
  319. /*                           If the flag is set, seven-wire "handshaking"  */
  320. /*                           will be used. (Default is three-wire.)        */
  321. /*                                                                         */
  322. /*           SERF_QUEUEDBRK  Set this flag if you want break commands to   */
  323. /*                           be queued along with all other signals. The   */
  324. /*                           default is that a break command interrupts    */
  325. /*                           the process immediately.                      */
  326. /*                                                                         */
  327. /*           SERF_RAD_BOOGIE Set this bit if you want high speed mode.     */
  328. /*                           This can be useful when you want to send and  */
  329. /*                           receive signals at high speed. When this flag */
  330. /*                           is set no parity is used, xON/xOFF handling   */
  331. /*                           is turned off, no break signals are allowed,  */
  332. /*                           and finally only eight-bit characters are     */
  333. /*                           used.                                         */
  334. /*                                                                         */
  335. /*           SERF_SHARED     Set this falg if you want to allow other      */
  336. /*                           tasks running at the same time to use the     */
  337. /*                           serial device. The default is exclusive-      */
  338. /*                           access. (If some other task is using the      */
  339. /*                           serial device with the shared bit set, and    */
  340. /*                           you call this function with exclusive access, */
  341. /*                           your request will fail.)                      */
  342. /*                                                                         */
  343. /*           SERF_EOFMODE    Set this flag if you want to check for end of */
  344. /*                           file characters. (You may use up to eight end */
  345. /*                           of file characters, which are specified       */
  346. /*                           below.)                                       */
  347. /*                                                                         */
  348. /*           SERF_XDISABLED  xOn/xOFF handling is turned off. (Default is  */
  349. /*                           on.)                                          */
  350. /*                                                                         */
  351. /* ef:       (ULONG) You may use the following extra flags:                */
  352. /*                                                                         */
  353. /*           SEXTF_MSPON     Set this flag if you want to use mark-space   */
  354. /*                           parity rather than odd-even parity.           */
  355. /*                                                                         */
  356. /*           SEXTF_MARK      If this and the SEXTF_MSPON flag is set, it   */
  357. /*                           will mark.                                    */
  358. /*                                                                         */
  359. /* chr:      (UBYTE *) Pointer to an array containing eight end of file    */
  360. /*           characters. If the serial flag "SERF_EOFMODE" is set, the     */
  361. /*           serial device will check each character which is sent or      */
  362. /*           received, and if it matches one of the end of file characters */
  363. /*           the read/wite request is terminated.                          */
  364.  
  365. UBYTE SetSerParams(
  366.   struct IOExtSer *ioreq, /* Pointer to our serial request block.          */
  367.   ULONG buffer_length,    /* Size of the Serial Device's own input buffer. */
  368.   ULONG baud_rate,        /* Baud rate (read and write). [110 - 292000]    */
  369.   ULONG break_time,       /* Break time in microseconds.                   */
  370.   UBYTE read_length,      /* Nr of bits, read (1-8). Parity not included.  */
  371.   UBYTE write_length,     /* Nr of bits, write (1-8). Parity not included. */
  372.   UBYTE stop_length,      /* Nr of bits, stop (1 or 2).                    */
  373.   UBYTE serial_flags,     /* Serial flags.                                 */
  374.   ULONG extended_flags,   /* Additional serial flags.                      */
  375.   UBYTE *eof_chars        /* Pointer to an array containing eight end-of-  */
  376.                           /* file characters.                              */
  377. )
  378. {
  379.   int loop;           /* Used in the loop.      */
  380.   UBYTE *ptr;         /* Unsigned byte pointer. */
  381.   
  382.   
  383.   /* Set the size of the Serial Device's own input buffer: */
  384.   ioreq->io_RBufLen = buffer_length;
  385.   
  386.   /* Set baud rate: */
  387.   ioreq->io_Baud = baud_rate;
  388.   
  389.   /* Set break time (in microseconds): */
  390.   ioreq->io_BrkTime = break_time;  
  391.   
  392.   /* Nr of bits to read per character: */
  393.   ioreq->io_ReadLen = read_length;
  394.  
  395.   /* Nr of bits to write per character: */
  396.   ioreq->io_WriteLen = write_length;
  397.   
  398.   /* Nr of stop bits: (Normally 1, if write_length is */
  399.   /* equal to 7 you may set stop_length to 2.)        */
  400.   ioreq->io_StopBits = stop_length;
  401.  
  402.   /* Set serial flags: */
  403.   ioreq->io_SerFlags = serial_flags;
  404.  
  405.   /* Set additional flags: */
  406.   ioreq->io_ExtFlags = extended_flags;
  407.   
  408.   
  409.   /* Get the address of the IOTArray: */
  410.   ptr = (UBYTE *) &(ioreq->io_TermArray);
  411.  
  412.   /* Set all eight end of file characters: */
  413.   for( loop=0; loop < 8; loop++ )
  414.   {
  415.     /* Copy character after character: */
  416.     *ptr = eof_chars[ loop ];
  417.  
  418.     /* Step one byte foreward: */
  419.     ptr++;
  420.   }
  421.   
  422.   
  423.   /* All values have now been set, lets do a SDCMD_SETPARAMS request: */
  424.   ioreq->IOSer.io_Command = SDCMD_SETPARAMS;
  425.   
  426.   /* Do our request, and when complete return 0 if */
  427.   /* OK, else an error value:                      */
  428.   return( (UBYTE) DoIO( ioreq ) );
  429. }
  430.  
  431.  
  432. /* SerError() tells the user what went wrong. You give it the error code */
  433. /* you received, and SerError() will print a short description of the    */
  434. /* problem. Useful when debugging.                                       */
  435. /*                                                                       */
  436. /* Synopsis: SerError( error );                                          */
  437. /*                                                                       */
  438. /* error:    (UBYTE) The error value you want to have explained.         */
  439.  
  440. void SerError( UBYTE error )
  441. {
  442.   switch( error )
  443.   {
  444.     case SerErr_DevBusy:
  445.       printf( "Some other task is already using the Serial Device!\n" );
  446.       break;
  447.     case SerErr_BufErr:
  448.       printf( "Not enough memory for the new input buffer!\n" );
  449.       break;
  450.     case SerErr_InvParam:
  451.       printf( "Invalid parameters!\n" );
  452.       break;
  453.     case SerErr_LineErr:
  454.       printf( "Line error!\n" );
  455.       break;
  456.     case SerErr_ParityErr:
  457.       printf( "Problems with the parity!\n" );
  458.       break;
  459.     case SerErr_TimerErr:
  460.       printf( "Timer error!\n" );
  461.       break;
  462.     case SerErr_BufOverflow:
  463.       printf( "Buffer overflowed!\n" );
  464.       break;
  465.     case SerErr_NoDSR:
  466.       printf( "No DSR!\n" );
  467.       break;
  468.     case SerErr_DetectedBreak:
  469.       printf( "A break was detected!\n" );
  470.       break;
  471.   }
  472. }
  473.  
  474.  
  475.  
  476. /* SerWriteNoWait() sends some data to the Serial Port, but returns */
  477. /* immediately. You only have to give it a pointer to the data you  */
  478. /* want to write and tell it how many bytes you want to transfer.   */
  479. /* Since it does not wait for the request to be completed, you have */
  480. /* to take care of removing the message yourself. Note that all     */
  481. /* requests that have been started must be completed or aborted     */
  482. /* before your program may close the serial device.                 */
  483. /*                                                                  */
  484. /* Synopsis: error = SerWriteNoWait( io, data, length );            */
  485. /*                                                                  */
  486. /* io:       (struct IOExtSer *) Pointer to an initialized serial   */
  487. /*           request block.                                         */
  488. /*                                                                  */
  489. /* data:     (BYTE *) Pointer to the first byte of the data you     */
  490. /*           want to send (write).                                  */
  491. /*                                                                  */
  492. /* length:   (ULONG) How many bytes you want to transfer. If you    */
  493. /*           want to continue to send data until we have received   */
  494. /*           an end-of-file character, set the length to -1. (Note  */
  495. /*           that it will then ONLY stop when it receives one of    */
  496. /*           the end-of-file characters.)                           */
  497.  
  498. void SerWriteNoWait(
  499.   struct IOExtSer *ioreq, /* Pointer to our serial request block.     */
  500.   BYTE *data,             /* Pointer to the data you want to send.    */
  501.   ULONG length            /* The length of the data you want to send. */
  502. )
  503. {
  504.   /* We want to send (write) some data: */
  505.   ioreq->IOSer.io_Command = CMD_WRITE;
  506.  
  507.   /* Give the start address of our data: */
  508.   ioreq->IOSer.io_Data = (APTR) data;
  509.  
  510.   /* Set the length of the message: */
  511.   ioreq->IOSer.io_Length = length;
  512.  
  513.   /* Do our request and return immediately: */
  514.   SendIO( ioreq );
  515. }
  516.  
  517.  
  518.  
  519. /* SerReadNoWait() reads some data from the Serial Port, but returns  */
  520. /* immediately. You only have to give it a pointer to some memory     */
  521. /* where the data should be stored, and tell it how many bytes you    */
  522. /* want to read. Since it does not wait for the request to be         */
  523. /* completed, you have to take care of removing the message yourself. */
  524. /* Note that all requests that have been started must be completed or */
  525. /* aborted before your program may close the serial device.           */
  526. /*                                                                    */
  527. /*                                                                    */
  528. /* Synopsis: error = SerReadNoWait( io, data, length );               */
  529. /*                                                                    */
  530. /* io:       (struct IOExtSer *) Pointer to an initialized serial     */
  531. /*           request block.                                           */
  532. /*                                                                    */
  533. /* data:     (BYTE *) Pointer to the memory buffer where you want to  */
  534. /*           store all data.                                          */
  535. /*                                                                    */
  536. /* length:   (ULONG) How many bytes you want to read. If you want to  */
  537. /*           continue to send data until we have received an end-of-  */
  538. /*           file character, set the length to -1. (Note that it      */
  539. /*           will then ONLY stop when it receives one of the end-of-  */
  540. /*           file characters.)                                        */
  541.  
  542. void SerReadNoWait(
  543.   struct IOExtSer *ioreq, /* Pointer to our serial request block. */
  544.   BYTE *data,             /* Where the data should be placed.     */
  545.   ULONG length            /* How many bytes you want to read.     */
  546. )
  547. {
  548.   /* We want to read some data: */
  549.   ioreq->IOSer.io_Command = CMD_READ;
  550.  
  551.   /* Give the start address of our data: */
  552.   ioreq->IOSer.io_Data = (APTR) data;
  553.  
  554.   /* Set how many bytes you want to read: */
  555.   ioreq->IOSer.io_Length = length;
  556.  
  557.   /* Do our request and return immediately: */
  558.   DoIO( ioreq );
  559. }
  560.  
  561.