UART Communication with PC Through FTDI

Using VSDSP legacy command line tools.
avizet
Senior User
Posts: 28
Joined: Tue 2021-06-29 11:25

UART Communication with PC Through FTDI

Post by avizet »

HI!
Currently, I'm working on UART communication with VS1010D with FTDI. I'm using the below code to develop a firmware for UART communication but this firmware isn't working. Can anyone please help me to develop UART communication firmware where I can give an input with Tera-Term and as an output return the same value?

Code: Select all


/// \file main.c VS1010D VSOS Executable main file
/// This is a starting point for developing VS1010D DLX libraries and executables

#define USP_TYPE UsbPacket2

#include <usbmachine.h>

#include <vo_stdio.h>
#include <volink.h>     // Linker directives like DLLENTRY
#include <apploader.h>  // RunLibraryFunction etc
#include <vo_gpio.h>
#include <vs1010c.h>
#include <protocol.h>
#include <usblowlib.h>
#include <protocol.h>
#include <scsi.h>
#include <swap.h>
#include <xvm.h>
//#include <lcd.h>
#include <protocol.h>
#include <devboard.h>
#include "configPins.h"
#include "calculate.c"

#include <vs1010dRom.h>

extern struct usbpkt2 usp;


//#include <playerinfo.h>
//#include <string.h>
//#include <lowlevels.h>
//#include <devSdSd.h>

u_int16 b0debounce = 0;
u_int16 b1debounce = 0;
u_int16 b2debounce = 0;

int USEUART0 = 0;

u_int16 flowdebounce = 0;
int FLOWCONTROLON = 1;

#define NOTIFICATION_FRAMERR 1
#define NOTIFICATION_BREAK 2

#define USB_TO_UART 1
#define UART_TO_USB 2

__y const u_int16 csw2[7] = {0xA120, 0x0000, 0x0000, 0x0200, 0x0000}; //"empty notification"
		
/* Final byte in csw
#define CDC_DCD         0x0100	// rx carrier
#define CDC_DSR         0x0200	// tx carrier
#define CDC_BREAK       0x0400    // break reception
#define CDC_RI          0x0800	// ring signal	
#define CDC_FRAME       0x1000    // frame error
#define CDC_PARITY      0x2000    // parity error
#define CDC_OVRRUN      0x4000    // overrun error
*/ 	

__y const u_int16 cswF[7] = {0xA120, 0x0000, 0x0000, 0x0200, 0x1000}; //framing error
__y const u_int16 cswB[7] = {0xA120, 0x0000, 0x0000, 0x0200, 0x0400}; //break

u_int16 lastUSBchar;
u_int16 lastUartchar;

__y u_int16 uart2FifoBuffer[32];
__y struct FIFOY uart2Fifo;
extern __y void* const scsi;
extern __y struct FIFOY usbFifo;

extern __y u_int16 usbFifoBuffer[16];

extern __y u_int16 usbSerialOut[8];
extern u_int32 usbSerialNumber;

void InitUsbHardware();
void ResetUsbHardware();
void PutSector(void);
void UsbSerialPutBytes(__y u_int16 *buf, u_int16 nBytes);
void MyUsbHandler1(void);

void (*myexpection)(u_int16*) = NULL;
void (*fptr_check)(u_int16*, u_int16*) = NULL;
void (*fptr_DCD_DSR)(void) = NULL;


/// Info structure of LCD display state
typedef struct lcdInfoStruct {
	u_int16 width; ///< width of visible area in pixels
	u_int16 height; ///< height of visible area in pixels
	u_int16 x; ///< Optional X coordinate of logical cursor in pixels. Origin is left top corner.
	u_int16 y; ///< Optional Y coordinate of logical cursor in pixels. Origin is left top corner.
	u_int16 textColor; ///< Current text color (RGB565). Used by the console, including printf.
	u_int16 backgroundColor; ///< Current background color (RGB565). Used as the background color for new text output.
	u_int16 charStyle; ///< 0:latin1 7x8, 1:small like vs1000
	u_int16 reserved;
	u_int16 clipx1,clipy1,clipx2,clipy2; ///< Current clipping rectangle (used for setting console text area)
	//u_int16 shadowColor, highlightColor, buttonFaceColor,buttonTextColor;
	u_int16 originX,originY;
	u_int16 *bkStripePtr;
	u_int16 pinA0CS;
} lcdInfo;

extern lcdInfo lcd0;

#ifdef CUSTOM_SERIALNUMBER
void setUSBserialnumber(void){
	FILE *fp = fopen(USB_SERIAL_LOCATION, "rb");
	char *serialnumber;
	s_int32 k;
	char *eptr;
	
	if(fp){
		serialnumber = vo_fgets(serialnumber,9,fp);
		
		#ifdef USEDEBUGPRINTS
		printf("Serialnumber: %s\n", serialnumber);
		#endif
		
		usbSerialNumber = strtoul(serialnumber, &eptr, 8);
		
		UsbSetSerialNumber(usbSerialNumber);
	}
	fclose(fp);
}
#endif
	
void sendBreakFraming(int operation){
	
	switch (operation){
		
		case NOTIFICATION_FRAMERR:
				
			#ifdef USEDEBUGPRINTS
			printf("FRAMING ERROR!\n");
			#endif
			
			usbsender.ep = 2;
			usbsender.bytes = 10;
			usbsender.buf = cswF;
			MyUsbHandler1();
			return;
			
		case NOTIFICATION_BREAK:
		
			#ifdef USEDEBUGPRINTS
			printf("BREAK!\n");
			#endif
			
			usbsender.ep = 2;
			usbsender.bytes = 10;
			usbsender.buf = cswB;
			MyUsbHandler1();
			return;
	}
}


void MyUsbSerialPutCh(register __a0 char c) {
	usbSerialOut[0] = (c<<8);
	usbsender.ep = 3;
	usbsender.bytes = 1;
	usbsender.buf = usbSerialOut;
	while(usbsender.buf) {
		MyUsbHandler1();
	}	
}

u_int16 MyUsbSerialGetCh(void) {
	if (FIFOYEmpty(&usbFifo)) {
		PERIP(USB_EP_ST2) &= ~USB_EP_ST_OSEND_NAK; //Enable one more packet to the endpoint (NEXT_NAK is set)
	}
	while (FIFOYEmpty(&usbFifo)) {
		MyUsbHandler1();
	}
	return FIFOYGet(&usbFifo);
}

IOCTL_RESULT MyUsbConsoleIoctl(register __i0 VO_FILE *self, s_int16 request, IOCTL_ARGUMENT arg) {
	if (request == IOCTL_CHECK_INPUT_AVAILABLE) {
		if (FIFOYEmpty(&usbFifo)) {
			PERIP(USB_EP_ST2) &= ~USB_EP_ST_OSEND_NAK; //Enable one more packet to the endpoint (NEXT_NAK is set)
		}
		MyUsbHandler1();
		return FIFOYFill(&usbFifo);
	}
	return 0;
}

u_int16  MyUsbConsoleWrite (register __i0 VO_FILE *self, void *buf, u_int16 sourceIndex, u_int16 bytes) {
	char c = *(char*)buf;
	MyUsbSerialPutCh(c);
};

u_int16 MyUsbConsoleRead(register __i0 VO_FILE *self, void *buf, u_int16 destinationIndex, u_int16 bytes) {
	*(char*)buf = MyUsbSerialGetCh();
	return 1;
};

const FILEOPS MyUsbConsoleFileOperations = {
	NULL, NULL, MyUsbConsoleIoctl, MyUsbConsoleRead, MyUsbConsoleWrite
};

const SIMPLE_FILE MyusbConsoleFile = {__MASK_FILE | __MASK_OPEN | __MASK_READABLE | __MASK_WRITABLE | __MASK_PRESENT,
	NULL, &MyUsbConsoleFileOperations};
	
__y u_int16 MylineCoding[] = {0x00c2, 0x0100, 0x0000, 0x0800};

extern unsigned char uartRxHasOddChar;


void setParams(u_int16 data[]){
	u_int32 dwDTERate = (((u_int32)data[0] << 16) | (u_int32)data[1]);
	u_int16 bits;
	int i;
	
	for(i = 0; i <= 3; i++){
		MylineCoding[i] = data[i];
	}
	
	dwDTERate = Swap32(dwDTERate);
	bits = calculate(dwDTERate);

	PERIP(UART_DIV) = bits;
	
#ifndef ENABLE_UART2
	PERIP(UART2_DIV) = bits;
#endif

}

__y void *MyDoExpect7Bytes(int k) {
	expectedEP0DataBytes = 7;
	myexpection = &setParams;
	return NULL; //stop handling packet
}


__y void *setDTR_RTS(void) {
#ifdef USE_DTR_RTS_PINS
	u_int16 status = usp.d.data[1] >> 8;
	
	if(!status & 0b11){
		GpioSetPin(DTR_PIN, 0);
		GpioSetPin(RTS_PIN, 0);
		return;
	}
	if(status & 0b1){
		GpioSetPin(DTR_PIN, 1);
	}
	else GpioSetPin(DTR_PIN, 0);
	
	if((status >> 1) & 0b1){
		GpioSetPin(RTS_PIN, 1);
	}
	else GpioSetPin(RTS_PIN, 0);
	
#endif
}


const __y u_int16 MydeviceDescriptorCDC[] = { 
  	//Device Descriptor, NOTE ENDIAN SWAP	
	0x1201,   // bLength | bDescriptorType
	0x1001,   // bcd USB Version (01.10) Low | high
	0x0202,   // bDeviceClass:    Defined in Interface Descriptor
	0x0040,   // bDeviceProtocol: -''-, Endpoint 0 size 64
	0xfb19,   // idVendorL VLSI 0x19fb
	0x0411,   // idProductL 0x1104 
	0x0000,   // bcdDeviceL
	0x0102,   // iManufacturerString
	0x0301    // SerialNumber
};


const __y u_int16 MyconfigurationDescriptorCDC[] = 
	"\p"
	"\x09" //Len
	"\x02" //Type: Conf desc
	"\x43\x00" //Total lenght
	"\x02" //Num of interfaces
	"\x01" //Configuration value
	"\x00" //iConfiguration String (was 0x04)
	"\x80" //Attrib: bus powered
	"\xc8" //400 mA
	
	"\x09" //Len
	"\x04" //Interface desc
	"\x00" //Interface Number 
	"\x00" //Alt setting
	"\x01" //Endpoints
	"\x02" //CDC
	"\x02" //Subclass ACM
	"\x00" //Protocol
	"\x00" //iInterface
	
	"\x05\x24\x00\x10\x01" //Interface:CS, Header Func, version 1.1	
	"\x04\x24\x02\x02" //Interface:ACM, ACM Func Spec, Subset
	"\x05\x24\x06\x00\x01" //Union Functional Descriptor: Interface, Union Func Desc (6), CDC, Data Class
	"\x05\x24\x01\x03\x01" //Call management: Interface, CM(1), DIY(3), data interface(1)
	"\x07\x05\x82\x03\x40\x00\xff" //EP: Notification EP(0x82:IN2) Attibutes(3) MaxPktSize(64), Interval(255)
	"\x09\x04\x01\x00\x02\x0a\x00\x00\x00" //Interface 1, Alt set 0, Endpoints(2), class CDC(10), subclass(0), protocol(0), string(0)
	"\x07\x05\x02\x02\x08\x00\x04" //Endpoint OUT2, Atributes(2)Bulk, 64 bytes, polling int(0)
	"\x07\x05\x83\x02\x08\x00\x04"; //Endpoint IN3, Atributes(2)Bulk, 64 bytes, polling int(0)


const __y void* const Mychapter9[] = { //USB chapter 9 protocol
	1, //IS_CHAPTER_9 // limit reply lenght to that requested by chapter 9 request
// recordLenght, matchWords, {data}*, replyEndpoint, replyLength, SideEffectFn, replyPacketPtr 
	7, 1, 0x0005, 0, 0, DoSetAddress, NULL, //Set address (zero reply, special)
	8, 2, 0x8006, 0x0001,  0, 18, DoNothing, MydeviceDescriptorCDC, //Get device descriptor
	8, 2, 0x8006, 0x0002,  0, 0x43, DoNothing, MyconfigurationDescriptorCDC, //Get configuration descriptor
	8, 2, 0x8006, 0x0003,  0, 4, DoNothing, languageDescriptor,
	8, 2, 0x8006, 0x0103,  0, (VENDOR_NAME_LENGTH * 2 + 2), DoNothing, vendorStringDescriptor,
	8, 2, 0x8006, 0x0203,  0, (MODEL_NAME_LENGTH * 2 + 2), DoNothing, productStringDescriptor,
	8, 2, 0x8006, 0x0303,  0, (SERIAL_NUMBER_LENGTH * 2 + 2), DoNothing, serialNumberDescriptor,
	7, 1, 0x0009, 0, 0, DoResetDataToggles, NULL, //Set any configuration (zero reply)
	8, 2, 0x0201, 0x0000, 0, 0, DoResetDataToggles, NULL, //Clear endpoint halt (zero reply)
	7, 1, 0xa121, 0, 7, DoNothing, MylineCoding, //Get line coding
	7, 1, 0x2122, 0, 0, setDTR_RTS, tenzeros, //Set control line state
	7, 1, 0x2120, 0, 0, MyDoExpect7Bytes, NULL, //Set line coding
	0
};


void Spi1SendWords(u_int16 *p, int words) {
	GpioSetPin(0x17,1);
	GpioSetPin(0x17,0);

	while (words--) {
		while (PERIP(SPI1_STATUS) & SPI_ST_TXRUNNING) {
			// Wait for SPI to become ready
		}
		PERIP(SPI1_DATA) = *p++;
	}
}


s_int16 MyGetUsbPacket() {
	u_int16 tmp,lenW;	
	u_int16 rdptr = PERIP(USB_RDPTR);	
	
	//if ((tmp=UserHook5(0))) return tmp; //Hook for suspend etc. //WITH PATCH, THIS LINE WILL CRASH!

	if (PERIP(USB_ST) & USB_ST_BRST) { //Handle bus reset
		PERIP(USB_ST) |= USB_ST_BRST;
		ResetUsbHardware();
		return -2;
	}

	if (rdptr == PERIP(USB_WRPTR)) return -1; //No new packets in buffer
	usp.prefix = usp.length = USB_MEM(rdptr + USB_RECV_MEM);
	usp.ep = (s_int16)(usp.length & 0x3C00) >> 10;
	usp.length &= 0x03FF;
	//printf("L%d ",usp.length);
	lenW = (usp.length + 1) >> 1;
	tmp = (rdptr + 1) & 0x03FF;
	if (lenW <= (ENDPOINT_SIZE_MAX+1)>>1) {
		RingBufCopyXfromY(usp.d.data, (USB_MEM_TYPE void *)(tmp + USB_RECV_MEM), lenW);
	}

	PERIP(USB_RDPTR) = (lenW + tmp) & 0x03FF;
	PERIP(USB_ST) = (USB_ST_RX /*| SETUP_INFO*/);
	return usp.length;
}


__y u_int16 myUsbFifoBuffer[128];

void MyInitUsbComms() {
	fprintf(&consoleFile,"FifoInit.");
	FIFOYInit(&usbFifo,myUsbFifoBuffer,sizeof(myUsbFifoBuffer));
	memcpyYY (deviceDescriptor, MydeviceDescriptorCDC, sizeof(MydeviceDescriptorCDC));
	chapter9 = Mychapter9; //protocol table
	InitUsbHardware();
	ResetUsbHardware();
}



void MyUsbHandler1() {
	if (MyGetUsbPacket() > 0) {
		
		if ((usp.ep == 0) && (expectedEP0DataBytes)) {
			if (usp.length == expectedEP0DataBytes) {
				
				if(myexpection) myexpection(&usp.d.data);
				myexpection = NULL;
				
				expectedEP0DataBytes = 0;
				SendZLP0();
			}
		} else if (usp.prefix & PREFIX_SETUP) {
			HandlePacket((__y void*)chapter9, usp.d.data); //Setup packet -> handle with chapter 9 protocol
		} /* else if ((usp1.ep == 3) && (usp1.d.data[0] == 0x5553)) { //MSC out (PC->Device) endpoint && SCSI_REQUEST
			csw[2] = usp.d.data[2]; //Get copy of transaction tag
			csw[3] = usp.d.data[3];
			HandlePacket((__y void*)scsi, &usp.d.data[7]); //It's a SCSI protocol packet
		} */ else if ((usp.ep == 2)) { //Serial data in
			u_int16 n = usp.length;
			u_int16 *p = &usp.d.data[0];
			if (n>8) fprintf(&consoleFile,"LARGER THAN 8!");
			//fprintf(&consoleFile,"%d",n);
			PERIP(UART2_DATA) = '0'+n;
			Spi1SendWords(p,4);
			//memset(p,0x4142,8);
			while (n) {
				FIFOYPut(&usbFifo,*p>>8);
				//Uart0PutChar(*p>>8);
				n--;
				if (n) {
					FIFOYPut(&usbFifo,*p&0xff);
					//Uart0PutChar(*p&0xff);
					n--;
				}
				p++;
			}
		}
	}
	UsbSender();
}

#if 0
void MyUsbHandler1() {
	if (MyGetUsbPacket() > 0) {
		
		if ((usp.ep == 0) && (expectedEP0DataBytes)) {
			if (usp.length == expectedEP0DataBytes) {
				
				if(myexpection) myexpection(&usp.d.data);
				myexpection = NULL;
				
				expectedEP0DataBytes = 0;
				SendZLP0();
			}
		} else if (usp.prefix & PREFIX_SETUP) {
			HandlePacket((__y void*)chapter9, usp.d.data); //Setup packet -> handle with chapter 9 protocol
		} else if ((usp.ep == 2)) { //Serial data in
			u_int16 n = usp.length;
			u_int16 *p = &usp.d.data[0];
			if (n>8) fprintf(&consoleFile,"LARGER THAN 8!");
			//fprintf(&consoleFile,"%d",n);
			//Spi1SendWords(p,4);
			memset(p,0x4142,8);
			while (n) {
				FIFOYPut(&usbFifo,*p>>8);
				//Uart0PutChar(*p>>8);
				n--;
				if (n) {
					FIFOYPut(&usbFifo,*p&0xff);
					//Uart0PutChar(*p&0xff);
					n--;
				}
				p++;
			}
		}
	}
	UsbSender();
}
#endif



void MyUsbSerialPutBytes(__y u_int16 *buf, u_int16 nBytes) {
	usbsender.ep = 3;
	usbsender.bytes = nBytes;
	usbsender.buf = buf;
	while(usbsender.buf) {
		MyUsbHandler1();
	}
}

void UartPutChar(char ch){
	if(USEUART0)Uart0PutChar(ch);
	
	#ifdef ENABLE_UART2
	else Uart2PutChar(ch);
	#endif
}

#ifdef USE_CHECKINPUTS
__y void *checkInputs(u_int16 *uartChar, u_int16 *usbChar) {
	if(*uartChar >> 8 == 27) RunLib("reboot", "8");
	if(*(char*)usbChar == 27) RunLib("reboot", "8");
}
#endif


#ifdef USE_DCD_DSR_PINS
__y void *check_DCD_DSR(void){
	if(b1debounce && GpioReadPin(DCD_PIN)) return;
	b1debounce = 0;
	if(b2debounce && GpioReadPin(DSR_PIN)) return;
	b2debounce = 0;
	
	if(GpioReadPin(DCD_PIN)){
		b1debounce = 1;
		
		#ifdef USEDEBUGPRINTS
		printf("DCD\n");
		#endif

		usbsender.ep = 2;
		usbsender.bytes = 10;
		usbsender.buf = csw2;
		
		MyUsbHandler1();
	}
		
	if(GpioReadPin(DSR_PIN)){
		b2debounce = 1;
		
		#ifdef USEDEBUGPRINTS
		printf("DSR\n");
		#endif

		usbsender.ep = 2;
		usbsender.bytes = 10;
		usbsender.buf = csw2;
		
		MyUsbHandler1();
	}
}
#endif


int checkState(void){

	#ifdef WANT_UART_SELECTABLE
	if(b0debounce && !GpioReadPin(UART_SELECTION_PIN)) return 0;
	b0debounce = 0;
	
	if(!GpioReadPin(UART_SELECTION_PIN)){
		b0debounce = 1;
		
		if(!USEUART0){
			USEUART0 = 1;
			
			#ifdef USEDEBUGPRINTS
			printf("\n...Using UART0...\n");
			#endif
			
			PERIP(INT_ENABLE1_LP) &= ~INTF1_UART2_RX;
			PERIP(INT_ENABLE1_HP) &= ~INTF1_UART2_RX;
		}
		else{
			USEUART0 = 0;
			
			#ifdef USEDEBUGPRINTS
			printf("\n...Using UART1...\n");
			#endif
			
			PERIP(INT_ENABLE1_LP) |= INTF1_UART2_RX;
			PERIP(INT_ENABLE1_HP) &= ~INTF1_UART2_RX;
		}		
		return 0;
	}
	#endif	

	#ifdef USE_DCD_DSR_PINS
	if(fptr_DCD_DSR) fptr_DCD_DSR();
	#endif
	
	#ifdef FLOW_SELECT_PIN
	if(flowdebounce && !GpioReadPin(FLOW_SELECT_PIN)) return 0;
	flowdebounce = 0;
	
	if(!GpioReadPin(FLOW_SELECT_PIN)){
		flowdebounce = 1;
		
		if(FLOWCONTROLON == 1) FLOWCONTROLON = 0;
		else FLOWCONTROLON = 1;
		
		#ifdef USEDEBUGPRINTS
		printf("FLOWCONTROL [1 = ON, 0 = OFF]: %i\n", FLOWCONTROLON);	
		#endif	     
	}
	#endif
	
	#ifdef ENABLE_UART2
	if((PERIP(UART2_STATUS) & UART_ST_FRAMERR) && PERIP(UART2_DATA)){
		sendBreakFraming(NOTIFICATION_FRAMERR);
	}
	else if((PERIP(UART2_STATUS) & UART_ST_FRAMERR) && !PERIP(UART2_DATA)){
		sendBreakFraming(NOTIFICATION_BREAK);
	}
	#endif
	
	#ifdef ENABLE_UART0
	if((PERIP(UART_STATUS) & UART_ST_FRAMERR) && PERIP(UART_DATA)){
		sendBreakFraming(NOTIFICATION_FRAMERR);
	}
	else if((PERIP(UART_STATUS) & UART_ST_FRAMERR) && !PERIP(UART_DATA)){
		sendBreakFraming(NOTIFICATION_BREAK);
	}
	#endif
	
	return 0;
}


#ifdef  USE_CTS_RTS_FLOW
int checkRTS_CTS(int n){
	VO_FILE *usbser = (VO_FILE*)&MyusbConsoleFile;
	if(n == 1){
		if(ioctl(usbser,IOCTL_CHECK_INPUT_AVAILABLE,NULL) > 0){	
			GpioSetPin(RTS_PIN, 1);
			
			if(FLOWCONTROLON){
			
				// clear to send
				if(GpioReadPin(CTS_PIN)){
					return 1;
				}
				//not clear to send
				else{
					MyUsbHandler1();
					return 0;
				}
			}
			else return 1;
		}
		else{
			GpioSetPin(RTS_PIN, 0);
			return 0;
		}
	}
	else if(n == 2) return 1;
}
#endif

extern const __y void* const chapter9MSC;
void UsbBootLoopNoReturn(void);


char exitCheckStr[]=" exit!";
int exitCheckN = 1;

int MyUsbSerialDongle(void) {
	VO_FILE *usbser = (VO_FILE*)&MyusbConsoleFile;
	u_int16 nBytes;
	u_int16 i;
	__y u_int16 *p;
	int id;
	
	MyInitUsbComms();


	
	GpioSetAsPeripheral(0x14);
	GpioSetAsPeripheral(0x15);
	GpioSetAsPeripheral(0x16);
	//GpioSetAsPeripheral(0x17);
	GpioSetPin(0x17,1);
	GpioSetPin(0x17,0);

	while(1) {
	

	//DISABLE SPI TV OUT
	PERIP(INT_ENABLE0_HP) &= ~(INTF_SPI1);
	PERIP(INT_ENABLE0_LP) &= ~(INTF_SPI1);
	lcd0.clipy2 = 0;
	SetJmpiHookFunction((void*)102, VoidVoid);
	

		
		#ifdef  USE_CTS_RTS_FLOW
		//cheking rts cts pins
		if(checkRTS_CTS(USB_TO_UART)){
		#else
		if(ioctl(usbser,IOCTL_CHECK_INPUT_AVAILABLE,NULL) > 0){	
			#endif
			lastUSBchar = MyUsbSerialGetCh();
			if (exitCheckN) {				
				if (exitCheckStr[exitCheckN] == '!') {
					if (lastUSBchar == '8') { // Reboot 8 -> USB console
						PERIP(USB_CF) = 0;
						DelayL(100000);
						RunLib("REBOOT","8");
					} else if (lastUSBchar == '4') { // Reboot 4 -> Flash writer
						PERIP(USB_CF) = 0;
						DelayL(100000);
						RunLib("REBOOT","4");
					} else if (lastUSBchar == '!') {
						vo_stdout = &consoleFile; // stdout back to UART
						SimpleShell(); // UART shell
					}
				}
				if (exitCheckStr[exitCheckN] == lastUSBchar) {
					lastUSBchar++;
					exitCheckN++;
				} else {
					exitCheckN = 0;
				}
			} 
			
			#ifdef USE_CHECKINPUTS
			if(fptr_check) fptr_check(NULL, &lastUSBchar);
			#endif
			

			//PERIP(UART_DATA) = lastUSBchar;
			UartPutChar(lastUSBchar); // copy incoming character from usb to uart
		}
		
		#ifdef  USE_CTS_RTS_FLOW
		if(checkRTS_CTS(UART_TO_USB)){
		#else
		{
			#endif
			if(USEUART0)nBytes = FIFOYFill(&uart0Fifo);
			else nBytes = FIFOYFill(&uart2Fifo);
		
			if (nBytes > 7) nBytes = 7;
			p = usbSerialOut;
			i = nBytes;

			
			while (i) {
				
				if(USEUART0){
					*p = FIFOYGet(&uart0Fifo) << 8; i--;
					if (i) {
						*p++ |= FIFOYGet(&uart0Fifo); i--;
					}
				}
				#ifndef ENABLE_UART2
				else{
					*p = FIFOYGet(&uart2Fifo) << 8; i--;
					if (i) {
						*p++ |= FIFOYGet(&uart2Fifo); i--;
					}
				}
				#endif
				
				#ifdef USE_CHECKINPUTS
				lastUartchar = *p;
				if(fptr_check) fptr_check(&lastUartchar, NULL);
				*p = lastUartchar;
				#endif
				
			}
			if (nBytes) MyUsbSerialPutBytes(usbSerialOut,nBytes);
		}
		
		if(checkState()) return 0;
	}
}


#ifndef ENABLE_UART2
#pragma interrupt y 0x31  //UART2 RECEIVE INTERRUPT
void MyUartReceiveInterrupt(void){	
	char ch = PERIP(UART2_DATA);	
	FIFOYPut(&uart2Fifo, ch);
}
#endif



ioresult main (char *params) {

	if (runlevel == 9) {
		vo_StartOS();
	}

	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');
	Uart0PutChar('H');

	printf("TVD\n");
	//Disable SPI1 TV-Out // disable tvout
	PERIP(INT_ENABLE0_LP) &= ~(INTF_SPI1); //Disable TV interrupt
	PERIP(INT_ENABLE0_HP) &= ~(INTF_SPI1); //Disable TV interrupt
	// Disable tv buffer and tv-out
	lcd0.clipy2 = 0;
	SetJmpiHookFunction((void*)102,VoidVoid);  //102=ScreenOutputFunction


	if (runlevel == 4) {
		sdSize = 1;
		VODEV('U') = VODEV('F');
		chapter9 = chapter9MSC;
		UsbBootLoopNoReturn();
	}

	#ifdef ALLOW_ONLY_RUNLEVEL9
	if(runlevel != 9) return S_OK;
	#endif
	
	#ifdef USE_CHECKINPUTS 
	fptr_check = &checkInputs;
	#endif
	
	#ifdef USE_DCD_DSR_PINS
	fptr_DCD_DSR = &check_DCD_DSR;
	#endif
	
	
	//DISABLE SPI TV OUT
	PERIP(INT_ENABLE0_HP) &= ~(INTF_SPI1);
	PERIP(INT_ENABLE0_LP) &= ~(INTF_SPI1);
	lcd0.clipy2 = 0;
	SetJmpiHookFunction((void*)102, VoidVoid);
	

	#ifdef CUSTOM_SERIALNUMBER
	setUSBserialnumber();
	#endif

	#ifdef USE_UART0	
	USEUART0 = 1;
	
	#ifdef USEDEBUGPRINTS
	printf("\n...Using UART0...\n");
	#endif
	
	#else
	USEUART0 = 0;
	
	#ifdef USEDEBUGPRINTS
	printf("\n...Using UART1...\n");
	#endif
	
	#endif

	#ifndef ENABLE_UART2
	FIFOYInit(&uart2Fifo,uart2FifoBuffer,sizeof(uart2FifoBuffer));
	#endif

	MyUsbSerialDongle();
	return S_OK;
}


void fini(void){
	PERIP(INT_ENABLE1_LP) &= ~INTF1_UART2_RX;
	runlevel = 8;
	
	#ifdef USEDEBUGPRINTS
	printf("\n\nExit\n\n");
	#endif
}

Hannu
VLSI Staff
Posts: 550
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: UART Communication with PC Through FTDI

Post by Hannu »

Connect 3.3V USB uart cable to your developer board and you should see boot texts, run default ROM player and you can exit to prompt with enter and execute programs.

After you have working serial connection you can reboot 2 or reboot 14 and copy your programs to SD card over USB and run them from the prompt.

Your code looks like our USB-CDC driver for VS1010. Are you looking for USB-UART software for VS1010 or what is your goal? Because ROM has USB serial console in ROM and 115200 8N1 serial dongle modes available on runlevels 8 and 9.
avizet
Senior User
Posts: 28
Joined: Tue 2021-06-29 11:25

Re: UART Communication with PC Through FTDI

Post by avizet »

Hi Hannu!

Thanks you your replay. Basically, I need to develop the UART serial communication through FTDI connection. I've to access the commend mode in VS1010D where I can control the firmware by external device. Here, I wish to give the command from tera-term or other external app to control the firmware.

I guess this will clear my goal. If need more information then please let me know.
Hannu
VLSI Staff
Posts: 550
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: UART Communication with PC Through FTDI

Post by Hannu »

So you have FTDI USB - serial converter? That's just connecting rx and tx in correct polarities together between the chips.

Or do you need USB console to VS1010? Runlevel 8 is your friend. Runlevel 8 boots VS1010 to USB ACM mode which works win10 and other operating systems.

If you want USB serial to RX0 and TX0, then runlevel 9.
These don't need any support programs and are good for testing purposes. The configuration on runlevel 9 is always 115200,8N1 and on runlevel 8 speed doesn't matter.

If you get those working, you're half way of your goal. Actually on runlevel 8 stdin and stdout work just fine. and you can run something useful as echo hello world on the prompt.

Or are you planning to write FTDI USB - serial converter clone?

So. Do you have minidemoboard, developer board or your own custom board?
avizet
Senior User
Posts: 28
Joined: Tue 2021-06-29 11:25

Re: UART Communication with PC Through FTDI

Post by avizet »

Hi Hannu!

Thanks for the replay.

1. So you have FTDI USB - serial converter?
Yes I have the FTDI USB - serial converter and I want to give command through this communication protocol from external software.
If I'm not wrong there is a built in firmware inside the VS ROM where I can search for any file and run it by giving command on the prompt.

Now, can you please let me know how the software search a file with the given key inside SD card? (by provided firmware inside VS1010 ROM)

2. do you need USB console to VS1010?
No. Currently I'm not looking for USB console.

3. If you want USB serial to RX0 and TX0, then runlevel 9.
I have used both USB serial and FTDI serial to RX0 and TX0 and able to run firmware from SD card and print "Hello World" in Tera-Term.
Currently, I'm searching for file inside SD card but I want to run a method from that dlx file. Is it possible? I mean after running the firmware file the VS1010 will take command and act based on firmware specification rather search for a file as previously do.

4. are you planning to write FTDI USB - serial converter clone?
No. I'm not planning for that at this stage.

5. Do you have minidemoboard, developer board or your own custom board?
Yes. I have the minidemoboard.

Can you please suggest me once the firmware is running on VS1010 then how can I control the inside functionality through prompt?

Thank You.
Hannu
VLSI Staff
Posts: 550
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: UART Communication with PC Through FTDI

Post by Hannu »

VS1010 has some small programs inside ROM and for example dir can list you the disk.

Code: Select all

VS1010>devices
D: SD/SD Card
F: SPI Flash c214
I: STREAM
R: ROMDISK
S: SD/SD Card

VS1010>dir r:
File list of ROMDISK r:*
     1: DEVICES.DLX
     2: DIR.DLX
     3: ECHO.DLX
     4: HELLO.MP3
     5: LIBLIST.DLX
     6: PEEK.DLX
     7: POKE.DLX
     8: REBOOT.DLX
     9: TYPE.DLX
 9 file(s) found.
Then you can use "play r:hello.mp3" to play the file. The play command can also handle play d:music/*.mp3

I wrote simple program which may help you. with 'a' it prints 'd' it lists contents of SD card root, and 'h' says hello. sending esc exits. It shows how to execute other programs with shellcmd() function.

Code: Select all

VS1010>repl
Hello, World!
Case A

HELLO.MP3	ok
File list of SD/SD Card d:*
<snip>

And when you have your system set up ready, you can use S:CONFIG.TXT to run it automatically on your device.
Attachments
repl.zip
Simple UART receiver
(58.59 KiB) Downloaded 358 times
avizet
Senior User
Posts: 28
Joined: Tue 2021-06-29 11:25

Re: UART Communication with PC Through FTDI

Post by avizet »

Hi Hannu!

Thank you so much. It's working and I'll let you know if I require more information.
avizet
Senior User
Posts: 28
Joined: Tue 2021-06-29 11:25

Re: UART Communication with PC Through FTDI

Post by avizet »

Hi Hannu!

Is there any way to read a file data serially through serial communication in VS1010D minidemo board? let's say I have 10 data inside a file and now I want to read that 10 data and show on the prompt screen.

Please let me know.

Thank you.
Hannu
VLSI Staff
Posts: 550
Joined: Mon 2016-05-30 11:54
Location: Finland
Contact:

Re: UART Communication with PC Through FTDI

Post by Hannu »

the type command does exactly this. Prints file to uart.

This is my totally untested implementation of same thing. It can be made faster with some buffer and fgets(), but this is simple.
You have most of the standard f*() functions available to work with files.

And you can have three files open at same time. One is S:CONFIG.TXT if program execution is started from there, second is your own file and third would be the media file.

Code: Select all

FILLE* fp = fopen("D:somefile");
if (fp) {
  while (feof(fp) == S_OK) {
    u_int16 c = fgetc(fp);
    printf("%c", c);
  }
  fclose(fp);
  fp = NULL;
} else {
  // Not open
}
avizet
Senior User
Posts: 28
Joined: Tue 2021-06-29 11:25

Re: UART Communication with PC Through FTDI

Post by avizet »

Hi Hannu!

Thank you again. It's working fine. Currently It's read only the Text File (.txt). I tried with doc file (.docx) but it return encrypted output where the baud rate is 115200. It's not a problem for me right now. I can continue my work with txt file. here is the complete code and with command "r" it will continue to read the file.

N.B: Please keep a readme.txt file in the SD card.

Code: Select all

/// \file main.c VS1010D VSOS Executable main file
/// This is a starting point for developing VS1010D DLX libraries and executables

#include <vo_stdio.h>
#include <volink.h>     // Linker directives like DLLENTRY
#include <apploader.h>  // RunLibraryFunction etc
#include <vs1010dRom.h>
#include <vo_gpio.h>
#include <vs1010c.h>
#include <playerinfo.h>

void readFile(){
	FILE* fp = fopen("D:readme.txt","r");
	if (fp) {
		int i=0;
	  while (feof(fp) == S_OK) {
	    u_int16 c = fgetc(fp);
	    	//if(i>3){
		    printf("%c", c);
			//}
	    i++;
	  }
	  fclose(fp);
	  fp = NULL;
	} else {
	  printf("Not Open");
	}
}


ioresult main (char *params) {
	printf("Hello, World!\n");
	while (1) {
		u_int16 c = fgetc(stdin);
		switch (c) {
		case 'r':
			printf("Case: (Read)  :\n");
			readFile();
			break;
		case 'd':
			shellcmd("dir", "d:");
			break;
		case 'h':
			shellcmd("play", "r:*mp3"); /* Play first found mp3 from R disk */
			break;
		case 27: /* ESC */
			goto end;
		default:
			;
		}
	}
	end:
	return S_OK;
}


Post Reply