Serial Port Comm

BlitzMax Forums/BlitzMax Programming/Serial Port Comm

Zenith(Posted 2005) [#1]
Anyone figure out serial port communication yet?
I can't figure out the best way to go about it. :(


Zenith(Posted 2005) [#2]
Actually, I got writing to the port done, but not reading from it. :)

It always EOF's right away.


BlitzSupport(Posted 2005) [#3]
You could try Nigel Brown's stuff here:

http://www.nigelibrown.pwp.blueyonder.co.uk/blitz/userlibs/index.htm

I think you need the dlportio.decls as well as the serial.zip file. You also need DLPortIO, which I believe is this thing here...

Disclaimer: I've never tried it!


Zenith(Posted 2005) [#4]
Hehe, do decls work in blitzmax?


BlitzSupport(Posted 2005) [#5]
No, but you may be able to use the information to create a suitable module. Or you may not... !


Zenith(Posted 2005) [#6]
Oh! I got it to work, had to test it on a loopback before it would stop being stupid. :)

Hehe, the pointer increments as data is dumped into the stream, so I couldn't figure out why it kept reading 0, -- so make sure to check how much the stream size has changed since the last time you read bytes from it, seek back, and the read until the size!

Ahhh, it's nice to have my PC talking to my FPGA.. ;)


Zenith(Posted 2005) [#7]
Anyway, for others:

Tested on Windows XP, SP1

You must open a port like so:
STREAM = OpenStream("COM1:") ' or COM2.. etc, or even OpenFile

To Write data through the serial port, one must writebyte() int, short, what not.

To Read Data, one must check the StreamSize(), if it is greater than the last check, there is data to be read.
You cannot just simple READ in the data, as each time data is read into the buffer, the stream position is incremented with it. So you must make sure to know how much has been read in.

At the start, you must seek back to the last known position the stream was at before any of this data has been written in.
To do this, each time I read in data, I will increment a variable by how much I have read in. You just keep incrementing it (as you read data in) until the stream's size and your variable are equal. You could even go by StreamPos().. (But you still need to know where you were before this new data came in!)

Note: The settings that are set are the ones Windows have as default in the device manager. So go into Device manager and setup whatever it is you need.

Just make sure to close the stream at the end. :)


kmac(Posted 2005) [#8]
Any chance you can post a working example for BlitzMax? I do have a serial device that I'd like to use but have never programmed outside of the included environment. As such, I don't even know how to test the various inputs (five buttons and a microphone with a volume threshold).

Thanks.


Zenith(Posted 2005) [#9]
Look down for the furthest version.


Zenith(Posted 2005) [#10]
Welp, Being as cool as I am (heh joking.) I went ahead and wrote a little library for serial, and possibly parallel port! (if you use LPT as the type possibly?)


But uhh, look further down for the latest version.


Panno(Posted 2005) [#11]
cool ! ;)

a chance to change the boudrate ?

u know its 9600/8/no/1 in winxp and 98 also i guess


Zenith(Posted 2005) [#12]
No, if you change the settings in Device Manager, that will be the settings used.

The functions to change the settings and such are in kernal32, but I don't know how to get them to work... Yet. ;)


TeaVirus(Posted 2005) [#13]
Nice! Thanks Zenith! I may try using this to play around with my OBD2 scanner...


Zenith(Posted 2005) [#14]
Figure I better add comments.. check it out. :)

Well, I'm gonna rewrite it as an object with methods as a module.

Ok, here it is as a module with an object/methods.
On my computer it is at:
C:\BlitzMax\mod\pub.mod\zcomm.mod
Module pub.zcomm
ModuleInfo "Version: 1.00"
ModuleInfo "Author: Matt Griffith (Zenith)"
ModuleInfo "License: Public Domain"
ModuleInfo "Modserver: BRL"

Import brl.standardIO
Import brl.system

Rem
	bbdoc: Zenith's Serial(And possibly? Parallel) Port Library. :)
		electrodev{NOSPAM}gmail.com
	I give out this code as public domain, FREE AS HELL.
	Give me credits if you want... ;)
	NOTE: THIS HAS ONLY BEEN TESTED UNDER WINDOWS XP WITH LOOPBACK HARDWARE
	WHERE RX IS BUFFERED INTO TX.
EndRem

Type Tcomm
	Field timeout,stream,id$
	
' Open up a stream using serial communication
' Or possibily parallel if you type in "LPT" instead of COM as type?
' timeout is in milliseconds..
' port refers to which ports, IE: COM1 COM2, LPT1.. and so forth	
	Method Open()
		Self.stream = OpenStream(Self.id+":")
	End Method

' Clean up the stream, each time you recieve data it is added to the
' stream, this can slowly grow into a huge size, however with this
' function you can reset the stream and reconnect right away, cleaning
' away all the old data. (Just make sure you have read it all before then)	
	Method Clean()
		CloseStream(Self.stream)
		Self.stream = OpenStream(Self.id+":")
	End Method

' Send data to the port, using a simple string - no delim characters or anything
' just send a string and it will send it until it reaches the end.	
	Method Send(send$)
		Local i
		For i=0 To Len(send)-1
			WriteByte(Self.stream,send[i])
		Next
	End Method

' Wait for data to be recieved on the stream.
' It will timeout if it doesn't get data until then.
	Method Wait()
		Local time = MilliSecs()
		While StreamPos(Self.stream)=0
			If MilliSecs()-time>Self.timeout ' we'll give it a 1 second time out
				Return 0
			EndIf
		Wend
		Return StreamSize(Self.stream)
	End Method
	
' Once you have checked if data is ready to be read with CommWait()
' You can then read it off, this will output a string.
' A string is probally a very bad way of getting data back and forth
' But I figured it would just be temporary.
' I'm not even sure if it will send bytes that are 0-32?! :(
	Method Recv$()
		Local data$,i
		SeekStream(Self.stream,0)
		For i=0 To StreamSize(Self.stream)-1
			data = data+Chr(ReadByte(Self.stream))
		Next
		Return data
	End Method
End Type



Now here's the example code, using methods -- It's much easier now. :)

Rem
	****EXAMPLE PROGRAM****
	Zenith's Serial(And possibly? Parallel) Port Library. :)
		electrodev{NOSPAM}gmail.com
	I give out this code as public domain, FREE AS HELL.
	Give me credits if you want... ;)
	NOTE: THIS HAS ONLY BEEN TESTED UNDER WINDOWS XP WITH LOOPBACK HARDWARE
	WHERE RX IS BUFFERED INTO TX.
EndRem

Framework brl.standardio
Import pub.zcomm
Strict
Local c:Tcomm = New Tcomm
c.id = "COM1"
c.timeout = 1000
c.Open()

If c.stream
	Print "STREAM CONNECTED on "+c.id
Else
	Print "STREAM FAILED TO CONNECT on "+c.id
	Input()
	End
EndIf

Repeat
	Local recv$,send$ = Input("PC> "),bytes
	Print "@Sending "+Len(send)+" byte(s)"
	' Send the data
	c.Send(send)
	' Wait for data to be recieved
	bytes = c.Wait()
	Print "@Recieving "+bytes+" byte(s)"
	If bytes
		' Ok, we have to data to be read in, now recieve it.
		recv$ = c.Recv()
		Print c.id+"> '" +recv+"'"
		c.Clean()
	Else
		Print c.id+" has timed out."
	EndIf
	
	FlushMem
Forever
Print "CLOSED STREAM.."
Input()


Make SURE TO Clean the Stream after Reading from it!


Panno(Posted 2005) [#15]
ha !
get some Bytes from Com1 without c++ under xp !!

thx


Nigel Brown(Posted 2005) [#16]
Have placed first file in Pub.zcomm and called it zcomm.bmax and I get and error "Can't find interface module 'pub.zcomm' Is there a document anywhere on adding modules? How can I fix this error?

zcomm will not compile either complains "module does not match commandline module" ???

OK found some text help on this and managed to use BMK to compile the module before calling it. Just need to check the program is working correctly now :-)