// Z-Controller by KOE
// Only SD-card
#include "std.h"
#include "emul.h"
#include "vars.h"
#include "sdcard.h"
#include "zc.h"
#include "util.h"
typedef ULONG (WINAPI *CH341GetVersion_t)(); // Get the DLL version number and return the version number
static CH341GetVersion_t CH341GetVersion = nullptr;
typedef ULONG (WINAPI *CH341GetDrvVersion_t)(); // Get the DLL version number and return the version number
static CH341GetDrvVersion_t CH341GetDrvVersion = nullptr;
typedef HANDLE (WINAPI *CH341OpenDevice_t)(ULONG);
static CH341OpenDevice_t CH341OpenDevice = nullptr;
typedef VOID (WINAPI *CH341CloseDevice_t)(ULONG);
static CH341CloseDevice_t CH341CloseDevice = nullptr;
typedef BOOL (WINAPI *CH341StreamSPI4_t)(
ULONG iIndex, // Specify CH341 device serial number
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
ULONG iLength, // Number of data bytes to be transmitted
PVOID ioBuffer );
static CH341StreamSPI4_t CH341StreamSPI4 = nullptr;
typedef BOOL (WINAPI *CH341Set_D5_D0_t)(ULONG,ULONG,ULONG);
static CH341Set_D5_D0_t CH341Set_D5_D0 = nullptr;
typedef PVOID (WINAPI *CH341GetDeviceName_t)(ULONG);
static CH341GetDeviceName_t CH341GetDeviceName = nullptr;
typedef BOOL (WINAPI *CH341SetStream_t)(ULONG,ULONG);// To specify the mode, see Downlink
// Bit 1-bit 0: I2C interface speed /SCL frequency, 00= low speed /20KHz,01= standard /100KHz(default),10= fast /400KHz,11= high speed /750KHz
// 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)
// Bit 7: Bit order in SPI bytes, 0= low first, 1= high first
// All other reservations must be 0
static CH341SetStream_t CH341SetStream = nullptr;
static HMODULE spiDll = nullptr;
//static int SpiDllInited = 0;
static HANDLE ch341 = NULL;
void TZc::Reset()
{
SdCard.Reset();
Cfg = 0;
Status = 0;
RdBuff = 0xff;
}
void TZc::Open(const char *Name)
{
if ( strcmp(Name, "<CH341>") != 0 )
{
// монтирование образа
SdCard.Open(Name);
IsCh341 = 0;
}
else
{
// инициализация ch341
IsCh341 = 1;
if ( ch341 == NULL )
{
// ULONG iDevIndex = 0;
if( CH341GetVersion == nullptr )
{
#ifdef __amd64__
spiDll = LoadLibrary("CH341DLLA64.DLL");
#else
spiDll = LoadLibrary("CH341DLL.DLL");
#endif
if (!spiDll)
{
#ifdef __amd64__
errmsg("failed to load CH341DLLA64.DLL");
#else
errmsg("failed to load CH341DLL.DLL");
#endif
err_win32();
exit(1);
}
CH341GetVersion = (CH341GetVersion_t)GetProcAddress(spiDll, "CH341GetVersion");
CH341GetDrvVersion = (CH341GetDrvVersion_t)GetProcAddress(spiDll, "CH341GetDrvVersion");
CH341OpenDevice = (CH341OpenDevice_t)GetProcAddress(spiDll, "CH341OpenDevice");
CH341CloseDevice = (CH341CloseDevice_t)GetProcAddress(spiDll, "CH341CloseDevice");
CH341StreamSPI4 = (CH341StreamSPI4_t)GetProcAddress(spiDll, "CH341StreamSPI4");
CH341Set_D5_D0 = (CH341Set_D5_D0_t)GetProcAddress(spiDll, "CH341Set_D5_D0");
CH341GetDeviceName = (CH341GetDeviceName_t)GetProcAddress(spiDll, "CH341GetDeviceName");
CH341SetStream = (CH341SetStream_t)GetProcAddress(spiDll, "CH341SetStream");
}
printf("CH341 version: %lu\r\n", CH341GetVersion( ));
char * n = (char*)CH341GetDeviceName(0);
if ( n != 0 )printf("CH341 name: %s\r\n", n);
if ( CH341OpenDevice == 0 )
{
errmsg("failed to load CH341OpenDevice");
err_win32();
exit(1);
}
ch341 = CH341OpenDevice(0);
if ( ch341 == 0 ){
errmsg("OpenDevice ch341 failed");
err_win32();
exit(1);
}
printf("CH341 drv version: %lu\r\n", CH341GetDrvVersion( ));
CH341SetStream(0, 0x80);
CH341Set_D5_D0(0, 0x29, 0x21);
Cfg = 0x01;
CH341Set_D5_D0(0, 0x29, 0x20);
u8 spi_str[20] = "DimkaM";
CH341StreamSPI4(0, 0x00, sizeof(spi_str), &spi_str);
CH341Set_D5_D0(0, 0x29, 0x21);
}
}
}
void TZc::Close()
{
// закрытия образа
SdCard.Close();
if ( ch341 != 0 )
{
// закрытие ch341
CH341CloseDevice(0);
ch341 = 0;
IsCh341 = 0;
}
}
void TZc::Wr(u32 Port, u8 Val)
{
switch(Port & 0xFF)
{
case 0x77: // config
if ( Cfg != ( Val & 3 ) )
{
Cfg = Val & 3;
if ( IsCh341 != 0 )
{
CH341Set_D5_D0(0, 0x29, ((Cfg>>1) & 0x01)|0x20);
}
}
break;
case 0x57: // data
if ( IsCh341 == 0 )
{
if (!(Cfg & 2)) // SD card selected
{
RdBuff = SdCard.Rd();
SdCard.Wr(Val);
}
else
RdBuff = 255;
}
else
{
RdBuff = Val;
CH341StreamSPI4(0, 0, 1, &RdBuff);
}
//printf("\nOUT %02X in %02X",Val,RdBuff);
break;
}
}
u8 TZc::Rd(u32 Port)
{
switch(Port & 0xFF)
{
case 0x77: // status
return Status; // always returns 0
case 0x57: // data
u8 tmp = RdBuff;
if ( IsCh341 == 0 )
{
if (!(Cfg & 2)) // SD card selected
{
RdBuff = SdCard.Rd();
SdCard.Wr(0xff);
}
else
RdBuff = 255;
}
else
{
RdBuff = 0xff;
CH341StreamSPI4(0, 0, 1, &RdBuff);
}
//printf("\nout FF IN %02X (next %02X)",tmp,RdBuff);
return tmp;
}
return 0xFF;
}
TZc Zc;