Copyright (c) Hyperion Entertainment and contributors.
Difference between revisions of "Parallel Device"
Steven Solie (talk | contribs) |
Steven Solie (talk | contribs) |
||
(11 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
+ | [[Category:Devices|Parallel]]{{NeedUpdate}} |
||
== Parallel Device == |
== Parallel Device == |
||
Line 5: | Line 6: | ||
== Parallel Device Commands and Functions == |
== Parallel Device Commands and Functions == |
||
+ | {| class="wikitable" |
||
− | <table> |
||
+ | ! Command |
||
− | <tbody> |
||
+ | ! Command Operation |
||
− | <tr class="odd"> |
||
+ | |- |
||
− | <td align="left">'''Command'''</td> |
||
+ | | CMD_FLUSH |
||
− | <td align="left">'''Command Operation'''</td> |
||
+ | | Purge all queued requests for the parallel device. Does not affect active requests. |
||
− | </tr> |
||
+ | |- |
||
− | <tr class="even"> |
||
+ | | CMD_READ |
||
− | <td align="left">CMD_FLUSH</td> |
||
+ | | Read a stream of characters from the parallel port. The number of characters can be specified or a termination character(s) can be used. |
||
− | <td align="left">8.8cmPurge all queued requests for the parallel device. Does not affect active requests.</td> |
||
+ | |- |
||
− | </tr> |
||
+ | | CMD_RESET |
||
− | <tr class="odd"> |
||
+ | | Reset the parallel port to its initialized state. All active and queued I/O requests will be aborted. |
||
− | <td align="left">CMD_READ</td> |
||
+ | |- |
||
− | <td align="left">8.8cmRead a stream of characters from the parallel port. The number of characters can be specified or a termination character(s) can be used.</td> |
||
+ | | CMD_START |
||
− | </tr> |
||
+ | | Restart all paused I/O over the parallel port. Reactivates the handshaking sequence. |
||
− | <tr class="even"> |
||
+ | |- |
||
− | <td align="left">CMD_RESET</td> |
||
+ | | CMD_STOP |
||
− | <td align="left">8.8cmReset the parallel port to its initialized state. All active and queued I/O requests will be aborted.</td> |
||
+ | | Pause all active I/O over the parallel port. Deactivates the handshaking sequence. |
||
− | </tr> |
||
+ | |- |
||
− | <tr class="odd"> |
||
+ | |CMD_WRITE |
||
− | <td align="left">CMD_START</td> |
||
+ | | Write out a stream of characters to the parallel port. The number of characters can be specified or a NULL-terminated string can be sent. |
||
− | <td align="left">8.8cmRestart all paused I/O over the parallel port. Reactivates the handshaking sequence.</td> |
||
+ | |- |
||
− | </tr> |
||
+ | | PDCMD_QUERY |
||
− | <tr class="even"> |
||
+ | | Return the status of the parallel port lines and registers. |
||
− | <td align="left">CMD_STOP</td> |
||
+ | |- |
||
− | <td align="left">8.8cmPause all active I/O over the parallel port. Deactivates the handshaking sequence.</td> |
||
+ | | PDCMD_SETPARAMS |
||
− | </tr> |
||
+ | | Set the parameters of the parallel port. |
||
− | <tr class="odd"> |
||
+ | |} |
||
− | <td align="left">CMD_WRITE</td> |
||
− | <td align="left">8.8cmWrite out a stream of characters to the parallel port. The number of characters can be specified or a NULL-terminated string can be sent.</td> |
||
− | </tr> |
||
− | <tr class="even"> |
||
− | <td align="left">PDCMD_QUERY</td> |
||
− | <td align="left">8.8cmReturn the status of the parallel port lines and registers.</td> |
||
− | </tr> |
||
− | <tr class="odd"> |
||
− | <td align="left">PDCMD_SETPARAMS</td> |
||
− | <td align="left">8.8cmSet the parameters of the parallel port.</td> |
||
− | </tr> |
||
− | </tbody> |
||
− | </table> |
||
− | |||
− | Exec Functions as Used in This Chapter: |
||
− | |||
− | <table> |
||
− | <tbody> |
||
− | <tr class="odd"> |
||
− | <td align="left">AbortIO()</td> |
||
− | <td align="left">8.8cmAbort a command to the parallel device. If the command is in progress, it is stopped immediately. If it is queued, it is removed from the queue.</td> |
||
− | </tr> |
||
− | <tr class="even"> |
||
− | <td align="left">BeginIO()</td> |
||
− | <td align="left">8.8cmInitiate a command and return immediately (asynchronous request). This is used to minimize the amount of system overhead.</td> |
||
− | </tr> |
||
− | <tr class="odd"> |
||
− | <td align="left">CheckIO()</td> |
||
− | <td align="left">8.8cmDetermine the current state of an I/O request.</td> |
||
− | </tr> |
||
− | <tr class="even"> |
||
− | <td align="left">CloseDevice()</td> |
||
− | <td align="left">8.8cmRelinquish use of the parallel device. All requests must be complete.</td> |
||
− | </tr> |
||
− | <tr class="odd"> |
||
− | <td align="left">DoIO()</td> |
||
− | <td align="left">8.8cmInitiate a command and wait for completion (synchronous request).</td> |
||
− | </tr> |
||
− | <tr class="even"> |
||
− | <td align="left">OpenDevice()</td> |
||
− | <td align="left">8.8cmObtain use of the parallel device.</td> |
||
− | </tr> |
||
− | <tr class="odd"> |
||
− | <td align="left">SendIO()</td> |
||
− | <td align="left">8.8cmInitiate a command and return immediately (asynchronous request).</td> |
||
− | </tr> |
||
− | <tr class="even"> |
||
− | <td align="left">WaitIO()</td> |
||
− | <td align="left">8.8cmWait for the completion of an asynchronous request. When the request is complete the message will be removed from your reply port.</td> |
||
− | </tr> |
||
− | </tbody> |
||
− | </table> |
||
− | |||
− | Exec Support Functions as Used in This Chapter: |
||
− | |||
− | <table> |
||
− | <tbody> |
||
− | <tr class="odd"> |
||
− | <td align="left">CreateExtIO()</td> |
||
− | <td align="left">8.8cmCreate an extended I/O request structure of type IOExtPar. This structure will be used to communicate commands to the parallel device.</td> |
||
− | </tr> |
||
− | <tr class="even"> |
||
− | <td align="left">CreatePort()</td> |
||
− | <td align="left">8.8cmCreate a signal message port for reply messages from the parallel device. Exec will signal a task when a message arrives at the port.</td> |
||
− | </tr> |
||
− | <tr class="odd"> |
||
− | <td align="left">DeleteExtIO()</td> |
||
− | <td align="left">8.8cmDelete an extended I/O request structure created by CreateExtIO().</td> |
||
− | </tr> |
||
− | <tr class="even"> |
||
− | <td align="left">DeletePort()</td> |
||
− | <td align="left">8.8cmDelete the message port created by CreatePort().</td> |
||
− | </tr> |
||
− | </tbody> |
||
− | </table> |
||
== Device Interface == |
== Device Interface == |
||
− | The parallel device operates like the other Amiga devices. To use it, you must first open the parallel device, then send I/O requests to it, and then close it when finished. See |
+ | The parallel device operates like the other Amiga devices. To use it, you must first open the parallel device, then send I/O requests to it, and then close it when finished. See [[Exec_Device_I/O|Exec Device I/O]] for general information on device usage. |
The I/O request used by the parallel device is called IOExtPar. |
The I/O request used by the parallel device is called IOExtPar. |
||
+ | <syntaxhighlight> |
||
− | |||
+ | struct IOExtPar |
||
− | |||
− | <pre>struct IOExtPar |
||
{ |
{ |
||
struct IOStdReq IOPar; |
struct IOStdReq IOPar; |
||
Line 123: | Line 49: | ||
UBYTE io_ParFlags; /* parallel device flags */ |
UBYTE io_ParFlags; /* parallel device flags */ |
||
struct IOPArray io_PTermArray; /* termination character array */ |
struct IOPArray io_PTermArray; /* termination character array */ |
||
− | }; |
+ | }; |
+ | </syntaxhighlight> |
||
+ | |||
See the include file devices/parallel.h for the complete structure definition. |
See the include file devices/parallel.h for the complete structure definition. |
||
Line 134: | Line 62: | ||
* Open the parallel device. Call OpenDevice(), passing the I/O request. |
* Open the parallel device. Call OpenDevice(), passing the I/O request. |
||
+ | <pre> |
||
− | <pre>struct MsgPort *ParallelMP; /* Pointer to reply port */ |
||
+ | struct MsgPort *ParallelMP; /* Pointer to reply port */ |
||
struct IOExtPar *ParallelIO; /* Pointer to I/O request */ |
struct IOExtPar *ParallelIO; /* Pointer to I/O request */ |
||
Line 141: | Line 70: | ||
CreateExtIO(ParallelMP,sizeof(struct IOExtPar)) ) |
CreateExtIO(ParallelMP,sizeof(struct IOExtPar)) ) |
||
if (OpenDevice(PARALLELNAME,0L,(struct IORequest *)ParallelIO,0) ) |
if (OpenDevice(PARALLELNAME,0L,(struct IORequest *)ParallelIO,0) ) |
||
− | printf("%s did not open\n",PARALLELNAME); |
+ | printf("%s did not open\n",PARALLELNAME); |
+ | </pre> |
||
+ | |||
During the open, the parallel device pays attention to just one flag; PARF_SHARED. For consistency, the other flag bits should also be properly set. Full descriptions of all flags will be given later. When the parallel device is opened, it fills the latest default parameter settings into the IOExtPar block. |
During the open, the parallel device pays attention to just one flag; PARF_SHARED. For consistency, the other flag bits should also be properly set. Full descriptions of all flags will be given later. When the parallel device is opened, it fills the latest default parameter settings into the IOExtPar block. |
||
Line 148: | Line 79: | ||
You read from the parallel device by passing an IOExtPar to the device with CMD_READ set in io_Command, the number of bytes to be read set in io_Length and the address of the read buffer set in io_Data. |
You read from the parallel device by passing an IOExtPar to the device with CMD_READ set in io_Command, the number of bytes to be read set in io_Length and the address of the read buffer set in io_Data. |
||
+ | <pre> |
||
− | <pre>#define READ_BUFFER_SIZE 256 |
||
+ | #define READ_BUFFER_SIZE 256 |
||
char ParallelReadBuffer[READ_BUFFER_SIZE]; /* Reserve SIZE bytes of storage */ |
char ParallelReadBuffer[READ_BUFFER_SIZE]; /* Reserve SIZE bytes of storage */ |
||
Line 154: | Line 86: | ||
ParallelIO->IOPar.io_Data = (APTR)&ParallelReadBuffer[0]; |
ParallelIO->IOPar.io_Data = (APTR)&ParallelReadBuffer[0]; |
||
ParallelIO->IOPar.io_Command = CMD_READ; |
ParallelIO->IOPar.io_Command = CMD_READ; |
||
− | DoIO((struct IORequest *)ParallelIO); |
+ | DoIO((struct IORequest *)ParallelIO); |
+ | </pre> |
||
+ | |||
If you use this example, your task will be put to sleep waiting until the parallel device reads 256 bytes (or terminates early). Early termination can be caused by error conditions. |
If you use this example, your task will be put to sleep waiting until the parallel device reads 256 bytes (or terminates early). Early termination can be caused by error conditions. |
||
Line 163: | Line 97: | ||
To write a NULL-terminated string, set the length to -1; the device will output from your buffer until it encounters and transmits a value of zero (0x00). |
To write a NULL-terminated string, set the length to -1; the device will output from your buffer until it encounters and transmits a value of zero (0x00). |
||
+ | <pre> |
||
− | <pre>ParallelIO->IOPar.io_Length = -1; |
||
+ | ParallelIO->IOPar.io_Length = -1; |
||
ParallelIO->IOPar.io_Data = (APTR)"Parallel lines cross 7 times... "; |
ParallelIO->IOPar.io_Data = (APTR)"Parallel lines cross 7 times... "; |
||
ParallelIO->IOPar.io_Command = CMD_WRITE; |
ParallelIO->IOPar.io_Command = CMD_WRITE; |
||
− | DoIO((struct IORequest *)ParallelIO); /* execute write */ |
+ | DoIO((struct IORequest *)ParallelIO); /* execute write */ |
+ | </pre> |
||
+ | |||
The length of the request is -1, meaning we are writing a NULL-terminated string. The number of characters sent can be found in io_Actual. |
The length of the request is -1, meaning we are writing a NULL-terminated string. The number of characters sent can be found in io_Actual. |
||
Line 175: | Line 112: | ||
All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort them with AbortIO(): |
All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort them with AbortIO(): |
||
+ | <pre> |
||
− | <pre>if (!(CheckIO(ParallelIO))) |
||
+ | if (!(CheckIO(ParallelIO))) |
||
{ |
{ |
||
AbortIO(ParallelIO); /* Ask device to abort request, if pending */ |
AbortIO(ParallelIO); /* Ask device to abort request, if pending */ |
||
} |
} |
||
WaitIO(ParallelIO); /* Wait for abort, then clean up */ |
WaitIO(ParallelIO); /* Wait for abort, then clean up */ |
||
− | CloseDevice((struct IORequest *)ParallelIO); |
+ | CloseDevice((struct IORequest *)ParallelIO); |
+ | </pre> |
||
+ | |||
== Ending A Read or Write with Termination Characters == |
== Ending A Read or Write with Termination Characters == |
||
− | |||
− | |||
Reads and writes from the parallel device may terminate early if an error occurs or if an end-of-file is sensed. For example, if a break is detected on the line, any current read request will be returned with the error ParErr_DetectedBreak. The count of characters read to that point will be in the io_Actual field of the request. |
Reads and writes from the parallel device may terminate early if an error occurs or if an end-of-file is sensed. For example, if a break is detected on the line, any current read request will be returned with the error ParErr_DetectedBreak. The count of characters read to that point will be in the io_Actual field of the request. |
||
− | |||
− | |||
You can specify a set of possible end-of-file characters that the parallel device is to look for in the input or output stream using the PDCMD_SETPARAMS command. These are contained in an io_PTermArray that you provide. io_PTermArray is used only when the PARF_EOFMODE flag is selected (see “Parallel Flags” below). |
You can specify a set of possible end-of-file characters that the parallel device is to look for in the input or output stream using the PDCMD_SETPARAMS command. These are contained in an io_PTermArray that you provide. io_PTermArray is used only when the PARF_EOFMODE flag is selected (see “Parallel Flags” below). |
||
Line 197: | Line 133: | ||
The read will terminate before the io_Length number of characters is read if a ‘Q’, ‘E’, or ‘A’ is detected. |
The read will terminate before the io_Length number of characters is read if a ‘Q’, ‘E’, or ‘A’ is detected. |
||
+ | {| class="wikitable" |
||
− | <sub>b</sub>oxIt’s Usually For Output.Most applications for the parallel device use the device for output, hence the termination feature is usually done on the output stream. |
||
+ | | ''It’s Usually For Output.'' Most applications for the parallel device use the device for output, hence the termination feature is usually done on the output stream. |
||
+ | |} |
||
== Setting Parallel Parameters == |
== Setting Parallel Parameters == |
||
Line 203: | Line 141: | ||
You can control the parallel parameters shown in the following table. The parameter name within the parallel IOExtPar data structure is shown below. All of the fields described in this section are filled with defaults when you call OpenDevice(). Thus, you need not worry about any parameter that you do not need to change. The parameters are defined in the include file devices/parallel.h. |
You can control the parallel parameters shown in the following table. The parameter name within the parallel IOExtPar data structure is shown below. All of the fields described in this section are filled with defaults when you call OpenDevice(). Thus, you need not worry about any parameter that you do not need to change. The parameters are defined in the include file devices/parallel.h. |
||
+ | '''Parallel Parameters (IOExtPar)''' |
||
− | ll |
||
+ | ; io_PExtFlags |
||
− | 2c'''Parallel Parameters (IOExtPar)'''<br /> |
||
+ | : Reserved for future use. |
||
− | '''IOExtPar''' &<br /> |
||
− | '''Field Name''' & '''Parallel Device Parameter It Controls'''<br /> |
||
− | io_PExtFlags & 9cmReserved for future use.<br /> |
||
− | io_PTermArray & 9cmA byte-array of eight termination characters, must be in descending order. If EOFMODE is set in the parallel flags, this array specifies eight possible choices of characters to use as an end-of-file mark. See the section above titled “Ending A Read Or Write with Termination Characters” and the PDCMD_SETPARAMS summary page in the Autodocs.<br /> |
||
− | io_Status & 9cmContains status information. It is filled in by the PDCMD_QUERY command.<br /> |
||
− | io_ParFlags & 9cmSee “Parallel Flags” below.<br /> |
||
+ | ; io_PTermArray |
||
+ | : A byte-array of eight termination characters, must be in descending order. If EOFMODE is set in the parallel flags, this array specifies eight possible choices of characters to use as an end-of-file mark. See the section above titled “Ending A Read Or Write with Termination Characters” and the PDCMD_SETPARAMS summary page in the Autodocs. |
||
+ | |||
+ | ; io_Status |
||
+ | : Contains status information. It is filled in by the PDCMD_QUERY command. |
||
+ | |||
+ | ; io_ParFlags |
||
+ | : See “Parallel Flags” below. |
||
You set the parallel parameters by passing an IOExtPar to the device with PDCMD_SETPARAMS set in io_Command and with the flags and parameters set to the values you want. |
You set the parallel parameters by passing an IOExtPar to the device with PDCMD_SETPARAMS set in io_Command and with the flags and parameters set to the values you want. |
||
+ | <pre> |
||
− | <pre>ParallelIO->io_ParFlags &= ~PARF_EOFMODE; /* Set EOF mode */ |
||
+ | ParallelIO->io_ParFlags &= ~PARF_EOFMODE; /* Set EOF mode */ |
||
ParallelIO->IOPar.io_Command = PDCMD_SETPARAMS; /* Set params command */ |
ParallelIO->IOPar.io_Command = PDCMD_SETPARAMS; /* Set params command */ |
||
if (DoIO(ParallelIO); |
if (DoIO(ParallelIO); |
||
− | printf("Error setting parameters!\n"); |
+ | printf("Error setting parameters!\n"); |
+ | </pre> |
||
+ | |||
The above code fragment modifies one bit in io_ParFlags, then sends the command. |
The above code fragment modifies one bit in io_ParFlags, then sends the command. |
||
+ | {| class="wikitable" |
||
− | <sub>b</sub>oxProper Time for Parameter Changes.A parameter change should not be performed while an I/O request is actually being processed, because it might invalidate already active request handling. Therefore you should use PDCMD_SETPARAMS only when you have no parallel I/O requests pending. |
||
+ | | ''Proper Time for Parameter Changes.'' A parameter change should not be performed while an I/O request is actually being processed, because it might invalidate already active request handling. Therefore you should use PDCMD_SETPARAMS only when you have no parallel I/O requests pending. |
||
+ | |} |
||
=== Parallel Flags (bit definitions for io_ParFlags) === |
=== Parallel Flags (bit definitions for io_ParFlags) === |
||
− | |||
− | |||
The flags shown in the following table can be set to affect the operation of the parallel device. Note that the default state of all of these flags is zero. The flags are defined in the include file devices/parallel.h. |
The flags shown in the following table can be set to affect the operation of the parallel device. Note that the default state of all of these flags is zero. The flags are defined in the include file devices/parallel.h. |
||
+ | '''Parallel Flags (io_ParFlags)''' |
||
+ | |||
+ | ; PARF_EOFMODE |
||
+ | : Set this bit if you want the parallel device to check I/O characters against io_TermArray and terminate the I/O request immediately if an end-of-file character has been encountered. ''Note'': This bit can be set and reset directly in the user’s IOExtPar block without a call to PDCMD_SETPARAMS. |
||
+ | ; PARF_ACKMODE |
||
+ | : Set this bit if you want to use ACK handshaking. |
||
+ | ; PARF_FASTMODE |
||
− | ll |
||
+ | : Set this bit if you want to use high-speed mode for transfers to high-speed printers. This mode will send out data as long as the BUSY signal is low. The printer must be able to raise the BUSY signal within three microseconds or data will be lost. Should only be used when the device has been opened for exclusive-access. |
||
+ | ; PARF_SLOWMODE |
||
− | 2c'''Parallel Flags (io_ParFlags)'''<br /> |
||
+ | : Set this bit if you want to use slow-speed mode for transfers to very slow printers. Should not be used with high-speed printers. |
||
− | '''Flag Name''' & '''Effect on Device Operation'''<br /> |
||
− | PARF_EOFMODE & 9cmSet this bit if you want the parallel device to check I/O characters against io_TermArray and terminate the I/O request immediately if an end-of-file character has been encountered. ''Note'': This bit can be set and reset directly in the user’s IOExtPar block without a call to PDCMD_SETPARAMS.<br /> |
||
− | PARF_ACKMODE & 9cmSet this bit if you want to use ACK handshaking.<br /> |
||
− | PARF_FASTMODE & 9cmSet this bit if you want to use high-speed mode for transfers to high-speed printers. This mode will send out data as long as the BUSY signal is low. The printer must be able to raise the BUSY signal within three microseconds or data will be lost. Should only be used when the device has been opened for exclusive-access.<br /> |
||
− | PARF_SLOWMODE & 9cmSet this bit if you want to use slow-speed mode for transfers to very slow printers. Should not be used with high-speed printers.<br /> |
||
− | PARF_SHARED & 9cmSet this bit if you want to allow other tasks to simultaneously access the parallel port. The default is exclusive access. If someone already has the port, whether for exclusive or shared access, and you ask for exclusive access, your OpenDevice() call will fail (must be modified before OpenDevice()).<br /> |
||
+ | ; PARF_SHARED |
||
+ | : Set this bit if you want to allow other tasks to simultaneously access the parallel port. The default is exclusive access. If someone already has the port, whether for exclusive or shared access, and you ask for exclusive access, your OpenDevice() call will fail (must be modified before OpenDevice()). |
||
== Querying the Parallel Device == |
== Querying the Parallel Device == |
||
− | |||
− | |||
You query the parallel device by passing an IOExtPar to the device with PDCMD_QUERY set in io_Command. The parallel device will respond with the status of the parallel port lines and registers. |
You query the parallel device by passing an IOExtPar to the device with PDCMD_QUERY set in io_Command. The parallel device will respond with the status of the parallel port lines and registers. |
||
+ | <pre> |
||
− | <pre>UWORD Parallel_Status; |
||
+ | UWORD Parallel_Status; |
||
ParallelIO->IOPar.io_Command = PDCMD_QUERY; /* indicate query */ |
ParallelIO->IOPar.io_Command = PDCMD_QUERY; /* indicate query */ |
||
DoIO((struct IORequest *)ParallelIO); |
DoIO((struct IORequest *)ParallelIO); |
||
− | Parallel_Status = ParallelIO->io_Status; /* store returned status */ |
+ | Parallel_Status = ParallelIO->io_Status; /* store returned status */ |
+ | </pre> |
||
+ | |||
The 8 status bits of the parallel device are returned in io_Status. |
The 8 status bits of the parallel device are returned in io_Status. |
||
+ | '''Parallel Device Status Bits''' |
||
− | lll |
||
+ | {| class="wikitable" |
||
− | |||
+ | ! Bit |
||
− | 3c'''Parallel Device Status Bits'''<br /> |
||
+ | ! Active |
||
− | '''Bit''' & '''Active''' & '''Function'''<br /> |
||
+ | ! Function |
||
− | 0 & high & Printer busy toggle (offline)<br /> |
||
+ | |- |
||
− | 1 & high & Paper out<br /> |
||
+ | | 0 || high || Printer busy toggle (offline) |
||
− | 2 & high & 9.2cmPrinter Select on the ''A1000''. On the ''A500'' and ''A2000'', select is also connected to to the parallel port’s ''Ring Indicator''. Be cautious when making cables.<br /> |
||
+ | |- |
||
− | 3 & – & read=0; write=1<br /> |
||
+ | | 1 || high || Paper out |
||
− | 4–7 & – & (reserved)<br /> |
||
+ | |- |
||
− | |||
+ | | 2 || high || Printer Select on the ''A1000''. On the ''A500'' and ''A2000'', select is also connected to to the parallel port’s ''Ring Indicator''. Be cautious when making cables. |
||
+ | |- |
||
+ | | 3 || – || read=0; write=1 |
||
+ | |- |
||
+ | | 4–7 || – || (reserved) |
||
+ | |} |
||
The parallel device also returns error codes whenever an operation is attempted. |
The parallel device also returns error codes whenever an operation is attempted. |
||
+ | <pre> |
||
− | <pre>struct IOPArray Terminators = |
||
+ | struct IOPArray Terminators = |
||
{ |
{ |
||
0x51454141, /* Q E A A */ |
0x51454141, /* Q E A A */ |
||
Line 280: | Line 236: | ||
ParallellIO->IOPar.io_Command = PDCMD_SETPARAMS; /* Set parameters */ |
ParallellIO->IOPar.io_Command = PDCMD_SETPARAMS; /* Set parameters */ |
||
if (DoIO((struct IORequest *)ParallelIO)) |
if (DoIO((struct IORequest *)ParallelIO)) |
||
− | printf("Set Params failed. Error: %ld ",ParallelIO->IOPar.io_Error); |
+ | printf("Set Params failed. Error: %ld ",ParallelIO->IOPar.io_Error); |
+ | </pre> |
||
+ | |||
The error is returned in the io_Error field of the IOExtPar structure. |
The error is returned in the io_Error field of the IOExtPar structure. |
||
+ | '''Parallel Device Error Codes''' |
||
− | lll |
||
+ | {| class="wikitable" |
||
− | |||
+ | ! Error |
||
− | 3c'''Parallel Device Error Codes'''<br /> |
||
+ | ! Value |
||
− | '''Error''' & '''Value''' & '''Explanation'''<br /> |
||
+ | ! Explanation |
||
− | ParErr_DevBusy & 1 & Device in use<br /> |
||
+ | |- |
||
− | ParErr_BufToBig & 2 & Out of memory<br /> |
||
+ | | ParErr_DevBusy || 1 || Device in use |
||
− | ParErr_InvParam & 3 & Invalid parameter<br /> |
||
+ | |- |
||
− | ParErr_LineErr & 4 & Parallel line error<br /> |
||
+ | | ParErr_BufToBig || 2 || Out of memory |
||
− | ParErr_NotOpen & 5 & Device not open<br /> |
||
+ | |- |
||
− | ParErr_PortReset & 6 & Port Reset<br /> |
||
+ | | ParErr_InvParam || 3 || Invalid parameter |
||
− | ParErr_InitErr & 7 & Initialization Error<br /> |
||
+ | |- |
||
− | |||
+ | | ParErr_LineErr || 4 || Parallel line error |
||
+ | |- |
||
+ | | ParErr_NotOpen || 5 || Device not open |
||
+ | |- |
||
+ | | ParErr_PortReset || 6 || Port Reset |
||
+ | |- |
||
+ | | ParErr_InitErr || 7 || Initialization Error |
||
+ | |} |
||
− | <pre> |
+ | <pre> |
+ | /* |
||
* Parallel.c |
* Parallel.c |
||
* |
* |
||
Line 378: | Line 345: | ||
DeletePort(ParallelMP); |
DeletePort(ParallelMP); |
||
} |
} |
||
+ | } |
||
− | }</pre> |
||
+ | </pre> |
||
+ | |||
== Additional Information on the Parallel Device == |
== Additional Information on the Parallel Device == |
||
− | Additional programming information on the parallel device can be found in the include files and the Autodocs for the parallel device. Both are contained in the |
+ | Additional programming information on the parallel device can be found in the include files and the Autodocs for the parallel device. Both are contained in the SDK. |
+ | {| class="wikitable" |
||
− | |ll| |
||
+ | ! Includes |
||
+ | |- |
||
+ | | devices/parallel.h |
||
+ | |} |
||
+ | {| class="wikitable" |
||
− | 2c'''Parallel Device Information'''<br /> |
||
+ | ! AutoDocs |
||
− | Includes & devices/parallel.h<br /> |
||
+ | |- |
||
− | & devices/parallel.i<br /> |
||
− | + | | parallel.doc |
|
+ | |} |
Latest revision as of 21:57, 22 May 2012
This page is not yet fully updated to AmigaOS 4.x some of the information contained here may not be applicable in part or totally. |
Contents
Parallel Device
The parallel device provides a hardware-independent interface to the Amiga’s Centronics-compatible parallel port. The primary use of the Amiga parallel port is for output to printers, but with its extensions for bi-directional I/O, it can also be used for communication with digitizers and high-speed links with other computers. The parallel device is based on the conventions of Exec device I/O, with extensions for parameter setting and control.
Parallel Device Commands and Functions
Command | Command Operation |
---|---|
CMD_FLUSH | Purge all queued requests for the parallel device. Does not affect active requests. |
CMD_READ | Read a stream of characters from the parallel port. The number of characters can be specified or a termination character(s) can be used. |
CMD_RESET | Reset the parallel port to its initialized state. All active and queued I/O requests will be aborted. |
CMD_START | Restart all paused I/O over the parallel port. Reactivates the handshaking sequence. |
CMD_STOP | Pause all active I/O over the parallel port. Deactivates the handshaking sequence. |
CMD_WRITE | Write out a stream of characters to the parallel port. The number of characters can be specified or a NULL-terminated string can be sent. |
PDCMD_QUERY | Return the status of the parallel port lines and registers. |
PDCMD_SETPARAMS | Set the parameters of the parallel port. |
Device Interface
The parallel device operates like the other Amiga devices. To use it, you must first open the parallel device, then send I/O requests to it, and then close it when finished. See Exec Device I/O for general information on device usage.
The I/O request used by the parallel device is called IOExtPar.
struct IOExtPar { struct IOStdReq IOPar; ULONG io_PExtFlags; /* additional parallel flags */ UBYTE io_Status; /* status of parallel port and registers */ UBYTE io_ParFlags; /* parallel device flags */ struct IOPArray io_PTermArray; /* termination character array */ };
See the include file devices/parallel.h for the complete structure definition.
Opening the Parallel Device
Three primary steps are required to open the parallel device:
- Create a message port using CreatePort(). Reply messages from the device must be directed to a message port.
- Create an extended I/O request structure of type IOExtPar using CreateExtIO(). CreateExtIO() will initialize the I/O request to point to your reply port.
- Open the parallel device. Call OpenDevice(), passing the I/O request.
struct MsgPort *ParallelMP; /* Pointer to reply port */ struct IOExtPar *ParallelIO; /* Pointer to I/O request */ if (ParallelMP=CreatePort(0,0) ) if (ParallelIO=(struct IOExtPar *) CreateExtIO(ParallelMP,sizeof(struct IOExtPar)) ) if (OpenDevice(PARALLELNAME,0L,(struct IORequest *)ParallelIO,0) ) printf("%s did not open\n",PARALLELNAME);
During the open, the parallel device pays attention to just one flag; PARF_SHARED. For consistency, the other flag bits should also be properly set. Full descriptions of all flags will be given later. When the parallel device is opened, it fills the latest default parameter settings into the IOExtPar block.
Reading from the Parallel Device
You read from the parallel device by passing an IOExtPar to the device with CMD_READ set in io_Command, the number of bytes to be read set in io_Length and the address of the read buffer set in io_Data.
#define READ_BUFFER_SIZE 256 char ParallelReadBuffer[READ_BUFFER_SIZE]; /* Reserve SIZE bytes of storage */ ParallelIO->IOPar.io_Length = READ_BUFFER_SIZE; ParallelIO->IOPar.io_Data = (APTR)&ParallelReadBuffer[0]; ParallelIO->IOPar.io_Command = CMD_READ; DoIO((struct IORequest *)ParallelIO);
If you use this example, your task will be put to sleep waiting until the parallel device reads 256 bytes (or terminates early). Early termination can be caused by error conditions.
Writing to the Parallel Device
You write to the parallel device by passing an IOExtPar to the device with CMD_WRITE set in io_Command, the number of bytes to be written set in io_Length and the address of the write buffer set in io_Data.
To write a NULL-terminated string, set the length to -1; the device will output from your buffer until it encounters and transmits a value of zero (0x00).
ParallelIO->IOPar.io_Length = -1; ParallelIO->IOPar.io_Data = (APTR)"Parallel lines cross 7 times... "; ParallelIO->IOPar.io_Command = CMD_WRITE; DoIO((struct IORequest *)ParallelIO); /* execute write */
The length of the request is -1, meaning we are writing a NULL-terminated string. The number of characters sent can be found in io_Actual.
Closing the Parallel Device
Each OpenDevice() must eventually be matched by a call to CloseDevice(). When the last close is performed, the device will deallocate all resources and buffers. The latest parameter settings will be saved for the next open.
All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort them with AbortIO():
if (!(CheckIO(ParallelIO))) { AbortIO(ParallelIO); /* Ask device to abort request, if pending */ } WaitIO(ParallelIO); /* Wait for abort, then clean up */ CloseDevice((struct IORequest *)ParallelIO);
Ending A Read or Write with Termination Characters
Reads and writes from the parallel device may terminate early if an error occurs or if an end-of-file is sensed. For example, if a break is detected on the line, any current read request will be returned with the error ParErr_DetectedBreak. The count of characters read to that point will be in the io_Actual field of the request.
You can specify a set of possible end-of-file characters that the parallel device is to look for in the input or output stream using the PDCMD_SETPARAMS command. These are contained in an io_PTermArray that you provide. io_PTermArray is used only when the PARF_EOFMODE flag is selected (see “Parallel Flags” below).
If EOF mode is selected, each input data character read into or written from the user’s data block is compared against those in io_PTermArray. If a match is found, the IOExtPar is terminated as complete, and the count of characters transferred (including the termination character) is stored in io_Actual.
To keep this search overhead as efficient as possible, the parallel device requires that the array of characters be in descending order. The array has eight bytes and all must be valid (that is, do not pad with zeros unless zero is a valid EOF character). Fill to the end of the array with the lowest value termination character. When making an arbitrary choice of EOF character(s), you will get the quickest response from the lowest value(s) available.
The read will terminate before the io_Length number of characters is read if a ‘Q’, ‘E’, or ‘A’ is detected.
It’s Usually For Output. Most applications for the parallel device use the device for output, hence the termination feature is usually done on the output stream. |
Setting Parallel Parameters
You can control the parallel parameters shown in the following table. The parameter name within the parallel IOExtPar data structure is shown below. All of the fields described in this section are filled with defaults when you call OpenDevice(). Thus, you need not worry about any parameter that you do not need to change. The parameters are defined in the include file devices/parallel.h.
Parallel Parameters (IOExtPar)
- io_PExtFlags
- Reserved for future use.
- io_PTermArray
- A byte-array of eight termination characters, must be in descending order. If EOFMODE is set in the parallel flags, this array specifies eight possible choices of characters to use as an end-of-file mark. See the section above titled “Ending A Read Or Write with Termination Characters” and the PDCMD_SETPARAMS summary page in the Autodocs.
- io_Status
- Contains status information. It is filled in by the PDCMD_QUERY command.
- io_ParFlags
- See “Parallel Flags” below.
You set the parallel parameters by passing an IOExtPar to the device with PDCMD_SETPARAMS set in io_Command and with the flags and parameters set to the values you want.
ParallelIO->io_ParFlags &= ~PARF_EOFMODE; /* Set EOF mode */ ParallelIO->IOPar.io_Command = PDCMD_SETPARAMS; /* Set params command */ if (DoIO(ParallelIO); printf("Error setting parameters!\n");
The above code fragment modifies one bit in io_ParFlags, then sends the command.
Proper Time for Parameter Changes. A parameter change should not be performed while an I/O request is actually being processed, because it might invalidate already active request handling. Therefore you should use PDCMD_SETPARAMS only when you have no parallel I/O requests pending. |
Parallel Flags (bit definitions for io_ParFlags)
The flags shown in the following table can be set to affect the operation of the parallel device. Note that the default state of all of these flags is zero. The flags are defined in the include file devices/parallel.h.
Parallel Flags (io_ParFlags)
- PARF_EOFMODE
- Set this bit if you want the parallel device to check I/O characters against io_TermArray and terminate the I/O request immediately if an end-of-file character has been encountered. Note: This bit can be set and reset directly in the user’s IOExtPar block without a call to PDCMD_SETPARAMS.
- PARF_ACKMODE
- Set this bit if you want to use ACK handshaking.
- PARF_FASTMODE
- Set this bit if you want to use high-speed mode for transfers to high-speed printers. This mode will send out data as long as the BUSY signal is low. The printer must be able to raise the BUSY signal within three microseconds or data will be lost. Should only be used when the device has been opened for exclusive-access.
- PARF_SLOWMODE
- Set this bit if you want to use slow-speed mode for transfers to very slow printers. Should not be used with high-speed printers.
- PARF_SHARED
- Set this bit if you want to allow other tasks to simultaneously access the parallel port. The default is exclusive access. If someone already has the port, whether for exclusive or shared access, and you ask for exclusive access, your OpenDevice() call will fail (must be modified before OpenDevice()).
Querying the Parallel Device
You query the parallel device by passing an IOExtPar to the device with PDCMD_QUERY set in io_Command. The parallel device will respond with the status of the parallel port lines and registers.
UWORD Parallel_Status; ParallelIO->IOPar.io_Command = PDCMD_QUERY; /* indicate query */ DoIO((struct IORequest *)ParallelIO); Parallel_Status = ParallelIO->io_Status; /* store returned status */
The 8 status bits of the parallel device are returned in io_Status.
Parallel Device Status Bits
Bit | Active | Function |
---|---|---|
0 | high | Printer busy toggle (offline) |
1 | high | Paper out |
2 | high | Printer Select on the A1000. On the A500 and A2000, select is also connected to to the parallel port’s Ring Indicator. Be cautious when making cables. |
3 | – | read=0; write=1 |
4–7 | – | (reserved) |
The parallel device also returns error codes whenever an operation is attempted.
struct IOPArray Terminators = { 0x51454141, /* Q E A A */ 0x41414141 /* fill to end with lowest value, must be in descending order */ }; ParallellIO->io_ParFlags != PARF_EOFMODE; /* Set EOF mode flag */ ParallelIO->io_PTermArray = Terminators; /* Set termination characters */ ParallellIO->IOPar.io_Command = PDCMD_SETPARAMS; /* Set parameters */ if (DoIO((struct IORequest *)ParallelIO)) printf("Set Params failed. Error: %ld ",ParallelIO->IOPar.io_Error);
The error is returned in the io_Error field of the IOExtPar structure.
Parallel Device Error Codes
Error | Value | Explanation |
---|---|---|
ParErr_DevBusy | 1 | Device in use |
ParErr_BufToBig | 2 | Out of memory |
ParErr_InvParam | 3 | Invalid parameter |
ParErr_LineErr | 4 | Parallel line error |
ParErr_NotOpen | 5 | Device not open |
ParErr_PortReset | 6 | Port Reset |
ParErr_InitErr | 7 | Initialization Error |
/* * Parallel.c * * Parallel device example * * Compile with SAS C 5.10: LC -b1 -cfistq -v -y -L * * Run from CLI only */ #include <exec/types.h> #include <exec/io.h> #include <exec/memory.h> #include <dos/dos.h> #include <devices/parallel.h> #include <clib/exec_protos.h> #include <clib/alib_protos.h> #include <stdio.h> #ifdef LATTICE int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */ int chkabort(void) { return(0); } /* really */ #endif void main(void) { struct MsgPort *ParallelMP; /* Define storage for one pointer */ struct IOExtPar *ParallelIO; /* Define storage for one pointer */ ULONG WaitMask; /* Collect all signals here */ ULONG Temp; /* Hey, we all need pockets :-) */ if (ParallelMP=CreatePort(0,0) ) { if (ParallelIO=(struct IOExtPar *) CreateExtIO(ParallelMP,sizeof(struct IOExtPar)) ) { if (OpenDevice(PARALLELNAME,0L,(struct IORequest *)ParallelIO,0) ) printf("%s did not open\n",PARALLELNAME); else { /* Precalculate a wait mask for the CTRL-C, CTRL-F and message port * signals. When one or more signals are received, Wait() will * return. Press CTRL-C to exit the example. Press CTRL-F to * wake up the example without doing anything. NOTE: A signal * may show up without an associated message! */ WaitMask = SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_F | 1L << ParallelMP->mp_SigBit; ParallelIO->IOPar.io_Command = CMD_WRITE; ParallelIO->IOPar.io_Length = -1; ParallelIO->IOPar.io_Data = (APTR)"Hey, Jude!\\r\n"; SendIO(ParallelIO); /* execute write */ printf("Sleeping until CTRL-C, CTRL-F, or write finish\n"); while(1) { Temp = Wait(WaitMask); printf("Just woke up (YAWN!)\n"); if (SIGBREAKF_CTRL_C & Temp) break; if (CheckIO(ParallelIO) ) /* If request is complete... */ { WaitIO(ParallelIO); /* clean up and remove reply */ printf("%ld bytes sent\n",ParallelIO->IOPar.io_Actual); break; } } AbortIO(ParallelIO); /* Ask device to abort request, if pending */ WaitIO(ParallelIO); /* Wait for abort, then clean up */ CloseDevice((struct IORequest *)ParallelIO); } DeleteExtIO(ParallelIO); } DeletePort(ParallelMP); } }
Additional Information on the Parallel Device
Additional programming information on the parallel device can be found in the include files and the Autodocs for the parallel device. Both are contained in the SDK.
Includes |
---|
devices/parallel.h |
AutoDocs |
---|
parallel.doc |