//this function sends text to the LCD, with compensation for non-linearity
//write a character to the LCD with wrap to the next line
void LCD_WriteChar(char c){
	HD44780_WriteByte(DATA, c);
	//wrap the cursor at the end of the line
	//1-20, line  1, 0x00-0x13
	//21-40, line 2, 0x40-0x53
	//41-60, line 3, 0x14-0x27 (20)
	//61-80, line 4, 0x54-0x67
	cursorPosition++;
	if (cursorPosition==21 || cursorPosition==41 || cursorPosition==61){
		LCD_CursorPosition(cursorPosition);
	}else if (cursorPosition==81){
		cursorPosition=0;
		LCD_CursorPosition(cursorPosition);
	}
}
示例#2
0
void printPart_lcd() {
    LCD_Clear();
    LCD_CursorPosition(0);

    LCD_WriteString(type_descs[PartSS]);
    if(PartSS == ERROR || PartSS >= NOID) return;

    LCD_WriteINT(part_val);
    LCD_WriteChar(part_unit);
    LCD_CursorPosition(21);

    LCD_WriteString("1:");
    LCD_WriteChar(pins[0]);
    LCD_WriteChar(' ');

    LCD_WriteString("2:");
    LCD_WriteChar(pins[1]);
    LCD_WriteChar(' ');

    LCD_WriteString("3:");
    LCD_WriteChar(pins[2]);
    LCD_WriteChar(' ');
}
//this function redraws the LCD, takes care of scrolling
void LCD_refresh(void){
	static unsigned char searchTerm=0;
	unsigned char i,j,k;
	
	if(trendParser.success==0) return; //don't clear the IP address until we successfully connect to terms feed

	switch(displayMode){
		case IDLE: break;//do nothing
		case UPDATE: //this section draws the basic frame with updating... in the scroll area
			//
			//	Basic screen layout (all lines)
			//
			//clear screen
			LCD_Clear();
			//Write line 1: Trending now:
			LCD_CursorPosition(1);
			LCD_WriteString("Trending now:");
			//write line 3: 
			LCD_CursorPosition(41);
			LCD_WriteString(">Recent tweets");
			//write line 2/4: updating...
			LCD_CursorPosition(21);
			LCD_WriteString("   updating...");
			LCD_CursorPosition(61);
			LCD_WriteString("   updating...");
			searchTerm=0;//reset the local searchTerm index variable that tracks which trend term is presently highlighted
			scrollOffset=0;//clear both scroll offsets
			scrollOffset2=0;
			displayMode=IDLE; //next time, the dislay does nothing
			break;
		case NEWSCROLL: //this draws the highlighted trend term on line three and continues to the scroll function
			//
			//	Update current trend (line 3)
			//
			LCD_CursorPosition(41); //line 3, position 1
			LCD_WriteString("                    ");//clear old term
			LCD_CursorPosition(41);

			//get the start position of the currently highlighted term
			//if it's 0, start at 0, else start at the end of the last term+1
			i=0;
			if(searchTerm!=0) i=trendParser.bufValueEndPosition[(searchTerm-1)];//get start postion (already +1 because of auto increment)
			j=0;
			k=(trendParser.bufValueEndPosition[searchTerm]-1); //save a few operations if we're not optimizing well
			while(i<k){ //repeat untill the end positon //<=
				if(j==20 || i==TREND_PARSER_BUFFER )break; //prevent overruns and line over-writes
				LCD_WriteChar(trendParser.buf[i]); //write the character fromt he buffer to the LCD
				i++;
				j++;
			}
			displayMode=SCROLL; //next time just scroll
		case SCROLL:

			//
			//	Trend scroll	(line 2)
			//
			LCD_CursorPosition(21);//line 2
			scrollPointer=scrollOffset; //adjust the scroll position based on the previous position

			for(i=0; i<20; i++){ //draw 20 characters, offset one from the previous time, loop 0 is we hit the end
				scrollPointer++;
				if(scrollPointer>=trendParser.bufWritePointer || scrollPointer>=TREND_PARSER_BUFFER ) scrollPointer=0;
				LCD_WriteChar(trendParser.buf[scrollPointer]); //write the character to the LCD
			}

			scrollOffset++; //next time start one positon further in the text buffer
				if(scrollOffset>=trendParser.bufWritePointer || scrollOffset>= TREND_PARSER_BUFFER){ //reset at the end, prevent overruns
				scrollOffset=0;
			}

			//
			//	Tweet scroll (line 4)
			//
			if(searchParser.term!=0){//if at least one trend term is populated, scroll the stored tweets (search results)

				LCD_CursorPosition(61);//line 4
				scrollPointer2=scrollOffset2; //get the offset from last time
				//j=searchParser.bufValueEndPosition[searchTerm];//store this so it's easier to get each time

				for(i=0; i<20; i++){ //write 20 characters from the tweet search parser buffer
					scrollPointer2++;
					if((scrollPointer2>searchParser.bufValueEndPosition[searchTerm]) || (scrollPointer2>= SEARCH_PARSER_BUFFER)){
						if(scrollPointer2<searchParser.bufWritePointer)
							LCD_WriteChar(searchParser.buf[scrollPointer2]); //display the next character 	HD44780_WriteByte(DATA, c);
						else
							LCD_WriteChar(' ');//lead out the end of the line end with blanks, don't do a partial repeat
					}else{
						LCD_WriteChar(searchParser.buf[scrollPointer2]); //display the next character
					}

				}

				scrollOffset2++;//increment the scroll offset
				//if we're at the end (10 from the end) or overrun, reset the scroll offset and change the highlighted trend term
				if((scrollOffset2+10)>=searchParser.bufValueEndPosition[searchTerm] || scrollOffset2>= SEARCH_PARSER_BUFFER){
					while(1){
						searchTerm++;//next term
						if(searchTerm==searchParser.term || searchTerm>=MAX_TREND_TERMS){
							searchTerm=0; //if more terms than we have fetched, or more than max, go back to 0
							scrollOffset2=0;//start at beginning next time
							break;//get out of this loop if we're starting over!
						}else{
							if(searchParser.bufValueEndPosition[searchTerm]!=0){
								scrollOffset2=(searchParser.bufValueEndPosition[(searchTerm-1)]);//get the end postion of the next tweet section
								scrollOffset2=scrollOffset2-10;//adjust for continous scroll
								break; //if there's no data for this term, skip it
							}
						}
					}
					displayMode=NEWSCROLL; //update the currently highlighted term next time before scrolling
				}
				
			}//scroll line 4

			break;
	}

}
void twatchTasks(char frameAdvance){ //this state machine services the #twatch

   static enum _twatchState
	{
		TWATCH_INIT=0,
		TWATCH_IDLE,
		TWATCH_TRENDS_TCP_START,
		TWATCH_TRENDS_TCP_SOCKET_OBTAINED,
		TWATCH_TRENDS_TCP_PROCESS_RESPONSE,
		TWATCH_TRENDS_TCP_DISCONNECT,
		TWATCH_SEARCH_TCP_START,
		TWATCH_SEARCH_TCP_SOCKET_OBTAINED,
		TWATCH_SEARCH_TCP_PROCESS_RESPONSE,
		TWATCH_SEARCH_TCP_DISCONNECT,
	} twatchState = TWATCH_INIT; //massive twitter parsing state machine

   static enum _HTTPstatus
	{
		UNKNOWN=0,
		OK,
		ERROR,
	} HTTPstatus = UNKNOWN; //get and track HTTP status and handle errors
	static unsigned char HTTPheaderBuf[20]; //used to store HTTP headers 
	static unsigned char HTTPheaderBufCnt; //pointer

	static BYTE refreshFeeds=0, HTTPretry=0, URLencode[]="%20";//extra static vars for twitter parser

	BYTE 				i,k;
	WORD				w;
	BYTE				vBuffer[51];
	BYTE				cnt;
	static TICK			Timer;
	static TCP_SOCKET	MySocket = INVALID_SOCKET;
	
	if(frameAdvance==1) refreshFeeds++; //counts the minutes

	switch(twatchState)
	{
		case TWATCH_INIT:
			trendParser.success=0; //clear these flag on first run
			searchParser.success=0;//display IP address and info until valid connection
			twatchState=TWATCH_TRENDS_TCP_START; //start TCP data grabber next cycle
			break;
		case TWATCH_IDLE:	//if this variable set, then start the refresh process		
			if(refreshFeeds>TWATCH_REFRESH_INTERVAL){ //if it has been at least 5 minutes, get new trends and tweet search results
				refreshFeeds=0;
				HTTPretry=0; //reset the number of retries
				twatchState=TWATCH_TRENDS_TCP_START; //start TCP data grabber next cycle
			}
			break;
		case TWATCH_TRENDS_TCP_START:
			//connect to twitter server
			MySocket = TCPOpen((DWORD)&ServerName[0], TCP_OPEN_RAM_HOST, ServerPort, TCP_PURPOSE_GENERIC_TCP_CLIENT);
			
			if(MySocket == INVALID_SOCKET) break; //abort if error, try again next time
			
			trendParser.updatingData=1; //updating data flag (probably not used anywhere)
			displayMode=UPDATE; //next LCD refresh will draw the update screen and then idle
			twatchState=TWATCH_TRENDS_TCP_SOCKET_OBTAINED;
			Timer = TickGet();
			break;

		case TWATCH_TRENDS_TCP_SOCKET_OBTAINED:
			// Wait for the remote server to accept our connection request
			if(!TCPIsConnected(MySocket))
			{
				// Time out if too much time is spent in this state
				if(TickGet()-Timer > 5*TICK_SECOND)
				{
					// Close the socket so it can be used by other modules
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					twatchState--;
				}
				break;
			}

			Timer = TickGet();

			if(TCPIsPutReady(MySocket) < 125u) break; //if socket error, break and wait
	
			//form our trending topics JSON datafeed request
			TCPPutROMString(MySocket, (ROM BYTE*)"GET ");
			TCPPutROMString(MySocket, TrendURL); //use the trend URL
			TCPPutROMString(MySocket, (ROM BYTE*)" HTTP/1.0\r\nHost: ");
			TCPPutString(MySocket, ServerName);
			TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n");

			TCPFlush(MySocket); //send HTTP request to Twitter
			
			//setup/clear the parser struct
			trendParser.bufWritePointer=0;
			trendParser.foundTag=0;
			trendParser.tagCharMatchCnt=0;
			trendParser.tagTotalCnt=0;
			trendParser.bufWritePointer=0;
			searchParser.bufWritePointer=0;//reset the tweet buffer write pointer
			searchParser.term=0; //reset the number of terns in the tweet search parser structure
			for(i=0; i<MAX_TREND_TERMS; i++) searchParser.bufValueEndPosition[i]=0;//reset all buffer positions to 0
			HTTPstatus = UNKNOWN; //reset the http status checker
			HTTPheaderBufCnt=0; //status checker buffer counter

			twatchState=TWATCH_TRENDS_TCP_PROCESS_RESPONSE; //next time process any incoming data
			break;

		case TWATCH_TRENDS_TCP_PROCESS_RESPONSE:

			if(!TCPIsConnected(MySocket)) twatchState = TWATCH_TRENDS_TCP_DISCONNECT; //check if we're still connected // Do not break;  We might still have data in the TCP RX FIFO waiting for us
	
			w = TCPIsGetReady(MySocket);//how many bytes waiting?	
	
			//process the server reply
			i = sizeof(vBuffer)-1;
			vBuffer[i] = '\0';
			while(w){
				if(w < i){
					i = w;
					vBuffer[i] = '\0';
				}
				w -= TCPGetArray(MySocket, vBuffer, i);

				for(cnt=0;cnt<i;cnt++){
					//---------------//
					switch(HTTPstatus){ //check the first few bytes for HTTP/1.1 200 OK
						case UNKNOWN: //cache until a line break, then check header for response code before extracting tags
							HTTPheaderBuf[HTTPheaderBufCnt]=vBuffer[cnt];//add to the headerbuf array
							if(HTTPheaderBufCnt<19) HTTPheaderBufCnt++; //if it won't overrun the array, increment the counter
						
							if(vBuffer[cnt]==0x0d){//if current character is a line break, examine the header for the response code
								//is it HTTP?
								if(HTTPheaderBuf[0]=='H' &&	HTTPheaderBuf[1]=='T' && 
								HTTPheaderBuf[2]=='T' && HTTPheaderBuf[3]=='P' ){						
									//loop past /1.x and space
									HTTPheaderBufCnt=4;
									while(HTTPheaderBuf[HTTPheaderBufCnt]!=' '){
										HTTPheaderBufCnt++;
										if(HTTPheaderBufCnt>19) break; //buffer overrun
									}
									HTTPheaderBufCnt++;
									//is it 200? (should be a ASCII->int loop that gets the actual value for error handling.... check for overrun
									if( (HTTPheaderBufCnt <=17 ) && HTTPheaderBuf[HTTPheaderBufCnt]=='2' &&	HTTPheaderBuf[HTTPheaderBufCnt+1]=='0' && 
										HTTPheaderBuf[HTTPheaderBufCnt+2]=='0'){
										HTTPstatus=OK;//200 OK
									}else{
										HTTPstatus=ERROR; //other status, error
									}
								}
							}
							break;
						case OK: //HTTP is OK, process the byte
							procTrend(vBuffer[cnt]); //json parsing state maching
							break;
						case ERROR://do nothing because we need to clear the buffer
							break;
					}
					//------------------//
				}//for loop
				
				if(twatchState == TWATCH_TRENDS_TCP_PROCESS_RESPONSE) break;
			}//while
	
			break;
	
		case TWATCH_TRENDS_TCP_DISCONNECT:
			TCPDisconnect(MySocket); //close the socket
			MySocket = INVALID_SOCKET;
	
			//did not get valid HTML, retry, got no tags, retry
			if(HTTPstatus!=OK || trendParser.tagTotalCnt==0 ){
				HTTPretry++;
				if(HTTPretry>HTTP_MAX_RETRY){//retry 3 times, then wait a minute....
					twatchState = TWATCH_IDLE;
					LCD_CursorPosition(21); //display waiting error
					LCD_WriteString("*Error, waiting 5min");
					break;
				}
				LCD_CursorPosition(21); //display retry error
				LCD_WriteString("*Error, reconnecting");
				twatchState = TWATCH_TRENDS_TCP_START;
				break;
			}
			HTTPretry=0;
		
			addToTrendBuffer(' ');//add trailing space
			
			trendParser.updatingData=0; //data update complete, clear update flag
			if(trendParser.success==0){ //if this is the first time throuigh, set the success flag
				trendParser.success=1; //set success flag, used to identify the very first successful xfer and clear IP address screen
				LCD_refresh(); //clear IP, show update screen
			}
			displayMode=NEWSCROLL;//start scrolling the terms, tweets will show when available in the parser struct
			twatchState = TWATCH_SEARCH_TCP_START; //will start searching on each term next time. searchParser.term set to 0 above...
			break;

		case TWATCH_SEARCH_TCP_START: //begins searching for recent tweets for each trending term
			
			//don't continue if there's no more term, an error, or overrun
			if(searchParser.term>=trendParser.tagTotalCnt || searchParser.term>=MAX_TREND_TERMS ){//don't continue if there's no more terms left to search
				twatchState = TWATCH_IDLE; //go back to idle
				break;
			}
			
			//skip if 0 length term
			if(trendParser.bufValueStartPosition[searchParser.term]==trendParser.bufValueEndPosition[searchParser.term]) {
				searchParser.term++; //increment to next trend term
				twatchState = TWATCH_SEARCH_TCP_START; //try again with the next trend term
				break;
			}
		
			//connect to twitter
			MySocket = TCPOpen((DWORD)&ServerName[0], TCP_OPEN_RAM_HOST, ServerPort, TCP_PURPOSE_GENERIC_TCP_CLIENT);

			if(MySocket == INVALID_SOCKET) break; //abort on error

			twatchState=TWATCH_SEARCH_TCP_SOCKET_OBTAINED;
			Timer = TickGet();
			break;

		case TWATCH_SEARCH_TCP_SOCKET_OBTAINED:
			// Wait for the remote server to accept our connection request
			if(!TCPIsConnected(MySocket)){
				// Time out if too much time is spent in this state
				if(TickGet()-Timer > 5*TICK_SECOND){
					// Close the socket so it can be used by other modules
					TCPDisconnect(MySocket);
					MySocket = INVALID_SOCKET;
					twatchState--;
					//searchParser.term++; //increment to next trend term, don't get stuck in loop
										//should add retries
				}
				break;
			}

			Timer = TickGet();

			if(TCPIsPutReady(MySocket) < 125u) break; //socket ready for writes?

			
			TCPPutROMString(MySocket, (ROM BYTE*)"GET "); //setup the HTTP GET request 
			TCPPutROMString(MySocket, SearchURL);	//JSON search datafeed URL
			#ifndef JSON_DEBUG
			//add the search term to the JSON search URL. Requires urlencoding
			i=trendParser.bufValueStartPosition[searchParser.term]; //get the starting position of the term in the trend term buffer
			k=trendParser.bufValueEndPosition[searchParser.term]-1; //end position is one less because of auto increment
			//add each character of the trend term to the search URL
			while((i<k) && i<TREND_PARSER_BUFFER ){ //append each byte to the URL until the end position
				//URLencode anything not a-zA-Z0-9 -_.!~*'()
				if(URLencodeChar(trendParser.buf[i], &URLencode[0])==0){
					TCPPut(MySocket, trendParser.buf[i]); //no URLencode required;
				}else{
					TCPPutString(MySocket, URLencode); //use the URLencoded character now in URLencode array
				}
				i++;
			}
			#endif
			//form the rest of the HTTP request
			TCPPutROMString(MySocket, (ROM BYTE*)" HTTP/1.0\r\nHost: ");
			TCPPutString(MySocket, ServerName);
			TCPPutROMString(MySocket, (ROM BYTE*)"\r\nConnection: close\r\n\r\n");

			TCPFlush(MySocket); //send the HTTP request to the Twitter server

			//setup the search parser struct
			searchParser.foundTag=0;
			searchParser.tagCharMatchCnt=0;
			searchParser.tagTotalCnt=0;
			searchParser.escape=0;
			HTTPstatus = UNKNOWN; //clear the HTTP status checker
			HTTPheaderBufCnt=0;

			addToSearchBuffer(0xff); //add beginning block to the text

			twatchState=TWATCH_SEARCH_TCP_PROCESS_RESPONSE;
			break;

		case TWATCH_SEARCH_TCP_PROCESS_RESPONSE:
			if(!TCPIsConnected(MySocket)) twatchState = TWATCH_SEARCH_TCP_DISCONNECT; //check for connection // Do not break;  We might still have data in the TCP RX FIFO waiting for us
	
			w = TCPIsGetReady(MySocket);	//how many bytes waiting?
	
			i = sizeof(vBuffer)-1;
			vBuffer[i] = '\0'; //add trailing 0 to array.

			while(w){ //process server reply
				if(w < i){
					i = w;
					vBuffer[i] = '\0';
				}
				w -= TCPGetArray(MySocket, vBuffer, i);

				for(cnt=0;cnt<i;cnt++){
					//---------------//
					switch(HTTPstatus){
						case UNKNOWN: //check header for response code before extracting tags
							HTTPheaderBuf[HTTPheaderBufCnt]=vBuffer[cnt];//add to the headerbuf array
							if(HTTPheaderBufCnt<19) HTTPheaderBufCnt++; //if it won't overrun the array, increment the counter
						
							if(vBuffer[cnt]==0x0d){//current character is a line break, examine the header for the response code
								//is it HTTP?
								if(HTTPheaderBuf[0]=='H' &&	HTTPheaderBuf[1]=='T' && 
								HTTPheaderBuf[2]=='T' && HTTPheaderBuf[3]=='P' ){						
									//loop past /1.x and space
									HTTPheaderBufCnt=4;
									while(HTTPheaderBuf[HTTPheaderBufCnt]!=' '){
										HTTPheaderBufCnt++;
										if(HTTPheaderBufCnt>19) break; //buffer overrun
									}
									HTTPheaderBufCnt++;
									//is it 200? (should be a ASCII->int loop that gets the actual value for error handling....
									if( ((HTTPheaderBufCnt+2) < 20) && HTTPheaderBuf[HTTPheaderBufCnt]=='2' &&	HTTPheaderBuf[HTTPheaderBufCnt+1]=='0' && 
										HTTPheaderBuf[HTTPheaderBufCnt+2]=='0'){
										HTTPstatus=OK;
									}else{
										HTTPstatus=ERROR;
									}
								}
							}
							break;
						case OK:
							procSearch(vBuffer[cnt]);
							break;
						case ERROR://do nothing because we need to clear the buffer
							break;
					}
					//------------------//
				}//for loop
				
				if(twatchState == TWATCH_SEARCH_TCP_PROCESS_RESPONSE) break;
			}//while
	
			break;
	
		case TWATCH_SEARCH_TCP_DISCONNECT:
			TCPDisconnect(MySocket); //close the socket
			MySocket = INVALID_SOCKET;

			//did not get valid HTML, retry, got no tags, retry once if no tags
			if(HTTPstatus!=OK ){
				HTTPretry++;
				if(HTTPretry>HTTP_MAX_RETRY){//retry, then wait till next time...
					twatchState = TWATCH_IDLE;
					break;
				}
				twatchState = TWATCH_SEARCH_TCP_START;
				break;
			}
			HTTPretry=0; //success, clear number or retries

			//repeat for each trend term
			searchParser.success=1;
			searchParser.term++;
			twatchState = TWATCH_SEARCH_TCP_START;
			break;

	}//switch
	
}//function
示例#5
0
void LCD_ExitCGRAM(void){ LCD_CursorPosition(cursorPosition);}
void main(void){  
	unsigned char i,cmd, param[9], tmp; 
	unsigned long lhfe;
	//unsigned char t[]={"Hello World"};

    init();			//setup the crystal, pins

	Delay_MS(10);	

	HD44780_Reset();//setup the LCD
	HD44780_Init();
	//LCD_Backlight(1);//turn it on, we ignore the parameter

LCD_CursorPosition(0);
LCD_WriteString("Part Ninja v0.0a");
LCD_CursorPosition(21);
LCD_WriteString("      testing...");

	while(1){
		PartType=0;
		PartMode=0;
		RepeatDetect=0;
		checkpins(0, 1, 2); //CBE npn --
		checkpins(0, 2, 1); //CBE npn
		checkpins(1, 0, 2); //CBE npn --
		checkpins(1, 2, 0); //CBE npn
		checkpins(2, 0, 1); //CBE npn
		checkpins(2, 1, 0); //CBE npn

		if(PartType==PART_TRANSISTOR){
			if(RepeatDetect==0){
				hfe[1] = hfe[0];
				vBE[1] = vBE[0];
			}

			if(hfe[0]>hfe[1]){
				hfe[1] = hfe[0];
				vBE[1] = vBE[0];
				tmp = c;
				c = e;
				e = tmp;
			}

			lhfe = hfe[1];

			lhfe *= (((unsigned long)4700 * 100) / (unsigned long)680);	//Verhältnis von High- zu Low-Widerstand

			if(vBE[1]<11) vBE[1] = 11;
			lhfe /= vBE[1];
			hfe[1] = (unsigned int) lhfe;

			LCD_Clear();
			LCD_CursorPosition(0);
			if(PartMode == PART_MODE_NPN) {
				LCD_WriteString("NPN ");
			} else if (PartMode==PART_MODE_PNP) {
				LCD_WriteString("PNP ");
			}
			LCD_WriteString("  hFE:");	
			LCD_WriteByteVal(hfe[1]);

			LCD_CursorPosition(21);
			LCD_WriteString("C=");
			LCD_WriteChar(c+0x31);
			LCD_WriteString(" B=");
			LCD_WriteChar(b+0x31);
			LCD_WriteString(" E=");			
			LCD_WriteChar(e+0x31);

		}else if(PartType==PART_FET){

			LCD_Clear();
			LCD_CursorPosition(0);
			if(PartMode == PART_MODE_NPN) {
				LCD_WriteString("N-");
			} else if (PartMode==PART_MODE_PNP) {
				LCD_WriteString("P-");
			}
			LCD_WriteString("FET ");

			f=gthvoltage;
			f=((f)/1024)*5;
			gthvoltage=f;
			LCD_WriteString("  Vth:");
			LCD_WriteByteVal(gthvoltage);
			//lcd_data('m');
			LCD_WriteString("v");

			LCD_CursorPosition(21);
			LCD_WriteString("G=");
			LCD_WriteChar(b+0x31);
			LCD_WriteString(" D=");
			LCD_WriteChar(c+0x31);
			LCD_WriteString(" S=");			
			LCD_WriteChar(e+0x31);



		}

	}


}//end main
void main(void){  
	unsigned char i,cmd, param[9]; 
	//unsigned char t[]={"Hello World"};

    init();			//setup the crystal, pins
	usbbufflush();	//setup the USB byte buffer

delayMS(10);	

	HD44780_Reset();//setup the LCD
	HD44780_Init();

    USBDeviceInit();//setup usb

    while(1){

        USBDeviceTasks(); 

    	if((USBDeviceState < CONFIGURED_STATE)||(USBSuspendControl==1)) continue;
		usbbufservice();//load any USB data into byte buffer
		
		cmd=waitforbyte();//wait for a byte from USB

		if(cmd!=MATRIX_ORBITAL_COMMAND){//assume text, if 254 then enter command mode

			LCD_WriteChar(cmd); //not a command, just write it to the display

		}else{//previous byte was 254, now get actual command

			switch(waitforbyte()){//switch on the command
				case BACKLIGHT_ON: //1 parameter (minutes 00=forever)
					param[0]=waitforbyte();
					LCD_Backlight(1);//turn it on, we ignore the parameter
					break;
				case BACKLIGHT_OFF:
					LCD_Backlight(0);//backlight off
					break;
				case CLEAR:
					LCD_Clear();
					break;
				case HOME:
					LCD_Home();
					break;
				case POSITION: //2 parameters (col, row)
					param[0]=waitforbyte();
					param[1]=waitforbyte();
					cmd=( ((param[1]-1)*20) + param[0] ); //convert to 20x4 layout (used defined lines, add rows...)
					LCD_CursorPosition(cmd);
					break;
				case UNDERLINE_CURSER_ON:
					LCD_UnderlineCursor(1);
					break;
				case UNDERLINE_CURSER_OFF:
					LCD_UnderlineCursor(0);
					break;
				case BLOCK_CURSER_ON:
					LCD_BlinkCursor(1);
					break;
				case BLOCK_CURSER_OFF:
					LCD_BlinkCursor(0);
					break;
				case BACKLIGHT_BRIGHTNESS://1 parameter (brightness)
					param[0]=waitforbyte();					
					break;
				case CUSTOM_CHARACTER: //9 parameters (character #, 8 byte bitmap)
					LCD_WriteCGRAM(waitforbyte());//write character address
					for(i=1; i<9; i++){
						LCD_WriteRAM(waitforbyte()); //send 8 bitmap bytes
					}
					break;
				default: //error
					break;
			}
		}
	    CDCTxService();
	}

}//end main