Or as a module, create a brown/comm.mod in modules and use this:
Strict
Rem
bbdoc: Serial communication library.
about: Allows serial comunication using the comm port.
End Rem
Module brown.comm
Import brl.retro
ModuleInfo "Version: 0.02"
ModuleInfo "Author: Nigel Brown (http://www.nigelibrown.pwp.blueyonder.co.uk/blitz)"
ModuleInfo "License: Public Domain"
ModuleInfo "Modserver: BRL"
Import BRL.StandardIO
Import BRL.Bank
Import BRL.System
Const GENERIC_READ = $80000000
Const GENERIC_WRITE = $40000000
Const OPEN_EXISTING = 3
Const FILE_ATTRIBUTE_NORMAL = $80
Const INVALID_HANDLE_VALUE = -1
Const FORMAT_MESSAGE_ALLOCATE_BUFFER = 256
Const FORMAT_MESSAGE_IGNORE_INSERTS = 512
Const FORMAT_MESSAGE_FROM_STRING = 1024
Const FORMAT_MESSAGE_FROM_HMODULE = 2048
Const FORMAT_MESSAGE_FROM_SYSTEM = 4096
Const FORMAT_MESSAGE_ARGUMENT_ARRAY = 8192
Extern "win32"
Function GetCommState:Int( handle:Int, DCB:Byte Ptr )
Function SetCommState:Int( handle:Int, DCB:Byte Ptr )
Function BuildCommDCBA:Int( config:Byte Ptr, DCB:Byte Ptr )
Function GetCommTimeouts:Int( handle:Int, Timeouts:Byte Ptr )
Function SetCommTimeouts:Int( handle:Int, Timeouts:Byte Ptr )
Function CreateFileA:Int( filename:Byte Ptr, DesiredAccess:Int, ShareMode:Int, SecurityAttribute:Int, CreationDistribution:Int, FlagsAndAttributes:Int, TemplateFile:Int )
Function CloseHandle:Int( handle:Int )
Function WriteFileA:Int( handle:Int, pBuffer:Byte Ptr, NumberOfBytesToWrite:Int, pNumberOfBytesWritten:Byte Ptr, pOverlapped:Int )="WriteFile@20"
Function ReadFileA:Int( handle:Int, pBuffer:Byte Ptr, NumberOfBytesToRead:Int, pNumberOfBytesRead:Byte Ptr, pOverlapped:Int )="ReadFile@20"
Function GetLastError:Int()
Function FormatMessageA:Int( dwFlags:Int, lpSource:Byte Ptr, dwMessageId:Int, dwLanguageId:Int, lpBuffer:Byte Ptr, nSize:Int, args[] )
End Extern
Type TComm
Field handle:Int
Field R_buffer:TBank
Field W_buffer:TBank
Field count:TBank
Field DCB:TBank
Field TimeOuts:TBank
Rem
bbdoc: Sets the baudrate.
about: [baud=b][parity=p][data=d][stop=s][to={on|off}][xon={on|off}][odsr={on|off}][octs={on|off}][dtr={on|off|hs}][rts={on|off|hs|tg}][idsr={on|off}]
For example, the following string specifies a baud rate of 9600, no parity, 8 data bits, and 1 stop bit:
baud=9600 parity=N data=8 stop=1
returns: If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError()
EndRem
Method Set:Int( config:String )
' Get States
If GetCommState( Self.handle, BankBuf(DCB) ) = 0 Then
Return False
ElseIf PeekInt(DCB, 0) <> 28
Return False
EndIf
' Build DCB
If BuildCommDCBA( config.ToCString(), BankBuf(DCB) ) = 0 Then
Return False
EndIf
' Set States
Return SetCommState( Self.handle, BankBuf(DCB) )
End Method
Rem
bbdoc: Sets the timeouts.
about: for read and write in ms. i.e. Timeout( 10, 10 ) will set 10 ms for each.
EndRem
Method TimeOut:Int( read:Int, write:Int )
' Get timeouts
If GetCommTimeouts( Self.handle, BankBuf(Timeouts) ) = 0 Then
Return False
EndIf
' ReadTotalTimeoutConstant
PokeInt Timeouts, 8, read
' WriteTotalTimeoutConstant
PokeInt Timeouts, 16, write
' Set Timeouts
Return SetCommTimeouts( Self.handle, BankBuf(Timeouts) )
End Method
Rem
bbdoc: Opens a TComm object.
about:
EndRem
Method Open:Int( port:Int )
Local temp:String = "COM" + port
If (port < 0) Or (port > 255) Then Return -1
Self.handle = CreateFileA( temp.ToCString(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0 )
R_buffer:TBank = CreateBank(1024)
W_buffer:TBank = CreateBank(1024)
count:TBank = CreateBank(4)
DCB:TBank = CreateBank(28)
TimeOuts:TBank = CreateBank(40)
Return Self.handle
End Method
Rem
bbdoc: Closes a TComm object.
about:
EndRem
Method Close:Int()
R_buffer:TBank = Null
W_Buffer:TBank = Null
count:TBank = Null
DCB:TBank = Null
TimeOuts:TBank = Null
Return CloseHandle( Self.handle )
End Method
Rem
bbdoc:
about:
EndRem
Method ReadBank:Int( buffer:TBank, size:Int )
If size > BankSize(buffer) Then Return -1
If ReadFileA( Self.handle, BankBuf(buffer), size, BankBuf(count), 0) = 0 Then
Return -1
Else
If PeekByte(count,0) = 0
Return -1
EndIf
Return PeekInt(count,0)
EndIf
End Method
Rem
bbdoc:
about:
EndRem
Method WriteBank:Int( buffer:TBank, size:Int )
If size > BankSize(buffer) Then Return -1
If WriteFileA( Self.handle, BankBuf(buffer), size, BankBuf(count), 0 ) = 0 Then
Return -1
Else
Return PeekInt(count,0)
EndIf
End Method
Rem
bbdoc:
about:
EndRem
Method ReadByte:Int()
If ReadFileA( Self.handle, BankBuf(R_buffer), 1, BankBuf(count), 0) = 0 Then
Return -1
Else
If PeekByte(count,0) =0
Return -1
EndIf
Return PeekByte(R_buffer, 0)
EndIf
End Method
Rem
bbdoc:
about:
EndRem
Method WriteByte:Int( val:Byte )
PokeByte( W_buffer, 0, val )
If WriteFileA( Self.handle, BankBuf(W_buffer), 1, BankBuf(count), 0 ) = 0 Then
Return -1
Else
Return PeekInt(count,0)
EndIf
End Method
Rem
bbdoc:
about:
EndRem
Method ReadShort:Short()
If ReadFileA( Self.handle, BankBuf(R_buffer), 2, BankBuf(count), 0) = 0 Then
Return -1
Else
If PeekByte(count,0) =0
Return -1
EndIf
Return PeekByte(R_buffer,0) Shl 8 + PeekByte(R_buffer,1)
EndIf
End Method
Rem
bbdoc:
about:
EndRem
Method WriteShort:Int( val:Short )
PokeShort( W_buffer, 0, val )
If WriteFileA( Self.handle, BankBuf(W_buffer), 2, BankBuf(count), 0 ) = 0 Then
Return -1
Else
Return PeekInt(count,0)
EndIf
End Method
Rem
bbdoc:
about:
EndRem
Method ReadString:String()
Local c:Int
Local line:String
Repeat
c = ReadByte()
If c = -1
' DebugLog "Serial Timeout"
Return Null
EndIf
Repeat
c = ReadByte()
If c = -1 Then Exit
If c = 10 Or c = 13 Then Exit
line = line + Chr(c)
Forever
' DebugLog "ReadSerialLine = " + line
Return line
Forever
End Method
Rem
bbdoc:
about:
EndRem
Method WriteString:Int( command:String )
If Len(command) > BankSize(W_buffer) Then Return -1
' DebugLog "serial data" + Len(command)
' build buffer from string.
For Local i:Int = 1 To Len(command)
PokeByte(W_buffer,i-1,Asc(Mid(command,i,1)))
' DebugLog "data = " + Asc(Mid(command,i,1))
Next
'
Local dwNumberOfBytesSent:Int = 0
While( dwNumberOfBytesSent < Len(command) )
If WriteFileA( Self.handle, BankBuf(W_buffer) + dwNumberOfBytesSent, 1, BankBuf(count), Null ) <> 0
If PeekInt(count,0) > 0
dwNumberOfBytesSent :+ 1
Else
'
Notify( "serial error 1:" ) + LastError()
Return -1
EndIf
Else
'
Notify( "serial error 2:" ) + LastError()
Return -1
EndIf
Wend
Return dwNumberOfBytesSent
Rem
' Send a string
If WriteFileA( Self.handle, BankBuf(W_buffer), Len(command), BankBuf(count), 0 ) = 0 Then
Return -1
Else
If PeekInt(count,0) <> Len(command)
Notify("A serial error has occured",True)
EndIf
Return PeekInt(count,0)
EndIf
EndRem
End Method
Rem
bbdoc:
about:
EndRem
Method LastError:String()
Local lpMsgBuf:Byte[255]
Local dw:Int = GetLastError()
'
FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, Null, dw, 0, lpMsgBuf, 255, Null )
Return "Error message: " + String.FromCString(lpMsgBuf)
End Method
End Type
[Admin Note: Please use the [codebox] tags instead of [code] when posting large pieces of code.] What are the forum codes?