Option Explicit '======================================================================================== 'Module Title: ComSupport_R2.Bas '======================================================================================== 'Author: Unknown - Communications routines modified by ZbasicAndy for "Super Comm Z" '======================================================================================== 'Date: '======================================================================================== 'Operating System: XP '======================================================================================== 'ZBasic IDE Version: 1.0.4 / ZBasic Compiler version 1-1-18 / ZX-40 Firmware 1.1.6 '======================================================================================== 'Target: ZX-40 '======================================================================================== 'Hardware: "Super Comm Z R1" ([4 software serial & 1 Hardware] RS232 ports with ZX-40 PCB) 'Main/Support Modules Needed: Super_Comm_Z_R1.bas - "sub main" basic module ' '======================================================================================== 'Comport(s) used: Comports 3,4,5 & 6 on ZX-40 for "Super Comm Z" '======================================================================================== 'Bugs fixes and updates: ' ' ' ' ' ' ' ' '======================================================================================== ' Module Description: ' ' This module subroutines are used to transfer data to and from all serial ports. ' Note that the queue size must be 9 bytes larger than the largest data element to ' provide space for the queue pointers. ' ' It is necessary to call DefineCom_X prior to communicating with each serial device. ' Use OpenSerialPort_X to initially open a ComX port, and then use ReOpenSerialPort_X ' each time that port needs to be reopened. ' ' There are many useful "generic" communication routines. The main I/O and all serial ports ' setup is done in the main subroutine e.g. Super_Comm_Z_R1.bas. All other modules refer ' to this module for communications. ' ' For Serial port diagnostics there is 4 turnaround subroutines to completely check all the ' comports on the "Super Comm Z" provided that you install a RS232 turnaround connnector ' on each serial port and jumper pins 2-3 on it. ' ' Warning ... Max baudrate is 9600 for all comports! ' '========================================================================================= ' ' '========================================================================================= 'Program Definitions: '========================================================================================= '========================================================================================= 'Constants '[Public | Private] Const As = (default private) '========================================================================================= '========================================================================================= 'Variables '{Public | Private | Dim} As (default private) '========================================================================================= 'min queue size = 10! private const InBufSize_3 as INTEGER = 50 ' 41-byte buffer. private const OutBufSize_3 as INTEGER = 50 ' 41-byte buffer. public InBuf_3(1 To InBufSize_3) as BYTE public OutBuf_3(1 To OutBufSize_3) as BYTE '------------------------------------------------------------------------------ private const InBufSize_4 as INTEGER = 50 ' 41-byte buffer. private const OutBufSize_4 as INTEGER = 50 ' 41-byte buffer. public InBuf_4(1 To InBufSize_4) as BYTE public OutBuf_4(1 To OutBufSize_4) as BYTE '------------------------------------------------------------------------------ private const InBufSize_5 as INTEGER = 50 ' 41-byte buffer. private const OutBufSize_5 as INTEGER = 50 ' 41-byte buffer. public InBuf_5(1 To InBufSize_5) as BYTE public OutBuf_5(1 To OutBufSize_5) as BYTE '---------------------------------------------------------------- private const InBufSize_6 as INTEGER = 50 ' 41-byte buffer. private const OutBufSize_6 as INTEGER = 50 ' 41-byte buffer. public InBuf_6(1 To InBufSize_6) as BYTE public OutBuf_6(1 To OutBufSize_6) as BYTE '============================================================================== '========================================================================================= 'Subroutines - Generic for all ZX-xx's '========================================================================================= public sub OpenSerialPort_3( _ ByVal BaudRate as LONG) ' Opens serial port n at the specified baud rate. CALL OpenQueue(InBuf_3, InBufSize_3) CALL OpenQueue(OutBuf_3, OutBufSize_3) CALL OpenCom(3, BaudRate, InBuf_3, OutBuf_3) END sub '------------------------------------------------------------------------------- public sub OpenSerialPort_4( _ ByVal BaudRate as LONG) CALL OpenQueue(InBuf_4, InBufSize_4) CALL OpenQueue(OutBuf_4, OutBufSize_4) CALL OpenCom(4, BaudRate, InBuf_4, OutBuf_4) END sub '------------------------------------------------------------------------------- public sub OpenSerialPort_5( _ ByVal BaudRate as LONG) CALL OpenQueue(InBuf_5, InBufSize_5) CALL OpenQueue(OutBuf_5, OutBufSize_5) CALL OpenCom(5, BaudRate, InBuf_5, OutBuf_5) END sub '------------------------------------------------------------------------------- public sub OpenSerialPort_6( _ ByVal BaudRate as LONG) CALL OpenQueue(InBuf_6, InBufSize_6) CALL OpenQueue(OutBuf_6, OutBufSize_6) CALL OpenCom(6, BaudRate, InBuf_6, OutBuf_6) END sub '=============================================================================== public sub ReOpenSerialPort_3( _ ByVal BaudRate as LONG) ' Reopens serial port n at the specified baud rate. CALL OpenCom(3, BaudRate, InBuf_3, OutBuf_3) END sub '-------------------------------------------------------------------------------- public sub ReOpenSerialPort_4( _ ByVal BaudRate as LONG) CALL OpenCom(4, BaudRate, InBuf_4, OutBuf_4) END sub '------------------------------------------------------------------------------- public sub ReOpenSerialPort_5( _ ByVal BaudRate as LONG) ' Reopens serial port 5 at the specified baud rate. CALL OpenCom(5, BaudRate, InBuf_5, OutBuf_5) END sub '------------------------------------------------------------------------------ public sub ReOpenSerialPort_6( _ ByVal BaudRate as LONG) CALL OpenCom(6, BaudRate, InBuf_6, OutBuf_6) END sub '=============================================================================== public sub PutByte_3( _ ByVal Value as BYTE) ' Sends one byte of binary data to serial port n. The byte is sent ' directly without translating it to a STRING type. CALL PutQueue(OutBuf_3, Value, 1) END sub '------------------------------------------------------------------------------- public sub PutByte_4( _ ByVal Value as BYTE) CALL PutQueue(OutBuf_4, Value, 1) END sub '------------------------------------------------------------------------------- public sub PutByte_5( _ ByVal Value as BYTE) CALL PutQueue(OutBuf_5, Value, 1) END sub '------------------------------------------------------------------------------- public sub PutByte_6( _ ByVal Value as BYTE) CALL PutQueue(OutBuf_6, Value, 1) END sub '=============================================================================== public sub GetByte_3( _ ByRef Value as BYTE, _ ByRef Success as BOOLEAN) ' Inputs a byte from serial port n, if available. Returns regardless. The ' Success flag is set depending on whether a byte is available. ' ' The byte is in direct binary format -- it is not in string format. ' Find out if anything is in the queue. Success = StatusQueue(InBuf_3) ' If data is in the queue, extract it. IF (Success) THEN CALL GetQueue(InBuf_3, Value, 1) ELSE Value = 0 END IF END sub '------------------------------------------------------------------------------- public sub GetByte_4( _ ByRef Value as BYTE, _ ByRef Success as BOOLEAN) ' Find out if anything is in the queue. Success = StatusQueue(InBuf_4) ' If data is in the queue, extract it. IF (Success) THEN CALL GetQueue(InBuf_4, Value, 1) ELSE Value = 0 END IF END sub '------------------------------------------------------------------------------- public sub GetByte_5( _ ByRef Value as BYTE, _ ByRef Success as BOOLEAN) ' Find out if anything is in the queue. Success = StatusQueue(InBuf_5) ' If data is in the queue, extract it. IF (Success) THEN CALL GetQueue(InBuf_5, Value, 1) ELSE Value = 0 END IF END sub '------------------------------------------------------------------------------- public sub GetByte_6( _ ByRef Value as BYTE, _ ByRef Success as BOOLEAN) ' Find out if anything is in the queue. Success = StatusQueue(InBuf_6) ' If data is in the queue, extract it. IF (Success) THEN CALL GetQueue(InBuf_6, Value, 1) ELSE Value = 0 END IF END sub '=============================================================================== public sub NewLine_3() ' Outputs a to serial port n. CALL PutByte_3(&h0D) CALL delay(0.50) CALL PutByte_3(&h0A) END sub '------------------------------------------------------------------------------- public sub NewLine_4() CALL PutByte_4(&h0D) CALL delay(0.50) CALL PutByte_4(&h0A) END sub '------------------------------------------------------------------------------- public sub NewLine_5() ' Outputs a to serial port n. CALL PutByte_5(&h0D) CALL delay(0.50) CALL PutByte_5(&h0A) END sub '------------------------------------------------------------------------------- public sub NewLine_6() CALL PutByte_6(&h0D) CALL delay(0.50) CALL PutByte_6(&h0A) END sub '=============================================================================== public sub PutLine_3( _ ByRef Tx as STRING) ' Outputs a STRING type, followed by . Output is to serial port n. CALL PutStr_3(Tx) CALL NewLine_3 END sub '------------------------------------------------------------------------------- public sub PutLine_4( _ ByRef Tx as STRING) CALL PutStr_4(Tx) CALL NewLine_4 END sub '------------------------------------------------------------------------------- public sub PutLine_5( _ ByRef Tx as STRING) ' Outputs a STRING type, followed by . Output is to serial port n. CALL PutStr_5(Tx) CALL NewLine_5 END sub '------------------------------------------------------------------------------- public sub PutLine_6( _ ByRef Tx as STRING) CALL PutStr_6(Tx) CALL NewLine_6 END sub '=============================================================================== public sub PutStr_3( _ ByRef Tx as STRING) ' Outputs a STRING type to serial port n. dim Length as INTEGER dim Ch as STRING * 1 dim bCh as BYTE dim I as INTEGER Length = Len(Tx) For I = 1 To Length Ch = Mid(Tx, I, 1) bCh = Asc(Ch) CALL PutByte_3(bCh) NEXT END sub '------------------------------------------------------------------------------- public sub PutStr_4( _ ByRef Tx as STRING) dim Length as INTEGER dim Ch as STRING * 1 dim bCh as BYTE dim I as INTEGER Length = Len(Tx) For I = 1 To Length Ch = Mid(Tx, I, 1) bCh = Asc(Ch) CALL PutByte_4(bCh) NEXT END sub '------------------------------------------------------------------------------- public sub PutStr_5( _ ByRef Tx as STRING) dim Length as INTEGER dim Ch as STRING * 1 dim bCh as BYTE dim I as INTEGER Length = Len(Tx) For I = 1 To Length Ch = Mid(Tx, I, 1) bCh = Asc(Ch) CALL PutByte_5(bCh) NEXT END sub '------------------------------------------------------------------------------- public sub PutStr_6( _ ByRef Tx as STRING) dim Length as INTEGER dim Ch as STRING * 1 dim bCh as BYTE dim I as INTEGER Length = Len(Tx) For I = 1 To Length Ch = Mid(Tx, I, 1) bCh = Asc(Ch) CALL PutByte_6(bCh) NEXT END sub '=============================================================================== public sub PutB_3( _ ByVal Value as BYTE) ' Outputs a BYTE type to serial port n. dim L as LONG L = CLng(Value) CALL PutL_3(L) END sub '------------------------------------------------------------------------------- public sub PutB_4( _ ByVal Value as BYTE) dim L as LONG L = CLng(Value) CALL PutL_4(L) END sub '------------------------------------------------------------------------------- public sub PutB_5( _ ByVal Value as BYTE) ' Outputs a BYTE type to serial port n. dim L as LONG L = CLng(Value) CALL PutL_5(L) END sub '------------------------------------------------------------------------------- public sub PutB_6( _ ByVal Value as BYTE) dim L as LONG L = CLng(Value) CALL PutL_6(L) END sub '=============================================================================== public sub PutI_3( _ ByVal Value as INTEGER) ' Outputs an INTEGER type to serial port n. dim L as LONG L = CLng(Value) CALL PutL_3(L) END sub '------------------------------------------------------------------------------- public sub PutI_4( _ ByVal Value as INTEGER) dim L as LONG L = CLng(Value) CALL PutL_4(L) END sub '------------------------------------------------------------------------------- public sub PutI_5( _ ByVal Value as INTEGER) ' Outputs an INTEGER type to serial port n. dim L as LONG L = CLng(Value) CALL PutL_5(L) END sub '------------------------------------------------------------------------------- public sub PutI_6( _ ByVal Value as INTEGER) dim L as LONG L = CLng(Value) CALL PutL_6(L) END sub '=============================================================================== public sub PutUI_3( _ ByVal Value as UNSIGNEDINTEGER) ' Outputs an UNSIGNEDINTEGER type to serial port n. dim L as LONG dim V as NEW UNSIGNEDINTEGER V = Value ' Clear L. L = 0 ' Copy Value into the lower two bytes of L. CALL BlockMove(2, MemAddress(V), MemAddress(L)) CALL PutL_3(L) END sub '------------------------------------------------------------------------------- public sub PutUI_4( _ ByVal Value as UNSIGNEDINTEGER) dim L as LONG dim V as NEW UNSIGNEDINTEGER V = Value ' Clear L. L = 0 ' Copy Value into the lower two bytes of L. CALL BlockMove(2, MemAddress(V), MemAddress(L)) CALL PutL_4(L) END sub '------------------------------------------------------------------------------- public sub PutUI_5( _ ByVal Value as UNSIGNEDINTEGER) ' Outputs an UNSIGNEDINTEGER type to serial port n. dim L as LONG dim V as NEW UNSIGNEDINTEGER V = Value ' Clear L. L = 0 ' Copy Value into the lower two bytes of L. CALL BlockMove(2, MemAddress(V), MemAddress(L)) CALL PutL_5(L) END sub '------------------------------------------------------------------------------- public sub PutUI_6( _ ByVal Value as UNSIGNEDINTEGER) dim L as LONG dim V as NEW UNSIGNEDINTEGER V = Value ' Clear L. L = 0 ' Copy Value into the lower two bytes of L. CALL BlockMove(2, MemAddress(V), MemAddress(L)) CALL PutL_6(L) END sub '=============================================================================== public sub PutUL_3( _ ByVal Value as UNSIGNEDLONG) ' Outputs an UNSIGNEDLONG type to serial port n. dim UL as NEW UNSIGNEDLONG dim L as LONG dim Digit as NEW UNSIGNEDLONG dim I as INTEGER dim Temp as NEW UNSIGNEDLONG ' IF the top bit is clear, the number is ready to go. IF ((Value AND &H80000000) = 0) THEN CALL PutL_3(CLng(Value)) EXIT sub END IF ' Divide by 10 is done by a right shift followed by a divide by 5. ' First clear top bit so we can do a signed divide. UL = Value UL = UL AND &H7FFFFFFF ' Shift to the right 1 bit. L = CLng(UL) L = L \ 2 ' Put the top bit back, except shifted to the right 1 bit. UL = CuLng(L) UL = UL OR &H40000000 ' The number now fits in a signed long. L = CLng(UL) ' Divide by 5. L = L \ 5 CALL PutL_3(L) ' Multiply by 10. Since multiply doesn't work yet for UNSIGNEDLONG, we ' have to do the equivalent addition. Temp = CuLng(L) UL = 0 For I = 1 To 10 UL = UL + Temp NEXT ' Find the rightmost digit. Digit = Value - UL CALL PutL_3(CLng(Digit)) END sub '------------------------------------------------------------------------------- public sub PutUL_4( _ ByVal Value as UNSIGNEDLONG) dim UL as NEW UNSIGNEDLONG dim L as LONG dim Digit as NEW UNSIGNEDLONG dim I as INTEGER dim Temp as NEW UNSIGNEDLONG ' If the top bit is clear, the number is ready to go. IF ((Value AND &H80000000) = 0) THEN CALL PutL_4(CLng(Value)) EXIT sub END IF ' Divide by 10 is done by a right shift followed by a divide by 5. ' First clear top bit so we can do a signed divide. UL = Value UL = UL AND &H7FFFFFFF ' Shift to the right 1 bit. L = CLng(UL) L = L \ 2 ' Put the top bit back, except shifted to the right 1 bit. UL = CuLng(L) UL = UL OR &H40000000 ' The number now fits in a signed LONG. L = CLng(UL) ' Divide by 5. L = L \ 5 CALL PutL_4(L) ' Multiply by 10. Since multiply doesn't work yet for UNSIGNEDLONG, we ' have to do the equivalent addition. Temp = CuLng(L) UL = 0 For I = 1 To 10 UL = UL + Temp NEXT ' Find the rightmost digit. Digit = Value - UL CALL PutL_4(CLng(Digit)) END sub '------------------------------------------------------------------------------- public sub PutUL_5( _ ByVal Value as UNSIGNEDLONG) dim UL as NEW UNSIGNEDLONG dim L as LONG dim Digit as NEW UNSIGNEDLONG dim I as INTEGER dim Temp as NEW UNSIGNEDLONG ' If the top bit is clear, the number is ready to go. IF ((Value AND &H80000000) = 0) THEN CALL PutL_5(CLng(Value)) EXIT sub END IF ' Divide by 10 is done by a right shift followed by a divide by 5. ' First clear top bit so we can do a signed divide. UL = Value UL = UL AND &H7FFFFFFF ' Shift to the right 1 bit. L = CLng(UL) L = L \ 2 ' Put the top bit back, except shifted to the right 1 bit. UL = CuLng(L) UL = UL OR &H40000000 ' The number now fits in a signed LONG. L = CLng(UL) ' Divide by 5. L = L \ 5 CALL PutL_5(L) ' Multiply by 10. Since multiply doesn't work yet for UNSIGNEDLONG, we ' have to do the equivalent addition. Temp = CuLng(L) UL = 0 For I = 1 To 10 UL = UL + Temp NEXT ' Find the rightmost digit. Digit = Value - UL CALL PutL_5(CLng(Digit)) END sub '------------------------------------------------------------------------------- public sub PutUL_6( _ ByVal Value as UNSIGNEDLONG) dim UL as NEW UNSIGNEDLONG dim L as LONG dim Digit as NEW UNSIGNEDLONG dim I as INTEGER dim Temp as NEW UNSIGNEDLONG ' If the top bit is clear, the number is ready to go. IF ((Value AND &H80000000) = 0) THEN CALL PutL_6(CLng(Value)) EXIT sub END IF ' Divide by 10 is done by a right shift followed by a divide by 5. ' First clear top bit so we can do a signed divide. UL = Value UL = UL AND &H7FFFFFFF ' Shift to the right 1 bit. L = CLng(UL) L = L \ 2 ' Put the top bit back, except shifted to the right 1 bit. UL = CuLng(L) UL = UL OR &H40000000 ' The number now fits in a signed LONG. L = CLng(UL) ' Divide by 5. L = L \ 5 CALL PutL_6(L) ' Multiply by 10. Since multiply doesn't work yet for UNSIGNEDLONG, we ' have to do the equivalent addition. Temp = CuLng(L) UL = 0 For I = 1 To 10 UL = UL + Temp NEXT ' Find the rightmost digit. Digit = Value - UL CALL PutL_6(CLng(Digit)) END sub '=============================================================================== public sub PutL_3( _ ByVal Operand as LONG) ' Outputs a LONG type to serial port n. const NegativeLimit as LONG = -2147483648 const Base as LONG = 10 ' Reserve space for "2147483648" dim Digit(1 To 10) as BYTE dim Tmp as LONG dim NDigits as INTEGER dim I as INTEGER ' Negative limit must be handled as a special case. IF (Operand = NegativeLimit) THEN Digit(10) = 2 + 48 Digit(9) = 1 + 48 Digit(8) = 4 + 48 Digit(7) = 7 + 48 Digit(6) = 4 + 48 Digit(5) = 8 + 48 Digit(4) = 3 + 48 Digit(3) = 6 + 48 Digit(2) = 4 + 48 Digit(1) = 8 + 48 NDigits = 10 ELSE NDigits = 0 Tmp = Abs(Operand) DO NDigits = NDigits + 1 Digit(NDigits) = CByte(Tmp mod Base) + 48 Tmp = Tmp \ Base IF Tmp = 0 THEN EXIT DO END IF LOOP END IF IF (Operand < 0) THEN CALL PutByte_3(45) ' "-" END IF ' Digits are stored in reverse order of display. For I = NDigits To 1 Step -1 CALL PutByte_3(Digit(I)) NEXT END sub '------------------------------------------------------------------------------- public sub PutL_4( _ ByVal Operand as LONG) const NegativeLimit as LONG = -2147483648 const Base as LONG = 10 ' Reserve space for "2147483648" dim Digit(1 To 10) as BYTE dim Tmp as LONG dim NDigits as INTEGER dim I as INTEGER ' Negative limit must be handled as a special case. IF (Operand = NegativeLimit) THEN Digit(10) = 2 + 48 Digit(9) = 1 + 48 Digit(8) = 4 + 48 Digit(7) = 7 + 48 Digit(6) = 4 + 48 Digit(5) = 8 + 48 Digit(4) = 3 + 48 Digit(3) = 6 + 48 Digit(2) = 4 + 48 Digit(1) = 8 + 48 NDigits = 10 ELSE NDigits = 0 Tmp = Abs(Operand) DO NDigits = NDigits + 1 Digit(NDigits) = CByte(Tmp mod Base) + 48 Tmp = Tmp \ Base IF Tmp = 0 THEN EXIT DO END IF LOOP END IF IF (Operand < 0) THEN CALL PutByte_4(45) ' "-" END IF ' Digits are stored in reverse order of display. For I = NDigits To 1 Step -1 CALL PutByte_4(Digit(I)) NEXT END sub '------------------------------------------------------------------------------- public sub PutL_5( _ ByVal Operand as LONG) const NegativeLimit as LONG = -2147483648 const Base as LONG = 10 ' Reserve space for "2147483648" dim Digit(1 To 10) as BYTE dim Tmp as LONG dim NDigits as INTEGER dim I as INTEGER ' Negative limit must be handled as a special case. IF (Operand = NegativeLimit) THEN Digit(10) = 2 + 48 Digit(9) = 1 + 48 Digit(8) = 4 + 48 Digit(7) = 7 + 48 Digit(6) = 4 + 48 Digit(5) = 8 + 48 Digit(4) = 3 + 48 Digit(3) = 6 + 48 Digit(2) = 4 + 48 Digit(1) = 8 + 48 NDigits = 10 ELSE NDigits = 0 Tmp = Abs(Operand) DO NDigits = NDigits + 1 Digit(NDigits) = CByte(Tmp mod Base) + 48 Tmp = Tmp \ Base IF Tmp = 0 THEN EXIT DO END IF LOOP END IF IF (Operand < 0) THEN CALL PutByte_5(45) ' "-" END IF ' Digits are stored in reverse order of display. For I = NDigits To 1 Step -1 CALL PutByte_5(Digit(I)) NEXT END sub '------------------------------------------------------------------------------- public sub PutL_6( _ ByVal Operand as LONG) const NegativeLimit as LONG = -2147483648 const Base as LONG = 10 ' Reserve space for "2147483648" dim Digit(1 To 10) as BYTE dim Tmp as LONG dim NDigits as INTEGER dim I as INTEGER ' Negative limit must be handled as a special case. IF (Operand = NegativeLimit) THEN Digit(10) = 2 + 48 Digit(9) = 1 + 48 Digit(8) = 4 + 48 Digit(7) = 7 + 48 Digit(6) = 4 + 48 Digit(5) = 8 + 48 Digit(4) = 3 + 48 Digit(3) = 6 + 48 Digit(2) = 4 + 48 Digit(1) = 8 + 48 NDigits = 10 ELSE NDigits = 0 Tmp = Abs(Operand) DO NDigits = NDigits + 1 Digit(NDigits) = CByte(Tmp mod Base) + 48 Tmp = Tmp \ Base IF Tmp = 0 THEN EXIT DO END IF LOOP END IF IF (Operand < 0) THEN CALL PutByte_6(45) ' "-" END IF ' Digits are stored in reverse order of display. For I = NDigits To 1 Step -1 CALL PutByte_6(Digit(I)) NEXT END sub '=============================================================================== public sub PutSci_3( _ ByVal Value as SINGLE) ' Outputs floating point number in scientific notation format. The output ' is to serial port n. dim Mantissa as SINGLE dim Exponent as INTEGER dim LMant as LONG dim D as INTEGER CALL SplitFloat(Value, Mantissa, Exponent) ' Sign. IF (Mantissa < 0!) THEN CALL PutByte_3(45) ' "-" END IF ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF ' First digit of mantissa. D = CInt(LMant \ 1000000) CALL PutByte_3(CByte(D + 48)) ' Decimal point. CALL PutByte_3(46) ' "." ' Remaining digits of mantissa. LMant = LMant mod 1000000 CALL PutL_3(LMant) ' Exponent. CALL PutByte_3(69) ' "E" IF (Exponent < 0) THEN CALL PutByte_3(45) ' "-" ELSE CALL PutByte_3(43) ' "+" END IF CALL PutI_3(Abs(Exponent)) END sub '------------------------------------------------------------------------------- public sub PutSci_4( _ ByVal Value as SINGLE) dim Mantissa as SINGLE dim Exponent as INTEGER dim LMant as LONG dim D as INTEGER CALL SplitFloat(Value, Mantissa, Exponent) ' Sign. IF (Mantissa < 0!) THEN CALL PutByte_4(45) ' "-" END IF ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF ' First digit of mantissa. D = CInt(LMant \ 1000000) CALL PutByte_4(CByte(D + 48)) ' Decimal point. CALL PutByte_4(46) ' "." ' Remaining digits of mantissa. LMant = LMant mod 1000000 CALL PutL_4(LMant) ' Exponent. CALL PutByte_4(69) ' "E" IF (Exponent < 0) THEN CALL PutByte_4(45) ' "-" ELSE CALL PutByte_4(43) ' "+" END IF CALL PutI_4(Abs(Exponent)) END sub '------------------------------------------------------------------------------- public sub PutSci_5( _ ByVal Value as SINGLE) dim Mantissa as SINGLE dim Exponent as INTEGER dim LMant as LONG dim D as INTEGER CALL SplitFloat(Value, Mantissa, Exponent) ' Sign. IF (Mantissa < 0!) THEN CALL PutByte_5(45) ' "-" END IF ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF ' First digit of mantissa. D = CInt(LMant \ 1000000) CALL PutByte_5(CByte(D + 48)) ' Decimal point. CALL PutByte_5(46) ' "." ' Remaining digits of mantissa. LMant = LMant mod 1000000 CALL PutL_5(LMant) ' Exponent. CALL PutByte_5(69) ' "E" IF (Exponent < 0) THEN CALL PutByte_5(45) ' "-" ELSE CALL PutByte_5(43) ' "+" END IF CALL PutI_5(Abs(Exponent)) END sub '------------------------------------------------------------------------------- public sub PutSci_6( _ ByVal Value as SINGLE) dim Mantissa as SINGLE dim Exponent as INTEGER dim LMant as LONG dim D as INTEGER CALL SplitFloat(Value, Mantissa, Exponent) ' Sign. IF (Mantissa < 0!) THEN CALL PutByte_6(45) ' "-" END IF ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF ' First digit of mantissa. D = CInt(LMant \ 1000000) CALL PutByte_6(CByte(D + 48)) ' Decimal point. CALL PutByte_6(46) ' "." ' Remaining digits of mantissa. LMant = LMant mod 1000000 CALL PutL_6(LMant) ' Exponent. CALL PutByte_6(69) ' "E" IF (Exponent < 0) THEN CALL PutByte_6(45) ' "-" ELSE CALL PutByte_6(43) ' "+" END IF CALL PutI_6(Abs(Exponent)) END sub '=============================================================================== public sub PutS_3( _ ByVal Value as SINGLE) ' Outputs a floating point number to serial port n. If the number can be ' displayed without using scientific notation, it is. Otherwise scientific ' notation is used. dim X as SINGLE dim DecimalPlace as INTEGER dim Mantissa as SINGLE dim Exponent as INTEGER dim DigitPosition as INTEGER dim Factor as LONG dim D as INTEGER dim LMant as LONG dim DecimalHasDisplayed as BOOLEAN ' Special case for zero. IF (Value = 0!) THEN CALL PutByte_3(48) ' "0" CALL PutByte_3(46) ' "." CALL PutByte_3(48) ' "0" EXIT sub END IF X = Abs(Value) ' Use scientific notation for values too big or too small. IF (X < 0.1) OR (X > 999999.9) THEN CALL PutSci_3(Value) EXIT sub END IF ' What follows is non-exponent displays for 0.1000000 < Value < 999999.9 ' Sign. IF (Value < 0!) THEN CALL PutByte_3(45) ' "-" END IF IF (X < 1!) THEN CALL PutByte_3(48) ' "0" CALL PutByte_3(46) ' "." DecimalPlace = 0 ' Convert number to a 7-digit INTEGER. LMant = FixL((X * 10000000#) + 0.5) ELSE CALL SplitFloat(X, Mantissa, Exponent) DecimalPlace = Exponent + 2 ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF END IF DecimalHasDisplayed = False Factor = 1000000 For DigitPosition = 1 To 7 IF (DigitPosition = DecimalPlace) THEN CALL PutByte_3(46) ' "." DecimalHasDisplayed = True END IF D = CInt(LMant \ Factor) CALL PutByte_3(CByte(D + 48)) LMant = LMant mod Factor ' Stop trailing zeros, except for one immediately following the ' decimal place. IF (LMant = 0) THEN IF (DecimalHasDisplayed) THEN EXIT sub END IF END IF Factor = Factor \ 10 NEXT END sub '------------------------------------------------------------------------------- public sub PutS_4( _ ByVal Value as SINGLE) dim X as SINGLE dim DecimalPlace as INTEGER dim Mantissa as SINGLE dim Exponent as INTEGER dim DigitPosition as INTEGER dim Factor as LONG dim D as INTEGER dim LMant as LONG dim DecimalHasDisplayed as BOOLEAN ' Special case for zero. IF (Value = 0!) THEN CALL PutByte_4(48) ' "0" CALL PutByte_4(46) ' "." CALL PutByte_4(48) ' "0" EXIT sub END IF X = Abs(Value) ' Use scientific notation for values too big or too small. IF (X < 0.1) OR (X > 999999.9) THEN CALL PutSci_4(Value) EXIT sub END IF ' What follows is non-exponent displays for 0.1000000 < Value < 999999.9 ' Sign. IF (Value < 0!) THEN CALL PutByte_4(45) ' "-" END IF IF (X < 1!) THEN CALL PutByte_4(48) ' "0" CALL PutByte_4(46) ' "." DecimalPlace = 0 ' Convert number to a 7-digit INTEGER. LMant = FixL((X * 10000000#) + 0.5) ELSE CALL SplitFloat(X, Mantissa, Exponent) DecimalPlace = Exponent + 2 ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF END IF DecimalHasDisplayed = False Factor = 1000000 For DigitPosition = 1 To 7 IF (DigitPosition = DecimalPlace) THEN CALL PutByte_4(46) ' "." DecimalHasDisplayed = True END IF D = CInt(LMant \ Factor) CALL PutByte_4(CByte(D + 48)) LMant = LMant mod Factor ' Stop trailing zeros, except for one immediately following the ' decimal place. IF (LMant = 0) THEN IF (DecimalHasDisplayed) THEN EXIT sub END IF END IF Factor = Factor \ 10 NEXT END sub '------------------------------------------------------------------------------- public sub PutS_5( _ ByVal Value as SINGLE) dim X as SINGLE dim DecimalPlace as INTEGER dim Mantissa as SINGLE dim Exponent as INTEGER dim DigitPosition as INTEGER dim Factor as LONG dim D as INTEGER dim LMant as LONG dim DecimalHasDisplayed as BOOLEAN ' Special case for zero. IF (Value = 0!) THEN CALL PutByte_5(48) ' "0" CALL PutByte_5(46) ' "." CALL PutByte_5(48) ' "0" EXIT sub END IF X = Abs(Value) ' Use scientific notation for values too big or too small. IF (X < 0.1) OR (X > 999999.9) THEN CALL PutSci_5(Value) EXIT sub END IF ' What follows is non-exponent displays for 0.1000000 < Value < 999999.9 ' Sign. IF (Value < 0!) THEN CALL PutByte_5(45) ' "-" END IF IF (X < 1!) THEN CALL PutByte_5(48) ' "0" CALL PutByte_5(46) ' "." DecimalPlace = 0 ' Convert number to a 7-digit INTEGER. LMant = FixL((X * 10000000#) + 0.5) ELSE CALL SplitFloat(X, Mantissa, Exponent) DecimalPlace = Exponent + 2 ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF END IF DecimalHasDisplayed = False Factor = 1000000 For DigitPosition = 1 To 7 IF (DigitPosition = DecimalPlace) THEN CALL PutByte_5(46) ' "." DecimalHasDisplayed = True END IF D = CInt(LMant \ Factor) CALL PutByte_5(CByte(D + 48)) LMant = LMant mod Factor ' Stop trailing zeros, except for one immediately following the ' decimal place. IF (LMant = 0) THEN IF (DecimalHasDisplayed) THEN EXIT sub END IF END IF Factor = Factor \ 10 NEXT END sub '------------------------------------------------------------------------------- public sub PutS_6( _ ByVal Value as SINGLE) dim X as SINGLE dim DecimalPlace as INTEGER dim Mantissa as SINGLE dim Exponent as INTEGER dim DigitPosition as INTEGER dim Factor as LONG dim D as INTEGER dim LMant as LONG dim DecimalHasDisplayed as BOOLEAN ' Special case for zero. IF (Value = 0!) THEN CALL PutByte_6(48) ' "0" CALL PutByte_6(46) ' "." CALL PutByte_6(48) ' "0" EXIT sub END IF X = Abs(Value) ' Use scientific notation for values too big or too small. IF (X < 0.1) OR (X > 999999.9) THEN CALL PutSci_6(Value) EXIT sub END IF ' What follows is non-exponent displays for 0.1000000 < Value < 999999.9 ' Sign. IF (Value < 0!) THEN CALL PutByte_6(45) ' "-" END IF IF (X < 1!) THEN CALL PutByte_6(48) ' "0" CALL PutByte_6(46) ' "." DecimalPlace = 0 ' Convert number to a 7-digit INTEGER. LMant = FixL((X * 10000000#) + 0.5) ELSE CALL SplitFloat(X, Mantissa, Exponent) DecimalPlace = Exponent + 2 ' Convert mantissa to a 7-digit INTEGER. LMant = FixL((Abs(Mantissa) * 1000000!) + 0.5) ' Correct for roundoff error. Mantissa can't be > 9.999999 IF (LMant > 9999999) THEN LMant = 9999999 END IF END IF DecimalHasDisplayed = False Factor = 1000000 For DigitPosition = 1 To 7 IF (DigitPosition = DecimalPlace) THEN CALL PutByte_6(46) ' "." DecimalHasDisplayed = True END IF D = CInt(LMant \ Factor) CALL PutByte_6(CByte(D + 48)) LMant = LMant mod Factor ' Stop trailing zeros, except for one immediately following the ' decimal place. IF (LMant = 0) THEN IF (DecimalHasDisplayed) THEN EXIT sub END IF END IF Factor = Factor \ 10 NEXT END sub '=============================================================================== private sub SplitFloat( _ ByVal Value as SINGLE, _ ByRef Mantissa as SINGLE, _ ByRef Exponent as INTEGER) ' Splits a floating point number into mantissa and exponent. The mantissa ' range is such that 1.0 <= Abs(Mantissa) < 10.0 for nonzero numbers, and ' zero otherwise. dim X as SINGLE dim Factor as SINGLE ' Zero is a special case. IF (Value = 0!) THEN Mantissa = 0! Exponent = 0 EXIT sub END IF X = Abs(Value) Exponent = 0 Factor = 1! ' Multiply or divide by ten to transform number to value between 1 and 10. DO IF (X >= 10!) THEN X = X / 10! Factor = Factor * 10! Exponent = Exponent + 1 ELSEIF (X < 1!) THEN X = X * 10! Factor = Factor * 10! Exponent = Exponent - 1 ELSE ' IF we reach this point, then 1.0 <= mantissa < 10.0. EXIT DO END IF LOOP ' Determine mantissa. IF (Exponent = 0) THEN Mantissa = Value ELSEIF (Exponent > 0) THEN Mantissa = Value / Factor ELSE Mantissa = Value * Factor END IF END sub '=============================================================================== ' Application Specific Subroutines - "Super Comm Z" ZX-40 (Diagnostics) '=============================================================================== 'Serial Comport Communication Turnaround Tests for comports 3-6. Public Sub Com3_TurnaroundTest(Byref OK as boolean) 'Jumper pins 2-3 (Tx & Rx) on J? RS232 connector for test 'add baudrate cycling to routines - needs testing Dim Success as Boolean static Tx3 as byte static Rx3 as byte static Baud_rate_selector as byte Tx3 = Tx3 + 1 'inc from 0-255 Call PutByte_3(Tx3) call delay(0.01) '10 ms works 'Debug.Print "Tx3 value is ";CStr(Tx3) CALL GetByte_3(Rx3,Success) 'CALL Clearqueue(InBuf_3) 'CALL delay(0.50) 'Debug.Print "Rx3 value is ";CStr(Rx3) 'CALL delay(0.50) if (Rx3 = Tx3) then 'Debug.Print "Com3 Turnaround Test is OK! " 'Call POR_LEDS() OK = true else 'Debug.Print "Com3 Turnaround Test is NOT OK! " OK = false end if Rx3 = 0 'clear Rx3 variable If Tx3 = 0 Then Baud_rate_selector = Baud_rate_selector + 1 'debug.print "Baud Rate Selector = "; Cstr(Baud_rate_selector) End If Select case Baud_rate_selector case 0 '300 Call ReOpenSerialPort_3(300) 'debug.print "300 baud" case 1 '600 Call ReOpenSerialPort_3(600) 'debug.print "600 baud" case 2 '1200 Call ReOpenSerialPort_3(1200) 'debug.print "1200 baud" case 3 '4800 Call ReOpenSerialPort_3(4800) 'debug.print "4800 baud" case 4 '9600 - max - due to 2 or more software uarts Call ReOpenSerialPort_3(9600) 'debug.print "9600 baud" Case Else Call ReOpenSerialPort_3(9600) 'debug.print "300 baud - Default" End Select End Sub '-------------------------------------------------------------------------------------- Public Sub Com4_TurnaroundTest(Byref OK as boolean) 'Jumper pins 2-3 (Tx & Rx) on J? RS232 connector for test 'add baudrate cycling to routines - needs testing Dim Success as Boolean static Tx4 as byte static Rx4 as byte static Baud_rate_selector as byte Tx4 = Tx4 + 1 'inc from 0-255 Call PutByte_4(Tx4) call delay(0.01) '10 ms works 'Debug.Print "Tx4 value is ";CStr(Tx4) CALL GetByte_4(Rx4,Success) 'CALL Clearqueue(InBuf_4) 'CALL delay(0.50) 'Debug.Print "Rx4 value is ";CStr(Rx4) 'CALL delay(0.50) if (Rx4 = Tx4) then 'Debug.Print "Com4 Turnaround Test is OK! " 'Call POR_LEDS() OK = true else 'Debug.Print "Com4 Turnaround Test is NOT OK! " OK = false end if Rx4 = 0 'clear Rx4 variable If Tx4 = 0 Then Baud_rate_selector = Baud_rate_selector + 1 'debug.print "Baud Rate Selector = "; Cstr(Baud_rate_selector) End If Select case Baud_rate_selector case 0 '300 Call ReOpenSerialPort_3(300) 'debug.print "300 baud" case 1 '600 Call ReOpenSerialPort_3(600) 'debug.print "600 baud" case 2 '1200 Call ReOpenSerialPort_3(1200) 'debug.print "1200 baud" case 3 '4800 Call ReOpenSerialPort_3(4800) 'debug.print "4800 baud" case 4 '9600 - max - due to 2 or more software uarts Call ReOpenSerialPort_3(9600) 'debug.print "9600 baud" Case Else Call ReOpenSerialPort_3(9600) 'debug.print "300 baud - Default" End Select End Sub '------------------------------------------------------------------------------------------- Public Sub Com5_TurnaroundTest(Byref OK as boolean) 'Jumper pins 2-3 (Tx & Rx) on J? RS232 connector for test 'add baudrate cycling to routines - needs testing Dim Success as Boolean static Tx5 as byte static Rx5 as byte static Baud_rate_selector as byte Tx5 = Tx5 + 1 'inc from 0-255 Call PutByte_5(Tx5) call delay(0.01) '10 ms works 'Debug.Print "Tx5 value is ";CStr(Tx5) CALL GetByte_5(Rx5,Success) 'CALL Clearqueue(InBuf_5) 'CALL delay(0.50) 'Debug.Print "Rx5 value is ";CStr(Rx5) 'CALL delay(0.50) if (Rx5 = Tx5) then 'Debug.Print "Com5 Turnaround Test is OK! " 'Call POR_LEDS() OK = true else 'Debug.Print "Com5 Turnaround Test is NOT OK! " OK = false end if Rx5 = 0 'clear Rx5 variable If Tx5 = 0 Then Baud_rate_selector = Baud_rate_selector + 1 'debug.print "Baud Rate Selector = "; Cstr(Baud_rate_selector) End If Select case Baud_rate_selector case 0 '300 Call ReOpenSerialPort_3(300) 'debug.print "300 baud" case 1 '600 Call ReOpenSerialPort_3(600) 'debug.print "600 baud" case 2 '1200 Call ReOpenSerialPort_3(1200) 'debug.print "1200 baud" case 3 '4800 Call ReOpenSerialPort_3(4800) 'debug.print "4800 baud" case 4 '9600 - max - due to 2 or more software uarts Call ReOpenSerialPort_3(9600) 'debug.print "9600 baud" Case Else Call ReOpenSerialPort_3(9600) 'debug.print "300 baud - Default" End Select End Sub '------------------------------------------------------------------------------------------- Public Sub Com6_TurnaroundTest(Byref OK as boolean) 'Jumper pins 2-3 (Tx & Rx) on J? RS232 connector for test 'add baudrate cycling to routines - needs testing Dim Success as Boolean static Tx6 as byte static Rx6 as byte static Baud_rate_selector as byte Tx6 = Tx6 + 1 'inc from 0-255 Call PutByte_6(Tx6) call delay(0.01) '10 ms works 'Debug.Print "Tx6 value is ";CStr(Tx6) CALL GetByte_6(Rx6,Success) 'CALL Clearqueue(InBuf_6) 'CALL delay(0.50) 'Debug.Print "Rx6 value is ";CStr(Rx5) 'CALL delay(0.50) if (Rx6 = Tx6) then 'Debug.Print "Com6 Turnaround Test is OK! " 'Call POR_LEDS() OK = true else 'Debug.Print "Com6 Turnaround Test is NOT OK! " OK = false end if Rx6 = 0 'clear Rx5 variable If Tx6 = 0 Then Baud_rate_selector = Baud_rate_selector + 1 'debug.print "Baud Rate Selector = "; Cstr(Baud_rate_selector) End If Select case Baud_rate_selector case 0 '300 Call ReOpenSerialPort_3(300) 'debug.print "300 baud" case 1 '600 Call ReOpenSerialPort_3(600) 'debug.print "600 baud" case 2 '1200 Call ReOpenSerialPort_3(1200) 'debug.print "1200 baud" case 3 '4800 Call ReOpenSerialPort_3(4800) 'debug.print "4800 baud" case 4 '9600 - max - due to 2 or more software uarts Call ReOpenSerialPort_3(9600) 'debug.print "9600 baud" Case Else Call ReOpenSerialPort_3(9600) 'debug.print "300 baud - Default" End Select End Sub '====================================================================================== 'Application Specific Communications Subroutines e.g. "Super Comm Z" Target ZX-40 Only '====================================================================================== 'Cycle all on board LEDs on power up. Public Sub POR_LEDS() 'Cycle all "Super Comm Z" Leds on power-up or reset Const LED_Dly as single = 0.05 ' 50 ms Call PutPin(1, zxOutputHigh) 'Turn on GRN1 Rx CALL delay(LED_Dly) Call PutPin(1, zxOutputLow) 'Turn off GRN1 Rx Call PutPin(24, zxOutputHigh) 'Turn on RED1 Tx CALL delay(LED_Dly) Call PutPin(24, zxOutputLow) 'Turn off RED1 Tx Call PutPin(2, zxOutputHigh) 'Turn on GRN2 Rx CALL delay(LED_Dly) Call PutPin(2, zxOutputLow) 'Turn off GRN2 Rx Call PutPin(25, zxOutputHigh) 'Turn on RED2 Tx CALL delay(LED_Dly) Call PutPin(25, zxOutputLow) 'Turn off RED2 Tx Call PutPin(4, zxOutputHigh) 'Turn on GRN3 Rx CALL delay(LED_Dly) Call PutPin(4, zxOutputLow) 'Turn off GRN3 Rx Call PutPin(26, zxOutputHigh) 'Turn on RED3 Tx CALL delay(LED_Dly) Call PutPin(26, zxOutputLow) 'Turn off RED3 Tx Call PutPin(28, zxOutputHigh) 'Turn on GRN4 Rx CALL delay(LED_Dly) Call PutPin(28, zxOutputLow) 'Turn off GRN4 Rx Call PutPin(27, zxOutputHigh) 'Turn on RED4 Tx CALL delay(LED_Dly) Call PutPin(27, zxOutputLow) 'Turn off RED4 Tx Call PutPin(29, zxOutputHigh) 'Turn on AMB1 Zrun CALL delay(LED_Dly) Call PutPin(29, zxOutputLow) 'Turn off AMB1 Zrun End Sub '================================================================================ Public Sub Comm_Status_LEDs() Dim status as boolean status = StatusQueue(InBuf_3) if (status)then Call PutPin(1, zxOutputHigh) 'Turn on GRN1 Rx ELSE Call PutPin(1, zxOutputLow) 'Turn off GRN1 Rx End if status = StatusQueue(OutBuf_3) if (status) then Call PutPin(24, zxOutputHigh) 'Turn on RED1 Tx ELSE Call PutPin(24, zxOutputLow) 'Turn off RED1 Tx End if '---------------------------------------------- status = StatusQueue(InBuf_4) if (status) then Call PutPin(2, zxOutputHigh) 'Turn on GRN2 Rx ELSE Call PutPin(2, zxOutputLow) 'Turn off GRN2 Rx End if status = StatusQueue(OutBuf_4) if (status) then Call PutPin(25, zxOutputHigh) 'Turn on RED2 Tx ELSE Call PutPin(25, zxOutputLow) 'Turn off RED2 Tx End if '---------------------------------------------- status = StatusQueue(InBuf_5) if (status) then Call PutPin(4, zxOutputHigh) 'Turn on GRN3 Rx ELSE Call PutPin(4, zxOutputLow) 'Turn off GRN3 Rx End if status = StatusQueue(OutBuf_5) if (status) then Call PutPin(26, zxOutputHigh) 'Turn on RED3 Tx ELSE Call PutPin(26, zxOutputLow) 'Turn off RED3 Tx End if '----------------------------------------------- status = StatusQueue(OutBuf_6) if (status) then Call PutPin(27, zxOutputHigh) 'Turn on RED4 Tx ELSE Call PutPin(27, zxOutputLow) 'Turn off RED4 Tx End if status = StatusQueue(InBuf_6) if (status) then Call PutPin(28, zxOutputHigh) 'Turn on GRN4 Rx ELSE Call PutPin(28, zxOutputLow) 'Turn off GRN4 Rx End if end sub '==============================================================================