image/svg+xml
Brteve's API for EveApps
Version 0.0.1
The reference document for common folder of EveApps project.
 
Loading...
Searching...
No Matches
EVE_HalImpl_MPSSE.c
Go to the documentation of this file.
1
32#include "EVE_HalImpl.h"
33#include "EVE_Platform.h"
34#if defined(MPSSE_PLATFORM)
35
36#ifdef _WIN32
37#include <timeapi.h>
38#pragma comment(lib, "Winmm.lib")
39#endif
40
41#if defined(EVE_MULTI_PLATFORM_TARGET)
42#define EVE_HalImpl_initialize EVE_HalImpl_MPSSE_initialize
43#define EVE_HalImpl_release EVE_HalImpl_MPSSE_release
44#define EVE_Hal_list EVE_Hal_MPSSE_list
45#define EVE_Hal_info EVE_Hal_MPSSE_info
46#define EVE_Hal_isDevice EVE_Hal_MPSSE_isDevice
47#define EVE_HalImpl_defaults EVE_HalImpl_MPSSE_defaults
48#define EVE_HalImpl_open EVE_HalImpl_MPSSE_open
49#define EVE_HalImpl_close EVE_HalImpl_MPSSE_close
50#define EVE_HalImpl_idle EVE_HalImpl_MPSSE_idle
51#define EVE_Hal_flush EVE_Hal_MPSSE_flush
52#define EVE_Hal_startTransfer EVE_Hal_MPSSE_startTransfer
53#define EVE_Hal_endTransfer EVE_Hal_MPSSE_endTransfer
54#define EVE_Hal_transfer8 EVE_Hal_MPSSE_transfer8
55#define EVE_Hal_transfer16 EVE_Hal_MPSSE_transfer16
56#define EVE_Hal_transfer32 EVE_Hal_MPSSE_transfer32
57#define EVE_Hal_transferMem EVE_Hal_MPSSE_transferMem
58#define EVE_Hal_transferProgMem EVE_Hal_MPSSE_transferProgMem
59#define EVE_Hal_transferString EVE_Hal_MPSSE_transferString
60#define EVE_Hal_hostCommand EVE_Hal_MPSSE_hostCommand
61#define EVE_Hal_hostCommandExt3 EVE_Hal_MPSSE_hostCommandExt3
62#define EVE_Hal_powerCycle EVE_Hal_MPSSE_powerCycle
63#define EVE_UtilImpl_bootupDisplayGpio EVE_UtilImpl_MPSSE_bootupDisplayGpio
64#define EVE_Hal_setSPI EVE_Hal_MPSSE_setSPI
65#define EVE_Hal_restoreSPI EVE_Hal_MPSSE_restoreSPI
66#endif
67
68#define LIBMPSSE_MAX_RD_BYTES_PER_CALL_IN_SINGLE_CH 65535
69#define LIBMPSSE_MAX_WR_BYTES_PER_CALL_IN_SINGLE_CH 65535
70
71#define LIBMPSSE_MAX_RD_BYTES_PER_CALL_IN_MULTI_CH 65535
72#define LIBMPSSE_MAX_WR_BYTES_PER_CALL_IN_MULTI_CH 65532
74/*********
75** INIT **
76*********/
77
78uint32_t s_NumChannels = 0;
79#ifdef _WIN32
80bool s_SleepMitigated = false;
81#endif
82
85
90{
91 /* Initialize the libmpsse */
93}
94
100{
101 /* Cleanup the MPSSE Lib */
102#ifdef _WIN32
103 if (s_SleepMitigated)
104 {
105 timeEndPeriod(1);
106 s_SleepMitigated = false;
107 }
108#endif
110}
111
116size_t EVE_Hal_list()
117{
118 s_NumChannels = 0;
119 SPI_GetNumChannels(&s_NumChannels);
120 return s_NumChannels;
121}
122
129void EVE_Hal_info(EVE_DeviceInfo *deviceInfo, size_t deviceIdx)
130{
131 FT_DEVICE_LIST_INFO_NODE chanInfo = { 0 };
132
133 memset(deviceInfo, 0, sizeof(EVE_DeviceInfo));
134 if (deviceIdx >= s_NumChannels)
135 return;
136
137 SPI_GetChannelInfo((uint32_t)deviceIdx, &chanInfo);
138
139 strcpy_s(deviceInfo->SerialNumber, sizeof(deviceInfo->SerialNumber), chanInfo.SerialNumber);
140 strcpy_s(deviceInfo->DisplayName, sizeof(deviceInfo->DisplayName), chanInfo.Description);
141 deviceInfo->Host = EVE_HOST_MPSSE;
142 deviceInfo->Opened = chanInfo.Flags & FT_FLAGS_OPENED;
143}
144
152bool EVE_Hal_isDevice(EVE_HalContext *phost, size_t deviceIdx)
153{
154 FT_DEVICE_LIST_INFO_NODE chanInfo = { 0 };
155
156 if (!phost)
157 return false;
158 if (EVE_HOST != EVE_HOST_MPSSE)
159 return false;
160 if (deviceIdx >= s_NumChannels)
161 return false;
162
163 if (!phost->SpiHandle)
164 return false;
165
166 if (!SPI_GetChannelInfo((uint32_t)deviceIdx, &chanInfo))
167 return false;
168
169 return phost->SpiHandle == chanInfo.ftHandle;
170}
171
178bool EVE_HalImpl_defaults(EVE_HalParameters *parameters, size_t deviceIdx)
179{
180 FT_DEVICE_LIST_INFO_NODE chanInfo = { 0 };
181 bool res = deviceIdx >= 0 && deviceIdx < s_NumChannels;
182 if (!res)
183 {
184 uint32_t i;
185 if (!s_NumChannels)
186 EVE_Hal_list();
187
188 // Select first open device
189 deviceIdx = 0;
190 for (i = 0; i < s_NumChannels; ++i)
191 {
192 if (SPI_GetChannelInfo((uint32_t)i, &chanInfo) != FT_OK)
193 continue;
194 if (!(chanInfo.Flags & FT_FLAGS_OPENED))
195 {
196 deviceIdx = i;
197 res = true;
198 break;
199 }
200 }
201 }
202 else
203 {
204 SPI_GetChannelInfo((uint32_t)deviceIdx, &chanInfo);
205 }
206 parameters->MpsseChannelNo = deviceIdx & 0xFF;
207 parameters->PowerDownPin = 7;
208 parameters->SpiClockrateKHz = 12000; /* in KHz */
209 if (!strcmp(chanInfo.Description, "UMFTPD2A B"))
210 {
211 /* Settings for FT9xx GPIO passthrough */
212 /* parameters->PowerDownPin = 7 + 16; */ /* Uses channel D, useful for FT9xx passthrough. See EVE_HalImpl_open */
213 /* parameters->SpiClockrateKHz = 600; */
214
215 /* Settings for FT9xx hardware SPI passthrough */
216 parameters->PowerDownPin = 0x80 + 43; /* GPIO pin 43 */
217 parameters->SpiClockrateKHz = 2000; // 2000;
218 }
219 return res;
220}
221
230bool EVE_HalImpl_open(EVE_HalContext *phost, const EVE_HalParameters *parameters)
231{
232 FT_STATUS status;
233 FT_DEVICE_LIST_INFO_NODE chanInfo = { 0 };
234 ChannelConfig channelConf; /* channel configuration */
235
236#ifdef EVE_MULTI_GRAPHICS_TARGET
237 phost->GpuDefs = &EVE_GpuDefs_FT80X;
238#endif
239
240 /* configure the spi settings */
241 channelConf.ClockRate = parameters->SpiClockrateKHz * 1000;
242 channelConf.LatencyTimer = 2;
244 channelConf.Pin = 0x00000000; /* FinalVal-FinalDir-InitVal-InitDir (for dir 0=in, 1=out) */
245
246 phost->SpiClockrateKHz = parameters->SpiClockrateKHz;
247 phost->MpsseChannelNo = parameters->MpsseChannelNo;
248 phost->PowerDownPin = parameters->PowerDownPin;
249
250 /* Open the first available channel */
251 status = SPI_OpenChannel(parameters->MpsseChannelNo, (FT_HANDLE *)&phost->SpiHandle);
252 phost->GpioHandle = phost->SpiHandle;
253 if (FT_OK != status)
254 {
255 eve_printf_debug("SPI open channel failed %d %p\n", parameters->MpsseChannelNo, phost->SpiHandle);
256 return false;
257 }
258 status = SPI_InitChannel((FT_HANDLE)phost->SpiHandle, &channelConf);
259 if (FT_OK != status)
260 {
261 eve_printf_debug("SPI init channel failed %d %p\n", parameters->MpsseChannelNo, phost->SpiHandle);
262 return false;
263 }
264
265 eve_printf_debug("\nhandle=0x%p status=0x%x\n", phost->SpiHandle, (unsigned int)status);
266
267 /* Special case, when connecting through UMFTPD2A, use channel D for GPIO */
268 if (phost->PowerDownPin >= 8 && ((phost->PowerDownPin & 0x80) == 0))
269 {
270 SPI_GetChannelInfo((uint32_t)phost->MpsseChannelNo, &chanInfo);
271 if (!strcmp(chanInfo.Description, "UMFTPD2A B"))
272 {
273 size_t slen = strlen(chanInfo.SerialNumber);
274 char cn = 'B' + (phost->PowerDownPin >> 3);
275 eve_printf_debug("%s (%s): Adding channel %c for GPIO\n", chanInfo.Description, chanInfo.SerialNumber, cn);
276 phost->PowerDownPin &= 7;
277 chanInfo.SerialNumber[slen - 1] = cn;
278 phost->GpioHandle = NULL;
279 if (FT_OpenEx(chanInfo.SerialNumber, FT_OPEN_BY_SERIAL_NUMBER, &phost->GpioHandle) != FT_OK)
280 {
281 eve_printf_debug("Failed to open channel D\n");
282 FT_Close(phost->SpiHandle);
283 return false;
284 }
285 else
286 {
287 eve_printf_debug("Channel D open OK\n");
288 }
289 if (FT_ResetDevice(phost->GpioHandle) != FT_OK
290 || FT_SetBitMode(phost->GpioHandle, (1 << phost->PowerDownPin), FT_BITMODE_SYNC_BITBANG) != FT_OK)
291 {
292 eve_printf_debug("Failed to prepare channel D\n");
293 FT_Close(phost->GpioHandle);
294 FT_Close(phost->SpiHandle);
295 return false;
296 }
297 }
298 }
299
300 /* Initialize the context variables */
301 phost->SpiDummyBytes = 1; /* by default ft800/801/810/811 goes with single dummy byte for read */
303 phost->Status = EVE_STATUS_OPENED;
305
306#ifdef _WIN32
307 /* Performance degradation workaround. Mitigate SPI_ToggleCS sleep, if it's detected. */
308 /* SPI_ToggleCS may be fixed to remove the sleep call in future versions of libMPSSE. */
309 /* This workaround applies only if the affected libMPSSE library is being used. */
310 if (!s_SleepMitigated)
311 {
312 /* This will sleep twice, once on each FALSE */
313 uint32_t ms, delta;
314 ms = EVE_millis();
315 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, TRUE);
316 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, FALSE);
317 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, TRUE);
318 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, FALSE);
319 delta = EVE_millis() - ms;
320 /* If the sleep time is more than a single full tick (either 15ms or 16ms),
321 we know for sure that it's sleeping a full tick twice. */
322 if (delta > 16)
323 {
324 /* Set thread scheduler for process to 1ms. */
325 timeBeginPeriod(1);
326 s_SleepMitigated = true;
327 /* Verify that it worked. */
328 eve_printf_debug("Mitigating libMPSSE sleep issue (%u ms)\n", (unsigned int)delta);
329 ms = EVE_millis();
330 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, TRUE);
331 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, FALSE);
332 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, TRUE);
333 SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, FALSE);
334 delta = EVE_millis() - ms;
335 /* EVE_millis may jump a whole tick at most */
336 if (delta > 16)
337 {
338 eve_printf_debug("MPSSE sleep issue may still persist (%u ms)\n", (unsigned int)delta);
339 }
340 else
341 {
342 eve_printf_debug("MPSSE sleep issue mitigated\n");
343 }
344 }
345 }
346#endif
347
348 return true;
349}
350
357{
358 phost->Status = EVE_STATUS_CLOSED;
360 if (phost->GpioHandle != phost->SpiHandle)
361 SPI_CloseChannel(phost->GpioHandle);
362 SPI_CloseChannel(phost->SpiHandle);
363 phost->GpioHandle = NULL;
364 phost->SpiHandle = NULL;
365}
366
373{
374 /* no-op */
375}
377
378/*************
379** TRANSFER **
380*************/
381
384
385#if defined(EVE_BUFFER_WRITES)
386static bool flush(EVE_HalContext *phost);
387#endif
388
397static inline uint32_t incrementRamGAddr(EVE_HalContext *phost, uint32_t addr, uint32_t inc)
398{
399 if (!EVE_Hal_supportCmdB(phost) || (addr != REG_CMDB_WRITE))
400 {
401 bool wrapCmdAddr = (addr >= RAM_CMD) && (addr < (RAM_CMD + EVE_CMD_FIFO_SIZE));
402 addr += inc;
403 if (wrapCmdAddr)
405 }
406 return addr;
407}
408
418static inline bool rdBuffer(EVE_HalContext *phost, uint8_t *buffer, uint32_t size)
419{
420 uint32_t sizeTransferred = 0;
421 uint32_t sizeRemaining = size;
422
423 while (sizeRemaining)
424 {
425 FT_STATUS status = SPI_Read(phost->SpiHandle, buffer, min(0xFFFF, sizeRemaining), &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES);
426 sizeRemaining -= sizeTransferred;
427 buffer += sizeTransferred;
428
429 if (status != FT_OK || !sizeTransferred)
430 {
431 eve_printf_debug("%d SPI_Read failed, sizeTransferred is %d with status %d\n", __LINE__, sizeTransferred, (int)status);
432 phost->Status = EVE_STATUS_ERROR;
433 return false;
434 }
435 }
436
437 return true;
438}
439
449static inline bool wrBuffer(EVE_HalContext *phost, const uint8_t *buffer, uint32_t size)
450{
451#if defined(EVE_BUFFER_WRITES)
452 if (buffer && (size < (sizeof(phost->SpiWrBuf) - phost->SpiWrBufIndex)))
453 {
454 /* Write to buffer */
455 memcpy(&phost->SpiWrBuf[phost->SpiWrBufIndex], buffer, size);
456 phost->SpiWrBufIndex += size;
457 return true;
458 }
459 else
460 {
461 if (buffer && phost->SpiWrBufIndex)
462 {
463 /* Buffer is over size, flush now */
464 if (!flush(phost))
465 return false;
466
467 /* Write to buffer */
468 if (size < sizeof(phost->SpiWrBuf))
469 return wrBuffer(phost, buffer, size);
470 }
471
472 if (buffer || phost->SpiWrBufIndex)
473 {
474 uint32_t sizeTransferred;
475 uint8_t hrdpkt[8];
476 uint32_t addr = phost->SpiRamGAddr;
477 FT_STATUS status;
478 uint32_t sizeRemaining;
479
480 if (!buffer)
481 {
482 /* Flushing */
483 buffer = phost->SpiWrBuf;
484 size = phost->SpiWrBufIndex;
485 phost->SpiWrBufIndex = 0;
486 }
487
488 /* Compose the HOST MEMORY WRITE packet */
489 hrdpkt[0] = (addr >> 16) | 0x80; /* MSB bits 10 for WRITE */
490 hrdpkt[1] = (addr >> 8) & 0xFF;
491 hrdpkt[2] = addr & 0xFF;
492
493 /* printf("wr %x\n", addr); */
494 status = SPI_Write((FT_HANDLE)phost->SpiHandle, hrdpkt, 3, &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES | SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
495
496 if ((status != FT_OK) || (sizeTransferred != 3))
497 {
498 eve_printf_debug("%d SPI_Write failed, sizeTransferred is %d with status %d\n", __LINE__, sizeTransferred, (int)status);
499 if (sizeTransferred != 3)
500 phost->Status = EVE_STATUS_ERROR;
501 return false;
502 }
503
504 sizeRemaining = size;
505 while (sizeRemaining)
506 {
507 uint32_t transferSize = min(0xFFFF, sizeRemaining);
508 FT_STATUS status = SPI_Write(phost->SpiHandle, (uint8 *)buffer, transferSize, &sizeTransferred,
510 sizeRemaining -= sizeTransferred;
511 buffer += sizeTransferred;
512
513 if (status != FT_OK || !sizeTransferred)
514 {
515 eve_printf_debug("%d SPI_Write failed, sizeTransferred is %d with status %d\n", __LINE__, sizeTransferred, (int)status);
516 phost->Status = EVE_STATUS_ERROR;
517 return false;
518 }
519 }
520
521 addr = incrementRamGAddr(phost, addr, size);
522 phost->SpiRamGAddr = addr;
523 }
524
525 return true;
526 }
527#else
528 uint32_t sizeTransferred = 0;
529 uint32_t sizeRemaining = size;
530
531 while (sizeRemaining)
532 {
533 FT_STATUS status = SPI_Write(phost->SpiHandle, (uint8 *)buffer, min(0xFFFF, sizeRemaining), &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES);
534 sizeRemaining -= sizeTransferred;
535 buffer += sizeTransferred;
536
537 if (status != FT_OK || !sizeTransferred)
538 {
539 eve_printf_debug("%d SPI_Write failed, sizeTransferred is %d with status %d\n", __LINE__, sizeTransferred, status);
540 phost->Status = EVE_STATUS_ERROR;
541 return false;
542 }
543 }
544
545 return true;
546#endif
547}
548
556static inline uint8_t transfer8(EVE_HalContext *phost, uint8_t value)
557{
558 if (phost->Status == EVE_STATUS_WRITING)
559 {
560 wrBuffer(phost, &value, sizeof(value));
561 }
562 else
563 {
564 rdBuffer(phost, &value, sizeof(value));
565 }
566 return value;
567}
568
569#if defined(EVE_BUFFER_WRITES)
577static bool flush(EVE_HalContext *phost)
578{
579 bool res = true;
580 if (phost->SpiWrBufIndex)
581 {
582 res = wrBuffer(phost, NULL, 0);
583 }
584 eve_assert(!phost->SpiWrBufIndex);
585#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
586 if (!EVE_Hal_supportCmdB(phost))
587 {
588 if (phost->SpiWpWritten)
589 {
590 phost->SpiWpWritten = false;
591 phost->SpiRamGAddr = REG_CMD_WRITE;
592 phost->SpiWrBufIndex = 2;
593 phost->SpiWrBuf[0] = phost->SpiWpWrite & 0xFF;
594 phost->SpiWrBuf[1] = phost->SpiWpWrite >> 8;
595 res = wrBuffer(phost, NULL, 0);
596 }
597 eve_assert(!phost->SpiWrBufIndex);
598 }
599#endif
600 return res;
601}
602#endif
603
609void EVE_Hal_flush(EVE_HalContext *phost)
610{
612#if defined(EVE_BUFFER_WRITES)
613 flush(phost);
614#endif
615}
616
625{
627
628#if defined(EVE_BUFFER_WRITES)
629 if (!EVE_Hal_supportCmdB(phost) && addr == REG_CMD_WRITE && rw == EVE_TRANSFER_WRITE)
630 {
631#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
632 /* Bypass fifo write pointer write */
633 phost->SpiWpWriting = true;
634#else
635 eve_assert(false);
636#endif
637 }
638 else if (addr != incrementRamGAddr(phost, phost->SpiRamGAddr, phost->SpiWrBufIndex) || rw == EVE_TRANSFER_READ)
639 {
640 /* Close any write transfer that was left open, if the address changed */
641 flush(phost);
642 phost->SpiRamGAddr = addr;
643 }
644#endif
645
646 if (rw == EVE_TRANSFER_READ)
647 {
648 uint8_t transferArray[5];
649 uint32_t sizeTransferred;
650
651#if defined(EVE_BUFFER_WRITES)
652 eve_assert(!phost->SpiWrBufIndex);
653#endif
654
655 /* Compose the read packet */
656 transferArray[0] = addr >> 16;
657 transferArray[1] = addr >> 8;
658 transferArray[2] = addr;
659 transferArray[3] = 0; // Dummy Read byte
660 transferArray[4] = 0; // Dummy Read byte
661
662 SPI_Write((FT_HANDLE)phost->SpiHandle, transferArray, 3 + phost->SpiDummyBytes, &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES | SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
663
664 if (phost->Status != EVE_STATUS_ERROR)
665 phost->Status = EVE_STATUS_READING;
666 }
667 else
668 {
669#if defined(EVE_BUFFER_WRITES)
670 if (phost->Status != EVE_STATUS_ERROR)
671 phost->Status = EVE_STATUS_WRITING;
672#else
673 uint8_t transferArray[3];
674 uint32_t sizeTransferred;
675
676 /* Compose the write packet */
677 transferArray[0] = (0x80 | (addr >> 16));
678 transferArray[1] = addr >> 8;
679 transferArray[2] = addr;
680
681 SPI_Write((FT_HANDLE)phost->SpiHandle, transferArray, 3, &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES | SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE);
682
683 if (phost->Status != EVE_STATUS_ERROR)
684 phost->Status = EVE_STATUS_WRITING;
685#endif
686 }
687}
688
695{
696 FT_STATUS status;
697#if defined(EVE_BUFFER_WRITES)
699#endif
700
702
703#if defined(EVE_BUFFER_WRITES)
704 /* Transfers to FIFO and DL are kept open */
705 addr = phost->SpiRamGAddr;
707 && !((addr >= RAM_CMD) && (addr < (RAM_CMD + EVE_CMD_FIFO_SIZE)))
708 && !((addr >= RAM_DL) && (addr < (RAM_DL + EVE_DL_SIZE))))
709 {
710 flush(phost);
711 }
712
713 if (phost->Status == EVE_STATUS_READING)
714 {
715 /* just disable the CS */
716 status = SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, FALSE);
717
718 if (status != FT_OK)
719 phost->Status = EVE_STATUS_ERROR;
720 else
721 phost->Status = EVE_STATUS_OPENED;
722 }
723 else if (phost->Status == EVE_STATUS_WRITING)
724 {
725#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
726 if (!EVE_Hal_supportCmdB(phost))
727 {
728 phost->SpiWpWriting = false;
729 }
730#endif
731 phost->Status = EVE_STATUS_OPENED;
732 }
733#else
734 /* just disable the CS */
735 status = SPI_ToggleCS((FT_HANDLE)phost->SpiHandle, FALSE);
736
737 if (phost->Status != EVE_STATUS_ERROR)
738 {
739 if (status != FT_OK)
740 phost->Status = EVE_STATUS_ERROR;
741 else
742 phost->Status = EVE_STATUS_OPENED;
743 }
744#endif
745}
746
755{
756#if defined(EVE_BUFFER_WRITES)
757#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
758 if (!EVE_Hal_supportCmdB(phost))
759 {
760 eve_assert(!phost->SpiWpWriting);
761 }
762#endif
763#endif
764 return transfer8(phost, value);
765}
766
775{
776 uint8_t buffer[2];
777#if defined(EVE_BUFFER_WRITES)
778#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
779 if (!EVE_Hal_supportCmdB(phost))
780 {
781 if (phost->SpiWpWriting)
782 {
783 phost->SpiWpWrite = value;
784 phost->SpiWpWritten = true;
785 return 0;
786 }
787 }
788#endif
789#endif
790 if (phost->Status == EVE_STATUS_READING)
791 {
792 rdBuffer(phost, buffer, 2);
793 return (uint16_t)buffer[0]
794 | (uint16_t)buffer[1] << 8;
795 }
796 else
797 {
798 buffer[0] = value & 0xFF;
799 buffer[1] = value >> 8;
800 wrBuffer(phost, buffer, 2);
801 return 0;
802 }
803}
804
813{
814 uint8_t buffer[4];
815#if defined(EVE_BUFFER_WRITES)
816#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
817 if (!EVE_Hal_supportCmdB(phost))
818 {
819 eve_assert(!phost->SpiWpWriting);
820 }
821#endif
822#endif
823 if (phost->Status == EVE_STATUS_READING)
824 {
825 rdBuffer(phost, buffer, 4);
826 return (uint32_t)buffer[0]
827 | (uint32_t)buffer[1] << 8
828 | (uint32_t)buffer[2] << 16
829 | (uint32_t)buffer[3] << 24;
830 }
831 else
832 {
833 buffer[0] = value & 0xFF;
834 buffer[1] = (value >> 8) & 0xFF;
835 buffer[2] = (value >> 16) & 0xFF;
836 buffer[3] = value >> 24;
837 wrBuffer(phost, buffer, 4);
838 return 0;
839 }
840}
841
850void EVE_Hal_transferMem(EVE_HalContext *phost, uint8_t *result, const uint8_t *buffer, uint32_t size)
851{
852 if (!size)
853 return;
854
855#if defined(EVE_BUFFER_WRITES)
856#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
857 if (!EVE_Hal_supportCmdB(phost))
858 {
859 eve_assert(!phost->SpiWpWriting);
860 }
861#endif
862#endif
863
864 if (result && buffer)
865 {
866 /* not implemented */
868 }
869 else if (result)
870 {
871 rdBuffer(phost, result, size);
872 }
873 else if (buffer)
874 {
875 wrBuffer(phost, buffer, size);
876 }
877}
878
888{
889 if (!size)
890 return;
891
892#if defined(EVE_BUFFER_WRITES)
893#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
894 if (!EVE_Hal_supportCmdB(phost))
895 {
896 eve_assert(!phost->SpiWpWriting);
897 }
898#endif
899#endif
900
901 if (result && buffer)
902 {
903 /* not implemented */
905 }
906 else if (result)
907 {
908 rdBuffer(phost, result, size);
909 }
910 else if (buffer)
911 {
912 wrBuffer(phost, buffer, size);
913 }
914}
915
926uint32_t EVE_Hal_transferString(EVE_HalContext *phost, const char *str, uint32_t index, uint32_t size, uint32_t padMask)
927{
928 uint32_t transferred;
929
930 if (!size)
931 {
932 /* TODO: Support different padding options */
933 eve_assert(padMask == 0x3);
934 EVE_Hal_transfer32(phost, 0);
935 return 4;
936 }
937
938#if defined(EVE_BUFFER_WRITES)
939#if !defined(EVE_SUPPORT_CMDB) || defined(EVE_MULTI_GRAPHICS_TARGET)
940 if (!EVE_Hal_supportCmdB(phost))
941 {
942 eve_assert(!phost->SpiWpWriting);
943 }
944#endif
945#endif
947 transferred = 0;
948 if (phost->Status == EVE_STATUS_WRITING)
949 {
951
952 for (;;)
953 {
954 char c = str[index + (transferred)];
955 buffer[transferred++] = c;
956 // putchar(c ? c : '_');
957 if (!c)
958 {
959 break;
960 }
961 if (transferred >= size)
962 {
963 buffer[transferred++] = 0;
964 // putchar('_');
965 break;
966 }
967 }
968 while (transferred & padMask)
969 {
970 buffer[transferred++] = 0;
971 // putchar('_');
972 }
973
974 eve_assert(transferred);
975
976 wrBuffer(phost, buffer, transferred);
977 }
978 else
979 {
980 /* not implemented */
982 }
983 return transferred;
984}
986
987/************
988** UTILITY **
989************/
990
993
1001{
1002 uint8_t transferArray[3];
1003 uint32_t sizeTransferred;
1004
1005 transferArray[0] = cmd;
1006 transferArray[1] = 0;
1007 transferArray[2] = 0;
1008
1009#if defined(EVE_BUFFER_WRITES)
1010 flush(phost);
1011#endif
1012 SPI_Write(phost->SpiHandle, transferArray, sizeof(transferArray), &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES | SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE | SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
1013}
1014
1022{
1023 uint8_t transferArray[3];
1024 uint32_t sizeTransferred;
1025
1026 transferArray[0] = cmd;
1027 transferArray[1] = (cmd >> 8) & 0xff;
1028 transferArray[2] = (cmd >> 16) & 0xff;
1029
1030#if defined(EVE_BUFFER_WRITES)
1031 flush(phost);
1032#endif
1033 SPI_Write(phost->SpiHandle, transferArray, sizeof(transferArray), &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES | SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE | SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
1034}
1035
1036static FT_STATUS EVE_HalImpl_passthroughGpio(EVE_HalContext *phost, uint8_t gpio, uint8_t val)
1037{
1038 /* Special behaviour for FT9xx passthrough to control GPIO pins on FT9xx.
1039 This produces a fake read */
1040
1041 int tries = 0;
1042
1043 uint8_t recvArray[2];
1044 uint8_t transferArray[8];
1045 uint32_t sizeTransferred;
1046 FT_STATUS ftRes;
1047
1048 transferArray[0] = 0;
1049 transferArray[1] = 0;
1050 transferArray[2] = 0;
1051 transferArray[3] = 0;
1052 transferArray[4] = 0xA5;
1053 transferArray[5] = gpio;
1054 transferArray[6] = val;
1055 transferArray[7] = 0xA5 ^ gpio ^ val;
1056
1057 recvArray[1] = 0;
1058
1059#if defined(EVE_BUFFER_WRITES)
1060 flush(phost);
1061#endif
1062 do
1063 {
1064 EVE_sleep(20);
1065 ftRes = SPI_Write(phost->SpiHandle, transferArray, sizeof(transferArray), &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES | SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE)
1066 || SPI_Read(phost->SpiHandle, recvArray, sizeof(recvArray), &sizeTransferred, SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES | SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE);
1067 ++tries;
1068 } while (ftRes == FT_OK && recvArray[1] != 0x5A && tries < 128);
1069
1070 if (tries >= 128 && ftRes == FT_OK)
1071 ftRes = FT_IO_ERROR;
1072
1073 return ftRes;
1074}
1075
1084bool EVE_Hal_powerCycle(EVE_HalContext *phost, bool up)
1085{
1086 bool res = true;
1087 FT_STATUS ftRes;
1088 uint8_t pin = (1 << phost->PowerDownPin);
1089 uint8_t pwd1 = pin;
1090 uint8_t pwd0 = 0;
1091 DWORD written;
1092 eve_assert(phost->PowerDownPin < 8 || phost->PowerDownPin & 0x80);
1093#if defined(EVE_BUFFER_WRITES)
1094 flush(phost);
1095#endif
1096 if (up)
1097 {
1098 if (phost->PowerDownPin & 0x80)
1099 ftRes = EVE_HalImpl_passthroughGpio(phost, phost->PowerDownPin & 0x7F, 0);
1100 else if (phost->GpioHandle == phost->SpiHandle)
1101 ftRes = FT_WriteGPIO(phost->GpioHandle, pin | 0x3B, pwd0 | 0x08); // PDN set to 0 ,connect BLUE wire of MPSSE to PDN# of FT800 board
1102 else
1103 ftRes = FT_Write(phost->GpioHandle, &pwd0, 1, &written);
1104 if (ftRes != FT_OK)
1105 res = false;
1106
1107 eve_assert(ftRes == FT_OK);
1108 EVE_sleep(20);
1109
1110 if (phost->PowerDownPin & 0x80)
1111 ftRes = EVE_HalImpl_passthroughGpio(phost, phost->PowerDownPin & 0x7F, 1);
1112 else if (phost->GpioHandle == phost->SpiHandle)
1113 ftRes = FT_WriteGPIO(phost->GpioHandle, pin | 0x3B, pwd1 | 0x08); // PDN set to 1 ,connect BLUE wire of MPSSE to PDN# of FT800 board
1114 else
1115 ftRes = FT_Write(phost->GpioHandle, &pwd1, 1, &written);
1116 if (ftRes != FT_OK)
1117 res = false;
1118
1119 eve_assert(ftRes == FT_OK);
1120 EVE_sleep(20);
1121 }
1122 else
1123 {
1124 if (phost->PowerDownPin & 0x80)
1125 ftRes = EVE_HalImpl_passthroughGpio(phost, phost->PowerDownPin & 0x7F, 1);
1126 else if (phost->GpioHandle == phost->SpiHandle)
1127 ftRes = FT_WriteGPIO(phost->GpioHandle, pin | 0x3B, pwd1 | 0x08); // PDN set to 1 ,connect BLUE wire of MPSSE to PDN# of FT800 board
1128 else
1129 ftRes = FT_Write(phost->GpioHandle, &pwd1, 1, &written);
1130 if (ftRes != FT_OK)
1131 res = false;
1132
1133 eve_assert(ftRes == FT_OK);
1134 EVE_sleep(20);
1135
1136 if (phost->PowerDownPin & 0x80)
1137 ftRes = EVE_HalImpl_passthroughGpio(phost, phost->PowerDownPin & 0x7F, 0);
1138 else if (phost->GpioHandle == phost->SpiHandle)
1139 ftRes = FT_WriteGPIO(phost->GpioHandle, pin | 0x3B, pwd0 | 0x08); // PDN set to 0 ,connect BLUE wire of MPSSE to PDN# of FT800 board
1140 else
1141 ftRes = FT_Write(phost->GpioHandle, &pwd0, 1, &written);
1142 if (ftRes != FT_OK)
1143 res = false;
1144
1145 eve_assert(ftRes == FT_OK);
1146 EVE_sleep(20);
1147 }
1148 return res;
1149}
1150
1158void EVE_Hal_setSPI(EVE_HalContext *phost, EVE_SPI_CHANNELS_T numchnls, uint8_t numdummy)
1159{
1160#if defined(EVE_BUFFER_WRITES)
1161 flush(phost);
1162#endif
1163 /* no-op */
1164}
1165
1167{
1168#if defined(EVE_BUFFER_WRITES)
1169 flush(phost);
1170#endif
1171 /* no-op */
1172}
1174
1175/*********
1176** MISC **
1177*********/
1178
1181
1190{
1191 /* no-op */
1192 return true;
1193}
1195
1196#endif /* #if defined(MPSSE_PLATFORM) */
1197
1198/* end of file */
static uint32_t c
Definition Common.c:38
static uint32_t wrBuffer(EVE_HalContext *phost, const void *buffer, uint32_t size, bool progmem, bool string)
Write buffer to Coprocessor's comand fifo.
Definition EVE_Cmd.c:191
#define EVE_CMD_STRING_MAX
Definition EVE_Cmd.h:44
#define strcpy_s(dst, sz, src)
#define eve_progmem_const
#define RAM_CMD
#define REG_CMDB_WRITE
#define EVE_CMD_FIFO_SIZE
Definition EVE_GpuDefs.h:58
#define REG_CMD_WRITE
#define RAM_DL
Definition EVE_GpuDefs.h:95
#define EVE_DL_SIZE
Definition EVE_GpuDefs.h:56
#define EVE_CMD_FIFO_MASK
Definition EVE_GpuDefs.h:60
EVE_SPI_CHANNELS_T
@ EVE_SPI_SINGLE_CHANNEL
EVE_HalPlatform g_HalPlatform
Definition EVE_Hal.c:43
EVE_HAL_EXPORT bool EVE_Hal_powerCycle(EVE_HalContext *phost, bool up)
Toggle PD_N pin of FT800 board for a power cycle.
@ EVE_STATUS_READING
Definition EVE_HalDefs.h:59
@ EVE_STATUS_CLOSED
Definition EVE_HalDefs.h:57
@ EVE_STATUS_OPENED
Definition EVE_HalDefs.h:58
@ EVE_STATUS_ERROR
Definition EVE_HalDefs.h:61
@ EVE_STATUS_WRITING
Definition EVE_HalDefs.h:60
EVE_HAL_EXPORT uint8_t EVE_Hal_transfer8(EVE_HalContext *phost, uint8_t value)
Write 8 bits to Coprocessor.
EVE_HAL_EXPORT uint16_t EVE_Hal_transfer16(EVE_HalContext *phost, uint16_t value)
Write 2 bytes to Coprocessor.
EVE_HAL_EXPORT bool EVE_Hal_isDevice(EVE_HalContext *phost, size_t deviceIdx)
Check whether the context is the specified device.
EVE_HAL_EXPORT void EVE_Hal_info(EVE_DeviceInfo *deviceInfo, size_t deviceIdx)
Get info of the specified device. Devices of type EVE_HOST_UNKNOWN should be ignored.
EVE_HAL_EXPORT uint32_t EVE_millis()
Get clock in miliseond.
EVE_HAL_EXPORT void EVE_Hal_startTransfer(EVE_HalContext *phost, EVE_TRANSFER_T rw, uint32_t addr)
Start data transfer to Coprocessor.
EVE_HAL_EXPORT void EVE_Hal_hostCommand(EVE_HalContext *phost, uint8_t cmd)
Send a host command to Coprocessor.
EVE_TRANSFER_T
Definition EVE_HalDefs.h:65
@ EVE_TRANSFER_WRITE
Definition EVE_HalDefs.h:68
@ EVE_TRANSFER_READ
Definition EVE_HalDefs.h:67
EVE_HAL_EXPORT void EVE_Hal_setSPI(EVE_HalContext *phost, EVE_SPI_CHANNELS_T numchnls, uint8_t numdummy)
Set number of SPI channel.
EVE_HAL_EXPORT uint32_t EVE_Hal_transferString(EVE_HalContext *phost, const char *str, uint32_t index, uint32_t size, uint32_t padMask)
Transfer a string to EVE platform.
static bool EVE_Hal_supportCmdB(EVE_HalContext *phost)
@ EVE_HOST_MPSSE
EVE_HAL_EXPORT size_t EVE_Hal_list()
List the available devices.
EVE_HAL_EXPORT void EVE_Hal_transferMem(EVE_HalContext *phost, uint8_t *result, const uint8_t *buffer, uint32_t size)
Transfer (read/write) a block data to Coprocessor.
EVE_HAL_EXPORT void EVE_sleep(uint32_t ms)
Sleep in milisecond.
EVE_HAL_EXPORT void EVE_Hal_transferProgMem(EVE_HalContext *phost, uint8_t *result, eve_progmem_const uint8_t *buffer, uint32_t size)
Transfer a block data from program memory.
EVE_HAL_EXPORT void EVE_Hal_restoreSPI(EVE_HalContext *phost)
EVE_HAL_EXPORT void EVE_Hal_endTransfer(EVE_HalContext *phost)
End data transfer.
EVE_HAL_EXPORT void EVE_Hal_flush(EVE_HalContext *phost)
Flush data to Coprocessor.
EVE_HAL_EXPORT void EVE_Hal_hostCommandExt3(EVE_HalContext *phost, uint32_t cmd)
This API sends a 3byte command to the phost.
EVE_HAL_EXPORT uint32_t EVE_Hal_transfer32(EVE_HalContext *phost, uint32_t value)
Write 4 bytes to Coprocessor.
Eve_Hal framework APIs.
bool EVE_HalImpl_open(EVE_HalContext *phost, const EVE_HalParameters *parameters)
Opens a new HAL context using the specified parameters.
bool EVE_HalImpl_defaults(EVE_HalParameters *parameters, size_t deviceIdx)
Get the default configuration parameters.
void EVE_HalImpl_close(EVE_HalContext *phost)
Close a HAL context.
void EVE_HalImpl_initialize()
Initialize HAL platform.
bool EVE_UtilImpl_bootupDisplayGpio(EVE_HalContext *phost)
Display GPIO pins.
void EVE_HalImpl_idle(EVE_HalContext *phost)
Idle. Call regularly to update frequently changing internal state.
void EVE_HalImpl_release()
Release HAL platform.
static uint8_t transfer8(EVE_HalContext *phost, uint8_t value)
Write 8 bit to Coprocessor.
static void rdBuffer(EVE_HalContext *phost, uint8_t *buffer, uint32_t size)
Read a block data from Coprocessor.
unsigned short uint16_t
unsigned int uint32_t
unsigned char uint8_t
Platform selector.
#define eve_assert(cond)
#define eve_printf_debug(fmt,...)
#define eve_debug_break()
static ft_uint32_t ft_uint8_t * buffer
Definition FT_Gpu_Hal.h:139
static ft_void_t ft_uint32_t * cmd
Definition FT_Gpu_Hal.h:184
static ft_uint32_t addr
Definition FT_Gpu_Hal.h:139
uint8_t uint8
Definition LibFT4222.h:66
#define TRUE
Definition Platform.h:197
#define FALSE
Definition Platform.h:198
unsigned long DWORD
Definition ff.h:61
@ FT_IO_ERROR
Definition ftd2xx.h:78
@ FT_OK
Definition ftd2xx.h:74
#define FT_OPEN_BY_SERIAL_NUMBER
Definition ftd2xx.h:102
FTD2XX_API FT_STATUS WINAPI FT_ResetDevice(FT_HANDLE ftHandle)
FTD2XX_API FT_STATUS WINAPI FT_SetBitMode(FT_HANDLE ftHandle, UCHAR ucMask, UCHAR ucEnable)
ULONG FT_STATUS
Definition ftd2xx.h:69
FTD2XX_API FT_STATUS WINAPI FT_Close(FT_HANDLE ftHandle)
PVOID FT_HANDLE
Definition ftd2xx.h:68
FTD2XX_API FT_STATUS WINAPI FT_OpenEx(PVOID pArg1, DWORD Flags, FT_HANDLE *pHandle)
FTD2XX_API FT_STATUS WINAPI FT_Write(FT_HANDLE ftHandle, LPVOID lpBuffer, DWORD dwBytesToWrite, LPDWORD lpBytesWritten)
@ FT_FLAGS_OPENED
Definition ftd2xx.h:1285
#define FT_BITMODE_SYNC_BITBANG
Definition ftd2xx.h:234
FTDI_API FT_STATUS SPI_Write(FT_HANDLE handle, uint8 *buffer, uint32 sizeToTransfer, uint32 *sizeTransfered, uint32 options)
FTDI_API FT_STATUS SPI_GetNumChannels(uint32 *numChannels)
#define SPI_CONFIG_OPTION_CS_ACTIVELOW
#define SPI_CONFIG_OPTION_CS_DBUS3
FTDI_API FT_STATUS SPI_CloseChannel(FT_HANDLE handle)
#define SPI_CONFIG_OPTION_MODE0
#define SPI_TRANSFER_OPTIONS_CHIPSELECT_ENABLE
FTDI_API void Init_libMPSSE(void)
FTDI_API FT_STATUS SPI_InitChannel(FT_HANDLE handle, ChannelConfig *config)
FTDI_API FT_STATUS FT_WriteGPIO(FT_HANDLE handle, uint8 dir, uint8 value)
FTDI_API FT_STATUS SPI_Read(FT_HANDLE handle, uint8 *buffer, uint32 sizeToTransfer, uint32 *sizeTransfered, uint32 options)
FTDI_API FT_STATUS SPI_OpenChannel(uint32 index, FT_HANDLE *handle)
#define SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES
FTDI_API void Cleanup_libMPSSE(void)
FTDI_API FT_STATUS SPI_GetChannelInfo(uint32 index, FT_DEVICE_LIST_INFO_NODE *chanInfo)
#define SPI_TRANSFER_OPTIONS_CHIPSELECT_DISABLE
FTDI_API FT_STATUS SPI_ToggleCS(FT_HANDLE handle, unsigned char state)
char DisplayName[256]
char SerialNumber[16]
EVE_HOST_T Host
uint8_t PowerDownPin
EVE_SPI_CHANNELS_T SpiChannels
EVE_STATUS_T Status
uint8_t SpiDummyBytes
uint32_t OpenedDevices