<?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>ItOpen - Open Web Solutions, WebGis Development</title>
	<atom:link href="http://www.itopen.it/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.itopen.it</link>
	<description>[lang_en]Open Web Solutions: WebGis, Open Source development[/lang_en][lang_it]Soluzioni WebGIS e sviluppo software Open Source[lang_it]</description>
	<lastBuildDate>Mon, 29 Apr 2013 15:33:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Driving a pair of 7 segments display with MSP430 Energia libraries</title>
		<link>http://www.itopen.it/2013/03/18/driving-a-pair-of-7-segments-display-with-msp430-energia-libraries/</link>
		<comments>http://www.itopen.it/2013/03/18/driving-a-pair-of-7-segments-display-with-msp430-energia-libraries/#comments</comments>
		<pubDate>Mon, 18 Mar 2013 13:19:41 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[MSP430 MCU]]></category>
		<category><![CDATA[Programmazione]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=1033</guid>
		<description><![CDATA[This is my second experiment with Energia LaunchPad boards. This time I wanted to see how difficult could be to adapt for the LaunchPad a program which I originally developed for Arduino. If are interested in how I did setup my Linux box for working with the LaunchPad and the Energia libraries, I&#8217;ve described the whole [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.itopen.it/wp-content/uploads/2013/03/20130317_001.jpg"><img class="size-medium wp-image-1034 alignright" alt="20130317_001" src="http://www.itopen.it/wp-content/uploads/2013/03/20130317_001-300x225.jpg" width="300" height="225" /></a></p>
<p>This is my second experiment with Energia LaunchPad boards. This time I wanted to see how difficult could be to adapt for the LaunchPad a program which I originally developed for Arduino.</p>
<p>If are interested in how I did setup my Linux box for working with the LaunchPad and the Energia libraries, I&#8217;ve described the whole process in <a title="MSP430 Energia Development on Linux" href="http://www.itopen.it/2013/03/01/msp430-energia-on-linux/">this post</a>.</p>
<p>It turned out to be quite easy and the program needed only a few pin configuration changes.</p>
<p>Here is a link to the breadboard schema:</p>
<p><a href="http://www.softwareliberopinerolo.org/images/arduino/D14-N_3_Display_7seg_.jpg">http://www.softwareliberopinerolo.org/images/arduino/D14-N_3_Display_7seg_.jpg</a></p>
<p>&nbsp;</p>
<p>The code:</p>
<pre class="wp-code-highlight prettyprint linenums:1">/**
Display 7 segmenti per corso arduino.

segmenti:    
a   3   P2_4
b   4  P1_1
c   5  P1_2
d   6  P1_3
e   7  P1_4
dp  8  P1_5
f   9  P2_0
g   10 P2_1
Q1  2 transistor unità P2_2
Q2  11 transistor decine P1_7
SW1 12 P2_3
SW2 13 P2_5
*/

#define SW1 P2_3
#define SW2 P2_5

#define DECINE P1_7
#define UNITA  P2_2

#define DEBOUNCE 200

byte valore = 0;
byte decine_attivo = 0;
byte seven_seg_digits[11][7] = {
                                { 0,0,0,0,0,0,0 },  // = blank
                                { 1,1,1,1,1,1,0 },  // = 0
                                { 0,1,1,0,0,0,0 },  // = 1
                                { 1,1,0,1,1,0,1 },  // = 2
                                { 1,1,1,1,0,0,1 },  // = 3
                                { 0,1,1,0,0,1,1 },  // = 4
                                { 1,0,1,1,0,1,1 },  // = 5
                                { 1,0,1,1,1,1,1 },  // = 6
                                { 1,1,1,0,0,0,0 },  // = 7
                                { 1,1,1,1,1,1,1 },  // = 8
                                { 1,1,1,0,0,1,1 }   // = 9
                                };

byte segment_to_pin[8] = {P2_4, P1_1, P1_2, P1_3, P1_4, P2_0, P2_1, P1_5};
unsigned long last_read;
byte led = 0;

void write_digit(byte cifra, bool dp){
    for(int i=0; i<7; i++){
        digitalWrite(segment_to_pin[i], seven_seg_digits[cifra+1][i]);
    }
    digitalWrite(segment_to_pin[7], dp);
}

void setup(){
    for(int p=0; p<8; p++){
        pinMode(segment_to_pin[p], OUTPUT);
        digitalWrite(segment_to_pin[p], HIGH);
    }
    pinMode(DECINE, OUTPUT);
    pinMode(UNITA, OUTPUT);
    pinMode(P1_0, OUTPUT);
    pinMode(P1_6, OUTPUT);
    digitalWrite(P1_0, LOW);
    digitalWrite(P1_6, LOW);
    pinMode(SW1, INPUT);
    pinMode(SW2, INPUT);
    digitalWrite(SW1, HIGH);
    digitalWrite(SW2, HIGH);
    last_read = millis();
}

void blank_digit(){
    for(int i=0; i<7; i++){         
        digitalWrite(segment_to_pin[i], 0);     
    }
    digitalWrite(segment_to_pin[7], 0); 
} 

void loop(){     
    if(digitalRead(SW1) == LOW){         
        if(millis() - last_read > DEBOUNCE){
            valore--;
            digitalWrite(P1_0, led);
            led = ! led;
            last_read = millis();
        }
    }
    if(digitalRead(SW2) == LOW){
        if(millis() - last_read > DEBOUNCE){
            valore++;
            digitalWrite(P1_6, led);
            led = ! led;
            last_read = millis();
        }
    }
    valore = constrain(valore, 0, 99);
    decine_attivo = !decine_attivo;
    if(decine_attivo){
        digitalWrite(UNITA, LOW);
        if(valore/10){
            write_digit(valore/10, 0);
        } else {
            blank_digit();
        }
        digitalWrite(DECINE, HIGH);
    } else {
        digitalWrite(DECINE, LOW);
        write_digit(valore%10, 0);
        digitalWrite(UNITA, HIGH);
    }
    delay(1);
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2013/03/18/driving-a-pair-of-7-segments-display-with-msp430-energia-libraries/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MSP430 LaunchPad Energia development on Linux</title>
		<link>http://www.itopen.it/2013/03/01/msp430-energia-on-linux/</link>
		<comments>http://www.itopen.it/2013/03/01/msp430-energia-on-linux/#comments</comments>
		<pubDate>Fri, 01 Mar 2013 09:57:19 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[MSP430 MCU]]></category>
		<category><![CDATA[Programmazione]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=989</guid>
		<description><![CDATA[A new baby is sitting on my desktop: yesterday arrived the MSP430 powered Launchpad development board.  These few notes describe the steps I did to setup a development environment for this board on Ubuntu Linux 12.04 LTS 64bit. The launchpad board Update: at the beginning of March 2012 TI raised the price of LaunchPad board [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.itopen.it/wp-content/uploads/2013/03/Energia.png"><img class="alignright size-medium wp-image-1004" alt="Energia" src="http://www.itopen.it/wp-content/uploads/2013/03/Energia-300x119.png" width="300" height="119" /></a></p>
<p>A new baby is sitting on my desktop: yesterday arrived the MSP430 powered Launchpad development board.  These few notes describe the steps I did to setup a development environment for this board on Ubuntu Linux 12.04 LTS 64bit.</p>
<h1>The launchpad board</h1>
<p><strong>Update: at the beginning of March 2012 TI raised the price of LaunchPad board to 10 $ shipping included.</strong></p>
<p>The launchpad board is a low-cost (less than 5 € shipping included) development board based on Texas Instruments <strong>MSP430</strong> family microcontrollers, it ships in a nice retail box with two different MCUs, an USB cable and a tiny 32KHz smd crystal ready to be soldered onto the board (you don&#8217;t normally need it for the basic operations), the software stack is a gcc backend and a clone of the Arduino IDE and libraries. This stack makes the switch from Arduino environment very easy.</p>
<p>The Arduino-like libraries are named Energia and can be downloaded as pre-packaged binaries from <a href="http://energia.nu/download/">http://energia.nu/download/</a> or from the GitHub repository: <a href="https://github.com/energia/Energia">https://github.com/energia/Energia</a></p>
<p>The community is still smaller than the huge Arduino community but it is growing fast, you can find a couple of useful links at the end of this article.</p>
<p><a href="http://www.itopen.it/wp-content/uploads/2013/03/LaunchPad-MSP430G2452-v1.5.jpg"><img class="aligncenter size-large wp-image-1005" alt="LaunchPad MSP430G2452-v1.5" src="http://www.itopen.it/wp-content/uploads/2013/03/LaunchPad-MSP430G2452-v1.5-1024x666.jpg" width="800" height="520" /></a></p>
<p>&nbsp;</p>
<p>Some &#8220;shields&#8221; compatible with LaunchPad are also available on TI store, particularly interesting the capacitive and audio shields, that add a touch interface and MP3 recording/playback capabilities to the device. For an overview of the available LaunchPads, see <a href="http://www.ti.com/ww/en/launchpad/overview_head.html">http://www.ti.com/ww/en/launchpad/overview_head.html</a></p>
<p>&nbsp;</p>
<h1>Comparison with Arduino</h1>
<p>The intent of TI when they launched their development board was clearly to follow and exploit the huge success of Arduino, this paragraph will attempt to shed some light on similarities and differences of Arduino and LaunchPad+Energia.</p>
<h2>Hardware</h2>
<p>The Launchpad board is  shipped with two different MCUSs: <strong>MSP430G2553</strong> and <strong>MSP430G2452</strong>, they are both 20 pin devices but the 452 has half the flash and RAM of the 5523.</p>
<p>Comparing MSP430 and Atmega328P is just like comparing apples and oranges but we can try to summarize tha main differences:</p>
<table>
<tbody>
<tr>
<th>MCU features</th>
<th>Arduino/Atmega328P</th>
<th style="text-align: left;">Energia/MSP430G2553</th>
</tr>
<tr>
<td>Architecture</td>
<td>8bit &#8211; RISC &#8211; Harward</td>
<td>16bit &#8211; RISC &#8211; Von Neumann</td>
</tr>
<tr>
<td>Power supply (typ.)</td>
<td>5V</td>
<td>3.3V</td>
</tr>
<tr>
<td>Flash</td>
<td>32KB</td>
<td>16KB</td>
</tr>
<tr>
<td>PINs</td>
<td>28</td>
<td>20</td>
</tr>
<tr>
<td>Timers</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>PWM pins</td>
<td>6</td>
<td>3</td>
</tr>
<tr>
<td>RAM</td>
<td>2KB</td>
<td>512B</td>
</tr>
<tr>
<td>clock</td>
<td>8 MHz int. or 16 MHz ext.</td>
<td>16 MHz int. + optional low speed ext.</td>
</tr>
<tr>
<th style="text-align: left;" colspan="3"><strong>Development board features</strong></th>
</tr>
<tr>
<td>on board LEDs connected to MCU pins</td>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>on board pushbuttons connected to MCU pins</td>
<td>1 (reset)</td>
<td>2 (reset +  one spare)</td>
</tr>
<tr>
<td>on board debugger + emulator</td>
<td>no</td>
<td>yes</td>
</tr>
<tr>
<td>on board programmer</td>
<td>no: bootloader only</td>
<td>yes</td>
</tr>
</tbody>
</table>
<p>What we can tell for sure it that <strong>Atmega328P</strong> beats <strong>MSP430G2553</strong> in Flash and RAM size, but where<strong> MSP430</strong> is clearly superior is:</p>
<ul>
<li>when used in low power modes</li>
<li>CPU speed thanks to 16bit architecture</li>
<li>MCU price: it costs about one third of the Atmega328P</li>
<li>development board price: ~ 5 $ vs. ~ 25 $ of an Arduino UNO</li>
</ul>
<p>On the contrary, Arduino compatible shields,  community and software libraries are far ahead of MSP430/Energia.</p>
<h1>Installing the software</h1>
<p>First you need to install the compiler packages:</p>
<pre class="wp-code-highlight prettyprint linenums:1">binutils-msp430 - Binary utilities supporting TI&#039;s MSP430 targets
gcc-msp430 - GNU C compiler (cross compiler for MSP430)
gdb-msp430 - The GNU debugger for MSP430
msp430-libc - Standard C library for TI MSP430 development
msp430mcu - Spec files, headers and linker scripts for TI&#039;s MSP430 targets
mspdebug - debugging tool for MSP430 microcontrollers</pre>
<p>If you plan to use the Energia libraries which provide an Arduino-like environment, you should download the package from <a href="http://energia.nu/download/">http://energia.nu/download/</a> and install them in a subfolder of your home directory, I installed them in a folder named &#8220;energia&#8221;.</p>
<p>To hold my sketches and libraries, I also created a folder named &#8220;energia_sketchbook&#8221;.</p>
<p>To summarize the steps:</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ sudo apt-get install binutils-msp430 gcc-msp430 gdb-msp430 msp430-libc msp430mcu mspdebug
$ cd
$ mkdir energia_sketchbook
$ wget -O energia.tgz http://energia.nu/download/download.php?file=energia-0101E0009-linux.tgz
$ tar -xzvf energia.tgz
$ mv energia-0101E0009 energia</pre>
<p>An additional step is required if you are on a 64bit architecture:</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ cd energia/lib
$ mv librxtxSerial.so librxtxSerial32.so
$ ln -s librxtxSerial64.so librxtxSerial.so</pre>
<p>After doing this, you should be able to launch the Energia IDE with</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ cd 
$ energia/energia</pre>
<h1>Development using a Makefile</h1>
<p>I&#8217;m the kind of programmer that hates complicated IDEs, moreover I can&#8217;t suffer Java(TM), for this reason I tend to use Makefiles to compile MCU code and the first thing I did was to setup a development environment using a Makefile to do all the compilation, linking and upload stuff.</p>
<p>This Makefile is freely adapted from the good job done by Tim Marston at <a href="http://ed.am/dev/make/arduino-mk">http://ed.am/dev/make/arduino-mk</a></p>
<p>&nbsp;</p>
<p>You can download the latest version of the Makefile from my repository: <a href="https://github.com/elpaso/energia-makefile">https://github.com/elpaso/energia-makefile</a></p>
<pre class="wp-code-highlight prettyprint linenums:1">$ cd
$ cd energia_sketchbook
$ wget https://github.com/elpaso/energia-makefile/raw/master/energia.mk
$ ln -s energia.mk Makefile</pre>
<p>The Make must be launched from within the directory containing the sketch you want to compile, the name of the directory must be the same name of the main sketch file which has the Arduino &#8220;.ino&#8221; file extension.</p>
<p>A couple of environment variables are used to instruct the Makefile where the libraries are located and to build code for the correct MCU (for a complete list of config vars, please refer to the Makefile itself, they are described in details in the header), you can set them once for all using .bashrc:</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ echo &#039;export ENERGIABOARD=lpmsp430g2553&#039; >> ~/.bashrc
$ echo &#039;export ENERGIADIR=/home/your_username/energia&#039; >> ~/.bashrc
$ . ~/.bashrc</pre>
<h1>Hello world!</h1>
<p>You are now ready to test your new Launchpad, the &#8220;Hello World&#8221; program for MCUs is the classic Blink program, which just blinks one of the two leds available on the board, you can just copy the example provided with the Energia IDE:</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ cd
$ cd energia_sketchbook
$ cp -r ../energia/examples/1.Basics/Blink .
$ cd Blink
$ make -f ../Makefile target</pre>
<p>You now need to connect the board to your PC with the provided USB cable.</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ make -f ../Makefile upload</pre>
<p>If everything went fine, you will see a nice blinking led at 1Hz on your Launchpad board.</p>
<h1>The serial nightmare</h1>
<p>The board has onboard USB-to-serial logic, but I had a really hard time before I could use it, and it&#8217;s still somewhat unstable.</p>
<p>Basically, there are some problems with the <strong>acm_cdc</strong> driver provided with latest Ubuntu kernels, I could make it work following the instructions on <a href="https://github.com/energia/Energia/wiki/Linux-Serial-Communication">https://github.com/energia/Energia/wiki/Linux-Serial-Communication</a></p>
<p>More info in this post (and previous pages):<br />
<a href="http://e2e.ti.com/support/low_power_rf/f/156/t/53610.aspx?pi239031349=3">http://e2e.ti.com/support/low_power_rf/f/156/t/53610.aspx?pi239031349=3</a></p>
<p>You will need to compile a patched kernel module named cdcacm (the stock module is called cdc_acm), and you mileage may vary, after compiling and loading the patched module I was able to read from serial just doing:</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ cat /dev/ttyACM1</pre>
<p>Sometimes I still need to unload and reload the module with:</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ sudo rmmod cdc_acm
$ sudo modprobe cdcacm</pre>
<h1>Conclusions</h1>
<p>Arduino and Energia differs too much, but I think they are both interesting devices, given the very low price of MSP430 and the Arduino-like development environment I feel that I will be using this MCUs wherever I can as long as I don&#8217;t need much flash and RAM.</p>
<p>Flash, RAM, community, libraries and examples are what make Arduino great, let&#8217;s see if Energia community will grow  fast and if TI will release more powerful MCUs for this interesting development board.</p>
<h1>Useful links</h1>
<ul>
<li><a href="http://www.ti.com/ww/en/launchpad/overview_head.html">http://www.ti.com/ww/en/launchpad/overview_head.html</a></li>
<li><span style="line-height: 13px;"><a href="http://processors.wiki.ti.com/index.php/Open_Source_Projects_-_MSP430">http://processors.wiki.ti.com/index.php/Open_Source_Projects_-_MSP430</a></span></li>
<li><a href="http://energia.nu/">http://energia.nu/</a></li>
<li><a href="https://github.com/energia/Energia">https://github.com/energia/Energia</a></li>
<li><a href="https://github.com/elpaso/energia-makefile">https://github.com/elpaso/energia-makefile</a></li>
<li><a href="http://forum.43oh.com/forum/28-energia/">http://forum.43oh.com/forum/28-energia/</a></li>
</ul>
<p>Happy hacking!</p>
<p>See also my new article about MSP430:</p>
<p><a href="http://www.itopen.it/2013/03/18/driving-a-pair-of-7-segments-display-with-msp430-energia-libraries/">http://www.itopen.it/2013/03/18/driving-a-pair-of-7-segments-display-with-msp430-energia-libraries/</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2013/03/01/msp430-energia-on-linux/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ligthning fast routing with OSRM</title>
		<link>http://www.itopen.it/2013/02/01/ligthning-fast-routing-with-osrm/</link>
		<comments>http://www.itopen.it/2013/02/01/ligthning-fast-routing-with-osrm/#comments</comments>
		<pubDate>Fri, 01 Feb 2013 12:57:26 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Server Side]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WebGis]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=965</guid>
		<description><![CDATA[

OSRM is a lightning fast open source routing engine for OpenStreetMap data. We are now using it in all the websites managed by our Django-powered GeoRouter platform.]]></description>
				<content:encoded><![CDATA[<h2>The routing engine</h2>
<p>Recently we have upgraded our multi-site Django-based platform (see: <a title="MapSlow Django &amp; OSRM powered platform" href="http://www.mapslow.eu/en/map" target="_blank">MapSlow</a>) to support OpenStreetMap routing with <a title="Project OSRM Home Page" href="http://project-osrm.org/" target="_blank">OSRM</a>.</p>
<p><a href="http://www.itopen.it/wp-content/uploads/2013/02/osrm_routing.png"><img class="alignright size-medium wp-image-968" alt="osrm_routing" src="http://www.itopen.it/wp-content/uploads/2013/02/osrm_routing-300x238.png" width="300" height="238" /></a></p>
<p>OSRM is a lightning fast routing server that uses OpenStreetMap data to calculate routes based on different <strong>routing profiles</strong>, the system is very flexible and configurable, you can setup profiles for car, foot, and bicycle and decide every detail about where the different users (pedestrian, cyclists etc.) can pass trough or cross.</p>
<p>The process of preparing OSM data  for routing requires high CPU and RAM resources and quite a lot of time, we are using a 16 cores and 32 GB RAM virtual instance and the full update takes about 90&#8242; for each profile (for Italy only!!), of course we are running this process (weekly) in the background, at night while server load is typically low.</p>
<p>Since we are using three different profiles, we need three independant OSRM server instances, each running instance requires a huge amount or RAM, for this reason we chose such a powerful server.</p>
<p>We are really satisfied with OSRM, the performances are very good and response is ligthning fast, allowing for a richful UX: while the user drags a waypoint the routes are immediately updated on the screen.</p>
<p>The only missing piece is the ability to use altitude data, this can be a problem when calculating routes for bicycle and foot profiles because they should really take altitude into account to calculate the shortest paths in terms of time.</p>
<h2>The viewer</h2>
<p>The map interface is developed with <a title="JavaScript Toolkit for Rich Web Mapping Applications" href="http://www.geoext.org/" target="_blank">GeoEXT</a> (an EXTJs and OpenLayers wrapper or as stated in the project&#8217;s page: a JavaScript Toolkit for Rich Web Mapping Applications), we managed to write an adapter to query the OSRM server and parse the JSON response to display vector data into the map canvas.</p>
<p>Driving directions are also processed to build a road-book composed by detailed maps and waypoints, with  turn-by-turn routing instructions.</p>
<p>&nbsp;</p>
<h2>Conclusions</h2>
<p>OSRM is a very good and robust project, well suited for fast routing applications. It has fully configurable profiles but each server instance support only one profile at a time, leading to increasing resources requirements as the number of needed profiles grows up.</p>
<p>The only important missing feature is the ability to use a DTM (Digital Terrain Model) to ajust driving speeds in not-flat areas, this obviously leads to wrong shortest (timewise and lengthwise) path calculations in most mountain and hill areas.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2013/02/01/ligthning-fast-routing-with-osrm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Arduino Pong Alarm Clock</title>
		<link>http://www.itopen.it/2013/01/29/arduino-pong-alarm-clock/</link>
		<comments>http://www.itopen.it/2013/01/29/arduino-pong-alarm-clock/#comments</comments>
		<pubDate>Tue, 29 Jan 2013 16:34:23 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[AVR MCU]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=949</guid>
		<description><![CDATA[The Matrixclock project This little project was born to build a present for my son&#8217;s birthday, I had a couple of components laying around and I decided to make something new. Goals build an easy-to-use alarm clock with a personal touch use only components I already had in stock use as few components as possible [...]]]></description>
				<content:encoded><![CDATA[<h2>The Matrixclock project</h2>
<p>This little project was born to build a present for my son&#8217;s birthday, I had a couple of components laying around and I decided to make something new.</p>
<h3>Goals</h3>
<ul>
<li>build an easy-to-use alarm clock with a personal touch</li>
<li><span style="line-height: 13px;">use only components I already had in stock</span></li>
<li>use as few components as possible</li>
<li>low power consumption</li>
<li>learn to solder some SOIC components</li>
</ul>
<h3>Design decisions</h3>
<ul>
<li><span style="line-height: 13px;">project a 3.3V circuit</span></li>
<li>use a 64 led matrix for the display&#8230;</li>
<li>a rotary encoder with integrated pushbutton for the controls</li>
<li>an RGB led to change the clock color while the time passes (60&#8242; cicle)</li>
<li>sometimes print some random messages addressed to my son</li>
<li>play a small song once every hour at his birthday</li>
<li>play a custom alarm music</li>
<li>an LDR sensor to adjust display and RGB brightness in the dark</li>
</ul>
<p>The project ended up using:</p>
<ul>
<li><span style="line-height: 13px;">ATMEGA328P-PU for the MCU, clocked @ 8MHz using internal oscillator and running @ 3.3V</span></li>
<li>DS1388 SOIC for the RTC (unfortunately DS1307 doesn&#8217;t run @ 3.3V)</li>
<li>an 8OHM speaker for the sound</li>
<li>an <a title="AS1107 8 digit led driver" href="http://www.ams.com/eng/Products/Lighting-Management/LED-Driver-ICs/AS1107">AS1107</a>  SOIC to drive the matrix (MAX7219 does not officialy run @ 3.3V even if it seemed ok to me when I tested it on the breadboard)</li>
</ul>
<p>Here is the scheme:</p>
<p><a href="http://www.itopen.it/wp-content/uploads/2013/01/matrixclock.svg"><img class="wp-image-951 alignnone" title="Matrixclock Scheme" alt="Matrixclock Scheme" src="http://www.itopen.it/wp-content/uploads/2013/01/matrixclock.svg" width="787" height="556" /></a></p>
<p style="text-align: left;">And my beloved jungle-breadboard <img src='http://www.itopen.it/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a title="20121215_002 di apasotti, su Flickr" href="http://www.flickr.com/photos/45502883@N06/8426191671/"><img alt="20121215_002" src="http://farm9.staticflickr.com/8049/8426191671_60df9fcc88_n.jpg" width="320" height="241" /></a></p>
<h2>Building the board</h2>
<p>Placing components was the most difficult and tedious work, I had to keep the board small and I only had 100x70mm boards available.</p>
<p><a href="http://www.itopen.it/wp-content/uploads/2013/01/matrixclock-brd.svg"><img class="wp-image-953 alignnone" title="Matrixclock board" alt="Matrixclock board" src="http://www.itopen.it/wp-content/uploads/2013/01/matrixclock-brd.svg" width="787" height="556" /></a></p>
<p>This was my first project using soic components, initially I was a bit scared about that, but it wasn&#8217;t too hard after all.</p>
<p>I used the toner-transfer technique to prepare the PCB:</p>
<p><a title="20121220_001 di apasotti, su Flickr" href="http://www.flickr.com/photos/45502883@N06/8426180975/"><img alt="20121220_001" src="http://farm9.staticflickr.com/8332/8426180975_6913efb610_n.jpg" width="320" height="241" /></a></p>
<p>&#8230; and HCL + H2O2 to etch the board:</p>
<p><a title="20121220_005 di apasotti, su Flickr" href="http://www.flickr.com/photos/45502883@N06/8426182721/"><img alt="20121220_005" src="http://farm9.staticflickr.com/8511/8426182721_32c18bd803_n.jpg" width="320" height="241" /></a></p>
<p>&nbsp;</p>
<p>And finally: some <a title="More photos of the clock" href="http://www.flickr.com/photos/45502883@N06/8427274884/in/photostream/">more photos on Flickr</a> and a short and ugly video showing the clock running.<br />
<object width="560" height="315" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowscriptaccess" value="always" /><param name="src" value="http://www.youtube.com/v/OGkkqt0ZhJw?version=3&amp;hl=it_IT&amp;rel=0" /><param name="allowfullscreen" value="true" /><embed width="560" height="315" type="application/x-shockwave-flash" src="http://www.youtube.com/v/OGkkqt0ZhJw?version=3&amp;hl=it_IT&amp;rel=0" allowFullScreen="true" allowscriptaccess="always" allowfullscreen="true" /></object></p>
<p>&nbsp;</p>
<h2>Follow the source Luke! (The code)</h2>
<p>The code is very patchy but <strong>Just Works (TM) </strong>, I used a couple of Arduino libraries and I merged the Pong game I&#8217;ve already written as a standalone sketch.</p>
<p>&nbsp;</p>
<pre class="wp-code-highlight prettyprint linenums:1">
/**
* Matrix Clock
*/

#define DEBUG_CLOCK 0
#define ENABLE_RGB  1 /* rgb led */


// Pins
#define ENCODER_PIN_1   2 // INT0
#define ENCODER_PIN_2   3 // INT1
#define SET_PIN         4 // digital pull up, connected to ENCODER push button
#define LC_PIN_1        8
#define LC_PIN_2        7
#define LC_PIN_3        6
#define ALM_SWITCH_PIN  A3
#define BUZZER_PIN      5 // digital (PWM?) -&gt; BUZZER -&gt; GND
#define RED_PIN         9
#define GREEN_PIN       10
#define BLUE_PIN        11
#define LDR_PIN         A2

// Includes
#include &quot;LedControl.h&quot;
#include &quot;8x8Font.h&quot;
#include &quot;3x5Font.h&quot;
#include &lt;EEPROM.h&gt;
#include &quot;EEPROMAnything.h&quot;
#include &lt;Wire.h&gt;
#include &quot;RTClib.h&quot;
#include &quot;Timer.h&quot;
#include &lt;Encoder.h&gt;
#include &quot;note.h&quot;
#include &quot;messages.h&quot;

#define NO_PORTB_PINCHANGES // to indicate that port b will not be used for pin change interrupts
#define NO_PORTC_PINCHANGES // to indicate that port c will not be used for pin change interrupts
// if there is only one PCInt vector in use the code can be inlined
// reducing latency and code size
// define DISABLE_PCINT_MULTI_SERVICE below to limit the handler to servicing a single interrupt per invocation.
#define       DISABLE_PCINT_MULTI_SERVICE
#include &lt;PinChangeInt.h&gt;

// FSM status
#define CLK_IDLE        0
#define CLK_PLAY        1
#define CLK_SET_ALM_H   2
#define CLK_SET_ALM_M   3
#define CLK_SET_TIM_H   4
#define CLK_SET_TIM_M   5
#define CLK_SET_TIM_S   6
#define CLK_SET_DAT_D   7
#define CLK_SET_DAT_M   8
#define CLK_SET_DAT_Y   9
#define CLK_SET_SPEED   10
#define CLK_SET_LAST    10 // Must be the last: check main code for status changes.

#define POS_CENTER      1
#define POS_LEFT        0
#define POS_RIGHT       2
#define SYM_ALM         0
#define SYM_DATE        1
#define SYM_TIME        2
#define SYM_SETUP       3

// Config
#define BIRTHDAY_M      4
#define BIRTHDAY_D      12
#define CHAR_SPEED      20

// Random message every
#define RANDOM_MSG_EVERY 6 * 60 * 1000 // 13 minutes
#define PRINT_DATE_EVERY_CICLES 5

// Alarm FSM
#define ALM_PLAY        1
#define ALM_STOP        0
#define ALM_CLEARED     2

// Pong
#define PADSIZE 3
#define BALL_DELAY 100
#define GAME_DELAY 9
#define BOUNCE_VERTICAL 1
#define BOUNCE_HORIZONTAL -1

#define HIT_NONE 0
#define HIT_CENTER 1
#define HIT_LEFT 2
#define HIT_RIGHT 3


// Timers
#define TIMEOUT         5000 // millis
#define DELAYED_TIMEOUT 20000 // millis
#define DEBOUNCE        200 // millis between pulses
#define ALM_RESET_AFTER_MINUTES     2 // timer for alarm reset


// Ugly globals...
uint8_t timeH;
uint8_t timeM;
volatile uint8_t timeS;
uint8_t dateD;
uint8_t dateM;
uint8_t dateY;
uint8_t dateW;
uint8_t almH;
uint8_t almM;
//int almDays;
uint8_t brightness = 8;
const uint8_t eeprom_id = 0x99;
DateTime now;
uint8_t print_date;
uint8_t char_speed = CHAR_SPEED;

// store clock status
int clockStatus = CLK_IDLE;


// Used in ISR, keep one-byte-long to avoid disabling INTs

byte alarmStatus = ALM_STOP;
volatile boolean setButtonPressed = false;
volatile unsigned long setButtonBounceTime=0; // variable to hold ms count to debounce a pressed switch

int oldStatus = CLK_IDLE;

// Timers
Timer timer;
volatile int idleTimer = 1000; // set to out of range value
volatile int alarmTimer = 1000;
volatile int storeConfigTimer = 1000;
volatile int ballTimer = 1000;

// Pong
byte direction; // Wind rose, 0 is north
int xball;
int yball;
int yball_prev;
int xpad;


// Sound
//char noteNames[] =     {&#039;C&#039;,&#039;D&#039;,&#039;E&#039;,&#039;F&#039;,&#039;G&#039;,&#039;a&#039;,&#039;b&#039;};
//unsigned int frequencies[] = {262,294,330,349,392,440,494};
//const byte noteCount = sizeof(noteNames); // the number of notes
                                          // (7 in this example)

//notes, a space represents a rest
// char song[] PROGMEM = &quot;CCGGaaGFFEEDDC GGFFEEDGGFFEED CCGGaaGFFEEDDC &quot;;
unsigned int alarm_song[] PROGMEM = {NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4, NOTE_G4, SILENCE, NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_C4, SILENCE, SILENCE, NOTE_G4, NOTE_G4, NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4,  NOTE_D4, SILENCE, NOTE_G4, NOTE_G4, NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4, SILENCE, SILENCE, NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4, NOTE_A4, NOTE_A4, NOTE_G4, SILENCE, NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4, NOTE_D4, NOTE_D4, NOTE_C4, SILENCE, END_SONG};

//do do re do fa mi   do do re do sol fa  do do do# la fa mi re   do do re do fa mi
// # G G A G C B | G G A G D C | G G + G E C B A | F F E C D C
unsigned int birthday_song[] PROGMEM = {NOTE_G4, NOTE_A4, NOTE_G4, NOTE_C5, NOTE_B4, SILENCE, NOTE_G4, NOTE_A4, NOTE_G4, NOTE_D5, NOTE_C5, SILENCE, NOTE_G4, NOTE_G5, NOTE_E5, NOTE_C5, NOTE_B4, NOTE_A4, SILENCE, NOTE_F4, NOTE_E4, NOTE_C4, NOTE_D4, NOTE_C4, SILENCE, END_SONG};

// Encoder
int encoderCount = 0;
Encoder myEnc(ENCODER_PIN_2, ENCODER_PIN_1);


#if DEBUG_CLOCK

RTC_DS1307 RTC;


// variables created by the build process when compiling the sketch
extern int __bss_end;
extern void *__brkval;
// function to return the amount of free RAM
int memoryFree()  {
    int freeValue;
    if((int)__brkval == 0)
        freeValue = ((int)&amp;freeValue) - ((int)&amp;__bss_end);
    else
        freeValue = ((int)&amp;freeValue) - ((int)__brkval);
    return freeValue;
}
#else

RTC_DS1388 RTC;

#endif


LedControl lc = LedControl(LC_PIN_1, LC_PIN_2, LC_PIN_3,1);

char char_buffer[8];
char char_buffer2[8];
char buf[64];

#if ENABLE_RGB

void setColor(int red, int green, int blue)
{
    analogWrite(RED_PIN, 255-red);
    analogWrite(GREEN_PIN, 255-green);
    analogWrite(BLUE_PIN, 255-blue);
}

//Convert a given HSV (Hue Saturation Value) to RGB(Red Green Blue) and set the led to the color
//  h is hue value, integer between 0 and 360
//  s is saturation value, double between 0 and 1
//  v is value, double between 0 and 1
//http://splinter.com.au/blog/?p=29
void setColorHsv(int h, double s, double v)
{
    byte rgb[3];

    // Make sure our arguments stay in-range
    h = max(0, min(360, h));
    s = max(0, min(1.0, s));
    v = max(0, min(1.0, v));
    if(s == 0)
    {
        // Achromatic (grey)
        rgb[0] = rgb[1] = rgb[2] = round(v * 255);
    } else {
        double hs = h / 60.0; // sector 0 to 5
        int i = floor(hs);
        double f = hs - i; // factorial part of h
        double p = v * (1 - s);
        double q = v * (1 - s * f);
        double t = v * (1 - s * (1 - f));
        double r, g, b;
        switch(i)
        {
                case 0:
                        r = v;
                        g = t;
                        b = p;
                        break;
                case 1:
                        r = q;
                        g = v;
                        b = p;
                        break;
                case 2:
                        r = p;
                        g = v;
                        b = t;
                        break;
                case 3:
                        r = p;
                        g = q;
                        b = v;
                        break;
                case 4:
                        r = t;
                        g = p;
                        b = v;
                        break;
                default: // case 5:
                        r = v;
                        g = p;
                        b = q;
        }
        rgb[0] = round(r * 255.0);
        rgb[1] = round(g * 255.0);
        rgb[2] = round(b * 255.0);
    }
    setColor(rgb[0], rgb[1], rgb[2]);
}



void setColorHueValue(int hueValue, uint8_t brightness)
{
    setColorHsv(hueValue, 1, constrain((double)brightness/15, 0.1, 1));
}

#endif


/*
* Play a note for a given time
*
*
void playNote(char note, int duration)
{
  // play the tone corresponding to the note name
  for (int i = 0; i &lt; noteCount; i++)
  {
    // try and find a match for the noteName to get the index to the note
    if (noteNames[i] == note) // find a matching note name in the array
      //  play the note using the frequency:
      tone(BUZZER_PIN, frequencies[i], duration);
  }
  // if there is no match then the note is a rest, so just do the delay
  delay(duration);
}
*/

/**
* Play a note for a given time
*
*/
void playFrequency(unsigned int note, int duration)
{
    if(note != SILENCE){
        tone(BUZZER_PIN, note, duration);
    }
    delay(duration);
}


/**
* Set IDLE status
*/
void setIdle()
{
    clockStatus = CLK_IDLE;
}


/**
 * Get encoder move
 */
void readEncoder(){
    encoderCount = myEnc.read()/4;
    if(encoderCount){
        myEnc.write(0);
    }
}


/**
 * String message handling
 */


char reverseByte(char b) {
   b = (b &amp; 0xF0) &gt;&gt; 4 | (b &amp; 0x0F) &lt;&lt; 4;
   b = (b &amp; 0xCC) &gt;&gt; 2 | (b &amp; 0x33) &lt;&lt; 2;
   b = (b &amp; 0xAA) &gt;&gt; 1 | (b &amp; 0x55) &lt;&lt; 1;
   return b;
}

void setSprite(char* font){
    for(int r = 0; r &lt; 8; r++){
        lc.setRow(0, r, reverseByte(*(font + r)));
    }
}

void load_char(char i, char* c){
    for(int r = 0; r &lt; 8; r++){
        c[r] = pgm_read_byte((char*)font_data + (i * 8) + r);
    }
}

void merge_char(char* c1, char* c2, char pos){
    for(int r = 0; r &lt; 8; r++){
        c1[r] = (c1[r] &lt;&lt; 1) | (c2[r] &gt;&gt; (8 - pos)) ;
    }
}

void print_string(char* s){
    load_char(32, char_buffer);
    bool valid = 1;
    while (valid){
        setSprite(char_buffer);
        load_char(*s ? *s : 32, char_buffer2);
        for(int r = 1; r &lt;= 8; r++){
            if(setButtonPressed){
                return;
            }
            merge_char(char_buffer, char_buffer2, r);
            setSprite(char_buffer);
            delay(char_speed);
        }
        valid = (char) *s;
        s++;
    }
}

void load_digits(char* c, uint8_t digits, uint8_t pos, uint8_t sym){
    for(uint8_t i=0; i&lt;5; i++){
        c[i] = pgm_read_byte((char*)small_font_data + digits / 10 * 5 + i) &lt;&lt; 4 | pgm_read_byte((char*)small_font_data + digits % 10 * 5 + i);
    }
    c[5] = 0;
    uint8_t shift = constrain(6 - 3 * pos, 0, 5);
    switch(sym){
        case SYM_ALM:
            c[6] = B00000010 &lt;&lt; shift;
            c[7] = B00000101 &lt;&lt; shift;
        break;
        case SYM_TIME:
            c[6] = B00000111 &lt;&lt; shift;
            c[7] = B00000010 &lt;&lt; shift;
        break;
        case SYM_DATE:
            c[6] = B00000111 &lt;&lt; shift;
            c[7] = B00000101 &lt;&lt; shift;
        break;
        case SYM_SETUP:
            c[6] = 0;
            c[7] = B00000111 &lt;&lt; shift;
        break;
    }
}

/**
 * Pong game
 */
void newGame() {
    lc.clearDisplay(0);
    // initial position
    xball = random(1, 7);
    yball = 1;
    direction = random(3, 6); // Go south
    load_char(1, char_buffer);
    setSprite(char_buffer);
    delay(700);
    lc.clearDisplay(0);
}


void setPad() {
    readEncoder();
    xpad = constrain(xpad + encoderCount, 0, 8 - PADSIZE);
}


/**
* Checks if the ball is in contact with the walls
*/
int checkBounce() {
    if(!xball || !yball || xball == 7 || yball == 6){
        int bounce = (yball == 0 || yball == 6) ? BOUNCE_HORIZONTAL : BOUNCE_VERTICAL;
        return bounce;
    }
    return 0;
}

int getHit() {
    if(yball != 6 || xball &lt; xpad || xball &gt; xpad + PADSIZE){
        return HIT_NONE;
    }
    if(xball == xpad + PADSIZE / 2){
        return HIT_CENTER;
    }
    return xball &lt; xpad + PADSIZE / 2 ? HIT_LEFT : HIT_RIGHT;
}

bool checkLoose() {
    return yball == 6 &amp;&amp; getHit() == HIT_NONE;
}

void hitSound(){
    playFrequency(NOTE_B4, 2);
}

void moveBall() {
    int bounce = checkBounce();
    if(bounce) {
        switch(direction){
            case 0:
                direction = 4;
            break;
            case 1:
                direction = (bounce == BOUNCE_VERTICAL) ? 7 : 3;
            break;
            case 2:
                direction = 6;
            break;
            case 6:
                direction = 2;
            break;
            case 7:
                direction = (bounce == BOUNCE_VERTICAL) ? 1 : 5;
            break;
            case 5:
                direction = (bounce == BOUNCE_VERTICAL) ? 3 : 7;
            break;
            case 3:
                direction = (bounce == BOUNCE_VERTICAL) ? 5 : 1;
            break;
            case 4:
                direction = 0;
            break;
        }
    }

    // Check hit
    switch(getHit()){
        case HIT_LEFT:
            if(direction == 0){
                direction =  7;
            } else if (direction == 1){
                direction = 0;
            }
            hitSound();
        break;
        case HIT_RIGHT:
            if(direction == 0){
                direction = 1;
            } else if(direction == 7){
                direction = 0;
            }
            hitSound();
        break;
        case HIT_CENTER:
            hitSound();
        break;
    }

    // Check orthogonal directions and borders ...
    // should never happen
    if((direction == 0 &amp;&amp; xball == 0) || (direction == 4 &amp;&amp; xball == 7)){
        direction++;
    }
    if(direction == 0 &amp;&amp; xball == 7){
        direction = 7;
    }
    if(direction == 4 &amp;&amp; xball == 0){
        direction = 3;
    }

    if(direction == 2 &amp;&amp; yball == 0){
        direction = 3;
    }
    if(direction == 2 &amp;&amp; yball == 6){
        direction = 1;
    }
    if(direction == 6 &amp;&amp; yball == 0){
        direction = 5;
    }
    if(direction == 6 &amp;&amp; yball == 6){
        direction = 7;
    }

    // Corner case:
    if(xball == 0 &amp;&amp; yball == 0){
        direction = 3;
    }
    if(xball == 0 &amp;&amp; yball == 6){
        direction = 1;
    }
    if(xball == 7 &amp;&amp; yball == 6){
        direction = 7;
    }
    if(xball == 7 &amp;&amp; yball == 0){
        direction = 5;
    }


    yball_prev = yball;
    if(2 &lt; direction &amp;&amp; direction &lt; 6) {
        yball++;
    } else if(direction != 6 &amp;&amp; direction != 2) {
        yball--;
    }
    if(0 &lt; direction &amp;&amp; direction &lt; 4) {
        xball++;
    } else if(direction != 0 &amp;&amp; direction != 4) {
        xball--;
    }
    xball = max(0, min(7, xball));
    yball = max(0, min(6, yball));
}

void gameOver() {
    load_char(33, char_buffer);
    setSprite(char_buffer);
    delay(1500);
    lc.clearDisplay(0);
}


void drawGame() {
    if(yball_prev != yball){
        lc.setRow(0, yball_prev, 0);
    }
    lc.setRow(0, yball, byte(1 &lt;&lt; (xball)));
    byte padmap = byte(0xFF &gt;&gt; (8 - PADSIZE) &lt;&lt; xpad) ;
    lc.setRow(0, 7, padmap);
}

void initGame(){
  randomSeed(analogRead(0));
  newGame();
  ballTimer = timer.every(BALL_DELAY, moveBall);

}

void playGame(){
    while(!setButtonPressed){
        timer.update();
        setPad();
        drawGame();
        if(checkLoose()) {
            gameOver();
            newGame();
        }
        delay(GAME_DELAY);
    }
    timer.stop(ballTimer);
}




/**
* Wake up effect, this is not returning
* check for status from button ISR
*
*/
void wakeUp(const unsigned int* song)
{
    while (pgm_read_word(song) != END_SONG)
    {
        if(alarmStatus != ALM_PLAY || setButtonPressed){
            alarmStatus = ALM_CLEARED;
            setButtonPressed = false;
            return;
        }
        playFrequency(pgm_read_word(song++), 333); // play the note
    }
    delay(4000); // wait four seconds before repeating the song
}


/**
 * Birthday
 */
void check_birthday(){
    unsigned int *song;
    song = birthday_song;
    if(dateD == BIRTHDAY_D &amp;&amp; dateM == BIRTHDAY_M &amp;&amp; timeH &gt; 9 &amp;&amp; timeH &lt; 21){
        load_char(3, char_buffer);
        setSprite(char_buffer);
        while (pgm_read_word(song) != END_SONG)
        {
            playFrequency(pgm_read_word(song++), 333); // play the note
        }
        delay(4000);
    }
}

/**
* Turn off alarm
*/
void stopAlarm(){
    alarmStatus = ALM_CLEARED;
    //digitalWrite(BUZZER_PIN, LOW);
    //digitalWrite(ALM_LED_PIN, LOW);
}


/**
* ISR on FALLING push button
*/
void setSetButtonPressed(){
    // this is the interrupt handler for button presses
    // it ignores presses that occur in intervals less then the bounce time
    if (abs(millis() - setButtonBounceTime) &gt; DEBOUNCE)
    {
        setButtonPressed = true;
        setButtonBounceTime = millis();  // set whatever bounce time in ms is appropriate
    }
}


/**
* Changes clock status
*/
void changeStatus()
{
    clockStatus++;
    if(clockStatus &gt; CLK_SET_LAST){
        setIdle();
    }
    // Start timer
    timer.stop(idleTimer);
    idleTimer = timer.after(TIMEOUT, setIdle);
    setButtonPressed = false;
}

/**
 * Store config to EEPROM
 */
void store_config(){
    // Read EEPROM
    int write = 0;
    write += EEPROM_writeAnything(write, eeprom_id);
    write += EEPROM_writeAnything(write, char_speed);
    write += EEPROM_writeAnything(write, almH);
    EEPROM_writeAnything(write, almM);
}

/**
 * Delayed store config
 */
void store_config_delayed(){
    timer.stop(storeConfigTimer);
    storeConfigTimer = timer.after(DELAYED_TIMEOUT, store_config);
}

/**
 * Adjust clock
 */
void storeDateTime(){
    RTC.adjust(DateTime(dateY, dateM, dateD, timeH, timeM, timeS));
}

/**
 * Adjust brightness
 */
void adjustBrightness(){
    brightness = map(analogRead(LDR_PIN), 0, 1023, 0, 15);
    lc.setIntensity(0, brightness);
#if ENABLE_RGB
    setColorHueValue((uint16_t)timeM * 6, brightness);
#endif

}

/**
 *  Random message
 */
void randomMessage(){
    if(clockStatus == CLK_IDLE){
        strcpy_P(buf, (char*)pgm_read_word(&amp;(messages[random(0, sizeof(messages)/sizeof(char *))])));
        print_string(buf);
    }
}

/**
 * Setup
 */
void setup() {

    // Read Alm from EEPROM
    // Read EEPROM
    if(EEPROM.read(0) == eeprom_id){
        int read = 1;
        read += EEPROM_readAnything(read, char_speed);
        read += EEPROM_readAnything(read, almH);
        EEPROM_readAnything(read, almM);
    } else {
        store_config();
    }

    pinMode(LDR_PIN, INPUT);
    adjustBrightness();

    // LCD
    // The MAX72XX is in power-saving mode on startup,
    // we have to do a wakeup call
    lc.shutdown(0,false);
    /* Set the brightness to a medium values range (0-15) */
    lc.setIntensity(0, brightness);
    /* and clear the display */
    lc.clearDisplay(0);

    // RTC
    Wire.begin();
    RTC.begin();
    if (! RTC.isrunning()) {
        // following line sets the RTC to the date &amp; time this sketch was compiled
        RTC.adjust(DateTime(__DATE__, __TIME__));
    }

    // Encoder &amp; push
    pinMode(SET_PIN, INPUT);
    digitalWrite(SET_PIN, HIGH);
    PCintPort::attachInterrupt(SET_PIN, &amp;setSetButtonPressed, FALLING);

    // Alm enable pin
    pinMode(ALM_SWITCH_PIN, INPUT);
    digitalWrite(ALM_SWITCH_PIN, HIGH); // pull up
    pinMode(BUZZER_PIN, OUTPUT);

    timer.every(1000, adjustBrightness);
    timer.every(RANDOM_MSG_EVERY, randomMessage);

    print_date = 0;
}


/**
 * Loop
 */
void loop() {
    if(setButtonPressed &amp;&amp; alarmStatus != ALM_PLAY){
        changeStatus();
    }

    // Read encoder
    readEncoder();

    // Read clock
    now = RTC.now();
    timeH = now.hour();
    timeM = now.minute();
    timeS = now.second();
    dateD = now.day();
    dateM = now.month();
    dateY = now.yoff();

    boolean alarmSwitchClosed;

    alarmSwitchClosed = (digitalRead(ALM_SWITCH_PIN) == LOW); // pull-up, closed is low

    // Check alarm, buttons pressed stop alarm
    int minutes_after_alarm;
    minutes_after_alarm = ((int)timeH * 60 + (int)timeM) - ((int)almH * 60 + (int)almM);


    if(clockStatus == CLK_IDLE &amp;&amp; alarmSwitchClosed &amp;&amp; alarmStatus == ALM_STOP &amp;&amp; minutes_after_alarm == 0){
        alarmStatus = ALM_PLAY;
    }

    if(alarmStatus == ALM_PLAY){
        if(clockStatus == CLK_IDLE &amp;&amp; alarmSwitchClosed &amp;&amp; !setButtonPressed){
            load_char(13, char_buffer);
            setSprite(char_buffer);
            wakeUp(alarm_song);
        } else {
            stopAlarm();
        }
    }

    if(clockStatus == CLK_PLAY){
        timer.stop(idleTimer);
        initGame();
        playGame();
        idleTimer = timer.after(TIMEOUT, setIdle);
    }

    if(clockStatus &gt; CLK_PLAY){
        uint8_t digits;
        uint8_t pos;
        uint8_t sym;
        switch(clockStatus) {
            case CLK_SET_ALM_H:
                pos = POS_LEFT;
                sym = SYM_ALM;
                digits = almH;
            break;
            case CLK_SET_ALM_M:
                pos = POS_CENTER;
                sym = SYM_ALM;
                digits = almM;
            break;
            case CLK_SET_TIM_H:
                pos = POS_LEFT;
                sym = SYM_TIME;
                digits = timeH;
            break;
            case CLK_SET_TIM_M:
                pos = POS_CENTER;
                sym = SYM_TIME;
                digits = timeM;
            break;
            case CLK_SET_TIM_S:
                pos = POS_RIGHT;
                sym = SYM_TIME;
                digits = timeS;
            break;
            case CLK_SET_DAT_D:
                pos = POS_LEFT;
                sym = SYM_DATE;
                digits = dateD;
            break;
            case CLK_SET_DAT_M:
                pos = POS_CENTER;
                sym = SYM_DATE;
                digits = dateM;
            break;
            case CLK_SET_DAT_Y:
                pos = POS_RIGHT;
                sym = SYM_DATE;
                pos = 2;
                digits = dateY;
            break;
            case CLK_SET_SPEED:
                digits = char_speed;
                pos = POS_CENTER;
                sym = SYM_SETUP;
            break;
        }
        if(encoderCount){
            // reset timeout
            timer.stop(idleTimer);
            idleTimer = timer.after(TIMEOUT, setIdle);
            // Update...
            switch(clockStatus) {
                case CLK_SET_ALM_H:
                    almH += encoderCount;
                    if(almH &gt; 23) almH = 0;
                    store_config_delayed();
                break;
                case CLK_SET_ALM_M:
                    almM += encoderCount;
                    if(almM &gt; 59) almM = 0;
                    store_config_delayed();
                break;
                case CLK_SET_TIM_H:
                    timeH  += encoderCount;
                    if(timeH &gt; 23) timeH = 0;
                    storeDateTime();
                break;
                case CLK_SET_TIM_M:
                    timeM += encoderCount;
                    if(timeM &gt; 59) timeM = 0;
                    storeDateTime();
                break;
                case CLK_SET_TIM_S:
                    timeS += encoderCount;
                    if(timeS &gt; 59) timeS = 0;
                    storeDateTime();
                break;
                case CLK_SET_DAT_D:
                    dateD += encoderCount;
                    if(dateD &gt; 31)dateD = 1;
                    storeDateTime();
                break;
                case CLK_SET_DAT_M:
                    dateM += encoderCount;
                    if(dateM &gt; 12) dateM= 1;
                    storeDateTime();
                break;
                case CLK_SET_DAT_Y:
                    dateY += encoderCount;
                    if(dateY &gt; 99) dateY = 0;
                    storeDateTime();
                break;
                case CLK_SET_SPEED:
                    char_speed+= encoderCount;
                    if(char_speed &gt; 30) char_speed = 10;
                    if(char_speed &lt; 10) char_speed = 30;
                    store_config_delayed();
                break;
           }
        }
        load_digits(char_buffer, digits, pos, sym);
        setSprite(char_buffer);
    } else {
        //strcpy_P(buf, PSTR(&quot;Ciao Leo... sono le&quot;));
        //print_string((char*) buf);
#if DEBUG_CLOCK
        //sprintf(buf, &quot;E: %d S: %d&quot;, encoderCount, clockStatus);
        //print_string(buf);
        //sprintf_P(buf, PSTR(&quot;F:%d&quot;), memoryFree());
        //print_string(buf);
        sprintf_P(buf, PSTR(&quot;B:%d&quot;), brightness);
        print_string(buf);
#endif
        sprintf_P(buf, PSTR(&quot;%02d:%02d:%02d&quot;), now.hour(), now.minute(), now.second());
        print_string(buf);

        if(print_date++ == PRINT_DATE_EVERY_CICLES){
            print_date = 0;
            sprintf_P(buf, PSTR(&quot;%02d-%02d-%d&quot;), now.day(), now.month(), now.year());
            print_string(buf);
        }

        // Show alarm
        if(alarmSwitchClosed &amp;&amp; alarmStatus == ALM_STOP){
            sprintf_P(buf, PSTR(&quot;%c %02d:%02d&quot;), 13, almH, almM);
            print_string(buf);
        }
    }

    if(timeM == 0){
        check_birthday();
    }

    // Hand timer
    if(alarmStatus != ALM_STOP &amp;&amp; minutes_after_alarm &gt;= ALM_RESET_AFTER_MINUTES){
        alarmStatus = ALM_STOP;
    }

     timer.update();

}
</pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2013/01/29/arduino-pong-alarm-clock/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DIY AVR programmer notes</title>
		<link>http://www.itopen.it/2012/12/04/diy-avr-programmer-notes/</link>
		<comments>http://www.itopen.it/2012/12/04/diy-avr-programmer-notes/#comments</comments>
		<pubDate>Tue, 04 Dec 2012 13:31:37 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Arduino]]></category>
		<category><![CDATA[AVR MCU]]></category>
		<category><![CDATA[Programmazione]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=935</guid>
		<description><![CDATA[Recently I&#8217;ve built a small clone of LittleWire Attiny85 based AVR programmer. A few notes to make it work with my toolchain follows: Avoid permission errors on Ubuntu 12.10 Due to permissions on USB you can get the following error: usbtiny_transmit: error sending control message: Operation not permitted to fix it: $ cat  /etc/udev/rules.d/10-usbtinyisp.rules # [...]]]></description>
				<content:encoded><![CDATA[<div id="attachment_936" class="wp-caption alignright" style="width: 310px"><a href="http://www.itopen.it/wp-content/uploads/2012/12/20121204_001.jpg"><img class="size-medium wp-image-936" title="DIY AVR programmer" alt="" src="http://www.itopen.it/wp-content/uploads/2012/12/20121204_001-300x225.jpg" width="300" height="225" /></a><p class="wp-caption-text">An AVR programmer based on LittleWire</p></div>
<p>Recently I&#8217;ve built a small clone of <a title="LittleWire Home Page" href="http://littlewire.cc/" target="_blank">LittleWire</a> Attiny85 based AVR programmer.</p>
<p>A few notes to make it work with my toolchain follows:</p>
<h3>Avoid permission errors on Ubuntu 12.10</h3>
<p>Due to permissions on USB you can get the following error:</p>
<pre class="wp-code-highlight prettyprint linenums:1">usbtiny_transmit: error sending control message: Operation not permitted</pre>
<p>to fix it:</p>
<pre class="wp-code-highlight prettyprint linenums:1">$ cat  /etc/udev/rules.d/10-usbtinyisp.rules
# USBTiny
ATTR{idVendor}==&quot;1781&quot;, ATTR{idProduct}==&quot;0c9f&quot;, GROUP=&quot;plugdev&quot;, MODE=&quot;0666&quot;
&lt;em id=&quot;__mceDel&quot;&gt;$ sudo restart udev&lt;/em&gt;</pre>
<p>unplug and plug the programmer to see the changes.</p>
<h3>Burn a bootloader on a factory new Atmega 328P-PU</h3>
<pre class="wp-code-highlight prettyprint linenums:1">avrdude -b 19200 -c usbtiny -p m328p -v -e -U efuse:w:0x05:m -U hfuse:w:0xD6:m -U lfuse:w:0xFF:m
avrdude -b 19200 -c usbtiny -p m328p -v -e -U flash:w:optiboot_atmega328.hex -U lock:w:0x0F:m</pre>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2012/12/04/diy-avr-programmer-notes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Power Tags for Joomla</title>
		<link>http://www.itopen.it/2012/11/23/power-tags-for-joomla/</link>
		<comments>http://www.itopen.it/2012/11/23/power-tags-for-joomla/#comments</comments>
		<pubDate>Fri, 23 Nov 2012 13:44:37 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Joomla]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=920</guid>
		<description><![CDATA[PowerTags is a new Joomla! 2.5.x component that let you easily add Tags to articles, weblinks and events (managed by the Eventlist component). The component is professionally supported and actively developed, it is released under AGPL license and is available for download for a small fee which will be used to maintain and further develop the component and to provide quick and efficient assistance to the users.]]></description>
				<content:encoded><![CDATA[<p><object><form action="https://www.paypal.com/cgi-bin/webscr" method="post"><input type="hidden" name="cmd" value="_xclick" /><input type="hidden" name="business" value="apasotti@gmail.com" /><input type="hidden" name="item_name" value="PowerTags - Joomla! Component" /><input type="hidden" name="amount" value="15" /><input type="hidden" name="currency_code" value="EUR" /><input type="hidden" name="item_number" value="5" /><input type="hidden" name="notify_url" value="http://www.itopen.it/wp-content/plugins/wp-cart-for-digital-products/paypal.php" /><input type="hidden" name="return" value="http://www.itopen.it/ppipn/thank-you.php" /><input type="hidden" name="mrb" value="3FWGC6LFTMTUG" /><input type="hidden" name="cbt" value="" /><input type="hidden" name="custom" value="" id="eStore_custom_values" /><input type="image" src="https://www.paypal.com/en_US/IT/i/btn/btn_buynowCC_LG.gif" class="eStore_buy_now_button" alt="Buy Now"/></form></object></p>
<div>
<div id="attachment_921" class="wp-caption alignright" style="width: 410px"><img class="size-full wp-image-921" title="PwerTags for Joomla! logo" src="http://www.itopen.it/wp-content/uploads/2012/11/powertags_banner_400.png" alt="" width="400" height="75" /><p class="wp-caption-text">PwerTags for Joomla! logo</p></div>
<p><img title="joomla_25" src="http://www.itopen.it/wp-content/uploads/2011/09/joomla_25.png" alt="" width="75" height="16" /></p>
</div>
<p><a class="rounded button" href="http://www.itopen.it/powertags_docs/">Browse PowerTags documentation!</a></p>
<p><a class="rounded button" href="http://joomla.itopen.it/">PowerTags demo site</a></p>
<div id="key-features">
<h2>Key features</h2>
<p><strong>Tags</strong> can be used to freely organize Joomla! content items (<strong>Tagged Items</strong>) in a more simple manner, you can attach multiple <strong>Tags</strong> to a single item and build a menu-like structure with the <strong>Tags</strong> using the dedicated <a href="http://www.itopen.it/powertags_docs/modules.html#modules"><em>Modules</em></a>. Another module can be used to show a <strong>tag-cloud</strong> and another one can be used to show <strong>related items</strong> (items that share the same <strong>Tags</strong>).</p>
<p>Adding tags to item is super-simple: <em>Ajax</em> powered <em>live-search</em> alllows you to scan the existing <strong>Tags</strong> while you type and to select matching <strong>Tags</strong> from a list, to reduce the risk of typos and duplicated <strong>Tags</strong>.</p>
<div>
<div class="wp-caption alignnone" style="width: 528px"><img title="Attaching and detching tags to an Article" src="http://www.itopen.it/powertags_docs/_images/pt_be_article_manager_live_search.png" alt="Attaching and detching tags to an Article" width="518" height="327" /><p class="wp-caption-text">Attaching and detching tags to an Article</p></div>
<p>Items can be tagged from the <strong>Back-End</strong> (control panel) and even from the <strong>Front-End</strong> (public site) (if a view is available for that component).</p>
</div>
<p>Style is important, you can associate a different icon to every <strong>Tag</strong> to style them differently.</p>
<p>What makes this component unique among other tagging tools in the <strong>Joomla!</strong> galaxy is the level of assistance (this is really what people pays for), its ease of use, its configurability and its rich set of features.</p>
<h2>Download</h2>
<p><strong>PowerTags </strong>for Joomla! is <strong>open source software</strong>, distributed under <a title="AGPL Licence Text" href="http://www.fsf.org/licensing/licenses/agpl-3.0.html" target="_blank"><strong>AGPL</strong></a> software license and it is also <a title="Wikipedia Free Software page" href="http://en.wikipedia.org/wiki/Free_software" target="_blank"><strong>free software</strong></a>, where “free” means that you can do (almost) whatever you want with this software but it does not mean that it costs nothing. We distribute the component only in bundle with paid 12 month support service that costs <strong> 15 €</strong>.</p>
<p>To receive a copy of <strong>PowerTags</strong> you are kindly requested to pay us <strong> 15 €</strong>, using the buttons located at the top or at the bottom of this page. You will receive a regular invoice at the end of the month. After a successful payment,  an email with the download link will be automatically sent to you PayPal’s account email address.</p>
<p>The money you give us will be used to further develop <strong>PowerTags</strong> and to provide professional assistance and support to those that will need it.</p>
<p>Together with 12 months support you will receive software updates for the same period of time, that means that you can pay just once and use the software forever in how many Joomla installations you like.</p>
<p>Please use the <strong>PayPal</strong> link at the top of this page, after a successful payment a download link will be sent you automatically.</p>
<p>Thank you for supporting <strong>PowerTags</strong> project!</p>
<h2>Refund policy</h2>
<p>We provide a <strong>7 days refund policy (one week)</strong>, if you are not satisfied with PowerTags you can ask for a refund within 7 days from the purchase and you will get a full refund (we will only keep the small transaction fees and only in case PayPal charge us for those).</p>
<div></div>
<div id="key-features"></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2012/11/23/power-tags-for-joomla/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to fix Jupgrade Migrating undefined error when upgrading to Joomla 3</title>
		<link>http://www.itopen.it/2012/11/05/fixing-jupgrade-migrating-undefined-error-when-upgrading-joomla/</link>
		<comments>http://www.itopen.it/2012/11/05/fixing-jupgrade-migrating-undefined-error-when-upgrading-joomla/#comments</comments>
		<pubDate>Mon, 05 Nov 2012 12:36:11 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Joomla]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=909</guid>
		<description><![CDATA[Recently I had an error message while migrating and old Joomla! 1.5 site to the new Joomla! 2.5, jupgrade failed with &#8220;Migrating undefined&#8221; error. After digging in the code I found a solution: You have to edit two files: jupgrade/installation/models/configuration.php jupgrade/installation/models/database.php and insert the following line near the top of the script: require_once JPATH_ROOT.'/jupgrade/libraries/cms/model/legacy.php'; When [...]]]></description>
				<content:encoded><![CDATA[<p><img class="alignright size-full wp-image-148" title="Joomla logo quadrato" src="http://www.itopen.it/wp-content/uploads/2007/10/joomlacolor.png" alt="" width="363" height="363" /></p>
<p>Recently I had an error message while migrating and old Joomla! 1.5 site to the new Joomla! 2.5, jupgrade failed with &#8220;Migrating undefined&#8221; error.</p>
<p>After digging in the code I found a solution:</p>
<p>You have to edit two files:<br />
<code><br />
jupgrade/installation/models/configuration.php<br />
jupgrade/installation/models/database.php<br />
</code><br />
and insert the following line near the top of the script:</p>
<p><code>require_once JPATH_ROOT.'/jupgrade/libraries/cms/model/legacy.php';</code></p>
<p>When done (after the failed upgrade), you can retry the migration checking the following options in Jupgrade configuration:</p>
<div id="attachment_911" class="wp-caption alignright" style="width: 310px"><a href="http://www.itopen.it/wp-content/uploads/2012/11/jupgrade_options.png"><img class="size-medium wp-image-911" title="jupgrade_options" src="http://www.itopen.it/wp-content/uploads/2012/11/jupgrade_options-300x264.png" alt="" width="300" height="264" /></a><p class="wp-caption-text">Jupgrade options</p></div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2012/11/05/fixing-jupgrade-migrating-undefined-error-when-upgrading-joomla/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>View your web pages CSS in 3D!</title>
		<link>http://www.itopen.it/2012/10/11/view-your-web-pages-css-in-3d/</link>
		<comments>http://www.itopen.it/2012/10/11/view-your-web-pages-css-in-3d/#comments</comments>
		<pubDate>Thu, 11 Oct 2012 15:53:23 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WebGis]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=897</guid>
		<description><![CDATA[I&#8217;ve just discovered that the latest versions of web developer FF extension supports 3D view of the web pages: super cool! Look at how nice is the  OpenLayers vector layer stacked on to the background map  layers. &#160;]]></description>
				<content:encoded><![CDATA[<div id="attachment_898" class="wp-caption alignright" style="width: 310px"><a href="http://www.itopen.it/wp-content/uploads/2012/10/3dcssview.png"><img class="size-medium wp-image-898" title="3dcssview" src="http://www.itopen.it/wp-content/uploads/2012/10/3dcssview-300x210.png" alt="" width="300" height="210" /></a><p class="wp-caption-text">3D css view</p></div>
<p>I&#8217;ve just discovered that the latest versions of web developer FF extension supports 3D view of the web pages: super cool!</p>
<p>Look at how nice is the  OpenLayers vector layer stacked on to the background map  layers.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2012/10/11/view-your-web-pages-css-in-3d/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux Hotel QGIS Hackfest 2012</title>
		<link>http://www.itopen.it/2012/10/08/linux-hotel-qgis-hackfest-2012/</link>
		<comments>http://www.itopen.it/2012/10/08/linux-hotel-qgis-hackfest-2012/#comments</comments>
		<pubDate>Mon, 08 Oct 2012 09:52:16 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[GIS]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=891</guid>
		<description><![CDATA[I&#8217;ve spent the last days at the Linux Hotel for the QGIS Hackfest 2012. It has been a great hackfest, the location was amazing, an old villa with a wonderful park and Linux computers everywere, a geeky atmosphere and all you need to work and relax together. I&#8217;ve closed a lot of tickets concerning the [...]]]></description>
				<content:encoded><![CDATA[<p><img class="alignright size-medium wp-image-895" title="Linux Hotel Essen" src="http://www.itopen.it/wp-content/uploads/2012/10/20121008_002-300x225.jpg" alt="" width="300" height="225" /><br />
I&#8217;ve spent the last days at the Linux Hotel for the QGIS Hackfest 2012.<br />
It has been a great hackfest, the location was amazing, an old villa with a wonderful park and Linux computers everywere, a geeky atmosphere and all you need to work and relax together.</p>
<p>I&#8217;ve closed a lot of tickets concerning the python plugin website and added a couple of new features, like the rating/voting system for plugins.</p>
<p>Everybody was really satisfied for the very good organization and liked to come back here for one of the next hackfests.</p>
<p>QGIS is growing fast and demonstrates the pover of free software, thanks to everybody who participated and made this possible!</p>
<p>Here are some pictures of the location and the event:</p>
<p><a href="http://www.flickr.com/photos/45502883@N06/sets/72157631719309094/with/8066288380/">http://www.flickr.com/photos/45502883@N06/sets/72157631719309094/with/8066288380/</a></p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2012/10/08/linux-hotel-qgis-hackfest-2012/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presentazione su Joomla! FAP al Joomla! day 2012 di Torino</title>
		<link>http://www.itopen.it/2012/10/01/presentazione-su-joomla-fap-al-joomla-day-2012-di-torino/</link>
		<comments>http://www.itopen.it/2012/10/01/presentazione-su-joomla-fap-al-joomla-day-2012-di-torino/#comments</comments>
		<pubDate>Mon, 01 Oct 2012 09:50:47 +0000</pubDate>
		<dc:creator>Alessandro Pasotti</dc:creator>
				<category><![CDATA[Joomla]]></category>
		<category><![CDATA[[lang_it]Accessibilità[/lang_it][lang_en]Accessibility[/lang_en]]]></category>

		<guid isPermaLink="false">http://www.itopen.it/?p=885</guid>
		<description><![CDATA[Sabato scorso ho partecipato al Joomla! day di Torino per presentare il progetto che porto avanti ormai da sei anni: Joomla! FAP, la versione accessibile di Joomla! adatta alle pubbliche amministrazioni italiane, conforme alla legge &#8220;Stanca&#8221;. È stato un piacere partecipare a questo evento e incontrare Alexred, Ste e tutti i partecipanti. Ho caricato la [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.itopen.it/wp-content/uploads/2007/10/joomlacolor.png"><img class="alignright size-full wp-image-148" title="Joomla logo quadrato" src="http://www.itopen.it/wp-content/uploads/2007/10/joomlacolor.png" alt="" width="363" height="363" /></a>Sabato scorso ho partecipato al Joomla! day di Torino per presentare il progetto che porto avanti ormai da sei anni: Joomla! FAP, la versione accessibile di Joomla! adatta alle pubbliche amministrazioni italiane, conforme alla legge &#8220;Stanca&#8221;.</p>
<p>È stato un piacere partecipare a questo evento e incontrare Alexred, Ste e tutti i partecipanti.</p>
<p>Ho caricato la mia presentazione su slideshare:</p>
<p><iframe style="border: 1px solid #CCC; border-width: 1px 1px 0; margin-bottom: 5px;" src="http://www.slideshare.net/slideshow/embed_code/14535631" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="427" height="356"></iframe></p>
<div style="margin-bottom: 5px;"><strong> <a title="Joomla fap-joomla-day-2012" href="http://www.slideshare.net/elpaso66/joomla-fapjoomladay2012" target="_blank">Joomla fap-joomla-day-2012</a> </strong> from <strong><a href="http://www.slideshare.net/elpaso66" target="_blank">elpaso66</a></strong></div>
<div style="margin-bottom: 5px;"></div>
<p>Il video dell&#8217;intervento:<br />
<iframe width="420" height="315" src="http://www.youtube.com/embed/QqsT85OW-Xw?rel=0" frameborder="0" allowfullscreen></iframe></p>
<div style="margin-bottom: 5px;">Arrivederci al prossimo Joomla! Day!</div>
<div style="margin-bottom: 5px;"></div>
]]></content:encoded>
			<wfw:commentRss>http://www.itopen.it/2012/10/01/presentazione-su-joomla-fap-al-joomla-day-2012-di-torino/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
