Contribution: A simple example of MPUSBAPI with FreeBasic

For issues with communication ports, protocols, etc.
Oceano
Posts: 43
Joined: Jun 05, 2009 20:37
Contact:

Contribution: A simple example of MPUSBAPI with FreeBasic

Postby Oceano » Jun 12, 2010 0:08

First of all, I want to thank *** MichaelW *** of this forum, without him I would have been impossible to implement MPUSBAPI.DLL in FreeBasic.

I also thank for their contributions to CCS and configurations:

* J1M ( http://hobbypic.com/ )

* Pedro ( http://www.unpocodelectronica.netau.net ... el-18f4550 )

* RedRaven ( http://picmania.garcia-cuervo.net/usb_1 ... nsfers.php )

* MigSantiago ( http://www.migsantiago.com )

* Slalen ( http://slalen.ifastnet.com/ )

-----------

The program is a very simple example of "Bulk Transfer", using the library MPUSBAPI.DLL.

1) We send to the PIC two numbers.
2) The PIC add the two numbers and sends the result to PC.

Note: Although declare 64 bytes to send and receive, we will only use two to send and one to receive.

FreeBasic code:

Code: Select all



#Inclib "mpusbapi"

#Include Once "windows.bi"

Extern "C"

   Declare Function MPUSBGetDLLVersion Alias "_MPUSBGetDLLVersion" () As Integer
   
   Declare Function MPUSBGetDeviceCount Alias "_MPUSBGetDeviceCount" _
                     (ByVal pVid_Pid As ZString Ptr) As Integer
                    
   Declare Function MPUSBOpen Alias "_MPUSBOpen" _
                     (ByVal instance As Integer, _
                      ByVal pVid_Pid As ZString Ptr, _
                      ByVal pEP As ZString Ptr, _
                      ByVal dwDir As Integer, _
                      ByVal dwReserved As Integer) As Integer
                      
   Declare Function MPUSBRead Alias "_MPUSBRead" _
                     (ByVal handle As Integer, _
                      ByVal pData As Byte Ptr, _
                      ByVal dwLen As Integer, _
                      ByRef pLength As Integer Ptr, _
                      ByVal dwMilliseconds As Integer) As Integer
                      
   Declare Function MPUSBWrite Alias "_MPUSBWrite" _
                     (ByVal handle As Integer, _
                      ByVal pData As Byte Ptr, _
                      ByVal dwLen As Integer, _
                      ByRef pLength As Integer Ptr, _
                      ByVal dwMilliseconds As Integer) As Integer
                      
   Declare Function MPUSBReadInt Alias "_MPUSBReadInt" _
                     (ByVal handle As Integer, _
                      ByVal pData As Byte Ptr, _
                      ByVal dwLen As Integer, _
                      ByRef pLength As Integer Ptr, _
                      ByVal dwMilliseconds As Integer) As Integer
                      
   Declare Function MPUSBClose Alias "_MPUSBClose" _
                     (ByVal handle As Integer) As Integer
                 
End Extern

Const MP_WRITE = 0
Const MP_READ  = 1

Const OutPipe  = "\MCHP_EP1"
Const InpPipe  = "\MCHP_EP1"

Dim As  Integer Version
Dim As  Integer MyInpPipe
Dim As  Integer MyOutPipe
Dim As  Integer SentDataLength
Dim As  Integer RecdDataLendth
Dim As  Integer DevCount

Dim As UByte    Put2PIC( 0 To 63 )
Dim As UByte    Get2Pic( 0 To 63 )

Dim Vid_Pid As String = "vid_04d8&pid_0011"

DevCount = MPUSBGetDeviceCount( StrPtr( Vid_Pid ) )
Print "Device Counts : "; DevCount

Version = MPUSBGetDLLVersion()
Print "MPUSBAPI.DLL Version : "; Hex( Version )

MyOutPipe = INVALID_HANDLE_VALUE
MyInpPipe = INVALID_HANDLE_VALUE

MyOutPipe = MPUSBOpen( 0, Vid_Pid, OutPipe, MP_WRITE, 0 )
MyInpPipe = MPUSBOpen( 0, Vid_Pid, InpPipe, MP_READ,  0 )

Print "Out Pipe : "; Hex(MyOutPipe)
Print "Inp Pipe : "; Hex(MyInpPipe)

If ( MyOutPipe = INVALID_HANDLE_VALUE ) Or _
   ( MyInpPipe =  INVALID_HANDLE_VALUE ) Then
   Print "Pipers Error!"
   MPUSBClose ( MyInpPipe )
        MPUSBClose ( MyOutPipe )
   Sleep
   End
EndIf

Print
Print "Add of two numbers, the result not must be greater than 255."
Print
Input "ADD1 (Example: 0..127)"; Put2PIC(0)
Input "ADD2 (Example: 0..127)"; Put2Pic(1)


MPUSBWrite(myOutPipe, @Put2PIC(0), 2, @SentDataLength, 1000)
MPUSBRead (myInpPipe, @Get2PIC(0), 1, @RecdDataLendth, 1000)

Print "The PIC's Artificial Intelligence results: "; Get2PIC(0)

MPUSBClose ( MyInpPipe )
MPUSBClose ( MyOutPipe )

Sleep

End



Important:

* The contents of the variable Vid_Pid = "vid_04d8&pid_0011" must be all lowercase. If you put a single letter in uppercase will not work.

* "\MCHP_EP1" notes that only one '\', as in VisualBasic. In C++ and Delphi are two '\\'.

CCS code:

Code: Select all


#include <18F4550.h>

#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)

#define USB_HID_DEVICE     FALSE             //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE  USB_ENABLE_BULK   //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE    1                 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE    2                 //size to allocate for the rx endpoint 1 buffer

#include <pic18_usb.h>      //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include "usb_desc_scope.h" //Enumerator Palitroquez!
#include <usb.c>            //handles usb setup tokens and get descriptor reports

#use fast_io(b) //you have to manually configure TRISB

void main(void) {

   int8 recibe[2];
   int8 envia[1];
   
   set_tris_b(0x00); //All PortB outputs
   output_b(0x00);   // PortB off
   
   setup_adc (adc_clock_div_32); //No ADC, no comparators...
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   port_b_pullups(FALSE);
   
   usb_init();  //init USB
   usb_task();  //enable usb device and interruptions
   usb_wait_for_enumeration();  //wait
   
   output_high(PIN_B7);  // the PortB.7 LED blink 3 times.
   delay_ms(500);
   output_low(PIN_B7);
   delay_ms(500);
   output_high(PIN_B7);
   delay_ms(500);
   output_low(PIN_B7);
   delay_ms(500);
   output_high(PIN_B7);
   delay_ms(500);
   output_low(PIN_B7);
   delay_ms(500);
   
   while (true)
   {
      if(usb_enumerated())  //if PicUSB is configurated
      {
         if (usb_kbhit(1))  //if it contains data
         {
            usb_get_packet(1, recibe, 2); //Take two bytes, which will
               //then be recibe[0] and recibe[1]
           
            envia[0]=recibe[0]+recibe[1]; //add the two received data
           
            output_b(envia[0]); //the result will be seen by PortB (with 8 LED)
           
            usb_put_packet(1, envia, 1, USB_DTS_TOGGLE); //moreover,
                                                                                   //sends the result to PC.

         }
      }
   }
}



You can change the PIC at:
# Include <18F4550.h>
by (for example):
# Include <18F2550.h>
While respecting the type 18Fxx5x. I tested it and works just as well.

Note:
The fuses are set for a 20 MHz crystal. If you want to put a 4 MHz crystal you have to change line #fuses... by:

Code: Select all

#fuses XTPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN


Only when the crystal is less or equal to 4MHz changed HSPLL by XTPLL.

PLLx changes depending of Xtal:
PLL1 = 4MHz
PLL2 = 8MHz
PLL3 = 12MHz
PLL4 = 16MHz
PLL5 = 20MHz

The PIC program calls a library called "usb_desc_scope.h." This file is required in the compilation. Copy and paste this code and you put that name to the file. This file must be in conjunction with the CCS source. You'll see that you can change data inside to personalize it.

Code: Select all


///////////////////////////////////////////////////////////////////////////
////                         usb_desc_scope.h                          ////
////                                                                   ////
//// An example set of device / configuration descriptors for use with ////
//// the USB Bulk demo (see ex_usb_scope.c)                            ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////                                                                   ////
//// Version History:                                                  ////
////                                                                   ////
//// July 13th, 2005:                                                  ////
////   Endpoint descriptor works if USB_EP1_TX_SIZE is 16bits          ////
////   Endpoint descriptor works if USB_EP1_RX_SIZE is 16bits          ////
////                                                                   ////
//// June 20th, 2005:                                                  ////
////   18fxx5x Initial release.                                        ////
////                                                                   ////
//// March 21st, 2005:                                                 ////
////   EP 0x01 and EP 0x81 now use USB_EP1_TX_SIZE and USB_EP1_RX_SIZE ////
////      to define max packet size, to make it easier for dynamically ////
////      changed code.                                                ////
////                                                                   ////
//// June 24th, 2002: Cleanup                                          ////
////                                                                   ////
//// May 6th, 2003: Fixed non-HID descriptors pointing to faulty       ////
////                strings                                            ////
////                                                                   ////
//// August 2nd, 2002: Initial Public Release                          ////
////                                                                   ////
////                                                                   ////
///////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services           ////
//// This source code may only be used by licensed users of the CCS    ////
//// C compiler.  This source code may only be distributed to other    ////
//// licensed users of the CCS C compiler.  No other use,              ////
//// reproduction or distribution is permitted without written         ////
//// permission.  Derivative programs created using this software      ////
//// in object code form are not restricted in any way.                ////
///////////////////////////////////////////////////////////////////////////

#IFNDEF __USB_DESCRIPTORS__
#DEFINE __USB_DESCRIPTORS__

#include <usb.h>

//////////////////////////////////////////////////////////////////
///
///   start config descriptor
///   right now we only support one configuration descriptor.
///   the config, interface, class, and endpoint goes into this array.
///
//////////////////////////////////////////////////////////////////

   #DEFINE USB_TOTAL_CONFIG_LEN      32 //config+interface+class+endpoint

   //configuration descriptor
   char const USB_CONFIG_DESC[] = {
   //config_descriptor for config index 1
         USB_DESC_CONFIG_LEN,     //length of descriptor size
         USB_DESC_CONFIG_TYPE,         //constant CONFIGURATION (0x02)
         USB_TOTAL_CONFIG_LEN,0,  //size of all data returned for this config
         1,      //number of interfaces this device supports
         0x01,                //identifier for this configuration.  (IF we had more than one configurations)
         0x00,                //index of string descriptor for this configuration
         0xC0,                //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 reserved and bit7=1
         0x32,                //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA)

   //interface descriptor 0 alt 0
         USB_DESC_INTERFACE_LEN,  //length of descriptor
         USB_DESC_INTERFACE_TYPE,      //constant INTERFACE (0x04)
         0x00,                //number defining this interface (IF we had more than one interface)
         0x00,                //alternate setting
         2,       //number of endpoints, not counting endpoint 0.
         0xFF,                //class code, FF = vendor defined
         0xFF,                //subclass code, FF = vendor
         0xFF,                //protocol code, FF = vendor
         0x00,                //index of string descriptor for interface

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor
         USB_DESC_ENDPOINT_TYPE,     //constant ENDPOINT (0x05)
         0x81,              //endpoint number and direction (0x81 = EP1 IN)
         0x02,              //transfer type supported (0 is control, 1 is iso, 2 is bulk, 3 is interrupt)
         USB_EP1_TX_SIZE & 0xFF,USB_EP1_TX_SIZE >> 8,         //maximum packet size supported
         0x01,              //polling interval in ms. (for interrupt transfers ONLY)

   //endpoint descriptor
         USB_DESC_ENDPOINT_LEN, //length of descriptor
         USB_DESC_ENDPOINT_TYPE,     //constant ENDPOINT (0x05)
         0x01,              //endpoint number and direction (0x01 = EP1 OUT)
         0x02,              //transfer type supported (0 is control, 1 is iso, 2 is bulk, 3 is interrupt)
         USB_EP1_RX_SIZE & 0xFF,USB_EP1_RX_SIZE >> 8,         //maximum packet size supported
         0x01,              //polling interval in ms. (for interrupt transfers ONLY)

  };

   //****** BEGIN CONFIG DESCRIPTOR LOOKUP TABLES ********
   //since we can't make pointers to constants in certain pic16s, this is an offset table to find
   //  a specific descriptor in the above table.

   //NOTE: DO TO A LIMITATION OF THE CCS CODE, ALL HID INTERFACES MUST START AT 0 AND BE SEQUENTIAL
   //      FOR EXAMPLE, IF YOU HAVE 2 HID INTERFACES THEY MUST BE INTERFACE 0 AND INTERFACE 1
   #define USB_NUM_HID_INTERFACES   0

   //the maximum number of interfaces seen on any config
   //for example, if config 1 has 1 interface and config 2 has 2 interfaces you must define this as 2
   #define USB_MAX_NUM_INTERFACES   1

   //define how many interfaces there are per config.  [0] is the first config, etc.
   const char USB_NUM_INTERFACES[USB_NUM_CONFIGURATIONS]={1};

   #if (sizeof(USB_CONFIG_DESC) != USB_TOTAL_CONFIG_LEN)
      #error USB_TOTAL_CONFIG_LEN not defined correctly
   #endif


//////////////////////////////////////////////////////////////////
///
///   start device descriptors
///
//////////////////////////////////////////////////////////////////

   //device descriptor
   char const USB_DEVICE_DESC[] ={
         USB_DESC_DEVICE_LEN,          //the length of this report
         0x01,                //constant DEVICE (0x01)
         0x10,0x01,           //usb version in bcd
         0x00,                //class code (if 0, interface defines class.  FF is vendor defined)
         0x00,                //subclass code
         0x00,                //protocol code
         USB_MAX_EP0_PACKET_LENGTH,   //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8)
         0xD8,0x04,           //vendor id (0x04D8 is Microchip)
         0x11,0x00,           //product id
         0x00,0x01,           //device release number
         0x01,                //index of string description of manufacturer. therefore we point to string_1 array (see below)
         0x02,                //index of string descriptor of the product
         0x00,                //index of string descriptor of serial number
         USB_NUM_CONFIGURATIONS   //number of possible configurations
   };


//////////////////////////////////////////////////////////////////
///
///   start string descriptors
///   String 0 is a special language string, and must be defined.  People in U.S.A. can leave this alone.
///
///   You must define the length else get_next_string_character() will not see the string
///   Current code only supports 10 strings (0 thru 9)
///
//////////////////////////////////////////////////////////////////

//the offset of the starting location of each string.
//offset[0] is the start of string 0, offset[1] is the start of string 1, etc.
const char USB_STRING_DESC_OFFSET[]={0,4,12};

#define USB_STRING_DESC_COUNT sizeof(USB_STRING_DESC_OFFSET)

char const USB_STRING_DESC[]={
   //string 0
         4, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         0x09,0x04,   //Microsoft Defined for US-English
   //string 1
         8, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'C',0,
         'C',0,
         'S',0,
   //string 2
         32, //length of string index
         USB_DESC_STRING_TYPE, //descriptor type 0x03 (STRING)
         'F',0,
         'R',0,
         'E',0,
         'E',0,
         'B',0,
         'A',0,
         'S',0,
         'I',0,
         'C',0,
         ' ',0,
         'U',0,
         'S',0,
         'B',0,
         '!',0,
         '!',0,

};


#ENDIF



In "usb_desc_scope.h" is the Vid_Pid for the PIC. It's very important that if you change this data you have to do also in FreeBasic source.

Click on the link and you can download the entire project.

https://sites.google.com/site/roboticproyects/picusb

There is also installing drivers asking you when you connect the PICUSB to PC.

To compile the source code FreeBasic, you also need the file "libmpusbapi.dll.a" for FreeBasic. You can do it yourself (on the thirteenth post: http://www.freebasic.net/forum/viewtopic.php?t=15698 ),
or download it in the link I put slightly higher.

So far I've only tested on WinXP and Colossus Edition 2 Reloaded.

Thank you.
towlerg
Posts: 2
Joined: Oct 26, 2012 21:15

Re: Contribution: A simple example of MPUSBAPI with FreeBasi

Postby towlerg » Oct 26, 2012 21:43

Hi

I'm new to this board, so I wouldn't usually start off by looking for help but here I am.

I was googleing around looking for a simple implementation of mpusbapi.dll that didn't involve a 25 file Visual Studio project, something simple for a simple soul. And this looked almost perfect but if I either breadboard the hardware of simulate it with Proteus I can not load the device drivers. I get an Unknown device (with a Vid and a Pid of 0000) in the Other devices section of Device Manager.
If I try to upgrade driver software for that entry it fails ('cause of course the Vid and Pid don't match).

I guess I'm doing something dim, but I can't figure out what it is.

I used the files from https://sites.google.com/site/roboticproyects/picusb. Any suggestion gratefully accepted.

Rgds George
Oceano
Posts: 43
Joined: Jun 05, 2009 20:37
Contact:

Re: Contribution: A simple example of MPUSBAPI with FreeBasi

Postby Oceano » Oct 27, 2012 0:48

Look at this example, but it's in Spanish. Two numbers is sent to the PIC, and the PIC performs addition and returned to the PC:

https://sites.google.com/site/proyectos ... k-Transfer

You can translate with google translator.

Note: Windows 7 gives an error if the library "MPUSBAPI.DLL" is ancient. On the Web, I have set before you can download the updated driver: Version 6.

Regards!
towlerg
Posts: 2
Joined: Oct 26, 2012 21:15

Re: Contribution: A simple example of MPUSBAPI with FreeBasi

Postby towlerg » Oct 27, 2012 13:46

Hi Oceano,

thanks for responding so quickly, I will look at the example you give.

Could you confirm that the object files from the download https://sites.google.com/site/roboticproyects/picusb are correctly compiled with the correct Vid/Pid, specifically "CCS_BULKtranfer.hex"? I don't know CCS but I'll try to recompile the hex file, although I guess that'll take a while.

Do you know of any other source for the compiled file "CCS_BULKtranfer.hex", for comparison?


Thanks once again for your help.

Rgds George
Oceano
Posts: 43
Joined: Jun 05, 2009 20:37
Contact:

Re: Contribution: A simple example of MPUSBAPI with FreeBasi

Postby Oceano » Oct 27, 2012 22:40

Hi George,

I only know CCS C to compile. It is for the PIC 18F4550 with a 20MHz crystal. The main program calls a library that is named "usb_desc_scope.h", and that is where it has the VID & PID. You can see in this library as follows:

Code: Select all

//device descriptor
   char const USB_DEVICE_DESC[] ={
         USB_DESC_DEVICE_LEN,          //the length of this report
         0x01,                //constant DEVICE (0x01)
         0x10,0x01,           //usb version in bcd
         0x00,                //class code (if 0, interface defines class.  FF is vendor defined)
         0x00,                //subclass code
         0x00,                //protocol code
         USB_MAX_EP0_PACKET_LENGTH,   //max packet size for endpoint 0. (SLOW SPEED SPECIFIES 8)
         0xD8,0x04,           //vendor id (0x04D8 is Microchip)
         0x11,0x00,           //product id
         0x00,0x01,           //device release number
         0x01,                //index of string description of manufacturer. therefore we point to string_1 array (see below)
         0x02,                //index of string descriptor of the product
         0x00,                //index of string descriptor of serial number
         USB_NUM_CONFIGURATIONS   //number of possible configurations
   };


Notice the part that says:

Code: Select all

  0xd8, 0x04, / / vendor id (0x04D8 is Microchip)
  0x11, 0x00, / / product id


Therefore, the PIC has the VID=04D8 & PID=0011.

There is a file within the drivers that is named "mchpusb.inf" and you can see that a part of it says:

Code: Select all

[DeviceList]
% DESCRIPTION% = DriverInstall, USB \ VID_04D8 & PID_0011
 
[DeviceList.ntamd64]
% DESCRIPTION% = DriverInstall64, USB \ VID_04D8 & PID_0011


Then in FreeBasic program, it specify:

Code: Select all

Vid_Pid Dim As String = "vid_04d8 & pid_0011"   '(You have to write it in lowercase for FreeBASIC.)


So the VID & PID HEX program, driver and FreeBasic program are the same and that is right.

I can only help with CCS C, I do not know other languages ​​to program PICs with USB. If you need to modify any part of the program, such as putting another crystal (4, 8, 12, 16 or 20MHz), or use another PIC of Microchip® (18Fxx5x), I'll be happy to do so.

The HEX is only valid for the PIC 18F4550, and a 20MHz crystal.

The version of the library for FreeBASIC "mpusbapi.dll" I put to download the 6.0 therefore work well in Windows 7 (I've tried) and I guess (I have not tried it) that in Vista also.


Greetings.

Return to “Hardware Interfaces / Communication”

Who is online

Users browsing this forum: No registered users and 2 guests