FT245BM bitbang support in BaCon
Dec 22, 2011 10:29:55 GMT 1
Post by volhout on Dec 22, 2011 10:29:55 GMT 1
I have been experimenting with a FTDI FT245BM USB chip.
This chip was designed to be a USB parallel printer port. But it has low level functionality called "bitbang mode" where you can control 8 IO pins individually, creating a 8 pin GPIO (general purpose input/output) port.
My intention was to use this functionality for a I2C project, but when it started working measurements show the I2C bus using bitbang mode would be too slow for the project. So the project was abandoned. But the functionality could be sufficient for anyone who wants to control a model railway, do some trafic control, home automation, or similar applications. The 8 bit port on the chip can be expanded with discrete logic chips at virtually no cost.
Yesterday BigBass (forum member) hinted me that others might benefit from what I had achieved, so I decided to post it here anyway.
Setup:
- Intel Core2duo PC with Puppy linux "WARY 5.1.4.1" and devx SFS installed running from USB stick (frugal)
- DLP-USB245M module from www.dlpdesign.com containing the FT245BM chip.
- on the DLP-USB245BM module, connect pins PVC, EXT, VIO and RST together to make the module bus powered. Use GND and pins D0...D7 for IO.
My test routine
This test code uses a driver, also written in BaCon, that acts as a layer between the actual FTDI library and the test code. The driver is listed here. This driver is by no means complete, but the functions listed do work, and for anyone interested, expand or modify it at will. This is simply where I abandoned the project.
The driver uses a linux library from FTDI (libftdi-0.19). This linux driver can be downloaded from their website. Just unzip the file, browse to the folder that contains the make file and type:
And the driver will be installed in Puppy Linux. It is a simple as that.
I hope this serves someone. If someone uses it for a project, then please port it on the forum. Always nice to see projects from others.
I want to thank Vovchik for his help getting this project until it's current state.
This chip was designed to be a USB parallel printer port. But it has low level functionality called "bitbang mode" where you can control 8 IO pins individually, creating a 8 pin GPIO (general purpose input/output) port.
My intention was to use this functionality for a I2C project, but when it started working measurements show the I2C bus using bitbang mode would be too slow for the project. So the project was abandoned. But the functionality could be sufficient for anyone who wants to control a model railway, do some trafic control, home automation, or similar applications. The 8 bit port on the chip can be expanded with discrete logic chips at virtually no cost.
Yesterday BigBass (forum member) hinted me that others might benefit from what I had achieved, so I decided to post it here anyway.
Setup:
- Intel Core2duo PC with Puppy linux "WARY 5.1.4.1" and devx SFS installed running from USB stick (frugal)
- DLP-USB245M module from www.dlpdesign.com containing the FT245BM chip.
- on the DLP-USB245BM module, connect pins PVC, EXT, VIO and RST together to make the module bus powered. Use GND and pins D0...D7 for IO.
My test routine
'-------------------------------------------------------------
'
' program to test the driver glue layer in ftdi_drv.bac
'
' 2011-12-22 Harm de Leeuw
'--------------------------------------------------------------
INCLUDE "ftdi_drv.bac"
LOCAL data TYPE unsigned char
LOCAL mask TYPE unsigned char
' -------------------------- OPEN CONNECTION ----------------------
PRINT "connect to USB module with FT245BM"
'set <B7,B4> as output and <B3,B0> as input
mask = 0xF0
ft245bm_open (mask)
PRINT "device connected in bitbang mode"
' ------------------- TEST FOR DISCRETE I/O ------------------------
PRINT "start dicrete IO ripple"
FOR data = 0 TO 254
ft245bm_poke (CHR$(data))
PRINT RIGHT$(HEX$(ft245bm_peek()),2);
PRINT " ";
NEXT data
PRINT
' ------------------ TEST FOR STRING STREAMING ---------------------
PRINT "start printing string"
'note "1" = ascii 49, "@" = ascii 64
'with mask = 0xFE this will toggle <B7,B4> between b'0011' and b'0100'
'and <B3,B0> will be input.
g$ = "1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@1@"
ft245bm_print (g$)
' --------------------------- CLOSE CONNECTION ---------------------
PRINT "done, closing down"
ft245bm_close ()
END
This test code uses a driver, also written in BaCon, that acts as a layer between the actual FTDI library and the test code. The driver is listed here. This driver is by no means complete, but the functions listed do work, and for anyone interested, expand or modify it at will. This is simply where I abandoned the project.
'---------------------------------------------------------------------------
' 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-12-22 Harm de Leeuw
'---------------------------------------------------------------------------
' Version
' 0.1 Supports open(mask), poke(byte), and close()
' 0.2 Added peek() function
' 0.3 Added print(string) to output bytes at max speed
'
'---------------------------------------------------------------------------
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,char*,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 (STRING 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), 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
'-----------------------------------------------------------------------
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
'-----------------------------------------------------------------------
The driver uses a linux library from FTDI (libftdi-0.19). This linux driver can be downloaded from their website. Just unzip the file, browse to the folder that contains the make file and type:
./configure
make
make install
And the driver will be installed in Puppy Linux. It is a simple as that.
I hope this serves someone. If someone uses it for a project, then please port it on the forum. Always nice to see projects from others.
I want to thank Vovchik for his help getting this project until it's current state.