Subversion Repositories pentevo

Rev

Rev 1124 | Rev 1140 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #include "std.h"
  2.  
  3. #include <io.h>
  4.  
  5. #include "emul.h"
  6. #include "vars.h"
  7. #include "sdcard.h"
  8.  
  9. #include "util.h"
  10.  
  11. typedef ULONG (WINAPI *CH341GetVersion_t)(); // Get the DLL version number and return the version number
  12. static CH341GetVersion_t CH341GetVersion = nullptr;
  13. typedef ULONG (WINAPI *CH341GetDrvVersion_t)(); // Get the DLL version number and return the version number
  14. static CH341GetDrvVersion_t CH341GetDrvVersion = nullptr;
  15. typedef HANDLE (WINAPI *CH341OpenDevice_t)(ULONG);
  16. static CH341OpenDevice_t CH341OpenDevice = nullptr;
  17. typedef VOID (WINAPI *CH341CloseDevice_t)(ULONG);
  18. static CH341CloseDevice_t CH341CloseDevice = nullptr;
  19. typedef BOOL (WINAPI *CH341StreamSPI4_t)(
  20.         ULONG                   iIndex,  // Specify CH341 device serial number
  21.         ULONG                   iChipSelect,  // Chip select control, if bit 7 is 0, the chip select control is ignored, if bit 7 is 1, the parameters are valid: Bit 1 and bit 0 are 00/01/10, respectively, select the D0/D1/D2 pin as low level. valid chip select
  22.         ULONG                   iLength,  // Number of data bytes to be transmitted
  23.         PVOID                   ioBuffer );
  24. static CH341StreamSPI4_t CH341StreamSPI4 = nullptr;
  25. typedef BOOL (WINAPI *CH341Set_D5_D0_t)(ULONG,ULONG,ULONG);
  26. static CH341Set_D5_D0_t CH341Set_D5_D0 = nullptr;
  27. typedef PVOID   (WINAPI *CH341GetDeviceName_t)(ULONG);
  28. static CH341GetDeviceName_t CH341GetDeviceName = nullptr;
  29. typedef BOOL    (WINAPI *CH341SetStream_t)(ULONG,ULONG);// To specify the mode, see Downlink
  30. // Bit 1-bit 0: I2C interface speed /SCL frequency, 00= low speed /20KHz,01= standard /100KHz(default),10= fast /400KHz,11= high speed /750KHz
  31. // Bit 2: SPI I/O number /IO pins, 0= single in/single out (D3 clock /D5 out /D7 in)(default),1= double in/double out (D3 clock /D5 out D4 out /D7 in D6 in)
  32. // Bit 7: Bit order in SPI bytes, 0= low first, 1= high first
  33. // All other reservations must be 0
  34. static CH341SetStream_t CH341SetStream = nullptr;
  35.  
  36. static HMODULE spiDll = nullptr;
  37. //static int SpiDllInited = 0;
  38. static HANDLE ch341 = NULL;
  39.  
  40. static u8 spiData = 0xff;
  41.  
  42. //-----------------------------------------------------------------------------
  43.  
  44. void TSdCard::Reset()
  45. {
  46. //    printf(__FUNCTION__"\n");
  47.    
  48.     CurrState = ST_IDLE;
  49.     ArgCnt = 0;
  50.     Cmd = CMD_INVALID;
  51.     DataBlockLen = 512;
  52.     DataCnt = 0;
  53.  
  54.     CsdCnt = 0;
  55.     //memset(Csd, 0, sizeof(Csd));
  56.     Csd[0] = (1 << 6); // CSD structure (SDHC)
  57.     Csd[1] = 0xE;  // TACC
  58.     Csd[2] = 0x00; // NSAC
  59.     Csd[3] = 0x32; // TRAN_SPEED
  60.     Csd[4] = 0x5B; // CCC x1x11011
  61.     Csd[5] = 0x59; // CCC 0101 | READ_BL_LEN 9
  62.     Csd[6] = 0x00; // READ_BL_PARTIAL | WRITE_BLK_MISALIGN | READ_BLK_MISALIGN | DSR_IMP
  63.  
  64.     UpdateCsdImageSize();
  65.  
  66.     Csd[10] = (1 << 6) | (0x3F << 1); // ERASE_BLK_EN | SECTOR_SIZE
  67.     Csd[11] = (1 << 7); // SECTOR_SIZE | WP_GRP_SIZE
  68.     Csd[12] = (2 << 2) | 2; // R2W_FACTOR | WRITE_BL_LEN 9
  69.     Csd[13] = (1 << 6); // WRITE_BL_LEN 9 | WRITE_BL_PARTIAL
  70.     Csd[14] = 0x00; // FILE_FORMAT_GRP | COPY | PERM_WRITE_PROTECT | TMP_WRITE_PROTECT | FILE_FORMAT
  71.     Csd[15] = 1; // CRC | 1
  72.  
  73.     CidCnt = 0;
  74.     memset(Cid, 0, sizeof(Cid));
  75.  
  76.     // OEM/Application ID (OID)
  77.     Cid[1] = 'U';
  78.     Cid[2] = 'S';
  79.  
  80.     // Product Name (PNM)
  81.     Cid[3] = 'U';
  82.     Cid[4] = 'S';
  83.     Cid[5] = '0' + (VER_HL / 10) % 10;
  84.     Cid[6] = '0' + VER_HL % 10;
  85.     Cid[7] = '0' + VER_A % 10;
  86.  
  87.     Cid[8] = 0x10; // Product Revision (PRV) (BCD)
  88.     Cid[14] = 0x04; // Manufacture Date Code (MDT)
  89.     Cid[15] = 1; // CRC7 | 1
  90.  
  91.     OcrCnt = 0;
  92.  
  93.     R7_Cnt = 0;
  94.  
  95.     AppCmd = false;
  96. }
  97.  
  98. void TSdCard::UpdateCsdImageSize()
  99. {
  100.     Csd[7] = (ImageSize >> 16) & 0x3F; // C_SIZE
  101.     Csd[8] = (ImageSize >> 8) & 0xFF; // C_SIZE
  102.     Csd[9] = ImageSize & 0xFF; // C_SIZE
  103. }
  104. //-----------------------------------------------------------------------------
  105.  
  106. void TSdCard::Wr(u8 Val)
  107. {
  108.     static u32 WrPos = -1U;
  109.     TState NextState = ST_IDLE;
  110. //    printf(__FUNCTION__" Val = %X\n", Val);
  111.    
  112.     if ( IsCh341 != 0 )
  113.     {
  114.         spiData = Val;
  115.         CH341StreamSPI4(0, 0, 1, &spiData);
  116.     }
  117.     else if ( ( Image != 0 ) && ( ( spiCfg & 0x02) == 0 ) )
  118.     {
  119.  
  120.         switch(CurrState)
  121.         {
  122.             case ST_IDLE:
  123.             //case ST_WR_DATA_SIG:
  124.             {
  125.                 if ((Val & 0xC0) != 0x40) // start=0, transm=1
  126.                    break;
  127.  
  128.                 Cmd = TCmd(Val & 0x3F);
  129.                 if (!AppCmd)
  130.                 {
  131.                     switch(Cmd) // Check commands
  132.                     {
  133.  
  134.                     case CMD_SEND_CSD:
  135.                         CsdCnt = 0;
  136.                     break;
  137.  
  138.                     case CMD_SEND_CID:
  139.                         CidCnt = 0;
  140.                     break;
  141.  
  142.                     case CMD_READ_OCR:
  143.                         OcrCnt = 0;
  144.                     break;
  145.  
  146.                     case CMD_SEND_IF_COND:
  147.                         R7_Cnt = 0;
  148.                     //break;
  149.  
  150.                     //case CMD_APP_CMD:
  151.                     //    AppCmd = true;
  152.                     }
  153.                 }
  154.                 NextState = ST_RD_ARG;
  155.                 ArgCnt = 0;
  156.             }
  157.             break;
  158.  
  159.             case ST_RD_ARG:
  160.                 NextState = ST_RD_ARG;
  161.                 ArgArr[3 - ArgCnt++] = Val;
  162.  
  163.     //            printf(__FUNCTION__" ST_RD_ARG val=0x%X\n", Val);
  164.                 if (ArgCnt == 4)
  165.                 {
  166.                     if (!AppCmd)
  167.                     {
  168.                         switch(Cmd)
  169.                         {
  170.                         case CMD_SET_BLOCKLEN:
  171.                             if (Arg<=4096)  DataBlockLen = Arg;
  172.                         break;
  173.  
  174.                         case CMD_READ_SINGLE_BLOCK:
  175.     //                        printf(__FUNCTION__" CMD_READ_SINGLE_BLOCK, Addr = 0x%X\n", Arg);
  176.                             fseek(Image, long(Arg), SEEK_SET);
  177.                             fread(Buf, DataBlockLen, 1, Image);
  178.                         break;
  179.  
  180.                         case CMD_READ_MULTIPLE_BLOCK:
  181.     //                        printf(__FUNCTION__" CMD_READ_MULTIPLE_BLOCK, Addr = 0x%X\n", Arg);
  182.                             fseek(Image, long(Arg), SEEK_SET);
  183.                             fread(Buf, DataBlockLen, 1, Image);
  184.                         break;
  185.  
  186.                         case CMD_WRITE_BLOCK:
  187.     //                        printf(__FUNCTION__" CMD_WRITE_BLOCK, Addr = 0x%X\n", Arg);
  188.                         break;
  189.  
  190.                         case CMD_WRITE_MULTIPLE_BLOCK:
  191.                             WrPos = Arg;
  192.     //                        printf(__FUNCTION__" CMD_WRITE_MULTIPLE_BLOCK, Addr = 0x%X\n", Arg);
  193.                         break;
  194.                         }
  195.                     }
  196.  
  197.                     NextState = ST_RD_CRC;
  198.                     ArgCnt = 0;
  199.                 }
  200.             break;
  201.  
  202.             case ST_RD_CRC:
  203.     //            printf(__FUNCTION__" ST_RD_CRC val=0x%X\n", Val);
  204.                 NextState = GetRespondType();
  205.             break;
  206.  
  207.             case ST_RD_DATA_SIG:
  208.                 if (Val==0xFE) // ╧ЁютхЁър ёшуэрЄєЁ√ фрээ√ї
  209.                 {
  210.                     DataCnt = 0;
  211.                     NextState = ST_RD_DATA;
  212.                 }
  213.                 else
  214.                     NextState = ST_RD_DATA_SIG;
  215.             break;
  216.  
  217.             case ST_RD_DATA_SIG_MUL:
  218.                 switch(Val)
  219.                 {
  220.                 case 0xFC: // ╧ЁютхЁър ёшуэрЄєЁ√ фрээ√ї
  221.     //                printf(__FUNCTION__" ST_RD_DATA_SIG_MUL, Start\n");
  222.                     DataCnt = 0;
  223.                     NextState = ST_RD_DATA_MUL;
  224.                 break;
  225.                 case 0xFD: // ╬ъюэўрэшх яхЁхфрўш
  226.     //                printf(__FUNCTION__" ST_RD_DATA_SIG_MUL, Stop\n");
  227.                     DataCnt = 0;
  228.                     NextState = ST_IDLE;
  229.                 break;
  230.                 default:
  231.                     NextState = ST_RD_DATA_SIG_MUL;
  232.                 }
  233.             break;
  234.  
  235.             case ST_RD_DATA: // ╧Ёшхь фрээ√ї т сєЇхЁ
  236.             {
  237.     //            printf(__FUNCTION__" ST_RD_DATA, Addr = 0x%X, Idx=%d\n", Arg, DataCnt);
  238.                 Buf[DataCnt++] = Val;
  239.                 NextState = ST_RD_DATA;
  240.                 if (DataCnt == DataBlockLen) // ╟ряшё№ фрээ√ї т SD ърЁЄє
  241.                 {
  242.                     DataCnt = 0;
  243.     //                printf(__FUNCTION__" ST_RD_DATA, Addr = 0x%X, write to disk\n", Arg);
  244.                     fseek(Image, long(Arg), SEEK_SET);
  245.                     fwrite(Buf, DataBlockLen, 1, Image);
  246.                     NextState = ST_RD_CRC16_1;
  247.                 }
  248.             }
  249.             break;
  250.  
  251.             case ST_RD_DATA_MUL: // ╧Ёшхь фрээ√ї т сєЇхЁ
  252.             {
  253.     //            printf(__FUNCTION__" ST_RD_DATA_MUL, Addr = 0x%X, Idx=%d\n", WrPos, DataCnt);
  254.                 Buf[DataCnt++] = Val;
  255.                 NextState = ST_RD_DATA_MUL;
  256.                 if (DataCnt == DataBlockLen) // ╟ряшё№ фрээ√ї т SD ърЁЄє
  257.                 {
  258.                     DataCnt = 0;
  259.     //                printf(__FUNCTION__" ST_RD_DATA_MUL, Addr = 0x%X, write to disk\n", WrPos);
  260.                     fseek(Image, long(WrPos), SEEK_SET);
  261.                     fwrite(Buf, DataBlockLen, 1, Image);
  262.                     WrPos += DataBlockLen;
  263.                     NextState = ST_RD_CRC16_1;
  264.                 }
  265.             }
  266.             break;
  267.  
  268.             case ST_RD_CRC16_1: // ╫Єхэшх ёЄрЁ°хую срщЄр CRC16
  269.                 NextState = ST_RD_CRC16_2;
  270.             break;
  271.  
  272.             case ST_RD_CRC16_2: // ╫Єхэшх ьырф°хую срщЄр CRC16
  273.                 NextState = ST_WR_DATA_RESP;
  274.             break;
  275.  
  276.             default:
  277.     //            printf(__FUNCTION__" St=0x%X,  val=0x%X\n", CurrState, Val);
  278.                 return;
  279.         }
  280.  
  281.         CurrState = NextState;
  282.     }
  283. }
  284.  
  285. //-----------------------------------------------------------------------------
  286.  
  287. u8 TSdCard::Rd()
  288. {
  289.     if( IsCh341 != 0 )
  290.     {
  291.         // u8 ret_spi = spiData;
  292.         // spiData = 0xff;
  293.         // CH341StreamSPI4(0, 0, 1, &spiData);
  294.         return spiData;
  295.     }
  296. //    printf(__FUNCTION__" cmd=0x%X, St=0x%X\n", Cmd, CurrState);
  297.     else if ( ( Image != 0 ) && ( ( spiCfg & 0x02) == 0 ) )
  298.     {
  299.         switch(Cmd)
  300.         {
  301.         case CMD_GO_IDLE_STATE:
  302.             if (CurrState == ST_R1)
  303.             {
  304.     //            Cmd = CMD_INVALID;
  305.                 CurrState = ST_IDLE;
  306.                 return 1;
  307.             }
  308.         break;
  309.         case CMD_SEND_OP_COND:
  310.             if (CurrState == ST_R1)
  311.             {
  312.     //            Cmd = CMD_INVALID;
  313.                 CurrState = ST_IDLE;
  314.                 return 0;
  315.             }
  316.         break;
  317.         case CMD_SET_BLOCKLEN:
  318.             if (CurrState == ST_R1)
  319.             {
  320.     //            Cmd = CMD_INVALID;
  321.                 CurrState = ST_IDLE;
  322.                 return 0;
  323.             }
  324.         break;
  325.         case CMD_SEND_IF_COND:
  326.             if (CurrState == ST_R7)
  327.             {
  328.                 switch (R7_Cnt++)
  329.                 {
  330.                  case 0: return 0x01; // R1
  331.                  case 1: return 0x00;
  332.                  case 2: return 0x00;
  333.                  case 3: return 0x01;
  334.                  default:
  335.                     CurrState = ST_IDLE;
  336.                     R7_Cnt = 0;
  337.                     return ArgArr[0]; // echo-back
  338.                 }
  339.             }
  340.         break;
  341.  
  342.         case CMD_READ_OCR:
  343.             if (CurrState == ST_R3)
  344.             {
  345.                 switch (OcrCnt++)
  346.                 {
  347.                  case 0: return 0x00; // R1
  348.                  case 1: return 0x80;
  349.                  case 2: return 0xFF;
  350.                  case 3: return 0x80;
  351.                  default:
  352.                     CurrState = ST_IDLE;
  353.                     OcrCnt = 0;
  354.                     return 0x00;
  355.                 }
  356.             }
  357.         break;
  358.  
  359.         case CMD_APP_CMD:
  360.             if (CurrState == ST_R1)
  361.             {
  362.                 CurrState = ST_IDLE;
  363.                 return 0;
  364.             }
  365.         break;
  366.  
  367.         case CMD_SD_SEND_OP_COND:
  368.             if (CurrState == ST_R1)
  369.             {
  370.                 CurrState = ST_IDLE;
  371.                 return 0;
  372.             }
  373.         break;
  374.  
  375.         case CMD_CRC_ON_OFF:
  376.             if (CurrState == ST_R1)
  377.             {
  378.                 CurrState = ST_IDLE;
  379.                 return 0;
  380.             }
  381.         break;
  382.  
  383.         case CMD_STOP_TRANSMISSION:
  384.             switch(CurrState)
  385.             {
  386.             case ST_R1:
  387.                 DataCnt = 0;
  388.                 CurrState = ST_IDLE;
  389.                 return 0;
  390.             case ST_R1b:
  391.                 DataCnt = 0;
  392.                 CurrState = ST_R1;
  393.                 return 0x7F;
  394.             case ST_RD_ARG:
  395.             case ST_RD_CRC:
  396.                 return 0;
  397.             }
  398.         break;
  399.  
  400.         case CMD_READ_SINGLE_BLOCK:
  401.             switch(CurrState)
  402.             {
  403.               unsigned int cpu_dt;
  404.  
  405.               case ST_R1:
  406.                   CurrState = ST_DELAY_S;
  407.                   InitialCPUt = cpu.t;
  408.                   return 0;
  409.  
  410.               case ST_DELAY_S:
  411.                   cpu_dt = cpu.t - InitialCPUt;
  412.                   if (cpu_dt < 0)
  413.                     cpu_dt += conf.frame;
  414.                   if (cpu_dt >= conf.sd_delay)
  415.                     CurrState = ST_STARTBLOCK;
  416.                   return 0xFF;
  417.  
  418.               case ST_STARTBLOCK:
  419.                   CurrState = ST_WR_DATA;
  420.                   DataCnt = 0;
  421.                   return 0xFE;
  422.  
  423.               case ST_WR_DATA:
  424.               {
  425.                   u8 Val = Buf[DataCnt++];
  426.                   if (DataCnt == DataBlockLen)
  427.                   {
  428.                     DataCnt = 0;
  429.                     CurrState = ST_WR_CRC16_1;
  430.                   }
  431.                   return Val;
  432.               }
  433.  
  434.               case ST_WR_CRC16_1:
  435.                   CurrState = ST_WR_CRC16_2;
  436.                   return 0xFF; // crc
  437.               case ST_WR_CRC16_2:
  438.                   CurrState = ST_IDLE;
  439.                   Cmd = CMD_INVALID;
  440.                   return 0xFF; // crc
  441.             }
  442.     //        Cmd = CMD_INVALID;
  443.         break;
  444.  
  445.         case CMD_READ_MULTIPLE_BLOCK:
  446.             switch(CurrState)
  447.             {
  448.               unsigned int cpu_dt;
  449.  
  450.               case ST_R1:
  451.                   CurrState = ST_DELAY_S;
  452.                   InitialCPUt = cpu.t;
  453.                   return 0;
  454.  
  455.               case ST_DELAY_S:
  456.                   cpu_dt = cpu.t - InitialCPUt;
  457.                   if (cpu_dt < 0)
  458.                     cpu_dt += conf.frame;
  459.                   if (cpu_dt >= conf.sd_delay)
  460.                     CurrState = ST_STARTBLOCK;
  461.                   return 0xFF;
  462.  
  463.               case ST_STARTBLOCK:
  464.                   CurrState = ST_IDLE;
  465.                   DataCnt = 0;
  466.                   return 0xFE;
  467.  
  468.               case ST_IDLE:
  469.               {
  470.                   if (DataCnt<DataBlockLen)
  471.                   {
  472.                     u8 Val = Buf[DataCnt++];
  473.                     if (DataCnt == DataBlockLen)
  474.                         fread(Buf, DataBlockLen, 1, Image);
  475.                     return Val;
  476.                   }
  477.                   else if (DataCnt>(DataBlockLen+8))
  478.                   {
  479.                     DataCnt=0;
  480.                     return 0xFE; // next startblock
  481.                   }
  482.                   else
  483.                   {
  484.                     DataCnt++;
  485.                     return 0xFF; // crc & pause
  486.                   }
  487.               }
  488.  
  489.     /*
  490.             case ST_R1:
  491.                 CurrState = ST_WR_DATA_SIG;
  492.                 return 0;
  493.             case ST_WR_DATA_SIG:
  494.                 CurrState = ST_IDLE;
  495.                 DataCnt = 0;
  496.                 return 0xFE;
  497.             case ST_IDLE:
  498.             {
  499.                 u8 Val = Buf[DataCnt++];
  500.                 if (DataCnt == DataBlockLen)
  501.                 {
  502.                     DataCnt = 0;
  503.                     fread(Buf, DataBlockLen, 1, Image);
  504.                     CurrState = ST_WR_CRC16_1;
  505.                 }
  506.                 return Val;
  507.             }
  508.             case ST_WR_CRC16_1:
  509.                 CurrState = ST_WR_CRC16_2;
  510.                 return 0xFF;
  511.             case ST_WR_CRC16_2:
  512.                 CurrState = ST_WR_DATA_SIG;
  513.                 return 0xFF;
  514.     */
  515.             }
  516.         break;
  517.  
  518.         case CMD_SEND_CSD:
  519.             switch(CurrState)
  520.             {
  521.             case ST_R1:
  522.                 CurrState = ST_DELAY_S;
  523.                 return 0;
  524.             case ST_DELAY_S:
  525.                 CurrState = ST_STARTBLOCK;
  526.                 return 0xFF;
  527.             case ST_STARTBLOCK:
  528.                 CurrState = ST_WR_DATA;
  529.                 return 0xFE;
  530.             case ST_WR_DATA:
  531.             {
  532.                 u8 Val = Csd[CsdCnt++];
  533.                 if (CsdCnt == 16)
  534.                 {
  535.                     CsdCnt = 0;
  536.                     CurrState = ST_IDLE;
  537.                     Cmd = CMD_INVALID;
  538.                 }
  539.                 return Val;
  540.             }
  541.             }
  542.     //        Cmd = CMD_INVALID;
  543.         break;
  544.  
  545.         case CMD_SEND_CID:
  546.             switch(CurrState)
  547.             {
  548.             case ST_R1:
  549.                 CurrState = ST_DELAY_S;
  550.                 return 0;
  551.             case ST_DELAY_S:
  552.                 CurrState = ST_STARTBLOCK;
  553.                 return 0xFF;
  554.             case ST_STARTBLOCK:
  555.                 CurrState = ST_WR_DATA;
  556.                 return 0xFE;
  557.             case ST_WR_DATA:
  558.             {
  559.                 u8 Val = Cid[CidCnt++];
  560.                 if (CidCnt == 16)
  561.                 {
  562.                     CidCnt = 0;
  563.                     CurrState = ST_IDLE;
  564.                     Cmd = CMD_INVALID;
  565.                 }
  566.                 return Val;
  567.             }
  568.             }
  569.     //        Cmd = CMD_INVALID;
  570.         break;
  571.  
  572.         case CMD_WRITE_BLOCK:
  573.     //        printf(__FUNCTION__" cmd=0x%X, St=0x%X\n", Cmd, CurrState);
  574.             switch(CurrState)
  575.             {
  576.             case ST_R1:
  577.                 CurrState = ST_RD_DATA_SIG;
  578.                 return 0x00;
  579.  
  580.             case ST_WR_DATA_RESP:
  581.             {
  582.                 CurrState = ST_IDLE;
  583.                 u8 Resp = ((STAT_DATA_ACCEPTED) << 1) | 1;
  584.                 return Resp;
  585.             }
  586.             }
  587.         break;
  588.  
  589.         case CMD_WRITE_MULTIPLE_BLOCK:
  590.             switch(CurrState)
  591.             {
  592.             case ST_R1:
  593.                 CurrState = ST_RD_DATA_SIG_MUL;
  594.                 return 0x00;    // !!! check this !!!
  595.             case ST_WR_DATA_RESP:
  596.             {
  597.                 CurrState = ST_RD_DATA_SIG_MUL;
  598.                 u8 Resp = ((STAT_DATA_ACCEPTED) << 1) | 1;
  599.                 return Resp;
  600.             }
  601.             }
  602.         break;
  603.         }
  604.  
  605.         if (CurrState == ST_R1) // CMD_INVALID
  606.         {
  607.             CurrState = ST_IDLE;
  608.             return 0x05;
  609.         }
  610.     }
  611.  
  612.     return 0xFF;
  613. }
  614.  
  615. //-----------------------------------------------------------------------------
  616.  
  617. TSdCard::TState TSdCard::GetRespondType()
  618. {
  619.     if (!AppCmd)
  620.     {
  621.         switch(Cmd)
  622.         {
  623.         case CMD_APP_CMD:
  624.             AppCmd = true;
  625.             return ST_R1;
  626.         case CMD_GO_IDLE_STATE:
  627.         case CMD_SEND_OP_COND:
  628.         case CMD_SET_BLOCKLEN:
  629.         case CMD_READ_SINGLE_BLOCK:
  630.         case CMD_READ_MULTIPLE_BLOCK:
  631.         case CMD_CRC_ON_OFF:
  632.         case CMD_SEND_CSD:
  633.         case CMD_SEND_CID:
  634.             return ST_R1;
  635.         case CMD_READ_OCR:
  636.             return ST_R3;
  637.         case CMD_SEND_IF_COND:
  638.             return ST_R7;
  639.         case CMD_STOP_TRANSMISSION:
  640.             return ST_R1b;
  641.  
  642.         case CMD_WRITE_BLOCK:
  643.         case CMD_WRITE_MULTIPLE_BLOCK:
  644.             return ST_R1;
  645.         }
  646.     }
  647.     else
  648.     {
  649.         AppCmd = false;
  650.         switch(Cmd)
  651.         {
  652.             case CMD_SD_SEND_OP_COND:
  653.                 return ST_R1;
  654.         }
  655.     }
  656.  
  657.     Cmd = CMD_INVALID;
  658.     return ST_R1;
  659.     //return ST_IDLE;
  660. }
  661.  
  662. //-----------------------------------------------------------------------------
  663.  
  664.  
  665. void TSdCard::Open(const char *Name)
  666. {
  667. //    printf(__FUNCTION__"\n");
  668.  
  669.     if ( strcmp(Name, "<CH341>") == 0 )
  670.     {
  671.         IsCh341 = 1;
  672.         if ( ch341 == NULL )
  673.         {
  674.             // ULONG iDevIndex = 0;
  675.             if( CH341GetVersion == nullptr )
  676.             {
  677. #ifdef __amd64__
  678.                 spiDll = LoadLibrary("CH341DLLA64.DLL");
  679. #else
  680.                 spiDll = LoadLibrary("CH341DLL.DLL");
  681. #endif
  682.                 if (!spiDll)
  683.                 {
  684. #ifdef __amd64__
  685.                     errmsg("failed to load CH341DLLA64.DLL");
  686. #else
  687.                     errmsg("failed to load CH341DLL.DLL");
  688. #endif
  689.                     err_win32();
  690.                     exit(1);
  691.                 }
  692.                
  693.                 CH341GetVersion = (CH341GetVersion_t)GetProcAddress(spiDll, "CH341GetVersion");
  694.                 CH341GetDrvVersion = (CH341GetDrvVersion_t)GetProcAddress(spiDll, "CH341GetDrvVersion");
  695.                 CH341OpenDevice = (CH341OpenDevice_t)GetProcAddress(spiDll, "CH341OpenDevice");
  696.                 CH341CloseDevice = (CH341CloseDevice_t)GetProcAddress(spiDll, "CH341CloseDevice");
  697.                 CH341StreamSPI4 = (CH341StreamSPI4_t)GetProcAddress(spiDll, "CH341StreamSPI4");
  698.                 CH341Set_D5_D0 = (CH341Set_D5_D0_t)GetProcAddress(spiDll, "CH341Set_D5_D0");
  699.                 CH341GetDeviceName = (CH341GetDeviceName_t)GetProcAddress(spiDll, "CH341GetDeviceName");
  700.                 CH341SetStream = (CH341SetStream_t)GetProcAddress(spiDll, "CH341SetStream");
  701.             }
  702.             printf("CH341 version: %lu\r\n", CH341GetVersion( ));
  703.            
  704.             char * n = (char*)CH341GetDeviceName(0);
  705.             if ( n != 0 )printf("CH341 name: %s\r\n", n);
  706.            
  707.             if ( CH341OpenDevice == 0 )
  708.             {
  709.                 errmsg("failed to load CH341OpenDevice");
  710.                 err_win32();
  711.                 exit(1);
  712.             }
  713.             ch341 = CH341OpenDevice(0);
  714.                
  715.             if ( ch341 == 0 ){
  716.                 errmsg("OpenDevice ch341 failed");
  717.                 err_win32();
  718.                 exit(1);
  719.             }
  720.             printf("CH341 drv version: %lu\r\n", CH341GetDrvVersion( ));
  721.            
  722.             CH341SetStream(0, 0x80);
  723.             CH341Set_D5_D0(0, 0x29, 0x21);
  724.             spiCfg = 0x01;
  725.            
  726.             CH341Set_D5_D0(0, 0x29, 0x20);
  727.             u8 spi_str[20] = "DimkaM";
  728.             CH341StreamSPI4(0, 0x00, sizeof(spi_str), &spi_str);
  729.             CH341Set_D5_D0(0, 0x29, 0x21);
  730.         }
  731.     }
  732.     else
  733.     {
  734.         IsCh341 = 0;
  735.        
  736.         assert(!Image);
  737.         Image = fopen(Name, "r+b");
  738.         if(!Image)
  739.         {
  740.             if(Name[0])
  741.             {
  742.                 errmsg("can't find SD card image `%s'", Name);
  743.             }
  744.             return;
  745.         }
  746.         ImageSize = u32(_filelengthi64(fileno(Image)) / (512 * 1024)) - 1;
  747.         UpdateCsdImageSize();
  748.        
  749.         spiCfg = 0x01;
  750.     }
  751. }
  752.  
  753. //-----------------------------------------------------------------------------
  754.  
  755. void TSdCard::Cs(u8 state)
  756. {
  757.    
  758.     if( ( state & 3 ) != spiCfg )
  759.     {
  760.         spiCfg = state & 3;
  761.        
  762.         if ( IsCh341 != 0 )
  763.         {
  764.             CH341Set_D5_D0(0, 0x29, ((spiCfg>>1) & 0x01)|0x20);
  765.         }
  766.     }
  767. }
  768.  
  769. //-----------------------------------------------------------------------------
  770.  
  771. void TSdCard::Close()
  772. {
  773.     if ( Image != 0 )
  774.     {
  775.         fclose(Image);
  776.         Image = 0;
  777.     }
  778.    
  779.     if ( ch341 != 0 )
  780.     {
  781.         CH341CloseDevice(0);
  782.         ch341 = 0;
  783.         IsCh341 = 0;
  784.     }
  785. }
  786.  
  787. //-----------------------------------------------------------------------------
  788.  
  789. TSdCard SdCard;
  790.  
  791. //-----------------------------------------------------------------------------
  792.