<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.microsoft.co.il/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Just code - Tamir Khason : Mobile</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx</link><description>Tags: Mobile</description><dc:language>en</dc:language><generator>CommunityServer 2007.1 (Build: 20917.1142)</generator><item><title>New year – new blog or how to migrate Community Server to any other engine, supports XML-RPC</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2009/01/01/new-year-new-blog-or-how-to-migrate-community-server-to-any-other-engine-supports-xml-rpc.aspx</link><pubDate>Fri, 02 Jan 2009 02:33:04 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:205248</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>0</slash:comments><description>&lt;p&gt;Please update your bookmarks, because the new url of this blog is &lt;a href="http://khason.net/"&gt;http://khason.net/&lt;/a&gt; (you have not update RSS feeds, it will be done automatically). Why I did it? Why I decided to go to “stand-alone”… Well. there are some reasons. Generally, I do not want to explain all those here, but trust me, there are some. The main reason is, that there is no responsible person in charge for this blog platform in Microsoft Israel. This why, if your blog is popular and you have a respect to your blog visitors, you cannot host it here… Take a look into new comments notifications in my inbox. Would you answer your readers with such “small amount” of SPAM and capcha, that cannot be fixed already for three years in this platform? This how my inbox looks like for last three years. So now, you should not ask me, why I not answered your email or comments. Aren’t you? :)&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Capture" border="0" alt="Capture" src="http://blogs.microsoft.co.il/blogs/tamir/Capture_1D7350A7.jpg" width="354" height="397" /&gt; &lt;/p&gt;  &lt;p&gt;Currently, all comments in this blog are disabled, so if you want to comment, please use new url of posts (this will appear shortly in the beginning of each post). Also, this post will not be syndicated in RSS.&lt;/p&gt;  &lt;p&gt;So, this post is the last. I loved this platform, and loved people started it. But, unfortunately, it seemed, that bloggers community is not important enough for new platform managers. &lt;/p&gt;  &lt;p&gt;Also, If you want to learn &lt;a target="_blank" href="http://khason.net/dev/how-to-migrate-from-cs2007-to-wordpress-movable-type-or-any-other-blog-engine-supports-xml-rpc-with-c/"&gt;how to use C# and XML-RCP to migrate from CS2007, used in this platform, visit my new home&lt;/a&gt; :)&lt;/p&gt;  &lt;p&gt;Have a great year and, as always, be good people. This post marked with all possible tags automatically. Sorry.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=205248" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/soft/default.aspx">soft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+tools/default.aspx">blogging tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF+crossbow/default.aspx">WPF crossbow</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/help/default.aspx">help</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Gadgets/default.aspx">Windows Gadgets</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Vista/default.aspx">Vista</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/thoughts/default.aspx">thoughts</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tools/default.aspx">tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/events/default.aspx">events</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/demos/default.aspx">demos</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF_2F00_E/default.aspx">WPF/E</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/download/default.aspx">download</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/jobs/default.aspx">jobs</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/VSTS/default.aspx">VSTS</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Accessibility/default.aspx">Accessibility</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Blogging+rules/default.aspx">Blogging rules</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/fun/default.aspx">fun</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Vista+Battery+Saver/default.aspx">Vista Battery Saver</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/SkyDrive/default.aspx">SkyDrive</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Live+Writer/default.aspx">Windows Live Writer</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Live/default.aspx">Windows Live</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Dell/default.aspx">Dell</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DevAcademy2/default.aspx">DevAcademy2</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF+quiz/default.aspx">WPF quiz</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/x64/default.aspx">x64</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WF/default.aspx">WF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/SVG/default.aspx">SVG</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/XPS/default.aspx">XPS</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/TechedIsrael2008/default.aspx">TechedIsrael2008</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/teched/default.aspx">teched</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/XNA/default.aspx">XNA</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/PLINQ/default.aspx">PLINQ</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/LINQ/default.aspx">LINQ</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Micro+Framework/default.aspx">Micro Framework</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/SAP/default.aspx">SAP</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/ASP.NET/default.aspx">ASP.NET</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/XLINQ/default.aspx">XLINQ</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DirectX/default.aspx">DirectX</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Linux/default.aspx">Linux</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mono/default.aspx">Mono</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DevAcademy3/default.aspx">DevAcademy3</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Math/default.aspx">Math</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/GIS/default.aspx">GIS</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Algorithms/default.aspx">Algorithms</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/TECH/default.aspx">TECH</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+7/default.aspx">Windows 7</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Charity/default.aspx">Charity</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/OFFTOPIC/default.aspx">OFFTOPIC</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Hardware/default.aspx">Hardware</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Interop/default.aspx">Interop</category></item><item><title>What boots faster – Netbook, powered Windows XP or Nokia E71 mobile phone?</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/12/18/what-boots-faster-netbook-powered-windows-xp-or-nokia-e71-mobile-phone.aspx</link><pubDate>Thu, 18 Dec 2008 19:08:42 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:194876</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>6</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/what-boots-faster-%e2%80%93-netbook-powered-windows-xp-or-nokia-e71-mobile-phone/"&gt;http://khason.net/blog/what-boots-faster-%e2%80%93-netbook-powered-windows-xp-or-nokia-e71-mobile-phone/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;Some days ago, somebody from Microsoft was shocked, when I told him, that I’m planning to run Windows XP (and later Windows 7) as operation system for mission critical automotive device. He even checked with Windows XP embedded team boot times for XP. They told him, that the minimum can be achieved is about 40 seconds cold boot and 30 seconds from hibernate state. I was upset and decided to tweak my system for smallest possible boot time. Here the result video. This is not the limit. I believe, that I’ll be able to decrease Windows XP boot time to less, then 10 seconds with a bit more efforts.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Note: &lt;/strong&gt;This is absolutely authentic and non-touched video, recorded today by me, comparing boot time of Windows XP on unbranded weak netbook (Atom 1.6, 128MB and 8G SSD) and my Nokia E71 mobile phone. 15 seconds boot time of Windows XP achieved by tweaking only well known registry values and OS configuration values without special profundity of system settings. &lt;/p&gt;  &lt;p&gt;&lt;object width="425" height="344"&gt;&lt;param name="movie" value="http://www.youtube.com/v/FjFy_EwmVlg&amp;amp;hl=en&amp;amp;fs=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/FjFy_EwmVlg&amp;amp;hl=en&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;  &lt;p&gt;Now the question: with todays’ devices, why we are not running XP for mobile and automotive mission critical devices?&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=194876" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/thoughts/default.aspx">thoughts</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/fun/default.aspx">fun</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+7/default.aspx">Windows 7</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Hardware/default.aspx">Hardware</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/ITPRO/default.aspx">ITPRO</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/VIDEO/default.aspx">VIDEO</category></item><item><title>Reading and decoding RDS (Radio Data System) in C#</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/12/12/reading-and-decoding-rds-radio-data-system-in-c.aspx</link><pubDate>Fri, 12 Dec 2008 18:44:24 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:191019</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>4</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/reading-and-decoding-rds-radio-data-system-in-c/"&gt;http://khason.net/blog/reading-and-decoding-rds-radio-data-system-in-c/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Radio_Data_System"&gt;RDS or Radio Data System&lt;/a&gt; is very common in US and many European countries. It is communication protocol used to send small amount of digital information using regular FM radio broadcast. This protocol is used to &amp;quot;tell&amp;quot; your receiver about alternative frequencies, time, program notifications, program types, traffic information and regular text (such as singer name or genre). Unfortunately in Israel RDS is not very common and there is very limited number of radio stations broadcasts RDS information. &lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/ReadinganddecodingRDSRadioDataSysteminC_1238A/image_01bbfbdd-e89d-4a4e-89cd-e209655b5664.png" width="207" height="54" /&gt; &lt;/p&gt; &lt;h3&gt;How RDS works?&lt;/h3&gt; &lt;p&gt;As mentioned earlier, it uses FM subcarrier to broadcast digital information. It was designed to support 10 and 18 characters numeric and 80 characters alphanumeric displays. RDS operates at 1187.5 bps and based on 26-bit word consisting of 16 data and 10 error detection bits. Due to the fact, that FM carrier is not very reliable, error code allows correct information to be received even if an error of 3-5 bits exists within 26 bit block. Each four data blocks interpreted as 104-bit signal and named &amp;quot;group&amp;quot;. Depending of the type of information, contained within the group, as different group type code is defined and transmitted within the group as upper five bits code. Even if more, then 104 bits required to completely send the information, there is no requirement that the next segment of the transmission be sent in the next group. There are 32 known groups types, defined by &lt;a&gt;RFC&lt;/a&gt;:&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;private enum groupType : byte {&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_0A = (0 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_0B = (0 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_1A = (1 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_1B = (1 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_2A = (2 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_2B = (2 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_3A = (3 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_3B = (3 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_4A = (4 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_4B = (4 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_5A = (5 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_5B = (5 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_6A = (6 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_6B = (6 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_7A = (7 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_7B = (7 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_8A = (8 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_8B = (8 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_9A = (9 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_9B = (9 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_10A = (10 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_10B = (10 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_11A = (11 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_11B = (11 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_12A = (12 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_12B = (12 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_13A = (13 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_13B = (13 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_14A = (14 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_14B = (14 * 2 + 1),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_15A = (15 * 2 + 0),&lt;br /&gt;&amp;nbsp;&amp;nbsp; RDS_TYPE_15B = (15 * 2 + 1)&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Not all groups are in use all the time. However, there are some commitments, defined by the protocol. For example, 1A have to be transmitted at least once a second. This group contains special information, required for receivers to be synchronized and locked into the transmitting channel. &lt;/p&gt; &lt;p&gt;Within the error correction information we also receive the direction to treat them.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;private enum correctedType : byte {&lt;br /&gt;&amp;nbsp;&amp;nbsp; NONE = 0,&lt;br /&gt;&amp;nbsp;&amp;nbsp; ONE_TO_TWO = 1,&lt;br /&gt;&amp;nbsp;&amp;nbsp; THREE_TO_FIVE = 2,&lt;br /&gt;&amp;nbsp;&amp;nbsp; UNCORRECTABLE = 3&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Also, each message type has it own limits. For example RT (Radio Text - 64 character text to display on your receiver) and PS (Programme Service - eight character station identification) message are limited to 2 groups, when PI (Programme Identification - unique code of the station) and PTY (Programme Type - one of 31 predefined program types - e.g. News, Drama, Music) are limited to 4.&lt;/p&gt; &lt;p&gt;In addition to those constraints, block types are also different. But in this case, there are only 4 kinds&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;private enum blockType : byte {&lt;br /&gt;&amp;nbsp;&amp;nbsp; A = 6,&lt;br /&gt;&amp;nbsp;&amp;nbsp; B = 4,&lt;br /&gt;&amp;nbsp;&amp;nbsp; C = 2,&lt;br /&gt;&amp;nbsp;&amp;nbsp; D = 0&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;So, what we&amp;#39;re waiting for? Let&amp;#39;s start working.&lt;/p&gt; &lt;h3&gt;Handling errors&lt;/h3&gt; &lt;p&gt;First of all we should take care on errors and fix them if possible. For this purpose, we should first count them and detect the way of fixing&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;var errorCount = (byte)((registers[0xa] &amp;amp; 0x0E00) &amp;gt;&amp;gt; 9);&lt;br /&gt;var errorFlags = (byte)(registers[0x6] &amp;amp; 0xFF);&lt;br /&gt;if (errorCount &amp;lt; 4) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; _blocksValid += (byte)(4 - errorCount);&lt;br /&gt;} else { /*drop data on more errors*/ return; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Once it done, we can try to fix them&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;//Also drop the data if more than two errors were corrected&lt;br /&gt;if (_getErrorsCorrected(errorFlags, blockType.B) &amp;gt; correctedType.ONE_TO_TWO) return;&lt;/p&gt; &lt;p&gt;private correctedType _getErrorsCorrected(byte data, blockType block) { return (correctedType)((data &amp;gt;&amp;gt; (byte)block) &amp;amp; 0x30); }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now, our registers should be fine and we can start the detection of group type&lt;/p&gt; &lt;h3&gt;Group Type Detection&lt;/h3&gt; &lt;p&gt;This is very simple task, all we have to do is to get five upper bites to get a type and version.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;var group_type = (groupType)(registers[0xD] &amp;gt;&amp;gt; 11);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Then we can handle PI and PTY, which we always have in RDS.&lt;/p&gt; &lt;h3&gt;PI and PTY treatment&lt;/h3&gt; &lt;p&gt;Now, let&amp;#39;s update pi code, due to the fact, that B format always have PI in words A and C&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;_updatePI(registers[0xC]);  &lt;p&gt;if (((byte)group_type &amp;amp; 0x01) != 0) {&lt;br /&gt; _updatePI(registers[0xE]);&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;To update PI, we should check whether the new value is different from the previous and update it only in case it changed. &lt;blockquote&gt; &lt;p&gt;private void _updatePI(byte pi) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; uint rds_pi_validate_count = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp; uint rds_pi_nonvalidated = 0;  &lt;p&gt;&amp;nbsp;&amp;nbsp; // if the pi value is the same for a certain number of times, update a validated pi variable&lt;br /&gt;&amp;nbsp;&amp;nbsp; if (rds_pi_nonvalidated != pi) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rds_pi_nonvalidated = pi;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rds_pi_validate_count = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rds_pi_validate_count++;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp; if (rds_pi_validate_count &amp;gt; PI_VALIDATE_LIMIT) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _piDisplay = rds_pi_nonvalidated;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Then we will update PTY &lt;blockquote&gt; &lt;p&gt;_updatePTY((byte)((registers[0xd] &amp;gt;&amp;gt; 5) &amp;amp; 0x1f));&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;PTY treatment is very similar to PI, however it can be multiplied.&amp;nbsp; &lt;blockquote&gt; &lt;p&gt;private void _updatePTY(byte pty) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; uint rds_pty_validate_count = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp; uint rds_pty_nonvalidated = 0;  &lt;p&gt;&amp;nbsp;&amp;nbsp; // if the pty value is the same for a certain number of times, update a validated pty variable&lt;br /&gt;&amp;nbsp;&amp;nbsp; if (rds_pty_nonvalidated != pty) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rds_pty_nonvalidated = pty;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rds_pty_validate_count = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; rds_pty_validate_count++;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp; if (rds_pty_validate_count &amp;gt; PTY_VALIDATE_LIMIT) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _ptyDisplay = rds_pty_nonvalidated;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;When we done with those two groups, we can start handling another. Today, we&amp;#39;ll handle only 0B, 2A and 2B types (I have a good reason for it, due to the fact, that only those are supported in Israel by now :) ) So,  &lt;h3&gt;Handling PS and different RTs&lt;/h3&gt; &lt;p&gt;Simple switch on those groups&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;switch (group_type) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; case groupType.RDS_TYPE_0B:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; addr = (byte)((registers[0xd] &amp;amp; 0x3) * 2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _updatePS((byte)(addr + 0), (byte)(registers[0xf] &amp;gt;&amp;gt; 8));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _updatePS((byte)(addr + 1), (byte)(registers[0xf] &amp;amp; 0xff));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp; case groupType.RDS_TYPE_2A:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; addr = (byte)((registers[0xd] &amp;amp; 0xf) * 4);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; abflag = (byte)((registers[0xb] &amp;amp; 0x0010) &amp;gt;&amp;gt; 4);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _updateRT(abflag, 4, addr, (byte[])registers.Skip(0xe), errorFlags);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp; case groupType.RDS_TYPE_2B:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; addr = (byte)((registers[0xd] &amp;amp; 0xf) * 2);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; abflag = (byte)((registers[0xb] &amp;amp; 0x0010) &amp;gt;&amp;gt; 4);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // The last 32 bytes are unused in this format&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp0[32] = 0x0d;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp1[32] = 0x0d;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtCnt[32] = RT_VALIDATE_LIMIT;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _updateRT(abflag, 2, addr, (byte[])registers.Skip(0xe), errorFlags);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;and let&amp;#39;s dig into PS.&lt;/p&gt; &lt;p&gt;In PS, we have high and low probability bits. So, if new bit in sequence matches the high probability bite and we have recieved enough bytes to max out the counter, we&amp;#39;ll push it into the low probability array.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;if (_psTmp0[idx] == default(byte)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_psCnt[idx] &amp;lt; PS_VALIDATE_LIMIT) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psCnt[idx]++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psCnt[idx] = PS_VALIDATE_LIMIT;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psTmp1[idx] = default(byte);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Else, if new byte matches with the low probability byte, we should swap them and then reset the counter, by flagging the text as in transition. &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;else if (_psTmp1[idx] == default(byte)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_psCnt[idx] &amp;gt;= PS_VALIDATE_LIMIT) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isTextChange = true;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psCnt[idx] = PS_VALIDATE_LIMIT + 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psTmp1[idx] = _psTmp0[idx];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psTmp0[idx] = default(byte);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;When we have an empty byte in high probability array or new bytes does not match anything we know, we should put it into low probability array.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;else if (_psCnt[idx] == null) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psTmp0[idx] = default(byte);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psCnt[idx] = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psTmp1[idx] = default(byte);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now, if we marked our text as changed, we should decrement the count for all characters to prevent displaying of partical message, which in still in transition.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (isTextChange) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (byte i = 0; i &amp;lt; _psCnt.Length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_psCnt[i] &amp;gt; 1) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psCnt[i]--;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Then by checking PS text for incompetence, when there are characters in high probability array has been seen fewer times, that was limited by validation. &lt;blockquote&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (byte i = 0; i &amp;lt; _psCnt.Length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_psCnt[i] &amp;lt; PS_VALIDATE_LIMIT) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isComplete = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Only if PS text in the high probability array is complete, we&amp;#39;ll copy it into display.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (isComplete) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (byte i = 0; i &amp;lt; _psDisplay.Length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _psDisplay[i] = _psTmp0[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;It is not very hard to treat PS. Isn&amp;#39;t it? Let&amp;#39;s see what&amp;#39;s going on with RT.&lt;/p&gt; &lt;p&gt;If A and B message flag changes, we&amp;#39;ll try to force a display by increasing the validation count for each byte. Then, we&amp;#39;ll wipe any cached text.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; if (abFlag != _rtFlag &amp;amp;&amp;amp; _rtFlagValid) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // If the A/B message flag changes, try to force a display&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // by increasing the validation count of each byte&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; _rtCnt.Length; i++) _rtCnt[addr + i]++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _updateRTValue();  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Wipe out the cached text &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; _rtCnt.Length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtCnt[i] = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp0[i] = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp1[i] = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now A and B flags are safe, sp we can start with message processing. First of all, NULL in RDS means space :)&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; _rtFlag = abFlag;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; _rtFlagValid = true;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; count; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (p[i] == null) p[i] = (byte)&amp;#39; &amp;#39;; &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The new byte matches the high probability byte also in this case. We habe to recieve this bite enough to max out counters. Then we can push it into the low probability as well. &lt;blockquote&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_rtTmp0[addr + i] == p[i]) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_rtCnt[addr + i] &amp;lt; RT_VALIDATE_LIMIT) _rtCnt[addr + i]++;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtCnt[addr + i] = RT_VALIDATE_LIMIT;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp1[addr + i] = p[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;When the new byte matches with low probability byte, we&amp;#39;ll swap them as well and reset counters to update text in transition flag. However in this case, our counter will go higher, then the validation limit. So we&amp;#39;ll have to remove it down later.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;else if (_rtTmp1[addr + i] == p[i]) { &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_rtCnt[addr + i] &amp;gt;= PS_VALIDATE_LIMIT) isChange = true;  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtCnt[addr + i] = RT_VALIDATE_LIMIT + 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp1[addr + i] = _rtTmp0[addr + i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp0[addr + i] = p[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now, the new byte is replaced an empty byte in the high probability array. Also, if this byte does not match anything, we should move it into low probability.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;else if (_rtCnt[addr + i] == null) { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp0[addr + i] = p[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtCnt[addr + i] = 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else _rtTmp1[addr + i] = p[i]; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now when the text is changing, we&amp;#39;ll decrement the counter for all characters exactly as we did for PS. &lt;blockquote&gt; &lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; _rtCnt.Length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_rtCnt[i] &amp;gt; 1) _rtCnt[i]--;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;However, right after, we&amp;#39;ll update display.&amp;nbsp; &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; _updateRTValue();&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;h3&gt;Displaying RT&lt;/h3&gt; &lt;p&gt;But how to convert all those byte arrays into readable message? Simple :)&lt;/p&gt; &lt;p&gt;First of all if text is incomplete, we should keep loading it. Also it makes sense to check whether the target array is shorter then maximum allowed to prevent junk from being displayed.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;for (i = 0; i &amp;lt; _rtTmp0.Length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; if (_rtCnt[i] &amp;lt; RT_VALIDATE_LIMIT) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; isComplete = false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp; if (_rtTmp0[i] == 0x0d) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now, when our Radio Text is in the high probability and it complete, we should copy buffers.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;if (isComplete) {&lt;br /&gt;&amp;nbsp;&amp;nbsp; _Text = string.Empty; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp; for (i = 0; i &amp;lt; _rtDisplay.Length; i += 2) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((_rtDisplay[i] != 0x0d) &amp;amp;&amp;amp; (_rtDisplay[i + 1] != 0x0d)) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtDisplay[i] = _rtTmp0[i + 1];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtDisplay[i + 1] = _rtTmp0[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtDisplay[i] = _rtTmp0[i];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtDisplay[i + 1] = _rtTmp0[i + 1];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_rtDisplay[i] != 0x0d)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _Text += _rtDisplay[i];  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (_rtDisplay[i + 1] != 0x0d)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _Text += _rtDisplay[i + 1];  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((_rtDisplay[i] == 0x0d) || (_rtDisplay[i + 1] == 0x0d))&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; i = (byte)_rtDisplay.Length;&lt;br /&gt;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And not forget to wipe out everything after the end of the message :)&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp; for (i++; i &amp;lt; _rtDisplay.Length; i++) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtDisplay[i] = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtCnt[i] = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp0[i] = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _rtTmp1[i] = 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;} &lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;And finally update the text&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Text = _Text;&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;We done. Now we can handle RDS digital messages, but what to do with analog data we get? Don&amp;#39;t you already know? I &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/02/17/sound-tone-and-dtmf-generation-by-using-managed-directsound-and-c-and-sine-tone-detection-with-pure-managed-goertzel-algorithm-implementation.aspx"&gt;blogged about it here&lt;/a&gt;. &lt;p&gt;Have a nice day and be good people, because you know how to write client, knows to get and parse radio data in managed code. &lt;p&gt;&lt;img border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/ReadinganddecodingRDSRadioDataSysteminC_1238A/image_988a1f1f-0dec-46b1-b494-3c75a0b9ce7d.png" width="263" height="44" /&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=191019" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Math/default.aspx">Math</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Hardware/default.aspx">Hardware</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Interop/default.aspx">Interop</category></item><item><title>Creating transparent buttons, panels and other control with Compact Framework and putting one into other</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/11/21/creating-transparent-buttons-panels-and-other-control-with-compact-framework-and-putting-one-into-other.aspx</link><pubDate>Fri, 21 Nov 2008 18:09:29 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:172845</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>1</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/creating-transparent-buttons-panels-and-other-control-with-compact-framework-and-putting-one-into-other/"&gt;http://khason.net/blog/creating-transparent-buttons-panels-and-other-control-with-compact-framework-and-putting-one-into-other/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;In &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx"&gt;WPF&lt;/a&gt;/&lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx"&gt;Silverlight&lt;/a&gt; world it&amp;#39;s very simple to make transparent controls and put anything inside anything. However, that&amp;#39;s not the situation in WinForms, and even worth in the world of compact devices with CF. Within this worlds, there is only one way to make controls transparent - to use color masks. Today, we&amp;#39;ll create transparent controls with Compact Framework and put it into panel, which has image background.&lt;/p&gt; &lt;p&gt;&lt;img border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/Creatingtransparentbuttonspanelsandother_11B71/image_679149a5-fff2-40ab-8966-6c6ffa40b692.png" width="259" height="397" /&gt; &lt;/p&gt; &lt;p&gt;So let&amp;#39;s start. First of all, we need create our own control. For this purpose, we have to inherit from Control and override couple of things. More precise: OnPaint and OnPaintBackground. We do not want to paint background for transparent control, so let&amp;#39;s prevent it.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;public class TransparentImageButton : Control&lt;br /&gt;&lt;/p&gt; &lt;p&gt;protected override void OnPaintBackground(PaintEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //prevent&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override void OnPaint(PaintEventArgs e) {&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Next, we have to get graphics, delivered by OnPain event argument and draw our image over it. However, BitBlt (which is used by core graphics system) is not very fast method, so it&amp;#39;s better for us to draw everything first and then copy final image to the device.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;Graphics gxOff; &lt;br /&gt;Rectangle imgRect;&lt;br /&gt;var image = (_isPressed &amp;amp;&amp;amp; PressedImage != null) ? PressedImage : Image;  &lt;p&gt;if (_imgOffscreen == null) {&lt;br /&gt; _imgOffscreen = new Bitmap(ClientSize.Width, ClientSize.Height);&lt;br /&gt;}  &lt;p&gt;gxOff = Graphics.FromImage(_imgOffscreen); &lt;br /&gt;gxOff.Clear(this.BackColor);&amp;nbsp; &lt;br /&gt;...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;p&gt;if (image != null) {&lt;br /&gt;var imageLeft = (this.Width - image.Width) / 2;&lt;br /&gt;var imageTop = (this.Height - image.Height) / 2;  &lt;p&gt;if (!_isPressed) imgRect = new Rectangle(imageLeft, imageTop, image.Width, image.Height);&lt;br /&gt;else imgRect = new Rectangle(imageLeft + 1, imageTop + 1, image.Width, image.Height);&lt;br /&gt;var imageAttr = new ImageAttributes();&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;To make images transparent, we have to use (as mentioned earlier) transparency color key (to tell windows what color it should not draw. We can code or provide this value to detect it by hitting any pixel on the image. Just like this: &lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;public static Color BackgroundImageColor(this Bitmap bmp) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return bmp.GetPixel(0, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Now we can keep working.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;imageAttr.SetColorKey(image.BackgroundImageColor(), image.BackgroundImageColor());&lt;br /&gt;gxOff.DrawImage(image, imgRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, imageAttr);&lt;br /&gt;} if (_isPressed) {&lt;br /&gt; var rc = this.ClientRectangle;&lt;br /&gt;&amp;nbsp; rc.Width--;&lt;br /&gt;&amp;nbsp; rc.Height--;&lt;br /&gt;&amp;nbsp; gxOff.DrawRectangle(new Pen(Color.Black), rc);&lt;br /&gt; }&lt;br /&gt;e.Graphics.DrawImage(_imgOffscreen, 0, 0);&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Also, we have to provide others with possibility to handle this even too, thus we will not forget to add base.OnPaint(e); at&amp;nbsp; the end.&lt;/p&gt; &lt;p&gt;Next step is to detect whether our button is clicked or not. We&amp;#39;ll override keyboard and mouse events to detect this.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;protected override void OnKeyDown(KeyEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isPressed = this.Focused; this.Invalidate();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.OnKeyDown(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override void OnKeyUp(KeyEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isPressed = false; this.Invalidate();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.OnKeyUp(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override void OnMouseDown(MouseEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isPressed = this.Focused; this.Invalidate();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.OnMouseDown(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override void OnMouseUp(MouseEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; _isPressed = false; this.Invalidate();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; base.OnMouseUp(e);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;Compile and run to see no problem, when our transparent button lies on solid color control, however, we want to put it into panel with background - just like this one. In this case, you can use real transparent PNG and GIF images, also you can replace transparent color with well known Magenta (or any other color).&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;public class ImagePanel : Panel {  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Bitmap Image { get; set; }  &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected override void OnPaintBackground(PaintEventArgs e) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; e.Graphics.DrawImage(Image, 0, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;When we&amp;#39;ll put it onto anything, that has no background color, we&amp;#39;ll see that our &amp;quot;fake transparency&amp;quot; disappears. Why this happen? To provide transparency Windows uses color masks, also while confederating facts, clipping algorithm within GDI is not very trustful, thus the only thing can be taken into account is color. But what to do if we have an image? We should clip it manually. We cannot just get the handle to parent device surface (see above about trustful GDI), so the only way to do it is by providing something, that we know for sure. For example interface, telling us, that parent has image, which drawn on the screen.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;internal interface IHaveImage {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Bitmap Image { get; set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;When we know it, all we have to do is to clip the region of this image (not device context) and draw it as part of our really transparent control.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;if (this.Parent is IHaveImage) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; var par = this.Parent as IHaveImage;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; gxOff.DrawImage(par.Image.Clip(this.Bounds), 0, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;The implementation of Image.Clip is very straight forward.&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;public static Bitmap GetSS(this Graphics grx, Rectangle bounds) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var res = new Bitmap(bounds.Width, bounds.Height);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var gxc = Graphics.FromImage(res);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IntPtr hdc = grx.GetHdc();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PlatformAPI.BitBlt(gxc.GetHdc(), 0, 0, bounds.Width, bounds.Height, hdc, bounds.Left, bounds.Top, PlatformAPI.SRCCOPY);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; grx.ReleaseHdc(hdc);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return res;&lt;br /&gt;}  &lt;p&gt;public static Bitmap Clip(this Bitmap source, Rectangle bounds) {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var grx = Graphics.FromImage(source);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return grx.GetSS(bounds);&lt;br /&gt;}&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;We done. Compiling all together will fake transparency for controls, even when it&amp;#39;s parents background is not pained with&amp;nbsp; solid color brush.&lt;/p&gt; &lt;p&gt;&lt;a href="http://cid-4e39ecd492e4eec1.skydrive.live.com/self.aspx/Public/TransButton.zip"&gt;Source code for this article&lt;/a&gt;&lt;/p&gt; &lt;p&gt;P.S. Do not even try to inherit your custom Button control from framework Button class, dev team &amp;quot;forgot&amp;quot; to expose it&amp;#39;s event for override. So, OnPaint, OnPaintBackground, OnKeyUp, OnKeydown, OnMouseUp and OnMouseDown aside with most of other base events will not work for you, also BaseButton class has no default constructor, so the only class you can inherit from is Control.&lt;/p&gt; &lt;p&gt;Have a nice day and be good people.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=172845" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/DEV/default.aspx">DEV</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Interop/default.aspx">Interop</category></item><item><title>Nokia Mail for Exchange 2.7 is out</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/09/27/nokia-mail-for-exchange-2-7-is-out.aspx</link><pubDate>Sat, 27 Sep 2008 06:47:58 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:146122</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>0</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/nokia-mail-for-exchange-27-is-out/"&gt;http://khason.net/blog/nokia-mail-for-exchange-27-is-out/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;New version of outstanding Exchange synchronization tool for Nokia phones is out. There are no big changes, except heart beat implementation of ActiveSync and fixes to contacts mapping bug is there. The main feature of this version is, that it can now run on any S60 phone (including 3.0, 3.1 and 3.2 devices), not only on E and N series. Full list of changes can be found &lt;a href="http://www.businesssoftware.nokia.com/mail_for_exchange/files/MailForExchange_2_7_0_Release_Notes.pdf"&gt;here&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;The bad news is, that Nokia MFE 2.7 still does not support inbox folders synchronization. This is the main feature missing in this great software. However, according the update rate, it should arrive soon.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://www.businesssoftware.nokia.com/mail_for_exchange_downloads.php"&gt;&lt;strong&gt;Download Nokia Mail for Exchange 2.7 &amp;gt;&amp;gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=146122" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/soft/default.aspx">soft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/download/default.aspx">download</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/TECH/default.aspx">TECH</category></item><item><title>A little bit about batteries</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/09/20/a-little-bit-about-batteries.aspx</link><pubDate>Sat, 20 Sep 2008 09:16:52 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:142589</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>5</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/a-little-bit-about-batteries/"&gt;http://khason.net/blog/a-little-bit-about-batteries/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;I tired to write about programming, code and similar nerd stuff. So today I’ll write about … batteries. How is it? :)&lt;/p&gt;  &lt;p&gt;Today, batteries are in use all over our life. We have a battery in our mobile phone, computer, camera, mp3 player, even microwave, alarm and hand clock. So, the main problem with batteries, scientists all over the world work about is how to extend the working and life time. Let’s try to understand how to know whether the battery is good for us.&lt;/p&gt;  &lt;h3&gt;How to measure batteries&lt;/h3&gt;  &lt;p&gt;The number, can tell us whether the battery will work longer for us is charge (or actual). We measure charge in Ampere/hours (Ah). One ampere-hour is equals to 3600 coulombs (ampere-seconds) and represents an amount of charge, transferred by a steady current of one ampere for one hour. As higher this number is, your battery will work longer for the same consumer.&lt;/p&gt;  &lt;p&gt;&lt;img title="image" style="display:inline;" height="318" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/image_5FDCA8A8.png" width="297" border="0" /&gt; &lt;/p&gt;  &lt;h3&gt;What does “steady current” means? &lt;/h3&gt;  &lt;p&gt;Steady current is the power in watts, associated with an amount of electricity, named voltage (V). So, constant voltage, associated with one Ah produces the power of the battery in Watts per hour (Wh). So, why we cannot measure batteries in Wh? The problem is, that the power vary during charge and discharge process. So, the exact energy is the integral over time of the instantaneous voltage time and the current. Calculation of those three parameters is simple:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;W = V * A&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Today’s battery contains large number of elements (cells) with different fillings. As higher the number of elements, this your battery will work longer. Total work time may vary because of different parameters: charging methods, temperature, the way we’re charging it, number of charge-discharge cycles, etc.&lt;/p&gt;  &lt;h3&gt;Types of batteries&lt;/h3&gt;  &lt;p&gt;There are various batteries, however the most famous are following:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Li-ION&lt;/strong&gt; (lithium-ion): Number of charge-discharge cycles is between 500 and 700. The number of it depends on the depth of discharge. As more the battery discharged, this less number of cycles the battery will provide. It necessary to make a number of cycles for 14-16 hours until the battery will provide its nominal capacity. Each cycle the battery’s current will be increased until the nominal. &lt;/p&gt;  &lt;p&gt;&lt;em&gt;Pros&lt;/em&gt;: Good energy to weight ration – the battery rather small in compare to the current because of their high energy density.    &lt;br /&gt;No memory effect (no loss of maximum energy capacity on repeatedly recharge after partial discharge)    &lt;br /&gt;Slow loss of charge when not in use&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Cons&lt;/em&gt;: Those batteries might explode under certain conditions.    &lt;br /&gt;Energy loss starts directly after first charge, thus don’t buy this battery if you need spare battery and will not use it directly after purchase.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;NiCd&lt;/strong&gt; (Nickel-Cadmium): Number or charge-discharge cycles is between 1000-1500. This number might increase if you’re using the battery properly. However, you need to “train” this battery to assure maximum performance.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Pros&lt;/em&gt;: Tolerate to deep discharge for long period.    &lt;br /&gt;High energy density     &lt;br /&gt;Low self-discharge rate – about 20%/month&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Cons&lt;/em&gt;: Cadmium is toxic material    &lt;br /&gt;Memory effect – wrong usage pattern may cause to “false bottom” effect. The battery will stop charging, before the total capacity gathered.    &lt;br /&gt;Negative temperature coefficient – As the cell temperature rose, the internal resistance fell.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;NiMH&lt;/strong&gt; (Nickel-metal hydride): Number of charge-discharge cycles is under 1000 and depends on depth of discharging. Those batteries are very similar to NiCd, however those batteries can have two or three times the capacity of an equivalent size NiCd, but discharge rate is also higher. &lt;/p&gt;  &lt;p&gt;&lt;em&gt;Pros&lt;/em&gt;: Less toxic, price effective and have higher capacity then NiCd    &lt;br /&gt;Memory effect&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Cons&lt;/em&gt;: High self discharge rate    &lt;br /&gt;High application discharge rate    &lt;br /&gt;Voltage drop near as it nears full discharge&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Li-Pol&lt;/strong&gt; (Lithium-polymer): Number of charge-discharge cycles is very low 100-150 and depends on depth of discharging. Newer Li-Pol batteries has higher cycle durability, however they are still expensive. This is successor of Li-ION batteries. &lt;/p&gt;  &lt;p&gt;&lt;em&gt;Pros&lt;/em&gt;: Energy density is over 20% higher, then that of Li-ION.    &lt;br /&gt;High charge rate, about 1-3 minutes for cell    &lt;br /&gt;Greater life cycle degradation rate in comparison to Li-ION    &lt;br /&gt;Very efficient current per size ration    &lt;br /&gt;Non explosive&lt;/p&gt;  &lt;p&gt;&lt;em&gt;Cons&lt;/em&gt;: High cost    &lt;br /&gt;Low charge-discharge rate&lt;/p&gt;  &lt;h3&gt;Bottom line&lt;/h3&gt;  &lt;p&gt;Today, most of batteries are Li-ION, in spite of the fact, that it has high life cycle degradation rate. This is about two years by now for general user.&amp;#160; Also, those batteries degrades, even when not in use inside devices. You cannot leave uncharged battery unattended, because of the fact, that recharge may become impossible if the current drops under certain level. Also, those batteries are sensitive to temperature changes. On very low or high temperature the current degrades. &lt;/p&gt;  &lt;p&gt;Ni-Cad batteries provides the most optimal life cycle degradation rate, however it very sensitive to the way, you’re using it. The ideal pattern for such batteries is “full charge - full discharge – full charge”, else you’ll suffer from the “memory effect”, I spoke earlier. &lt;/p&gt;  &lt;h3&gt;Chargers&lt;/h3&gt;  &lt;p&gt;As you already understand, there is a wide range of battery types, so chargers are also different for those types of batteries. So, how to know if the charger we have is good for me and what to choose. &lt;/p&gt;  &lt;p&gt;The best charger for your battery is the one, you got with the device. It tuned for the battery you have. But can we use 3rd party chargers? The answer is: yes, we can, however it’s very important to understand, that if you have Li-ION battery and slow charger, you might be unable to charge it, even if you’ll put it in forever. &lt;/p&gt;  &lt;p&gt;Slow chargers works with current equals to about 1/10 of nominal battery current, thus it will take about 10-12 hours to full recharge cycle. Quick chargers uses 1/2-1 of nominal battery current, so recharge cycle can take between 1 to 3 hours.&lt;/p&gt;  &lt;p&gt;In both cases, do not leave NiCd and NiMH batteries in charger for a long time after the end of charging process. Even after the end of charge, those batteries keep charging, thus the quality will degrade. The story is different for Li-ION and Li-Pol batteries, those types of batteries are indifferent for overcharging. They usually have controllers to stop charging process after full recharge.&lt;/p&gt;  &lt;p&gt;Car chargers are not very healthy devices to charge batteries. Each time you’re turn your car on, it initiate new charge cycle, thus the quality of battery will degrade.&lt;/p&gt;  &lt;h3&gt;How to prolong battery life time?&lt;/h3&gt;  &lt;p&gt;Let’s assume, that most of devices have Li-ION battery. Once, you got a new device do not start using it with minimal capacity, also do not want to full discharge. Recharge it number of times until the capacity will be equal to almost equal to the nominal power.&lt;/p&gt;  &lt;p&gt;Also, switch your device to turn into idle mode after reasonable amount of time. It’s better, if it possible to switch or hibernate the device, rather then turn it into idle. Turn off all unused modules (such as GPS, Wi-Fi, Blootooth for mobile phones). Large number of concurrently running processes are also degrade the power quickly, so you can use &lt;a href="http://www.codeplex.com/vistabattery"&gt;Vista Battery Saver&lt;/a&gt; to decrease this number in Windows Vista. In PDAs, almost all plugins for battery level and processes performance measurement usually only use the battery, rather then provide usable information. If you can, turn GPRS in your mobile phones and use only GSM, this might save about 30% of energy without QoS degradation. Also, in places without coverage mobile phones increase the level of signal, so decrease the time, you can use the device. &lt;/p&gt;  &lt;p&gt;If during the charging process, the temperature of battery exceeds 60C (140F), stop charging immediately and recycle the charger. If the battery become swollen, recycle the battery. If Ni-MH battery discharges very quick, it’s possible to restore it, however restore is impossible for Li-ION batteries. If you’re feeling, that the capacity of Ni-MH battery degrades, you can calibrate it. Never train Li-ION batteries, the quality will degrade. &lt;/p&gt;  &lt;p&gt;Do not store your battery empty. Charge it unto 40%-50% of nominal capacity and store in 15C (60F) in fridge.&amp;#160; Also it worth to recharge unused batteries once a half-year. However, the best you can do is to use battery. This what it designed for.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=142589" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Performance/default.aspx">Performance</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/help/default.aspx">help</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Vista+Battery+Saver/default.aspx">Vista Battery Saver</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Work+process/default.aspx">Work process</category></item><item><title>Mobile version of this blog</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/07/15/mobile-version-of-this-blog.aspx</link><pubDate>Tue, 15 Jul 2008 17:00:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:118099</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>0</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/mobile-version-of-this-blog/"&gt;http://khason.net/blog/mobile-version-of-this-blog/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;10x to great service of &lt;a href="http://www.mofuse.com/"&gt;mofuse&lt;/a&gt;, I have &lt;a href="http://m.0x15.net/"&gt;mobile version&lt;/a&gt; of this blog now. So bookmark it: &lt;a title="http://m.0x15.net/" href="http://m.0x15.net/"&gt;http://m.0x15.net/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;img title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/Mobileversionofthisblog_B6DC/image_222a37ec-f62c-41a3-a5e5-e6eecb4df709.png" width="133" height="249" /&gt; &lt;img title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/Mobileversionofthisblog_B6DC/image_341211ed-35ba-486b-925b-6c86b5d390e7.png" width="134" height="251" /&gt; &lt;/p&gt;  &lt;p&gt;Here the QR code for your convenience&lt;/p&gt;  &lt;p&gt;&lt;img title="image" border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/Mobileversionofthisblog_B6DC/image_4a1e7bb2-68ba-4fc8-a4f8-6c601f7b67ae.png" width="160" height="159" /&gt; &lt;/p&gt; &lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=118099" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+tools/default.aspx">blogging tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tools/default.aspx">tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category></item><item><title>The truth about HTC has been revealed!</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/06/18/the-truth-about-htc-has-been-revealed.aspx</link><pubDate>Wed, 18 Jun 2008 19:55:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:105596</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>2</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/the-truth-about-htc-has-been-revealed/"&gt;http://khason.net/blog/the-truth-about-htc-has-been-revealed/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;HTC is underground factory, that manufacturing cat eater cyborgs (&lt;i&gt;Cats? Why Cats? Don’t you know, what PDA is? It’s &lt;b&gt;P&lt;/b&gt;ussy &lt;b&gt;D&lt;/b&gt;efended &lt;b&gt;A&lt;/b&gt;sset. Other words male mouser&lt;/i&gt;). Especially, those cyborgs eat cats is disguise of Mobile Phones.&lt;/p&gt;  &lt;p&gt;&lt;img src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/ThetruthaboutHTChasbeenrevealed_DFC8/Cat-eater_3.gif" title="Cat-eater" alt="Cat-eater" width="240" border="0" height="240" /&gt; &lt;/p&gt;  &lt;h3&gt;Where HTC located?&lt;/h3&gt;  &lt;p&gt;&lt;a href="http://www.htc.com/www/default.aspx"&gt;HTC&lt;/a&gt; located on the moon. Not in China. The facility is in one of moon craters inside the old spacecraft, abandoned by HAL from a space odyssey. Once a year, this moonbus rides to the Earth with new cyborgs production on board.&lt;/p&gt;  &lt;h3&gt;HTC production&lt;/h3&gt;  &lt;p&gt;At glance, &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/06/12/phone-history-or-why-i-throw-my-tytn-ii.aspx"&gt;the production of HTC&lt;/a&gt; looks like a regular mobile phones, however it has no phone capabilities. Therefore, once it leaves moonbus it eats fist mobile phone found. Momentarily after, cyborg’s internal infrastructure adopts the consumed cat and starts to operate as long as life endures, producing the illusion, that the cyborg is regular mobile phone.&lt;/p&gt;  &lt;p&gt;However, the main mission of HTC production is to eat cats. It do the offense nightly, when the owner sleeps. It comes out and every time, seeing a cat, exclaims: “&lt;b&gt;H&lt;/b&gt;ey, &lt;b&gt;T&lt;/b&gt;hat’s &lt;b&gt;C&lt;/b&gt;at!”, then swallows the victim. Once the cyborg loaded up, it return to the owner.&lt;/p&gt;  &lt;p&gt;The other ability of HTC production is zombying of its owners. It washes their brains and commands them to think, that cyborgs are the best mobile phone ever. All other phones are missing of features and very user unfriendly. Because of it, most of mobile phone owners forgot how to use regular mobile phones.&lt;/p&gt;  &lt;h3&gt;Cyborg detection&lt;/h3&gt;  &lt;p&gt;In spite of good camouflage, it’s possible to detect cyborgs:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Occasional pressing of phone screen does nothing for regular mobile phones, however cyborgs very sensitive to this action&lt;/li&gt;    &lt;li&gt;Upper cover of the cyborg consists of strange rectangle thing. It’s the antenna, used by the cyborg for zombying owners.&lt;/li&gt;    &lt;li&gt;One of following words might appear in cyborg’s front or back panel: i-mate,t-mobile,eten,asus,htc,orange,AT&amp;amp;T&lt;/li&gt;    &lt;li&gt;Sustained use of cyborgs causes headache or migraine. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;The cyborgs are extremely dangerous for cat population of the Earth, thus every time, you detect the cyborg, please, report to WWF, Heath Officer or FBI.&lt;/p&gt;  &lt;p&gt;Thank you for cooperation.&lt;/p&gt;  &lt;p&gt;&lt;i&gt;&lt;font size="1"&gt;[illustration by &lt;a href="http://dakraken.deviantart.com/"&gt;DaKraken&lt;/a&gt;, inspired by &lt;/font&gt;&lt;/i&gt;&lt;a href="http://absurdopedia.wikia.com/wiki/HTC"&gt;&lt;i&gt;&lt;font size="1"&gt;absurdopedia&lt;/font&gt;&lt;/i&gt;&lt;/a&gt;&lt;i&gt;&lt;font size="1"&gt;]&lt;/font&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;script src="http://digg.com/tools/diggthis.js" type="text/javascript"&gt;&lt;/script&gt; 
&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=105596" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/thoughts/default.aspx">thoughts</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/fun/default.aspx">fun</category></item><item><title>Phone history or why I throw my Tytn II</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/06/12/phone-history-or-why-i-throw-my-tytn-ii.aspx</link><pubDate>Fri, 13 Jun 2008 00:44:56 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:102993</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>10</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/phone-history-or-why-i-throw-my-tytn-ii/"&gt;http://khason.net/blog/phone-history-or-why-i-throw-my-tytn-ii/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;I decided to throw out my &lt;a href="http://en.wikipedia.org/wiki/HTC_TyTN_II"&gt;HTC TYTN II&lt;/a&gt; (Actually AT&amp;amp;T Tilt) and get old &lt;a href="http://en.wikipedia.org/wiki/Nokia_E61"&gt;Nokia E61&lt;/a&gt; back. Why I’m doing it? Tytn is much better, then old Nokia? It’s 3.75G/HSUPA mobile phone, running latest Windows Mobile 6.1 OS. It also has full QUERTY keyboard, 2.8” LCD monitor, 3MP camera and even very good integrated GPS. Nokia has neither. It’s processor is x4 faster and memory x3 bigger. Why I cannot use it? Why I want my old “keyboard brick” back?&lt;/p&gt;  &lt;p&gt;&lt;img title="e61" border="0" alt="e61" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/PhonehistoryorwhyIthrowmyTytnII_1238A/e61_72dba306-556c-4240-8f95-18da6eadfe72.jpg" width="476" height="654" /&gt; &lt;/p&gt;  &lt;p&gt;First of all, I need &lt;strong&gt;phone&lt;/strong&gt;. Not “freaky damn good uber extensible device”. I want to push one button to receive/make call, push another button to read/answer email. That’s all I need. I need business phone. I do not want to be worry about battery/&lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/01/31/my-windows-mobile-does-not-sound-alarms-my-windows-mobile-alerts-whenever-it-want-to-alert.aspx"&gt;alarms&lt;/a&gt;/meeting/time offset/current time/something wrong/too much processes/no memory/fault/occasionally shutdown/my ears near end call or mute button and all other “goodies” come with TYTN 2 device. I want to be able to dial number without looking on device. I want to be able to do it either when its sunny day outside. I want to push one button to refuse receive call, send “I’m sorry” SMS and turn ring off simultaneously. &lt;strong&gt;And I do not want to reinstall ROMS to figure one with small amounts of bugs and then reinstall 300 programs that allows me to do it&lt;/strong&gt;. I want &lt;strong&gt;business&lt;/strong&gt; &lt;strong&gt;phone, that knows what I need&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;Just see the regular flow &lt;strong&gt;phone&lt;/strong&gt; usage – make call:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Click power/unlock button&lt;/li&gt;    &lt;li&gt;Enter password (there is &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2007/12/28/how-to-disable-exchange-security-policy-for-windows-mobile-devices.aspx"&gt;exchange policy&lt;/a&gt;). To do this you &lt;strong&gt;have to look on screen&lt;/strong&gt;. If you wont you’ll absolutely unable to know where each button on screen. Windows mobile using &lt;strong&gt;different keyboard&lt;/strong&gt; for lock and phone utility.&lt;/li&gt;    &lt;li&gt;You should press left hardware button. It is not very easy task, ‘cos if your phone doing something now, you’ll wait for response between 1-2 seconds. If you’ll press it twice – you’ll arrive into calendar utility (only for this layout everyone in UX team of Windows Mobile should be fired.&lt;/li&gt;    &lt;li&gt;Press Phone button opens dialer utility. If you want any of your last incoming/outgoing/missed calls, you should press another soft button on screen (up jog button not always responses as required)&lt;/li&gt;    &lt;li&gt;Choose phone to call (another non-responsive hardware up/down buttons) and then&lt;/li&gt;    &lt;li&gt;Press middle big button…&lt;/li&gt;    &lt;li&gt;Nothing happes… “OK” button?&lt;/li&gt;    &lt;li&gt;You arrived to the contact information (I want to call)!!! Just side note, Windows Mobile is very smart system and if you have more, then one number per contact (work/mobile/office/text) it will call this number by default forever.&lt;/li&gt;    &lt;li&gt;Finally I choose a number I want to call (if you choose Text field of contact it brings your SMS interface instead of dialer) and calling the contact&lt;/li&gt;    &lt;li&gt;Busy… Redial? Automatic redial? Nothing. Now you should keep sitting and trying to process all above steps each time you want to redial…&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Very useful, very easy tool. Isn’t it? Now let’s call the contact with E61&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Click unlock button&lt;/li&gt;    &lt;li&gt;Enter password (your keyboard is always the same and you should not look into it to dial 5 button is marked)&lt;/li&gt;    &lt;li&gt;Move jog up&lt;/li&gt;    &lt;li&gt;Move jog down&lt;/li&gt;    &lt;li&gt;Move your finger left and up (each button has its unique profile and you can feel it)&lt;/li&gt;    &lt;li&gt;Dial&lt;/li&gt;    &lt;li&gt;Busy? E61 will redial for you until it’ll catch the contact or you’ll cancel operation. You even do not need to hold phone near ear. Once it success, you’ll hear gentle sound from external speaker.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Should not it work this way? It should, because it is &lt;strong&gt;phone&lt;/strong&gt;, not PDA device.&lt;/p&gt;  &lt;p&gt;What about exchange synchronization? Works perfectly. I do not want E61I (successor of E61) it much slower and bugger, then E61. I’m waiting for E71 (smaller) to see if it good for me. but meanwhile, I’m paying $300 to get my E61 back. &lt;u&gt;Someone want to buy my Tilt&lt;/u&gt;? Bid in comments.&lt;/p&gt;  &lt;p&gt;All above is the reason I do not want IPhone. It’s toy. Very cool and beautiful toy. It is not &lt;strong&gt;tool&lt;/strong&gt; I need everyday.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;P.S.&lt;/em&gt; I think Microsoft should think a lot about Windows CE 5.x, used as WM. It is not OS for phones, it’s OS for devices with some tools to be able to make calls. Microsoft never be the favorite of mobile market (like Steve Ballmer want it to be), unless they understand, that CE is not operation system for &lt;strong&gt;phones&lt;/strong&gt;. Just in case, currently Nokia holds 33% of the market, next is Motorola (20%), and Samsung (13%). Pay attention all three companies have &lt;strong&gt;phone operation system&lt;/strong&gt;. It’s not about coolness of the device. It’s all about usability of tools.&lt;/p&gt;  &lt;p&gt;&lt;em&gt;P.P.S&lt;/em&gt; Yes, it’s much easier to find or develop additional tools for Windows Mobile, rather then for Symbian. But I’m ready to pay this bill if I’ll be able to use my &lt;strong&gt;phone as phone&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;img title="AT&amp;amp;T Tilt" border="0" alt="AT&amp;amp;T Tilt" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/PhonehistoryorwhyIthrowmyTytnII_1238A/image_711e5136-1435-43ee-827f-df1191728717.png" width="461" height="307" /&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=102993" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/soft/default.aspx">soft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/thoughts/default.aspx">thoughts</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tools/default.aspx">tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category></item><item><title>Quick note: New TechEd downloads</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/06/05/quick-note-new-teched-downloads.aspx</link><pubDate>Thu, 05 Jun 2008 15:25:15 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:99360</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>2</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/quick-note-new-teched-downloads/"&gt;http://khason.net/blog/quick-note-new-teched-downloads/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;There is TechEd in Orlando, and this means, that there are a lot of new announcements. Let’s fill up our download managers with &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/05/16/gas-price-windows-vista-sidebar-gadget-new-version-is-available-for-download.aspx"&gt;expensive fuel&lt;/a&gt; and start.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.microsoft.com/downloads/details.aspx?familyid=3D6F581E-C093-4B15-AB0C-A2CE5BFFDB47&amp;amp;displaylang=en"&gt;New WM 6.1 images (both standard and professional)&lt;/a&gt; – absolutely required if you’re programming Windows Mobile&lt;/li&gt;    &lt;li&gt;&lt;a href="http://code.msdn.microsoft.com/mef"&gt;Managed Extensibility Framework&lt;/a&gt; – I blogged about it a little in the past. Really cool approach for adding extensibility features to your applications. &lt;a href="http://blogs.msdn.com/kcwalina/archive/2008/04/25/MEF.aspx"&gt;Krzysztof explains&lt;/a&gt; new features there.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://windowslivewriter.spaces.live.com/blog/cns!D85741BB5E0BE8AA!1508.entry"&gt;Windows Live Writer new CTP + new SDK&lt;/a&gt; – the best tool to post into your blog.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/data/cc655792.aspx"&gt;New CTP of Microsoft Project Codename “Velocity”&lt;/a&gt; – great approach for development applications, using high performance in memory cache. &lt;a href="http://blogs.msdn.com/velocity/archive/2008/06/02/introducing-project-codename-velocity.aspx"&gt;Here the deep explanations&lt;/a&gt; in the team blog + &lt;a href="http://code.msdn.microsoft.com/velocity"&gt;quick start and samples&lt;/a&gt;.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Silverlight 2.0 beta 2 + Microsoft Expression Blend 2.5 June preview will be available for download very soon. Keep watching. Meanwhile, you can start learn about &lt;a href="http://timheuer.com/blog/archive/2008/06/04/silverlight-2-introduces-tabcontrol.aspx"&gt;new TabControl&lt;/a&gt;, &lt;a href="http://timheuer.com/blog/archive/2008/06/04/silverlight-introduces-visual-state-manager-vsm.aspx"&gt;VisualStateManager&lt;/a&gt;, &lt;a href="http://timheuer.com/blog/archive/2008/06/04/skinning-silverlight-controls-made-easier.aspx"&gt;new templating system&lt;/a&gt; and &lt;a href="http://timheuer.com/blog/archive/2008/06/03/use-silverlight-with-any-feed-without-cross-domain-files.aspx"&gt;cross-domain policy&lt;/a&gt; from Tim Heuer’s blog. Also there are &lt;a href="http://silverlight.net/blogs/jesseliberty/archive/2008/06/03/beta-2-event-bubbling.aspx"&gt;some news about event bubbling&lt;/a&gt; in beta 2 in Jesse’s blog.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=99360" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/soft/default.aspx">soft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+tools/default.aspx">blogging tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/download/default.aspx">download</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Live+Writer/default.aspx">Windows Live Writer</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/teched/default.aspx">teched</category></item><item><title>Action required: Smart client users group</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/05/22/action-required-smart-client-users-group.aspx</link><pubDate>Fri, 23 May 2008 01:44:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:91573</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>8</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/action-required-smart-client-users-group/"&gt;http://khason.net/blog/action-required-smart-client-users-group/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;Recently I browsed &lt;a href="http://ineta.org" target="_blank"&gt;INETA&lt;/a&gt; to seek for some group and was really surprising. There is no Smart Client user group registered there. Maybe there is a reason? Let’s understand what Smart Client is? &lt;/p&gt;  &lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Smart_client" target="_blank"&gt;According wikipedia&lt;/a&gt;, the term &amp;quot;Smart Client&amp;quot; is meant to refer to simultaneously capturing the benefits of a &amp;quot;&lt;a href="http://en.wikipedia.org/wiki/Thin_client"&gt;thin client&lt;/a&gt;&amp;quot; (zero-install, auto-update) and a &amp;quot;&lt;a href="http://en.wikipedia.org/wiki/Fat_client"&gt;fat client&lt;/a&gt;&amp;quot; (high performance, high productivity). However, I think, that this term is much wider. It is not only thin-fat client application, it’s also most of applications we’re using today. &lt;/p&gt;  &lt;p&gt;&lt;img src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/ActionrequiredSmartclientusersgroup_13148/image_9b0168ec-d360-436a-a934-f287471e7222.png" title="image" alt="image" border="0" height="315" width="453" /&gt; &lt;/p&gt;  &lt;h3&gt;Thick Client&lt;/h3&gt;  &lt;p&gt;We always want to provide our users with best experience and increase their performance. However we are (as developers) want to avoid complicated development and deployment. This why we should know as much as possible about user’s system, when users do not want to have real footprint in their systems. That’s dilemma. Is it possible to solve it? Let’s look deeper…&lt;/p&gt;  &lt;p&gt;Are we really need installation? Most of old software installations put things in registry. It because you were never sure what client has in his system and were our application can put files or temporary data. Today, when we have local application or user isolated storage, so we not really need to use registry. Maybe only for our own ego – this is cool to have something like “HKLM/Software/MYNAME” in 1,000,000 user’s computers…&lt;/p&gt;  &lt;p&gt;No installation is good, but what to me with maintenance. We want our system connected…&lt;/p&gt;  &lt;h3&gt;Thin Client&lt;/h3&gt;  &lt;p&gt;Could you imagine your user to visit product site twice a week to see what’s going on? I can not. However I know, that if I’ll ask him first about automatic updates and he’ll agree to forget about application maintenance, his experience will be much better.&lt;/p&gt;  &lt;p&gt;So,we are connected. What now? I want to make time reporting system. Web service? Maybe some kind of distributed application. Maybe, even &lt;a href="http://twitter.com/tamir" target="_blank"&gt;Twitter&lt;/a&gt;? This way we can be sure, that our data is safe and if user reinstall whole system, he do not really need to care about backups. &lt;/p&gt;  &lt;p&gt;But users not always have internet access. Sometimes they are offline. How to solve the problem of occasionally connected users? I do not want him every lunch want for two minutes, until I realize, that there is no internet connection and will not even give him a chance to use the application?&lt;/p&gt;  &lt;p&gt;&lt;img src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/ActionrequiredSmartclientusersgroup_13148/image_10278991-02bf-4f23-9df9-d51332414509.png" title="image" alt="image" border="0" height="412" width="632" /&gt; &lt;/p&gt;  &lt;p&gt;So, we also want our system to be useful offline. But what’s up with Web 10.0? We want millions. We want very broad reach for our application. Also we want to be able to manage application updates remotely?&lt;/p&gt;  &lt;p&gt;Let’s take a look into other pan of application development. Do you like JavaScript? I do not! I think it’s too complicated to develop things for web. We should invest into at least 50% of coverage and integration tests, while giving customers pretty poor user experience. What is we want to provide the same look and feel everywhere? In web, desktop, mobile and other devices? Our customers want the application everywhere?&lt;/p&gt;  &lt;h3&gt;Summary&lt;/h3&gt;  &lt;p&gt;This is exactly what Smart client designed for. Technologies such as .NET, WPF, Silverlight from Microsoft, Flex, Thermo from Adobe and others tries to make you to be there with your application. But how to do it? How to answer all those hard questions, I asked?&lt;/p&gt;  &lt;p&gt;I want to announce new (currently virtual) user group, dedicated to Smart Client development. I do not want to restrict this group geographically, due to fact, that current infrastructures allows us to forget about distances and be together. Join today “Smart Client development” user group.&lt;/p&gt;  &lt;p&gt;In order to join, just send me an email to &lt;i&gt;tamir [at] khason.biz&lt;/i&gt; with information about you. I put the request to create this user group in INETA. Once it will be opened, I’ll send everyone email to register and connect them selves to this group.&lt;/p&gt;  &lt;p&gt;Be in touch.&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=91573" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/thoughts/default.aspx">thoughts</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/VSTS/default.aspx">VSTS</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Web/default.aspx">Web</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Windows+Live/default.aspx">Windows Live</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category></item><item><title>Networking and sockets in Silverlight 1.0 (mobile to?)</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/03/24/networking-and-sockets-in-silverlight-1-0-mobile-to.aspx</link><pubDate>Mon, 24 Mar 2008 14:08:05 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:69276</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>3</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/networking-and-sockets-in-silverlight-10-mobile-to/"&gt;http://khason.net/blog/networking-and-sockets-in-silverlight-10-mobile-to/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;Well, well, well. Two days ago, &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/03/22/networking-raw-sockets-in-silverlight-and-wpf-messaging-in-general.aspx"&gt;we spoke about using sockets within Silverlight 2.0 and WPF&lt;/a&gt;. Today, we&amp;#8217;ll make a step ahead and will use TCP or UDP client-server connection within Silverlight 1.0. Yes, 1.0 (the one with JavaScript only and no sockets). So, let&amp;#8217;s start Rock &amp;#8216;n Roll.&lt;/p&gt;  &lt;p&gt;&lt;img border="0" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/NetworkingandsocketsinSilverli.0mobileto_8E67/image_cc46d8e5-3ab0-4269-818c-f319237ad7db.png" width="606" height="600" /&gt; &lt;/p&gt;  &lt;p&gt;Oh, baby &amp;#8211; it cannot be done! Just kidding :) Silverlight 1.0 itself cannot use sockets, however ASP.NET can. We&amp;#8217;ll reuse our socket library (from the previous post) and reference it to the ASP.NET page, that hosts our Silverlight 1.0 application. &lt;/p&gt;  &lt;p&gt;So, on page load we&amp;#8217;ll create our client channel and fully reuse the way we worked within WPF and WinForms. The only difference is that we&amp;#8217;ll have three static web methods within our ASP.NET C# code&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;[System.Web.Services.WebMethod]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static string GetHoursAngle()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return ((msg.Hours * 30) + (12 * msg.Minutes / 60)).ToString();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; [System.Web.Services.WebMethod]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static string GetMinutesAngle()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return (msg.Minutes * 6).ToString();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; [System.Web.Services.WebMethod]      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public static string GetSecondsAngle()       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return (msg.Seconds * 6).ToString();       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Those methods can be used (almost) from client side. In order to do it we should register ScriptManager and enable PageMethods on the page&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;lt;asp:ScriptManager ID=&amp;quot;manager&amp;quot; EnablePageMethods=&amp;quot;True&amp;quot;&amp;#160; runat=&amp;quot;server&amp;quot; /&amp;gt;       &lt;br /&gt;&amp;lt;/form&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Then, create simple Javascript to call to our web methods&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; function UpdateHoursHand(angle)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; updateClockHand(&amp;#39;hTransform&amp;#39;,angle);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; function UpdateMinutesHand(angle)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; updateClockHand(&amp;#39;mTransform&amp;#39;,angle);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; function UpdateSecondsHand(angle)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; updateClockHand(&amp;#39;sTransform&amp;#39;,angle);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/script&amp;gt;&amp;#160;&amp;#160; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;There is no problem to access Silverlight from the hosting webpage, so we&amp;#8217;ll add following method to the Silverlight javascript &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;      &lt;br /&gt;if (!window.Silverlight1Client)       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Silverlight1Client = {}       &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;Silverlight1Client.Page = function()      &lt;br /&gt;{       &lt;br /&gt;}       &lt;br /&gt;Silverlight1Client.Page.prototype =       &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; handleLoad: function(control, userContext, rootElement)       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; this.control = control;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; canvas = rootElement;       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;var canvas;&amp;#160;&amp;#160;&amp;#160;&amp;#160; // the root canvas &lt;/p&gt;    &lt;p&gt;function updateClockHand(element, value)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160; hand = canvas.findName(element);       &lt;br /&gt;&amp;#160; hand.Angle = value;       &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;if (!window.Silverlight)      &lt;br /&gt;{       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Silverlight = {};       &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;Silverlight.createDelegate = function(instance, method) {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; return function() {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; return method.apply(instance, arguments);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }       &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;&amp;lt;/script&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now, we have prototype, that can access our Silverlight control, we have web methods, that can bring us information from the server side the only thing we should do is to enable server-side (where we actually receive&amp;#160; update notification) to call client side javascript in order to update layout. And this cannot be done due to the nature of client-server web architecture.&lt;/p&gt;  &lt;p&gt;But who told, that we cannot force client side to tickle server side upon the event? We can &amp;#8211; not very nice solution, but it works &amp;#8211; set timer.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;function UpdateClockHands()      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; PageMethods.GetHoursAngle(UpdateHoursHand);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; PageMethods.GetMinutesAngle(UpdateMinutesHand);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; PageMethods.GetSecondsAngle(UpdateSecondsHand);       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; setTimeout(&amp;quot;UpdateClockHands()&amp;quot;,1000);&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We add timer recursively to call client side javascript one a second and how it works. &lt;/p&gt;  &lt;p&gt;At the end the small diamond for upcoming &lt;strong&gt;DEV335&lt;/strong&gt;: &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/teched/default.aspx"&gt;Game Development Using Microsoft&amp;#8217;s Latest Technologies&lt;/a&gt;&amp;#8230;&lt;/p&gt;  &lt;p&gt;&lt;embed width="448" height="361" type="application/x-shockwave-flash" wmode="transparent" src="http://i71.photobucket.com/player.swf?file=http://vid71.photobucket.com/albums/i149/dedushka_jo/24032008094150.flv"&gt;&lt;/p&gt; &lt;/embed&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=69276" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Tips+and+Tricks/default.aspx">Tips and Tricks</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/TechedIsrael2008/default.aspx">TechedIsrael2008</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/teched/default.aspx">teched</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/ASP.NET/default.aspx">ASP.NET</category></item><item><title>Running WPF on gas pump (or other Windows CE devices)?</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/03/13/running-wpf-on-gas-pump-or-other-windows-ce-devices.aspx</link><pubDate>Thu, 13 Mar 2008 20:06:07 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:65881</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>2</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/running-wpf-on-gas-pump-or-other-windows-ce-devices/"&gt;http://khason.net/blog/running-wpf-on-gas-pump-or-other-windows-ce-devices/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;What do you think, is it possible to run WPF on Windows CE enabled devices (e.g. gas pumps, GPS systems, robots, game or automatic teller machines or, even, scientific calculators)? Let&amp;#39;s see following code:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;StackPanel panel = new StackPanel(Orientation.Horizontal);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Ellipse ellipse = new Ellipse(10, 10);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ellipse.Fill = new SolidColorBrush(Colors.Red);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ellipse.Stroke = new Pen(Color.Black);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Rectangle rect = new Rectangle();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rect.Width = 40;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; rect.Height = 40;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Line l = new Line(20, 20);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Polygon polygon = new Polygon(new int[] { 0, 0, 20, 0, 20, 20, 0, 20 });      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; panel.Children.Add(ellipse);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; panel.Children.Add(rect);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; panel.Children.Add(l);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; panel.Children.Add(polygon); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; panel.AddHandler(Buttons.ButtonUpEvent, (ButtonEventHandler)delegate     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; panel.Orientation = panel.Orientation == Orientation.Horizontal ? Orientation.Vertical : Orientation.Horizontal;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }, false);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Or even this code&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;void OnButtonHeld(object o)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Button b = (Button)o;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Dispatcher.Invoke(TimeSpan.FromTicks(10), (ButtonHeldDelegate)delegate(Button btn)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; while (Buttons.IsButtonDown(btn))      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; switch (btn)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case Button.Left: p.X--; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case Button.Up: p.Y--; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case Button.Right: p.X++; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case Button.Down: p.Y++; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; case Button.Select: p.X = mainWindow.Width / 2; p.Y = mainWindow.Height / 2; break;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; moveMouse();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }, b);      &lt;br /&gt;} &lt;/p&gt;    &lt;p&gt;void moveMouse()     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; host.DrawRectangle(Colors.Black,2,p.X,p.Y, 100, 100,0,0,Colors.Red,0,0,Colors.Blue,100,100,255);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; host.Flush();      &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This code will run on any Windows CE device. And it is not WPF :) It&amp;#39;s &lt;a href="http://msdn2.microsoft.com/en-us/embedded/bb267253.aspx" target="_blank"&gt;.NET Micro Framework&lt;/a&gt;. Actually, when we&amp;#39;re looking for it&amp;#39;s syntax, it looks like WPF/Silverlight and .NET Micro Framework have the same architect. However, it cannot use hardware acceleration and has very limited number of objects. All this because of it&amp;#39;s purpose &amp;quot;platform to devices that do not need the fuller functionality available in the .NET Framework and the .NET Compact Framework&amp;quot;. I would add Windows Presentation Foundation as well.&lt;/p&gt;  &lt;p&gt;The application model of .NET Micro Framework is very similar to WPF. It has native CLR/PAL and HAL and managed libraries. &lt;/p&gt;  &lt;p&gt;&lt;img height="324" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/RunningWPFongaspumporotherWindowsCEdevic_E251/image_8d1277cc-3f51-4b8d-8b2b-e91d3bea8037.png" width="503" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;Sufficient number of components in CLR - types, threads and timers, reflection, serialization, GC, networking, other connectivities etc., enables you to create, even games, that will run on even &lt;a href="http://blogs.microsoft.co.il/blogs/zivraf/archive/2008/03/13/a-heart-device-is-found-vulnerable-to-hacker-attacks.aspx" target="_blank"&gt;Heart Device&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;Other words, cool technology and possible cool appliance for your programming skills.&amp;#160; &lt;/p&gt;  &lt;p&gt;How to start? First of all, &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=EB0EF2A6-03E2-402C-89A4-A636BD0080C5&amp;amp;displaylang=en" target="_blank"&gt;download .NET Micro Framework v2.5&lt;/a&gt; (VS2005, you can also add Microsoft.SPOT assemblies into your regular VS2008 project) and start programming. It&amp;#39;s really simple (I build snake game for less, then hour)&lt;/p&gt;  &lt;p&gt;See your applications, running on embedded devices. BTW, I&amp;#39;ll probably present something, developed with this framework in my TechEd session aside with WPF, Silverlight and XNA... Keep tuned and have a nice day&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=65881" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/blogging+general/default.aspx">blogging general</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/TechedIsrael2008/default.aspx">TechedIsrael2008</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/teched/default.aspx">teched</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/XNA/default.aspx">XNA</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Micro+Framework/default.aspx">Micro Framework</category></item><item><title>Sound, tone and DTMF generation by using managed DirectSound and C# and sine tone detection with pure managed Goertzel algorithm implementation</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/02/17/sound-tone-and-dtmf-generation-by-using-managed-directsound-and-c-and-sine-tone-detection-with-pure-managed-goertzel-algorithm-implementation.aspx</link><pubDate>Mon, 18 Feb 2008 01:15:37 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:59466</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>11</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/sound-tone-and-dtmf-generation-by-using-managed-directsound-and-c-and-sine-tone-detection-with-pure-managed-goertzel-algorithm-implementation/"&gt;http://khason.net/blog/sound-tone-and-dtmf-generation-by-using-managed-directsound-and-c-and-sine-tone-detection-with-pure-managed-goertzel-algorithm-implementation/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;Well, today, we&amp;#39;ll speak about math. A lot of math. We have a number of challenges today.&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Generate sine, square or dual sine tone (DTMF - sounds, that your phone keyboard produces)&lt;/li&gt;    &lt;li&gt;Playing it in managed code&lt;/li&gt;    &lt;li&gt;Detection of base frequencies by using Goertzel (Fast Fourier) algorithm&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Let&amp;#39;s start with generation of tone. All we need is DirectSound. First of all, we should create format of wave sound&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;using DXS = Microsoft.DirectX.DirectSound;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now, let&amp;#39;s create our Device&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;Microsoft.DirectX.DirectSound.Device m_device = new Microsoft.DirectX.DirectSound.Device();     &lt;br /&gt;SourceHost = App.Current.MainWindow.Content as FrameworkElement; &lt;/p&gt;    &lt;p&gt;m_device.SetCooperativeLevel(((HwndSource)PresentationSource.FromVisual(SourceHost)).Handle, DXS.CooperativeLevel.Priority);&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;As you can see, it, actually Control, thus we have to give him handle to sit on. 90%, that when you&amp;#39;ll run it, you&amp;#39;ll get strange exception: &amp;quot;DLL &amp;#39;C:\Windows\assembly\GAC\Microsoft.DirectX\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.dll&amp;#39; is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.&amp;quot;. In order to get rid of it, just disable handling of LoaderLock exceptions under Managed Debugging Assistants section in Visual Studio Debug menu. Not very clear why it happens, but it is. After doing it, we can continue with in memory wave generation.&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;DXS.WaveFormat format = new DXS.WaveFormat();     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; format.BitsPerSample = BitsPerSample;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; format.Channels = Channels;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; format.BlockAlign = BlockAlign;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; format.FormatTag = DXS.WaveFormatTag.Pcm;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; format.SamplesPerSecond = SampleRate;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; format.AverageBytesPerSecond = format.SamplesPerSecond * format.BlockAlign; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; DXS.BufferDescription desc = new DXS.BufferDescription(format);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; desc.DeferLocation = true;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; desc.BufferBytes = sample.Length;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Now, when we&amp;#39;ll create SecondaryBuffer to play with the Device&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;CurrentSample = sample;     &lt;br /&gt;CurrentBuffer = new DXS.SecondaryBuffer(desc, m_device);      &lt;br /&gt;CurrentBuffer.Write(0, sample, DXS.LockFlag.EntireBuffer);      &lt;br /&gt;CurrentBuffer.Play(0, DXS.BufferPlayFlags.Default);&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;We done. Now let&amp;#39;sw create buffer to play. We&amp;#39;ll start from the simplest sine wave. This type of wave looks like this&lt;/p&gt;  &lt;p&gt;&lt;img height="334" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/SoundtoneandDTMFgenerationbyusingmanaged_11CE1/image_21061627-9bf6-49c3-b26d-de564dbf6ce1.png" width="464" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;Not too hard to understand how to generate it&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;int length = (int)(SampleRate * BlockAlign * duration);     &lt;br /&gt; byte[] buffer = new byte[length]; &lt;/p&gt;    &lt;p&gt; double A = frequency * 2 * Math.PI / (double)SampleRate;     &lt;br /&gt; for (int i = 0; i &amp;lt; length; i++)      &lt;br /&gt; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160; //buffer[i] = (byte)(Math.Sin(i*A));      &lt;br /&gt; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;However, phone tones (DTMF) have double wave format. It looks like this&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;img height="338" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/SoundtoneandDTMFgenerationbyusingmanaged_11CE1/image_4cb36e15-7706-4e20-ae09-01094dd59211.png" width="558" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;As you can see, we take two waves and create it&amp;#39;s composition. Here the table of tones to be used for DTMF creation.&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2"&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="right"&gt;&lt;strong&gt;Upper &lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="left"&gt;&lt;strong&gt;Band&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;&amp;#160;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;1209 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;1336 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;1477 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;1633 Hz&lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;         &lt;p align="center"&gt;&amp;#160;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;697 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;1&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;2&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;3&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;A&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;         &lt;p align="center"&gt;&lt;strong&gt;Lower&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;770 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;4&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;5&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;6&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;B&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;         &lt;p align="center"&gt;&lt;strong&gt;Band&lt;/strong&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;852 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;7&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;8&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;9&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;C&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;         &lt;p align="center"&gt;&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;941 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;*&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;0&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;         &lt;p align="center"&gt;#&lt;/p&gt;       &lt;/td&gt;        &lt;td valign="top"&gt;D&lt;/td&gt;     &lt;/tr&gt;   &lt;/table&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;There are also events in telephony. They build on two frequencies as well&lt;/p&gt;  &lt;table cellspacing="0" cellpadding="2"&gt;     &lt;tr&gt;       &lt;td valign="top"&gt;&amp;#160;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;strong&gt;Lower Band&lt;/strong&gt;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;strong&gt;Upper Band&lt;/strong&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Busy signal&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;480 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;620 Hz&lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Dial tone&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;350 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;440 Hz&lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;      &lt;tr&gt;       &lt;td valign="top"&gt;Flash (ringback)&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;440 Hz&lt;/em&gt;&lt;/td&gt;        &lt;td valign="top"&gt;&lt;em&gt;480 Hz&lt;/em&gt;&lt;/td&gt;     &lt;/tr&gt;   &lt;/table&gt;  &lt;p&gt;So, in order to create such waves, we&amp;#39;ll have to use following function (the simple one)&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;(128 + 63 * Math.Sin(n * 2 * Math.PI * LowFreq / rate) + 63 * Math.Sin(n * 2 * Math.PI * HighFreq / rate))&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Actually, dual (or triple) sines should be generated by using something like this &lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;int length = (int)(SampleRate * BlockAlign * duration);     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; byte[] buffer = new byte[length]; &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; double A = frequency * 2 * Math.PI / (double)SampleRate;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (int i = 0; i &amp;lt; length; i++)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if (i &amp;gt; 1) buffer[i] = (byte)(2 * Math.Cos(A) * buffer[i - 1] - buffer[i - 2]);      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else if (i &amp;gt; 0) buffer[i] = (byte)(2 * Math.Cos(A) * buffer[i - 1] - (Math.Cos(A)));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else buffer[i] = (byte)(2 * Math.Cos(A) * Math.Cos(A) - Math.Cos(2 * A));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Done. We can generate and play sounds, tones and DTMF. How to detect what has been played? For this purpose, we should use Fourier transform, but it&amp;#39;s very slow, thus Dr&amp;#39; Gerald Goertzel developed fast Fourrier Transform algorithm, that used almost in every DSP related product. A little theory about it can be found &lt;a href="http://en.wikipedia.org/wiki/Goertzel_algorithm" target="_blank"&gt;in Wikipedia&lt;/a&gt; (implementation there rather bad). &lt;/p&gt;  &lt;p&gt;I simplified it, due to fact, that we actually know source possible frequencies, thus all we have to do is to check the result with well-known values&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public double CalculateGoertzel(byte[] sample, double frequency, int samplerate)     &lt;br /&gt;{      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; double Skn, Skn1, Skn2;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Skn = Skn1 = Skn2 = 0;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; for (int i = 0; i &amp;lt; sample.Length; i++)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Skn2 = Skn1;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Skn1 = Skn;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Skn = 2 * Math.Cos(2 * Math.PI * frequency / samplerate) * Skn1 - Skn2 + sample[i];      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; double WNk = Math.Exp(-2 * Math.PI * frequency / samplerate); &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; return 20* Math.Log10(Math.Abs((Skn - WNk * Skn1)));     &lt;br /&gt;}&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;This method checks it will steps of 5&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;public int TestGoertzel(int frequency, byte[] sample)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int stepsize = frequency / 5;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Dictionary&amp;lt;int,double&amp;gt; res = new Dictionary&amp;lt;int,double&amp;gt;();      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for (int i = 0; i &amp;lt; 10; i++)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; int freq = stepsize * i;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; res.Add(freq,CalculateGoertzel(sample,freq,SampleRate));      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;And the actual result is rather clear&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;1200 - -272.273842954695     &lt;br /&gt;2400 - -198.538262992751      &lt;br /&gt;3600 - -214.476846236253      &lt;br /&gt;4800 - -224.242925995697      &lt;br /&gt;&lt;strong&gt;6000 - 87.1653837206957 &amp;lt;- here result       &lt;br /&gt;&lt;/strong&gt;7200 - -225.52220053475      &lt;br /&gt;8400 - -222.836254116698      &lt;br /&gt;9600 - -230.526410368965      &lt;br /&gt;10800 - -220.587695185849&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Have a fun with sines, waves and math and be good people. BTW, you can implement full telephone keypad, that actually working with &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/archive/2008/02/13/custom-editors-accessibility-and-attached-properties.aspx" target="_blank"&gt;one of my previous posts&lt;/a&gt;. To test it, just call any service, that required you to press any of phone buttons and sound the phone you just generated - it will accept it :)&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=59466" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/WPF/default.aspx">WPF</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tutorial/default.aspx">tutorial</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/source/default.aspx">source</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category></item><item><title>My Windows Mobile does not sound alarms / my Windows Mobile alerts whenever it want to alert</title><link>http://blogs.microsoft.co.il/blogs/tamir/archive/2008/01/31/my-windows-mobile-does-not-sound-alarms-my-windows-mobile-alerts-whenever-it-want-to-alert.aspx</link><pubDate>Fri, 01 Feb 2008 03:03:00 GMT</pubDate><guid isPermaLink="false">b5c4f5bc-c09b-4439-a595-91a98c1847df:55401</guid><dc:creator>Tamir Khason</dc:creator><slash:comments>27</slash:comments><description>&lt;h3&gt;[This blog was migrated. You will not be able to comment here.&lt;br /&gt;The new URL of this post is &lt;a href="http://khason.net/blog/my-windows-mobile-does-not-sound-alarms-my-windows-mobile-alerts-whenever-it-want-to-alert/"&gt;http://khason.net/blog/my-windows-mobile-does-not-sound-alarms-my-windows-mobile-alerts-whenever-it-want-to-alert/&lt;/a&gt;]&lt;/h3&gt;&lt;hr /&gt;&lt;p&gt;Many of Windows Mobile users are suffering from different problems, related to clocks, alarms and reminders. This problem exists almost in all Windows Mobile systems (Windows Mobile 2003, WM5, WM6, etc).&amp;#160; Why this happens and how to take care on it?&lt;/p&gt;  &lt;p&gt;There root of this problem is something called &amp;quot;Notification Queue&amp;quot;. The main propose of it is to run tasks and activate alarms and reminders at scheduled times, particularly when the device is in standby or low power mode.&amp;#160; There are a lot of problems with this module - troubles with alarm and reminders, which not working, or, alternatively, playing not in time after device reboot. &lt;/p&gt;  &lt;p&gt;There are some bugs, reported to Microsoft and &lt;a href="https://connect.microsoft.com/feedback/default.aspx?SiteID=502&amp;amp;wa=wsignin1.0" target="_blank"&gt;one of topmost requests from the next version of Windows Mobile&lt;/a&gt; is to produce more reliable alarm clock.&amp;#160; &lt;/p&gt;  &lt;p&gt;For some reason, there is very little information about working with notifications queue in internet. There is absolutely no information about it in MSDN. And a lot of misinformation all over the network. I gathered up all I can from anywhere and now, I know what the cause for problems with alarms, alerts, notifications and reminders in Windows Mobile systems. I also learned how to fix it.&lt;/p&gt;  &lt;p&gt;The root problem of notification queue is duplicate entries, produced by different applications, such as clock, ActiveSync, Alert, missed calls notifies and more. Windows mobile has no tools to treat this problem. &lt;/p&gt;  &lt;p&gt;I build such tool and called it &lt;a href="http://blogs.microsoft.co.il/files/folders/55400/download.aspx" target="_blank"&gt;AlarmFixWM&lt;/a&gt;. It scans your Windows Mobile system for duplicate entries in notification queue and eliminate them. All you have to do, is do download it, put it into one of directories inside your mobile device (no installation), then run and hit Scan button. The program will do all the rest.&lt;/p&gt;  &lt;p&gt;&lt;img height="328" alt="image" src="http://blogs.microsoft.co.il/blogs/tamir/WindowsLiveWriter/MyWindowsMobiledoesnotsoundalarmsmyWindo_13609/image_697ce793-9342-4fa5-8bd5-589588b22aff.png" width="243" border="0" /&gt; &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;If you are not suffering from problem, related to Windows Mobile alerts, do not use this application. &lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;I&amp;#39;d be happy &lt;a href="http://blogs.microsoft.co.il/blogs/tamir/contact.aspx" target="_blank"&gt;to hear your feedbacks&lt;/a&gt; (also, if you want to learn more about this problem, you can ask me). And &lt;u&gt;don&amp;#39;t forget to backup your device before using this program&lt;/u&gt;!&lt;/p&gt;  &lt;p&gt;Are there other tools, doing the same work? Yes, there are two: &lt;a href="http://www.dinarsoft.com/memmaid/" target="_blank"&gt;MemMaid&lt;/a&gt; and &lt;a href="http://s-k-tools.com/index.html?sktools/m_feat.html" target="_blank"&gt;SKTools&lt;/a&gt;. Both are commercial and doing much more (cleaning your device inside). If all you want, is to get rid of wrong or not occurred alarms, &lt;a href="http://blogs.microsoft.co.il/files/folders/55400/download.aspx" target="_blank"&gt;AlarmFixWM&lt;/a&gt; is all you need.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://blogs.microsoft.co.il/files/folders/55400/download.aspx" target="_blank"&gt;Download AlarmFixWM (12.1k) &amp;gt;&amp;gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://blogs.microsoft.co.il/aggbug.aspx?PostID=55401" width="1" height="1"&gt;</description><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/soft/default.aspx">soft</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Mobile/default.aspx">Mobile</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/promo/default.aspx">promo</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/tools/default.aspx">tools</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/download/default.aspx">download</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.microsoft.co.il/blogs/tamir/archive/tags/Microsoft/default.aspx">Microsoft</category></item></channel></rss>