<?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>pablo estrada</title>
	<atom:link href="http://www.pabloestrada.us/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pabloestrada.us</link>
	<description></description>
	<lastBuildDate>Mon, 05 Mar 2012 05:02:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>A simple AM/FM radio</title>
		<link>http://www.pabloestrada.us/2012/03/a-simple-amfm-radio/</link>
		<comments>http://www.pabloestrada.us/2012/03/a-simple-amfm-radio/#comments</comments>
		<pubDate>Mon, 05 Mar 2012 05:02:29 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[Arduino]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=311</guid>
		<description><![CDATA[I&#8217;ve been working on building a simple AM/FM radio, operated through just a few buttons and knobs, and with decent audio quality. It has a simple display and fits in a fairly compact package, more or less the size of hardcover book. Not long ago, I would have built a traditional receiver design using discrete [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on building a simple AM/FM radio, operated through just a few buttons and knobs, and with decent audio quality. It has a simple display and fits in a fairly compact package, more or less the size of hardcover book.</p>
<br />
<p>Not long ago, I would have built a traditional receiver design using discrete components, probably a <a href="http://en.wikipedia.org/wiki/Superheterodyne_receiver" target="_blank">superheterodyne</a> (used in the vast majority of inexpensive alarm clocks and portable AM/FM radios lying around in homes) or perhaps a <a href="http://en.wikipedia.org/wiki/Regenerative_circuit" target="_blank">regenerative receiver</a> for novelty. Today, the popularity of small, digital, low-cost devices with integrated AM/FM radios has driven more parts of the radio into integrated circuits (though often keeping the superheterodyne design).</p>
<br />
<p><strong>Radio hardware</strong></p>
<p>I was excited to find the <a href="http://www.silabs.com/products/audiovideo/amfmreceivers/Pages/default.aspx" target="_blank">Silicon Labs Si473x</a> family of radio ICs. The <a href="http://www.silabs.com/products/audiovideo/amfmreceivers/Pages/Si473435.aspx" target="_blank">Si4735</a> includes AM/FM/SW/LW reception in a single IC that requires just a few external components and two external antennas. Essentially, the chip replaces what traditionally requires a few dozen discrete components and it eliminates manual adjustment of tuning sub-circuits.</p>
<br />
<p>The reduced bill of materials doesn&#8217;t simplify everything. Instead of sourcing, assembling, and tuning discrete RF/IF components, the radio IC must be interfaced over a serial, 2-wire, or 3-wire connection. Silicon Labs provides guidance through its datasheet and a few application notes, but I found some steps, such as the power-on sequence, could have been more clearly documented.</p>
<br />
<p><a href="http://sparkfun.com/" target="_blank">Sparkfun</a> sells the Si4735 AM/FM IC and an <a href="http://www.sparkfun.com/products/10342" target="_blank">Arduino shield</a> that includes the IC, a crystal, and a few components that support the AM and FM antennas. Using the shield absolves one of any SMD soldering or source the diodes, crystals, and inductors that support the chip.</p>
<br />
<p>Sparkfun wrote some code to help users get started with the shield, and a few others have extended it and added some very cool features, such as querying the IC to get its current frequency and adding RDBS processing to get FM station and programming information off the air. Wagner Sartori Junior (<a href="http://wiki.wsartori.com/wiki/Trunet_Radio" target="_blank">Trunet</a>) and <a href="http://carrierfrequency.blogspot.com/2011/08/si4735-amfmswlw-radio-project.html" target="_blank">Jon Carrier</a> added quite a bit of this functionality, so it&#8217;s thanks to them and Sparkfun that getting the Si4735 up and running with these cool features is so easy.</p>
<br />
<p><strong>Other hardware</strong></p>
<p>I needed some other hardware besides the Si4735 shield and Arduino board. For the display I used a serial enabled white-on-black 16&#215;2 character <a href="http://www.sparkfun.com/products/9067" target="_blank">LCD display</a>. A <a href="http://www.sparkfun.com/products/9117" target="_blank">rotary encoder</a> is used as the tuning knob and band-switching push button, and a simple 10 kΩ potentiometer controls the volume. The Si4735 support volume adjustments via software, but I chose an analog potentiometer for simplicity.</p>
<br />
<p>The Si4735 shield outputs a very small audio signal (I haven&#8217;t tried to measure it yet), so an off-shield audio amplifier is mandatory. I opted for a mono amplifier based on a single <a href="http://www.onsemi.com/PowerSolutions/product.do?id=NE5534" target="_blank">NE5534</a> op amp. It has good performance, is reasonably priced, and doesn&#8217;t require too many supporting components. I considered adding stereo support but the radio didn&#8217;t require very high quality FM output, and there is a stereo headphone jack in case it&#8217;s really desired. The circuit I used is from <a href="http://www.electronics-diy.com/" target="_blank">http://www.electronics-diy.com/</a></p>

<div id="attachment_337" class="wp-caption alignnone" style="width: 720px"><a href="http://www.pabloestrada.us/media/2012/02/DSC_6251-copy.jpg"><img class="size-full wp-image-337" title="Arduino, shield, and LCD" src="http://www.pabloestrada.us/media/2012/02/DSC_6251-copy.jpg" alt="" width="710" height="589" /></a><p class="wp-caption-text">Arduino, shield, and LCD</p></div>

<br />
<p><strong>Software</strong></p>
<p>Jon Carrier&#8217;s code is <a href="https://github.com/jjcarrier/Si4735" target="_blank">hosted on Github</a> and includes example sketches. I played with them quite a bit before using bits and pieces in my own sketch. Jon put a lot of effort into making RDBS work, and while it&#8217;s quite cool to see the station and song information scroll across the screen, I don&#8217;t use it. I do like to see the station&#8217;s callsign, so I kept this part and display the callsign on the second line of the LCD display. Many stations don&#8217;t transmit RDBS data, so in case the station callsign is unknown, my LCD doesn&#8217;t display any information on the second line. I also removed the volume and seek states, since I&#8217;m handling the volume level through an analog potentiometer and I don&#8217;t care for a separate seek mode at this time (perhaps I will later).</p>
<br />
<p>I experienced a few of the issues that have been brought up in the comments on <a href="http://carrierfrequency.blogspot.com/2011/08/si4735-amfmswlw-radio-project.html" target="_blank">Jon&#8217;s page</a>. In particular, I frequently saw the system start or very quickly jump to its initial frequency + 0.1 MHz, and I also found the LCD screen locking up when I turned the rotary encoder very quickly. I used a serial connection of 9600 baud (the default value for the serial enabled LCD) and I wasn&#8217;t able to really troubleshoot this behavior. I&#8217;ve read in a few places that these LCDs can lock up when they receive data too quickly, so my wild guess is that this was somehow happening, perhaps from other things coming unintentionally on the serial line. A few times I also reproduced the 655.3 MHz and 0.0 MHz frequency change that Jon mentioned, even though the code is supposed to restrict the frequency to the broadcast band range when using the rotary encoder for tuning. It seems some of these issues may come from the rotary encoder, debouncing (or lack thereof), and/or the rotary callback function.</p>
<br />
<p>There are many sample rotary encoder implementations, some using interrupts, some using the digitalRead function in the main loop, and so on. Since the tuning knob and responsiveness is so central to the radio&#8217;s operation, I wanted to make sure the rotary encoder&#8217;s data was reliably read and displayed on the LCD, even for very fast rotation rates. I made a separate sketch to prototype this part of the system and ended up using Arduino&#8217;s built-in interrupts based on the code found <a href="http://home.online.no/~togalaas/rotary_encoder/" target="_blank">here</a>. Once this was working on its own, I integrated it as the interrupt and callback in the radio sketch.</p>
<br />
<p><strong>An important note about using the shield</strong></p>
<p><strong></strong>The Si4735 and the shield communicate through 3.3V, not the 5V that boards like the Arduino Uno, Duemilanove, and Diecimilia expect. This is documented in the comments of the Sparkfun product page and on a few forums/blogs. The two generally accepted workarounds are to:</p>
<ol>
	<li><a href="http://arduino.cc/forum/index.php?topic=66554.0" target="_blank">Insert a silicon diode</a> between pin D12 and the GPO1 line on the shield. Trunet also documents how to do this on his <a href="http://wiki.wsartori.com/wiki/Trunet_Radio" target="_blank">wiki</a>.</li>
	<li><a href="http://www.ka1kjz.com/?p=1331" target="_blank">Use a level-shifter</a> to convert between 3.3V and 5V signals.</li>
</ol>
<p>Both are hacks for using the shield with 5V Arduino boards and require a bit of surgery in severing a trace on the shield. Using the level-shifter is the more &#8220;robust&#8221; approach and I chose this because it gives the flexibility to send and receive SPI commands to the Si4735. Inserting the silicon diode allows reading SPI data, but not writing it. However, it takes up space on the shield and limits the possibility of adding other components on top of it. Another issue with the shield is that it connects the GND and AREF pins &#8211; meaning AREF is permanently tied to ground, unless you break that connection. This is important if you need to use the Arduino&#8217;s analog pins.</p>
<br />
<p><strong>Next steps</strong></p>
<p>The radio works as designed, the audio amplifier is built out on a protoboard (and is certainly loud enough), and the display and tuning are smooth, so all that&#8217;s left is to connect the power supply, mount the components inside the enclosure, which is made from <a href="http://www.ampersandart.com/hardbord.html" target="_blank">Ampersand Hardbord</a>. The tuning knobs are simple diamond knurled cylindrical knobs <a href="http://search.digikey.com/scripts/DkSearch/dksus.dll?WT.z_header=search_go&amp;lang=en&amp;site=us&amp;keywords=226-3130-ND&amp;x=0&amp;y=0" target="_blank">from Digikey</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2012/03/a-simple-amfm-radio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Conferencing</title>
		<link>http://www.pabloestrada.us/2010/12/conferencing/</link>
		<comments>http://www.pabloestrada.us/2010/12/conferencing/#comments</comments>
		<pubDate>Fri, 17 Dec 2010 02:13:46 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[conferences]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=296</guid>
		<description><![CDATA[My participation in conferences is almost always limited to the speaker&#8217;s side, behind a podium, or simply at a booth or on the show floor. I rarely participate as an attendee, but recently I had the chance to attend a conference simply to, well, do the things one does at conferences: attend talks and sessions, [...]]]></description>
			<content:encoded><![CDATA[My participation in conferences is almost always limited to the speaker&#8217;s side, behind a podium, or simply at a booth or on the show floor. I rarely participate as an attendee, but recently I had the chance to attend a conference simply to, well, do the things one does at conferences: attend talks and sessions, meet/greet others, and go to the demo booths!

Sitting in the audience I realized some speakers kept me quite engaged and others let my attention lapse a bit during their talk. Some conclusions from notes I took during talks I attended:<br /><br />
<ul>
	<li><strong>Don&#8217;t labour on the obvious</strong><br />
If you represent a large, well-known company, say Intel* for example, but you are talking about a narrower topic, don&#8217;t spend five minutes repeating what your company is already known for (in Intel&#8217;s case, that would be semiconductors and processors). It&#8217;s ok to discuss the larger area to give context and perspective, but please don&#8217;t spend more than absolutely necessary (yes, Intel is in the semiconductor and processor businesses, I GET IT).</li>
	<li><strong>Unreadable slides are pointless</strong><br />
If I can&#8217;t read the material on the slide it&#8217;s almost pointless to present it, especially if it has all text and no visual cues. And then to go on and read the unreadable-to-me text is simply punishment.</li>
</ul>
<ul>
	<li>E<strong>asily digested slides build rapport</strong><br />
As a counter to the previous point: easily read and digested slides are the opposite of pointless. Rather than alienate the audience, they help build rapport with the speaker as the audience internalizes the content and forms an opinion about it. And an easily digested slide ensures the audience won&#8217;t drown in details or attempt to listen to the speaker and read the slide at the same time, which may reduce comprehension.</li>
	<li><strong>Simple <em>is</em> beautiful</strong><br />
Be clear, confident, and concise. Make a point and back it up. Don&#8217;t try to make ten points in the space of five, and don&#8217;t make references to related points unless they are in proper context. Stay on-topic and don&#8217;t ramble.</li>
</ul>
<ul>
	<li><strong>Make it worthwhile</strong><br />
Make it valuable to the audience. If the objective is to introduce your product or service, make sure the audience leaves with a clear understanding of it. If the objective is to demonstrate complex and difficult achievements, let the audience leave with a sense of wonder. Don&#8217;t regurgitate a press release or blog. In most cases, people are in the audience attending your talk and skipped others that may be of interest because they felt yours would be more worthwhile.</li>
</ul>
<br />
By no means is this list even remotely comprehensive or unbiased, rather, it has just a few things I&#8217;ll keep in mind the next time I&#8217;m behind the podium.]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/12/conferencing/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>*pure*</title>
		<link>http://www.pabloestrada.us/2010/12/pure/</link>
		<comments>http://www.pabloestrada.us/2010/12/pure/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 04:41:22 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=293</guid>
		<description><![CDATA[I do hope HTML5 and CSS3 are not the next &#60;table&#62;&#60;tr&#62;&#60;th&#62;&#60;/th&#62;&#60;/tr&#62;&#60;tr&#62;&#60;td&#62;&#60;/td&#62;&#60;/tr&#62;&#60;/table&#62; of the web. I kid. Mostly.]]></description>
			<content:encoded><![CDATA[I do hope HTML5 and CSS3 are not the next<br /><br />
<code>&lt;table&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</code>
<br /><br /> of the web. <br /><br /> I kid. Mostly.<br />]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/12/pure/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VII Network photographer Donald Weber: Interrogations</title>
		<link>http://www.pabloestrada.us/2010/11/vii-network-photographer-donald-weber-interrogations/</link>
		<comments>http://www.pabloestrada.us/2010/11/vii-network-photographer-donald-weber-interrogations/#comments</comments>
		<pubDate>Wed, 01 Dec 2010 04:58:09 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[photo]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=286</guid>
		<description><![CDATA[VII Network photographer Donald Weber&#8217;s series Interrogations, a work-in-progress, is captivating and provocative: http://www.viiphoto.com/showstory.php?nID=1180 If you&#8217;re not familiar with his photography, I encourage you to see some of his other projects, such as: Bastard Eden, Our Chernobyl or Zek: In the Prison of the East.]]></description>
			<content:encoded><![CDATA[VII Network photographer Donald Weber&#8217;s series Interrogations, a work-in-progress, is captivating and provocative:
<br /><br />
<a href="http://www.viiphoto.com/showstory.php?nID=1180" target="_blank">http://www.viiphoto.com/showstory.php?nID=1180</a>
<br /><br />
If you&#8217;re not familiar with his photography, I encourage you to see some of his other projects, such as:<br />
<a href="http://www.viiphoto.com/showstory.php?nID=652" target="_blank">Bastard Eden, Our Chernobyl</a> or <a href="http://www.viiphoto.com/showstory.php?nID=654" target="_blank">Zek: In the Prison of the East</a>.]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/11/vii-network-photographer-donald-weber-interrogations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web2py: an application framework</title>
		<link>http://www.pabloestrada.us/2010/08/web2py-an-application-framework/</link>
		<comments>http://www.pabloestrada.us/2010/08/web2py-an-application-framework/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 22:46:19 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=279</guid>
		<description><![CDATA[Recently I&#8217;ve been using web2py as an application framework and front-end structure for a web page I&#8217;m extending. This is rooted in previous pages, tweeting the world cup, which then led to dropping tweets into a SimpleGeo layer. Web2py is described as a Free and open source full-stack enterprise framework for agile development of fast, [...]]]></description>
			<content:encoded><![CDATA[Recently I&#8217;ve been using <a href="http://www.web2py.com/" target="_blank">web2py</a> as an application framework and front-end structure for a web page I&#8217;m extending. This is rooted in previous pages, <a href="http://www.pabloestrada.us/2010/07/tweeting-the-world-cup/" target="_blank">tweeting the world cup</a>, which then led to <a href="http://www.pabloestrada.us/2010/07/dropping-tweets-into-a-simplegeo-layer/" target="_blank">dropping tweets into a SimpleGeo layer</a>. Web2py is described as a <br /><br /><cite>Free and open source full-stack enterprise framework for agile development of fast, scalable, secure and portable database-driven web-based applications.</cite>  <br /><br /> It is written in Python and was created by <a href="http://mycti.cti.depaul.edu/people/facultyInfo_mycti.asp?id=343" target="_blank">Massimo Di Pierro</a>. He is amazingly omnipresent in support and development of web2py. <br /><br /> When considering how to extend the tweet-dropping capability, I looked at a few options. The program to record the tweets into a SimpleGeo layer was already written in Python so I looked at web applications and frameworks built around Python or at least with Python support. Looking back a bit, it seems a lot hinged on one program which ended up being but one very small element in a larger structure. But I was enjoying fiddling with Python and there are plenty of frameworks to choose from. I didn&#8217;t have much time to evaluate and test different frameworks so I wanted to make a decision quickly.<br /><br />A framework that naturally comes to mind is Django. It&#8217;s popular, widely used in production, well documented, and actively supported through the community. Others like CherryPy and webpy are also available. After the head-slap that was realizing web2py is not related to webpy, I took a closer look and decided to go with web2py. My need was mostly to quickly make a prototype, and while the others would have been fine for this also, it seemed web2py would allow me to get up and running as with minimal learning of new template languages and other overhead. It also seemed to be easy to deploy to Google App Engine. Having limited information I knew there was some risk I would run into a roadblock while carrying a lot of sunk time into the development, but I estimated it was reasonable. <br /><br /> Now with an application framework comes <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank">MVC</a>, hand-in-glove. I&#8217;d never used an MVC framework so I was completely green. MVC is a pretty broad model but it&#8217;s often seen in web frameworks such as Django and yes, web2py. web2py follows the MVC model but as I would soon learn, it is quite flexible. My use case really didn&#8217;t require many views at all, and probably only a couple of controllers at most. The flexibility of web2py allowed me to rapidly prototype what I wanted while still retaining the robust structure that MVC brings, and yet at the same time mostly abstract this from the user and even myself to some extent. It really seems to be the best combination in that sense. <br /><br /> As I investigated and experimented with the most suitable implementation of web2py for my need, I found an <a href="http://groups.google.com/g/4247fb7b/t/e6b210847f910f6f/d/b049f1c7ecb64d4d" target="_blank">explanation</a> on the difference between push and pull frameworks by Massimo: <br /><br />
<cite>There are two types of frameworks push and pull. In a push framework (like web2py, Django, Rails) the URL is mapped into a function, which returns data (in the form of a dictionary) and the data is rendered by one view. In a pull framework (like Struts and JBoss) the URL is mapped into a view which calls one or more controller functions. From your question I assume you have a pull framework in mind. You can mimic a pull framework in web2py in multiple ways. One way is via ajax requests&#8230;</cite>
<br /><br /> This was exactly the flexibility I was looking for and just didn&#8217;t know it. I needed one or two views initially, and several groups of controller functions exposed within the same view. Reading this message gave me confidence I wasn&#8217;t going down a deep framework crevasse with no rope to haul myself back out if needed. <br /><br /> The learning curve for web2py is quite reasonable. It doesn&#8217;t have a separate template language per se, but it does have a structure and reusable components that, along with built-in helper functions, make prototyping speedy. And it allows Python code to be typed directly into .html files, by enclosing the Python code within <code>{{ }}</code>. <br /><br /> Extensive documentation for web2py is easily found and you can start by going through the <a href="http://web2py.com/book/default/chapter/03" target="_blank">tutorial</a> on the web2py website. It&#8217;ll take you from rendering a simple web page to creating a wiki in one chapter! Other examples demonstrate some of the easier-to-implement functions and they really show-off how easy it is to get something functional up and running. ]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/08/web2py-an-application-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A single serving site</title>
		<link>http://www.pabloestrada.us/2010/07/a-single-serving-site/</link>
		<comments>http://www.pabloestrada.us/2010/07/a-single-serving-site/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 05:05:53 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/2010/07/a-single-serving-site/</guid>
		<description><![CDATA[Just because: http://isdoloresparkclosed.com/(http://en.wikipedia.org/wiki/User:Tlogmer/Single_serving_sites)]]></description>
			<content:encoded><![CDATA[<p>Just because: <a href="http://isdoloresparkclosed.com/" title="Is it?" target="_blank">http://isdoloresparkclosed.com/</a><br /><br />(<a href="http://en.wikipedia.org/wiki/User:Tlogmer/Single_serving_sites">http://en.wikipedia.org/wiki/User:Tlogmer/Single_serving_sites</a>) </p>]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/07/a-single-serving-site/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dropping Tweets into a SimpleGeo Layer</title>
		<link>http://www.pabloestrada.us/2010/07/dropping-tweets-into-a-simplegeo-layer/</link>
		<comments>http://www.pabloestrada.us/2010/07/dropping-tweets-into-a-simplegeo-layer/#comments</comments>
		<pubDate>Wed, 14 Jul 2010 01:23:23 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=231</guid>
		<description><![CDATA[The mandated decay imposed on my previous experiment due to restricting Twitter searches to no more than a week (or so) in the past had me thinking of a more permanent method to archive tweets and their geo-location information. On the same day I wrapped up SF Tweets the World Cup 2010, Andrew at SimpleGeo [...]]]></description>
			<content:encoded><![CDATA[<a href="http://www.pabloestrada.us/media/2010/07/Picture-5.png"><img class="alignnone size-medium wp-image-243" title="Picture 5" src="http://www.pabloestrada.us/media/2010/07/Picture-5-e1279069793364-300x176.png" alt="" width="300" height="176" /></a>
<br /><br />
The mandated decay imposed on my previous experiment due to restricting Twitter searches to no more than a week (or so) in the past had me thinking of a more permanent method to archive tweets and their geo-location information. On the same day I wrapped up <a href="http://www.pabloestrada.us/worldcup/" target="_blank">SF Tweets the World Cup 2010</a>, Andrew at <a href="http://www.simplegeo.com/" target="_blank">SimpleGeo</a> wrote about <a href="http://blog.simplegeo.com/post/790366330/foursquare-simplegeo" target="_blank">how to map Foursquare checkins to a SimpleGeo layer</a>. This way the checkins are all visible on one layer and the user can perform spatial queries on them.
<br /><br />
Andrew&#8217;s example <a href="http://github.com/mager/simplegeo-sandbox/blob/master/geodata/foursquare/parse.py" target="_blank">Python script</a> looked simple enough that I took it as a base to do the same as I&#8217;d essentially done with the World Cup tweets, but instead of plotting tweets on a Google map they would be inserted into a SimpleGeo layer. This time, rather than searching on a keyword and collecting any returned results, the purpose was to collect tweets from a Twitter user, in this case, my own.
<br /><br />
I could have accessed the Twitter API directly as I did for the World Cup tweets, but the availability of some simple and excellent Twitter clients/libraries for Python made it too easy to avoid. I quickly found a few and settled on <a href="http://github.com/joshthecoder/tweepy" target="_blank">Tweepy</a>, by joshthecoder. It&#8217;s described as a Python library with &#8220;complete coverage&#8221; of the Twitter API. And just as cool, it has reasonably <a href="http://joshthecoder.github.com/tweepy/docs/index.html" target="_blank">detailed documentation</a>. Sold!
<br /><br />
The first step was to get Tweepy returning tweets. For a single user&#8217;s timeline Tweepy provides the method <code>tweepy.api.user_timeline</code>, one of several timeline methods. By default this returns the last 20 tweets as objects available for manipulation, including the fields of interest here such as coordinates, if available, the tweet ID, date and time, and so on. It&#8217;s quite easy to get Tweepy talking with Twitter and in minutes I had my latest 20 tweets on the screen. Since I&#8217;m no Python guru, it took me a bit longer to get familiar with the objects returned to me and their available attributes and methods. Someone even slightly Python-adept could have breezed through this in just a few clock cycles, but it&#8217;s part of the learning process for me.
<br /><br />
Assigning latitude and longitude is pretty easy as long as the tweet has the associated <code>tweet.geo</code> data. As I noted in the <a href="http://www.pabloestrada.us/2010/07/tweeting-the-world-cup/" target="_blank">World Cup blog post</a>, this is often not the case. This was an important reason to plot my own tweets: I have control over the geotagging of each tweet, and don&#8217;t have to depend on others to do it. If I were to grab tweets from the search API or the public timeline, it&#8217;s likely a small percentage would have latitude and longitude information.
<br /><br />
But wait, what about Twitter places? Yes, users can attach place-based geographic information to their tweets. This allows the user to reveal the general location from which the tweet is sent without revealing the exact coordinates. Naturally, a bounding box described this area on a map, and Twitter has associated a unique URL for each place. In my case, many of my tweets are sent from the Richmond in San Francisco.  The XML attached to my tweets sent from the Richmond and identified as such is this:
<br /><br />
<code> &lt;twitter:place xmlns:georss="http://www.georss.org/georss"&gt;
<br />&lt;twitter:id&gt;64be9bb264eb76c1&lt;/twitter:id&gt; &lt;twitter:name&gt;Central Richmond&lt;/twitter:name&gt; &lt;twitter:full_name&gt; Central Richmond, San Francisco &lt;/twitter:full_name&gt; &lt;twitter:place_type&gt; neighborhood &lt;/twitter:place_type&gt; &lt;twitter:url&gt; http://api.twitter.com/1/geo/id/64be9bb264eb76c1.json &lt;/twitter:url&gt; &lt;twitter:attributes&gt; &lt;twitter:bounding_box&gt; &lt;georss:polygon&gt;37.77212997 -122.49240012 37.77212997 -122.47178184 37.78442901 -122.47178184 37.78442901 -122.49240012&lt;/georss:polygon&gt; &lt;/twitter:bounding_box&gt; &lt;twitter:country code="US"&gt;The United States of America&lt;/twitter:country&gt;
<br />&lt;/twitter:attributes&gt;&lt;/twitter:place&gt; </code>
<br /><br />
A bounding box like this is not difficult to deal with, but there should be some consideration on how the information is presented when it is in the same context as markers on a map with lat and lon coordinates. But that&#8217;s a digression&#8230;
<br /><br />
Once the proper modules are imported, the two key components to call are the SimpleGeo <code>Client(MY_OAUTH_KEY, MY_OAUTH_SECRET)</code> and the Tweepy <code>tweepy.api.user_timeline(MY_TWITTER_USERNAME)</code>. All that basically remains is to throw objects from one universe into the other. Tweepy returns status objects and the SimpleGeo client adds records to a database.
<br /><br />
My own tweets don&#8217;t always have associated coordinates, so even though I can choose to tag or not tag a tweet with coordinates, it&#8217;s smart to check and ensure a tweet has the necessary properties before trying to add it to a layer. If a tweet has coordinates, its status object will have an array in <code>tweet.geo['coordinates']</code> of the form <code>[lat,lon]</code>. That&#8217;s simple to verify and require before calling the function to insert the object into the layer. Some other properties are useful: the tweet&#8217;s URL, the place (this could be useful later even if the lat,lon coordinates are included), the text of the tweet itself, and the time-stamp.
<br /><br />
I ran into one hiccup with the time-stamp with regard to time zones and offsets. Each Tweepy status returns a time-stamp in GMT form. When I first added these to the SimpleGeo layer they had an offset of +7 hours (the magnitude of the difference between PDT and GMT zones). To account for this I manually subtracted the time zone offset from the tweet&#8217;s time-stamp, and that fixed it. I peeked at the Tweepy code to see if I could do it more elegantly, but I&#8217;m not sure I understand how it handles <code>locale</code> as there is some comment about backward-compatibility with Python 2.4.
<br /><br />
It&#8217;s also quite simple to delete records and I did this a few times as an experiment and to check I was manipulating the layer&#8217;s objects correctly. A simple call to SimpleGeo&#8217;s <code>client.delete_record</code> will delete the object by passing the layer and object ID.
<br /><br />
I didn&#8217;t change anything from Andrew&#8217;s Foursquare example to add the objects into the record and it worked! Next steps might be to add duplicate record checking, pagination, and spatial queries into the SimpleGeo layer. Thanks to Andrew for his help on getting my example to work &#8211; he gave me some pointers and was readily available to help me out.
<br /><br />
The .py file is available here: <a href="http://gist.github.com/474741" target="_blank">http://gist.github.com/474741</a>]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/07/dropping-tweets-into-a-simplegeo-layer/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Tweeting the World Cup</title>
		<link>http://www.pabloestrada.us/2010/07/tweeting-the-world-cup/</link>
		<comments>http://www.pabloestrada.us/2010/07/tweeting-the-world-cup/#comments</comments>
		<pubDate>Sat, 10 Jul 2010 02:03:56 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[googlemaps]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=216</guid>
		<description><![CDATA[A few weekends ago I went down to the Haight to watch the USA vs England World Cup match. I&#8217;ve watched other World Cup matches at Mad Dog in the Fog but I seriously underestimated the crowd that would ride the wave of USA World Cup mania and try to cram into one of the [...]]]></description>
			<content:encoded><![CDATA[<p>A few weekends ago I went down to the Haight to watch the USA vs England World Cup match. I&#8217;ve watched other World Cup matches at <a href="http://www.yelp.com/biz/mad-dog-in-the-fog-san-francisco" target="_blank">Mad Dog in the Fog</a> but I seriously underestimated the crowd that would ride the wave of USA World Cup mania and try to cram into one of the more popular viewing-pubs. Fifteen minutes before kickoff a long line had already formed, complete with metal barriers and an anxious crowd. Instead of waiting impatiently for the odd fan to leave Mad Dog and let the standby-line inside one-by-one, I went two blocks west to <a href="http://www.dannycoyles.com/" target="_blank">Danny Coyles</a>. It was also full, but only to the edge, so I managed to grab a spot just outside the open window with a clear view of one of the screens. As I snuggled into the optimal viewing position, I wondered how many people had tweeted from inside Mad Dog, perhaps noting how crowded it was inside, or even if others had tweeted about the long lines well before the match started. Naturally, this can be searched, but I also wondered where people might be tweeting as the game started. Where people heading over to other pubs, just like I went to Danny Coyles? It would be really sweet if I could pull up a map around my current location and find tweets <em>relevant to my interest</em> (in this case, the USA vs England match), and read them on a location-by-location basis. Surely, this has been considered before, right? Hmmm&#8230; <br /><br />
If you&#8217;re interested, the site is here: <a href="http://www.pabloestrada.us/worldcup/" target="_blank">http://www.pabloestrada.us/worldcup/</a>
<br /><span id="more-216"></span>
<br />
<br />
I wondered how difficult it might be to plot out local tweets on a Google map and see their geographic distribution, so I checked out the Google Maps API on a recommendation from a friend that the API is <a href="http://code.google.com/apis/maps/documentation/javascript/" target="_blank">well documented</a>, easy to understand and straightforward to implement. Indeed, throwing a map onto a web page is almost trivial and all that&#8217;s needed are some very basic parameters including latitude and longitude coordinates that define the map&#8217;s center. Easy enough, I thought. The next step was slurping some tweets from the Twitter API.<br /><br />Pulling data from the Twitter search API is pretty straightforward and has been implemented elsewhere. Choosing to use jQuery not only simplified data retrieval, but also put the broad set of jQuery functions and plugins within reach. jQuery&#8217;s widespread use and well-docmuented API shortens the time to implementation for me. Naturally, I depended on Google search. However, many implementations use the JSON format instead of JSONP. I understand this is done for security reasons, and this necessitates the use of a server-side proxy. I chose JSONP simply because it doesn&#8217;t need the proxy. <br /><br />Twitter&#8217;s <a href="http://search.twitter.com/advanced" target="_blank">advanced search page</a> allowed me to construct the query and cross-checked with what I&#8217;d written based on their <a href="http://apiwiki.twitter.com/Twitter-Search-API-Method:-search" target="_blank">API documentation</a> for the Search API. The documentation covers all the optional parameters and provides simple examples of their use, however, I would only later realize at least two parameters are missing range (allowed values): the since and until parameters; they allow the search to be restricted to a date range. I wished to restrict the search over given match dates to only return results that were tweeted during (or near) the game. The finest resolution for this restriction is entire days, so it&#8217;s not possible to restrict the search to within certain hours of a date.<br /><br /> At first I tried to use <code>$.ajax</code> to make the query as it provides a bit more flexibility than the $.getJSON function. At this point I was using mostly Google Chrome for testing and kept getting <code>null</code> as the returned value. In tracing this down, I found there was an unexpected character in line 1 of the HTML file, causing an Uncaught SyntaxError (Unexpected token) as a result. That seemed odd, because I certainly wasn&#8217;t changing the first (or first few) lines of the HTML file. After some searching I found this may be related to an old defect in Chrome. It seems a BOM character is inserted at the front of the JSON response, according to this: <a href="http://code.google.com/p/chromium/issues/detail?id=176" target="_blank">http://code.google.com/p/chromium/issues/detail?id=176</a>. To avoid it I instead used <code>$.getJSON</code>. It has a bit less flexibility than <code>$.ajax</code>, but I worked around that by simply defining the callback function in <code>$.getJSON</code> to call another function, which I constructed separately. This also kept the code a bit more modular and easier to read. Once I had a proper query constructed and had a proper grip on the returned data, I saved the JSON response to a test.js file so I could keep developing without having to poll the API each and every time I, say, changed the color of some text on the page. It also froze the search results so I could test cases of tweets with different location results.<br /><br />As I looked over the search results, I realized a very low percentage of tweets are tagged with geo-location data. Those that are make it very easy to jump from tweet to Google map, since the geo-tags include latitude and longitude &#8211; perfect for placing on a map! Unfortunately, most tweets don&#8217;t have this data. The Twitter search API makes it easy to restrict a search to a geographic area; my search was restricted to a 12 mile radius around San Francisco. I quickly realized the variety of location information among the tweets. Some users populate their profile with a location description: this could be San Francisco, or SF, or San Francisco, CA. Others populate a location that includes latitude and longitude, but is prefixed by a string such as &#8220;iPhone: &#8221; or &#8220;ÜT: &#8220;. This really reduces the value of placing the tweets on a map of local (city) scale. When comparing tweets between different cities, this is perfectly valid and useful, and is probably sufficient resolution to make a geographic comparison. For example, one could plot out tweets from San Francisco and Los Angeles on one map. In that case, it may not be necessary to know exactly where in San Francisco a tweet originated. But in my case, I wanted to distinguish tweets sent from Mad Dog vs Danny Coyles, and this level of resolution just isn&#8217;t enough. <br /><br />I decided not to plot tweets with unspecific location information on the map. This would not be intuitive because a user naturally associates a pinpoint on a map with that specific geographic location. Where should tweets tagged with the location, &#8220;SF,&#8221; be placed on the map? I considered placing them all in the middle, or very close to the middle, of the city (this is somewhere in or near The Castro). But then how could they be differentiated from a tweet that really did originate in The Castro and was tagged with latitude and longitude coordinates? I decided to list the tweets below the map but only plot tweets with coordinates onto the map. I used some simple regular expressions to match a few variations in location, for example, the iPhone or ÜT prefixes to coordinates. <br /><br />The next step was to automatically trigger a search based on a World Cup match. The user shouldn&#8217;t have to type in &#8220;#GER&#8221; to search for Germany on the date of the Germany vs Spain semifinal. I placed all 64 matches on the right side of the page with the score for each team. Using small flag icons next to each team name, I had javascript extract the team name from the <code>img src</code> attribute of the flag to automatically trigger a search for the corresponding hashtag for that team. I also encoded each <code>a href</code> attribute with the match number so that the search could key off an array of 64 date values and restrict the search to the match date. This was pretty easy using regular expressions, but I later realized that using regex was completely overkill since the length and format of each <code>img src</code> string does not change for all the teams and all the matches. Only later when I tested in Internet Explorer did I realize this. Thanks, IE, for reminding me of the stings developers endured in years past when trying to write cross-browser compatible code for Netscape and IE 4, and who knows what other nightmares. Internet Explorer treats calls to <code>String.split()</code> with regular expressions differently than other browsers. But of course! I found a brief explanation on a page titled <a href="http://code.google.com/p/trimpath/wiki/InelegantJavaScript" target="_blank">Inelegant JavaScript</a>. Woohoo! In the end, it was pretty easy to <code>slice()</code> the string I needed and that took care of it. But hey, I learned some simple regular expressions and browser inconsistencies, right?<br /><br />The next step was to take the process location information from the relevant tweets and place each one on the map. I used each team&#8217;s flag in place of the default Google map marker. If more than one team&#8217;s tweets were to be plotted on the map, this would produce a visual display of the distribution and relative magnitude between groups of tweeters mentioning each team. At some point this could even go further and plot some type of mood indicator for fans of each team, but that would require more processing and estimation of the tweet text and some guessing based on that. My map only plots one team at a time, but that&#8217;s not hard to change. In fact, I had some trouble <em>not</em> to do that, as I wanted to clear the map of all flags when a new search was triggered. The previous version (V2) of the Google API had a method to clear markers, but the current version requires each marker to be tracked so it can be individually erased when the clear marker function is called. Luckily, <a href="http://stackoverflow.com/" target="_blank">Stack Overflow</a> came to the rescue with a <a href="http://stackoverflow.com/questions/1544739/google-maps-api-v3-how-to-remove-all-markers/1544885#1544885" target="_blank">solution for V3</a>.<br /><br />I made a function to take the JSON data and clicked-on team name. The function dynamically appended the contents of a <code><div></code> with the user profile image (avatar) of the Twitter user, the location information sent with the tweet, and the contents of the tweet. For tweets containing coordinate information, a function is triggered to plot the tweet on the Google map with the corresponding team flag. That function also creates an InfoWindow (tooltip) containing the user profile image and tweet contents, making each flag clickable, just like default Google markers. That adds a bit of personalization to each tweet on the map, and it&#8217;s cool to see the user&#8217;s profile next to their tweet and team flag.<br /><br />After everything was working as expected, I used another function to build the search string URL based on the team name, match date, and some Twitter search parameters. Once everything was working I disconnected the test.js file and connected the code to the Twitter search API using this function to provide the input to <code>$.getJSON</code>.<br /><br />There are still possible improvements, for example, I&#8217;ve done nothing to consider the speed of searches or anything to make the content update look a bit more smooth. There are also no graceful failures, for example, if a search yields no results or fails for another reason, or if a user clicks on a match in the future (because this triggers a search on a future date). Currently, nothing happens and no error is presented. Finally, this whole experiment will expire in its current form a few days or weeks after the end of the World Cup when the match dates become too old for the Twitter search API. Just like the tournament, it&#8217;s been fun while it lasted.<br /><br /></p>]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/07/tweeting-the-world-cup/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Gearing Up for ARG vs GER</title>
		<link>http://www.pabloestrada.us/2010/07/gearing-up-for-arg-vs-ger/</link>
		<comments>http://www.pabloestrada.us/2010/07/gearing-up-for-arg-vs-ger/#comments</comments>
		<pubDate>Sat, 03 Jul 2010 02:33:34 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=209</guid>
		<description><![CDATA[And to warm up, a New York Times article on Maradona. An Apology to Maradona, a Rollicking Genius, By ROB HUGHES Should this match live up to expectations, it will be historic.]]></description>
			<content:encoded><![CDATA[And to warm up, a New York Times <a href="http://www.nytimes.com/2010/07/03/sports/soccer/03maradona.html" target="_blank">article on Maradona</a>.
<br /><br />
<span style="padding-left: 30px;">An Apology to Maradona, a Rollicking Genius, By ROB HUGHES</span>
<br /><br />
Should this match live up to expectations, it will be historic.]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/07/gearing-up-for-arg-vs-ger/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Class Abuse</title>
		<link>http://www.pabloestrada.us/2010/06/class-abuse/</link>
		<comments>http://www.pabloestrada.us/2010/06/class-abuse/#comments</comments>
		<pubDate>Sat, 26 Jun 2010 03:08:17 +0000</pubDate>
		<dc:creator>pablo</dc:creator>
				<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://www.pabloestrada.us/?p=176</guid>
		<description><![CDATA[The introductory video on the Compass site really intrigued me &#8211; http://compass-style.org/docs/. Compass is described on its site as: &#8220;a stylesheet authoring tool that uses the Sass stylesheet language to make your stylesheets smaller and your web site easier to maintain. Compass provides ports of the best of breed css frameworks that you can use [...]]]></description>
			<content:encoded><![CDATA[The introductory video on the <a href="http://compass-style.org/" target="_blank">Compass</a> site really intrigued me &#8211; <a href="http://compass-style.org/docs/" target="_blank">http://compass-style.org/docs/</a>.
<br /><br />
Compass is described on its site as:<br /><br />
<blockquote>&#8220;a stylesheet authoring tool that uses the Sass stylesheet language to make your stylesheets smaller and your web site easier to maintain. Compass provides ports of the best of breed css frameworks that you can use without forcing you to use their presentational class names. It’s a new way of thinking about stylesheets that must be seen in action!&#8221;</blockquote>
<br />
As I watched, I thought: Yes! It&#8217;s true! CSS can really suck sometimes!  I loved the comment, &#8220;ferociously abusing your classes.&#8221;  As CSS has evolved, it seems abuse has become more and more common, and maybe necessary, and people hammer away and pound it into submission.  Grids!  And with CSS3 grinding its cleats into the grass, I&#8217;ve seen sites emerge with complex and delicate layouts that show off the power and magic, and not least of all the promise of &#8211;the future&#8211;.
<br /><br />
But just because you can doesn&#8217;t mean you should.  I&#8217;d like to use CSS(3) as a way to move away from the extremely carefully positioned and crafted layouts that, even though technically impressive, are visually confusing and crowded.  Somewhere, there must be a former HTML 4 hack who labored so hard, for so long, to implement something similar using nothing but <code>&lt;tr&gt;</code> and <code>&lt;td&gt;</code> cells who surely feels like the ability to do this with (relative) ease is better than nirvana.  Liquid, fluid, blah blah blah.  I don&#8217;t mean to say I don&#8217;t admire and desire a carefully, precisely positioned and crafted layout.  I do.  I just don&#8217;t think everything should be placed on n-th pixel resolution just because we can.
<br /><br />
Two examples:
<br />
1) <a href="http://www.uxmag.com/" target="_blank">UX Magazine</a>
<br />
<a href="http://www.pabloestrada.us/media/2010/06/UX-magazine.png"><img class="alignnone size-medium wp-image-178" title="UX-magazine" src="http://www.pabloestrada.us/media/2010/06/UX-magazine-300x223.png" alt="" width="300" height="223" /></a>
<br /><br />
Is it cleanly organized and orderly?  Certainly it is.  Is the text highly readable?  Mostly yes, except for some of the categories that are the top heading in each box.  Is it cluttered?  I think it is.  My eyes go nowhere and everywhere at the same time. It&#8217;s easy to understand the navigation and news sidebar, however, the center content seems all to have equal relative weight.  Maybe that&#8217;s the intent, as the footer notes the content is based on articles published one-at-a-time.  The quote from Bertrand Russell looks as if he tweeted it &#8211; I like that.
<br /><br />
2) <a href="http://jeffcroft.com/" target="_blank">Jeff Croft</a>
<br />
<a href="http://www.pabloestrada.us/media/2010/06/Jeff-Croft.png"><img class="alignnone size-medium wp-image-182" title="Jeff-Croft" src="http://www.pabloestrada.us/media/2010/06/Jeff-Croft-300x257.png" alt="" width="300" height="257" /></a>
<br />
This looks just as organized and orderly, and in my view, much easier to understand visually.  It lets the reader feel in control of the visual content and not barraged with everything at once.  I don&#8217;t like everything there, but it&#8217;s the style of site I&#8217;d like to make.
<br /><br />
Searching around for CSS frameworks I found this excellent article from Eric Meyer about the <a href="http://adactio.com/journal/1498" target="_blank">lessons of CSS frameworks</a>.  Great tips to keep in mind, especially <em>before</em> diving into frameworks.
<br /><br />
This site is based on a WordPress theme, which itself is based on a 900 grid system.  As I hacked at it, I mostly stripped away from it, partially because it had more functions than I wanted or needed, and partially to just simplify it (instead of just ignoring unused parts).  My frustrations took root in the naming conventions and myriad div and span elements.  <code>&lt;div class="span-13"&gt;</code>, anyone?  How about A collection of 224 Grid and CSS Layouts?  No, thanks.
<br /><br />
Anyway, this isn&#8217;t about being anti-grid.  Compass looked cool, at least from its introduction.  Naturally this led me to <a href="http://sass-lang.com/" target="_blank">Saas</a>.  The ability to assign and use variables, perform simple math, and even simply nesting are appealing enough to give it a try.  Functions and mixins?  Woah.  Now, I&#8217;m not sure if this will move away from such lovely-named classes, as was claimed (but not actually done) in the introductory video.  But leaving that aside, I&#8217;m still tickled enough to give it a try.  Their <a href="http://sass-lang.com/tutorial.html" target="_blank">tutorial</a> gives a quick overview.]]></content:encoded>
			<wfw:commentRss>http://www.pabloestrada.us/2010/06/class-abuse/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 2.349 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2012-03-04 23:01:36 -->

