BaCon Bits

For discussions about programming, programming questions/advice, and projects that don't really have anything to do with Puppy.
Message
Author
Volhout
Posts: 547
Joined: Sun 28 Dec 2008, 08:41

#49 Post by Volhout »

I am trying to write a BaCon glue layer to the FTDI (USB serial port) chip. I plan to use this chip in bitbang mode to get 8 individual IO pins.

I managed to connect to the chip, to write data out, and to read data back. Problem is that each write or read takes 1 msecond.
I want to test if sending out multiple bytes in 1 write command achieves a faster throughput. The C-code header file allows this.

test program:

'-------------------------------------------------------------
'
' program to test the driver glue layer in ftdi_drv.bac
'
' 2011-09-02 Harm de Leeuw
'--------------------------------------------------------------

INCLUDE "ftdi_drv.bac"

LOCAL data TYPE unsigned char
LOCAL mask TYPE unsigned char

PRINT "connect to USB module with FT245BM"
mask = 0xFF
ft245bm_open (mask)
PRINT "device connected, enabling bitbang mode"

'PRINT "start banging"
'FOR data = 0 TO 254
' ft245bm_poke (data)
' PRINT RIGHT$(HEX$(ft245bm_peek()),2)
'NEXT data
'PRINT "stop banging, disable bitbang mode"

'trigger
ft245bm_poke (0xFF)
ft245bm_poke (0x00)
ft245bm_poke (0xFF)

'test
PRINT "start printing string"
g$="2"
ft245bm_print (g$)
PRINT "done, closing down"

INPUT a

ft245bm_close ()

END





My glue layer -------------------------------------------------------

'---------------------------------------------------------------------------
' BaCon driver for FTDI USB-SERIAL convertor chips. Uses compiled libraries
' from FTDI : libftdi-0.19. When compiled (./configure, make, make install)
' this library generates libftdi.so.1
' 2011-09-02 Harm de Leeuw
'---------------------------------------------------------------------------
' Version
' 0.1 Supports open(mask), poke(byte), and close()
' 0.2 Added peek() function
'---------------------------------------------------------------------------
TRAP LOCAL

' Import some calls first
CONST library$ = "libftdi.so.1"

' Get the functions from the library
IMPORT ftdi_init(long) FROM library$ TYPE int
IMPORT ftdi_usb_open(long,int,int) FROM library$ TYPE int
IMPORT ftdi_get_error_string(long) FROM library$ TYPE char* ALIAS ftdi_get_error_string$
IMPORT ftdi_read_chipid(long,long) FROM library$ TYPE int
IMPORT ftdi_usb_close(long) FROM library$ TYPE int
IMPORT ftdi_deinit(long) FROM library$ TYPE void
IMPORT ftdi_write_data(long,long,int) FROM library$ TYPE int
IMPORT ftdi_set_bitmode(long,unsigned char,unsigned char) FROM library$ TYPE int
IMPORT ftdi_disable_bitbang(long) FROM library$ TYPE int
IMPORT ftdi_usb_get_strings(long,long,long,int,long,int,long,int) FROM library$ TYPE int
IMPORT ftdi_read_pins(long,long) FROM library$ TYPE int

CONST TYPE_AM = 0
CONST TYPE_BM = 1
CONST TYPE_2232C = 2
CONST TYPE_R = 3
CONST TYPE_2232H = 4
CONST TYPE_4232H = 5

CONST BITMODE = 0x01

' BaCon does not know types so we define
' a RECORD with the needed members
RECORD ftdic
' USB specific
LOCAL usb_dev TYPE long
LOCAL usb_read_timeout TYPE int
LOCAL usb_write_timeout TYPE int
' FTDI specific
LOCAL type TYPE int
LOCAL baudrate TYPE int
LOCAL bitbang_enabled TYPE unsigned char
LOCAL *readbuffer TYPE unsigned char
LOCAL readbuffer_offset TYPE unsigned int
LOCAL readbuffer_remaining TYPE unsigned int
LOCAL readbuffer_chunksize TYPE unsigned int
LOCAL writebuffer_chunksize TYPE unsigned int
LOCAL max_packet_size TYPE unsigned int
' FTDI FT2232C requirecments
LOCAL interface TYPE int
LOCAL index TYPE int
' Endpoints
LOCAL in_ep TYPE int
LOCAL out_ep TYPE int
' General
LOCAL bitbang_mode TYPE unsigned char
LOCAL eeprom_size TYPE int
LOCAL error_str TYPE char*
LOCAL async_usb_buffer TYPE char*
LOCAL async_usb_buffer_size TYPE unsigned int
END RECORD

'-----------------------------------------------------------------------
SUB ft245bm_open (unsigned char io_mask)
'-----------------------------------------------------------------------
' this function initializes the FTDI 245 BM chip attached to the USB bus
' of the PC in bitbang mode (8 bit wide IO port). The io_mask define the
' data direction ("1"=out, "0"=in).
' timing: every byte write takes 1 milisecond, regardless CPU speed.

IF ftdi_init(ADDRESS(ftdic)) < 0 THEN
PRINT "ftdi_init failed"
END 1
END IF
ret = ftdi_usb_open(ADDRESS(ftdic), 0x0403, 0x6001)
IF ret < 0 THEN
PRINT "unable to open ftdi device: ", ret, " (", ftdi_get_error_string$(ADDRESS(ftdic)), ")"
END 1
END IF
ret = ftdi_set_bitmode(ADDRESS(ftdic), io_mask, BITMODE)
IF ret < 0 THEN
PRINT "unable to set bitmode: ", ret, " (", ftdi_get_error_string$(ADDRESS(ftdic)), ")"
END 1
END IF
END SUB

'-----------------------------------------------------------------------
SUB ft245bm_poke (unsigned char data)
'-----------------------------------------------------------------------
' this function sends out a byte to the 8 bit wide io port of the ftdi
' 245bm chip. The actual data output is masked by the io_mask set in
' the init command.
ret = ftdi_write_data(ADDRESS(ftdic), ADDRESS(data), 1)
IF ret < 0 THEN
PRINT "unable to write: ", ret, " (", ftdi_get_error_string$(ADDRESS(ftdic)), ")"
END 1
END IF
END SUB


'-----------------------------------------------------------------------
SUB ft245bm_close ()
'-----------------------------------------------------------------------
' this function disconnects the ftdi 245bm chip from the USB bus.
' first bitbang mode is disabled, putting the io pins in tristate.
ret = ftdi_disable_bitbang(ADDRESS(ftdic))
IF ret < 0 THEN
PRINT "unable to close ftdi device: ", ret, " (", ftdi_get_error_string$(ADDRESS(ftdic)), ")"
END 1
END IF
ret = ftdi_usb_close(ADDRESS(ftdic))
IF ret < 0 THEN
PRINT "unable to close ftdi device: ", ret, " (", ftdi_get_error_string$(ADDRESS(ftdic)), ")"
END 1
END IF
ftdi_deinit(ADDRESS(ftdic))
END SUB

'-----------------------------------------------------------------------
FUNCTION ft245bm_peek () TYPE unsigned char
'-----------------------------------------------------------------------
' this function reads the 8 io pins from the ftdi 245bm chip, and returns
' the value. The value read is depending on the mask set when opening the
' connection.
LOCAL data TYPE unsigned char
ret = ftdi_read_pins(ADDRESS(ftdic), ADDRESS(data))
IF ret < 0 THEN
PRINT "unable to read: ", ret, " (", ftdi_get_error_string$(ADDRESS(ftdic)), ")"
END 1
END IF
RETURN data
END FUNCTION

' *** TEST ***
'-----------------------------------------------------------------------
SUB ft245bm_print (STRING data)
'-----------------------------------------------------------------------
' this function sends out a string of bytes byte to the 8 bit wide io
' port of the ftdi ' 245bm chip. The actual data output is masked by
' the io_mask set in the init command by the chip.
LOCAL len TYPE int
len = LEN(data)
PRINT len
PRINT data FORMAT "%s"
ret = ftdi_write_data(ADDRESS(ftdic), data, len)
IF ret < 0 THEN
PRINT "unable to write: ", ret, " (", ftdi_get_error_string$(ADDRESS(ftdic)), ")"
END 1
END IF
END SUB
' *** TEST ***

'-----------------------------------------------------------------------




The void that does not work is ft245bm_print. In the line

ret = ftdi_write_data(ADDRESS(ftdic), data, len)

I get a compiler error that data is converted from pointer to integer. Whereas I defined data as a string. Even if I replace

data

with

ADDRESS(data)

it does not work.

Any idea's ??

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#50 Post by GatorDog »

This does look interesting, and I'd like to be able to do it myself.
Hopefully someone with some experience with this will check in.

rod

User avatar
PjotAwake
Posts: 34
Joined: Wed 03 Nov 2010, 20:58
Location: The Hague, The Netherlands
Contact:

#51 Post by PjotAwake »

Hi Volhout,
I get a compiler error that data is converted from pointer to integer. Whereas I defined data as a string.
The problem is in the IMPORT definition of 'ftdi_write_data'. This is defined as follows:

Code: Select all

IMPORT ftdi_write_data(long,long,int) FROM library$ TYPE int
As you can see, BaCon now expects the second argument to be a 'long' while you are trying to send a string.

The issue is solved when this definition is corrected. Also according to these docs the second argument should be a string. Therefore, change the IMPORT into the following:

Code: Select all

IMPORT ftdi_write_data(long,char*,int) FROM library$ TYPE int
Of course, you need to remove the ADDRESS construct from the second argument if you invoke this function, and also change the 'ft245bm_poke' function. Its argument should be a STRING also, and should be invoked as follows:

Code: Select all

ft245bm_poke (CHR$(0xFF))
ft245bm_poke (CHR$(0))
ft245bm_poke (CHR$(0xFF))
Now compilation will work.

M.vr.grt,
Peter

Volhout
Posts: 547
Joined: Sun 28 Dec 2008, 08:41

#52 Post by Volhout »

Hi Peter,

Thanks for your help. It compiles now, and it actually works. GREAT !!
I think I was lucky that the poke worked

Final goal is to implement I2C through this interface, and the functions that I have now are sufficient to do I2C writes, and with carefull design, even I2C ACK. Still need to think about I2C read . If I bitbang that then it will be terribly slow.

Thanks for your help,

Volhout

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

Searched for notebook example.

#53 Post by sunburnt »

##### SOLVED #####

Searched but didn`t find any examples of how to use it.
TEXT creates a new tab, and I assumed new widgets go on the new panel.
The list boxes on the panels are good, but the buttons are off the bottom.

Code: Select all

tab0_ = NOTEBOOK("Debian Packages",tabW,tabH) : ATTACH(winMAIN_,tab0_,tabX,tabY)
lstGRPS_ = LIST(lstGrpsW,lstH) : ATTACH(tab0_,lstGRPS_,lstGrpsX,allY) : CALLBACK(lstGRPS_,lstGRPS)

lstPKGS_ = LIST(lstPkgsW,lstH) : ATTACH(tab0_,lstPKGS_,lstPkgsX,allY) : CALLBACK(lstPKGS_,lstPKGS)

btnBIN_ = BUTTON(INTL$("Binary"),90,btnH) : ATTACH(tab0_,btnBIN_,btnBinX,btnY) : CALLBACK(btnBIN_,btnBIN)

btnSRC_ = BUTTON(INTL$("Source"),90,btnH) : ATTACH(tab0_,btnSRC_,btnSrcX,btnY) : CALLBACK(btnSRC_,btnSRC)

btnQUIT_ = BUTTON(INTL$("Quit"),60,btnH) : ATTACH(tab0_,btnQUIT_,btnQuitX,btnY) : CALLBACK(btnQUIT_,QUIT)

TEXT(tab0_,"Package Info.")
edINFO_ = EDIT(edInfoW,edInfoH) : ATTACH(tab0_,edINFO_,edInfoX,allY)
DISPLAY
The geometry is mostly variables, but you can see what I`ve done.
Thanks GatorDog... Terry

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#54 Post by GatorDog »

TEXT creates a new tab, and I assumed new widgets go on the new panel.
Yes. Attaching new widgets to a tab goes on the currently active tab. If you want
to place something on a previously created tab, you first need to select the tab
with, for ex. SET(tab0_, n). (The first tab being "0" zero).

If you haven't tried bacon3G yet, give it a go. (Gators Gui Guide for HUG).
For example under "Widgets", scroll down to Notebook, and see-

Code: Select all

NOTEBOOK
Notebook_ = NOTEBOOK("caption", xsize, ysize)

Creates a notebook with one tab containing a caption, and a width of xsize
  and a height of ysize.

A notebook tab is treated as a window, that is you can directly attach
  widgets to it. In essence, notebook tabs are a collection of windows.

- Attach tab to your main widow - ATTACH(Mainwin_, Notebook_, xpos, ypos)

- Add another tab - TEXT(Notebook_, "New tab name")

- Add a widget to the current tab - ATTACH(Notebook_, Widget_, xpos, ypos)

- Get caption in the active tab - Var$ = GRAB$(Notebook_)

- Get current tab number - Var = GET(Notebook_)

- Set current tab to, (first tab is zero) - SET(Notebook_, n)

- You either populate a tab immediately after defining it or you will have to
  set the tab as the current tab with SET(Notebook_, n) before populating it.
As you'll see, it's an attempt to pull the information for HUG widgets together.
There are some examples for using widgets like the MSGDIALOG.
Preview of the gtk-stock buttons and a color chart with hex code and color
names. I keep it handy while I'm makin' Bacon' :wink:

The attached is the source and a compiled (standalone) version of bacon3G.

rod
Attachments
bacon3g.tar.gz
bacon3G source and standalone bin
(82.54 KiB) Downloaded 542 times

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

#55 Post by sunburnt »

Just dnlded it as soon as I saw it... Another Q here.

Compile gives error: Could not parse line. ( At the first CASE )

Code: Select all

							' error messages
SUB errMSG(STRING Err$)
	SELECT Err$
		CASE "pet"
			Msg$ = "ERROR: Failed making .pet package!"
		CASE "squ"
			Msg$ = "ERROR: Failed making .sfs package!"
		CASE "sqa"
			Msg$ = "ERROR: Failed making .sq(n) package!"
	END SELECT
	TEXT(msgERR_,Msg$)
	SHOW(msgERR_)
END SUB
							' make Puppy ".pet" package
SUB btnPET
	SYSTEM pkg2pet inDir$ outFile$
	IF RETVAL > 0 THEN errMSG "pet"
END SUB
The calling sub is at the bottom.
The SELECT statement looks just like the one in the BaCon docs.!

Apparently you can`t "one line" the: CASE "pet" : Msg$ = "ERROR: ...

I`m still a little vague about passing variables ( "pet" > Err$ ).
Is what I have correct? Or do I: Err = "pet" and then call: errMSG ?

And do I need to hide the MSGDIALOG before or after I make it?

Thanks...
Last edited by sunburnt on Mon 12 Sep 2011, 04:29, edited 4 times in total.

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

#56 Post by sunburnt »

GatorDog; Your Bacon3G has missing icons.

BTN 2 "Discard", BTN 3 All below "Zoom In" "Zoom Out" "Best Fit".

But maybe they`re just missing on my PC...

It looks like there`s another tab to the right of MEMO, but it`s off the GUI.

Looks really useful, thanks for the effort on your part.!
Thought I`d tell you... Terry

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#57 Post by GatorDog »

Hi sunburnt,
sunburnt wrote:GatorDog; Your Bacon3G has missing icons.

BTN 2 "Discard", BTN 3 All below "Zoom In" "Zoom Out" "Best Fit".
Missing for me also. I don't know if they are missing in Puppy or there's a problem with gtk :?:
I included them so it can be seen first off that the icon isn't working; rather than finding it out over and over again the hard way.
It looks like there`s another tab to the right of MEMO, but it`s off the GUI.
Ok thanks for feedback. Did you by chance recompile and change the font size or dpi?
I used the sizes that Barry recommended for use in Puppy, which seems to work well for me.
ie. HUGOPTIONS("BASEXFTDPI 78") and HUGOPTIONS("FONT DejaVu Sans 12")
I think the reason Barry came up with those HUGOPTIONS is so that a GUI would
look good regardless of what "theme" the user is running.
But it would be good to know if there is a problem with them.

You can change "CONST Mainwin_width = 525" to something a little wider (550 for example)
and recompile. Be sure to use at least Bacon beta 24 and hug 61 from a previous post above
or grab the latest beta's from here. Although it doesn't look like HUG is in the beta dir right now.
Or I can recompile one for you with a wider setting.

rod

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#58 Post by GatorDog »

Terry,
Compile gives error: Could not parse line. ( At the first CASE )
Try changing

Code: Select all

   IF RETVAL > 0 THEN errMSG "pet"
to

Code: Select all

   IF RETVAL > 0 THEN errMSG( "pet" )
- add "(" and ")"

rod

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

#59 Post by sunburnt »

Ahhh yes... "Passing an argument" is different for subs than for running files.
Different syntax () for the same thing, both are position dependent I assume?

Another problem with the same set of subs:

SYSTEM "pkg2pet" inDir$ outFile$

# Cause: expected ')' before inDir$

Again, this looks exactly like the Bacon docs.
Thanks one more time!

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#60 Post by GatorDog »

Code: Select all

SYSTEM "pkg2pet" inDir$ outFile$ 
For that I think you'll need something like:

Code: Select all

myCmd$ = CONCAT$("pkg2pet", " ", inDir$, " ", outFile$ )
SYSTEM myCmd$ 
rod
add-
In this case, I think this will work also:

Code: Select all

SYSTEM CONCAT$("pkg2pet", " ", inDir$, " ", outFile$ )
But generally I've been trying not to get carried away with making long compounded statements.

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

#61 Post by sunburnt »

Yeah... I`ve used the CONCAT$ before, I just didn`t think of using it here.
And boy is that a pain in the arse! I`m remembering how crude Basic is...

I`ve said here many times, it takes 10 lines of Visual Basic for 1 of Bash.
Bash script`s intimidating as you start learning it, but it`s very powerful.!
But BaCon will compile! Too bad there isn`t a real converter for script to C.

P.S. Hey GatorDog, should I post a pic. of my app. here for all to see?

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#62 Post by GatorDog »

P.S. Hey GatorDog, should I post a pic. of my app. here for all to see?
Sure. Go ahead and throw in the source code too. We all can learn :)

rod

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

#63 Post by sunburnt »

A BaCon-HUG GUI front end for pDebThing, a Debian package downloader.
I wrote another GUI in gtkDialog, they both use the same Bash script backend.
I could have written more of the backend code in BaCon Basic,
. but it just calls shell commands anyway, so I didn`t write much of it in BaCon.

This is a good example of the type of GUI`s I talk about, with no backend code.
This way the backend and frontend ( GUI ) code is separate and replaceable.
Here there is one set of backend code and two sets of frontend code I wrote.
More GUIs could be written in Perl or Python, and the backend C or whatever.

Both GUIs look the same as they both use GTK widgets.

# The first pic. is the main tab panel of the Debian downloader.
The left ListBox shows the groups of packages.
Click a group and it`s list of packages shows in the right ListBox.
The right ListBox shows the packages in the selected group.
Click a package and it`s description info. shows on the second tab panel.

# The second pic. is the second tab panel that shows the description info.
Attachments
000_DebDnld_BaCon.png
Upper one is package selection , lower one is package info.
(63.47 KiB) Downloaded 1200 times
Last edited by sunburnt on Tue 13 Sep 2011, 21:54, edited 3 times in total.

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#64 Post by GatorDog »

sunburnt

Looking neat and clean :D

rod

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

#65 Post by sunburnt »

GatorDog; Trying to get the GUI to show all the info.
Here`s one part for the first listbox, the second`s the same.
The var. TMP$ is set above and the files exist. What`s wrong?

Code: Select all

TMP$ = "/tmp/deb-dnld"

	OPEN CONCAT$(TMP$,"/main.list") FOR READING AS inFile
	WHILE NOT(ENDFILE(inFile)) DO
		READLN TXT$ FROM inFile
		IF CHOP$(TXT$) = "" THEN CONTINUE
		TEXT(lstGRPS_,TXT$)
	WEND
	CLOSE FILE inFile
And this is the info. box, is this code right for filling an edit box?

Code: Select all

	OPEN CONCAT$(TMP$,"/pkg.info") FOR READING AS inFile
	WHILE NOT(ENDFILE(inFile)) DO
		READLN TXT$ FROM inFile
		INFO$ = CONCAT$(INFO$,TXT$,NL$)
	WEND
	CLOSE FILE inFile
	TEXT(edINFO_,INFO$)
Last edited by sunburnt on Tue 13 Sep 2011, 05:25, edited 1 time in total.

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#66 Post by GatorDog »

Terry,
I think your file I/O code itself is OK.

I'm guessing that for the top code snippet that you're getting a blank List?
I'll bet you a Little Debbies Chocolate Snack Cookie that "main.list" has
a final newline (NL$) character. NL$ is the default seperator when reading
in a text file. So, the final NL$ is seperating the text before it from the "nothing" (ie. null)
after it. So the final thing the TEXT(lstGRPS_,TXT$) is a null character.
Guess what that does. It clears the list box.

If you want to skip blank lines, you can put this in the WHILE loop
IF CHOP$(TXT$) = "" THEN CONTINUE
That will just skip processing that line and go read in the next line.
If you want the blank line, then substitute in a space for that list line.
IF CHOP$(TXT$) = "" THEN TMP$ = " "

An edit widget is cleared the same way, TEXT(Edit_widget_, "").
But your code there is adding a NL$ to each line so I don't think that's a problem there.

rod

ed. Snack Cookie vs. Snake Cookie :oops:

User avatar
sunburnt
Posts: 5090
Joined: Wed 08 Jun 2005, 23:11
Location: Arizona, U.S.A.

#67 Post by sunburnt »

Hey GatorDog; Look above at the corrected first listBox, I`m sure that`s right...
The listboxes are still empty...

I see that the CHOP line is removing blank lines.
And you`re right... All 3 lists have a trailing blank line or more.
All 3 files are there for this testing, and are there sometimes during operation.

I assume the info. editBox handles null lines, other wise it couldn`t show them.

### Q: Would this work also: IF TXT$ <> "" THEN TEXT(lstGRPS_,TXT$)
It gives a compile error: Cause: expected expression before token ","
Last edited by sunburnt on Tue 13 Sep 2011, 08:32, edited 1 time in total.

User avatar
GatorDog
Posts: 138
Joined: Tue 12 Sep 2006, 16:43

#68 Post by GatorDog »

sunburnt,
I don't spot anything yet that looks out of place, but I may be looking through
the wrong section of my tri-focals :lol:

If you'd like to, either upload your code and the sample files your working with
or PM them, and I'll take a look.

rod

Post Reply