home *** CD-ROM | disk | FTP | other *** search
- 'Example of using the word functions that are in the
- 'WORD.BAS file to manipulate the I/O ports.
- '
- 'By: George Spafford Copyright 1993
- '
- 'No additional libraries required
- '
- 'v1.0 05/02/93
- '
- '**************************************************
-
- 'If you use these routines, please have the courtesy
- 'of registering the tutorial.
-
- 'Make sure that you have all of your variables typed
- 'correctly before you use one of the following
- 'routines. Use integers where integers are identified (%).
- 'Use long integers where long integers are identified (&).
-
- 'Int2Long& is a function that accepts a signed
- 'integer and returns an unsigned long integer. Since
- 'BASIC uses the high bit to toggle the sign of an
- 'integer, you must convert it to a long integer before
- 'you perform any bit operations on it.
-
- DECLARE FUNCTION Int2Long& (IntNumber%)
-
- 'BASIC does NOT have a built in facility to PEEK
- 'words! Tell the PeekWord% function where to look,
- 'and it will read in a word at that segment and offset.
-
- DECLARE FUNCTION PeekWord% (Segment%, Offset%)
-
- 'As with Peeks, BASIC does not support a POKE function
- 'for words. This next subroutine adds that capability.
- 'Tell the subroutine the segment, offset and word that
- 'you wish it to POKE in and it will do so.
-
- DECLARE SUB PokeWord (Segment%, Offset%, Word%)
-
- 'As you code more and more programs, try to make your code
- 'as modular as possible. By creating objects (OOP systems),
- 'you can significantly increase your code reusability.
- 'Try to only create the wheel once! Some of the demos would
- 'benefit greatly by judicial use of subroutines. In order to
- 'have top-down readability, I did not modularize the code.
- 'Just a FYI -- George
-
- DEFINT A-Z
- Title$ = "S3 Demo of WORD functions and I/O ports Copyright George Spafford 1993"
-
- Main:
- CLS
- PRINT Title$
- LOCATE 3, 30: PRINT "To enter hexadecimal numbers, prefix your answer"
- LOCATE 4, 30: PRINT "with &H. For example, &H400 represents 400 Hex."
- LOCATE 3, 1
- GOSUB ReadPorts
- PRINT "Menu Port Address"
- PRINT "---- ---- -------"
- PRINT " 1. COM1: "; HEX$(COM1); " Hex" 'HEX$ formats numeric
- PRINT " 2. COM2: "; HEX$(COM2) 'input to a hexadecimal
- PRINT " 3. COM3: "; HEX$(COM3) 'string representation
- PRINT " 4. COM4: "; HEX$(COM4)
- PRINT " 5. LPT1: "; HEX$(LPT1)
- PRINT " 6. LPT2: "; HEX$(LPT2)
- PRINT " 7. LPT3: "; HEX$(LPT3)
- PRINT " 8. LPT4: "; HEX$(LPT4)
- PRINT "======================="
- PRINT
- PRINT "Please select an option:"
- PRINT
- INPUT "(D)elete (E)dit (S)wap (Q)uit: ", Ans$
- Ans$ = LTRIM$(RTRIM$(UCASE$(Ans$))) 'trim spaces and make the
- 'answer upper case.
- IF Ans$ = "" THEN PRINT : PRINT : END 'if answer is NULL then end
-
- 'Just a note regarding efficiency when conditions are involved:
- 'If you have more than a couple of repetitive tasks to test, use
- 'the SELECT CASE method. IF THEN statements require converting and
- 'testing a condition each time. A select only has to convert the test
- 'variable once and then evaluate it against all of the answers.
- 'Taking this approach one step further, if you can use integer varaibles,
- 'then the test is even faster. In the instance below, speed is not a
- 'factor, readability is.
-
- SELECT CASE Ans$
- CASE "D"
- PRINT
- INPUT "Delete which port: ", Del$
- Del$ = LTRIM$(RTRIM$(Del$))
- IF Del$ <> "" THEN
- Value = VAL(Del$)
- GOSUB Choice
- IF Offset <> 0 THEN
- CALL PokeWord(0, Offset, 0)
- END IF
- END IF
- CASE "E"
- PRINT
- INPUT "Edit which port: ", Edit$
- Edit$ = LTRIM$(RTRIM$(Edit$))
- IF Edit$ <> "" THEN
- PRINT
- Value = VAL(Edit$)
- GOSUB Choice
- IF Offset <> 0 THEN
- INPUT "New value: ", NewValue
- CALL PokeWord(0, Offset, NewValue)
- END IF
- END IF
- CASE "S"
- PRINT
- INPUT "Swap port one: ", From$
- Value = VAL(From$)
- GOSUB Choice
- FromAddr = Addr
- FromOffset = Offset
- INPUT "Swap port two: ", To$
- Value = VAL(To$)
- GOSUB Choice
- ToAddr = Addr
- ToOffset = Offset
- IF ToOffset <> 0 AND FromOffset <> 0 THEN
- CALL PokeWord(0, ToOffset, FromAddr)
- CALL PokeWord(0, FromOffset, ToAddr)
- END IF
- CASE "Q"
- PRINT : PRINT : END
- END SELECT
- GOTO Main
- END
-
- Choice:
- Addr = 0
- SELECT CASE Value
- CASE 1
- Addr = COM1
- Offset = COM1off
- CASE 2
- Addr = COM2
- Offset = COM2off
- CASE 3
- Addr = COM3
- Offset = COM3off
- CASE 4
- Addr = COM4
- Offset = COM4off
- CASE 5
- Addr = LPT1
- Offset = LPT1off
- CASE 6
- Addr = LPT2
- Offset = LPT2off
- CASE 7
- Addr = LPT3
- Offset = LPT3off
- CASE 8
- Addr = LPT4
- Offset = LPT4off
- CASE ELSE
- Addr = 0
- Offset = 0
- END SELECT
-
-
- ReadPorts:
- 'The BIOS data area starts at 0000:0400. The first
- '16 bytes of it concerns the I/O ports. If the port
- 'is enabled, there will be a word entry that describes
- 'the I/O address where data should be sent when that device
- 'is used. If the word is 0, then the device has not been
- 'recognized. If a value is forced, then the system will
- 'recognize that port whether it truly exists or not.
- 'For example, some systems do not automatically scan
- 'for COM3 and COM4 at POST (Power On Self-Test) time. You
- 'must enter the address manually for that port if you
- 'need to use it in those instances.
-
- COM1off = &H400 'Save Offset
- COM1 = PeekWord%(0, COM1off) 'Get I/O address used
- COM2off = &H402
- COM2 = PeekWord%(0, COM2off)
- COM3off = &H404
- COM3 = PeekWord%(0, COM3off)
- COM4off = &H406
- COM4 = PeekWord%(0, COM4off)
- LPT1off = &H408
- LPT1 = PeekWord%(0, LPT1off)
- LPT2off = &H40A
- LPT2 = PeekWord%(0, LPT2off)
- LPT3off = &H40C
- LPT3 = PeekWord%(0, LPT3off)
- LPT4off = &H40E
- LPT4 = PeekWord%(0, LPT4off)
- RETURN
-
- DEFSNG A-Z
- FUNCTION Int2Long& (IntNumber%)
- 'If the integer is negative, we need to add 65536
- 'to the number (which is 2 * integer limit) to get
- 'our new long integer.
-
- IF IntNumber% < 0 THEN
- Int2Long& = 65536 + IntNumber%
- ELSE
- Int2Long& = IntNumber%
- END IF
- END FUNCTION
-
- FUNCTION PeekWord% (Segment%, Offset%)
- DEF SEG = Segment% 'set segment
- High = PEEK(Offset% + 1) 'High byte is at offset + 1
- Low = PEEK(Offset%) 'Low byte is at offset
- PeekWord% = (High * 256) + Low 'Compute the word value
- DEF SEG 'return to default segment
- END FUNCTION
-
- SUB PokeWord (Segment%, Offset%, Word%)
- DEF SEG = Segment% 'Set segment
- High = (Word% \ 256) 'perform integer division
- 'to compute the high byte
- Low = Word% - (High * 256) 'compute the low byte
- POKE (Offset% + 1), High 'POKE in the high byte
- POKE Offset%, Low 'POKE in the low byte
- DEF SEG 'return to the default segment
- END SUB
-
-