<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Hdelossantos.com&#187; Professional</title>
	<atom:link href="http://www.hdelossantos.com/category/professional/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.hdelossantos.com</link>
	<description>Tales of the Wisconsin Experience</description>
	<lastBuildDate>Sat, 21 Jan 2012 19:54:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>Creating a Register File using Behavioral Verilog</title>
		<link>http://www.hdelossantos.com/2010/10/18/creating-a-register-file-using-behavioral-verilog/</link>
		<comments>http://www.hdelossantos.com/2010/10/18/creating-a-register-file-using-behavioral-verilog/#comments</comments>
		<pubDate>Mon, 18 Oct 2010 17:58:56 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[Sample Work]]></category>
		<category><![CDATA[behavioral verilog]]></category>
		<category><![CDATA[hardware description language]]></category>
		<category><![CDATA[hdl]]></category>
		<category><![CDATA[register]]></category>
		<category><![CDATA[register file]]></category>
		<category><![CDATA[Verilog]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=701</guid>
		<description><![CDATA[Behavioral Verilog is the most abstract style of Verilog code. The code looks very similar to C, but one has to remember that in hardware operations occur in parallel, and everything is running at once. This sample register file will be a 16 entries by 8-bits per entry. It will have 2 synchronous write ports, [...]]]></description>
			<content:encoded><![CDATA[<p>Behavioral Verilog is the most abstract style of Verilog code. The code looks very similar to C, but one has to remember that in hardware operations occur in parallel, and everything is running at once. </p>
<p>This sample register file will be a 16 entries by 8-bits per entry. It will have 2 synchronous write ports, and an asynchronous read port as well as an active low asynchronous reset.<br />
<span id="more-701"></span><br />
We begin with our module header, parameters, and i/o declarations.</p>
<pre class="brush: verilog; title: ; notranslate">
module register_file(data_out, clk, wr_en_1, wr_en_2, rst, data_in_1, data_in_2,	wr_addr_1, wr_addr_2, rd_addr);

	parameter ENTRIES = 16;
	parameter REG_OFFSET = 8;
	integer i;

	input clk, wr_en_1, wr_en_2, rst;
	input [7:0] data_in_1, data_in_2;
	input [2:0] wr_addr_1, wr_addr_2;
	input [3:0] rd_addr;
	output reg [7:0] data_out;

	reg [7:0] registers [ENTRIES - 1:0];
</pre>
<p>By using parameters we can easily create register files of different sizes by passing new parameter values during instantiation. This can be done as such:</p>
<pre class="brush: verilog; title: ; notranslate">
register_file #(16, 32) reg_file(data_out, clk, wr_en_1, wr_en_2, rst, data_in_1, data_in_2,	wr_addr_1, wr_addr_2, rd_addr);
</pre>
<p>This will instantiate the same module with 16 32-bit entries.</p>
<p>Inside our module in an always block we declare that we want it to execute only in case of a clock&#8217;s positive edge, or a reset&#8217;s negative edge. Since the rest is active low, it will change states from 1->0 (negative edge).</p>
<pre class="brush: verilog; title: ; notranslate">
always @(posedge clk, negedge rst) begin
</pre>
<p>We then take care of our two write ports and reset. If reset is equal to 0, then we need to reset all of the values in the register file. Otherwise if wr_en_1 is 1, we want to write to write port 1, else we want to write to write port 2.</p>
<pre class="brush: verilog; title: ; notranslate">
always @(posedge clk, negedge rst) begin
		if(rst == 1'b0) begin
			for(i = 0; i &lt; ENTRIES; i = i + 1) begin
				registers[i] &lt;= 7'b0;
			end
		end

		else if(wr_en_1)
			registers[wr_addr_1] &lt;= data_in_1;
		else
			registers[REG_OFFSET + wr_addr_2] &lt;= data_in_2;
end
</pre>
<p>That take care of the two synchronous write ports. Since hardware operations occur in parallel, we can have multiple always blocs which will all execute at the same time. For the write port we simply want the always block to be triggered every time the read address (<b>read_addr</b>) changes.</p>
<pre class="brush: verilog; title: ; notranslate">
always @(rd_addr) begin
		data_out = registers[rd_addr];
end
</pre>
<p>And this is the complete code for the register file:<br />
<b>register_file.v</b>:</p>
<pre class="brush: verilog; title: ; notranslate">
module register_file(data_out, clk, wr_en_1, wr_en_2, rst, data_in_1, data_in_2,	wr_addr_1, wr_addr_2, rd_addr);

	parameter ENTRIES = 16;
	parameter REG_OFFSET = 8;
	integer i;

	input clk, wr_en_1, wr_en_2, rst;
	input [7:0] data_in_1, data_in_2;
	input [2:0] wr_addr_1, wr_addr_2;
	input [3:0] rd_addr;
	output reg [7:0] data_out;

	reg [7:0] registers [ENTRIES - 1:0];

	always @(posedge clk, negedge rst) begin
		if(rst == 1'b0) begin
			for(i = 0; i &lt; ENTRIES; i = i + 1) begin
				registers[i] &lt;= 7'b0;
			end
		end

		else if(wr_en_1)
			registers[wr_addr_1] &lt;= data_in_1;
		else
			registers[REG_OFFSET + wr_addr_2] &lt;= data_in_2;
	end

	always @(rd_addr) begin
		data_out = registers[rd_addr];
	end

endmodule
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2010/10/18/creating-a-register-file-using-behavioral-verilog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Talking Twitter</title>
		<link>http://www.hdelossantos.com/2009/10/10/talking-twitter/</link>
		<comments>http://www.hdelossantos.com/2009/10/10/talking-twitter/#comments</comments>
		<pubDate>Sun, 11 Oct 2009 05:58:43 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Computer Engineering]]></category>
		<category><![CDATA[Computer Science]]></category>
		<category><![CDATA[Sample Work]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[array]]></category>
		<category><![CDATA[art]]></category>
		<category><![CDATA[c language]]></category>
		<category><![CDATA[code assignment]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[device programming]]></category>
		<category><![CDATA[file]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[hanly de los santos]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[mobile device]]></category>
		<category><![CDATA[POST]]></category>
		<category><![CDATA[product]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[register]]></category>
		<category><![CDATA[show]]></category>
		<category><![CDATA[speech recognition]]></category>
		<category><![CDATA[speech-to-text]]></category>
		<category><![CDATA[tea]]></category>
		<category><![CDATA[text-to-speech]]></category>
		<category><![CDATA[text2speech]]></category>
		<category><![CDATA[TTS library]]></category>
		<category><![CDATA[tv]]></category>
		<category><![CDATA[tweet]]></category>
		<category><![CDATA[tweets]]></category>
		<category><![CDATA[twitta]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=437</guid>
		<description><![CDATA[A week ago, for my mobile device programming class, I had to add text-to-speech and speech-to-text capabilities to a freely available Android program called Twitta. The features I added were very crudely superimposed on the Twitta interface, therefore this edit is by no means polished or intended for production usage. There are 3 button &#8220;S&#8221;, [...]]]></description>
			<content:encoded><![CDATA[<p>A week ago, for my mobile device programming class, I had to add text-to-speech and speech-to-text capabilities to a freely available Android program called <a href="http://code.google.com/p/twitta/">Twitta</a>. The features I added were very crudely superimposed on the Twitta interface, therefore this edit is by no means polished or intended for production usage.</p>
<p>There are 3 button &#8220;S&#8221;, &#8220;X&#8221;, and &#8220;R&#8221;. &#8220;S&#8221; starts the playback of all of the tweets which are currently displayed on the screen. Once the user scrolls down and new tweets appear on the screen the button can be pressed again and only the new ones will be read. &#8220;X&#8221; stops the playback of the messages. &#8220;R&#8221; prompts the user to speak their tweet. The google speech to text engine converts it to text and is displayed on the edit bar. If the message was wrong, pressing &#8220;R&#8221; again clears it and prompts for new speech. The message can also be edited with the keyboard. Below is a video of the application in action:</p>
<div align="center">
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/gnMUc1TuxpE&#038;hl=en&#038;fs=1&#038;"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/gnMUc1TuxpE&#038;hl=en&#038;fs=1&#038;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></div>
<p><span id="more-437"></span></p>
<p>The source code is below. The sections edited by me are enclosed in comments.</p>
<pre class="brush: plain; title: ; notranslate">
/*
 * Copyright (C) 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.dart.android.twitter;

import java.io.IOException;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.*;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.AdapterContextMenuInfo;

import com.dart.android.twitter.TwitterApi.ApiException;
import com.dart.android.twitter.TwitterApi.AuthException;
import com.google.android.photostream.UserTask;
import com.google.tts.TTS;
import com.google.tts.TTS.InitListener;

public class TwitterActivity extends BaseActivity implements InitListener{
  private static final String TAG = &quot;TwitterActivity&quot;;

  //BEGIN: Added by Hanly De Los Santos
  //Speech
  private static boolean ttsReady = false;
  private static TTS myTTS;
  private static ConcurrentLinkedQueue&lt;String&gt; tweetStrings;
  private Button speak;
  private Button stop;
  private Button reco;
  private static final int VOICE_RECOGNITION_REQUEST_CODE = 1234;
  //END: Added by Hanly De Los Santos

  // Views.
  private ListView mTweetList;
  private TweetAdapter mTweetAdapter;

  private TweetEdit mTweetEdit;
  private ImageButton mSendButton;

  private TextView mProgressText;

  // State.
  private int mState;

  private static final int STATE_ALL = 0;
  private static final int STATE_REPLIES = 1;

  // Tasks.
  private UserTask&lt;Void, Void, RetrieveResult&gt; mRetrieveTask;
  private UserTask&lt;Void, Void, SendResult&gt; mSendTask;
  private UserTask&lt;Void, Void, RetrieveResult&gt; mFollowersRetrieveTask;

  // Refresh data at startup if last refresh was this long ago or greater.
  private static final long REFRESH_THRESHOLD = 5 * 60 * 1000;

  // Refresh followers if last refresh was this long ago or greater.
  private static final long FOLLOWERS_REFRESH_THRESHOLD = 12 * 60 * 60 * 1000;

  private static final String LAUNCH_ACTION = &quot;com.dart.android.twitter.TWEETS&quot;;
  private static final String NEW_TWEET_ACTION = &quot;com.dart.android.twitter.NEW&quot;;

  private static final String EXTRA_TEXT = &quot;text&quot;;

  public static Intent createIntent(Context context) {
    Intent intent = new Intent(LAUNCH_ACTION);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    return intent;
  }

  public static Intent createNewTaskIntent(Context context) {
    Intent intent = createIntent(context);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    return intent;
  }

  public static Intent createNewTweetIntent(String text) {
    Intent intent = new Intent(NEW_TWEET_ACTION);
    intent.putExtra(EXTRA_TEXT, text);

    return intent;
  }

  private boolean isReplies() {
    return mState == STATE_REPLIES;
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //BEGIN: Added by Hanly De Los Santos

    //Initialize TTS Service
    myTTS = new TTS(this, this, true);
    tweetStrings = new ConcurrentLinkedQueue&lt;String&gt;();

    //END: Added by Hanly De Los Santos

    if (!getApi().isLoggedIn()) {
      Log.i(TAG, &quot;Not logged in.&quot;);
      handleLoggedOut();
      return;
    }

    setContentView(R.layout.main);

    Intent intent = getIntent();
    String action = intent.getAction();

    mState = mPreferences.getInt(
        Preferences.TWITTER_ACTIVITY_STATE_KEY, STATE_ALL);

    mTweetList = (ListView) findViewById(R.id.tweet_list);

    mTweetEdit = new TweetEdit((EditText) findViewById(R.id.tweet_edit),
        (TextView) findViewById(R.id.chars_text));
    mTweetEdit.setOnKeyListener(tweetEnterHandler);

    if (NEW_TWEET_ACTION.equals(action)) {
      mTweetEdit.setText(intent.getStringExtra(EXTRA_TEXT));
    }

    mProgressText = (TextView) findViewById(R.id.progress_text);

    mSendButton = (ImageButton) findViewById(R.id.send_button);
    mSendButton.setOnClickListener(new View.OnClickListener() {
      public void onClick(View v) {
        doSend();
      }
    });

    //BEGIN: Added by Hanly De Los Santos
    // Speak Button
    this.speak = (Button)this.findViewById(R.id.Speak);
    this.speak.setOnClickListener(new OnClickListener() {

		@Override
		public void onClick(View v) {
			if(tweetStrings != null){
				new Thread(new Runnable(){
	        		public void run(){
		        		try{
		        			Speak startSpeak = new Speak();
		        	        while(!myTTS.isSpeaking()){
		        	        	for(int i=0; i&lt;tweetStrings.size(); i++){
		        	        		String speak = (String)tweetStrings.poll();
		        		        	startSpeak.speak(ttsReady, myTTS, speak);
		        		        	final String TAG = &quot;Hanly-Pop Out&quot;;
		        		            Log.v(TAG, speak);
		        		        }
		        	        }
		        		}
		        		catch(Exception e){}
	        		}
	        	}).start();
		    }
		}
    });

    this.stop = (Button)this.findViewById(R.id.Stop);
    this.stop.setOnClickListener(new OnClickListener() {

    	@Override
		public void onClick(View v) {
			Speak startSpeak = new Speak();
			startSpeak.stop(ttsReady, myTTS);
		}
    });

    //Start of speech recognition code
    this.reco = (Button)this.findViewById(R.id.Reco);
    this.reco.setOnClickListener(new OnClickListener(){

    	@Override
		public void onClick(View v) {
    		startVoiceRecognitionActivity();
		}
    });
    //END: Added by Hanly De Los Santos

    // Mark all as read.
    getDb().markAllTweetsRead();

    setupState();

    registerForContextMenu(mTweetList);

    boolean shouldRetrieve = false;

    long lastRefreshTime = mPreferences.getLong(
        Preferences.LAST_TWEET_REFRESH_KEY, 0);
    long nowTime = Utils.getNowTime();

    long diff = nowTime - lastRefreshTime;
    Log.i(TAG, &quot;Last refresh was &quot; + diff + &quot; ms ago.&quot;);

    if (diff &gt; REFRESH_THRESHOLD) {
      shouldRetrieve = true;
    } else if (Utils.isTrue(savedInstanceState, SIS_RUNNING_KEY)) {
      // Check to see if it was running a send or retrieve task.
      // It makes no sense to resend the send request (don't want dupes)
      // so we instead retrieve (refresh) to see if the message has posted.
      Log.i(TAG, &quot;Was last running a retrieve or send task. Let's refresh.&quot;);
      shouldRetrieve = true;
    }

    if (shouldRetrieve) {
      doRetrieve();
    }

    long lastFollowersRefreshTime = mPreferences.getLong(
        Preferences.LAST_FOLLOWERS_REFRESH_KEY, 0);

    diff = nowTime - lastFollowersRefreshTime;
    Log.i(TAG, &quot;Last followers refresh was &quot; + diff + &quot; ms ago.&quot;); 

    if (diff &gt; FOLLOWERS_REFRESH_THRESHOLD) {
      doRetrieveFollowers();
    }
  }

//BEGIN: Added by Hanly De Los Santos
  private void startVoiceRecognitionActivity() {
	  mTweetEdit.setText(&quot;&quot;);
	  Intent intent = new Intent(&quot;android.speech.action.RECOGNIZE_SPEECH&quot;);
	  startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
	}

	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == VOICE_RECOGNITION_REQUEST_CODE &amp;&amp; resultCode == RESULT_OK) {
          // Fill the list view with the strings the recognizer thought it could have heard
          ArrayList&lt;String&gt; matches = data.getStringArrayListExtra(
                  RecognizerIntent.EXTRA_RESULTS);
          try{
        	  Thread.currentThread().sleep(1000);//sleep for 1000 ms
        	}
        	catch(Exception ie){
        	//If this thread was interrupted by another thread
        	}
    	  Speak startSpeak = new Speak();
          String speak = &quot;Did you say &quot;+matches.toString();
          startSpeak.speak(ttsReady, myTTS, speak);
          mTweetEdit.setTextAndFocus(matches.toString().replaceAll(&quot;[\\]\\[]&quot;, &quot;&quot;));
          final String TAG = &quot;Hanly-Speak Result&quot;;
          Log.v(TAG, matches.toString());
      }

      super.onActivityResult(requestCode, resultCode, data);
  }
	//END: Added by Hanly De Los Santos
  @Override
  protected void onResume() {
    super.onResume();

    if (!getApi().isLoggedIn()) {
      Log.i(TAG, &quot;Not logged in.&quot;);
      handleLoggedOut();
      return;
    }
  }

  private void doRetrieveFollowers() {
    Log.i(TAG, &quot;Attempting followers retrieve.&quot;);

    if (mFollowersRetrieveTask != null
        &amp;&amp; mFollowersRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      Log.w(TAG, &quot;Already retrieving.&quot;);
    } else {
      mFollowersRetrieveTask = new FollowersTask().execute();
    }
  }

  private static final String SIS_RUNNING_KEY = &quot;running&quot;;

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (mRetrieveTask != null
        &amp;&amp; mRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      outState.putBoolean(SIS_RUNNING_KEY, true);
    } else if (mSendTask != null
        &amp;&amp; mSendTask.getStatus() == UserTask.Status.RUNNING) {
      outState.putBoolean(SIS_RUNNING_KEY, true);
    }
  }

  @Override
  protected void onRestoreInstanceState(Bundle bundle) {
    super.onRestoreInstanceState(bundle);

    mTweetEdit.updateCharsRemain();
  }

  @Override
  protected void onDestroy() {
    Log.i(TAG, &quot;onDestroy.&quot;);

    if (mSendTask != null &amp;&amp; mSendTask.getStatus() == UserTask.Status.RUNNING) {
      // Doesn't really cancel execution (we let it continue running).
      // See the SendTask code for more details.
      mSendTask.cancel(true);
    }

    if (mRetrieveTask != null
        &amp;&amp; mRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      mRetrieveTask.cancel(true);
    }

    // Don't need to cancel FollowersTask (assuming it ends properly).

    super.onDestroy();
  }

  // UI helpers.

  private void updateProgress(String progress) {
    mProgressText.setText(progress);
  }

  private void setupState() {
    Cursor cursor;

    if (isReplies()) {
      cursor = getDb().fetchReplies();
      setTitle(&quot;@&quot; + getApi().getUsername());
    } else {
      cursor = getDb().fetchAllTweets();
      setTitle(R.string.app_name);
    }

    startManagingCursor(cursor);

    mTweetAdapter = new TweetAdapter(this, cursor);
    mTweetList.setAdapter(mTweetAdapter);
  }

  private static final int CONTEXT_MORE_ID = 3;
  private static final int CONTEXT_REPLY_ID = 0;
  private static final int CONTEXT_RETWEET_ID = 1;
  private static final int CONTEXT_DM_ID = 2;

  @Override
  public void onCreateContextMenu(ContextMenu menu, View v,
      ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);

    AdapterView.AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
    Cursor cursor = (Cursor) mTweetAdapter.getItem(info.position);
    long userId = cursor.getLong(cursor
        .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER_ID));
    String user = cursor.getString(cursor
        .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER));

    menu.add(0, CONTEXT_MORE_ID, 0, user);
    menu.add(0, CONTEXT_REPLY_ID, 0, R.string.reply);
    menu.add(0, CONTEXT_RETWEET_ID, 0, R.string.retweet);

    MenuItem item = menu.add(0, CONTEXT_DM_ID, 0, R.string.dm);
    item.setEnabled(getDb().isFollower(userId));
  }

  @Override
  public boolean onContextItemSelected(MenuItem item) {
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    Cursor cursor = (Cursor) mTweetAdapter.getItem(info.position);

    if (cursor == null) {
      Log.w(TAG, &quot;Selected item not available.&quot;);
      return super.onContextItemSelected(item);
    }

    switch (item.getItemId()) {
    case CONTEXT_MORE_ID:
      String who = cursor.getString(
          cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER));
      launchActivity(UserActivity.createIntent(who));

      return true;
    case CONTEXT_REPLY_ID:
      int userIndex = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER);
      // TODO: this isn't quite perfect. It leaves extra empty spaces if you
      // perform the reply action again.
      String replyTo = &quot;@&quot; + cursor.getString(userIndex);
      String text = mTweetEdit.getText();
      text = replyTo + &quot; &quot; + text.replace(replyTo, &quot;&quot;);
      mTweetEdit.setTextAndFocus(text);

      return true;
    case CONTEXT_RETWEET_ID:
      String retweet = &quot;RT @&quot;
          + cursor.getString(cursor
              .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER))
          + &quot; &quot;
          + cursor.getString(cursor
              .getColumnIndexOrThrow(TwitterDbAdapter.KEY_TEXT));
      mTweetEdit.setTextAndFocus(retweet);

      return true;
    case CONTEXT_DM_ID:
      String user = cursor.getString(cursor
          .getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER));
      launchActivity(DmActivity.createIntent(user));
      return true;
    default:
      return super.onContextItemSelected(item);
    }
  }

  private static class TweetAdapter extends CursorAdapter {

    public TweetAdapter(Context context, Cursor cursor) {
      super(context, cursor);

      mInflater = LayoutInflater.from(context);

      mUserTextColumn = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_USER);
      mTextColumn = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_TEXT);
      mProfileImageUrlColumn = cursor
          .getColumnIndexOrThrow(TwitterDbAdapter.KEY_PROFILE_IMAGE_URL);
      mCreatedAtColumn = cursor
          .getColumnIndexOrThrow(TwitterDbAdapter.KEY_CREATED_AT);
      mSourceColumn = cursor.getColumnIndexOrThrow(TwitterDbAdapter.KEY_SOURCE);

      mMetaBuilder = new StringBuilder();
    }

    private LayoutInflater mInflater;

    private int mUserTextColumn;
    private int mTextColumn;
    private int mProfileImageUrlColumn;
    private int mCreatedAtColumn;
    private int mSourceColumn;

    private StringBuilder mMetaBuilder;

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
      View view = mInflater.inflate(R.layout.tweet, parent, false);

      ViewHolder holder = new ViewHolder();
      holder.tweetUserText = (TextView) view.findViewById(R.id.tweet_user_text);
      holder.tweetText = (TextView) view.findViewById(R.id.tweet_text);
      holder.profileImage = (ImageView) view.findViewById(R.id.profile_image);
      holder.metaText = (TextView) view.findViewById(R.id.tweet_meta_text);
      view.setTag(holder);

      return view;
    }

    private static class ViewHolder {
      public TextView tweetUserText;
      public TextView tweetText;
      public ImageView profileImage;
      public TextView metaText;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
      ViewHolder holder = (ViewHolder) view.getTag();

      holder.tweetUserText.setText(cursor.getString(mUserTextColumn));
      Utils.setTweetText(holder.tweetText, cursor.getString(mTextColumn));

    //BEGIN: Added by Hanly De Los Santos
      String say = cursor.getString(mUserTextColumn)+&quot; said &quot;+cursor.getString(mTextColumn);

      while(!tweetStrings.contains(say))
    	  tweetStrings.add(say); 

    // END: Added by Hanly De Los Santos

      String profileImageUrl = cursor.getString(mProfileImageUrlColumn);

      if (!Utils.isEmpty(profileImageUrl)) {
        holder.profileImage.setImageBitmap(TwitterApplication.mImageManager.get(
            profileImageUrl));
      }

      try {
        Date createdAt = TwitterDbAdapter.DB_DATE_FORMATTER.parse(cursor
            .getString(mCreatedAtColumn));
        holder.metaText.setText(Tweet.buildMetaText(mMetaBuilder, createdAt,
            cursor.getString(mSourceColumn)));
      } catch (ParseException e) {
        Log.w(TAG, &quot;Invalid created at data.&quot;);
      }
    }

    public void refresh() {
      getCursor().requery();
    }

  }

  private void draw() {
    mTweetAdapter.refresh();
  }

  private void goTop() {
    mTweetList.setSelection(0);
  }

  private void enableEntry() {
    mTweetEdit.setEnabled(true);
    mSendButton.setEnabled(true);
  }

  private void disableEntry() {
    mTweetEdit.setEnabled(false);
    mSendButton.setEnabled(false);
  }

  // Actions.

  private void doSend() {
    if (mSendTask != null &amp;&amp; mSendTask.getStatus() == UserTask.Status.RUNNING) {
      Log.w(TAG, &quot;Already sending.&quot;);
    } else {
      String status = mTweetEdit.getText().toString();

      if (!Utils.isEmpty(status)) {
        mSendTask = new SendTask().execute();
      }
    }
  }

  private enum SendResult {
    OK, IO_ERROR, AUTH_ERROR, CANCELLED
  }

  private class SendTask extends UserTask&lt;Void, Void, SendResult&gt; {
    @Override
    public void onPreExecute() {
      onSendBegin();
    }

    @Override
    public SendResult doInBackground(Void... params) {
      try {
        String status = mTweetEdit.getText().toString();
        JSONObject jsonObject = getApi().update(status);
        Tweet tweet = Tweet.create(jsonObject);

        if (!Utils.isEmpty(tweet.profileImageUrl)) {
          // Fetch image to cache.
          try {
            getImageManager().put(tweet.profileImageUrl);
          } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
          }
        }

        getDb().createTweet(tweet, false);
      } catch (IOException e) {
        Log.e(TAG, e.getMessage(), e);
        return SendResult.IO_ERROR;
      } catch (AuthException e) {
        Log.i(TAG, &quot;Invalid authorization.&quot;);
        return SendResult.AUTH_ERROR;
      } catch (JSONException e) {
        Log.w(TAG, &quot;Could not parse JSON after sending update.&quot;);
        return SendResult.IO_ERROR;
      } catch (ApiException e) {
        Log.e(TAG, e.getMessage(), e);
        return SendResult.IO_ERROR;
      }

      return SendResult.OK;
    }

    @Override
    public void onPostExecute(SendResult result) {
      if (isCancelled()) {
        // Canceled doesn't really mean &quot;canceled&quot; in this task.
        // We want the request to complete, but don't want to update the
        // activity (it's probably dead).
        return;
      }

      if (result == SendResult.AUTH_ERROR) {
        logout();
      } else if (result == SendResult.OK) {
        onSendSuccess();
      } else if (result == SendResult.IO_ERROR) {
        onSendFailure();
      }
    }
  }

  private void onSendBegin() {
    disableEntry();
    updateProgress(&quot;Updating status...&quot;);
  }

  private void onSendSuccess() {
    mTweetEdit.setText(&quot;&quot;);
    updateProgress(&quot;&quot;);
    enableEntry();
    draw();
    goTop();
  }

  private void onSendFailure() {
    updateProgress(&quot;Unable to update status&quot;);
    enableEntry();
  }

  private void doRetrieve() {
    Log.i(TAG, &quot;Attempting retrieve.&quot;);

    if (mRetrieveTask != null
        &amp;&amp; mRetrieveTask.getStatus() == UserTask.Status.RUNNING) {
      Log.w(TAG, &quot;Already retrieving.&quot;);
    } else {
      mRetrieveTask = new RetrieveTask().execute();
    }
  }

  private void onRetrieveBegin() {
    updateProgress(&quot;Refreshing...&quot;);
  }

  private enum RetrieveResult {
    OK, IO_ERROR, AUTH_ERROR, CANCELLED
  }

  private class RetrieveTask extends UserTask&lt;Void, Void, RetrieveResult&gt; {
    @Override
    public void onPreExecute() {
      onRetrieveBegin();
    }

    @Override
    public void onProgressUpdate(Void... progress) {
      draw();
    }

    @Override
    public RetrieveResult doInBackground(Void... params) {
      JSONArray jsonArray;

      long maxId = getDb().fetchMaxId();

      try {
        jsonArray = getApi().getTimelineSinceId(maxId);
      } catch (IOException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      } catch (AuthException e) {
        Log.i(TAG, &quot;Invalid authorization.&quot;);
        return RetrieveResult.AUTH_ERROR;
      } catch (ApiException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      }

      ArrayList&lt;Tweet&gt; tweets = new ArrayList&lt;Tweet&gt;();
      HashSet&lt;String&gt; imageUrls = new HashSet&lt;String&gt;();

      for (int i = 0; i &lt; jsonArray.length(); ++i) {
        if (isCancelled()) {
          return RetrieveResult.CANCELLED;
        }

        Tweet tweet;

        try {
          JSONObject jsonObject = jsonArray.getJSONObject(i);
          tweet = Tweet.create(jsonObject);
          tweets.add(tweet);
        } catch (JSONException e) {
          Log.e(TAG, e.getMessage(), e);
          return RetrieveResult.IO_ERROR;
        }

        imageUrls.add(tweet.profileImageUrl);

        if (isCancelled()) {
          return RetrieveResult.CANCELLED;
        }
      }

      getDb().addTweets(tweets, false);

      if (isCancelled()) {
        return RetrieveResult.CANCELLED;
      }

      publishProgress();

      for (String imageUrl : imageUrls) {
        if (!Utils.isEmpty(imageUrl)) {
          // Fetch image to cache.
          try {
            getImageManager().put(imageUrl);
          } catch (IOException e) {
            Log.e(TAG, e.getMessage(), e);
          }
        }

        if (isCancelled()) {
          return RetrieveResult.CANCELLED;
        }
      }

      return RetrieveResult.OK;
    }

    @Override
    public void onPostExecute(RetrieveResult result) {
      if (result == RetrieveResult.AUTH_ERROR) {
        logout();
      } else if (result == RetrieveResult.OK) {
        SharedPreferences.Editor editor = mPreferences.edit();
        editor.putLong(Preferences.LAST_TWEET_REFRESH_KEY, Utils.getNowTime());
        editor.commit();
        draw();
        goTop();
      } else {
        // Do nothing.
      }

      updateProgress(&quot;&quot;);
    }
  }

  private class FollowersTask extends UserTask&lt;Void, Void, RetrieveResult&gt; {
    @Override
    public RetrieveResult doInBackground(Void... params) {
      try {
        ArrayList&lt;Long&gt; followers = getApi().getFollowersIds();
        getDb().syncFollowers(followers);
      } catch (IOException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      } catch (AuthException e) {
        Log.i(TAG, &quot;Invalid authorization.&quot;);
        return RetrieveResult.AUTH_ERROR;
      } catch (ApiException e) {
        Log.e(TAG, e.getMessage(), e);
        return RetrieveResult.IO_ERROR;
      }

      return RetrieveResult.OK;
    }

    @Override
    public void onPostExecute(RetrieveResult result) {
      if (result == RetrieveResult.OK) {
        SharedPreferences.Editor editor = mPreferences.edit();
        editor.putLong(Preferences.LAST_FOLLOWERS_REFRESH_KEY, Utils
            .getNowTime());
        editor.commit();
      } else {
        // Do nothing.
      }
    }
  }

  // Menu.

  @Override
  public boolean onCreateOptionsMenu(Menu menu) {
    MenuItem item = menu.add(0, OPTIONS_MENU_ID_REFRESH, 0, R.string.refresh);
    item.setIcon(R.drawable.refresh);

    item = menu.add(0, OPTIONS_MENU_ID_DM, 0, R.string.dm);
    item.setIcon(android.R.drawable.ic_menu_send);

    /*
    item = menu.add(0, OPTIONS_MENU_ID_TOGGLE_REPLIES, 0,
        R.string.show_at_replies);
    item.setIcon(android.R.drawable.ic_menu_zoom);
    */

    return super.onCreateOptionsMenu(menu);
  }

  @Override
  public boolean onPrepareOptionsMenu(Menu menu) {
    /*
    MenuItem item = menu.findItem(OPTIONS_MENU_ID_TOGGLE_REPLIES);

    if (isReplies()) {
      item.setIcon(R.drawable.ic_menu_zoom_out);
      item.setTitle(R.string.show_all);
    } else {
      item.setIcon(android.R.drawable.ic_menu_zoom);
      item.setTitle(R.string.show_at_replies);
    }
    */

    return super.onPrepareOptionsMenu(menu);
  }

  public void toggleShowReplies() {
    mState = mState == STATE_REPLIES ? STATE_ALL : STATE_REPLIES;

    SharedPreferences.Editor editor = mPreferences.edit();
    editor.putInt(Preferences.TWITTER_ACTIVITY_STATE_KEY, mState);
    editor.commit();

    setupState();
  }

  private static final String INTENT_MODE = &quot;mode&quot;;
  private static final int MODE_REPLIES = 1;

  @Override
  public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case OPTIONS_MENU_ID_REFRESH:
      doRetrieve();
      return true;
    case OPTIONS_MENU_ID_REPLIES:
      Intent repliesIntent = new Intent(this, TwitterActivity.class);
      repliesIntent.putExtra(INTENT_MODE, MODE_REPLIES);
      startActivity(repliesIntent);
      return true;
    case OPTIONS_MENU_ID_DM:
      launchActivity(DmActivity.createIntent());
      return true;
    case OPTIONS_MENU_ID_TOGGLE_REPLIES:
      toggleShowReplies();
      return true;
    }

    return super.onOptionsItemSelected(item);
  }

  // Various handlers.

  private View.OnKeyListener tweetEnterHandler = new View.OnKeyListener() {
    public boolean onKey(View v, int keyCode, KeyEvent event) {
      if (keyCode == KeyEvent.KEYCODE_ENTER
          || keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {
        if (event.getAction() == KeyEvent.ACTION_UP) {
          doSend();
        }
        return true;
      }
      return false;
    }
  };

	@Override
	public void onInit(int arg0) {
		ttsReady = true;
	}
}
</pre>
<p>Below is the Speak class which simply takes in a string of text and utilizing the Text-to-Speech synthesizes it.</p>
<pre class="brush: plain; title: ; notranslate">
package com.dart.android.twitter;

import com.google.tts.TTS;

public class Speak {

	public void speak(boolean ttsReady, TTS myTTS, String textToSpeak){
		if (ttsReady) {
			// This param does only work on pre-recorded voice and has no
			// effect on this speak.
			String[] params = { &quot;VOICE_FEMALE&quot; };
			// Speaks the text
			myTTS.speak(textToSpeak, 1, params);
		} 

		else {
			// Notifys the user if the TTS service is not ready or installed
//			Toast.makeText(this, &quot;TTS is not ready or  installed&quot;,
//					Toast.LENGTH_LONG).show();
		}
	}

	public void stop(boolean ttsReady, TTS myTTS){
		myTTS.stop();
	}

}
</pre>
<p>If you want to try the working copy you can download it by clicking the link below.</p>
<p><a href="/school_content/bin/TwitterActivity.apk"><img src="/images/download_now.png"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2009/10/10/talking-twitter/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Previous Work Samples</title>
		<link>http://www.hdelossantos.com/2008/12/22/previous-work-samples/</link>
		<comments>http://www.hdelossantos.com/2008/12/22/previous-work-samples/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 21:04:44 +0000</pubDate>
		<dc:creator>Hanly</dc:creator>
				<category><![CDATA[Sample Work]]></category>

		<guid isPermaLink="false">http://www.hdelossantos.com/?p=366</guid>
		<description><![CDATA[These are PDF files upwards of 30 MB, please use a high speed connection when viewing. Capstone Project (Upgrade High School&#8217;s Network Infrastructure) This is a project my friend, Stacie Gonzalez and I started in order to bring attention to the deplorable condition of the network at our high school (Miami Lakes Educational Center). We [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p><span style="color: #ff0000;">These are PDF files upwards of 30 MB, please use a high speed connection when viewing.</span></p></blockquote>
<ul>
<li><a class="lightview" title=" :: :: menubar: true, width: 800, height: 500" rel="iframe" href="/professional_content/Capstone_FINAL.pdf">Capstone Project (Upgrade High School&#8217;s Network Infrastructure)</a></li>
</ul>
<blockquote><p>This is a project my friend, Stacie Gonzalez and I started in order to bring attention to the deplorable condition of the network at our high school (Miami Lakes Educational Center). We initially started it as a letter and petition to the school&#8217;s principal stating the the weaknesses of the then current infrastructure, which caused daily problems when attempting to get online (The letter is included in the PDF). Our school&#8217;s principal then gave us the task of designing several alternatives to correct the situation, which we made our Capstone Graduation Project. We then presented the design to the CIO of Miami-Dade County Public Schools (M-DCPS) and her subordinates, the administrators of: security, finance, and network infrastructure. Our proposal was then used as the basis for upgrading the school&#8217;s infrastructure. For our work with both the school and the Miami-Dade County Public Schools staff, <a class="lightview" title=" :: :: menubar: true, width: 900, height: 500" rel="iframe" href="http://newsroom.cisco.com/dlls/2006/prod_091206.html">we were awarded the Cisco Networking Academy &#8217;3R&#8217; award</a>.</p></blockquote>
<ul>
<li><a class="lightview" title=" :: :: menubar: true, width: 800, height: 600" rel="iframe" href="/professional_content/ACL_School_Proposal_Documentation.pdf">CAAP Internship Design Project (Design Network for High School)</a></li>
</ul>
<blockquote><p>During an internship with the (M-DCPS) Cisco Academy Apprenticeship Program (CAAP) I led a team of five other students in completing our network design project. We were asked to design a ficticious school and its network. Our design was teh winning design during the 2006 summer intership.</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://www.hdelossantos.com/2008/12/22/previous-work-samples/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.578 seconds -->

