This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
en:projects:ucecho_fpga [2013/01/28 02:29] – Add Python 2.6 Example for UCEcho Host coflynn | en:projects:ucecho_fpga [2016/09/15 08:35] (current) – gelöscht stefan | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== ucecho for ZTEX USB FPGA boards ====== | ||
- | The following example runs on [[http:// | ||
- | |||
- | The firmware (defined in [[en: | ||
- | |||
- | The Bitstream for the FPGA configuration is defined in [[en: | ||
- | |||
- | The host software (defined in [[en: | ||
- | |||
- | Uploading the Firmware to EEPROM is also supported by the firmware (e.g. using the FWLoader utility). | ||
- | |||
- | The example is a part of the package and may serve a good starting point for own projects. | ||
- | |||
- | ===== Firmware: ucecho.c ===== | ||
- | This is the C source code for the firmware: | ||
- | <code c> | ||
- | # | ||
- | # | ||
- | |||
- | // Cypress vendor ID and product ID may only (!) be used for experimental purposes | ||
- | SET_VPID(0x4b4, | ||
- | |||
- | // define endpoints 2 and 4, both belong to interface 0 (in/out are from the point of view of the host) | ||
- | EP_CONFIG(2, | ||
- | EP_CONFIG(4, | ||
- | |||
- | // identify as ZTEX USB FPGA Module 1.2 (Important for FPGA configuration) | ||
- | IDENTITY_UFM_1_2(1.0.0.0, | ||
- | |||
- | // give them a nice name | ||
- | # | ||
- | |||
- | // this is called automatically after FPGA configuration | ||
- | # | ||
- | OEC = 255; | ||
- | ] | ||
- | |||
- | // include the main part of the firmware kit, define the descriptors, | ||
- | # | ||
- | |||
- | |||
- | void main(void) | ||
- | { | ||
- | WORD i,size; | ||
- | | ||
- | // init everything | ||
- | init_USB(); | ||
- | |||
- | EP2CS &= ~bmBIT0; | ||
- | SYNCDELAY; | ||
- | EP4CS &= ~bmBIT0; | ||
- | |||
- | SYNCDELAY; | ||
- | EP4BCL = 0x80; // skip package, (re)arm EP4 | ||
- | SYNCDELAY; | ||
- | EP4BCL = 0x80; // skip package, (re)arm EP4 | ||
- | |||
- | while (1) { | ||
- | if ( !(EP4CS & bmBIT2) ) { // EP4 is not empty | ||
- | size = (EP4BCH << 8) | EP4BCL; | ||
- | if ( size>0 && size< | ||
- | for ( i=0; i<size; i++ ) { | ||
- | IOC = EP4FIFOBUF[i]; | ||
- | EP2FIFOBUF[i] = IOB; // ... and written back to EP2 buffer | ||
- | } | ||
- | EP2BCH = size >> 8; | ||
- | SYNCDELAY; | ||
- | EP2BCL = size & 255; // arm EP2 | ||
- | } | ||
- | SYNCDELAY; | ||
- | EP4BCL = 0x80; // skip package, (re)arm EP4 | ||
- | } | ||
- | } | ||
- | } | ||
- | </ | ||
- | |||
- | ===== Bitstream: fpga/ | ||
- | This is the VHDL source code for the FPGA bitstream: | ||
- | <code vhdl> | ||
- | library ieee; | ||
- | use IEEE.std_logic_1164.all; | ||
- | use IEEE.numeric_std.all; | ||
- | |||
- | entity ucecho is | ||
- | port( | ||
- | pc : in unsigned(7 downto 0); | ||
- | pb : out unsigned(7 downto 0); | ||
- | CLK : in std_logic | ||
- | ); | ||
- | end ucecho; | ||
- | |||
- | |||
- | --signal declaration | ||
- | architecture RTL of ucecho is | ||
- | |||
- | begin | ||
- | dpUCECHO: process(CLK) | ||
- | begin | ||
- | if CLK' event and CLK = ' | ||
- | if ( pc >= 97 ) and ( pc <= 122) | ||
- | then | ||
- | pb <= pc - 32; | ||
- | else | ||
- | pb <= pc; | ||
- | end if; | ||
- | end if; | ||
- | end process dpUCECHO; | ||
- | | ||
- | end RTL; | ||
- | </ | ||
- | |||
- | |||
- | ===== Java host software: UCEcho.java ===== | ||
- | This is the Java source code for the driver: | ||
- | <code java> | ||
- | import java.io.*; | ||
- | import java.util.*; | ||
- | |||
- | import ch.ntb.usb.*; | ||
- | |||
- | import ztex.*; | ||
- | |||
- | // ***************************************************************************** | ||
- | // ******* ParameterException ************************************************** | ||
- | // ***************************************************************************** | ||
- | // Exception the prints a help message | ||
- | class ParameterException extends Exception { | ||
- | public final static String helpMsg = new String ( | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | " | ||
- | | ||
- | public ParameterException (String msg) { | ||
- | super( msg + " | ||
- | } | ||
- | } | ||
- | |||
- | // ***************************************************************************** | ||
- | // ******* Test0 *************************************************************** | ||
- | // ***************************************************************************** | ||
- | class UCEcho extends Ztex1v1 { | ||
- | |||
- | // ******* UCEcho ************************************************************** | ||
- | // constructor | ||
- | public UCEcho ( ZtexDevice1 pDev ) throws UsbException, | ||
- | super ( pDev ); | ||
- | } | ||
- | |||
- | // ******* claimInterface ****************************************************** | ||
- | // claims interface 0 | ||
- | public void claimInterface ( ) throws UsbException{ | ||
- | if ( LibusbJava.usb_claim_interface(handle(), | ||
- | throw new UsbException(" | ||
- | } | ||
- | |||
- | // ******* releaseInterface **************************************************** | ||
- | // releases interface 0 | ||
- | public void releaseInterface ( ) { | ||
- | LibusbJava.usb_release_interface(handle(), | ||
- | } | ||
- | | ||
- | // ******* echo **************************************************************** | ||
- | // writes a string to Endpoint 4, reads it back from Endpoint 2 and writes the output to System.out | ||
- | public void echo ( String input ) throws UsbException { | ||
- | byte buf[] = input.getBytes(); | ||
- | int i = LibusbJava.usb_bulk_write(handle, | ||
- | if ( i<0 ) | ||
- | throw new UsbException(" | ||
- | System.out.println(" | ||
- | |||
- | try { | ||
- | Thread.sleep( 10 ); | ||
- | } | ||
- | catch ( InterruptedException e ) { | ||
- | } | ||
- | |||
- | buf = new byte[1024]; | ||
- | i = LibusbJava.usb_bulk_read(handle, | ||
- | if ( i<0 ) | ||
- | throw new UsbException(" | ||
- | System.out.println(" | ||
- | } | ||
- | | ||
- | // ******* main **************************************************************** | ||
- | public static void main (String args[]) { | ||
- | | ||
- | int devNum = 0; | ||
- | boolean force = false; | ||
- | | ||
- | try { | ||
- | // init USB stuff | ||
- | LibusbJava.usb_init(); | ||
- | |||
- | // scan the USB bus | ||
- | ZtexScanBus1 bus = new ZtexScanBus1( ZtexDevice1.cypressVendorId, | ||
- | if ( bus.numberOfDevices() <= 0) { | ||
- | System.err.println(" | ||
- | System.exit(0); | ||
- | } | ||
- | | ||
- | // scan the command line arguments | ||
- | for (int i=0; i< | ||
- | if ( args[i].equals(" | ||
- | i++; | ||
- | try { | ||
- | if (i> | ||
- | devNum = Integer.parseInt( args[i] ); | ||
- | } | ||
- | catch (Exception e) { | ||
- | throw new ParameterException(" | ||
- | } | ||
- | } | ||
- | else if ( args[i].equals(" | ||
- | force = true; | ||
- | } | ||
- | else if ( args[i].equals(" | ||
- | bus.printBus(System.out); | ||
- | System.exit(0); | ||
- | } | ||
- | else if ( args[i].equals(" | ||
- | System.err.println(ParameterException.helpMsg); | ||
- | System.exit(0); | ||
- | } | ||
- | else throw new ParameterException(" | ||
- | } | ||
- | | ||
- | |||
- | // create the main class | ||
- | UCEcho ztex = new UCEcho ( bus.device(devNum) ); | ||
- | | ||
- | // upload the firmware if necessary | ||
- | if ( force || ! ztex.valid() || ! ztex.dev().productString().equals(" | ||
- | ztex.uploadFirmware( " | ||
- | } | ||
- | | ||
- | // upload the bitstream if necessary | ||
- | if ( force || ! ztex.getFpgaConfiguration() ) { | ||
- | System.out.println(" | ||
- | } | ||
- | |||
- | |||
- | // claim interface 0 | ||
- | ztex.claimInterface(); | ||
- | | ||
- | // read string from stdin and write it to USB device | ||
- | String str = ""; | ||
- | BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) ); | ||
- | while ( ! str.equals(" | ||
- | System.out.print(" | ||
- | str = reader.readLine(); | ||
- | ztex.echo(str); | ||
- | System.out.println("" | ||
- | } | ||
- | | ||
- | // release interface 0 | ||
- | ztex.releaseInterface(); | ||
- | | ||
- | } | ||
- | catch (Exception e) { | ||
- | System.out.println(" | ||
- | } | ||
- | | ||
- | |||
- | } | ||
- | </ | ||
- | |||
- | ====== C host software: UCEcho.c ====== | ||
- | |||
- | It is also possible to access the device with other programming languages. In this case the firmware must be loaded using the FWLoader utility included in the SDK. | ||
- | |||
- | The C source code of the host software is: | ||
- | |||
- | <code c> | ||
- | /*! | ||
- | | ||
- | | ||
- | | ||
- | |||
- | This program is free software; you can redistribute it and/or modify | ||
- | it under the terms of the GNU General Public License version 3 as | ||
- | | ||
- | |||
- | This program is distributed in the hope that it will be useful, but | ||
- | | ||
- | | ||
- | | ||
- | |||
- | You should have received a copy of the GNU General Public License | ||
- | along with this program; if not, see http:// | ||
- | !*/ | ||
- | #include < | ||
- | #include < | ||
- | #include < | ||
- | #include < | ||
- | |||
- | #define BUFSIZE | ||
- | |||
- | struct usb_device *device; | ||
- | usb_dev_handle *handle; | ||
- | char buf[BUFSIZE]; | ||
- | |||
- | // find the first ucecho device | ||
- | struct usb_device *find_device () | ||
- | { | ||
- | struct usb_bus *bus_search; | ||
- | struct usb_device *device_search; | ||
- | |||
- | bus_search = usb_busses; | ||
- | while (bus_search != NULL) | ||
- | { | ||
- | device_search = bus_search-> | ||
- | while (device_search != NULL) | ||
- | { | ||
- | if ( (device_search-> | ||
- | { | ||
- | handle = usb_open(device_search); | ||
- | usb_get_string_simple(handle, | ||
- | if ( ! strncmp(" | ||
- | return device_search; | ||
- | usb_close(handle); | ||
- | } | ||
- | device_search = device_search-> | ||
- | } | ||
- | bus_search = bus_search-> | ||
- | } | ||
- | | ||
- | return NULL; | ||
- | } | ||
- | |||
- | // main | ||
- | int main(int argc, char *argv[]) | ||
- | { | ||
- | usb_init(); | ||
- | usb_find_busses(); | ||
- | usb_find_devices(); | ||
- | |||
- | device = find_device(); | ||
- | |||
- | if ( device == NULL ) { // nothing found | ||
- | fprintf(stderr, | ||
- | return 1; | ||
- | } | ||
- | |||
- | if (usb_claim_interface(handle, | ||
- | fprintf(stderr, | ||
- | return 1; | ||
- | } | ||
- | | ||
- | while ( strcmp(" | ||
- | // read string from stdin | ||
- | printf(" | ||
- | scanf(" | ||
- | |||
- | // write string to ucecho device | ||
- | int i = usb_bulk_write(handle, | ||
- | if ( i < 0 ) { | ||
- | fprintf(stderr, | ||
- | return 1; | ||
- | } | ||
- | printf(" | ||
- | |||
- | // read string back from ucecho device | ||
- | i = usb_bulk_read(handle, | ||
- | if ( i < 0 ) { | ||
- | fprintf(stderr, | ||
- | return 1; | ||
- | } | ||
- | printf(" | ||
- | |||
- | } | ||
- | |||
- | usb_release_interface(handle, | ||
- | usb_close(handle); | ||
- | return 0; | ||
- | } | ||
- | </ | ||
- | |||
- | |||
- | ====== Python host software: UCEcho.py ====== | ||
- | |||
- | It is also possible to access the device with other programming languages. In this case the firmware must be loaded using the FWLoader utility included in the SDK. For testing you can run UCEcho.jar first and then run this file. For Python be sure to install [[http:// | ||
- | |||
- | The Python source code of the host software is: | ||
- | |||
- | <code python> | ||
- | # | ||
- | # | ||
- | # Based on work from http:// | ||
- | # | ||
- | # This program is free software; you can redistribute it and/or modify | ||
- | # it under the terms of the GNU General Public License version 3 as | ||
- | # | ||
- | # | ||
- | # This program is distributed in the hope that it will be useful, but | ||
- | # | ||
- | # | ||
- | # | ||
- | # | ||
- | # You should have received a copy of the GNU General Public License | ||
- | # along with this program; if not, see http:// | ||
- | # | ||
- | import sys | ||
- | try: | ||
- | import usb | ||
- | except: | ||
- | print "usb import failed. Install pyusb from http:// | ||
- | sys.exit() | ||
- | | ||
- | |||
- | if __name__ == ' | ||
- | |||
- | #Find Device | ||
- | dev = usb.core.find(idVendor=0x221A, | ||
- | |||
- | if dev is None: | ||
- | print " | ||
- | print " You should run UCEcho.jar first, and then without unplugging" | ||
- | print " USB module run this program to ensure all devices are fully" | ||
- | print " programmed." | ||
- | | ||
- | sys.exit() | ||
- | |||
- | # set the active configuration. With no arguments, the first | ||
- | # configuration will be the active one | ||
- | dev.set_configuration() | ||
- | |||
- | #You can find these from the descriptors - see pyusb doc for an | ||
- | #example of this. I'm simplifying this because I know exact | ||
- | #interface & endpoint addresses | ||
- | writeEP = 0x04 | ||
- | readEP = 0x82 | ||
- | interface = 0 | ||
- | |||
- | resp = " | ||
- | |||
- | while resp != " | ||
- | resp = raw_input(" | ||
- | dev.write(writeEP, | ||
- | print "Send %d bytes: `%s'" | ||
- | ret = dev.read(readEP, | ||
- | retstr = '' | ||
- | print "Read %d bytes: `%s'" | ||
- | </ | ||
- | |||
- | ====== Example call ====== | ||
- | |||
- | It follows an example call with output: | ||
- | < | ||
- | stefan@ws2:/ | ||
- | FPGA configuration time: 1353 ms | ||
- | Enter a string or `quit' to exit the program: Hello world! | ||
- | Send 12 bytes: `Hello world!' | ||
- | Read 12 bytes: `HELLO WORLD!' | ||
- | |||
- | Enter a string or `quit' to exit the program: quit | ||
- | Send 4 bytes: `quit' | ||
- | Read 4 bytes: `QUIT' | ||
- | </ |