⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mainf.cpp

📁 Cypress Suite USB 3.4.6
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainF.h"
#include "StatusF.h"
#include "dbt.h"


// {DD57F00D-F1D4-4b88-AC34-28D73328F836}
static GUID GUID_ADAPT_DEVICE_REQUEST_NOTIFICATION = {0xdd57f00d, 0xf1d4, 0x4b88, 0xac, 0x34, 0x28, 0xd7, 0x33, 0x28, 0xf8, 0x36};

typedef struct _CUSTOM_EVENT {
    ULONG  Version;
    USHORT MajorFunction;
    USHORT MinorFunction;
} CUSTOM_EVENT, *PCUSTOM_EVENT;


//______________________________________________________________________________
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
//______________________________________________________________________________
__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{
   bArrival  = false;
   AppDir    = ExtractFileDir(Application->ExeName);

   FX2Device = new CCyUSBDevice(Handle);
   FindFX2();
}


//______________________________________________________________________________
//
// This method allows detection of hot-plugged devices
//

void __fastcall TMainForm::WndProc(TMessage &Message)
{
  if (Message.Msg == WM_DEVICECHANGE) {

    // Executes on the DBT_DEVNODECHANGED WParam following the DBT_DEVICEARRIVAL
    // Gives the device time to get ready, otherwise FindListener won't succeed
    // in openning a device.

    if (bArrival) FindFX2();

    bArrival = (Message.WParam == DBT_DEVICEARRIVAL);

    if (Message.WParam == DBT_DEVICEREMOVECOMPLETE) {

      PDEV_BROADCAST_HDR bcastHdr = (PDEV_BROADCAST_HDR) Message.LParam;
      if (bcastHdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {

        PDEV_BROADCAST_HANDLE pDev = (PDEV_BROADCAST_HANDLE) Message.LParam;
        if (pDev->dbch_handle == FX2Device->DeviceHandle()) {
          FX2Device->Close();
          DevPresentBtn->Glyph = LEDOffBtn->Glyph;
          LgEEBtn->Enabled = false;
          SmEEBtn->Enabled = false;
        }

      }
    }


    // The CyUSB.sys driver automatically sends this DBT_CUSTOMEVENT
    // when any of the below 5 major IRP codes are processed.
    if (Message.WParam == DBT_CUSTOMEVENT) {

      PDEV_BROADCAST_HDR bcastHdr = (PDEV_BROADCAST_HDR) Message.LParam;
      if (bcastHdr->dbch_devicetype == DBT_DEVTYP_HANDLE) {

        PDEV_BROADCAST_HANDLE pDev = (PDEV_BROADCAST_HANDLE) Message.LParam;
        if (pDev->dbch_eventguid == GUID_ADAPT_DEVICE_REQUEST_NOTIFICATION) {
          PCUSTOM_EVENT pEvent = (PCUSTOM_EVENT)pDev->dbch_data;

          switch (pEvent->MajorFunction) {
          case 0x00: //IRP_MJ_CREATE
            break;
          case 0x02: //IRP_MJ_CLOSE
            break;
          case 0x16: //IRP_MJ_POWER
            break;
          case 0x17: //IRP_MJ_SYSTEM_CONTROL
            break;
          case 0x1b: //IRP_MJ_PNP
            break;
          }
        }   
      }
    }


  }

  TForm::WndProc(Message);

}

//______________________________________________________________________________
//
// This routine just checks to see if the device has VendorID == 0x04B4
//

void __fastcall TMainForm::FindFX2(void)
{
    // Disable as if no device found
    DevPresentBtn->Glyph = LEDOffBtn->Glyph;
    LgEEBtn->Enabled = false;
    SmEEBtn->Enabled = false;

    int devices = FX2Device->DeviceCount();

    if (devices == 0) return;
    
    int d = 0;
    int VID = 0;

    while ((d < devices) && (VID != 0x04B4)) {
      FX2Device->Open(d);

      if (!FX2Device->IsOpen()) {  // Try a reset
        FX2Device->Reset();
        Sleep(1000);
        FX2Device->Open(d);
      }

      VID = FX2Device->VendorID;
      d++;
    }

    if (FX2Device->IsOpen()) {
      if (VID == 0x04B4) {
        DevPresentBtn->Glyph = LEDOnBtn->Glyph;
        LgEEBtn->Enabled = true;
        SmEEBtn->Enabled = true;

        // All the control transfers use REQ_VENDOR and TGT_DEVICE
        FX2Device->ControlEndPt->ReqType = REQ_VENDOR;
        FX2Device->ControlEndPt->Target = TGT_DEVICE;

      }
    }
}

//______________________________________________________________________________
//
// This routine called when either LgEEBtn or SmEEBtn is clicked
//

void __fastcall TMainForm::LgEEBtnClick(TObject *Sender)
{
  if (!FX2Device->IsOpen()) throw Exception("No FX2 Devices connected.");

  bool bBigEE = (Sender == LgEEBtn);
  String Caption = bBigEE ? "Select file to download into large (512 - 64K byte) EEPROM" : "Select file to download into small (16 - 256 byte) EEPROM";

  FileSpec = FOpenDialog(Caption,"i2c EEPROM Files (*.iic)|*.iic|All Files (*.*)|*.*|",MainForm->AppDir, Handle);
  if (FileSpec.Length() == 0) return;

  StatusForm->Caption = bBigEE ? "Large EEPROM" : "Small EEPROM";
  StatusForm->MsgLabel->Caption = "Downloading " + ExtractFileName(FileSpec) + " . . .";
  StatusForm->Show();
  Refresh();
  StatusForm->Refresh();



  // Download VendAX.hex code
  LoadHexToRAM("VendAX");

  // Set the ReqCode to be used for the EEPROM check and programming
  FX2Device->ControlEndPt->ReqCode = bBigEE ? 0xA9 : 0xA2;

  // See if there's an EEPROM attached
  LONG len = 2;
  WORD wCDCD;
  PUCHAR buf = (PUCHAR) &wCDCD;
  FX2Device->ControlEndPt->Value = 0;
  FX2Device->ControlEndPt->Index = 0;

  FX2Device->ControlEndPt->Read(buf,len);

  if (wCDCD == 0xCDCD) {
    StatusForm->Hide();
    MessageBox(NULL, "EEPROM not enabled.", "Error", MB_OK | MB_ICONEXCLAMATION);
    return;
  }

  // 0xA9 and 0xA2 are also the request codes used in the EEPROM download
  PerformCtlFileTransfer();

  StatusForm->Hide();

}

//______________________________________________________________________________
//
// LoadHexToRAM loads a .hex file into RAM.
//
// If the file to be loaded is larger than 8KB, this method should be called twice:
// first with bLow = false and again with bLow = true.
//
// When bLow = false, all lines of code above the 8KB boundary are loaded.
// When bLow = true, all lines of code below the 8KB boundary are loaded.
//
// This application only calls this method once, passing "VendAX".  But, it can
// be used to download any valid .hex file

bool __fastcall TMainForm::LoadHexToRAM(String fName, bool bLow)
{
  // Load all the text lines from the .hex file into a String List for easy
  // manipulation

  TStringList *sList = new TStringList;

  if (fName.Pos("VendAX")) {
    GetVendAX(sList);
  } else {
    TFileStream *srcStream = new TFileStream(fName,fmOpenRead | fmShareDenyWrite);
    if (srcStream == NULL) return false;
    sList->LoadFromStream(srcStream);
    delete srcStream;
  }


  String tmp;
  int v;

  // Delete non-data records
  for (int i=sList->Count - 1; i>=0; i--) {
    if (sList->Strings[i].Length()) {
      tmp = sList->Strings[i].SubString(8,2);   // Get the Record Type into v
      v = 0;  HexToBin(tmp.c_str(),(char *)&v,1); v *= 2;
      if (v) sList->Delete(i);                  // Data records are type == 0
    }
  }

  // Re-construct the strings to only contain the offset followed by the data
  for (int i=0; i<sList->Count; i++) {
    // Remove comments
    v = sList->Strings[i].Pos("//");
    if (v) sList->Strings[i].SetLength(v-1);

    // Build string that just contains the offset followed by the data bytes
    if (sList->Strings[i].Length()) {
      // Get the offset
      String sOffset = sList->Strings[i].SubString(4,4);

      // Get the string of data chars
      tmp = sList->Strings[i].SubString(2,2);
      v = 0;  HexToBin(tmp.c_str(),(char *)&v,1); v *= 2;
      String s = sList->Strings[i].SubString(10,v);

      // Replace the string in the list
      sList->Strings[i] = sOffset + s;
    }

  }

  if (bLow) ResetFX2(1);      // Stop the processor

  FX2Device->ControlEndPt->ReqCode = bLow ? 0xA0 : 0xA3;
  FX2Device->ControlEndPt->Index = 0;
  FX2Device->ControlEndPt->Value = 0;

  // Go through the list, loading data into RAM
  String DataString = "";
  WORD nxtoffset = 0;
  LONG xferLen = 0;

  WORD offset;
  int RamSize = 0x2000;  // 8KB

  UCHAR buf[MAX_CTLXFER_SIZE];

  char  c;
  PCHAR pc;

  for (int i=0; i<sList->Count; i++) {
    // Get the offset
    tmp = sList->Strings[i].SubString(1,4);
    HexToBin(tmp.c_str(),(char *)&offset,2);
    pc = (char *) &offset; c = pc[0]; pc[0]=pc[1]; pc[1]=c;  // Swap the bytes

    int sLen = sList->Strings[i].Length();

    // Handle a line that straddles the 8KB boundary
    int bytes = (sLen - 4)/2;
    LONG lastAddr = offset + bytes;

    // This case is the last segment to be sent to low memory
    if (bLow && (offset < RamSize) && (lastAddr > RamSize))
      bytes = RamSize - offset;

    // In this case, we found the first segment to be sent to the high memory
    if (!bLow && (offset < RamSize) && (lastAddr > RamSize)) {
      bytes = lastAddr - RamSize;
      String s = "xxxx"+sList->Strings[i].SubString(sLen - (bytes*2)+1,bytes*2);
      sList->Strings[i] = s;
      offset = RamSize;
    }

    if ((bLow &&  (offset < RamSize)) || // Below 8KB - internal RAM
       (!bLow && (offset >= RamSize)) ) {

      xferLen += bytes;

      if ((offset == nxtoffset) && (xferLen < MAX_CTLXFER_SIZE)) {
        DataString += sList->Strings[i].SubString(5,bytes*2);
      } else {
        LONG len = DataString.Length() / 2;
        if (len) {
          Hex2Bytes(DataString,buf);
          FX2Device->ControlEndPt->Write(buf, len);
        }

        FX2Device->ControlEndPt->Value = offset;  // The destination address

        DataString = sList->Strings[i].SubString(5,bytes*2);

        xferLen = bytes;

      }

      nxtoffset = offset + bytes;  // Where next contiguous data would sit
    }
  }

  // Send the last segment of bytes
  LONG len = DataString.Length() / 2;
  if (len) {
     Hex2Bytes(DataString,buf);
     FX2Device->ControlEndPt->Write(buf, len);
  }

  if (bLow) ResetFX2(0);      // Start running this new code

  return true;

}

//______________________________________________________________________________


bool TMainForm::PerformCtlFileTransfer(void)
{
   PCHAR buf;
   TFileStream *fStream;
   bool success;

   LONG bufLen;
   String tmp;

   fStream = new TFileStream(FileSpec,fmOpenRead | fmShareDenyWrite);

   if (fStream) {
     LONG fSize = fStream->Size;

     FX2Device->ControlEndPt->TimeOut = 25000;
     FX2Device->ControlEndPt->Index = 0;

     if (fSize <= MAX_CTLXFER_SIZE) {   // Small file

       FX2Device->ControlEndPt->Value = 0;  // The destination address

       buf = new UCHAR[fSize];
       fStream->Read(buf, fSize);
       success = FX2Device->ControlEndPt->Write(buf, fSize);

       if (!success)
         Application->MessageBox("File transfer failed.","Write to Device");

       delete[] buf;

     } else {                           // Big file
       LONG bufLen;

       buf = new UCHAR[MAX_CTLXFER_SIZE];

       success = true;
       do {
         FX2Device->ControlEndPt->Value = fStream->Position;  // Dest address

         bufLen = fSize - fStream->Position;
         if (bufLen > MAX_CTLXFER_SIZE) bufLen = MAX_CTLXFER_SIZE;

         fStream->Read(buf, bufLen);
         success &= FX2Device->ControlEndPt->Write(buf, bufLen);

       } while (success && (fStream->Position < fSize));

       if (!success)
         Application->MessageBox("File transfer failed.","Write to Device");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -