CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

18F4550 PICUSB interface to Microchip mpusbapi.dll Delphi Ex

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

18F4550 PICUSB interface to Microchip mpusbapi.dll Delphi Ex
PostPosted: Wed Aug 16, 2006 8:50 am     Reply with quote

English is the langua franca of this board so here is an english version.

Gracias a JIM for the original code posting in Spanish. This code is similar but different in some details.

Info:
a) This example is for Bulk transfer and is Bus powered

b) The PC delphi code example interfaces with mpusbapi.dll

c) After enumeration the device manager will show PIC 18XX5X USB Devices sub cat PicUSB
The PIC 18XX5X USB Devices is only visible in the device manager when enumerated correctly. Incorrect enumeration may result in a caution flag device not working or will display nothing ( a.k.a. a Microsoft politically correct multilanguage error message that's equally useful for the deaf dumb and blind).

d) Works with Win2000 should work with WinXP

e) vid is $04D8 and pid is $0011
these numbers are correlated with the data in the drivers install
file picusb.inf
This file has dependency files mchpusb.sys picusbci.dll picusb.cat
wdmstub.sys
Note:
If you can't find Jim's files go to
www.microchip.com and search for PICDEM Full Speed USB
and download MCHPFSUSB_Setup.exe run it and it will install the files
that are needed
Be aware
The files aren't the same as JIM used ( ex doesn't use picusbci.dll)
it uses mchpusb.inf for its install
Follow the instructions to alter the inf file for the PID 0011 if you you
use the code below or alternatively alter the PID in the pic
code descriptor
TB095 shows the install instructions and screen shots for the MCHPusb.sys driver If you use mchpfsusb then mchpusb.inf and not picusb.inf is the install file you'll be using


f) The file picusb.inf is used at install time ( done first time only) and results in the registration
HKey_LOCAL_MACHINE> SYSTEM>ControlSet001>Enum>USB
the external usb device (PIC18F4550) when enumerated will bind to
these Win 2000/XP drivers

g) The connections to the PIC are D- pin 23 Cable wire is white
D+ pin 24 Cable wire is Green
_____________
|XXXXXXXXXXX|
| |
| 1 2 3 4 |
|____________ |
5v D- D+ 0v

h) No need for external pullups on either D- or D+ ...PIC code
handles it

i)
Code:


#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV2,VREGEN


// 20 mhz external crystal is pre scalled by div 5 (PLL5) to 4mhz
// PLL multiplies by 16 to 96Mhz USBDIV post scales with div by 2 to 48MHZ
// CPU clock is post scaled with
//                              CPUDIV1 by with div by 2 for 48 MHZ
//                              CPUDIV2 by with div by 3 for 32 MHZ
//
//   Notes: working Aug6 2006
///  1) PIC is powered from the usb port
//   2) if the PIC is removed without first being logically detached it will  occasionally hang the port
//      requiring a PC reboot to clear it
//   3) When running the debugger the ICDU40 can become desynched with the 18F4550
//      Pressing the reset button on the PIC board before pressing go in the debugger
//      will resysnc ( symptoms of desync are garbled printing in the monitor window
//      garbage values of variables in the debugger .. the pic will appear to enumerate
//      but all subsequent transfers are ruined.
//      ICDU40 will show clock as 47.41 MHZ and is unstable if CPUDIV1 is used
//                      CPUDIV2 is used to give 32MHZ MCU clock
//                      to avoid 48MHZ CCS debugger issues above
//                      ( Note USB clock is set by USBDIV an is at 48MHZ)
///
///  4)  The PC interfaces in delphi via mpusbapi.dll
///     device manager will show after enumeration PIC18XX device
///                                                sub cat PICUSB
///  5)   this was installed via inf and sys files from microchip
//        vid is $04D8  and pid is $0011
//        these numbers are correlated with the data in the drivers install
//        file picusb.inf
//        this file has dependency files  mchpusb.sys  picusbci.dll picusb.cat
//        wdmstub.sys
//        the file picusb.inf is used at install time and results in the registration
//        HKey_LOCAL_MACHINE> SYSTEM>ControlSet001>Enum>USB
//        the external usb device (PIC18F4550) when enumerated will bind to these
//        Win 2000/XP drivers
//   6)   Changes to CCS config descriptor (PICUSB.h )to reflect bus powered
//         0xC0,  //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 reserved and bit7=1
//         0x80,                  //bit 6=1 if self powered, bit 5=1 if supports remote wakeup (we don't), bits 0-4 reserved and bit7=1
//         0x64,                //maximum bus power required (maximum milliamperes/2)  (0x32 = 100mA 0x64 =200ma)
//
//         Changes to device descriptor     
//         0xD8,0x04,           //vendor id Vid (0x04D8 is Microchip)
//         0x11,0x00,           //product id Pid (0x0011)
//         correlates with picusb.inf
//   7)    example PC calls in this case Delphi
//         function _MPUSBGetDLLVersion:DWORD; stdcall;external 'mpusbapi.dll';
//         function _MPUSBGetDeviceCount(pVID_PID:PCHAR8):DWORD; stdcall;external 'mpusbapi.dll';
//         function _MPUSBOpen(instance:DWORD;pVID_PID:PCHAR8;pEP:PCHAR8;dwDir:DWORD;dwReserved:DWORD):THANDLE; stdcall;external 'mpusbapi.dll';
//         function _MPUSBRead(handle:THANDLE;var pData:PBYTE;dwLen:DWORD;var pLength:DWORD;dwMilliseconds:DWORD):DWORD; stdcall;external 'mpusbapi.dll';
//         function _MPUSBReadInt(handle:THANDLE;var pData:PBYTE;dwLen:DWORD;var pLength:PDWORD;dwMilliseconds:DWORD):DWORD; stdcall;external 'mpusbapi.dll';
//         function _MPUSBWrite(handle:THANDLE;pData:PBYTE;dwLen:DWORD;var pLength:DWORD;dwMilliseconds:DWORD):DWORD; stdcall;external 'mpusbapi.dll';
//         function _MPUSBClose(handle:THANDLE):DWORD; stdcall;external 'mpusbapi.dll';
//         vid_pid:PCHAR8='vid_04d8&pid_0011';  // VID and PID for Demo USB FS board
//         out_pipe:PCHAR8='\MCHP_EP1';
//         in_pipe:PCHAR8='\MCHP_EP1';
///          example of a PC call to turn on a led in th ePIC code below
/*
 procedure led_control(mode:byte;red_green:byte;on_off:byte);
var
   selection:DWORD;
   send_buf:PBYTE;
   receive_buf:PBYTE;
   RecvLength:DWORD;
   SentLength:DWORD;
  label quit,finish;
begin
selection:=0; // USB device that have PID & VID as we configed.
  myOutPipe:= _MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0);
  myInPipe:= _MPUSBOpen(selection,vid_pid,in_pipe,MP_READ,0);

  if ((myOutPipe = INVALID_HANDLE_VALUE) or (myInPipe = INVALID_HANDLE_VALUE)) then
  begin
   Form1.Edit1.text:='Status : USB Error';
   exit;
  end;
 send_buf[0]:=mode;    // ledmode command
  send_buf[1]:=red_green;   // red led
  send_buf[2]:=on_off;   // 0=off
  RecvLength:=1;

 //  if  write or read are successfull they return a handle ( non zero)
  if(_MPUSBWrite(myOutPipe,send_buf,3,SentLength,1000)=0) then  goto quit;

  if( _MPUSBRead(myInPipe,receive_buf,1,RecvLength,1000)=0) then goto quit;

   if (receive_buf[0] <>  $55 )  then  goto quit;


  goto finish;
 quit:
 form1.Edit1.Text:='Status : LED Communication Error!';

 finish:
  _MPUSBClose(myOutPipe);
  _MPUSBClose(myInPipe);
  myInPipe:= INVALID_HANDLE_VALUE;
  myOutPipe:=INVALID_HANDLE_VALUE;
end;
*/
////////////////////////////////// end of notes ///////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////////
//
//  on power connection RED LED flashes a heart beat when running
//  green led is off until PIC is enumerated
//  green led flashes when data is received
//  yellow led flashes on a detach command
//  PC delphi code controls red/green/yellow tristate led
//              until a detach is made by delphi or a manual PIC button press
//              after receipt of detach command yellow is flashed
//

#device ADC=10             /// select 10 bit value

/// special macros /////////////////////////////////////////////
/// #x id the litteral value of the variable x
/// suppose x is variable reboot then #x is the litteral "reboot"
#define debugnbr(x)   printf("%s is %d\r\n",#x,x);
#define debughex(x)   printf("%s is %X\r\n",#x,x);


#use delay(clock=32000000)
#define TRACE false
#define TRACE_HOST_REQ false
    #use rs232(debugger)

  //  #USE RS232(STREAM=SIO,BAUD=9600,XMIT=PIN_C6,RCV=PIN_C7) /* xmit pin c6 rcv c7 */

/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines.  For dynamic configuration of the CCS Library
// for your application several defines need to be made.  See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#define USB_HID_DEVICE     FALSE             //disable  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    64                 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE    64                 //size to allocate for the rx endpoint 1 buffer


/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here.  If you are
// not using connection sense, comment out this line.  Without connection
// sense you will not know if the device gets disconnected.
//       (connection sense should look like this:
//                             100k
//        5V    VBUS-----+----/\/\/\/\/\----- (USB_CON_SENSE_PIN ON PIC PIN_B5)
//                     |
//                     +----/\/\/\/\/\-----GND
//                             100k
//        (where VBUS is pin1 of the USB connector)
//
//        USB power rail breaks connection after D- D+
/////////////////////////////////////////////////////////////////////////////
#define USB_CON_SENSE_PIN PIN_B5  // wired as above

//////////////////////////////////////////////
///
///     5v  ----/\/\/\--+--__\__---- GND
///              100k   | NO switch
///                     |
///     B4 -------------
/////////////////////////////////////////////
#define MY_USB_DETACH_PIN PIN_B4
///// ADDITIONAL DEVICE PIN ASSIGNMENTS
#define ENUM_LED    PIN_B0   /// green led for enumerated
                             /// flashes when data received
#define red_led PIN_B1
#define green_led PIN_B2
#define POWER_LED PIN_C0    /// flashes when not connected
/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries.  See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
/// without USB_USE_FULL_SPEED explicitly defined as FALSE (slow speed ) PIC defaults to high speed

#include <pic18_usb.h>     //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <PicUSB.h>         //descriptors
/// Notes changes were made to the decriptors
/// see above note 6     
#include <usb.c>           //handles usb setup tokens and get descriptor reports


/////   constant defines
#define LINK_CMD 0
#define LED_CMD  1
#define ADC_CMD  2
#define DETACH_CMD 3
#define LED_ON  output_high
#define LED_OFF output_low

#define mode      received[0]
#define param1    received[1]
#define param2    received[2]
#define result    sent[0]
#define ack_connection 0x25
#define ack_led_cmd    0x55
#define ack_pot_cmd    0x65
#define BULK_SIZE 512
#define STOP_FLASHING 0
#define FOREVER 99
#define ALWAYS_OFF 98
#define ALWAYS_ON  97

/////////////////////////////////// GLOBALS ///////////////////////////////////////////////
char bulk_buffer[BULK_SIZE]; /// global environment string version file date  time device clock

int16 index;

int8 yled_state,rled_state,yflashes,rflashes;
#INT_TIMER0
clock_isr()
{
 switch (yflashes)
 {
 case STOP_FLASHING:
      break;
 case ALWAYS_ON:
           yflashes=STOP_FLASHING;
          LED_ON(green_led);
          LED_ON(red_led);
       break;
 case ALWAYS_OFF:
          yflashes=STOP_FLASHING;
          LED_OFF(green_led);
          LED_OFF(red_led);
       break;
 default:

  if (yflashes!=FOREVER ) yflashes--;
  if (yled_state)
                {
                 LED_ON(green_led);
                 LED_ON(red_led);
                 yled_state=false;
                }
  else
                {
                 LED_OFF(green_led);
                 LED_OFF(red_led);
                 yled_state=true;
                }
 }// end switch yflashes

 switch(rflashes)
 {
 case STOP_FLASHING:
 break;
 case ALWAYS_ON:
          LED_ON(POWER_LED);
          rflashes=STOP_FLASHING;
       break;
 case ALWAYS_OFF:
          LED_OFF(POWER_LED);
          rflashes=STOP_FLASHING;
       break;
 default:
  if (rflashes!=FOREVER ) rflashes--;
  if (rled_state)
                {
                 LED_ON(POWER_LED);

                 rled_state=false;
                }
  else
                {
                 LED_OFF(POWER_LED);

                 rled_state=true;
                }

 }// end switch rflashes
}

void usb_print(char c)
{

/// called from printf char by char
if (index <BULK_SIZE) bulk_buffer[index++]=c;

}



void flash_yellow(int8 times)
{
yflashes=times; // assign gobal flashes for clock isr

}

void flash_power(int8 times)
{
rflashes=times; // assign gobal flashes for clock isr

}
/////////////////////////////////////////////////////////////////////////////
//
// usb_debug_task()
//
// When called periodically, displays debugging information over serial
// to display enumeration and connection states.  Also lights green and red leds
// based upon enumeration and connection status.
//
/////////////////////////////////////////////////////////////////////////////
void usb_debug_task(void) {
   static int8 last_connected;
   static int8 last_enumerated;
   int8 new_connected;
   int8 new_enumerated;

   new_connected=usb_attached();
   new_enumerated=usb_enumerated();

   if (new_connected)
      flash_power(FOREVER);
   else
      flash_power(ALWAYS_ON);

   if (new_enumerated)
      LED_ON(ENUM_LED);
   else
      LED_OFF(ENUM_LED);

   if (new_connected && !last_connected)
   #IF TRACE
      printf("\r\n\n attached ");
   #ENDIF
   if (!new_connected && last_connected)
   #IF TRACE
      printf("\r\n\n detached ");
    #ENDIF
   if (new_enumerated && !last_enumerated)
   #IF TRACE
      printf("\r\n\n enum ");
   #ENDIF
   if (!new_enumerated && last_enumerated)
   #IF TRACE
      printf("\r\n\n unenum ");
   #ENDIF
   last_connected=new_connected;
   last_enumerated=new_enumerated;
}
void main(void) {

   int8 received[3],i;
   int8 data[2],reboots,sent[1];

   int16 value;

   rled_state=0;
   yled_state=0;
   set_timer0(0);
   setup_counters(RTCC_INTERNAL,RTCC_DIV_32); //48mhz/4=12,000,000
                                               // scaled by 256*256 (16 bit) includes every
                                               // scaled by 32 12000000/256*256*32 .3 secs
   flash_yellow(ALWAYS_OFF);
   flash_power(ALWAYS_ON);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   setup_adc_ports( AN0_ANALOG);
   setup_adc( ADC_CLOCK_INTERNAL );
   set_adc_channel( 0 ); ///// PIN A0

   usb_init_cs();
   reboots=0;

   restart:

   #IF TRACE
   //debug(reboots);
   printf("start=%X \n\r",reboots);
   #ENDIF

   // retreive environment info for LINK_CMD
     index=0; /// begining of string id_string
     printf(usb_print,"ver %s  %s  %s  %s \n\r",getenv("VERSION_STRING"),__DATE__,__TIME__,getenv("DEVICE"));

     printf(usb_print,"%s",__FILE__);

   output_float(MY_USB_DETACH_PIN); /// allow 100k to pull pin high
   while (TRUE)
   {
      usb_task();
      usb_debug_task();
      if(usb_enumerated())
      {

       if (input(MY_USB_DETACH_PIN)==0)
          {
             /// switch was closed
             usb_put_packet(1, sent, 0, USB_DTS_TOGGLE); /// send 0 packet to terminate
             usb_detach();
             #IF TRACE
             printf("detach manual\n\r");
             #ENDIF
             flash_yellow(FOREVER);
             while(true); //freeze here waiting for unplugging
          }
         if (usb_kbhit(1))
         {
            LED_OFF(ENUM_LED); // flash to indicate data received
            usb_get_packet(1, received, 3); //3bytes from pipe EP1 usb_get_packet(end pt, payload, payload size)
            switch (mode) /// received[0] is mode
             {
            case LINK_CMD:

               sent[0]=ack_connection;
               usb_put_packet(1, sent, 1, USB_DTS_TOGGLE); //send 1byte via EP1 to PC 0x25 to acknowledge
                                                           //usb_get_packet(end pt, payload, payload size)

               flash_yellow(ALWAYS_OFF); /// may have been on from prev detach

              // printf("L"); ///!!!!!!!!!!!!!!!!!!!!!!!!!!!!! possible compiler bug work around

               #IF TRACE

               printf("\n\r mode=%X param1=%X param2=%X ACK",mode,param1,param2);
               #ENDIF



               usb_puts(1, bulk_buffer, index, 50); // data and length is sent


               break;

            case  LED_CMD:

               //// control tricolor both led red and green on gives yellow
               flash_yellow(STOP_FLASHING); /// don't allow clock isr to control leds
               if (param1 == 1 ) LED_ON(red_led);
               if (param1 == 0 ) LED_OFF(red_led);
               if (param2 == 1 ) LED_ON(green_led);
               if (param2 == 0 ) LED_OFF(green_led);
               sent[0]=ack_led_cmd;
               usb_put_packet(1, sent, 1, USB_DTS_TOGGLE); //send 1byte via EP1 to PC 0x55 to acknowledge
               #IF TRACE
               printf("mode=%X param1=%X param2=%X\n\r",mode,param1,param2);
               #ENDIF
             break;
            case ADC_CMD:

             /// read the value of the center tap of a 50 k pot using the ADC
             /// center tap is connected to A0 ADC channel0 outside legs to GND and 5V
             sent[0]=ack_pot_cmd;
             usb_put_packet(1, sent, 1, USB_DTS_TOGGLE); //send 1byte via EP1 to PC 0x55 to acknowledge
             delay_ms(100);
             value = Read_ADC(); /// 10 bit resolution  data is overlayed on value
             data[0]=make8(value,1);
             data[1]=make8(value,0);

             usb_put_packet(1, data, 2, USB_DTS_TOGGLE);
             #IF TRACE
             printf("mode=%X param1=%X param2=%X pot=%lu \n\r",mode,param1,param2,value);
             #ENDIF
            break;
            case DETACH_CMD:
             /// PC will issue a detach and PIC can be unplugged
             usb_put_packet(1, sent, 0, USB_DTS_TOGGLE); /// send 0 packet to terminate
             usb_detach();          // stop driving D- D+
             #IF TRACE
             printf("detach mode=%X\n\r",mode);
             #ENDIF
             flash_yellow(FOREVER);
             break;
           default:
             //// unknown command so we detach and restart
             usb_put_packet(1, sent, 0, USB_DTS_TOGGLE); /// send 0 packet to terminate
             usb_detach();
             #IF TRACE
             printf("detach mode=%X\n\r",mode);
             #ENDIF
             flash_yellow(FOREVER);
             goto restart;
             } //end of switch
           LED_ON(ENUM_LED); // end of flashing green enum to indicate data received LED
         }// kbhit
      }// enum
   }// true

}
[img][/img]
////////////////////////////// delphi pascal example PC code follows
////////// the pc needs the microchip driver installed to work
Code:
unit dkusb;
// uses the microchip interface dll mpusbapi.dll
// vid is $04D8  and pid is $0011
// these numbers are correlated with the data in the drivers install
// file picusb.inf
// this file has dependency files  mchpusb.sys  picusbci.dll picusb.cat
// wdmstub.sys
// the file picusb.inf is used at install time and results in the registration
// HKey_LOCAL_MACHINE> SYSTEM>ControlSet001>Enum>USB
// the external usb device (PIC18F4550) when enumerated will bind to these
// Win 2000/XP drivers
// the connections to the PIC are D- pin 23 Cable wire is white
//                                D+ pin 24 Cable wire is Green
//                                _____________
//                                |XXXXXXXXXXX|
//                                |           |
//                                | 1  2  3 4 |
//                                |___________|
//                                  5v D- D+ 0v
//
//     PIC18F4550 is coded to auto pull up on D+ to indicate High speed usb
//     the PIC code contains the descriptors that will link and launch the
//     the above PC system drivers
//     Notes
//          A USB message can be made up of one or more packets
//          An in pipe and an out pipe are established
//          more than one external device can use the system drivers
//          using the same pid vid values.
///
//    PIC sends $25 to acknowledge connection
//    PIc sends $55 to acknowledge command ( led red/greem on/off)



interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, dsled, ComCtrls, ExtCtrls, Buttons;
 Const
   MAXSIZE=64;
   MPUSB_FAIL=0;
   MPUSB_SUCCESS=1;
   MP_WRITE:DWORD=0;
   MP_READ:DWORD=1;
   MAX_NUM_MPUSB_DEV=127;
   
type
   DWORD = LongInt;
  PCHAR8 =  array[0..MAXSIZE] of char;
  PBYTE = array[0..MAXSIZE] of BYTE;
  PDWORD =  array[0..MAXSIZE] of DWORD;
  PVOID = Pointer;
  UINT = Cardinal;

  TForm1 = class(TForm)
    Link_to_PC: TButton;
    Label1: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    Memo1: TMemo;
    Devices: TButton;
    dsled1: Tdsled;
    detach: TButton;
    Flash_blue: TTimer;
    PICinfo: TLabel;
    Label7: TLabel;
    Image1: TImage;
    Clear: TButton;
    RS232_Tx: TButton;
    RXtimer: TTimer;
    RS232_Rx: TBitBtn;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Link_to_PCClick(Sender: TObject);
    procedure DevicesClick(Sender: TObject);


 

    procedure detachClick(Sender: TObject);
    procedure Flash_blueTimer(Sender: TObject);
    procedure ClearClick(Sender: TObject);
 
    procedure RS232_TxClick(Sender: TObject);
    procedure RXtimerTimer(Sender: TObject);
    procedure RS232RxClick(Sender: TObject);






  private
    { Private declarations }
  public
    { Public declarations }
    end;
function _MPUSBGetDLLVersion:DWORD; stdcall;external 'mpusbapi.dll';
function _MPUSBGetDeviceCount(pVID_PID:PCHAR8):DWORD; stdcall;external 'mpusbapi.dll';
function _MPUSBOpen(instance:DWORD;pVID_PID:PCHAR8;pEP:PCHAR8;dwDir:DWORD;dwReserved:DWORD):THANDLE; stdcall;external 'mpusbapi.dll';
function _MPUSBRead(handle:THANDLE;var pData:PBYTE;dwLen:DWORD;var pLength:DWORD;dwMilliseconds:DWORD):DWORD; stdcall;external 'mpusbapi.dll';
function _MPUSBReadInt(handle:THANDLE;var pData:PBYTE;dwLen:DWORD;var pLength:PDWORD;dwMilliseconds:DWORD):DWORD; stdcall;external 'mpusbapi.dll';
function _MPUSBWrite(handle:THANDLE;pData:PBYTE;dwLen:DWORD;var pLength:DWORD;dwMilliseconds:DWORD):DWORD; stdcall;external 'mpusbapi.dll';
function _MPUSBClose(handle:THANDLE):DWORD; stdcall;external 'mpusbapi.dll';



var
  Form1: TForm1;
  vid_pid:PCHAR8='vid_04d8&pid_0011';  // VID and PID for Demo USB FS board
  out_pipe:PCHAR8='\MCHP_EP1';
  in_pipe:PCHAR8='\MCHP_EP1';
  myOutPipe:THANDLE;
  myInPipe:THANDLE;
  isConnected:boolean;
 
  rcv_in_progress: boolean;
implementation
uses ShellAPI;


{$R *.DFM}
procedure CheckInvalidHandle;
begin
  if(GetLastError=ERROR_INVALID_HANDLE) then
  begin
        _MPUSBClose(myOutPipe);
        _MPUSBClose(myInPipe);

        myInPipe:=INVALID_HANDLE_VALUE;
        myOutPipe:=INVALID_HANDLE_VALUE;
  end
  else
    ShowMessage('Error Code :'+inttostr(GetLastError()));
end;

Function GetSummary:Integer;
Var tempPipe:THandle;
    count:DWORD;
    max_Count:DWORD;
    i:Byte;
    dummy:pchar8;
Begin
  tempPipe := INVALID_HANDLE_VALUE;
  count:=0;
  max_count := _MPUSBGetDeviceCount(vid_pid);
  Form1.Memo1.Lines.Clear ;
   if(max_count=0) then
  Begin
      result:= max_count;
    Form1.Memo1.Lines.add('No device found');
    exit;
  End
   Else
    Form1.memo1.lines.add(IntToStr(max_Count) + ' device(s) with ' + vid_pid  +  ' currently attached');
  count := 0;
  For i:=0 to MAX_NUM_MPUSB_DEV-1 Do
  Begin
    tempPipe := _MPUSBOpen(i,vid_pid,dummy,MP_READ,0);
    if(tempPipe <> INVALID_HANDLE_VALUE) then
    Begin
      Form1.memo1.lines.add('Instance Index ' + IntToStr(i));
      _MPUSBClose(tempPipe);
      Inc(count);
    End;
    if(count = max_count) Then break;
  End;
  result:= max_count;
End;//end GetSummary


function SendReceivePacket(SendData:PBYTE;SendLength:DWORD;var ReceiveData:PBYTE;
var ReceiveLength:DWORD;SendDelay:UINT;ReceiveDelay:UINT):DWORD; stdcall;
var
  SentDataLength:DWORD ;
  ExpectedReceiveLength:DWORD;

begin
 ExpectedReceiveLength:= ReceiveLength;
 if((myOutPipe <> INVALID_HANDLE_VALUE) and (myInPipe <> INVALID_HANDLE_VALUE)) then
   begin
    if(_MPUSBWrite(myOutPipe,SendData,SendLength,SentDataLength,SendDelay)<>0) then
     if(_MPUSBRead(myInPipe,ReceiveData,ExpectedReceiveLength,ReceiveLength,ReceiveDelay)<>0) then
       begin
       if(ReceiveLength = ExpectedReceiveLength) then
        begin
         Result:=1; // OK
         exit;
        end
       else
        if(ReceiveLength < ExpectedReceiveLength) then
         begin
           Result:=2; // failed, incorrect receive length
           exit;
         end
        end
     else
      CheckInvalidHandle()
    else
      CheckInvalidHandle()
   end
 else
   begin
     Result:=0; // Error
   end;
end;




procedure TForm1.FormCreate(Sender: TObject);
var vers:dword;
begin
vers:=_MPUSBGetDLLVersion ;
myOutPipe:=INVALID_HANDLE_VALUE;
myInPipe:= INVALID_HANDLE_VALUE;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if (myOutPipe <> INVALID_HANDLE_VALUE) then _MPUSBClose(myOutPipe);
        if (myInPipe <> INVALID_HANDLE_VALUE) then _MPUSBClose(myInPipe);
        myInPipe:= INVALID_HANDLE_VALUE;
        myOutPipe:=INVALID_HANDLE_VALUE;
end;

procedure TForm1.Link_to_PCClick(Sender: TObject);

var
   selection:DWORD;
   send_buf:PBYTE;
   receive_buf:PBYTE;
   RecvLength:DWORD;
   SentLength:DWORD;
   Expected:DWORD;
   i :integer;
label quit, finish;

begin
  selection:=0; // USB device that have PID & VID as we configed.
   RxTimer.Enabled:=false;
  if (_MPUSBGetDeviceCount(vid_pid)=0) then
  begin
    Edit1.text:='Status : Device not connected';
    Edit2.text:='Firmware version : unkhown';
    exit;
  end
  else
  begin
    Edit1.text:='Status : Device connected';
    Edit2.text:=vid_pid;
    Flash_blue.Enabled:=false;
    dsled1.ledon:=true;
  end;
  /////////     open the pipes
  myOutPipe:= _MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0);
  myInPipe:= _MPUSBOpen(selection,vid_pid,in_pipe,MP_READ,0);

  if ((myOutPipe = INVALID_HANDLE_VALUE) or (myInPipe = INVALID_HANDLE_VALUE)) then
  begin
   Edit1.text:='Status : USB Error';
   exit;
  end;


  /// pipes are open
  //// poll the PIC for a $25 acknowledge
  send_buf[0]:=0;    // link mode command
  send_buf[1]:=0;   // not validated
  send_buf[2]:=0;   // not validated
  RecvLength:=1;

   //  if  write or read are successfull they return a handle ( non zero)
  if(_MPUSBWrite(myOutPipe,send_buf,3,SentLength,1000)=0) then  goto quit;

  if( _MPUSBRead(myInPipe,receive_buf,3,RecvLength,1000)=0) then goto quit;
  // we have complete a handshake
   if ((receive_buf[0] =  $25 ) and (RecvLength = 3)) then
     begin
      Expected:=receive_buf[2]*256+receive_buf[1];


     RS232_TX.Enabled:=true;
     RS232_RX.Enabled:=true;

     end;






  RecvLength:=0;   // read return actual length
  /// PIC bulk transfer buffer size is 512
  if( _MPUSBRead(myInPipe,receive_buf,512,RecvLength,1000)=0) then goto quit;
  if not (RecvLength =Expected) then goto quit;
   // we have received the PIC compile time enviroment
  PICinfo.Caption:='PIC Firmware version : ';
  for i:=0 to RecvLength-1 do PICinfo.Caption:=PICinfo.Caption+char(receive_buf[i]);




 goto finish;
 quit:
  Edit1.Text:='Status : LNK Communication Error!';
 finish:
  _MPUSBClose(myOutPipe);
  _MPUSBClose(myInPipe);
  if rcv_in_progress then RxTimer.Enabled:=true;
  myInPipe:= INVALID_HANDLE_VALUE;
  myOutPipe:=INVALID_HANDLE_VALUE;
end;



procedure TForm1.DevicesClick(Sender: TObject);
begin
GetSummary;
end;








procedure TForm1.detachClick(Sender: TObject);
var
   selection:DWORD;
   send_buf:PBYTE;
   receive_buf:PBYTE;
   RecvLength:DWORD;
   SentLength:DWORD;

   ADC_value:integer;
   label quit,finish;
begin
/////////     open the pipes
selection:=0; // USB device that have PID & VID as we configed.
  myOutPipe:= _MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0);
  myInPipe:= _MPUSBOpen(selection,vid_pid,in_pipe,MP_READ,0);

  if ((myOutPipe = INVALID_HANDLE_VALUE) or (myInPipe = INVALID_HANDLE_VALUE)) then
  begin
   Edit1.text:='Status : USB Error';
   exit;
  end;


  /// pipes are open
  //// poll the PIC for a $65 acknowledge
  send_buf[0]:=3;    // detach  mode command
  send_buf[1]:=0;   // not validated
  send_buf[2]:=0;   // not validated
  RecvLength:=1;

   //  if  write or read are successfull they return a handle ( non zero)
  if(_MPUSBWrite(myOutPipe,send_buf,3,SentLength,1000)=0) then  goto quit;


  Edit1.Text:='Status : Detached !';
   Flash_blue.Enabled:=true;
 goto finish;

  quit:
  Edit1.Text:='Status : Detach Communication Error!';
 finish:
  _MPUSBClose(myOutPipe);
  _MPUSBClose(myInPipe);

  myInPipe:= INVALID_HANDLE_VALUE;
  myOutPipe:=INVALID_HANDLE_VALUE;
end;

procedure TForm1.Flash_blueTimer(Sender: TObject);
begin
dsled1.Oncolor:=ClNavy;
dsled1.OFFColor:=CLGray;
dsled1.Ledon:=not dsled1.ledon;
end;



procedure TForm1.ClearClick(Sender: TObject);
begin
Form1.Memo1.Lines.Clear ;
end;


procedure TForm1.RS232_TxClick(Sender: TObject);
var
   selection:DWORD;
   send_buf:PBYTE;
   transmit_buf:PBYTE;
   receive_buf:PBYTE;
   RecvLength:DWORD;
   SentLength:DWORD;
   XmitLength:DWORD;
   i :integer;
   Expected:integer;
   this_line:string;
label quit, finish;

begin
  selection:=0; // USB device that have PID & VID as we configed.

  /////////     open the pipes
  myOutPipe:= _MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0);
  myInPipe:= _MPUSBOpen(selection,vid_pid,in_pipe,MP_READ,0);

  if ((myOutPipe = INVALID_HANDLE_VALUE) or (myInPipe = INVALID_HANDLE_VALUE)) then
  begin
   Edit1.text:='Status : USB Error';
   exit;
  end;
  this_line:=memo1.Lines.Strings[0];
  Expected:=length(this_line);
  for i:=0 to Expected-1 do transmit_buf[i]:=byte(this_line[i]);
  send_buf[0]:=2;    // Rs232 xmit  mode command
  send_buf[1]:=Expected div 256;
  send_buf[2]:=Expected mod 256;
  /// pipes are open
  //// poll the PIC for a $65 acknowledge


  RecvLength:=1;

   //  if  write or read are successfull they return a handle ( non zero)
  if(_MPUSBWrite(myOutPipe,send_buf,3,SentLength,1000)=0) then  goto quit;
  /// ecpected length is set to to 1
  if( _MPUSBRead(myInPipe,receive_buf,1,RecvLength,1000)=0) then goto quit;
  // we have complete a handshake
   if ((receive_buf[0] =  $65 ) and (RecvLength = 1)) then
     begin

  //// bulk transfer received buffer siz is 512
    XmitLength:=expected;
    if( _MPUSBWrite(myInPipe,transmit_buf,XmitLength,SentLength,1000)=0) then goto quit;

    if not(SentLength =XmitLength) then goto quit;



  end;

 goto finish;
 quit:
  Edit1.Text:='Status : RS232TX Communication Error!';
 finish:
  _MPUSBClose(myOutPipe);
  _MPUSBClose(myInPipe);

  myInPipe:= INVALID_HANDLE_VALUE;
  myOutPipe:=INVALID_HANDLE_VALUE;
end;

procedure TForm1.RXtimerTimer(Sender: TObject);
//// receive data from USB
var
   selection:DWORD;
   send_buf:PBYTE;
   receive_buf:PBYTE;
   RecvLength:DWORD;
   SentLength:DWORD;
   i :integer;
   Expected:DWORD;
    new_line:string;
label quit, finish;

begin
  memo1.font.color:=ClGreen;
  selection:=0; // USB device that have PID & VID as we configed.

  /////////     open the pipes
  myOutPipe:= _MPUSBOpen(selection,vid_pid,out_pipe,MP_WRITE,0);
  myInPipe:= _MPUSBOpen(selection,vid_pid,in_pipe,MP_READ,0);

  if ((myOutPipe = INVALID_HANDLE_VALUE) or (myInPipe = INVALID_HANDLE_VALUE)) then
  begin
   Edit1.text:='Status : USB Error';
   exit;
  end;


  /// pipes are open
  //// poll the PIC for a $55 acknowledge
  send_buf[0]:=1;    // Rs232 recv  mode command
  send_buf[1]:=0;   // not validated
  send_buf[2]:=0;   // not validated
  RecvLength:=1;

   //  if  write or read are successfull they return a handle ( non zero)
  if(_MPUSBWrite(myOutPipe,send_buf,3,SentLength,1000)=0) then  goto quit;
  /// ecpected length is set to to 1
  if( _MPUSBRead(myInPipe,receive_buf,3,RecvLength,1000)=0) then goto quit;
  // we have complete a handshake
   if ((receive_buf[0] =  $55 ) and (RecvLength = 3)) then
     begin
     Expected:=receive_buf[2]*256+receive_buf[1];
     if Expected=0 then goto finish; /// there is no data available yet
  //// bulk transfer received buffer siz is 512
    if( _MPUSBRead(myInPipe,receive_buf,512,RecvLength,1000)=0) then goto quit;

   if not(RecvLength =Expected) then goto quit;

   if (RecvLength > 0) then
     begin
      /// place data in memo box
      new_line:='';
      for i:=0 to RecvLength-1 do
         begin
         
          new_line:=new_line+char(receive_buf[i]);
         end;
       Memo1.lines.Text:=Memo1.lines.Text+new_line;
      end;

end;

 goto finish;
 quit:
  Edit1.Text:='Status : RS232RX Communication Error!';
 finish:
  _MPUSBClose(myOutPipe);
  _MPUSBClose(myInPipe);

  myInPipe:= INVALID_HANDLE_VALUE;
  myOutPipe:=INVALID_HANDLE_VALUE;
end;

procedure TForm1.RS232RxClick(Sender: TObject);
begin
if RxTimer.enabled=false then
 begin

 RS232_Rx.Font.Color:=ClGreen;
 rcv_in_progress:=true;
 RxTimer.enabled:=true;
 end

 else
 begin
RS232_Rx.Font.Color:=ClRed;
  rcv_in_progress:=false;
  RxTimer.enabled:=false;
 end;

end;

end.


Last edited by Douglas Kennedy on Thu Dec 30, 2010 8:24 am; edited 1 time in total
matheuslps



Joined: 29 Sep 2010
Posts: 73
Location: Brazil

View user's profile Send private message MSN Messenger

PostPosted: Fri Nov 05, 2010 8:11 pm     Reply with quote

Hello man, I am from Brazil and I do not know I to speak in english very well.

I am working at this PicUSB project, but I am having some isues with the host part.

The problem is: The PC recognize the PIC, I installed the driver. But the host program did with the Visual C# can not control the PIC. It was working, but stoped and I do not know why!?

The PIC firmware is the same that J1M did, and I get this error when I try to debug the host program:

http://img443.imageshack.us/img443/1967/errofm.jpg

May you help me with this? I can not see any light at the end of the tunnel.

thanks

Matheus Lopes do Brasil
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group