serial port

BlitzMax Forums/BlitzMax Programming/serial port

can someone help me to learn how to send a signal via COM port from a blitzmax software?
I need to interface a portable computer with another device and need to send a trigger to exactly mark the time of an event (keypress, for instance) in the second computer (equipped with a dedicated slot which can receive digital signals via COM port)

...yes, I never learned assembler

thank you
allos

I'm not really savvy when it comes to what ports are what. I have got this code though which uses the Inpout32 DLL which can be downloaded from somewhere. I was using a 25 pin serial port and that seemed to work.

Global IOP = LoadLibraryA("Inpout32")
Global Out32(Port:Int,Value:Int)=getprocaddress(IOP,"Out32")

Global Lpt1 = $9800

Out32(Lpt1,1)


I used a tutorial someone posted to be able to load the DLL and the function.

The second value in Out32 is a binary value which will trigger the pins. Lpt1 is the port number. I think that should work for everyone.

If you can't find the DLL on the internet I will upload to my website for you.

[edit] I found the DLL: http://www.logix4u.net/inpout32.htm [/edit]

thank you, but I think this code (and related web page) are about parallel port, not serial port
bye
allos

Hi
I'm plannig to move to BlitzMax, but first I need to know if
the communication between blitzmax and ports (both serial and paralell) are posible.
Have you found the way to stablish the link between blitzmax and the serial port??

By the way, if you have a usart in your pc (not via a usb to serial hardware), then you just do a Out to the base port of the usart (usually 0x3F8, see the hardware properties of your comm) that`s all for start a serial communiation. To change the speed and other parameter`s is more complicated. To read to, but if you are interested could talk later

Juan

There is a com module around here somewhere..

wxMAX will supply you with multi platform serial capability, and checkout my webpage for Parallel I/O under the BlitzMAX section look for DLPortIO. p.s. Click the name for link.

Thank's

I already use DLPortIO with Blitz3D and some .decls for kernel32.dll. I have no problem using any ono of them. My quesiton is, how I do a similar thing with BlitzMax. I dont have BlitzMax, and probably move me to thath plataform, but I want to know before if it's posible to handle port's and how.

checkout my webpage for Parallel I/O under the BlitzMAX section look for DLPortIO. p.s. Click the name for link.


That's the one I was thinking of!

@Odriozola Almeida, something like this:

Global	DllHandle=LoadLibraryA("DLPORTIO.dll")

Global	DlPortReadPortUchar:Byte( port:Int )"Win32"=GetProcAddress(DllHandle,"DlPortReadPortUchar")
Global	DLPortReadPortUshort:Short( port:Int )"Win32"=GetProcAddress(DllHandle,"DLPortReadPortUshort")
Global	DLPortReadPortUlong:Int( port:Int )"Win32"=GetProcAddress(DllHandle,"DLPortReadPortUlong")

Global	DlPortReadPortBufferUchar( port:Int, buffer:Byte Ptr, count:Int )"Win32"=GetProcAddress(DllHandle,"DlPortReadPortBufferUchar")
Global	DlPortReadPortBufferUshort( port:Int, buffer:Short Ptr, count:Int )"Win32"=GetProcAddress(DllHandle,"DlPortReadPortBufferUshort")
Global	DlPortReadPortBufferUlong( port:Int, buffer:Int Ptr, count:Int )"Win32"=GetProcAddress(DllHandle,"DlPortReadPortBufferUlong")

Global	DlPortWritePortUchar( port:Int, value:Byte )"Win32"=GetProcAddress(DllHandle,"DlPortWritePortUchar")
Global	DlPortWritePortUshort( port:Int, value:Short )"Win32"=GetProcAddress(DllHandle,"DlPortWritePortUshort")
Global	DlPortWritePortUlong( port:Int, value:Int )"Win32"=GetProcAddress(DllHandle,"DlPortWritePortUlong")

Global	DlPortWritePortBufferUchar( port:Int, buffer:Byte Ptr, count:Int )"Win32"=GetProcAddress(DllHandle,"DlPortWritePortBufferUchar")
Global	DlPortWritePortBufferUshort( port:Int, buffer:Short Ptr, count:Int )"Win32"=GetProcAddress(DllHandle,"DlPortWritePortBufferUshort")
Global	DlPortWritePortBufferUlong( port:Int, buffer:Int Ptr, count:Int )"Win32"=GetProcAddress(DllHandle,"DlPortWritePortBufferUlong")



GUAU!

(in spanish sound like WOW, most like dog's do)

Thank's a lot

I'll have the evaluation blitzmax, so tray and pray (as always)

I supose that this is for all registered dll's??

best regards!

Juan

Rem

	My "Hellow World" in BlitzMax!

		A simple application that sends 1000 count values a second to the base port
	of LPT and read 4 times a second the status port (base+1)
	
	Just for test DLPORTIO.dll, thank´s Nigel Brown for your help!

End Rem

Strict

Graphics 640,480,0


Global	DllHandle=LoadLibraryA("DLPORTIO.dll")
Global	DlPortReadPortUchar:Byte( port:Int )"Win32"=GetProcAddress(DllHandle,"DlPortReadPortUchar")
Global	DlPortWritePortUchar( port:Int, value:Byte )"Win32"=GetProcAddress(DllHandle,"DlPortWritePortUchar")

Global Pasada
Global Vueltas
Global Lectura


Const PuertoDatos   = $378	'base LPT adress in my machine, 8 bits (output)
Const PuertoEstado  = $379	'status port 5 most significant bits used (input)
Const PuertoControl = $37A	'4 bits (thre of them inverted) bit 5 stablish the 
							'direction of data port, by default bit cleared
							'data port is output.

Delay 10

Pasada = 0
Vueltas = 0

While Not KeyHit(KEY_ESCAPE)
	
	DlPortWritePortUchar(PuertoDatos,Pasada)		'write nex value to the port
	Pasada = Pasada + 1
	Delay 1
	'1 ms BitTime in Bit0 of LPT data port = 500 Hz square signal (pin 2 of the DB25 male connector)
	'2 ms BitTime in Bit1 of LPT data port = 250 Hz square signal (pin 3)
	'and so on... in powers of 2
	'128 ms BitTime in Bit7 of LPT data port (pin 9)


	If Pasada=250 Then
		Pasada=0
		Vueltas=Vueltas+1
		'read status pins four times a second
		Lectura = DlPortReadPortUchar(PuertoEstado) ~ $80	'msb is inverted
		Cls
		DrawText "Vueltas: "+Vueltas,20,20
		DrawText "Lectura: "+Right(Bin(Lectura),8),20,40	'show just 8 bits
		DrawText "Lectura: "+Lectura,20,60
		Flip
	End If
Wend

DlPortWritePortUchar(PuertoDatos,0)

End


Just a note: you can use {code}Print "Hey!"{/code} (replace the {} with []) to get code in a codebox.

thank's Plash

(i'm new in this thing's)

some one knows how to translate to blitz max this??

.lib "Kernel32.dll" 

RtlMoveMemory%(Destination*,Source,Length) : "RtlMoveMemory" 
RtlMoveMemory2%(Destination,Source*,Length) : "RtlMoveMemory" 

apiCreateFile%(lpFileName$, dwDesiredAccess, dwShareMode, lpSecurrityAttributes, dwCreationDistribution, dwFlagsAndAttributes, hTemplateFile) : "CreateFileA" 
apiSetupComm%(hFile, dwInQueue, dwOutQueue) : "SetupComm" 
apiGetCommState%(hFile, lpDCB*) : "GetCommState" 
apiSetCommState%(hFile, lpCDB*) : "SetCommState" 
apiSetCommMask%(hFile, dwEvtMask) : "SetCommMask" 
apiCloseHandle%(hObject) : "CloseHandle" 
apiEscapeCommFunction%(hFile, dwFunc) : "EscapeCommFunction" 
apiWriteFile%(hFile, lpBuffer*, nNumberOfBytesToWrite, lpNumberOfBytesWritten*, lpOverlapped) : "WriteFile" 
apiSetCommTimeouts%(hFile, lpCommTimeouts*) : "SetCommTimeouts" 
apiClearCommError%(hFile, lpErrors*, lpStat*) : "ClearCommError" 
apiReadFile%(hFile, lpBuffer*, nNumberOfBytesToRead, lpNumberOfBytesRead*, lpOverlapped) : "ReadFile"


specially those who reference poniters ("*")

Extern "win32"
	Function RtlMoveMemory(Destination:Byte Ptr, Source:Int, Length:Int) = "RtlMoveMemory@12" 
	Function RtlMoveMemory2:Int(Destination:Int, Source:Byte Ptr, Length:Int) = "RtlMoveMemory@12" 
	
	Function apiCreateFile:Int(lpFileName:String, dwDesiredAccess:Int, dwShareMode:Int, lpSecurrityAttributes:Int, dwCreationDistribution:Int, dwFlagsAndAttributes:Int, hTemplateFile:Int) = "CreateFileA@28" 
	Function apiSetupComm:Int(hFile:Int, dwInQueue:Int, dwOutQueue:Int) = "SetupComm@12" 
	Function apiGetCommState:Int(hFile:Int, lpDCB:Byte Ptr) = "GetCommState@8" 
	Function apiSetCommState:Int(hFile:Int, lpCDB:Byte Ptr) = "SetCommState@8" 
	Function apiSetCommMask:Int(hFile:Int, dwEvtMask:Int) = "SetCommMask@8" 
	Function apiCloseHandle:Int(hObject:Int) = "CloseHandle@4" 
	Function apiEscapeCommFunction:Int(hFile:Int, dwFunc:Int) = "EscapeCommFunction@8" 
	Function apiWriteFile:Int(hFile:Int, lpBuffer:Byte Ptr, nNumberOfBytesToWrite:Int, lpNumberOfBytesWritten:Byte Ptr, lpOverlapped:Int) = "WriteFile@20" 
	Function apiSetCommTimeouts:Int(hFile:Int, lpCommTimeouts:Byte Ptr) = "SetCommTimeouts@12" 
	Function apiClearCommError:Int(hFile:Int, lpErrors:Byte Ptr, lpStat:Byte Ptr) = "ClearCommError@12" 
	Function apiReadFile:Int(hFile:Int, lpBuffer:Byte Ptr, nNumberOfBytesToRead:Int, lpNumberOfBytesRead:Byte Ptr, lpOverlapped:Int) = "ReadFile@20"
End Extern

That should do it, though I'm not 100% positive I got the :Byte Ptr thing right.

EDIT: The <func>@<num> part is used because apiReadFile does not exist in kernel32.dll, its basically telling the compiler to call ReadFile, through apiReadFile.
The @<num> part of that is just <num> = number of parameters * 4.

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?

Thank's again both

A nice piece of code, I hope to understand it soon, let me read about modules and will try some things.

I'm not a programmer, ellectronics is my area, I like software and I read an play mostly with Pascal (3.0 .. 6.0)
I read some C (djgpp) and assembler 8086 (I work with microcontrollers). Basic of course. For a year in my free times i'm learning Blitz3D for a project I supose some day will finish.

I write some thing's enterely by instinct.

Starting with the definitions I saw in DLPORTIO and the one's you sent me, I try to write some thing like your's, but I find that the string definition:

apiCreateFile:Int(lpFileName:String, dwDesiredAccess:Int, dwShareMode:Int, lpSecurrityAttributes:Int, dwCreationDistribution:Int, dwFlagsAndAttributes:Int, hTemplateFile:Int) = "CreateFileA"


At first I receive an error when I call that function, then I saw that the definition start with "apiCreateFile" and end with "CreateFileA" I decide to declare:

global apiCreateFile:Int(lpFileName:String, dwDesiredAccess:Int, dwShareMode:Int, lpSecurrityAttributes:Int, dwCreationDistribution:Int, dwFlagsAndAttributes:Int, hTemplateFile:Int)"Win32"=GetProcAddress(DllHandle,"CreateFileA")


I didn't get an error

when the compiler doesn't recongnize the "*"

I defined the pointers as Byte Ptr, and I reveive no error message

so

I rewrite the functions in SERIALIO.BB the way I think they should work (FREEBANK doesn't exists but seems thah BlitzMax is intelligent enaugh to free all the things one leave with out use!??)

but CreateFile doesn't seems to work properly, didn`t return other value than -1 (having a port free in my machine).

I put Varptr nameVar whenever shoul be a pointer but still doesn' wor, really I don't know why!

Thank's again

I don't think you can send Varptr variables to external functions, other then that I would have to see what your code is actually doing to figure out why createfile returns -1.

Well, I try to use your EXTERNS declares but the compiler seems to have a trouble with the @12 in the apiSetCommTimeOuts, so I tried Niegel's module.
Work's!
After some wrong writing command's the BMK build the mod

I suppose, I forgotten something because from a new bmx file doesen't see the type TComm. Do I have to do something else to mod's other than bmk?

Any way, I comment (') the module's declarations and use all of the code in a .bmx, plus some code to test the metod's and work fine.

Thank's both for your help
Be patient with me, for each answer I resolve, I got 100 new question's, but keep walking (like jhonny)