Пример #1
0
int
main(void)
{
  uint8_t ui1;

  LCD_init();
  KbdInit();

  /* Enable Global Interrupts */
  sei();

  LCD_bl_on;
  LCD_WR_LINE_NP(0, 0, PSTR("PS2 Kbd: "), 9);
  LCD_refresh();
  _delay_ms(1000);

  for (ui1=0; ; ui1++) {
    if (KBD_HIT) {
      LCD_POS(0, 9);
      LCD_PUTCH(KbdData);
      KBD_RESET_KEY;
    }
//    LCD_POS(0, 11);
//    LCD_PUT_UINT8X(drC);
    LCD_POS(0, 14);
    LCD_PUT_UINT8X(ui1);
//    LCD_POS(1, 0);
//    LCD_PUT_UINT8X(bitC);
//    LCD_PUT_UINT8X(kbdDr[0]);
//    LCD_PUT_UINT8X(kbdDr[1]);
//    LCD_PUT_UINT8X(kbdDr[2]);
//    LCD_PUT_UINT8X(kbdDr[3]);
    LCD_refresh();
    _delay_ms(500);
  }

  return 0;
}
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